Files
makelore/.project-docs/20-architecture/system-overview.md
brother7 eedd20d061
Some checks failed
Electron E2E / Electron E2E (macos-latest) (push) Has been cancelled
Electron E2E / Electron E2E (ubuntu-latest) (push) Has been cancelled
Electron E2E / Electron E2E (windows-latest) (push) Has been cancelled
docs(integration): record remember password boundary
2026-08-20 23:45:13 +08:00

16 KiB
Raw Blame History

System Overview

Current Architecture

Makelore 是 Electron 桌面客户端。Renderer 负责项目操作与状态展示Electron Main 持有认证、文件系统、安全打包、Works Square 网络访问和发布安全校验。

Main Components

Component Responsibility Notes
Renderer 项目配置、一键提交状态 不接触账号 Token、ZIP、幂等键或本地绝对路径
Host API 校验本地项目请求并投影安全响应 发布 mutation 还必须通过 Renderer capabilityHost token/base 不能单独触发发布
Project Configuration & Template 保存不可变 ProjectType,原子生成新项目骨架 小游戏/小程序生成受控 Vite 模板;自定义保持最小项目空间
Project Release Builder Main-owned 安全快照、本地 npm/Vite 构建、双归档与 artifact contract 固定 npm 11.6.2Vite 由项目 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_urlruntime_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 WebSocketMain → Host API/SSE → Renderer store 命令、Run 与设计事件共用双向 WebSocketConversation 更新按 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 URLRenderer 不获得任意归档 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/me 401 必须清理 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 dev now 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 saved or cancelled; 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-store at 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=0 disables 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 等待。Electron net.fetch 失败后的 Node fetch 透明回退只允许 GETHEADOPTIONSPATCH/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。

  • 当前长期边界记录于 README、ADR-001 至 ADR-005、集成任务 20260807-integrate-login-client-a4f8、源任务 20260810-static-release-only-a91c20260812-client-built-release-makelore-7e5b20260812-design-image-to-image-client-c91e 及本次 Integration Gate后续如改变唯一入口、凭据所有权、构建执行边界、Conversation 状态归属、Learning 项目分发边界、Robot 配网/绑定安全边界或重新引入客户端部署协调器,应新增 ADR。

Last Updated

2026-08-20