Files
SlabUploader/docs/contracts/TEST-SPEC.md
T
Ty 01aa4c52c3 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/.
2026-09-18 21:02:06 -07:00

153 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Test spec contract
Status: SPEC · 2026-09-18 · reconciled against the finished PoR.
Defines the affirmative test bar. It cites requirement IDs; `docs/REQUIREMENTS.md` is normative.
The human walkthrough is `docs/UAT-PRACTICE.md`.
## Requirements impact
| Requirement | Impact on this design |
|---|---|
| QUALITY-5, QUALITY-10, QUALITY-15 | TDD for the deterministic core; vectors TV-1..TV-10 |
| QUALITY-20, QUALITY-35, QUALITY-50 | inference-off suite, Woo-mock integration, Compose UI E2E |
| QUALITY-25, QUALITY-30 | evidence rules; Ty owns gate exit |
| QUALITY-40, QUALITY-45 | property checks and bdft identity |
| QUALITY-55 .. QUALITY-100 | pipeline vectors |
| QUALITY-105, QUALITY-110 | dishonest proxies; M3 exit evidence |
| QUALITY-115, QUALITY-120, QUALITY-125 | browser E2E, no raw codes, AES round-trip |
| APP-45, APP-55, APP-60, APP-65 | health, logging, accessibility, log redaction |
| SETTINGS-80, PUBLISH-30/31/35 | failure handling under test |
## 1. Layers and harness
| Layer | Written | Location | Rule source |
|---|---|---|---|
| Unit | TDD before the code exists | `backend/tests/unit/`, `frontend/src/__tests__/` | deterministic core and validation |
| API contract | with the feature | `backend/tests/contract/` (pytest + httpx TestClient) | `docs/contracts/API.md` |
| Integration | with the feature | `backend/tests/integration/` (respx Woo mock) | `docs/contracts/WOO-API.md`, `docs/contracts/CONTENT-WOO.md` |
| UI / E2E | with the feature | `frontend/e2e/` (Playwright, Compose stack, mocked Woo) | `docs/contracts/UX.md` |
| Ops | with deploy config | `deploy/tests/` (shell) | `deploy/` |
Allowed results are `pass`, `fail`, `not run`, and optionally `blocked`. Every `pass` or `fail`
needs runner evidence; no evidence means `not run`. The only bug log is Gitea issues. Ty reads raw
results and owns gate exit; an agent never declares a gate green (`QUALITY-25`, `QUALITY-30`).
## 2. Fundamentals (FUND)
- FUND-1..4 — no browser/DOM/network deps in pure tests; semantic selectors; real Tab navigation;
reactivity flush. (test practice)
- FUND-5, FUND-6, FUND-7 — Tab order, 320 px reflow, visible focus ring → `APP-60`
- FUND-8..11 — app factory per test, lifespan, override cleanup, no real network (test practice)
- FUND-12, FUND-13, FUND-16 — FK and constraint enforcement, migration integrity (test practice)
- FUND-14 — WAL with no stale reads (test practice)
- FUND-15 — illegal status transitions rejected → `APP-5`
- FUND-17 — fresh nonce per encrypt; tamper fails → `SETTINGS-25`
- FUND-18 — ciphertext absent from GET; only configured booleans → `SETTINGS-75`
- FUND-19 — missing key refuses startup → `SETTINGS-25`
- FUND-20 — Basic Auth with application passwords over HTTPS, not consumer keys → `SETTINGS-15`
- FUND-21 — 401/400/404 mapped, not passed raw → `APP-50`
- FUND-22 — pre-create SKU lookup, duplicate race → `PUBLISH-15`
- FUND-23 — timeouts/network errors graceful, no stack → `PUBLISH-30`, `PUBLISH-35`
- FUND-24 — no secret material in logs → `APP-65`
- FUND-25 — HTTPS, health through proxy, port collision → `OPS-5`, `OPS-15`, `OPS-20`
## 3. Deterministic vectors (TV)
- TV-1 — green patch not touching the border survives; U2Net not invoked → `QUALITY-55`
- TV-2 — dark interior wood survives; flood fill isolates border-connected regions → `QUALITY-60`
- TV-3 — 96 in, 1.5 in, 0.64 sqft yields 0.96 bdft; 1 sqft at 1 in equals 1 bdft → `QUALITY-65`
- TV-4 — 6 in stations on a 96 in axis report min, max, average → `QUALITY-70`
- TV-5 — one square end, one 45 degree cut; axis follows prevailing length → `QUALITY-75`
- TV-6 — 3:4 crop, 90 percent fill at extremes, transparent PNG, 800 px floor → `QUALITY-80`
- TV-7 — undersized source warns, is not upscaled, not publishable until retake → `QUALITY-85`
- TV-8 — 0.96 bdft at 12.50 gives 12.00; a 150.00 override is stored → `QUALITY-90`
- TV-9 — 1 in rounds up into the synced Woo thickness band → `QUALITY-95`
- TV-10 — half-up 2 decimal rounding cases → `QUALITY-100`
Validation:
- SKU charset 3–24 alphanumeric and hyphen → `REVIEW-45`
- title/short_description/description within limits → `REVIEW-50`
AES:
- round-trip decrypt; ciphertext never in GET → `QUALITY-125`, `SETTINGS-75`
- missing key refuses startup → `SETTINGS-25`
API contract / health / draft:
- `GET /api/health` shape and non-200 on DB/volume failure → `APP-45`
- `POST /api/v1/slabs` multipart returns 201 calibrated → `docs/contracts/API.md`, `APP-5`
## 4. Gate C and Woo
- `SLAB-UAT-*` creates a draft regardless of setting → `PUBLISH-10`
- duplicate SKU before create returns 409 with `edit_sku` / `open_existing` → `PUBLISH-15`
- test-woo ok, resyncs taxonomy → `SETTINGS-40`
- WOO_BASE_URL read-only, PUT rejected → `SETTINGS-5`, `SETTINGS-85`
- startup refuses missing or http WOO_BASE_URL → `SETTINGS-10`
- Woo create stores `woo_product_id`, purges images → `PUBLISH-25`
- Woo 409 mapped to field recovery, draft retained → `PUBLISH-15`
- taxonomy anchor unchanged on no-op, bumps on change → `SETTINGS-55`
- failed publish marks failed, keeps photos, writes sync_log, retries to success → `PUBLISH-30`
## 5. Inference
- with inference off: Call 1 skipped, no inference calls, suite passes → `METADATA-75`, `QUALITY-20`
- test-inference returns ok, mode stateful/stateless, vision_capable → `SETTINGS-45`
- test-inference fail blocks Call 2 only → `SETTINGS-45`
- Call 1 at or above 0.7 pre-fills; below stays empty; override wins → `METADATA-45`, `METADATA-50`
- Call 1 sends clean processed photos at 1024, synced taxonomy, user metadata → `METADATA-35`
- Call 2 user-triggered only, fresh full context → `METADATA-55`, `METADATA-60`
- model does not invent dimensions → `METADATA-65`
- generation logged → `METADATA-66`
- prompts stored with revisions → `METADATA-105`
## 6. UI end-to-end (UIE / E2E)
- capture controls, overlay, axis, numbers, ready gates → `CAPTURE-40`, `CAPTURE-45`, `CAPTURE-50`,
`CAPTURE-60`, `CAPTURE-70`, `CAPTURE-80`, `CAPTURE-85`, `CAPTURE-90`, `REVIEW-5`, `REVIEW-20`
- review pre-fill and editability → `METADATA-45`, `REVIEW-40`
- duplicate SKU, stale value, success, failure messages → `PUBLISH-15`, `PUBLISH-20`, `PUBLISH-25`,
`PUBLISH-30`, `PUBLISH-35`
- inference-off content path, Generate text disabled → `METADATA-70`, `METADATA-110`
- settings screen and read-only URL → `SETTINGS-5`, `SETTINGS-15`, `SETTINGS-20`, `SETTINGS-30`,
`SETTINGS-35`, `SETTINGS-65`
- cross-browser capture through publish → `QUALITY-115`
## 7. API surface
- revisions and conflict → `APP-20`
- PUT stores derived, no recompute → `APP-40`
- secrets absent from GET → `SETTINGS-75`
- infer-taxon/content 202 and poll; timeout → `METADATA-35`, `METADATA-115`
- publish preconditions → `REVIEW-5`
- taxonomy sync, anchor, cache retention → `SETTINGS-50`, `SETTINGS-55`
- delete soft, published undeletable → `docs/contracts/API.md`
- test-woo fails closed → `SETTINGS-80`
- taxonomy re-pull and 1 hour publish refresh → `SETTINGS-60`
- species picker synced only → `METADATA-5`
## 8. Ops and instrumentation
- compose health, inventory, test-woo, draft status → `OPS-15`, `SETTINGS-40`, `SETTINGS-65`, `APP-45`
- backup and restore retention and cycle → `OPS-30`, `OPS-35`
- health non-200 on DB/volume, `woo_reachable` false → `APP-45`
- request id in logs → `APP-55`
- inference_log and sync_log written → `METADATA-66`, `PUBLISH-30`
## 9. Purged cases
Removed because the behavior was superseded: four-knob cases (edge offset, feather), the shared
validation module and its 412 path, `previous_response_id` and the per-slab thread, "inventory
photos" as the Call 1 input, prompt files edited without restart, 80 percent / 1600 px crop values,
and manual override of the computed fields.
## 10. New cases
- keyboard tab order, focus ring, and 320 px reflow → `APP-60`
- no secret material in any log output → `APP-65`
## 11. Rules that do not change
Inference is optional and the full suite passes with it off. `bdft = sqft × thickness_in`, no
divide-by-12. The client is authoritative for deterministic math; the server stores the numbers.
No new product locks live in this document.