6.0 KiB
HWLAB v0.3 User Billing And Account Authority
本文定义 HWLAB v0.3 多用户注册、登录、API key、用户状态和计费状态的权威边界。v0.3 采用 sub2api-style 应用内账号体系,由 hwlab-user-billing 服务负责账户与计费,不再把 Keycloak 作为注册/登录依赖。v0.2 的 Keycloak/OIDC 口径仅保留在 spec-v02-auth.md 中,不能反向覆盖 v0.3。
服务职责
hwlab-user-billing 是 v0.3 账户与计费 authority。它提供:
POST /v1/auth/register、POST /v1/auth/login、POST /v1/auth/logout、POST /v1/auth/refresh。GET /v1/me、GET /v1/billing/summary、POST /v1/api-keys。POST /internal/auth/introspect,供hwlab-cloud-api将 session/API key 归一成 HWLAB actor。POST /internal/billing/preflight和POST /internal/billing/record,供 Code Agent、AIPOD、HWPOD 等消耗型操作做余额预检、reservation 和 usage record。GET /internal/admin/billing/summary、POST /internal/admin/credits/adjust、POST /internal/admin/users/status,供 admin-only cloud-api 路径代理。GET /internal/admin/billing/plans,供 admin-only cloud-api 路径查看 plan、resource entitlement、quota、concurrency 和 RPM 的权威配置。
hwlab-cloud-api 仍是浏览器和 AgentRun/HWPOD 等业务入口的应用层边界。它不得直连 user-billing 数据表完成用户状态、余额或 API key 判定;用户态请求必须通过 user-billing introspection 或 admin/internal route 得到结构化结果。
状态与数据库边界
所有持久状态必须集中在 PK01 唯一外置 PostgreSQL。HWLAB v0.3 namespace 内不得新增自有 PostgreSQL StatefulSet、PVC 数据库或第二套账户库。hwlab-user-billing 的运行面健康和 admin summary 必须持续暴露以下语义,且不得打印 DSN、密码或 token:
stateAuthority=pk01-postgresstateless=truedatabaseAuthority=pk01-external-postgresredisRole=cache-only
namespace-local Redis 可以部署在 hwlab-v03 中,但只允许作为 cache、短期锁、临时队列或限流辅助;Redis 不能成为余额、交易、API key、session、用户状态或 usage ledger 的 source of truth。
用户状态
hwlab_users.status 是 v0.3 用户启停 authority。admin Web 的状态修改路径固定为:
Cloud Web admin Users page
-> PATCH /v1/admin/billing/users/{userId}/status
-> hwlab-cloud-api admin session check
-> hwlab-user-billing POST /internal/admin/users/status
-> PK01 hwlab_users.status
公网 PATCH /v1/admin/billing/users/{userId}/status 必须要求 Web admin session。未登录或非 admin 请求返回 auth_required/forbidden,不能因为知道 user id 而直通 internal route。/internal/admin/users/status 只面向集群内部 admin boundary,不能作为公网 API。
被禁用用户必须在 user-billing introspection 层被阻断。API key 和 session 查询都必须带 hwlab_users.status='active' 条件;Cloud API、AgentRun runner、Code Agent、AIPOD 和 HWPOD 不能缓存或复用被禁用用户的旧 principal 绕过状态检查。
计费交易
token/credit 计价遵循 reservation/record 分层:消耗型操作先通过 user-billing preflight/reservation 确认余额和计价上下文,再在操作完成或失败时记录 usage/release。Cloud API 可以保存业务 trace、agent session 和运行证据,但不能把这些派生记录当成余额账本。
plan/entitlement 是 user-billing 的资源授权 authority。hwlab_credit_accounts.plan_id 必须指向 PK01 中的 plan;hwlab_resource_entitlements 按 resource_type 表达服务是否启用、月度 quota、并发 reservation 上限和 RPM 上限。0 代表 unlimited,禁用必须通过 enabled=false 或 plan 状态表达,不能靠缺行或硬编码默认值猜测。code_agent、aipod、hwpod 是 v0.3 多用户云服务的基础资源类型,新增资源类型必须进入同一 plan/entitlement 模型。
/internal/billing/preflight 必须在余额预留前执行 entitlement、monthly quota、active reservation concurrency 和 RPM 检查。RPM 与 quota 的权威统计来自 PK01 PostgreSQL reservation/usage 记录;Redis 只能作为后续 cache 或短期加速层,不能成为限流、余额、quota 或授权的唯一来源。preflight 成功后才创建 reservation;running 阶段只保留 reservation,不提前扣费;completed 记录 usage/debit;failed、blocked、timeout、canceled 等未完成状态 release reservation。
新增 AIPOD/HWPOD 云托管产品时,产品维度、资源 id、reservation id、usage amount 和状态变迁应进入 user-billing 的 PK01 表结构或迁移;不要在 cloud-api 内新增平行计费表作为第二账本。
Secret 与 Bootstrap
bootstrap admin、internal token、数据库连接串和 API key sourceRef 都必须通过受控 Secret 同步入口注入。排障时只能输出 SecretRef 名称、key 名、presence、fingerprint、字节数或 redacted prefix;不得从 runtime Kubernetes Secret 反解、回填或记录真实凭据。
Web admin 登录和按钮级 smoke 依赖 bootstrap admin sourceRef 存在。若 runtime Secret object 存在但本地 sourceRef 缺失,应修复 sourceRef 或上游 Secret 生成入口,再重新 secret-sync;不要把 runtime Secret 解码成文档、issue 或本地 env 文件。
验收要点
v0.3 多用户与计费验收至少包含:
GET /health/live与GET /health/ready证明服务无状态、PK01 PostgreSQL 权威和 Redis cache-only。- 普通用户可注册/登录并读取自己的
billing/summary,响应不包含 password hash、session token 原文、API key 原文或数据库连接串。 - admin Web session 可读取
/v1/admin/billing/summary,并通过/v1/admin/billing/users/{userId}/status禁用/启用用户。 - disabled 用户的 session/API key introspection 失败,不能继续发起 Code Agent、AIPOD、HWPOD 或余额消耗。
- Code Agent 计费 preflight/record 与 agent session owner 一致,usage 写入 PK01 user-billing ledger。