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.
- package/README.md +4 -6
- package/dist/bin.js +0 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +74 -43
- package/dist/index.js.map +1 -1
- package/dist/internal/skill-installer.d.ts +9 -0
- package/dist/internal/skill-installer.d.ts.map +1 -0
- package/dist/internal/skill-installer.js +53 -0
- package/dist/internal/skill-installer.js.map +1 -0
- package/package.json +2 -6
- package/skills/manifest.json +2 -32
- package/skills/openxiangda-v2/SKILL.md +11 -42
- package/skills/openxiangda-v2/references/architecture.md +5 -0
- package/skills/openxiangda-v2/references/backend.md +5 -0
- package/skills/openxiangda-v2/references/data-authz.md +5 -0
- package/skills/openxiangda-v2/references/delivery.md +11 -0
- package/skills/openxiangda-v2/references/frontend.md +5 -0
- package/docs/architecture/admin-shell-v2.md +0 -1030
- package/docs/architecture/ant-design-pro-v6-admin-foundation.md +0 -343
- package/docs/architecture/app-api-user-delegation-v2.md +0 -40
- package/docs/architecture/authorization-consistency-v2.md +0 -419
- package/docs/architecture/best-practice-template-rebuild-v2.md +0 -206
- package/docs/architecture/environment-configuration-kernel-v2.md +0 -290
- package/docs/architecture/field-component-migration-matrix-v1-to-v2.md +0 -76
- package/docs/architecture/field-value-contract-boundary.md +0 -92
- package/docs/architecture/frontend-runtime-mount-v2.md +0 -82
- package/docs/architecture/implementation-roadmap.md +0 -79
- package/docs/architecture/local-development-v2.md +0 -136
- package/docs/architecture/mobile-user-standard-pages-v2.md +0 -88
- package/docs/architecture/native-configuration-projection-v2.md +0 -488
- package/docs/architecture/native-kernel-inventory-v2.md +0 -196
- package/docs/architecture/native-managed-files-v2.md +0 -18
- package/docs/architecture/on-demand-production-environment-v2.md +0 -102
- package/docs/architecture/proven-field-components-and-standard-surfaces-v2.md +0 -133
- package/docs/architecture/release-verification-receipt-v2.md +0 -72
- package/docs/architecture/repository-and-release.md +0 -65
- package/docs/architecture/school-contact-default-access-v2.md +0 -13
- package/docs/architecture/stable-field-protocol-adoption.md +0 -174
- package/docs/architecture/standard-surface-runtime-corrections-v2.md +0 -108
- package/docs/architecture/tenant-public-origin-implementation-blueprint.md +0 -484
- package/docs/architecture/tenant-public-origin-v2.md +0 -236
- package/docs/architecture/verification-orchestration-v2.md +0 -24
- package/docs/backend.md +0 -102
- package/docs/concepts.md +0 -34
- package/docs/data-authz.md +0 -127
- package/docs/delivery.md +0 -77
- package/docs/design/admin/README.md +0 -124
- package/docs/design/admin/data-management-v1.png +0 -0
- package/docs/design/admin/workbench-v1.png +0 -0
- package/docs/design/admin/workflow-detail-v1.png +0 -0
- package/docs/design/admin-pro-v6/README.md +0 -26
- package/docs/design/admin-pro-v6/data-management.png +0 -0
- package/docs/design/admin-pro-v6/workbench.png +0 -0
- package/docs/design/admin-pro-v6/workflow-submit-modal.png +0 -0
- package/docs/design/admin-shell-dashboard-v2.png +0 -0
- package/docs/design/admin-standard-pages-v2.png +0 -0
- package/docs/design/admin-v2/README.md +0 -60
- package/docs/design/admin-v2/data-management.png +0 -0
- package/docs/design/admin-v2/form-detail.png +0 -0
- package/docs/design/admin-v2/form-submit.png +0 -0
- package/docs/design/admin-v2/workbench.png +0 -0
- package/docs/design/admin-v2/workflow-detail.png +0 -0
- package/docs/design/admin-v2/workflow-submit.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/README.md +0 -293
- package/docs/design/openxiangda-2.0-high-fidelity/admin-component-acceptance.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/admin-data-form.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/admin-workbench.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/mobile-approval-preview.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/mobile-data-list.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/mobile-form.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/mobile-request-form.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/mobile-request-list.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/mobile-submit-workflow-preflight.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/mobile-workbench.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/mobile-workflow-detail.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/user-pc-data-list.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/user-pc-form-workflow-preview.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/user-pc-request-form-approval.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/user-pc-request-list.png +0 -0
- package/docs/design/openxiangda-2.0-high-fidelity/user-pc-workbench.png +0 -0
- package/docs/field-components.md +0 -93
- package/docs/frontend.md +0 -78
- package/docs/getting-started.md +0 -148
- package/docs/index.md +0 -27
- package/docs/llms.txt +0 -20
- package/docs/reference/cli.md +0 -69
- package/docs/reference/mcp.md +0 -31
- package/docs/school-contact-relations.md +0 -136
- package/docs/workflow-events.md +0 -86
- package/skills/openxiangda-v2-architecture/SKILL.md +0 -30
- package/skills/openxiangda-v2-architecture/agents/openai.yaml +0 -4
- package/skills/openxiangda-v2-backend/SKILL.md +0 -48
- package/skills/openxiangda-v2-backend/agents/openai.yaml +0 -4
- package/skills/openxiangda-v2-data-authz/SKILL.md +0 -58
- package/skills/openxiangda-v2-data-authz/agents/openai.yaml +0 -4
- package/skills/openxiangda-v2-delivery/SKILL.md +0 -88
- package/skills/openxiangda-v2-delivery/agents/openai.yaml +0 -4
- package/skills/openxiangda-v2-frontend/SKILL.md +0 -50
- package/skills/openxiangda-v2-frontend/agents/openai.yaml +0 -4
- package/skills/openxiangda-v2-workflow-events/SKILL.md +0 -56
- package/skills/openxiangda-v2-workflow-events/agents/openai.yaml +0 -4
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
# OpenXiangda 2.0 最佳实践模板重建计划
|
|
2
|
-
|
|
3
|
-
状态:2026-08-16 已确认,正在实施
|
|
4
|
-
|
|
5
|
-
本计划把现有“企业采购申请”从生命周期验收应用提升为 OpenXiangda 2.0 官方最佳实践模板。当前线上版本只证明身份、数据、文件、流程和部署链路可运行,不满足视觉、交互和平台字段完整性要求,在本计划完成前不得再标记为最终模板。
|
|
6
|
-
|
|
7
|
-
## 1. 设计读取与目标
|
|
8
|
-
|
|
9
|
-
- 页面类型:企业内部管理和流程协作应用。
|
|
10
|
-
- 目标用户:PC 管理人员、移动端业务申请人与审批人。
|
|
11
|
-
- 设计语言:Ant Design Pro 企业后台,统一浅色主题,冷灰画布、白色内容面、单一品牌蓝和必要语义色。
|
|
12
|
-
- 设计参数:视觉变化 3/10,动效 2/10,信息密度 6/10。
|
|
13
|
-
- PC Admin 只服务桌面视口;移动用户端使用独立 UI 树,不缩放或响应式复用 Admin DOM。
|
|
14
|
-
- 已评审设计稿是页面结构、视觉层级、间距、状态和操作顺序的可执行验收合同。业务数据可以变化,但不得以“组件库默认样式”或“仅参考信息架构”为理由偏离设计。
|
|
15
|
-
|
|
16
|
-
### 1.1 冻结设计基线(2026-08-16 用户确认)
|
|
17
|
-
|
|
18
|
-
下列四张评审稿是后续实现与截图回归的唯一视觉基线。文件名和 SHA-256 用于避免附件顺序或会话压缩后误认图稿。
|
|
19
|
-
|
|
20
|
-
| 基线 | 评审附件 | SHA-256 | 不可降级的页面合同 |
|
|
21
|
-
| --- | --- | --- | --- |
|
|
22
|
-
| PC 工作台 | `codex-clipboard-0d456ded-03fe-46f3-bc8f-ed93ed003cd7.png` | `007935119779d48e2bb82297035a2ccf9ae86bbfc2ae0960db209ed981dc79be` | 220px 分组侧栏、56px 顶栏、44px 标签栏;问候、四色指标、待办表、四宫格快捷入口、折线趋势和最近活动完整出现 |
|
|
23
|
-
| PC 标准列表 | `codex-clipboard-57286809-2220-42e3-ae70-bcaded18632d.png` | `9e8f40af155c47e846350eb626e07c174426030b1753670f42ed8bd2aa1a4424` | 页标题与主动作、两行结构化搜索区、工具栏、紧凑表格、状态标签、行操作和完整分页几何对齐 |
|
|
24
|
-
| PC 表单与提交预览 | `codex-clipboard-2f203d66-c537-4729-8ce7-02d392739e3f.png` | `024eac21eadea7807ab077b80c1dcfa426f6d8fdd3434955ae0744629392956b` | 表单保持一个主提交动作;保存业务数据并 prepare 后才弹出 Modal;Modal 包含摘要、真实审批路径、返回修改和确认提交 |
|
|
25
|
-
| 移动五核心页 | `codex-clipboard-807017c4-ef50-43dd-bdc2-298902d85ada.png` | `99f6abe17fd7cd1be10f3534d268aa1c8f10f1ad31b3739126597b5d1b6172aa` | 独立工作台、数据列表、表单提交、底部审批预览、流程任务详情;卡片、状态、附件、时间线、底部安全区操作栏和正式图标必须齐全 |
|
|
26
|
-
|
|
27
|
-
每页实现必须同时通过结构断言、交互断言和指定视口截图回归。字段内容可以换成真实业务数据,页面区块、相对层级、对齐、主动作顺序和语义色不得擅自删减。
|
|
28
|
-
|
|
29
|
-
### 1.2 线上复核增量基线(2026-08-17)
|
|
30
|
-
|
|
31
|
-
P1-P5 的技术链路交付不等于产品模板验收。用户在 prod-1 preproduction 复核后发现页面仍存在重复信息、列表交互退化、文件组件能力退化、环境入口和流程业务引用错误,因此 P1-P5 的产品状态重新打开;以下七张实拍图与本节合同覆盖 1.1 中冲突的旧描述。
|
|
32
|
-
|
|
33
|
-
| 复核基线 | 评审附件 | SHA-256 | 新增或修正合同 |
|
|
34
|
-
| --- | --- | --- | --- |
|
|
35
|
-
| 当前模板问题页 | `codex-clipboard-ea7a610d-0ebf-4c63-977a-ceb5bcc18ee5.png` | `8ce67f32f9c69d51fd985f8a1623a6c41fcf8760775001a62736ab6fd3d6ddc3` | 顶栏和缓存标签已表达当前位置时,内容区不得重复面包屑、页标题和说明;全局顶栏不显示搜索框 |
|
|
36
|
-
| 参考 Shell | `codex-clipboard-315df6dc-9cbc-4f25-87e6-9e6997ccc30f.png` | `46bd393288080486a573aba9a09768a4f2647badc6fdc76c93d9358041ea14ac` | 侧栏分组、图标、选中态、顶栏与标签几何采用成熟企业后台密度 |
|
|
37
|
-
| 参考侧栏 | `codex-clipboard-458d7e0f-ead5-488d-9c8c-6959294f6672.png` | `40d851713e2f4eaf4c029fc8234d636e6c0f654fc63658fdf10ac322683eb2c5` | 分组、子项、折叠和滚动区可辨识,图标统一使用语义色和正式图标 |
|
|
38
|
-
| 参考标准列表 | `codex-clipboard-928424b7-b02e-49ff-bb08-d5abaa98a70f.png` | `cb3945283db167c4aeb747d8fd5613cf7107d356db72e73d824d56d50170916c` | 筛选默认一行并可展开更多;筛选下方左侧为业务操作,右侧为刷新和列表设置;表格支持服务端排序 |
|
|
39
|
-
| 参考列表设置 | `codex-clipboard-e1f64efb-3634-4563-a251-a9e4e48b339e.png` | `0bb7c01364cb5161b2fe0591409cb0e97132bdf8ea32f37fcc71b155001e317d` | 设置抽屉固定包含“搜索项、列设置、排序、显示”四类账号级偏好,不修改资源合同 |
|
|
40
|
-
| 当前流程预览问题 | `codex-clipboard-60472a98-577b-418d-8eca-34aafded02d9.png` | `421d011f1d939763b02f8b1ff0c7a5c15a0134e38d5129770631d8a26a85d81c` | 提交预览只展示审批路径,不重复业务表单摘要;审批节点必须展示内核解析出的具体审批人,不能用“无需指定审批人”掩盖未解析状态 |
|
|
41
|
-
| 当前流程详情错误 | `codex-clipboard-4a7aadd0-c484-4f87-89cc-583d2a2fc47d.png` | `4263041dddd7307ce69f390f8a36b9195f9d1314d846b47f415fcb5e959268d7` | 流程 Surface 必须提供可验证的 DataRef,详情只能据此读取业务数据;缺失引用是合同错误并须在提交链路修复 |
|
|
42
|
-
|
|
43
|
-
本轮另外冻结三项行为合同:应用列表打开时优先进入已激活 production,否则自动进入已激活 preproduction;preproduction 顶栏在 production 已发布时提供快捷切换;官方模板必须提供覆盖全部稳定字段类型的验收表单。附件和图片继续由 `openxiangda-field-kit` 消费 Files API,迁移 1.x 已验证的上传、下载、预览、缩略图、进度、失败重试和删除交互,但 2.0 不依赖 1.x 运行包、不新增第二份文件协议。
|
|
44
|
-
|
|
45
|
-
## 2. 问题证据
|
|
46
|
-
|
|
47
|
-
1. `ProLayout` 未显式提供唯一菜单选中键,`/admin` 与其子路径可能同时高亮。
|
|
48
|
-
2. 缓存标签直接使用 `Tabs editable-card` 并以局部 CSS 修补,标签、侧栏、顶栏和页面边界没有共同几何基准。
|
|
49
|
-
3. 工作台、数据列表和移动页面只完成通用组件拼接,没有落实已评审稿的信息层级、色彩、图标和状态设计;线上复核还发现内容区重复标题、顶栏冗余搜索和标准列表能力退化。
|
|
50
|
-
4. 部门字段只提供关键词扁平搜索。平台后端能返回真实部门和路径,但当前 2.0 Field Kit 没有根组织浏览、树展开、懒加载、面包屑和完整路径展示。
|
|
51
|
-
5. 参考应用把用户 ID 同时写入目录值的 `label` 与 `value`,导致列表出现裸 UUID。
|
|
52
|
-
6. Chromium 测试只验证可见与可点击,没有唯一菜单选中、裸 ID、组织树、视觉截图和布局几何门禁。
|
|
53
|
-
7. 应用入口固定打开 production,未发布 production 时没有回退到 preproduction;用户端快捷入口丢失应用基础路径并错误跳转到 `/m`。
|
|
54
|
-
8. 流程预览重复展示业务摘要且没有稳定呈现具体审批人;流程详情收到的 DataRef 不完整时只能展示“业务数据加载失败”。
|
|
55
|
-
9. 2.0 文件控件只保留最简上传路径,未达到 1.x 已稳定的预览、下载、缩略图、进度、失败恢复和删除体验。
|
|
56
|
-
|
|
57
|
-
## 3. 能力所有者与稳定不变量
|
|
58
|
-
|
|
59
|
-
| 能力 | 唯一所有者 | 不变量 |
|
|
60
|
-
| --- | --- | --- |
|
|
61
|
-
| 路由、菜单、缓存标签描述 | 应用 route manifest,经 `openxiangda-admin` 投影 | 不维护第二套路由或菜单树;任一路径只选中一个最具体菜单项 |
|
|
62
|
-
| Admin 布局和标准页面 | `openxiangda-admin` | 应用不能复制 Shell、ProTable、ProForm、详情和流程标准壳;内容区不重复顶栏已有上下文 |
|
|
63
|
-
| 移动页面组合 | `openxiangda-user/mobile` | 与 Admin 分离,只消费同一身份、Data、Workflow 和 Field Kit 合同 |
|
|
64
|
-
| 字段值和渲染 | `openxiangda-contracts` + `openxiangda-field-kit` | 保持已经运行稳定的值协议,不以显示字符串替换平台值 |
|
|
65
|
-
| 人员和部门目录 | Platform Server Directory API | Field Kit 不复制组织数据;平台 API 是唯一事实来源 |
|
|
66
|
-
| 文件 | Platform Server Files API + Field Kit | 上传、下载、鉴权、预览和稳定文件值不得由应用自建 |
|
|
67
|
-
| 环境 head 与默认应用入口 | Platform Server Environment Head + 平台管理前端 | production 存在时优先,否则回退 preproduction;前端不维护第二份发布状态 |
|
|
68
|
-
| 显示身份 | Native Principal/RoleSession/Directory | 默认页面不得显示 UUID、内部 code 或原始 JSON |
|
|
69
|
-
| 业务数据和流程状态 | Data/App API 与 Workflow Kernel | 页面只解释合同,不复制权限、审批或状态机规则 |
|
|
70
|
-
|
|
71
|
-
1.x View、1.x 工作流、1.x 自动化和 `tools/openxiangda` 不依赖本轮包,也不接受本轮修改。
|
|
72
|
-
|
|
73
|
-
## 4. 实施阶段
|
|
74
|
-
|
|
75
|
-
### P0 设计合同和门禁
|
|
76
|
-
|
|
77
|
-
- 修正 PC、移动设计文档,删除“只参考信息架构、不还原设计”的降级条款。
|
|
78
|
-
- 为工作台、列表、表单、流程预览、详情和移动五屏记录布局、颜色、间距、状态和唯一主动作。
|
|
79
|
-
- 建立与冻结稿同尺寸的 1536x1024 PC 基线,以及 390x844、375x812 移动视口基线。
|
|
80
|
-
|
|
81
|
-
完成条件:设计基线可以转换为机器断言,当前线上页面应明确失败。
|
|
82
|
-
|
|
83
|
-
### P1 Admin Shell
|
|
84
|
-
|
|
85
|
-
- 由最具体的可见菜单路径确定唯一 `selectedKey`。
|
|
86
|
-
- 统一 56px 顶栏、44px 标签栏、220px 侧栏和页面内容网格。
|
|
87
|
-
- 用 Ant Design 公开 Tabs API 和语义槽实现有界缓存标签,不使用默认 editable-card 外观。
|
|
88
|
-
- 完成品牌、折叠、通知、个人中心、身份切换和环境标识的固定位置;移除当前没有完整能力闭环的全局搜索框。
|
|
89
|
-
|
|
90
|
-
完成条件:菜单唯一选中;标签、顶栏和内容区边界对齐;直接 URL、详情路由和身份切换均保持正确。
|
|
91
|
-
|
|
92
|
-
### P2 平台 Field Kit
|
|
93
|
-
|
|
94
|
-
- 保持现有人员、部门、地址、附件等稳定值协议。
|
|
95
|
-
- 将 1.x 已验证的部门树交互迁移或桥接到 2.0:根组织、懒加载、关键词搜索、面包屑、完整路径、单选/多选和移动底部面板。
|
|
96
|
-
- 人员选择支持按组织浏览和搜索;列表、详情和表单共享显示解析。
|
|
97
|
-
- 附件与图片继续只走平台文件组件;日期、区间、下拉、级联和地址逐项验证移动体验。
|
|
98
|
-
|
|
99
|
-
人员按组织浏览本轮决策:
|
|
100
|
-
|
|
101
|
-
- 平台 Directory API 是人员和部门的唯一事实来源,不在应用、Devkit 或浏览器建立组织副本。
|
|
102
|
-
- 新增的人员浏览合同以部门 ID、页码和页大小为输入,直接复用平台现有 `getDepartmentMembersPage(..., true)` 可见范围检查;每页最多 100 人。
|
|
103
|
-
- 关键词搜索保持原合同,按部门浏览是独立的加法合同;失败必须显示可重试错误,不能降级为自由文本或裸 ID。
|
|
104
|
-
- Field Kit 继续持久化 `{ label, value }`,组织路径只作为显示元数据;身份 epoch 变化后丢弃旧请求。
|
|
105
|
-
- 回滚以 Directory 加法路由、Devkit 方法和 Field Kit 消费提交为边界,不迁移数据库、不修改 1.x 控制器。
|
|
106
|
-
|
|
107
|
-
完成条件:真实平台组织数据可从根节点浏览;源码没有 ID-only 目录值;未知内部编码在开发阶段失败而不是进入页面。
|
|
108
|
-
|
|
109
|
-
### P3 标准 PC 页面
|
|
110
|
-
|
|
111
|
-
- 工作台:问候、四个有界指标、待办、快捷入口、趋势与最近活动。
|
|
112
|
-
- 数据管理:默认一行筛选、更多筛选、服务端搜索/排序/分页、搜索项/列/排序/显示设置、密度、刷新、导出和有界行操作。
|
|
113
|
-
- 表单:分组、字段策略、附件和一个主提交动作。
|
|
114
|
-
- 流程:点击提交并保存业务数据后才打开真实审批预览 Modal;Modal 只展示含具体审批人的真实路径,不重复业务表单摘要。
|
|
115
|
-
- 详情:业务字段、审批时间线、审计记录和 Surface 允许的操作。
|
|
116
|
-
|
|
117
|
-
完成条件:设计稿中的层级与操作顺序逐页面通过截图和交互验收,采购领域代码不进入通用包。
|
|
118
|
-
|
|
119
|
-
Admin 工作台还原本轮决策:
|
|
120
|
-
|
|
121
|
-
- 问题证据是冻结基线中的 PC 工作台与当前实现在顶栏信息层级、快捷入口数量、待办表格、指标变化信息和卡片几何上不一致;设计附件是唯一验收源。
|
|
122
|
-
- `openxiangda-admin` 是 Shell 和工作台结构的唯一所有者;模板 HomePage 只提供真实有界数据、图标、文案和跳转,不复制布局 CSS。
|
|
123
|
-
- 稳定合同是 56px 顶栏、44px 标签栏、220px 侧栏、四列指标、左待办/右快捷入口、左趋势/右最近活动;业务数据变化不得导致布局跳动或裸 ID。
|
|
124
|
-
- 请求失败分区降级为可读空态,不阻断 Shell;身份 epoch 变化后废弃旧请求。待办最多 5 条、最近活动最多 5 条、快捷入口最多 4 个、图表最多 7 个时间点。
|
|
125
|
-
- 回滚边界是 `openxiangda-admin` 工作台/Shell 提交和模板 HomePage 组合提交;不修改 Data、Workflow、Directory 或 1.x 运行时。
|
|
126
|
-
- 可证伪验证包括 1536x1024 几何断言、工作台截图基线、唯一菜单选中、四指标/两工作区/两活动区可见与页面无运行时错误。
|
|
127
|
-
|
|
128
|
-
标准列表、表单、流程与详情本轮决策:
|
|
129
|
-
|
|
130
|
-
- 问题证据是冻结基线中的标准列表和提交预览拥有明确的搜索、工具栏、表格、分页、单一主动作与审批 Modal 层级,而当前实现仍以组件默认排版为主,缺少冻结视口截图门禁。
|
|
131
|
-
- `openxiangda-admin` 唯一拥有标准列表、表单、详情、审批预览与流程详情的页面结构;应用只提供资源/字段定义、业务数据保存函数、文案、图标和路由,不复制通用页面 CSS,也不在页面内重建权限或流程规则。
|
|
132
|
-
- Data/App API 唯一拥有业务数据,Workflow Kernel 唯一拥有 preparation、Surface 和任务状态;页面必须先保存业务数据再 prepare,只有用户点击主提交按钮后才能打开预览,确认后使用同一 preparation token 发起流程。
|
|
133
|
-
- 列表只发有界的服务端分页、筛选和排序请求;搜索提交覆盖旧请求,身份 epoch 变化后旧响应无效。列配置只保存显示偏好,不改变资源合同。删除与流程动作保留 revision/idempotency 并显示明确冲突或失败。
|
|
134
|
-
- 页面不显示裸 ID、内部 code、原始 JSON、token 或未经 Directory/Field Kit 解析的平台值;附件和图片只经 Files/Field Kit,人员、部门、地址、日期、选项等继续保持稳定值协议。
|
|
135
|
-
- 回滚边界是 `openxiangda-admin` 标准页组件与模板组合提交;不修改 Data、Workflow、Directory、Files 后端合同,不触碰 1.x 页面、流程和自动化。
|
|
136
|
-
- 可证伪验证包括 1536x1024 列表和表单/审批预览截图,搜索/重置/排序/分页/列配置交互,提交前预览不存在,保存与 prepare 后 Modal 出现,确认后进入详情,以及流程 Surface 只渲染后端允许操作。
|
|
137
|
-
|
|
138
|
-
### P4 独立移动用户端
|
|
139
|
-
|
|
140
|
-
- 重建工作台、申请列表、申请表单、提交预览、流程任务详情。
|
|
141
|
-
- 使用正式图标、状态标签、移动卡片、底部导航与安全区操作栏,不使用字符图标。
|
|
142
|
-
- 所有持久化字段经 `openxiangda-field-kit/mobile`。
|
|
143
|
-
|
|
144
|
-
完成条件:390x844 真机视口下完成申请与审批主路径,不加载桌面 `antd` 或 Admin DOM。
|
|
145
|
-
|
|
146
|
-
独立移动五页本轮决策:
|
|
147
|
-
|
|
148
|
-
- 问题证据是冻结移动五核心页基线与当前页面在品牌顶栏、正式图标、卡片层级、列表状态、表单密度、审批预览和任务时间线上均不一致;当前模板仍出现字符图标和业务 ID,不能作为官方最佳实践。
|
|
149
|
-
- `openxiangda-user/mobile` 唯一拥有移动 Shell、工作台、列表、表单、审批预览和任务详情结构;模板只提供有界业务数据、字段定义、文案、图标语义和路由,不复制移动页面壳与通用 CSS。
|
|
150
|
-
- 移动端是独立 DOM 与路由树,不加载 `openxiangda-admin` 或桌面 `antd`;所有持久化输入和值展示继续经 `openxiangda-field-kit/mobile`,不得绕过既有人员、部门、地址、日期、选项、附件和图片值协议。
|
|
151
|
-
- Data/App API 唯一拥有业务数据,Workflow Kernel 唯一拥有 preparation、Surface、时间线和操作。提交页只有一个主动作,点击并保存业务数据、完成 prepare 后才显示底部审批预览;详情底栏只展示 Surface 返回且允许的操作。
|
|
152
|
-
- 首页待办、最近使用和快捷入口均有界;列表保持服务端分页、筛选与下拉刷新。身份 epoch 变化后废弃旧响应。目录或文件能力失败时展示可重试状态,不能退化为自由文本、字符占位或裸 ID。
|
|
153
|
-
- 资源边界是 390x844 与 375x812 两个目标视口、底部安全区、列表单页 20 条、首页最近事项最多 5 条、快捷入口最多 4 个;不为桌面宽度增加响应式分支。
|
|
154
|
-
- 回滚边界是 `openxiangda-user`、`openxiangda-field-kit` 移动渲染和模板移动组合提交;不修改稳定字段存储协议、Data/Workflow/Directory/Files 后端合同,也不触碰 1.x View、流程或自动化。
|
|
155
|
-
- 可证伪验证包括五个独立页面结构断言、提交前无预览、prepare 后底部预览、确认后进入流程详情、无裸 UUID/内部 code/字符图标,以及 390x844 和 375x812 截图回归;本地 fixture 只稳定视觉,真实能力仍在 P5 preproduction 验收。
|
|
156
|
-
|
|
157
|
-
### P5 候选、发布和在线验收
|
|
158
|
-
|
|
159
|
-
- 工具链执行 `pnpm verify:affected`;正式候选执行 `pnpm verify:release` 和 Changesets。
|
|
160
|
-
- 从候选 tarball 在空目录创建新应用并完成 generate/check/test/build。
|
|
161
|
-
- 同步独立参考应用,以同一 AppPackage 部署 prod-1 preproduction。
|
|
162
|
-
- 线上验证 OAuth2、RoleSession、真实 Directory、Data/App API、Workflow 和 Files;通过后才把同一 AppVersion 晋级 production。
|
|
163
|
-
|
|
164
|
-
## 5. 失败、并发、安全与资源边界
|
|
165
|
-
|
|
166
|
-
- 身份 epoch 变化后取消或丢弃旧请求;菜单、标签和显示缓存不得跨 identity scope。
|
|
167
|
-
- 标签最多 12 个,保活页面最多 6 个;截图基线不能依赖随机数据或内部 ID。
|
|
168
|
-
- 组织树按需加载,单页搜索和子节点都有界;目录失败显示可重试错误,不降级成自由文本输入。
|
|
169
|
-
- 列表只使用服务端分页、排序和筛选;工作台图表只消费受限聚合。
|
|
170
|
-
- 浏览器不持久化 token、权限结论、组织副本、业务响应或流程 preparation token。
|
|
171
|
-
- 任何裸 UUID、原始 JSON、内部环境 key、角色 code 或流程节点 key进入默认页面都视为构建或 E2E 失败。
|
|
172
|
-
|
|
173
|
-
## 6. 回滚边界
|
|
174
|
-
|
|
175
|
-
- P1-P4 分别以 `openxiangda-admin`、`openxiangda-field-kit`、`openxiangda-user` 和模板提交为源码回滚单元,但不发布混合代际包。
|
|
176
|
-
- 远端回滚以完整 AppVersion 为单位;不在运行时保留旧 Shell、旧移动页面或目录自由输入兼容开关。
|
|
177
|
-
- 目录 API 若需要扩展,只增加有界浏览合同;现有搜索合同保持可用。不得建立第二份组织存储。
|
|
178
|
-
- 1.x 不参与发布、迁移或回滚。
|
|
179
|
-
|
|
180
|
-
## 7. 可证伪验收矩阵
|
|
181
|
-
|
|
182
|
-
| 范围 | 必须通过 |
|
|
183
|
-
| --- | --- |
|
|
184
|
-
| Shell | 任一路径恰好一个菜单选中;标签边界对齐;无全局搜索和内容区重复标题;直接 URL、关闭、恢复、身份/环境切换正确 |
|
|
185
|
-
| 视觉 | PC 冻结稿尺寸 1536x1024(并补充 1280x800 结构检查);移动 390x844、375x812 截图回归 |
|
|
186
|
-
| 数据 | 默认一行与更多筛选、服务端搜索/排序/分页、四类列表设置、空/错/加载、revision 冲突 |
|
|
187
|
-
| 字段 | 官方验收表单覆盖 `text/textarea/number/money/percent/boolean/date/datetime/dateRange/option/options/radio/checkbox/cascade/user/users/department/departments/attachments/images/address/location/richtext/signature/subtable/json/serial/workflowStatus`;关联表单组件弃用 |
|
|
188
|
-
| 目录 | 打开即能看到真实根组织;树展开、搜索、路径、单选/多选和失败重试 |
|
|
189
|
-
| 身份 | 页面显示真实姓名/部门;正则扫描页面不存在裸 UUID |
|
|
190
|
-
| 流程 | 提交前没有预览;保存和 prepare 后弹窗;预览仅含具体审批人路径;Surface DataRef 可读业务数据;同意、拒绝、转交、回退、加签和代理按 Surface 展示 |
|
|
191
|
-
| 边界 | 移动包没有 Admin/桌面录入依赖;应用没有自建人员、部门和文件协议 |
|
|
192
|
-
| 发布 | 新建应用与独立参考应用使用相同候选包;preproduction 在线通过后才允许 production 晋级 |
|
|
193
|
-
| 环境 | 应用列表 production 不存在时自动进入 preproduction;preproduction 可切换到已发布 production;用户端跳转保留应用 base path |
|
|
194
|
-
|
|
195
|
-
## 8. 交付记录
|
|
196
|
-
|
|
197
|
-
| 日期 | 阶段 | 状态 | 证据 |
|
|
198
|
-
| --- | --- | --- | --- |
|
|
199
|
-
| 2026-08-16 | P0 | 已完成 | 完成线上问题审计;PC/移动设计文档已从“信息架构参考”升级为可执行设计合同;本计划已记录所有权、不变量、失败边界、回滚和验收矩阵 |
|
|
200
|
-
| 2026-08-17 | P1 | 已完成 | Admin 按最长可见路径保持唯一菜单激活并支持无路径菜单组;Shell 固定为 220px 侧栏、56px 顶栏、44px 标签栏,具备折叠、面包屑、菜单搜索、通知入口、环境、身份切换和个人中心;工作台完成四色指标、真实待办、四宫格快捷入口、7 日趋势与最近活动。Playwright 在 1536x1024 验证几何、交互、无运行时错误,并冻结 `admin-workbench-1536x1024-chromium-darwin.png` 截图基线 |
|
|
201
|
-
| 2026-08-16 | P2 | 已完成 | Directory v2 已提供按层部门树和按部门分页人员浏览,直接复用平台已有的可见范围,不建立第二份组织存储;Desktop 以左树右人员列表和全局搜索消费合同,Mobile 以独立组织钻取和本部门人员面板消费合同;Field Kit 对仅含 ID 的历史稳定值调用 Directory resolve,未知值显示语义占位而不暴露内部 ID。平台定向 4 测试、Devkit 50 测试、Local Platform 21 测试、Field Kit 8 测试与 `verify:affected` 35/35 任务通过 |
|
|
202
|
-
| 2026-08-17 | P3 | 已完成 | 标准列表将主动作、搜索卡、表格工具、服务端分页与行操作分层;详情统一字段渲染与审计;流程表单按 section 分组且只有一个主提交动作,保存业务数据并 prepare 后才展示含业务摘要和真实节点的确认 Modal,确认后进入无裸 ID/code 的流程详情。已冻结 `admin-data-list`、`admin-data-detail`、`admin-workflow-form`、`admin-workflow-preview`、`admin-workflow-detail` 五张 1536x1024 Chromium 基线,并以第二次不更新快照的运行证明基线稳定;边界 fixture 仅用于视觉确定性,真实 PostgreSQL/NestJS 和 preproduction 验收仍保留在 P5 |
|
|
203
|
-
| 2026-08-17 | P4 | 已完成 | 独立移动用户端已按冻结稿重建工作台、数据列表、表单提交、底部审批预览和流程任务详情;使用正式 SVG 图标、语义状态、移动卡片、安全区操作栏和独立路由树,人员、部门、日期、选项、地址、附件与图片仍全部经 `openxiangda-field-kit/mobile`。已冻结五张 390x844 核心页基线和一张 375x812 工作台基线;连续不更新快照运行 2/2 通过,页面无裸 ID/code,`verify:affected` 19/19 任务通过,移动入口依赖门禁确认未加载桌面 Admin/Ant Design。视觉 fixture 只用于确定性截图,真实 OAuth2、Directory、Data、Workflow 与 Files 保留到 P5 prod-1 preproduction 验收 |
|
|
204
|
-
| 2026-08-17 | P5 | 已完成 | 平台后端不可变版本 `20260817-043631-6fd2f6136179abca` 已部署 prod-1,102 条 SQL migration 预检为 0 pending/0 conflict,K3s 后端 1/1 Ready;参考应用 AppVersion `e4713605-fd2d-4710-9b44-518ac779465d` 只部署 preproduction。真实 OAuth2 用户和应用管理员 RoleSession 验证 Directory 根部门/部门人员/裸 ID 解析、Data/App API 用户审计字段、Files 完整下载;Workflow 实例 `139a39ba-7f6e-4840-a25a-40933917166b` 完成部门负责人、财务复核员、采购管理员三角色切换和审批,最终 `approved`,时间线与 created/completed 工作中心均通过。独立参考应用 `da67d7d` 固化了仅允许 preproduction、默认只读且不输出凭据的可重复验收脚本和收据;production 保持停止,平台入口、参考应用 Admin 与 1.x HGY Admin 均返回 HTTP 200 |
|
|
205
|
-
| 2026-08-17 | 产品复核 | 重新打开 | prod-1 实拍证明 P1/P3/P5 仍有可见回归:重复页面上下文、列表设置缺失、文件控件退化、流程预览与 DataRef 错误、环境入口错误。此前“已完成”仅保留为技术链路证据,不再代表官方模板验收通过;按 1.2 增量基线重新开发、截图和在线验收 |
|
|
206
|
-
| 2026-08-17 | 产品复核本地修复 | 已完成,待线上 | 已关闭内容区重复 PageHeader 与全局搜索;标准列表具备默认单行/更多筛选、平台目录筛选、左右工具区和四类账号级设置;Files Field Kit 恢复拖拽、图片、进度、取消、鉴权预览、下载和未绑定清理;审批预览只展示具体审批人路径,Surface 统一 `dataRef`;应用入口 production 不存在时回退 preproduction,用户端链接保留应用 base path;组件验收页覆盖全部稳定字段类型。Admin Chromium 主链路 1/1、Mobile 2/2、Admin/Field Kit 单元测试与模板生产构建已通过,新增 `admin-field-gallery-*`、更新 `admin-data-*` 与 `admin-workflow-*` 1536x1024 基线;尚未替代 prod-1 真实 OAuth2/Directory/Data/Workflow/Files 验收。 |
|
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
# OpenXiangda 2.0 环境配置内核
|
|
2
|
-
|
|
3
|
-
状态:方案已确认并按 Native 实施顺序推进。2026-08-15 已完成 E4 运行时闭环:应用身份和预发/生产原生环境成对创建、Native DeploymentRun、按 run 隔离的候选 workload、`pending -> active -> retiring -> revoked` 运行凭据、凭据与 Head CAS 同事务激活、旧 token 随 Head 变化立即失效;App Gateway 使用最长 60 秒 invocation token + 最长 30 秒 Ed25519 请求 assertion,官方 NestJS 全局 transport guard 绑定当前 Native Head 与完整 HTTP 请求,本地平台使用同构协议且拒绝重放。单体 Nest 的后台消费由短租约选出一个活动实例,应用 Secret 只允许当前 Head 身份按声明读取,terminal/cancelled/超时候选由精确 GC 回收,`alpha -> native-2` 切换必须通过全平台实例 release/capability 门禁。Native production 仍须完成后续 E5 和真实预发 E2E 后再开放。
|
|
4
|
-
|
|
5
|
-
生命周期修订:2026-08-16 已确认新应用默认只创建预发环境,正式环境在首次明确发布时惰性创建。本文中“provision 成对创建预发/生产”的既有实现描述由[按需正式环境](./on-demand-production-environment-v2.md)取代;环境隔离、不可变 AppVersion、Head CAS 和预发/正式运行态分离等不变量保持不变。
|
|
6
|
-
|
|
7
|
-
## 1. 决策摘要
|
|
8
|
-
|
|
9
|
-
OpenXiangda 2.0 的运行语义采用三层模型:
|
|
10
|
-
|
|
11
|
-
1. **不可变定义层**:AppVersion 组合 frontend、backend、config、contracts 等不可变修订;包内角色、能力、数据策略和逻辑数据定义从 config revision 编译,contracts revision 保存跨前后端消费的资源/能力/事件/流程契约摘要,不在部署时覆盖应用级“当前配置”。
|
|
12
|
-
2. **环境选择层**:最终的 `app_runtime_environment_heads_v2` 是某个原生环境当前运行哪个 AppVersion/DeploymentRun 的唯一指针。预发和生产可以选择不同修订;晋级仍使用同一个 AppVersion,不重建制品。现有 `app_environment_heads_v2` 的 `environment_id` 外键指向 legacy `app_environments`,只作为 alpha 历史审计事实,不能原地改造成最终 Head。
|
|
13
|
-
3. **环境运行态层**:RoleMembership、manual role、业务范围 grant、RelationshipGrant、RoleSession、Workflow 实例、Event receipt、OAuth client 和 Secret 等可变状态绑定远程环境。生产运行态不能被预发部署覆盖。
|
|
14
|
-
|
|
15
|
-
2.0 只有一套远程环境身份模型:一个稳定 `tenant + appCode` 下恰好包含一个 `preproduction`,并在首次明确晋级时最多创建一个 `production` 原生运行环境;每个已创建环境有稳定 UUID 和不可变 route key。同一个 AppVersion 先部署到预发,再原样晋级生产。`local` 是开发机上的运行模式,不注册环境 UUID、不创建远程 Head/OAuth/Secret/RoleSession,也不能作为 deploy/promote 目标。现有 `app_environment_sets/app_environments` 用“不同 appType 分别代表预发和生产”的模型保留给 1.x 发布治理,不再由 2.0 CLI、AppVersion 或 native runtime 使用。
|
|
16
|
-
|
|
17
|
-
物理存储和逻辑运行契约必须分开:Data API 的物理表与新增列是应用级、单调扩展的共享基础设施,业务行继续通过 `environment_key` 隔离;当前允许访问哪些字段、capability、字段策略和 data policy,则由请求环境 Head 选择的不可变 config revision 投影决定。contracts revision 用于证明前端、后端与配置引用的是同一组稳定代码,不保存完整字段 schema。
|
|
18
|
-
|
|
19
|
-
该模型取代当前“每个环境部署都把包配置 UPSERT 到 `tenant + app` 全局活动表”的做法。不能只给旧表增加一个字段:1.x 仍依赖共享 `roles/api_permissions/business_scope_*`,直接改造会让两个内核的所有权、回滚和滚动发布继续互相牵连。2.0 建立原生投影表;1.x 原表保持原语义。
|
|
20
|
-
|
|
21
|
-
## 2. 源码证据与问题边界
|
|
22
|
-
|
|
23
|
-
| 证据 | 当前行为 | 后果 |
|
|
24
|
-
| --- | --- | --- |
|
|
25
|
-
| Deployment executor | alpha 合同仍允许 development、preproduction、production 调用同一个 `configService.activate()` | alpha development 仍能进入配置激活链路;Native v3 必须一次删除该远程通道而不是保留兼容别名 |
|
|
26
|
-
| `activateAuthorization()` | 写 `roles`、`api_permissions`、`business_scope_*` 和 `app_authz_states_v2`,唯一范围只有 `tenant + app` | 开发候选可在尚未晋级生产时改变生产授权语义 |
|
|
27
|
-
| `AppRoleSessionV2Entity` | 已包含 `environment_key` | 会话被环境隔离,但其引用的 assignment、role 和 authz state 没有隔离,边界不闭合 |
|
|
28
|
-
| `app_data_resources_v2` | schema、capability、data policy 和字段策略是 `tenant + app + code` 全局可变记录 | 开发部署可提前改变生产 Data API 的逻辑契约和授权 |
|
|
29
|
-
| Data API 物理业务表 | 行含 `environment_key`,RLS 和事务请求也绑定环境 | 数据行隔离基础已经存在,无需按环境复制物理表 |
|
|
30
|
-
| AppVersion / alpha Environment Head | AppVersion 已组合 component revision;`app_environment_heads_v2` 同时重复保存组件指针,且 `environment_id` 外键指向 legacy `app_environments` | AppVersion 组合骨架可保留并补数据库不可变约束;alpha Head 不能复用,原生 Head 只保存 AppVersion、DeploymentRun 和 CAS revision,避免两份组件指针漂移 |
|
|
31
|
-
| 两套环境实体 | legacy `app_environments` 要求每个环境绑定不同 appType;Application v2 Head 又在同一 appType 下使用环境 key,且 `environment_id` 可空 | 同一“环境”存在两种主键/晋级模型;2.0 必须引入单一原生 registry,并停止调用 legacy set |
|
|
32
|
-
| Kubernetes Runtime | workload/Service 名包含 AppVersion,候选 readiness 后才在数据库事务中更新 Head;网关读取 Head 对应 DeploymentRun 的 runtime 地址 | 候选不会在 Head 提交前承接应用网关流量;激活失败保留旧流量,但失败候选需要回收 |
|
|
33
|
-
| App API Gateway / Nest Guard | 已签发按当前 Head 和具体 HTTP 请求绑定的短期 invocation/assertion,Nest 全局 guard 先离线验签再实时消费调用身份;健康与签名回调使用各自边界 | 路径证明已闭合;下一步由 runtime lease 关闭同进程 Worker/Scheduler 的副作用激活窗口 |
|
|
34
|
-
| 候选运行凭据 | 当前 runtime credential 在候选 readiness 前已经进入可用链路;同一个 Nest 进程可以同时承载 API、Worker 和 Scheduler | 未激活 AppVersion 的启动逻辑、定时任务或 Worker 可能提前访问 Data API 或产生外部副作用,破坏原子晋级 |
|
|
35
|
-
|
|
36
|
-
问题不是单一权限缓存缺陷,而是“不可变包定义”和“环境活动投影”之间缺少统一边界。授权 A0、Data API D0 和后续 Admin A1 必须建立在同一个环境配置内核上。
|
|
37
|
-
|
|
38
|
-
## 3. 不变量与能力所有者
|
|
39
|
-
|
|
40
|
-
1. AppVersion 和所有 component revision 一经创建不可修改;规范化内容摘要由平台重算。
|
|
41
|
-
2. 每个原生环境只有一个活动 Head;用户请求只能从认证得到的 `tenant/app/environmentId` 解析 Head,不能接受业务参数覆盖。环境 key 先经 registry 精确解析并与 Principal 中的 id/key 双重核对。
|
|
42
|
-
3. 一次环境激活要么同时提交 Head、授权环境状态、Workflow/Event 活动指针和部署成功状态,要么全部不提交。
|
|
43
|
-
4. 候选 Kubernetes 工作负载通过 readiness 不代表已激活;只有数据库 Head 提交后才对网关可见。
|
|
44
|
-
5. 预发、生产的可变运行态相互独立。显式“复制角色成员/范围”是管理操作,不是环境部署的隐式副作用;本地运行态不进入远程数据库。
|
|
45
|
-
6. PostgreSQL 是活动 Head、授权版本和安全状态的事实源;Redis、浏览器缓存和 Kubernetes annotation 都不能替代它。
|
|
46
|
-
7. 物理数据 schema 只允许向前兼容、单调扩展。删除字段、改变类型或给有数据的表增加无默认值必填字段必须走独立数据迁移协议,不能混入普通 AppVersion 激活。
|
|
47
|
-
8. 1.x 继续由现有角色、权限和业务范围表负责;2.0 原生内核不得双写这些表作为长期运行方式。
|
|
48
|
-
9. 同一个 AppVersion 从预发晋级生产时使用相同 component/authz/config-contract revision;环境运行态、Secret 和 OAuth client 不随包复制。
|
|
49
|
-
10. 所有环境切换有可观察的 expected Head revision;并发部署不能以“最后提交者覆盖”伪装成两个都成功。
|
|
50
|
-
11. `environmentId` 是控制面与授权运行态的持久身份;`environmentKey` 创建后不可改,只承担 URL、日志、Kubernetes label 和现有 Data API 行隔离。需要新 key 时创建新环境并执行显式迁移,不做原地 rename。
|
|
51
|
-
12. 业务 App API 请求必须同时通过业务身份授权和平台网关路径证明;静态请求头、NodePort 可达性或集群网络位置都不是路径证明。
|
|
52
|
-
13. 候选 runtime 在 Head 提交前只能完成无副作用自检;不能取得正式应用身份,Worker/Scheduler 不能领取任务。Head 回滚或租约丢失后停止领取新任务,在途任务按幂等/lease 协议完成或接管。
|
|
53
|
-
|
|
54
|
-
能力所有者划分:
|
|
55
|
-
|
|
56
|
-
| 能力 | 唯一所有者 |
|
|
57
|
-
| --- | --- |
|
|
58
|
-
| AppVersion 与组件组合 | `ApplicationVersionV2Service` |
|
|
59
|
-
| 环境活动选择和 CAS | `ApplicationEnvironmentActivationV2Service`(从 executor 内联事务提取) |
|
|
60
|
-
| 不可变配置编译 | `ApplicationConfigurationCompilerV2Service` |
|
|
61
|
-
| 原生授权修订与环境授权状态 | `AppAuthorizationKernelV2Service` |
|
|
62
|
-
| Data API 物理 schema | `AppDataPhysicalSchemaV2Service` |
|
|
63
|
-
| Data API 逻辑契约解析 | `AppDataContractV2Service` |
|
|
64
|
-
| 候选 Runtime 创建/readiness/回收 | `ApplicationRuntimeV2Service` |
|
|
65
|
-
| 2.0 环境注册、key→id 解析与 side-effect policy | `ApplicationRuntimeEnvironmentV2Service` |
|
|
66
|
-
| 活动 runtime 解析、短时调用委托、网关断言签发与密钥轮换 | `ApplicationApiGatewayV2Service` + 平台 `ApplicationInvocationTokenService` / `GatewayAssertionKeyService` |
|
|
67
|
-
| 网关断言验证与单进程 API/Worker/Scheduler 激活门控 | 官方 `openxiangda-nest`;应用代码只注册 handler,不自行推断 Head |
|
|
68
|
-
|
|
69
|
-
Executor 只编排阶段,不直接实现授权版本 SQL、逻辑数据契约写入或 Head 选择规则。
|
|
70
|
-
|
|
71
|
-
## 4. 版本与运行态模型
|
|
72
|
-
|
|
73
|
-
### 4.0 原生环境注册
|
|
74
|
-
|
|
75
|
-
```text
|
|
76
|
-
app_runtime_environments_v2
|
|
77
|
-
id uuid,
|
|
78
|
-
tenant_id, app_type,
|
|
79
|
-
environment_key preproduction|production,
|
|
80
|
-
environment_kind preproduction|production,
|
|
81
|
-
display_name, status active|decommissioned,
|
|
82
|
-
side_effect_policy_json,
|
|
83
|
-
revision, created_by, updated_by, created_at, updated_at
|
|
84
|
-
UNIQUE (tenant_id, app_type, environment_key)
|
|
85
|
-
UNIQUE (tenant_id, app_type, environment_kind)
|
|
86
|
-
|
|
87
|
-
app_runtime_environment_heads_v2
|
|
88
|
-
environment_id uuid PRIMARY KEY -> app_runtime_environments_v2.id
|
|
89
|
-
tenant_id, app_type,
|
|
90
|
-
active_app_version_id uuid NOT NULL,
|
|
91
|
-
active_deployment_run_id uuid NOT NULL,
|
|
92
|
-
revision bigint NOT NULL,
|
|
93
|
-
activated_by, activated_at
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
- 一个 2.0 app 固定两个长期远程环境;不支持 development 远程环境、任意自定义 key、同 kind 多环境或 key rename。
|
|
97
|
-
- 新应用 provision 事务只创建 preproduction;首次 promotion 在唯一约束下惰性创建 production。普通部署请求不能隐式补环境,生产环境必须有更严格 side-effect policy 与管理员确认。
|
|
98
|
-
- `environmentId` 进入 OAuth client、Secret、RoleSession、Workflow/Event、DeploymentRun 和授权运行态;对外 DTO 同时返回 id/key/kind,但任何写请求中的 id/key 必须与认证 Principal、app 和 registry 相互匹配。
|
|
99
|
-
- 旧 `app_environment_sets/app_environments` 的跨 appType swap、attach 和 policy 接口不再出现在 openxiangda-v2 CLI/Skill。旧 CLI 和 1.x 应用保持原行为。
|
|
100
|
-
- 原生 Head 不重复保存 frontend/backend/config/contracts revision。AppVersion 是组件组合的唯一事实,`app_version_projection_bindings_v2` 是 AppVersion 到编译后配置闭包的唯一映射;读取方通过它们解析。数据库复合外键必须证明 Head、AppVersion、DeploymentRun 与 environment 属于同一个 tenant/app,不能只靠服务层比较 UUID。
|
|
101
|
-
- 现存 alpha Application v2 Head 不迁移、不预分配 native UUID,也不参与 Native Head 初始化。新的 native reference app 使用全新 app code,并通过显式环境创建命令生成 registry UUID;旧 `head.environment_id` 只留在 alpha 历史中。K4 前 alpha Head 与新应用的原生 Head 可以同时存储,但每个请求只按全局 contract generation 读取其中一套;这不是在线双读或双写。K5 保留 alpha 数据库历史,只撤销明确列出的旧 runtime principal 并删除旧 alpha K3s workload。
|
|
102
|
-
|
|
103
|
-
```mermaid
|
|
104
|
-
flowchart LR
|
|
105
|
-
Package["不可变 AppPackage"] --> Version["AppVersion"]
|
|
106
|
-
Version --> Frontend["frontend revision"]
|
|
107
|
-
Version --> Backend["backend revision"]
|
|
108
|
-
Version --> Config["config revision"]
|
|
109
|
-
Version --> Contracts["contracts revision"]
|
|
110
|
-
Head["Native Environment Head"] --> Version
|
|
111
|
-
Config --> Projection["immutable configuration projection"]
|
|
112
|
-
Contracts --> Projection
|
|
113
|
-
Projection --> AuthzRevision["deduplicated authz revision"]
|
|
114
|
-
Head --> Runtime["versioned Runtime address"]
|
|
115
|
-
Environment["Runtime Environment UUID"] --> Head
|
|
116
|
-
EnvAuthz["Environment Authz State"] --> AuthzRevision
|
|
117
|
-
EnvAuthz --> Environment
|
|
118
|
-
EnvAuthz --> Head
|
|
119
|
-
Request["authenticated environment request"] --> Head
|
|
120
|
-
Request --> EnvAuthz
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### 4.1 不可变定义
|
|
124
|
-
|
|
125
|
-
- `app_component_revisions_v2` 和 `app_versions_v2` 继续保存制品摘要、组合及 provenance,但增加数据库级 UPDATE/DELETE 拒绝触发器;相同 digest 冲突时必须逐字段重读并比较,不能仅按 digest 命中后返回既有行。
|
|
126
|
-
- 配置编译器从经过字节摘要校验的 config/contracts artifact 生成只增不改的关系投影。`metadata_json.configurationBundle` 只作为 alpha 历史审计字段,不能成为原生编译输入的事实源。
|
|
127
|
-
- 授权子集单独计算 canonical digest,生成 `app_authz_revisions_v2`;相同授权声明跨多个 AppVersion 去重。
|
|
128
|
-
- `app_configuration_projections_v2` 聚合 authz、data、event、workflow 和 runtime-requirement 五类不可变领域修订;`app_version_projection_bindings_v2` 为每个原生 AppVersion 固定绑定一个完整投影。即使某领域为空也绑定一个空修订,不用 nullable 表达语义。
|
|
129
|
-
- Data API 逻辑资源定义绑定不可变 data-contract revision;contracts revision 保存编译后的 resource/capability/handler closure,而不是覆盖 `app_data_resources_v2` 的活动 JSON。
|
|
130
|
-
- Workflow/Event 的定义进入不可变领域修订;环境 Head、delivery/receipt、实例/task、暂停/恢复、轮换等运行态仍按环境保存。新 Native 应用从空状态建立这些运行态;现有 alpha 环境化表只保留历史,既不离线迁移,也不由新 config 激活器原地 UPSERT。
|
|
131
|
-
|
|
132
|
-
### 4.2 环境选择
|
|
133
|
-
|
|
134
|
-
`app_runtime_environment_heads_v2` 是新的最小活动指针,以 `environment_id` 唯一定位。它不复制组件 revision 或配置投影字段;这些事实由 AppVersion 和不可变 projection binding 提供。激活命令必须携带部署开始时观察到的 `expectedHeadRevision`:
|
|
135
|
-
|
|
136
|
-
- 首次激活要求 `expectedHeadRevision = 0`;
|
|
137
|
-
- 已有 Head 使用 `UPDATE ... WHERE revision = expectedHeadRevision RETURNING ...`;
|
|
138
|
-
- 未命中返回稳定 409,DeploymentRun 标记 conflict,不覆盖另一场已经成功的部署;
|
|
139
|
-
- 相同 DeploymentRun + 相同 AppVersion + 相同目标 Head 的超时重试返回既有成功结果,不重复推进 revision。
|
|
140
|
-
|
|
141
|
-
### 4.3 环境运行态
|
|
142
|
-
|
|
143
|
-
以下控制面和授权资源必须以 `environment_id` 外键定位,同时保留 tenant/app 复合约束用于防串联和查询计划:
|
|
144
|
-
|
|
145
|
-
- 授权环境状态、manual role、RoleMembership、delegation ceiling;
|
|
146
|
-
- scope grant source 的物化状态、有效 grant、RelationshipGrant;
|
|
147
|
-
- RoleSession;
|
|
148
|
-
- OAuth client、Secret、Event delivery/receipt、Workflow instance/task/provider binding;
|
|
149
|
-
- Data API 幂等事务和业务数据行。
|
|
150
|
-
|
|
151
|
-
最后一项暂时例外:现有动态 Data API 物理表与幂等记录以 `tenant + app + immutable environment_key` 隔离。Data API Principal 必须同时含 registry `environmentId/environmentKey`,RLS 先校验二者映射,再比较行 key。没有必要为所有大表立即回填 UUID;新控制面表不再复制这种字符串主键。
|
|
152
|
-
|
|
153
|
-
应用最高管理员是显式的应用级平台授权,可跨该应用所有环境并天然绕过业务数据范围;绕过必须出现在 explain/audit 中。普通业务角色和范围不使用跨环境通配符。
|
|
154
|
-
|
|
155
|
-
## 5. Data API:物理 schema 与逻辑契约分离
|
|
156
|
-
|
|
157
|
-
Data API 不为每个环境创建一张表。最终模型为:
|
|
158
|
-
|
|
159
|
-
| 层 | 范围 | 行为 |
|
|
160
|
-
| --- | --- | --- |
|
|
161
|
-
| physical resource | `tenant + app + resourceCode` | 稳定 physical table;保存已部署版本所需字段的兼容并集 |
|
|
162
|
-
| physical schema generation | 应用级单调整数 | 只新增 nullable 字段、索引和兼容约束;DDL 可在候选准备阶段完成 |
|
|
163
|
-
| logical resource definition | `configRevision + resourceCode` | name、可见字段、capability、data policy、field policy、状态 |
|
|
164
|
-
| runtime resolution | `tenant + app + environmentId -> native Head -> AppVersion -> projection binding -> data-contract revision` | 每次请求只使用该环境活动逻辑定义;contracts revision 校验消费代码闭合 |
|
|
165
|
-
| business row | `tenant + app + environment + id` | 由 RLS 强制环境隔离 |
|
|
166
|
-
|
|
167
|
-
候选开发版本新增 nullable 字段时,物理列可能先存在,但生产活动逻辑契约看不到也不能读写该字段。字段删除或类型改变不能通过“让生产继续用旧修订”掩盖物理兼容问题,必须先通过 expand/backfill/contract 数据迁移。
|
|
168
|
-
|
|
169
|
-
逻辑 `nullable:false` 不等于候选阶段立即添加物理 `NOT NULL`。只要任一环境 Head 仍运行不认识该字段的旧 revision,旧写入就无法提供它;因此:
|
|
170
|
-
|
|
171
|
-
1. expand 始终添加 nullable 物理列,目标环境的逻辑契约在 create/update 时执行 required 校验;
|
|
172
|
-
2. 需要数据库级 `NOT NULL` 时,AppPackage 只声明 intent,平台生成独立 schema migration plan;
|
|
173
|
-
3. 所有活动 Head 都已支持字段、历史行完成有界 backfill、验证查询为零缺失后,才以独立 contract job 设置约束;
|
|
174
|
-
4. 回滚到旧 AppVersion 不删除约束前要证明旧写路径仍能提供字段,否则回滚 preflight 拒绝。
|
|
175
|
-
|
|
176
|
-
物理 DDL 不放在最终 Head 激活事务:`AppDataPhysicalSchemaV2Service` 使用每资源 advisory lock、持久 schema-generation ledger、有限 `lock_timeout/statement_timeout` 和幂等步骤。添加索引使用 PostgreSQL 允许的并发构建路径并记录 `building|ready|failed`;失败/无效索引由精确 repair job 处理。单个 AppVersion 默认最多 20 个新增字段、10 个新增索引,超过需独立容量计划;运行中不得扫描全表计算默认值。DDL 成功但后续 runtime/Head 激活失败时,兼容的额外列/索引可以保留,旧环境逻辑契约仍不可见。
|
|
177
|
-
|
|
178
|
-
授权角色引用的 capability catalog 由 AppVersion 组合时校验:平台保留管理 capability、`authz.capabilities` 显式声明的 backend/UI capability、Data Resource 自动导出的数据/字段 capability 必须闭合;contracts revision 记录闭合后的代码集合供前后端生成类型和验包。Nest `@RequireCapability` 与 Admin route 使用生成常量,构建时校验其属于 contracts。不存在、跨应用或只被角色引用但未声明的 capability 使 AppVersion prepare 失败。
|
|
179
|
-
|
|
180
|
-
## 6. App API 路径证明与候选执行门控
|
|
181
|
-
|
|
182
|
-
### 6.1 双重授权边界
|
|
183
|
-
|
|
184
|
-
平台网关先验证调用者原始用户/OAuth2 access token,按认证上下文解析稳定 `environmentId` 和活动 Head,只能向该 Head 对应的 DeploymentRun 转发。原始 access token 到此终止,不能进入应用容器或应用日志。网关签发两个职责分离的短时工件:
|
|
185
|
-
|
|
186
|
-
1. `Authorization: Bearer <application-invocation-token>`:最长 60 秒,audience 绑定目标应用、环境和 DeploymentRun;携带最小 Principal/RoleSession 引用、源 token id 摘要和授权版本,用于 Nest 向 Data API/Workflow 等平台接口做 on-behalf-of 调用。平台消费时仍实时验证 RoleSession、membership/grant、环境 authz state 和当前 Head,不能只相信 JWT 中的 allow 结果。
|
|
187
|
-
2. `X-OpenXiangda-Gateway-Assertion`:最长 30 秒的 Ed25519 JWS,证明具体 HTTP 请求由平台网关根据当前 Head 转发。断言至少绑定:
|
|
188
|
-
|
|
189
|
-
```text
|
|
190
|
-
issuer, audience=openxiangda-app-backend,
|
|
191
|
-
tenantId, appCode, environmentId, environmentKey,
|
|
192
|
-
appVersionId, deploymentRunId,
|
|
193
|
-
method, normalizedPath, canonicalQueryDigest, bodyDigest,
|
|
194
|
-
invocationTokenDigest, roleSessionIdDigest,
|
|
195
|
-
jti, iat, nbf, exp, keyId
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
- 私钥只属于平台;runtime 只获得当前/上一把公钥或受控 JWKS,轮换期间两把公钥有界重叠。不能给每个应用复制平台签名私钥。
|
|
199
|
-
- Nest 全局 transport guard 先验证断言签名、时间、请求摘要和自身注入的 app/environment/version/run 身份,再由 AuthZ Guard 验证 invocation token、RoleSession/Application Principal 和 `@RequireCapability()`。任一层失败都 fail closed。
|
|
200
|
-
- 调用者原始 `Authorization`、RoleSession 原值和业务数据不写入断言,只写 SHA-256 digest;两个工件都不进入浏览器、日志或应用响应。`jti` 用于短窗口重放诊断;有副作用的业务操作仍必须使用应用级 idempotency key,不能把短时签名当 exactly-once。
|
|
201
|
-
- invocation token 不能换取 refresh token,不能访问别的应用/环境/run;过期、源登录会话撤销、RoleSession stale、runtime 不再是当前 Head 时拒绝。用户请求结束后应用不得持久化它。对外 OAuth2 client 仍通过平台网关调用,client access token 也不原样转发给应用。
|
|
202
|
-
- 只有 `/__platform/health`、`/__platform/ready` 和版本自检允许没有业务身份;Events 使用订阅 HMAC/receipt,Workflow provider 使用平台回调签名。其他自定义 controller 即使没有 `@RequireCapability()` 也不得绕过 transport guard;缺 capability 的服务身份请求继续拒绝。
|
|
203
|
-
- 现有 `X-OpenXiangda-Forwarded-By` 降级为诊断字段,不参与授权。NodePort、cluster DNS 或反向代理直连都因缺断言失败。
|
|
204
|
-
|
|
205
|
-
Kubernetes 仍提供第一层缩小攻击面:共享与独立档位都生成 default-deny ingress;cluster-dns 只允许标记过的平台网关 namespace,node-port 必须配置明确的 gateway source CIDR/主机防火墙规则后才允许部署。NetworkPolicy/安全组配置错误不能扩大授权,因为 Nest 的离线签名验证仍是强制边界。请求体采用流式摘要并沿用 20 MiB 上限,避免为了签名在网关和 Nest 中各无界复制一份。
|
|
206
|
-
|
|
207
|
-
### 6.2 候选 runtime 状态
|
|
208
|
-
|
|
209
|
-
runtime credential 采用 `pending -> active -> retiring -> revoked` 状态并绑定 `environmentId + appVersionId + deploymentRunId`:
|
|
210
|
-
|
|
211
|
-
1. P0 创建 pending credential 和一次可恢复的 secret;pending 只能调用版本化 readiness/activation-status 端点,token 服务不为它签发 Data API、App API、Workflow 或外部调用 scope。
|
|
212
|
-
2. P1/P2 启动完整 Nest 进程,但官方 runtime gate 只开放健康/版本自检;API 需要活动 Head 网关断言,Worker/Scheduler 尚无活动租约。应用 `OnModuleInit` 必须无业务副作用,模板测试和静态规则禁止自行启动 cron/queue consumer。
|
|
213
|
-
3. P3 在同一个数据库事务中 CAS Head、激活目标 runtime credential、推进活动 generation 并把旧 credential 标记 retiring。数据库提交后,新网关断言、invocation token 和 runtime token 才能引用该 run/version;旧 run 的 runtime token 立即不能发起新平台业务调用,在途任务由 claim lease/idempotency 重新接管。
|
|
214
|
-
4. 单体 Nest 中的 Worker/Scheduler 通过平台长轮询获得短时 runtime lease;lease 绑定当前 Head revision/run,只有活动版本可续租。失去租约后停止领取新任务;已领取任务使用既有 claim lease、幂等键和接管协议,不强杀到一半。
|
|
215
|
-
5. Event/Workflow 投递目标始终从活动 Head 解析,不向 pending/retiring runtime 派发新命令。旧版本只在有界 draining window 处理在途工作,随后撤销凭据并精确回收。
|
|
216
|
-
|
|
217
|
-
平台对自身通道提供强保证:pending runtime 无 Data API/App API/Workflow scope、不领取任务、不接收事件,也不获得 active-only Secret。应用作者仍可能在第三方库初始化时直接访问外部系统,这不是 Nest 生命周期能单独证明的边界。2.0 首期信任应用开发者,不建设域名代理、CIDR 审批或通用 egress 策略 DSL;外部系统连接由应用后端正常开发和负责。平台只保证自身发放的业务身份、租约和 Secret 在 Head 激活前不可用,避免把复杂而不完整的网络策略包装成安全保证。
|
|
218
|
-
|
|
219
|
-
## 7. 环境激活状态机
|
|
220
|
-
|
|
221
|
-
| 阶段 | 动作 | 失败语义 |
|
|
222
|
-
| --- | --- | --- |
|
|
223
|
-
| P0 immutable prepare | 校验 AppPackage,创建/复用 component、authz、config-data 投影和 pending runtime credential;校验 contracts closure;执行允许的单调 DDL | 没有活动 Head 变化;pending identity 无业务 scope;可安全重试 |
|
|
224
|
-
| P1 runtime candidate | 创建按 AppVersion 命名的 Deployment/Service/Secret | 不覆盖旧 workload;runtime gate 禁止业务入口和后台消费;失败记录可重试 |
|
|
225
|
-
| P2 readiness | 验证候选健康、版本/环境自检和受限平台握手 | 不使用正式应用身份、不产生业务副作用;未通过不进入激活事务 |
|
|
226
|
-
| P3 activation transaction | advisory lock `environmentId`;复核 tenant/app/key 与 registry;CAS Head;切 authz/data/workflow/event 指针;激活目标 credential/lease generation;记录 DeploymentRun succeeded | 任一项失败整笔回滚,旧 Head/凭据/配置/路由保持不变 |
|
|
227
|
-
| P4 post-commit | 网关按新 Head 签发断言;新 runtime 取得 lease;旧 runtime 进入 draining;清理旧缓存 namespace | 协调失败由 reconciler 重试;新请求仍只到 Head,后台未取得 lease 时保持暂停 |
|
|
228
|
-
| P5 failed candidate GC | retryable run 保留候选供同版本重试;terminal/cancelled 或超过 TTL 的候选回收 | GC 只按 run/app/version 精确删除,禁止标签宽删活动 Head workload |
|
|
229
|
-
|
|
230
|
-
当前版本化 Service 不需要替换为稳定 Service selector:应用网关已经从环境 Head 读取活动 DeploymentRun 的 runtime 地址,因此 Head 是现有流量开关。需要补的是 CAS、失败候选回收和“Head 指向的 workload 不可删除”保护。
|
|
231
|
-
|
|
232
|
-
## 8. 并发、失败与回滚
|
|
233
|
-
|
|
234
|
-
| 场景 | 必须行为 |
|
|
235
|
-
| --- | --- |
|
|
236
|
-
| 同一环境两个部署并发 | advisory lock 后用 expected Head revision;恰好一个按其预期激活,另一个 409 或在显式重新计划后重试 |
|
|
237
|
-
| Kubernetes 成功、数据库激活失败 | 旧 Head 继续路由;候选进入可重试或 GC 状态,不执行旧 workload retirement |
|
|
238
|
-
| 物理 schema expand 成功、候选部署失败 | 兼容列/索引保留并由 ledger 记录;旧逻辑 revision 不暴露它们,不做破坏性回滚 |
|
|
239
|
-
| 数据库激活成功、旧 workload 删除失败 | 新 Head 正常服务;记录告警并由幂等 GC 重试 |
|
|
240
|
-
| 相同 AppVersion 晋级 | 复用所有不可变修订;只切目标环境 Head 和该环境活动状态 |
|
|
241
|
-
| 授权摘要未变 | 环境 authzVersion 不变,旧 RoleSession 可继续;Head revision 仍因应用版本切换而增长 |
|
|
242
|
-
| 授权摘要改变 | 仅目标环境 authzVersion +1,并使该环境旧 RoleSession stale;其他环境不受影响 |
|
|
243
|
-
| 回滚 AppVersion | 创建新的 rollback DeploymentRun,CAS 切回历史不可变修订;运行态数据不倒退,兼容性 preflight 必须通过 |
|
|
244
|
-
| 配置数据定义回滚缺少新字段 | 旧逻辑修订忽略多余物理列;不删除列,不回滚业务数据 |
|
|
245
|
-
| PostgreSQL 不可用 | Head、授权和 Data API fail closed;不得从 Redis/Kubernetes 猜活动版本 |
|
|
246
|
-
| NodePort 被公网或同集群其他 Pod 直连 | 无有效网关断言时 Nest 在业务代码前拒绝;健康端点不返回配置、凭据或业务数据 |
|
|
247
|
-
| 候选容器启动后 Head 激活失败 | pending credential 不能取得业务 token,Worker/Scheduler 没有 lease;候选进入 retry/GC,不产生生产副作用 |
|
|
248
|
-
| Head 已切换但 runtime lease 暂时不可得 | 用户 API 仍按网关断言服务;后台停止领取新任务并告警,reconciler 恢复 lease,不让旧版本代领新任务 |
|
|
249
|
-
|
|
250
|
-
## 9. 2.0 Alpha 合同切换
|
|
251
|
-
|
|
252
|
-
用户已经明确 2.0 不承担当前 alpha 客户端兼容;稳定 1.x 在独立工具链和旧表上维护。因此这里采用一次明确的 contract cutover,不建设长期 alpha/native 双内核:
|
|
253
|
-
|
|
254
|
-
1. **K0 preflight evidence**:按显式 allowlist 交叉验证 Application v2 AppVersion/Head 闭包与 K3s managed workload,证明 prod-1 只有可重建的 alpha reference。只存在 legacy DeliveryRun/Runtime/Event 的应用必须被排除;不读取主体/业务值、不生成迁移计划。
|
|
255
|
-
2. **K1 build offline**:增加 runtime environment registry、最小原生 Head、immutable projection、native authz/data resolution 和新 Admin context,并在仓库/本地或隔离测试环境创建全新 app code 的 native reference;所有新路径先由测试/本地新应用验证,但尚不对线上 2.0 路由开放。alpha 路径继续只读旧 Head,native 路径只读新 Head,禁止请求级 fallback;1.x 代码不引用这些表。
|
|
256
|
-
3. **K2 capable rollout**:把同一 native-capable Platform Server 镜像部署到全部实例,读取实例 capability 清单;这时旧 2.0 路由仍保持 alpha,但新写入口关闭。readiness 不能代替全实例版本证明。
|
|
257
|
-
4. **K3 short write fence**:进入平台级 2.0 maintenance window,只暂停 Application v2 部署、Data API 写、role/scope 管理、Workflow/Event 新动作;1.x 和平台其他能力继续运行。等待在途 2.0 请求/worker lease 有界排空,撤销全部 alpha RoleSession 和 runtime OAuth token。prod-1 在此阶段只验证 Native artifact/Head 闭包与无业务凭据的 candidate readiness,不为测试建立 generation 旁路。
|
|
258
|
-
5. **K4 atomic contract switch**:数据库只做一次带 expected revision 的 `openxiangda_v2_contract_generation=native-2` CAS;新平台路由只读 Native 表,且只有已经绑定 Native Head 的新 reference 可路由,在验收窗口完成真实 Postgres/PostgREST/K3s/浏览器预发 E2E;旧 alpha endpoint 返回稳定 `410 OPENXIANGDA_V2_ALPHA_CONTRACT_REMOVED` 与最低客户端版本,不做 legacy serializer、双读或 alpha 数据导入。
|
|
259
|
-
6. **K5 verify and reopen**:新 reference 预发 E2E 通过后开放 Native 常规应用创建/写入,同一 Native AppVersion 晋级生产并再验收。观察期后仅撤销明确列出的旧 alpha runtime OAuth/principal 并删除两个旧 alpha K3s workload;alpha 数据库历史保留,1.x 共享表不删除。
|
|
260
|
-
|
|
261
|
-
回滚边界:K4 之前可回滚 native-capable 镜像;K4 后只回滚到同样理解 `native-2` schema/route 的修复镜像,不能恢复 alpha 授权语义或重新打开旧 endpoint。若 K4 后验收失败,保持 2.0 maintenance、修复或把 reference app Head 切回 native 历史版本;1.x 始终不进入该栅栏。
|
|
262
|
-
|
|
263
|
-
多实例门禁由平台进程自动心跳,无需应用开发者参与。每个实例上报 `PLATFORM_RELEASE_VERSION` 和固定 Native capability 集;单实例默认期望数量为 `1`,多实例部署只需把所有实例的 `OPENXIANGDA_PLATFORM_EXPECTED_INSTANCES` 设置为同一个总数。实例必须在短 TTL 内全部存活、release 完全一致且能力无缺失,`switch-native` 才能提交;`status` 同时返回逐实例证据。
|
|
264
|
-
|
|
265
|
-
## 10. 可证伪验收
|
|
266
|
-
|
|
267
|
-
1. 同一应用 preproduction 发布不同角色/字段策略后,production 的 RoleSession、capability explain 和 Data API 响应逐字节不变;local 开发不产生任何远程状态。
|
|
268
|
-
2. 同一 appCode 的原生 preproduction/production 拥有不同 environment UUID;同一 AppVersion 先预发后生产,两环境引用相同 immutable revision id/digest,但 RoleMembership、Secret、OAuth client 和 scope grant 不共享。
|
|
269
|
-
3. 两个并发部署使用同一 expected Head revision,恰好一个成功;失败者不能覆盖成功者。
|
|
270
|
-
4. 候选 runtime readiness 成功后强制让 activation SQL 失败,网关仍请求旧 AppVersion,候选随后被精确 GC。
|
|
271
|
-
5. 开发 config data resource 增加字段后物理列存在,但生产活动定义查询/写入该字段均拒绝;生产晋级后才可使用。
|
|
272
|
-
6. 回滚到旧 config revision 不删除物理列、不损坏新数据,旧逻辑字段集恢复。
|
|
273
|
-
7. PostgreSQL/Redis/Kubernetes 分别注入故障,证明 Head 和授权事实不从缓存或 annotation 推断。
|
|
274
|
-
8. 代表性 1.x 登录、角色、表单权限和 legacy environment-set 操作不访问任何新 2.0 原生表;2.0 CLI 不再调用 legacy environment-set API。
|
|
275
|
-
9. 直接访问活动、旧版和候选 NodePort:缺失、过期、错误 appVersion、错误 body digest 和重放断言全部在 Nest 业务 handler 前拒绝;正常网关请求仍通过 OAuth2/RoleSession/capability 判定,应用容器和访问日志中不存在调用者原始 access token。
|
|
276
|
-
10. invocation token 不能跨 app/environment/run、不能刷新;Head 切换、源会话撤销、RoleSession/membership stale 后均拒绝。真实 Nest→Data API 链路证明委托身份与原调用者的授权结果相同,但应用拿不到原始 bearer。
|
|
277
|
-
11. 候选 readiness 保持 10 分钟并人为触发 Scheduler tick/Worker 消息,Data API、外部副作用和任务领取计数均为零;Head 提交后只有新 run 获得 lease,回滚后新 run 停止领取。
|
|
278
|
-
12. 网关签名密钥轮换覆盖 current/previous 接受窗口、未知 key fail closed、时钟偏差上限和 20 MiB 流式摘要内存上限。
|
|
279
|
-
|
|
280
|
-
## 11. 实施顺序
|
|
281
|
-
|
|
282
|
-
1. CP0/CP1:按[Alpha 退役与 Native 切换前置审计](./native-kernel-inventory-v2.md)实现显式 allowlist classifier、Platform Server 镜像 `scripts/` 中的纯 Node 只读入口和根部署 preflight。它不增加 evidence schema/数据库角色/Secret/ServiceAccount/RBAC/通用 importer,不扫描业务表;根脚本复用 backend release Job 构造原语,从权威镜像摘要运行两个无 SA token 的短生命受限资源 Job,用 DB-A/K3s-A/DB-B/K3s-B 语义摘要证明 prod-1 只有可重建的 alpha reference,不部署候选镜像。`CP*` 不与本文 `P0-P4` 环境激活协议共享编号。
|
|
283
|
-
2. E1:按[原生配置投影实施蓝图](./native-configuration-projection-v2.md)建立 config/contracts v3、不可变配置编译器、最小原生 Head、authz/data/event/workflow/runtime-requirement 投影、contracts closure 及 idempotent digest 测试。
|
|
284
|
-
3. E2:Data API physical/logical 分离,先离线对照新旧 resolver,再随 native generation 一次按环境切读;不建立在线双读模式。
|
|
285
|
-
4. E3:原生环境授权内核,详见 [授权一致性基线](./authorization-consistency-v2.md)。
|
|
286
|
-
5. E4:抽取 Environment Activation service,加入 Head CAS、pending runtime credential、网关断言、单进程 runtime lease、失败候选 GC 和多实例 capability gate。
|
|
287
|
-
6. E5:执行短时 2.0 contract cutover,开放全新 app identity 的 native reference;不迁移旧 alpha reference,也不建设 alpha/native 长期兼容层。
|
|
288
|
-
7. E6:Admin A1/A2 消费 native RoleSession context,随后实现 Shell 产品轨。
|
|
289
|
-
|
|
290
|
-
每个阶段独立 SQL migration、平台提交和回滚说明;不得把 E1-E6 合成一次不可观察的大发布。
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# OpenXiangda 1.x → 2.0 全量字段组件迁移矩阵
|
|
2
|
-
|
|
3
|
-
状态:2026-08-18 已完成并通过组件、模板与三端回归验证
|
|
4
|
-
|
|
5
|
-
关联决策:[`proven-field-components-and-standard-surfaces-v2.md`](./proven-field-components-and-standard-surfaces-v2.md)
|
|
6
|
-
|
|
7
|
-
## 1. 迁移原则
|
|
8
|
-
|
|
9
|
-
- “复用 1.0”指复用已经验证的功能、信息顺序、交互状态、错误反馈和移动端适配,不在 2.0
|
|
10
|
-
包中建立对 1.x 源码、运行时、工作区或发布接口的依赖。
|
|
11
|
-
- 2.0 只保留一套稳定值。兼容输入只允许在明确的归一化边界内发生,提交后必须收敛到本表定义的
|
|
12
|
-
2.0 稳定值。
|
|
13
|
-
- Desktop 和 Mobile 共享稳定值、校验规则、文件控制器和错误语义,使用独立 renderer 实现。
|
|
14
|
-
- 每个组件必须覆盖编辑、只读、禁用、必填、空值、加载、失败、提交回显;文件类组件额外覆盖
|
|
15
|
-
上传、进度、取消、重试、预览、下载、删除和稳定身份去重。
|
|
16
|
-
- 页面布局容器不冒充字段。分区、栅格、说明、列表/详情容器由 Surface/Page 层实现。
|
|
17
|
-
|
|
18
|
-
## 2. Registry 全量映射
|
|
19
|
-
|
|
20
|
-
| 1.x Registry 名称 | 2.0 `FieldKind` | 2.0 稳定值 | Desktop / Mobile 行为基线 | 当前实施状态 |
|
|
21
|
-
| --- | --- | --- | --- | --- |
|
|
22
|
-
| `TextField` | `text` | `string \| null` | 单行输入、placeholder、长度/计数、清空、前后缀、只读文本 | 已完成 |
|
|
23
|
-
| `NumberField` | `number` / `money` / `percent` | `number \| null` | 数值边界、步长、精度、单位位置、千分位;移动数字输入 | 已完成 |
|
|
24
|
-
| `TextAreaField` / `TextareaField` | `textarea` | `string \| null` | 多行自适应、最少/最多行、长度/计数、只读换行 | 已完成 |
|
|
25
|
-
| `SelectField` | `option` | `{label,value} \| null` | 搜索、清空、禁用项、稳定标签回显 | 已完成,纳入回归 |
|
|
26
|
-
| `MultiSelectField` | `options` | `{label,value}[]` | 多选、最大数量、响应式标签、移动 Popup/CheckList | 已完成 |
|
|
27
|
-
| `RadioField` | `radio` | `{label,value} \| null` | 单选组、禁用项、只读标签 | 已完成,纳入回归 |
|
|
28
|
-
| `CheckboxField` | `checkbox` | `{label,value}[]` | 多选组、禁用项、只读标签集合 | 已完成,纳入回归 |
|
|
29
|
-
| `DateField` | `date` / `datetime` | ISO/格式化日期字符串或 `null` | 日期与日期时间选择、清空、只读格式化 | 已完成,纳入回归 |
|
|
30
|
-
| `CascadeDateField` | `dateRange` | `[start,end]` | 成对日期、可选日期限制、范围校验、移动分步选择 | 已完成 |
|
|
31
|
-
| `AttachmentField` | `attachments` | `StableAttachmentValue[]` | 上传进度、取消/重试、预览、下载、删除、同名文件不合并 | 已完成 |
|
|
32
|
-
| `ImageField` | `images` | `StableAttachmentValue[]`,`variant=image` | 图片选择、缩略图、预览、上传状态、删除 | 已完成 |
|
|
33
|
-
| `SubFormField` | `subtable` | `Record<string,unknown>[]` | 行增删、子字段编辑、最少/最多行、只读明细 | 已完成 |
|
|
34
|
-
| `UserSelectField` / `EmployeeSelectField` | `user` / `users` | `{label,value}` 或数组 | 组织树、搜索、单/多选、已选回显 | 已完成,纳入回归 |
|
|
35
|
-
| `DepartmentSelectField` | `department` / `departments` | `{label,value}` 或数组 | 部门树、路径、搜索、单/多选 | 已完成,纳入回归 |
|
|
36
|
-
| `CascadeSelectField` | `cascade` | `{label,value}[]` 路径 | 级联路径、叶子选择、清空、只读路径 | 已完成,纳入回归 |
|
|
37
|
-
| `AddressField` | `address` | `StableAddressValue` | 省市区级联、详细地址、完整地址回显 | 已完成,纳入回归 |
|
|
38
|
-
| `AssociationFormField` | 不迁移 | - | 平台组件弃用;复杂关联查询由应用页面和 App API 实现 | 已确认弃用 |
|
|
39
|
-
| `EditorField` | `richtext` | 清洗后的 HTML `string` | 常用格式、链接安全、移动简化工具栏、只读二次清洗 | 已完成 |
|
|
40
|
-
| `SerialNumberField` | `serial` | 平台生成的 `string \| null` | 创建前占位、创建后只读,不允许客户端伪造 | 已完成,纳入回归 |
|
|
41
|
-
| `LocationField` | `location` | `StableLocationValue` | 钉钉优先、浏览器降级、地址/坐标/精度、重定位/清空 | 已完成 |
|
|
42
|
-
| `DigitalSignatureField` | `signature` | `StableSignatureValue` | 手写、清空/重签、预览、轨迹/时间/哈希、有界 PNG | 已完成 |
|
|
43
|
-
| `JSONField` | `json` | JSON value | 编辑时语法错误、格式化、只读结构展示 | 已完成,纳入回归 |
|
|
44
|
-
|
|
45
|
-
## 3. 2.0 原生扩展
|
|
46
|
-
|
|
47
|
-
以下能力不需要伪装成 1.x Registry 项,但必须服从相同的三端状态和稳定值规则:
|
|
48
|
-
|
|
49
|
-
| `FieldKind` | 用途 | 稳定值与边界 |
|
|
50
|
-
| --- | --- | --- |
|
|
51
|
-
| `boolean` | 业务开关 | `boolean`;只读显示明确“是/否”语义 |
|
|
52
|
-
| `workflowStatus` | 流程状态投影 | `{label,value}`;只读为主,不维护第二份流程状态 |
|
|
53
|
-
| `departments` / `users` | 组织多选变体 | `{label,value}[]`;复用目录合同和 RoleSession |
|
|
54
|
-
|
|
55
|
-
## 4. 页面层组件
|
|
56
|
-
|
|
57
|
-
1.x 中已验证但不属于字段 Registry 的页面能力迁移到标准 Surface/Page:
|
|
58
|
-
|
|
59
|
-
| 能力 | 2.0 所有者 | 三端要求 |
|
|
60
|
-
| --- | --- | --- |
|
|
61
|
-
| 表单分区、说明、栅格 | Admin/User Surface | Desktop 高密度双列;Mobile 单列分区 |
|
|
62
|
-
| 搜索、筛选、列表、分页 | Admin/User Data Page | 服务端查询;移动端卡片列表,不压缩桌面表格 |
|
|
63
|
-
| 详情与只读容器 | Admin/User Detail Page | 保持字段顺序;文件仍可按权限预览/下载 |
|
|
64
|
-
| 草稿、提交与首错定位 | Form Controller | 草稿允许未完成;提交阻止上传中与字段错误 |
|
|
65
|
-
| 审批预检 | Workflow Page | 保存业务数据并 prepare 成功后,Desktop Modal / Mobile Popup 打开 |
|
|
66
|
-
| 工作台、待办、我的申请 | User/Admin Shell | 同一 RoleSession/Data/Workflow API,不复制状态源 |
|
|
67
|
-
|
|
68
|
-
## 5. 验收清单
|
|
69
|
-
|
|
70
|
-
- 除已明确弃用的关联表单外,1.0 标准字段都有明确的 2.0 映射;别名不重复实现。
|
|
71
|
-
- 每种 `FieldKind` 至少有值归一化测试;关键字段有 Desktop、Mobile、只读和失败态测试。
|
|
72
|
-
- `attachments` 与 `images` 只能绑定到真实声明为 `file` 的 DataResource 字段。
|
|
73
|
-
- 同名不同 `fileId` 的文件保留两份;相同 `fileId` 或同一稳定 URL 只显示一份。
|
|
74
|
-
- Mobile renderer 的依赖图不得包含 Desktop `antd`。
|
|
75
|
-
- 业务 PC、Mobile、Admin 示例使用同一套 FieldDefinition 和后端合同,页面组合可以独立。
|
|
76
|
-
- 1.x 源码、包名、工作区探测与发布 API 不得进入任何 2.0 可发布包。
|