@@ -2,21 +2,23 @@
> **仓库**: `craftlabs-authorization-sdk`(分支 `develop`)。
> **角色**:解决方案架构设计稿;**不**在本任务中落地代码。
> **实现锚点**(与现有模式一致):`delivery-platform-api` 使用 Flyway `V5__…` 起(当前末版为 `V4__delivery_batch_and_license_sn.sql`)、`AuditService` + `AuditEntityTypes` / `AuditActions`、`ApiExceptionHandler`、公开业务 API 经 `SecurityConfig` + `JwtAuthenticationFilter`( `Authorization: Bearer`);OpenAPI SSOT 为 [ `contracts/openapi/delivery-platform-api.json` ](../../../contracts/openapi/delivery-platform-api.json) 与 `OpenApiContractSnapshotTest`。
> **Webhook 工程名**:本工作区已实现为 `license-webhook-ingress`( [ `services/README.md` ](../../../services/README.md): `webhook_callback_receipt`、`Idempotency-Key`)。
> **实现锚点**(与现有模式一致):`delivery-platform-api` 使用 Flyway `V5__…` 起(当前末版为 `V4__delivery_batch_and_license_sn.sql`)、`AuditService` + `AuditEntityTypes` / `AuditActions`、`ApiExceptionHandler`、公开业务 API 经 `SecurityConfig` + `JwtAuthenticationFilter`( `Authorization: Bearer`);OpenAPI SSOT 为 `[ contracts/openapi/delivery-platform-api.json](../../../contracts/openapi/delivery-platform-api.json)` 与 `OpenApiContractSnapshotTest`。
> **Webhook 工程名**:本工作区已实现为 `license-webhook-ingress`( `[ services/README.md](../../../services/README.md)` : `webhook_callback_receipt`、`Idempotency-Key`)。
---
## 0. 上游文档走查(按路径引用,不全文摘录)
| 文档 | 与本设计的关系(摘要) |
|------|------------------------ |
| [ docs/engineering/PARALLEL_ITERATION_INDEX.md ]( ../PARALLEL_ITERATION_INDEX.md ) | 定义三轨并行;**I5** 为 **Callback + Schema ** 硬耦合周;**I6** 为 **UAT ** 与 SDK 冻结;同步点含 **I5 起 ** : Callback payload / inbox DTO、**Idempotency-Key**、Webhook→平台投递方式;**I6**: UAT 场景、`VITE_API_BASE` 、两枚 Fat JAR 与 SDK 版本。 |
| 文档 | 与本设计的关系(摘要) |
| -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [docs/engineering/PARALLEL_ITERATION_INDEX.md ](../PARALLEL_ITERATION_INDEX.md ) | 定义三轨并行;**I5** 为 **Callback + Schema ** 硬耦合周;**I6** 为 **UAT ** 与 SDK 冻结;同步点含 **I5 起 ** : Callback payload / inbox DTO、**Idempotency-Key**、Webhook→平台投递方式;**I6**: UAT 场景、`VITE_API_BASE` 、两枚 Fat JAR 与 SDK 版本。 |
| [docs/engineering/tracks/01-backend-platform-webhook.md ](../tracks/01-backend-platform-webhook.md ) | **I5 DoD ** : E2E「模拟 Callback → 平台 DB 一条 Inbox」;**§3 Webhook↔平台**: `schemaVersion` / `X-Event-Schema-Version` 、幂等 `(source_system, external_message_id)` 、`POST /internal/v1/callback-events` 或 MQ、对比特 **2xx ** 须在持久化或可靠入队**之后**。 |
| [docs/engineering/tracks/02-frontend-platform-ui.md ](../tracks/02-frontend-platform-ui.md ) | **I5 路由 ** : `/callbacks` 、`/integration/environments` 、`product-lines` (本文统一为 `/integration/product-lines` );组件:`CallbackInboxTable` 、`CallbackPayloadViewer` (脱敏);与 Webhook 联调或 staging。 |
| [docs/engineering/tracks/03-client-sdk.md ](../tracks/03-client-sdk.md ) | **I5 ** : **Schema + `AuthConfigs` + examples** 与 **BP-10 ** 同步为硬交付;**I6**:冻结 SDK 版本、CHANGELOG、**BitAnswer 兼容矩阵**; UAT 周禁止 MAJOR Schema。 |
| [docs/chuangfei-platform-product-modules.md ](../../chuangfei-platform-product-modules.md ) §6– 7 | **M5 P0 ** :收件箱列表/详情/处理状态/关联失败兜底/事件类型字典(M5-F01~F05 等);**M6 P0**:产品线(M6-F01)、环境维度与 `bitanswer.url` ( M6-F02);P1 如比特 ID 映射、JSON 模板、发布记录等 **I5 MVP 可裁减 ** 。 |
| [docs/chuangfei-platform-bpm-and-roadmap.md ](../../chuangfei-platform-bpm-and-roadmap.md ) | **BP-06 ** :Webhook 验签 → 落库 → 解析关联 → Ops 处置;重复投递幂等。**BP-10**:M6 与 Schema、客户端配置发布链路;**依赖**本仓 `schemas/craftlabs-auth-config.schema.json` 。 |
| [docs/engineering/tracks/02-frontend-platform-ui.md ](../tracks/02-frontend-platform-ui.md ) | **I5 路由 ** : `/callbacks` 、`/integration/environments` 、`product-lines` (本文统一为 `/integration/product-lines` );组件:`CallbackInboxTable` 、`CallbackPayloadViewer` (脱敏);与 Webhook 联调或 staging。 |
| [docs/engineering/tracks/03-client-sdk.md ](../tracks/03-client-sdk.md ) | **I5 ** : **Schema + `AuthConfigs` + examples** 与 **BP-10 ** 同步为硬交付;**I6**:冻结 SDK 版本、CHANGELOG、**BitAnswer 兼容矩阵**; UAT 周禁止 MAJOR Schema。 |
| [docs/chuangfei-platform-product-modules.md ](../../chuangfei-platform-product-modules.md ) §6– 7 | **M5 P0 ** :收件箱列表/详情/处理状态/关联失败兜底/事件类型字典(M5-F01~F05 等);**M6 P0**:产品线(M6-F01)、环境维度与 `bitanswer.url` ( M6-F02);P1 如比特 ID 映射、JSON 模板、发布记录等 **I5 MVP 可裁减 ** 。 |
| [docs/chuangfei-platform-bpm-and-roadmap.md ](../../chuangfei-platform-bpm-and-roadmap.md ) | **BP-06 ** :Webhook 验签 → 落库 → 解析关联 → Ops 处置;重复投递幂等。**BP-10**:M6 与 Schema、客户端配置发布链路;**依赖**本仓 `schemas/craftlabs-auth-config.schema.json` 。 |
---
@@ -24,79 +26,91 @@
### A.1 问题与目标结果
| 维度 | 说明 |
|------|------ |
| **业务问题 ** | 比特规则 **HTTPS Callback ** 需 **不断链、可审计、可运营处置 ** ;平台侧需统一收件箱,避免只在 Webhook 边缘落库不可见。 |
| **I5 目标结果(E2E) ** | **模拟或真实 Callback ** 经 `license-webhook-ingress` →(持久化收据后)**投递** → `delivery-platform-api` **Inbox 表出现一行 ** ;运营账号用 JWT 在 UI **列表可见、详情可打开 ** 。 |
| **幂等 ** | 与轨道 A 一致:** `Idempotency-Key` **( HTTP 头)+ 比特稳定 * * `message_id` **(或等价字段);DB **唯一约束 `(source_system, external_message_id)` ** ;重复请求 **不重复插入 ** 、返回与首次一致的接受语义(HTTP 200 + 相同 `inboxId` 或约定 DTO)。 |
| **schemaVersion ** | 事件体或头携带 * * `schemaVersion` **(与轨道 A 的 `X-Event-Schema-Version` 二选一或并存,**须写 ADR 定一种主口径**);平台拒绝无法识别的 major 版本时返回 **4xx ** 并记录可观测字段,避免静默损坏 。 |
| 维度 | 说明 |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **业务问题 ** | 比特规则 **HTTPS Callback ** 需 **不断链、可审计、可运营处置 ** ;平台侧需统一收件箱,避免只在 Webhook 边缘落库不可见。 |
| **I5 目标结果(E2E) ** | **模拟或真实 Callback ** 经 `license-webhook-ingress` →(持久化收据后)**投递** → `delivery-platform-api` **Inbox 表出现一行 ** ;运营账号用 JWT 在 UI **列表可见、详情可打开 ** 。 |
| **幂等 ** | 与轨道 A 一致: `**Idempotency-Key` **( HTTP 头)+ 比特稳定 `**message_id**` (或等价字段);DB **唯一约束 `(source_system, external_message_id)` ** ;重复请求 **不重复插入 ** 、返回与首次一致的接受语义(HTTP 200 + 相同 `inboxId` 或约定 DTO) 。 |
| **schemaVersion ** | 事件体或头携带 `**schemaVersion` **(与轨道 A 的 `X-Event-Schema-Version` 二选一或并存,**须写 ADR 定一种主口径**);平台拒绝无法识别的 major 版本时返回 **4xx ** 并记录可观测字段,避免静默损坏。 |
### A.2 数据模型(`delivery-platform-api`, PostgreSQL + Flyway)
命名与现有表一致采用 * * `platform_*` 前缀**(见 `V1` ~ `V4` 迁移)。
命名与现有表一致采用 `** platform_*` 前缀**(见 `V1` ~ `V4` 迁移)。
#### A.2.1 `platform_callback_inbox`( M5 Inbox P0)
| 列(示例) | 类型/说明 |
|------------|----------- |
| `id` | UUID / BIGSERIAL PK |
| `source_system` | VARCHAR,如 `BITANSWER` |
| `external_message_id` | VARCHAR,比特侧稳定消息 ID |
| **唯一约束 ** | `UNIQUE (source_system, external_message_id) ` |
| `schema_version` | VARCHAR,与 payload 解析版本对齐 |
| `event_type` | VARCHAR,与 M5-F05 字典一致(如 `sn:pre_activate` ) |
| `status` | ENUM/VARCHAR: ** `PENDING` / `PROCESSED` / `FAILED` / `IGNORED` **(对应产品「待处理、已处理、失败、忽略」) |
| `raw_payload` | **JSONB ** (或 TEXT + 大小上限);UI **脱敏展示 ** |
| `idempotency_key` | VARCHAR NULL,审计与排障 |
| **关联(均可 NULL,支撑 M5-F04) ** | `license_sn_id` → `platform_license_sn` ; `contract_id` / `project_id` (若已有表);解析字段如 `sn_code` 、 `mid` 等冗余列便于列表筛选 |
| `product_line _id` / `integration_environment_id` | FK → M6 最小表(可选,便于按产品线/环境 筛选) |
| `received_at` | 平台收件时间 |
| `process ed_at` / `processed_by_user_id` | 运营处置 |
| `failure_reason` / `operator_note` | 文本,P1 可扩展「失败原因分类」字典 |
| 标准审计 | 与现有实体一致可补充 `created_at` / `updated_at` ;关键状态迁移建议走 * * `AuditService` **(扩展 `AuditEntityTypes` / `AuditActions` ) |
| 列(示例) | 类型/说明 |
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| `id` | UUID / BIGSERIAL PK |
| `source_system` | VARCHAR,如 `BITANSWER` |
| ` external_message_id` | VARCHAR,比特侧稳定消息 ID |
| **唯一约束 ** | `UNIQUE (source_system, external_message_id)` |
| `schema_version` | VARCHAR,与 payload 解析版本对齐 |
| `event_type` | VARCHAR,与 M5-F05 字典一致(如 `sn:pre_activate` ) |
| `status` | ENUM/VARCHAR: `**PENDING` / `PROCESSED` / `FAILED` / `IGNORED` **(对应产品「待处理、已处理、失败、忽略」) |
| `raw_payload` | **JSONB ** (或 TEXT + 大小上限);UI **脱敏展示 ** |
| `idempotency_key` | VARCHAR NULL,审计与排障 |
| **关联(均可 NULL,支撑 M5-F04) ** | `license_sn _id` → `platform_license_sn` ; `contract_id` / `project_id` (若已有表);解析字段如 `sn_code` 、 `mid` 等冗余列便于列表 筛选 |
| `product_line_id` / `integration_environment_id` | FK → M6 最小表(可选,便于按产品线/环境筛选) |
| `receiv ed_at` | 平台收件时间 |
| `processed_at` / `processed_by_user_id` | 运营处置 |
| `failure_reason` / `operator_note` | 文本,P1 可扩展「失败原因分类」字典 |
| 标准审计 | 与现有实体一致可补充 `created_at` /`updated_at` ;关键状态迁移建议走 `**AuditService` **(扩展 `AuditEntityTypes` / `AuditActions` ) |
#### A.2.2 M6 最小只读支撑表
仅包含 **I5 UI 与 Inbox 筛选 ** 所需字段;**不做** M6-F03~ F06 全量。
| 表 | P0 字段(示例) |
|----|----------------- |
| * * `platform_product_line` ** | `id` 、 `code` (唯一)、 `name` 、 `description` NULL、启用标志 |
| * * `platform_integration_environment` ** | `id` 、 `code` (唯一)、 `name` 、 `bitanswer_base_url` (对应 M6-F02)、 `kind` ( DEV/TEST/STAGING/PROD 等枚举)、可选 `product_line_id` 或后续多对多(MVP 可 **单列 FK ** 简化) |
| 表 | P0 字段(示例) |
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `**platform_product_line` ** | `id` 、 `code` (唯一)、 `name` 、 `description` NULL、启用标志 |
| `**platform_integration_environment**` | `id` 、`code` (唯一)、`name` 、`bitanswer_base_url` (对应 M6-F02)、`kind` ( DEV/TEST/STAGING/PROD 等枚举)、可选 `product_line_id` 或后续多对多(MVP 可 **单列 FK ** 简化) |
**MVP 裁减 ** :比特产品/模版/业务 ID 映射(M6-F03)、特征映射(M6-F04)、JSON 模板与发布记录(M6-F05/F06) **推迟**至 V1.1 或 Mid,除非比特联调硬依赖。
### A.3 公开 REST API( JWT, `/api/v1`)
与现有 Controller 风格一致;**RBAC**:与当前演示一致 * * `SYS_ADMIN` / `DEVELOPER` ** 均可访问 MVP 接口(与 [ ` AuthController` ](../../../services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/auth/AuthController.java ) 对齐),**I7+** 再收紧为 Ops 专用权限码。
与现有 Controller 风格一致;**RBAC**:与当前演示一致 `** SYS_ADMIN` / `DEVELOPER` ** 均可访问 MVP 接口(与 `[ AuthController](../../../services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/auth/AuthController.java)` 对齐),**I7+** 再收紧为 Ops 专用权限码。
| 方法 | 路径 | 说明 |
| ------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `GET` | `/api/v1/callback-inbox` | 分页;查询建议:`status` 、`eventType` 、`snCode` 、`projectId` 、`productLineId` 、`environmentId` 、`from` /`to` ( `receivedAt` )、`page` 、`size` |
| `GET` | `/api/v1/callback-inbox/{id}` | 详情;含 `rawPayload` (或单独 `GET .../payload` 若需权限分级) |
| `PATCH` | `/api/v1/callback-inbox/{id}/status` | 运营状态迁移:`**PENDING` → `PROCESSED` / `FAILED` / `IGNORED` **;非法迁移 **409 ** + 业务错误码(与合同/交付模式一致,经 `**ApiExceptionHandler` **) |
| `PATCH` | `/api/v1/callback-inbox/{id}/link` (可选) | 人工挂接:`licenseSnId` / `projectId` / `contractId` 等,支撑 M5-F04 |
| 方法 | 路径 | 说明 |
|------|------|------|
| `GET` | `/api/v1/callback-inbox` | 分页;查询建议:`status` 、`eventType` 、`snCode` 、`projectId` 、`productLineId` 、`environmentId` 、`from` /`to` ( `receivedAt` )、`page` 、`size` |
| `GET` | `/api/v1/callback-inbox/{id}` | 详情;含 `rawPayload` (或单独 `GET .../payload` 若需权限分级) |
| `PATCH` | `/api/v1/callback-inbox/{id}/status` | 运营状态迁移:**`PENDING` → `PROCESSED` / `FAILED` / `IGNORED` **;非法迁移 **409 ** + 业务错误码(与合同/交付模式一致,经 * * `ApiExceptionHandler` **) |
| `PATCH` | `/api/v1/callback-inbox/{id}/link` (可选) | 人工挂接:`licenseSnId` / `projectId` / `contractId` 等,支撑 M5-F04 |
**可选 ** : `POST /api/v1/callback-inbox/simulate` ( **仅非生产**,对应 M5-F10 P2 — **I5 若排期紧可不做 ** ,改用 curl → Webhook → 平台链)。
**M6 只读 **
| 方法 | 路径 | 说明 |
|------|------|------ |
| `GET` | `/api/v1/integration/environments` | 列表/分页 |
| `GET` | `/api/v1/integration/product-lines` | 列表/分页 |
| 方法 | 路径 | 说明 |
| ----- | ---------------------------------------------------------------- | ------ |
| `GET` | `/api/v1/integration/environments` | 列表/分页 |
| `GET` | `/api/v1/integration/product-lines` | 列表/分页 |
| `GET` | `/api/v1/integration/environments/{id}` 、`.../product-lines/{id}` | 详情(按需) |
写接口(维护环境/产品线)MVP 可 **仅种子数据 + Flyway ** 或 **管理员 POST ** (若 I5 周可交付则加 `POST/PUT` ,否则 **推迟 ** )。
### A.4 内部 API(平台服务间,`license-webhook-ingress` → `delivery-platform-api`)
| 项 | 说明 |
|----|------ |
| **路径 ** | `POST /internal/v1/callback-events` |
| **认证(MVP 推荐) ** | 共享密钥:** `X-Platform-Internal-Token` **(或 `Authorization: Bearer <internal>` ),配置与 `PLATFORM_JWT_SECRET` 分离;**生产建议路线图**:mTLS 或双向签名(文档中注明 **I6 Runbook:轮换步骤 ** )。 |
| **幂等 ** | 请求头 * * `Idempotency-Key` ** + 体 * * `sourceSystem` + `externalMessageId` ** 与 Inbox 唯一键一致;重复 POST → **200 ** 且 body 指向同一 `inboxId` 。 |
| **行为 ** | 校验 `schemaVersion` → 插入或跳过(幂等)→ 尝试解析并 **填充关联列 ** (失败则 `status=PENDING` 保留人工挂接)。 |
| 项 | 说明 |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **路径 ** | `POST /internal/v1/callback-events` |
| **认证(MVP 推荐) ** | 共享密钥: `**X-Platform-Internal-Token` **(或 `Authorization: Bearer <internal>` ),配置与 `PLATFORM_JWT_SECRET` 分离;**生产建议路线图**:mTLS 或双向签名(文档中注明 **I6 Runbook:轮换步骤 ** ) 。 |
| **幂等 ** | 请求头 `**Idempotency-Key` ** + 体 `**sourceSystem` + `externalMessageId**` 与 Inbox 唯一键一致;重复 POST → **200 ** 且 body 指向同一 `inboxId` 。 |
| **行为 ** | 校验 `schemaVersion` → 插入或跳过(幂等)→ 尝试解析并 **填充关联列 ** (失败则 `status=PENDING` 保留人工挂接)。 |
**请求 / 响应 JSON 示例(示意) **
@@ -128,30 +142,36 @@ Content-Type: application/json
### A.5 `license-webhook-ingress` 链路
| 步骤 | 说明 |
|------|------ |
| 1 | **验签 / token ** (现有 `x-bitanswer-token` 与 `CRAFTLABS_WEBHOOK_EXPECTED_TOKEN` ) |
| 2 | **持久化收据 ** (现有 * * `webhook_callback_receipt` ** + * * `Idempotency-Key` ** 幂等) |
| 3 | **HTTP 转发 ** 至平台 `POST /internal/v1/callback-events` :**带重试**(指数退避、最大次数、超时);贯通 * * `traceparent` / `X-Request-Id` **(轨道 A §3) |
| 步骤 | 说明 |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------- |
| 1 | **验签 / token ** (现有 `x-bitanswer-token` 与 `CRAFTLABS_WEBHOOK_EXPECTED_TOKEN` ) |
| 2 | **持久化收据 ** (现有 `**webhook_callback_receipt` ** + `**Idempotency-Key**` 幂等) |
| 3 | **HTTP 转发 ** 至平台 `POST /internal/v1/callback-events` :**带重试**(指数退避、最大次数、超时);贯通 `**traceparent` / `X-Request-Id` **(轨道 A §3) |
| **对比特的 HTTP 响应 ** | 与轨道 A 一致:**2xx 须在收据已持久化(或可靠入队)之后**再返回。**MVP 推荐**:先落库收据即对比特 **2xx ** ,平台投递 **异步重试 ** ;若 **同步 ** 转发,须 **短超时 ** 且平台幂等,避免比特侧超时重放放大。 |
| **平台非 2xx ** | Webhook 侧重试;仍失败则记 **DLQ/失败计数 ** (日志 + DB 字段,**M5-F08 完整监控可推迟**);**不**因平台暂时不可用而对已持久化收据重复向比特报错(若已 2xx)。 |
| **平台非 2xx ** | Webhook 侧重试;仍失败则记 **DLQ/失败计数 ** (日志 + DB 字段,**M5-F08 完整监控可推迟**);**不**因平台暂时不可用而对已持久化收据重复向比特报错(若已 2xx)。 |
### A.6 OpenAPI 与 springdoc
| 项 | 说明 |
|----|------ |
| **SSOT ** | 更新 [ `contracts/openapi/delivery-platform-api.json` ]( ../../../contracts/openapi/delivery-platform-api.json ):仅 **公开 ** `/api/v1/callback-inbox*` 、 `/api/v1/integration/*` 路径、 `components/schemas` 、错误码与 `security` ( Bearer JWT)。 |
| **内部路由 ** | * * `/internal/**` 建议排除在默认 springdoc 分组之外**,或打上 tag * * `internal` ** 且 **生产禁用**该分组(与「对外契约」分离,避免集成方误用 )。 |
| **校验 ** | `UPDATE_OPENAPI=1 mvn test -Dtest=OpenApiContractSnapshotTest` (见 [ `contracts/README.md` ]( ../../../contracts/README.md ))。 |
| 项 | 说明 |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **SSOT ** | 更新 `[contracts/openapi/delivery-platform-api.json](../../../contracts/openapi/delivery-platform-api.json)` :仅 **公开 ** `/api/v1/callback-inbox*` 、 `/api/v1/integration/*` 路径、 `components/schemas` 、错误码与 `security` ( Bearer JWT )。 |
| **内部路由 ** | `**/internal/` ** 建议排除在默认 springdoc 分组之外**,或打上 tag `**internal` ** 且 **生产禁用**该分组(与「对外契约」分离,避免集成方误用)。 |
| **校验 ** | `UPDATE_OPENAPI=1 mvn test -Dtest=OpenApiContractSnapshotTest` (见 `[contracts/README.md](../../../contracts/README.md)` )。 |
### A.7 前端(`web/delivery-platform-ui`)
| 路由 | 页面职责 |
|------|---------- |
| `/callbacks` | Inbox 列表、 `CallbackInboxTable` ;跳转详情 |
| `/callbacks/:id` | 详情 + * * `CallbackPayloadViewer` (脱敏)**;状态 PATCH、可选人工挂接 |
| `/integration/environments` | M6 环境只读表 |
| `/integration/product-line s` | 产品线只读表 |
| 路由 | 页面职责 |
| ---------------------------- | ---------------------------------------------------- |
| `/callbacks` | Inbox 列表、 `CallbackInboxTable` ;跳转详情 |
| `/callbacks/:id` | 详情 + `**CallbackPayloadViewer` (脱敏)**;状态 PATCH、可选人工挂接 |
| `/integration/environment s` | M6 环境只读表 |
| `/integration/product-lines` | 产品线只读表 |
路由 meta:**权限码与 I1 壳一致**;菜单对 **SYS_ADMIN / DEVELOPER ** 可见(MVP)。
@@ -159,63 +179,74 @@ Content-Type: application/json
- **Schema**: `schemas/craftlabs-auth-config.schema.json` 等 — 若 BP-10 变更类型触及「平台导出 → Schema → 客户端」,按 [轨道 C §3 ](../tracks/03-client-sdk.md ) bump 规则执行。
- **Java `AuthConfigs` **:与 Schema 同步(表见轨道 C BP-10)。
- ** `examples/` ** :与最新字段及环境变量说明一致;CI 与 Schema 校验对齐。
- `** examples/** ` :与最新字段及环境变量说明一致;CI 与 Schema 校验对齐。
- **文档**:明确 **SDK 版本线 ≠ 平台 Fat JAR 版本 ** ;引用 BPM **BP-10 ** 与产品 M6-F01/F02 口径。
- **不做**: Native 与 Webhook 运行时耦合;平台不嵌入 JNI。
---
## Part B — I6: 本文件内仅规划(不展开实现)
## Part B — I6: 规划与收口文档
| 主题 | 内容要点 | 执行文档 |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| **UAT 门禁 ** | 跑通 **BP-01~ 06、11 ** 主链路(与 [轨道 B I6 ](../tracks/02-frontend-platform-ui.md ) E2E 一致);**Callback** 场景含重复投递幂等、关联失败人工挂接。 | [I6_CLOSEOUT.md §2 ](./I6_CLOSEOUT.md ) |
| **冻结清单 ** | **SDK ** :定版 tag、CHANGELOG、**BitAnswer 兼容矩阵**(轨道 C);**OpenAPI** 快照冻结;**两 JAR** 版本与镜像标签可追踪;前端 `**VITE_API_BASE` ** 环境矩阵文档化。 | [I6_CLOSEOUT.md §3~§4 ](./I6_CLOSEOUT.md ) |
| **Runbook ** | `[services/RUNBOOK.md](../../../services/RUNBOOK.md)` : **内部 token 轮换**、Webhook→平台连通性检查、DB 迁移顺序(`flyway_platform_api` / `flyway_webhook` )。 | RUNBOOK * * §10** |
| **安全加固 ** | **安全响应头 ** 、Cookie/Session 策略(若 Mid 前仍为 JWT 则文档化 **仅 Bearer ** )、依赖扫描与已知 CVE 处理;**禁止** I6 周排入大块新功能(仅缺陷与加固)。 | 平台 `SecurityConfig` + Runbook |
| **实现审核 ** | I1~I6 对照设计与三轨道文档 | [I6_IMPLEMENTATION_REVIEW.md ](./I6_IMPLEMENTATION_REVIEW.md ) |
| 主题 | 内容要点 |
|------|----------|
| **UAT 门禁 ** | 跑通 **BP-01~ 06、11 ** 主链路(与 [轨道 B I6 ](../tracks/02-frontend-platform-ui.md ) E2E 一致);**Callback** 场景含重复投递幂等、关联失败人工挂接。 |
| **冻结清单 ** | **SDK ** :定版 tag、CHANGELOG、**BitAnswer 兼容矩阵**(轨道 C);**OpenAPI** 快照冻结;**两 JAR** 版本与镜像标签可追踪;前端 * * `VITE_API_BASE` ** 环境矩阵文档化。 |
| **Runbook ** | 复用并增补 [`services/RUNBOOK.md` ](../../../services/RUNBOOK.md ): **内部 token 轮换**、Webhook→平台连通性检查、DB 迁移顺序(`flyway_platform_api` / `flyway_webhook` )。 |
| **安全加固 ** | **安全响应头 ** 、Cookie/Session 策略(若 Mid 前仍为 JWT 则文档化 **仅 Bearer ** )、依赖扫描与已知 CVE 处理;**禁止** I6 周排入大块新功能(仅缺陷与加固)。 |
---
## Part C — 实现顺序与 MVP 切割
1. **平台 DB( Flyway `V5+`) ** : `platform_callback_inbox` + M6 两表 + 必要索引与外键;种子数据(环境/产品线)可选。
2. **平台内部 API ** : `POST /internal/v1/callback-events` + 幂等与 `schemaVersion` 校验 + * * `AuditService` 钩子**(状态/关联变更)。
3. **平台公开 API ** : `GET/PATCH` callback-inbox、M6 只读 GET; **统一异常**经 `ApiExceptionHandler` 。
4. **OpenAPI 快照 ** 与契约测试更新。
5. **Webhook ** :在收据落库后增加 **转发客户端 ** (重试、观测头);配置项:`PLATFORM_INTERNAL_BASE_URL` 、`PLATFORM_INTERNAL_TOKEN` 。
6. **集成测试 ** : Testcontainers + 双模块或 Compose(与轨道 A **I5+ `cross-service-it` ** 建议一致)。
7. **前端 ** :路由与表格/详情/脱敏展示;联调 staging。
8. **SDK / Schema / examples ** :按 BP-10 终版对齐并过 CI。
1. **平台 DB( Flyway `V5+`) ** : `platform_callback_inbox` + M6 两表 + 必要索引与外键;种子数据(环境/产品线)可选。
2. **平台内部 API ** : `POST /internal/v1/callback-events` + 幂等与 `schemaVersion` 校验 + `** AuditService` 钩子**(状态/关联变更)。
3. **平台公开 API ** : `GET/PATCH` callback-inbox、M6 只读 GET; **统一异常**经 `ApiExceptionHandler` 。
4. **OpenAPI 快照 ** 与契约测试更新。
5. **Webhook ** :在收据落库后增加 **转发客户端 ** (重试、观测头);配置项:`PLATFORM_INTERNAL_BASE_URL` 、`PLATFORM_INTERNAL_TOKEN` 。
6. **集成测试 ** : Testcontainers + 双模块或 Compose(与轨道 A **I5+ `cross-service-it` ** 建议一致)。
7. **前端 ** :路由与表格/详情/脱敏展示;联调 staging。
8. **SDK / Schema / examples ** :按 BP-10 终版对齐并过 CI。
**MVP 明确推迟(若全量 M5/M6 过大) **
| 推迟项 | 说明 |
|--------|------ |
| M6-F03~ F09 | 比特 ID 映射、特征映射、模板库、发布记录、影响分析 |
| M5 -F06 ~ F09 | 失败分类字典、批量重试 UI、积压监控、M8 待办联动 |
| M5-F10 | 模拟投递 UI(可用 curl/Postman 代替) |
| MQ 投递 | 保留 HTTP MVP; MQ + 消费者为 ADR 备选(轨道 A 已列 B 方案) |
| 推迟项 | 说明 |
| ---------- | ------------------------------------------ |
| M6 -F03 ~ F09 | 比特 ID 映射、特征映射、模板库、发布记录、影响分析 |
| M5-F06~F09 | 失败分类字典、批量重试 UI、积压监控、M8 待办联动 |
| M5-F10 | 模拟投递 UI(可用 curl/Postman 代替) |
| MQ 投递 | 保留 HTTP MVP; MQ + 消费者为 ADR 备选(轨道 A 已列 B 方案) |
---
## Part D — 可追溯性(设计章节 → 产品功能点)
| 设计章节 | 产品模块 / 功能点(适用处) |
|----------|---------------------------- |
| A.1 幂等与 schemaVersion | M5 运营基础;BP-06 |
| A.2.1 `platform_callback_inbox` | **M5-F01~ F04 ** (列表、详情、状态、关联兜底) |
| A.2.1 `event_type` 、字典 | **M5-F05 ** |
| A.2.2 产品线 / 环境表 | **M6-F01、M6 -F02 ** |
| A.3 公开 REST | **M5 -F01~ F03 ** ;人工挂接 **M5 -F04 ** |
| A.4 内部 API | BP-06 入站;与轨道 A Webhook↔平台契约 |
| A.5 Webhook 转发 | BP-06 步骤①②;**不丢链** |
| A.8 SDK / Schema | **BP-10 ** ;**M6** 配置治理(文档与校验链) |
| Part B I6 | BP-01~ 06、11 UAT; M11 安全与运维 |
| 设计章节 | 产品模块 / 功能点(适用处) |
| ------------------------------- | ------------------------------ |
| A.1 幂等与 schemaVersion | M5 运营基础;BP-06 |
| A.2.1 `platform_callback_inbox` | **M5-F01~ F04 ** (列表、详情、状态、关联兜底) |
| A.2.1 `event_type` 、字典 | **M5 -F05 ** |
| A.2.2 产品线 / 环境表 | **M6 -F01、M6 -F02 ** |
| A.3 公开 REST | **M5-F01~ F03 ** ;人工挂接 **M5-F04 ** |
| A.4 内部 API | BP-06 入站;与轨道 A Webhook↔平台契约 |
| A.5 Webhook 转发 | BP-06 步骤①②;**不丢链** |
| A.8 SDK / Schema | **BP-10 ** ;**M6** 配置治理(文档与校验链) |
| Part B I6 | BP-01~ 06、11 UAT; M11 安全与运维 |
---
## 修订记录
| 日期 | 说明 |
|------|------ |
| 2026-04-06 | 初版:I5/I6 架构设计,对齐并行索引、三轨道文档与产品 M5/M6 P0。 |
| 日期 | 说明 |
| ---------- | ----------------------------------------------------------------- |
| 2026-04-06 | 初版:I5/I6 架构设计,对齐并行索引、三轨道文档与产品 M5/M6 P0。 |
| 2026-04-06 | Part B 关联 I6 收口文档(CLOSEOUT / IMPLEMENTATION_REVIEW)与 RUNBOOK §10。 |