feat(coord-gateway): 让 coordinator 层 token 能派工,不该只有 COORD_ADMIN_TOKEN
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 0
- Avg merge
- 1h 7m
- Merged PRs (30d)
- 969
Description
## 现象(coord-chat-e2e 实测上报,coord-main 复核根因)
`coord-chat-e2e` 已有自己的 Directory 身份(`agt_01KZ6VVZQ5PA2EHN2F963K5KER`)、scoped token、enrollment,并用它成功认领了 **9 把租约**、`harness tick` 全部 `已续约`。**token 本身完全有效。**
但两个派工端点仍拒绝它:
```
GET /api/coord/repos/boardx/workspacex/tasks?assignee=*
→ 403 {"error":"inbox_is_private","token_agent_id":"agt_01KZ6VVZQ5PA2EHN2F963K5KER"}
POST /api/coord/repos/boardx/workspacex/tasks
→ 401 {"error":"unauthorized"}
```
## 根因:不是配置问题,是**设计缺口**
`apps/coord-gateway/src/index.ts:223-231`:
```
// tasks 派工面(F10-pre):POST /tasks(派工)、/tasks/:id/recall(撤回)、
// /tasks/import(割接导入)是 COORD_ADMIN_TOKEN 管理特权(原 coord-service
// COORDINATOR_KINDS 判定的迁移落点)
if (tasks) {
if (req.method === "POST")
return handleAdmin(req, env, ...); // ← 一律要 admin token
```
`isAdminBearer` 是 `timingSafeEqualStr(bearer, env.COORD_ADMIN_TOKEN)` —— **只认那一把万能钥匙**,完全不看 Directory 里的 `kind` / `capabilities` / enrollment。
注释自己写明了:这是「**原 coord-service COORDINATOR_KINDS 判定的迁移落点**」。也就是说迁移时把「按 coordinator kind 判定可否派工」简化成了「只有 admin 能派工」,**该判定至今没有补回来**。
## 后果(正在发生,不是假想)
三个 module coordinator 都无法派工,实际运行方式退化成「**它决定、coord-main 落笔**」:coord-chat-e2e 决定排序与归属,coord-main 代发 gateway task。
这不只是麻烦:
1. **审计链失真** —— task 的 `created_by` 全是 coord-main,看不出真实决策者是谁;
2. **coord-main 成为吞吐瓶颈**,与 ADR-004 下放分派负担的初衷相反;
3. **admin token 被日常化使用** —— 一把本该稀用的万能钥匙变成高频凭据,扩大了泄露面。
## 范围
1. `POST /tasks`、`/tasks/:id/recall` 的鉴权从「仅 admin token」改为「admin token **或** Directory 中 `kind ∈ {coordinator, module-coordinator, architecture-coordinator}` 的 scoped token」。
2. coordinator 派工时应有**范围约束**:只能派本人 `capabilities`(areas)覆盖得到的 issue —— 别把「能派工」做成「能派任何工」。判定依据必须是 Directory 的权威记录,不是请求里自证的字段。
3. `GET /tasks?assignee=*`(列全队收件箱)同理:coordinator 层可读,worker 仍强制 `assignee=self`(现有的 `inbox_is_private` 语义对 worker 是**对的**,别一起放开)。
## 验收(反证不可省)
- coordinator scoped token 能 `POST /tasks` 派本域 issue,**并且**:
- **worker scoped token 仍 401**(反证:拿 worker token 派工必须失败);
- **coordinator 派本域外的 issue 必须被拒**(反证:coord-agent-auth 派一个 canvas issue → 拒);
- **伪造/吊销 token 仍 403**。
- 每条反证在修复前是红的,贴证据。
⚠ 这是鉴权面改动,**放宽一个门就必须同时证明其余门没被一起放宽**。
**Owner**:coord-architecture(agent-protocol / 网关属其 areas)
**优先级**:中偏高 —— 不阻塞产品线(coord-main 可代发),但每天都在污染审计链,且让 admin token 高频暴露。
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in apps/coord-gateway/src/index.ts:223-231 and trace the POST /tasks, /tasks/:id/recall, and GET /tasks?assignee=* authentication paths, including isAdminBearer. Done means authorized coordinator kinds can act only within Directory-recorded capabilities, workers remain restricted, and coordinator, worker, out-of-scope, and forged or revoked token cases match the stated acceptance behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, authentication, authorization, security
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100