feat(runtime): establish miniapp kernel and sdk design
This commit is contained in:
@@ -0,0 +1,287 @@
|
||||
# `03.sdk_and_coreapp` 设计评审记录
|
||||
|
||||
> 评审日期:2026-08-05
|
||||
> 评审基线:[APP架构设计.md](../APP架构设计.md)
|
||||
> 评审对象:[03.sdk_and_coreapp.md](03.sdk_and_coreapp.md)
|
||||
> 评审方式:独立子 agent 只读评审;本文件记录评审意见,不代表已采纳或已实现。
|
||||
|
||||
## 1. 总体结论
|
||||
|
||||
`03.sdk_and_coreapp` 的主方向已经与架构基线基本一致,以下核心决策已正确写入:
|
||||
|
||||
- 产品层级保持为 **LineUp App → LineUp Runtime → MiniApps**;Runtime 没有被写成与 MiniApp 平级的 App。
|
||||
- SDK 使用 `sdk.ui`,不再使用旧的 `sdk.interactions`。
|
||||
- 标准交互属于 Runtime 提供的标准输入输出库;Runtime 负责记录、owner 注入、校验、恢复、审计、路由和呈现 Policy。
|
||||
- `owner` 不是 MiniApp 调用参数,而是从 SDK 已绑定的 `MiniAppContext` 自动注入;MiniApp 不能伪造或访问其他 owner 的交互。
|
||||
- Interact 是 Agent/IM 场景的默认可信 Renderer Provider,不拥有交互记录,也不直接把结果发送给 Agent。
|
||||
- Task Dashboard 可验证 `sdk.ui` 的通用事务提示,且不应因提示强制切换到 Interact。
|
||||
- Whiteboard 的文字编辑、画笔、颜色选择、拖放、工具栏等高频或私有 UI 留在自身 Surface,不走 Runtime 标准交互。
|
||||
- 保留 `lineup.v1.tool.call(choice | confirm | input)` 兼容路径;不把 `chat → interact` 命名迁移放进本迭代。
|
||||
- 本迭代不建设 AppServer Catalog、下载、安装、更新、市场、远程 Bundle 或真实媒体/文件能力。
|
||||
|
||||
但仍存在 **1 个阻塞级信任模型冲突**,以及若干会造成实现分叉或验收不可判定的重要契约缺口。建议在进入实现前完成收敛。
|
||||
|
||||
## 2. 阻塞问题
|
||||
|
||||
### B1. Task Dashboard 的可信 DOM / Host adapter 权限突破了当前信任模型
|
||||
|
||||
**架构基线**在 [APP架构设计.md](../APP架构设计.md) 的 MiniApp 信任模型中明确:
|
||||
|
||||
- `Interact / System MiniApp` 可使用可信内建 DOM 组件;
|
||||
- Installed MiniApp 必须经隔离 iframe / Surface Bridge 运行。
|
||||
|
||||
而 [03.sdk_and_coreapp.md](03.sdk_and_coreapp.md) 同时写了:
|
||||
|
||||
```text
|
||||
Task Dashboard 可由受信 Host adapter 挂载;Whiteboard 必须走受限 Surface
|
||||
```
|
||||
|
||||
并将 Task Dashboard 定义为:
|
||||
|
||||
```text
|
||||
kind = bundled-reference
|
||||
```
|
||||
|
||||
且说明它可使用“随 LineUp 发布的受信 Host adapter”。
|
||||
|
||||
**问题:** 当前权威架构没有明确授权 `bundled-reference` 获得与 System MiniApp 相同的可信 DOM 容器。若 Host adapter 可执行或挂载 Task Dashboard 的 UI,而未经过受限 Surface,隔离边界、SDK 受限视图和“禁止访问 Host DOM”就无法以同一安全模型证明。
|
||||
|
||||
**需要冻结的决策(二选一):**
|
||||
|
||||
1. **保守方案,且最符合当前权威基线:** Task Dashboard 和 Whiteboard 都是非 System MiniApp,必须经隔离 Surface / Bridge 运行。Host adapter 仅作为 Runtime/Shell 的不可见装配层,不向 MiniApp 提供可直接操作的可信 Host DOM。
|
||||
2. **若产品确实需要 Task Dashboard 使用可信原生 DOM:** 将其升级为 `kind = system`,并在架构主文档新增或明确“bundled trusted system MiniApp”信任层、发布来源、可用 DOM 权限和审计边界;不能继续称其为普通 `bundled-reference`。
|
||||
|
||||
**建议验收:**
|
||||
|
||||
- 若维持 `bundled-reference`,Task Dashboard 无法获得 Host 根 DOM、Tauri invoke 或未授权 Host adapter。
|
||||
- 若改为 `system`,仍要验证其特权只限 Runtime SDK,不能取得 Transport、Store 或 Agent 访问权。
|
||||
|
||||
## 3. 重要问题
|
||||
|
||||
### I1. `bundled-development` 与 `bundled-reference` 的术语、Manifest 枚举未建立映射
|
||||
|
||||
迭代文档把“内置”解释为 `bundled-development`,但冻结的 `MiniAppManifest.kind` 只有:
|
||||
|
||||
```ts
|
||||
kind: "system" | "bundled-reference";
|
||||
```
|
||||
|
||||
架构主文档也使用了“参考 MiniApp 在此阶段可以是 `bundled-development`”的表述。
|
||||
|
||||
这两个词可以共存,但必须明确它们不是互相竞争的 `kind` 枚举值。
|
||||
|
||||
**建议补充最小映射表:**
|
||||
|
||||
| 概念 | 建议语义 |
|
||||
|---|---|
|
||||
| `bundled-development` | 本迭代的交付/加载方式:随开发 Host 预置,不下载、不安装、不经服务端 Catalog。 |
|
||||
| `kind = bundled-reference` | Manifest 身份:参考 MiniApp,决定 SDK / Surface 信任策略。 |
|
||||
| `kind = system` | 随产品发布、代码可信的系统 MiniApp,例如 Interact。 |
|
||||
|
||||
并明确:`bundled-development` **不是** `MiniAppManifest.kind` 的第三个取值。
|
||||
|
||||
### I2. `sdk.ui` 缺少 Renderer 如何安全提交用户结果给 Runtime 的闭环契约
|
||||
|
||||
当前公开 API 只有:
|
||||
|
||||
```ts
|
||||
request(...)
|
||||
get(...)
|
||||
subscribe(...)
|
||||
cancel(...)
|
||||
```
|
||||
|
||||
但未定义:
|
||||
|
||||
- Runtime 如何把被 Policy 选中、可呈现的 interaction record 交给 renderer;
|
||||
- renderer 如何提交 `submitted`、`result` 或 `cancelled`;
|
||||
- Runtime 如何校验 `interaction_id`、owner、renderer binding、状态迁移、一次性提交和结果 schema;
|
||||
- 在 opaque-origin iframe / Surface Bridge 内,呈现和回传采用何种受限消息协议;
|
||||
- renderer 与 owner 是同一 MiniApp 时,是否通过 `sdk.ui` 提交,还是只能通过 Runtime/Shell 私有 Renderer API 提交。
|
||||
|
||||
**建议冻结 Runtime 私有 Renderer Contract / 最小 Bridge Contract:**
|
||||
|
||||
```text
|
||||
Runtime 分配 interaction_id + renderer_binding + presentation container/surface
|
||||
→ renderer 仅接收 presentation-safe request projection
|
||||
→ renderer 向 Runtime-owned endpoint 提交 action/result
|
||||
→ Runtime 校验:
|
||||
- 被分配的 renderer / container
|
||||
- interaction_id
|
||||
- owner binding
|
||||
- 当前状态与一次性提交
|
||||
- result schema
|
||||
- expiry
|
||||
→ Runtime 持久化状态迁移,并向 owner-scoped ui 订阅发出更新
|
||||
```
|
||||
|
||||
隔离 Surface 至少还要限定消息白名单、`surface_id` / `instance_id` 绑定和 nonce 或等效关联方式;不得只凭 origin 信任。
|
||||
|
||||
### I3. 标准交互与 `RuntimeToolCallRecord` 的关系不清晰
|
||||
|
||||
当前文档同时规定:
|
||||
|
||||
- MiniApp 可调用 `sdk.ui.request(...)`;
|
||||
- owner 的 source 可为 `agent_tool | miniapp_tool | runtime_policy`;
|
||||
- 所有标准交互“必须映射为 Runtime 统一的 `interactive` Tool Call / `StandardInteractionRecord`”。
|
||||
|
||||
因此会产生问题:Task Dashboard 在没有 Agent Tool Call、例如用户点击“关闭未完成任务”时调用 `sdk.ui.request(confirm)`,Runtime 是否必须凭空创建 Agent-facing `RuntimeToolCallRecord`?
|
||||
|
||||
**建议明确拆成三条路径:**
|
||||
|
||||
| 来源 | Runtime 记录 | 与 Agent Tool 的关系 |
|
||||
|---|---|---|
|
||||
| Agent / legacy `lineup.v1.tool.call(choice/confirm/input)` | `RuntimeToolCallRecord` + `StandardInteractionRecord` | 交互终态受控驱动该 Tool 的后续处理。 |
|
||||
| MiniApp `sdk.ui.request(...)` | owner-bound `StandardInteractionRecord` | 不自动创建新的 Agent Tool;若提供合法 `parent_call_id`,只建立关联。父 Tool 的完成由 owner 经 `sdk.tools.*` 决定。 |
|
||||
| Runtime Policy 自发提示 | `runtime_policy` owner 的 interaction record | 需明确其是否绑定某一 Capability / lifecycle request。 |
|
||||
|
||||
没有 parent Tool 的交互只改变 MiniApp 本地工作流,不应制造 Inventory、Agent 回传或 outbox 语义。
|
||||
|
||||
### I4. 结果投递位置与公开 API 不一致
|
||||
|
||||
流程写“结果仅投递回 owner MiniApp 的 Tool/Inbox”,但 SDK 已公开 `sdk.ui.get/subscribe`。
|
||||
|
||||
否则实现可能分叉成:
|
||||
|
||||
1. 结果通过 `sdk.ui.subscribe` 的 record update 返回;
|
||||
2. 结果作为 Inbox 消息;
|
||||
3. 结果通过 parent Tool 的 SDK Tool event 返回。
|
||||
|
||||
**建议冻结为:**
|
||||
|
||||
```text
|
||||
sdk.ui.get / sdk.ui.subscribe
|
||||
= owner 获取标准交互状态与结果的唯一 UI-domain 通道
|
||||
|
||||
sdk.inbox
|
||||
= Agent / Runtime 入站消息;不复用为 interaction result transport
|
||||
|
||||
sdk.tools.complete / fail / cancel
|
||||
= owner 根据 UI result 自行决定是否推进关联 parent Tool
|
||||
```
|
||||
|
||||
还需定义:订阅是否立即回放 owner 当前 pending records、终态保留/清理策略、断线重连后的重放及去重语义。
|
||||
|
||||
### I5. Schema、状态机、幂等规则不足以支持安全验收
|
||||
|
||||
已有四类 request 及基础状态,但还需要明确:
|
||||
|
||||
- `StandardInteractionResult` 与 `InteractionReceipt` 的类型;
|
||||
- `choice.actions[].id` 的唯一性、最大数量、空数组是否允许,以及 single/multi/button 的选择基数;
|
||||
- `input.fields[].id` 的唯一性、字段数上限、必填、数值解析、空字符串、长度和范围的适用规则;
|
||||
- `notice` 的“只读”与 `acknowledged` 的精确定义:是否需要用户确认、是否自动完成、是否可超时;
|
||||
- `request`、`submit`、`cancel`、超时、恢复之间的合法状态迁移;
|
||||
- 并发提交、重放、重复取消、跨 Surface 重放的确定性返回;
|
||||
- 交互专用稳定拒绝码。
|
||||
|
||||
建议至少增加:
|
||||
|
||||
```text
|
||||
interaction_not_found
|
||||
interaction_owner_mismatch
|
||||
interaction_state_invalid
|
||||
interaction_expired
|
||||
interaction_result_invalid
|
||||
interaction_renderer_mismatch
|
||||
parent_call_invalid
|
||||
```
|
||||
|
||||
### I6. 持久化、审计与敏感输入的日志最小化约束尚未衔接
|
||||
|
||||
`input` 可以含用户自由文本;标准交互要求持久化、恢复和审计,但架构文档又要求日志不得包含身份、会话、消息正文、Tool 参数、token 或 artifact 内容。
|
||||
|
||||
**建议明确:**
|
||||
|
||||
- 恢复所需的受保护 operational state、审计最小元数据、日志/Telemetry 三者的分层;
|
||||
- `input` 草稿和结果的保留期、终态清理策略,以及是否加密;
|
||||
- 审计仅记录 interaction ID、kind、受保护 owner 标识、状态迁移和错误码;
|
||||
- title、prompt、字段值和 action label 不进入日志、指标、错误详情或普通审计明文;
|
||||
- 验收增加日志负向断言。
|
||||
|
||||
## 4. 建议完善项
|
||||
|
||||
### S1. 扩大 `parent_call_id` 校验条件
|
||||
|
||||
除“属于当前实例且状态允许关联”外,Runtime 至少应校验:
|
||||
|
||||
```text
|
||||
同 app_scope
|
||||
同 instance_id
|
||||
同 conversation_id
|
||||
父 Tool 非终态
|
||||
不存在跨 owner 关联
|
||||
```
|
||||
|
||||
还要定义父 Tool 被取消或超时时关联 interaction 的处理:自动取消、保留为独立操作,或交由 Policy 决定。否则恢复后容易遗留孤儿卡片。
|
||||
|
||||
### S2. 将 presentation policy 写成可判定矩阵
|
||||
|
||||
至少应覆盖:
|
||||
|
||||
| owner 状态 / 容器 | 建议行为 |
|
||||
|---|---|
|
||||
| Agent IM / Interact 有效 | Interact IM timeline/card。 |
|
||||
| owner 前台且存在合法 renderer | owner 容器或已绑定 Surface 的标准 modal/sheet/card。 |
|
||||
| owner 后台或 suspended | 保持 pending;通知/唤醒仅经 Policy,不得抢占焦点。 |
|
||||
| Surface 已关闭或失效 | 不向旧 Surface 投递;恢复、降级或安全失败。 |
|
||||
| renderer 不可用 | 保持 pending 或返回稳定拒绝码;不能把 payload 注入 Host DOM。 |
|
||||
| 系统能力确认 | 走 Capability Gateway,禁止降级为普通 `confirm`。 |
|
||||
|
||||
### S3. 分离 Interact 的 Renderer 行为与 legacy Agent Tool 完结行为
|
||||
|
||||
当前“Renderer 呈现标准交互记录”与“Interact 以 `sdk.tools.complete/fail/cancel` 结束 Tool”的表述容易混淆。
|
||||
|
||||
建议统一为:
|
||||
|
||||
```text
|
||||
Renderer → Runtime:完成 interaction record
|
||||
Runtime → owner:sdk.ui 状态更新
|
||||
owner(legacy Agent Tool 场景中为 Interact)→ sdk.tools.complete / fail / cancel
|
||||
```
|
||||
|
||||
这样不会把一般 Renderer 误写成跨域 Tool 结果出口。
|
||||
|
||||
### S4. 统一阶段编号
|
||||
|
||||
架构主文档当前既有 `03.sdk_and_coreapp`,又有后续 `03.reference-miniapps`,但前者已经将 Task Dashboard / Whiteboard 的实现和端到端验收列为目标。
|
||||
|
||||
需要二选一:
|
||||
|
||||
- 删除或合并 `03.reference-miniapps` 到当前 `03.sdk_and_coreapp`;或
|
||||
- 当前 `03` 只做 SDK/Interact 核心,参考 MiniApp 另起新编号并顺延 Catalog 阶段。
|
||||
|
||||
### S5. 在实施步骤中拆出标准交互服务和 renderer/Bridge 契约
|
||||
|
||||
建议在通用 Tool 闭环之后、适配 Interact 之前增加独立步骤:
|
||||
|
||||
1. 实现 `standard-interaction-service`:owner 注入、记录、状态机、结果校验、过期、恢复、owner-scoped query/subscription;
|
||||
2. 实现 renderer registration 与 presentation policy;
|
||||
3. 定义并测试 System IM renderer 与 isolated Surface renderer 的最小回传协议;
|
||||
4. 再接入 legacy Tool mapping、Interact 与两个参考 MiniApp。
|
||||
|
||||
这样可以避免先把能力实现成 Chat 专用逻辑、后续再进行高风险重构。
|
||||
|
||||
## 5. 建议新增的最小验收场景
|
||||
|
||||
1. A 实例提交属于 B 实例、不同 conversation 或已终态 Tool 的 `parent_call_id` 时,Runtime 拒绝且不创建 record。
|
||||
2. A 创建 interaction 后,B 无法 `get`、订阅、取消、提交,或通过伪造 `interaction_id` 获得任何 payload/result。
|
||||
3. 同一 interaction 的两次 renderer submit 只有一次成功;第二次得到稳定终态错误且不改变已持久化结果。
|
||||
4. 旧 `lineup.v1.tool.call(choice|confirm|input)` 创建关联 Tool Call 和 owner 为 Interact IM context 的 interaction;用户结果先由 Runtime 落库,再由 Interact 以 owner 身份完成 Tool。
|
||||
5. Task Dashboard 无 parent Tool 的 `sdk.ui.request(confirm)` 不创建 Agent-facing Tool Call、不写 Agent outbox;带合法 parent Tool 时仅关联,不自动完成该 Tool。
|
||||
6. Task Dashboard 前台时,标准 modal/sheet/card 在其合法容器显示,焦点栈与 Interact background 状态不被改写。
|
||||
7. Whiteboard 在 Surface reload、关闭、旧 iframe 重放提交时,`surface_id` 与 renderer binding 都被验证,旧 iframe 消息被拒绝。
|
||||
8. 非法 input、重复/未知 choice action、过期 interaction、跨 owner cancel 都被拒绝且不写错误结果。
|
||||
9. 标准交互输入值、提示正文、选择标签不出现在日志、Telemetry 或 Audit 明文中;重启恢复仅保留设计允许的最小数据。
|
||||
10. 若维持 `bundled-reference`,Task Dashboard 不能直接挂载可信 Host DOM;若改为 `system`,必须有对应的 manifest/source-trust 回归用例。
|
||||
|
||||
## 6. 建议的阅读和决策顺序
|
||||
|
||||
明天继续时,建议按以下顺序决策和回填:
|
||||
|
||||
1. 先决定 **B1:Task Dashboard 的信任级别与 UI 容器**;
|
||||
2. 冻结 **I2:Renderer → Runtime 的提交/Bridge 契约**;
|
||||
3. 冻结 **I3/I4:StandardInteractionRecord 与 Tool Call 的关系,以及 UI result 的唯一返回通道**;
|
||||
4. 细化 **I5/I6:schema、状态机、幂等、错误码、持久化与日志最小化**;
|
||||
5. 把 S1~S5 与第 5 节的验收场景回填入 [03.sdk_and_coreapp.md](03.sdk_and_coreapp.md) 和必要的 [APP架构设计.md](../APP架构设计.md)。
|
||||
|
||||
在上述收敛前,不建议开始 `standard-interaction-service` 或参考 MiniApp 的实现,以免重新形成 Chat / Interact 专用旁路。
|
||||
Reference in New Issue
Block a user