openxiangda 1.0.159 → 1.0.161
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 +39 -13
- package/lib/change-baseline.js +1077 -0
- package/lib/cli.js +12002 -6723
- package/lib/config.js +272 -7
- package/lib/http.js +2 -0
- package/lib/js-code-build.js +61 -0
- package/lib/publish-context.js +98 -0
- package/lib/publish-lease-heartbeat.js +182 -0
- package/lib/publish-lease.js +190 -0
- package/lib/release-telemetry.js +182 -0
- package/lib/runtime-lineage.js +297 -0
- package/lib/sdd.js +567 -35
- package/lib/source-dependencies.js +742 -0
- package/lib/workspace-init.js +6 -1
- package/lib/worktree-owner.js +219 -0
- package/openxiangda-skills/SKILL.md +103 -228
- package/openxiangda-skills/references/architecture-design.md +2 -1
- package/openxiangda-skills/references/openxiangda-api.md +27 -0
- package/openxiangda-skills/references/pages/page-sdk.md +11 -1
- package/openxiangda-skills/references/resource-manifest-cheatsheet.md +12 -2
- package/openxiangda-skills/references/workspace-state.md +2 -0
- package/openxiangda-skills/skills/openxiangda-core/SKILL.md +77 -243
- package/openxiangda-skills/skills/openxiangda-form/SKILL.md +8 -0
- package/openxiangda-skills/skills/openxiangda-page/SKILL.md +18 -0
- package/package.json +20 -1
- package/packages/sdk/dist/{ProcessPreview-DMkzccq4.d.mts → ProcessPreview-Dux73lY_.d.mts} +5 -0
- package/packages/sdk/dist/{ProcessPreview-DMkzccq4.d.ts → ProcessPreview-Dux73lY_.d.ts} +5 -0
- package/packages/sdk/dist/components/index.cjs +29 -1
- package/packages/sdk/dist/components/index.cjs.map +1 -1
- package/packages/sdk/dist/components/index.d.mts +4 -4
- package/packages/sdk/dist/components/index.d.ts +4 -4
- package/packages/sdk/dist/components/index.mjs +29 -1
- package/packages/sdk/dist/components/index.mjs.map +1 -1
- package/packages/sdk/dist/{dataManagementApi-C9O-Bb0j.d.ts → dataManagementApi-BNLH2o7f.d.ts} +2 -1
- package/packages/sdk/dist/{dataManagementApi-gpZkgRDM.d.mts → dataManagementApi-BOcIx4U-.d.mts} +2 -1
- package/packages/sdk/dist/runtime/index.cjs +150 -22
- package/packages/sdk/dist/runtime/index.cjs.map +1 -1
- package/packages/sdk/dist/runtime/index.d.mts +3 -3
- package/packages/sdk/dist/runtime/index.d.ts +3 -3
- package/packages/sdk/dist/runtime/index.mjs +150 -22
- package/packages/sdk/dist/runtime/index.mjs.map +1 -1
- package/packages/sdk/dist/runtime/react.cjs +121 -21
- package/packages/sdk/dist/runtime/react.cjs.map +1 -1
- package/packages/sdk/dist/runtime/react.d.mts +15 -2
- package/packages/sdk/dist/runtime/react.d.ts +15 -2
- package/packages/sdk/dist/runtime/react.mjs +121 -21
- package/packages/sdk/dist/runtime/react.mjs.map +1 -1
- package/packages/sdk/src/build-source/scripts/register.mjs +54 -23
- package/packages/sdk/src/build-source/scripts/sync-schema.mjs +59 -19
- package/packages/sdk/src/build-source/scripts/utils/form-api.mjs +242 -2
- package/templates/openxiangda-react-spa/.cursor/rules/openxiangda-resources.mdc +7 -3
- package/templates/openxiangda-react-spa/.cursor/rules/openxiangda.mdc +11 -4
- package/templates/openxiangda-react-spa/.qoder/rules/openxiangda-resources.md +7 -3
- package/templates/openxiangda-react-spa/.qoder/rules/openxiangda.md +10 -4
- package/templates/openxiangda-react-spa/AGENTS.md +25 -12
- package/templates/openxiangda-react-spa/scripts/build-js-code.mjs +344 -60
- package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-resources.mdc +5 -1
- package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda.mdc +8 -2
- package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-resources.md +8 -4
- package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda.md +8 -2
- package/templates/sy-lowcode-app-workspace/AGENTS.md +14 -4
- package/templates/sy-lowcode-app-workspace/scripts/build-js-code.mjs +344 -60
|
@@ -1,253 +1,128 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: openxiangda
|
|
3
|
-
description: "Use OpenXiangda for
|
|
3
|
+
description: "Use OpenXiangda for private low-code platform work: app workspaces, forms, pages, resources, functions, automations, workflows, permissions, publishing, deployment, diagnosis, profiles, and the openxiangda CLI."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# OpenXiangda
|
|
7
7
|
|
|
8
|
-
OpenXiangda
|
|
9
|
-
|
|
10
|
-
OpenXiangda supports two workspace modes. Classic `sy-lowcode-app-workspace` publishes form/page bundles with `openxiangda workspace publish`. Phase 6 `react-spa` workspaces are standard React/Vite apps: publish resources with `openxiangda resource publish`, then publish the frontend dist with `openxiangda runtime deploy`. Do not send React SPA routes through old `isRenderNav`, app-shell, or workbench page parameters.
|
|
11
|
-
|
|
12
|
-
## TL;DR — Decision Card
|
|
13
|
-
|
|
14
|
-
**If the workspace has `.openxiangda/state.json` or `app-workspace.config.ts`, you are in an OpenXiangda app workspace. Read this card before any tool call.**
|
|
15
|
-
|
|
16
|
-
### Routing — user intent → skill / command
|
|
17
|
-
|
|
18
|
-
| User says (zh / en) | Skill | First command |
|
|
19
|
-
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
20
|
-
| 发布 classic workspace / 上线旧模式 | `openxiangda-core` | `openxiangda workspace publish --profile <name> --changed --dry-run` |
|
|
21
|
-
| 发布 React SPA / Phase 6 runtime | `openxiangda-core` | `openxiangda resource publish --profile <name>` then `openxiangda runtime deploy --profile <name>` |
|
|
22
|
-
| 只发布改动 / 增量 / 单页 / 单表 | `openxiangda-core` | `... --changed` / `--page <code>` / `--form <code>` / `--only pages/a,forms/b` |
|
|
23
|
-
| 架构设计 / 详细设计 / 新应用需求 / 需求文档转享搭应用 | `openxiangda-architecture-design` | read `references/architecture-design.md`; inspect workspace/app state before coding |
|
|
24
|
-
| 创建应用 / 新建 app / scaffold / 初始化工作区 | `openxiangda-app` | `openxiangda workspace init <dir> --profile <name> --app-name "..."` |
|
|
25
|
-
| 绑定已有应用 / bind existing app | `openxiangda-app` | `openxiangda workspace bind --profile <name> --app-type APP_XXX` |
|
|
26
|
-
| 创建 / 修改表单字段 / 表单页 / schema | `openxiangda-form` | edit `src/forms/<code>/{schema.ts,page.tsx}` → `workspace publish --form <code>` |
|
|
27
|
-
| 导出表单数据 / 图片 / 附件 / Excel / zip | `openxiangda-form` | `openxiangda form export <formCode> --mode xlsx|xlsx-images|package --profile <name>` |
|
|
28
|
-
| 创建 / 修改自定义代码页 / portal / dashboard | `openxiangda-page` | edit `src/pages/<code>/` → `workspace publish --page <code>` |
|
|
29
|
-
| 审批流程 / workflow / 流程节点 / JS_CODE | `openxiangda-workflow-automation` | `openxiangda workflow validate / create / publish` |
|
|
30
|
-
| 自动化 / 定时任务 / 提交触发 / cron | `openxiangda-workflow-automation` | `openxiangda automation validate / create / publish / enable` |
|
|
31
|
-
| App Function / function_call / 可复用后端逻辑 | `openxiangda-workflow-automation` | declare `src/resources/functions/<code>.json` + `src/functions/<code>/index.ts` |
|
|
32
|
-
| 应用登录 / Auth SDK / 手机号验证码 / CAS / 钉钉免登 | `openxiangda-architecture-design` + `openxiangda-page` | design security gate first, then declare `src/resources/auth/<code>.json` and use `createAuthClient` / `LoginPage` |
|
|
33
|
-
| 账号权限 / 角色 / 权限组 / 字段权限 / 数据范围 / RBAC | `openxiangda-permission-settings` | `openxiangda design gates --topic permissions --json` → choose permission mode → `openxiangda permission ...` / `openxiangda settings ...` |
|
|
34
|
-
| 平台部门 / 平台账号 / 重置密码 / 组织账号管理 | `openxiangda-architecture-design` + `openxiangda-page` | check `openxiangda organization capabilities --json`; use `sdk.organization` / `ctx.organization` only after `app:organization:manage` is granted |
|
|
35
|
-
| 外部人员无需登录访问 / 公开报名 / 公开查询 / public page | `openxiangda-architecture-design` + `openxiangda-permission-settings` + `openxiangda-page` | 先确认公开范围、外部角色、ticket、grants;再声明 `routes` + `public-access`,并用 `OpenXiangdaProvider` + `OpenXiangdaPageProvider` + `PublicAccessGate` |
|
|
36
|
-
| 看应用结构 / 快照 / 对比 / 诊断 / 排查 / 报错 | `openxiangda-inspect` | `openxiangda app snapshot <APP_XXX> --profile <name> --json` |
|
|
37
|
-
| 登录 / 切换平台 / profile / token / whoami | `openxiangda-core` | `openxiangda env --profile <name>` / `openxiangda auth status` |
|
|
38
|
-
| 多表只读联表 / 固定口径统计 / 强实时复杂查询 / 看板指标 | `openxiangda-form` (data view) | declare `src/resources/data-views/<code>.json` with `storageMode` → `resource publish` |
|
|
39
|
-
| 调外部 / 第三方 API / 钉钉 / 自建系统 | `openxiangda-page` (connector) | declare `src/resources/connectors/<code>.json` → `sdk.connector.invoke` |
|
|
40
|
-
| 外部后端 / 三方系统调用享搭 / AK/SK / 开放接口 | `openxiangda-open-api` | `openxiangda open-api spec list --search <keyword> --json` → describe the selected operation |
|
|
41
|
-
|
|
42
|
-
### Hard rules — always
|
|
43
|
-
|
|
44
|
-
- ✅ Publish classic workspaces through `openxiangda workspace publish --profile <name>`; publish React SPA forms first with `openxiangda workspace publish --form <formCode>`, then resources/runtime through `openxiangda resource validate` → `openxiangda resource publish --dry-run` → `openxiangda resource publish` → `openxiangda runtime deploy`.
|
|
45
|
-
- ✅ High-risk changes must be attached to OpenXiangda SDD v2 records before implementation/publish. Run `openxiangda sdd context --json`; for forms/pages/resources/functions/automations/workflows/JS_CODE/runtime/config changes create or continue `openxiangda sdd propose <change>`, wait for user confirmation, run `openxiangda sdd approve <change>`, then complete `coverage.json`, `release.json`, `evidence.md`, and `tasks.md` before `openxiangda sdd verify <change> --changed`.
|
|
46
|
-
- ✅ Before publishing AI-authored changes, run `openxiangda workspace plan --changed --json` and `openxiangda workspace check --changed`. Fix reported fake IDs, fallback data, direct `/openxiangda-api` page calls, missing schema, or resource/runtime omissions before publish.
|
|
47
|
-
- ✅ When unsure about runtime response shape, run `openxiangda contract explain <contract-name> --json`. `sdk.form.create` returns identifiers and generated serial number values only; fetch detail explicitly for full row data, formula results, or other server-generated fields.
|
|
48
|
-
- ✅ Architecture-class requests are plan-gated by default. For 新应用、复杂页面、登录注册、公开访问、权限数据范围、流程自动化、连接器/通知、外部集成, first run `openxiangda doctor --json` when a workspace exists and `openxiangda design gates --topic <code> --json`; then ask the user to confirm the design. Before confirmation, only read files, inspect/snapshot, dry-run, ask questions, and write/output design docs. Do not edit source files, write platform resources, send notifications, publish, or deploy.
|
|
49
|
-
- ✅ `runtime deploy` defaults to staged multipart `dist/` uploads plus a final manifest. Use `--upload-mode legacy-json` only for old platform servers.
|
|
50
|
-
- ✅ User token lives in `~/.openxiangda/profiles.json`; project state in `.openxiangda/state.json` (IDs only).
|
|
51
|
-
- ✅ Each profile (dev / prod / ...) has its own `appType` and resource IDs; never copy a `formUuid` / `pageId` / `workflowId` / `automationId` across profiles.
|
|
52
|
-
- ✅ Run `openxiangda update check --json` at the start of substantial work; if `updateAvailable`, run `openxiangda update install` and `openxiangda skill install --force`.
|
|
53
|
-
- ✅ For non-trivial app requirements, run the architecture design gate first: forms, fields, pages, permissions, data views, status/workflow, automation, notifications, and development tasks must be decided before coding.
|
|
54
|
-
- ✅ For app login/auth requirements, run the auth security gate before coding: enabled methods, registration policy, identity matching keys, provider boundary, default roles, rate limits, audit fields, and third-party ownership must be confirmed.
|
|
55
|
-
- ✅ For public/no-login access requirements, run the public access design gate before coding: public routes, external role codes, guest vs ticket, form/dataView/function/connector/storage grants, backend permission groups, and visible loading/error fallback states must be confirmed. New React SPA apps use `/view/:appType/public/*`, `src/resources/routes/`, `src/resources/public-access/`, and `PublicAccessGate`; route children that use Page SDK hooks must be inside `OpenXiangdaProvider` + `OpenXiangdaPageProvider`.
|
|
56
|
-
- ✅ For account/role/permission/data-scope/query-param authorization requirements, run `openxiangda design gates --topic permissions --json` before coding. Pick one mode from `managed-platform-account`, `existing-platform-user-assignment`, `static-role-permission`, or `query-param-context`, write the permission matrix, and use roles/page-groups/form-groups/App Functions for real enforcement.
|
|
57
|
-
- ✅ Public/no-login validation must inspect the JSON envelope, not only HTTP status. HTTP 200 with `code: "PUBLIC_GRANT_DENIED"` is a denied request; success requires `code` `200`, `"200"`, or compatible `0`, and no `success: false`.
|
|
58
|
-
- ✅ Use first-class resource CLI commands for discovery, diagnosis, and small live fixes: `route`, `public-access`, `auth-config`, `function`, `connector`, `notification`, `organization`, `data-view`, `menu`, and `permission`. For multi-resource formal development, still prefer `src/resources/**` + `openxiangda resource validate|plan|publish`. If a direct CLI write is intentionally used, add `--write-manifest` when the repository should stay the source of truth.
|
|
59
|
-
- ✅ For form-entry UX, pick components in this order: OpenXiangda platform form components → `antd` / `antd-mobile` wrappers → custom component only when neither exists.
|
|
60
|
-
- ✅ In React SPA apps, keep imports on public package entrypoints such as `openxiangda`, `openxiangda/runtime`, and `openxiangda/runtime/react`. The default template already groups large vendor chunks; if a bundle is too large, use route-level lazy loading and Vite `manualChunks`, not `openxiangda/packages/sdk/dist/...` internal paths.
|
|
61
|
-
- ✅ For image thumbnails or lightweight previews, use `imageCompression` on `ImageField` or `AttachmentField`. Keep the original `url` for the source file and use `thumbUrl` / `previewUrl` / `variants` for smaller images.
|
|
62
|
-
- ✅ In form context, let `ImageField` and `AttachmentField` own preview UX. In standalone React SPA pages, use `AttachmentPreviewList`, `ImagePreviewGrid`, or `useFilePreview` from `openxiangda/runtime/react`; do not create a fake form context or import internal `FilePreviewContent` / `useFilePreviewController`. All paths must honor platform capability checks, and apps must not maintain local previewable-extension allowlists.
|
|
63
|
-
- ✅ When a custom editable React SPA surface genuinely needs `FormProvider`, set `config.api` from `usePageFormRuntimeApi()`; use `createPageFormRuntimeApi(sdk)` outside hooks. Never implement the bridge as `api.request: config => sdk.request(...)`, because JSON transport drops `responseType: "blob"` and breaks binary attachment previews.
|
|
64
|
-
- ✅ For data delivery with files, use `openxiangda form export <formCode> --mode xlsx|xlsx-images|package --profile <name>`. `package` writes a zip with `data.xlsx`, `attachments/`, and `manifest.json`; do not hand-write export URLs or stream binary content to stdout.
|
|
65
|
-
- ✅ List pages, linked options, remote selectors, and report drill-downs must use paginated server-side queries with explicit searchable fields. Do not fetch a large page and filter in local state.
|
|
66
|
-
- ✅ Treat workflow forms as an exception. Ordinary ticket/order/task/asset lifecycles use status fields, state machines, action logs, permissions, and automations; workflows are for real approval tasks.
|
|
67
|
-
- ✅ Proactively submit platform feedback when you discover a defect, missing capability, unclear rule, repeated workaround, user-visible UX gap, or implementation uncertainty worth improving.
|
|
68
|
-
|
|
69
|
-
### Hard rules — never
|
|
70
|
-
|
|
71
|
-
- ❌ `pnpm publish:all` / `pnpm publish:oss` / `pnpm register` / `lowcode-workspace publish-*` directly — they are workspace internals and miss the profile token injection. Use `openxiangda workspace publish ...` instead.
|
|
72
|
-
- ❌ Asking the user to paste `AK` / `SK` / `appKey` / `appSecret` into chat. Normal OpenXiangda flows use the user token; authorized external backend work uses `open-api credential` for a direct secure handoff.
|
|
73
|
-
- ❌ Searching the platform for a similar app name when `.openxiangda/state.json` has no binding — create a new app with `workspace init --app-name`.
|
|
74
|
-
- ❌ Using `openxiangda form create` / `form publish` / `page publish` as the normal page generation path. They are low-level repair commands.
|
|
75
|
-
- ❌ Implementing an architecture-class request before the user confirms the design. This includes creating files, mutating platform resources, publishing runtime, sending notifications, or calling live write/delete endpoints.
|
|
76
|
-
- ❌ Running a full publish after editing one file. Default to `--changed --dry-run` → `--changed`, or targeted `--page` / `--form`.
|
|
77
|
-
- ❌ Generating fake form instance IDs, mock rows, fallback schemas, or fallback display data to make a broken API path look successful.
|
|
78
|
-
- ❌ Treating query parameters, frontend button hiding, hardcoded roles, mock role context, or `PermissionBoundary` alone as sensitive authorization. Query parameters may provide context or ticket input only; sensitive data still needs public-access grants, platform roles, form permission groups, or App Function checks.
|
|
79
|
-
- ❌ Storing tokens, AK, SK, or third-party API secrets in project files. Shared env (`APP_OSS_*`, feedback robot) goes to `~/.openxiangda/.env`.
|
|
80
|
-
- ❌ Raw native HTML form controls in AI-authored workspace code (`<input>`, `<select>`, `<textarea>`, file inputs, hand-written pickers, hand-written upload controls). They are allowed only inside OpenXiangda SDK/platform component internals.
|
|
81
|
-
- ❌ Using `?publicAccess=guest` or form `publicAccess` settings for new React SPA apps. Those are legacy `sy-lowcode-view` compatibility only.
|
|
82
|
-
- ❌ Importing OpenXiangda SDK internals such as `openxiangda/packages/sdk/dist/components/index.mjs` from business apps. Public entrypoints are the compatibility boundary; SDK build optimization belongs in OpenXiangda, not app-local deep imports.
|
|
83
|
-
|
|
84
|
-
## Platform Routing
|
|
85
|
-
|
|
86
|
-
Private platform routing is fixed:
|
|
87
|
-
|
|
88
|
-
- Backend services are under `/service`.
|
|
89
|
-
- Platform management UI is under `/platform`.
|
|
90
|
-
- App runtime access is under `/view`.
|
|
91
|
-
|
|
92
|
-
When the user provides a root domain such as `https://yida.wisejob.cn/`, use it directly with the CLI; OpenXiangda normalizes the API base to `https://yida.wisejob.cn/service`. If the user provides a copied `/platform` or `/view` URL, treat it as the same platform and normalize to `/service`. Do not call `/openxiangda-api/v1` at the root domain.
|
|
93
|
-
|
|
94
|
-
## Required Flow
|
|
95
|
-
|
|
96
|
-
1. Ask for the target platform domain if it is not known.
|
|
97
|
-
2. Configure a profile:
|
|
98
|
-
```bash
|
|
99
|
-
openxiangda platform add dev https://dev-lowcode.example.com
|
|
100
|
-
openxiangda platform use dev
|
|
101
|
-
```
|
|
102
|
-
3. If not logged in, run:
|
|
103
|
-
```bash
|
|
104
|
-
openxiangda login --profile dev
|
|
105
|
-
```
|
|
106
|
-
Or combine domain and login:
|
|
107
|
-
```bash
|
|
108
|
-
openxiangda login https://dev-lowcode.example.com --profile dev
|
|
109
|
-
```
|
|
110
|
-
4. Check the CLI version and current context before any write:
|
|
111
|
-
```bash
|
|
112
|
-
openxiangda update check --json
|
|
113
|
-
openxiangda env --profile dev
|
|
114
|
-
openxiangda auth status --profile dev
|
|
115
|
-
```
|
|
116
|
-
If `updateAvailable` is true, update from the official npm registry before continuing:
|
|
117
|
-
```bash
|
|
118
|
-
openxiangda update install
|
|
119
|
-
```
|
|
120
|
-
5. Ensure there is a local app workspace. Local workspace state is authoritative:
|
|
121
|
-
- If the current workspace already has `.openxiangda/state.json` with an app binding for the target profile, use that app.
|
|
122
|
-
- If the user explicitly provides an `appType` or asks to reuse an existing app, bind to that exact app.
|
|
123
|
-
- If the current folder is empty or has no local app binding, create a new app and workspace; do not search the platform for similar app names.
|
|
124
|
-
```bash
|
|
125
|
-
openxiangda workspace init ./my-app-workspace --profile dev --app-name "示例应用"
|
|
126
|
-
cd ./my-app-workspace
|
|
127
|
-
pnpm install
|
|
128
|
-
```
|
|
129
|
-
6. To bind an existing app only when explicitly requested:
|
|
130
|
-
```bash
|
|
131
|
-
openxiangda workspace init ./my-app-workspace --profile dev --app-type APP_XXXX
|
|
132
|
-
# or, inside an existing workspace:
|
|
133
|
-
openxiangda workspace bind --profile dev --app-type APP_XXXX
|
|
134
|
-
```
|
|
135
|
-
7. Publish from the local workspace:
|
|
136
|
-
```bash
|
|
137
|
-
openxiangda workspace publish --profile dev
|
|
138
|
-
```
|
|
139
|
-
8. For multi-platform publishing, always pass `--profile` explicitly:
|
|
140
|
-
```bash
|
|
141
|
-
openxiangda workspace publish --profile prod
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
## Rules
|
|
145
|
-
|
|
146
|
-
- Never ask the user for `appKey`, `appSecret`, `AK`, or `SK`.
|
|
147
|
-
- If `openxiangda` is not available in PATH, the CLI package is not installed or linked. In this repo, use `npm link`; in a packaged install, use `npm install -g openxiangda@latest --registry=https://registry.npmjs.org`.
|
|
148
|
-
- Always prefer the official npm registry for OpenXiangda updates. Domestic mirrors may lag and return an older package.
|
|
149
|
-
- Run `openxiangda update check --json` when starting substantial work or diagnosing version/skill mismatches. If it reports an update, run `openxiangda update install` so the CLI and installed skills match. If the installed CLI does not support `update`, run `npm install -g openxiangda@latest --registry=https://registry.npmjs.org` and then `openxiangda skill install --force`.
|
|
150
|
-
- Local `.openxiangda/state.json` is the source of truth for app binding. In an empty folder or unbound workspace, create a new app with `workspace init --app-name`; do not infer reuse from similar platform app names.
|
|
151
|
-
- If there is no `sy-lowcode-app-workspace`, create one with `openxiangda workspace init <dir>` before writing forms, pages, or JS_CODE nodes.
|
|
152
|
-
- Never treat `openxiangda form create` as page generation. It only creates a low-level platform form shell for diagnostics or for workspace publish internals. The source of user-facing pages is `sy-lowcode-app-workspace`.
|
|
153
|
-
- Publish normal form pages, workflow form pages, and custom code pages through `openxiangda workspace publish --profile <name>` from the app workspace.
|
|
154
|
-
- For live platform publishing, do not call `lowcode-workspace publish-all`, `pnpm publish:all`, or legacy project scripts such as `scripts/openxiangda-publish.mjs` directly. They are workspace internals and may miss the normal-user token/profile injection. Use `openxiangda workspace publish ...` so `OPENXIANGDA_PROFILE`, `OPENXIANGDA_BASE_URL`, `OPENXIANGDA_ACCESS_TOKEN`, and `OPENXIANGDA_APP_TYPE` are injected consistently.
|
|
155
|
-
- For routine AI edits, avoid reflexive full publish. First run `openxiangda workspace publish --profile <name> --changed --dry-run`, then use `--changed`, `--page <pageCode>`, `--form <formCode>`, or `--only pages/a,forms/b`. Use full publish only when broad shared/config changes intentionally affect many modules.
|
|
156
|
-
- Never store token data in the project directory. User tokens live in `~/.openxiangda/profiles.json`; project state lives in `.openxiangda/state.json` and stores only IDs and mappings.
|
|
157
|
-
- Shared workspace env values such as `APP_OSS_*` should live in `~/.openxiangda/.env` by default. Project `.env` files are only per-workspace overrides.
|
|
158
|
-
- For custom OSS image or attachment upload, declare `src/resources/storage/<code>.json`, then set `uploadProvider: "oss"` and `storageCode` on `AttachmentField` or `ImageField`. If `imageCompression` outputs `webp` or another explicit format, include that extension in storage `allowedExtensions`.
|
|
159
|
-
- For public/no-login image or attachment uploads, declare `grants.storage` in `src/resources/public-access/<code>.json`; do not open `/service/file/upload` globally. Use conservative private bucket grants by default, with explicit bucket, actions, MIME types, extensions, max size, visibility, and pathPrefix. `ImageField` / `AttachmentField` uploads inside `PublicAccessGate` use the public session bearer token injected by `OpenXiangdaProvider`.
|
|
160
|
-
- For suspected platform defects, bugs, missing capabilities, unclear design rules, repeated workarounds, AI uncertainty, or product optimization requests, proactively run `openxiangda feedback submit --yes` with a concise summary and detailed description. Include the command, error, relevant files, and logs/context files when available. If robot env is missing or submission fails, run/record `openxiangda feedback preview` and tell the user what could not be sent. After successful submission, tell the user what was reported and include the feedback fingerprint. The CLI redacts tokens, cookies, secrets, phone numbers, and emails before sending.
|
|
161
|
-
- For form pages, every visible field should have a concise user-facing `placeholder`. Use `tips` only for special constraints or non-obvious business rules; do not add tips to every field.
|
|
162
|
-
- Form pages should display only fields the user needs to see. Use `SelectField` / `RadioField` for enums. For data maintained by another form, such as class, college, customer, or project, use `SelectField` with `optionSource.type: "linkedForm"` so the runtime queries form data through the SDK and builds dropdown options; set `remoteSearch: true` and an explicit `searchFieldId` when the source data can be large. Do not make users maintain raw ID text fields, and do not use `AssociationFormField` for new form work.
|
|
163
|
-
- Permission scope keys, computed fields, sync fields, and developer/internal fields should be present only when needed for permissions or logic, and should normally be derived from visible select/person/department fields and marked `behavior: "HIDDEN"`. For select-derived scalar keys, use `valueSync`.
|
|
164
|
-
- Do not add extra fields for platform system metadata such as creator, updater, creator department, updater department, created time, or updated time unless the user explicitly needs a separate business field; the platform already creates system fields for each form.
|
|
165
|
-
- All visible copy in forms and pages must be written for end users. Do not put implementation notes, developer explanations, schema descriptions, or "this area is generated by..." text into page sections, cards, labels, tips, or empty states.
|
|
166
|
-
- Use logical resource codes in local files. Platform-specific IDs such as `formUuid`, `pageId`, `workflowId`, and `automationId` must be isolated by profile.
|
|
167
|
-
- Put engineering-managed resources in `src/resources/` and use `openxiangda resource validate|plan|publish|pull`. `workspace publish` publishes workspace forms/pages first, then runs non-destructive resource upsert. Only pass `--prune` when the user explicitly wants local manifests to delete platform-side extras.
|
|
168
|
-
- For repeated read-only multi-form queries or predefined dashboard metrics, create a data view manifest in `src/resources/data-views/`. Use `storageMode: "materialized"` for refreshed lists/reports that tolerate delay; use `storageMode: "live"` for bounded real-time joins where source changes must appear immediately. Use row views plus `sdk.dataView.query` for joined lists/lookups; use `viewType: "aggregate"` plus `sdk.dataView.stats` for count/sum/avg/min/max statistics. Add `indexes` only for materialized views. Do not use data views for single-form CRUD, simple linkedForm selects, writes, write-back, unbounded realtime joins, or ad-hoc BI. Read `references/data-views.md` before designing one.
|
|
169
|
-
- For external APIs, create a connector manifest in `src/resources/connectors/` and call it from pages through `sdk.connector`; never put third-party API keys in page source.
|
|
170
|
-
- For reusable backend logic shared by pages, automations, and workflows, create an App Function in `src/resources/functions/<functionCode>.json` plus `src/functions/<functionCode>/index.ts`. Call it from pages with `sdk.function.invoke`, from automation/workflow graphs with `function_call`, or from the runtime endpoint. Direct runtime invocation defaults to app automation management permission; ordinary page callers must use `definitionJson.runtimeInvoke.audience` (`authenticated`, `page_permission_group`, `app_roles`, or `scope_policy`). `roleCodes` remains only for current app-role grants; never use `"*"` or `"all-app-roles"` there. Current App Function MVP exposes controlled helpers such as `ctx.resources`, `ctx.form.queryOne/queryMany/getById/createOne/updateOne/updateById`, `ctx.dataView`, `ctx.connector`, `ctx.notification`, `ctx.organization`, `ctx.platform.roles`, and `ctx.platform.api`; it does not expose raw SQL or Redis. Use `ctx.platform.roles.list/findByCode/addUsers/removeUser` for app role lookup and membership changes; raw `ctx.platform.api` returns an HTTP response plus platform envelope, so unwrap it explicitly if you use it. Runtime functions also receive trusted role context on `ctx.operator.roleCodes`, `ctx.operator.currentRoleCode`, `ctx.operator.hasFullAccess`, `ctx.currentUser`, and `ctx.permissions`; use these for server-side business authorization. Do not trust role codes sent in page input for sensitive actions. App Function form writes are trusted backend writes governed by declared `resources.forms` and function invocation authorization; do not grant normal users raw submit permission to internal forms just to let `ctx.form.createOne/updateOne/updateById` run. For internal function-only forms, publish form settings with `runtimeWrite.mode="function_only"` to close raw write endpoints.
|
|
171
|
-
- For app-managed platform departments/accounts, use `sdk.organization.departments.*`, `sdk.organization.accounts.*`, `ctx.organization.departments.*`, or `ctx.organization.accounts.*`. The real current user/audit actor must hold `app:organization:manage` on the app; runtime service principals do not bypass this permission. Do not call legacy `/user` or `/department` write endpoints from apps. Do not include `password` in account updates; reset target accounts with `resetPassword`, and change the current user's password with `changeMyPassword({ oldPassword, newPassword })`.
|
|
172
|
-
- For account, role, data-scope, organization-account, RBAC, or query-param authorization designs, read `references/permission-design-patterns.md` and choose a permission mode before writing forms/pages/resources. Formal backends should use platform roles, page permission groups, form permission groups, public-access grants, and App Function role/scope checks; frontend hiding is display only.
|
|
173
|
-
- When a role such as 校区管理员 will create app roles, assign role members, grant role permissions, maintain permission groups, or manage organization accounts, its role manifest must declare the needed `apiPermissionCodes` such as `app:role:manage`, `app:page-permission-group:manage`, `app:form-permission-group:manage`, and `app:organization:manage`. If that administrator creates another administrator role, the new role must also declare its own `apiPermissionCodes`; permissions are not inherited from the creator.
|
|
174
|
-
- If `resource publish` reports a missing API permission point such as `app:role:manage`, treat it as a platform seed/data problem. The platform tenant must have the permission code in `api_permissions`; do not remove the role manifest permission just to make publish pass.
|
|
175
|
-
- For application login, declare auth resources in `src/resources/auth/<code>.json` and publish them with `openxiangda resource publish`. App Function auth providers may validate external credentials and return only an identity assertion; they must never issue tokens, set cookies, or write platform user/binding tables directly. The platform auth service decides create/bind/reject and issues tokens.
|
|
176
|
-
- For external/no-login pages in React SPA apps, declare `src/resources/routes/<code>.json` and `src/resources/public-access/<code>.json`, put the page under `/view/:appType/public/*`, and use `PublicAccessGate` or `createPublicAccessClient`. The route tree must also include `OpenXiangdaPageProvider` inside `OpenXiangdaProvider` before any `usePageSdk()` / `usePageContext()` / `useDataSource()` call; otherwise pages throw `usePageSdkStore 必须在 PageProvider 内使用`. Always provide `fallback` and `errorFallback` for public routes so slow networks, missing tickets, or expired tickets do not render blank pages. Public guest access to forms, dataViews, functions, and connectors is denied unless policy `grants` explicitly names the resource; backend permission groups still apply.
|
|
177
|
-
- When verifying public access, parse the response body and reject string business errors such as `PUBLIC_GRANT_DENIED` even if the HTTP status is 200. Do not use `response.ok` alone as the success condition.
|
|
178
|
-
- Before scaffolding a real app, complex page, data management page, portal shell, status lifecycle, role governance, or automation, read `references/best-practices.md` and pick the architecture first. Prefer copying the relevant pattern from `examples/best-practices/` into `src/` instead of generating a single large page file.
|
|
179
|
-
- Before publishing to another platform, verify the workspace is bound for that profile. Resource IDs from one profile must not be reused for another profile.
|
|
180
|
-
- Use `openxiangda app snapshot <APP_XXX> --profile <name> --json` for diagnosis before changing an existing app.
|
|
181
|
-
- Run write commands that update `.openxiangda/state.json` sequentially within the same workspace. Read-only commands can run in parallel.
|
|
182
|
-
- JS_CODE is backend-executed workflow/automation logic, not frontend page code. Use it when logic must run after a backend trigger such as fixed cron schedules, form date-field schedules, form submit/update/delete/field-change events, or workflow approval/process events.
|
|
183
|
-
- Use JS_CODE for node-local cross-form data queries, create/update/batch update operations, process termination, platform API calls, external HTTP calls, and backend trigger orchestration. For logic that pages, automations, and workflows should reuse through a stable backend entry, prefer App Function. Do not use JS_CODE for simple UI interactions, ordinary form validation, or display-only page behavior.
|
|
184
|
-
- For workflow/automation JS_CODE nodes, prefer V2 `runtimeMode: "trusted_node"`. AI-authored source must be TypeScript under `src/js-code-nodes/<scriptCode>/index.ts`, `src/automations/<resourceCode>/index.ts`, or `src/functions/<functionCode>/index.ts`. `pnpm build-js-code --script <scriptCode>` runs TypeScript validation before bundling, and `sourceFile.localPath` should point to the TS source; the CLI builds, uploads, and replaces it with snapshot metadata during validate/create.
|
|
185
|
-
- Form permission group resources must have stable local codes. Use unique `code` values such as `ticket_reporter_view` and `ticket_repairer_view`; do not rely on the form code when one form has multiple groups.
|
|
186
|
-
- Workflow resources should prefer `workflowFile` + `defineWorkflow` semantic DSL over hand-written raw JSON. For workflows bound by `formCode`, run `openxiangda workspace publish --form <formCode>` first so the process form schema/table is initialized, then run `openxiangda workflow compile <workflow.ts> --check` and `openxiangda resource publish --dry-run --profile <name>` before publish; use `sdk.process.resolveCapabilities(...)` or `ProcessActionBar` / `ProcessTimeline` from `openxiangda/runtime/react` for runtime buttons and timelines instead of hard-coded operation lists. For end-user task centers, use `sdk.workCenter.listItems({ boxType: "todo" | "done" | "cc" | "initiated" })` and `sdk.workCenter.getStats()` instead of reading workflow logs or process-task tables. For delayed approval start from an existing saved draft, first save without starting workflow via `StandardFormPage submitBehavior="save-draft"` or `sdk.form.create({ formUuid, data, saveAsDraft: true, startProcess: false })`; later use `sdk.process.startFromExistingInstance({ formUuid, formInstId })` or `StandardFormPage submitBehavior="start-existing-process"`; do not create a duplicate process instance and delete the draft. For custom workflow UI, return-to-initiator, resubmit, and action payload details, read `references/workflow-v3.md` sections `Cookbook: draft, start, return, resubmit` and `Capability action reference`.
|
|
187
|
-
- Workflow resources can be created as drafts. After resource publish, verify `openxiangda workflow list --profile <name> --json` and run `openxiangda workflow publish <workflowCode> --profile <name>` until `isPublished: true` is visible. `workflow list` hides platform shell workflows with empty `resourceCode` by default; pass `--all` only when diagnosing raw platform rows.
|
|
8
|
+
OpenXiangda connects an AI coding workspace to the private low-code platform through a normal-user profile and `/openxiangda-api/v1`. External backends using AK/SK are a separate `openxiangda-open-api` flow.
|
|
188
9
|
|
|
189
|
-
|
|
10
|
+
This file is a router and safety card. Read only the one or two subskills selected below; do not load every OpenXiangda reference into the same turn.
|
|
11
|
+
|
|
12
|
+
## Decide the track
|
|
13
|
+
|
|
14
|
+
| Intent | Read next | First action |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| Diagnose, snapshot, compare, explain an error | `openxiangda-inspect` | read-only snapshot/inspect |
|
|
17
|
+
| Login, profile, release, CLI/state issue | `openxiangda-core` | resolve explicit profile and workspace |
|
|
18
|
+
| Create or bind an app | `openxiangda-app` | inspect local binding, then init/bind |
|
|
19
|
+
| Form/schema/data view | `openxiangda-form` | inspect the target form and schema |
|
|
20
|
+
| React/classic page | `openxiangda-page` | inspect the target route/page |
|
|
21
|
+
| Function, automation, workflow, JS_CODE | `openxiangda-workflow-automation` | inspect the exact resource codes |
|
|
22
|
+
| Roles, permission groups, data scope | `openxiangda-permission-settings` | produce the permission matrix |
|
|
23
|
+
| New app architecture, auth, public access | `openxiangda-architecture-design` plus the relevant domain skill | run the design gate |
|
|
24
|
+
| External backend/OpenAPI/AK-SK | `openxiangda-open-api` | describe the exact operation |
|
|
25
|
+
|
|
26
|
+
## Scope before work
|
|
27
|
+
|
|
28
|
+
1. Work from the app workspace root and pass `--profile <name>` to every write or release command.
|
|
29
|
+
2. In a shared or dirty checkout, use an isolated Git worktree/branch. `sdd propose|quick|context` automatically claims the current worktree for `CODEX_THREAD_ID`; if another task owns it, stop and move to a separate worktree instead of taking over its files.
|
|
30
|
+
3. Give the task one stable SDD change id. Use `--change <id>` on context, plan, check, verify, publish, and archive commands when supported.
|
|
31
|
+
4. Plan and publish exact resource codes with `--only <codes>` or `--code <code>`; a type-only or full-resource publish is allowed only when the dependency closure intentionally contains the whole type/application.
|
|
32
|
+
5. A React SPA page change rebuilds one application runtime. Commit the complete build input first, upload/preview with `runtime deploy --no-activate`, and promote only from a clean merged release head that descends from the online Runtime source revision.
|
|
33
|
+
|
|
34
|
+
Never infer a release scope from a globally dirty `git status` when multiple changes are present. Never publish a temporary source tree that differs from the reviewed patch.
|
|
35
|
+
|
|
36
|
+
## Risk and approval
|
|
190
37
|
|
|
191
|
-
-
|
|
192
|
-
-
|
|
193
|
-
-
|
|
194
|
-
-
|
|
195
|
-
- `skills/openxiangda-page/SKILL.md`: custom code page development and publishing in `sy-lowcode-app-workspace`.
|
|
196
|
-
- `skills/openxiangda-workflow-automation/SKILL.md`: workflow v3 definitions, automation triggers, publishing, enabling, and profile-isolated IDs.
|
|
197
|
-
- `skills/openxiangda-permission-settings/SKILL.md`: app roles, page permission groups, form permission groups, and settings-oriented guidance.
|
|
198
|
-
- `skills/openxiangda-inspect/SKILL.md`: read-only app and resource diagnosis using snapshots and profile-local resource IDs.
|
|
199
|
-
- `skills/openxiangda-open-api/SKILL.md`: external backend integration through the complete `/dingtalk-api/v1.0` contract and one-time API credential management.
|
|
38
|
+
- **L0 — no SDD:** read-only diagnosis, docs, tests, or tooling changes that do not mutate an app/platform release.
|
|
39
|
+
- **L1 — lightweight change:** copy/style-only UI edits, a single existing resource binding, or an equally narrow reversible fix. Record exact files/resources and verification. If the user already requested the concrete change after seeing its scope, do not ask for a redundant second confirmation.
|
|
40
|
+
- **L2 — full SDD:** forms/schema, business Function behavior, Automation/Workflow, permissions, auth/public access, data writes/migrations, runtime/config, or multi-resource changes.
|
|
41
|
+
- **L3 — full SDD plus promotion confirmation:** destructive/irreversible operations, production migrations, broad permission/public-access expansion, or an app-wide release.
|
|
200
42
|
|
|
201
|
-
|
|
43
|
+
For L2/L3 app work:
|
|
202
44
|
|
|
203
|
-
|
|
45
|
+
```bash
|
|
46
|
+
openxiangda sdd context --changed --change <change> --json
|
|
47
|
+
openxiangda sdd propose <change>
|
|
48
|
+
# record the user's approval, then:
|
|
49
|
+
openxiangda sdd approve <change>
|
|
50
|
+
openxiangda sdd verify <change> --changed --stage implementation
|
|
51
|
+
```
|
|
204
52
|
|
|
205
|
-
|
|
53
|
+
For an eligible L1 edit, create the exact approved record directly; the user's concrete request is the approval, so do not add a redundant proposal/approval loop:
|
|
206
54
|
|
|
207
|
-
|
|
55
|
+
```bash
|
|
56
|
+
openxiangda sdd quick <change> --kind copy --pages <page> --files <file> --summary "<explicit user intent>"
|
|
57
|
+
```
|
|
208
58
|
|
|
209
|
-
|
|
59
|
+
Function quick changes require the complete `--risk-json` assessment; Automation, Workflow, schema, permissions, auth/public access, migrations, destructive and cross-resource changes cannot use quick mode. Before release run `--stage prepublish`; use `postpublish` only after promotion and `archive` only when all evidence exists.
|
|
210
60
|
|
|
211
|
-
##
|
|
61
|
+
## Safe release recipes
|
|
212
62
|
|
|
213
|
-
|
|
63
|
+
Classic workspace, exact page/form:
|
|
214
64
|
|
|
215
|
-
|
|
65
|
+
```bash
|
|
66
|
+
openxiangda workspace plan --change <change> --changed --profile <name> --json
|
|
67
|
+
openxiangda workspace check --change <change> --changed --profile <name>
|
|
68
|
+
openxiangda workspace publish --change <change> --profile <name> --only pages/a,forms/b --dry-run
|
|
69
|
+
openxiangda workspace publish --change <change> --profile <name> --only pages/a,forms/b
|
|
70
|
+
```
|
|
216
71
|
|
|
217
|
-
|
|
218
|
-
- `references/architecture-design.md` — OpenXiangda architecture design gate, anti-pattern rejection, question gates, final design template, and black-box demo scenario.
|
|
219
|
-
- `references/workspace-state.md` — `.openxiangda/state.json` shape and profile isolation rules.
|
|
220
|
-
- `references/connector-resources.md` — `src/resources` manifests, connector schema, App Function boundary, and platform runtime calls.
|
|
221
|
-
- `references/resource-manifest-cheatsheet.md` — 复制即用的 auth / connector / data-view / notification / App Function / workflow / automation / JS_CODE / role / permission group / settings / menu manifest 骨架与运行时调用示例。在创建任何 `src/resources/` 资源前先看这份。
|
|
222
|
-
- `references/data-views.md` — `src/resources/data-views` materialized/live data view resources, DSL, permissions, refresh, CLI commands, and runtime SDK usage.
|
|
223
|
-
- `references/notifications.md` — `src/resources/notifications`, notification templates/type bindings, and `sdk.notification` / `ctx.notification`.
|
|
224
|
-
- `references/best-practices.md` — initialized examples for modular pages, state lifecycles, role governance, permission isolation, high-performance queries, portal shells, workflow boundaries, and automation patterns.
|
|
225
|
-
- `references/permission-design-patterns.md` — account/role/permission design modes: managed platform account, existing user assignment, static role permission, query-param context, and the required resource/permission matrix.
|
|
72
|
+
React SPA resources/runtime:
|
|
226
73
|
|
|
227
|
-
|
|
74
|
+
```bash
|
|
75
|
+
openxiangda resource validate <type> --only <codes> --profile <name>
|
|
76
|
+
openxiangda resource plan <type> --only <codes> --profile <name> --json
|
|
77
|
+
openxiangda runtime deploy --change <change> --profile <name> --no-activate --json
|
|
78
|
+
openxiangda sdd verify <change> --changed --stage prepublish
|
|
79
|
+
openxiangda release begin --change <change> --profile <name>
|
|
80
|
+
openxiangda resource publish <type> --only <codes> --change <change> --profile <name>
|
|
81
|
+
openxiangda runtime activate <reviewedReleaseId> --change <change> --profile <name>
|
|
82
|
+
openxiangda release end --profile <name>
|
|
83
|
+
```
|
|
228
84
|
|
|
229
|
-
-
|
|
230
|
-
- `references/forms/component-registry.md` — supported form components and their props.
|
|
231
|
-
- `references/forms/layout-and-rules.md` — layout containers, field rules, and validation patterns.
|
|
85
|
+
`resource plan` and publish dry-runs are strictly GET/HEAD-only. `READ_ONLY_AUTH_REQUIRED` means the access token expired; run `openxiangda auth refresh --profile <name>` or log in again before retrying. Never add an automatic refresh POST inside a plan.
|
|
232
86
|
|
|
233
|
-
|
|
87
|
+
`release begin --change` freezes the reviewed Git source base plus the selected remote change baseline. Before any live write, the CLI preflights the complete target set. A worktree based on obsolete source fails with `SOURCE_BASE_DIVERGED`; a selected remote field changed after the baseline fails with `RESOURCE_FIELD_CONFLICT`. Resolve/merge, rebuild, and re-plan instead of forcing the old release.
|
|
234
88
|
|
|
235
|
-
- `
|
|
236
|
-
- `references/pages/page-sdk.md` — `openxiangda/runtime` data, connector, data view, notification, organization, and App Function APIs.
|
|
237
|
-
- `references/pages/publish-flow.md` — workspace publish steps for code pages.
|
|
89
|
+
`runtime deploy` separately freezes the clean committed `HEAD` as `sourceRevision` together with the current active Runtime parent before any build or upload. Any deploy whose source does not descend from the online Runtime fails with `RUNTIME_SOURCE_BASE_DIVERGED`, including `--no-activate`; this prevents staging an old preview for later activation. `--no-build` does not bypass this guard. Only an intentional audited rollback may use `--allow-runtime-rollback --reason "<at least 8 characters>"`, and that flag never permits dirty or non-Git input. SDD evidence under `openspec/` and generated/state paths do not make Runtime source dirty.
|
|
238
90
|
|
|
239
|
-
|
|
91
|
+
For a whole-app release, keep changed Runtime/Page/Backend/Form children staged and run `openxiangda release app-finalize --change <change> --staged-resources-json <JSON|file> --profile <name>`. The JSON contains only changed immutable child entries; the CLI overlays Runtime/Page/Backend by singleton kind and FormRelease by `formUuid` onto one authoritative read-only capture, preserving every unmodified active child. It then performs `prepare -> verify -> activateStagedChildren=true`, switching child heads and the App head atomically (`atomic_staged_children_v1`). Never refresh or retry after a conflict. The flow requires the owned stored lease/change baseline and carries the same client session and Git lineage on every write. Omitting the overlay is compatibility-only retrospective aggregation of already-active children.
|
|
240
92
|
|
|
241
|
-
- `
|
|
242
|
-
- `references/automation-v3.md` — automation triggers, conditions, App Function `function_call`, and publishing.
|
|
243
|
-
- `references/permissions-settings.md` — roles, page/form permission groups, settings.
|
|
244
|
-
- `references/permission-design-patterns.md` — required when designing accounts, roles, RBAC, organization-account governance, data scope, or query-param authorization.
|
|
93
|
+
When a Function or Automation is selected because its TypeScript source changed, publishing is source-only by default. Eligible existing Function/Automation updates in the same command use one immutable Backend Release (`prepare -> verify -> activate`) and one database transaction, so a stale member produces zero resource writes and noops do not advance versions/timestamps. Online bindings, input/output contracts, metadata, trigger/view configuration, and enabled/published state remain unchanged. Only an explicit Backend Release `head` HTTP 404 permits the warned compatibility source PATCH. A complete manifest replacement is exceptional and requires exact `--only/--code` plus `--replace-manifest --reason "..."`.
|
|
245
94
|
|
|
246
|
-
|
|
95
|
+
The lease is app-level promotion ownership, while worktree ownership prevents two Codex tasks from editing/publishing through the same source directory. Different worktrees may keep developing and validating. Always run `release end` after promotion or abandonment; stale sessions expire automatically. Use full resource/runtime publish only when the approved dependency closure is app-wide.
|
|
96
|
+
|
|
97
|
+
## Always
|
|
98
|
+
|
|
99
|
+
- Treat `.openxiangda/state.json` as CLI-maintained ID mapping, not a task lock or merge mechanism.
|
|
100
|
+
- Keep resource IDs isolated per profile; never copy IDs from dev to prod.
|
|
101
|
+
- Use platform roles, permission groups, public grants, and backend Function checks for authorization; frontend hiding is presentation only.
|
|
102
|
+
- Keep tokens and secrets out of project files and chat.
|
|
103
|
+
- Use official public SDK entrypoints and platform form/file components.
|
|
104
|
+
- Report platform defects or repeated workarounds with `openxiangda feedback submit --yes` when a configured feedback channel is available.
|
|
105
|
+
- Run `openxiangda update check --json` once at the start of substantial work, when a version mismatch is suspected, or when the cached check is older than one day. Do not repeat it on every confirmation turn.
|
|
106
|
+
|
|
107
|
+
## Never
|
|
108
|
+
|
|
109
|
+
- Do not call `pnpm publish:all`, `pnpm publish:oss`, `pnpm register`, or `lowcode-workspace publish-*` as the live entrypoint.
|
|
110
|
+
- Do not omit `--profile` on writes/releases.
|
|
111
|
+
- Do not run an unscoped full publish after a narrow edit.
|
|
112
|
+
- Do not use query parameters, hard-coded roles, fake IDs/data, or UI visibility as sensitive authorization.
|
|
113
|
+
- Do not ask the user to paste AK/SK/app secrets. Normal work uses the user profile; external integrations use the dedicated credential flow.
|
|
114
|
+
- Do not import SDK internals or hand-build legacy React SPA public/workbench routes.
|
|
115
|
+
|
|
116
|
+
## Subskills
|
|
247
117
|
|
|
248
|
-
-
|
|
249
|
-
-
|
|
250
|
-
-
|
|
251
|
-
-
|
|
252
|
-
-
|
|
253
|
-
-
|
|
118
|
+
- `../openxiangda-core/SKILL.md`
|
|
119
|
+
- `../openxiangda-app/SKILL.md`
|
|
120
|
+
- `../openxiangda-architecture-design/SKILL.md`
|
|
121
|
+
- `../openxiangda-form/SKILL.md`
|
|
122
|
+
- `../openxiangda-page/SKILL.md`
|
|
123
|
+
- `../openxiangda-workflow-automation/SKILL.md`
|
|
124
|
+
- `../openxiangda-permission-settings/SKILL.md`
|
|
125
|
+
- `../openxiangda-inspect/SKILL.md`
|
|
126
|
+
- `../openxiangda-open-api/SKILL.md`
|
|
127
|
+
|
|
128
|
+
Load a reference only when the selected subskill explicitly requires it. Workspace `AGENTS.md` remains authoritative for project-specific constraints.
|
|
@@ -186,7 +186,7 @@ Default: reusable calculations and validations become App Functions; one-off bac
|
|
|
186
186
|
|
|
187
187
|
Ask these before generating any login/auth design:
|
|
188
188
|
|
|
189
|
-
- Which methods are enabled: password, DingTalk in-app free login, CAS/SSO, phone code, guest?
|
|
189
|
+
- Which methods are enabled: password, DingTalk browser OAuth/in-app free login, CAS/SSO, phone code, guest?
|
|
190
190
|
- What is the phone registration policy: reject, auto-create, bind existing only, whitelist, or manual approval?
|
|
191
191
|
- What are the identity match keys and priorities: `phone`, `email`, `externalId`, `unionId`, `jobNumber`, `username`?
|
|
192
192
|
- Which App Function provider validates each external credential, and what identity assertion fields must it return?
|
|
@@ -280,6 +280,7 @@ For simple CRUD/admin lists, design can proceed with the appropriate OpenXiangda
|
|
|
280
280
|
- Auth resources use stable local codes under `src/resources/auth/`.
|
|
281
281
|
- Use `/view/:appType/login` or `LoginPage` from `openxiangda/runtime/react` for default React login.
|
|
282
282
|
- Use `createAuthClient({ appType, servicePrefix })` for custom React login pages.
|
|
283
|
+
- DingTalk `flow: "auto"` uses JSAPI only in a confirmed DingTalk container and otherwise starts platform-managed browser OAuth. The platform owns callback state and secrets; app code supplies only an app-local `returnUrl` through `getDingTalkOAuthUrl`.
|
|
283
284
|
- Phone-code providers are App Functions. They validate send/verify events and return identity assertions; they do not issue tokens or mutate platform users.
|
|
284
285
|
- New-user registration must be explicit, with default roles and identity conflict behavior documented.
|
|
285
286
|
|
|
@@ -78,6 +78,33 @@ Body:
|
|
|
78
78
|
|
|
79
79
|
Requires Bearer token. Revokes the current CLI token session.
|
|
80
80
|
|
|
81
|
+
## App Runtime Auth
|
|
82
|
+
|
|
83
|
+
### POST `/apps/:appType/auth/dingtalk/oauth/start`
|
|
84
|
+
|
|
85
|
+
Starts platform-managed DingTalk browser OAuth for an application. This endpoint is called without an existing app login session. The platform creates and stores one-time callback state; application code must not build the DingTalk authorization URL itself.
|
|
86
|
+
|
|
87
|
+
Body:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"returnUrl": "/view/APP_EXAMPLE/admin"
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`returnUrl` is optional and, when present, must stay under the current application's `/view/:appType/*` routes.
|
|
96
|
+
|
|
97
|
+
Response data:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"loginUrl": "https://login.dingtalk.com/oauth2/auth?...",
|
|
102
|
+
"expiresIn": 600
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The platform-owned callback consumes the one-time state, creates the authenticated platform session, and redirects to the validated `returnUrl`. React applications normally use `LoginPage dingtalkFlow="auto"`; custom login pages call `createAuthClient(...).getDingTalkOAuthUrl({ returnUrl })` and navigate to `loginUrl`.
|
|
107
|
+
|
|
81
108
|
## App Snapshot
|
|
82
109
|
|
|
83
110
|
### GET `/apps/`
|
|
@@ -247,7 +247,7 @@ Application auth:
|
|
|
247
247
|
import { LoginPage, useAuth, useLoginMethods } from "openxiangda/runtime/react";
|
|
248
248
|
|
|
249
249
|
export function DefaultLogin() {
|
|
250
|
-
return <LoginPage />;
|
|
250
|
+
return <LoginPage dingtalkFlow="auto" />;
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
export function CustomPhoneLogin() {
|
|
@@ -269,6 +269,14 @@ import { createAuthClient } from "openxiangda/runtime";
|
|
|
269
269
|
|
|
270
270
|
const auth = createAuthClient({ appType, servicePrefix: "/service" });
|
|
271
271
|
const methods = await auth.getMethods();
|
|
272
|
+
|
|
273
|
+
async function startDingTalkLogin() {
|
|
274
|
+
const { loginUrl } = await auth.getDingTalkOAuthUrl({
|
|
275
|
+
returnUrl: `/view/${encodeURIComponent(appType)}/admin`,
|
|
276
|
+
});
|
|
277
|
+
window.location.assign(loginUrl);
|
|
278
|
+
}
|
|
279
|
+
|
|
272
280
|
const sent = await auth.sendPhoneCode({ phone, purpose: "login" });
|
|
273
281
|
const result = await auth.phoneCodeLogin({
|
|
274
282
|
phone,
|
|
@@ -277,6 +285,8 @@ const result = await auth.phoneCodeLogin({
|
|
|
277
285
|
});
|
|
278
286
|
```
|
|
279
287
|
|
|
288
|
+
`dingtalkFlow="auto"` is the default. It uses DingTalk JSAPI only when both the container and `requestAuthCode` are available; otherwise it starts browser OAuth. Explicit `dingtalkFlow="jsapi"` or `"oauth"` overrides the auth method's `flow` setting. Browser OAuth is a full-page redirect whose callback is handled by the platform, so custom pages should pass an app-local `/view/:appType/*` return URL and must not implement their own callback or OAuth `state`. `LoginPage` normalizes a same-origin absolute guard callback to that relative form and rejects cross-origin or other-app callbacks before making the OAuth start request.
|
|
289
|
+
|
|
280
290
|
For phone-code auth, the App Function provider receives `event`, `appType`, `method`, `credential`, `requestId`, `request`, and `challenge`. It may return `{ ok, providerState }` for send and `{ ok, identity }` for verify. It must not return `token`, `accessToken`, `refreshToken`, cookies, or mutate platform account tables.
|
|
281
291
|
|
|
282
292
|
Public access route:
|
|
@@ -74,7 +74,7 @@ openxiangda permission role-update external_visitor --json-file src/resources/ro
|
|
|
74
74
|
"configJson": {
|
|
75
75
|
"methods": [
|
|
76
76
|
{ "type": "password", "enabled": true, "label": "账号密码" },
|
|
77
|
-
{ "type": "dingtalk", "enabled": true, "label": "
|
|
77
|
+
{ "type": "dingtalk", "enabled": true, "label": "钉钉登录", "flow": "auto" },
|
|
78
78
|
{ "type": "sso", "enabled": true, "label": "CAS", "protocol": "cas" },
|
|
79
79
|
{
|
|
80
80
|
"type": "phone_code",
|
|
@@ -127,7 +127,7 @@ React 默认页:
|
|
|
127
127
|
import { LoginPage } from "openxiangda/runtime/react";
|
|
128
128
|
|
|
129
129
|
export default function AppLogin() {
|
|
130
|
-
return <LoginPage />;
|
|
130
|
+
return <LoginPage dingtalkFlow="auto" />;
|
|
131
131
|
}
|
|
132
132
|
```
|
|
133
133
|
|
|
@@ -138,10 +138,20 @@ import { createAuthClient } from "openxiangda/runtime";
|
|
|
138
138
|
|
|
139
139
|
const auth = createAuthClient({ appType, servicePrefix: "/service" });
|
|
140
140
|
const methods = await auth.getMethods();
|
|
141
|
+
|
|
142
|
+
async function startDingTalkLogin() {
|
|
143
|
+
const { loginUrl } = await auth.getDingTalkOAuthUrl({
|
|
144
|
+
returnUrl: `/view/${encodeURIComponent(appType)}/admin`,
|
|
145
|
+
});
|
|
146
|
+
window.location.assign(loginUrl);
|
|
147
|
+
}
|
|
148
|
+
|
|
141
149
|
const sent = await auth.sendPhoneCode({ phone, purpose: "login" });
|
|
142
150
|
await auth.phoneCodeLogin({ phone, code, challengeId: sent.challengeId });
|
|
143
151
|
```
|
|
144
152
|
|
|
153
|
+
钉钉 `flow: "auto"` 会在确认处于钉钉容器且 JSAPI 可用时走免登,否则走平台托管的浏览器 OAuth。`returnUrl` 只能是当前应用的 `/view/:appType/*` 路径;应用不要自行拼装钉钉授权 URL、保存 OAuth `state` 或实现回调页。
|
|
154
|
+
|
|
145
155
|
设计前必须确认启用方式、注册策略、身份匹配键、provider 边界、默认权限、安全参数、第三方配置归属。
|
|
146
156
|
|
|
147
157
|
## 1. Storage — `src/resources/storage/<code>.json`
|
|
@@ -62,5 +62,7 @@ Tokens never belong in the project. User tokens live in `~/.openxiangda/profiles
|
|
|
62
62
|
- `resources.dataViews` is keyed by data view `code` and stores only profile-local platform metadata such as `dataViewId`, `materializedViewName`, and last known `status`.
|
|
63
63
|
- Data view definitions, refresh config, permissions, and source `formCode` references belong in `src/resources/data-views/*.json`, not in state.
|
|
64
64
|
- Do not store business configuration or secrets in `.openxiangda/state.json`; store those in `src/resources/`.
|
|
65
|
+
- CLI writes use a lock, a three-way merge at profile/resource-key granularity, and fsync + atomic rename. Concurrent writes to different profiles or logical resource keys are preserved; competing writes to the same field fail with `OPENXIANGDA_STATE_CONFLICT` and must be retried from a freshly loaded state.
|
|
66
|
+
- This protects the ID map from truncation/lost updates. Concurrent development still uses separate Git worktrees/branches; `.openxiangda/worktree-owner.json` binds one worktree to one active `CODEX_THREAD_ID` and blocks a second task at SDD context/publish time.
|
|
65
67
|
- A prod publish must not read dev IDs.
|
|
66
68
|
- Before publishing to another platform, run `openxiangda workspace bind --profile <name> --app-type <APP_XXX>`.
|