# 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 就继续保留兼容层
