openxiangda 2.2.2 → 2.4.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/documentation/backend.md +19 -2
- package/documentation/getting-started.md +7 -7
- package/documentation/manifest.json +4 -4
- package/documentation/workflow-events.md +58 -0
- package/package.json +22 -19
- package/releases/2.3.0.json +37 -0
- package/releases/2.4.0.json +37 -0
- package/skills/manifest.json +1 -1
- package/skills/openxiangda-v2/SKILL.md +4 -4
- package/skills/openxiangda-v2/references/backend.md +19 -2
- package/skills/openxiangda-v2/references/getting-started.md +7 -7
- package/skills/openxiangda-v2/references/workflow-events.md +58 -0
package/documentation/backend.md
CHANGED
|
@@ -45,10 +45,27 @@ operation、事件消费者、人员提供器,然后运行 `pnpm openxiangda c
|
|
|
45
45
|
|
|
46
46
|
只读前置条件使用 `record-exists` 或 `record-match`,它们不要求同记录 mutation,
|
|
47
47
|
但仍执行 read capability、字段权限与行级授权。需要与数据库当前时间比较时使用
|
|
48
|
-
`databaseNowAssertion('publishAt', 'lte')
|
|
49
|
-
|
|
48
|
+
`databaseNowAssertion('publishAt', 'lte')`;平台在守卫行锁及写入前校验完成后,
|
|
49
|
+
用一次 PostgreSQL `clock_timestamp()` 完成所有动态断言,并把该接受时刻作为
|
|
50
|
+
`evaluatedAt` 存入幂等回执。它不是最终提交时刻。相同幂等键重放不会重新
|
|
50
51
|
读取当前时间。不得把 `Date.now()`、SQL 表达式、时区偏移或调用方时钟塞入断言。
|
|
51
52
|
|
|
53
|
+
新建或更新的时间窗口使用 `operation-time`,直接引用本次操作提交的 datetime 字段:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
const guards = [
|
|
57
|
+
{ kind: 'operation-time', operationIndex: 0, field: 'startsAt',
|
|
58
|
+
operator: 'gt', offsetMilliseconds: 0, errorCode: 'OPENXIANGDA_NOT_FUTURE' },
|
|
59
|
+
{ kind: 'operation-time', operationIndex: 0, field: 'startsAt',
|
|
60
|
+
operator: 'lte', offsetMilliseconds: 2592000000, errorCode: 'OPENXIANGDA_TOO_FAR' },
|
|
61
|
+
];
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
上述规则表示第一个 create/update 操作的 startsAt 必须晚于平台接受时刻,
|
|
65
|
+
且最多提前 30 天。字段须已声明、可写,并在操作 data 中提供带 Z 或显式偏移的
|
|
66
|
+
ISO 时间字符串;不接受空值、嵌套路径、引用或表达式。offsetMilliseconds 是
|
|
67
|
+
最多正负 366 天的整数,所有时间条件共享一个接受时刻。需要平台 Data API 1.1.0。
|
|
68
|
+
|
|
52
69
|
|
|
53
70
|
## 业务动作与普通查询 {#business-action}
|
|
54
71
|
|
|
@@ -11,10 +11,10 @@ OpenXiangda 2.0 默认生成 React 应用和共享契约。普通 CRUD、标准
|
|
|
11
11
|
以下命令的版本占位符由随包资料替换为该根包的精确版本。网站源码阅读者应先确认要使用的发行版本。
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
pnpm dlx openxiangda@2.
|
|
15
|
-
pnpm dlx openxiangda@2.
|
|
16
|
-
pnpm dlx openxiangda@2.
|
|
17
|
-
pnpm dlx openxiangda@2.
|
|
14
|
+
pnpm dlx openxiangda@2.4.0 skill install --force
|
|
15
|
+
pnpm dlx openxiangda@2.4.0 auth status --base-url <平台地址> --json
|
|
16
|
+
pnpm dlx openxiangda@2.4.0 login --base-url https://platform.example.com
|
|
17
|
+
pnpm dlx openxiangda@2.4.0 create my-app --base-url https://platform.example.com
|
|
18
18
|
cd my-app
|
|
19
19
|
pnpm openxiangda context --json
|
|
20
20
|
pnpm openxiangda dev
|
|
@@ -114,9 +114,9 @@ MCP 的 `docs_read` 可以读取本说明,当前没有独立的源码操作 MC
|
|
|
114
114
|
无需本地工作区,使用本 Skill 随包精确版本或已安装的对应 CLI:
|
|
115
115
|
|
|
116
116
|
```bash
|
|
117
|
-
pnpm dlx openxiangda@2.
|
|
118
|
-
pnpm dlx openxiangda@2.
|
|
119
|
-
pnpm dlx openxiangda@2.
|
|
117
|
+
pnpm dlx openxiangda@2.4.0 auth status --base-url <平台> --json
|
|
118
|
+
pnpm dlx openxiangda@2.4.0 source resolve <仓库URL> --base-url <平台> --json
|
|
119
|
+
pnpm dlx openxiangda@2.4.0 source clone <仓库URL> <新目录> --base-url <平台> --json
|
|
120
120
|
```
|
|
121
121
|
|
|
122
122
|
登录缺失或站点不匹配时,先按该平台执行 login。resolve 根据平台已经登记的绑定返回
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "openxiangda.documentation/v1",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"topics": [
|
|
5
5
|
{
|
|
6
6
|
"id": "getting-started",
|
|
7
7
|
"title": "安装与开始开发",
|
|
8
8
|
"file": "getting-started.md",
|
|
9
|
-
"sha256": "
|
|
9
|
+
"sha256": "bff9fdb110552a735202c9ec0fe6112f3d852760b0888d469973923dc492f5cd"
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"id": "product-design",
|
|
@@ -72,13 +72,13 @@
|
|
|
72
72
|
"id": "workflow-events",
|
|
73
73
|
"title": "审批、事件与通知",
|
|
74
74
|
"file": "workflow-events.md",
|
|
75
|
-
"sha256": "
|
|
75
|
+
"sha256": "998422cb6270a086fab19848553e7fa20655e062a2c6a724683247df59427b7b"
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
"id": "backend",
|
|
79
79
|
"title": "按需后端与业务动作",
|
|
80
80
|
"file": "backend.md",
|
|
81
|
-
"sha256": "
|
|
81
|
+
"sha256": "9ef4d6ac9b4bee97d28daeacf7e88a9460f2402a35e0ece4ba2888cdceb354e7"
|
|
82
82
|
},
|
|
83
83
|
{
|
|
84
84
|
"id": "administration",
|
|
@@ -37,6 +37,64 @@ Head、实例/任务版本、允许的命令集合与 CSRF。命令请求只提
|
|
|
37
37
|
`expectedTaskVersion`/`expectedInstanceVersion` 不再是合同。冲突必须刷新 Surface,
|
|
38
38
|
不得自动重放旧意图。
|
|
39
39
|
|
|
40
|
+
### 撤回与业务终止策略
|
|
41
|
+
|
|
42
|
+
需要按业务时间限制取消时,在固定 Workflow definition 中声明:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
instanceCommands: {
|
|
46
|
+
withdraw: { beforeFact: 'startsAt' },
|
|
47
|
+
terminate: {
|
|
48
|
+
capability: 'app:reservation-center:meeting:cancel',
|
|
49
|
+
beforeFact: 'startsAt',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`beforeFact` 必须是 `inputSchema` 中 required 的根字段,类型为
|
|
55
|
+
`string`、格式为 `date-time`,并通过 `subject.factProjection` 映射到非空
|
|
56
|
+
`datetime` 业务字段。例如定义与模型的相关部分为:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
// Workflow definition
|
|
60
|
+
inputSchema: {
|
|
61
|
+
type: 'object',
|
|
62
|
+
additionalProperties: false,
|
|
63
|
+
required: ['startsAt'],
|
|
64
|
+
properties: { startsAt: { type: 'string', format: 'date-time' } },
|
|
65
|
+
},
|
|
66
|
+
subject: {
|
|
67
|
+
resourceCode: 'meetings',
|
|
68
|
+
factProjection: { startsAt: 'startsAt' },
|
|
69
|
+
},
|
|
70
|
+
// meetings 模型字段
|
|
71
|
+
fields: [{ code: 'startsAt', label: '开始时间', type: 'datetime', required: true }],
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
时间值必须携带 `Z` 或 `±HH:mm` 时区,可省略秒的小数部分或使用 1–3 位小数,
|
|
75
|
+
例如 `2026-09-08T09:00:00+08:00`、`2026-09-08T01:00:00.000Z`。
|
|
76
|
+
标准字段和 Data API 将 datetime 规范化为毫秒 ISO 字符串后冻结为事实。
|
|
77
|
+
平台在锁定实例后,
|
|
78
|
+
按数据库当前时间严格判断 `当前时间 < 截止时间`;事先取得 token 不能绕过
|
|
79
|
+
后续的时限或授权检查。缺失或非法事实拒绝执行。Surface 到期禁用操作,
|
|
80
|
+
应用收到冲突后刷新详情,不自动换幂等键重试。
|
|
81
|
+
|
|
82
|
+
撤回始终只允许发起人。终止允许原应用超级管理员,或当前角色并集拥有
|
|
83
|
+
所声明精确 capability 的用户;capability 必须在同一应用显式声明,不支持
|
|
84
|
+
通配符。该授权同时允许读取对应流程实例的详情及时间线,包括完成后查阅;
|
|
85
|
+
不授予审批、抄送、改派、删除、普通数据读取或管理后台权限。撤销 capability
|
|
86
|
+
后读取和终止权限都失效。撤回、终止均要求填写原因;超级管理员也遵守已声明时限。
|
|
87
|
+
|
|
88
|
+
不声明 `instanceCommands` 时沿用既有行为;只为终止授权时可以省略其
|
|
89
|
+
`beforeFact`。声明策略的交付包自动要求平台能力
|
|
90
|
+
`workflow.instance-cancellation-policy`,旧平台无法激活该应用版本。
|
|
91
|
+
已经固定该策略的实例存在期间,平台回滚也必须保留策略执行能力。
|
|
92
|
+
发布新 definition 不会改写旧实例固定的 definition 版本,因此不会给旧实例
|
|
93
|
+
补上截止时间或业务管理员终止授权。升级前应盘点存量实例,按各自原定义完成
|
|
94
|
+
或由原有授权主体处置;不要通过重发事件或改写事实迁移策略。已使用新策略的
|
|
95
|
+
实例在截止后及终态仍允许当前被授权的业务管理员查阅,撤销其 capability
|
|
96
|
+
也会撤销这些存量实例的详情读取权限。
|
|
97
|
+
|
|
40
98
|
## 事实和消息投影
|
|
41
99
|
|
|
42
100
|
Workflow 在同一 PostgreSQL 事务中提交状态、fact 和 outbox。每个实例使用严格单调的 `instanceSequence`,每位审批人拥有独立 participant 生命周期。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openxiangda",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "OpenXiangda 2.0 的统一命令、应用 SDK、MCP 与中文 AI 技能资料。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -58,13 +58,13 @@
|
|
|
58
58
|
"antd-mobile": "5.42.3",
|
|
59
59
|
"dayjs": "1.11.18",
|
|
60
60
|
"docx-preview": "0.3.7",
|
|
61
|
-
"openxiangda-cli": "2.2.
|
|
62
|
-
"openxiangda-contracts": "2.
|
|
63
|
-
"openxiangda-devkit-core": "2.
|
|
61
|
+
"openxiangda-cli": "2.2.5",
|
|
62
|
+
"openxiangda-contracts": "2.4.0",
|
|
63
|
+
"openxiangda-devkit-core": "2.4.0",
|
|
64
64
|
"openxiangda-legacy": "npm:openxiangda@1.0.268",
|
|
65
|
-
"openxiangda-mcp": "2.0.
|
|
66
|
-
"openxiangda-nest": "2.0.
|
|
67
|
-
"openxiangda-skill-kit": "2.0.
|
|
65
|
+
"openxiangda-mcp": "2.0.6",
|
|
66
|
+
"openxiangda-nest": "2.0.6",
|
|
67
|
+
"openxiangda-skill-kit": "2.0.7",
|
|
68
68
|
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
@@ -130,18 +130,18 @@
|
|
|
130
130
|
},
|
|
131
131
|
"openxiangdaRelease": {
|
|
132
132
|
"schemaVersion": "openxiangda.release-notes/v1",
|
|
133
|
-
"version": "2.
|
|
134
|
-
"title": "
|
|
133
|
+
"version": "2.4.0",
|
|
134
|
+
"title": "事务接受时刻与预约时间窗口",
|
|
135
135
|
"status": "reviewed",
|
|
136
|
-
"summary": "
|
|
136
|
+
"summary": "增加绑定提交字段的时间守卫,统一在锁等待结束后使用平台数据库时间判断业务期限。",
|
|
137
137
|
"newFeatures": [
|
|
138
|
-
"
|
|
138
|
+
"operation-time 守卫可检查 create/update 中的 datetime 字段,支持正负 366 天以内的整数毫秒偏移和六种比较。"
|
|
139
139
|
],
|
|
140
140
|
"fixes": [
|
|
141
|
-
"
|
|
141
|
+
"动态时间条件使用守卫锁及写入前校验完成后的数据库接受时刻,成功重放保持原 evaluatedAt。"
|
|
142
142
|
],
|
|
143
143
|
"affectedUsers": [
|
|
144
|
-
"
|
|
144
|
+
"需要预约窗口、截止时间、签到时间或并发事务时间条件的 V2 应用开发者。"
|
|
145
145
|
],
|
|
146
146
|
"compatibility": {
|
|
147
147
|
"node": ">=24",
|
|
@@ -149,18 +149,21 @@
|
|
|
149
149
|
"v1",
|
|
150
150
|
"v2"
|
|
151
151
|
],
|
|
152
|
-
"v1Policy": "V1
|
|
153
|
-
"platformPolicy": "
|
|
152
|
+
"v1Policy": "V1 引擎和已有应用契约不变。",
|
|
153
|
+
"platformPolicy": "新编译的数据应用要求 Data API 1.1.0 和匹配的共享校验器;平台预检拒绝不支持该能力的目标。"
|
|
154
154
|
},
|
|
155
155
|
"upgradeSteps": [
|
|
156
|
-
"
|
|
156
|
+
"将应用精确依赖升级至 openxiangda 2.4.0,更新锁文件并刷新技能资料。",
|
|
157
|
+
"平台部署匹配版本后执行正式检查、测试发布、数据库截止和真实角色验收。"
|
|
157
158
|
],
|
|
158
159
|
"knownLimitations": [
|
|
159
|
-
"
|
|
160
|
+
"evaluatedAt 是动态条件的接受时刻,不是最终数据库提交时刻。",
|
|
161
|
+
"字段必须是声明且可写的 datetime 字面值,不支持空值、嵌套路径或操作引用。",
|
|
162
|
+
"工具包发布不代表平台已部署或应用业务验收已通过。"
|
|
160
163
|
],
|
|
161
164
|
"issues": [],
|
|
162
|
-
"sha256": "
|
|
163
|
-
"url": "https://github.com/1377385356/openxiangda/releases/tag/v2.
|
|
165
|
+
"sha256": "2c4e0bf9f880e72a454010d2590fe3ac5b2993a215473c8e29ef29e77431e42a",
|
|
166
|
+
"url": "https://github.com/1377385356/openxiangda/releases/tag/v2.4.0"
|
|
164
167
|
},
|
|
165
168
|
"scripts": {
|
|
166
169
|
"build": "node ../../scripts/prune-package-dist.mjs && tsc -p tsconfig.json && node scripts/copy-assets.mjs",
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "openxiangda.release-notes/v1",
|
|
3
|
+
"version": "2.3.0",
|
|
4
|
+
"title": "流程实例撤回期限与业务终止授权",
|
|
5
|
+
"status": "reviewed",
|
|
6
|
+
"summary": "为标准流程实例增加可选的撤回时间限制和精确业务能力终止授权,应用编译器与平台共用策略校验。",
|
|
7
|
+
"newFeatures": [
|
|
8
|
+
"流程可声明 instanceCommands,以必填时间事实限制撤回,并以同应用的精确能力授权业务管理员终止。"
|
|
9
|
+
],
|
|
10
|
+
"fixes": [
|
|
11
|
+
"阻止未绑定时间事实、跨应用能力和未声明终止能力进入可发布应用包。"
|
|
12
|
+
],
|
|
13
|
+
"affectedUsers": [
|
|
14
|
+
"需要限制标准流程撤回时间或授权业务角色终止流程的 V2 应用开发者。"
|
|
15
|
+
],
|
|
16
|
+
"compatibility": {
|
|
17
|
+
"node": ">=24",
|
|
18
|
+
"workspaceGenerations": [
|
|
19
|
+
"v1",
|
|
20
|
+
"v2"
|
|
21
|
+
],
|
|
22
|
+
"v1Policy": "V1 引擎与应用契约不变。",
|
|
23
|
+
"platformPolicy": "开发与部署需要匹配的共享校验器版本。使用新策略必须由平台提供 workflow.instance-cancellation-policy 1.0.0;平台预检会拒绝不支持该能力的版本。"
|
|
24
|
+
},
|
|
25
|
+
"upgradeSteps": [
|
|
26
|
+
"将应用 openxiangda 精确依赖升级为 2.3.0,更新锁文件并刷新技能与资料。",
|
|
27
|
+
"待目标平台部署匹配版本后执行正式检查、测试发布及真实角色验收。"
|
|
28
|
+
],
|
|
29
|
+
"knownLimitations": [
|
|
30
|
+
"新策略只作用于声明该策略的新定义,不改写既有实例固定的定义。",
|
|
31
|
+
"撤回和终止的线上执行由平台版本提供;本工具包发布不代表平台已完成部署。",
|
|
32
|
+
"驳回意见校验与 Data API 事务时钟问题不在本次工具包修复范围。"
|
|
33
|
+
],
|
|
34
|
+
"issues": [],
|
|
35
|
+
"sha256": "134f47befeec3138041d5eb24558379135456cf2f7d437502643fc5919331ec4",
|
|
36
|
+
"url": "https://github.com/1377385356/openxiangda/releases/tag/v2.3.0"
|
|
37
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "openxiangda.release-notes/v1",
|
|
3
|
+
"version": "2.4.0",
|
|
4
|
+
"title": "事务接受时刻与预约时间窗口",
|
|
5
|
+
"status": "reviewed",
|
|
6
|
+
"summary": "增加绑定提交字段的时间守卫,统一在锁等待结束后使用平台数据库时间判断业务期限。",
|
|
7
|
+
"newFeatures": [
|
|
8
|
+
"operation-time 守卫可检查 create/update 中的 datetime 字段,支持正负 366 天以内的整数毫秒偏移和六种比较。"
|
|
9
|
+
],
|
|
10
|
+
"fixes": [
|
|
11
|
+
"动态时间条件使用守卫锁及写入前校验完成后的数据库接受时刻,成功重放保持原 evaluatedAt。"
|
|
12
|
+
],
|
|
13
|
+
"affectedUsers": [
|
|
14
|
+
"需要预约窗口、截止时间、签到时间或并发事务时间条件的 V2 应用开发者。"
|
|
15
|
+
],
|
|
16
|
+
"compatibility": {
|
|
17
|
+
"node": ">=24",
|
|
18
|
+
"workspaceGenerations": [
|
|
19
|
+
"v1",
|
|
20
|
+
"v2"
|
|
21
|
+
],
|
|
22
|
+
"v1Policy": "V1 引擎和已有应用契约不变。",
|
|
23
|
+
"platformPolicy": "新编译的数据应用要求 Data API 1.1.0 和匹配的共享校验器;平台预检拒绝不支持该能力的目标。"
|
|
24
|
+
},
|
|
25
|
+
"upgradeSteps": [
|
|
26
|
+
"将应用精确依赖升级至 openxiangda 2.4.0,更新锁文件并刷新技能资料。",
|
|
27
|
+
"平台部署匹配版本后执行正式检查、测试发布、数据库截止和真实角色验收。"
|
|
28
|
+
],
|
|
29
|
+
"knownLimitations": [
|
|
30
|
+
"evaluatedAt 是动态条件的接受时刻,不是最终数据库提交时刻。",
|
|
31
|
+
"字段必须是声明且可写的 datetime 字面值,不支持空值、嵌套路径或操作引用。",
|
|
32
|
+
"工具包发布不代表平台已部署或应用业务验收已通过。"
|
|
33
|
+
],
|
|
34
|
+
"issues": [],
|
|
35
|
+
"sha256": "2c4e0bf9f880e72a454010d2590fe3ac5b2993a215473c8e29ef29e77431e42a",
|
|
36
|
+
"url": "https://github.com/1377385356/openxiangda/releases/tag/v2.4.0"
|
|
37
|
+
}
|
package/skills/manifest.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
{
|
|
5
5
|
"name": "openxiangda-v2",
|
|
6
6
|
"description": "使用 OpenXiangda 2.0 从模糊业务想法、已有资料或具体变更出发,通过对话发现模块、完成详细产品设计,再开发、检查和交付应用。维护 1.x 应用时使用对应的 1.x 技能。",
|
|
7
|
-
"sha256": "
|
|
7
|
+
"sha256": "ef5fadf78a37085d925678710fecbdca3a466987a27770aa6421c869be6bbc03"
|
|
8
8
|
}
|
|
9
9
|
]
|
|
10
10
|
}
|
|
@@ -18,10 +18,10 @@ description: 使用 OpenXiangda 2.0 从模糊业务想法、已有资料或具
|
|
|
18
18
|
未创建工作区时使用本 Skill 随根包发布的精确版本:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
pnpm dlx openxiangda@2.
|
|
22
|
-
pnpm dlx openxiangda@2.
|
|
23
|
-
pnpm dlx openxiangda@2.
|
|
24
|
-
pnpm dlx openxiangda@2.
|
|
21
|
+
pnpm dlx openxiangda@2.4.0 auth status --base-url <平台地址> --json
|
|
22
|
+
pnpm dlx openxiangda@2.4.0 login --base-url <平台地址>
|
|
23
|
+
pnpm dlx openxiangda@2.4.0 create <应用目录> --base-url <同一平台地址>
|
|
24
|
+
pnpm dlx openxiangda@2.4.0 skill install --force
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
创建前把产品要求的目标平台明确带入命令,不从旧登录态推断站点。已有工作区从原绑定恢复,平台不一致时先解决登录与目标,不改 link 文件跨站创建。
|
|
@@ -45,10 +45,27 @@ operation、事件消费者、人员提供器,然后运行 `pnpm openxiangda c
|
|
|
45
45
|
|
|
46
46
|
只读前置条件使用 `record-exists` 或 `record-match`,它们不要求同记录 mutation,
|
|
47
47
|
但仍执行 read capability、字段权限与行级授权。需要与数据库当前时间比较时使用
|
|
48
|
-
`databaseNowAssertion('publishAt', 'lte')
|
|
49
|
-
|
|
48
|
+
`databaseNowAssertion('publishAt', 'lte')`;平台在守卫行锁及写入前校验完成后,
|
|
49
|
+
用一次 PostgreSQL `clock_timestamp()` 完成所有动态断言,并把该接受时刻作为
|
|
50
|
+
`evaluatedAt` 存入幂等回执。它不是最终提交时刻。相同幂等键重放不会重新
|
|
50
51
|
读取当前时间。不得把 `Date.now()`、SQL 表达式、时区偏移或调用方时钟塞入断言。
|
|
51
52
|
|
|
53
|
+
新建或更新的时间窗口使用 `operation-time`,直接引用本次操作提交的 datetime 字段:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
const guards = [
|
|
57
|
+
{ kind: 'operation-time', operationIndex: 0, field: 'startsAt',
|
|
58
|
+
operator: 'gt', offsetMilliseconds: 0, errorCode: 'OPENXIANGDA_NOT_FUTURE' },
|
|
59
|
+
{ kind: 'operation-time', operationIndex: 0, field: 'startsAt',
|
|
60
|
+
operator: 'lte', offsetMilliseconds: 2592000000, errorCode: 'OPENXIANGDA_TOO_FAR' },
|
|
61
|
+
];
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
上述规则表示第一个 create/update 操作的 startsAt 必须晚于平台接受时刻,
|
|
65
|
+
且最多提前 30 天。字段须已声明、可写,并在操作 data 中提供带 Z 或显式偏移的
|
|
66
|
+
ISO 时间字符串;不接受空值、嵌套路径、引用或表达式。offsetMilliseconds 是
|
|
67
|
+
最多正负 366 天的整数,所有时间条件共享一个接受时刻。需要平台 Data API 1.1.0。
|
|
68
|
+
|
|
52
69
|
|
|
53
70
|
## 业务动作与普通查询 {#business-action}
|
|
54
71
|
|
|
@@ -11,10 +11,10 @@ OpenXiangda 2.0 默认生成 React 应用和共享契约。普通 CRUD、标准
|
|
|
11
11
|
以下命令的版本占位符由随包资料替换为该根包的精确版本。网站源码阅读者应先确认要使用的发行版本。
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
pnpm dlx openxiangda@2.
|
|
15
|
-
pnpm dlx openxiangda@2.
|
|
16
|
-
pnpm dlx openxiangda@2.
|
|
17
|
-
pnpm dlx openxiangda@2.
|
|
14
|
+
pnpm dlx openxiangda@2.4.0 skill install --force
|
|
15
|
+
pnpm dlx openxiangda@2.4.0 auth status --base-url <平台地址> --json
|
|
16
|
+
pnpm dlx openxiangda@2.4.0 login --base-url https://platform.example.com
|
|
17
|
+
pnpm dlx openxiangda@2.4.0 create my-app --base-url https://platform.example.com
|
|
18
18
|
cd my-app
|
|
19
19
|
pnpm openxiangda context --json
|
|
20
20
|
pnpm openxiangda dev
|
|
@@ -114,9 +114,9 @@ MCP 的 `docs_read` 可以读取本说明,当前没有独立的源码操作 MC
|
|
|
114
114
|
无需本地工作区,使用本 Skill 随包精确版本或已安装的对应 CLI:
|
|
115
115
|
|
|
116
116
|
```bash
|
|
117
|
-
pnpm dlx openxiangda@2.
|
|
118
|
-
pnpm dlx openxiangda@2.
|
|
119
|
-
pnpm dlx openxiangda@2.
|
|
117
|
+
pnpm dlx openxiangda@2.4.0 auth status --base-url <平台> --json
|
|
118
|
+
pnpm dlx openxiangda@2.4.0 source resolve <仓库URL> --base-url <平台> --json
|
|
119
|
+
pnpm dlx openxiangda@2.4.0 source clone <仓库URL> <新目录> --base-url <平台> --json
|
|
120
120
|
```
|
|
121
121
|
|
|
122
122
|
登录缺失或站点不匹配时,先按该平台执行 login。resolve 根据平台已经登记的绑定返回
|
|
@@ -37,6 +37,64 @@ Head、实例/任务版本、允许的命令集合与 CSRF。命令请求只提
|
|
|
37
37
|
`expectedTaskVersion`/`expectedInstanceVersion` 不再是合同。冲突必须刷新 Surface,
|
|
38
38
|
不得自动重放旧意图。
|
|
39
39
|
|
|
40
|
+
### 撤回与业务终止策略
|
|
41
|
+
|
|
42
|
+
需要按业务时间限制取消时,在固定 Workflow definition 中声明:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
instanceCommands: {
|
|
46
|
+
withdraw: { beforeFact: 'startsAt' },
|
|
47
|
+
terminate: {
|
|
48
|
+
capability: 'app:reservation-center:meeting:cancel',
|
|
49
|
+
beforeFact: 'startsAt',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`beforeFact` 必须是 `inputSchema` 中 required 的根字段,类型为
|
|
55
|
+
`string`、格式为 `date-time`,并通过 `subject.factProjection` 映射到非空
|
|
56
|
+
`datetime` 业务字段。例如定义与模型的相关部分为:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
// Workflow definition
|
|
60
|
+
inputSchema: {
|
|
61
|
+
type: 'object',
|
|
62
|
+
additionalProperties: false,
|
|
63
|
+
required: ['startsAt'],
|
|
64
|
+
properties: { startsAt: { type: 'string', format: 'date-time' } },
|
|
65
|
+
},
|
|
66
|
+
subject: {
|
|
67
|
+
resourceCode: 'meetings',
|
|
68
|
+
factProjection: { startsAt: 'startsAt' },
|
|
69
|
+
},
|
|
70
|
+
// meetings 模型字段
|
|
71
|
+
fields: [{ code: 'startsAt', label: '开始时间', type: 'datetime', required: true }],
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
时间值必须携带 `Z` 或 `±HH:mm` 时区,可省略秒的小数部分或使用 1–3 位小数,
|
|
75
|
+
例如 `2026-09-08T09:00:00+08:00`、`2026-09-08T01:00:00.000Z`。
|
|
76
|
+
标准字段和 Data API 将 datetime 规范化为毫秒 ISO 字符串后冻结为事实。
|
|
77
|
+
平台在锁定实例后,
|
|
78
|
+
按数据库当前时间严格判断 `当前时间 < 截止时间`;事先取得 token 不能绕过
|
|
79
|
+
后续的时限或授权检查。缺失或非法事实拒绝执行。Surface 到期禁用操作,
|
|
80
|
+
应用收到冲突后刷新详情,不自动换幂等键重试。
|
|
81
|
+
|
|
82
|
+
撤回始终只允许发起人。终止允许原应用超级管理员,或当前角色并集拥有
|
|
83
|
+
所声明精确 capability 的用户;capability 必须在同一应用显式声明,不支持
|
|
84
|
+
通配符。该授权同时允许读取对应流程实例的详情及时间线,包括完成后查阅;
|
|
85
|
+
不授予审批、抄送、改派、删除、普通数据读取或管理后台权限。撤销 capability
|
|
86
|
+
后读取和终止权限都失效。撤回、终止均要求填写原因;超级管理员也遵守已声明时限。
|
|
87
|
+
|
|
88
|
+
不声明 `instanceCommands` 时沿用既有行为;只为终止授权时可以省略其
|
|
89
|
+
`beforeFact`。声明策略的交付包自动要求平台能力
|
|
90
|
+
`workflow.instance-cancellation-policy`,旧平台无法激活该应用版本。
|
|
91
|
+
已经固定该策略的实例存在期间,平台回滚也必须保留策略执行能力。
|
|
92
|
+
发布新 definition 不会改写旧实例固定的 definition 版本,因此不会给旧实例
|
|
93
|
+
补上截止时间或业务管理员终止授权。升级前应盘点存量实例,按各自原定义完成
|
|
94
|
+
或由原有授权主体处置;不要通过重发事件或改写事实迁移策略。已使用新策略的
|
|
95
|
+
实例在截止后及终态仍允许当前被授权的业务管理员查阅,撤销其 capability
|
|
96
|
+
也会撤销这些存量实例的详情读取权限。
|
|
97
|
+
|
|
40
98
|
## 事实和消息投影
|
|
41
99
|
|
|
42
100
|
Workflow 在同一 PostgreSQL 事务中提交状态、fact 和 outbox。每个实例使用严格单调的 `instanceSequence`,每位审批人拥有独立 participant 生命周期。
|