# Document Note Service · Batch 11 · local/dev notes backend **A-owned · session_a** File-backed FastAPI service exposing CRUD + aggregate endpoints for the document note system defined in `docs/assets/notes/document_note_schema.json`. ## Why Batch 6 shipped a per-doc notes loop backed by `localStorage`. That works as a scaffold but loses notes when the browser cache is wiped and cannot be seen across devices. Batch 11 adds a real persistence path. The Universal Document Shell tries the backend first and falls back to `localStorage` when offline — documented honestly with a mode badge. ## Run ```bash bash run.sh # 127.0.0.1:8091 ``` Environment: | Var | Default | Purpose | |-----|---------|---------| | `DNS_HOST` | `127.0.0.1` | bind host | | `DNS_PORT` | `8091` | bind port | | `DNS_STORE_PATH` | `./notes_store.json` | persistence file | ## Endpoints | Method | Path | Purpose | |--------|------|---------| | GET | `/api/notes/health` | liveness + counts | | POST | `/api/notes/create` | `{doc_id, title, body?, note_type?, priority?, section_ref?, created_by_type?}` | | GET | `/api/notes/list[?doc_id=…]` | list notes, optionally filtered | | PATCH | `/api/notes/{note_id}` | update status / linked_change_ref / title / body / priority | | DELETE | `/api/notes/{note_id}` | hard delete | | GET | `/api/notes/aggregate` | counters + top-5 open docs + recent activity | | GET | `/api/notes/by-doc` | per-doc summary | ## Example ```bash # Create curl -s -X POST http://127.0.0.1:8091/api/notes/create \ -H 'Content-Type: application/json' \ -d '{"doc_id":"/document-groups.html","title":"Add iconography","note_type":"design","priority":"P2"}' # List (all) curl -s http://127.0.0.1:8091/api/notes/list | jq # List by doc curl -s 'http://127.0.0.1:8091/api/notes/list?doc_id=/document-groups.html' | jq # Transition to done (PATCH) curl -s -X PATCH http://127.0.0.1:8091/api/notes/note-xxxx \ -H 'Content-Type: application/json' \ -d '{"status":"done","linked_change_ref":"abcd123"}' # Aggregate curl -s http://127.0.0.1:8091/api/notes/aggregate | jq ``` ## Honest state - **Local/dev only.** No TLS. No auth on these endpoints. - **Single-writer.** Running more than one uvicorn worker will lose updates — do not scale this service as-is. - **File persistence** via atomic rewrite (temp-file + rename). Fine for dev-sized backlog (/api/notes/list?doc_id=…` first. On success, notes are read/written through the backend. On any network error, it falls back to `localStorage[ds.notes:]` and the mode badge turns to `NOTES · OFFLINE · LOCAL`. Base URL resolution order: 1. `` 2. `window.DS_NOTES_BASE = 'http://host:port'` 3. default `http://127.0.0.1:8091` 4. `none` to disable backend entirely ## Non-goals (deferred) - Per-note auth (Batch 12+) - Transition history / audit trail - Multi-worker concurrency safety - Notifications - Cross-device sync beyond the single backend - WebSocket / SSE for live updates - Theme clustering ## Contracts - `notes_contract.json` — endpoint shapes - `../assets/notes/document_note_schema.json` — field spec - `../assets/notes/document_note_status_matrix.json` — state machine - `../assets/notes/document_note_backlog_model.json` — aggregate rules