# 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.`:**按需**订——有连接订阅了才建 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 边界)。