# 控制台应用接入 单管理员在「应用接入」页面创建应用、初始队列与 SDK 凭据,查看环境、队列、权限和有效期,平滑换证,复制或下载 `.env` 配置。数据库只保存 Token 摘要:完整 Token 仅在新建或轮换时交付,列表和详情不能反查旧秘密。 ## 1. 启用和使用 部署配置指定唯一有跨应用接入管理权限的控制台登录名: ```sh export ORBIT_CONSOLE_APPLICATION_ADMIN=admin ``` 该账号必须已经通过 bootstrap 或 console-user create 创建。配置为空时所有应用接入管理请求返回 403,不会自动提升已有账号;多节点使用相同配置。继续使用单管理员,不引入角色管理系统。现有控制台账号与会话的绑定凭据仍须有效;到期前可在本页轮换。轮换 SDK Token 不改变浏览器独立会话秘密。 本地 Compose 已为 `admin` 配置该入口,访问 `http://127.0.0.1:18080/console/#/applications`。 1. 点击「新建应用」,填写应用名称、环境、命名空间、初始队列和操作原因。 2. 选择 Worker、结果订阅、定时、流程等需要的能力及有效期。基础权限包含任务提交/查询/取消、队列读取/管理。 3. 创建成功后复制或下载完整 `.env`,交给该应用的服务端配置。默认地址使用当前页面来源,详情中可改为容器地址或部署域名。 4. 已接入应用可以随时查看元数据和配置模板。模板中的 Token 是占位值,必须替换成已经保存的原 Token。 5. 「平滑换证」保留 application_id、namespace_id、credential_id、队列、任务和订阅;新 Token 立即生效,旧 Token 在配置的过渡期内继续使用(页面默认 7 天,支持 1/7/30 天),便于逐台更新配置。详情展示旧 Token 实际截止,全部服务切换后可点「结束过渡」。 6. 默认「长期有效」,不需要每月人工换证;已有凭据可点「调整有效期」直接设为长期,原 Token 保持不变。 环境与命名空间形成隔离边界。不同应用应分别创建;同一应用的多个命名空间在列表中分别展示。页面支持新建应用及其初始队列;业务列表可通过应用筛选栏切换范围,分别展示各应用数据。未提供应用删除、身份迁移或现有应用新增命名空间的表单;已有 CLI 的 `--application-id` 仍可增加命名空间,队列 SDK 可增加同范围队列。 ## 2. 路由与认证 这些是浏览器管理端接口,不属于业务 SDK。只接受有效的 `orbit_console_session` HttpOnly Cookie,并在数据库事务中重新核验部署指定的管理员账号和会话;即使 SDK 凭据拥有全部业务权限也不能访问。 | 方法与路径 | 用途 | | --- | --- | | `GET /console/applications?after=` | 按命名空间 ID 升序读取 50 条接入范围,返回 `items`、可选 `next`;`after` 为排他起点 | | `GET /console/applications/{namespace_id}` | 应用/环境详情、最多 100 个队列和 100 张脱敏凭据;超出返回 `truncated=true` | | `POST /console/applications/prepare` | 校验意图,生成固定操作 ID、资源 ID、Token、绝对到期时间;不创建资源、不轮换秘密 | | `POST /console/applications/apply` | 提交准备结果,原样重报返回原脱敏回执 | POST 必须有 `Content-Type: application/json` 和 `X-Orbit-Console: 1`;浏览器 Origin 必须匹配当前主机,拒绝跨站 Fetch Metadata,不提供跨域授权。响应禁止缓存,成功信封为 `{"data": ...}`。未知字段、重复 JSON 键、显式 null 和错误类型被拒绝,正文上限 512 KiB。 ## 3. 新建应用 prepare 请求: ```json { "kind": "CREATE", "application": "order-service", "namespace": "default", "environment": "test", "queue": "orders", "capabilities": ["worker", "events", "schedules", "workflows"], "expected_revision": "0", "valid_days": 0, "reason": "接入订单服务" } ``` 名称以字母或数字开头,后续只允许字母、数字、`_ . : -`,environment 最长 32,其余最长 128。valid_days 为 0–365 的整数,默认 0 表示长期有效;reason 非空、最多 1024 个 Unicode 字符,不含换行或 NUL。capabilities 可选 `worker`、`events`、`schedules`、`workflows`、`recovery`、`resources`,不可重复。新建不传 namespace_id / credential_id,expected_revision 省略或为字符串 `"0"`。 prepare 响应 data 为固定操作对象: ```json { "version": 2, "input": {"kind":"CREATE","application":"order-service","namespace":"default","environment":"test","queue":"orders","capabilities":["worker","events"],"expected_revision":"0","valid_days":0,"reason":"接入订单服务"}, "operation_id": "11111111111111111111111111111111", "application_id": "22222222222222222222222222222222", "namespace_id": "33333333333333333333333333333333", "queue_id": "44444444444444444444444444444444", "credential_id": "55555555555555555555555555555555", "token": "服务端生成的完整 Token" } ``` 以上是结构示意,ID、令牌及时间以服务端返回为准。将 **data 整体原样** POST 到 apply,不包 `data` 外层。应用、额度、命名空间、队列、凭据摘要、审计和幂等回执在同一事务提交。初始队列并发 4、开始速率 10/秒,沿用 bootstrap 默认策略;凭据队列范围为新命名空间的全部队列。重名应用返回 409,不覆盖原资源。 ## 4. 平滑换证 prepare 请求: ```json { "kind": "ROTATE", "namespace_id": "33333333333333333333333333333333", "credential_id": "55555555555555555555555555555555", "expected_revision": "1", "valid_days": 0, "grace_days": 7, "reason": "更新接入凭据" } ``` expected_revision 为读取到的字符串版本。只允许上述轮换字段,不混入新应用名称或能力组。准备对象包含原 application_id / namespace_id / credential_id,没有 queue_id。apply 复用原有凭据轮换事务:将原摘要保留到固定过渡截止,替换当前摘要与可选到期时间,版本加一,保存脱敏回执及人类账号审计;权限组不改变。已撤销的凭据禁止变更。ROTATE 的 grace_days 范围 0–30,API 省略/0 保持立即停用旧 Token 的兼容语义,页面显式提交 7;实际截止不超过旧 Token 原到期时间。过渡未结束时再次轮换返回 409。 页面在过渡期将按钮标为「过渡中 · 暂不可换证」,同时显示原因、实际截止和切换步骤。这表示上一轮换证已生效;再次轮换会挤掉仍在使用的旧 Token,所以暂时禁止。将已保存的新 Token 配置到所有服务、Worker 和结果消费者,并收尾在途任务。到期后页面刷新会恢复换证按钮;只有确认全部切换完成,才可提前点「结束过渡,停用旧 Token」。结束过渡会立即停用旧 Token,不能仅为解锁按钮而操作。已撤销凭据单独显示「已撤销 · 不可换证」。 apply 成功 data: ```json { "operation_id": "11111111111111111111111111111111", "application_id": "22222222222222222222222222222222", "namespace_id": "33333333333333333333333333333333", "credential_id": "55555555555555555555555555555555", "revision": "2", "deduplicated": false } ``` ## 5. 调整有效期与结束过渡 prepare 输入示例: ```json { "kind": "SET_EXPIRY", "namespace_id": "33333333333333333333333333333333", "credential_id": "55555555555555555555555555555555", "expected_revision": "2", "valid_days": 0, "reason": "服务凭据设置为长期有效" } ``` SET_EXPIRY 不生成新 Token,只更新当前有效期;valid_days=0 为长期,1–365 为从准备时间计算的天数。FINALIZE 使用相同身份/版本字段,kind 改为 FINALIZE,valid_days 必须为 0,用于提前停用旧 Token。两者均禁止 grace_days 和新建字段,prepare 不返回 token;FINALIZE 也不返回 expires_at。apply 使用完整原对象,具有相同的并发版本、幂等和审计约束。 新版 prepare 对象带 version=2;expires_at 为空时**省略字段**,不要传显式 null。ROTATE 有过渡期时另外包含固定 previous_valid_until;详情中的 previous_valid_until 是受旧到期时间约束后的实际截止,未设置时省略。详情/回执不会返回旧秘密。历史不带 version 的固定操作仍按原语义重放。 完整滚动更新及 SDK 客户端生命周期说明见[凭据手册](authentication.md)。更换配置不会自动刷新已创建的客户端,须在过渡截止前完成重建或逐台重启并排空在途任务。 ## 6. 超时、重复和审计 - 页面提交前把整个固定操作保留在当前内存;请求超时或结果未知时,按钮变成「重试确认」,重用同一份内容。不能再次 prepare 来代替核对。 - 页面允许「保存待核对操作」下载私密 JSON;含真实 Token,应放到受限目录。恢复时登录同一管理员后,向 apply 发送该文件正文。不要把 Cookie 或操作文件提交 Git,也不要放到 URL。 - 关闭/刷新页面会丢失内存中的 Token,页面会提醒先保存。若新建已经成功、交付内容未保存,可从应用列表重新生成同一凭据的 Token;不要再次创建同名应用。 - 原操作返回的回执是历史快照,可能已被后续轮换替代。页面会重新读取当前凭据版本后才展示配置。 - 管理审计主体是 `console:`;正文只有权限、资源 ID、到期时间等元数据。列表、审计、幂等回执和业务记录都不保存秘密原文。 - 当前管理员退出、会话过期或账号停用后不能重放管理操作。SDK Token 撤销/到期与控制台登录资格沿用既有账号绑定约束。 | 错误 | HTTP | 处理 | | --- | --- | --- | | UNAUTHENTICATED | 401 | 登录有效控制台账号 | | PERMISSION_DENIED | 403 | 核对唯一管理员配置、会话及同源请求 | | INVALID_ARGUMENT | 400 | 核对字段、能力组、固定身份及有效期 | | NOT_FOUND | 404 | 核对命名空间/凭据是否存在 | | STATE_CONFLICT | 409 | 应用名称已存在、凭据已撤销、版本已变更或旧 Token 仍在过渡期;读取当前状态 | | IDEMPOTENCY_CONFLICT | 409 | 原操作内容被修改,保留原始操作核对 | | 数据库/网络故障 | 5xx / 网络错误 | 不假定失败,保留原操作重报 | 可重复运行的真实 HTTP 场景见 [test-console-applications.py](../../scripts/test-console-applications.py),标准容器入口 `make console-e2e` 同时验证此链路。基础 SDK 使用方式见 [SDK 接入](../sdk/README.md)。 业务数据的应用筛选、队列分页及会话隔离见[应用范围接口](console-scope.md)。