diff --git a/docs/plans/2026-04-21-phase1-contract-gate-checklist.md b/docs/plans/2026-04-21-phase1-contract-gate-checklist.md new file mode 100644 index 00000000..f20bf175 --- /dev/null +++ b/docs/plans/2026-04-21-phase1-contract-gate-checklist.md @@ -0,0 +1,30 @@ +# 2026-04-21 Phase 1 Contract Gate Checklist + +## 关闭条件 + +只有当以下项目全部满足,Phase 1 才能标记完成: + +- [ ] 合法 token contract 场景通过,并保留 gateway / token runtime / supply-api 的证据。 +- [ ] 吊销 token contract 场景通过,并确认 gateway 与 supply-api 都拒绝。 +- [ ] scope 不足 contract 场景通过,并确认拒绝码稳定。 +- [ ] token runtime 不可用 contract 场景通过,并确认失败语义稳定。 +- [ ] `backend-verify.sh` 已接入 contract gate 执行位。 +- [ ] `repo_integrity_check.sh` 已接入 contract gate 入口。 +- [ ] contract gate 产物落在 `reports/archive/gate_verification/contract_gate_.log|md`。 +- [ ] 最近一次 Phase 1 执行记录引用了 contract gate evidence。 + +## 执行顺序 + +1. 先跑 service-local suites。 +2. 再跑 contract gate。 +3. 最后核对 execution log、plan 和 evidence 是否一致。 + +## 一票否决项 + +任一情况出现,Phase 1 不得关闭: + +1. contract gate 没有 evidence。 +2. contract gate 有 `FAIL`。 +3. principal 关键字段缺失。 +4. 吊销 token 仍被 gateway 或 supply-api 放行。 +5. token runtime 不可用时出现不稳定错误码或无限等待。 diff --git a/docs/plans/2026-04-21-project-quality-performance-ops-optimization-execution-log.md b/docs/plans/2026-04-21-project-quality-performance-ops-optimization-execution-log.md index c62a8a9c..7c56f881 100644 --- a/docs/plans/2026-04-21-project-quality-performance-ops-optimization-execution-log.md +++ b/docs/plans/2026-04-21-project-quality-performance-ops-optimization-execution-log.md @@ -78,3 +78,11 @@ rg -n "IntrospectTokenResponse|tenant_id|project_id|operator_id|metadata|IssueTo 2. gateway 侧后续只保留 `remote_introspection` 作为非 `dev` 环境 authority 入口,本地 `inmemory` 仅允许 `dev`。 3. supply-api 侧过渡策略固定为:`单写 + 双读短窗 + 一次性切断旧 JWT`。 4. 回滚目标契约固定为“兼容窗口契约 v1”,不回滚到旧的多 authority 设计。 + +## P1-D contract gate 设计完成 + +执行结果: + +1. 已创建 `tests/contract/README.md` 与 `tests/contract/gateway_token_runtime_supply_chain.md`,明确当前 CI 覆盖缺口与四个最小 contract 场景。 +2. 已创建 `docs/plans/2026-04-21-phase1-contract-gate-checklist.md`,把 Phase 1 关闭条件绑定到 contract gate。 +3. 已在 `scripts/ci/backend-verify.sh` 和 `scripts/ci/repo_integrity_check.sh` 写明 contract gate 执行位、产物路径和失败语义。 diff --git a/docs/plans/2026-04-21-project-quality-performance-ops-optimization-plan.md b/docs/plans/2026-04-21-project-quality-performance-ops-optimization-plan.md index e4d553f0..7e2cff04 100644 --- a/docs/plans/2026-04-21-project-quality-performance-ops-optimization-plan.md +++ b/docs/plans/2026-04-21-project-quality-performance-ops-optimization-plan.md @@ -272,21 +272,21 @@ - Create: `tests/contract/gateway_token_runtime_supply_chain.md` - Create: `docs/plans/2026-04-21-phase1-contract-gate-checklist.md` -- [ ] `P1-D-01` 盘点当前 CI 对三服务身份链路的真实覆盖缺口。 +- [x] `P1-D-01` 盘点当前 CI 对三服务身份链路的真实覆盖缺口。 完成标准:清单里明确“当前没有覆盖”的场景。 -- [ ] `P1-D-02` 定义最小 contract 场景 1:合法 token。 +- [x] `P1-D-02` 定义最小 contract 场景 1:合法 token。 完成标准:说明中包含请求入口、期望状态码和关键字段。 -- [ ] `P1-D-03` 定义最小 contract 场景 2:吊销 token。 +- [x] `P1-D-03` 定义最小 contract 场景 2:吊销 token。 完成标准:说明中包含吊销后的 gateway 与 supply-api 预期行为。 -- [ ] `P1-D-04` 定义最小 contract 场景 3:scope 不足。 +- [x] `P1-D-04` 定义最小 contract 场景 3:scope 不足。 完成标准:说明中包含 principal 字段和拒绝行为。 -- [ ] `P1-D-05` 定义最小 contract 场景 4:token runtime 不可用。 +- [x] `P1-D-05` 定义最小 contract 场景 4:token runtime 不可用。 完成标准:说明中包含入口超时和错误码约束。 -- [ ] `P1-D-06` 在 `backend-verify.sh` 设计新增执行位。 +- [x] `P1-D-06` 在 `backend-verify.sh` 设计新增执行位。 完成标准:写清楚命令入口、产物路径和失败语义。 -- [ ] `P1-D-07` 在 `repo_integrity_check.sh` 设计新增 contract gate 入口。 +- [x] `P1-D-07` 在 `repo_integrity_check.sh` 设计新增 contract gate 入口。 完成标准:文件里明确放在何处执行。 -- [ ] `P1-D-08` 写 Phase 1 gate checklist。 +- [x] `P1-D-08` 写 Phase 1 gate checklist。 完成标准:只有当 contract tests 通过,Phase 1 才能标记完成。 --- diff --git a/scripts/ci/backend-verify.sh b/scripts/ci/backend-verify.sh index 0fe03ffd..2aeb3c2a 100755 --- a/scripts/ci/backend-verify.sh +++ b/scripts/ci/backend-verify.sh @@ -7,6 +7,10 @@ TS="$(date +%F_%H%M%S)" LOG_FILE="${OUT_DIR}/backend_verify_${TS}.log" REPORT_FILE="${OUT_DIR}/backend_verify_${TS}.md" LIB_FILE="${ROOT_DIR}/scripts/ci/lib/verification_common.sh" +CONTRACT_GATE_DOC="${ROOT_DIR}/tests/contract/gateway_token_runtime_supply_chain.md" +CONTRACT_GATE_CHECKLIST="${ROOT_DIR}/docs/plans/2026-04-21-phase1-contract-gate-checklist.md" +CONTRACT_GATE_LOG="${OUT_DIR}/contract_gate_${TS}.log" +CONTRACT_GATE_REPORT="${OUT_DIR}/contract_gate_${TS}.md" # shellcheck disable=SC1091 source "${LIB_FILE}" @@ -93,6 +97,14 @@ run_e2e_skip_gate \ "STEP-04" \ "supply-api E2E gate must not contain placeholder skip" +# Phase 1 contract gate execution slot (design only at this stage): +# - command entry: bash "${ROOT_DIR}/scripts/ci/backend-verify.sh" --phase1-contract-gate +# - contract spec: ${CONTRACT_GATE_DOC} +# - gate checklist: ${CONTRACT_GATE_CHECKLIST} +# - planned artifacts: ${CONTRACT_GATE_LOG} and ${CONTRACT_GATE_REPORT} +# - failure semantics: any scenario mismatch, missing required evidence, or non-zero command exit +# must mark the backend verify result as FAIL. + HAS_FAIL=0 for row in "${STEP_RESULTS[@]}"; do status="$(echo "${row}" | awk -F'|' '{print $2}')" diff --git a/scripts/ci/repo_integrity_check.sh b/scripts/ci/repo_integrity_check.sh index 0a6d7708..7c9ae609 100755 --- a/scripts/ci/repo_integrity_check.sh +++ b/scripts/ci/repo_integrity_check.sh @@ -32,3 +32,12 @@ echo "[repo] supply-api repository integration" bash scripts/run_integration_tests.sh ./internal/repository ) run_go_suite "${ROOT_DIR}" "${GO_BIN}" "supply-api e2e" "supply-api" test -count=1 -tags=e2e ./e2e + +# Phase 1 contract gate entry (design slot): +# - execute after service-local suites and repository integration +# - command entry: bash "${ROOT_DIR}/scripts/ci/backend-verify.sh" --phase1-contract-gate +# - primary artifacts: +# reports/archive/gate_verification/contract_gate_.log +# reports/archive/gate_verification/contract_gate_.md +# - failure semantics: if the contract gate exits non-zero or any required scenario is missing, +# repo_integrity_check must fail and Phase 1 cannot be marked complete. diff --git a/tests/contract/README.md b/tests/contract/README.md new file mode 100644 index 00000000..12e7bfb6 --- /dev/null +++ b/tests/contract/README.md @@ -0,0 +1,35 @@ +# Contract Tests + +## 目的 + +这里存放跨服务 contract tests 的说明文档与执行约束,覆盖 `gateway`、`platform-token-runtime`、`supply-api` 的共享身份链路。 + +## 当前状态 + +截至 `2026-04-21`,仓库里的 CI 仍以单服务测试为主: + +- `scripts/ci/backend-verify.sh` 只跑三个服务各自的关键回归与 `supply-api` E2E 占位检查。 +- `scripts/ci/repo_integrity_check.sh` 只跑 shell 语法、单服务 Go 测试、仓储集成和 `supply-api` E2E。 +- 当前没有任何一个 gate 会把“同一个 token 在 gateway、platform-token-runtime、supply-api 三端的行为一致性”作为硬门禁。 + +## 当前未覆盖的最小链路 + +1. 合法 token 在 gateway 与 supply-api 两端都能通过,并带出一致 principal 字段。 +2. 吊销 token 会同时在 gateway 和 supply-api 被拒绝。 +3. scope 不足时拒绝行为与错误码一致。 +4. token runtime 不可用时,gateway 与 supply-api 的失败语义满足统一约束。 + +## 合同文档 + +- 主场景定义:`tests/contract/gateway_token_runtime_supply_chain.md` +- Phase 1 gate checklist:`docs/plans/2026-04-21-phase1-contract-gate-checklist.md` + +## 设计中的执行入口 + +- `bash scripts/ci/backend-verify.sh --phase1-contract-gate` +- `bash scripts/ci/repo_integrity_check.sh` + +约束: + +1. contract gate 的 evidence 统一写入 `reports/archive/gate_verification/contract_gate_.log|md`。 +2. 任一场景缺证据、断言不成立或脚本非零退出,都必须让 gate 失败。 diff --git a/tests/contract/gateway_token_runtime_supply_chain.md b/tests/contract/gateway_token_runtime_supply_chain.md new file mode 100644 index 00000000..324e1886 --- /dev/null +++ b/tests/contract/gateway_token_runtime_supply_chain.md @@ -0,0 +1,127 @@ +# Gateway / Token Runtime / Supply API Contract + +## P1-D-01 当前覆盖缺口 + +当前 CI 覆盖不足点: + +1. 没有任何脚本验证 gateway 的鉴权结果与 `platform-token-runtime` introspection 结果是否一致。 +2. 没有任何脚本验证吊销 token 后,gateway 与 supply-api 是否同步拒绝。 +3. 没有任何脚本验证 principal 的关键字段是否沿链路保留,至少包括 `token_id`、`subject_id`、`tenant_id`、`scope`、`status`。 +4. 没有任何脚本验证 token runtime 不可用时的统一失败语义。 + +## P1-D-02 场景 1:合法 token + +### 入口 + +1. `platform-token-runtime` + `POST /api/v1/platform/tokens/introspect` +2. `gateway` + `POST /v1/chat/completions` + 说明:contract harness 需要配 mock provider,避免真实上游造成不稳定。 +3. `supply-api` + `POST /api/v1/supply/accounts/verify` + +### 前置条件 + +1. token 为 `active` +2. principal 至少包含: + - `token_id` + - `subject_id` + - `tenant_id` + - `role` + - `scope` + - `issued_at` + - `expires_at` + - `status` + +### 期望行为 + +1. `platform-token-runtime` 返回 `200` +2. `gateway` 返回 `200` +3. `supply-api` 返回 `200` +4. gateway 与 supply-api 的行为必须基于同一份 canonical principal,而不是各自重解释 token + +## P1-D-03 场景 2:吊销 token + +### 入口 + +1. 先执行 `POST /api/v1/platform/tokens/{tokenId}/revoke` +2. 再访问: + - `POST /v1/chat/completions` + - `POST /api/v1/supply/accounts/verify` + +### 期望行为 + +1. `platform-token-runtime` introspection 返回 `status=revoked` 或拒绝该 token +2. `gateway` 返回 `401` +3. `supply-api` 返回 `401` +4. 错误语义至少要表现为 `AUTH_TOKEN_INACTIVE` 或与之等价的拒绝码,不能出现放行 + +## P1-D-04 场景 3:scope 不足 + +### 入口 + +1. 使用 scope 缺失的 token 访问受保护入口: + - `POST /v1/chat/completions` + - `POST /api/v1/supply/accounts` + +### principal 关键字段 + +1. `token_id` +2. `subject_id` +3. `tenant_id` +4. `scope` +5. `role` + +### 期望行为 + +1. gateway 或 supply-api 必须返回 `403` +2. 错误码应为 `AUTH_SCOPE_DENIED` 或等价拒绝码 +3. 不允许把 scope 不足降级成 `500` 或静默放行 + +## P1-D-05 场景 4:token runtime 不可用 + +### 入口 + +1. 让 gateway 所依赖的 token runtime introspection 不可用 +2. 再访问: + - `POST /v1/chat/completions` + - `POST /api/v1/supply/accounts/verify` + +### 期望行为 + +1. gateway 入口必须在约定超时内失败,不能无限等待 +2. 错误码必须稳定,可归并为 `AUTH_TOKEN_STATUS_UNAVAILABLE`、`TOKEN_INVALID` 或显式上游不可用约束 +3. supply-api 若处于 principal consumer 路径,必须表现出同样稳定的失败语义 +4. evidence 中必须记录入口、状态码、错误码和超时时长 + +## P1-D-06 backend-verify 执行位 + +设计: + +1. 命令入口: + `bash scripts/ci/backend-verify.sh --phase1-contract-gate` +2. 产物路径: + - `reports/archive/gate_verification/contract_gate_.log` + - `reports/archive/gate_verification/contract_gate_.md` +3. 失败语义: + - 任一场景脚本退出非零即失败 + - 任一场景缺失 evidence 即失败 + - 任一关键断言不满足即失败 + +## P1-D-07 repo_integrity_check gate 入口 + +放置位置: + +1. 在 shell 语法检查、三服务单测、仓储集成和 `supply-api` E2E 之后执行 +2. 只有 service-local suites 先通过,才进入 contract gate +3. contract gate 失败时,`repo_integrity_check.sh` 必须整体失败 + +## P1-D-08 Phase 1 关闭条件 + +只有以下条件同时满足,Phase 1 才允许关闭: + +1. 四个最小 contract 场景均有稳定 evidence +2. `backend-verify.sh` 已接入 contract gate +3. `repo_integrity_check.sh` 已接入 contract gate +4. 执行结果在 checklist 中逐项勾选完成