# LineUp App 架构设计 **状态:** 当前权威设计基线 **更新日期:** 2026-08-04 **适用实现:** Tauri 2 Desktop Host 与同代码 Web Reference Host **本文取代:** `DESIGN.md`、`M4_COMPATIBILITY_AND_RELEASE.md`、`TECHNOLOGY_SELECTION.md` ## 1. 设计结论 **LineUp 是用户安装和使用的主应用;LineUp Runtime 是 LineUp App 内部提供给小程序的核心 运行环境。** Runtime 不是与小程序平级的产品 App,也不是一个独立客户端。 ```text LineUp App │ ├── App Shell / Host │ ├── 当前前台小程序的挂载与切换 │ ├── 连接状态、通知和安全恢复入口 │ └── Tauri / Web Host Provider │ ├── LineUp Runtime │ ├── AppServer / Remote Agent 通信 │ ├── Conversation、Store、sync loop、outbox │ ├── MiniApp Registry、Instance、Focus、Lifecycle │ ├── Tool Router、Inbox、Inventory │ ├── Surface、Capability、Artifact、Audit │ └── LineUp MiniApp SDK │ └── MiniApps ├── Interact(系统内建:IM / Audio / Video) ├── Task Dashboard(参考 / 已安装小程序) ├── Whiteboard(参考 / 已安装小程序) ├── Draw-and-Guess(参考 / 已安装小程序) └── 未来第三方小程序 ``` 任何 MiniApp 都必须通过 Runtime SDK 使用通信、Tool、生命周期、Surface 和系统能力;不得 建立独立 Agent 通信链路,或直接访问 Host 特权、Store、认证信息及其他 MiniApp 数据。 ## 2. 产品边界与术语 | 术语 | 含义 | 不能做什么 | |---|---|---| | **LineUp App** | 用户实际使用的主应用、产品容器和交付单位。 | 不能把业务规则重新堆进 Shell。 | | **App Shell / Host** | Tauri 或 Web 中的挂载、切换、通知、恢复和受限 Host Provider。 | 不解释 Agent 协议,不决定 Tool/App 路由。 | | **LineUp Runtime** | App 内部的长期协调环境;唯一拥有通信、可靠性、MiniApp 调度与安全决策。 | 不负责任意 MiniApp 的具体 DOM 或业务 UX。 | | **MiniApp** | 运行在 Runtime 上的功能单元。 | 不直连 Agent/AppServer,不直写 Runtime 状态。 | | **System MiniApp** | 随 LineUp 发布、代码可信的内建 MiniApp,如 Interact。 | 仍不能绕过 Runtime 调度或 Capability Policy。 | | **Installed MiniApp** | 经验证后在受限 Surface 中运行的小程序。 | 不访问 Host DOM、Tauri invoke、token、任意网络或其他 MiniApp。 | | **MiniApp SDK** | Runtime 向 MiniApp 开放的受控能力集合。 | 不是通用 Web、Tauri 或 Agent SDK。 | | **Tool** | Agent 通过 Runtime 调用的、Manifest 已声明的 MiniApp 功能。 | 不是 App 内部任意函数。 | | **Capability** | Runtime/Host 保管的录音、文件、通知等系统能力。 | 不是 MiniApp 自动拥有的权限。 | | **Surface** | 复杂交互使用的受限 UI 容器。 | 不承载未验证远端脚本或 Host 特权。 | ### 2.1 Interact MiniApp `Interact` 是第一个系统级 MiniApp,也是用户与 Agent 的默认交互入口: ```text Interact MiniApp ├── IM Mode:文字、图片、短消息、任务和结果投影 ├── Audio Mode:实时语音(后续) ├── Video Mode:实时视频(后续) └── IM 标准交互的默认 Renderer Provider:notice / choice / confirm / input ``` 当前实现仍保留兼容名称: ```text 产品概念:Interact MiniApp 当前 app_scope:chat 当前目录:tauri/src/core-apps/chat/ ``` 目录和作用域改名属于独立迁移任务,不能和 Runtime/MiniApp SDK 重构混在一起。 Interact 是可信内建代码,因此可以使用 LineUp 的可信 DOM 组件;但它和所有 MiniApp 一样, 必须经 SDK 请求 Runtime 行为,不能直接访问 Transport、Conversation Store、焦点栈、App Registry、原始 Agent Envelope 或系统能力。 ## 3. 当前技术与 Host 基线 唯一客户端实现与验收基线是: ```text Tauri 2 Desktop Host + Web Reference Host ``` 它们运行同一份 TypeScript Runtime 与 MiniApp 代码,并不是两个客户端: - **Web Reference Host**:浏览器开发、Tailscale 联调和自动化验证入口;只能提供可安全降级 的浏览器能力。 - **Tauri Desktop Host**:正式桌面交付;只在 Runtime 授权后提供文件、通知、媒体等 Host Provider 能力。 不规划独立 Android/Kotlin 客户端,也不规划 Wails Host。已退役的 Android/Wails Spike 只保留 在 Git 历史中,不能作为架构、协议、目录或验收依据。 开发命令: ```bash cd lineup-app/tauri npm run web:dev # Web / Tailscale Reference Host npm run desktop:dev # Tauri Desktop Host npm test -- --run # Runtime、MiniApp 与 Host 回归 npm run build # TypeScript 检查与 Web production build ``` Web Host 与 AppServer 的地址必须按访问位置匹配:同机浏览器使用 `127.0.0.1`,Tailscale 浏览器 使用受信任的 Tailscale 地址。`0.0.0.0` 仅是服务器监听地址,不能作为浏览器 API 目标。 ## 4. Runtime 的唯一所有权 Runtime 是以下对象的唯一所有者: ```text Transport Conversation Store sync loop outbox 协议兼容与原始 Envelope 校验 作用域筛选与 message_id 去重 MiniApp Inbox 与 ACK MiniApp Registry、Instance、Focus、Lifecycle Tool Router、Inventory、Capability、Surface、审计与恢复 ``` 当前消息路径必须保持单向: ```text AppServer / Remote Agent → LineUp Runtime → 协议、scope、权限、去重和持久化 → MiniApp SDK Inbox / Tool Call → MiniApp UX → SDK Result / Progress / Lifecycle Request → Runtime 校验、审计、outbox → AppServer / Remote Agent ``` 禁止项: ```text MiniApp 直接 fetch AppServer 或 Agent MiniApp 直接读写 Conversation Store、sync cursor 或 outbox MiniApp 构造或发送原始 Agent Envelope MiniApp 直接切换其他 MiniApp、改写 focus stack 或 Registry MiniApp 直接调用 Tauri invoke、Host DOM 根节点或系统能力 Surface 从消息 payload 直接加载 URL、HTML、CSS、JS、Bundle 或 source ``` ## 5. MiniApp 信任模型与 SDK 权限视图 所有 MiniApp 共享 Runtime 的协议语义,但按来源获得不同的 SDK 视图。 | 能力 | Interact / System MiniApp | Installed MiniApp | |---|---:|---:| | 接收自身 Inbox、ACK | 可以 | 可以 | | 接收 Runtime Tool Call | 可以 | 可以 | | 上报 progress / result / error | 可以 | 可以 | | 请求前台、后台、关闭 | 可以,由 Runtime 决定 | 可以,由 Runtime 决定 | | 请求 Surface | 可以,经 Runtime Policy | 可以,经 Runtime Policy | | 请求 Capability | 可以,经 Runtime Policy | 可以,经 Runtime Policy | | 可信内建 DOM 组件 | 可以 | 不可以 | | 隔离 iframe / Surface Bridge | 可选 | 必须 | | 直连 Transport、Store、Agent | 不可以 | 不可以 | | 直接 Host / Tauri / OS 调用 | 不可以 | 不可以 | | 读取其他 MiniApp 数据 | 不可以 | 不可以 | 系统内建不等于绕过 Runtime:可信来源只决定代码的发布与 UI 执行方式,不改变 Runtime 的 通信、焦点、Tool、权限和审计边界。 ## 6. MiniApp 实例、焦点与恢复 MiniApp Registry 管理“有哪些小程序”,Instance Manager 管理“哪些实例正在运行”。二者不能 混为一个状态。 ```ts type MiniAppInstanceRecord = { instance_id: string; app_scope: string; conversation_id?: string; state: | "starting" | "foreground" | "background" | "suspended" | "stopping" | "stopped" | "failed"; parent_instance_id?: string; started_at: string; stopped_at?: string; error?: string; }; ``` Runtime 保存焦点栈,不以单个 MiniApp 自己的布尔状态作为事实来源: ```text focus stack: chat:audio-001 draw-and-guess:game-001 foreground: draw-and-guess:game-001 background: chat:audio-001 ``` 当扩展 MiniApp 关闭或失败时,Runtime 必须恢复焦点栈中的前一有效实例。重启后,Runtime 恢复有界的实例与焦点状态;`starting` 或 `stopping` 中断的实例必须安全降级为 `suspended`, 不得伪装为已完成的 Host 操作。 ## 7. MiniApp SDK v1 下一阶段的核心交付是 **LineUp MiniApp SDK v1**。SDK 不是万能 API,而是 Runtime 根据 Manifest、实例状态、权限和 Policy 开放的最小请求集合。 ```ts interface LineUpMiniAppSDK { readonly context: MiniAppContext; inbox: MiniAppInboxAPI; tools: MiniAppToolAPI; ui: StandardInteractionAPI; lifecycle: MiniAppLifecycleAPI; surfaces: MiniAppSurfaceAPI; capabilities: MiniAppCapabilityRequestAPI; } type MiniAppContext = { app_scope: string; instance_id: string; conversation_id: string; app_version: string; state: "starting" | "foreground" | "background" | "suspended"; }; ``` ### 7.1 Inbox ```ts interface MiniAppInboxAPI { list(after_message_id?: string): readonly MiniAppMessage[]; subscribe(listener: (message: MiniAppMessage) => void): Unsubscribe; acknowledge(message_id: string): boolean; } ``` Runtime 在投递前校验 Envelope、scope、目标 MiniApp、实例状态和去重;消息先持久化,再由 MiniApp ACK。后台化、刷新、Surface 重载或 Runtime 重启不能丢失未处理消息。 ### 7.2 Tool ```ts interface MiniAppToolAPI { subscribe(listener: (call: MiniAppToolCall) => void): Unsubscribe; get(call_id: string): MiniAppToolCall | undefined; reportProgress(call_id: string, progress: MiniAppToolProgress): Promise; complete(call_id: string, result: JsonObject): Promise; fail(call_id: string, failure: MiniAppToolFailure): Promise; cancel(call_id: string, reason?: string): Promise; } ``` `complete`、`fail`、`cancel` 都是对 Runtime 的请求,不是直接网络发送。Runtime 必须验证 `call_id` 的实例归属、合法状态迁移、输入/输出 schema、幂等性和权限,然后持久化、审计并 写入 outbox。 ### 7.3 标准交互、Lifecycle、Surface 与 Capability Runtime 通过 `sdk.ui` 提供 `notice`、`choice`、`confirm`、`input` 四种标准交互原语。这是由 Runtime 统一拥有的标准输入输出库:Runtime 创建和持久化交互记录,注入 owner、校验请求/结果、 负责恢复、审计与路由,并依照 Shell Policy 决定呈现位置。 `owner` 不属于 SDK 调用参数。Runtime 仅从 SDK 已绑定的 `MiniAppContext` 注入 `app_scope`、`instance_id`、`conversation_id`,并可带有已验证的 `parent_call_id`、`surface_id` 与 来源;MiniApp 不可伪造、覆盖或访问其他 owner 的交互。`presentation` 只能作为 `inline`、`modal` 或默认形式的偏好,最终仍由 Runtime/Shell 决定。 Runtime 内部至少持久化以下归属信息: ```ts type StandardInteractionOwner = { app_scope: string; instance_id: string; conversation_id: string; parent_call_id?: string; surface_id?: string; source: "agent_tool" | "miniapp_tool" | "runtime_policy"; }; ``` Agent 在 IM 中的提问由 Interact 作为默认可信 Renderer Provider 呈现在 IM 时间线/卡片内。前台 MiniApp 自己请求的低复杂度事务提示,可在该 MiniApp 的有效容器或 Surface 中以 Runtime 批准的 标准 modal、sheet 或 card 呈现,不能因此强制切换到 Interact。结果始终先返回 Runtime,再仅投递 给 owner MiniApp;MiniApp 不可自行创建 Host 弹窗或直接将结果发送给 Agent。 复杂、高频或私有的业务 UI(例如 Whiteboard 画布文字编辑、画笔、颜色选择、拖放和工具栏)留在 MiniApp 自己的 Surface 内,不使用标准交互库。系统权限确认(文件、麦克风、通知等)则属于 Runtime/Host Capability Gateway,而不是普通 `confirm`。 ```ts interface MiniAppLifecycleAPI { requestForeground(): Promise; requestBackground(): Promise; requestClose(reason?: string): Promise; } ``` MiniApp 只能请求生命周期变化;Runtime 决定是否允许,处理 pending Tool/Surface,并负责 焦点恢复。 Surface 与 Capability 也只能请求: ```text MiniApp requestOpenSurface / requestCapability → Runtime 校验 Manifest、Policy、实例状态和用户确认要求 → Host Provider 执行受限操作 → Runtime 记录审计并返回受控结果 ``` 不应在 SDK v1 提供 `fetch`、任意网络、任意文件系统、剪贴板、麦克风、摄像头或 Tauri 直接调用。高风险能力以后通过 Capability Request 按需开放。 ## 8. Tool Contract 与 Inventory MiniApp 只能在 Manifest 中声明 Tool;Agent 只能调用当前 Runtime 已公布 Inventory 中的 Tool。 ```ts type ToolDescriptor = { id: string; // 例如 task-dashboard.open version: 1; handling: "direct" | "interactive" | "launch" | "foreground" | "operation"; target: { app_scope: string; requires_foreground: boolean; restore_previous_focus: boolean; }; input_schema: JsonSchema; output_schema: JsonSchema; permissions?: readonly string[]; timeout_ms?: number; }; ``` 统一调度路径: ```text Agent Tool Invoke → Runtime 校验 Envelope、Inventory revision、Tool Descriptor、参数、scope、App 状态和权限 → 创建可持久化 Tool Call / 审计记录 → Tool Router 判定 direct / interactive / launch / foreground / operation → 投递到目标 MiniApp instance → MiniApp SDK 报告 progress / result / error → Runtime 校验输出 schema、持久化、更新焦点、写 outbox → Agent 收到可靠结果 ``` `notice`、`choice`、`confirm`、`input` 是 Runtime 的统一 `interactive` Tool/交互记录能力。 Interact 提供 Agent/IM 场景的默认 Renderer,而不拥有记录或绕过统一 Tool Call、持久化和结果路径; 其他 MiniApp 只能通过 `sdk.ui` 在自身有效容器使用 Runtime 批准的标准 Renderer。 建议稳定拒绝码至少包括: ```text inventory_revision_mismatch tool_not_advertised tool_input_invalid tool_output_invalid app_disabled app_instance_not_found app_scope_mismatch lifecycle_denied capability_denied call_already_final ``` ## 9. Surface、Bundle、Capability 与发布安全 复杂 UI 只能运行在受限 Surface 中。Installed MiniApp 的生产 Bundle 必须满足: ```text 签名 Manifest → 精确 byte size 校验 → SHA-256 校验 → 原子写入已验证 cache → app_id + exact version 解析 → sandbox="allow-scripts" 的隔离 Surface ``` ### 9.1 Host 兼容矩阵 | 情况 | Host 必须行为 | 禁止行为 | 观测信号 | |---|---|---|---| | 旧 Client 收到未知 `lineup.v1.*` | 安全 fallback,不执行 | 将 payload 当 HTML/能力执行 | `unsupported_type` / `unsupported_version` | | 新 Client 收到旧 plain text | 仅作为 Markdown 显示 | 赋予交互或能力 | legacy markdown renderer | | 不支持目标 Surface version | 不挂载,显示安全提示 | 自动前移到相邻版本 | `surface_unavailable` | | 收到生产 Surface | 仅在签名、长度、SHA-256 成功后挂载已验证 bytes | 接收 URL、HTML、JS、Bundle/source | install disposition | | 候选 Bundle 验证失败 | 保留当前 active 已验证版本 | 覆盖 active bytes 或执行候选 | `signature_invalid` 等 | | active Bundle 被撤销 | 原子回滚到已验证 predecessor;没有则不可用 | 回退到未验证缓存/远端 URL | `rolled_back` / `unavailable` | | Bridge 收到非当前 iframe 消息 | 丢弃 | 仅相信 origin 字符串或调用 Host API | bridge rejection counter | | Capability Catalog 变化 | 发布最小新 Inventory | 用过期 Inventory 自动执行 | catalog revision | ### 9.2 生产发布序列 1. 发布方创建不可变 artifact 与生产 Manifest:`app_id`、精确版本、artifact ID、长度、 SHA-256、最小 Host 版本、权限、可信 `key_id`、Ed25519 签名。 2. Manifest 与 Bundle 部署在 Host 配置的 HTTPS artifact 服务;Manifest 不携带 URL、HTML、 CSS、JS 或 source。 3. Host 在临时内存中验证签名、精确长度与 SHA-256;失败不写 cache。 4. 验证成功后原子安装,并只解析精确 `app_id + version`;不得自动前移版本。 5. 仅向满足最小 Host 版本且已启用目标版本的 Client 灰度发布。 6. 监控签名、摘要、下载、Bridge 与 Capability 状态;安全事件发生时只回滚到已验证的 predecessor。 7. 回滚后保留审计元数据,但不记录 artifact 内容、URL、token、文件路径或 Capability 参数; 新 artifact 必须使用新版本号。 正式 HTTPS Host 才可被标记为 production-capable。HTTP LAN 开发 Host 在浏览器 WebCrypto 受限时必须安全拒绝验签,不能为了联调放宽该规则。 ## 10. 当前实现状态 ### 10.1 已完成:历史安全基础 历史 M0~M4 已完成并沉淀在当前代码中;它们不是新的平行排期: | 历史阶段 | 保留能力 | |---|---| | M0 | HTTP Transport、Conversation Store、协议解码、Markdown、安全 fallback、基础回归 | | M1 | Tool Call、Task、可靠交互结果、执行摘要、可信 choice/confirm/input | | M2 | Surface Registry、实例生命周期、隔离 iframe 与恢复 | | M3 | Capability Registry、用户确认、审计与受限 Host 执行 | | M4 | 签名 Manifest、Bundle 校验/缓存/回滚、golden fixture | ### 10.2 已完成:第二次升级 ```text 00.base → Runtime 托管 Interact IM(当前兼容名 chat)的稳定基线 01.kernel → MiniApp Instance / Focus / Lifecycle、Tool Router、App Orchestrator、 Extension SDK 雏形、Workspace 持久化和恢复 ``` 当前实现已验证登录、同步、本地回显、Markdown、安全渲染、Tool Call、Task、Surface、 Capability、App Inbox、outbox、实例焦点恢复和生产构建。自动化回归当前为 23 个测试文件、 99 个测试;`npm run build` 通过。 Runtime 的关键结构位于: ```text tauri/src/runtime/app-management/ tauri/src/runtime/coordination/ tauri/src/runtime/persistence/ tauri/src/runtime/protocol/ tauri/src/runtime/surfaces/ tauri/src/runtime/capabilities/ tauri/src/core-apps/chat/ ``` ### 10.3 下一阶段:03.sdk_and_coreapp 下一阶段不是应用市场,也不是立即建设服务端下载目录。目标见 [03.sdk_and_coreapp.md](迭代/03.sdk_and_coreapp.md):定义并验证 MiniApp SDK v1: ```text 冻结 AppManifest、ToolDescriptor、Tool Call、App Context、Result/Progress/Error 和错误码 → Runtime 实现通用 SDK 请求路由、schema 校验、审计、恢复和 revisioned Inventory → Interact 适配为第一个 System MiniApp SDK 样本 → Task Dashboard 作为第一个参考 MiniApp 验证 Tool、progress、result、focus 与恢复 → Whiteboard 验证受限 Surface、状态 patch、Artifact 与 Capability 请求 ``` 参考 MiniApp 在此阶段可以是 `bundled-development`:随开发 Host 内置、有 Manifest 和 Runtime 注册记录,但不依赖服务端 Catalog、远程下载或第三方发布。 ### 10.4 后续阶段 MiniApp SDK 与参考实现稳定后,再按顺序推进: ```text 03.reference-miniapps → 完成 Task Dashboard / Whiteboard 的端到端参考实现 04.app-delivery-registry → Catalog Entry、Manifest/Bundle 下载、验签、安装、启用、禁用、更新、回滚、移除 05.catalog-and-market(按产品需要) → 搜索、分类、发布者、安装 UX、组织分发与可能的商业能力 ``` “市场”属于最后的产品分发层,不能反向决定 Runtime、SDK、Tool 或安全模型。 ## 11. 验收与发布门槛 每次 Runtime、MiniApp SDK 或 Host 改动至少满足: ```text npm test -- --run npm run build ``` 对于 SDK/参考 MiniApp,还必须有以下证据: 1. 合法与非法 Manifest、Inventory revision、Tool 输入/输出 schema 的自动化测试; 2. Tool 启动 MiniApp、前后台切换、结果回传、失败回焦和重启恢复的场景测试; 3. Interact 的 `notice / choice / confirm / input` IM 呈现不退化,且覆盖 owner 自动注入、跨 owner 访问/提交拒绝、owner 结果回路与 MiniApp 容器内呈现的测试; 4. Installed MiniApp 无法取得 Host DOM、Tauri invoke、token、任意网络或其他 MiniApp 数据; 5. 有头浏览器验证登录、同步、本地回显和代表性 MiniApp 路径; 6. 对生产 Bundle,验证签名 `open → patch → close → rollback`、隔离 Bridge 和 Capability 拒绝路径; 7. `git diff --check` 无格式错误,日志不得包含身份、会话、消息正文、Tool 参数、token 或 artifact 内容。 ## 12. 相关文档与源码导航 - [迭代/00.base.md](迭代/00.base.md):Runtime 托管 Interact IM 的稳定基线。 - [迭代/01.kernel.md](迭代/01.kernel.md):Runtime Kernel 与 MiniApp 编排目标和验收。 - [tauri/src/README.md](tauri/src/README.md):当前源码目录和依赖方向。 - [tauri/README.md](tauri/README.md):Tauri/Web Host 的运行、回归与历史实施细节。 - [程序文件清单与功能说明.md](程序文件清单与功能说明.md):实现文件和功能说明。 - [LineUp App 最终设计方案](../设计/02.正式方案/app_final_design.md):跨文档详细契约来源; 若与本文的产品术语或当前迭代顺序冲突,以本文为准并同步更新上游方案。