openxiangda-skill-kit 2.0.0-alpha.39 → 2.0.0-alpha.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +4 -6
  2. package/dist/bin.js +0 -0
  3. package/dist/index.d.ts +3 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +74 -43
  6. package/dist/index.js.map +1 -1
  7. package/dist/internal/skill-installer.d.ts +9 -0
  8. package/dist/internal/skill-installer.d.ts.map +1 -0
  9. package/dist/internal/skill-installer.js +53 -0
  10. package/dist/internal/skill-installer.js.map +1 -0
  11. package/package.json +2 -6
  12. package/skills/manifest.json +2 -32
  13. package/skills/openxiangda-v2/SKILL.md +11 -42
  14. package/skills/openxiangda-v2/references/architecture.md +5 -0
  15. package/skills/openxiangda-v2/references/backend.md +5 -0
  16. package/skills/openxiangda-v2/references/data-authz.md +5 -0
  17. package/skills/openxiangda-v2/references/delivery.md +11 -0
  18. package/skills/openxiangda-v2/references/frontend.md +5 -0
  19. package/docs/architecture/admin-shell-v2.md +0 -1030
  20. package/docs/architecture/ant-design-pro-v6-admin-foundation.md +0 -343
  21. package/docs/architecture/app-api-user-delegation-v2.md +0 -40
  22. package/docs/architecture/authorization-consistency-v2.md +0 -419
  23. package/docs/architecture/best-practice-template-rebuild-v2.md +0 -206
  24. package/docs/architecture/environment-configuration-kernel-v2.md +0 -290
  25. package/docs/architecture/field-component-migration-matrix-v1-to-v2.md +0 -76
  26. package/docs/architecture/field-value-contract-boundary.md +0 -92
  27. package/docs/architecture/frontend-runtime-mount-v2.md +0 -82
  28. package/docs/architecture/implementation-roadmap.md +0 -79
  29. package/docs/architecture/local-development-v2.md +0 -136
  30. package/docs/architecture/mobile-user-standard-pages-v2.md +0 -88
  31. package/docs/architecture/native-configuration-projection-v2.md +0 -488
  32. package/docs/architecture/native-kernel-inventory-v2.md +0 -196
  33. package/docs/architecture/native-managed-files-v2.md +0 -18
  34. package/docs/architecture/on-demand-production-environment-v2.md +0 -102
  35. package/docs/architecture/proven-field-components-and-standard-surfaces-v2.md +0 -133
  36. package/docs/architecture/release-verification-receipt-v2.md +0 -72
  37. package/docs/architecture/repository-and-release.md +0 -65
  38. package/docs/architecture/school-contact-default-access-v2.md +0 -13
  39. package/docs/architecture/stable-field-protocol-adoption.md +0 -174
  40. package/docs/architecture/standard-surface-runtime-corrections-v2.md +0 -108
  41. package/docs/architecture/tenant-public-origin-implementation-blueprint.md +0 -484
  42. package/docs/architecture/tenant-public-origin-v2.md +0 -236
  43. package/docs/architecture/verification-orchestration-v2.md +0 -24
  44. package/docs/backend.md +0 -102
  45. package/docs/concepts.md +0 -34
  46. package/docs/data-authz.md +0 -127
  47. package/docs/delivery.md +0 -77
  48. package/docs/design/admin/README.md +0 -124
  49. package/docs/design/admin/data-management-v1.png +0 -0
  50. package/docs/design/admin/workbench-v1.png +0 -0
  51. package/docs/design/admin/workflow-detail-v1.png +0 -0
  52. package/docs/design/admin-pro-v6/README.md +0 -26
  53. package/docs/design/admin-pro-v6/data-management.png +0 -0
  54. package/docs/design/admin-pro-v6/workbench.png +0 -0
  55. package/docs/design/admin-pro-v6/workflow-submit-modal.png +0 -0
  56. package/docs/design/admin-shell-dashboard-v2.png +0 -0
  57. package/docs/design/admin-standard-pages-v2.png +0 -0
  58. package/docs/design/admin-v2/README.md +0 -60
  59. package/docs/design/admin-v2/data-management.png +0 -0
  60. package/docs/design/admin-v2/form-detail.png +0 -0
  61. package/docs/design/admin-v2/form-submit.png +0 -0
  62. package/docs/design/admin-v2/workbench.png +0 -0
  63. package/docs/design/admin-v2/workflow-detail.png +0 -0
  64. package/docs/design/admin-v2/workflow-submit.png +0 -0
  65. package/docs/design/openxiangda-2.0-high-fidelity/README.md +0 -293
  66. package/docs/design/openxiangda-2.0-high-fidelity/admin-component-acceptance.png +0 -0
  67. package/docs/design/openxiangda-2.0-high-fidelity/admin-data-form.png +0 -0
  68. package/docs/design/openxiangda-2.0-high-fidelity/admin-workbench.png +0 -0
  69. package/docs/design/openxiangda-2.0-high-fidelity/mobile-approval-preview.png +0 -0
  70. package/docs/design/openxiangda-2.0-high-fidelity/mobile-data-list.png +0 -0
  71. package/docs/design/openxiangda-2.0-high-fidelity/mobile-form.png +0 -0
  72. package/docs/design/openxiangda-2.0-high-fidelity/mobile-request-form.png +0 -0
  73. package/docs/design/openxiangda-2.0-high-fidelity/mobile-request-list.png +0 -0
  74. package/docs/design/openxiangda-2.0-high-fidelity/mobile-submit-workflow-preflight.png +0 -0
  75. package/docs/design/openxiangda-2.0-high-fidelity/mobile-workbench.png +0 -0
  76. package/docs/design/openxiangda-2.0-high-fidelity/mobile-workflow-detail.png +0 -0
  77. package/docs/design/openxiangda-2.0-high-fidelity/user-pc-data-list.png +0 -0
  78. package/docs/design/openxiangda-2.0-high-fidelity/user-pc-form-workflow-preview.png +0 -0
  79. package/docs/design/openxiangda-2.0-high-fidelity/user-pc-request-form-approval.png +0 -0
  80. package/docs/design/openxiangda-2.0-high-fidelity/user-pc-request-list.png +0 -0
  81. package/docs/design/openxiangda-2.0-high-fidelity/user-pc-workbench.png +0 -0
  82. package/docs/field-components.md +0 -93
  83. package/docs/frontend.md +0 -78
  84. package/docs/getting-started.md +0 -148
  85. package/docs/index.md +0 -27
  86. package/docs/llms.txt +0 -20
  87. package/docs/reference/cli.md +0 -69
  88. package/docs/reference/mcp.md +0 -31
  89. package/docs/school-contact-relations.md +0 -136
  90. package/docs/workflow-events.md +0 -86
  91. package/skills/openxiangda-v2-architecture/SKILL.md +0 -30
  92. package/skills/openxiangda-v2-architecture/agents/openai.yaml +0 -4
  93. package/skills/openxiangda-v2-backend/SKILL.md +0 -48
  94. package/skills/openxiangda-v2-backend/agents/openai.yaml +0 -4
  95. package/skills/openxiangda-v2-data-authz/SKILL.md +0 -58
  96. package/skills/openxiangda-v2-data-authz/agents/openai.yaml +0 -4
  97. package/skills/openxiangda-v2-delivery/SKILL.md +0 -88
  98. package/skills/openxiangda-v2-delivery/agents/openai.yaml +0 -4
  99. package/skills/openxiangda-v2-frontend/SKILL.md +0 -50
  100. package/skills/openxiangda-v2-frontend/agents/openai.yaml +0 -4
  101. package/skills/openxiangda-v2-workflow-events/SKILL.md +0 -56
  102. package/skills/openxiangda-v2-workflow-events/agents/openai.yaml +0 -4
@@ -1,196 +0,0 @@
1
- # OpenXiangda 2.0 Alpha 退役与 Native 切换前置审计
2
-
3
- 状态:方案已确认;CP0-CP2 已在主线实现并通过本地/一次性 PostgreSQL/smoke 验证,尚未执行 prod-1 只读 preflight;不代表 Native 运行时或 K4 generation 切换已实现
4
-
5
- 适用范围:prod-1 上的 OpenXiangda 2.0 实验状态;不迁移、不清理、不改变任何 1.x 应用
6
- 替代方案:本文取代“全平台 inventory evidence schema + 通用 importer”设计
7
-
8
- ## 1. 架构结论
9
-
10
- OpenXiangda 2.0 明确不兼容 1.x,当前 prod-1 又只有一个可重建的 2.0 reference 应用,因此不建设长期迁移子系统。Native 内核从新配置合同、新数据库表和新建应用开始;旧 alpha reference 的业务数据、角色、OAuth、Event、Workflow 和 Runtime 不迁移,只在观察期内保留为审计事实。
11
-
12
- 切换前只实现一个小型、只读、显式 allowlist 的发布前置审计:它证明线上不存在必须迁移的真实 2.0 应用,并证明 1.x 事实不会被误分类。审计不创建数据库 schema/role/LOGIN/Secret,不扫描平台全部业务数据,不生成写计划,也不成为 Admin 或应用 CLI 的永久能力。
13
-
14
- 这项决定建立在 2026-08-13 的源码和 prod-1 只读证据上,而不是“以后大概只有测试数据”的假设。
15
-
16
- ## 2. 本轮架构门禁
17
-
18
- | 维度 | 决定 |
19
- | --- | --- |
20
- | 问题证据 | 原设计从 `app_delivery_runs`、`app_runtime_releases`、Event Outbox 等共享表枚举“2.0 事实”,但生产中这些表包含大量 1.x 发布与事件记录;按表名或能力版本分类会误伤稳定应用。真正的 Application v2 AppVersion/Head 和 K3s application-v2 workload 只有 reference app。 |
21
- | 能力所有者 | Platform Server 的 Native Kernel 拥有新 2.0 数据模型,同一不可变 Platform Server 镜像内的独立 Node 脚本拥有只读分类器;根部署仓库拥有短生命 Job/K3s metadata/receipt 编排与后续 generation CAS;新建独立 reference app 拥有 Native 验收数据。旧 alpha 表只作为停止写入的历史事实,不成为 Native 输入。 |
22
- | 稳定不变量 | 1.x 路由、发布、Runtime、数据、Event Outbox 和旧应用记录不读取 Native 表,也不进入退役范围;Native 不读取 alpha 表作为 fallback;旧 alpha 数据不复制、不重写、不删除;新 reference app 不复用旧 app code、UUID、OAuth、Secret、RoleSession、业务表或 K3s workload。 |
23
- | 上下游契约 | 切换前审计只接受显式 `tenant/app` allowlist,并以 Application v2 package schema、AppVersion/Head 闭包和 K3s managed label 交叉验证;E1 的 bundle v3 与 Native 表从空状态编译;Admin、CLI、SDK 只消费 Native generation。 |
24
- | 并发与失败 | 审计脚本在独立 `REPEATABLE READ READ ONLY` 事务中生成确定性数据库语义摘要。根脚本按 `DB-A -> K3s-A -> DB-B -> K3s-B` 运行两个同镜像 Job 和两次 metadata list,前后任一语义摘要变化即 stale。receipt 不能单独授权 K4;切换时仍必须重做轻量 recheck 并与 kernel expected revision 同事务 CAS。审计失败只阻断 2.0 generation 切换,不影响 1.x 或现有 alpha reference。 |
25
- | 安全与资源 | 审计入口不启动 Midway/HTTP/Redis/队列/Scheduler。根脚本从当前 Deployment 只复用 `envFrom` 引用,不读取或复制 Secret 值;Job 固定执行经主线和发布 manifest 验证的镜像摘要,禁用 ServiceAccount token,只读根文件系统,100m/128Mi request、500m/512Mi limit、60 秒 deadline。数据库连接从第一条语句起默认只读,再进入显式只读事务;这是受控发布代码的防误写边界,不伪装成独立数据库 principal 的强安全隔离。只输出 allowlist app 的稳定标识、状态和数量,不输出用户、业务字段、URL、token、hash、密文或物理表名。最大 20 个 alpha app、2 MiB JSON、60 秒。 |
26
- | 回滚单元 | K4 前 Native schema/compiler/gate 均 additive;alpha reference 继续可用。K4 后不恢复 alpha 语义,失败时保持 2.0 maintenance 并发布 Native-aware 修复;1.x 始终在线。新 reference app 使用 Native Head 回滚,不依赖旧 alpha 数据。 |
27
- | 可证伪验收 | 构造仅有 legacy DeliveryRun/Runtime/Event Outbox 的 1.x app,必须不进入 alpha scope;构造 package schema 不匹配、Head 闭包破损、额外 K3s workload、运行中 DeliveryRun、待处理 Event/Workflow 或 revision 变化,必须阻断;报告中放置 Secret/user/business canary,输出必须零命中。 |
28
-
29
- ## 3. 生产事实与决策依据
30
-
31
- 2026-08-13 在 prod-1 运行了只读事务和 K3s metadata 查询,没有执行任何写入。结果如下:
32
-
33
- | 事实 | 只读结果 | 架构含义 |
34
- | --- | --- | --- |
35
- | `app_versions_v2` | 仅 `001/openxiangda-v2-reference-app`,12 个 AppVersion | Application v2 实际使用者只有 reference app |
36
- | `app_environment_heads_v2` | reference app 的 preproduction、production 各 1 个 Head | 没有第二个需要迁移的 Native 候选应用 |
37
- | K3s `managed-by=openxiangda-application-v2` | reference app 的 preproduction、production 各 1 个 Deployment/Pod | 运行面与数据库 Head 闭包一致 |
38
- | Data Resource | 5 个资源,共 37 行;全部已有明确 preproduction/production key | README 和脚本证明它们是可重复生成的验收数据,不是用户业务数据 |
39
- | Authz | 4 个活动 assignment、2 个活动 relationship grant;RoleSession 是验收操作产生 | 由 seed/E2E 在新 reference app 重新创建,不迁移主体关系 |
40
- | OAuth/Secret | 每环境 1 个活动 OAuth client,另有撤销记录;runtime Secret 为 0 | 新环境重新签发,绝不搬运凭据 |
41
- | Event | 每环境 2 个订阅;90 个 reference outbox、16 成功 delivery、6 DLQ、4 成功 receipt | 属于韧性验收历史;不重放、不迁移 |
42
- | Workflow | 8 个 instance,其中 1 个 running;15 个 human task,其中 1 个 assigned | 都是验收实例;切换前终止旧 runtime,历史留存,不迁移流程实例 |
43
- | 共享旧能力表 | `app_delivery_runs`、`app_runtime_releases`、`app_event_outbox_v2` 中有大量其他 app | “表名带 v2”不等于 Application v2;不能用这些表独立扩大 scope |
44
-
45
- reference app 仓库明确说明它是独立验收应用;`seed-production.mjs`、`prod-e2e.mjs` 和 OAuth E2E 使用可重复 seed、唯一 runId 和最终撤销。上述 37 行和流程/事件记录可以由新应用重新生成,因此迁移它们只会把 alpha 数据模型和脏历史带入 Native。
46
-
47
- ## 4. 明确拒绝的方案
48
-
49
- | 方案 | 拒绝原因 |
50
- | --- | --- |
51
- | 为审计新建全平台 evidence schema、per-database reader role、独立 DB Secret、ServiceAccount/RBAC 或常驻 Job 体系 | 为一次实验切换增加长期数据库安全面、凭据轮换、RBAC、报告存储和发布维护成本;当前没有真实迁移对象支撑该复杂度。这不禁止根部署脚本复用已有 release Job 原语创建无 ServiceAccount 的短生命、受限资源容器 |
52
- | 根据 `app_delivery_runs` / `app_runtime_releases` / Event Outbox 自动发现 2.0 app | 这些是 1.x 与 2.0 共用的历史能力表,生产事实已经证明会把大量稳定 1.x app 错纳入范围 |
53
- | 通用 importer,把 alpha role/grant/data/workflow/event 搬到 Native | reference 数据可重建;通用 importer 需要主体映射、敏感决策 UI、CAS/generation 和业务数据扫描,形成一套只使用一次的产品 |
54
- | 原地升级 alpha Head、RoleSession、Data Resource 表 | 会保留 nullable legacy 字段、全局授权语义和双重事实源;Native 必须用能直接表达约束的新表 |
55
- | 切换时删除 alpha 数据 | 删除扩大事故半径且没有必要;旧记录不被 Native 读取即可,物理清理由独立 retention 项目处理 |
56
- | 新 reference app 复用旧 app code | 容易使 alpha OAuth、RoleSession、业务表、Event/Workflow 状态被误读;新应用必须有新 identity |
57
-
58
- ## 5. Alpha scope 的唯一判定
59
-
60
- 审计工具不做“全库智能发现”。操作者必须显式提交 allowlist:
61
-
62
- ```text
63
- tenantId/appCode
64
- decision = rebuild-on-native | retain-blocked
65
- expectedAlphaAppVersionCount
66
- expectedHeadKeys
67
- expectedManagedWorkloads
68
- changeRef
69
- ```
70
-
71
- 每个 allowlist app 必须满足以下闭包:
72
-
73
- 1. 至少一个 `app_versions_v2` 行,且 `package_manifest_json.schemaVersion = openxiangda.app-package/v2`;
74
- 2. 每个 alpha Head 指向同 tenant/app 的 AppVersion 和 succeeded Application v2 DeploymentRun;
75
- 3. 只统计该集合在 OAuth、Secret、Authz、Data、Event、Workflow 中的聚合状态;不会因为其他 app 出现在同一表就扩充集合;
76
- 4. K3s 对象必须同时具有 `app.kubernetes.io/managed-by=openxiangda-application-v2`、相同 app code/environment label 和 Head 对应 AppVersion annotation;
77
- 5. `app_delivery_runs` 只有同时属于 allowlist app 且 package schema 精确匹配时才算 Application v2;
78
- 6. `app_runtime_releases`、legacy forms/pages/roles、共享 Event Outbox 永远不能独立把 app 加入集合。
79
-
80
- 自动发现到 allowlist 外的有效 Application v2 AppVersion/Head/workload 时返回 `UNDECLARED_ALPHA_APPLICATION` 并阻断。只存在 legacy DeliveryRun/Runtime/Event 的 app 不报告详情,只记录 `legacyExcludedCount`,以证明分类器没有误纳入。
81
-
82
- ## 6. 最小只读审计入口
83
-
84
- 首期只在 Platform Server 镜像已有 `scripts/` 运维入口体系增加一个 CommonJS 命令,不放入 `src/configuration.ts` 的 Midway 生命周期:
85
-
86
- ```text
87
- node scripts/openxiangda-v2-native-cutover-inspect.js \
88
- --mode snapshot \
89
- --allowlist /run/openxiangda/native-cutover-allowlist.json
90
- ```
91
-
92
- 约束:
93
-
94
- - 入口直接创建一个 `pg.Client`,只复用 `run-sql-migrations.js` 已导出的 PostgreSQL SSL 解析合同;不导入 `src/configuration.ts`、service/entity/repository,不启动 Midway、HTTP、队列、Scheduler、DingTalk Stream、Redis、RabbitMQ 或 Kubernetes client;
95
- - 根脚本从当前 Platform Server Deployment 提取 `envFrom` 引用到临时 Job,镜像内进程只消费环境变量;不复制、打印或持久化凭据;
96
- - `pg.Client` 连接参数加入 `default_transaction_read_only=on`、15 秒 statement timeout、2 秒 lock timeout 和 20 秒 idle-in-transaction timeout;连接后首先验证 `transaction_read_only=on`,再执行 `BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY`,单 Job 和根脚本总 deadline 均为 60 秒;
97
- - SQL 固定、参数化、只读;禁止动态表名、业务表扫描、`COUNT(*)` 大表扫描和任意写语句;Data 只读取资源级安全计数/状态,切换决策不依赖精确业务行数;
98
- - 脚本成功时 stdout 只写一个 canonical JSON document,stderr 仅允许无参数稳定错误码;报告不进入应用 OSS、长期 ConfigMap、Git 或浏览器;
99
- - 根部署脚本复用现有 backend release Job 构造原语:从权威 version manifest 验证主线、release lineage 和镜像 digest,创建一个短期无秘密 allowlist ConfigMap 和两个 `automountServiceAccountToken=false` Job;不新建 ServiceAccount/RoleBinding/Secret,不 patch Deployment;
100
- - 根脚本在主机本地以 `0600` 先写临时文件,对 DB-A/K3s-A/DB-B/K3s-B 重算 semantic digest 并校验预算后才原子 rename 为 receipt;任一 Head、AppVersion、活动 run、pending delivery/task、kernel revision 或受管 workload 语义变化都报告 stale;
101
- - 无论成功失败,Job/Pod/ConfigMap 都在取完日志后删除;根脚本无权将 incomplete/stale 报告标为可切换;
102
- - 普通 build/update 不自动执行;只有显式 Native cutover preflight 调用。
103
-
104
- 报告只含:schema/release/image digest、allowlist digest、每个 app 的 AppVersion/Head/status 数量、是否存在 active run/pending event/pending workflow、K3s workload identity/readiness、分类、blocker、四段 semantic digest 和有效期。用户、角色主体、业务关系、业务字段、错误 payload、URL、Secret/OAuth 值及其 hash 都不输出。K3s semantic digest 只覆盖 UID/generation/observedGeneration、镜像 digest、replica/readiness、相关 label/annotation 和 service target,不因无关 resourceVersion 或时间戳飘移。
105
-
106
- ## 7. Native 重新创建策略
107
-
108
- Native reference 必须由 `create-openxiangda` 的当前本地候选工件创建成新的独立 Git 仓库和新 app code。它复用业务场景和验收断言,不复用任何线上 identity 或状态:
109
-
110
- ```text
111
- 旧:openxiangda-v2-reference-app (alpha,冻结/留存)
112
- 新:openxiangda-v2-native-reference-app (native-2,从空状态创建)
113
- ```
114
-
115
- 新应用按以下顺序建立事实:
116
-
117
- 1. Native provision 事务创建 preproduction、production;local 只由本地工具链创建临时运行状态;
118
- 2. bundle v3 编译为不可变 authz/data/event/workflow/runtime revisions 和 AppVersion binding;
119
- 3. seed 只在 local/preproduction 运行,且每次带唯一 runId;
120
- 4. 角色 membership、学院/仪器关系和 super-admin grant 由 Native Admin/SDK 显式创建;
121
- 5. OAuth 与应用 Secret 在各环境重新签发,值只出现一次;
122
- 6. 先用真实本地 tarball 和本地平台验证,再将同一 AppVersion 部署 preproduction,验收后晋级 production;
123
- 7. production 通过后才允许退役旧 alpha K3s workload 和 OAuth principal。
124
-
125
- 旧 alpha 的 running Workflow 和 assigned task 不迁移。K3 drain 时停止旧应用入口与 consumer,记录最终数量;历史状态保留在 alpha 表中。Native 只展示新 app code 的实例。
126
-
127
- ## 8. 切换状态机
128
-
129
- | 阶段 | 动作 | 失败语义与回滚 |
130
- | --- | --- | --- |
131
- | K0 evidence | 运行最小只读审计,确认 allowlist 只有 alpha reference,生成 receipt | 只读;失败不影响线上 |
132
- | K1 native build | 增加 Native schema、compiler、generation gate、CLI/SDK/Admin,创建全新 reference repo | additive;alpha/1.x 仍运行 |
133
- | K2 capable rollout | 全部 Platform Server 实例升级到理解 alpha/native generation 的同一 release,Native 路由仍关闭 | 可回滚到同样不写 Native 的兼容 release |
134
- | K3 validate/drain | 本地/隔离测试环境完成新 reference 全链路;prod-1 只验证 immutable artifact、Native Head 闭包和无业务凭据的 candidate readiness;暂停 2.0 alpha 写和 consumer,等待活动 run/lease 归零 | 保持 2.0 maintenance;1.x 不受影响 |
135
- | K4 native switch | CAS 将 generation 切为 `native-2`;alpha 2.0 endpoint 稳定 410;只有已经 Native Head 绑定的新 reference 可路由,在验收窗口跑真实预发 E2E | 不回 alpha;失败保持 Native 常规创建入口关闭,并发 Native-aware 修复 |
136
- | K5 accept/retire | 预发 E2E 通过后开放 Native 常规创建/写入,同一 AppVersion 晋级 production 并再跑完整 E2E;观察期后撤销旧 alpha runtime OAuth、删除旧 alpha K3s workload | 新 reference 用 Native Head 回滚;数据库 alpha 历史不删除 |
137
-
138
- K4 不执行大批数据 UPDATE/INSERT,也不运行 importer。切换事务只更新 kernel generation/revision 和审计 receipt,因此锁和回滚面有界。
139
-
140
- ## 9. 与 1.x 的隔离
141
-
142
- 1.x 不使用 `app_versions_v2 + app_environment_heads_v2 + exact package schema` 的 Application v2 闭包。即使 1.x 应用曾使用 Delivery V2、React SPA Runtime、Event Outbox、App Function、Workflow 或 OAuth,也不能因此进入 Native scope。
143
-
144
- Native migration 只增加新表/索引和 generation gate;不修改 legacy 表的语义、不删除旧列、不把 `environment_id` 塞进 1.x 行、不改旧 runtime resolver。代表性 1.x 应用在 K0-K5 每阶段进行登录、页面、数据、流程/自动化和 Runtime 回归,但其数据从不进入审计报告或清理计划。
145
-
146
- ## 10. 实现文件计划(确认后)
147
-
148
- ### Platform Server
149
-
150
- | 文件/目录 | 变化 |
151
- | --- | --- |
152
- | `scripts/openxiangda-v2-native-cutover-inspect.js` | 镜像内 CommonJS 只读入口;显式 allowlist、固定查询、稳定 JSON/错误码;不进入 Midway 编译/生命周期 |
153
- | `scripts/lib/openxiangda-v2-native-cutover.js` | scope classifier、report schema、canonical digest、blocker;纯函数,不读取 process/env |
154
- | `test/openxiangda-v2-native-cutover-inspect.test.ts` | 真实 PostgreSQL:legacy exclusion、Application v2 闭包、只读拒写、stale、canary、预算 |
155
- | `scripts/verify-openxiangda-v2-native-cutover.js` | 静态证明入口不依赖 Midway/service/entity/Redis/queue/stream,查询字面量不含写 SQL/动态 relation,且 SSL 复用 migration runner 合同 |
156
- | `scripts/verify-openxiangda-v2.js` | 将切换审计静态门禁、一次性 PostgreSQL 和单元测试纳入平台候选验证;无独立 evidence migration |
157
-
158
- ### 根部署仓库
159
-
160
- | 文件/目录 | 变化 |
161
- | --- | --- |
162
- | `scripts/openxiangda-v2-native-cutover-preflight.sh` | 校验主线/release lineage/image digest;从当前 Deployment 构造两个受限资源短生命 Job,编排 DB-A/K3s-A/DB-B/K3s-B,原子保存 receipt,不 patch Deployment |
163
- | `scripts/openxiangda-v2-native-cutover-k3s-snapshot.jq` | 严格校验 allowlist 与全集群受管 Deployment/Service 闭包,只保留 UID/generation/readiness/image digest/服务目标等安全语义 |
164
- | `scripts/openxiangda-v2-native-cutover-consistency.jq` | 按 tenant/app/environment 交叉校验数据库 Head 与 K3s workload 的 AppVersion/package digest 闭包 |
165
- | `config/openxiangda-v2-native-cutover.allowlist.example.json` | 无秘密显式 allowlist;正式文件不进 Git |
166
- | `scripts/openxiangda-v2-native-cutover-smoke.sh` | mock kubectl/报告,证明 Job 无 SA token/资源有界/镜像摘要锁定、两次摘要变化 fail closed、失败不切 generation、普通发布不自动执行 |
167
-
168
- ### OpenXiangda 2.0 工具链
169
-
170
- 首期不增加 inventory 命令。应用 CLI 无权查看跨应用生产事实。工具链只负责 bundle v3、新应用生成、Native capability 检查和部署;切换前审计属于平台运维面。
171
-
172
- ## 11. 可证伪验收矩阵
173
-
174
- 1. prod-1 报告只识别显式 alpha reference;只存在 legacy DeliveryRun/Runtime/Event 的应用全部 excluded。
175
- 2. 增加一个 allowlist 外、package schema 正确的 AppVersion/Head/workload 后,preflight 以 `UNDECLARED_ALPHA_APPLICATION` 失败。
176
- 3. Head 指向错误 app/version/run、K3s annotation 不匹配、额外可服务旧 workload、活动 DeliveryRun/lease、pending Event delivery 或 pending Workflow task 均阻断 K4。
177
- 4. 数据库 session 首条查询和事务内都证明 `transaction_read_only=on`;注入 INSERT/UPDATE/DELETE/DDL canary 全部失败,数据库 LSN/目标行数不变。
178
- 5. 报告、stderr、receipt 对预置 token/Secret/user/resource/business canary 零命中;不存在连接信息、物理表名或业务字段。
179
- 6. 60 秒/2 MiB/20 app 任一预算超限都 fail closed,不截断后继续切换。
180
- 7. 在 DB-A/K3s-A/DB-B/K3s-B 的任意间隔并发切 Head、新增 workload 或改受管 Service target,前后摘要不一致使报告 stale;即使 receipt 未过期,K4 的轻量 recheck/revision CAS 也必须拒绝后续变化。
181
- 8. 新 reference app 的所有 UUID、app code、业务表、OAuth、Secret、membership、RoleSession、Event/Workflow state 与旧 alpha 无交集。
182
- 9. Native reference 在本地、preproduction、production 完成同一 AppVersion 的 OAuth、Secret、四角色切换、Data API、受限事务、Workflow、代理/加签、Event 重试/receipt、Nest App API 和 Admin Chromium 验收;local 不创建远程 registry/Head。
183
- 10. K0-K5 每阶段代表性 1.x 登录、页面、数据、流程/自动化与 Runtime 正向通过;其数据库记录和 K3s workload没有被 audit/retire 修改。
184
- 11. K4 只有一次有 revision 条件的 kernel generation CAS;无 alpha→native 批量数据写、无 importer、无业务表扫描。
185
- 12. K5 只撤销明确列出的旧 alpha runtime principal并删除两个旧 alpha K3s workload;数据库 alpha 历史保留,任何 `DROP ... CASCADE` 或按表名清理都被 verifier 拒绝。
186
-
187
- ## 12. 确认后的实施顺序
188
-
189
- 1. CP0:实现最小 scope classifier/report schema 与真实 PostgreSQL legacy-exclusion 测试。
190
- 2. CP1:实现 Platform Server `scripts/` 独立只读入口、默认只读 session、静态依赖/SQL 门禁。
191
- 3. CP2:已实现根部署 preflight、受限资源短生命 Job、全集群两阶段 K3s metadata/recheck 与本地 receipt;脚本与两个 JQ 合同作为不可变 deploy assets 绑定版本清单。下一步先发布包含 CP0-CP2 的 capable release,再在 prod-1 显式运行只读 preflight;不由普通发布自动触发、不切换 generation。
192
- 4. E1/A0:实现 Native schema、bundle v3 compiler、环境配置和授权投影;不导入 alpha。
193
- 5. 创建全新独立 `openxiangda-v2-native-reference-app`,用本地未发布包做完整验证。
194
- 6. 完成 E2-E5、Admin A-D 和安全轨后,按 K2-K5 切换并验收。
195
-
196
- 确认本设计只表示允许开始 CP0/CP1;不授权 K4 generation 切换、删除旧 workload、撤销凭据或发布生产版本。`CP*` 只表示 cutover preflight,与环境激活协议已有的 `P0 planning / P1 candidate / P2 readiness / P3 activate / P4 retire` 严格分离。每个动作仍按本路线图的独立门禁执行。
@@ -1,18 +0,0 @@
1
- # Native 托管文件闭环
2
-
3
- ## 决策记录
4
-
5
- | 维度 | 决策 |
6
- | --- | --- |
7
- | 问题证据 | Devkit、Nest SDK 与本地平台已经使用 `/native/data/**`,但 prod-1 的真实 `files/uploads/initiate` 返回 404;平台能力发现仍声明 `data.managed-files`,Field Kit 因而在运行时才失败。 |
8
- | 能力所有者 | Platform Server Native Data API 唯一拥有文件元数据、绑定、下载授权和对象存储访问;Platform Storage 拥有签名与对象操作;Field Kit 只拥有稳定附件值适配和 UI。 |
9
- | 稳定不变量 | 业务字段继续保存既有 `name/url/size/type/provider/fileId/...` 稳定附件项;`DataFileRef` 只用于 initiate/complete 传输。2.0 只调用 Native 路径,不回退旧 `/data/**`。 |
10
- | 受影响合同 | 既有 initiate、complete、delete、content 客户端方法获得真实 Native 服务端实现;Field Kit 保存的受保护 URL 改为 Native 路径;能力名与 DTO 不变。 |
11
- | 失败与并发 | 上传绑定创建时的 Environment Head;Head 改变后未绑定文件拒绝完成/绑定。业务创建、更新、受限事务和文件绑定同事务提交;重复完成幂等,并发绑定只有一个记录成功。 |
12
- | 安全与资源 | 用户请求必须携带当前 RoleSession;应用身份上传/删除要求 `data:write`、下载要求 `data:read`。服务端校验字段权限、数据权限、大小、数量和类型;未绑定/孤立对象由有界租约清理。 |
13
- | 回滚边界 | 工具包只修正 2.0 Native URL 和本地同构实现;无 1.x 代码。平台表独立于旧文件表,回滚包不会改变旧应用数据。 |
14
- | 可证伪验证 | 包测试逐字节断言所有文件 URL 为 Native;本地真实 PostgreSQL 完成上传、绑定、下载和清理;prod-1 使用同一 AppVersion 验证 OAuth2/RoleSession、Data、文件与 Workflow 全链路。 |
15
-
16
- Platform Server 的持久化与运行边界详见根编排仓库
17
- `docs/architecture/2026-08-16-openxiangda-native-managed-files.md`。本仓库不得用旧
18
- Data API fallback 掩盖平台未就绪,也不得把对象存储凭据暴露给应用代码。
@@ -1,102 +0,0 @@
1
- # OpenXiangda 2.0 按需正式环境
2
-
3
- 状态:2026-08-16 已正式发包并完成 prod-1 全新应用在线验收。
4
-
5
- ## 问题证据
6
-
7
- 当前 `app provision` 会同时创建预发和正式环境,参考应用部署后也容易同时保留两套后端工作负载。大多数 2.0 应用长期处于开发或试验阶段,不会正式投入使用。提前创建正式环境、运行凭据、环境状态和 Kubernetes 工作负载没有业务价值,还会增加资源占用、运维噪音和发布失败面。
8
-
9
- ## 能力归属
10
-
11
- - 应用身份、环境注册、DeploymentRun、环境 Head 和运行期启停状态由平台控制面唯一拥有。
12
- - Git 仓库和 AppPackage 只拥有源码、声明与不可变 AppVersion,不保存环境是否已创建或正在运行的事实。
13
- - CLI、MCP、AI 和 Admin 管理端只是控制面客户端,不自行推导或补写正式环境。
14
-
15
- ## 决策
16
-
17
- 一个 2.0 逻辑应用默认只创建稳定的 `preproduction` 环境。`production` 是可选的长期环境,仅在开发者首次执行明确的“发布正式版”操作时惰性创建。
18
-
19
- 1. `app provision` 幂等创建应用身份、应用最高管理员授权和预发环境,不创建正式环境。
20
- 2. 日常 `deploy` 只向预发部署新的不可变 AppVersion。
21
- 3. 首次 `promote <preproduction-deployment-id> production` 选择一个已在预发成功运行的 AppVersion,创建正式环境并把同一个 AppVersion 发布到正式环境。发布过程不重新构建制品。
22
- 4. 后续 `promote` 复用已有正式环境,只更新其环境 Head。
23
- 5. 预发和正式工作负载均支持显式启动、停止。停止只把期望运行副本降为零,不删除环境、业务数据、审计、Secret 元数据或历史 DeploymentRun。
24
- 6. 从未正式发布的应用永远没有正式环境、正式 RoleSession、正式 OAuth/Secret 运行态或正式后端 Pod。
25
-
26
- ## 稳定不变量
27
-
28
- - 一个应用始终恰好有一个预发环境,最多有一个正式环境;环境 key 创建后不可改。
29
- - 同一个 AppVersion 从预发发布到正式,前端、后端镜像、配置和数据契约摘要保持完全一致。
30
- - 预发与正式的业务数据、角色成员、范围授权、OAuth 客户端、Secret 值、Workflow 实例和 Event receipt 相互独立。
31
- - 首次正式发布不复制预发业务数据。需要初始化数据时使用应用明确声明、可审计且可重试的 seed/import 操作。
32
- - 环境不存在、环境已停止和环境发布失败是三种不同状态,网关和管理端必须返回可区分的结果。
33
- - 1.x 应用、流程、自动化和既有发布模型不读取也不写入该生命周期。
34
-
35
- ## 控制面契约
36
-
37
- | 操作 | 结果 |
38
- |---|---|
39
- | `app provision` | 创建应用身份和预发环境 |
40
- | `deploy preproduction` | 构建或提交 AppPackage,并把候选 AppVersion 部署到预发 |
41
- | `environment start/stop preproduction` | 启停预发工作负载,环境事实保持不变 |
42
- | `promote <deployment-id> production` | 首次惰性创建正式环境,或复用已有正式环境,发布预发验证过的同一 AppVersion |
43
- | `environment start/stop production` | 显式启停正式工作负载,不删除正式环境 |
44
-
45
- 管理端应用列表至少显示“仅预发、预发运行中、预发已停止、正式发布中、已发布、正式发布失败”,并提供与状态匹配的确定性操作。普通用户页面不展示环境 UUID、AppVersion ID、workflow code 或内部错误码;这些信息只进入应用管理员诊断面板。
46
-
47
- ## 失败与并发
48
-
49
- - 首次正式发布使用稳定 operation/idempotency key,并以 `tenant + app + production` 唯一约束防止双击或并发会话创建两个正式环境。
50
- - 发布先验证源 DeploymentRun、AppVersion 摘要、平台 capability、必需 Secret 和集群资源,再创建 Kubernetes 工作负载。
51
- - 数据库注册与 Kubernetes 就绪不能伪装成一个跨系统事务。正式环境先进入 `provisioning`,只有候选工作负载通过 readiness 后,才在一个数据库事务中激活环境 Head 和发布成功状态。
52
- - 候选失败时不产生正式活动 Head,不影响预发,也不覆盖既有正式版本。首次失败可以保留同一个正式环境身份和失败记录,重试继续使用该身份。
53
- - 资源不足必须在创建 Pod 前返回明确的 CPU、内存或配额诊断,不能停留在无提示的 Pending。
54
-
55
- ## 资源边界
56
-
57
- | 应用状态 | 默认运行后端数 |
58
- |---|---:|
59
- | 预发已停止且从未发布 | 0 |
60
- | 正在预发验证 | 1 |
61
- | 已发布且预发已停止 | 1 |
62
- | 正式运行并同时进行预发验证 | 临时 2 |
63
-
64
- 平台可以为长期未访问的预发应用提供自动停止策略,但不能自动删除环境或业务数据。正式环境不做自动停止,除非开发者明确配置。
65
-
66
- ## 回滚边界
67
-
68
- - 该变化只调整 2.0 新应用的环境创建时机和控制面命令语义,不删除已经存在的正式环境。
69
- - 已有双环境 2.0 测试应用可以继续运行,后续通过显式清理任务停止或删除无用的正式工作负载。
70
- - 实现阶段必须采用可独立回滚的数据库和 API 变更;回滚时允许恢复“provision 同时创建两环境”的旧行为,但不得删除惰性创建后产生的正式环境事实。
71
-
72
- ## 可证伪验收
73
-
74
- 1. 新应用执行 `app provision` 后,数据库和控制面查询只返回预发环境,Kubernetes 中没有正式 Deployment 或 Pod。
75
- 2. 预发部署成功后首次执行 `release production`,平台创建唯一正式环境,并发布与预发完全相同摘要的 AppVersion。
76
- 3. 并发执行两次首次正式发布,只能产生一个正式环境和一个活动 Head;另一个请求幂等复用或返回稳定冲突。
77
- 4. 首次发布因资源不足或 readiness 失败时,预发 Head 不变化,正式环境没有活动 Head,也没有残留运行 Pod。
78
- 5. 停止预发后副本数为零,再次启动恢复相同环境和活动版本。
79
- 6. 1.x 发布、流程和自动化回归测试结果不受影响。
80
-
81
- ## 当前实现
82
-
83
- - Platform Server migration 为 Native 环境增加 `runtime_state`,并把 `start`、`stop` 纳入同一 DeploymentRun 状态机和并发唯一约束。
84
- - provision 默认只创建 `preproduction`;首次 promotion 由平台事务性确保唯一 `production` 环境。
85
- - K3s 执行器只缩放当前 Head 指向的 Deployment。状态只在目标副本就绪或归零且 Head 未变化后提交;停止后的 App API 返回稳定的 503 错误码。
86
- - CLI 提供 `environment status/start/stop`;MCP 提供只读环境资源以及 `environment_status`、`start_environment`、`stop_environment` 三个工具。
87
- - AppPackage 自动要求 `environment.on-demand-production` 与 `environment.runtime-lifecycle`,旧平台会在上传制品前被能力协商拒绝。
88
-
89
- ## prod-1 在线证据
90
-
91
- - 全新应用 `openxiangda-v2-lifecycle-acceptance` provision 后只存在
92
- `preproduction`;AppVersion 为 `7c931943-1335-479b-93fb-5facb9bf49c3`,
93
- 包摘要为 `05460ac2e35bd08e36fe289436002d5dc00d6967b2634c70488a95725f34b113`。
94
- - 同一预发环境完成 stop→0、start→1/1 Ready、再次 stop→0,三次操作都由
95
- Durable DeploymentRun 驱动,未重建 AppPackage,也未手工修改 Deployment。
96
- - 首次显式 promotion 才创建唯一 production 环境
97
- `6cacce98-43cb-4055-99d5-2c8782d01835`;promotion run
98
- `e54bfd7b-7320-4bbc-9d44-8f96aa1e0a16` 激活上述同一 AppVersion 与包摘要。
99
- - 验收结束时预发为 stopped/0 副本,正式为 running/1 Ready Pod;应用池仍受
100
- 原 `2.5 CPU/4Gi` 配额约束,没有为通过验收临时提高资源上限。
101
- - 正式 `/view/openxiangda-v2-lifecycle-acceptance/admin`、reference app 和
102
- legacy HGY Admin 均返回 HTTP 200,证明新生命周期没有进入 1.x 路径。
@@ -1,133 +0,0 @@
1
- # 经过验证的平台字段组件与三端标准页面决策
2
-
3
- 状态:2026-08-18 已实现并通过组件、模板、三端与完整本地运行时验证
4
-
5
- 适用范围:OpenXiangda 2.0 `openxiangda-contracts`、`openxiangda-field-kit`、
6
- `openxiangda-user`、官方应用模板及其本地验收夹具。OpenXiangda 1.x 运行时、
7
- 工作区识别、发布协议和已部署应用不在改动范围内。
8
-
9
- ## 1. 问题证据
10
-
11
- 当前 2.0 参考应用暴露了四类可复现问题:
12
-
13
- 1. Desktop 附件组件同时组合受控稳定值与 Ant Upload 内部 `fileList`。上传成功后,
14
- 业务值加入一份完成项,Ant Upload 的成功回调又保留一份本地项,导致相同附件重复显示。
15
- 2. 组件验收页以 `purchase_requests` 作为文件上下文,却上传字段 `images`;该资源只声明
16
- `attachments` 为 `file`,平台按声明失败关闭并返回
17
- `OPENXIANGDA_NATIVE_DATA_FILE_FIELD_INVALID:images`。
18
- 3. `location` 和 `signature` 在 Desktop/Mobile 仅渲染只读文本,`richtext` 退化为多行文本;
19
- 图片和附件的移动交互也缺少 1.x 已验证的进度、预览、失败重试和清理生命周期。
20
- 4. 移动 Form.Item 没有显式投影 `required` 标记;参考应用本地部门审批绑定在选择部门后
21
- 找不到该范围内的 `department_manager` 成员,提交返回
22
- `WORKFLOW_V2_APPROVER_RESOLUTION_EMPTY:department-review`。
23
-
24
- 现有移动工作台虽然具备基本数据和导航,但卡片比例、信息密度、表单分区、提交前审批预览
25
- 和流程详情没有达到 2026-08-18 验收稿的结构与视觉基线。
26
-
27
- ## 2. 能力所有者
28
-
29
- | 能力 | 唯一所有者 |
30
- | --- | --- |
31
- | 附件、图片、位置、签名及富文本稳定值 | `openxiangda-contracts` |
32
- | 字段输入、只读展示、上传状态机、预览与端侧交互 | `openxiangda-field-kit` |
33
- | 文件声明、上传票据、内容读取、绑定与孤儿清理 | OpenXiangda Platform Native Data API |
34
- | 身份、RoleSession、目录和数据范围 | OpenXiangda Platform |
35
- | 流程准备、审批人解析、动作与审计 | Workflow Kernel v2 |
36
- | Admin 桌面页面组合 | `openxiangda-admin` 与应用 Admin routes |
37
- | 业务用户 Desktop/Mobile 页面组合 | `openxiangda-user` 的独立 renderer |
38
- | 采购领域字段、文案和路由贡献 | 官方参考应用 |
39
-
40
- 1.x 源码只作为行为、交互和测试基线。2.0 包不得导入 1.x 模块、探测 1.x 工作区、调用
41
- 1.x API,或复制 1.x 的页面壳和发布生命周期。
42
-
43
- ## 3. 稳定不变量与受影响合同
44
-
45
- 1. 附件和图片继续保存 `StableAttachmentValue[]`,人员/部门继续保存
46
- `{ label, value }`,位置继续保存 `StableLocationValue`;不得新增第二种兼容值格式。
47
- 2. 签名值必须成为 contracts 中明确版本的稳定 JSON 值,沿用 1.x 的预览、轨迹、时间戳和
48
- 哈希语义。当前 Native Data 只允许文件绑定到 `file` 字段,签名 JSONB 不得借用旁路文件字段;
49
- 本轮使用有界 PNG data URL,后续若引入嵌套文件绑定必须单独版本化协议。浏览器不保存对象存储凭据。
50
- 3. 富文本持久化为经过清洗的 HTML 字符串,空值为 `null` 或空字符串;只读展示禁止执行
51
- script、事件属性和危险 URL。
52
- 4. 每个文件上传必须绑定一个真实 DataResource `file` 字段。组件验收使用独立的验收资源,
53
- 不增加绕过声明的通用上传 API,也不把测试字段混入采购业务资源。
54
- 5. 文件 UI 只维护一个受控生命周期:`local/uploading -> stable/done` 或 `error`。
55
- 替换和去重使用本地 uid、`fileId` 和稳定 URL 的确定性标识;成功回调不得追加第二份条目。
56
- 6. Desktop 与 Mobile 共享值归一化、上传控制器、错误模型和能力边界,但分别实现布局、
57
- 选择器、预览和动作区域。设备分支只在用户端入口选择,不把 Desktop 控件缩放成 Mobile。
58
- 7. `required` 是 Surface 的视觉和客户端校验投影;NestJS/App API、Data API 与 Workflow
59
- 仍是业务必填和授权的最终裁决者。
60
- 8. 审批人为空必须继续失败关闭。参考夹具应提供与所选部门范围匹配的真实角色成员,
61
- 不允许前端默认审批人、回退发起人或隐藏错误。
62
- 9. Admin、业务用户 PC 与 Mobile 使用相同 route/data/workflow 合同;三端可以有独立页面组合,
63
- 不能维护第二份数据、权限或流程状态。
64
-
65
- 公开受影响面包括:Field Kit 的 Desktop/Mobile/Readonly 导出与样式、User 包的标准页面、
66
- 模板 DataResource/Surface/fixture、组件使用指南和参考应用路由与测试。Native Data API 的文件
67
- 安全语义和现有 URL 不变化。
68
-
69
- 本轮采用简单目录和单一 Registry。1.x 只提供已验证的功能、样式、交互与移动端基线,不建立
70
- 逐文件追溯、兼容运行时或第二套协议。组件通过一个 `fileService` 调用既有 2.0 文件接口,页面和
71
- 字段组件不感知 initiate/PUT/complete/delete-unbound 的步骤。
72
-
73
- ## 4. 失败、并发与清理行为
74
-
75
- - 同一控件的并发上传有独立 abort/progress 状态;单个失败不覆盖其他文件,重复选择按稳定标识去重。
76
- - 超出数量、大小或 accept 规则在上传前显示字段内错误;服务端仍重复校验并返回权威错误。
77
- - 组件卸载或取消未完成上传时中止请求;已经取得票据但未完成的文件继续由平台未绑定文件清理兜底。
78
- - 删除未绑定文件调用现有删除接口;已绑定文件只从候选表单值移除,由记录更新事务执行绑定/孤儿转换。
79
- - 预览 Object URL 在关闭、替换和卸载时释放;预览失败保留下载动作和可重试错误。
80
- - 定位优先使用钉钉能力,失败后降级浏览器 Geolocation;超时、拒绝和不支持分别显示可恢复错误。
81
- - 签名保存只接受非空轨迹,生成图片和哈希任一步失败都不覆盖原值;重复保存以最后一次成功值为准。
82
- - 富文本迁移 1.x 的完整格式、表格、链接、图片、粘贴/拖拽与安全只读能力。需要上传图片时,
83
- Surface 显式提供一个声明为 `file` 的伴随字段,编辑器仍通过同一个 `fileService` 上传;未配置时
84
- 保留图片 URL,不建立旁路上传协议。编辑器销毁后不得提交迟到回调。
85
- - Workflow prepare/start 使用既有 revision、token 和幂等键;审批人解析为空时保留节点编码并引导修正配置。
86
-
87
- ## 5. 安全与资源上限
88
-
89
- - 默认附件最多 10 个、单个 50MB;字段声明可以收紧,不能由页面放宽平台声明。
90
- - 默认图片最多 9 个、单个 20MB;只接受图片 MIME/扩展名,缩略图使用稳定受管内容入口。
91
- - 签名画布 CSS 高度不超过 320px,轨迹点最多 10,000 个;PNG data URL 最大 512KB。
92
- - 富文本工具栏和表格维持 1.x 的有界集合;HTML 在写入和只读展示前清洗。
93
- - Object URL、上传任务、Toast/Modal 和定位监听在卸载时清理,不建立全局可变状态。
94
- - 浏览器不得持久化文件内容、下载票据、Workflow preparation token、RoleSession 或业务响应。
95
- - 组件验收资源只授予参考应用已有受控角色,不扩大其他租户或生产应用能力。
96
-
97
- ## 6. 设计基线
98
-
99
- 三端继续使用 Ant Design 作为唯一设计系统。Admin 保持 Pro 的桌面数据管理密度;业务用户 PC
100
- 使用独立桌面 renderer;Mobile 以 2026-08-18 五屏验收稿为视觉基线:工作台、数据列表、
101
- 表单提交、底部审批预览、流程详情。
102
-
103
- 移动页面采用冷灰背景、白色业务分区、蓝色主操作、4-8px 圆角、清晰分隔线和底部安全区;
104
- 必填星号紧邻标签。AIDA、营销 Hero、滚动叙事和 GSAP 不适用于高频操作型产品,不进入实现。
105
-
106
- ## 7. 回滚边界与影响面
107
-
108
- 实现拆成可独立回滚的发布单元:
109
-
110
- 1. contracts + Field Kit 的字段生命周期和组件;
111
- 2. User Desktop/Mobile 标准页面;
112
- 3. 官方模板的验收资源、流程夹具和高保真页面。
113
-
114
- 每个单元通过 Changeset 独立版本化。回滚使用对应 npm 包版本和 AppVersion,不需要数据库数据迁移。
115
- 新增验收资源可随模板 AppVersion 回滚;既有 `purchase_requests` 数据和文件绑定不修改。
116
- 1.x 仓库、已发布 1.x 包、其他租户和当前生产 Head 不引用本次未发布源码,影响面为零。
117
-
118
- `relation`/关联表单不再属于 Field Kit 标准组件,不迁移到新模板。普通供应商选择使用单选、
119
- 下拉或应用自己的业务页面;复杂关联查询由应用 App API 和页面自行实现。
120
-
121
- ## 8. 可证伪验收
122
-
123
- 1. Desktop/Mobile 连续上传两个同名文件时,每个服务端 `fileId` 只显示一次;上传成功不保留本地副本。
124
- 2. 图片在独立验收资源的 `images` 字段完成 initiate/upload/complete/preview/remove,不再返回字段无效。
125
- 3. 附件、图片、定位、签名和富文本具备 Desktop、Mobile、Readonly、disabled、empty、loading、error 状态测试。
126
- 4. contracts/Field Kit 往返测试证明稳定附件、位置、签名和富文本值不依赖 1.x 运行时。
127
- 5. 所有移动必填字段显示红色 `*`,空提交把错误定位到控件;桌面标记和现有 ProForm 行为不退化。
128
- 6. 选择 `dept-product`、`dept-design` 和 `dept-engineering` 分别准备采购流程时,部门节点都能解析至少一名
129
- 合法 `department_manager`;删除对应夹具后测试必须稳定复现 `WORKFLOW_V2_APPROVER_RESOLUTION_EMPTY`。
130
- 7. 390x844、430x932、1280x800、1440x900 的 Playwright 截图无文字溢出、重叠、布局跳动或桌面控件混入移动端。
131
- 8. 工作台、列表、表单、审批预览、流程详情与验收稿逐屏比对;提交主路径只有一个主按钮。
132
- 9. `openxiangda generate/check/test`、`pnpm verify:affected`、Ant Design lint、模板单测与 Desktop/Mobile E2E 全部通过。
133
- 10. 静态边界检查证明 2.0 包没有 1.x import、1.x workspace detection、原生绕过上传或第二份权限/流程状态。
@@ -1,72 +0,0 @@
1
- # OpenXiangda 2.0 发布验证凭据
2
-
3
- 状态:2026-08-16 决策确认,进入实现。
4
-
5
- ## 问题证据
6
-
7
- 一次工具链发布先显式执行了 `pnpm verify:release`,随后
8
- `pnpm release:publish` 又重新运行完整候选依赖闭包、全新应用、reference app、
9
- Skills 和文档门禁。13 个包已经写入 npm 后,发布命令又尝试修改独立 reference
10
- 仓库的 lockfile,并因该仓库存在正常源码改动而以失败退出。registry 已经发生不可逆
11
- 写入,但命令表面状态仍是失败,既浪费时间,也扩大了跨仓库并发和恢复歧义。
12
-
13
- ## 能力所有者
14
-
15
- - `release-publish.mjs` 是工具链候选工件、验证凭据和 npm/Git 发布状态的唯一所有者。
16
- - Git `master` 是源码与版本清单事实源;冻结 tarball 是待发布字节事实源;npm 和 Git
17
- tag 只保存已经发布的不可变结果。
18
- - 独立 reference app 只拥有自身源码和 lockfile。工具链发布器可在隔离副本中消费它做
19
- 验收,但不得在 npm 发布事务中修改其工作树。
20
- - AI、CLI 会话和 reference 仓库均不拥有发布状态,也不能临场选择版本、测试范围或
21
- 跳过门禁。
22
-
23
- ## 稳定不变量与命令合同
24
-
25
- 1. `pnpm verify:release` 是正式候选的准备与验证入口。它只打包一次,运行机器规划的
26
- 正式门禁,并留下 phase 为 `validated` 的凭据。
27
- 2. 凭据绑定精确 Git HEAD、registry、普通/全量模式、候选包版本、工件清单摘要以及
28
- 每个 tarball 的 SHA-256、npm integrity 和字节数。
29
- 3. `pnpm release:publish` 只接受同一提交的 `validated` 凭据;没有凭据或凭据仍为
30
- `planned` 时在第一次 registry 写入前失败,并提示先执行对应 verify 命令。
31
- 4. publish 重新检查主线、候选尚未被并发发布、dist-tag 可恢复状态和全部工件摘要,
32
- 但不重复 check/test/build、Chromium、reference、Skills 或文档门禁。
33
- 5. `verify:release:full` 生成 full 凭据,只能由 `release:publish:full` 消费;普通与全量
34
- 模式不能交叉复用。
35
- 6. reference 验收继续使用一次性 loopback registry 中的同一批冻结 tarball;发布后
36
- lockfile 收敛由显式 `pnpm release:sync-reference` 完成,不影响 npm/Git 发布成功。
37
- 7. 1.x 仓库、应用、流程、自动化和发布脚本不读取该凭据,也不进入本门禁。
38
-
39
- ## 失败、并发与资源边界
40
-
41
- - 验证失败保留 `planned` 凭据和冻结工件,修复源码形成新提交后可安全废弃;同一提交
42
- 重试 verify 复用工件并重新执行尚未成功的正式门禁。
43
- - publish 在每个不可逆阶段前后原子写凭据。进程中断后,已发布且 integrity 一致的包
44
- 被跳过;内容不同、外部 dist-tag 漂移或 Git tag 指向其他提交时 fail closed。
45
- - 一旦进入 `publishing-packages`,凭据不能跨 Git 提交重建或丢弃;必须在原提交上恢复
46
- 到 npm 内容、dist-tag 和 Git tag 全部收敛。
47
- - reference 工作树脏、不可访问或锁文件尚未同步不再发生在 registry 事务内,因而不会
48
- 把“包已发布”伪装成“发布失败”。显式同步仍要求 reference 的 `master` 干净且与远端
49
- 一致。
50
- - 凭据和 tarball 位于 Git 私有目录,不进入应用包或 npm;文件权限为 0600。状态机不
51
- 持有 npm token、应用 Secret 或用户数据。验证次数从两次降为一次,不增加浏览器、
52
- PostgreSQL 或临时 registry 的并发实例。
53
-
54
- ## 受影响合同与回滚边界
55
-
56
- 这是 2.0 工具仓维护命令的 breaking workflow change:发布者必须先 verify,再
57
- publish。公开 npm 包内容、应用运行时协议、Data API、Workflow 和平台数据库均不变。
58
- 回滚单元仅包含发布脚本、测试、文档和 Skill;尚未写 registry 时可以整体回滚。开始
59
- 写 registry 后只能依照原凭据向前恢复,不能用代码回滚覆盖已发布版本。
60
-
61
- ## 可证伪验证
62
-
63
- 1. 无凭据直接 publish 在任何 npm 写调用前失败。
64
- 2. verify 成功后 receipt 为 `validated`,第二次 verify 不重跑门禁,publish 复用同一
65
- manifest/tarball 并不调用 `release-validate.mjs`。
66
- 3. 修改 HEAD、registry、full 模式、manifest 或任一 tarball 后,publish 在写入前失败。
67
- 4. 在 `planned`、`validated`、`publishing-packages`、`packages-published`、
68
- `dist-tags-synchronized` 注入中断,重试只执行允许的后续阶段。
69
- 5. reference 仓库脏时,正式 publish 状态机测试仍可完成;显式 sync 单独给出清晰错误。
70
- 6. release 脚本单测、边界扫描、2.0 受影响验证和模拟 registry 故障测试通过,测试不得
71
- 连接真实写权限 registry。
72
-
@@ -1,65 +0,0 @@
1
- # OpenXiangda 2.0 仓库与发布架构
2
-
3
- ## 已确认决策
4
-
5
- - 2.0 是独立产品线,不提供任何 1.x 开发、迁移或兼容入口。
6
- - 1.x 旧应用由独立仓库和旧运行时维护;平台可以暂时同时托管两代应用。
7
- - 新应用只安装工作区本地 `openxiangda-cli`,不经过全局 1.x CLI。
8
- - pnpm 管理 workspace,Turborepo 计算受影响任务,Changesets 管理独立包版本。
9
- - 官方应用模板保存并发布一组经过完整验证的精确依赖版本。
10
-
11
- ## 包发布单元
12
-
13
- | 单元 | 职责 | 版本策略 |
14
- | --- | --- | --- |
15
- | contracts/compiler/devkit-core/nest | 平台协议和后端 SDK | 独立 SemVer,依赖范围由 Changesets 更新 |
16
- | workflow | Workflow Kernel v2 的纯定义与规划 | 独立 SemVer |
17
- | cli/mcp/skill-kit/create-openxiangda | AI 与开发工具入口 | 独立 SemVer |
18
- | admin/testing | 前端框架和测试工具 | 独立 SemVer |
19
- | application template | 经验证的应用 BOM | 精确固定上述包版本 |
20
-
21
- ## 测试层级
22
-
23
- 1. 提交与 PR 使用 `pnpm verify:affected`,只运行受影响包及其依赖任务。
24
- 2. 已评审 Changesets 先由 `pnpm release:version` 在干净且已同步远端的 `master` 上物化;人工只审核生成的版本、内部依赖与模板 BOM,不手改版本。版本 diff 必须提交并推送后才成为候选源码事实。
25
- 3. 发布候选运行 `pnpm release:plan`,由真实候选 tarball 差异和包依赖图确定门禁;待消费 Changesets 未物化时在任何构建前失败。
26
- 4. `pnpm verify:release` 从干净的远端 `master` 生成一次带摘要的候选工件清单;候选安装和 reference 验证消费相同 tarball,只执行一次正式验证,并留下绑定 HEAD、registry、模式和工件摘要的 `validated` receipt。`pnpm release:publish` 没有该凭据就拒绝写 registry,只重复不可变与并发前置检查后发布同一批字节,不重新打包或重跑门禁。公开 registry 发布完成后,通过独立的 `pnpm release:sync-reference` 收敛 reference 仓库锁文件;跨仓库同步不属于 npm 发布事务。
27
- 从源码创建候选 tarball 前,制品入口按候选包及其 workspace 依赖统一执行一次 Turbo 增量构建;不能直接打包工作区里可能过期的 `dist`。如果输入已经是带摘要的 release artifact manifest,则跳过构建并只消费冻结制品。
28
- 5. 每次候选都在全新独立项目安装真实 tarball 并完成 generate/check/test/build;浏览器相关变化再执行完整 Chromium E2E。
29
- 6. 平台集成测试部署到测试环境;只有平台协议或部署能力变更才需要阻塞核心发布。
30
- 7. prod-1 只晋级已经验证的相同 npm 版本、AppPackage 和 OCI digest,不重新构建。
31
-
32
- 任何层级都不得调用 1.x 测试套件。
33
-
34
- ## 确定性发布
35
-
36
- ```text
37
- reviewed Changesets
38
- -> authoritative master commit
39
- -> deterministic Changesets version materialization
40
- -> reviewed version commit on authoritative master
41
- -> frozen dependency install
42
- -> immutable tarball/version preflight
43
- -> deterministic affected validation plan
44
- -> candidate closure + independent tarball verification
45
- -> validated receipt
46
- -> npm publish of the exact validated tarballs
47
- -> explicit published reference lock synchronization + frozen install
48
- -> independent-project acceptance
49
- -> immutable promotion
50
- ```
51
-
52
- 发包阶段不允许 AI 决定包、版本、测试范围或发布顺序。AI 可以编写代码和
53
- Changeset,但包版本只能由 Changesets 物化,最终范围由 Git diff、workspace
54
- 依赖图和机器校验共同确定。版本物化不提交、不发布;正式候选必须是远端
55
- `master` 可审计提交,Git 中的 package.json、候选 tarball、npm 版本和 Git tag
56
- 共同指向同一份源码事实。
57
-
58
- 增量门禁不是按文件名随意跳测试:计划器读取 npm 当前版本和上一发布版本,解包并比较真实发行物。候选包和依赖闭包永远 check/test/build,候选 tarball 永远安装进全新应用。Admin 或浏览器契约变化触发 Chromium;核心 SDK/后端/Workflow 变化触发 reference app;Skill Kit 变化触发 Skill 与文档;未知包、没有可比较前版或显式 `--full` 一律运行完整矩阵。`verify:release` 成功后固定门禁证据,正式写 registry 前只再次确认候选版本仍未被并发发布以及 receipt 和工件未变化。
59
-
60
- ## OAuth2 外部应用身份
61
-
62
- 2.0 外部应用采用 OAuth2 Client Credentials。平台签发短期 access token,
63
- token 至少绑定 tenant、application、environment、client 和 scope。client secret
64
- 只在创建或轮换时返回一次,平台保存不可逆摘要;支持双密钥轮换窗口、即时吊销、
65
- 速率限制和完整审计。应用 NestJS 后端只信任平台校验并注入的 service Principal。
@@ -1,13 +0,0 @@
1
- # School-contact default access v2
2
-
3
- ## Decision
4
-
5
- - Problem evidence: the product contract says an authenticated application user defaults to the unrestricted tenant-local school-contact scope, while `OpenXiangdaSchoolContactV2Service.resolveAccess` currently denies a valid Principal when its active RoleSession has no explicit school-contact capability.
6
- - Capability owner: the platform school-contact service owns relation data-scope resolution. The Native authorization kernel remains the owner of Principal and RoleSession verification and is not bypassed or duplicated.
7
- - Stable invariants: platform identity codes remain descriptive claims rather than switchable application roles; tenant, application, environment, Principal, RoleSession, pagination, and query enforcement remain server-verified.
8
- - Contract: a verified non-guest Principal with no explicit school-contact scope defaults to `all`. Explicit `read`, `class:read`, and `self:read` resolve in the order `all > class > self`, allowing an application role to narrow the default. Invalid or missing Principal/RoleSession continues to fail before data access.
9
- - Failure and concurrency: authorization errors propagate unchanged; access resolution is read-only and introduces no cache, retry, queue, lock, or cross-request state.
10
- - Security and resource bounds: the default applies only after the existing v2 authentication and RoleSession boundary and never relaxes tenant/application isolation. The broader authenticated-user visibility is the explicitly accepted product policy.
11
- - Affected contracts: the typed NestJS school-contact client and response types do not change. Only the default scope selected by the platform service changes.
12
- - Rollback: code and documentation rollback only; there is no migration or persisted authorization rewrite.
13
- - Falsifiable verification: tests prove default `all`, explicit `class`/`self`, widest-capability precedence, and fail-closed missing Principal evidence; `pnpm verify:affected` must pass.