Files
lijiaoqiao/docs/supply_technical_design_enhanced_v1_2026-03-25.md

8.6 KiB
Raw Blame History

供应侧技术设计增强版XR-001

  • 版本v1.1
  • 日期2026-03-27
  • 状态:生效(实施基线)
  • 目标:补齐供应侧关键写路径的幂等、并发、事务、不变量与可靠性闭环
  • 关联 SSOT
    • llm_gateway_subapi_evolution_plan_v4_2_2026-03-24.md
    • acceptance_gate_single_source_v1_2026-03-18.md
    • supply_button_level_prd_v1_2026-03-25.md
    • supply_api_contract_openapi_draft_v1_2026-03-25.yaml
    • database_domain_model_and_governance_v1_2026-03-27.md

1. 设计边界与约束

  1. 业务链路固定为:用户A供给 -> 平台 -> 用户B购买平台服务
  2. 供应方上游凭证仅平台托管,任何北向接口不得回显可复用凭证片段。
  3. 所有关键写操作必须支持双键幂等:request_id + idempotency_key
  4. 所有状态迁移必须满足“显式前置状态 + 原子落库 + 审计可追溯”。
  5. 所有跨系统副作用必须通过 Outbox/Saga 触发,禁止在数据库事务中直连外部系统。

2. 关键写路径与幂等协议

2.1 适用操作

  1. POST /api/v1/supply/accounts
  2. POST /api/v1/supply/packages/{id}/publish
  3. POST /api/v1/supply/packages/batch-price
  4. POST /api/v1/supply/settlements/withdraw
  5. POST /api/v1/supply/settlements/{id}/cancel

2.2 入站协议MUST

  1. Header 必填:X-Request-IdUUID
  2. Header 必填:Idempotency-Key(长度 16-128
  3. 幂等作用域:tenant_id + operator_id + api_path + idempotency_key
  4. 幂等有效期:24h(提现类可扩展到 72h
  5. 契约落地状态:已在 OpenAPI 写操作路径挂载上述 header并补充 409/202 幂等语义示例2026-03-27

2.3 语义规范

  1. 首次成功:返回业务成功码(200/201)并写入幂等记录。
  2. 重放同参:返回同一业务结果,idempotent_replay=true
  3. 重放异参:返回 409 IDEMPOTENCY_PAYLOAD_MISMATCH
  4. 首次处理中:返回 202 IDEMPOTENCY_IN_PROGRESS,携带 retry_after_ms

2.4 存储建议PostgreSQL

create table if not exists supply_idempotency_record (
  id bigserial primary key,
  tenant_id bigint not null,
  operator_id bigint not null,
  api_path varchar(200) not null,
  idempotency_key varchar(128) not null,
  request_id varchar(64) not null,
  payload_hash char(64) not null,
  response_code int,
  response_body jsonb,
  status varchar(20) not null, -- processing/succeeded/failed
  expires_at timestamp not null,
  created_at timestamp not null default now(),
  updated_at timestamp not null default now(),
  unique (tenant_id, operator_id, api_path, idempotency_key)
);

3. 并发控制策略(按领域动作)

3.1 账号挂载与状态迁移

  1. 账号状态变更(激活/暂停/禁用)采用乐观锁:version 字段 CAS 更新。
  2. 激活操作 SQL 需带前置状态:where id=? and status in ('pending','suspended') and version=?
  3. 同一账号同一时刻只允许一个状态迁移事务;冲突返回 409 SUP_ACC_4091

3.2 套餐发布与批量调价

  1. 套餐单条迁移采用乐观锁,保证 draft -> active -> paused -> expired 不跳态。
  2. 批量调价采用“分片事务 + 明细回执”模式,单条失败不回滚全部成功项。
  3. 批量任务必须落审计明细:total/success/failed/failed_items[]

3.3 提现发起与撤销

  1. 发起提现采用悲观锁:select ... for update 锁定供应方可提现余额行。
  2. 约束:同一供应方同一时刻最多 1 笔 processing 提现单。
  3. 唯一约束建议:
create unique index if not exists uq_settlement_supplier_processing
on supply_settlements(user_id)
where status = 'processing';
  1. 余额扣减与结算单创建必须同事务提交,任一失败整体回滚。

4. 领域不变量Invariant

编号 不变量 触发动作 拒绝码
INV-ACC-001 active 账号不可删除 删除账号 SUP_ACC_4092
INV-ACC-002 账号 disabled 仅管理员可恢复 激活账号 SUP_ACC_4031
INV-PKG-001 sold_out 只能系统迁移 人工改状态 SUP_PKG_4092
INV-PKG-002 expired 套餐不可直接恢复 发布上架 SUP_PKG_4093
INV-PKG-003 售价不得低于保护价 发布/调价 SUP_PKG_4001
INV-SET-001 processing/completed 不可撤销 撤销申请 SUP_SET_4092
INV-SET-002 提现金额不得超过可提现余额 发起提现 SUP_SET_4001
INV-SET-003 结算单金额与余额流水必须平衡 结算入账 SUP_SET_5002

说明:所有不变量失败必须写入审计事件 invariant_violation,并携带 rule_code


5. 事务边界与副作用编排

5.1 本地事务内(必须原子)

  1. 领域状态变更(账号/套餐/结算单)
  2. 资金子账变更(冻结/解冻/可提现)
  3. 幂等记录更新(processing -> succeeded/failed
  4. 审计日志落库(最小字段集)
  5. Outbox 事件入库

5.2 事务外(异步执行)

  1. 通知发送(站内信/邮件/短信)
  2. 导出任务生成
  3. 风险引擎异步评分
  4. BI 聚合看板更新

5.3 Outbox 事件规范

  1. 事件命名:supply.{domain}.{action}.{result}
  2. 必填字段:event_id/request_id/tenant_id/object_id/before_state/after_state
  3. 消费保障:至少一次投递 + 消费幂等(以 event_id 去重)

6. 失败注入与回滚策略

场景ID 注入点 预期行为 验收点
FI-001 提现创建后数据库超时 事务回滚,不产生挂单 余额不变、无孤儿单
FI-002 幂等记录已存在同键异参 返回 409 不改业务状态
FI-003 套餐发布时状态冲突 返回 409 状态不跳变
FI-004 审计落库失败 主事务失败并回滚 无“成功但无审计”
FI-005 Outbox 入库失败 主事务失败并回滚 无“状态已变更但无事件”
FI-006 导出服务不可用 主事务成功,异步重试 业务不阻塞
FI-007 外部 query key 请求 网关拒绝 M-016=100%
FI-008 响应误回显凭证片段 安全门禁阻断 M-013=0

7. SLO 与页面动作映射

页面按钮 API SLI SLO Error Budget
BTN-ACC-001 立即验证 /api/v1/supply/accounts/verify 可用率 + P95 可用率 >= 99.9%P95 <= 800ms 月度 0.1%
BTN-ACC-002 提交挂载 /api/v1/supply/accounts 成功率 成功率 >= 99.5% 月度 0.5%
BTN-PKG-002 发布上架 /api/v1/supply/packages/{id}/publish 成功率 + 冲突率 成功率 >= 99.5%,冲突率 <= 0.3% 月度 0.5%
BTN-PKG-005 批量调价 /api/v1/supply/packages/batch-price 局部成功可解释率 明细可解释率 = 100% 0
BTN-SET-002 发起提现 /api/v1/supply/settlements/withdraw 一致性 + 时延 billing_error_rate_pct<=0.1%P95<=1200ms 与 M-004 联动
BTN-SET-003 撤销申请 /api/v1/supply/settlements/{id}/cancel 成功率 成功率 >= 99.9% 月度 0.1%

8. 审计与安全对齐

  1. 所有关键写请求必须记录:request_id/idempotency_key/operator_id/object_id/result_code
  2. 错误体、导出、日志统一经过脱敏扫描;命中即触发 P0。
  3. 与门禁指标映射:
    1. M-013凭证泄露事件数=0
    2. M-014平台凭证入站覆盖率=100%
    3. M-015需求方绕平台直连事件=0
    4. M-016外部 query key 拒绝率=100%

9. 实施与验收清单

  1. API 网关:校验并透传 X-Request-IdIdempotency-Key
  2. 数据库:新增幂等表、状态版本字段、提现唯一索引。
  3. 服务层:统一幂等拦截器与冲突返回码。
  4. 测试层:新增并发冲突、幂等重放、失败注入专项。
  5. 门禁层:将 FI-001~FI-008 纳入 SUP-*SEC-* Gate。
  6. 证据层:执行日志、指标截图、审计抽样、签署记录齐全。

达到以上 6 项即视为 XR-001 关闭。


10. 跨域数据库约束(新增)

  1. 供应域不是独立孤岛,必须依赖 Core/IAM/Auth/Billing/Audit 五域主表。
  2. 供应域关键表必须补齐三类字段:
    1. 加密字段:*_cipher_algo*_kms_key_alias*_key_version*_fingerprint
    2. 单位字段:quota_unitprice_unitamount_unitcurrency_code
    3. 审计字段:request_ididempotency_keyaudit_trace_idcreated_ipupdated_ipversion
  3. 数据库实施顺序固定:
    1. platform_core_schema_v1.sql
    2. supply_schema_v1.sql
    3. supply_schema_v1_patch_2026-03-27.sql
  4. 未完成上述顺序与字段补齐,不得判定 XR-001 关闭。