# push-gateway 对接契约

> 负责人：ai02
> 关联：[matrix.md](./matrix.md)、[msg.proto](../../../packages/shared-proto/proto/msg.proto)、[events.proto](../../../packages/shared-proto/proto/events.proto)

---

## §1 我提供什么（对外接口）

### 1.1 gRPC 接口（如有）

无对外 gRPC。push-gateway 是 WebSocket/SSE 推送入口。

### 1.2 HTTP 端点（如有）

| Method | Path                | 用途                                   | 认证                             |
| ------ | ------------------- | -------------------------------------- | -------------------------------- |
| GET    | /ws                 | WebSocket 升级端点（实时推送通知）     | JWT 必需（query param 传 token） |
| GET    | /sse                | SSE 推送端点（备选实时通道）           | JWT 必需                         |
| POST   | /internal/broadcast | 内部广播接口（msg 服务触发）           | 内网 mTLS                        |
| POST   | /internal/send      | 内部单推接口（msg 服务触发）           | 内网 mTLS                        |
| GET    | /healthz            | 健康检查（liveness）                   | 公开                             |
| GET    | /readyz             | 就绪检查（readiness，含 Kafka 连通性） | 公开                             |
| GET    | /metrics            | Prometheus 指标端点                    | 公开（内网）                     |

### 1.3 GraphQL schema（如 BFF）

不适用。

### 1.4 Kafka 事件发布（如有）

无。push-gateway 不发布事件，仅消费事件触发推送。

### 1.5 错误码前缀

`PUSH_`（如 PUSH_CONNECTION_FAILED、PUSH_CHANNEL_CLOSED、PUSH_AUTH_INVALID）

---

## §2 我消费什么（依赖上游）

### 2.1 gRPC 调用（同步）

无主动 gRPC 调用上游。

### 2.2 Kafka 事件订阅（异步）

| Topic                       | Event                             | 发布方     | mock 策略                                                                   |
| --------------------------- | --------------------------------- | ---------- | --------------------------------------------------------------------------- |
| edu.msg.notification.events | NotificationEvent（action: sent） | msg (ai10) | msg 就绪前不订阅，使用本地定时器每 30 秒推送 1 条 mock 通知到所有连接客户端 |

### 2.3 HTTP 调用（如有）

无。

### 2.4 内部接口（msg 调用 push-gateway）

| 被调用方     | Method.Path              | 用途               | 说明                                     |
| ------------ | ------------------------ | ------------------ | ---------------------------------------- |
| push-gateway | POST /internal/broadcast | msg 服务批量推送   | msg 收到业务事件后渲染模板，调此接口广播 |
| push-gateway | POST /internal/send      | msg 服务单用户推送 | msg 渲染后定向推送给目标用户             |

---

## §3 就绪信号

### 3.1 我依赖的上游就绪标志

- [ ] msg gRPC 50056 启用（ai10）—— 通知事件来源
- [ ] edu.msg.notification.events topic 有事件发布（ai10）
- [ ] iam gRPC 50052 启用（ai06）—— WebSocket 连接时 JWT 验签（可选，push-gateway 可独立验签）

### 3.2 我的就绪标志（供下游消费）

- [ ] push-gateway HTTP :8081 启用（/healthz 返回 200）
- [ ] /readyz 返回 200（含 Kafka 连通性检查通过）
- [ ] WebSocket /ws 端点可升级连接（JWT 鉴权后建立长连接）
- [ ] SSE /sse 端点可建立 EventStream
- [ ] /internal/broadcast + /internal/send 接收 msg 推送并下发到在线客户端
- [ ] Kafka consumer edu.msg.notification.events 订阅成功

---

## §4 Mock 策略

### 4.1 我提供的 mock

在 push-gateway 真实就绪前，为下游（各前端 portal）提供以下 mock：

- **WebSocket mock**：前端开发期使用 mock-socket 库模拟 WS 连接
  - 连接成功后每 30 秒推送 1 条 mock 通知（type="system", title="测试通知"）
- **SSE mock**：前端使用 EventSource polyfill，本地定时推送 mock 事件
- **HTTP mock**：/internal/* 接口返回 200 success

### 4.2 我消费的 mock

在真实上游就绪前，push-gateway 使用以下 mock：

- **NotificationEvent mock**：msg 就绪前，push-gateway 内置定时器每 30 秒生成 1 条 mock NotificationEvent（action=sent），推送到所有在线客户端
- **JWT 验签**：iam 就绪前使用本地固定 mock RS256 公钥验签 WebSocket 连接的 token
- **Kafka 订阅**：msg 就绪前不启动 Kafka consumer，使用本地定时器替代
