openxiangda-skill-kit 2.1.0 → 2.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda-skill-kit",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "description": "OpenXiangda 2.0 中文 AI 技能的校验、分发与安装。",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,7 +17,7 @@
17
17
  "README.md"
18
18
  ],
19
19
  "dependencies": {
20
- "openxiangda-devkit-core": "2.9.0"
20
+ "openxiangda-devkit-core": "2.10.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "tsx": "4.23.12",
@@ -1,10 +1,18 @@
1
1
  ---
2
2
  name: openxiangda-v2
3
- description: 使用 OpenXiangda 2.0 从模糊业务想法、已有资料或具体变更出发,通过对话发现模块、完成详细产品设计,使用原版 OpenDesign 桌面和 CLI形成整体视觉与可运行原型,再开发、检查和交付应用。维护 1.x 应用时使用对应的 1.x 技能。
3
+ description: 使用 OpenXiangda 2.0 从模糊业务想法、已有资料或具体变更出发,通过对话发现模块、完成详细产品设计,由 AI 在工作区内调用 OpenDesign 原版 CLI/Skill/MCP 形成整体视觉与可运行原型,再开发、检查和交付应用。OpenDesign 客户端只作为可选预览器;维护 1.x 应用时使用对应的 1.x 技能。
4
4
  ---
5
5
 
6
6
  # OpenXiangda 2.0
7
7
 
8
+ ## 应用结构基线(必须遵守)
9
+
10
+ 每个业务应用默认先建立并保留标准管理后台。管理后台是应用骨架,承载资源模型、表单、数据列表、详情/编辑、权限和流程入口;AI 必须先从后台完成数据与契约,再实现用户端体验。不得因为制作用户端首页而删除、隐藏或替换后台 Shell、后台路由或显式菜单。
11
+
12
+ OpenDesign 按页面归属使用:后台页面可以用 OpenDesign 优化布局、视觉和交互,但必须复用平台后台 Shell、导航、字段行为和权限;用户端 PC 与移动端可以分别使用 OpenDesign 的完整视觉和交互,并通过平台 runtime/Data API 读取后台数据。不得用单页 HTML、iframe 或独立假后台冒充管理后台,也不得在用户端复制后台权限和导航状态。
13
+
14
+ 设计、实现和发布验收必须分别核验管理后台入口、表单、数据列表、流程入口,以及用户端 PC/移动端入口。缺少标准管理后台的应用结构不完整,不能发布。
15
+
8
16
  ## 先理解任务
9
17
 
10
18
  新应用或模糊业务想法先读[对话发现与产品设计](references/product-design.md),从资料和真实流程主动提出模块建议,逐轮少量提问、复述确认并更新 AppSpec。完整首发的 PRD、旅程、逐页交互、视觉/原型、权限与架构形成权威基线后,才制定实施计划和编写业务实现。用户不知道模块时给出有理由的推荐和代价,不能把整套设计问题丢回用户。
@@ -13,7 +21,19 @@ description: 使用 OpenXiangda 2.0 从模糊业务想法、已有资料或具
13
21
 
14
22
  遇到已有 V1 项目时,先核实 V2 能力覆盖、项目是否仍在测试阶段和迁移成本;能力满足、仍在测试阶段且代价可控时,优先建议转用 V2。先做只读评估,再按项目确认详细设计、数据/流程映射、测试和回滚;迁移实施前的原项目维护仍使用匹配的 V1 引擎。
15
23
 
16
- 有界面影响的开发和改版默认读[OpenDesign 工作流](references/design-workflow.md),使用 `openxiangda design open` `design cli` 直接调用原版,随包方法仅作离线参考,形成设计包、可运行原型、浏览器修正和实现交接。保留字段与权限行为,旧默认皮肤或设备偏好可按任务重新设计。设计与原型资源使用 AppSpec assets 固定;不把结构检查或示例数据当成实际验收。
24
+ 有界面影响的开发和改版默认读[OpenDesign 工作流](references/design-workflow.md),由 AI 在当前 OpenXiangda 工作区读取相关 Skill,并通过 `openxiangda design cli` 或原版 stdio MCP 自动完成设计方向、原型、lint、修正和产物交接;不要求用户打开或操作 OpenDesign 客户端。客户端只用于用户主动查看或人工预览。随包方法仅作离线参考,保留字段与权限行为,旧默认皮肤或设备偏好可按任务重新设计。设计与原型资源使用 AppSpec assets 固定;不把结构检查或示例数据当成实际验收。
25
+
26
+ ## AI 自动设计与开发
27
+
28
+ AI 接到新应用、页面或改版任务时,在同一个 OpenXiangda 工作区内执行以下闭环,不把设计任务转交给用户操作客户端:
29
+
30
+ 1. 读取本 Skill、`references/design-workflow.md` 和任务相关的 OpenDesign Skill;从当前 AppSpec、平台契约和用户材料确定页面、角色、设备与验收目标。
31
+ 2. 用 `openxiangda design cli` 查询原版方向、模板、设计系统和插件;需要持续会话时启动 `openxiangda design cli mcp`,把原版设计工具接入当前 AI Agent。所有 CLI 参数、JSON、标准输入输出和取消都由原版处理。
32
+ 3. 在任务工作区创建或复用原版项目,向原版 Agent 提交任务上下文,生成可运行原型;AI 自己读取文件、运行 lint/预览检查并按结果修正。
33
+ 4. 将本轮实际采用的设计文件、token、原型和来源版本复制或导出到 `appspec/design`,然后继续生成 OpenXiangda 页面、字段和业务实现。设计产物与应用源码属于同一变更链,不要求用户在客户端中搬运文件。
34
+ 5. 运行本项目的 check、浏览器和真实角色验收;只有实际证据通过后才进入部署流程。原型、示例数据或客户端截图不能替代业务验收。
35
+
36
+ 如果原版 CLI 或 MCP 不可用,保留真实错误并停止依赖原版的设计步骤;可以继续不依赖设计运行时的只读分析,但不能伪造设计产物或把离线参考当成原版执行结果。
17
37
 
18
38
  ## 定位当前版本
19
39
 
@@ -79,7 +99,7 @@ pnpm exec openxiangda --mcp-stdio --cwd <workspace>
79
99
 
80
100
  平台拥有身份、授权、业务数据、环境和部署状态。应用只声明自己的模型、页面和规则;普通 CRUD 走 Data API,标准审批和通知按需声明,真实业务动作才启用 Nest。编译器生成契约,应用不改生成输出、不维护第二份权限或能力目录。菜单建议只供初次复制到应用声明,不是运行时自动发现。
81
101
 
82
- 匿名访问使用 frontend.publicAccess、createAnonymousPublicClient 与平台浏览器凭证,不建立 guest 角色或公开普通 Data API。角色并集来自当前用户,Perspective 只收窄读取。
102
+ 匿名访问使用 frontend.publicAccess、createAnonymousPublicClient 与平台浏览器凭证,不建立 guest 角色或公开普通 Data API。提交策略的 `create` 必须配套 `draft`;只读外部数据使用 `public.list`/`public.read` 和显式 `publicRecordFields`,附件/图片/清洗后的富文本走平台代理 URL,子表用 `publicSubtableFields` 显式投影,不需要 draft,且不接受任意筛选、排序或投影。角色并集来自当前用户,Perspective 只收窄读取。
83
103
 
84
104
  ## 完成与失败
85
105
 
@@ -41,7 +41,21 @@ impersonation token。mutation 必须携带 UUID `operationId`、`reason`,更
41
41
 
42
42
  匿名外部访问不属于 RBAC 角色或 current-user 行策略。公开表单、续填、附件、重复校验和同一
43
43
  浏览器的本人记录访问只通过[`frontend.publicAccess` 专用合同](public-access.md)开放;平台继续在
44
- 专用端点和 PostgreSQL/RLS 中强制匿名主体、字段、策略及提交回执边界。
44
+ 专用端点和 PostgreSQL/RLS 中强制匿名主体、字段、策略及提交回执边界。需要向外部发布目录、公告或
45
+ 可用性列表时,使用同一合同的 `public.list`/`public.read` 与 `publicRecordFields`,明确绑定资源和
46
+ 字段;`file`、`image` 和清洗后的 `text.rich` 可以公开,返回的托管文件引用只能通过匿名文件内容路由
47
+ 读取,不暴露对象存储地址。子表字段必须在 `publicSubtableFields` 中再次选择子资源字段,例如:
48
+
49
+ ```ts
50
+ publicRecordFields: ['name', 'cover', 'description', 'items'],
51
+ publicSubtableFields: { items: ['sku', 'quantity'] },
52
+ ```
53
+
54
+ 子表只支持一层、固定子字段和有界行数;嵌套子表、签名字段、未声明字段都会在编译或运行时拒绝。
55
+ 公共读取不需要 `draft`,不继承角色权限,也不开放普通 Native Data API、where、排序、聚合或导出参数。
56
+ 普通 Native Data API 的 `select`、`where`、批量、聚合和导出输入只适用于已认证用户或应用后端;把它暴露给匿名
57
+ 浏览器会产生资源/字段枚举、条件推断、查询放大和文件 ID 猜测面。公共端点可以复用 Native RLS 和文件
58
+ 绑定校验,但必须保留固定资源、固定字段、固定排序和固定分页的较小输入面。
45
59
 
46
60
  数值边界直接声明在字段上,`min`/`max` 为闭区间,并且只允许用于
47
61
  `number.integer` 和 `number.decimal`。跨字段约束声明在资源的
@@ -1,10 +1,10 @@
1
1
  # OpenDesign 设计、原型与实现
2
2
 
3
- 有界面影响的新应用、页面或改版,默认直接使用 **原版 OpenDesign** 做设计、原型、预览和修正,再交接到享搭实现业务。享搭只提供启动、安装发现和完整原生 CLI 透传;项目、模板、设计系统、插件、Agent、导出及更新都由 OpenDesign 管理。纯后端、文字校正等按影响沿用已有设计。
3
+ 有界面影响的新应用、页面或改版,默认由 **OpenXiangda 2.0 的 AI 工作流调用原版 OpenDesign CLI、Skill 和 MCP** 完成设计、原型、预览和修正,再在同一工作区交接到享搭实现业务。OpenDesign 客户端是可选预览器,不是用户必须操作的开发入口。享搭只提供安装发现、原生 CLI 透传和 Agent 接入边界;项目、模板、设计系统、插件、导出及更新都由 OpenDesign 管理。纯后端、文字校正等按影响沿用已有设计。
4
4
 
5
5
  ## 原版安装与完整 CLI {#native}
6
6
 
7
- 从[官方发行页](https://github.com/nexu-io/open-design/releases/latest)安装原版应用。macOS 自动发现 `/Applications/Open Design.app` 或 `~/Applications/Open Design.app`;其他平台或源码安装用绝对路径 `OPENXIANGDA_OPENDESIGN_CLI` 指向原生 CLI 文件,也支持原生 `OD_BIN` 与 `OD_NODE_BIN`。不搜索 PATH 中的 `od`,避免调用操作系统的同名命令。当前桌面自动发现已在官方 macOS arm64 0.22.2 验证;其他平台使用显式入口,不声称已完成桌面验证。
7
+ 从[官方发行页](https://github.com/nexu-io/open-design/releases/latest)安装原版运行时或 CLI。AI 工作流优先通过绝对路径 `OPENXIANGDA_OPENDESIGN_CLI`(也支持 `OD_BIN` 与 `OD_NODE_BIN`)调用原生 CLI;macOS 桌面自动发现 `/Applications/Open Design.app` 或 `~/Applications/Open Design.app` 仅用于可选预览。不要要求用户打开客户端,也不搜索 PATH 中的 `od`,避免调用操作系统的同名命令。当前桌面自动发现已在官方 macOS arm64 0.22.2 验证;其他平台使用显式入口,不声称已完成桌面验证。
8
8
 
9
9
  ```bash
10
10
  pnpm openxiangda design open
@@ -20,9 +20,9 @@ pnpm openxiangda design cli mcp
20
20
 
21
21
  `cli` 后面的参数、标准输入、输出、JSON、错误码和取消交给原版;享搭不维护上游命令白名单。查看每条原生命令的 `--help` 再执行当前需要的操作。原版 MCP 可直接接到支持 stdio 的 Agent,启动命令为 `openxiangda design cli mcp`;它与享搭平台 MCP 分别拥有设计项目和平台契约,不合并权限。
22
22
 
23
- 桌面版通过原版 sidecar 查询动态服务端口,原生 `OD_DAEMON_URL` 显式设置优先。没有服务时先执行 `design open`。原版桌面文件导入等操作可能要求在桌面中选择目录或继承原生授权上下文;保留原版错误并使用其桌面入口,不伪造 token 或改数据库。享搭不会在 npm 安装时下载桌面应用、自动修改 Agent 凭据或开启云付费功能。
23
+ AI 通过 CLI/MCP 工作时使用原生 `OD_DAEMON_URL` 或原版自动发现的本地运行时;不需要先执行 `design open`。桌面版 sidecar 只在用户主动预览时使用。原版桌面文件导入等操作可能要求桌面授权上下文;AI 应保留原版错误并停止该步骤,不伪造 token 或改数据库。享搭不会在 npm 安装时下载桌面应用、自动修改 Agent 凭据或开启云付费功能。
24
24
 
25
- 第一次启动可以在原版界面选择已有本地 Codex/Claude Agent;模型和登录由原版及所选 Agent 管理。需要原版图像、视频、音频或云服务时按原版配置相应提供商。原生功能按其实际依赖可用,不把所有功能都描述为无需配置。
25
+ AI Agent 通过原版 CLI/MCP 使用设计能力;模型和登录由原版及所选提供商管理。用户需要人工查看时才打开客户端。需要原版图像、视频、音频或云服务时按原版配置相应提供商。原生功能按其实际依赖可用,不把所有功能都描述为无需配置。
26
26
 
27
27
  ## 随包离线参考 {#resources}
28
28
 
@@ -41,6 +41,8 @@ pnpm openxiangda design cli mcp
41
41
 
42
42
  按用户任务、业务材料和实际设备选择整体方向,包括导航形态、布局、层次、密度、字体、色彩、间距、组件与交互状态。已有“标准后台必须默认外观”“后台一律不设计移动”等审美和设备约定不再是限制。设备适用性由真实任务决定;不要机械增加没有用户任务的页面。
43
43
 
44
+ 应用结构先于视觉改版:标准管理后台是默认骨架,必须保留平台 Shell、后台路由、显式菜单、资源表单、数据列表、权限和流程入口。OpenDesign 对后台只做布局、视觉和交互优化,不能用独立原型、单页 HTML 或 iframe 替换后台。用户端 PC 与移动端按真实旅程分别设计,可以完整采用 OpenDesign 的视觉与交互,但通过平台 runtime/Data API 连接后台数据,并保持与后台分离的权限和导航状态。设计交接时分别标记后台、用户端 PC、用户端移动端的页面归属和验收入口。
45
+
44
46
  先复用 PC/移动 Field Kit 的输入、校验、上传、只读和权限行为。组件外观、布局及专业控件可据设计优化;换组件时证明字段值、未保存输入、拒绝和恢复行为仍正确。Shell 的路由、当前用户、授权菜单事实继续来自平台;`ui` 提供视觉参数,局部 CSS 可以编排布局,结构扩展应走平台支持的组件接口,不能复制导航状态。
45
47
 
46
48
  上游模板的桌面/手机预览框、固定侧栏、虚构指标、限定图表库和示例品牌仅服务其示例。原文中的字体/颜色数量、渐变等规则用于评审设计理由,不能压过实际品牌、中文阅读或已确认任务。借鉴参考的可描述特征,不复制品牌素材或凭空声称业务事实。
@@ -50,7 +52,7 @@ pnpm openxiangda design cli mcp
50
52
  ## 从设计到真实页面 {#loop}
51
53
 
52
54
  1. 从当前 AppSpec 和实际界面识别主任务、目标用户、设备、约束与已有证据。新方向给出有理由的推荐;实际有取舍时最多比较两个方向,已确认意图不重复问。
53
- 2. 打开原版 OpenDesign,在其界面或 CLI 创建项目、选择模板/设计系统,提供任务与必要参考;工作目录由用户任务确定。使用原版工作流形成设计方向,保留上游的项目和资源结构。
55
+ 2. AI 通过原版 CLI/MCP 创建或复用项目、选择模板/设计系统,提供任务与必要参考;工作目录由当前 OpenXiangda 工作区确定。使用原版工作流形成设计方向,保留上游的项目和资源结构;用户可选打开客户端查看。
54
56
  3. 通过原版 Agent、项目和预览做可运行原型,关键任务能从入口走到完成。标明示例数据;覆盖适用的空、加载、失败、拒绝、校验、提交中和成功状态。真实业务请求尚未接入时明确说明。
55
57
  4. 使用原版预览、lint、导出和修正能力;在目标尺寸实际打开、点击和键盘操作。证据记录实际 URL/文件、尺寸、操作与发现,没有浏览器证据就写未验证。不能用 AI 评分或勾选表代替画面和操作结果。
56
58
  5. 依据已有授权和实际答复记录确认范围,固定设计文档和 assets 摘要。工具检查只证明资料与资源一致,不代表审美通过。
@@ -16,6 +16,14 @@
16
16
 
17
17
  管理后台的设备范围按实际办理任务确定。数据管理、录入和报表复用平台 Shell 的路由与菜单事实,视觉依据[OpenDesign 工作流](design-workflow.md)设计;存在手机办理任务时同步设计与验证。
18
18
 
19
+ ### 应用骨架优先与 OpenDesign 页面边界
20
+
21
+ 标准管理后台是每个业务应用的默认开发骨架,必须保留后台 Shell、显式菜单、资源表单、数据列表、详情/编辑、权限和流程入口。开发顺序先完成后台资源与契约,再实现用户端 PC/移动端;不能以用户端首页或设计原型替代后台。
22
+
23
+ OpenDesign 可以在标准后台内部优化布局、视觉和交互,但后台仍复用平台 Shell、导航、字段行为和权限。用户端 PC 与移动端可以分别采用 OpenDesign 的完整视觉和交互,通过平台 runtime/Data API 使用后台数据。禁止用单页 HTML、iframe 或自定义假后台替换标准后台,也不能把后台权限、导航状态复制到用户端。
24
+
25
+ 发布前分别验证后台入口、表单、数据列表、流程入口和用户端 PC/移动端入口;没有完成后台骨架的应用不得发布。
26
+
19
27
  | 任务 | 页面与组件起点 |
20
28
  | --- | --- |
21
29
  | 简单管理列表、表单、详情 | 显式标准 CRUD,复用平台字段行为并应用本应用设计 |
@@ -141,4 +141,4 @@ context 的 `readyForImplementation` 为真时才制定具体实现任务,把
141
141
  - [Design OS,固定提交](https://github.com/buildermethods/design-os/tree/529dedb43bfec24b2cbb128f26dd8cbc6143f754)(MIT)。
142
142
  - [Spec Kit,固定提交](https://github.com/github/spec-kit/tree/4a7341a93d944d6efe153b71da4a1adb9c2b578c)(MIT)。
143
143
 
144
- 有界面影响的工作默认通过 design open / design cli 使用原版 OpenDesign,完成可运行原型、浏览器修正及实现交接,见[设计工作流](design-workflow.md)。原版运行时拥有完整设计资源和工作流;随包方法与 Craft 仅作离线参考。
144
+ 有界面影响的工作默认由 AI 通过 design cli / 原版 MCP 使用 OpenDesign,完成可运行原型、浏览器修正及实现交接,见[设计工作流](design-workflow.md)。客户端仅用于用户主动预览;原版运行时拥有完整设计资源和工作流,随包方法与 Craft 仅作离线参考。
@@ -2,6 +2,7 @@
2
2
 
3
3
  OpenXiangda 2.0 支持没有平台账号的外部访客打开一个明确公开的用户页面,保存并续填草稿、
4
4
  上传平台托管附件、执行具名重复校验、正式提交,并在同一浏览器中查看自己已提交的列表和详情。
5
+ 应用也可以显式发布某个资源的部分记录字段,让外部浏览器分页查询公开记录或读取一条公开记录。
5
6
 
6
7
  该能力识别的是“持有同一个平台 HttpOnly 浏览器凭证的访问者”,不是经过实名验证的自然人。
7
8
  清除 Cookie、无痕模式、另一浏览器或另一设备都会成为新的匿名访问者,不能找回原草稿和记录。
@@ -21,7 +22,7 @@ User-Agent 或浏览器指纹猜测同一个人。
21
22
  ## 应用声明
22
23
 
23
24
  资源仍然按普通 Native Resource 声明。公开能力只在一个静态 `surface: 'user'` 路由上增加一个
24
- 严格有界的 `frontend.publicAccess` 策略:
25
+ 严格有界的 `frontend.publicAccess` 策略;同一路由可以按设备或资源声明多条策略,调用方必须带策略码:
25
26
 
26
27
  ```ts
27
28
  export default defineOpenXiangdaApp({
@@ -104,9 +105,83 @@ export default defineOpenXiangdaApp({
104
105
  | `create` | 以幂等键正式提交当前草稿 |
105
106
  | `own.list` | 分页查看同一浏览器正式提交的记录 |
106
107
  | `own.read` | 查看同一浏览器的一条正式提交详情 |
108
+ | `public.list` | 分页查看当前策略明确发布的资源记录 |
109
+ | `public.read` | 读取当前策略明确发布的一条资源记录 |
107
110
 
108
111
  `own.list` 和 `own.read` 不是一般查询权限。服务端固定注入匿名主体、当前公开策略和已提交草稿
109
- 回执条件,不接受调用方的 where、排序、投影或统计表达式。
112
+ 回执条件,不接受调用方的 where、排序、投影或统计表达式。`public.list` 和 `public.read` 同样不是
113
+ 一般查询权限:它们只读取策略绑定资源在当前租户、应用和环境下的记录,服务端固定按创建时间和 id
114
+ 倒序分页,只返回 `publicRecordFields` 中显式列出的字段和记录 `id`。附件、图片和清洗后的富文本
115
+ 通过平台托管文件路由公开,不返回对象存储地址。子表字段必须在 `publicSubtableFields` 中再次显式
116
+ 列出子资源字段,服务端按声明顺序和行数上限返回一层子表数据。签名字段仍不公开。当前不支持调用方
117
+ 筛选、排序、聚合或导出。
118
+
119
+ ## `draft` 与公共读取
120
+
121
+ `draft` 是匿名提交的服务端事务载体,不是“外部访问”本身,也不是公共读取的前置条件。提交表单时,
122
+ 平台需要先把不完整的输入保存到当前匿名浏览器的草稿,并用 `revision` 做并发控制;附件元数据绑定
123
+ 到草稿;最终 `create` 会在同一数据库事务中锁定草稿、重新执行必填和重复校验、创建业务记录、标记
124
+ 草稿已提交,并用幂等键保证不重复创建。因此声明 `create` 必须同时声明 `draft: { enabled: true }`,
125
+ 而且同一策略的 `draft.read` 与 `draft.update` 必须成对出现。
126
+
127
+ 公共只读场景不需要草稿。只声明 `public.list`/`public.read` 和 `publicRecordFields` 的策略可以直接
128
+ 调用公共查询;它不会获得 `create`、`draft`、`own.*` 或普通 Native Data API 权限。不要为了查询已发布
129
+ 数据创建一个“空草稿”,也不要把 `draft id` 传给浏览器。
130
+
131
+ 例如,目录页面可以只发布明确选定的字段:
132
+
133
+ ```ts
134
+ {
135
+ code: 'catalog-public',
136
+ routeCode: 'catalog',
137
+ mode: 'anonymous',
138
+ resourceCode: 'catalog-items',
139
+ operations: ['public.list', 'public.read'],
140
+ fields: ['name', 'category', 'available', 'internalNote'],
141
+ publicRecordFields: ['name', 'category', 'available', 'items'],
142
+ publicSubtableFields: { items: ['sku', 'quantity'] },
143
+ }
144
+ ```
145
+
146
+ `publicRecordFields` 必须是 `fields` 和资源字段的子集;附件、图片和 `text.rich` 可公开,签名仍被
147
+ 拒绝。公开子表字段必须配置 `publicSubtableFields`,其键是父资源的子表字段,值是子资源字段列表;
148
+ 编译器会拒绝未声明字段、嵌套子表和缺少子字段投影。公共读取沿用明确公开的 `frontend.publicAccess`
149
+ 路由和匿名浏览器凭证,不创建 guest 角色或虚拟内部用户。
150
+
151
+ 需要隐藏停用、归档或租户标记记录时,使用固定 `publicFilters`,由服务端对每次 `public.list`/
152
+ `public.read` 强制追加。当前只支持最多 16 个不同字段的 `eq` 等值条件,字段必须属于策略的
153
+ `fields` 且仅允许布尔、文本、数值、日期和时间标量;调用方不能覆盖、追加或删除这些条件:
154
+
155
+ ```ts
156
+ publicFilters: [{ field: 'enabled', operator: 'eq', value: true }]
157
+ ```
158
+
159
+ 匿名创建需要平台生成的不可预测字段时,使用 `serverGeneratedFields`。这些字段不属于
160
+ `fields`,调用方不能在草稿中写入;提交事务会由平台生成随机值并在提交回执的 `generated`
161
+ 对象中返回。`random-token` 只适用于不承载身份信息的核验令牌等用途:
162
+
163
+ ```ts
164
+ serverGeneratedFields: [{ field: 'qrToken', kind: 'random-token' }]
165
+ ```
166
+
167
+ 需要跨资源复核预约窗口等业务不变量时,可声明 `schedule`,绑定两个只读公开策略和资源字段。
168
+ 平台会在最终创建事务中重新读取启用校区与规则,校验星期、日期范围、提前小时数和离散时段;页面端
169
+ 校验只能改善体验,不能替代这次服务端复核。
170
+
171
+ 子表中的文件引用会自动带上受控的 `resourceCode` 与父字段绑定;应用如需为附件生成下载地址,使用
172
+ `fileContentUrl(fileId, disposition, variant, resourceCode, parentFieldCode)`,不要自行拼接文件路径。
173
+
174
+ ## 为什么不开放普通 Native Data API
175
+
176
+ 普通 Native Data API 是内部或应用后端的可信数据边界,允许调用方提交
177
+ `select`、`where`、`order`、批量查询、聚合和导出,并按当前登录用户角色执行行列权限。匿名
178
+ 公开发布的语义不同:它必须只绑定一个资源和不可变字段白名单,不接受调用方筛选、排序、聚合、
179
+ 导出或自带角色,也必须把文件绑定到公开记录和公开字段后再读取。
180
+
181
+ 直接把普通 Native Data API 暴露给浏览器会允许枚举内部资源和字段、通过筛选和计数推断未公开数据,
182
+ 放大查询资源消耗,并增加文件 ID 猜测、审计字段泄露和权限合同混用的风险。因此公共端点继续是
183
+ 专用的 `public.list`/`public.read`;底层可以复用 Native 的 RLS 和文件所有权校验,但不把 Native
184
+ Data API 的输入面开放给匿名调用方。
110
185
 
111
186
  ## 页面客户端
112
187
 
@@ -133,6 +208,10 @@ const receipt = await client.submit(withPhoto.revision, crypto.randomUUID());
133
208
 
134
209
  const page = await client.listOwn({ pageSize: 20 });
135
210
  const detail = await client.getOwn(receipt.recordId);
211
+
212
+ // 只读公开目录不需要先读取或保存 draft。
213
+ const publicPage = await client.listPublic({ pageSize: 20 });
214
+ const publicDetail = await client.getPublic(publicPage.items[0].data.id as string);
136
215
  ```
137
216
 
138
217
  必须先 `bootstrap()`。草稿更新始终使用最近返回的 revision,冲突时重新读取,不能覆盖写。