docs(m3): place create decisions in the contracts

- DATA-MODEL.md: storage engine (stdlib sqlite3 + schema.sql, no ORM/migrations),
  pragmas, per-test isolation.
- API.md: revision coupling, async job model, PUT check order, server-derived ready.
- PROMPTS.md: no prompt files ship; the DB is the only prompt source.
This commit is contained in:
2026-09-19 10:12:32 -07:00
parent 6435199f08
commit 2ba5428269
3 changed files with 17 additions and 4 deletions
+10 -3
View File
@@ -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
+5
View File
@@ -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`
+2 -1
View File
@@ -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