# API Overview / API 总览 ## 中文 ### 页面作用 本页描述 `accounts.svc.plus` 当前 HTTP 面的总边界: - 路由族如何划分。 - 每组路由由哪些 `api/*.go` 文件拥有。 - 认证链路如何叠加。 - 成功与失败响应的公共形状是什么。 参数、返回体字段和逐接口依赖关系请继续阅读: - [认证与鉴权](auth.md) - [接口矩阵](endpoints.md) - [错误约定](errors.md) ### 基础路由族 | 路由族 | 典型路径 | 主要 owner file | 说明 | | --- | --- | --- | --- | | 健康与版本 | `GET /healthz` `GET /api/ping` | `api/api.go` | 活性检查与运行时镜像版本信息。 | | 公共认证入口 | `/api/auth/register` `/api/auth/login` `/api/auth/oauth/*` | `api/api.go` | 注册、登录、邮箱校验、OAuth 跳转、JWT refresh。 | | 会话保护认证面 | `/api/auth/session` `/api/auth/xworkmate/*` `/api/auth/subscriptions` | `api/api.go` `api/xworkmate.go` `api/config_sync.go` `api/stripe.go` | 以 session token 为主路径的控制面接口。 | | Auth 作用域下的管理员接口 | `/api/auth/admin/*` | `api/admin_users_metrics.go` `api/admin_users.go` `api/admin_sandbox.go` `api/admin_assume.go` `api/homepage_video.go` | 给 dashboard / BFF 使用的管理员接口。 | | 公共 `/api/admin/*` 管理面 | `/api/admin/users/metrics` `/api/admin/traffic/*` | `api/admin_users_metrics.go` `api/admin_agents.go` `api/accounting.go` | 与前端约定的管理员根路径。 | | 内部服务接口 | `/api/internal/*` | `api/internal_public_overview.go` `api/internal_sandbox_guest.go` `api/internal_network_identities.go` `api/accounting.go` | 仅供受信任服务调用,走 internal service token。 | | Agent 控制接口 | `/api/agent-server/v1/*` | `api/agent_server.go` `api/user_agents.go` | 给 agent 或用户控制台提供节点与客户端视图。 | | 账户读面 | `/api/account/*` | `api/accounting.go` | 使用量、账单、策略快照读取。 | | Legacy alias | `/api/agent/nodes` | `api/user_agents.go` | 旧路径别名,规范路径是 `/api/agent-server/v1/nodes`。 | ### 认证模型 #### 1. Session first 当前控制面的主事实来源是 API 进程内 session store: - 登录、邮箱验证成功、密码重置确认成功、OAuth callback 都会签发 session token。 - token 同时通过响应体字段 `token` 返回,并通过 `xc_session` cookie 下发。 - 多数业务 handler 最终都调用 `handler.lookupSession` / `handler.requireAuthenticatedUser` 做真实鉴权。 #### 2. Optional JWT middleware `RegisterRoutes` 只在 `tokenService != nil` 时给 `/api/auth` 的保护组和 `/api/admin` 组叠加: - `auth.TokenService.AuthMiddleware()` - `auth.RequireActiveUser(h.store)` 因此真实行为是: - 当 `auth.enable` 关闭时,业务仍按 session 主路径工作。 - 当 `auth.enable` 打开时,部分路由会先经过 JWT middleware,然后在 handler 内继续读取 session。 - 这就是为什么文档统一把当前模式描述为“session-first, JWT-optional”。 #### 3. Internal service token `/api/internal/*` 统一使用 `auth.InternalAuthMiddleware()`: - 读取 `Authorization: Bearer ` - 与环境变量 `INTERNAL_SERVICE_TOKEN` 比较 - 失败时直接返回简化错误 JSON #### 4. Agent token `/api/agent-server/v1/users` 与 `/api/agent-server/v1/status` 走 `agentserver.Registry.Authenticate`: - 读取 `Authorization: Bearer ` - 允许共享 token + `X-Agent-ID` / `agentId` 解析具体节点身份 - 认证成功后进入 `Registry` 与 `store.NodeHealthSnapshot` 更新链路 ### 响应约定 | 类别 | 典型形状 | 说明 | | --- | --- | --- | | 通用成功 | `{"message": "...", ...}` 或领域对象 JSON | 大多数 handler 直接输出业务对象,不包统一 envelope。 | | 会话成功 | `{"token": "...", "expiresAt": "...", "user": {...}}` | 登录、邮箱验证、密码重置确认、MFA 完成等都会返回 session 信息。 | | 通用失败 | `{"error":"code","message":"..."}` | 由 `respondError` 统一组装,是最常见错误形状。 | | 简化失败 | `{"error":"..."}` | 多见于 agent/internal/simple GORM handlers。 | | Agent DTO | `agentproto.ClientListResponse`、`204 No Content` | `/users` 返回结构化 DTO,`/status` 成功时无响应体。 | ### 关键 handler owner map | 文件 | 负责的接口面 | | --- | --- | | `api/api.go` | 注册、登录、session、OAuth、MFA、订阅、权限矩阵、`/healthz`、`/api/ping`。 | | `api/xworkmate.go` | XWorkmate profile、secret locator、Vault-backed secret 读写、tenant bootstrap。 | | `api/config_sync.go` | `/api/auth/sync/config` 与 `/api/auth/sync/ack`。 | | `api/stripe.go` | Stripe checkout、portal、webhook。 | | `api/admin_users_metrics.go` | `/api/admin/*` 路由注册、用户指标权限控制。 | | `api/admin_users.go` | 创建用户、暂停/恢复、删除、renew uuid、黑名单。 | | `api/admin_agents.go` | 管理面 agent 状态聚合。 | | `api/accounting.go` | `/api/account/*`、`/api/admin/traffic/*`、内部策略与心跳。 | | `api/agent_server.go` | Agent 拉取 client 列表、上报状态。 | | `api/user_agents.go` | 用户/控制台读取节点列表,含 sandbox 特判。 | | `api/homepage_video.go` | 公共首页视频与管理员首页视频配置。 | | `api/admin_sandbox.go` | Sandbox binding 读写。 | | `api/admin_assume.go` | Root 假扮 sandbox 会话。 | | `api/internal_*` | 内部 public overview、sandbox guest、network identities。 | ### 当前实现注意点 1. `/api/auth/password/reset` 与 `/api/auth/password/reset/confirm` 被挂在 authProtected 组下,但核心业务逻辑本身仍是邮箱 / token 驱动;启用 JWT middleware 后会多一层前置校验。 2. `/api/auth/sandbox/binding` 既接受正常会话,也接受内部服务 token,因为 Console Guest/Demo 需要在无本地浏览器状态时读取绑定信息。 3. `/api/agent-server/v1/nodes` 没有挂在 token middleware 下,而是在 handler 内自行解析 session 或内部服务身份。 4. `/api/ping` 的 `version`、`commit`、`tag` 来自运行时 `IMAGE` 环境变量解析结果,而不是 Git 本地状态。 ## English ### What This Page Covers This page defines the current HTTP surface of `accounts.svc.plus`: - how route families are split, - which `api/*.go` files own them, - how authentication layers stack, - and what the shared success / error shapes look like. For endpoint-level parameters, response fields, and dependency wiring, continue with: - [Authentication](auth.md) - [Endpoint Matrix](endpoints.md) - [Error Conventions](errors.md) ### Route Families | Route family | Example paths | Main owner files | Purpose | | --- | --- | --- | --- | | Health and version | `GET /healthz`, `GET /api/ping` | `api/api.go` | Liveness and runtime image-derived version metadata. | | Public auth entrypoints | `/api/auth/register`, `/api/auth/login`, `/api/auth/oauth/*` | `api/api.go` | Registration, login, email verification, OAuth redirects, JWT refresh. | | Session-protected auth surface | `/api/auth/session`, `/api/auth/xworkmate/*`, `/api/auth/subscriptions` | `api/api.go`, `api/xworkmate.go`, `api/config_sync.go`, `api/stripe.go` | Primary control-plane APIs built around session tokens. | | Auth-scoped admin APIs | `/api/auth/admin/*` | `api/admin_users_metrics.go`, `api/admin_users.go`, `api/admin_sandbox.go`, `api/admin_assume.go`, `api/homepage_video.go` | Admin APIs used by the dashboard / BFF. | | Public `/api/admin/*` admin root | `/api/admin/users/metrics`, `/api/admin/traffic/*` | `api/admin_users_metrics.go`, `api/admin_agents.go`, `api/accounting.go` | Frontend-facing admin root path. | | Internal service APIs | `/api/internal/*` | `api/internal_public_overview.go`, `api/internal_sandbox_guest.go`, `api/internal_network_identities.go`, `api/accounting.go` | Trusted service-to-service APIs protected by the internal service token. | | Agent control APIs | `/api/agent-server/v1/*` | `api/agent_server.go`, `api/user_agents.go` | Node and client views for agents and the control console. | | Account read models | `/api/account/*` | `api/accounting.go` | Usage, billing, and policy snapshot reads. | | Legacy alias | `/api/agent/nodes` | `api/user_agents.go` | Backward-compatible alias for `/api/agent-server/v1/nodes`. | ### Authentication Model #### 1. Session-first The primary control-plane fact source is the process-local session store: - login, email verification success, password reset confirmation, and OAuth callback all issue a session token, - the token is returned in the body as `token` and also set as the `xc_session` cookie, - most business handlers ultimately call `handler.lookupSession` or `handler.requireAuthenticatedUser`. #### 2. Optional JWT middleware `RegisterRoutes` adds these middlewares to the protected `/api/auth` group and the `/api/admin` root only when `tokenService != nil`: - `auth.TokenService.AuthMiddleware()` - `auth.RequireActiveUser(h.store)` So the actual runtime behavior is: - when `auth.enable` is off, business routes still work through the session-centric path, - when `auth.enable` is on, some routes first pass JWT middleware and then still load the session in the handler, - which is why the current system should be described as session-first and JWT-optional. #### 3. Internal service token `/api/internal/*` is guarded by `auth.InternalAuthMiddleware()`: - it reads `Authorization: Bearer `, - compares it to `INTERNAL_SERVICE_TOKEN`, - and returns simplified JSON errors on failure. #### 4. Agent token `/api/agent-server/v1/users` and `/api/agent-server/v1/status` authenticate through `agentserver.Registry.Authenticate`: - they read `Authorization: Bearer `, - support shared tokens plus `X-Agent-ID` / `agentId` to resolve the concrete node, - and then enter the registry and node-health persistence pipeline. ### Response Conventions | Category | Typical shape | Notes | | --- | --- | --- | | Generic success | `{"message": "...", ...}` or a domain object | Most handlers return domain JSON directly instead of a global envelope. | | Session success | `{"token": "...", "expiresAt": "...", "user": {...}}` | Returned by login, email verification, password reset confirmation, MFA completion, and similar flows. | | Standard failure | `{"error":"code","message":"..."}` | Produced by `respondError`; this is the most common error envelope. | | Simplified failure | `{"error":"..."}` | Common in internal / agent / simple GORM-backed handlers. | | Agent DTOs | `agentproto.ClientListResponse`, `204 No Content` | `/users` returns a typed DTO, while `/status` returns no body on success. | ### Handler Ownership Map | File | Owned API surface | | --- | --- | | `api/api.go` | Registration, login, session, OAuth, MFA, subscriptions, permission matrix, `/healthz`, `/api/ping`. | | `api/xworkmate.go` | XWorkmate profile, secret locator metadata, Vault-backed secret mutation, tenant bootstrap. | | `api/config_sync.go` | `/api/auth/sync/config` and `/api/auth/sync/ack`. | | `api/stripe.go` | Stripe checkout, portal, and webhook handling. | | `api/admin_users_metrics.go` | `/api/admin/*` route registration plus metrics permission guards. | | `api/admin_users.go` | User creation, pause/resume, delete, renew UUID, blacklist operations. | | `api/admin_agents.go` | Aggregated admin agent status view. | | `api/accounting.go` | `/api/account/*`, `/api/admin/traffic/*`, internal policy reads, node heartbeat ingest. | | `api/agent_server.go` | Agent client-list reads and status reports. | | `api/user_agents.go` | User / console node list reads, including sandbox-specific behavior. | | `api/homepage_video.go` | Public homepage video reads plus admin homepage video settings. | | `api/admin_sandbox.go` | Sandbox binding reads and writes. | | `api/admin_assume.go` | Root-only sandbox assume session flow. | | `api/internal_*` | Internal public overview, sandbox guest, and network identity reads. | ### Important Current Behaviors 1. `/api/auth/password/reset` and `/api/auth/password/reset/confirm` are mounted under the protected auth group even though their business logic is email / reset-token driven; enabling JWT middleware adds an extra precondition. 2. `/api/auth/sandbox/binding` accepts either a normal session or the internal service token because the Console Guest/Demo flow must read binding state without relying on browser-local state. 3. `/api/agent-server/v1/nodes` is intentionally outside token middleware and resolves sessions or trusted internal-service identity inside the handler. 4. `/api/ping` derives `version`, `commit`, and `tag` from the runtime `IMAGE` environment variable, not from local Git state.