# Project Bootstrap（技术计划）

## 1. 目标与约束（来自 spec）

- 目标：完成项目初始化可落地的工程与基础设施约定（client/server + dev/prod 隔离 + MySQL/Redis 命名与访问边界）。
- 关键选择：
  - 后端依赖：`requirements.txt` + `pip`
  - 定时/异步：Celery + Redis
  - 环境：仅 dev / prod
  - Redis 隔离：ACL + key 前缀（`dev:*` / `pro:*`）
  - 部署：**不在本需求中提供 Docker 起 MySQL/Redis**（MySQL/Redis 已部署），后端通过环境变量连接
  - 数据库迁移：Alembic
  - Redis 生产环境：**maxmemory=256MB 硬限制**

## 2. 总体方案

### 2.1 MySQL（schema 隔离）

- prod schema：`mindfulness`
- dev schema：`mindfulness_dev`
- 字符集：`utf8mb4`
- 连接方式：后端通过 `DATABASE_URL`（SQLAlchemy Async）连接到对应 schema

### 2.2 Redis（ACL + 前缀隔离 + 内存限制）

- 单 Redis 实例（同机同容器可行）。
- 通过 **ACL 用户**限制不同环境只能访问各自前缀：
  - dev 用户：只能访问 `dev:*`
  - prod 用户：只能访问 `pro:*`
- 应用侧硬约束：所有 Redis key 必须带环境前缀（`dev:` / `pro:`）。
- 生产 maxmemory：`256mb`，并采用“少用 Redis、短 TTL、避免任务积压”的策略。

> 重要：Celery broker 以“可靠投递”为优先，计划中默认 **不启用** Celery result backend（或启用时必须设置 TTL）。

### 2.3 运行方式（不限定部署形态）

本需求只要求：

- MySQL 与 Redis **已可访问**
- 后端通过 `.env.dev/.env.prod`（或等价环境变量注入方式）获取连接信息
- API/Celery/Beat 以任意进程管理方式运行（Docker/systemd/进程托管均可），但需满足验收项

## 3. 目录与文件落地清单

> 本计划只定义“应该创建/调整什么”，具体文件内容在 tasks 阶段逐项实现。

### 3.1 后端依赖与启动入口（server）

- `server/requirements.txt`
- `server/app/main.py`（FastAPI 入口）
- `server/app/core/config.py`（pydantic-settings，按 `APP_ENV` 加载 `.env.dev/.env.prod`）
- `server/app/worker.py`（Celery app 入口）
- `server/alembic.ini` + `server/alembic/`（迁移脚手架）
- `server/.env.example`（字段结构，不含真实值）

### 3.2 基础设施（infra）

本需求不强制创建 `infra/`（因为 MySQL/Redis 已部署）。

可选新增（仅用于“文档化配置/备份参考”，不要求参与部署）：

- `infra/redis/users.acl`（ACL 用户定义备份）
- `infra/redis/redis.prod.conf`（prod 配置备份，包含 maxmemory=256mb）
- `infra/mysql/init/00-create-schemas.sql`（创建 `mindfulness_dev/mindfulness` 的 SQL 备份）

## 4. Redis ACL 与 maxmemory 的落地方案

### 4.1 ACL 文件（`infra/redis/users.acl`）

> 若 Redis 已在服务器配置完成，本节用于“约定与验收”。

- 定义 `dev_user`、`pro_user` 两个账号
- 分别限制 key pattern：
  - dev：`~dev:*`
  - prod：`~pro:*`
- 建议禁用默认用户，避免未授权访问（推荐）：`user default off`

### 4.2 Redis 配置（`infra/redis/redis.prod.conf`）

> 若 Redis 已在服务器配置完成，本节用于“约定与验收”。

- `maxmemory 256mb`
- `maxmemory-policy noeviction`（队列场景优先“不丢任务”，宁可让写入失败报警）
- 开启 ACL（例如 `aclfile .../users.acl`）

### 4.3 应用侧约束（在代码实现时落地）

为确保 ACL 真的起作用，需要做到：

- **所有业务 key 带前缀**：例如 `dev:cache:...` / `pro:cache:...`
- **Celery 队列名带前缀**：例如 `dev:push` / `pro:push`
- **禁用或限制 result backend**：默认不启用；如启用必须设置短 TTL（例如 1 小时/1 天）
- **任务参数保持小**：只传 id，不传长文本/大 payload，避免队列膨胀导致 Redis 触顶

## 5. 环境变量与配置约定

### 5.1 后端 `.env.dev/.env.prod`（字段示例）

- `APP_ENV=dev|prod`
- `DATABASE_URL=.../mindfulness_dev`（dev）或 `.../mindfulness`（prod）
- `REDIS_URL=redis://<user>:<pass>@redis:6379/0`
- `CELERY_BROKER_URL=redis://<user>:<pass>@redis:6379/0`
- `CELERY_RESULT_BACKEND`：默认不配置（或仅在 dev 开启）

### 5.2 密钥管理

- `.env.dev/.env.prod` 不进仓库
- 提供 `.env.example` 仅展示字段结构

## 6. 实施步骤（建议顺序）

### 阶段 A：验证现有 MySQL/Redis 与隔离策略

- Redis：ACL 生效验证（dev 用户无法访问 `pro:*`，prod 用户无法访问 `dev:*`）
- Redis：prod 配置验证（`maxmemory=256mb` 生效）
- MySQL：确认 `mindfulness_dev` 与 `mindfulness` 两个 schema 已创建（若未创建则创建）

### 阶段 B：后端最小可运行骨架

- `requirements.txt` 固化依赖
- FastAPI 最小健康检查接口（如 `/healthz`）
- SQLAlchemy 连接与基础会话
- Alembic 初始化与一次空迁移验证

### 阶段 C：Celery 最小闭环

- Celery app 初始化，broker 指向 Redis（按环境选择 dev_user/pro_user）
- 1 个示例任务（例如打印/写库）验证 worker 可消费
- 如需要定时：beat 定时触发任务验证

## 7. 验收与自检清单（plan 阶段定义）

- **环境隔离**
  - dev 连接 `mindfulness_dev`，prod 连接 `mindfulness`
  - dev 的 Redis 凭证无法读写 `pro:*`，反之亦然
- **资源约束**
  - prod Redis `maxmemory=256mb` 生效
  - 不启用（或短 TTL）result backend，避免长期堆积
- **可运行性**
  - FastAPI 能启动并提供基础接口
  - Celery worker 能消费任务，beat（如启用）能触发定时任务

## 8. 风险与应对

- Redis 256MB 触顶风险：
  - 控制队列积压（worker 数量/并发）
  - 禁用或缩短结果存储 TTL
  - 任务 payload 只传 id
- 多环境同机误用风险：
  - 强制不同 ACL 用户 + 前缀
  - Celery 队列名带前缀，避免互相消费

