mirror of
https://github.com/hpd840321/craftlabs-authorization-sdk.git
synced 2026-06-10 02:20:28 +08:00
d53ddf32c8
I8: platform proxies replay to webhook; webhook ops token filter and internal replay endpoint; delivery service supports read/replay flows. I9: platform GET callback webhook delivery status by inbox id; UI shows read-only status block and handles load errors without blocking the page. Also refresh OpenAPI, Runbook notes, test fixtures and YAML; fix Vite dev axios baseURL so /api uses proxy; improve login error messaging. Made-with: Cursor
151 lines
7.0 KiB
Markdown
151 lines
7.0 KiB
Markdown
# 平台后端部署 Runbook(单机 Fat JAR)
|
||
|
||
面向 **广州创飞** 小团队:**单/双进程 `java -jar`** + **PostgreSQL 15**,无 K8s 前提。
|
||
|
||
## 1. 组件与端口
|
||
|
||
| 进程 | JAR | 默认端口 | 说明 |
|
||
|------|-----|----------|------|
|
||
| 交付平台 API | `delivery-platform-api-*-SNAPSHOT.jar` | **8080** | JWT、M1+ 领域 API、Flyway 表 **`flyway_platform_api`** |
|
||
| License Webhook | `license-webhook-ingress-*-SNAPSHOT.jar` | **8081** | 比特 Callback;Flyway 表 **`flyway_webhook`** |
|
||
|
||
两进程可部署在 **同一主机** 或 **两台主机**;共用同一数据库实例时,须使用 **不同 Flyway 历史表**(已在 `application.yml` 配置)。
|
||
|
||
## 2. 构建产物
|
||
|
||
```bash
|
||
mvn -f services/pom.xml -pl delivery-platform-api -am clean package
|
||
mvn -f services/pom.xml -pl license-webhook-ingress -am clean package
|
||
```
|
||
|
||
产物:`services/*/target/*.jar`(Spring Boot repackage)。
|
||
|
||
## 3. PostgreSQL 15
|
||
|
||
本地/联调示例:
|
||
|
||
```bash
|
||
docker compose -f services/docker-compose.yml up -d
|
||
```
|
||
|
||
默认库 `craftlabs_platform`、用户/密码 `craftlabs`/`craftlabs`(**生产须替换**)。
|
||
|
||
**网络**:数据库 **不对公网**;仅应用主机或 VPC 内可达。
|
||
|
||
## 4. 环境变量(摘要)
|
||
|
||
### 共用数据源(两服务均可)
|
||
|
||
| 变量 | 说明 |
|
||
|------|------|
|
||
| `SPRING_DATASOURCE_URL` | 例:`jdbc:postgresql://db:5432/craftlabs_platform` |
|
||
| `SPRING_DATASOURCE_USERNAME` | 数据库用户 |
|
||
| `SPRING_DATASOURCE_PASSWORD` | 数据库密码 |
|
||
|
||
### 平台 API 专有
|
||
|
||
| 变量 | 说明 |
|
||
|------|------|
|
||
| `PLATFORM_JWT_SECRET` | **必填(生产)**,长度 ≥ **32** 字符;用于签发/校验 JWT |
|
||
| `PLATFORM_JWT_EXPIRY_SECONDS` | 可选,默认 `43200`(12h) |
|
||
|
||
### Webhook 专有
|
||
|
||
| 变量 | 说明 |
|
||
|------|------|
|
||
| `CRAFTLABS_WEBHOOK_EXPECTED_TOKEN` | **生产强烈建议设置**;与请求头 `x-bitanswer-token` 一致 |
|
||
|
||
## 5. 启动顺序与迁移
|
||
|
||
- **Flyway**:各 JAR **首次启动** 时自动迁移;无强制先后,但 **同一库** 上两应用使用 **不同历史表**,互不覆盖。
|
||
- **建议**:先确认数据库已创建且账号可连,再先后启动 **API** 与 **Webhook**(顺序可互换)。
|
||
|
||
示例(生产请用 systemd/supervisor 等托管):
|
||
|
||
```bash
|
||
export SPRING_DATASOURCE_URL=jdbc:postgresql://127.0.0.1:5432/craftlabs_platform
|
||
export SPRING_DATASOURCE_USERNAME=craftlabs
|
||
export SPRING_DATASOURCE_PASSWORD='********'
|
||
export PLATFORM_JWT_SECRET='至少32字符的随机密钥'
|
||
|
||
java -jar delivery-platform-api-0.1.0-SNAPSHOT.jar
|
||
|
||
# 另一终端
|
||
export CRAFTLABS_WEBHOOK_EXPECTED_TOKEN='与比特控制台配置一致'
|
||
java -jar license-webhook-ingress-0.1.0-SNAPSHOT.jar
|
||
```
|
||
|
||
## 6. 健康检查
|
||
|
||
- API:`GET http://127.0.0.1:8080/actuator/health`
|
||
- Webhook:`GET http://127.0.0.1:8081/actuator/health`
|
||
|
||
## 7. 契约与前端
|
||
|
||
- OpenAPI 快照:`contracts/openapi/delivery-platform-api.json`
|
||
- 运行时文档:`http://<api-host>:8080/swagger-ui.html`(生产建议 **限制 IP** 或 **关闭**)
|
||
|
||
前端静态资源由 **Nginx/Caddy** 托管,`/api` **反代** 至 8080;参见 `web/delivery-platform-ui` README / `vite` 开发代理配置。
|
||
|
||
## 8. 禁止事项(架构)
|
||
|
||
- 平台 **classpath 禁止** `craftlabs-auth-bitanswer`(Maven Enforcer + CI 门禁);详见根目录 `contracts/README.md` 与 `services/pom.xml` 说明。
|
||
|
||
## 9. 回滚
|
||
|
||
- 应用:回退上一版 JAR 并重启。
|
||
- 数据库:Flyway **无自动 down**;回滚需 **人工迁移脚本** 或从备份恢复(生产变更前应备份)。
|
||
|
||
## 10. I5/I6:内部 Token、Webhook → 平台与轮换
|
||
|
||
### 10.1 变量对照
|
||
|
||
| 组件 | 变量 / 配置键 | 说明 |
|
||
|------|----------------|------|
|
||
| **平台** `delivery-platform-api` | `PLATFORM_INTERNAL_TOKEN` 或 `CRAFTLABS_PLATFORM_INTERNAL_TOKEN` → `platform.internal.token` | 校验入站 `X-Platform-Internal-Token` |
|
||
| **Webhook** `license-webhook-ingress` | `CRAFTLABS_PLATFORM_INTERNAL_TOKEN` → `craftlabs.platform.internal.token` | 出站请求头,**须与平台一致** |
|
||
| **Webhook** | `PLATFORM_INTERNAL_BASE_URL` → `craftlabs.platform.internal.base-url` | 平台根 URL,无尾斜杠;转发 `POST …/internal/v1/callback-events` |
|
||
|
||
未配置 `base-url` 或 token 时,Webhook **仅落库收据**,不向平台投递(本地可只验 bitanswer token)。
|
||
|
||
### 10.2 连通性自检(平台已启动)
|
||
|
||
```bash
|
||
# 将 <TOKEN> 与平台环境变量一致
|
||
curl -sS -o /dev/null -w "%{http_code}\n" \
|
||
-X POST "http://127.0.0.1:8080/internal/v1/callback-events" \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-Platform-Internal-Token: <TOKEN>" \
|
||
-H "Idempotency-Key: runbook-probe-$(date +%s)" \
|
||
-d '{"schemaVersion":"1.0","sourceSystem":"BITANSWER","externalMessageId":"runbook-probe-msg","eventType":"probe","rawPayload":{}}'
|
||
```
|
||
|
||
期望:**401** 表示路由可达但 Token 错误;**400** 可能为体缺字段;**200** 且 JSON 含 `inboxId` 表示鉴权与入队逻辑正常。
|
||
|
||
### 10.3 Token 轮换(简要)
|
||
|
||
1. 在平台与 Webhook **同时**配置新 Token(滚动窗口内可同时接受旧+新需改代码时另议;**MVP 为单值**,应选维护窗**同步切换**)。
|
||
2. 重启 **平台** API,再重启 **Webhook**(避免 Webhook 仍用旧值调用已切换的平台)。
|
||
3. 用 **§10.2** 探测;再在 UI **Callback 收件箱** 验证新事件可见。
|
||
4. 审计:记录轮换时间与操作人(可另走工单)。
|
||
|
||
### 10.4 Flyway 历史表
|
||
|
||
- 平台:`flyway_platform_api`(迁移含 `platform_callback_inbox`、M6 表等)。
|
||
- Webhook:`flyway_webhook`(`V1` 收据表、`V2` **`webhook_platform_delivery`** 平台投递出库)。**同一 PostgreSQL 实例** 下两表共存,**勿**手动改名或合并。
|
||
|
||
### 10.5 I7:异步投递与调度(Webhook)
|
||
|
||
| 配置 | 说明 |
|
||
|------|------|
|
||
| `craftlabs.platform.delivery.scheduler-enabled` | 默认 `true`;单测/特殊场景可 `false` |
|
||
| `craftlabs.platform.delivery.tick-ms` | 调度间隔(毫秒) |
|
||
| `craftlabs.platform.delivery.max-attempts` | 单条投递最大尝试次数,超限标记 **`DEAD`** |
|
||
| `craftlabs.platform.delivery.batch-size` | 每 tick 最多拉取条数 |
|
||
|
||
比特 Callback **2xx** 在收据落库与 **出站行入队** 之后返回;真正 `POST` 平台由后台线程执行。`DEAD` 行需人工依据 `last_error` 与平台侧幂等处理。
|
||
|
||
**I8 — DEAD 重放入队**:在平台与 Webhook 配置 **`LICENSE_WEBHOOK_BASE_URL`**(Webhook 根 URL)与 **`LICENSE_WEBHOOK_OPS_TOKEN`**(两侧相同;保护 Webhook `POST /internal/v1/platform-deliveries/by-receipt/{receiptId}/replay`)。**OPS / SYS_ADMIN** 可在 UI **Callback 详情** 触发「重新入队出库」,平台会按收件箱的 `webhookReceiptId` 代调 Webhook;仅当出库行为 **`DEAD`** 时成功。亦可手工:`curl -X POST -H "X-Webhook-Ops-Token: …" "http://<webhook>/internal/v1/platform-deliveries/by-receipt/<receiptId>/replay"`。
|
||
|
||
**I9 — 出库状态只读**:平台 `GET /api/v1/callback-inbox/{id}/webhook-delivery` 代调 Webhook `GET …/by-receipt/{receiptId}`(同一 Ops Token);UI 详情展示 `status` / `attempts` / `lastError` 等。
|