# I00 邀请边界独立复审

复审日期：2026-10-03。复审员独立于邀请领域作者，仅阅读业务代码，并在隔离 PostgreSQL 与临时 Go 测试 overlay 中复现边界。业务修复由主 Agent 或领域作者完成。

当前结论：发现的 2 项 P2 集成问题均已由主 Agent 修复并独立复验闭环；本轮未发现尚未关闭的 P1/P2。问题分别为手动绑定遗漏可信 IP、已有账号后续设备漏参与同设备判断。邀请领域的并发预留、规则快照、证据权限、奖励事务重放与这两项修复通过本轮限定范围验证；本结论不表示已具备真实观看自动发奖的上线条件。

## 范围与验证依据

读审 `services/platform/src/referral.mjs`、`migrations/005-referral.sql`、邀请领域/认证/HTTP 测试与 `REFERRALS.md`，并交叉检查 `auth.mjs`、`server.mjs`、`runtime.mjs`、`platform.mjs`、Go 公共邀请路由/消费者桥接、E00 `creditReward`。

- 独立重跑修复后的测试：Node **25/25**，包括领域 15、官方认证 hook 5、运行时 HTTP 5；Go 公共邀请路由 1 项及独立伪造 IP overlay 通过。
- 补充真实 PostgreSQL 9 组检查：注册时限精确边界、可信 IP 风险、App/撤销/Web 重播设备、真实 E00 issuer/能力修订/安装撤销、发奖准备后终态、活动关闭后迟发奖励、数据库确认事务失败后 30 并发重放。
- 另用真实官方 OTP/运行时/PG 验证已有账号登录设备观察、原注册时间不变、同设备拒绑与独立设备可绑定。
- Go 使用临时 overlay 增加断言，不编辑原业务源码。修复前四个公共邀请命令的可信 IP 均为空；修复后加入伪造 IP 头仍只传实际 socket IP。
- 数据库由现有 helper 创建 PostgreSQL 18 的独立 RAM 容器、随机本机端口，所有测试在 finally 关闭自有连接与容器。未连接生产数据库、未发送外部邮件、未获取真实上游视频。

复现脚本与完整日志保存在 `work/existing-project/i00-independent-*`，用于开发核对，不属于生产组件。

## P2-01：手动绑定丢失同 IP 风险（已修复，独立复验闭环）

修复前，Go 登录代理会从实际请求 socket 提供可信 IP，但 `consumerPlatform.call` 在公共邀请接口转内部命令时只携带 Bridge、Cookie 与 Authorization。Node 邀请入口将缺失的可信 IP 处理为 `null`，从而绕过 `bindReferral` 的 `shared_ip` 风险记录。

复现：同 IP、不同已验证设备的两个账号，在注册时未填邀请码，随后调用公共手动绑定。只读 Go overlay 观测四个邀请命令的 IP 头为空；真实 PG 以相同缺失上下文执行绑定，记录无 `shared_ip`，合格证据后 worker 可自动批准。以实际可信 IP 重复相同流程则记录 `shared_ip`，worker 批准被 `admin_review_required` 拒绝。

修复：主 Agent 修改 Go internal call，仅从 `original.RemoteAddr` 解析并验证 IP，设置 `X-Dramivio-Client-IP`。不转发客户端同名头、Forwarded 或 Real-IP。

独立回归：原红测试变绿；客户端伪造 `X-Dramivio-Client-IP=203.0.113.77`、`X-Forwarded-For=203.0.113.78`、`X-Real-IP=203.0.113.79` 时，内部后端仍收到实际 socket `192.168.1.10`。真实 PG 的同 IP 风险与管理员复核要求保持生效。尚不把此拆分验证描述为一次完整浏览器/Go/PG 联调。

## P2-02：已有账号后续设备漏参与同设备判断（已修复，独立复验闭环）

修复前 `bindReferral` 只对比 `referral_user_device`。该表在注册与邀请接口中追加设备；官方认证 hook 仅在新建用户时运行。已有账号在另一设备登录并实际使用 E00 App 安装会话/媒体交付，并不一定触发任何邀请接口，因此这台已被服务器识别的设备不在 I00 设备历史中。

真实 PG 复现步骤：

1. 邀请人 A 在 D1 注册并取得邀请码。
2. A 在 D2 获得真实 E00 `approvedInstallationSession`，完成目录映射、reserve、preflight 与 committed 授权。
3. 新账号 B 在同一服务器识别的 D2 注册，用 A 的旧邀请码绑定。
4. 数据库确认 A 的 E00 安装记录包含 D2；实际 `bindReferral` 返回 `bound`，预期为 `skipped/same_device`。

影响：同设备防刷仅覆盖 I00 已见设备，漏掉其他已可信观察到的安装/交付设备；旧码可绕过该限制。未声称签名浏览器 cookie 能识别真实物理设备，复现针对系统内已有的同一可信设备标识。

已将证据交给主 Agent，由其复用可信 E00 设备历史并补齐既有认证生命周期的设备观察。业务未由本复审员修改。

主 Agent 已将双方可信设备集合扩展为 I00 已见设备、E00 App 安装、解锁及 committed reservation；保持原双方 owner 锁，没有新增指纹或锁体系。独立复验：原 App 安装/交付路径拒绝，撤销的安装历史仍拒绝，独立 D3 正常绑定。另补 Web 同集当天 D1→D2 重播：E00 复用 D1 解锁，仅 committed reservation 保存 D2；该变体先复现漏判，扩展集合后也拒绝同 D2 绑定。

再补实际认证变体：A 在 D1 注册取旧码，在 D2 通过官方 OTP 登录原账号，不播放且不打开邀请页；随后 B 在同 D2 注册填旧码。修复前真实 Better Auth/runtime/PG HTTP 验证 A 的 I00 D2 观察为 0，B 建立 `observed` 关系。各步骤使用不同可信 IP，未依赖 IP 缺失；设备来自受信网关上下文替身，未伪造框架用户 ID。

主 Agent 增加成熟 Better Auth 官方 `hooks.after`，仅在 `sign-in/email-otp` 的真实已验证 `newSession.user` 存在时调用 `onVerifiedSignIn` 追加设备观察；该观察不接收邀请码、不改框架注册时间、不重新归因。独立原步骤复验：A 的 D2 观察为 1，B 注册时无邀请关系，手动绑定返回 `same_device`；A 原 `registered_at` 保持不变，独立设备新账号仍正常建立 `observed` 关系。对应证据为 `i00-existing-login-device.log`（修前）及 `i00-existing-login-device-fixed.log`（修后）。

## 已验证边界

| 边界 | 本轮证据与结论 |
| --- | --- |
| 绑定一次、自邀、循环 | 原有真实 PG 测试重复 100 并发，同 invitee 一个关系与一次预留；变更邀请人拒绝，自邀与循环拒绝。 |
| 注册窗口 | 独立验证恰满 24 小时拒绝，期限内 1 毫秒可绑定；HTTP 重登录不会刷新框架注册时间。 |
| 首次可信合格观看 | 可信证明在绑定前记录会拒绝绑定；迟到的绑定前证明撤销尚未批准的关系。H00 位置、离线声明和无权 actor 不能代替证明。 |
| 同 IP | 可绑定但必须风险复核；可信 IP 传递缺口见 P2-01。单 IP 不直接拒绝正常共享网络用户。 |
| 同设备 | 已见注册/登录设备、可信 E00 安装/解锁/committed 重播设备共同判断；App、撤销历史、Web 重播及已有账号纯登录变体已独立闭环。 |
| 活动快照 | 关闭活动/新规则仅影响新绑定；原承诺的 required/reward/TTL 与名额继续保持。独立验证关闭后 75 小时发奖，仍按原 4 集快照。 |
| 日/月名额与余额预留 | 原有真实 PG 100 不同 invitee 并发，不超过日/月与未到期余额加 held 承诺上限；相同稳定事件已入 E00 时不重复计承诺。 |
| 可信交付授权 | 独立验证 wrong issuer、capability revision 改变、前台区间跨真实安装撤销均失败关闭，未增加合格集。 |
| 去重与墙钟 | 同 UUID/证据/同集不重复；跨已记录集墙钟重叠拒绝，短集比例与倍速阈值在原有实际 PG 测试中通过。 |
| 窗口与迟到审核 | 完全在原观看窗口且首次可信收件不超过 5 分钟宽限的证明可晚处理；达标后超过 72 小时仍保留承诺，不自动释放。 |
| 收件水位 | 未达标过期先 held/awaiting；只有可信 drained watermark 可释放，普通定时器当前时间不能当真实队列水位。 |
| Outbox 跨事务重放 | 独立在 E00 已提交后，确认阶段执行 PG 除零故障，确认事务回滚而真实奖励保持 1 份；30 并发重放恢复同一 receipt，credit ledger 仍仅 1 条。 |
| 连接与终态 | 原有 max=1 pool 测试无嵌套连接等待；独立验证邀请人准备后终态拒新 credit，原有测试验证 invitee 同竞态；已成功 credit 再终态可恢复原 receipt，不重复发奖。 |
| 公共接口 | Go/Node allowlist 只有 summary/code/bind/appeal；watch/review/publish/credit/process 不公开。身份取真实 verified Better Auth session，设备取服务器 cookie 上下文；伪造 body 身份/权限不发奖。 |

## 能力边界与后续验收

已实现的是邀请归属、活动快照、预留、可信证明输入边界、审核与 E00 奖励 Outbox。证明的布尔检查是可信适配器的断言，本轮用本地替身调用；它们不是实际媒体签名验证器。真实源签名、交付日志、前台租约联合验证，持久化收件/水位适配器，生产 worker 调度监控，管理员 RBAC 页面，账号注销联合流程与申诉结案/补偿/撤奖仍待后续阶段。

应继续保持默认活动关闭；真实自动达标发奖应在上述真实适配器接通并完成独立联调后启用。公共邀请接口已接通不等于用户实际观看已能可靠自动发奖。配置行串行化保证本轮 v1 正确性，未做生产吞吐验收；数据库重放也不构成跨外部发行系统的端到端 Exactly Once。
