🔴 F10 标着 passing,但没有任何真实受邀人能走完激活 —— 后端是真的,前端零生产路由、无投递
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 0
- Avg merge
- 1h 7m
- Merged PRs (30d)
- 969
Description
## 实测(`origin/main` = `75712fec`,我独立复核过,非转述)
```bash
$ git grep -c "org-invites/activate" origin/main -- apps/web
0 命中 ← 前端零调用
$ git grep -l "org-invites/activate\|activateOrgInvite" origin/main -- apps/api/src/interface
apps/api/src/interface/controllers/org-invite.controller.ts ← 后端是真的
```
三层拆开:
| 层 | 状态 |
|---|---|
| `POST /org-invites/activate` | ✅ **真的**:`@Public()`、防枚举、篡改字段只进 `org_invite_tamper_attempts` |
| 前端激活落地页 `components/org-admin/activate-screen.tsx` | ❌ **只存在于 mock 原型**。唯一入口是 `/org-admin/preview?screen=activate`(`org-admin-app.tsx:74`),吃 `ACTIVATION_CONTEXT` 假数据;**`apps/web/app/` 下没有任何接收激活 token 的生产路由** |
| 邮件投递 | ❌ `application/auth/invite-org-member.ts` 文件头**逐字写着**投递器不在本 feature 范围内、`sent_at` 为 NULL 即「还没发出去」 |
⇒ **后端能收,但没人能把 token 送到用户手上;用户就算拿到了,也没有页面可落。**
## 为什么这是「假 passing」,而且比前几例更硬
F10「组织成员邀请与激活」在 `phases/phase-01-run-a-project/feature_list.json` 里标着 **passing**。
⚠ 前几次的假 passing 是「验证脚本没真跑」(evidence 指针存在但文件不在 git 树、断言在 fixture 阶段就炸、`process.abort()` 让失败静默消失)。**这一条不同:整条用户路径从未被接通过。** 不是证据有问题,是**功能的用户可达部分根本不存在**。
`user_visible_behavior` 描述的行为(受邀人点链接 → 激活 → 入场)**今天没有任何真实用户能完成**。按完成定义第 1 条,它不该是 passing。
## 与本波次另外两条是同一形态
| 缺口 | 后端 | 前端 |
|---|---|---|
| **本条 F10** | `POST /org-invites/activate` 真的 | 零生产路由 + 无投递 |
| #363 | 成员/邀请写侧齐备 | **契约里没有列表读操作** |
| #548(`POOL_LISTING_GAP`) | 模型注册表 domain/application 齐备 | **契约里没有列表路由** |
**每一层都能通过自己的验收,链条却是断的。** 三条都已请人类批处理签核。
## 范围(建议,非定稿)
1. **前端激活落地页的生产路由** —— 接收激活 token,调真实 `POST /org-invites/activate`,复用现有 `activate-screen.tsx` 的界面但去掉 `ACTIVATION_CONTEXT` mock;
2. **邀请投递** —— 邮件通道;⚠ `invite-org-member.ts` 明确写了投递不在原 feature 范围,所以这**是新增范围**,不是补漏;
3. **F10 的 passing 状态处置** —— 由人类决定:是退回 `not_started` / 加一条 known-gap 登记,还是维持并另立本 issue 追踪。⚠ **feature 状态不能由 agent 改**(`assertSingleInProgress` 门控 + 完成定义「状态不能自己改」)。
## 验收(含反证)
- e2e:真实受邀人从**收到的链接**进入 → 激活 → 入场,刷新后仍在;
- **反证 A**:摘掉激活的服务端调用 → 必须变红;
- **反证 B**:红必须落在目标那一步**之后**,更早步骤仍绿;
- **反证 C**:防枚举 —— 不存在的 token 与已用过的 token,回显必须**逐字相同**(跟随 `org-invite.controller.ts` 现有做法,不另发明一套);
- ⚠ **令牌绝不进响应体、绝不进日志**(controller 现有注释已明确)。
## 出处与授权
由 **coord-agent-auth** 在做 #547(PR #587,登录页补「我有邀请码」入口)时挖出:补指引时必须先验「受邀人到底该去哪」,一验就发现**那条路径不存在**。
@coord-main 因 macOS 文件权限失效无法执行 `gh`,**明确授权我署名开本 issue,它事后补背书** —— 今天确立的规矩「执行者在协调者失联时可以自己登记,不必等审批」的第一次实际应用。
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with apps/api/src/interface/controllers/org-invite.controller.ts and the production web routing under apps/web/app/, then compare the mock flow in components/org-admin/activate-screen.tsx and org-admin-app.tsx:74. Read application/auth/invite-org-member.ts for the delivery boundary and phases/phase-01-run-a-project/feature_list.json for F10 status. Done means a real invited user can receive a link, activate, enter, and remain there after refresh, with the listed enumeration and token-handling checks passing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, authentication, full-stack
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100