From c417c988b175be06c77f3c4a31ecda4cdd3a421d Mon Sep 17 00:00:00 2001 From: Lyon <88232613+pikasTech@users.noreply.github.com> Date: Fri, 26 Jun 2026 11:50:23 +0800 Subject: [PATCH] docs: add HWLAB users nav ACL spec (#956) Co-authored-by: Codex --- .../specs/PJ2026-010501-account-session.md | 6 +- ...26-01050105-yaml-first-users-nav-access.md | 369 ++++++++++++++++++ 2 files changed, 373 insertions(+), 2 deletions(-) create mode 100644 project-management/PJ2026-01/specs/PJ2026-01050105-yaml-first-users-nav-access.md diff --git a/project-management/PJ2026-01/specs/PJ2026-010501-account-session.md b/project-management/PJ2026-01/specs/PJ2026-010501-account-session.md index 2a2556fa..31eadea8 100644 --- a/project-management/PJ2026-01/specs/PJ2026-010501-account-session.md +++ b/project-management/PJ2026-01/specs/PJ2026-010501-account-session.md @@ -81,7 +81,7 @@ D601 v0.3 当前已具备 app-local 注册、登录、登出、会话检查、 | PJ2026-01050102 | 会话状态 | 本规格 6.2 | session 检查、当前用户和禁用状态生效 | 注册登录、平台 Secret | API key、Agent编排、客户端 | | PJ2026-01050103 | Profile安全 | 本规格 6.3 | profile、密码修改和安全设置 | 用户身份、客户端账户入口 | 用户自服务、admin 用户管理 | | 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. 原子需求 @@ -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 来定义用户身份。 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 补救身份。 + +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。 diff --git a/project-management/PJ2026-01/specs/PJ2026-01050105-yaml-first-users-nav-access.md b/project-management/PJ2026-01/specs/PJ2026-01050105-yaml-first-users-nav-access.md new file mode 100644 index 00000000..0af36508 --- /dev/null +++ b/project-management/PJ2026-01/specs/PJ2026-01050105-yaml-first-users-nav-access.md @@ -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 和运行面 Secret;CLI 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` 或对应业务 capability;MDTODO/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 与受控 CLI;P2 后端 provisioning 与 enforcement;P3 前端导航与路由;P4 D601 v0.3 发布验收。P0 SPEC 完成前不得把代码实现、部署、CI/CD 或验收列为已完成。新发现事项只能分类为当前阶段 must-fix、真实领域差异或 out-of-scope parked risk,不因 grep 命中继续追加开放轮次。