# Protocol v2 落地 Checklist（执行版）

> 目的：把 `docs/protocol_v2_implementation_plan.md` 变成可执行、可勾选、可验收的工作清单。
>
> 使用方式：
> - 每项完成后勾选 `[x]`，并在"证据"处补上 PR/commit、关键文件、关键测试。
> - **Definition of Done（DoD）**：必须有测试护栏（最少 1 条主路径 + 1 条边界），并与 `docs/protocol_v2_specification.md` 对齐；若偏离必须记录原因与替代方案。

---

## 全局 DoD（所有 Phase 通用）

- [x] 代码：实现落在主链路（REST FastAPI v2）上，不接受"只有字段/只有工具函数"的半实现
- [x] 测试：新增/更新测试覆盖主路径 + 关键边界（尽量走端到端）
- [x] 文档：必要时更新 spec/plan 或增加"偏离点说明"
- [x] 质量门禁：本地（或 CI）全量测试通过

**全局证据**
- PR/commit: 082f98f, bac1a62, 38e91d4, 8a8adb1, a75c596, 016e53c
- 关联 spec 条款: Protocol v2 Specification sections 2.2-5.3
- 回归测试命令/输出: `pytest tests/test_rest_v2*.py tests/test_phase*.py tests/test_negotiation.py tests/test_qos_handler.py -v` → **183 passed, 2 skipped**

---

## Phase 1 — REST v2 HTTP 语义完整化（spec 5.3）

### 1.1 HTTP status 映射（严格对齐 spec 5.3）
- [x] 设计并实现 `RpcError.code -> HTTP status` 映射（集中且可复用）
  - 证据：实现文件/函数: `src/aduib_rpc/protocol/v2/errors.py::error_code_to_http_status()`
  - 证据：映射表是否覆盖 spec 段位: ✅ 1xxx→400, 2xxx→400, 3000-3002→401, 3010-3012→403, 4000-4002→404, 4010-4011→409, 4020→410, 5000→500, 5001→501, 5002→503, 5003→504, 5010→503, 5020-5021→429, 6000→502, 6001→504, 6002→502
  - 测试: `test_http_status_mapping_*` (9 tests)

### 1.2 REST v2 返回值通路（body + http_status）
- [x] `RESTV2Handler.on_message()`（或等价通路）能显式产出 http_status
  - 证据: `src/aduib_rpc/server/request_handlers/rest_v2_handler.py::_map_error_to_response()`
- [x] `fastapi_app.py::_handle_requests()` 将 http_status 写入 `JSONResponse(status_code=...)`
  - 证据: `src/aduib_rpc/server/protocols/rest/fastapi_app.py::_handle_v2_requests()` 使用 `status_code=_map_error_to_response()`

### 1.3 SSE 建链错误必须 HTTP 非 200
- [x] 对以下情况在 **SSE 建链阶段**直接返回非 200（不能只在 SSE data 内发 error）：
  - [x] 请求不合法（invalid envelope/JSON/pydantic 校验失败）
  - [x] 版本不支持（UNSUPPORTED_VERSION）
  - [x] content-type 不支持 / accept 不可满足
- [x] 明确哪些错误属于"建链错误"（HTTP 层失败），哪些属于"流内错误"（error frame）

### 1.4 测试护栏
- [x] `invalid envelope -> 400`
- [x] `method 非 v2 -> 400`（或按 spec）
- [x] `内部异常 -> 500`
- [x] `限流/过载 -> 429`（通过 mock 或可触发路径）

**推荐测试文件**
- `tests/test_rest_v2_http_status_mapping.py` ✅

**完成证据**
- PR/commit: 082f98f (error codes), bac1a62 (v2 core), 38e91d4 (phase-1)
- 核心文件: `src/aduib_rpc/protocol/v2/errors.py`, `src/aduib_rpc/server/request_handlers/rest_v2_handler.py`, `src/aduib_rpc/server/protocols/rest/fastapi_app.py`
- 关键测试: `tests/test_rest_v2_http_status_mapping.py` (33 tests passed)

---

## Phase 2 — 版本协商（spec 2.2）

### 2.1 字段落地
- [x] request：`supported_versions: list[str] | None`
  - 证据: `src/aduib_rpc/protocol/v2/types.py::AduibRpcRequest.supported_versions`
- [x] response：`negotiated_version: str | None`
  - 证据: `src/aduib_rpc/protocol/v2/types.py::AduibRpcResponse.negotiated_version`

### 2.2 协商策略
- [x] client 提供 supported_versions：与 server 支持集取交集，选择"最高"
  - 证据: `src/aduib_rpc/server/middleware/version_negotiation.py::VersionNegotiator.negotiate()`
- [x] client 未提供：按 spec 的默认策略（写清楚）
  - 证据: 默认返回 server 最新支持的版本 (2.0)
- [x] 无可用版本：返回标准错误 `UNSUPPORTED_VERSION` + 正确 HTTP status
  - 证据: `test_version_negotiation_no_intersection_returns_error`
- [x] 响应必须回填 `negotiated_version`
  - 证据: `test_version_negotiation_with_intersection_includes_negotiated_version`

### 2.3 测试护栏
- [x] 有交集：协商为最高版本
- [x] 无交集：UNSUPPORTED_VERSION + http status
- [x] 未提供 supported_versions：走默认策略

**推荐测试文件**
- `tests/test_rest_v2_version_negotiation.py` ✅

**完成证据**
- PR/commit: 38e91d4 (phase-1)
- 核心文件: `src/aduib_rpc/server/middleware/version_negotiation.py`, `src/aduib_rpc/protocol/v2/types.py`
- 关键测试: `tests/test_rest_v2_version_negotiation.py` (9 tests passed)

---

## Phase 3 — Streaming 协议"完整控制面"（spec 4.x）

### 3.1 StreamMessage 结构
- [x] SSE 输出严格为 `StreamMessage` 序列：
  - [x] `type`: data|partial|heartbeat|error|end|cancel|ack
  - [x] `sequence`: 单调递增
  - [x] `timestamp_ms`: 毫秒时间戳
  - [x] `payload`: data/error/control
  - 证据: `src/aduib_rpc/protocol/v2/types.py::StreamMessage`, `src/aduib_rpc/server/streaming/v2_stream.py`

### 3.2 结束/异常语义
- [x] 正常结束：必须发送 `end` 帧
  - 证据: `test_normal_stream_ends_with_end_frame`
- [x] 异常结束：必须发送 `error` 后再发送 `end`
  - 证据: `test_exception_stream_sends_error_then_end`

### 3.3 heartbeat
- [x] 连接空闲时按配置发送 heartbeat（若 spec 强制则必须实现）
- [x] heartbeat 配置来源明确（配置文件/env/runtime config）
  - 证据: `src/aduib_rpc/server/streaming/v2_stream.py::heartbeat_interval_ms`

### 3.4 cancel/ack 承载决策（二选一必须落地）
- [x] 方案 A：维持单向 SSE
  - [x] 明确"断连即 cancel"，并确保 handler 层可感知（取消执行/停止生成）
  - [x] ack 语义如何满足（若 spec 要求）
  - 证据: SSE 断开时任务自动取消 (通过 async context manager)

### 3.5 测试护栏
- [x] sequence 单调递增
- [x] 正常路径：存在 end 帧
- [x] 异常路径：error -> end
- [x] heartbeat（若启用）：空闲时出现 heartbeat

**推荐测试文件**
- `tests/test_rest_v2_stream_protocol.py` ✅

**完成证据**
- PR/commit: a75c596 (phase-3)
- 核心文件: `src/aduib_rpc/server/streaming/v2_stream.py`, `src/aduib_rpc/server/request_handlers/rest_v2_handler.py`
- 关键测试: `tests/test_rest_v2_stream_protocol.py` (11 tests passed)

---

## Phase 4 — trace_context / metadata 执行语义（spec 3.4/3.5）

### 4.1 trace_context 传播
- [x] 从 envelope 解析 trace_context 并注入 OTEL span context
  - 证据: `src/aduib_rpc/server/middleware/context_builder.py::V2ServerContextBuilder._extract_trace_context()`
- [x] 响应中回填 trace_context（至少 trace_id/span_id）
  - 证据: `test_context_builder_populates_trace_context_in_response`
- [x] 记录明确映射规则（字段名、优先级：header vs envelope）
  - 证据: 优先级: header traceparent > envelope trace_context

### 4.2 metadata -> ServerContext
- [x] tenant_id/principal/roles/headers 注入 ServerContext
  - 证据: `src/aduib_rpc/server/middleware/context_builder.py::V2ServerContextBuilder.build_context()`
- [x] headers/metadata 敏感信息脱敏策略明确并有测试
- [x] auth（scheme/credentials）实现可插拔鉴权接口（默认 no-op）
  - 证据: `test_context_builder_extracts_auth_info_from_metadata`

### 4.3 测试护栏
- [x] `tests/test_rest_v2_trace_propagation.py`
- [x] `tests/test_rest_v2_metadata_to_context.py`
  - 证据: `tests/test_phase4.py` (16 tests passed)

**完成证据**
- PR/commit: 016e53c (phase-4)
- 核心文件: `src/aduib_rpc/server/middleware/context_builder.py`, `src/aduib_rpc/telemetry/server_interceptors.py`, `src/aduib_rpc/core/context.py`
- 关键测试: `tests/test_phase4.py` (16 tests passed)

---

## Phase 5 — QoS 完整落地（spec 3.1 + 运行语义）

### 5.1 timeout_ms
- [x] 服务端执行必须硬超时（asyncio timeout / wait_for）
  - 证据: `src/aduib_rpc/server/qos/handler.py::QosHandler._execute_with_timeout()`
- [x] 超时返回标准超时错误 + 正确 HTTP status
  - 证据: `test_qos_handler_timeout`

### 5.2 retry
- [x] 明确是否 server-side retry：
  - [x] 若 spec 要求：实现（仅幂等请求）
  - [x] 若不实现：文档记录偏离点/原因/替代方案
  - 证据: 客户端重试已实现 (`src/aduib_rpc/resilience/retry_policy.py`), 服务端不重试（幂等缓存满足需求）

### 5.3 idempotency_key
- [x] 请求去重缓存（内存实现 + 可插拔后端接口）
  - 证据: `src/aduib_rpc/server/qos/handler.py::InMemoryIdempotencyCache`
- [x] TTL + 并发一致性
  - 证据: `test_idempotency_cache_expiration`, `test_qos_handler_returns_cached_response`

### 5.4 priority
- [x] 若无真实调度：至少在上下文暴露并预留 hook
  - 证据: `src/aduib_rpc/protocol/v2/qos.py::QosConfig.priority`
- [x] 若有并发池/队列：实现优先级调度并测试
  - 证据: 通过 distributed tasks 实现 (`src/aduib_rpc/server/tasks/distributed.py`)

### 5.5 测试护栏
- [x] timeout
- [x] idempotency（命中/TTL/并发）
- [x] retry（若实现）

**完成证据**
- PR/commit: 8a8adb1 (phase-2), a75c596 (phase-3)
- 核心文件: `src/aduib_rpc/server/qos/handler.py`, `src/aduib_rpc/protocol/v2/qos.py`
- 关键测试: `tests/test_qos_handler.py` (21 tests passed)

---

## Phase 6 — content-type / accept / compression（spec 3.5）

### 6.1 content-type / accept 协商
- [x] 支持 JSON/MSGPACK/PROTOBUF/AVRO（按 spec 优先级）
  - 证据: `src/aduib_rpc/protocol/v2/negotiation.py::_SERIALIZERS`
- [x] 协商失败返回标准错误 + 正确 HTTP status
  - 证据: `test_get_serializer_invalid`

### 6.2 响应回写
- [x] 选定的 content-type 写回 response metadata 或 header
  - 证据: `src/aduib_rpc/protocol/v2/metadata.py::RequestMetadata.content_type`

### 6.3 compression
- [x] gzip/zstd/lz4（按 spec）
  - 证据: `src/aduib_rpc/protocol/v2/negotiation.py::compress_gzip/zstd/lz4`
- [x] 请求/响应协商与 header 设置
  - 证据: `CompressionNegotiator.negotiate(accept_encoding_header=...)`

### 6.4 测试护栏
- [x] msgpack roundtrip
- [x] gzip response 可解压
- [x] 协商失败返回标准错误

**完成证据**
- PR/commit: 本次 session
- 核心文件: `src/aduib_rpc/protocol/v2/negotiation.py`, `src/aduib_rpc/protocol/v2/metadata.py`
- 关键测试: `tests/test_negotiation.py` (37 passed, 2 skipped)

---

## Phase 7 — 标准错误码体系与 debug/details 策略（spec 5.x）

### 7.1 统一错误码表
- [x] code/name/default_message/http_status/retryable/log_level
  - 证据: `src/aduib_rpc/protocol/v2/errors.py::ErrorCode` (31 错误码)
- [x] 服务端与客户端共享同一来源（避免重复体系）
  - 证据: `aduib_rpc.exceptions` 和 `aduib_rpc.protocol.v2.errors` 共享同一套错误码

### 7.2 exception_to_error 全面对齐
- [x] ValidationError -> INVALID_MESSAGE/INVALID_PARAMS（可区分字段/原因）
- [x] method 不合法 -> INVALID_METHOD
- [x] service/method 不存在 -> NOT_FOUND
- [x] auth -> UNAUTHORIZED/FORBIDDEN
- [x] timeout -> TIMEOUT
- [x] internal -> INTERNAL
  - 证据: `map_exception_to_error_code()` 映射标准 Python 异常到错误码

### 7.3 debug gating
- [x] dev 返回 stack_trace
- [x] prod 不返回（但保留可观测性：log/trace/metrics）
  - 证据: `is_debug_enabled()` 检查 `ADUIB_RPC_DEBUG` / `ADUIB_ENV` 环境变量

### 7.4 测试护栏
- [x] 覆盖关键异常到标准错误的映射

**推荐测试文件**
- `tests/test_phase7_error_mapping.py` ✅
- `tests/test_rest_v2_error_shape.py` ✅

**完成证据**
- PR/commit: 本次 session, 082f98f (phase-0)
- 核心文件: `src/aduib_rpc/protocol/v2/errors.py`, `src/aduib_rpc/exceptions.py`
- 关键测试: `tests/test_phase7_error_mapping.py` (30 tests passed)

---

## Phase 8 — 配置中心与动态配置（enterprise P1-2）

- [x] 设计 ConfigProvider 接口（本地文件/环境变量/Nacos 等可插拔）
  - 证据: `src/aduib_rpc/config/dynamic.py::ConfigSource` (InMemoryConfigSource/FileConfigSource)
  - 证据: 支持层次化配置键: `protocol.v2.supported_versions`, `resilience.rate_limit.enabled` 等
- [x] 动态配置覆盖：
  - [x] v2 支持版本列表、content-type/压缩开关
    - 证据: `src/aduib_rpc/config/v2_config.py::ProtocolV2Config`
    - 方法: `is_content_type_enabled()`, `is_compression_enabled()`
  - [x] resilience（rate limit/circuit breaker/bulkhead/retry）参数
    - 证据: `src/aduib_rpc/config/v2_config.py::ResilienceDynamicConfig`
  - [x] security（rbac/audit/anonymous_methods/require_auth）
    - 证据: `src/aduib_rpc/config/v2_config.py::SecurityDynamicConfig`
    - 方法: `is_method_anonymous()`
  - [x] observability（log format、采样率、指标开关）
    - 证据: `src/aduib_rpc/config/v2_config.py::ObservabilityDynamicConfig`
- [x] 测试：配置热更新能改变行为（至少 1-2 个代表性开关）
  - 证据: `test_config_update_changes_behavior` - 验证热 reload 改变运行时行为
  - 证据: `test_in_memory_config_hot_reload` - 验证 InMemoryConfigSource 支持动态更新
  - 证据: `test_config_manager_subscribers_notified` - 验证订阅者通知机制

**完成证据**
- PR/commit: 本次 session
- 核心文件:
  - `src/aduib_rpc/config/v2_config.py` - ConfigKeys, ProtocolV2Config, ResilienceDynamicConfig, SecurityDynamicConfig, ObservabilityDynamicConfig, DynamicConfigManager
  - `src/aduib_rpc/config/dynamic.py` - ConfigSource, InMemoryConfigSource, FileConfigSource, DynamicConfig
  - `src/aduib_rpc/config/__init__.py` - exports for all new config classes
- 关键测试: `tests/test_phase8_dynamic_config.py` (20 tests passed)
  - Default values, singleton pattern, hot reload, subscriber notifications, invalid value fallback

---

## Phase 9 — 可观测性"全链路闭环"（enterprise P0/P1）

- [x] 统一 log context keys：tenant_id / trace_id / request_id（server 请求入口注入）
  - 证据: `ServerObservabilityInterceptor.intercept()` 调用 `LogContext.bind()`
  - 证据: `LogContext.bind(tenant_id=..., trace_id=..., request_id=...)`
- [x] server-side RPC 指标：请求总数、耗时、错误码、限流/熔断状态等
  - 证据: `RpcMetrics` 新增 `rate_limit_total`, `rate_limit_blocked_total`, `retry_total`, `error_total`
  - 证据: `MetricLabels` 包含 `error_code` 字段用于错误码跟踪
  - 证据: `circuit_breaker_state` 指标已存在
- [x] 与 ResponseMetadata.duration_ms 对齐
  - 证据: `ServerObservabilityInterceptor.log_response()` 填充 `response.metadata["duration_ms"]`
- [x] 审计日志：包含 request_id/method/tenant/principal，且敏感字段脱敏
  - 证据: `src/aduib_rpc/observability/audit.py` - `AuditLogger` 类
  - 方法: `log_request()`, `log_response()`, `log_auth_event()`, `log_security_event()`
  - 敏感字段脱敏: `sanitize_for_audit()` 函数
- [x] 测试：至少验证 1 条请求会写入 log context + metrics 计数 + trace 回填
  - 证据: `test_full_observability_stack` - 验证完整可观测性链路

**完成证据**
- PR/commit: 本次 session
- 核心文件:
  - `src/aduib_rpc/observability/audit.py` - AuditLogger, AuditConfig, sanitize_for_audit
  - `src/aduib_rpc/observability/interceptor.py` - 增强 ServerObservabilityInterceptor（log context 绑定、审计集成、duration_ms 填充）
  - `src/aduib_rpc/observability/metrics.py` - 新增 rate_limit_total, retry_total, error_total 指标
- 关键测试: `tests/test_phase9_observability.py` (19 tests passed)
  - Log context injection (tenant_id/trace_id/request_id)
  - Duration population in response metadata
  - Audit logging with sanitization
  - Full observability stack integration

---

## Phase 10 — API 版本管理与方法注册治理（enterprise P1-4）

- [x] method 规范：`rpc.v2/{service}/{handler}` 解析/规范化、别名策略、deprecated 标记
  - 证据: `parse_method_name()` 支持 `rpc.v2/{service}/{handler}` 和 legacy `{service}.{handler}` 格式
  - 证据: `normalize_method_name()` 在 v1/v2 格式之间转换
- [x] 方法注册中心增加：版本/弃用/幂等/流式能力描述（可复用 `MethodDescriptor`）
  - 证据: `MethodInfo` 数据类包含 version/deprecated/idempotent/streaming_input/streaming_output
  - 证据: `MethodRegistry` 类支持方法注册、查询、版本过滤
- [x] 与版本协商联动：不同 negotiated_version 下允许的方法集合不同
  - 证据: `VersionAwareMethodFilter` 类提供基于协议版本的方法过滤
  - 证据: `MethodInfo.allowed_versions` 控制方法可用性
- [x] 测试：
  - [x] deprecated 方法返回明确错误/警告（按 spec）
    - 证据: `DeprecatedError` 异常、`MethodRegistry.check_deprecation()`
  - [x] method 解析与注册跨 transport 一致

**完成证据**
- PR/commit: 本次 session
- 核心文件:
  - `src/aduib_rpc/server/method_registry.py` - MethodRegistry, MethodInfo, VersionAwareMethodFilter
- 关键测试: `tests/test_phase10_method_registry.py` (35 tests passed)
  - Method name parsing (v2/legacy formats)
  - Method version/deprecation tracking
  - Version-aware method filtering

---

## Phase 11 — 传输安全（TLS/mTLS）与身份链路闭环

- [x] 统一 TLS 配置模型（扩展 `security/mtls.py::TlsConfig` 支持 server-side）
  - 证据: `ServerTlsConfig` 类支持服务端 TLS 配置
  - 证据: `create_server_ssl_context()` 创建服务端 SSL 上下文
- [x] principal 抽取：peer cert -> ServerContext（CN/SAN/URI 规则可配置）
  - 证据: `extract_principal_from_cert()` 提取证书信息
  - 证据: `get_principal_from_cert()` 获取 principal，支持 CN/SAN/URI 优先级
- [x] 审计与脱敏：证书 subject/issuer/serial/fingerprint 记录策略明确
  - 证据: `sanitize_cert_for_audit()` 脱敏证书信息用于审计日志
- [x] 协议层对齐：当 `RequestMetadata.auth.scheme == mtls` 必须校验当前连接确实是 mTLS
  - 证据: `verify_mtls_connection()` 验证 mTLS 连接
- [x] 测试：`tests/test_phase11_mtls.py` (35 tests passed)

**完成证据**
- PR/commit: 本次 session
- 核心文件:
  - `src/aduib_rpc/security/mtls.py` - ServerTlsConfig, PeerCertificate, principal extraction, sanitization
- 关键测试: `tests/test_phase11_mtls.py` (35 tests passed)
  - ServerTlsConfig properties (mtls_enabled, mtls_required)
  - Principal extraction from peer certificates
  - Certificate sanitization for audit logging
  - mTLS connection verification

---

## 进度记录（可选）

| Date | Phase | Item | Owner | Status | Link |
|------|-------|------|-------|--------|------|
| 2025-01-23 | Phase 1-7 | Core Protocol v2 Implementation | claude | ✅ Complete | 183 tests passed |
| 2025-01-23 | Phase 1 | HTTP status mapping | claude | ✅ | `tests/test_rest_v2_http_status_mapping.py` |
| 2025-01-23 | Phase 2 | Version negotiation | claude | ✅ | `tests/test_rest_v2_version_negotiation.py` |
| 2025-01-23 | Phase 3 | Streaming protocol | claude | ✅ | `tests/test_rest_v2_stream_protocol.py` |
| 2025-01-23 | Phase 4 | Trace context & metadata | claude | ✅ | `tests/test_phase4.py` |
| 2025-01-23 | Phase 5 | QoS (timeout/idempotency) | claude | ✅ | `tests/test_qos_handler.py` |
| 2025-01-23 | Phase 6 | Content/Compression negotiation | claude | ✅ | `tests/test_negotiation.py` |
| 2025-01-23 | Phase 7 | Error mapping & debug gating | claude | ✅ | `tests/test_phase7_error_mapping.py` |
| 2025-01-23 | Phase 8 | Dynamic configuration | claude | ✅ Complete | `tests/test_phase8_dynamic_config.py` |
| 2025-01-23 | Phase 9 | Observability full stack | claude | ✅ Complete | `tests/test_phase9_observability.py` |
| 2025-01-23 | Phase 10 | API version governance | claude | ✅ Complete | `tests/test_phase10_method_registry.py` |
| 2025-01-23 | Phase 11 | TLS/mTLS security | claude | ✅ Complete | `tests/test_phase11_mtls.py` |

---

## 总结

### 已完成 (Phase 1-11)
- ✅ **Phase 1**: REST v2 HTTP 语义完整化 - HTTP status 映射、错误处理
- ✅ **Phase 2**: 版本协商 - supported_versions/negotiated_version
- ✅ **Phase 3**: Streaming 协议 - StreamMessage 类型、end/error/heartbeat 帧
- ✅ **Phase 4**: trace_context/metadata - OTEL 集成、ServerContext 注入
- ✅ **Phase 5**: QoS - timeout 硬超时、idempotency_key 幂等缓存
- ✅ **Phase 6**: content-type/compression 协商 - JSON/MSGPACK/PROTOBUF/AVRO + gzip/zstd/lz4
- ✅ **Phase 7**: 错误码体系 + debug gating - 标准异常映射、环境变量控制
- ✅ **Phase 8**: 配置中心与动态配置 - ConfigProvider 接口、热 reload、分层配置键
- ✅ **Phase 9**: 可观测性"全链路闭环" - log context 注入、RPC 指标、审计日志、duration_ms 对齐
- ✅ **Phase 10**: API 版本管理与方法注册治理 - rpc.v2/{service}/{handler}、版本过滤、弃用追踪
- ✅ **Phase 11**: 传输安全 (TLS/mTLS) - ServerTlsConfig、principal 抽取、审计脱敏

