docs(phase2): reconcile requirements and migrate capabilities/contracts
Surface-matrix sweep of every source doc; added nine missed behaviors (METADATA-115, REVIEW-50, APP-55/60/65, SETTINGS-45 mode, Generate-text availability, defaults-off). 153 requirements, 0 coverage gaps. Migrated capabilities to docs/capabilities/ and contracts to docs/contracts/; added WOO-API, API, DATA-MODEL, PROMPTS, UX, TEST-SPEC. Populated MILESTONES; branch-neutral trunk docs; renamed umbrella term to Woo Slab Taxonomy. Archived reconciliation working records under .audit/archive/.
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
# 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.
|
||||
- The local slab row is deleted on successful publish; `sync_log` and `inference_log` are
|
||||
append-only and retained.
|
||||
|
||||
## 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 |
|
||||
| `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.
|
||||
Reference in New Issue
Block a user