openxiangda 2.0.0-alpha.98 → 2.0.0
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/LICENSE +21 -0
- package/README.md +23 -20
- package/bin/distribution/commands.js +55 -0
- package/bin/distribution/launcher.js +49 -0
- package/bin/distribution/migrate.js +60 -0
- package/bin/distribution/releases.js +52 -0
- package/bin/distribution/skills.js +80 -0
- package/bin/distribution/update.js +68 -0
- package/bin/distribution/workspace.js +85 -0
- package/bin/run.js +9 -11
- package/dist/browser/AuthoritativeSelector.d.ts +3 -2
- package/dist/browser/AuthoritativeSelector.d.ts.map +1 -1
- package/dist/browser/AuthoritativeSelector.js +39 -24
- package/dist/browser/AuthoritativeSelector.js.map +1 -1
- package/dist/browser/Shell.d.ts.map +1 -1
- package/dist/browser/Shell.js +24 -18
- package/dist/browser/Shell.js.map +1 -1
- package/dist/browser/admin-information-architecture.d.ts +4 -2
- package/dist/browser/admin-information-architecture.d.ts.map +1 -1
- package/dist/browser/admin-information-architecture.js +2 -2
- package/dist/browser/admin-information-architecture.js.map +1 -1
- package/dist/browser/application.d.ts.map +1 -1
- package/dist/browser/application.js +3 -3
- package/dist/browser/application.js.map +1 -1
- package/dist/browser/components/platform-fields/AttachmentFileList.d.ts.map +1 -1
- package/dist/browser/components/platform-fields/AttachmentFileList.js +5 -1
- package/dist/browser/components/platform-fields/AttachmentFileList.js.map +1 -1
- package/dist/browser/components/platform-fields/MobileFieldControls.d.ts.map +1 -1
- package/dist/browser/components/platform-fields/MobileFieldControls.js +2 -2
- package/dist/browser/components/platform-fields/MobileFieldControls.js.map +1 -1
- package/dist/browser/components/platform-fields/ResourceReferenceField.d.ts +4 -2
- package/dist/browser/components/platform-fields/ResourceReferenceField.d.ts.map +1 -1
- package/dist/browser/components/platform-fields/ResourceReferenceField.js +2 -2
- package/dist/browser/components/platform-fields/ResourceReferenceField.js.map +1 -1
- package/dist/browser/components/platform-fields/SubtableField.d.ts.map +1 -1
- package/dist/browser/components/platform-fields/SubtableField.js +60 -80
- package/dist/browser/components/platform-fields/SubtableField.js.map +1 -1
- package/dist/browser/components/platform-fields/rich-text-value.d.ts.map +1 -1
- package/dist/browser/components/platform-fields/rich-text-value.js +11 -1
- package/dist/browser/components/platform-fields/rich-text-value.js.map +1 -1
- package/dist/browser/components/resource/GeneratedResourceCrud.d.ts.map +1 -1
- package/dist/browser/components/resource/GeneratedResourceCrud.js +33 -114
- package/dist/browser/components/resource/GeneratedResourceCrud.js.map +1 -1
- package/dist/browser/components/resource/GeneratedResourceForm.d.ts +3 -1
- package/dist/browser/components/resource/GeneratedResourceForm.d.ts.map +1 -1
- package/dist/browser/components/resource/GeneratedResourceForm.js +11 -4
- package/dist/browser/components/resource/GeneratedResourceForm.js.map +1 -1
- package/dist/browser/components/resource/RecordChangeHistory.d.ts +12 -0
- package/dist/browser/components/resource/RecordChangeHistory.d.ts.map +1 -0
- package/dist/browser/components/resource/RecordChangeHistory.js +61 -0
- package/dist/browser/components/resource/RecordChangeHistory.js.map +1 -0
- package/dist/browser/components/resource/RecordDetailFrame.d.ts +30 -0
- package/dist/browser/components/resource/RecordDetailFrame.d.ts.map +1 -0
- package/dist/browser/components/resource/RecordDetailFrame.js +25 -0
- package/dist/browser/components/resource/RecordDetailFrame.js.map +1 -0
- package/dist/browser/components/resource/ResourceFormFrame.d.ts +2 -1
- package/dist/browser/components/resource/ResourceFormFrame.d.ts.map +1 -1
- package/dist/browser/components/resource/ResourceFormFrame.js +4 -4
- package/dist/browser/components/resource/ResourceFormFrame.js.map +1 -1
- package/dist/browser/components/resource/StandardResourcePages.d.ts +2 -4
- package/dist/browser/components/resource/StandardResourcePages.d.ts.map +1 -1
- package/dist/browser/components/resource/StandardResourcePages.js +8 -26
- package/dist/browser/components/resource/StandardResourcePages.js.map +1 -1
- package/dist/browser/components/resource/SurfaceFields.d.ts +5 -3
- package/dist/browser/components/resource/SurfaceFields.d.ts.map +1 -1
- package/dist/browser/components/resource/SurfaceFields.js +37 -12
- package/dist/browser/components/resource/SurfaceFields.js.map +1 -1
- package/dist/browser/components/resource/resource-import.d.ts +16 -1
- package/dist/browser/components/resource/resource-import.d.ts.map +1 -1
- package/dist/browser/components/resource/resource-import.js +58 -34
- package/dist/browser/components/resource/resource-import.js.map +1 -1
- package/dist/browser/components/resource/useResourceFormDrafts.d.ts.map +1 -1
- package/dist/browser/components/todo/ApplicationTodoCenterPage.d.ts +5 -2
- package/dist/browser/components/todo/ApplicationTodoCenterPage.d.ts.map +1 -1
- package/dist/browser/components/todo/ApplicationTodoCenterPage.js +19 -14
- package/dist/browser/components/todo/ApplicationTodoCenterPage.js.map +1 -1
- package/dist/browser/components/workflow/StandardWorkflowPages.d.ts +21 -5
- package/dist/browser/components/workflow/StandardWorkflowPages.d.ts.map +1 -1
- package/dist/browser/components/workflow/StandardWorkflowPages.js +175 -192
- package/dist/browser/components/workflow/StandardWorkflowPages.js.map +1 -1
- package/dist/browser/components/workflow/WorkflowRecordEditor.d.ts +2 -1
- package/dist/browser/components/workflow/WorkflowRecordEditor.d.ts.map +1 -1
- package/dist/browser/components/workflow/WorkflowRecordEditor.js +7 -4
- package/dist/browser/components/workflow/WorkflowRecordEditor.js.map +1 -1
- package/dist/browser/platform-client.d.ts +10 -4
- package/dist/browser/platform-client.d.ts.map +1 -1
- package/dist/browser/platform-client.js +78 -17
- package/dist/browser/platform-client.js.map +1 -1
- package/dist/browser/record-detail.css +115 -0
- package/dist/browser/runtime.d.ts.map +1 -1
- package/dist/browser/runtime.js +26 -2
- package/dist/browser/runtime.js.map +1 -1
- package/dist/browser/styles.css +1 -0
- package/dist/browser/workflow-launch.d.ts +4 -1
- package/dist/browser/workflow-launch.d.ts.map +1 -1
- package/dist/browser/workflow-launch.js +32 -0
- package/dist/browser/workflow-launch.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js.map +1 -1
- package/documentation/AGENTS.md +26 -0
- package/documentation/administration.md +27 -0
- package/documentation/application-foundation.md +162 -0
- package/documentation/appspec.md +152 -0
- package/documentation/backend.md +132 -0
- package/documentation/concepts.md +61 -0
- package/documentation/data-authz.md +62 -0
- package/documentation/delivery.md +110 -0
- package/documentation/development.md +32 -0
- package/documentation/field-components.md +236 -0
- package/documentation/frontend.md +269 -0
- package/documentation/getting-started.md +66 -0
- package/documentation/interaction-patterns.md +56 -0
- package/documentation/manifest.json +120 -0
- package/documentation/product-design.md +142 -0
- package/documentation/public-access.md +167 -0
- package/documentation/reference/cli.md +27 -0
- package/documentation/reference/mcp.md +649 -0
- package/documentation/testing.md +63 -0
- package/documentation/upgrading.md +39 -0
- package/documentation/workflow-events.md +181 -0
- package/launcher-skill/openxiangda/SKILL.md +24 -0
- package/package.json +72 -9
- package/releases/2.0.0.json +50 -0
- package/skills/manifest.json +2 -2
- package/skills/openxiangda-v2/SKILL.md +64 -51
- package/skills/openxiangda-v2/agents/openai.yaml +2 -2
- package/skills/openxiangda-v2/references/administration.md +27 -0
- package/skills/openxiangda-v2/references/application-foundation.md +162 -0
- package/skills/openxiangda-v2/references/appspec.md +132 -47
- package/skills/openxiangda-v2/references/backend.md +101 -248
- package/skills/openxiangda-v2/references/cli.md +27 -0
- package/skills/openxiangda-v2/references/concepts.md +61 -0
- package/skills/openxiangda-v2/references/data-authz.md +36 -388
- package/skills/openxiangda-v2/references/delivery.md +110 -49
- package/skills/openxiangda-v2/references/development.md +32 -0
- package/skills/openxiangda-v2/references/field-components.md +236 -0
- package/skills/openxiangda-v2/references/frontend.md +254 -280
- package/skills/openxiangda-v2/references/getting-started.md +66 -0
- package/skills/openxiangda-v2/references/interaction-patterns.md +56 -0
- package/skills/openxiangda-v2/references/mcp.md +649 -0
- package/skills/openxiangda-v2/references/product-design.md +142 -0
- package/skills/openxiangda-v2/references/public-access.md +92 -84
- package/skills/openxiangda-v2/references/testing.md +45 -56
- package/skills/openxiangda-v2/references/upgrading.md +39 -0
- package/skills/openxiangda-v2/references/workflow-events.md +143 -266
- package/skills/openxiangda-v2/references/architecture.md +0 -9
- package/skills/openxiangda-v2/references/commands.md +0 -21
- package/skills/openxiangda-v2/references/discovery.md +0 -15
- package/skills/openxiangda-v2/references/workspace.md +0 -62
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# AppSpec:需求、设计与交付记录
|
|
2
|
+
|
|
3
|
+
AppSpec 是默认开发流程中的业务记录,保存在应用 Git 仓库。AI 负责整理需求、分析架构和性能、维护记录;产品经理主要说明目标与业务规则。当前总纲、实现声明、实际验收和平台部署各有自己的事实来源,不能互相替代。
|
|
4
|
+
|
|
5
|
+
## 资料结构
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
appspec/
|
|
9
|
+
app.md # 当前有效目标、规则、架构、页面、权限、容量
|
|
10
|
+
product/ # 来源、范围与 PRD
|
|
11
|
+
experience/ # 旅程、逐页交互
|
|
12
|
+
design/ # 视觉、权限、架构与原型引用
|
|
13
|
+
reviews/ # 实际确认与设计基线
|
|
14
|
+
capabilities/ # 复杂后再按业务能力拆分,不要求小应用创建
|
|
15
|
+
changes/active/ # 本轮需求、设计、任务、验收与交接
|
|
16
|
+
changes/history/ # 完成后的变更,按年保存
|
|
17
|
+
decisions/ # 需要长期引用的架构决定
|
|
18
|
+
verification/ # 绑定测试版本的业务验收报告
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
新应用按[产品设计](./product-design.md)完成本期详细材料和设计基线;既有变更只更新受影响范围,文案和无行为变化沿用有效基线。业务规则使用 `### REQ-*`,可观察验收使用 `#### AC-*`;ID 稳定,变更引用当前总纲或能力中的规则。声明和生成契约保存模型、字段与接口,AppSpec 不复制 Schema 全集。截图、请求轨迹等证据保留实际文件或 HTTPS 引用,不提交凭据和敏感业务数据。
|
|
22
|
+
|
|
23
|
+
## 从模糊需求到实现
|
|
24
|
+
|
|
25
|
+
1. 读取当前总纲、设计索引与相关稳定 ID,分析用户提供资料,区分事实、候选建议、实际确认、延期与冲突。
|
|
26
|
+
2. 主动帮助用户从真实任务发现模块,逐轮少量提问、建议与复述,已确认且未变的决定持续有效。
|
|
27
|
+
3. 完成本期产品、旅程、逐页交互、视觉/原型、权限和架构设计;按角色走查主任务与异常,维护容量预算与可证伪 AC。
|
|
28
|
+
4. ChangeSpec 的 documents 引用一份 review 设计文档;评审关联受评设计的传递引用闭包、实际确认来源和 baselineDigest。具体模板及范围规则见[产品设计](./product-design.md#templates)。
|
|
29
|
+
5. readyForImplementation 成立后制定实施计划,关联 REQ、设计、源码和 AC;本轮任务及原有交付章节完整后 readyForTest 成立。
|
|
30
|
+
6. 实施、检查、测试部署、真实角色验收、生产晋级后,更新持续有效规则、实际结果和交接,再归档。
|
|
31
|
+
|
|
32
|
+
`未确认问题` 下的 `- [ ]` 表示正式交付阻断项。非阻断假设另写说明。只有章节、一个 `passed` 标记或 AI 的判断,均不能证明业务验收实际发生。
|
|
33
|
+
|
|
34
|
+
## 命令与阶段边界
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pnpm openxiangda spec init
|
|
38
|
+
pnpm openxiangda spec new booking-window --title "限制可预约时段" --risk L2
|
|
39
|
+
pnpm openxiangda spec context booking-window --json
|
|
40
|
+
pnpm openxiangda spec check
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
已有工作区优先用 `spec new` 生成本地记录。访谈尚未创建应用时,可在 `appspec/changes/active/<变更ID>.md` 手工建草稿:front matter 使用 `schema: openxiangda.appspec/change/v1`、与文件名一致的 `id`、`title`、`status: draft`、`currentSpec: pending`、适用的 `risk`,以及 `documents: [实际评审ID]`。不必为整理设计先创建远端应用。
|
|
44
|
+
|
|
45
|
+
| 阶段或风险 | ChangeSpec 必需正文 |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| 设计阶段 | 为什么、需求依据、方案与影响、验收、性能与容量预算;引用详细权威材料并说明本轮影响 |
|
|
48
|
+
| 设计就绪后 | 补齐任务与实现;草稿不能冒充已可测试 |
|
|
49
|
+
| L2 / L3 | 另写数据与权限、回滚;引用权限和架构材料,说明适用范围或不适用理由 |
|
|
50
|
+
| L3 | 另写失败、并发与幂等、架构决策;需要长期决定时关联实际 ADR |
|
|
51
|
+
| 关闭前 | 验证与发布、交接,填写实际结果和剩余事项 |
|
|
52
|
+
|
|
53
|
+
`未确认问题` 单独保留阻断项,设计评审和实施任务按[开工顺序](./product-design.md#readiness)分步完成。章节名用于定位缺口,空标题、模板提示和未执行的验收计划均不是完成证据。
|
|
54
|
+
|
|
55
|
+
有且仅有一个活动变更时自动关联。多个活动变更或引用历史记录时,在本次 Git 提交说明中加入 `AppSpec: booking-window`。格式、无行为重构可引用已有记录,在提交说明写清不改变业务行为的依据,无需制造重复文档;新的行为变化仍要更新相应变更。
|
|
56
|
+
|
|
57
|
+
| 操作 | 实际要求 |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| dev、只读分析 | 可以研究和预览,不能把原型当作已完成交付 |
|
|
60
|
+
| 普通 check / check_app | 技术验证照常进行,需求与设计缺口作为单独诊断返回 |
|
|
61
|
+
| spec context | 返回 readyForImplementation、readyForTest、评审摘要与缺口;不自动确认 |
|
|
62
|
+
| spec check | 严格检查当前文档、设计基线、关联变更和测试发布前的完整性 |
|
|
63
|
+
| 测试 deploy / deploy_app | 总纲、设计、需求依据、性能预算、AC 计划完整;尚不要求线上业务验收报告 |
|
|
64
|
+
| 生产晋级 | 读取指定成功测试运行的同一制品,并核对绑定该版本的实际验收报告 |
|
|
65
|
+
| spec close | 当前长期规则已回写,“验证与发布”和“交接”有实际结论;未发布、取消和未覆盖项明确说明 |
|
|
66
|
+
|
|
67
|
+
发布前提交、推送并合入远端默认主分支。测试部署之后的验收报告是后续提交,生产仍复用原测试包,不因主线新增报告而重新构建。参见[发布与恢复](./delivery.md)。
|
|
68
|
+
|
|
69
|
+
## 测试版本的验收报告
|
|
70
|
+
|
|
71
|
+
按实际观察建立 `appspec/verification/<测试运行ID>.json`。以下仅展示格式,示例数值和结果不能作为真实证据;报告必须覆盖测试版本 AC 计划,失败和未测场景不能冒充通过。
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"schemaVersion": "openxiangda.business-verification/v1",
|
|
76
|
+
"appCode": "booking-app",
|
|
77
|
+
"changeId": "booking-window",
|
|
78
|
+
"sourceDeploymentId": "实际测试运行ID",
|
|
79
|
+
"packageDigest": "实际包的64位SHA256",
|
|
80
|
+
"recordedAt": "实际记录时间ISO8601",
|
|
81
|
+
"scenarios": [
|
|
82
|
+
{
|
|
83
|
+
"id": "AC-BOOKING-001",
|
|
84
|
+
"status": "passed",
|
|
85
|
+
"actor": "实际测试身份及角色",
|
|
86
|
+
"observation": "实际操作、数据条件和观察到的结果",
|
|
87
|
+
"evidence": [".openxiangda/evidence/booking-001.png"]
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
"performance": [
|
|
91
|
+
{
|
|
92
|
+
"scenario": "实际测量的页面或接口链路",
|
|
93
|
+
"sample": "测试环境、数据量、样本次数与测量口径",
|
|
94
|
+
"targetMs": 2000,
|
|
95
|
+
"observedMs": 450,
|
|
96
|
+
"evidence": [".openxiangda/evidence/performance.json"]
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
本地证据路径必须位于工作区内且文件存在;长期报告也可引用 HTTPS 证据。工具核对引用格式、版本绑定、场景覆盖与数值,不替代对截图、业务含义或外部证据真实性的评估。授权角色成功和禁止角色拒绝分别验证;支持范围之外的渠道在需求范围与未覆盖清单中明确说明。
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pnpm openxiangda spec verify --deployment <测试运行ID>
|
|
106
|
+
# 报告也可显式指定;生产晋级按运行 ID 读取默认路径
|
|
107
|
+
pnpm openxiangda spec verify --deployment <测试运行ID> --evidence appspec/verification/<测试运行ID>.json
|
|
108
|
+
pnpm openxiangda spec close booking-window --current-spec merged --summary "实际完成情况与剩余事项"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
MCP `appspec_verify` 读取同一报告与运行事实。`spec verify` 根据当前关联需求核对;生产晋级另外从测试源码提交读取原计划,因此主线后续需求不能冒充旧版本已测内容。不得伪造用户确认、测试身份、执行结果或部署成功。官方工具的记录门槛不代表平台所有直接接口都强制执行了同一业务流程。
|
|
112
|
+
|
|
113
|
+
## 新任务找回上下文
|
|
114
|
+
|
|
115
|
+
### 架构决定的编号与创建
|
|
116
|
+
|
|
117
|
+
需要长期引用的决定写入 `appspec/decisions/` 下的 Markdown。ADR 的 `id` 格式是 `ADR-` 加**恰好四位数字**,可选 `-` 分隔的大写字母或数字后缀,例如 `ADR-0001`、`ADR-0001-DATA-OWNER`;`ADR-001` 不合法。文件名建议与 ID 一致,引用使用元数据中的 ID。当前没有独立的 ADR 创建命令,可以手工创建,随后用 `spec context <ID>` 和 `spec check` 核对。
|
|
118
|
+
|
|
119
|
+
以下是 `appspec/decisions/ADR-0001.md` 的提议示例;它不表示已经确认或可以发布:
|
|
120
|
+
|
|
121
|
+
```markdown
|
|
122
|
+
---
|
|
123
|
+
schema: openxiangda.appspec/decision/v1
|
|
124
|
+
id: ADR-0001
|
|
125
|
+
title: 业务数据的权威来源
|
|
126
|
+
status: proposed
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
# 业务数据的权威来源
|
|
130
|
+
|
|
131
|
+
## 问题与方案
|
|
132
|
+
|
|
133
|
+
业务记录由平台 Data API 持有,应用按当前用户权限读取;前端不另建持久业务数据库。
|
|
134
|
+
|
|
135
|
+
## 影响与验证
|
|
136
|
+
|
|
137
|
+
关联查询使用平台字段来源,验收时分别核对允许与禁止角色的真实读取结果。
|
|
138
|
+
|
|
139
|
+
## 未确认问题
|
|
140
|
+
|
|
141
|
+
- [ ] 确认本期是否存在需要独立后端事务的业务不变量。
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
ADR 状态支持 `proposed`、`accepted`、`superseded`、`rejected`;按真实决定更新,不为通过检查直接填 `accepted`。可选元数据为 `date`、`deciders`、`supersedes`、`documents`;确认依据和方案取舍写正文。变更用 `decisions: [ADR-0001]` 关联,设计材料也可用 `documents: [ADR-0001]` 引用。修正已有编号时同步相关引用并保留 Git 历史,不删除旧决定来规避检查。
|
|
145
|
+
|
|
146
|
+
### 按 ID 读取
|
|
147
|
+
|
|
148
|
+
`context` / `workspace_context` 默认返回总纲、相关变更索引、阶段缺口和下一步。`spec context` / `appspec_context` 的 context v4 默认只返回总纲正文及有界索引,按稳定 ID 加载相关能力、变更、ADR 和 DES-* 设计正文及 documents 传递引用。product/experience/design/reviews 的单层 Markdown 也进入当前资料与原测试提交读取;非 Markdown 原型只引用不执行。当前资料最多 128 文件、2 MiB,正文上下文最多 256 KiB,超出时明确诊断。
|
|
149
|
+
|
|
150
|
+
历史与当前资料独立预算,每页 50 条,使用 `--history-offset 50` 或 MCP `historyOffset` 翻页。历史索引仅读取头部,稳定历史 ID 可直接读取页外正文;归档增加不会挤掉当前资料。索引读取上限为 256 个年份目录、10 万个记录名和 5 秒,达到预算给出提示,文件不会删除。`workspaceDigest` 对应当前资料与实时契约,分页不改变它;`selectionDigest` 对应选中的具体正文与契约。
|
|
151
|
+
|
|
152
|
+
当前仓库规格不等于生产已上线功能。环境使用哪个版本从平台读取;历史用于解释演进原因,后续实现优先遵循当前有效规则。旧 alpha 记录没有设计评审时不会自动升级成已确认;补齐真实设计和评审后重新测试发布。旧 2.0 应用升级后补齐实际记录,不导入 1.x SDD,也不自动生成虚假确认或验收。
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# NestJS 后端
|
|
2
|
+
|
|
3
|
+
默认模板只包含 Web 和共享契约。只有需要执行服务端业务动作时才增加 NestJS。记录列表、详情、新增、编辑和删除直接由浏览器调用平台 Data API,不在 controller 中重写一遍。
|
|
4
|
+
|
|
5
|
+
平台网关验证当前用户完整的应用角色并集,并把经平台重验的角色、capability 与可选 Perspective 交给 Nest SDK。业务 controller 使用生成的 operation 合同和 capability 装饰器;平台仍是身份与授权的唯一所有者。请求作用域 `OpenXiangdaDataApiService` 自动继承 Perspective 读取投影;绕过 Data API 的自定义读取才使用 `@CurrentPerspective()` 显式投影。应用代码不替换身份、不保存平台凭据,也不建立第二套用户或权限状态。
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm openxiangda dev
|
|
9
|
+
pnpm openxiangda check
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
在 `openxiangda.config.ts` 声明 `backend: { enabled: true }`,或添加需要执行应用代码的
|
|
13
|
+
operation、事件消费者、人员提供器,然后运行 `pnpm openxiangda check` 或 `pnpm dev`。
|
|
14
|
+
工具从当前版本的内置模板初始化后端源码并安装依赖;后续不会覆盖业务代码。
|
|
15
|
+
标准表单、流程定义/激活和平台待办通知使用平台运行时,不会隐式启用 Nest。
|
|
16
|
+
|
|
17
|
+
依赖安装失败会保留新源码并报告 `OPENXIANGDA_BACKEND_INSTALL_FAILED`;重试相同命令
|
|
18
|
+
即可继续。关闭 backend 不自动删除用户源码。仅删除已经确认不用的后端目录和其依赖。
|
|
19
|
+
本地 `/api` 经过 connected proxy 进入 Nest;发布态由同源应用网关转发。
|
|
20
|
+
|
|
21
|
+
| 需求 | 使用的 SDK | 权威边界 |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| 当前用户与角色并集 | `@CurrentUser()` | 网关验证结果,业务不管理凭据 |
|
|
24
|
+
| 当前用户范围的数据 | `OpenXiangdaDataApiService` | 平台行/字段权限和读取 Perspective |
|
|
25
|
+
| 已授权业务动作的跨模型读写 | `OpenXiangdaBusinessDataApiService` | 声明的 operation;平台保留发起人审计 |
|
|
26
|
+
| 原子写入与幂等回执 | `.transaction(idempotentTransaction(...))` | 同一平台事务,不读后再写 |
|
|
27
|
+
| 分派对象必须具有指定角色 | 事务 `role-member` 条件 | 具名动作声明允许核对的角色;平台核对有效成员与并发 |
|
|
28
|
+
| 托管文件 | Data SDK 的 `initiateFileUpload` / `completeFileUpload` / `copyManagedFile` | 平台文件归属和操作授权 |
|
|
29
|
+
| 标准流程 | `OpenXiangdaWorkflowService`;带业务提交用 `OpenXiangdaBusinessProcessService` | 平台命令 token、版本和回执 |
|
|
30
|
+
| 当前用户待办 | `OpenXiangdaTodoService` | 平台投影,不另建待办表 |
|
|
31
|
+
| 通知 | `OpenXiangdaBusinessNotificationService` | 平台收件人、通道、投递和幂等 |
|
|
32
|
+
| 域事件 | 事务 `emitEvent` / `@OpenXiangdaEventHandler` | 平台 outbox 与消费回执 |
|
|
33
|
+
| 请求和动作日志 | `OpenXiangdaLoggerService`、`OpenXiangdaPlatformError.request` | Nest 日志输出和平台请求关联 |
|
|
34
|
+
|
|
35
|
+
下方代码是接入片段,模型与角色需要在应用中显式声明。独立的完整示例由工具链维护者在新建应用中做打包验收。
|
|
36
|
+
|
|
37
|
+
自定义 operation 的 capability 必须先在 `authz.capabilities` 以
|
|
38
|
+
`kind: 'backend'` 声明,再由 operation 和允许调用它的角色共同引用。普通资源 CRUD
|
|
39
|
+
能力仍由编译器生成,不写入显式 capability catalog。
|
|
40
|
+
|
|
41
|
+
访客重复预约统一使用 `OpenXiangdaStandardOperations.createVisitorReservation`。
|
|
42
|
+
`duplicateMatch` 是字段代码到本次提交值的非空对象,不是字段名数组;它与 `data`
|
|
43
|
+
必须来自同一个不可变请求,并连同 `idempotencyKey` 一次提交给平台事务。应用不先查
|
|
44
|
+
重、不自行加锁、不在重试时重新生成业务时间。
|
|
45
|
+
|
|
46
|
+
只读前置条件使用 `record-exists` 或 `record-match`,它们不要求同记录 mutation,
|
|
47
|
+
但仍执行 read capability、字段权限与行级授权。需要与数据库当前时间比较时使用
|
|
48
|
+
`databaseNowAssertion('publishAt', 'lte')`;平台用一次 PostgreSQL transaction time
|
|
49
|
+
完成所有断言,并把该时间作为 `evaluatedAt` 存入幂等回执。相同幂等键重放不会重新
|
|
50
|
+
读取当前时间。不得把 `Date.now()`、SQL 表达式、时区偏移或调用方时钟塞入断言。
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
## 业务动作与普通查询 {#business-action}
|
|
54
|
+
|
|
55
|
+
`OpenXiangdaDataApiService` 按当前用户的普通资源、行和字段权限执行。具名业务动作使用 `OpenXiangdaBusinessDataApiService`:入口先检查该动作 capability,平台在精确应用和环境内以受信任后端执行,并保留发起人与动作审计。业务动作不能接受任意模型/字段/用户 ID 后不做业务校验;应用负责该动作的输入约束和业务不变量。
|
|
56
|
+
|
|
57
|
+
同一业务变更用一次受限事务表达。断言、派生计数、写入和事件保持原子性;遇到可重试响应时复用不可变 payload 和 idempotencyKey,不先读取可变状态再决定写入。
|
|
58
|
+
|
|
59
|
+
## 在分派事务中核对目标角色 {#role-member}
|
|
60
|
+
|
|
61
|
+
维修派单、指定审核人等规则不能只依赖页面筛选或先查成员再写入。先在对应
|
|
62
|
+
`backend.operations[]` 的 `platformAccess` 声明允许核对的应用角色:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
platformAccess: { roleAssertions: { roleCodes: ['technician'] } }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`technician` 必须存在于本应用 `authz.roles`,最多声明 20 个角色。应用管理员身份
|
|
69
|
+
不自动代表维修角色。人员候选可以使用已有且已委托管理范围的成员查询;这项声明
|
|
70
|
+
本身不授予成员管理或人员目录权限。
|
|
71
|
+
|
|
72
|
+
在 `OpenXiangdaBusinessDataApiService` 的同一次事务中表达业务状态与目标角色:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
await businessData.transaction({
|
|
76
|
+
schemaVersion: 'openxiangda.data-transaction-request/v2',
|
|
77
|
+
idempotencyKey: input.idempotencyKey,
|
|
78
|
+
guards: [
|
|
79
|
+
{ kind: 'role-member', userId: input.technicianId, roleCode: 'technician',
|
|
80
|
+
errorCode: 'OPENXIANGDA_ASSIGNEE_INVALID' },
|
|
81
|
+
{ kind: 'record-assert', resourceCode: 'service-orders', id: input.id,
|
|
82
|
+
lockKey: `service-order:${input.id}`, errorCode: 'OPENXIANGDA_ORDER_STATE_INVALID',
|
|
83
|
+
assertions: [{ kind: 'value', field: 'status', operator: 'eq', value: 'approved' }] },
|
|
84
|
+
],
|
|
85
|
+
operations: [{ operation: 'update', resourceCode: 'service-orders', id: input.id,
|
|
86
|
+
expectedRevision: input.revision, data: { assignedTo: input.technicianId, status: 'assigned' } }],
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
以上是接入片段;模型、字段、角色、动作 capability 和请求输入仍需在应用中声明。
|
|
91
|
+
角色条件只有 `kind/userId/roleCode/errorCode`,不接受环境、成员快照、调用者锁名或
|
|
92
|
+
调用者时间。所有 guard 合计最多 20 项。带业务写入的流程提交同样可以使用这一条件。
|
|
93
|
+
普通用户 Data SDK、应用凭据和事件处理器不能使用;伪造操作请求头不能获得授权。
|
|
94
|
+
|
|
95
|
+
平台在同一事务内核对当前租户、应用、环境和版本,以数据库取得的统一时间检查
|
|
96
|
+
显式成员是否生效、过期或已撤销,并核对授权投影就绪。条件不成立返回指定失败码,
|
|
97
|
+
无业务写入;没有声明返回 `OPENXIANGDA_ROLE_ASSERTION_NOT_DECLARED`。并发角色撤销、
|
|
98
|
+
投影或环境切换返回 `OPENXIANGDA_ROLE_ASSERTION_CONFLICT`,锁等待最多 1 秒,整笔回滚。
|
|
99
|
+
保留原请求和幂等键,根据当前业务状态决定是否重试。成功请求重放只返回已有结果;
|
|
100
|
+
同一幂等请求绑定原发起人和业务动作,换人或换动作不能复用该回执。
|
|
101
|
+
|
|
102
|
+
分派已接受后撤销角色,不会自动撤销历史分派;后续处理动作必须重新验证当前权限,
|
|
103
|
+
由管理员重新分派。此规则应写入 AppSpec,并实测撤销先发生和分派先发生两种顺序。
|
|
104
|
+
|
|
105
|
+
## 启动与依赖注入 {#bootstrap}
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import 'reflect-metadata';
|
|
109
|
+
import { bootstrapOpenXiangdaApplication } from 'openxiangda/nest';
|
|
110
|
+
import { AppModule } from './app.module.js';
|
|
111
|
+
await bootstrapOpenXiangdaApplication(AppModule);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
使用标准启动器保留原始请求体校验、代理信任和关闭处理。可注入依赖使用明确的 Nest 注入 token/装饰器,遵循生成后端的现有模式;不另建网关身份验证或自行转发授权 JSON。请求关联使用平台传入的 request ID。
|
|
115
|
+
|
|
116
|
+
## 通知与事件 {#notifications}
|
|
117
|
+
|
|
118
|
+
具名用户动作发送通知使用 `OpenXiangdaBusinessNotificationService.send()`,携带稳定 eventId、messageKey、sourceSequence 和 idempotencyKey。重放同一事件返回已有消息;同一 messageKey 的更高序列用于收敛状态。通知目标使用声明的 PC/移动路由代码及参数,不拼接环境域名或身份凭据。
|
|
119
|
+
|
|
120
|
+
签名事件处理器使用 `sendFromEvent()`,在声明中指定事件 data 内的收件人与文案路径,由平台验证不可变事件后解析。普通业务动作不需要平台通知管理权限。需要高级钉钉卡片时才使用已授权的管理服务和已启用通道,不能把它设为普通审批的默认依赖。
|
|
121
|
+
|
|
122
|
+
通知协议常量也从同一个公开入口导入:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import {
|
|
126
|
+
OpenXiangdaBusinessNotificationService,
|
|
127
|
+
OPENXIANGDA_NOTIFICATION_BUSINESS_SEND_V2,
|
|
128
|
+
OPENXIANGDA_NOTIFICATION_EVENT_SEND_V2,
|
|
129
|
+
} from 'openxiangda/nest';
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
用户动作 send 的 schemaVersion 使用 OPENXIANGDA_NOTIFICATION_BUSINESS_SEND_V2;事件处理 sendFromEvent 使用 OPENXIANGDA_NOTIFICATION_EVENT_SEND_V2。二者的调用上下文和收件人来源不同,不能混用。
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# 核心架构
|
|
2
|
+
|
|
3
|
+
```mermaid
|
|
4
|
+
flowchart LR
|
|
5
|
+
Repo["应用 Git 仓库"] --> CI["项目 CLI / MCP"]
|
|
6
|
+
CI --> Package["不可变 AppPackage"]
|
|
7
|
+
Package --> Control["平台控制面"]
|
|
8
|
+
Control --> Deploy["DeploymentRun"]
|
|
9
|
+
Deploy --> Web["前端静态包"]
|
|
10
|
+
Deploy --> Backend["按需启用的 NestJS 容器"]
|
|
11
|
+
Deploy --> Config["Data/AuthZ/Workflow/Event 配置版本"]
|
|
12
|
+
Backend --> Data["统一 Data API"]
|
|
13
|
+
Backend --> Kernel["Workflow Kernel v2"]
|
|
14
|
+
Backend --> Events["事件投递服务"]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 工程边界
|
|
18
|
+
|
|
19
|
+
- Git 仓库是应用源码与声明的事实来源。
|
|
20
|
+
- AppPackage 是交付边界,包含前端摘要、后端镜像摘要、配置包摘要和契约版本。
|
|
21
|
+
- 平台是运行状态的事实来源,持久保存应用版本、部署运行、检查点与环境激活状态。
|
|
22
|
+
- AI、CLI、MCP 都是控制面客户端,不负责持有发布状态。
|
|
23
|
+
|
|
24
|
+
## 运行档位
|
|
25
|
+
|
|
26
|
+
纯 CRUD 和标准审批无需应用后端。需要后端时使用平台可控的运行方式:每应用独立容器,共享 Kubernetes 集群、节点池、网关和可观测基础设施。后续可以用资源配额形成共享档与独享档,但不建设多应用共用 Node 进程。
|
|
27
|
+
|
|
28
|
+
## 数据边界
|
|
29
|
+
|
|
30
|
+
首期不为应用创建独立数据库。业务后端通过统一 Data API 访问平台数据;Data API 提供资源化查询、字段策略、行级授权、并发修订和受限事务批处理。这样保留统一治理,又不限制应用后端表达业务逻辑。
|
|
31
|
+
|
|
32
|
+
应用后端声明具名 Operation 时,不应重新手写用户、部门、资源引用和文件字段协议。`openxiangda/config` 提供 `resourceRecordSchema`、`schemaRef`、`composeJsonSchema` 和 `composeAppOperationSchemas`:它们从同一 Resource declaration 和公共 `FIELD_VALUE_SCHEMAS` 投影请求/响应 JSON Schema,只允许有界的本地 `$defs`/`$ref`,不会改变 Data API、权限或业务事务 owner。
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import {
|
|
36
|
+
composeAppOperationSchemas,
|
|
37
|
+
resourceRecordSchema,
|
|
38
|
+
schemaRef,
|
|
39
|
+
} from 'openxiangda/config';
|
|
40
|
+
|
|
41
|
+
const schemas = composeAppOperationSchemas({
|
|
42
|
+
request: {
|
|
43
|
+
type: 'object',
|
|
44
|
+
additionalProperties: false,
|
|
45
|
+
required: ['record'],
|
|
46
|
+
properties: { record: schemaRef('InstrumentRecord') },
|
|
47
|
+
},
|
|
48
|
+
response: schemaRef('InstrumentRecord'),
|
|
49
|
+
definitions: {
|
|
50
|
+
InstrumentRecord: resourceRecordSchema(instruments, {
|
|
51
|
+
fields: ['name', 'owner'],
|
|
52
|
+
}),
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## 版本列车
|
|
58
|
+
|
|
59
|
+
OpenXiangda 2.0 使用兼容版本列车,而不是要求所有 npm 包共享同一个版本号。各包按职责独立递增;应用只直接安装精确版本的 `openxiangda` 根包并提交锁文件,内部物理依赖由根包确定,不能使用范围或 `latest`。AppPackage 记录 AppPackage、configuration bundle、contract bundle 和 compiler contract 的原子兼容四元组;平台通过唯一的 `capabilities.configurationCompatibility` 契约声明完整可接受组合、验证端点与 validator 能力版本。CLI 必须把真实生成的 configuration/contract bundle 交给目标平台只读预检,并在应用生产构建、后端镜像构建和制品上传前拒绝不兼容组合;平台部署准备阶段继续权威复验,不允许删字段或向下协商。
|
|
60
|
+
|
|
61
|
+
AppPackage 的 `compatibility.requiredPlatformCapabilities` 也是 compiler 输出:每项固定包含 `code`、`contractVersion` 和只覆盖该能力相关规范化声明的 `usageDigest`。平台 `features[code]` 必须处于 `available` 且 `contractVersion` 精确相等;`preview`、缺失或版本不同都不能部署。应用配置没有 `platform.requiredCapabilities`,构建 API 也没有追加入口;不得手改 AppPackage 或用字符串能力名绕过 compiler。摘要不包含运行期业务数据或 secret 值,平台部署准备仍须根据原始 config/contract bytes 权威重算。CLI、MCP、Skills 和文档随相关包变更发布,不因无关包升级而强制全量重发。
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Data API 与权限
|
|
2
|
+
|
|
3
|
+
授权由四层组成:页面/操作 capability、行谓词、字段 read,以及字段 create/update。前端只消费平台返回的最终访问结果来隐藏按钮、只读输入和剔除 payload;平台每次请求重新执行权威校验。
|
|
4
|
+
|
|
5
|
+
以下仅以仪器管理应用举例,不是平台默认模型或角色。该示例的行规则是:学校管理员不受行谓词限制;学院管理员按记录 `collegeId` 匹配;仪器管理员按 `instrumentAdminIds` 包含当前用户匹配。不要增加影子范围字段。
|
|
6
|
+
|
|
7
|
+
`collegeId` 是应用 `colleges` Native Resource 的记录 UUID。学院 scope dimension 通过
|
|
8
|
+
`valueSource.kind=native_resource` 绑定同一资源,选择器只展示平台按当前 membership 与
|
|
9
|
+
create/update 闭包返回的值。人员和部门保存平台目录真实 ID;部门不等于学院,也不能作为
|
|
10
|
+
学院范围的隐式来源。
|
|
11
|
+
|
|
12
|
+
字段策略支持 `read`、`create`、`update` 和 `mask`。显式空数组拒绝,能力数组采用 all-of。无权更新字段不仅 disabled,还必须从更新 payload 删除。
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm openxiangda check
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
角色成员、维度授权和平台管理员由平台管理面维护,不属于应用开发 CLI。
|
|
19
|
+
|
|
20
|
+
自定义 PC/移动页面需要维护当前应用角色时,使用
|
|
21
|
+
`openxiangda/core` 的 `loadRoleManagementCatalog`、
|
|
22
|
+
`listRoleMemberships`、`searchRoleManagementUsers`、成员 mutation 与
|
|
23
|
+
role-management-grant mutation。应用/平台超级管理员可以把全部角色或明确的
|
|
24
|
+
目标角色集合委托给一个业务角色;普通业务管理者只有同时具备
|
|
25
|
+
`management.delegate` 时,才能把自己已有的目标角色和动作子集继续委托。
|
|
26
|
+
平台按当前用户角色并集重算,接口不接受 actor、tenant、active role 或
|
|
27
|
+
impersonation token。mutation 必须携带 UUID `operationId`、`reason`,更新/撤销还必须
|
|
28
|
+
携带最新 `expectedRevision`;409 后重新加载,不能猜 revision。使用前读取当前角色管理目录,详见[管理入口](./administration.md)。
|
|
29
|
+
|
|
30
|
+
匿名外部访问不属于 RBAC 角色或 current-user 行策略。公开表单、续填、附件、重复校验和同一
|
|
31
|
+
浏览器的本人记录访问只通过[`frontend.publicAccess` 专用合同](./public-access.md)开放;平台继续在
|
|
32
|
+
专用端点和 PostgreSQL/RLS 中强制匿名主体、字段、策略及提交回执边界。
|
|
33
|
+
|
|
34
|
+
数值边界直接声明在字段上,`min`/`max` 为闭区间,并且只允许用于
|
|
35
|
+
`number.integer` 和 `number.decimal`。跨字段约束声明在资源的
|
|
36
|
+
`invariants` 中;每条约束只能比较同一记录的两个已声明字段,最多 20 条,
|
|
37
|
+
由平台在 create/update/increment 的最终候选记录上统一执行。
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
{
|
|
41
|
+
code: 'sessions',
|
|
42
|
+
name: '场次',
|
|
43
|
+
fields: [
|
|
44
|
+
{ code: 'startAt', type: 'datetime', label: '开始', required: true },
|
|
45
|
+
{ code: 'endAt', type: 'datetime', label: '结束', required: true },
|
|
46
|
+
{ code: 'capacity', type: 'number.integer', label: '容量', min: 0 },
|
|
47
|
+
{ code: 'occupied', type: 'number.integer', label: '已占用', min: 0 },
|
|
48
|
+
],
|
|
49
|
+
invariants: [
|
|
50
|
+
{ code: 'time-order', expression: { leftField: 'startAt', operator: 'lt', rightField: 'endAt' } },
|
|
51
|
+
{ code: 'capacity-not-exceeded', expression: { leftField: 'capacity', operator: 'gte', rightField: 'occupied' } },
|
|
52
|
+
],
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`date-range` 与 `datetime-range` 必须显式声明 `rangeBoundary`,取值为 closed 或 half-open。选择半开区间 `[start, end)` 时相邻时间段不冲突;闭区间端点相接可能重叠。
|
|
57
|
+
|
|
58
|
+
业务 uuid 字段与系统 id 不同:可选业务 UUID 省略时为空,必填字段需调用方提供合法值,平台不会替业务 UUID 自动生成默认值。
|
|
59
|
+
|
|
60
|
+
业务分派需要目标人员具有指定角色时,使用[事务中的角色条件](./backend.md#role-member),
|
|
61
|
+
由平台在写入事务中核对当前有效成员。候选查询、页面隐藏、应用管理员身份和历史
|
|
62
|
+
角色列表都不能替代这一规则,也不应在应用中复制一份权限状态。
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# 部署、生产晋级与恢复
|
|
2
|
+
|
|
3
|
+
应用开发者从工作区执行 `pnpm openxiangda`。平台负责应用版本、运行状态和恢复决定。工具链自身的 npm 发布由平台维护者负责,应用项目无需复制发包脚本或平台验证矩阵。
|
|
4
|
+
|
|
5
|
+
## 测试部署
|
|
6
|
+
|
|
7
|
+
发布前,先将本轮源码、生成契约及必要记录合入并推送仓库的远端默认主分支,然后从干净且同步的主分支工作区发布。工具从 origin 的远端 HEAD 识别主分支,不把任务分支的 upstream 当作主线。未提交、未推送、未合并或落后主线的问题会在构建和上传前返回;工具不会自动合并分支或覆盖其他会话的改动。
|
|
8
|
+
|
|
9
|
+
开发开始时先同步主线并读取项目现状,开发完成包括提交、推送与主线整合。每个工作区保持一个写者;需要并行时使用独立目录并明确各任务范围。日常 dev/check 仍可验证未提交源码。没有 Git 远端的项目应先建立并绑定仓库再发布。
|
|
10
|
+
|
|
11
|
+
准备部署时直接执行 deploy,它已经包含兼容性预检、生成、检查、测试和构建。只想检查代码时使用 [check](./testing.md),无需在 deploy 前重复运行全套检查。
|
|
12
|
+
|
|
13
|
+
测试发布还会核对 [AppSpec](./appspec.md) 的需求依据、架构、权限、性能预算和验收计划。缺失时给出具体记录位置,先补实际设计;首次测试部署不要求预先完成线上业务验收。
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm openxiangda deploy --dry-run --json
|
|
17
|
+
pnpm openxiangda deploy
|
|
18
|
+
pnpm openxiangda status --json
|
|
19
|
+
pnpm openxiangda logs <deployment-id> --json
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
默认目标为 `test`,平台内部标识为 `preproduction`。只读预览不生成构建产物、不上传制品、不提交 DeploymentRun;因此预览成功不能证明代码已通过检查。正式检查使用本地完整校验,再通过目标平台的 `configurationCompatibility` 核对同源规则、密钥、已有物理模型和登录提供方等只读条件;失败时停止后续步骤。只有启用了自定义 Nest 后端的应用才需要构建后端镜像及对应 Docker 环境。
|
|
23
|
+
|
|
24
|
+
生成的不可变 AppVersion 绑定前端、可选后端、配置契约和制品摘要。默认提交后持续跟踪同一运行,直到平台成功、失败或取消,最多观察 15 分钟。`--no-wait` 只提交,适用于已有状态跟踪器的自动化;此时返回运行 ID 不代表部署完成。
|
|
25
|
+
|
|
26
|
+
构建、上传及平台执行都会显示当前阶段和耗时,长步骤每 10 秒反馈一次。平台的准备、部署、切换和健康检查状态来自原运行。观察超时或连接中断不会取消部署或重建候选,使用下面的命令继续跟踪:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pnpm openxiangda status <deployment-id> --watch
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
网络响应不确定时先查询原运行,不凭本地输出创建重复部署。平台部署成功后,仍需执行真实角色的业务验收。
|
|
33
|
+
|
|
34
|
+
相同源码候选重试时,工具会重新核对本地验证证据、封存清单和制品字节,复用仍有效的构建结果及后端镜像;已上传内容按摘要查询并复用。只有环境条件改变时不需要重建源码制品。输出损坏、输入变化或缓存缺失时自动回到正式检查和构建。缓存位于 `.openxiangda/build/`,不是新的部署状态源;提交响应不确定时使用原候选和幂等键,已有失败运行按其 recovery 恢复。
|
|
35
|
+
|
|
36
|
+
## 测试环境验收
|
|
37
|
+
|
|
38
|
+
至少记录应用版本、目标环境、真实角色、复现数据、预期和实际结果。按改动范围检查页面、权限、业务规则和失败路径;详见[校验与验收](./testing.md)。
|
|
39
|
+
|
|
40
|
+
| 证据 | 能说明什么 |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| 本地 check 成功 | 本次声明兼容,检查、测试和构建通过 |
|
|
43
|
+
| 包密封完成 | 存在可识别的不可变候选版本 |
|
|
44
|
+
| DeploymentRun 成功 | 平台完成该版本的部署流程 |
|
|
45
|
+
| 真实角色的页面与业务操作通过 | 对应场景在目标环境可用 |
|
|
46
|
+
| 生产晋级成功并回读 | 生产使用指定测试版本;仍需核对实际入口与关键业务 |
|
|
47
|
+
|
|
48
|
+
构建成功、提交成功和真实业务验收是不同证据,报告时分别给出实际状态。
|
|
49
|
+
|
|
50
|
+
## 生产晋级
|
|
51
|
+
|
|
52
|
+
生产必须复用已成功部署到测试环境的同一版本,不能从当前源码直接重建:
|
|
53
|
+
|
|
54
|
+
先按真实操作保存 `appspec/verification/<测试运行ID>.json` 并提交、推送到主线。晋级会从测试源码提交读取原验收计划,核对报告的运行 ID、包摘要、AC 场景与性能证据;主线后来的需求不改变已测范围。
|
|
55
|
+
|
|
56
|
+
该版本的源码提交必须仍包含在权威远端主分支中。主分支后来有新提交,不会改变本次晋级的制品。若任务分支采用 squash/rebase 合并,应在最终主线提交上重新冻结并验证测试候选,不能继续晋级合并前的提交。
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pnpm openxiangda deploy --environment production --from <test-deployment-id> --dry-run --json
|
|
60
|
+
pnpm openxiangda deploy --environment production --from <test-deployment-id>
|
|
61
|
+
pnpm openxiangda status --json
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
预览会精确读取指定测试运行的封存配置并核对生产密钥、模型和登录条件,返回源运行、版本与摘要。主线后来变化或版本较旧,不会使预检改用当前源码或最近版本列表。测试运行失败、版本缺失或条件不符时直接失败。平台在真正晋级时再次权威校验。生产参数不接受测试环境的 `environmentId` 或 `idempotencyKey`。已有生产发布授权时可继续执行;授权不明确时先准备版本、预览及验收证据,再确认具体发布对象。
|
|
65
|
+
|
|
66
|
+
## 失败、重试与回滚
|
|
67
|
+
|
|
68
|
+
`logs` 返回首个失败 `rootFailure`、最近失败 `latestFailure`、候选状态、尝试账本与 `recovery`。无失败时对应字段为 null。按平台给出的 `recovery.nextCommand` 处理;只在 `recovery.cancelAllowed` 为真时取消。已激活的运行不能用 cancel 撤销。
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pnpm openxiangda retry <deployment-id>
|
|
72
|
+
pnpm openxiangda cancel <deployment-id>
|
|
73
|
+
pnpm openxiangda rollback --to <app-version-id>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
环境版本回滚不保证撤销数据库业务写入;数据修复需要单独计划与验证。暂停与恢复默认作用于测试环境;生产必须显式选择:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pnpm openxiangda stop
|
|
80
|
+
pnpm openxiangda start
|
|
81
|
+
pnpm openxiangda stop --environment production
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
stop 保留数据与配置,start 从当前不可变版本恢复。不要把暂停、取消、回滚当作同一种操作。
|
|
85
|
+
|
|
86
|
+
## 自动化与错误定位
|
|
87
|
+
|
|
88
|
+
CLI 的 `--json` 输出单个 `openxiangda.cli-result/v2` 对象;失败包含 code、message、retryable、remediation、nextCommand,以及适用的 pointer/details。自动化依据 code 和结构化字段决策,不解析中文描述。
|
|
89
|
+
|
|
90
|
+
`check`、`deploy` 和持续状态观察的结果带 `data.execution`,包含本次操作 ID、总耗时及各阶段状态和耗时。阶段进度写到 stderr,保持 `--json` 的 stdout 可解析;`--json-events` 则通过 `command.status` 返回同源结构化进度。MCP 客户端提供 `progressToken` 时收到标准进度通知;不订阅通知仍能从最终结果读取阶段摘要。MCP `deploy_app.wait` 默认 true,`deployment_status.watch` 可继续观察原运行。
|
|
91
|
+
|
|
92
|
+
兼容性错误会列出当前工具链与目标平台的版本、能力和契约要求。按定位修复声明或升级目标平台,不删除真实业务要求、改写摘要或绕过权限来让预检通过。应用所需能力由规范化声明派生,应用不能手写一份能力列表冒充平台支持。
|
|
93
|
+
|
|
94
|
+
`OPENXIANGDA_CONFIGURATION_VALIDATOR_MISMATCH` 表示工具链与平台的校验实现不配套,应按发布说明升级对应版本;它会在构建、镜像推送和制品上传前出现。模型类型不能原地替换时,按提示设计新字段及数据转换;必需密钥缺失时配置目标环境后继续,不修改源码伪装问题已解决。
|
|
95
|
+
|
|
96
|
+
MCP 的 check_app、deployment_plan、deploy_app 使用与 CLI 相同的环境与生产晋级参数规则。完整参数以[CLI](./reference/cli.md)与[MCP](./reference/mcp.md)为准。
|
|
97
|
+
|
|
98
|
+
## 构建前运行配额
|
|
99
|
+
|
|
100
|
+
`deploy --dry-run`(MCP `deployment_plan`)会只读查询目标 TEST 的运行配额,输出 `runtimeCapacity` 的核验时间、所需增量、各配额剩余量和缺口。`sufficient: false` 表示当前不足;`null` 表示无需新增或未核验,必须结合 `basis` 与 `capacity.checked` 阅读。专用命名空间未检查不能当成资源充足。
|
|
101
|
+
|
|
102
|
+
正式 deploy 在检查脚本和镜像构建前预检;平台缺少配套能力或无法核验时明确停止。配额快照不预留资源,实际执行再次检查。已有可验证密封候选会携带摘要和幂等键,平台识别 `existing-run` 时返回原运行,不把它当作新副本;观察或恢复原运行使用 status/retry。不要为绕过配额创建新包或切换目标环境。
|
|
103
|
+
|
|
104
|
+
## TEST 单副本维护替换
|
|
105
|
+
|
|
106
|
+
平台配额只允许一个后端副本时,可显式选择维护替换。它会停止当前 TEST 后端,期间应用不可用;成功后激活新版本,失败时由原 DeploymentRun 恢复旧后端。恢复尚未完成时继续占用原运行,status/logs 显示恢复阶段与首个失败,不允许用新部署或取消跳过恢复。
|
|
107
|
+
|
|
108
|
+
先运行 `openxiangda deploy --environment test --strategy maintenance-replace --dry-run --json` 查看前驱版本、Head revision 和停止后的容量估算,再使用相同参数去掉 `--dry-run` 提交。计划不预留资源。只有已存在、身份匹配的单副本 TEST 后端才可使用;前端应用、新应用和 production 不支持。默认仍为 rolling,不会因配额不足自动停止实例。
|
|
109
|
+
|
|
110
|
+
策略属于部署幂等请求。默认维护幂等键含策略,显式幂等键不能在不同策略之间复用。已有运行通过 status/retry 恢复;持续恢复中的运行保持 preparing/maintenance-recovery-required,平台会重试恢复,恢复失败时保留原运行与错误。
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# 需求与开发流程
|
|
2
|
+
|
|
3
|
+
先确认用户要完成的任务,再选择数据模型、页面和权限。使用项目锁定的 `pnpm openxiangda`,读取 `context --json` 与相关专题。现有项目的代码和实时契约优先于其他项目的样例。
|
|
4
|
+
|
|
5
|
+
## 新应用先完成设计基线
|
|
6
|
+
|
|
7
|
+
从模糊想法开始时,按[对话发现与产品设计](./product-design.md)分析已有资料、提出可解释的模块建议,用少量自然语言问题持续沟通确认。完整首发范围的 PRD、旅程、页面交互、原型、权限和架构设计齐备后,再制定实施计划和编写业务实现。用户已给出完整材料时先核对矛盾和遗漏,不重复访谈;已有确认持续有效。
|
|
8
|
+
|
|
9
|
+
## 根据任务决定工作量 {#risk}
|
|
10
|
+
|
|
11
|
+
| 变化 | 需要明确的内容 | 验证 |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| 格式、无行为重构 | 保留现有行为,无需创建需求记录 | 受影响静态检查和现有测试 |
|
|
14
|
+
| 文案、字段展示、局部规则 | 业务含义、影响页面和预期结果 | 对应数据和交互 |
|
|
15
|
+
| 跨模型、权限、状态变化 | 用户角色、正反场景、数据和恢复边界 | 真实角色、API 和浏览器 |
|
|
16
|
+
| 身份、迁移、并发、外部副作用 | 所有者、失败与幂等、资源边界、回滚和架构决定 | 所涉及契约的专项验证 |
|
|
17
|
+
|
|
18
|
+
技术命名、可逆布局等在已有要求内决定。新的业务含义、权限扩大或尚未授权的外部操作需要用户决定;已经明确授权的范围不重复询问。用户只要求分析时,不自动创建应用或发布。
|
|
19
|
+
|
|
20
|
+
## 选择平台能力 {#capabilities}
|
|
21
|
+
|
|
22
|
+
- 普通数据管理:通过 `defineDataModel`、`defineApplicationModule` 和显式 CRUD 视图声明;模型不自动生成菜单或写权限。
|
|
23
|
+
- PC/移动页面:先复用平台组件和标准页面,再使用受支持的页面、插槽与导航扩展。详见[前端](./frontend.md)。
|
|
24
|
+
- 无平台账号的外部表单:使用[匿名公开访问](./public-access.md),不用普通 RBAC 角色冒充匿名主体。
|
|
25
|
+
- 标准审批、待办与通知:按需声明平台能力,见[工作流](./workflow-events.md)。
|
|
26
|
+
- 真实事务或外部集成:使用[按需后端](./backend.md),不为每张表重写 CRUD 控制器。
|
|
27
|
+
|
|
28
|
+
## 实施与交接 {#iteration}
|
|
29
|
+
|
|
30
|
+
开发使用 `pnpm openxiangda dev`,过程中运行必要的聚焦测试。交接前按[检查与验收](./testing.md)验证;授权发布后按[交付](./delivery.md)部署。失败保留错误码、位置和原始候选,依据平台恢复指令继续。
|
|
31
|
+
|
|
32
|
+
[AppSpec](./appspec.md)保存业务意图、设计与交付记录,不复制字段 Schema、生成契约和部署状态。新应用维护具体设计和评审,复杂度随业务展开;既有小变更沿用有效设计,仅修订受影响记录,无行为变化可引用已有记录。每轮先读取当前规则、澄清业务、评估架构、权限和性能,随后实施与验证,发布后更新当前规格及交接。测试部署前需要设计和验收计划,生产晋级前需要绑定测试运行及包摘要的实际验收报告。
|