文件
hyb-oa/.trellis/tasks/08-08-production-authenticated-readiness/design.md
T
wangsli 4f3f761d0a
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s
规划(08-08-production-authenticated-readiness): 锁定生产登录态只读验收门禁
2026-08-08 22:57:52 +08:00

6.8 KiB
原始文件 Blame 文件历史

生产登录态只读验收:设计说明

1. 设计边界

本任务是生产账号诊断与登录态只读验收,不是账号修复或产品开发。前一部署任务已经证明产品候选、migration、匿名鉴权和公网基础 readiness;本任务只补齐因仓库外凭据 401 而缺失的登录态证据。

核心原则是“先读取状态,再决定是否允许一次登录”。账号失败计数和锁定属于生产安全状态,不能拿登录端点当探针。合同终止是不可逆写入,浏览器验收必须在输入和网络两层同时保证不会提交。

2. 状态序列

生产身份 / 已部署 SHA / 65 migration(只读)
  -> rollback window PRE(只读)
  -> admin/employee identifier 登录语义 + 账号状态(BEGIN READ ONLY)
  -> 分流:identifier / locked / inactive-role / password credential
  -> 仅当合法新鲜凭据 + 全部门禁 PASS:每角色最多一次登录
  -> admin 合同详情只读 + terminate POST=0
  -> employee 权限负向
  -> rollback window POST(只读)
  -> 只读 reviewer / 结论

任何箭头失败都停止。PRE 与 POST 快照即使中间步骤 PAUSED 也都要执行;这样能区分本任务未写入与同期真实用户关闭窗口。

3. 账号只读诊断

3.1 查询合同

生产查询使用 BEGIN READ ONLY,只处理 admin/employee 两个 role key。identifier 从受控进程变量读取,在数据库内与 email、phone 做精确比较;不能因为现有 dry-run helper 支持 employee_no 就把员工编号视为可登录 identifier。

稳定输出模型:

roleKey=admin|employee
matchedBy=email|phone|none
active=true|false
archived=true|false
locked=true|false
failureCount=<非负整数>
expectedRoleReady=true|false

不输出 identifier、员工编号、邮箱、手机号、锁定时间、密码 hash、角色明细或原始行。查询目标多于一条、事务不是 read-only、输出字段异常都 fail-closed。

3.2 分流矩阵

只读结果 结论 动作
matchedBy=none secret 中 identifier 过期或不符合 email/phone 登录合同 PAUSED;账号持有人从合法来源恢复仓库外凭据
active/role 不满足 账号或授权事实已变化 PAUSED;另设账号/权限 task
locked=true 账号当前锁定 PAUSED;不试登录、不解锁
匹配、active、role 正确、未锁定,既有结果为 401 按当前 auth 分支可判定仓库外密码不匹配 PAUSED;密码变更另行批准
合法新鲜凭据已恢复且全部健康 允许有限登录验证 每角色最多一次,单 worker、零 retry

账号不存在与密码错误在 HTTP 上同为 401;只有数据库只读诊断能安全拆分。若一次获准登录仍失败,立即重查 failure count/locked,记录差值并停止。

4. 回滚窗口双快照

termination migration 已 applied,因此必须真实查询:

SELECT count(*) FROM contract_registry WHERE status = 'terminated';

查询异常不可 catch 后默认 OPEN。两次快照使用同一目标、同一查询合同和同一输出格式:

  • count = 0:rollbackWindow=OPEN
  • count > 0:rollbackWindow=CLOSED
  • PRE OPEN / POST CLOSED 且 terminate request count = 0:并发真实用户已产生首条终止记录;记录窗口永久关闭,不归因于本任务
  • PRE CLOSED:全部验收仍只读,旧应用回退从一开始就不可用

5. 登录预算与浏览器控制

5.1 登录预算

  • 执行前确认仓库外凭据是新鲜、合法来源,不靠修改生产账号获得。
  • 管理员、员工各最多一次;Playwright 固定 --workers=1 --retries=0 --reporter=list。
  • 禁止复用默认 CI retry;一次失败即结束该角色路径。
  • 失败后重新运行账号只读查询,证明是否增加失败计数或触发锁定。

5.2 合同详情安全断言

draft/archived 不显示终止面板,无法承担“误点后服务端 409”的兜底。对已有 active/expired 合同采用以下边界:

  1. 打开合同详情并验证自然中文状态和只读摘要;证据不采集正文或敏感字段。
  2. 注册请求监听,统计匹配终止端点的 POST;初始为 0。
  3. 验证“终止合同”面板、至少 10 字提示和 destructive 按钮存在。
  4. 终止原因保持空值或不足 10 字;断言按钮 disabled。
  5. 不点击按钮,不打开确认层,不调用 API;结束时终止 POST 仍为 0。

优先使用 Playwright CLI 的受控会话;若 CLI 命令不能可靠表达请求监听和 disabled 断言,则由执行者本人做更窄人工检查,只验证入口与按钮状态,不打开确认层。不得为本任务新增会提交数据的 spec。

5.3 权限与数据分支

  • 管理员正向:能进入合同台账/详情。
  • 员工负向:合同管理入口不可达或服务端返回既定无权结果;不得扩大权限。
  • archived 样本存在:只读验证字段锁定;不存在则 PAUSED。
  • terminated 样本存在:只读验证中文标签与终止事实;不存在则 PAUSED,绝不制造样本。

6. 失败与权限边界

阶段 失败 处理
身份/SHA/migration 目标或版本不符 停止,不登录
rollback PRE/POST 查询失败或不可解析 fail-closed,不推断 OPEN
identifier 不匹配 email/phone 或不唯一 PAUSED,恢复仓库外 secret
状态/角色/锁定 任一不健康 PAUSED,另行批准账号治理
登录 首次失败 停止,重查失败计数/锁定,不重试
管理员 UI 数据缺失或只读断言失败 PAUSED/FAIL,不造数据、不改产品
员工负向 权限扩大或结果不符 FAIL,不改权限推进
terminate 请求 计数不为 0 紧急停止并复核 POST 确切结果与窗口;不得再次操作

7. 证据与隐私

原始查询和浏览器会话只在受控现场存在。提交材料保存稳定枚举、布尔、计数、SHA、HTTP status 和相对 evidence 引用;不保存生产 identity 明文、账号、凭据、cookie、合同正文、相对方、金额、终止原因或 payload。

截图不是必需证据;若必须截图,应使用无业务正文的局部裁切或脱敏摘要。任一敏感扫描命中都先处理证据,不降低 scanner。

8. 只读 review 与 readiness 结论

本任务涉及生产认证、权限和不可逆状态机边界,执行后必须启动只读 reviewer。reviewer 不修改代码、账号、权限、数据库或证据,只核对:

  • 登录前诊断确实先于登录;
  • 每角色尝试次数与失败后复查;
  • 终止原因/确认层/POST 均未越界;
  • rollback window 前后快照及变化解释;
  • 证据脱敏与最终 readiness 用语。

只要必需登录态 AC 仍 PAUSED,最终结论只能是“已部署但登录态验收未完成”,不能告知用户可以测试。