boardx / boardx/workspacex

feat(coord-gateway): 让 coordinator 层 token 能派工,不该只有 COORD_ADMIN_TOKEN

Open
#480 0 comments 0 reactions 0 assignees View on GitHub
out-of-scope owner:coord-architecture
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.