Files
qinglong/docs/adr/ADR-0336-model-price-catalog-management-domain-ownership.md
T

91 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-0336Model Price Catalog Management 领域归属
- 状态:Accepted
- 日期:2026-08-10
- 关联 RFCQL-RFC-0001 D-05、D-06、D-17、D-37、D-85、D-87、D-157、D-161、D-213、D-243、D-244、D-257
- 关联 ADRADR-0172、ADR-0173、ADR-0174、ADR-0177、ADR-0276、ADR-0334、ADR-0335
## 背景
`@qinglong/ai``pricing/modelPriceCatalogManagement.ts` 有 968 行,同时承担:
1. 公开管理 operation、Policy/authorization schema、service/repository port 与 request/result contract
2. 六类稳定错误、强 User principal freshness 与 exact-shape 基础校验;
3. Policy decision、authorization command、committed authorization 的 canonical digest、normalization 与 catalog command binding
4. publish/transition 的 Policy、quota、separation-of-duty 与 repository 编排。
这些职责属于同一个 Model Price Catalog management capability,共享强身份、Policy decision、authorization digest 与一次
catalog mutation 协议。它们没有独立部署、依赖、权限主体、生产 consumer 或供应链生命周期,不能仅因 968 行再拆一个
workspace package;但继续放在一个平铺文件中,会把公开 contract、纯 codec 与有副作用的 service orchestration 混为同一
审查单元,也让 Local/Cluster repository 对稳定授权门面的依赖看起来像对一个 god module 的依赖。
编辑前对 33 个 function/class 逐一执行 GitNexus upstream impact21 HIGH、5 MEDIUM、7 LOW、0 CRITICAL。HIGH
主要来自被 Local/PostgreSQL repository 共同使用的 exact validation、digest 与 authorization normalizer;最大影响是
`InvalidModelPriceCatalogManagementValueError`12 direct/48 total/0 process)和 `invalid`19/36/0)。接口与对象方法的
method-level impact 均为 LOW。已在编辑前告警,并把本批限定为原样 ownership 移动。
## 决策
保留一个 `@qinglong/ai` package、原 `pricing/modelPriceCatalogManagement` 导入路径和显式 public facade。在同一 Pricing
领域建立 package-private owner 目录:
```text
modelPriceCatalogManagement.ts # 42-line stable explicit facade
model-price-catalog-management/
├── contracts.ts # schemas, public ports, requests/results and stable errors
├── validation.ts # exact values, principal freshness and shared fail-closed helpers
├── authorization.ts # Policy/command/authorization canonical codec and bindings
└── service.ts # publish/transition Policy, quota and duty orchestration
```
依赖方向固定为 `contracts <- validation <- authorization``service` 只向这三层和既有 catalog contract 依赖;contract/codec
不得反向取得 repository、Pool、SQLite 或 PostgreSQL authority。根 facade 显式逐项转发原有 runtime/type export,不以
wildcard 意外公开 `BaseManagementRequest` 或内部 validation helper。
授权 digest domain、JSON field/order、exact-key validation、强认证 assurance、五分钟 freshness、operation/revision pairing、
Policy allow、quota idempotency key、separation-of-duty、repository 调用顺序、error class/code/message 与 public import path 均
保持。服务仍先在 request command 构造前验证 principal,并在 authorization 前再次按当前 clock 复验;本轮不借目录化改变
这一安全时序。
四个 owner 文件分别是 contracts 231、validation 243、authorization 349、service 229 行。没有按每个 operation、错误类或
normalizer 建立单文件;最大文件 349 行,同时包含一组共同变化的完整 authorization codec。
## 小设备与集群影响
不启用 AI 的 Edge、Standalone、Adopted 与 Application 六档制品逐字节、逐文件不变:最小 Edge 仍为
3,658,234 bytes、358 files、49 loaded modules。启用 AI 的四档因一个旧编译文件变成 facade 加四个 owner 编译文件,统一
增加 7,961 bytes/4 filesloaded modules 不变:Edge/Standalone AI 为 5,097,847/5,097,895 bytes、483 files、50 modules
Edge/Standalone Application AI 为 6,216,271/6,216,403 bytes、594 files、115 modules。没有新增 workspace package、生产
dependency、连接、timer、watcher、listener、线程或常驻对象;未启用 AI 的低配路由设备不承担目录化成本。
Cluster 继续使用同一个 `@qinglong/ai` package、Pool/schema/roles 和 management service,没有新增 Pod、Service、sidecar、
连接池或 Kubernetes resource。PostgreSQL 18.4 arm64 physical-streaming HA 门通过 `remote_apply`、timeline 1→2、旧主
fencing、`pg_rewind` 后只读同步 rejoin 与 AI schema/ACL 跨晋升存活,最终 `gates.passed=true`
## 被否决方案
1. **新增 Model Price Catalog Management workspace package**:没有独立部署、重依赖、authority 或多消费者边界,只会增加低配设备 importer、packlist 与 SBOM 粒度。
2. **继续保留 968 行文件**:公开 contract、canonical codec 与有副作用 service 无法独立审阅。
3. **按 publish/transition 或每个 normalizer 一文件**:会制造单 operation 文件,把共享 digest/principal/binding 不变量切碎。
4. **把 Local/PostgreSQL repository 一并合到 management 目录**:会混淆 domain service 与两个方言 adapter 的事务/连接 authority。
5. **直接导出 owner 文件为 package subpath**:会把内部层次固化成公共兼容承诺,并允许 consumer 绕过稳定 facade。
6. **趁移动统一 SQLite/PostgreSQL 或调整 principal 复验次数**:属于行为与安全时序变更,不能混入 ownership 重构。
## 验收证据
- public facade 968→42 行;owner 为 231/243/349/229 行,总计 1,094 行,最大 349;没有一方法一文件。
- 编译后的 facade 仍只有原 21 个 runtime export;所有 type export 由原路径生成,内部 `BaseManagementRequest` 与 validation helper 未公开。
- `@qinglong/ai` check 通过;AI package 212 项为 209 pass/3 条件 skip/0 fail;完整 16-package clean build/test 在允许 loopback TLS listener 的环境退出 0。
- package boundary、Edge import、Cluster dependency、Cluster deployment 四项审计全部 compatibleworkspace 仍为 16 package`singleSourcePackages=[]``shallowSourcePackages=[]`。AI 为 123 source、1 root/122 nestedEdge imported modules 仍为 121。
- 十档 artifact 均 compatible;非 AI 六档精确不变,AI 四档 +7,961 bytes/+4 files/+0 loaded modules。
- PostgreSQL HA Docker 门退出 0,旧主 fencing、promotion、rejoin、AI migration/ACL 和最终 gate 全部通过。
- `git diff --check` 通过;GitNexus 强制重建为 44,428 nodes/101,355 edges/1,738 clusters/296 flows。post-impact 保持 0 processservice、Policy creator 与两个 repository binding normalizer 为 LOW,底层 exact validation/digest/authorization codec 仍按预期显示跨三模块 HIGH,没有出现新 execution flow。
- `detect_changes` all 为 12 files/31 symbols/0 process/lowcompare `develop` 为 14/34/0/low;当前 QL3 孵化树尚未完整进入默认分支索引,因此 detect result 只作 Git 基线补充。
## 后续约束
`contracts.ts` 不取得 I/O authority`validation.ts` 不拥有业务 operation`authorization.ts` 不调用 repository`service.ts`
不复制 canonical digest/normalization。新增字段或 schema version 必须同时评审 canonical digest、durable replay 与双方言 adapter
新增 management operation 按共同变化原因归入现有层,不能自动增加文件或 package。只有出现独立部署、独立权限主体、显著可选
依赖、多个生产 consumer 或可测 artifact 裁剪价值时,才重新评估 workspace package 边界。