fix: remove v02 authorization residue
This commit is contained in:
@@ -27,8 +27,8 @@
|
||||
- GitHub PR/issue 能力通过 `toolCredentials[].tool=github` 注入,默认 SecretRef 是 `agentrun-v01-tool-github-pr` key `GH_TOKEN`。
|
||||
- UniDesk SSH passthrough 通过 `toolCredentials[].tool=unidesk-ssh` 注入,默认 SecretRef 是 `agentrun-v01-tool-unidesk-ssh` key `UNIDESK_SSH_CLIENT_TOKEN`。
|
||||
- `UNIDESK_SSH_CLIENT_TOKEN` 只授予 UniDesk frontend `/ws/ssh` scoped client 能力;route allowlist 由 UniDesk frontend 配置控制。HWLAB 不持有 provider token、主 server SSH key 或完整 frontend 登录态。
|
||||
- `runnerJob.transientEnv` 只能承接本次 runner job 需要的短期执行上下文,例如 `HWLAB_DEVICE_POD_API_KEY` 和 `UNIDESK_MAIN_SERVER_IP`;`HWLAB_DEVICE_POD_API_KEY` 必须标记 sensitive,不得承载 GitHub token、UniDesk SSH client token、provider key、长期 SSH key 或 registry token。
|
||||
- HWLAB v0.2 device-pod 能力在 runner 内只通过 `hwpod -> HWLAB_RUNTIME_API_URL -> hwlab-cloud-api` 进入。`HWLAB_RUNTIME_API_URL` 指向当前 namespace 的 `hwlab-cloud-api` Service;`HWLAB_RUNTIME_WEB_URL` 仅供需要浏览器同源语义的工具查看 Cloud Web。AgentRun 不把 `HWLAB_DEVICE_POD_API_KEY` 发往 Cloud Web,也不以 Cloud Web 代理替代设备 API。
|
||||
- `runnerJob.transientEnv` 只能承接本次 runner job 需要的短期执行上下文,例如 owner-scoped `HWLAB_API_KEY`、`HWLAB_RUNTIME_API_URL` 和 `UNIDESK_MAIN_SERVER_IP`;敏感项必须标记 sensitive,不得承载 GitHub token、UniDesk SSH client token、provider key、长期 SSH key 或 registry token。
|
||||
- HWLAB v0.2 device-pod 能力在 runner 内只通过 `hwpod -> HWLAB_RUNTIME_API_URL -> hwlab-cloud-api` 进入。`HWLAB_RUNTIME_API_URL` 指向当前 namespace 的 `hwlab-cloud-api` Service;`HWLAB_RUNTIME_WEB_URL` 仅供需要浏览器同源语义的工具查看 Cloud Web。AgentRun 不以 Cloud Web 代理替代设备 API。
|
||||
|
||||
## ResourceBundle
|
||||
|
||||
|
||||
@@ -149,8 +149,6 @@ CREATE TABLE IF NOT EXISTS device_pods (
|
||||
|
||||
历史版本中的 `profile_ref`、`gateway_ref` 或 `device_pod_json` 可以在迁移时折叠进 `profile_json`。第一阶段不新增 `device_pod_profile_revisions`;需要审计版本、回滚或多环境批准时再引入 profile revision 表。
|
||||
|
||||
历史版本中的 `device_pod_grants` 不是当前 v0.2 device pod 授权契约。目标状态的 device pod 可见、操作、profile 修改和 job 提交权限只由 OpenFGA relation 表达;旧表若仍存在于已发布数据库中,只能作为历史迁移输入,不得作为写入口、健康必需表或 allow 判定来源。
|
||||
|
||||
## REST API
|
||||
|
||||
## API 接口说明
|
||||
@@ -255,7 +253,7 @@ manages: many devicePodId
|
||||
- `hwlab-device-pod` 一个实例可以列出并执行多个 `devicePodId` 的状态/job。
|
||||
- cloud-api legacy compatibility entry 只能返回 blocked authority payload,不得合成 fake device pod 数据或作为正式 device-pod DEV-LIVE 证据。
|
||||
- 强副作用 job 必须有 `reason`;正式路径只使用 Web session/cookie 或映射到具体用户的 `HWLAB_API_KEY` 做身份授权。
|
||||
- AgentRun runner 访问 device-pod 必须使用 cloud-api 组装的用户 `HWLAB_API_KEY`,该 key 恢复为发起 Code Agent session 的 owner 用户;不得使用跨用户共享、对所有正式 device-pod 授权的 system key。
|
||||
- AgentRun runner 访问 device-pod 必须使用 cloud-api 组装的用户 `HWLAB_API_KEY`,该 key 恢复为发起 Code Agent session 的 owner 用户;权限继续由 OpenFGA relation 判定。
|
||||
- 撤销 device pod relation 必须同时影响该用户通过 Web session、CLI API key 和 AgentRun `hwpod` 的可见性与使用权;revoke API key 后 CLI 和 runner 内旧 key 都必须失效。
|
||||
|
||||
## CLI 实现口径
|
||||
@@ -264,7 +262,7 @@ manages: many devicePodId
|
||||
|
||||
- `profile list/show` 调用 cloud-api `/v1/device-pods` 和 `/status`,只显示服务端脱敏 profile 摘要和 `profileHash`。
|
||||
- AgentRun runner 中只使用装配好的 `HWLAB_RUNTIME_API_URL` 和映射到当前用户的 `HWLAB_API_KEY`,直接访问 `hwlab-cloud-api`;不得手动传 `--api-base-url`,也不得改走 Cloud Web 同源代理。
|
||||
- `setup first-admin` 和 `admin device-pod upsert` 只作为 cloud-api REST wrapper,用于首次空库 seed 或 admin profile 管理;device pod 授权统一使用 `hwlab-cli client access device-pods grant/revoke` 的 Admin Access API,不走 `hwpod admin grant`。
|
||||
- `setup first-admin` 和 `admin device-pod upsert` 只作为 cloud-api REST wrapper,用于首次空库 seed 或 admin profile 管理;device pod 授权统一使用 `hwlab-cli client access device-pods grant/revoke` 的 Admin Access API。
|
||||
- `devicePodId:workspace|debug-probe|io-probe...` selector 转换为 `POST /v1/device-pods/{devicePodId}/jobs` 或 job status/output/cancel REST,不直接调用 `/v1/rpc/hardware.invoke.shell`。
|
||||
- `bootsharp --pod-id <devicePodId>` 和 `<devicePodId>:workspace:/ bootsharp` 都转换为 `workspace.bootsharp` job,用于返回 workspace tree、AGENTS.md 摘要和当前路径提示;该入口是上下文恢复和 DS 派单的首个探测动作,不读取本地 profile。
|
||||
- workspace 写操作覆盖 `apply-patch`、`put`、`rm`、`rmdir`、`build` 和 `keil add-source/remove-source` 等 Keil 工程维护动作。
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
本规格与 [spec-device-pod.md](spec-device-pod.md) 配套:用户和权限规格定义谁可以看见、创建和使用 device pod;device-pod 规格定义 profile authority、REST/job 和硬件执行边界。
|
||||
|
||||
登录入口、Keycloak OIDC、Web session、CLI API key 和 `AuthPrincipal` 归一见 [spec-v02-auth.md](spec-v02-auth.md)。OpenFGA、Admin Access WebUI 和同路径 CLI 细节见 [spec-v02-openfga-authorization.md](spec-v02-openfga-authorization.md)。本文只定义认证完成后的角色、资源归属、device pod capability、tool capability 和 code agent owner 授权;正式用户鉴权只有 Web session 与 CLI/API key 两类,除非明确标注为 bootstrap/legacy,不再把本地账号密码登录或 device-pod 系统 key 作为目标登录体验。
|
||||
登录入口、Keycloak OIDC、Web session、CLI API key 和 `AuthPrincipal` 归一见 [spec-v02-auth.md](spec-v02-auth.md)。OpenFGA、Admin Access WebUI 和同路径 CLI 细节见 [spec-v02-openfga-authorization.md](spec-v02-openfga-authorization.md)。本文只定义认证完成后的角色、资源归属、device pod capability、tool capability 和 code agent owner 授权;正式用户鉴权只有 Web session 与 CLI/API key 两类。
|
||||
|
||||
实施跟踪见 [pikasTech/HWLAB#531](https://github.com/pikasTech/HWLAB/issues/531),原 `docs/plan/v02-multi-user-migration.md` 迁移计划全文已迁入该 issue 评论。
|
||||
|
||||
@@ -23,7 +23,7 @@ Postgres 是用户、session、业务对象和迁移 ledger 的持久化边界
|
||||
- 只保留两类角色:`admin` 和 `user`。
|
||||
- `code agent session` 直接归属于创建它的用户;普通用户只能查看、继续和取消自己的 session。
|
||||
- `device pod` 由 `admin` 或被授予 `profile_editor` 的用户管理;普通用户只有在被授权后才能看到、操作或提交对应 device pod job。
|
||||
- device pod 授权按 `viewer`、`operator`、`profile_editor`、`job_submitter` 等 OpenFGA relation 表达;旧 `device_pod_grants` 不再代表目标状态的完整使用权,也不得作为 allow 判定或管理入口。
|
||||
- device pod 授权按 `viewer`、`operator`、`profile_editor`、`job_submitter` 等 OpenFGA relation 表达。
|
||||
- 工具能力必须独立授权,例如 `hwpod`、`unidesk_ssh`、`trans_cmd` 和 GitHub 写工具;拥有 Code Agent session 不等于拥有这些工具。
|
||||
- MVP 不新增产品级 `audit_events` 用户审计表,也不把用户权限依赖到 audit。现有硬件 trace/evidence/audit 字段属于硬件闭环证据,不是多用户权限模型的一部分。
|
||||
- 强副作用 device-pod job 只额外要求业务 `reason`;设备互斥由 executor、gateway 和硬件 host 串行化或返回 blocker,不进入用户权限模型。
|
||||
@@ -125,16 +125,6 @@ CREATE TABLE IF NOT EXISTS device_pods (
|
||||
|
||||
`profile_json` 中的 gateway route、host workspace、probe UID、串口端口和 host CLI 都是服务端权威字段;普通用户响应只能看到脱敏 profile 摘要和 `profile_hash`。
|
||||
|
||||
### 历史 `device_pod_grants`
|
||||
|
||||
历史版本曾用 `device_pod_grants` 表表达普通用户对 device pod 的全权限兼容授权。当前 v0.2 目标状态以 OpenFGA tuple 为准;该表不再由当前 schema 创建,不是 runtime readiness 必需表,不得新增写入口,也不得作为正式 allow source。若已有数据库仍保留该表,只能作为一次性迁移输入读取,迁移完成后权限必须写入 OpenFGA relation。
|
||||
|
||||
- 不新增 `capability`、`scope`、`expires_at` 字段;细粒度 relation 不回写到该表,统一写 OpenFGA。
|
||||
- 在 OpenFGA `enforce` 模式下,撤销授权就是删除对应 tuple;该表若仍有 legacy 行也不能放行请求。
|
||||
- AgentRun runner 不使用跨用户共享的 device-pod 系统 key。runner 内 `hwpod` 只能使用映射到 Code Agent session owner 的 `HWLAB_API_KEY`,并按同一用户的 OpenFGA device pod relation 与 tool capability 授权。
|
||||
- 当前 schema 和 runtime schema ensure 必须以 `DROP TABLE IF EXISTS device_pod_grants` 表达收敛,不得重新出现 `CREATE TABLE IF NOT EXISTS device_pod_grants`。如果 live Postgres 中仍存在该表,应按历史迁移残留处理,迁移或确认无效后删除;不能把它作为健康检查、授权回退或 Admin Access 展示来源。
|
||||
- 代码中允许保留的 `device_pod_grants` 引用只限于历史说明、`DROP TABLE` 和“不得创建旧表”的测试断言。Web、CLI、Cloud API 和 AgentRun 路径不得新增旧表读写 helper、旧 grant fallback 或旧 route 兼容入口。
|
||||
|
||||
## 权限矩阵
|
||||
|
||||
| 操作 | `admin` | `user` |
|
||||
@@ -176,7 +166,7 @@ cli
|
||||
-> AuthPrincipal(authMethod='api-key')
|
||||
```
|
||||
|
||||
登录、Keycloak issuer、CLI API key 和 24 小时 Web session 规则见 [spec-v02-auth.md](spec-v02-auth.md)。资源授权模块只消费已经恢复出的 actor/AuthPrincipal。`/auth/session` 使用 cookie 查 `user_sessions`,再查 `users` 得到 `actor`;API key 认证直接从 `api_keys -> users` 得到同一 actor。`/auth/logout` 标记 `user_sessions.revoked_at`。Keycloak access token、refresh token、realm role 和 device-pod 内部系统 key 都不能绕过这里的 actor 恢复与资源授权。
|
||||
登录、Keycloak issuer、CLI API key 和 24 小时 Web session 规则见 [spec-v02-auth.md](spec-v02-auth.md)。资源授权模块只消费已经恢复出的 actor/AuthPrincipal。`/auth/session` 使用 cookie 查 `user_sessions`,再查 `users` 得到 `actor`;API key 认证直接从 `api_keys -> users` 得到同一 actor。`/auth/logout` 标记 `user_sessions.revoked_at`。Keycloak access token、refresh token、realm role 和内部 service token 都不能绕过这里的 actor 恢复与资源授权。
|
||||
|
||||
### admin 创建用户
|
||||
|
||||
@@ -203,9 +193,9 @@ browser admin Access UI
|
||||
-> return effective permission matrix
|
||||
```
|
||||
|
||||
撤销授权走 `DELETE /v1/admin/access/users/{userId}/device-pods/{devicePodId}/{relation}`。`/v1/admin/device-pod-grants` 旧全权限入口不再保留;管理员只能通过 Admin Access API 写入或删除 OpenFGA relation。
|
||||
撤销授权走 `DELETE /v1/admin/access/users/{userId}/device-pods/{devicePodId}/{relation}`。管理员只能通过 Admin Access API 写入或删除 OpenFGA relation。
|
||||
|
||||
旧 `hwpod admin grant`、`device-pod-cli admin grant` 或等价本地全权限 grant 命令不属于 v0.2 授权路径。需要给用户开通 device pod 或工具能力时,统一使用 Admin Access API、Admin Access WebUI 或同路径 `hwlab-cli client access ...`,并按具体 relation 或 `tool:*#can_use` 写入 OpenFGA tuple。
|
||||
需要给用户开通 device pod 或工具能力时,统一使用 Admin Access API、Admin Access WebUI 或同路径 `hwlab-cli client access ...`,并按具体 relation 或 `tool:*#can_use` 写入 OpenFGA tuple。
|
||||
|
||||
### 用户列出 device pod
|
||||
|
||||
@@ -251,9 +241,9 @@ code agent prompt、runner 或 worker 不得直接绕过 cloud-api 调用 device
|
||||
|
||||
## 内部架构
|
||||
|
||||
`hwlab-cloud-api` 内部应按 auth/session/API key、authorization、agent session owner、device-pod grant 和 admin API 模块分层。所有模块共享同一 Postgres runtime store 和 migration ledger,避免拆出早期 `hwlab-user-api` 造成跨服务一致性成本。
|
||||
`hwlab-cloud-api` 内部应按 auth/session/API key、authorization、agent session owner、device-pod relation 和 admin API 模块分层。所有模块共享同一 Postgres runtime store 和 migration ledger,避免拆出早期 `hwlab-user-api` 造成跨服务一致性成本。
|
||||
|
||||
`user_sessions` 存浏览器 session token hash;`api_keys` 存映射到用户的 CLI/runner API key;`agent_sessions.owner_user_id` 绑定 Code Agent session;`device_pods` 存 profile authority;OpenFGA tuple 表示用户对 device pod、agent session 和工具的细粒度能力。`device_pod_grants` 只能作为迁移时读取旧数据的历史表,不得作为正式授权写入口或 allow 决策来源。不得再引入对所有正式 device pod 授权的共享用户 key;`HWLAB_DEVICE_POD_API_KEY` 如仍存在,只能作为 cloud-api 到 device-pod 的内部服务凭据。
|
||||
`user_sessions` 存浏览器 session token hash;`api_keys` 存映射到用户的 CLI/runner API key;`agent_sessions.owner_user_id` 绑定 Code Agent session;`device_pods` 存 profile authority;OpenFGA tuple 表示用户对 device pod、agent session 和工具的细粒度能力。cloud-api 调用 device-pod 内部执行服务使用内部 service token,该 token 不参与用户鉴权、不写入 runner env,也不产生 actor。
|
||||
|
||||
## API 接口说明
|
||||
|
||||
@@ -330,5 +320,4 @@ Kubernetes 只做运行时隔离和资源兜底,不承载 HWLAB 用户权限
|
||||
| `users`、`user_sessions`、OpenFGA relation 和 job 表 | 部分实现 | access-control bootstrap 覆盖 users、sessions、device_pods、access_tuples 和 jobs;Device Pod 强副作用 job 已接入 reason 校验,真实硬件执行仍依赖 gateway/device-host-cli 在线。 |
|
||||
| Code Agent owner 绑定 | 已实现 | 已在 `agent_sessions` 写入 `owner_user_id`、conversation/thread/trace 和脱敏 session evidence;trace/result cache 也按 owner/admin 限制访问。 |
|
||||
| OpenFGA 细粒度授权模型 | 核心已实现/持续约束 | v0.2 enforce runtime 已通过 Admin Access API 和同路径 CLI 管理 device pod relation 与 tool capability;后续扩展仍必须按 [spec-v02-openfga-authorization.md](spec-v02-openfga-authorization.md) 保持同一 authority。 |
|
||||
| legacy device pod grant 兼容 | 已退出目标路径 | `/v1/admin/device-pod-grants`、旧全权限 grant fallback 和 `device_pod_grants` authority 不再保留;历史表只可作为一次性迁移输入,当前 schema 只允许 `DROP TABLE IF EXISTS device_pod_grants`。 |
|
||||
| 不用 Kubernetes 表达用户权限 | 已实现/持续约束 | 规格明确禁止普通用户持有 kubeconfig 或直连 Service 权限。 |
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
- Web 用户通过 Keycloak OIDC 登录或注册,HWLAB 不再把本地账号密码表单作为目标登录体验。
|
||||
- Web 使用 `hwlab-cloud-api` 发行的 httpOnly `hwlab_session`,每个 session token 最长 24 小时;第一版不做复杂 refresh token 管理,但必须可撤销、可重新登录轮换。
|
||||
- CLI 是纯 CLI 体验,不打开浏览器、不跳转 Web、不做 device-code flow,也不直接消费 Keycloak access token;标准凭据是环境变量 `HWLAB_API_KEY`。
|
||||
- AgentRun runner 内的 `hwpod` 也必须使用同一类用户 API key 认证,映射到发起 Code Agent session 的 `users.id`;`HWLAB_DEVICE_POD_API_KEY` 只能作为 cloud-api 到 device-pod 的内部服务凭据或迁移期兼容项,不能作为正式用户鉴权方式。
|
||||
- AgentRun runner 内的 `hwpod` 也必须使用同一类用户 API key 认证,映射到发起 Code Agent session 的 `users.id`;device-pod 内部 service token 只允许 cloud-api 调用内部执行服务,不能恢复用户 actor。
|
||||
- 每个用户在首次登录后自动拥有一个默认 API key;用户也可以在 Web 中创建、查看、失效或重新生成 API key。
|
||||
- API key 长效有效,除非用户或管理员手动 revoke/regenerate;它不跟 Web session 的 24 小时过期绑定。
|
||||
- Keycloak 只做身份认证和账号注册;HWLAB 的 `users.role`、`users.status`、OpenFGA relation 和 Code Agent owner 仍是应用层授权 source of truth。
|
||||
- device-pod 权限只由 `users.role/status`、Code Agent session owner 和 OpenFGA relation 控制;不存在“对所有正式 device pod 授权”的共享 runner key。
|
||||
- device-pod 权限只由 `users.role/status`、Code Agent session owner 和 OpenFGA relation 控制;runner 只接收当前 owner 的用户 API key。
|
||||
|
||||
## 系统边界
|
||||
|
||||
@@ -276,7 +276,7 @@ API key 行为:
|
||||
|
||||
## T6
|
||||
|
||||
阅读 docs/reference/spec-v02-auth.md,然后检查 cloud-api 日志、trace、CLI 默认输出和 issue 复现材料,确认不出现 Keycloak client secret、session token、完整 API key、历史 `HWLAB_DEVICE_POD_API_KEY` 或 Postgres URL 原文;AgentRun runner 中也不得存在跨用户共享的 device-pod 系统 key。
|
||||
阅读 docs/reference/spec-v02-auth.md,然后检查 cloud-api 日志、trace、CLI 默认输出和 issue 复现材料,确认不出现 Keycloak client secret、session token、完整 API key 或 Postgres URL 原文;AgentRun runner 中只能出现映射到当前 owner 的用户 API key。
|
||||
|
||||
## 规格的实现情况
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ devops-infra git mirror 仍是 PipelineRun 和 Argo CD 的集群内读写源。`
|
||||
- Tekton/Argo 的 rendered runtime desired state。
|
||||
- image digest、publish state、reuse evidence 或 CI 生成的 rollout metadata。
|
||||
|
||||
如果权限、schema 或 runtime desired state 发生迁移,必须分别核对 source schema/代码、`v0.2-gitops` rendered YAML 和 live runtime。以 `device_pod_grants` 这类旧路径为例:source branch 应只保留当前 migration/ensure 逻辑,`v0.2-gitops` 与 live ConfigMap 应体现发布后的 rendered state,fixed workspace 下 ignored `runtime-v02/postgres.yaml` 即使存在也不能代表真相。
|
||||
如果权限、schema 或 runtime desired state 发生迁移,必须分别核对 source schema/代码、`v0.2-gitops` rendered YAML 和 live runtime。source branch 只保留当前目标 schema 和实现,`v0.2-gitops` 与 live ConfigMap 体现发布后的 rendered state,fixed workspace 下 ignored `runtime-v02/postgres.yaml` 即使存在也不能代表真相。
|
||||
|
||||
`v0.2-gitops` branch 必须包含:
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ Code Agent session 是显式资源,不再由普通 `client agent send`、Workb
|
||||
- `client access ...` 是 Admin Access 页面的同路径 CLI,不直连 OpenFGA,不手动传 OpenFGA token,不把 `19667` Cloud API 当作 Web 等价验收路径。所有授权读写都必须输出 runtimeEndpoint、route、actor、mode、decision 和 effective matrix 摘要。
|
||||
- `client gateway pressure` 是 device-pod/gateway 高频故障的真实业务传输压测入口;必须覆盖 small stdout、大 stdout、长单行 stdout、stderr flood、结构化 timeout 和超出 gateway inflight 上限的并发请求。所有场景必须返回 JSON、HTTP/route/traceId/requestId、字节数、truncated 标记、sha256 和 bounded preview;失败必须明确是 `http_*`、`stdout_not_truncated`、`stderr_not_truncated`、`timeout_not_observed`、`structured_gateway_busy` 等可定位原因,禁止无输出、长时间黑洞或只靠 shell pipe 截断。
|
||||
- 输出默认是 JSON;任何失败都要有 `ok:false`、`action`、`status`、HTTP 状态、route 和可定位错误,不允许无 stdout 成功。可能返回大对象的 `client` 子命令默认返回紧凑摘要,避免高频排障输出爆炸;需要完整响应体时显式加 `--full`。
|
||||
- `device-pod-cli`/`hwpod` 在 AgentRun runner 中是设备 API 标准短入口,必须自动使用装配的 `HWLAB_RUNTIME_API_URL` 直达 `hwlab-cloud-api`,并使用映射到当前 Code Agent session owner 的 `HWLAB_API_KEY`;不能把 Cloud Web 同源代理当作设备 API 通道,也不能手动传 URL、session token 或历史 `HWLAB_DEVICE_POD_API_KEY`。`job output` 默认也必须返回紧凑 JSON:保留 job/status/blocker/freshness/text/evidence 摘要,省略嵌套 gateway dispatch 和长命令;需要完整 payload 时显式加 `--full`。Code Agent 和人工不得用 `| head`、`grep` 或 shell 管道作为默认输出压缩方式,避免 stdout pipe、子进程信号转发或长输出造成 commandExecution 黑洞。
|
||||
- `device-pod-cli`/`hwpod` 在 AgentRun runner 中是设备 API 标准短入口,必须自动使用装配的 `HWLAB_RUNTIME_API_URL` 直达 `hwlab-cloud-api`,并使用映射到当前 Code Agent session owner 的 `HWLAB_API_KEY`;不能把 Cloud Web 同源代理当作设备 API 通道,也不能手动传 URL 或 session token。`job output` 默认也必须返回紧凑 JSON:保留 job/status/blocker/freshness/text/evidence 摘要,省略嵌套 gateway dispatch 和长命令;需要完整 payload 时显式加 `--full`。Code Agent 和人工不得用 `| head`、`grep` 或 shell 管道作为默认输出压缩方式,避免 stdout pipe、子进程信号转发或长输出造成 commandExecution 黑洞。
|
||||
- Code Agent 交互必须默认暴露 `traceId`、`resultUrl`、终态和 assistant 回复文本摘要;不能要求用户先拉全量 trace 再手工查找回复。
|
||||
- CLI 本地登录态必须支持 `--profile NAME` 隔离,同一 base URL 下不同 profile 写入 `.state/hwlab-cli/profiles/<base-url-hash>/<profile>.json`。切换到其他账号再切回原账号时,`client workbench restore/status` 必须从服务端账号 workspace 恢复之前的 `workspaceId`、`conversationId`、`sessionId`、`threadId`、`activeTraceId` 和 revision,而不是只依赖本地文件。
|
||||
- `client workbench restore/status/watch/reset` 是账号 workspace 的非视觉入口:`restore/status` 对应 `GET /v1/workbench/workspace`,`watch` 对应 `/events?afterRevision=`,`reset --confirm` 对应服务端 reset。输出必须显示 workspace revision、selected conversation/session、active trace 和本地 state file,且不得保存 password、session token 原文以外的 Secret 值。
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
- 承担 runtime health、DB readiness、登录鉴权、`AuthPrincipal`、OpenFGA 授权 check/write、用户/session/API key 权限、Code Agent 对话、trace/result 轮询、gateway outbound registry、M3 IO 控制、device-pod authority/job 和 live build inventory。
|
||||
- 是 `hwlab-cloud-web`、Code Agent session、device-pod 用户态操作、Admin Access API、AgentRun 工具注入和 gateway outbound poll 的唯一应用层收口点;普通用户不直接访问内部 `hwlab-device-pod` Service 或 OpenFGA Service。
|
||||
- 读取 `hwlab-cloud-api-v02-db/database-url`、`hwlab-v02-code-agent-provider/openai-api-key` 和 `hwlab-v02-code-agent-codex-auth/auth.json` 等 v02 独立 SecretRef;用户 API key 存在 Postgres `api_keys`,不得再以 `hwlab-v02-device-pod-api-key/api-key` 这类跨用户 SecretRef 授权 device-pod。文档和日志只允许记录 SecretRef 名称、key、字节数或哈希指纹,不记录值。
|
||||
- 读取 `hwlab-cloud-api-v02-db/database-url`、`hwlab-v02-code-agent-provider/openai-api-key` 和 `hwlab-v02-code-agent-codex-auth/auth.json` 等 v02 独立 SecretRef;用户 API key 存在 Postgres `api_keys`,device-pod 用户态授权只能从该表恢复到用户 actor。文档和日志只允许记录 SecretRef 名称、key、字节数或哈希指纹,不记录值。
|
||||
- 读取 OpenFGA URL、auth token、store/model 指针和 mode 时只能通过 env/SecretRef/Postgres runtime config;`/health/live` 和 `/v1/admin/access/summary` 只输出 readiness、mode、storeId/modelId 摘要和 degraded reason,不输出 token、Postgres URL 或 tuple secret。
|
||||
|
||||
## 内部架构
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
| HWLAB v0.2 Postgres | 业务对象、用户、session、API key、access_tuples 摘要、OpenFGA store/model 指针和迁移 ledger 的 durable source。 |
|
||||
| `hwlab-cloud-web` | Admin Access 页面和同源 API proxy;不直接调用 OpenFGA。 |
|
||||
| `hwlab-cli client` | Web 等价非视觉授权管理入口;通过 `19666` Cloud Web 同源 path 调 cloud-api,不直连 OpenFGA。 |
|
||||
| AgentRun v0.1 runner | 只消费 cloud-api 根据用户权限注入的短期工具环境;不持有跨用户共享 device-pod key、GitHub token 或 UniDesk SSH token。 |
|
||||
| AgentRun v0.1 runner | 只消费 cloud-api 根据用户权限注入的短期工具环境;工具凭据必须按 tool capability 独立授权。 |
|
||||
|
||||
OpenFGA 是 HWLAB 应用层授权基础设施,不是 Kubernetes RBAC、ServiceAccount、NetworkPolicy 或 Keycloak realm role 的替代。普通用户不获得 kubeconfig、内部 Service 直连、OpenFGA token 或 Keycloak admin 权限。
|
||||
|
||||
@@ -121,7 +121,7 @@ authenticate -> AuthPrincipal -> load domain object -> openfga check -> reason c
|
||||
模式语义:
|
||||
|
||||
- `enforce` 是唯一正式运行模式:device pod、agent session 和工具能力以 OpenFGA check 为准。OpenFGA 不可达、store/model 未就绪或 check 超时时,高风险写操作 fail closed;低风险只读可以返回 degraded blocker,不得静默放行。
|
||||
- `off` / `shadow` 不作为 v0.2 runtime 目标路径;旧文档、测试或 render 如再次把它们作为业务 allow source,应优先删除而不是兼容。
|
||||
- `off` / `shadow` 不作为 v0.2 runtime 目标路径;文档、测试或 render 如再次把它们作为业务 allow source,应优先删除而不是兼容。
|
||||
|
||||
tuple 写入必须由 cloud-api admin API 统一完成,并和 Postgres domain state 保持事务级或可恢复一致:
|
||||
|
||||
@@ -148,7 +148,7 @@ Cloud Web 和 CLI 只能通过 cloud-api 的 admin API 管理授权。第一版
|
||||
|
||||
所有 write API 必须要求当前 actor 具备 `access_manager system:hwlab` 或 admin tuple;普通 `user` 不可调用。响应必须包含结构化 `authorization` 字段:`mode`、`allowed`、`decisionSource`、`storeId`、`modelId`、`relation`、`object` 和 redacted actor。
|
||||
|
||||
Cloud Web 必须把 Admin Access 读写 API 作为同源代理路径转发给 cloud-api,包括 `POST /v1/admin/access/check`、`PATCH /v1/admin/access/users/{userId}`、device pod relation 的 `PUT/DELETE` 和 tool capability 的 `PUT/DELETE`。不得在 Cloud Web 本地保留 `/v1/admin/device-pod-grants`、旧全权限 grant fallback 或旧表读取逻辑;旧 route 只可在迁移排查时作为“不存在”的负向烟测,不得作为兼容 API 合同维护。
|
||||
Cloud Web 必须把 Admin Access 读写 API 作为同源代理路径转发给 cloud-api,包括 `POST /v1/admin/access/check`、`PATCH /v1/admin/access/users/{userId}`、device pod relation 的 `PUT/DELETE` 和 tool capability 的 `PUT/DELETE`。Cloud Web 不保存授权副本,也不直接访问 OpenFGA。
|
||||
|
||||
## Admin Access WebUI
|
||||
|
||||
@@ -187,8 +187,6 @@ CLI 输出必须是 JSON,包含 `runtimeEndpoint`、HTTP route、actor 摘要
|
||||
|
||||
权限变更的真实入口验收必须以 Cloud Web 同源 origin 为准。最小闭环是:`client access summary` 确认 `openfga.mode=enforce` 且 ready;对一个普通用户执行某个 device pod relation 的 `check false -> grant -> check true -> revoke -> check false`;对至少一个工具能力执行同样闭环,`trans_cmd` 必须覆盖;最后 `users inspect` 确认测试 tuple 已撤回。验收报告必须记录 `baseUrl`、method/path、actor、relation/object、HTTP status、OpenFGA decision 和最终 effective matrix 摘要。
|
||||
|
||||
旧路径清理的验收不以旧 API 兼容为目标。可以用 `POST /v1/admin/device-pod-grants` 返回 Cloud Web `404` 证明旧入口不存在,但源码测试不应为了历史 route 维护长期行为;长期测试只表达 Admin Access/OpenFGA 当前目标路径。
|
||||
|
||||
## AgentRun 工具能力边界
|
||||
|
||||
Cloud API 在创建 AgentRun command/runner 时必须按 OpenFGA 决策装配 transient env 和工具说明:
|
||||
@@ -231,7 +229,7 @@ Cloud API 在创建 AgentRun command/runner 时必须按 OpenFGA 决策装配 tr
|
||||
|
||||
## T8
|
||||
|
||||
阅读 docs/reference/spec-v02-openfga-authorization.md 和 docs/reference/spec-user-access.md,然后检查 source schema、`v0.2-gitops` rendered ConfigMap 和 live Postgres:确认 source 不创建 `device_pod_grants`,render/live schema 包含 `DROP TABLE IF EXISTS device_pod_grants`,live `information_schema.tables` 中该表数量为 `0`。只允许历史说明、DROP 和“不得创建旧表”的测试断言引用该名称。
|
||||
阅读 docs/reference/spec-v02-openfga-authorization.md 和 docs/reference/spec-user-access.md,然后检查 source schema、`v0.2-gitops` rendered ConfigMap 和 live Postgres:确认 source、render 和 live schema 都只保留 OpenFGA/Admin Access 当前授权结构;live Postgres 中不应存在任何已退出的 device pod 授权表或兼容写入口。
|
||||
|
||||
## 规格的实现情况
|
||||
|
||||
@@ -239,9 +237,8 @@ Cloud API 在创建 AgentRun command/runner 时必须按 OpenFGA 决策装配 tr
|
||||
| --- | --- | --- |
|
||||
| OpenFGA 作为 v0.2 内部授权服务 | 已实现/持续约束 | v0.2 runtime 以 `enforce` 模式运行,summary 暴露 redacted store/model 和 readiness;OpenFGA 不向公网、浏览器或 CLI 暴露。 |
|
||||
| Cloud API OpenFGA client/bootstrap/check/write | 已实现 | Admin Access API 可 check/write tuple,响应包含 structured decision 和 redacted OpenFGA 状态。 |
|
||||
| 细粒度 device pod / session / tool 授权 | 核心已实现/持续扩展 | device pod relation 和 tool capability 已替代旧全权限 grant;后续 session/tool 扩展必须继续写 OpenFGA tuple。 |
|
||||
| 细粒度 device pod / session / tool 授权 | 核心已实现/持续扩展 | device pod relation 和 tool capability 统一写 OpenFGA tuple;后续 session/tool 扩展必须继续保持同一 authority。 |
|
||||
| Admin Access WebUI | 部分实现/持续约束 | Cloud Web Access 页面使用同一 Admin Access API;浏览器交互深测可作为专项验收,但不得新增第二条授权路径。 |
|
||||
| 同路径 CLI | 已实现 | `client access ...` 走 Cloud Web 同源 path,已覆盖 summary、users、check、device pod relation grant/revoke 和 tool grant/revoke。 |
|
||||
| AgentRun 工具注入按用户权限过滤 | 部分实现/持续约束 | `hwpod`、`unidesk_ssh`、`trans_cmd`、GitHub 写工具必须独立授权;实现和验收不得退回共享系统 key。 |
|
||||
| legacy `device_pod_grants` authority | 已退出目标路径 | source schema 不再创建旧表,runtime schema ensure 保留 DROP,旧 `/v1/admin/device-pod-grants` 不作为 API 合同。 |
|
||||
| AgentRun 工具注入按用户权限过滤 | 部分实现/持续约束 | `hwpod`、`unidesk_ssh`、`trans_cmd`、GitHub 写工具必须独立授权;runner 中的 `HWLAB_API_KEY` 必须映射到当前 Code Agent session owner。 |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user