openxiangda-skill-kit 2.0.0-alpha.33 → 2.0.0-alpha.34

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.
@@ -0,0 +1,40 @@
1
+ # App API 用户委托数据访问
2
+
3
+ ## 问题证据
4
+
5
+ - 平台网关已经把浏览器当前 Principal、RoleSession 和精确请求摘要签入短期 Gateway Assertion,`OpenXiangdaAuthzGuard` 也把验证后的用户上下文写入请求作用域。
6
+ - 官方采购示例的用户 App API 却注入了 `OpenXiangdaApplicationDataApiService`。该 facade 明确用于无 HTTP 请求的 Worker/Scheduler,并用 workload OAuth2 应用身份及空 RoleSession 调用 Data API。
7
+ - prod-1 preproduction 验收中,用户上传并完成的托管文件由应用身份事务绑定,平台以 `OPENXIANGDA_NATIVE_DATA_FILE_OWNERSHIP_MISMATCH` 拒绝;同一路径还会让业务数据策略从当前用户漂移到应用身份。
8
+
9
+ ## 决策
10
+
11
+ ### 能力所有者
12
+
13
+ - 平台网关和经验证的 NestJS 请求作用域是用户 App API 身份的唯一所有者。
14
+ - `OpenXiangdaDataApiService` 是用户 HTTP 请求内访问 Data API 的唯一 facade,必须原样转发 Gateway invocation authorization 和 RoleSession。
15
+ - `OpenXiangdaApplicationDataApiService` 仅属于没有用户 HTTP 上下文的 Worker、Scheduler、事件消费者和显式服务调用,继续使用平台托管 OAuth2 workload identity。
16
+
17
+ ### 稳定不变量与受影响合同
18
+
19
+ 1. 用户 App API 的 capability、数据权限、审计 actor、托管文件所有权和事务幂等主体始终是同一个已验证 RoleSession。
20
+ 2. 应用后端不得从正文、查询或自定义 header 构造用户身份;只使用全局 transport guard 写入的请求作用域。
21
+ 3. 本轮不增加委托 token、额外数据库状态或新平台接口,只修正官方模板的 facade 选择和文档。
22
+ 4. Worker/Scheduler 的 OAuth2、Native Data API 路径、稳定字段值、1.0 应用、流程和自动化合同不变。
23
+
24
+ ### 失败、并发、安全与资源边界
25
+
26
+ - 缺少 Gateway invocation 或 RoleSession 时,请求作用域 Data API fail closed;不能自动回退应用身份。
27
+ - 每个请求使用自己的 NestJS request scope,不缓存或跨请求复用用户 RoleSession;应用 OAuth token 缓存仍只属于 workload facade。
28
+ - 文件上传、完成和业务事务必须使用同一用户 RoleSession;后台任务如需处理文件,必须先以应用身份自行创建该文件,不能接管用户未绑定文件。
29
+
30
+ ### 回滚边界
31
+
32
+ - 模板和示例应用可独立回滚到上一提交;平台 API 和数据库无需回滚。
33
+ - 已发布旧 2.0 测试应用不自动改写。2.0 当前没有兼容承诺,新生成应用直接采用正确 facade。
34
+
35
+ ## 可证伪验收
36
+
37
+ 1. 模板测试断言用户 App API 注入 `OpenXiangdaDataApiService`,并拒绝重新引入 `OpenXiangdaApplicationDataApiService`。
38
+ 2. Nest SDK 的现有测试继续证明 request-scoped facade 转发 RoleSession,workload facade 使用空 RoleSession 且只在 401 后刷新一次。
39
+ 3. prod-1 真实应用完成“用户上传 → App API 事务绑定 → Data API 读取 → 受保护下载”,文件 UUID、稳定附件值和审计主体保持一致。
40
+ 4. 同一记录继续完成 Workflow prepare/start,并在部门管理员角色工作中心可见。
package/docs/backend.md CHANGED
@@ -20,9 +20,11 @@ src/health liveness/readiness
20
20
 
21
21
  用户身份必须绑定 RoleSession;应用身份绑定 tenant、app、environment、client、credentialVersion 和 scopes。业务 controller 使用生成的 `appOperations` 和 `@OpenXiangdaOperation()` 同时绑定不可变 operation contract 与 capability;`OpenXiangdaAuthzGuard` 对服务身份要求 `app:invoke` 和完全匹配的 operation capability。`@RequireCapability()` 只保留给官方 SDK 内部与非业务适配层,应用 controller 不应散写 capability 字符串。应用身份可以调用授权的 App API/Data API,但 Workflow 客户端拒绝没有用户 RoleSession 的上下文。
22
22
 
23
+ 用户发起的 App API 必须注入请求作用域的 `OpenXiangdaDataApiService`。它沿用网关已验证的 authorization 和 RoleSession,使 capability、数据策略、审计 actor、文件上传所有权与后端事务保持同一用户身份;缺少 RoleSession 时必须拒绝,不能静默回退 workload 应用身份。
24
+
23
25
  Application 2.0 的远程运行环境只有 `preproduction`、`production` 两条固定通道,`environmentKey` 是 Principal、RoleSession、事件、Workflow、App API 和运行容器共同使用的稳定身份键,并与通道名一致;`environmentId` 是 Native registry 中必须参与授权和防串联校验的稳定 UUID。`local` 是 CLI 管理的 loopback 运行模式,不是 environmentKey,也不创建远程 OAuth、Secret、Head 或 RoleSession。需要同类多环境时必须升级发布契约,不能把 UUID 或任意字符串临时当成 `environmentKey`。
24
26
 
25
- Worker、Scheduler 或事件消费者没有浏览器请求上下文时,注入 `OpenXiangdaApplicationDataApiService`。每个已部署后端的应用环境都有一个平台托管的 workload OAuth2 client;平台自动创建或复用客户端,并通过 Kubernetes Secret 注入 `OPENXIANGDA_OAUTH_CLIENT_ID`、`OPENXIANGDA_OAUTH_CLIENT_SECRET` 和 `OPENXIANGDA_OAUTH_SCOPES`,这些保留变量不写入 `backend.secrets`。本地开发时 CLI 自动创建 workspace runtime client,并只向 NestJS 进程注入同名变量;前端进程、生成 manifest、日志和 AppPackage 都不包含原始 Secret。
27
+ Worker、Scheduler 或事件消费者没有浏览器请求上下文时,才注入 `OpenXiangdaApplicationDataApiService`。每个已部署后端的应用环境都有一个平台托管的 workload OAuth2 client;平台自动创建或复用客户端,并通过 Kubernetes Secret 注入 `OPENXIANGDA_OAUTH_CLIENT_ID`、`OPENXIANGDA_OAUTH_CLIENT_SECRET` 和 `OPENXIANGDA_OAUTH_SCOPES`,这些保留变量不写入 `backend.secrets`。本地开发时 CLI 自动创建 workspace runtime client,并只向 NestJS 进程注入同名变量;前端进程、生成 manifest、日志和 AppPackage 都不包含原始 Secret。
26
28
 
27
29
  运行凭据的状态只包含 clientId、当前版本、hint、宽限期和待激活轮换元数据,不返回 Secret。`openxiangda oauth runtime rotate --environment <key> --idempotency-key <key>` 使用当前版本 CAS 暂存新凭据,并自动对当前激活 AppVersion 创建一次同版本滚动部署;部署准备阶段才把待激活凭据提升为当前凭据。旧 Pod 使用的上一版本在指定宽限期内仍可换 token,因此轮换不依赖同时重启全部副本。失败或重复请求不会生成第二份凭据,运维重试必须复用幂等键。
28
30
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda-skill-kit",
3
- "version": "2.0.0-alpha.33",
3
+ "version": "2.0.0-alpha.34",
4
4
  "description": "Validation and deterministic packaging for OpenXiangda 2.0 AI skills.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",