Files
SlabUploader/docs/contracts/DATA-MODEL.md
T
Ty 63a99e8154 docs(m3): close create contract gaps (soft delete, publish poll, prompts, image volume)
- R1 soft delete: add deleted_at to slabs; exclude deleted rows from GETs
- R2 publish: terminal poll returns woo_product_id then the working row is
  discarded; the app never deletes from WooCommerce (reworks PUBLISH-25)
- R3 prompts: SQLite is the point of record; file-based prompts superseded,
  compose prompt mount removed
- R4 images: photo bytes are SQLite BLOBs; /images is a health probe + staging

Details recorded in .audit/m3-build-plan.md.
2026-09-19 09:28:53 -07:00

6.5 KiB
Raw Blame History

Data model contract

Status: SPEC · 2026-09-18. Store: SQLite.

Requirements impact

Requirement Impact on this design
APP-5 slab status enum and transitions
APP-20 ids, timestamps, revisions
APP-40 derived numbers stored, never recomputed
CAPTURE-25, CAPTURE-30, CAPTURE-70, CAPTURE-80, CAPTURE-85, CAPTURE-90, CAPTURE-95, CAPTURE-105, CAPTURE-115, CAPTURE-130, CAPTURE-135, CAPTURE-160 slab and photo columns, units, PNG
METADATA-5, METADATA-10, METADATA-15, METADATA-30 taxonomy cache tables and slab taxonomy columns
METADATA-35, METADATA-45, METADATA-55, METADATA-66, METADATA-105 inference columns, prompts tables, logs
PUBLISH-25, PUBLISH-30 purge on success, append-only log
REVIEW-10, REVIEW-25, REVIEW-45, REVIEW-50 prose, price, SKU, field limits
SETTINGS-5, SETTINGS-10, SETTINGS-20, SETTINGS-25, SETTINGS-30, SETTINGS-35, SETTINGS-50, SETTINGS-51, SETTINGS-55, SETTINGS-65, SETTINGS-90 settings, crypto, rates, taxonomy stamps

1. Conventions

  • Slab ids are client-generated UUIDv4; all other ids are integer autoincrement.
  • Timestamps are UTC ISO-8601 text.
  • Slab status is one of draft, calibrated, ready, publishing, published, failed.
  • Inches are stored as the rounded 1/8-inch value the user entered.
  • sqft and bdft are stored to 2 decimals half-up.
  • price is stored to 2 decimals half-up.
  • Multi-select taxonomy values are JSON arrays of Woo ids.
  • Secrets are stored as value_enc = nonce(12) || ciphertext, AES-GCM; the master key is the env SLAB_AES_KEY and is never in the DB.
  • On successful publish the local working slab row is discarded (photos purged, device draft cleared); sync_log and inference_log are append-only and retained. Nothing is deleted from WooCommerce.
  • Soft delete sets deleted_at (text, null until then) on unpublished drafts; deleted rows are excluded from all GET responses.
  • 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.

2. slabs

Column Type Constraint / default
id text PK, client UUIDv4
status text enum, default draft
sku text 3–24, alphanumeric and hyphen; unique locally
length_in real 1/8-inch step
thickness_in real 1/8-inch step
sqft real 2 dp
bdft real 2 dp
width_min_in, width_max_in, width_avg_in real 6-inch stations
species_id int FK woo_categories, one leaf
wood_category_ids json one or more leaf ids
edge_type_term_id int one term
figure_term_ids json one or more terms
grade_term_id int exactly one term
thickness_term_id int round-up band term
moisture_term_id int default kiln-dried term
fig_tag_ids json optional
feat_tag_ids json optional
price real 2 dp
price_source text recommendation | override
title, short_description, description text required non-empty; title warn >60, short_description warn >160
content_source text manual | llm | template
species_confidence, figure_confidence, grade_confidence real null below 0.7
inference_status text null | inferring | done | failed
calibration_photo_id text FK slab_photos
client_rev, server_rev int default 1
woo_product_id int null until publish
published_at text null until publish
deleted_at text null until soft-deleted; unpublished drafts only
created_at, updated_at text UTC ISO-8601

No inference_thread_id column exists; provider threads are not used.

3. slab_photos

Column Type Constraint
id text PK, UUID
slab_id text FK slabs
seq int capture order
is_calibration int (bool) exactly one true per slab
original_blob blob retained while draft/retry
processed_blob blob transparent PNG, alpha preserved
width_px, height_px int processed dimensions
created_at text UTC ISO-8601

The calibration photo exists; other batch photos are visual inventory only. Rows are purged on successful publish.

4. pricing_rules

Column Type Constraint
id int PK
species_id int FK woo_categories, UNIQUE
price_per_bdft real flat, no tiers
created_at, updated_at text UTC ISO-8601

5. Taxonomy cache

  • woo_categories — species and wood-category leaves only; parents group and are never assigned.
  • woo_attributes / woo_attribute_terms — exactly the five locked attributes Edge Type, Figure, Grade, Thickness, Moisture, with their terms.
  • woo_tags — only the fig-* and feat-* families; other store tags are ignored.

Rebuild is one transaction; on failure the previous cache is kept.

6. settings

Key Storage Default
woo_wp_username plain —
woo_app_password value_enc —
inference_base_url value_enc —
inference_api_key value_enc —
inference_model plain —
inference_enabled plain false
content_llm_enabled plain false
brand_voice plain —
geo_context plain —
woo_create_status plain draft
taxonomy_last_sync_at plain —
taxonomy_anchor plain —

WOO_BASE_URL is not a settings row; it is env, HTTPS only, read-only.

7. prompts and prompt_revisions

Prompts live in the database with all revisions; each call uses the active revision and the history is retained.

  • prompts: id, name (call1 | call2), active_revision_id, created_at, updated_at.
  • prompt_revisions: id, prompt_id FK, content text, created_at, created_by.

8. sync_log

Append-only; never deleted on publish. Columns: id, slab_id, woo_product_id, status (success | failed), payload_hash (sha256 of the outbound payload), message, created_at.

9. inference_log

Append-only audit. Columns: id, slab_id, call (1 | 2), prompt_revision_id FK, model, request_payload, response_payload, latency_ms, created_at.

10. Status transitions

draft → calibrated → ready → publishing → published, with failed reachable from any step and retryable. calibrated is set when the draft uploads; ready requires the full set.