M1 身份与导航实施及验收
# M1 身份与导航实施及验收
当前状态:M1 已完成。2026-10-23 用户明确确认“M1 已经人工验收”,此前暂缓的浏览器门槛按本次整体人工验收确认结项。身份/会话/权限及双库自动化结果保留,人工部分的证据来源为用户确认;本次没有新增代理浏览器观测,也不推断所用浏览器、账号或证书细节。结构化记录为 docs/evidence/m1-manual-acceptance.json 与 m1-results.json。M2 也已获用户独立人工验收确认,见 实施记录。
# 已实现的闭环
fago/modules/fago-identity/internal/runtime:admin/platform 独立账号、会话、令牌 audience;256 bit 不透明令牌,主库只存摘要。access 默认 15 分钟;refresh Cookie 上限 7 天、会话绝对上限 30 天;业务 idle 由策略行控制,种子 30 分钟;必须改密会话绝对上限 30 分钟。- 刷新按账号 → 会话 → token 加锁;旧 refresh 再使用时,先提交撤销和审计,再返回 401002。合法刷新保留同会话旧 access,直至其自身到期。密码修改与本人撤销使用同一锁序,不能在并发刷新后留下有效的旧凭证。
- 连续 5 次口令失败锁定 15 分钟,锁定期间不递增计数。正确口令登录清零;未知账号、租户停用和过期对外使用统一凭证错误。Redis 限流在口令校验前执行,故障返回 503;限流拒绝不增加账号失败计数。测试使用独立随机 IP 及精确清理,覆盖账号第 21 次与 IP 第 101 次拒绝以及伪造转发头不能覆盖审计来源,双库并行不会共享测试 IP 额度。
- 初始化口令至少 14 字符、最多 72 字节;M1 原始基线按平台种子策略(最短 8 位、四类字符中三类)验证;当前 M2 已统一接入租户有效覆盖/继承策略,平台身份继续使用平台默认。成功改密更新密码版本、撤销本人全部会话、清 Cookie 并要求重新登录。策略管理页和口令有效期已在 M2 实施,见对应记录。
fago/apps/fago-server/internal/auth:固定 realm 路由、精确 Origin、X-App-Request、JSON 根对象/未知字段/尾部/大小校验。拒绝客户端租户头覆盖,不向任意 Origin 开放带凭证的 CORS。- 全项目错误使用
github.com/samber/oops v1.21.0;保留errors.Is/As、领域和堆栈。HTTP 从受控业务码表生成中文提示,不能输出内部错误链、Public 任意文本、属性或堆栈;不把密码、token、Cookie、DSN 或请求体放入 Oops 属性。 0001_base历史字节保持不变;0002_identity增加独立身份与权限目录,0003_mlps_identity增加账户锁定、活动时间及安全策略;0004_auth_audit_source追加受信 TCP 来源 IP,保留历史未知来源为空,不伪造回填。迁移逐版本检查 dirty、连续性和校验和。
新增项目配置 YAML、生产 JSON 内容加密、独立敏感数据脱敏模块及联调证据见 配置与数据安全。
# API 与前端
两个 API 前缀分别是 /api/admin/v1 与 /api/platform/v1:
| 入口 | 行为 |
|---|---|
POST /auth/login、/auth/refresh、/auth/logout | Cookie 专用入口、来源校验、刷新轮换与服务端撤销 |
GET /auth/me、/auth/codes、/auth/menus | 同一授权快照及 X-Authz-Version;必须改密会话拒绝 |
PUT /profile/password | 本人改密,不能指定其他用户或租户 |
GET /auth/sessions、DELETE /auth/sessions/{id} | 只查看/撤销本人同 realm 会话;他人目标一律 404001 |
租户 GET /system/menu-options、/system/permission-options | 按实际权限码读取发布目录,返回目录键与标签 |
平台 GET /permissions | 平台目录读取,不复用租户权限 |
HTTPS Origin 使用 __Secure-admin_rt、__Secure-platform_rt(HttpOnly、Secure、SameSite=Strict);HTTP Origin 使用 dev_admin_rt、dev_platform_rt 且不带 Secure。Path 分别为 /api/admin/v1/auth、/api/platform/v1/auth,无 Domain。development-http 在开发/测试仅 loopback;生产允许 HTTP 但启动 WARN。详见 登录与会话。
前端主要接入文件为 api/admin.ts、auth/{realm,session,coordination,legacy}.ts 与 router/{access,manifest}.ts。租户区域从 /auth/login 进入,平台区域从 /platform/auth/login 进入;各自有工作台、个人中心、改密与权限目录。租户用户/组织/角色编辑和只读审计查询已在 M2 接入;平台租户/套餐 CRUD 仍归 M3。
- access、权限码及动态路由只在内存;启动清理 localStorage/sessionStorage 中旧
core-access与 token 键。 - 登录和恢复先检查
mustChangePassword,受限页不请求 me/codes/menus。个人中心可发起普通本人改密,成功后同样撤销全部会话。 - 仅 401001 触发一次刷新和原请求重试。403、401002、刷新失败不循环;迟到的旧 access 401 优先重用已刷新的 access。
- 同页 single-flight,多页 Web Locks 串行 Cookie 登录/刷新/退出;BroadcastChannel 只广播 realm 内退出或身份变化,不广播 token。缺少 Web Locks 时禁用自动恢复/刷新,提示重新登录;不使用基于短延迟 ping 的不可靠互斥。
- 授权版本包含 realm、租户和用户 ID 及各级版本,避免同租户不同用户的初始版本碰撞。me/codes/menus 版本不一致最多重取一次;持续不一致不安装半套权限。普通请求发现版本变化时清空旧动态路由并重载。退出、身份切换及晚到的异步响应以本地 revision/generation 隔离。
- 页面异步操作也校验 realm 与身份版本:旧会话撤销、旧改密页返回登录和旧会话列表响应,均不能清除或覆盖在等待期间建立的新身份。
- 本地 manifest、路径与静态保留路由共同约束动态菜单;权限按钮使用服务端相同 permission code。退出失败仍清本地身份,并明确提示服务端撤销未确认。
# 验证证据
下表保留 M1 阶段的已归档基线,计数对应当时范围;当前 schema v9 与扩展后的合同/测试结果见 M2 实施记录。原人工待办现由 2026-10-23 用户整体确认补齐;既有自动化结果与人工确认分别注明来源。
| 检查 | 本轮结果与覆盖 |
|---|---|
bash scripts/test-backend.sh | 14 模块 workspace race 测试及 vet 通过;含 Oops 错误链、公开提示脱敏和 panic 脱敏 |
bash scripts/test-independent.sh | 14 模块 GOWORK=off 独立构建与测试通过,显式依赖/DAG/internal 检查通过 |
bash scripts/integration.sh | 专用 MySQL/PostgreSQL 测试库通过,含身份、锁定、idle、必须改密、跨 realm、Cookie、限流、会话归属及原有 M0 隔离/恢复 |
TestIntegrationIdentityAuthorization | 两库真实 HTTP 验证普通用户权限不足、跨 realm、租户头覆盖、他人会话保护、角色/版本变更、受限改密与 Cookie 清理 |
TestIntegrationIdentityLifecycle | 两库、两套 realm 的真实 HTTP 验证:登出后的 access/refresh 拒绝;账号禁用立即拒绝新登录、存活 access 与两条 refresh,并提交全部会话撤销;验证登出审计 |
TestIntegrationIdentityConcurrency | 合法轮换保留旧 access、重放撤销提交、同 refresh 单赢家、改密/撤销与刷新竞争通过 |
TestIntegrationMigrationUpgrade | 两库均验证随机空库初始化、重复迁移、带数据 v1 升级、历史 checksum 保留、旧版本 dirty/漂移拒绝;结束删除自己创建的随机测试库 |
bash scripts/web.sh contract | OpenAPI 72 个操作、585 个样例通过;类型重新生成,Cookie/来源头与实际 API 对齐 |
scripts/smoke-m1-contract.mjs | 普通 JSON 与 JWE 均通过;两库加密模式各租户 15 项、平台 14 项,共 58 项;受限登录、刷新、改密撤销、目录、会话和重放均校验 |
admin.test.ts、security-transport.test.ts、identity-races.test.ts | 36 项通过,包含 7 项基础 JWE、10 项双 realm 加密刷新组合、7 项真实 Vue 页面身份竞争,以及并发/迟到 401、403、失效刷新、身份切换、无 Web Locks、版本不一致、非法菜单与旧存储清理 |
bash scripts/web.sh typecheck、build | 类型检查与生产构建通过;生产包未含 mock 后端/适配器/上游统计脚本 |
| HTTP 浏览器 | 已验证受限登录及重载恢复、改密 API 撤销后回登录、重新登录、个人中心、租户/平台真实目录读取、平台跨标签恢复/退出及租户会话独立恢复 |
| HTTPS 浏览器 | 用户确认人工验收通过(2026-10-23)。此前 2026-10-22 的证书阻塞记录保留为历史;本次未新增代理观测。两套 Cookie 服务端回归仍独立保留 |
本轮逐项核对 M1 退出要求;测试名称均可在源文件找到,测试结果对应专用数据库与实际客户端,不以计划状态替代:
| M1 要求 | 证据与判定 |
|---|---|
| 初始账号登录、受限刷新、固定改密、撤销后重新登录 | 两库 JWE HTTP 合同各 15/14 项通过;HTTP 浏览器受限页重载通过。原浏览器改密门槛按用户 2026-10-23 的 M1 整体人工验收确认结项 |
| 正常页面重载恢复;退出后不能继续访问 | HTTP 浏览器和双库 Cookie 回归通过;原可信 HTTPS 浏览器门槛按用户 2026-10-23 的 M1 整体人工验收确认结项 |
| 过期 access 仅刷新一次;403/401002/刷新失败不循环 | 原有客户端回归 + 两 realm 的 10 项真实 JOSE 组合测试通过;并发及迟到 401 的每次重试均重新生成请求号/响应密钥 |
| refresh 重放、同 refresh 并发、改密/撤销竞争 | TestIntegrationIdentityConcurrency 双库 race 通过;重放副作用提交而非回滚 |
| 用户禁用、登出后存活 access 与 refresh 均拒绝 | TestIntegrationIdentityLifecycle 两库、两 realm 的实际 HTTP + 服务验证通过,查询确认没有未撤销会话 |
| 账户锁定、idle、受限绝对期限与改密口令策略 | TestIntegrationIdentityBaseline 对应子例双库通过,校验审计和持久化状态 |
| 独立平台/租户身份及禁止租户头覆盖 | realms 与 TestIntegrationIdentityAuthorization 双库通过;独立目录与 HTTP 浏览器验证通过 |
| 无权限直输 URL/直接调用 API 都拒绝 | 本地 manifest/保留路径客户端测试、HTTP 普通账号 403 及他人会话 404 双库通过 |
| me/codes/menus 同版、变更生效、迟到响应不能污染身份 | 授权快照/版本测试、客户端 generation/revision 与 7 项 Vue 页面竞争测试通过 |
| 登录、失败、撤销审计及敏感信息保护 | 双库持久化断言、来源 IP/伪造头测试、Oops 与脱敏模块边界通过 |
| 配置文件、生产加密与开发明文、独立脱敏模块 | 见 配置与数据安全,配置/密码学/实际 HTTP/客户端与模块检查均通过 |
原暂缓阶段已结项,依据是用户完成验收后的直接确认。此前本地夹具状态、证书拦截记录及 .cache/m1-https-handoff.* 仅作为历史上下文保留,不用来反推用户使用了哪个账号或证书,也不继续要求回复浏览器名称或发送凭证。
个人中心与平台目录截图均为本机专用测试账号;其中没有生产身份或凭证:


# 本地运行与验收结项
在外层仓库根目录使用现有脚本。设置数据库与 Redis 后,先执行独立迁移;租户初始化使用默认 BOOTSTRAP_REALM=admin,平台初始化必须显式 BOOTSTRAP_REALM=platform。两者都要求操作者提供自己的初始化口令,重复初始化不重置凭证。
API 可通过环境 YAML 与 APP_CONFIG_FILE 配置,环境变量优先;生产须提供外部内容加密私钥及 key_id。Cookie 与 Origin 可由 APP_AUTH_COOKIE_PROFILE 与 APP_AUTH_ORIGINS 覆盖。例如仅限本机的 HTTP 开发可使用 development-http 与 http://127.0.0.1:5174,前端可通过 FAGO_API_PROXY_TARGET 指向自己启动的 API,避免替换其他开发进程。生产推荐配置浏览器看到的精确 Origin 与可信 HTTPS;HTTP 部署时 API 启动 WARN。本轮没有向操作系统添加信任根。
2026-10-23 结项:用户确认 M1 已完成整体人工验收,结合上述逐项自动化证据,M1 退出条件已满足。未取得新的代理截图或浏览器细节,因此人工结论明确标为用户确认;本次仅更新文档与验收状态。M1 完成不等同于 R1 或二级等保整体验收,也不扩展 Oracle、SQL Server、DM、完整 SSO 或生产工作流的认证范围。
历史顺序:2026-10-22 用户曾暂缓 M1 人工验收并要求独立推进 M2;2026-10-23 用户明确确认 M1 已人工验收,原暂缓与受阻状态已解除。M2 独立人工项仍按其验收记录处理。