16 KiB
System Overview
Current Architecture
Makelore 是 Electron 桌面客户端。Renderer 负责项目操作与状态展示;Electron Main 持有认证、文件系统、安全打包、Works Square 网络访问和发布安全校验。
Main Components
| Component | Responsibility | Notes |
|---|---|---|
| Renderer | 项目配置、一键提交状态 | 不接触账号 Token、ZIP、幂等键或本地绝对路径 |
| Host API | 校验本地项目请求并投影安全响应 | 发布 mutation 还必须通过 Renderer capability;Host token/base 不能单独触发发布 |
| Project Configuration & Template | 保存不可变 ProjectType,原子生成新项目骨架 |
小游戏/小程序生成受控 Vite 模板;自定义保持最小项目空间 |
| Project Release Builder | Main-owned 安全快照、本地 npm/Vite 构建、双归档与 artifact contract | 固定 npm 11.6.2;Vite 由项目 lockfile 锁定;产物与预检使用同一内存字节 |
| Works Session & Remembered Password | Main-owned 登录、刷新、注销、七天真实活动滑动续期与可选密码回填 | 登录、刷新、注销统一经过 Works Square;轮换凭据由 Main 安全持有和持久化。记住密码使用独立的 packaged-only OS 加密记录,不进入 Renderer 持久状态或 Works Square;客户端不携带 OAuth client secret |
| Module Access Policy | Main-owned /api/auth/me projection → Renderer auth state → module chooser/router |
Renderer 只接收 Code/Canvas/Learning/Robot 四个布尔值;缺失对象或字段默认开启,服务端 design 映射客户端 painting |
| Submission Binding | 保存云端已接受的精确 app/version/review/hash 绑定 | schema v2 只记录成功提交;旧中间态迁移为 legacy_retired,不恢复后台任务 |
| Play URL Projection | 校验服务端公共播放地址 | 只接受同源 HTTPS 和精确 /apps/{app_id}/;优先 play_url,runtime_url 仅一版本回退 |
| Built Artifact Preflight | 在上传前对最终 built snapshot 做桌面/移动 UX fail-fast | Main 使用临时 loopback origin 与 Electron WebContents/CDP;不使用 Playwright、不生成可信证明 |
| App Updater | Main 选择平台/架构 feed、驱动 electron-updater 并记录原始诊断 | Renderer 只接收状态和脱敏后的单条用户提示;稳定源缺包保持错误 |
| AI Design Workspace | 保存项目身份、Conversation 列表、生成任务和资产 | 任务和资产在切换 Conversation 后继续可见 |
| AI Design Conversation | 保存消息、Brief、Quote、turnRevision 与服务端 Agent Session 绑定 |
同一 Workspace 内互相隔离;Session 由服务端持久化 |
| AI Design Image Source Picker | 当前 Workspace 已完成图片或本地上传 | 图片 Brief 绑定图生图参考图;视频 Brief 绑定首帧;提交一个真实 Asset ID |
| AI Design Gateway Routing | Main 云端适配器 ↔ Conversation WebSocket;Main → Host API/SSE → Renderer store | 命令、Run 与设计事件共用双向 WebSocket;Conversation 更新按 Workspace + Conversation 路由,任务更新按 Workspace 归并 |
| AI Design Quote & Task Controls | 当前 Conversation Quote 与 Workspace 任务 | 最终 Prompt/generation options 每次修改由服务端重新计价;任务结果在详情中预览并经 Main-owned asset download 保存 |
| Prompt Museum | Canvas “获取灵感”页面 → Main Host API → Works Square | 服务端驱动的审核内容、筛选和分页;Renderer 不持有 Works Token 或内置数据集,“使用此 Prompt”只回填输入框 |
| Learning Project Catalog | 服务端分页项目卡片、README 详情与用户选择的 ZIP 下载 | Renderer 只持有安全项目 DTO 和 Markdown;不提供生成、进度、本地课程库或播放器 |
| Learning Main Boundary | 固定 Host API → Works Square project list/detail/media/archive | Main 持有 Works Bearer、封面/历史媒体代理、原生保存路径、受控重定向、临时文件、SHA-256/ZIP 签名校验与原子落盘;归档下载不执行大小校验,README 图片节点可直接加载无凭据 HTTPS URL,Renderer 不获得任意归档 URL 或本地路径 |
| Robot Workspace | Account-scoped agent configuration, device activation/binding, assignment, and credential-recovery UI | Renderer receives only safe Works Square projections. Configuration choices come from the USER-scoped safe catalog; unavailable current values remain editable without exposing provider credentials or configuration internals. |
| AI Hardware Main Route | Fixed /api/works/ai-hardware Host API to Works Square proxy | Main owns Bearer auth, stable operation IDs, bounded retry, ETag/If-Match, request/response limits, error redaction, and the fixed no-store configuration-catalog proxy. Versioned responses accept only canonical strong or weak numeric ETags that equal the DTO revision; mutations always emit strong If-Match. It never forwards Renderer authorization headers. |
| Robot Hotspot Module | Main-owned bounded scan/connect/verify interface with Windows WLAN and macOS CoreWLAN/CoreLocation adapters | Accepts only short-lived opaque candidates from the latest scan, exposes no BSSID/interface/profile/native diagnostic, and retains the system-Wi-Fi fallback. |
| Guided Hotspot Binding V1 | Implemented, default-on Renderer journey over in-page hotspot selection, the current firmware Portal, and six-digit Binding | Exact environment value 0 disables the journey. Hotspot discovery is unauthenticated convenience; Portal credential entry remains firmware-owned, and no BLE, automatic claim, or firmware change is part of V1. |
Important Boundaries
-
Renderer 只能通过 Main Host API 发起认证操作。Electron Main 是 access/refresh token 的唯一客户端所有者;登录、刷新、注销统一经过 Works Square 固定路由,客户端不得直连 one-feel/custom 身份服务,也不得保存 confidential OAuth client secret。
-
可选的记住密码记录属于 Electron Main 的独立本机边界,只能在正式安装包且 OS 凭据加密可用时落盘;Renderer 不得持久化账号密码,Works Square 不得接收记住标志或新增密码持久化。
-
Code、Canvas、Learning 与 Robot 是四个已启用顶层产品模块;Robot 仍是唯一硬件产品模块,不存在单独 Hardware 卡片。
-
每个登录用户可由 Works
module_access关闭任意顶层模块入口。Main 只投影四个布尔值;被关闭卡片置灰不可点,根/深层/别名路由在MainLayout和模块初始化前拦截。Code provider 必须等待 auth policy hydration,而全局/settings不属于 Code policy guard。 -
模块入口策略是用户交互与客户端初始化边界,不是服务端 API 授权。终止性
/api/auth/me401必须清理 Main 和 Renderer 会话;各模块 API 仍须独立强制认证与授权。 -
Product UI language is Chinese-only. Unsupported system or persisted language values normalize to
zh; removed locale files are not runtime fallbacks. -
Packaged Canvas remains cloud-only with no local fallback.
pnpm run devnow uses the cloud adapter; the local Workspace adapter requires the explicit development command and remains unpackaged-only. -
Prompt Museum is a read-only curated inspiration surface, not a user-content community. Main owns Works authentication and forwards only the bounded list/detail routes; the client never bundles museum content or automatically submits a selected Prompt.
-
Learning uses a Main-owned read-only project-catalog boundary. Renderer does not receive Works credentials, object-storage identifiers, arbitrary archive URLs, temporary/final paths, or an arbitrary network proxy. README raw HTML is disabled; Markdown image nodes alone may load validated credential-free HTTPS URLs directly, including SVG and other formats Electron supports. Main continues to validate covers/historical media and streams a selected project ZIP through bounded same-origin redirects, SHA-256, ZIP signature, and atomic rename before returning only
savedorcancelled; it ignores archive size metadata and applies no client download-size ceiling. -
AI hardware network access is Main-owned. Renderer cannot hold Works Square or Xiaozhi credentials and cannot select arbitrary upstream paths or headers.
-
Robot model, language, and voice choices are dynamically projected from the Xiaozhi USER catalog through Works Square and Electron Main; the catalog is bounded, account-scoped, and
private, no-storeat each public hop. -
One local account maps to one server-side Xiaozhi account binding. Agents and devices are resources beneath that account binding, not separate Xiaozhi users.
-
Robot/Canvas/module-selection routes must not initialize AI Programming projects or providers.
-
Guided Hotspot Binding is implemented behind a Main-owned capability that is true by default; exact
NIANCODE_AI_HARDWARE_GUIDED_HOTSPOT_BINDING=0disables it, while capability-read failure falls back to direct six-digit Binding. The guided state is process-local, opener failures expose only the same fixed address for manual copy, and Binding conflicts refresh the safe account overview. -
Robot hotspot scanning and connection are local Main operations that return before Works credentials/upstream access. Renderer may submit only an opaque candidate ID from the latest bounded scan; Main alone filters open printable
Xiaozhi-*SSIDs, performs platform association, and verifies the exact current SSID. -
Hotspot discovery and connection do not authenticate a Robot. BSSID, interface/profile details, native diagnostics, location data, and Wi-Fi credentials never cross the Main boundary; permission or platform failure keeps the system-settings/manual path available.
-
The fixed portal action may open only
http://192.168.4.1/in the system browser and must not acquire cloud credentials or call Works Square. Renderer never supplies a portal URL and never handles Wi-Fi credentials. -
A successful Binding means account ownership was established; it is not evidence that the Robot is currently online or protocol-ready.
-
发布只有现有项目配置底部的一个入口,不新增发布工作台、侧栏或资源卡。
-
创建者发布唯一调用链是
ProjectPublishAction → publishWorksProjectSource → Main-owned release build → preflightStaticArtifact → source+built+artifact_contract 上传 → 状态轮询;客户端不再提供 Compose runner、deploy-check、watcher/arm/upload 协调或手工 ZIP 上传入口。 -
release builder 对 Main-owned 安全快照运行安装包内固定 npm 11.6.2 的
ci --ignore-scripts,并显式调用项目package-lock.json锁定的 Vite。不得使用全局 PATH、预存node_modules或 Renderer 提供的路径/origin。项目 Vite config/plugins 以桌面用户权限执行,该边界不是 sandbox。 -
preflightStaticArtifact以临时 HTTP loopback origin 提供最终built_archive的同一内存文件快照,并用 fresh 非持久、未挂载的 Electron WebContents/CDP 检查桌面/移动视口、错误、白屏及外域访问;不安装/调用 Playwright。 -
客户端预检是可绕过的 UX fail-fast:没有可信 receipt,也不复刻生产 opaque-origin。服务端不执行项目 Vite,而是独立重算和校验 source/built/contract 字节、固化不可变 Release;人工审核仍不可绕过。未来若要求 runtime 强门禁,需由可信 verifier 绑定精确构建产物。
-
ProjectType由创建请求写入项目配置,UI 与 Host API 不提供类型变更;缺少类型的旧配置归一为custom。 -
本地
projectType只选择产品路径和内部构建 preset,不是可信授权声明;Main 仍需安全打包,服务端仍需独立校验清单和包体。 -
云端确认上传成功后,本机 submission binding 失败只能产生固定、无路径的
binding_warning,不能把请求改判为失败;Renderer 仍继续轮询服务端校验与 Release 固化状态。 -
公共播放投影只有在上游
playable === true、版本名非空且 URL 通过同源 HTTPS、无 userinfo/loopback、长度、精确路径和无 query/fragment 校验时才可播放;不可信数据 fail closed。 -
Renderer 只能获得安全状态字段和安全投影的公共播放 URL,不得持有发布凭据、归档路径或自动部署状态。
-
落盘文件名
works-cloud-deploy.json仅为已安装客户端的数据兼容;领域模型和代码接口是 submission binding,不表示仍存在 cloud deployment coordinator。 -
AI 绘画中,一个 Workspace 可包含多条 Conversation;消息、Brief、Quote 和
turnRevision属于 Conversation,生成任务和资产属于 Workspace。新建 Conversation 不得隐式创建新 Workspace。 -
每条 Conversation 复用服务端持久 Agent Gateway Session。客户端不得在注销或退出时 DELETE 该 Session;只关闭本地事件流并清除本机 Session-id 缓存,重新访问时从 Conversation API 刷新。
-
已连接的 Conversation Session 通过同一 WebSocket 提交
command.submit并接收command.accepted、Run 与设计事件。只有发送失败、连接关闭或 ACK 超时属于可回退的传输故障,REST 必须复用同一client_command_id;结构化 Gateway 业务错误不得再次提交,未知上游错误文本不得穿透 Main 安全投影。 -
Main-owned Canvas Workspace JSON 请求和 shared Works token refresh 的完整生命周期最多 30 秒,超时 abort transport 并以固定
504 DESIGN_WORKSPACE_REQUEST_TIMEOUT结束 Renderer 等待。Electronnet.fetch失败后的 Node fetch 透明回退只允许GET、HEAD、OPTIONS;PATCH/POST 等 mutation 只允许由持有显式幂等身份的上层协议决定重试,不能由底层 transport 隐式重放。该边界不改变上面的 WebSocket→REST 幂等 fallback。 -
Renderer 的异步与流式状态必须同时校验 Workspace + Conversation 身份;项目任务事件只按 Workspace 归并,避免切换会话时丢失任务或接收迟到消息。
-
确认生成按 Quote 对账 Workspace 任务。任务事务已提交但 Run 随后失败时可通过 REST 恢复任务可见性;内部任务对账失败不写当前 Conversation 的用户错误,任务恢复也不授权旧请求回写已切换的 Conversation 或清理新 pending turn。
-
Updater feed 选择、原始错误日志、下载和安装生命周期只属于 Electron Main。Renderer 不得把缺失稳定 manifest 投影为“已是最新版”,也不得显示原始堆栈、URL、路径或错误码;并发检查共享同一错误事件时只发送一次错误状态,后续独立重试仍可重新报告。
-
图片与视频复用同一个单图来源选择器。图片 Brief 可从当前 Workspace 的已完成作品或本地上传中选择一张参考图继续生成;视频 Brief 使用同一入口绑定首帧。两条路径都必须通过现有 Workspace Asset 上传/选择契约提交一个真实
attachmentAssetIds,不得用本地路径或自然语言描述代替资产身份。 -
Canvas generation confirmation must use the latest server Quote after final Prompt or generation-option edits; the client displays server pricing and submits parameter values but does not derive provider dimensions, supplier pricing, or design-point cost.
-
Canvas project deletion is an explicit destructive Workspace mutation guarded by exact project-name confirmation. Renderer clears the deleted Workspace's local state and selects the most recently updated remaining Workspace; upstream hiding, cancellation, reservation release, and settlement remain service-owned behavior.
-
当前兼容协议仍通过精确 quick reply
从作品列表选择图片打开选择器,并由当前 Brief medium 区分用途;仅medium === image使用图生图语义,video、null 或缺失 medium 保持视频首帧语义。该展示文案耦合不得扩散到更多用途,后续应升级为结构化 action/purpose。
Related Decisions
- 当前长期边界记录于 README、ADR-001 至 ADR-005、集成任务
20260807-integrate-login-client-a4f8、源任务20260810-static-release-only-a91c、20260812-client-built-release-makelore-7e5b、20260812-design-image-to-image-client-c91e及本次 Integration Gate;后续如改变唯一入口、凭据所有权、构建执行边界、Conversation 状态归属、Learning 项目分发边界、Robot 配网/绑定安全边界或重新引入客户端部署协调器,应新增 ADR。
Last Updated
2026-08-20