Expose a runnable backend without giving the ingress layer secrets
Some checks failed
verify / verify (push) Has been cancelled

The backend can now be inspected through a loopback-only gateway while the database-aware API remains on the internal data network. A governed synthetic demo proves readiness, pgvector retrieval, reranking, and citation output through real HTTP without invoking cloud models.

Constraint: The previously exposed Bailian key is compromised and cannot be used for live validation

Constraint: The API must be locally reachable while retaining no internet egress

Rejected: Attach the API directly to the ingress network | a real socket test proved that configuration still had egress

Rejected: Publish a port from the internal-only network | Docker Desktop did not expose the host port

Confidence: high

Scope-risk: moderate

Reversibility: clean

Directive: Keep model and database credentials out of the gateway; do not relax the fixed demo identity/profile filters

Tested: make verify; 63 pytest tests; strict mypy; Ruff; Secret scan; Compose config; three backend image builds; API/DB/gateway healthy; migration exit 0; Swagger browser check; live/ready/meta/status/search HTTP; 20/20/20 index; API egress ENETUNREACH; empty gateway mounts and business environment

Not-tested: Live Bailian calls require a newly rotated key; full generated-answer flow and React UI are not implemented
This commit is contained in:
2026-07-12 16:37:02 +08:00
parent e89cca2b55
commit cfd6d4cbad
16 changed files with 1207 additions and 37 deletions

View File

@@ -7,7 +7,7 @@
| 已完成阶段 | Stage 0仓库、安全和设计基线 |
| 整体完成度 | 约 12%,合理区间 10%15% |
| 设计完成度 | 设计基线已完成;实现中发现新约束时继续通过 ADR 和文档修订维护 |
| 业务代码完成度 | 约 8%Stage 1 的离线/数据库 PoC 已验收,真实百炼 smoke 仍待新 Key前端产品功能尚未实现 |
| 业务代码完成度 | 约 10%Stage 1 的 Docker API、离线检索和数据库 PoC 已验收,真实百炼 smoke 仍待新 Key前端产品功能尚未实现 |
| 当前预计剩余工期 | 约 913 周,含 300 题正式标注、盲测、论文和答辩缓冲 |
| 进度权威来源 | 本文的阶段状态、验收证据和已推送提交 |
@@ -50,7 +50,7 @@
| Stage 9 答辩、发布与归档 | 3% | `TODO` | 0% |
| **合计** | **100%** | — | **12%** |
Stage 1 已完成可离线验收的数据库、适配器契约synthetic seed 子闭环,阶段内部约完成 85%;但真实三模型 smoke 仍依赖轮换后的新 Key因此 Stage 1 不提前计入整体里程碑。本文复选框表示“已通过验收”,不表示“文件是否已经出现”。当前可诚实表述为:**设计基线完成,整体里程碑约 12%Stage 1 离线部分可运行,真实百炼验证尚未完成。**
Stage 1 已完成可离线验收的数据库、适配器契约synthetic seed 和只读 API 子闭环,阶段内部约完成 90%;但真实三模型 smoke 仍依赖轮换后的新 Key因此 Stage 1 不提前计入整体里程碑。本文复选框表示“已通过验收”,不表示“文件是否已经出现”。当前可诚实表述为:**设计基线完成,整体里程碑约 12%Stage 1 离线后端可运行,真实百炼验证尚未完成。**
## 2. 阶段依赖与关键路径
@@ -134,6 +134,7 @@ Stage 0 DONE
- [x] 创建 `backend/pyproject.toml` 和依赖锁文件,不引入未说明依赖。
- [x] 创建最小 `backend/Dockerfile`,使用非 root 用户和固定基础镜像 digest。
- [x] 创建最小 `compose.yaml`,包含 `db + migrate + provider-smoke + seed-demo/offline`
- [x] 启动最小 FastAPI `api + gateway`,内部 API 无 egressgateway 无 Secret 并仅发布回环端口;提供真实数据库 readiness、Swagger 和只读 synthetic demo 检索。
- [x] 创建 PostgreSQL bootstrap、migrator 和 app 分权角色初始化脚本;备份只读角色在备份功能落地时单独创建。
- [x] 创建 Alembic 基线迁移,启用 pgvector 并建立 1024 维向量表/HNSW 基线。
- [x] 确保运行期服务不挂载 bootstrap 或 migrator Secret。
@@ -162,8 +163,9 @@ Stage 0 DONE
- [x] `docker compose up db migrate` 在空 volume 成功建立扩展、角色和表。
- [ ] `docker compose run --rm provider-smoke` 三模型探测成功,日志无 Secret。
- [x] `docker compose run --rm seed-demo-offline` 完成 20 条虚构数据写入、检索和重排;真实模式待新 Key。
- [x] `api + gateway` 镜像构建并达到 healthylive/ready/meta/demo status/demo search 均通过真实 HTTP 验收。
- [x] 第二次运行 seed 后数据库计数与第一次相同,均为 chunks/vectors/searchable = 20/20/20。
- [x] 41 项测试证明 Embedding 维度/下标、Rerank 下标、Chat 流式响应和失败路径正确。
- [x] 63 项测试证明模型契约、健康检查、固定上游 gateway、离线 demo、数据治理和失败路径正确。
- [x] `make verify`、Secret 扫描、固定镜像构建和 `git diff --check` 通过。
### 2026-07-12 已验证运行证据
@@ -171,6 +173,8 @@ Stage 0 DONE
- 全新 volume 上 `db` 达到 healthy`migrate` 以非超级用户退出码 0版本为 `0001_initial_schema`
- `vector` 扩展与 HNSW 基线存在app/migrator 均非超级用户app 无 `rag` schema DDL 权限但具有所需 DML。
- 两次离线 seed 均输出 20/20/209 个可回答虚构问题 Hit@3 = 9/9。
- FastAPI 容器使用 app 最小权限角色,根文件系统只读且无 egress无 Secret gateway 仅提供回环入口Swagger 可见demo search 返回合成片段与不透明 citation ID。
- API 容器对公网 TCP 探测返回 `ENETUNREACH (101)`gateway 的 mounts 为空且不含数据库或百炼业务环境变量。
- PostgreSQL 重启后计数仍为 20/20/20。
- app 尝试修改已 `CLOUD_APPROVED``cloud_text` 被审批不可变触发器拒绝;尝试建表被权限拒绝。
- 唯一未验收项是真实 `text-embedding-v4` / `qwen3-rerank` / `deepseek-v4-flash` smoke 与真实模式 seed。
@@ -180,6 +184,7 @@ Stage 0 DONE
- [x] `S1-A`:数据库初始化、分权角色、迁移和最小 Compose 已随 `f4ba5d5` 验证并推送。
- [ ] `S1-B`:三模型适配器和 fake 契约测试已随 `f4ba5d5` 推送;新 Key 下的 live smoke 未完成,因此节点保持未完成。
- [x] `S1-C`20 条虚构 seed、幂等验证、运行证据和文档已随 `f4ba5d5` 推送。
- [ ] `S1-D`:内部 API、无 Secret gateway、只读 demo 检索和真实 HTTP/Docker 运行证据;验证后提交并推送。
`f4ba5d5` 是 Stage 1 离线可执行闭环提交,不代表 Stage 1 已完成;阶段完成仍以真实三模型 smoke 和真实模式 seed 通过为准。

View File

@@ -21,7 +21,7 @@ bash scripts/init-local-secrets.sh
离线模式使用确定性的 1024 维 feature-hash 向量和词法重排器,只验证数据治理、批处理、迁移、向量写入、权限过滤、检索、重排和幂等性,不把它当成真实模型质量。
```bash
docker compose up -d --build db migrate
docker compose up -d --build gateway
docker compose --profile tools run --rm seed-demo-offline
docker compose --profile tools run --rm seed-demo-offline
```
@@ -44,6 +44,28 @@ Seed 的实际流程是:
7. 对 Top K 候选重排并输出虚构问题的 Hit@3
8. 相同输入再次执行使用相同 ID 和幂等 upsert不增加行数。
### 2.1 查看后端运行效果
内部 API 只连接 `internal` data 网络,只挂载 app 数据库 Secret不连接外网也不挂载百炼 Key。无 Secret、无数据库凭证的 gateway 同时连接 ingress 与 data 网络,并且仅发布到本机回环地址 `127.0.0.1:8000`。两个容器都以数值非 root 用户运行,根文件系统只读,并移除 Linux capabilities。
```bash
curl http://127.0.0.1:8000/health/live
curl http://127.0.0.1:8000/health/ready
curl http://127.0.0.1:8000/api/v1/demo/status
curl -X POST http://127.0.0.1:8000/api/v1/demo/search \
-H 'Content-Type: application/json' \
--data '{"query":"花岗斑岩铜矿化特征","top_k":3}'
```
预期结果:
- readiness 返回 `database=ok`
- demo status 返回 chunks/vectors/searchable = 20/20/20
- search 只返回 `synthetic-demo` 数据集中的合成标题、批准后的片段、页码、分数和不透明 citation ID
- Swagger 位于 <http://127.0.0.1:8000/docs>。
该接口是 Stage 1 的离线可见效果,不调用百炼,也不代表完整问答生成链或 React 前端已经完成。
## 3. 真实百炼能力探测
完成旧 Key 轮换后: