diff --git a/docs/contracts/API.md b/docs/contracts/API.md index 786d8a4..3ac4bfb 100644 --- a/docs/contracts/API.md +++ b/docs/contracts/API.md @@ -36,7 +36,12 @@ The outbound WooCommerce payload is owned by `docs/contracts/WOO-API.md`. - **Envelope:** every error is `{ "error": { "code": string, "message": string, "detail": object|null } }`. - **Lists:** returned in full, no pagination. - **Revisions:** create/update carry `client_rev`; the server echoes `server_rev`; a mismatch is - `409 revision_conflict`. + `409 revision_conflict`. A background inference write bumps `server_rev`; the client adopts the + polled `server_rev` before its next write. +- **Async work:** inference and publish run through one in-process job queue with a single + consumer; a status transition is compare-and-set inside one write transaction, so a poll never + observes a half-applied transition. Tests run the queue inline so contract tests are + deterministic. - **IDs and time:** slab ids are client-generated UUIDv4; timestamps are UTC ISO-8601. - **Photos:** `multipart/form-data` with `data` (JSON), `files[]` (original images), and `meta[]` (`{ "seq": n }`). One photo is the calibration photo, chosen by the owner. @@ -108,8 +113,10 @@ completion. ### `PUT /api/v1/slabs/{id}` Partial update of editable fields plus `client_rev`. Stores client-sent derived fields and does -not recompute them. `409 revision_conflict`, `409 duplicate_sku` (SKU field actions `edit_sku` / -`open_existing`), `422 stale_field` (current options included). +not recompute them. Checks run in order: `409 revision_conflict`, then `409 duplicate_sku` (SKU +field actions `edit_sku` / `open_existing`), then `422 stale_field` (current options included). +`status` becomes `ready` only when the full required set is present; it is server-derived and a +client never sets it. ### `DELETE /api/v1/slabs/{id}` Soft delete of unpublished drafts only (sets `deleted_at`); `204`. Deleted rows are excluded from diff --git a/docs/contracts/DATA-MODEL.md b/docs/contracts/DATA-MODEL.md index 5c8349d..df7c27c 100644 --- a/docs/contracts/DATA-MODEL.md +++ b/docs/contracts/DATA-MODEL.md @@ -35,6 +35,11 @@ Status: SPEC · 2026-09-18. Store: SQLite. - Photo bytes live in `slab_photos` BLOBs; the `/images` volume is not a second store. It holds a health-probe file and short-lived staging for 1024 px Call-1 JPEGs and Woo media uploads, purged after use. +- The store is SQLite through the stdlib `sqlite3` module and a checked-in `schema.sql` + (`CREATE TABLE IF NOT EXISTS`); there is no ORM and no migration framework. Pragmas are + `journal_mode=WAL`, `foreign_keys=ON`, `busy_timeout`, `synchronous=NORMAL`, with one + process-wide connection behind a lock. The database path and image directory are explicit so a + test runs against isolated storage. ## 2. `slabs` diff --git a/docs/contracts/PROMPTS.md b/docs/contracts/PROMPTS.md index ee004fc..27c8652 100644 --- a/docs/contracts/PROMPTS.md +++ b/docs/contracts/PROMPTS.md @@ -19,7 +19,8 @@ Owns prompt storage, prompt inputs, and the two inference calls. ## 1. Storage and revisions - Prompts live in the database, not in text files, with all revisions retained. Tables are in - `docs/contracts/DATA-MODEL.md` §7. + `docs/contracts/DATA-MODEL.md` §7. No prompt files ship with the application; the database is + the only prompt source. - Each call reads the active revision fresh. - Editing a prompt creates a new revision; history is never overwritten. - Every generation is logged with its inputs, the request/response when a model was used, and the