背景
当前控制台(Console)的工作区只支持创建,没有任何归档/删除入口。组织随项目演推进会积累大量历史工作区,无法清理;同时,后端 admin 层已有的归档能力存在安全语义缺口。本 issue 建议补齐工作区归档(软删除)能力,并对齐 Anthropic 官方的工作区归档语义。
现状证据(代码)
1. 后端 admin 层已有归档,但仅限 admin API,且不级联
- 路由
internal/admin/handler.go:48:r.Post("/{workspace_id}/archive", h.archiveWorkspace)
- service
internal/admin/service.go:299:ArchiveWorkspace
- DB
internal/db/admin.go:396-405:ArchiveAdminWorkspace
update workspaces
set archived_at = coalesce(archived_at, now()),
updated_at = now()
where organization_id = $1 and external_id = $2
returning ...
仅对 workspaces 表设置 archived_at,没有同步处理该 workspace 下的 console_api_keys。
2. 控制台层(面向终端用户的 Console API)完全没有 workspace 归档端点
internal/platformapi/console_api_keys.go:52-57 的 console workspace 路由只有:
POST /workspaces
GET /workspaces/{workspaceId}/api_keys
POST /workspaces/{workspaceId}/api_keys
POST /workspaces/{workspaceId}/api_keys/{apiKeyId}
GET /workspaces/{workspaceId}/api_keys/policy
GET /workspaces/{workspaceId}/api_key_count
没有任何 archive / 删除端点。
3. 归档 workspace 后,其 API key 仍可查询和使用
internal/db/console_api_keys.go:329-332 的 api_key 查询只过滤 key 自身的 archived_at,不 join workspace 的 archived 状态:
from console_api_keys
...
and archived_at is null -- 这是 console_api_keys.archived_at,与 workspaces.archived_at 无关
因此:归档一个 workspace 后,该 workspace 下的 API key 仍然能被列出,鉴权路径也不感知 workspace 已归档——归档形同虚设。
4. 前端工作区设置页没有归档入口
web/src/features/settings/WorkspacesSettingsPage.tsx:160-169 的 Actions 列只有两个链接:
<ButtonLink variant="outline" size="sm" href={workspaceApiKeysPath(workspace.id)}>API keys</ButtonLink>
<ButtonLink variant="ghost" size="sm" href={workspaceWebhooksPath(workspace.id)}>Webhooks</ButtonLink>
没有归档/删除操作。
5. 项目已有 default workspace 机制
internal/admin/service.go:847,938 使用 s.cfg.DefaultWorkspaceExternalID 标识默认工作区,internal/platformapi/platform_bootstrap_builders.go:122 有 IsDefault bool 字段。归档时应排除默认工作区。
Anthropic 官方文档依据
来源:Workspaces – Claude Platform Docs、Archive Workspace – Claude API Reference。
归档语义(原文):
Archiving:
- Preserves historical data for reporting
- Deactivates the workspace and all associated API keys
- Cannot be undone
Archiving a workspace immediately revokes all API keys in that workspace. This action cannot be undone.
默认工作区不可归档(原文):
Every organization has a Default Workspace that cannot be renamed, archived, or deleted. The Default Workspace has no ID and doesn't appear in list endpoints.
权限边界(原文):
Only organization admins can create workspaces. Workspaces themselves and organization members are managed at the organization level through the Admin API, which requires an Admin API key (sk-ant-admin…).
端点(原文):
POST /v1/organizations/workspaces/{workspace_id}/archive (x-api-key: Admin API key)
→ 返回 Workspace 对象(含 archived_at,RFC 3339;未归档为 null)
现状与官方语义的差距
| 维度 |
Anthropic 官方 |
当前实现 |
差距 |
| 删除语义 |
软删除、不可逆 |
已有 archived_at 软删除 |
✅ 对齐 |
| 归档级联 |
立即吊销该 workspace 所有 API key |
归档只盖 workspaces.archived_at,不碰 key;key 查询/鉴权不感知 workspace 归档 |
❌ 安全缺口 |
| 默认工作区 |
不可归档 |
有 DefaultWorkspaceExternalID 配置,但归档未排除 |
⚠️ 缺保护 |
| 权限边界 |
org admin 级(Admin API key) |
admin 层归档已存在且分层正确,但 console / 前端无入口 |
⚠️ 缺入口 |
| 端点 |
POST .../workspaces/{id}/archive |
admin 层已有;console 层缺失 |
⚠️ 缺 console 端点 |
建议的修复方向(概要)
- 在 console 层补
POST /workspaces/{id}/archive(面向 Console 用户),鉴权要求 org admin。
- 归档时级联吊销该 workspace 下所有
console_api_keys(设 archived_at = now()),对齐官方「立即吊销所有 API key」。
- 禁止归档默认工作区(
DefaultWorkspaceExternalID)与当前激活工作区(防自锁)。
- 前端
WorkspacesSettingsPage 的 Actions 列改为 DropdownMenu,加「归档」项 + 破坏性确认 AlertDialog(参考 WorkspaceApiKeysPage 的删除=归档范本)。
- 同步设计文档与测试。
详细的方案、改动清单、验证计划与待拍板的决策点见下方讨论 comment。
背景
当前控制台(Console)的工作区只支持创建,没有任何归档/删除入口。组织随项目演推进会积累大量历史工作区,无法清理;同时,后端 admin 层已有的归档能力存在安全语义缺口。本 issue 建议补齐工作区归档(软删除)能力,并对齐 Anthropic 官方的工作区归档语义。
现状证据(代码)
1. 后端 admin 层已有归档,但仅限 admin API,且不级联
internal/admin/handler.go:48:r.Post("/{workspace_id}/archive", h.archiveWorkspace)internal/admin/service.go:299:ArchiveWorkspaceinternal/db/admin.go:396-405:ArchiveAdminWorkspace仅对
workspaces表设置archived_at,没有同步处理该 workspace 下的console_api_keys。2. 控制台层(面向终端用户的 Console API)完全没有 workspace 归档端点
internal/platformapi/console_api_keys.go:52-57的 console workspace 路由只有:没有任何
archive/ 删除端点。3. 归档 workspace 后,其 API key 仍可查询和使用
internal/db/console_api_keys.go:329-332的 api_key 查询只过滤 key 自身的archived_at,不 join workspace 的 archived 状态:因此:归档一个 workspace 后,该 workspace 下的 API key 仍然能被列出,鉴权路径也不感知 workspace 已归档——归档形同虚设。
4. 前端工作区设置页没有归档入口
web/src/features/settings/WorkspacesSettingsPage.tsx:160-169的 Actions 列只有两个链接:没有归档/删除操作。
5. 项目已有 default workspace 机制
internal/admin/service.go:847,938使用s.cfg.DefaultWorkspaceExternalID标识默认工作区,internal/platformapi/platform_bootstrap_builders.go:122有IsDefault bool字段。归档时应排除默认工作区。Anthropic 官方文档依据
来源:Workspaces – Claude Platform Docs、Archive Workspace – Claude API Reference。
归档语义(原文):
默认工作区不可归档(原文):
权限边界(原文):
端点(原文):
现状与官方语义的差距
archived_at软删除workspaces.archived_at,不碰 key;key 查询/鉴权不感知 workspace 归档DefaultWorkspaceExternalID配置,但归档未排除POST .../workspaces/{id}/archive建议的修复方向(概要)
POST /workspaces/{id}/archive(面向 Console 用户),鉴权要求 org admin。console_api_keys(设archived_at = now()),对齐官方「立即吊销所有 API key」。DefaultWorkspaceExternalID)与当前激活工作区(防自锁)。WorkspacesSettingsPage的 Actions 列改为 DropdownMenu,加「归档」项 + 破坏性确认 AlertDialog(参考WorkspaceApiKeysPage的删除=归档范本)。详细的方案、改动清单、验证计划与待拍板的决策点见下方讨论 comment。