5.1 KiB
Python 骨架架构概览
本文档说明当前 Python skeleton 的职责边界与目录组织。它描述的是“后续迁移承载体”,不是完整业务实现。
当前目标
这一轮的目标是提供一个稳定、轻量、可持续扩展的基础工程,使后续可以逐步迁移:
- TickTick integration
- Home Assistant integration
- poo records
- location / life trajectory
目录设计
app/
应用核心代码目录。
main.py- FastAPI app factory
- lifespan
- 基础路由注册
config.py- 环境变量驱动的 settings
db.py- 统一数据层:一个
Base、一个绑定app_database_url的 cached engine(SQLite WAL)、get_engine/get_session_local/reset_db_caches/get_db_session
- 统一数据层:一个
dependencies.py- 通用依赖注入
api/- HTTP routes
api/routes/api/:JSON API(/api/*前缀),供 React SPA 调用:会话/鉴权、配置读写、数据查询、记录 CRUD- 裸 ingestion 端点:
GET /public-ip/check、POST /homeassistant/publish、POST /poo/record、GET /poo/latest、TickTick OAuth 等
models/- SQLAlchemy models
- 所有模型(auth / config / public_ip / location / poo)共用同一个
Base,均落在单一app.db中
schemas/- Pydantic schemas
services/- 业务服务层
- 当前已迁入 config page 的 DB 持久化逻辑
- 当前已迁入 public IPv4 检查、状态持久化与变化通知逻辑
- 当前已迁入 SMTP 发信与测试发信逻辑
integrations/- 外部系统适配层
- 当前已迁入 Home Assistant outbound adapter
static/- 极简静态资源
alembic_app/
App DB 的唯一 Alembic migration 链,同时管理 location / poo_records 表。M1 将三个独立 DB 合并进 app.db 后,alembic_location/ 与 alembic_poo/ 已退役,全部由此链统一管理。
tests/
pytest 测试目录。后续可以在这里自然扩展:
- unit tests
- mock tests
- integration tests
frontend/
React SPA 前端(M2 引入)。Vite + React + TypeScript + Mantine,由 FastAPI 同源托管。
src/:React 源码src/api/:由openapi/openapi.json生成的类型化 client(schema.d.ts)+ fetch 封装dist/:npm run build产物,由 FastAPI 的SPA_DIST_DIR挂载并对非/api路径做 fallback
scripts/
辅助脚本目录。当前包含:
export_openapi.py:导出 OpenAPI schema 静态产物run_migrations.py:运行 Alembic migrationapp_db_adopt.py:App DB 接管 / 初始化migrate_legacy_data.py:一次性历史数据搬迁脚本admin_cli.py:Admin CLI 逃生通道(M4),见下方"登录加固"说明
openapi/
OpenAPI schema 静态产物(openapi.json / openapi.yaml),由 python scripts/export_openapi.py 生成,纳入版本控制。前端 codegen 以此为契约源。
登录加固(M4)
M4 在基础 Argon2 + server-side session 鉴权之上叠加了三层防御:
防爆破 / 指数退避:app/services/login_throttle.py 按 client IP 与 username 双键记失败计数,失败超过 3 次后指数增长等待时间(最长 15 分钟),POST /api/auth/login 在退避窗口内直接返回 429 + Retry-After,不执行 Argon2 验证。成功登录后清零。退避是延迟而非永久封号;全局开关 AUTH_LOGIN_THROTTLE_ENABLED(CONFIG_FIELDS,默认开);反代后需设 AUTH_TRUST_FORWARDED_FOR=true(.env 部署级,默认 false)。
CLI 逃生通道:scripts/admin_cli.py(入口 python -m scripts.admin_cli)直连本地 DB,无需 HTTP 服务运行、无需任何已存凭据,支持:重置密码(reset-password)、解锁退避(unlock)、关停 TOTP(disable-totp,零凭据最终逃生)、重新发放 TOTP secret(reissue-totp)、查看用户列表(list-admin)。CLI 只动 auth 行,不触碰用户数据表。
可选 TOTP 二次验证:admin 可在设置页自选启用 RFC 6238 TOTP。启用后登录为两步(密码 → 6 位动态码或一次性恢复码);不启用维持纯密码。TOTP secret 明文存库(与其他 secret 一致,靠文件权限保护);恢复码以 Argon2 哈希存储,使用后消费(一次性)。后端使用 pyotp,二维码由前端 qrcode.react 渲染。issuer 标签由 AUTH_TOTP_ISSUER(.env 部署级)配置,默认回退 app_name。
详细说明:docs/auth.md
当前约束
- 当前数据库继续使用 SQLite
当前不引入前后端分离已退役(M2):现为 React SPA + JSON/api层,由 FastAPI 同源托管- 当前不设计 Notion 模块
- 当前通知能力仍保持极小范围,不引入独立通知中心或多渠道抽象
关于 Notion
Notion 在 Go 版本中仍是现状模块,但在 Python 重构中已经明确属于 removed scope。
因此当前 Python skeleton:
- 不提供 Notion integration 模块
- 不提供 Notion schema
- 不预留 Notion 相关业务流
如果未来需要回顾其历史作用,应继续参考 Go 版本和现有迁移盘点文档,而不是在 Python 骨架中保留它。