Files
BPOS-Service-Gateway/docs/开发环境册.md
T

133 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BPOS-Service-Gateway 开发环境册
> 简版。与姊妹仓《BPOS-Service-Task/docs/开发环境册.md》共享设施与纪律段落,本册只写本仓差异与要点。
>
> **凭证纪律**:本册只写环境变量的**键名**,绝不落主机、IP、账号、口令、密钥值。
> 真值去共享设施的凭证发放渠道要,写进本机 `.env`(该文件永不入 git)。
---
## 1. 本仓是什么
API 网关(`bpos-service-gateway`):前端唯一入口。
会话鉴权 · 按域路由(task/data/agent)· SSE 推送中心 · 上传转对象存储。
**8800,无自有库**——不持久化,故无 `db:migrate`、无 outbox、无 relay、无 consumer。
NATS 只用连通性(订阅 `touch.>` 与按需的 `stream.task.*`)。
> 落仓状态:上游《BPOS仓库结构》原六仓拓扑未含网关,§3"待定项"记为待定;
> `docs/proto-v13` 分支上已有【提案】"已建独立仓 BPOS-Service-Gateway",**待架构负责人确认**。
---
## 2. 共享设施与配置
### 2.1 一条硬性纪律:不许自建本地设施
**严禁在本机启动 Docker / 容器 / 任何本地替代基础设施。** NATS 在共享开发机上,
Keycloak 是共享站点。设施不可达时如实降级或停下,**不起本地兜底**:
NATS 不可达 → SSE 推送停摆、`/health` 照实报 fail,但代理/上传/健康检查照常服务
(`src/app/server.ts` 明确不因此拖垮 HTTP 面)。交付如实标注 `SKIPPED-INFRA-DOWN` 或报 BLOCKED。
### 2.2 环境变量(只写键名)
`.env.example` 是权威清单。
| 键名 | 作用 | 缺省与后果 |
|---|---|---|
| `PORT` | HTTP 监听端口 | 缺省 8800 |
| `NATS_URL` | 共享 NATS | `src/shared/config.ts` 有开发期缺省,部署一律显式配 |
| `KEYCLOAK_URL` / `KEYCLOAK_REALM` | 验签用的站点与 realm | 用户 token 与服务 token 同一 realm |
| `KEYCLOAK_CLIENT_ID` | 本仓 client,缺省 `api-gateway` | |
| `KEYCLOAK_CLIENT_SECRET` | **须为 `api-gateway` 服务账号的密钥** | 只从环境读、无缺省。配错/配成别的 client 的密钥=换来别人的服务账号 token(或直接被拒),SSE 的订阅授权全线失败并"人人被拒"。**值绝不写进任何文档或提交**,从 Keycloak 该 client 的 Credentials 页取 |
| `TASK_SERVICE_URL` | 代理与订阅授权的目标 | 缺省本机 8801 |
| `DATA_SERVICE_URL` | 代理目标 | 缺省本机 8802 |
| `AGENT_SERVICE_URL` | 代理目标 | 缺省本机 8901(开发期即 Task 仓的 fake-agent 桩) |
| `OBJECT_STORE_MODE` / `OBJECT_STORE_DIR` | 上传落盘(FS 适配器) | 缺省目录 `./.objectstore`,已在 `.gitignore` |
**为什么这里必须是 `api-gateway` 自己的密钥**:SSE 订阅授权要拿服务账号 token 去问任务服务
`GET /task/:id/access` 与 `GET /workflow/:id/access`,后者在任务侧是
`requireService(['api-gateway'])`——只认网关。`src/shared/service-token.ts` 用
`config.keycloak.clientId` + `KEYCLOAK_CLIENT_SECRET` 换 `client_credentials` token,
两者必须是**同一个 client** 的。相关的 realm 角色与 audience mapper 配置记录见
`docs/keycloak-setup-log.md`——**该文不含任何密钥值**(它自己在开头也声明"不含任何 secret、
密码或完整 token"),**但记有 Keycloak 站点地址与 realm 名**,引用或外发时注意范围。
`.env` / `.env.*` 已在 `.gitignore`(`!.env.example` 例外)。收尾核验里
`git log --all --oneline --diff-filter=A -- .env | wc -l` 必须为 `0`。
---
## 3. 端口与运行
**新人第一步**:本仓 `package.json` 的 `engines` 声明 **Node ≥ 22**;包管理器用 **pnpm**
(仓内有 `pnpm-lock.yaml` 与 `pnpm-workspace.yaml`,别用 npm/yarn 装)。
```bash
pnpm i # 装依赖
cp .env.example .env # 照 §2.2 逐项填;真值向共享设施的凭证发放渠道索取,不要向别人的 .env 复制
pnpm dev # tsx watch,读 .env,起在 :8800
pnpm gates # typecheck + lint + test
```
**无 `db:migrate`**(本仓无自有库)。
启动顺序:建 SseHub → 建 app → 起 HTTP → 连 NATS(通则 `hub.attachNats`,不通只告警)。
`SIGINT`/`SIGTERM`:**先收 SSE 长连**再 `server.close()`——那些响应永远不结束,
不主动关就会一直等;3s 兜底强退。
跨仓端口速查:Gateway 8800(无库)、Task 8801(`jx_dispatch`)、Data 8802(`jx_business`)、
fake-agent 桩 8901(在 Task 仓 `tools/fake-agent.ts`,Activity 仓交付真桩后退役)。
---
## 4. 总线用法:只订阅,不建流
本仓**不建流、不发布业务事件、无 outbox、无 relay、无 durable**。
只用 core NATS 订阅两类推送主题(BUS-08 尽力而为,本就不落 JetStream):
- `touch.>`:连上就订,进程内按连接可见性扇出;
- `stream.task.<id>`:**按需**订——有连接订阅了才建 NATS 订阅,最后一个连接退订就撤掉。
三条 JetStream 流(`BPOS_EVT` / `BPOS_CMD` / `BPOS_DLQ`)由 Task / Data 两仓引导,与本仓无关。
---
## 5. 测试纪律
本仓无库,共享库那套 `zz_test_` 前缀 / `afterAll` 谓词清理 / LIKE 下划线转义 / 生产扫描排除
的纪律**在本仓无直接落点**,但三条相关的仍适用:
1. **集成用例打的是共享 Keycloak 与共享 NATS**,不许起本地替身;不可达就如实跳过或失败。
2. **`test/support/token.ts` 是三仓同一性文件**(逐字节相同)——改它要同步三仓并重跑同一性脚本。
3. 用例造出来的 taskId / workflowId 一律用 `zz_test_` 前缀:它们会经服务账号 token 打到
任务服务的 `/access` 端点上,落在**共用**的 `jx_dispatch` 库前面,前缀是那边扫描排除的抓手。
---
## 6. 门禁与验收
```bash
pnpm typecheck # tsc --noEmit
pnpm lint # eslint src test
pnpm vitest run # 全量
pnpm gates # 上面三条
```
跨仓同一性由 Task 仓的脚本统一跑(三仓需为同级目录):
```bash
node ../BPOS-Service-Task/scripts/check-identity.mjs # 期望 16/16
```
本仓参与其中 11 条:`keycloak-auth.ts`、`bus/nats.ts`、`contracts/envelope.ts`、`app/health.ts`、
`test/support/token.ts`、`vitest.config.ts`(三仓)+ `shared/errors.ts`、`shared/service-token.ts`、
`shared/trace.ts`(与 Task 两仓)+ `upload/objectstore.ts`、`upload/fs-store.ts`
(与 Task 的 `channel/objectstore.ts`、`channel/fs-store.ts` 同内容、不同路径)。
**改这些文件必须同步复制到相关仓,再重跑脚本。**
仓内既有记录:`docs/keycloak-setup-log.md`(realm 角色 `service`、两个服务账号的 audience mapper、
共享 client 影响面、解码真 token 的验证结果)。
验收演练的一手记录在姊妹仓:`BPOS-Service-Task/tools/n2-acceptance.md`(touch 经 SSE 到浏览器)、
`n3-acceptance.md`(编排全链)、`BPOS-Service-Data/tools/n1-acceptance.md`(含网关这条腿的 aud 边界)。