openxiangda-skill-kit 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 +2 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -19
- package/dist/index.js.map +1 -1
- package/dist/workspace-guidance.d.ts +13 -0
- package/dist/workspace-guidance.d.ts.map +1 -0
- package/dist/workspace-guidance.js +67 -0
- package/dist/workspace-guidance.js.map +1 -0
- package/package.json +12 -3
- package/skills/manifest.json +2 -2
- package/skills/openxiangda-v2/SKILL.md +63 -46
- 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 -237
- 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 -239
- package/skills/openxiangda-v2/references/delivery.md +110 -42
- 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 +269 -101
- 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 +167 -0
- package/skills/openxiangda-v2/references/testing.md +45 -48
- package/skills/openxiangda-v2/references/upgrading.md +39 -0
- package/skills/openxiangda-v2/references/workflow-events.md +152 -138
- package/skills/openxiangda-v2/references/architecture.md +0 -7
- 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 -25
|
@@ -1,167 +1,181 @@
|
|
|
1
|
-
# Workflow
|
|
1
|
+
# Workflow 与 Notification Hub 2.0 边界
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
and [Testing](testing.md) before enabling this optional layer.
|
|
3
|
+
标准 Workflow 与 Notification Hub 已作为 OpenXiangda 2.0 可选平台模块重新开放。它们不属于默认 CRUD 模板,也不兼容或复用 1.x 工作流、消息中心、模板、卡片、回调、表和 API。
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
## 标准详情与当前用户入口
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
普通记录、流程记录、任务和实例复用同一详情框架。流程详情提供申请内容、审批历史和变更记录三个标签页;管理员在当前抽屉或页面中切换到普通表单编辑,直接保存并自动留下变更记录,审批结果保持不变。PC 子表在表格内编辑,父表提交时统一校验。
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
- Workflow Kernel v2 owns definitions, instances, tasks, participants, commands, transitions and audit facts.
|
|
12
|
-
- Application Events v2 owns durable facts and delivery.
|
|
13
|
-
- Notification Hub v2 owns templates, rules, logical messages, channel delivery, callbacks and message operations.
|
|
14
|
-
- Named Action business notifications use `OpenXiangdaBusinessNotificationService` and the platform-owned `application.informational.standard` template. App Gateway authorizes the current user once; Notification Hub revalidates the action proof, sends as the application principal, and retains initiating user/action audit. Ordinary users never need `app:notification2:send`.
|
|
15
|
-
- Native Identity/AuthZ v2 owns the current user and the union of that user's current application roles. Perspective is read-only and never changes workflow participation or action authorization.
|
|
16
|
-
- Never import, query, migrate or call 1.x workflow/message code, tables, APIs, queues, templates or callbacks.
|
|
9
|
+
待办中心通过 Workflow 查询 `pending`、`handled`、`created`、`cc` 四种视图;消息中心默认向 Notification Hub 查询 `view=all`,沿用应用声明的渲染扩展。各入口按服务端 `detailNavigation` 打开详情,页面不自行拼接人员范围。
|
|
17
10
|
|
|
18
|
-
|
|
11
|
+
抄送由动态 Surface 提供 `cc` 操作,使用 `user_select` 多选组件收集 1 至 20 位人员。任务 Surface 可以正式包含实例抄送命令;前端按 `operation.execute.href` 和该 Surface 的 token 提交,不另造任务命令或 token。公共事件为 `openxiangda.workflow.instance.cc_added.v2`。
|
|
19
12
|
|
|
20
|
-
|
|
13
|
+
## 能力 owner
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
localized definition title, so applications do not maintain code-to-title
|
|
28
|
-
maps. A standalone page receives all durable business context through its
|
|
29
|
-
typed save handler and URL/search contract; it must never depend on transient
|
|
30
|
-
router location state. Work center, task and instance pages remain reachable
|
|
31
|
-
without becoming launch menu entries. Bind the generated metadata with
|
|
32
|
-
`defineWorkflowLaunchContributions(workflowDefinitions, handlers)`; handlers
|
|
33
|
-
only persist the durable business revision, while generated code keeps title
|
|
34
|
-
and launch mode authoritative.
|
|
15
|
+
- Workflow Kernel v2 唯一拥有定义、实例、任务、参与人、命令、流转、委托、加签和流程审计。
|
|
16
|
+
- Application Events v2 唯一拥有已提交事实的 journal/outbox、顺序、投递和回执。
|
|
17
|
+
- Notification Hub v2 唯一拥有逻辑消息、模板、规则、渠道路由、渲染、发送、更新、关闭、外部绑定、动作收据和消息运维。
|
|
18
|
+
- Data API/App API 唯一拥有业务记录;Workflow 只保存 `dataRef` 和 revision-bound facts,消息只保存允许展示的安全投影。
|
|
19
|
+
- Native Identity/AuthZ v2 唯一拥有当前用户、当前应用角色并集和数据范围;Perspective 只影响读取展示,不改变 Workflow 的发起、任务与操作授权。
|
|
35
20
|
|
|
36
|
-
|
|
21
|
+
Workflow 发起只接受 `{ resourceCode, id }` 形式的 `dataRef`,并要求独立的
|
|
22
|
+
正整数 `dataRevision`。definition 的 `inputSchema` 根对象必须显式
|
|
23
|
+
`additionalProperties: false`,未声明的 facts/answers 直接拒绝。Provider
|
|
24
|
+
回调只接受带完整业务/数据/definition/binding/fact digest 的
|
|
25
|
+
`openxiangda.workflow-assignee-request/v2.1`。
|
|
37
26
|
|
|
38
|
-
|
|
27
|
+
## 标准工作流范围
|
|
39
28
|
|
|
40
|
-
|
|
29
|
+
首期只支持 `approval`、`condition`、`end`,以及 `single`、`any`、`all`、`sequence` 审批模式。标准操作为提交、同意、拒绝、退回、重新提交、转交、委托、前/后加签、撤回、管理员改派、管理员终止和不改变流程状态的催办。
|
|
41
30
|
|
|
42
|
-
|
|
43
|
-
2. Bind prepare to the saved revision and all submission answers.
|
|
44
|
-
3. Resolve required organization/approver choices.
|
|
45
|
-
4. Start with a stable idempotency key distinct from the draft-save key.
|
|
46
|
-
5. Use the Surface revision/concurrency token for every command.
|
|
31
|
+
复杂业务状态机继续放在应用领域服务。不要把任意 JavaScript、Service Task、BPMN、通用长事务或业务记录复制进 Workflow。
|
|
47
32
|
|
|
48
|
-
|
|
33
|
+
所有页面和消息动作必须来自后端 Workflow Surface 的 `operations[]`。前端、模板和渠道 Adapter 不自行推断操作权限。
|
|
34
|
+
Surface 同时签发短期、一次性的 `commandToken`,绑定当前用户/会话、应用环境
|
|
35
|
+
Head、实例/任务版本、允许的命令集合与 CSRF。命令请求只提交
|
|
36
|
+
`commandToken + idempotencyKey + input`;旧的 caller-authored
|
|
37
|
+
`expectedTaskVersion`/`expectedInstanceVersion` 不再是合同。冲突必须刷新 Surface,
|
|
38
|
+
不得自动重放旧意图。
|
|
49
39
|
|
|
50
|
-
##
|
|
40
|
+
## 事实和消息投影
|
|
51
41
|
|
|
52
|
-
|
|
42
|
+
Workflow 在同一 PostgreSQL 事务中提交状态、fact 和 outbox。每个实例使用严格单调的 `instanceSequence`,每位审批人拥有独立 participant 生命周期。
|
|
53
43
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
-
|
|
57
|
-
|
|
58
|
-
- channel priority/fallback;
|
|
59
|
-
- default detail target;
|
|
60
|
-
- whether to show Workflow Surface actions;
|
|
61
|
-
- whether a separate result message is required.
|
|
44
|
+
Native Data 事件的 capture plan 由当前 Head 的 Event、Data、AuthZ revision
|
|
45
|
+
与 resource 四元组共同确定。新增快照字段或扩展 RLS 会形成新的不可变 plan,
|
|
46
|
+
不会与旧 plan 冲突;历史 replay/re-emission 复制原 fact 的数据与 plan digest,
|
|
47
|
+
不会用当前 Head 重新投影历史事实。
|
|
62
48
|
|
|
63
|
-
|
|
49
|
+
每条 Workflow fact v2 都必须携带不可变实例身份信封:`workflowCode`、
|
|
50
|
+
`definitionVersion`、`bindingVersion`、`instanceId`、`generation`、
|
|
51
|
+
`businessKey`、`instanceSequence`、`revision`、`dataRef`、`dataRevision`、
|
|
52
|
+
`actor` 与 `cause`。消费者不得从当前 Workflow Head 反推历史事实版本。
|
|
64
53
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
`
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
54
|
+
配置中的 `workflows.activations` 是完整 desired set;删除声明即停用新发起,
|
|
55
|
+
不是增量 patch。definition 和 activation 必须一致声明
|
|
56
|
+
`acceptedCommandDeactivationPolicy`:`finish-pinned` 让已接受的 durable process
|
|
57
|
+
command 按固定版本完成,`cancel-on-deactivate` 在声明删除后取消尚未启动的命令;
|
|
58
|
+
既有 Workflow instance 始终按固定版本继续。所有审批人 Provider 的 `min/max`
|
|
59
|
+
默认 1/200,最大 200。
|
|
60
|
+
需要按流程实例串行投递时只声明 `ordering: 'workflow-instance'`,不接受下划线别名。
|
|
72
61
|
|
|
73
|
-
|
|
74
|
-
`OpenXiangdaBusinessNotificationService.sendFromEvent()`. The application
|
|
75
|
-
declares safe paths under event `data` for recipients, title and summary;
|
|
76
|
-
Notification Hub verifies the active durable delivery and resolves those paths
|
|
77
|
-
itself. The audit actor remains the application event consumer with eventId,
|
|
78
|
-
deliveryId and subscription code as initiating source. Missing or forged event
|
|
79
|
-
proof, arbitrary recipient values and user impersonation are rejected.
|
|
62
|
+
Notification Hub 消费事实:
|
|
80
63
|
|
|
81
|
-
|
|
64
|
+
- `participant.activated` 创建待处理消息;
|
|
65
|
+
- participant 完成、转交、委托、加签、暂停或恢复时更新对应收件人的逻辑消息;
|
|
66
|
+
- instance 完成、拒绝、撤回或终止时更新该实例全部历史消息;
|
|
67
|
+
- 消息回调必须调用 Workflow 命令,等待 Workflow 新事实后再更新卡片。
|
|
82
68
|
|
|
83
|
-
|
|
69
|
+
发送采用至少一次语义,以 `messageKey + recipient + channel` 幂等。RabbitMQ 只负责唤醒,PostgreSQL fact、message projection、outbox 和 receipt 才是恢复事实。
|
|
84
70
|
|
|
85
|
-
|
|
71
|
+
## 详情跳转
|
|
86
72
|
|
|
87
|
-
|
|
88
|
-
codes on the Workflow definition declaration. The desktop route must be an
|
|
89
|
-
`admin` route, the mobile route must be a `user` route, and both paths contain
|
|
90
|
-
exactly `:instanceId`:
|
|
73
|
+
消息使用 canonical `navigationTarget`,而不是模板拼接环境 URL。它可以描述平台路由、应用路由或白名单外部地址,由平台按 tenant、environment 和 channel 解析 desktop/mobile/deep link。
|
|
91
74
|
|
|
92
|
-
|
|
93
|
-
frontend: {
|
|
94
|
-
root: 'apps/web',
|
|
95
|
-
routes: [
|
|
96
|
-
{
|
|
97
|
-
code: 'purchase-detail',
|
|
98
|
-
path: '/admin/operations/purchases/:instanceId',
|
|
99
|
-
label: '采购审批详情',
|
|
100
|
-
surface: 'admin',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
code: 'purchase-detail-mobile',
|
|
104
|
-
path: '/m/purchases/:instanceId',
|
|
105
|
-
label: '移动采购审批详情',
|
|
106
|
-
surface: 'user',
|
|
107
|
-
},
|
|
108
|
-
],
|
|
109
|
-
},
|
|
110
|
-
workflows: {
|
|
111
|
-
definitions: [{
|
|
112
|
-
version: 1,
|
|
113
|
-
definition: purchaseApproval,
|
|
114
|
-
launch: { mode: 'work-center-only' },
|
|
115
|
-
detailRouteCode: {
|
|
116
|
-
desktop: 'purchase-detail',
|
|
117
|
-
mobile: 'purchase-detail-mobile',
|
|
118
|
-
},
|
|
119
|
-
}],
|
|
120
|
-
bindings: [],
|
|
121
|
-
activations: [],
|
|
122
|
-
},
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
Bind the generated routes with `defineApplicationContributions`. Inside the
|
|
126
|
-
page, read `instanceId` from React Router and optional `taskId` from the query.
|
|
127
|
-
Use `loadWorkflowInstanceSurface`, `loadWorkflowTaskSurface` and
|
|
128
|
-
`loadWorkflowTimeline` from `openxiangda/core`; render only operations returned
|
|
129
|
-
by the Surface. The platform resolves the same declaration for desktop/mobile
|
|
130
|
-
work centers, Notification Hub logical messages, DingTalk cards and other
|
|
131
|
-
channel snapshots. Omitting `detailRouteCode` keeps the standard pages. A
|
|
132
|
-
declared but missing or incompatible route fails closed rather than falling
|
|
133
|
-
back silently.
|
|
134
|
-
|
|
135
|
-
Standard launch entry is also a platform Surface. Desktop uses
|
|
136
|
-
`/admin/workflows/:workflowCode/new` and mobile uses
|
|
137
|
-
`/m/workflows/:workflowCode/start`; both first load
|
|
138
|
-
`loadWorkflowLaunchSurface(workflowCode)`, then use the same durable
|
|
139
|
-
`saveBusinessRevision -> prepareWorkflowStart -> startWorkflow` protocol.
|
|
140
|
-
`custom-page` and `work-center-only` declarations do not expose the standard
|
|
141
|
-
launch Surface. After start, navigate through the device's standard instance
|
|
142
|
-
entry so the current `detailRouteCode` contract can redirect consistently.
|
|
143
|
-
|
|
144
|
-
An application-level inbox is enabled in explicit admin navigation with
|
|
145
|
-
`adminApplicationTodoCenterPage()`. It projects Notification Hub messages and
|
|
146
|
-
per-recipient interaction for the current logged-in user only; it is not the
|
|
147
|
-
Notification Hub management console. Use its `去处理` navigation to enter the
|
|
148
|
-
authorized Workflow or application page, and keep approve/reject/transfer
|
|
149
|
-
commands on the destination Surface.
|
|
150
|
-
|
|
151
|
-
## Interactive channel actions
|
|
75
|
+
详情地址不能携带登录 Token、Cookie 或任何身份替换凭据。点击后必须重新认证,并由 Data/AuthZ/Workflow 执行真实权限校验;当前 Perspective 只能重新应用读取投影。
|
|
152
76
|
|
|
153
|
-
|
|
77
|
+
“跳回业务记录”和“完全接管流程详情”是两个不同合同。标准 Workflow 页需要提供
|
|
78
|
+
“查看业务详情”时,在 subject resource 上声明明确的 route code 对:
|
|
154
79
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
80
|
+
```ts
|
|
81
|
+
const purchaseResource = {
|
|
82
|
+
code: 'purchases',
|
|
83
|
+
name: '采购申请',
|
|
84
|
+
detailRouteCode: {
|
|
85
|
+
desktop: 'purchase-record-detail',
|
|
86
|
+
mobile: 'purchase-record-detail-mobile',
|
|
87
|
+
},
|
|
88
|
+
fields: [/* ... */],
|
|
89
|
+
} satisfies AppDataResourceDeclaration;
|
|
90
|
+
```
|
|
160
91
|
|
|
161
|
-
|
|
92
|
+
两条 route 都必须是已认证的 `surface: 'user'` 页面并要求该资源的 read capability;
|
|
93
|
+
桌面 path 不得进入 `/m`,移动 path 必须以 `/m/` 开头,且各自只能包含一个动态记录参数。
|
|
94
|
+
参数名可以是业务语义名,例如 `:purchaseId` 或 `:applicationId`。编译器把映射写入
|
|
95
|
+
不可变资源 Contract 和生成的 `resourceDefinitions`,平台从同一环境 active Contract
|
|
96
|
+
读取并代入 Workflow Surface 已授权的 recordId。未声明时返回空业务记录目标;已发布
|
|
97
|
+
映射畸形时严格失败。平台和浏览器都不得再按 `resourceCode` 猜路径,也不得用别名补洞。
|
|
162
98
|
|
|
163
|
-
|
|
99
|
+
流程需要完全接管详情页时,在 definition declaration 上声明桌面端与移动端 route code:
|
|
164
100
|
|
|
165
|
-
|
|
101
|
+
```ts
|
|
102
|
+
{
|
|
103
|
+
version: 1,
|
|
104
|
+
definition: purchaseApproval,
|
|
105
|
+
launch: { mode: 'work-center-only' },
|
|
106
|
+
detailRouteCode: {
|
|
107
|
+
desktop: 'purchase-detail',
|
|
108
|
+
mobile: 'purchase-detail-mobile',
|
|
109
|
+
},
|
|
110
|
+
}
|
|
111
|
+
```
|
|
166
112
|
|
|
167
|
-
|
|
113
|
+
`desktop` 必须引用 `surface: 'admin'` 的 route,`mobile` 必须引用
|
|
114
|
+
`surface: 'user'` 的 route;两个 path 都必须且只能包含
|
|
115
|
+
`:instanceId`。任务入口由平台追加有界 `taskId` query。应用使用
|
|
116
|
+
`defineApplicationContributions(appRoutes, { pages })` 绑定桌面和移动组件,
|
|
117
|
+
页面通过 `openxiangda/core` 的 `loadWorkflowInstanceDetail`、
|
|
118
|
+
`loadWorkflowTaskDetail` 读取修订一致的聚合详情,只渲染 Surface 返回的操作。
|
|
119
|
+
旧 Surface 与 timeline 读取继续供兼容客户端使用。
|
|
120
|
+
|
|
121
|
+
平台在当前环境 Head 的不可变 Contract Bundle 上统一解析:桌面/移动工作台、
|
|
122
|
+
Notification Hub 的 `workflow.detail` 逻辑目标、钉钉卡片以及其他渠道快照得到
|
|
123
|
+
同一组自定义路径。未声明时保留标准详情;声明存在但 route 缺失、surface 错误或
|
|
124
|
+
path 不合法时严格失败,不退回标准页掩盖合同错误。
|
|
125
|
+
|
|
126
|
+
标准详情由平台统一渲染,不要求应用复制资源详情页。Workflow Surface 的
|
|
127
|
+
`presentation.businessDetail` 按实例固定的 Data logical revision、资源声明 digest 和
|
|
128
|
+
physical resource 定位结构,但每次读取同一 Native Data record 的当前字段值;发起时
|
|
129
|
+
`requestedRevision` 只用于命令 token/CAS,当前 `sourceRevision` 和当前值始终随重新读取更新,
|
|
130
|
+
禁止把业务字段值改成流程启动快照。字段投影同时应用当前用户策略并统一排除
|
|
131
|
+
`system: true`、平台内部字段与过滤后为空的分组;
|
|
132
|
+
父子表按同一 logical revision 和父记录外键读取,单表最多 200 行。页面同时消费
|
|
133
|
+
`presentation.summary`、服务端 timeline `display.entries` 和 operation descriptors。
|
|
134
|
+
桌面端与移动端拥有独立 DOM;同意/拒绝等决策操作固定在底部主操作区,转交、退回、
|
|
135
|
+
加签等低频操作进入“更多操作”,意见只在点击动作后的确认弹窗或移动端底部抽屉中输入。
|
|
136
|
+
`stale` 只是 revision 元数据,不显示常驻横幅也不预先阻断操作;只有服务端命令 token/CAS
|
|
137
|
+
返回真实 `freshSurface` 冲突时才提示“内容已更新,请刷新后重试”,且绝不自动重放命令。
|
|
138
|
+
同意、拒绝、退回、转交和加签记录并入对应纵向节点;实例撤回/终止是独立终态事件,
|
|
139
|
+
展示操作者、动作、意见和唯一 `primaryDisplayTime`,
|
|
140
|
+
不另设“操作记录”。标准业务页不渲染流程/任务/资源/记录 UUID、事件序列、revision 或失败指针。
|
|
141
|
+
申请人、审批人和操作者显示目录/快照解析名称、可选部门以及真实头像;缺失或加载失败时
|
|
142
|
+
统一使用平台默认头像,不生成姓名首字,也不回退 userId。
|
|
143
|
+
|
|
144
|
+
PC 标准任务与实例详情的 canonical 路径分别为 `/tasks/:taskId` 和
|
|
145
|
+
`/workflows/:instanceId`,使用独立全屏页面,不进入后台 Shell;不提供旧 admin 路径的
|
|
146
|
+
别名或重定向。移动端继续使用独立的 `/m/tasks/:taskId` 和 `/m/workflows/:instanceId` 页面。
|
|
147
|
+
|
|
148
|
+
流程详情中的附件、富文本图片和签名不直接复用普通 Data API 文件地址。浏览器调用
|
|
149
|
+
Workflow instance-scoped preview/content 路由,平台在每次文件读取时重新校验当前身份、
|
|
150
|
+
实例参与权限、固定业务记录、资源、字段和 file id;URL 不携带登录态或替代身份。
|
|
151
|
+
|
|
152
|
+
标准发起页使用独立的 `WorkflowLaunchSurface` 读取当前激活合同:桌面路径为
|
|
153
|
+
`/workflows/:workflowCode/start`,移动路径为
|
|
154
|
+
`/m/workflows/:workflowCode/start`。`standalone`/`hidden-handoff` 缺省使用同一个
|
|
155
|
+
compiler-owned `processOperationCode`、subject declaration 和标准 process commit;平台在一个
|
|
156
|
+
事务中写业务数据和 durable command。action-owned 资源改为声明
|
|
157
|
+
`launch.submission.kind: 'named-operation'`,显式绑定 create/existing 请求来源、响应 subject/
|
|
158
|
+
processCommand 路径和 allowlisted context 预填。标准页调用原 Named Action,由应用服务端保留
|
|
159
|
+
业务校验、幂等与原子提交;缺少/null processCommand 是成功的免审结果,不生成流程。页面只在
|
|
160
|
+
确实返回 command 时把 `commandId` 写入 URL,刷新、跨设备和 worker 恢复都重新读取
|
|
161
|
+
`ProcessCommandSurface`;`awaiting_input` 只回答已生成 requirement,`started` 再进入 pinned
|
|
162
|
+
instance entry。浏览器不再导出 prepare/start 发起协议。
|
|
163
|
+
|
|
164
|
+
通用应用待办页通过 `frontend.user.applicationTodoCenter: true` 启用,平台同时提供
|
|
165
|
+
`/todos` 和 `/m/todos`。它只投影当前登录用户的 Notification Hub 收件人数据,
|
|
166
|
+
`查看详情` 使用上述统一导航解析;待办页不常驻业务详情,审批命令仍在目标 Workflow
|
|
167
|
+
Surface 上执行。
|
|
168
|
+
|
|
169
|
+
## 应用声明
|
|
170
|
+
|
|
171
|
+
应用只在明确启用可选模块时,在 `openxiangda.config.ts` 声明 workflow definition、binding、assignee provider、notification profile、template reference 和安全字段投影。Git 声明是拓扑事实源;平台管理页面只负责版本、激活、预览、诊断和有界运行参数,不建立第二份活动定义。
|
|
172
|
+
|
|
173
|
+
事件处理器调用 `OpenXiangdaBusinessNotificationService.sendFromEvent()` 时,
|
|
174
|
+
对应订阅还必须声明
|
|
175
|
+
`platformAccess: { notification: { mode: 'business-standard' } }`。编译器将该声明写入
|
|
176
|
+
不可变 Configuration/Contract Bundle,并据此生成精确的 `notification-hub-v2`
|
|
177
|
+
能力闭包;不发送通知的订阅不得声明该依赖,未知 access 或 mode 直接失败。
|
|
178
|
+
|
|
179
|
+
## 验证
|
|
180
|
+
|
|
181
|
+
至少验证:完整标准详情投影、父子表边界、流程附件读取、桌面/移动独立渲染、全部标准操作、多人模式、重复/并发命令、stale revision、重启 replay、乱序事件、重复回调、消息终态全量更新、详情跳转、错用户/错租户/过期动作、渠道超时/unknown、死信重放和 1.x 零触碰。
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
# OpenXiangda 2.0 Architecture
|
|
2
|
-
|
|
3
|
-
Keep one React application, one optional NestJS service and one platform-owned data contract. Application code directly depends only on `openxiangda`; use `openxiangda/config`, `openxiangda/core`, `openxiangda/field-kit`, `openxiangda/react`, `openxiangda/nest` and `openxiangda/testing` as the public subpaths. Do not import the physical `openxiangda-*` implementation packages.
|
|
4
|
-
|
|
5
|
-
Declare resources, routes, capabilities, row policies and operation-aware field policies once in `openxiangda.config.ts`. The compiler owns derived contracts; the root package owns Field Kit, CRUD Renderer, Shell, clients and Nest integration; the platform owns identity, authorization, data, environment Heads and deployment state.
|
|
6
|
-
|
|
7
|
-
Ordinary list, detail, create, update and delete operations go directly through Data API. Add a NestJS endpoint only for a business action that cannot be represented as CRUD. Run `pnpm openxiangda check` after every contract change.
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# OpenXiangda 2.0 Commands
|
|
2
|
-
|
|
3
|
-
> Generated from `DEVKIT_COMMANDS`. Do not edit manually.
|
|
4
|
-
|
|
5
|
-
| Command | Risk | Purpose |
|
|
6
|
-
| --- | --- | --- |
|
|
7
|
-
| `pnpm openxiangda create` | deploy | 创建、绑定并初始化应用 |
|
|
8
|
-
| `pnpm openxiangda dev` | write-local | 连接平台测试数据启动本地 Web 与 Nest |
|
|
9
|
-
| `pnpm openxiangda check` | write-local | 生成契约并在目标平台预检后执行检查、测试和构建 |
|
|
10
|
-
| `pnpm openxiangda accept` | deploy | 按计划准备可选的真实预发验收身份 |
|
|
11
|
-
| `pnpm openxiangda deploy` | deploy | 部署测试环境或显式复用测试版本部署生产 |
|
|
12
|
-
| `pnpm openxiangda status` | read | 查询最近或指定部署状态 |
|
|
13
|
-
| `pnpm openxiangda logs` | read | 查询最近或指定部署日志 |
|
|
14
|
-
| `pnpm openxiangda cancel` | deploy | 幂等取消尚未提交激活的部署 |
|
|
15
|
-
| `pnpm openxiangda retry` | deploy | 显式重试可恢复的失败部署 |
|
|
16
|
-
| `pnpm openxiangda start` | deploy | 从当前不可变版本启动应用环境 |
|
|
17
|
-
| `pnpm openxiangda stop` | deploy | 将应用环境缩容为零并保留数据 |
|
|
18
|
-
| `pnpm openxiangda rollback` | deploy | 回滚测试或生产环境 |
|
|
19
|
-
| `pnpm openxiangda login` | write-local | 通过平台浏览器授权登录 |
|
|
20
|
-
| `pnpm openxiangda skill` | write-local | 安装当前版本的 AI Skill |
|
|
21
|
-
| `pnpm openxiangda spec` | write-local | 维护可选的 AppSpec 需求与变更辅助 |
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# Requirement Discovery
|
|
2
|
-
|
|
3
|
-
Before editing, write a compact decision record covering:
|
|
4
|
-
|
|
5
|
-
- business objective and measurable outcome;
|
|
6
|
-
- actors and positive/negative scenarios;
|
|
7
|
-
- resources, field meanings, required values and lifecycle states;
|
|
8
|
-
- role memberships, operation capabilities, field restrictions and row scope;
|
|
9
|
-
- external systems, side effects, concurrency and idempotency;
|
|
10
|
-
- environment, security, volume and latency bounds;
|
|
11
|
-
- acceptance evidence for UI, API, PostgreSQL/RLS and delivery.
|
|
12
|
-
|
|
13
|
-
Separate known facts, assumptions and unresolved choices. Inspect the workspace protocol and existing declarations before inventing a contract. If a choice changes data meaning, authorization, external writes or release scope, resolve it before implementation. Ordinary naming or layout details may use a documented reasonable assumption.
|
|
14
|
-
|
|
15
|
-
The output is complete only when every requirement maps to an owner and a falsifiable acceptance check. Do not begin with source patches and reconstruct intent afterward.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# OpenXiangda 2.0 Application Agent Contract
|
|
2
|
-
|
|
3
|
-
- Use only the workspace-pinned CLI: `pnpm openxiangda <command>`. Never invoke a bare global `openxiangda` inside a 2.0 task.
|
|
4
|
-
- `appspec/` is the optional OpenXiangda 2.0 business-intent layer. Before changing observable behavior, read the bounded index with `pnpm openxiangda spec context --json`, then select only the relevant stable ID; use no ChangeSpec for L0 work, one short ChangeSpec for L1, and add permission/rollback/concurrency detail only for L2/L3. Before close, the user—not AI—confirms `currentSpec=merged` or `not-applicable`. AppSpec is advisory and never a release gate. Never read, import or migrate 1.x `openspec/` or SDD.
|
|
5
|
-
- Use Vite, React Router, Refine Core and Ant Design. Do not add Umi, ProComponents or another admin shell.
|
|
6
|
-
- Bind every generated `appRoutes` entry to its local page with `defineApplicationContributions`; desktop `admin` routes stay inside the platform Shell, while `user` routes render without an admin Shell for independent mobile/user experiences. Generated resource CRUD routes are compiler-owned under `/admin/resources/<resourceCode>...` and `/m/admin/resources/<resourceCode>...`; never recreate root resource paths, aliases or redirects. Explicit routes that have the same canonical shape as another explicit or generated route fail compilation, even when dynamic parameter names differ. Use only the typed `toolbar`, `row` and `detail` resource slots for generated resource actions. Declare the complete editable admin menu with `defineAdminNavigation` and its page/group helpers; the Shell renders only generated `adminNavigation` references and permissions only filter them. Do not create another router, menu store, layout, identity provider, permission store or copied CRUD page; route/action access uses capability or `allOf`/`anyOf`, while Data/App API and Workflow authorization remain server-owned.
|
|
7
|
-
- Declare each resource once in `openxiangda.config.ts` with only `code`, `name`, `fields` and optional `mutationOwner`, generated/list/layout/data-policy settings. Each field owns type, label, required state, Surface flags, reference/file metadata and access. Resource codes are lower kebab-case. Use `native` for direct Data API mutations, `action`, `readonly` or `workflow` for non-Native ownership; never grant or generate Native mutation for a non-Native owner.
|
|
8
|
-
- Never write resource-level `schemaVersion`, `appCode`, `schema`, `surface`, `capabilities`, `fieldPolicies` or `platform/data` modules. The compiler derives the strict DataResource, CRUD capabilities, Surface and AI Schema. The application manifest still starts with its one top-level `schemaVersion: 3`.
|
|
9
|
-
- Ordinary list/get/create/update/delete, filters, export and batch operations use the platform Native Data API. Do not create Function CRUD or NestJS wrappers.
|
|
10
|
-
- Add NestJS only for a named business action that needs a cross-resource transaction, an invariant or an external side effect.
|
|
11
|
-
- Every interactive business action binds `@OpenXiangdaOperation(operation)` and injects `OpenXiangdaBusinessDataApiService`, `OpenXiangdaBusinessNotificationService`, or `OpenXiangdaStandardOperations`. The platform checks the action capability once at App API ingress; the trusted backend then has full Data/managed business-notification access only to its exact application/environment while audit retains the initiating user and action. Do not author `authorizationJSON`, forward user tokens, grant ordinary users `app:notification2:send`, or reapply the user's resource, row and field permissions inside the action.
|
|
12
|
-
- A NestJS backend declares only `enabled`, `isolation: 'shared' | 'dedicated'` and `resourceProfile: 'light' | 'standard'`. Never put raw Kubernetes resources, replicas, ports or environment maps in application metadata; the platform owns capacity and scaling.
|
|
13
|
-
- Use the current logged-in user and the union of that user's application roles. An optional declared Perspective projects only read visibility (pages, rows and fields); create/update/delete, workflows and custom actions continue to authorize against the complete union. Standard Data API calls inherit `X-OpenXiangda-Perspective` automatically. Use `@CurrentPerspective()` only when custom Nest code reads outside the standard Data API, and apply an equivalent read projection explicitly. Business code must not persist a platform Token or authorization result and must not implement a second identity path.
|
|
14
|
-
- Fields inherit the resource read/create/update capabilities. Use field `access` only to tighten them; arrays are all-of and `false` is explicit deny. There is no `write` fallback.
|
|
15
|
-
- Field `type` is semantic, never a hand-authored database type. The supported catalog is exactly `text.short`, `text.long`, `text.rich`, `number.integer`, `number.decimal`, `boolean`, `date`, `time`, `datetime`, `date-range`, `datetime-range`, `option.single`, `option.multiple`, `cascade.single`, `cascade.multiple`, `user.single`, `user.multiple`, `department.single`, `department.multiple`, `resource-ref.single`, `resource-ref.multiple`, `file`, `image`, `signature`, `address`, `location`, `json`, `serial-number`, `uuid` and `subtable`. The compiler alone derives PostgreSQL columns, constraints and indexes.
|
|
16
|
-
- Declare every custom operation capability in `authz.capabilities` with `kind: 'backend'`, then reference that same code from the operation and its allowed roles. Generated resource CRUD capabilities do not go in this catalog.
|
|
17
|
-
- Build App Operation request/response schemas with `resourceRecordSchema`, `schemaRef`, `composeJsonSchema` and `composeAppOperationSchemas` from `openxiangda/config`. They project the same Resource declaration and canonical field value protocols; never import a physical toolchain package or repeat user, department, resource-reference or managed-file schemas by hand.
|
|
18
|
-
- Visitor duplicate protection uses `createVisitorReservation({ duplicateMatch: { fieldCode: submittedValue }, ... })`. `duplicateMatch` is a non-empty value map, never a field-name array, and no mutable pre-read is allowed.
|
|
19
|
-
- Desktop and mobile pages share values, validation and authorization, but use separate renderers. Options, members and departments store display snapshots; resource references store direct JSON display values; attachments, images and signatures use platform-managed file references.
|
|
20
|
-
- `option.*`, `user.*`, `department.*` and `resource-ref.*` values never collapse to scalar IDs. Single values store one labeled object and multiple values store object arrays. `resource-ref.*` JSON is not a foreign key, trusted target snapshot or automatically refreshed copy; current target state is read by `resourceCode` plus `value`. A resource source `labelField` must be `text.short` or `text.long`; `serial-number` is allowed in source search, description and snapshot fields, but not as the label. `location` accepts only exact WGS84 coordinates captured by DingTalk or browser geolocation; it has no manual input or `manual` source. Roles that consume directory-backed fields explicitly include `app:<app-code>:directory:read`.
|
|
21
|
-
- Derive role grants with `resourceCapabilityCodes(appCode, resourceCode)`. Declare current-user rows only with `currentUserDataPolicy(...)`; do not invent operators, values or alternate current-user spellings.
|
|
22
|
-
- Do not add compatibility aliases, migration branches or silent fallbacks for an earlier 2.0 alpha contract. Replace an incorrect contract and regenerate the application.
|
|
23
|
-
- Standard Workflow and Notification Hub are optional 2.0 modules. Enable them only through the canonical `openxiangda.config.ts` declarations and generated clients; declare each Workflow launch as `standalone`, `custom-page`, `hidden-handoff` or `work-center-only`, put only self-contained standalone launch pages in navigation, and bind durable save handlers with `defineWorkflowLaunchContributions` without repeating generated titles. Desktop and mobile standard launch pages load the same canonical Workflow launch Surface. To replace Workflow detail, declare both desktop and mobile `detailRouteCode` values whose routes contain exactly `:instanceId`; Work Center, the application todo center and notification channels consume the platform-resolved paths, while every Surface and command remains server-authorized. Add the standard current-user todo page only with `adminApplicationTodoCenterPage()`; never query Notification Hub management APIs from a user page. Never depend on temporary router location state or copy 1.x workflow/message code, tables, APIs, templates or callbacks into this workspace. Keep ordinary CRUD and application-specific state machines independent of them.
|
|
24
|
-
- Run `pnpm openxiangda check --json` after contract changes and read `data.sealedArtifact`; check never seals, and an older `.openxiangda/build/app-package.json` is not the current check result. Use `pnpm openxiangda accept --plan <file>` only for optional real preproduction identity acceptance; it never blocks delivery. Deploy with `pnpm openxiangda deploy`, inspect with `pnpm openxiangda status` and `pnpm openxiangda logs`, and use the platform rollback command rather than mutating K3s directly.
|
|
25
|
-
- AI-native clients start the workspace protocol through the same pinned binary: `pnpm exec openxiangda --mcp-stdio --cwd <workspace>`. Read `openxiangda://workspace/contracts` or call `contract_describe`; for first-time menu authoring, copy `data.adminNavigationAuthoring.suggestion.expression` once into `frontend.admin.navigation` with its listed `openxiangda/config` imports, then edit that application-owned declaration. Never treat the proposal as runtime discovery. When AppSpec is enabled, also read `openxiangda://workspace/appspec` or call `appspec_context`. Require `aiCatalog` and `aiCatalogDigest` to match the normal compiler output. This is a stdio transport mode, not another application-owned server. Never write an application MCP server, Catalog file, preview store or second authorization path.
|