docs: add HWLAB users nav ACL spec (#956)

Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
Lyon
2026-06-26 11:50:23 +08:00
committed by GitHub
parent c35ebd079a
commit c417c988b1
2 changed files with 373 additions and 2 deletions
@@ -81,7 +81,7 @@ D601 v0.3 当前已具备 app-local 注册、登录、登出、会话检查、
| PJ2026-01050102 | 会话状态 | 本规格 6.2 | session 检查、当前用户和禁用状态生效 | 注册登录、平台 Secret | API key、Agent编排、客户端 | | PJ2026-01050102 | 会话状态 | 本规格 6.2 | session 检查、当前用户和禁用状态生效 | 注册登录、平台 Secret | API key、Agent编排、客户端 |
| PJ2026-01050103 | Profile安全 | 本规格 6.3 | profile、密码修改和安全设置 | 用户身份、客户端账户入口 | 用户自服务、admin 用户管理 | | PJ2026-01050103 | Profile安全 | 本规格 6.3 | profile、密码修改和安全设置 | 用户身份、客户端账户入口 | 用户自服务、admin 用户管理 |
| PJ2026-01050104 | 身份恢复 | 本规格 6.4 | 邮箱验证、找回密码和多因素认证边界 | 邮件/通知能力、平台配置 | 用户恢复、运营支持 | | PJ2026-01050104 | 身份恢复 | 本规格 6.4 | 邮箱验证、找回密码和多因素认证边界 | 邮件/通知能力、平台配置 | 用户恢复、运营支持 |
| PJ2026-01050105 | Web鉴权 | 本规格 6.5 | 浏览器 session transport、canonical principal 和 recovery 身份边界 | 注册登录、会话状态、权限配额 | API契约、Web工作台、业务 API | | PJ2026-01050105 | 用户导航ACL | [PJ2026-01050105 用户导航ACL](PJ2026-01050105-yaml-first-users-nav-access.md) | 浏览器 session transport、canonical principal、YAML 预置用户和根导航 ACL 边界 | 注册登录、会话状态、权限配额、YAML运维 | API契约、Web工作台、业务 API |
## 6. 原子需求 ## 6. 原子需求
@@ -129,10 +129,12 @@ profile 安全设置只拥有账号资料和登录安全事实。余额通知、
| 编号 | 短名 | 主责模块 | 关联模块 | | 编号 | 短名 | 主责模块 | 关联模块 |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| USER-ACCT-REQ-005 | Web鉴权 | PJ2026-01050105 Web鉴权 | [API契约](PJ2026-010403-api-contract.md)、[客户端](PJ2026-0104-client.md)、[权限配额](PJ2026-010503-access-quota.md) | | USER-ACCT-REQ-005 | 用户导航ACL | [PJ2026-01050105 用户导航ACL](PJ2026-01050105-yaml-first-users-nav-access.md) | [API契约](PJ2026-010403-api-contract.md)、[客户端](PJ2026-0104-client.md)、[权限配额](PJ2026-010503-access-quota.md)、[YAML运维](PJ2026-010603-yaml-first-ops.md) |
账号会话应把浏览器同源 `hwlab_session` 视为 Web session transport,由后端唯一认证入口解释为 canonical principal。Cloud Web、Workbench、Usage、Billing、Admin 和 Code Agent 等业务面只能消费这个 principal 与后端 capability 摘要,不得在页面、route 或业务 handler 中重新解析 cookie prefix、Bearer、`hws_`、API key secret、user-billing token 或 localStorage authority 来定义用户身份。 账号会话应把浏览器同源 `hwlab_session` 视为 Web session transport,由后端唯一认证入口解释为 canonical principal。Cloud Web、Workbench、Usage、Billing、Admin 和 Code Agent 等业务面只能消费这个 principal 与后端 capability 摘要,不得在页面、route 或业务 handler 中重新解析 cookie prefix、Bearer、`hws_`、API key secret、user-billing token 或 localStorage authority 来定义用户身份。
canonical principal 至少应表达 `authenticated``authMethod``identityAuthority``sessionKind`、actor 摘要和脱敏 capability 摘要。`authMethod` 用于说明 transport 来源,例如 Web session、user-billing session、API key 或 local-bootstrap`identityAuthority` 用于说明身份事实归属,例如 `hwlab-local``user-billing``bootstrap-recovery``sessionKind` 用于区分浏览器、API key 和 recovery 身份。local/bootstrap 或 recovery 身份不能静默伪装成完整业务用户,必须在 canonical principal 中显式标记其能力边界和 blocker。 canonical principal 至少应表达 `authenticated``authMethod``identityAuthority``sessionKind`、actor 摘要和脱敏 capability 摘要。`authMethod` 用于说明 transport 来源,例如 Web session、user-billing session、API key 或 local-bootstrap`identityAuthority` 用于说明身份事实归属,例如 `hwlab-local``user-billing``bootstrap-recovery``sessionKind` 用于区分浏览器、API key 和 recovery 身份。local/bootstrap 或 recovery 身份不能静默伪装成完整业务用户,必须在 canonical principal 中显式标记其能力边界和 blocker。
身份验证和业务授权必须分层:账号会话先证明“当前调用主体是谁”;权限配额、账单后台、Agent编排、Workbench 和 Admin 再判断“该主体能做什么”。billing、usage、API key、Workbench 或 Code Agent 的业务 capability 不得反过来决定 Web 是否已登录。未登录、禁用、撤销或能力不可用必须返回结构化错误或 blocker,不能让前端通过二次登录、API key 输入、cookie prefix 判断或 fallback endpoint 补救身份。 身份验证和业务授权必须分层:账号会话先证明“当前调用主体是谁”;权限配额、账单后台、Agent编排、Workbench 和 Admin 再判断“该主体能做什么”。billing、usage、API key、Workbench 或 Code Agent 的业务 capability 不得反过来决定 Web 是否已登录。未登录、禁用、撤销或能力不可用必须返回结构化错误或 blocker,不能让前端通过二次登录、API key 输入、cookie prefix 判断或 fallback endpoint 补救身份。
D601 v0.3 预置用户、根导航 `navId`、nav profile、Secret sourceRef、session access claim、router guard 和后端 API capability enforcement 的专项边界见 [PJ2026-01050105 用户导航ACL](PJ2026-01050105-yaml-first-users-nav-access.md)。该专项规格是本需求在 YAML-first 预置用户与根导航访问控制方向的 P0 SPEC-first source of truth。
@@ -0,0 +1,369 @@
# SPEC: PJ2026-01050105 YAML-first users/nav access
## 修改历史
| 版本 | 对应 commit id | 更新日期 | 变更说明 |
| --- | --- | --- | --- |
当前正文仍在规格治理草稿中;未定稿前不新增版本号,不为单次编辑追加 `待提交` 版本。
## 正文
## PJ2026-01050105 用户导航ACL需求规格
## 1. 文档控制
| 字段 | 内容 |
| --- | --- |
| 编号 | PJ2026-01050105 |
| 短名 | 用户导航ACL |
| 层级 | L3 子课题 |
| 状态 | 已生效 |
| 实现引用版本 | draft-2026-06-26-users-nav-acl |
| 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) |
| 上级规格 | [PJ2026-010501 账号会话](PJ2026-010501-account-session.md) |
| 关联规格 | [PJ2026-010503 权限配额](PJ2026-010503-access-quota.md)、[PJ2026-010401 Web工作台](PJ2026-010401-web-workbench.md)、[PJ2026-010403 API契约](PJ2026-010403-api-contract.md)、[PJ2026-010603 YAML运维](PJ2026-010603-yaml-first-ops.md)、[PJ2026-010601 发布流水](PJ2026-010601-controlled-release.md)、[PJ2026-010404 项目管理](PJ2026-010404-project-management.md) |
| 规格治理索引 | [规格治理](spec-governance.md) |
本文采用 ISO/IEC/IEEE 29148 需求规格模板的项目裁剪版:正文只保留 D601 v0.3 YAML-first 预置用户、根导航访问控制、前后端 enforcement 和发布验收的稳定边界。
本规格范围内新增或修改的源码文件必须在文件头部标注 `SPEC: PJ2026-01050105 用户导航ACL draft-2026-06-26-users-nav-acl`,并用一句话说明文件职责。纯 YAML/config、锁文件、生成产物和无法承载注释头的二进制产物不要求加头部,但对应解析器、渲染器或 CLI 入口必须能追溯到本规格。
## 2. 目的和范围
### 2.1 目的
用户导航ACL负责把 D601 HWLAB v0.3 的预置用户、密码来源、角色、状态、根导航可见性和后端访问兜底拒绝收敛到 YAML-first source of truth,使 `admin` 与运营预置普通用户可以通过同一 bootstrap/sync 流程进入本地用户表、OpenFGA 或应用 ACL,并让 Cloud Web 根导航、router guard 和后端 API guard 使用同一份访问摘要。
本规格的目标状态是:`admin``huiggao@163.com` 都由 UniDesk/HWLAB owning YAML 声明;密码明文只存在于 gitignored owner-only `.env/...` sourceRef 和运行面 SecretCLI plan/status 只输出 sourceRef、key、presence、fingerprint 和 mutation 摘要;Cloud API 在 `/v1/auth/session``/v1/users/me` 返回非敏感访问摘要;Cloud Web 只显示当前用户被授权的根导航;未授权用户直接访问前端路由或后端 API 时被稳定拒绝。
### 2.2 范围内
- D601 v0.3 预置用户 YAML、nav profile YAML 和 node/lane `accessControl` configRef。
- `admin` 全量导航访问与 `huiggao@163.com``Code``MDTODO` 根导航访问。
- 密码强密码生成、gitignored plaintext sourceRef、password hash/bootstrap Secret 和 redacted plan/status。
- 多用户 bootstrap/sync 幂等落库,包括 `id``username/email``displayName``role``status`、password hash 和 nav profile binding。
- OpenFGA system/admin/tool 关系与应用层 nav claim 的映射边界。
- `/v1/auth/session``/v1/users/me` 的非敏感 `access.nav.allowedIds` 摘要。
- Cloud Web 根导航 `navId` 模型、`AppShell` 过滤、router meta 校验和 403/redirect 用户体验。
- Code/workbench、MDTODO/project-management、admin 等后端 API capability guard。
- D601 v0.3 env-reuse、git-mirror、GitOps、Tekton、Argo 和 web-probe 登录导航验收。
### 2.3 范围外
- 不引入 Keycloak、外部 IAM 或第三方身份源。
- 不把 Sub2API 的 DB settings/custom menu 机制复制为 HWLAB source of truth。
- 不只做前端隐藏;router 和后端 API 必须兜底拒绝。
- 不把明文密码、password hash、session token、API key、DB DSN 或 Secret value 输出到 issue、日志、Git 提交、PR 描述、CI 日志或普通 CLI 输出。
- 不在运行面 Secret、pod env、日志或数据库中反推、解码或回填本地 owner-only sourceRef。
- 不把 D601 legacy、G14 v0.2、旧 direct port、旧 `dev/prod` 或手工 SQL/`kubectl patch` 作为完成态路径。
## 3. 术语表
| 术语 | 定义 |
| --- | --- |
| 预置用户 | 由 YAML 声明并通过受控 bootstrap/sync 幂等进入 HWLAB 本地用户表的账号。 |
| nav profile | YAML 中声明的根导航访问集合,包含稳定 profile id 与 `allowedNavIds`。 |
| navId | Cloud Web 每个根导航入口和对应 router/API capability 的稳定标识,例如 `workbench.code`。 |
| 根导航ACL | 用户对登录后左侧根导航项的可见性和可访问性约束。 |
| access claim | 后端根据用户、角色、状态和 nav profile 生成的非敏感访问摘要。 |
| app-local ACL | Cloud API 应用层对 navId/capability 的访问判断;它可以消费 OpenFGA 结果,但不把前端导航当作唯一防线。 |
| sourceRef | YAML 中指向 owner-only 明文密码来源的声明,输出时只能显示 path/key/presence/fingerprint,不显示值。 |
| password hash | Cloud API 用户表或 bootstrap Secret 中保存的密码摘要;不能输出到普通 CLI、issue 或日志。 |
| `nav_access_denied` | 用户已认证但缺少目标 nav/capability 时返回的稳定错误码。 |
## 4. 系统边界和接口
本规格把用户导航ACL作为账号会话下的登录后访问切片看待;本章只描述输入、输出和责任边界。
| 边界项 | 内容 |
| --- | --- |
| 外部使用者 | 普通用户、平台管理员、Cloud Web、Cloud API、HWLAB CLI、D601 发布操作员和 web-probe。 |
| 外部输入 | D601/v03 node/lane 选择、users/navProfiles YAML、password sourceRef、登录凭据、Web session cookie、直接访问的前端路由和后端 API path。 |
| 受控资源 | 本地用户表、password hash、user/nav profile binding、OpenFGA tuple、应用层 capability map、Cloud Web 根导航和 route meta。 |
| 外部输出 | 登录/session 结果、当前用户摘要、`access.nav.allowedIds`、导航可见性、403/redirect、redacted plan/status、发布与验收摘要。 |
| 用户接口 | Cloud Web 登录后页面、`/v1/auth/session``/v1/users/me`、受保护业务 API、UniDesk/HWLAB 受控 CLI、D601 v0.3 web-probe。 |
| 系统边界 | 用户导航ACL负责预置身份、导航 capability 和兜底授权;不拥有 Workbench、Project Management、Admin、billing 或发布流水的业务事实,只消费它们的 API 和发布入口。 |
### 4.1 目标架构图
```mermaid
flowchart LR
subgraph YAML[UniDesk/HWLAB YAML source of truth]
Users[users.d601-v03.yaml]
Profiles[nav-profiles.yaml]
Lane[hwlab-node-lanes accessControl refs]
end
subgraph CLI[受控 CLI]
Plan[plan/status]
Generate[generate-password]
Sync[bootstrap/sync]
end
subgraph Runtime[HWLAB v0.3 runtime]
Secret[Kubernetes Secret password hashes]
DB[(local users DB)]
FGA[OpenFGA tuples]
Claims[AccessClaims service]
end
subgraph Client[Cloud Web]
Session[/v1/auth/session]
Shell[AppShell nav filter]
Router[router nav guard]
API[protected API guard]
end
Lane --> Users
Lane --> Profiles
Users --> Plan
Profiles --> Plan
Plan --> Generate
Plan --> Sync
Generate --> Users
Sync --> Secret
Sync --> DB
Sync --> FGA
DB --> Claims
FGA --> Claims
Claims --> Session
Session --> Shell
Session --> Router
Router --> API
```
### 4.2 数据流图
```mermaid
flowchart TD
Source[gitignored plaintext env sourceRef] --> Hash[CLI/local transform to password hash]
Hash --> Secret[hwlab-v03 bootstrap/user Secret]
UsersYaml[users.d601-v03.yaml] --> Sync[bootstrap user sync]
ProfilesYaml[nav-profiles.yaml] --> Sync
Secret --> Sync
Sync --> UserTable[local user table]
Sync --> Binding[user_nav_profile binding]
Sync --> OpenFGA[OpenFGA admin/tool tuples]
Login[POST /v1/auth/login] --> UserTable
UserTable --> Session[session principal]
Binding --> Claims[access.nav.allowedIds]
OpenFGA --> Claims
Claims --> AuthSession[/v1/auth/session or /v1/users/me]
AuthSession --> WebNav[Cloud Web root nav]
AuthSession --> RouteGuard[router guard]
RouteGuard --> BackendGuard[API capability guard]
```
数据流要求:明文密码只从 owner-only sourceRef 进入本地 transform;运行面验收只看 password hash/Secret presence/fingerprint。`access.nav.allowedIds` 是给前端的非敏感摘要,不包含 password、hash、Secret、OpenFGA 内部 tuple dump 或用户不可见能力细节。
### 4.3 Bootstrap/sync 时序图
```mermaid
sequenceDiagram
participant Op as Operator
participant CLI as UniDesk/HWLAB controlled CLI
participant FS as owner-only .env sourceRef
participant K8S as hwlab-v03 Secret
participant API as Cloud API bootstrap/sync
participant DB as Local users DB
participant FGA as OpenFGA
participant Web as Cloud Web
Op->>CLI: generate-password --user huiggao@163.com
CLI->>FS: write plaintext to gitignored sourceRef
CLI-->>Op: sourceRef/key/presence/fingerprint only
Op->>CLI: plan/status or sync --node D601 --lane v03
CLI->>FS: read plaintext sourceRef
CLI->>K8S: apply password hash Secret and config refs
CLI->>API: trigger bootstrap/sync through rollout or startup
API->>DB: upsert user and nav profile binding
API->>FGA: upsert system/admin/tool relations as needed
Web->>API: /v1/auth/session
API-->>Web: actor + access.nav.allowedIds + valuesRedacted=true
```
同步必须幂等。重复执行不得生成新用户 id、重复 OpenFGA tuple 或泄漏旧密码;当 sourceRef 缺失、key 缺失、profile 不存在、navId 不存在或 role/profile 冲突时,CLI/status 应返回 YAML path 与 redacted blocker。
## 5. 内部分工与规格索引
| 编号 | 内部模块 | 规格文档 | 主责边界 | 上游依赖 | 下游支撑 |
| --- | --- | --- | --- | --- | --- |
| PJ2026-0105010501 | YAML配置 | 本规格 6.1 | users/navProfiles/accessControl configRef schema 与 redacted plan/status | YAML运维、D601 lane 配置 | bootstrap/sync、发布流水 |
| PJ2026-0105010502 | 密码来源 | 本规格 6.2 | 强密码生成、owner-only sourceRef、hash transform 和 Secret 输出边界 | YAML配置、Secret source | 用户同步、运行面启动 |
| PJ2026-0105010503 | 用户同步 | 本规格 6.3 | 多用户幂等 upsert、role/status/nav profile binding | 账号会话、平台数据库 | 登录、session、用户管理 |
| PJ2026-0105010504 | ACL映射 | 本规格 6.4 | OpenFGA 与应用层 nav claim 的组合、capability 矩阵 | 权限配额、API契约 | 后端 API guard、session access claims |
| PJ2026-0105010505 | Web导航 | 本规格 6.5 | 根导航 navId、AppShell 过滤、router guard 和直接访问拒绝 | Web工作台、项目管理、API契约 | 用户入口、web-probe |
| PJ2026-0105010506 | 发布验收 | 本规格 6.6 | D601 v0.3 env-reuse/git-mirror/GitOps/Tekton/Argo 与登录导航验收 | 发布流水、源码同步、公开入口 | 验收收口、runtime evidence |
| PJ2026-0105010507 | 代码引用 | 本规格 6.7 | SPEC-first 文件头、实现引用版本和阶段边界 | 规格治理 | 实现审计 |
### 5.1 YAML schema 草案
```yaml
# config/hwlab-access-control/users.d601-v03.yaml
version: 1
kind: HwlabAccessControlUsers
metadata:
name: d601-v03-users
target:
repo: pikasTech/HWLAB
node: D601
lane: v03
users:
- id: usr_v03_admin
username: admin
displayName: HWLAB v0.3 Admin
role: admin
status: active
passwordSourceRef:
kind: envFile
path: .env/hwlab/d601-v03-admin.env
key: HWLAB_BOOTSTRAP_ADMIN_PASSWORD
passwordHashTransform: hwlab-sha256
navProfile: admin-full
- id: usr_huiggao_163
username: huiggao@163.com
email: huiggao@163.com
displayName: huiggao
role: user
status: active
passwordSourceRef:
kind: envFile
path: .env/hwlab/d601-v03-users.env
key: HWLAB_USER_HUIGGAO_PASSWORD
passwordHashTransform: hwlab-sha256
navProfile: code-mdtodo-only
```
```yaml
# config/hwlab-access-control/nav-profiles.yaml
version: 1
kind: HwlabAccessControlNavProfiles
metadata:
name: hwlab-nav-profiles
navProfiles:
- id: admin-full
allowedNavIds: ["*"]
- id: code-mdtodo-only
allowedNavIds:
- workbench.code
- project.mdtodo
```
```yaml
# config/hwlab-node-lanes.yaml excerpt
lanes:
v03:
targets:
D601:
accessControl:
usersRef: config/hwlab-access-control/users.d601-v03.yaml#users
navProfilesRef: config/hwlab-access-control/nav-profiles.yaml#navProfiles
rollout:
namespace: hwlab-v03
deployment: hwlab-cloud-api
sessionClaims:
exposeNavAllowedIds: true
```
Schema 校验只验证字段形状、类型、引用存在性、navProfile/navId 交叉引用、sourceRef path/key presence 和 target node/lane 一致性;具体用户、profile、navId 集合和 sourceRef 路径以 YAML 为准,不在代码中藏默认。
### 5.2 根导航与 enforcement 矩阵
| navId | 前端路由示例 | 后端 API capability | admin-full | code-mdtodo-only |
| --- | --- | --- | --- | --- |
| `workbench.code` | `/workbench`, `/workbench/sessions/:sessionId` | `workbench.code` | allow | allow |
| `project.mdtodo` | `/projects/mdtodo` | `project.mdtodo` | allow | allow |
| `project.list` | `/projects` | `project.list` | allow | deny |
| `dashboard.overview` | `/dashboard` | `dashboard.overview` | allow | deny |
| `user.apiKeys` | `/api-keys` | `user.apiKeys` | allow | deny |
| `usage.read` | `/usage` | `usage.read` | allow | deny |
| `billing.read` | `/billing` | `billing.read` | allow | deny |
| `performance.read` | `/performance` | `performance.read` | allow | deny |
| `skills.read` | `/skills` | `skills.read` | allow | deny |
| `settings.read` | `/settings` | `settings.read` | allow | deny |
| `gate.read` | `/gate` | `gate.read` | allow | deny |
| `help.read` | `/help` | `help.read` | allow | deny |
| `admin.access` | `/admin/access` | `admin.access` + role admin | allow | deny |
| `admin.users` | `/admin/users` | `admin.users` + role admin | allow | deny |
| `admin.billing` | `/admin/billing` | `admin.billing` + role admin | allow | deny |
| `admin.hwpodGroups` | `/admin/hwpod-groups` | `admin.hwpodGroups` + role admin | allow | deny |
| `admin.providerProfiles` | `/admin/provider-profiles` | `admin.providerProfiles` + role admin | allow | deny |
直接访问 deny 项时,Cloud Web router 应显示 403/redirect 到允许的默认入口;后端 API 应返回 403 和 `nav_access_denied`,不得返回越权数据。`/v1/admin/*` 继续要求 admin role;普通 nav claim 不能提升为 admin。
## 6. 原子需求
### 6.1 USER-NAV-REQ-001 YAML-first 用户与导航配置真相
| 编号 | 短名 | 主责模块 | 关联模块 |
| --- | --- | --- | --- |
| USER-NAV-REQ-001 | YAML配置 | PJ2026-0105010501 YAML配置 | [YAML运维](PJ2026-010603-yaml-first-ops.md)、[账号会话](PJ2026-010501-account-session.md) |
D601 v0.3 的预置用户和根导航 ACL 必须由 YAML 声明,并通过 node/lane `accessControl` configRef 串联 users、navProfiles、runtime namespace、rollout target 和 session claim 输出开关。
`admin` 必须由 YAML 管理其全量导航访问能力;`huiggao@163.com` 必须由 YAML 声明为 active 普通用户并绑定 `code-mdtodo-only` nav profile。代码不得内置这些用户、邮箱、role、nav profile、namespace、Secret 名或 navId 集合作为隐藏默认;缺少 YAML 或引用冲突时应报告配置路径和 redacted blocker。
CLI plan/status 默认输出应包含 usersRef、navProfilesRef、node/lane、namespace、用户 logical id、username、role、status、navProfile、allowedNavIds 摘要、sourceRef/key、presence、fingerprint、target Secret/key、mutation 摘要和下一步命令;不得默认展开完整 YAML 或 Secret 值。
### 6.2 USER-NAV-REQ-002 密码 sourceRef 与强密码生成
| 编号 | 短名 | 主责模块 | 关联模块 |
| --- | --- | --- | --- |
| USER-NAV-REQ-002 | 密码来源 | PJ2026-0105010502 密码来源 | [YAML运维](PJ2026-010603-yaml-first-ops.md)、[发布流水](PJ2026-010601-controlled-release.md) |
受控 CLI 必须提供强密码生成入口,使 operator 可以为 `huiggao@163.com` 生成强密码并写入 gitignored owner-only plaintext sourceRef。该入口只能在本地显示 sourceRef、key、presence、byte count、fingerprint 和写入状态;不得把明文回显到普通 stdout、issue、PR、CI 日志或 runtime status。
运行面只接收 password hash 或等价安全摘要。hash transform 名称由 YAML 声明;transform 实现只能作为小型 adapter 或共享 Secret helper 存在,不得把明文、hash 或历史默认密码写入代码。缺少 sourceRef、key 缺失、sourceRef 未被 git ignore、fingerprint 不匹配或 transform 未知时,sync 必须停止并输出 redacted blocker。
### 6.3 USER-NAV-REQ-003 多用户 bootstrap/sync 幂等落库
| 编号 | 短名 | 主责模块 | 关联模块 |
| --- | --- | --- | --- |
| USER-NAV-REQ-003 | 用户同步 | PJ2026-0105010503 用户同步 | [账号会话](PJ2026-010501-account-session.md)、[权限配额](PJ2026-010503-access-quota.md) |
Cloud API bootstrap/sync 必须根据 YAML 中的用户声明幂等维护本地用户表和 nav profile binding。每个用户至少维护稳定 `id``username/email``displayName``role``status`、password hash 摘要和 nav profile id。
重复 sync 应只更新声明字段,不创建重复用户,不删除未被本 YAML owner 声明的运行面用户,除非 YAML 明确提供 retirement policy。禁用、role 变化、password rotation 和 nav profile 变化都必须有可审计 mutation 摘要;摘要只显示对象 id、字段名、sourceRef、fingerprint 和变更类型,不显示敏感值。
### 6.4 USER-NAV-REQ-004 OpenFGA 与应用层 ACL 映射
| 编号 | 短名 | 主责模块 | 关联模块 |
| --- | --- | --- | --- |
| USER-NAV-REQ-004 | ACL映射 | PJ2026-0105010504 ACL映射 | [权限配额](PJ2026-010503-access-quota.md)、[API契约](PJ2026-010403-api-contract.md) |
`admin` 必须继续获得 OpenFGA `system:hwlab#admin` 或等价全访问能力;`huiggao@163.com` 不得获得 system admin。Code 和 MDTODO 的访问可以采用“OpenFGA 管核心资源 + 应用层 nav claim”的组合,也可以扩展 OpenFGA model 增加 `nav_item`,但 YAML 必须是 source of truth。
应用层 ACL 必须从 authenticated canonical principal、user status、role、nav profile 和必要 OpenFGA 判断生成 access claim。`/v1/auth/session``/v1/users/me` 应返回 `access.nav.allowedIds` 和必要 capability 摘要,并设置 `valuesRedacted=true`;响应不得包含 password hash、Secret、完整 OpenFGA tuple dump 或内部敏感字段。
后端 API 必须按 capability 兜底拒绝:Code/workbench 相关 API 需要 `workbench.code` 或对应业务 capabilityMDTODO/project-management 相关 API 需要 `project.mdtodo` 或对应业务 capability`/v1/admin/*` 继续要求 admin。未授权时返回 403、`nav_access_denied` 和脱敏 route/capability 摘要。
### 6.5 USER-NAV-REQ-005 Cloud Web 根导航与 router guard
| 编号 | 短名 | 主责模块 | 关联模块 |
| --- | --- | --- | --- |
| USER-NAV-REQ-005 | Web导航 | PJ2026-0105010505 Web导航 | [Web工作台](PJ2026-010401-web-workbench.md)、[项目管理](PJ2026-010404-project-management.md)、[API契约](PJ2026-010403-api-contract.md) |
Cloud Web 每个根导航项必须声明稳定 `navId`,并在 route meta 中声明所需 nav/capability。`AppShell` 不得无条件渲染完整硬编码导航;它必须消费 `/v1/auth/session``/v1/users/me` 返回的 access claim 过滤根导航。
router guard 必须同时处理 `requiresAuth``requiresAdmin``navId`/capability。用户登录后访问自己无权的页面时,应显示 403 或跳转到第一个允许的默认入口;直接输入 URL、刷新、深链、浏览器后退和 session hydrate 都必须走同一 guard。前端隐藏不是安全边界,后端 API guard 必须独立执行。
`huiggao@163.com` 登录后左侧只能显示 `Code``MDTODO` 两个入口;`admin` 登录后显示全部现有导航入口。禁止通过 localStorage、fake flag、cookie prefix、role 字符串硬编码或用户邮箱特判控制导航。
### 6.6 USER-NAV-REQ-006 D601 v0.3 受控发布与原入口验收
| 编号 | 短名 | 主责模块 | 关联模块 |
| --- | --- | --- | --- |
| USER-NAV-REQ-006 | 发布验收 | PJ2026-0105010506 发布验收 | [发布流水](PJ2026-010601-controlled-release.md)、[YAML运维](PJ2026-010603-yaml-first-ops.md)、[公开入口](PJ2026-010604-public-entry.md) |
该能力必须进入 D601 v0.3 env-reuse、git-mirror checkout、GitOps、Tekton、Argo 和 public Web 验收链路。正式交付不得通过手工热改 runtime Secret、临时 SQL、pod env patch、直接 `kubectl` 或数据库 update 完成。
发布前 plan/status 应证明 users/navProfiles configRef 可解析、password sourceRef present、fingerprint 可见、target namespace/deployment 对齐 D601/v03 YAML。发布后验收至少覆盖:`admin` 登录可见全部导航并可访问 admin API;`huiggao@163.com` 登录只见 `Code``MDTODO`;允许路由 `/workbench``/workbench/sessions/:sessionId``/projects/mdtodo` 可访问;deny 矩阵中的前端路由被拒绝或重定向;对应后端 API 返回 403 `nav_access_denied`session/me 响应只含非敏感 access 摘要。
判定相关实现完成前,必须在 D601/v03 正式 public origin 或 YAML 声明的等价 web-probe origin 完成原入口登录/导航/API 验收,并记录 source commit、PipelineRun、Argo/runtime revision、public origin、用户名摘要、navId 列表、403 错误码和 `valuesRedacted=true`。若 D601 provider、git-mirror、Tekton、Argo 或 public entry 不可用,应将其作为 blocker 记录,不能用源码检查或源码合并单独判定完成。
### 6.7 USER-NAV-REQ-007 SPEC-first 代码引用与阶段边界
| 编号 | 短名 | 主责模块 | 关联模块 |
| --- | --- | --- | --- |
| USER-NAV-REQ-007 | 代码引用 | PJ2026-0105010507 代码引用 | [规格治理](spec-governance.md)、[YAML运维](PJ2026-010603-yaml-first-ops.md) |
本规格的后续实现阶段必须引用本规格编号和实现引用版本。修改的 YAML parser、access-control CLI、Cloud API auth/session/users/me、OpenFGA/ACL mapper、API guard、Cloud Web nav model、router guard 和 web-probe 验收脚本都应能追溯到 `PJ2026-01050105 用户导航ACL draft-2026-06-26-users-nav-acl`
实现阶段按固定顺序推进:P1 YAML schema 与受控 CLIP2 后端 provisioning 与 enforcementP3 前端导航与路由;P4 D601 v0.3 发布验收。P0 SPEC 完成前不得把代码实现、部署、CI/CD 或验收列为已完成。新发现事项只能分类为当前阶段 must-fix、真实领域差异或 out-of-scope parked risk,不因 grep 命中继续追加开放轮次。