openxiangda 1.0.268 → 1.0.270
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 +20 -1
- package/lib/cli.js +417 -24
- package/lib/config.js +60 -56
- package/lib/design-gates.js +18 -0
- package/lib/migration-advice.js +19 -0
- package/lib/release-plan.js +2 -0
- package/lib/workspace-init.js +11 -4
- package/openxiangda-skills/SKILL.md +8 -0
- package/openxiangda-skills/references/architecture-patterns.md +218 -218
- package/openxiangda-skills/references/component-guide.md +122 -122
- package/openxiangda-skills/references/openxiangda-api.md +12 -0
- package/openxiangda-skills/references/platform-data-model.md +285 -285
- package/openxiangda-skills/references/resource-manifest-cheatsheet.md +32 -2
- package/openxiangda-skills/references/troubleshooting.md +224 -224
- package/openxiangda-skills/references/webhooks.md +213 -0
- package/openxiangda-skills/references/workspace-state.md +1 -1
- package/openxiangda-skills/skills/openxiangda-core/SKILL.md +1 -1
- package/openxiangda-skills/skills/openxiangda-workflow-automation/SKILL.md +3 -0
- package/package.json +26 -23
- package/packages/sdk/dist/{ProcessPreview-Cyk6uv-w.d.mts → ProcessPreview-DSUIJi5V.d.mts} +2 -3
- package/packages/sdk/dist/{ProcessPreview-Cyk6uv-w.d.ts → ProcessPreview-DSUIJi5V.d.ts} +2 -3
- package/packages/sdk/dist/components/index.d.mts +41 -42
- package/packages/sdk/dist/components/index.d.ts +41 -42
- package/packages/sdk/dist/{dataManagementApi-CE8Zyj3a.d.ts → dataManagementApi-Ro9itwm8.d.ts} +2 -2
- package/packages/sdk/dist/{dataManagementApi-4fSaCA5t.d.mts → dataManagementApi-p_HOhQnA.d.mts} +2 -2
- package/packages/sdk/dist/runtime/index.d.mts +3 -4
- package/packages/sdk/dist/runtime/index.d.ts +3 -4
- package/packages/sdk/dist/runtime/react.d.mts +5 -5
- package/packages/sdk/dist/runtime/react.d.ts +5 -5
- package/packages/sdk/src/build-source/scripts/utils/mime-types.mjs +70 -70
- package/packages/sdk/src/build-source/scripts/utils/oss-client.mjs +128 -128
- package/packages/sdk/src/build-source/scripts/utils/progress.mjs +57 -57
- package/templates/openxiangda-react-spa/.cursor/rules/openxiangda-resources.mdc +1 -0
- package/templates/openxiangda-react-spa/.cursor/rules/openxiangda.mdc +6 -0
- package/templates/openxiangda-react-spa/.qoder/rules/openxiangda-resources.md +1 -0
- package/templates/openxiangda-react-spa/.qoder/rules/openxiangda.md +6 -0
- package/templates/openxiangda-react-spa/AGENTS.md +8 -0
- package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-resources.mdc +2 -0
- package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda.mdc +7 -1
- package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-resources.md +1 -0
- package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda.md +7 -1
- package/templates/sy-lowcode-app-workspace/AGENTS.md +9 -1
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# OpenXiangda 1.x Inbound Webhooks
|
|
2
|
+
|
|
3
|
+
Inbound Webhook 用于让门禁、支付、IoT 等外部系统主动调用 OpenXiangda
|
|
4
|
+
应用。平台只负责通用接入:接收和保存原始请求、限制大小、按幂等键串行化、
|
|
5
|
+
调用唯一绑定的 App Function,并把 Function 的处理结果映射为稳定 HTTP 状态。
|
|
6
|
+
供应商签名规则、事件筛选和业务写入始终属于应用 Function。
|
|
7
|
+
|
|
8
|
+
## 声明 Webhook
|
|
9
|
+
|
|
10
|
+
在 `src/resources/webhooks/<code>.json` 创建 Manifest:
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"code": "yuquan_access",
|
|
15
|
+
"name": "玉泉门禁开门事件",
|
|
16
|
+
"description": "接收 REC_SUCCESS 事件并匹配琴房预约",
|
|
17
|
+
"targetFunctionCode": "qfyy_access_event",
|
|
18
|
+
"idempotencyQueryParam": "nonce",
|
|
19
|
+
"maxBodyBytes": 262144,
|
|
20
|
+
"status": "active"
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `targetFunctionCode` 必须是同一租户、同一应用内已经启用的 Function。
|
|
25
|
+
- `idempotencyQueryParam` 默认是 `nonce`。该参数为空时,平台使用请求摘要。
|
|
26
|
+
- `maxBodyBytes` 默认 256 KiB,允许范围为 1 KiB 到 1 MiB。
|
|
27
|
+
- 平台网关对公开入口统一限制 1 MiB,并按来源 IP 限制 100 请求/秒、突发
|
|
28
|
+
200;超限返回 429。该限制不代替验签和业务幂等。
|
|
29
|
+
- Manifest 不得包含 Webhook Secret、签名算法或供应商凭据。
|
|
30
|
+
- 发布后从 `.openxiangda/state.json` 的
|
|
31
|
+
`resources.webhooks.<code>.callbackUrl` 取得完整回调地址;`callbackPath` 是相对
|
|
32
|
+
当前 profile API base(通常为 `<origin>/service`)的路径。不要自行用 `appType`
|
|
33
|
+
拼接公开 URL。
|
|
34
|
+
|
|
35
|
+
## 声明和配置 Secret
|
|
36
|
+
|
|
37
|
+
Webhook Secret 使用现有 App Function Secret。Function 必须使用
|
|
38
|
+
`function_v2 + trusted_node_v2`,并在 Manifest 顶层声明引用:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"code": "qfyy_access_event",
|
|
43
|
+
"name": "处理玉泉门禁事件",
|
|
44
|
+
"secretRefs": [
|
|
45
|
+
{ "name": "yuquan_webhook_secret", "required": true }
|
|
46
|
+
],
|
|
47
|
+
"definitionJson": {
|
|
48
|
+
"version": "function_v2",
|
|
49
|
+
"runtimeMode": "trusted_node",
|
|
50
|
+
"runtimeContractVersion": "trusted_node_v2",
|
|
51
|
+
"timeoutMs": 30000,
|
|
52
|
+
"sourceFile": {
|
|
53
|
+
"localPath": "src/functions/qfyy_access_event/index.ts"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"status": "active"
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Webhook Function 的 `timeoutMs` 必须在 1 到 120000 毫秒之间。平台在配置和
|
|
61
|
+
每次调用时都会重新校验运行时契约,Function 后续被禁用、降级为旧运行时或把
|
|
62
|
+
超时调到上限之外时,Webhook 会返回可重试的非 2xx,而不会以宽权限身份执行。
|
|
63
|
+
|
|
64
|
+
Secret 值只通过隐藏输入或标准输入写入平台:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
openxiangda secret create yuquan_webhook_secret \
|
|
68
|
+
--value-stdin --change <change-id> --profile <name>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
禁止把值写进 Webhook/Function Manifest、源码、`.env`、日志、异常或函数返回值。
|
|
72
|
+
|
|
73
|
+
## Function 输入
|
|
74
|
+
|
|
75
|
+
Function 的第二个参数和 `ctx.input` 都是以下对象:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
interface WebhookInput {
|
|
79
|
+
deliveryId: string;
|
|
80
|
+
idempotencyKey: string;
|
|
81
|
+
webhookCode: string;
|
|
82
|
+
receivedAt: string;
|
|
83
|
+
rawBody: string;
|
|
84
|
+
rawBodyBase64: string;
|
|
85
|
+
rawQueryString: string;
|
|
86
|
+
query: Record<string, string[]>;
|
|
87
|
+
headers: Record<string, string[]>;
|
|
88
|
+
body: unknown;
|
|
89
|
+
request: { method: "POST"; path: string };
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`query` 保留重复参数及其顺序。`rawBody` 是签名使用的原始 UTF-8 文本;
|
|
94
|
+
`body` 只用于验签成功后的业务解析。平台会从 `headers` 中移除 Authorization、
|
|
95
|
+
Cookie、代理凭据和客户端证书头。
|
|
96
|
+
|
|
97
|
+
## 验签顺序
|
|
98
|
+
|
|
99
|
+
验签、时间窗和事件来源检查必须发生在任何 `ctx.form`、`ctx.dataView`、
|
|
100
|
+
`ctx.connector`、`ctx.notification`、`ctx.platform` 或 `ctx.utils.http` 调用之前。
|
|
101
|
+
永远不要对 `input.body` 再 `JSON.stringify` 后验签,空格、字段顺序或转义变化会
|
|
102
|
+
使签名失真。
|
|
103
|
+
|
|
104
|
+
下面展示 HMAC-SHA1 和常量时间比较。`buildCanonicalText` 只是结构示例;必须按
|
|
105
|
+
供应商正式文档确认字段顺序、分隔符、URL 编码和 hex/base64 输出格式:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
109
|
+
import type { AppFunctionContextV2 } from "openxiangda/runtime";
|
|
110
|
+
|
|
111
|
+
type WebhookInput = {
|
|
112
|
+
deliveryId: string;
|
|
113
|
+
idempotencyKey: string;
|
|
114
|
+
rawBody: string;
|
|
115
|
+
query: Record<string, string[]>;
|
|
116
|
+
body: unknown;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
function first(query: Record<string, string[]>, name: string) {
|
|
120
|
+
return String(query[name]?.[0] || "");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function equalEncodedSignature(actual: string, expected: string) {
|
|
124
|
+
const left = Buffer.from(actual.trim().toLowerCase(), "utf8");
|
|
125
|
+
const right = Buffer.from(expected.trim().toLowerCase(), "utf8");
|
|
126
|
+
return left.length === right.length && timingSafeEqual(left, right);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function buildCanonicalText(input: WebhookInput) {
|
|
130
|
+
// Replace this illustrative order with the provider's exact contract.
|
|
131
|
+
return [
|
|
132
|
+
first(input.query, "nonce"),
|
|
133
|
+
first(input.query, "timestamp"),
|
|
134
|
+
first(input.query, "orgId"),
|
|
135
|
+
input.rawBody,
|
|
136
|
+
].join("");
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export default async function handleWebhook(
|
|
140
|
+
ctx: AppFunctionContextV2,
|
|
141
|
+
input: WebhookInput,
|
|
142
|
+
) {
|
|
143
|
+
const secret = await ctx.secrets.get("yuquan_webhook_secret");
|
|
144
|
+
const expected = createHmac("sha1", secret)
|
|
145
|
+
.update(buildCanonicalText(input), "utf8")
|
|
146
|
+
.digest("hex");
|
|
147
|
+
const actual = first(input.query, "signature");
|
|
148
|
+
if (!actual || !equalEncodedSignature(actual, expected)) {
|
|
149
|
+
return { webhook: { outcome: "rejected", status: 401 } };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const timestamp = Number(first(input.query, "timestamp"));
|
|
153
|
+
if (!Number.isFinite(timestamp) || Math.abs(Date.now() - timestamp) > 5 * 60_000) {
|
|
154
|
+
return { webhook: { outcome: "rejected", status: 401 } };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const event = input.body as {
|
|
158
|
+
callbackTag?: string;
|
|
159
|
+
data?: {
|
|
160
|
+
isAuth?: boolean;
|
|
161
|
+
deviceSn?: string;
|
|
162
|
+
jobNum?: string;
|
|
163
|
+
recognizeTime?: string;
|
|
164
|
+
recognizeType?: number;
|
|
165
|
+
memberId?: string;
|
|
166
|
+
personType?: number;
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
if (event.callbackTag !== "REC_SUCCESS" || event.data?.isAuth !== true) {
|
|
170
|
+
return { webhook: { outcome: "ignored" } };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// The application must atomically claim input.idempotencyKey in its own
|
|
174
|
+
// business record before creating/updating reservation data.
|
|
175
|
+
await processAccessEventIdempotently(ctx, input.idempotencyKey, event.data);
|
|
176
|
+
return { webhook: { outcome: "accepted" } };
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`processAccessEventIdempotently` 是应用函数中的业务实现,不是平台内置 API。应把
|
|
181
|
+
`idempotencyKey` 写入带唯一约束或等价原子保护的业务记录,然后再执行副作用。
|
|
182
|
+
平台提供 at-least-once 投递;如果 Function 已产生副作用,但进程在成功回执落库前
|
|
183
|
+
中断,同一事件会再次执行。
|
|
184
|
+
|
|
185
|
+
## 返回契约
|
|
186
|
+
|
|
187
|
+
- 普通返回,或 `{ webhook: { outcome: "accepted" } }`:HTTP 200。
|
|
188
|
+
- `{ webhook: { outcome: "ignored" } }`:HTTP 200,适合已验签但无需处理的事件。
|
|
189
|
+
- `{ webhook: { outcome: "rejected", status: 400|401|403|409|422 } }`:指定 4xx。
|
|
190
|
+
- `{ webhook: { outcome: "retry" } }` 或抛出异常:HTTP 503,通知供应商重试。
|
|
191
|
+
|
|
192
|
+
平台不会把 Function 返回值、日志、异常详情或 Secret 回显给外部调用方。
|
|
193
|
+
投递原始请求和审计信息默认保留 180 天,由平台部署环境统一配置;应用不应把
|
|
194
|
+
Webhook 投递表当作永久业务档案,需要长期保存的字段应在验签后写入自己的表单。
|
|
195
|
+
|
|
196
|
+
## 校验、发布和诊断
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
openxiangda resource validate webhook --profile <name>
|
|
200
|
+
openxiangda resource plan webhook --only yuquan_access --profile <name> --json
|
|
201
|
+
openxiangda resource publish webhook --only yuquan_access \
|
|
202
|
+
--change <change-id> --profile <name>
|
|
203
|
+
|
|
204
|
+
openxiangda webhook list --profile <name> --json
|
|
205
|
+
openxiangda webhook get yuquan_access --profile <name> --json
|
|
206
|
+
openxiangda webhook deliveries yuquan_access --profile <name> --json
|
|
207
|
+
openxiangda webhook delivery yuquan_access <delivery-id> --profile <name> --json
|
|
208
|
+
openxiangda webhook disable yuquan_access \
|
|
209
|
+
--change <change-id> --profile <name>
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
先发布并验证 Function,再启用 Webhook。新 Function 与 Webhook 同轮交付时,可以
|
|
213
|
+
先以 `status: "disabled"` 发布 Webhook,验证 Function 后再把状态改为 `active`。
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
OpenXiangda durable project bindings live in `.openxiangda/state.json`. Volatile release execution, candidate, deployment, and recovery progress lives under the private `.openxiangda/releases/` journal and must not be copied into the durable ID map.
|
|
4
4
|
|
|
5
|
-
Tokens
|
|
5
|
+
Tokens are private workspace files and must never be committed. User tokens live in `.openxiangda/profiles.json`. Shared workspace env values such as `APP_OSS_*` live in `~/.openxiangda/.env` by default, while project `.env` is only a local override.
|
|
6
6
|
|
|
7
7
|
## Shape
|
|
8
8
|
|
|
@@ -181,7 +181,7 @@ openxiangda platform use dev
|
|
|
181
181
|
|
|
182
182
|
Root, `/platform`, and `/view` URLs normalize to `<origin>/service`. Normal work uses the user's profile token and `/openxiangda-api/v1`; never ask for AK/SK. Each profile has independent `appType` and resource IDs.
|
|
183
183
|
|
|
184
|
-
Durable local resource/environment mappings live in `.openxiangda/state.json`; volatile candidate/deployment progress lives in the private `.openxiangda/releases/` journal. User tokens live in
|
|
184
|
+
Durable local resource/environment mappings live in `.openxiangda/state.json`; volatile candidate/deployment progress lives in the private `.openxiangda/releases/` journal. User tokens live in `.openxiangda/profiles.json`; shared environment values live in `~/.openxiangda/.env`. Never copy resource IDs between profiles or commit workspace login files.
|
|
185
185
|
|
|
186
186
|
For an environment-managed workspace with more than one target, `function invoke` requires an explicit `--environment <target>` and prints the resolved profile, environment, kind, appType, and environmentId to stderr before the request. Treat this line as part of the diagnostic evidence; do not infer production behavior from an invocation whose resolved target is preproduction.
|
|
187
187
|
|
|
@@ -105,6 +105,8 @@ JS_CODE is the backend execution escape hatch for workflow and automation. Use i
|
|
|
105
105
|
|
|
106
106
|
App Function is the reusable backend execution model. Use it when the logic should be called by custom pages, multiple automations, workflows, or the runtime API. Source lives in `src/functions/<functionCode>/index.ts`; manifest lives in `src/resources/functions/<functionCode>.json`. Call it from pages with `sdk.function.invoke(code, { input })`, from graph definitions with `function_call`, or from the runtime endpoint `/:appType/v1/functions/:code/invoke.json`. Direct runtime invocation defaults to app automation management permission; ordinary page callers must declare `definitionJson.runtimeInvoke.audience` (`authenticated`, `page_permission_group`, `app_roles`, or `scope_policy`). Prefer `export default async function(ctx, input) {}` for App Function source; the second argument is the invoke input and the same value is available as `ctx.input`. Current MVP exposes controlled helpers only and does not expose raw SQL or Redis. App Functions and trusted-node Automation scripts can call `ctx.files.readAsBase64` with an attachment from the current `ctx.formData`, or with a server-verified form record/field reference. This helper reads platform storage without a browser session, rejects arbitrary URLs and non-images, caps files at 10 MiB, and must be used without logging or persisting the Base64. App Functions can call `ctx.process.startFromExistingInstance`, `resolveCapabilities`, `resubmitTask`, `withdraw`, and `transferTask`; published trusted code may access resources in its current tenant/application, while workflow/task authorization, audit, event, replay, cross-app, and cross-tenant boundaries remain enforced. `resources` is optional mapping/audit metadata rather than an application-internal authorization list. Keep internal forms closed to direct user submit unless the business explicitly needs raw form submission; use `runtimeWrite.mode="function_only"` for function-only forms.
|
|
107
107
|
|
|
108
|
+
For inbound third-party callbacks, declare `src/resources/webhooks/<code>.json` with a fixed `targetFunctionCode`; do not expose `appType` as a public routing identifier and do not put provider verification fields or Secret values in the Webhook manifest. The Function must use `input.rawBody` for signature verification before any data/helper/network call, read only top-level declared `secretRefs`, and use `input.idempotencyKey` to protect business writes because delivery is at-least-once. Read `references/webhooks.md` for the complete envelope, HMAC example, response directives, publish commands, and delivery diagnosis.
|
|
109
|
+
|
|
108
110
|
For third-party credentials, use top-level metadata-only `secretRefs` plus `definitionJson.version="function_v2"` and `runtimeContractVersion="trusted_node_v2"`; read a declared value with `await ctx.secrets.get(name)` and call public business APIs through `ctx.utils.http`. Never use `process.env` for platform secrets. Values are managed with `openxiangda secret create|rotate --value-stdin --change <change> --profile <name>` and never appear in Git, build output, snapshots, plan diffs, logs, exceptions, or traces. Local tests may use `function test --secret-from-env logical=ENV` only; the value is passed to an isolated child over stdin and is never written to workspace/cache/state. For a Root App transaction, use exact-scope `resource publish function --only <code> --stage-only` and include its verified `stagedResource` in `release app-finalize`.
|
|
109
111
|
|
|
110
112
|
For new AI-authored automations, prefer code-first `automation_code_ts` resources instead of visual v3 graph definitions. Put the source in `src/automations/<resourceCode>/index.ts`, define `definition.code.json` with `kind: "automation_code_ts"`, and provide `preview.json` for read-only frontend display. Use `ctx.logger.debug/info/warn/error(message, data?)` at every important step; OpenXiangda can inspect logs with `automation executions`, `automation logs`, and `automation diagnose`.
|
|
@@ -199,3 +201,4 @@ Use `automation disable` before risky edits. Published automations create a draf
|
|
|
199
201
|
- Notification resources and runtime calls: `references/notifications.md`
|
|
200
202
|
- API fields: `references/openxiangda-api.md`
|
|
201
203
|
- Profile-isolated IDs: `references/workspace-state.md`
|
|
204
|
+
- Inbound Webhook declaration, verification, idempotency, and delivery diagnosis: `references/webhooks.md`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openxiangda",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.270",
|
|
4
4
|
"description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"bin": {
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"source:admin-list": "node scripts/sync-admin-list-source.mjs",
|
|
69
69
|
"check": "node --check bin/openxiangda.js && node --check lib/*.js && node --check packages/sdk/src/build-source/src/cli.mjs && node --check packages/sdk/src/build-source/scripts/*.mjs && node --check packages/sdk/src/build-source/scripts/utils/*.mjs",
|
|
70
70
|
"test": "npm run test:fast",
|
|
71
|
-
"test:fast": "npm run check && node scripts/delivery-v2-package-smoke.mjs && node scripts/delivery-v2-executor-smoke.mjs && node scripts/delivery-v2-release-conformance-smoke.mjs && node scripts/http-proxy-smoke.mjs && node scripts/form-export-cli-smoke.mjs && node scripts/open-api-cli-smoke.mjs && node scripts/release-plan-smoke.mjs && node scripts/typed-resource-plan-smoke.mjs && node scripts/integration-bundle-smoke.mjs && node scripts/content-cache-smoke.mjs && node scripts/dependency-capsule-smoke.mjs && node scripts/sdd-stages-smoke.mjs && node scripts/environment-swap-cli-smoke.mjs && node scripts/environment-policy-cli-smoke.mjs",
|
|
71
|
+
"test:fast": "npm run check && node scripts/delivery-v2-package-smoke.mjs && node scripts/delivery-v2-executor-smoke.mjs && node scripts/delivery-v2-release-conformance-smoke.mjs && node scripts/http-proxy-smoke.mjs && node scripts/form-export-cli-smoke.mjs && node scripts/open-api-cli-smoke.mjs && node scripts/release-plan-smoke.mjs && node scripts/typed-resource-plan-smoke.mjs && node scripts/webhook-resource-cli-smoke.mjs && node scripts/integration-bundle-smoke.mjs && node scripts/content-cache-smoke.mjs && node scripts/dependency-capsule-smoke.mjs && node scripts/sdd-stages-smoke.mjs && node scripts/environment-swap-cli-smoke.mjs && node scripts/environment-policy-cli-smoke.mjs",
|
|
72
72
|
"test:changed": "npm run check && node scripts/run-test-suite.mjs --changed --evidence",
|
|
73
73
|
"test:contract": "npm run check && node scripts/run-test-suite.mjs --contract --evidence",
|
|
74
74
|
"test:release": "npm run check && node scripts/run-test-suite.mjs --release --evidence",
|
|
@@ -80,6 +80,7 @@
|
|
|
80
80
|
"test:content-cache": "node scripts/content-cache-smoke.mjs",
|
|
81
81
|
"test:dependency-capsule": "node scripts/dependency-capsule-smoke.mjs",
|
|
82
82
|
"test:typed-resource-plan": "node scripts/typed-resource-plan-smoke.mjs",
|
|
83
|
+
"test:webhook-resource": "node scripts/webhook-resource-cli-smoke.mjs",
|
|
83
84
|
"test:integration-bundle": "node scripts/integration-bundle-smoke.mjs",
|
|
84
85
|
"prepublishOnly": "npm run release:evidence:verify && node scripts/release-mainline-guard.mjs",
|
|
85
86
|
"prepack": "npm run source:admin-list && npm run build:sdk",
|
|
@@ -146,7 +147,9 @@
|
|
|
146
147
|
"test:skill-install": "bash scripts/skill-install-smoke.sh",
|
|
147
148
|
"test:workspace-init": "bash scripts/workspace-init-smoke.sh",
|
|
148
149
|
"open-api:sync": "node scripts/sync-dingtalk-openapi.mjs",
|
|
149
|
-
"open-api:verify": "node scripts/sync-dingtalk-openapi.mjs --check"
|
|
150
|
+
"open-api:verify": "node scripts/sync-dingtalk-openapi.mjs --check",
|
|
151
|
+
"test:migration-advice": "node scripts/migration-advice-smoke.mjs",
|
|
152
|
+
"test:workspace-auth": "node scripts/workspace-auth-smoke.mjs"
|
|
150
153
|
},
|
|
151
154
|
"dependencies": {
|
|
152
155
|
"@ant-design/cssinjs": "^1.23.0",
|
|
@@ -230,43 +233,43 @@
|
|
|
230
233
|
},
|
|
231
234
|
"openxiangdaRelease": {
|
|
232
235
|
"schemaVersion": "openxiangda.release-notes/v1",
|
|
233
|
-
"version": "1.0.
|
|
234
|
-
"title": "OpenXiangda V1
|
|
236
|
+
"version": "1.0.270",
|
|
237
|
+
"title": "OpenXiangda V1 Inbound Webhook",
|
|
235
238
|
"status": "reviewed",
|
|
236
|
-
"summary": "
|
|
239
|
+
"summary": "V1 应用可以声明公开 Inbound Webhook,由平台可靠接入并转发给固定 App Function,供应商验签和业务处理仍由应用负责。",
|
|
237
240
|
"newFeatures": [
|
|
238
|
-
"
|
|
241
|
+
"新增 src/resources/webhooks/*.json 资源声明、校验、计划、发布、拉取和停用能力。",
|
|
242
|
+
"新增 webhook list/get/create/update/upsert/disable/deliveries/delivery 命令,用于配置和投递诊断。",
|
|
243
|
+
"Webhook Function 获得原始 Body、原始 Query、重复参数数组、安全 Headers、投递 ID 和幂等键。"
|
|
239
244
|
],
|
|
240
245
|
"fixes": [
|
|
241
|
-
"
|
|
242
|
-
"
|
|
243
|
-
"V1 主 Skill 使用 openxiangda-v1 名称,安装时保留统一入口和 V2 技能。",
|
|
244
|
-
"V1 发布仅允许 legacy-v1 渠道,防止维护版覆盖 V2 的 latest。"
|
|
246
|
+
"Function 资源在 Webhook 之前发布,prune 对遗失的 Webhook 执行停用而不是删除审计数据。",
|
|
247
|
+
"模板、Skill、命令发现和 API 参考统一说明 rawBody 验签、secretRefs 和业务幂等要求。"
|
|
245
248
|
],
|
|
246
249
|
"affectedUsers": [
|
|
247
|
-
"
|
|
248
|
-
"已经安装全局统一入口的 V1 用户"
|
|
250
|
+
"需要接收门禁、支付、IoT 或其他第三方主动回调的 OpenXiangda V1 应用开发者。"
|
|
249
251
|
],
|
|
250
252
|
"compatibility": {
|
|
251
253
|
"node": ">=18;全局 V2 统一入口需要 >=24",
|
|
252
254
|
"workspaceGenerations": [
|
|
253
255
|
"v1"
|
|
254
256
|
],
|
|
255
|
-
"workspacePolicy": "
|
|
256
|
-
"platformPolicy": "
|
|
257
|
+
"workspacePolicy": "现有 V1 资源保持兼容;只有声明 webhooks 的应用会创建公开回调端点。",
|
|
258
|
+
"platformPolicy": "必须部署包含 V1 Webhook 管理/公开入口、SQL 迁移和网关规则的平台版本。App Function Secret 必须按部署规范启用。"
|
|
257
259
|
},
|
|
258
260
|
"upgradeSteps": [
|
|
259
|
-
"
|
|
260
|
-
"
|
|
261
|
-
"
|
|
262
|
-
"
|
|
261
|
+
"将 V1 项目依赖锁定到 openxiangda@1.0.270 或运行同代 update install。",
|
|
262
|
+
"执行 skill install --force 和 skill bootstrap --force,阅读 references/webhooks.md。",
|
|
263
|
+
"先发布声明 secretRefs 的 trusted_node_v2 Function,再声明并发布 Webhook。",
|
|
264
|
+
"从 .openxiangda/state.json 读取 callbackUrl,配置到供应商并用投递查询命令完成验签、重试和幂等验收。"
|
|
263
265
|
],
|
|
264
266
|
"knownLimitations": [
|
|
265
|
-
"
|
|
266
|
-
"
|
|
267
|
+
"首版公开入口只接受 application/json 的 HTTP POST,单端点 Body 上限不超过 1 MiB。",
|
|
268
|
+
"平台不内置供应商签名算法;Function 必须按照供应商正式协议使用 rawBody 验签。",
|
|
269
|
+
"投递语义为 at-least-once,应用必须用 input.idempotencyKey 原子保护业务副作用。"
|
|
267
270
|
],
|
|
268
271
|
"issues": [],
|
|
269
|
-
"sha256": "
|
|
270
|
-
"url": "https://github.com/1377385356/openxiangda-v1/releases/tag/v1.0.
|
|
272
|
+
"sha256": "7ec9e6eebb0b509833283274bde2fdfba48a099c76cea862f77a08441a4ef1dd",
|
|
273
|
+
"url": "https://github.com/1377385356/openxiangda-v1/releases/tag/v1.0.270"
|
|
271
274
|
}
|
|
272
275
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React__default, { ReactNode } from 'react';
|
|
2
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
2
|
|
|
4
3
|
type FormSectionVariant = 'plain' | 'card';
|
|
5
4
|
type FormSectionAccent = 'blue' | 'green';
|
|
@@ -18,7 +17,7 @@ interface FormSectionProps {
|
|
|
18
17
|
contentClassName?: string;
|
|
19
18
|
children: React__default.ReactNode;
|
|
20
19
|
}
|
|
21
|
-
declare function FormSection({ title, description, variant, accent, icon, iconKey, collapsible, defaultCollapsed, className, titleClassName, contentClassName, children, }: FormSectionProps):
|
|
20
|
+
declare function FormSection({ title, description, variant, accent, icon, iconKey, collapsible, defaultCollapsed, className, titleClassName, contentClassName, children, }: FormSectionProps): React__default.JSX.Element;
|
|
22
21
|
|
|
23
22
|
/** 字段行为状态 */
|
|
24
23
|
type FieldBehavior = 'NORMAL' | 'READONLY' | 'DISABLED' | 'HIDDEN';
|
|
@@ -1290,4 +1289,4 @@ interface ProcessPreviewProps {
|
|
|
1290
1289
|
}
|
|
1291
1290
|
declare const ProcessPreview: React__default.FC<ProcessPreviewProps>;
|
|
1292
1291
|
|
|
1293
|
-
export { type
|
|
1292
|
+
export { type DepartmentSelectFieldProps as $, type ApprovalPermission as A, type ReturnParams as B, type ChangeRecordQueryParams as C, type SaveTaskParams as D, type TransferParams as E, type FieldDefinition as F, type TextFieldProps as G, type TextAreaFieldProps as H, type InitiatorSelectCandidate as I, type SelectFieldProps as J, type RadioFieldProps as K, type CheckboxFieldProps as L, type MultiSelectFieldProps as M, type NumberFieldProps as N, type OptionItem as O, type ProcessStatus as P, type DateFieldProps as Q, type RuntimeResponse as R, type StatusMeta as S, type TaskStatus as T, type CascadeDateFieldProps as U, type ValidationPreset as V, type WithdrawParams as W, type AttachmentFieldProps as X, type ImageFieldProps as Y, type SubFormFieldProps as Z, type UserSelectFieldProps as _, type FormRuntimeApi as a, type ImageVariant as a$, type CascadeSelectFieldProps as a0, type AddressFieldProps as a1, type AssociationFormFieldProps as a2, type EditorFieldProps as a3, type EditorChoiceOption as a4, type SerialNumberFieldProps as a5, type LocationFieldProps as a6, type DigitalSignatureFieldProps as a7, type JSONFieldProps as a8, type AttachmentItem as a9, type DefaultValueLinkageConfig as aA, type DepartmentSearchParams as aB, type DepartmentSearchResult as aC, type DepartmentSearchScope as aD, type DepartmentTreeNode as aE, type DigitalSignatureValue as aF, type EditorToolbarAction as aG, type FieldLayoutNode as aH, type FieldValueSyncConfig as aI, type FilePreviewCapabilityBatch as aJ, type FilePreviewProvider as aK, type FilePreviewRenderMode as aL, type FilePreviewSurface as aM, type FilePreviewType as aN, type FormEffectAction as aO, type FormEffectCondition as aP, type FormEffectConditionOperator as aQ, type FormEngineMode as aR, type FormLayoutNode as aS, FormSection as aT, type FormSectionProps as aU, type FormSubmitBehavior as aV, type FormTemplateConfig as aW, type GridLayoutCell as aX, type GridLayoutNode as aY, type ImageCompressionConfig as aZ, type ImageCompressionVariantConfig as a_, type PreparedFilePreview as aa, type FilePreviewCapability as ab, type FilePreviewMetadata as ac, type FilePreviewRequest as ad, type ProcessAction as ae, type InitiatorSelectedApprovers as af, type ReturnPolicy as ag, type ChangeRecord as ah, type StandardFormPageMode as ai, type LowcodePageSchema as aj, type AddressValue as ak, type ApprovalActionType as al, ApprovalTimeline as am, type ApprovalTimelineProps as an, type AssociationFormConfig as ao, type AssociationValue as ap, type AttachmentImageVariants as aq, type BaseFieldProps as ar, type BaseLayoutNode as as, type DataFilter as at, type DataLinkageCondition as au, type DataLinkageConfig as av, type DateRangeRestriction as aw, type DateRestrictionConfig as ax, type DateShortcutConfig as ay, type DateShortcutType as az, type FormSchema as b, type InitiatorSelectScope as b0, type JSONFieldEditorContext as b1, type JSONFieldRendererContext as b2, type LayoutVisibleWhen as b3, type LinkedFormOptionConfig as b4, type LocationValue as b5, type LowcodePageMeta as b6, type LowcodePageNode as b7, type LowcodePageNodeType as b8, type OptionSourceType as b9, type PeopleShortcutConfig as ba, type PeopleShortcutType as bb, type PreviewImageItem as bc, type ProcessNodeType as bd, ProcessPreview as be, type ProcessPreviewProps as bf, type RuntimeAuthHeadersProvider as bg, type RuntimeDataQueryParams as bh, type RuntimeDataQueryResult as bi, type RuntimeRequestConfig as bj, type RuntimeUploadOptions as bk, type RuntimeUploadProvider as bl, type SectionLayoutNode as bm, type SignaturePoint as bn, type StepLayoutItem as bo, type StepsLayoutNode as bp, type SubFormColumn as bq, type TabLayoutItem as br, type TabsLayoutNode as bs, type TextShortcutConfig as bt, type TextShortcutType as bu, type UserDisplayFormat as bv, type UserItem as bw, type FormRuntimeApiConfig as c, type FormEngineConfig as d, type FieldBehavior as e, type FormRuntimeConfig as f, type FormAppearanceConfig as g, type ValidationRule as h, type FormEffect as i, type OptionSourceConfig as j, type FormDataDeleteParams as k, type ChangeRecordListResponse as l, type FormDataQueryParams as m, type FormInstanceData as n, type InitiatorSelectRequirement as o, type ProcessBasicInfo as p, type ProcessDefinition as q, type ProcessTask as r, type ReturnableNodeResult as s, type ReturnableNode as t, type ViewPermissionQueryParams as u, type ViewPermissionSummary as v, type ApproveParams as w, type PreviewParams as x, type ProcessRoute as y, type ResubmitParams as z };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React__default, { ReactNode } from 'react';
|
|
2
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
2
|
|
|
4
3
|
type FormSectionVariant = 'plain' | 'card';
|
|
5
4
|
type FormSectionAccent = 'blue' | 'green';
|
|
@@ -18,7 +17,7 @@ interface FormSectionProps {
|
|
|
18
17
|
contentClassName?: string;
|
|
19
18
|
children: React__default.ReactNode;
|
|
20
19
|
}
|
|
21
|
-
declare function FormSection({ title, description, variant, accent, icon, iconKey, collapsible, defaultCollapsed, className, titleClassName, contentClassName, children, }: FormSectionProps):
|
|
20
|
+
declare function FormSection({ title, description, variant, accent, icon, iconKey, collapsible, defaultCollapsed, className, titleClassName, contentClassName, children, }: FormSectionProps): React__default.JSX.Element;
|
|
22
21
|
|
|
23
22
|
/** 字段行为状态 */
|
|
24
23
|
type FieldBehavior = 'NORMAL' | 'READONLY' | 'DISABLED' | 'HIDDEN';
|
|
@@ -1290,4 +1289,4 @@ interface ProcessPreviewProps {
|
|
|
1290
1289
|
}
|
|
1291
1290
|
declare const ProcessPreview: React__default.FC<ProcessPreviewProps>;
|
|
1292
1291
|
|
|
1293
|
-
export { type
|
|
1292
|
+
export { type DepartmentSelectFieldProps as $, type ApprovalPermission as A, type ReturnParams as B, type ChangeRecordQueryParams as C, type SaveTaskParams as D, type TransferParams as E, type FieldDefinition as F, type TextFieldProps as G, type TextAreaFieldProps as H, type InitiatorSelectCandidate as I, type SelectFieldProps as J, type RadioFieldProps as K, type CheckboxFieldProps as L, type MultiSelectFieldProps as M, type NumberFieldProps as N, type OptionItem as O, type ProcessStatus as P, type DateFieldProps as Q, type RuntimeResponse as R, type StatusMeta as S, type TaskStatus as T, type CascadeDateFieldProps as U, type ValidationPreset as V, type WithdrawParams as W, type AttachmentFieldProps as X, type ImageFieldProps as Y, type SubFormFieldProps as Z, type UserSelectFieldProps as _, type FormRuntimeApi as a, type ImageVariant as a$, type CascadeSelectFieldProps as a0, type AddressFieldProps as a1, type AssociationFormFieldProps as a2, type EditorFieldProps as a3, type EditorChoiceOption as a4, type SerialNumberFieldProps as a5, type LocationFieldProps as a6, type DigitalSignatureFieldProps as a7, type JSONFieldProps as a8, type AttachmentItem as a9, type DefaultValueLinkageConfig as aA, type DepartmentSearchParams as aB, type DepartmentSearchResult as aC, type DepartmentSearchScope as aD, type DepartmentTreeNode as aE, type DigitalSignatureValue as aF, type EditorToolbarAction as aG, type FieldLayoutNode as aH, type FieldValueSyncConfig as aI, type FilePreviewCapabilityBatch as aJ, type FilePreviewProvider as aK, type FilePreviewRenderMode as aL, type FilePreviewSurface as aM, type FilePreviewType as aN, type FormEffectAction as aO, type FormEffectCondition as aP, type FormEffectConditionOperator as aQ, type FormEngineMode as aR, type FormLayoutNode as aS, FormSection as aT, type FormSectionProps as aU, type FormSubmitBehavior as aV, type FormTemplateConfig as aW, type GridLayoutCell as aX, type GridLayoutNode as aY, type ImageCompressionConfig as aZ, type ImageCompressionVariantConfig as a_, type PreparedFilePreview as aa, type FilePreviewCapability as ab, type FilePreviewMetadata as ac, type FilePreviewRequest as ad, type ProcessAction as ae, type InitiatorSelectedApprovers as af, type ReturnPolicy as ag, type ChangeRecord as ah, type StandardFormPageMode as ai, type LowcodePageSchema as aj, type AddressValue as ak, type ApprovalActionType as al, ApprovalTimeline as am, type ApprovalTimelineProps as an, type AssociationFormConfig as ao, type AssociationValue as ap, type AttachmentImageVariants as aq, type BaseFieldProps as ar, type BaseLayoutNode as as, type DataFilter as at, type DataLinkageCondition as au, type DataLinkageConfig as av, type DateRangeRestriction as aw, type DateRestrictionConfig as ax, type DateShortcutConfig as ay, type DateShortcutType as az, type FormSchema as b, type InitiatorSelectScope as b0, type JSONFieldEditorContext as b1, type JSONFieldRendererContext as b2, type LayoutVisibleWhen as b3, type LinkedFormOptionConfig as b4, type LocationValue as b5, type LowcodePageMeta as b6, type LowcodePageNode as b7, type LowcodePageNodeType as b8, type OptionSourceType as b9, type PeopleShortcutConfig as ba, type PeopleShortcutType as bb, type PreviewImageItem as bc, type ProcessNodeType as bd, ProcessPreview as be, type ProcessPreviewProps as bf, type RuntimeAuthHeadersProvider as bg, type RuntimeDataQueryParams as bh, type RuntimeDataQueryResult as bi, type RuntimeRequestConfig as bj, type RuntimeUploadOptions as bk, type RuntimeUploadProvider as bl, type SectionLayoutNode as bm, type SignaturePoint as bn, type StepLayoutItem as bo, type StepsLayoutNode as bp, type SubFormColumn as bq, type TabLayoutItem as br, type TabsLayoutNode as bs, type TextShortcutConfig as bt, type TextShortcutType as bu, type UserDisplayFormat as bv, type UserItem as bw, type FormRuntimeApiConfig as c, type FormEngineConfig as d, type FieldBehavior as e, type FormRuntimeConfig as f, type FormAppearanceConfig as g, type ValidationRule as h, type FormEffect as i, type OptionSourceConfig as j, type FormDataDeleteParams as k, type ChangeRecordListResponse as l, type FormDataQueryParams as m, type FormInstanceData as n, type InitiatorSelectRequirement as o, type ProcessBasicInfo as p, type ProcessDefinition as q, type ProcessTask as r, type ReturnableNodeResult as s, type ReturnableNode as t, type ViewPermissionQueryParams as u, type ViewPermissionSummary as v, type ApproveParams as w, type PreviewParams as x, type ProcessRoute as y, type ResubmitParams as z };
|