Files
Agent-System-Documents/docs/proposals/2026-10-12-svc-unified-deploy-and-login-key.md
T
weichenandCursor 7df7d786d0 Record r1 approval for svc unified deploy proposal
Why: user approved the proposal and U1/U4 specs and authorized push/PRs
plus U1/U4 implementation start.
Evidence: SELF conversation approval 2026-10-12; implementation still NOT_RUN.
Impact: planning status only.
Refs: docs/proposals/2026-10-12-svc-unified-deploy-and-login-key.md

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 03:32:55 +00:00

14 KiB
Raw Blame History

title, type, date, artifact_contract, execution, product_contract_source
title type date artifact_contract execution product_contract_source
svc 统一部署与一次性登录 Key 方案 feature 2026-10-12 ce-unified-plan/v1 code ce-plan-bootstrap

svc 统一部署与一次性登录 Key 方案 r1

确认状态:已批准(2026-10-12 用户「批准,继续推进」:需求拆解→实施计划五阶段及 U1/U4 规格一并批准;授权推送/PR 与启动 U1/U4 实施;合入仍由 owner 执行)。业务实施、测试、部署与运行验收在批准时仍为 NOT_RUN,由后续实施任务推进。 修订记录:r1=2026-10-12 草案经源码复核后定稿(四项取舍采纳;补齐 §6 合同;对齐恢复方案 KTD 与已合入的 recovery U1 实例身份);同日获批并进入推送与 U1/U4 实施。 需求来源:2026-10-12 用户提出将 svc.sh 增强为统一部署入口(二进制与源码、环境准备、无初始密码开户与账户恢复),并要求一次性 API Key 只能兑换「设置密码」受限会话。负责人:weichen;编制:Cursor Agent。 主记录:本文;任务卡:Dev .task/feature-svc-unified-deploy-login-key.md。源码路径以 Dev 根目录为基准。

1. 目标与成功边界

目标:在干净或既有机器上,用同一套 svc 入口完成二进制或源码部署、按档准备依赖,并通过后端账户能力完成无初始密码开户与账户恢复;一次性登录 Key 只能兑换设密受限会话,完成设密前不能访问业务数据。

必须区分三类能力:

能力 结果 非目标
统一安装 / 升级 指定版本或提交物化为可切换候选;切换后实例身份、DB、数据根与账户不变 不接管共享 PostgreSQL;不因发现端口而认领外部服务
环境检测与准备 doctor 只报告;env prepare 按模式执行可幂等计划 不把任意发行版 Go/Node 标为可构建;工具链版本读自所选提交或发布清单
账户激活 / 恢复 无预设密码开户或签发恢复 Key;原子兑换 → 受限会话 → 设密 → 正常登录 不删除重建用户;不迁移业务归属;普通找回默认不撤销长期集成 Key

与 服务重启与全量数据恢复方案 r2 的关系:

  • 复用 KTD1–5、KTD12:持久 manifest、唯一监管者、team=PG 且失败不回落 SQLite、readiness 与身份。
  • 复用 已合入的 recovery U1(Dev #415):runtime/<name>/manifest.json、启动身份校验、svc init、原子写路径(见 Dev docs/recovery/u1-identity-manifest.md)。
  • 本方案新增:部署来源统一(binary/source)、doctor/env prepare、账户生命周期与一次性登录 Key、安装入口与双轨收敛。
  • 命名区分:账户恢复 Key ≠ 服务数据恢复。

2. 当前事实及重点差距

源码基线(SELF·工作区观察,启动 precheck READY):Dev af9c2de663be5ff102dcab7698464a645832f569;Backend gitlink 以该提交为准;本地评审时曾对照 3fa0d3a / Backend 696ef15,与当前 main 可能有漂移,实施前以 task-sync 后 SHA 为准。运行验收 NOT_RUN。

对象 已存在的基础 尚需补齐
部署来源 deploy --from local|dev|release|rdm;dev/rdm 独立缓存物化;release 读本地 Releases 仓并校验 sha256 远程下载/离线导入;统一 install;release@ver 钉扎(现 sort -V|tail -1 取最大版本,见 scripts/svc.sh resolve_release)
部署生命周期 预检失败不停机;预检通过后 先停再构建;无程序备份/自动回滚 候选获取与校验全程不停旧服务;缺摘要硬失败;迁移后回退独立判断
实例身份 recovery U1:manifest + marker + init;svc.env 派生 账户 CLI 必须绑定实例最终配置;缺绑定拒绝,禁止回落 ./data
环境 端口/flock/pg 工具链按需检查;文档列前提 doctor / env prepare;无 flock 时不得放行冲突操作(现状直通)
账户 CLI user create|reset-password|list;省略密码 → 随机明文一次 + must_change 无密码创建 + 激活 Key;恢复 Key;OpenExisting(不建空库、不静默 migrate)
API Key 明文只显示一次;可长期复用;无 TTL/次数 独立一次性登录凭据表;不可走 Bearer/?key=
强制改密 前端门控 + /api/me 标志;changePassword 要求原密码 服务端中间件拦截待改密/受限会话;设密分型(一次性会话不要求原密码)
安装双轨 Dev svc deploy 多实例;Releases install.sh 系统 systemd 统一部署计划;install.sh 薄封装或明确遗留

命题裁定(源码复核):

  1. 长期 API Key 是 show-once plaintext,不是 single-use — 成立。
  2. 无统一中间件拦截 must_change_password — 成立。

3. 需求合同

ID 范围 要求与可判定验收
R1 安装入口 doctor / install / 兼容 --from 生成同一部署计划;二进制无需 Go/Node;源码固定提交且子模块组合可核验
R2 实例身份 启停、升级、开户、签发 Key 命中同一 store 与 data 根;缺失/不符拒绝;与恢复案 R2/manifest 一致
R3 切换安全 构建/下载/摘要失败时旧服务继续;程序+插件+前端作为版本组合切换;固定版本不得被「最大版本」替代
R4 存储档 team 默认 PG+auth;existing / managed-local / local(SQLite) 显式选择;PG 失败不回落 SQLite
R5 开户 无初始密码;角色明确;创建与激活 Key 同事务;同名冲突不覆盖
R6 账户恢复 精确命中既有账户;不改密码/不吊销会话/不改业务数据于签发时;保持 owner/角色/成员关系
R7 一次性 Key ≥256bit、只存摘要、activate|recover、默认 TTL 30min、状态机、原子兑换、专用 POST body
R8 受限会话 仅身份查询、设密、退出;业务/下载/SSE/admin/插件拒绝;普通 must_change 同样服务端限制
R9 设密事务 写 hash、清待激活/待改密、作废未用恢复凭据、失效相关会话同事务;成功后销毁受限会话并要求密码重新登录
R10 集成 Key 普通找回默认保留长期 API Key;失陷恢复显式 --revoke-all-credentials
R11 首次管理员 仅核验为新实例(无用户且无历史业务标记);事务防并发;不得因「未发现管理员」接管有数据环境
R12 证据 验收绑定固定源码/制品摘要/环境;SELF/REPLAY/GATE 分源

4. 技术决策(KTD)

KTD1. 部署方式只决定程序来源,不决定数据位置。 binary ↔ source 可切换;切换保持 DB、数据根、账户与 instance_id。

KTD2. 账户规则只在 Go 后端。 脚本调用实例对应版本的 CLI;不直接改用户表。

KTD3. 一次性登录凭据独立于长期 api_keys。 专用表与兑换 API;普通 Bearer、SSE ?key=、长期 Key 路径均拒绝。

KTD4. 受限会话为独立 scope。 默认 10 分钟;allowlist 仅 me / 设密 / logout。

KTD5. 团队安装默认 PostgreSQL;存储选择显式。 与恢复 KTD5、config.Tier=team 一致。

KTD6. 一次性 Key 默认 30 分钟(可配置建议范围 5–120 分钟);审计记实际 TTL。

KTD7. 激活/恢复设密成功后必须重新密码登录(销毁受限会话、清 cookie)。普通主动改密可保留「要求原密码」路径;激活路径不要求原密码。

KTD8. 普通账户恢复默认保留长期集成 Key;失陷显式撤销全部凭据。 两种情况均保留业务数据。

KTD9. 候选校验完成前不停旧服务;切换短窗;schema 迁移后能否自动回退旧程序另行判断,失败不自动用备份覆盖业务库。

KTD10. 双轨收敛到同一部署计划。 新旧 CLI 同后端;Releases install.sh 变为薄封装或文档降级为遗留,禁止第三套生命周期。

5. 职责划分与接口示例

部分 负责
svc.sh doctor、env prepare、获取制品、构建、实例配置、生命周期、调用账户 CLI
后端 CLI 创建账户、签发/撤销一次性 Key、核验目标库、OpenExisting、操作审计
后端认证 原子消费 Key、受限会话、设密事务、中间件限制
登录页 输入一次性 Key、设密、过期/重发提示;遵循 DESIGN.md
发布制品 版本、平台、摘要、组件版本、能力声明

拟新增 CLI(当前脚本尚不支持;兼容 --from 保留):

./svc.sh doctor --mode binary --tier team
./svc.sh install prod --mode binary --version <固定版本>
./svc.sh install prod --mode source --repo <仓库> --ref <固定提交>
./svc.sh prod deploy --mode binary --version <固定版本>
./svc.sh prod user create --owner alice --role user
./svc.sh prod user issue-login-key --owner alice --purpose recover
./svc.sh prod user list
./svc.sh prod user revoke-login-key --id <凭据编号>

Linux 服务账户与应用账户分开管理。

6. 规格合同(实施前必须写进 U1/U4,否则返工)

  1. 独立凭据类型 + POST body 兑换 API。
  2. 会话 scope / 中间件 allowlist;覆盖 must_change 普通首登。
  3. 设密接口分型:受限会话不校验原密码;普通改密继续要求原密码;同事务完成写 hash / 清标志 / 作废 Key / 吊销会话。
  4. 密码未设置状态:password_hash 可空或 sentinel;VerifyLogin 拒绝未设密;创建 = 用户行 + 激活 Key 同事务。
  5. CLI OpenExisting:目录/DB 不存在则失败;运维模式可禁止自动 migrate / 要求 schema 兼容。
  6. release@<ver> 必须解析到该版本目录;缺摘要硬失败。
  7. 部署:获取/构建/校验不停旧服务;组合切换;迁移后回退独立判断。
  8. install 与 --from 同一计划;双轨收敛(KTD10)。
  9. 首次管理员仅新实例;事务防并发。
  10. 凭据交付:交互 stdout 一次 / 非交互 chmod 600 文件;日志与 evidence 只记凭据 ID;随机密码路径首期可并存但默认无密码 + Key。
  11. 无 flock 时拒绝冲突生命周期与账户操作(收紧现状「直通」)。

详细设计(正文在 Dev 仓,随本任务分支提交):

  • U1:docs/svc-deploy/u1-instance-account-binding.md
  • U4:docs/svc-deploy/u4-one-time-login-key.md

7. 增量与完成门槛

增量 主要范围 完成条件
U1 实例—账户绑定补齐 账户 CLI 读实例 manifest;OpenExisting;锁缺失拒绝;install 骨架对接既有 identity 开户/签发命中同一 store;错误 data/DSN 拒绝;与 recovery U1 字段对齐
U2 二进制与源码来源 下载/离线导入、仓库物化、版本清单、候选先校验 无开发仓可部署;固定版本与摘要可核验;修复 release 钉扎
U3 环境检测与准备 系统适配器、依赖计划、专用工具链、监管配置 Ubuntu/Debian 首验;幂等;不接管共享服务;binary 不装 Go/Node
U4 一次性凭据与认证限制 Backend CLI/Store/Server/迁移 原子开户/兑换/设密;受限会话无法调业务 API;并发兑换单胜
U5 脚本与登录页接线 账户命令、首次管理员、凭据交付、Login/设密页 新建与恢复走通;刷新与异常可续;DESIGN.md
U6 组合与故障验收 Dev 组合、发布包、真机、数据保护 两种部署 × 存储档;故障注入;浏览器 + 真机;治理回归

近期优先 U1、U4(可并行兄弟分支、共用 R0)。跨仓顺序:Backend(U4)→ Frontend(U5)→ Dev gitlink + svc.sh(U1/U2/U3/U5);组合 make test 后宣称可合入。

必须覆盖的验收场景(摘要)

干净机器二进制安装;源码固定提交与子模块;两种部署互切后数据不变;构建/摘要/配置失败旧服务可用;PG 身份不符拒绝且不回落 SQLite;无密码开户且不覆盖既有;同 Key 并发兑换仅一次成功;受限会话拒业务/SSE/admin;消费后建会话失败与设密中途失败无半完成态;恢复前后业务与权限对账;SQLite 与真实 PG;治理回归;源码测试不代替浏览器与真机。

额外钉住:release@v 多版本不得装成更高版本;账户 CLI 不得回落默认 ./data。

8. 一次性 Key 流程

flowchart LR
  A["创建账户或签发恢复 Key"] --> B["输入一次性 Key"]
  B --> C["后端原子消费"]
  C --> D["仅允许设置密码的短期会话"]
  D --> E["设置并确认新密码"]
  E --> F["作废恢复凭据及相关旧会话"]
  F --> G["使用新密码正常登录"]

凭据规则:独立前缀;只存摘要;用途 activate|recover;状态未使用/已消费/已撤销/已过期;密码变更后旧恢复凭据不可再用。符合 OWASP Forgot Password 与 Session Management;保留现有 CSRF 校验。

9. 风险与未授权范围

  • 实施、故障注入、真机部署、浏览器验收:未授权 / NOT_RUN。
  • 本任务交付终点:正式提案 r1 + U1/U4 规格 + 任务卡与索引入口;推送/PR 须另获授权。
  • 与 recovery U1 重叠处只做增量,不重做已合入的 manifest 层。

10. 规划进展与下一步

  • 本次推进:源码复核;四项取舍定案;正式提案 r1;U1/U4 规格细化。
  • 首选下一任务(待授权):并行启动 U1 实施与 U4 实施(兄弟分支、共用 R0);U2/U3 规格可随后写作但不阻塞 U1/U4。
  • 前置:人工批准本提案 r1(至少需求表 + 方案设计 + U1/U4 实施计划阶段);实施前 make precheck 与 task-sync。