Commit 0165bc11 by luoqi

fix(deploy): 机器形态自检 —— 该托管却漏 COMPOSE_MANAGED=1 直接退出

## 事故(2026-07-26,生产 friday / 47.99.62.30)

在生产机漏了 `COMPOSE_MANAGED=1` 跑 deploy-prod.sh。不叠加 managed override 时,
docker-compose.prod.yml 把 DATABASE_URL 硬编码成 `postgres:5432`(容器内自带 PG),于是:

  22:35:33  起了 pac-postgres-1 / pac-redis-1 两个空容器(volume 同刻创建)
  22:35~36  pac-migrate 对着这个**全新空库**跑完 29 条迁移,建出整套 schema
            ← 在这里被打断
  22:38:29  正确那次(COMPOSE_MANAGED=1)把两条新迁移写进托管库

托管生产库**未被写坏**,逐项核对:patients 425,874 / facts 25,022,720 /
在池 236,553 / assigned 36 / personas 409,368 / plan_executions 7 —— 与事故前一致
(patients、facts 的 +2/+206 是正常增量摄入)。空库那侧唯一有行的表是 _prisma_migrations(29 行)。

## 真正的后遗症(已清理)

机器上留下一个「schema 齐全的空库」。危害不在占资源,在于:
**下次再漏 COMPOSE_MANAGED,service 会顺利连上它、health 200、脚本三项验证全绿,
生产静默服务空库且零告警。** 原本"空 PG 没 schema 会崩"这张天然安全网就此失效。

已在生产执行:docker rm -f pac-postgres-1 pac-redis-1
              docker volume rm pac_postgres_data pac_redis_data
清理前核过:两 volume 无其他容器挂载 / pac-service 连的是 RDS+托管 Redis /
pac-web 无 DB 环境变量 / 本地库业务表全 0 / 全机再无其他 volume。清理后 health+web+私网 200。

## 防线

不依赖人记得加环境变量,而是问机器自己 —— 读 `.env` 的 DATABASE_URL 指向哪儿:
  · postgres / localhost / 127.0.0.1 → 自带 DB 形态,放行(测试机)
  · 其他主机(RDS 等)               → 托管形态,没设 COMPOSE_MANAGED=1 就 die

闸放在 main() 最前,早于任何 git/docker 动作 —— 拦下时机器状态零变更。
报错只打主机名不打整串 URL(不泄露 .env 口令)。

## 验证

- 新增 tests/deploy-managed-guard.spec.ts 5 例,真起 bash 跑脚本:
  托管+漏设→退出且给出正确命令 / 报错不含口令 / 托管+设了→放行 /
  自带 DB→放行(不误伤测试机) / localhost 与 127.0.0.1 同样放行
- 482 单测通过(35 suites),service tsc 干净

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
parent 13733519
Pipeline #3445 failed in 0 seconds