# Plan: Env Config Refactor **Date:** 2026-02-05 **Author:** AI Assistant **Status:** Draft ## Overview 对 `.env` / `.env.example` 与 `backend/src/core/config/settings.py` 做一次一致性重构,消除同一含义的重复配置来源(例如 `DATABASE_URL` 与分段口令、host/port 与完整 URL)。目标是明确一组规范化环境变量,确保后端仅通过 Settings 读取,并兼顾 `infra/docker/docker-compose.yml` 的现有依赖。 ## Requirements ### Functional - [ ] 提出“规范化环境变量”清单(canonical set),覆盖后端与 Supabase 本地栈的关键配置。 - [ ] 定义 Settings 的读取与推导策略(优先级、默认值、派生字段)。 - [ ] 给出 `.env` / `.env.example` 的迁移步骤与兼容策略。 - [ ] 兼容 `infra/docker/docker-compose.yml` 使用的变量(保证 compose 不被破坏)。 ### Non-Functional - [ ] Performance: Settings 解析不增加明显启动耗时 - [ ] Security: 不在仓库中暴露真实密钥;对后端使用的数据库 URL 与密钥来源保持单一可信源 ## Technical Approach 以“后端设置单一来源 + docker-compose 继续使用 Supabase 变量”为原则: - 后端只接受 `SOCIAL_DATABASE_URL` 与必要的 Supabase 访问变量(`public_url/anon_key/service_role_key/jwt_secret`)。 - Supabase stack 继续使用 `SOCIAL_SUPABASE__*` 变量,保持 compose 模板稳定。 - 通过 Settings 做派生字段(例如 `supabase.url`)与兼容性读入(可选旧字段,设置弃用期)。 ### Key Decisions | Decision | Rationale | |----------|-----------| | 保留 `SOCIAL_DATABASE_URL` 作为后端唯一数据库连接来源 | 避免与分段 `POSTGRES_*` 产生冲突,清晰配置入口 | | Supabase stack 变量继续使用 `SOCIAL_SUPABASE__*` | docker-compose 已广泛引用,改动成本高 | | Settings 允许短期兼容旧字段 | 保障迁移期间部署安全,减少切换风险 | ## Implementation Steps ### Phase 1: Inventory & Mapping (2 hours) 1. 盘点 `.env` / `.env.example` 与 `settings.py` 的变量差异,标注重复与冲突字段。 2. 输出 canonical env vars 列表与映射关系表(旧 -> 新)。 ### Phase 2: Settings Refactor (3 hours) 1. 在 `settings.py` 中实现新的读取优先级与派生字段。 2. 为旧字段加兼容读取与弃用注记(仅内存兼容,不继续写入)。 ### Phase 3: Env Templates Update (2 hours) 1. 更新 `.env.example` 为 canonical 变量,并标注“后端使用/compose 使用”。 2. 更新 `.env`(本地开发用)以匹配新模板。 ### Phase 4: Validation & Docs (2 hours) 1. 本地启动 docker-compose,验证 Supabase stack 与后端连接正常。 2. 写简要迁移说明(README 或 docs/ 中短节)。 ## Files to Modify | File | Changes | |------|---------| | `.env.example` | 替换为 canonical 变量,移除重复字段 | | `.env` | 与模板对齐,移除重复字段 | | `backend/src/core/config/settings.py` | 调整 Settings 读取与派生策略 | | `infra/docker/docker-compose.yml` | 仅在必要时新增兼容映射变量 | | `README.md` 或 `docs/*` | 增加迁移说明 | ## Files to Create | File | Purpose | |------|---------| | `docs/plans/PLAN-env-config-refactor-2026-02-05.md` | 规划文档 | ## Dependencies - [ ] 无新增第三方依赖 ## Proposed Canonical Env Vars ### Backend (Settings) - `SOCIAL_DATABASE_URL` (required) — 后端数据库连接(唯一来源) - `SOCIAL_SUPABASE__PUBLIC_URL` — Supabase 公网/本地外部访问 URL - `SOCIAL_SUPABASE__API_EXTERNAL_URL` — Supabase Auth 回调外部 URL - `SOCIAL_SUPABASE__ANON_KEY` — 前端/匿名访问 key - `SOCIAL_SUPABASE__SERVICE_ROLE_KEY` — 后端服务角色 key - `SOCIAL_SUPABASE__JWT_SECRET` — JWT 验证密钥(后端验证用) ### Supabase Stack (docker-compose) - `SOCIAL_SUPABASE__POSTGRES_HOST` - `SOCIAL_SUPABASE__POSTGRES_PORT` - `SOCIAL_SUPABASE__POSTGRES_DB` - `SOCIAL_SUPABASE__POSTGRES_PASSWORD` - `SOCIAL_SUPABASE__KONG_HTTP_PORT` - `SOCIAL_SUPABASE__KONG_HTTPS_PORT` - `SOCIAL_SUPABASE__SITE_URL` - `SOCIAL_SUPABASE__JWT_SECRET` - `SOCIAL_SUPABASE__ANON_KEY` - `SOCIAL_SUPABASE__SERVICE_ROLE_KEY` - 其余 `SOCIAL_SUPABASE__*` 保持现状(Logflare、SMTP、Pooler 等) ## Mapping Strategy 1. **Backend DB** - Only: `SOCIAL_DATABASE_URL` - Deprecated: `SOCIAL_SUPABASE__POSTGRES_*`(后端不再拼接) 2. **Supabase URL** - Primary: `SOCIAL_SUPABASE__PUBLIC_URL` - Fallback: `SOCIAL_SUPABASE__API_EXTERNAL_URL` - Settings 中 `supabase.url` 由上述字段派生 3. **Docker Compose** - 继续读 `SOCIAL_SUPABASE__POSTGRES_*` - 不引入 `SOCIAL_DATABASE_URL` 到 compose,以免混淆职责 ## Migration Steps 1. 在 `settings.py` 中增加兼容逻辑:若 `SOCIAL_DATABASE_URL` 不存在,可临时从 `SOCIAL_SUPABASE__POSTGRES_*` 组装(同时记录弃用)。 2. 更新 `.env.example`:只保留 canonical 变量并标注用途。 3. 更新 `.env`:移除重复字段,确保本地后端使用 `SOCIAL_DATABASE_URL`。 4. 校验 compose:`infra/docker/docker-compose.yml` 不依赖被移除字段。 5. 发布说明:提示下游用户迁移并在下个版本移除兼容逻辑。 ## Testing Strategy - **Unit Tests:** Settings 派生字段与优先级规则 - **Integration Tests:** 后端连接 Supabase DB(使用 `SOCIAL_DATABASE_URL`) - **E2E Tests:** 关键登录/读写流程(确认 JWT 与 Service Role 配置无误) ## Risks & Mitigations | Risk | Impact | Likelihood | Mitigation | |------|--------|------------|------------| | compose 变量被误删导致 Supabase 启动失败 | High | Medium | 迁移前后对照 `docker-compose.yml`,保留全部 `SOCIAL_SUPABASE__*` 依赖 | | 后端数据库连接断开 | High | Medium | 兼容旧字段,先引入新变量再切换 | | 开发环境 `.env` 未更新 | Medium | High | 更新模板并在 README 明确迁移步骤 | ## Estimated Effort | Phase | Effort | |-------|--------| | Phase 1 | 2 hours | | Phase 2 | 3 hours | | Phase 3 | 2 hours | | Phase 4 | 2 hours | | **Total** | **9 hours** |