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 1ed41df3..eef5e17f 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 @@ -61,3 +61,11 @@ rg -n "IntrospectTokenResponse|tenant_id|project_id|operator_id|metadata|IssueTo 1. 已在 `platform-token-runtime/README.md` 明确 `platform-token-runtime` 是唯一 token authority。 2. 文档现在把 canonical principal 的最小字段边界写死为 `token_id`、`subject_id`、`tenant_id`、`role`、`scope`、`issued_at`、`expires_at`、`status`。 3. 文档同时要求未来扩展字段必须同步更新 DDL、OpenAPI、存储模型和审计字段,避免边界漂移。 + +## P1-B token runtime schema 对齐决策 + +执行结果: + +1. 已创建 `docs/plans/2026-04-21-token-runtime-schema-alignment-notes.md`,记录 schema、model、runtime store、audit store 的字段差异。 +2. 单一决策为“保留字段并贯穿”,不采用删除字段 / shrink SQL 路线。 +3. 后续实现顺序固定为:`model -> store -> API -> audit -> tests`。 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 f9bde34a..21c15eeb 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 @@ -220,21 +220,21 @@ - Modify: `platform-token-runtime/internal/auth/service/postgres_audit_store.go` - Create: `docs/plans/2026-04-21-token-runtime-schema-alignment-notes.md` -- [ ] `P1-B-01` 打开 schema,圈出 `tenant_id`、`project_id`、`operator_id`、`metadata` 所在列。 +- [x] `P1-B-01` 打开 schema,圈出 `tenant_id`、`project_id`、`operator_id`、`metadata` 所在列。 完成标准:对齐笔记里列出字段和表名。 -- [ ] `P1-B-02` 打开 `TokenRecord`,列出当前缺失字段。 +- [x] `P1-B-02` 打开 `TokenRecord`,列出当前缺失字段。 完成标准:差异清单写入对齐笔记。 -- [ ] `P1-B-03` 决策“保留字段并贯穿”还是“删除字段并收缩契约”。 +- [x] `P1-B-03` 决策“保留字段并贯穿”还是“删除字段并收缩契约”。 完成标准:对齐笔记里只保留一个决策,不允许双轨。 -- [ ] `P1-B-04` 如果选择保留,先写字段迁移顺序。 +- [x] `P1-B-04` 如果选择保留,先写字段迁移顺序。 完成标准:顺序包含 model、store、API、audit、tests。 -- [ ] `P1-B-05` 如果选择删除,先写 shrink SQL 和历史数据影响说明。 +- [x] `P1-B-05` 如果选择删除,先写 shrink SQL 和历史数据影响说明。 完成标准:说明中覆盖 fresh setup 和 existing DB 两种情况。 -- [ ] `P1-B-06` 检查 `postgres_runtime_store.go` 的 `INSERT`/`SELECT` 字段映射。 +- [x] `P1-B-06` 检查 `postgres_runtime_store.go` 的 `INSERT`/`SELECT` 字段映射。 完成标准:每个字段映射都被记录。 -- [ ] `P1-B-07` 检查 `postgres_audit_store.go` 的写入字段映射。 +- [x] `P1-B-07` 检查 `postgres_audit_store.go` 的写入字段映射。 完成标准:审计模型缺口被单独列出。 -- [ ] `P1-B-08` 为字段一致性写一个最小执行清单。 +- [x] `P1-B-08` 为字段一致性写一个最小执行清单。 完成标准:包含“改 model、改 SQL、改 test、跑验证”四类动作。 ### Task P1-C: 收敛 gateway 与 supply-api 的身份实现 diff --git a/docs/plans/2026-04-21-token-runtime-schema-alignment-notes.md b/docs/plans/2026-04-21-token-runtime-schema-alignment-notes.md new file mode 100644 index 00000000..6ed5a31d --- /dev/null +++ b/docs/plans/2026-04-21-token-runtime-schema-alignment-notes.md @@ -0,0 +1,263 @@ +# 2026-04-21 Token Runtime Schema Alignment Notes + +## 1. 输入范围 + +- `sql/postgresql/token_runtime_schema_v1.sql` +- `platform-token-runtime/internal/auth/service/inmemory_runtime.go` +- `platform-token-runtime/internal/auth/service/postgres_runtime_store.go` +- `platform-token-runtime/internal/auth/service/postgres_audit_store.go` +- `platform-token-runtime/internal/auth/service/token_verifier.go` +- `platform-token-runtime/internal/httpapi/token_api.go` + +## 2. P1-B-01 Schema 字段落点 + +### 2.1 `auth_platform_tokens` + +来源:`sql/postgresql/token_runtime_schema_v1.sql:11` + +| 字段 | 列位置 | 说明 | +|---|---|---| +| `tenant_id` | `sql/postgresql/token_runtime_schema_v1.sql:16` | token 归属租户 | +| `project_id` | `sql/postgresql/token_runtime_schema_v1.sql:17` | token 归属项目 | +| `operator_id` | 无 | 当前 token 主表没有该列 | +| `metadata` | 无 | 当前 token 主表没有该列 | + +### 2.2 `auth_token_audit_events` + +来源:`sql/postgresql/token_runtime_schema_v1.sql:47` + +| 字段 | 列位置 | 说明 | +|---|---|---| +| `tenant_id` | `sql/postgresql/token_runtime_schema_v1.sql:57` | 审计事件租户 | +| `project_id` | `sql/postgresql/token_runtime_schema_v1.sql:58` | 审计事件项目 | +| `operator_id` | `sql/postgresql/token_runtime_schema_v1.sql:59` | 操作人 | +| `metadata` | `sql/postgresql/token_runtime_schema_v1.sql:61` | 事件附加信息 | + +## 3. P1-B-02 当前模型缺口 + +### 3.1 `TokenRecord` + +来源:`platform-token-runtime/internal/auth/service/inmemory_runtime.go:18` + +当前字段: + +- `TokenID` +- `AccessToken` +- `SubjectID` +- `Role` +- `Scope` +- `IssuedAt` +- `ExpiresAt` +- `Status` +- `RequestID` +- `RevokedReason` + +与 schema / canonical principal 的差异: + +- 缺 `TenantID` +- 缺 `ProjectID` +- 不承载 `OperatorID` +- 不承载 `Metadata` + +### 3.2 `IssueTokenInput` + +来源:`platform-token-runtime/internal/auth/service/inmemory_runtime.go:31` + +当前仅包含 `SubjectID`、`Role`、`Scope`、`TTL`、`RequestID`、`IdempotencyKey`,没有 `TenantID`、`ProjectID`、`Metadata`。 + +### 3.3 `VerifiedToken` + +来源:`platform-token-runtime/internal/auth/service/token_verifier.go:42` + +当前仅包含 `TokenID`、`SubjectID`、`Role`、`Scope`、`IssuedAt`、`ExpiresAt`、`NotBefore`、`Issuer`、`Audience`,缺 `TenantID`,与最新 canonical principal 约束不一致。 + +### 3.4 `AuditEvent` + +来源:`platform-token-runtime/internal/auth/service/token_verifier.go:66` + +当前仅包含 `EventID`、`EventName`、`RequestID`、`TokenID`、`SubjectID`、`Route`、`ResultCode`、`ClientIP`、`CreatedAt`,缺: + +- `TenantID` +- `ProjectID` +- `OperatorID` +- `Metadata` + +## 4. P1-B-03 单一决策 + +决策:`保留字段并贯穿` + +理由: + +1. `tenant_id` 已进入最小 canonical principal 契约,不能再通过删除字段回退。 +2. `project_id`、`operator_id`、`metadata` 已进入现有 schema,且 Phase 1 目标明确要求补齐证据链与审计闭环,此时删除只会扩大文档、DDL 与代码的漂移面。 +3. 当前问题不是“字段多余”,而是“DDL 已定义但模型和 store 没有贯穿”;收缩契约会让后续多租户和审计治理重新返工。 + +## 5. P1-B-04 字段迁移顺序 + +按以下单轨顺序执行: + +1. `model` + 更新 `TokenRecord`、`IssueTokenInput`、`VerifiedToken`、`AuditEvent`、`AuditEventFilter` 的字段定义。 +2. `store` + 先改 `runtime_store.go` / `postgres_runtime_store.go`,再改 `audit_store.go` / `postgres_audit_store.go` 的读写映射。 +3. `API` + 更新 `token_api.go` 的 `issue` 请求、`introspect` 响应、`audit-events` 输出与过滤参数。 +4. `audit` + 把 middleware、issue / refresh / revoke / introspect 的发射点补齐 `tenant_id`、`project_id`、`operator_id`、`metadata` 来源。 +5. `tests` + 补充 runtime store、audit store、HTTP API、middleware 的字段断言与回归验证。 + +## 6. P1-B-05 删除路线说明 + +不采用删除路线。 + +按 `P1-B-03` 的单一决策,当前不编写 shrink SQL,也不定义 existing DB 的收缩策略;后续实施只走“保留字段并贯穿”。 + +## 7. P1-B-06 `postgres_runtime_store.go` 字段映射检查 + +### 7.1 `INSERT` / `UPSERT` + +来源:`platform-token-runtime/internal/auth/service/postgres_runtime_store.go:84` + +当前已写入: + +- `token_id` +- `token_fingerprint` +- `hash_algo` +- `subject_id` +- `role_code` +- `scope_json` +- `status` +- `issued_at` +- `expires_at` +- `revoked_reason` +- `revoked_at` +- `issue_request_id` +- `issue_idempotency_key` +- `issue_request_hash` + +当前未写入 schema 已存在列: + +- `tenant_id` +- `project_id` +- `last_seen_at` +- `created_at` / `updated_at` 依赖 DB 默认值,不是问题 + +### 7.2 `SELECT` + +来源: + +- `platform-token-runtime/internal/auth/service/postgres_runtime_store.go:156` +- `platform-token-runtime/internal/auth/service/postgres_runtime_store.go:167` + +当前读取: + +- `token_id` +- `subject_id` +- `role_code` +- `scope_json` +- `status` +- `issued_at` +- `expires_at` +- `issue_request_id` +- `revoked_reason` + +当前未读取 schema 已存在列: + +- `tenant_id` +- `project_id` +- `token_fingerprint` +- `revoked_at` +- `last_seen_at` + +结论: + +1. runtime store 当前只覆盖了最小旧字段集,没有贯穿多租户 / 项目字段。 +2. 即使 OpenAPI 已补 `tenant_id`,代码运行态仍无法产出该字段,后续必须先补 model 和 store。 + +## 8. P1-B-07 `postgres_audit_store.go` 字段映射检查 + +### 8.1 `Emit` + +来源:`platform-token-runtime/internal/auth/service/postgres_audit_store.go:68` + +当前写入: + +- `event_id` +- `event_name` +- `request_id` +- `token_id` +- `subject_id` +- `route` +- `result_code` +- `client_ip` +- `created_at` + +当前未写入 schema 已存在列: + +- `tenant_id` +- `project_id` +- `operator_id` +- `metadata` + +### 8.2 `QueryEvents` + +来源:`platform-token-runtime/internal/auth/service/postgres_audit_store.go:121` + +当前读取 / 过滤: + +- `event_id` +- `event_name` +- `request_id` +- `token_id` +- `subject_id` +- `route` +- `result_code` +- `client_ip` +- `created_at` + +当前未读取 / 未过滤: + +- `tenant_id` +- `project_id` +- `operator_id` +- `metadata` + +结论: + +1. audit schema 已预留审计闭环字段,但 `AuditEvent` / `AuditEventFilter` / Postgres store 三层都没有承接。 +2. 这会导致数据即使以后由其他地方补写,也无法通过当前查询接口读出和验证。 + +## 9. P1-B-08 最小执行清单 + +### 9.1 改 model + +- 给 `TokenRecord` 补 `TenantID`、`ProjectID` +- 给 `IssueTokenInput` 补 `TenantID`、`ProjectID`、`Metadata` +- 给 `VerifiedToken` 补 `TenantID` +- 给 `AuditEvent` 补 `TenantID`、`ProjectID`、`OperatorID`、`Metadata` +- 给 `AuditEventFilter` 补 `TenantID`、`ProjectID`、`OperatorID` + +### 9.2 改 SQL / store + +- `runtime_store.go` 持久化并返回 `TenantID`、`ProjectID` +- `postgres_runtime_store.go` 的 `INSERT` / `SELECT` / `UPSERT` 同步 `tenant_id`、`project_id` +- `audit_store.go` 与 `postgres_audit_store.go` 同步 `tenant_id`、`project_id`、`operator_id`、`metadata` + +### 9.3 改 API + +- `token_api.go` 的 `issue` 请求体补字段入口 +- `token_api.go` 的 `introspect` 响应补 `tenant_id` +- `audit-events` 查询与返回体补齐审计扩展字段 + +### 9.4 改 tests + +- `postgres_runtime_store_test.go` 增加 `tenant_id` / `project_id` 断言 +- `postgres_audit_store_test.go` 增加 `operator_id` / `tenant_id` / `metadata` 断言 +- `token_api_test.go` 增加 issue/introspect/audit-events 字段断言 +- middleware / executable tests 增加审计字段传递断言 + +### 9.5 跑验证 + +- `cd "/home/long/project/立交桥/platform-token-runtime" && GOCACHE=/tmp/lijiaoqiao-go-cache-platform-token-runtime go test ./...` +- `cd "/home/long/project/立交桥" && bash scripts/ci/repo_integrity_check.sh`