docs(ci): define phase1 contract gate
Add the cross-service contract gate documentation, create the Phase 1 checklist, wire explicit contract-gate design slots into backend-verify and repo integrity scripts, and mark P1-D complete in the plan.
This commit is contained in:
30
docs/plans/2026-04-21-phase1-contract-gate-checklist.md
Normal file
30
docs/plans/2026-04-21-phase1-contract-gate-checklist.md
Normal file
@@ -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_<timestamp>.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 不可用时出现不稳定错误码或无限等待。
|
||||
@@ -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 执行位、产物路径和失败语义。
|
||||
|
||||
@@ -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 才能标记完成。
|
||||
|
||||
---
|
||||
|
||||
@@ -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}')"
|
||||
|
||||
@@ -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_<timestamp>.log
|
||||
# reports/archive/gate_verification/contract_gate_<timestamp>.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.
|
||||
|
||||
35
tests/contract/README.md
Normal file
35
tests/contract/README.md
Normal file
@@ -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_<timestamp>.log|md`。
|
||||
2. 任一场景缺证据、断言不成立或脚本非零退出,都必须让 gate 失败。
|
||||
127
tests/contract/gateway_token_runtime_supply_chain.md
Normal file
127
tests/contract/gateway_token_runtime_supply_chain.md
Normal file
@@ -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_<timestamp>.log`
|
||||
- `reports/archive/gate_verification/contract_gate_<timestamp>.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 中逐项勾选完成
|
||||
Reference in New Issue
Block a user