# Poo Recorder 本文档说明 `poo recorder` 在 Python 项目中的当前行为边界,以及 poo SQLite 的 Alembic 接管策略。 ## 当前基线 当前生产版本中的真实 SQLite schema 为: ```sql CREATE TABLE poo_records ( timestamp TEXT NOT NULL, status TEXT NOT NULL, latitude REAL NOT NULL, longitude REAL NOT NULL, PRIMARY KEY (timestamp) ); ``` 历史上 legacy Go 实现使用: ```sql PRAGMA user_version = 1; ``` 当前 Python 迁移以这套 schema 为事实基线,不重新设计表结构。 ## 当前已迁入的 API 当前 Python 项目已经接入: - `POST /poo/record` - `GET /poo/latest` ### `POST /poo/record` 用途: - 记录一条 poo event - 最佳努力地刷新 Home Assistant sensor - 如果配置了 `POO_WEBHOOK_ID`,最佳努力地触发 Home Assistant webhook 请求体: ```json { "status": "done", "latitude": "1.23", "longitude": "4.56" } ``` 当前策略: - unknown field:`400 bad request` - 数值非法:`400 bad request` - 记录成功后,即使 Home Assistant side effect 失败,也不会回滚本地 DB 写入 ### `GET /poo/latest` 用途: - 读取最新一条 poo 记录 - 将其重新发布到 Home Assistant sensor 当前外部行为与 legacy 保持一致: - 成功:空响应体,HTTP 200 - 如果当前 DB 里还没有任何 poo 记录:仍返回空响应体,HTTP 200,但不会发布 sensor - 真正的发布失败:简洁 `internal server error` ## Home Assistant side effects 当前已复用 Python 项目中已有的 Home Assistant outbound adapter。 当前支持: - 发布 / 更新 poo status sensor - 可选触发 webhook 相关配置: - `HOME_ASSISTANT_BASE_URL` - `HOME_ASSISTANT_AUTH_TOKEN` - `HOME_ASSISTANT_TIMEOUT_SECONDS` - `POO_SENSOR_ENTITY_NAME` - `POO_SENSOR_FRIENDLY_NAME` - `POO_WEBHOOK_ID` ## Alembic 接管策略 poo 的接管逻辑刻意保持与 location 一致。 当前 baseline revision: - `20260420_01_poo_baseline` 当前提供的脚本入口: ```bash python scripts/poo_db_adopt.py ``` 或: ```bash python -m scripts.poo_db_adopt ``` 规则如下: 1. 如果本地不存在 poo DB 文件: - 视为新库初始化 - 通过 `alembic_poo upgrade head` 创建新库 2. 如果本地已经存在 legacy DB: - 先检查 `poo_records` 表 schema - 再检查 `PRAGMA user_version = 1` - 只有完全匹配,才通过 Alembic `stamp` 接管 3. 如果 schema 或 `user_version` 不匹配: - 直接失败 - 不自动修复 4. 如果数据库已经存在 `alembic_version`: - 只有 revision 与当前 baseline 一致才接受 - 否则直接失败 同时,应用启动时也会对 `POO_DATABASE_URL` 做只读校验: - 文件不存在:拒绝启动 - DB 尚未被 Alembic 接管:拒绝启动 - revision 不匹配:拒绝启动 ## 明确移除 Notion 这一轮不会迁入任何 Notion 逻辑。 也就是说,当前 Python 版的 poo recorder: - 不保留 Notion adapter - 不保留 Notion sync - 不保留 `tableId` 依赖 - 不因为 legacy 中存在 Notion 就继续保留兼容层