WI-015 · Platform & Contracts · data-model-layers

Data authority & RLS foundation (tenants/memberships/roles/permissions/assignments, auth helpers, deny-by-default membership RLS, schema+migration contract, demo parity)

queued P0 high risk   Owner: Paul   0% · 0/5 tasks complete

Evidence
docs/technical/data-model.md; supabase/schema.sql

Goals

Consolidate the data-model layers in schema.sql (idempotent) with a documented owner-scoped RLS upgrade path (data-model.md).

Implementation — what to build

Spec (docs/specs/P6)

  • Membership/permission RLS from day one (no scattered owner_id=auth.uid()); demo = fixtures + no-op (never permissive prod policies); schema.sql=bootstrap, ordered migrations=authoritative.
  • Scan/validation storage persists the canonical P1 ScanResult + the P3 validation receipt AS-IS (the branded canonical shape minted by WI-012) — never a flattened projection; the stored shape is the contract shape P1/P2/P3 all speak.

Build (foundation)

  • tenants/memberships/roles/permissions/sale_team_assignments; private.* auth helpers (is_tenant_member/has_tenant_permission/has_sale_permission/is_buyer_owner); deny-by-default RLS template with WITH CHECK on insert+update; composite (tenant_id,id) FKs; migration ledger + schema.sql + generated types + demo parity.

Test (Supabase branch, real JWTs)

  • Empty-DB + prior-version upgrade migration; tenant A vs B isolation across personas; cross-tenant FK rejection; insert/update authority-field escape attempts blocked.

Gap-resolution expansion (D26, 2026-06-20)

  • Auth/identity foundation (account model, provisioning, buyer↔seller duality) + migration from nullable owner_id / using(true) MVP policies to membership RLS (closes G4/C18).

Secrets split (D34)

  • Model per-tenant credential storage in a private schema (encrypted, service-role-only); app-level secrets stay in the Cloudflare runtime, not the DB.

Checklist

  • Canonical layer: estate_sales, estate_sale_items, estate_sale_item_photos, estate_sale_ai_runs, estate_sale_exports, seller_profiles, discount_phases.
  • Marketplace/buyer + seller-intelligence layers (taxonomy/tags, saved_searches, watches, demand_signals, wishlist_matches, appraisal_recommendations, notifications, token_ledger…).
  • Tracking-identity (qr_codes / item_identity_bindings), disposition (buyer_offers / disposition_recommendations), ingestion layers.
  • inventory_status_events as the single audit trail for status + disposition transitions.
  • Idempotent DDL (run whole file) + taxonomy seed; document RLS: MVP permissive → owner_id = auth.uid(), buyer tables by buyer_id.

Gates & testing

  • P6 Data-model layers are consolidated (canonical, marketplace, seller-intelligence, tracking-identity, disposition, ingestion) with a documented RLS owner-scoped upgrade path.
    CODE TEST HITL QA

Requirements

  • REQ-PLAT-002 accepted Data-model layers must be consolidated with a documented RLS upgrade path.
    Done when: Canonical, marketplace, seller-intelligence, tracking-identity, disposition, and ingestion layers are documented with an owner-scoped RLS path.
  • REQ-PLAT-005 accepted The canonical seller data layer must model sales, items (with lifecycle/appraisal/demand fields), photos, AI runs, exports, seller profiles, and discount phases.
    Done when: estate_sales, estate_sale_items, estate_sale_item_photos, estate_sale_ai_runs, estate_sale_exports, seller_profiles, discount_phases exist in schema.sql with the documented fields.
  • REQ-PLAT-006 accepted The marketplace/buyer data layer must model taxonomy/tags, buyer profiles, saved searches, watches, saves, wanted items, match alerts, followers, notifications, tokens, submissions, discount codes, and appraisals.
    Done when: The listed buyer tables exist with buyer_id scoping ready for Auth.
    Spec: docs/technical/data-model.md (Marketplace/buyer)
  • REQ-PLAT-007 accepted The seller-intelligence layer must model alerts, demand signals, wishlist matches, appraisal recommendations, and status events.
    Done when: seller_alerts, item_demand_signals, wishlist_matches, appraisal_recommendations, inventory_status_events exist.
    Spec: docs/technical/data-model.md (Seller intelligence)
  • REQ-PLAT-008 accepted Documented upgrade paths must exist for pgvector (semantic search) and PostGIS (geo).
    Done when: Search/geo helpers (troveSearch haversine; FTS/RPC/Meilisearch later) have a documented path to pgvector/PostGIS without contract changes.
  • REQ-SEC-003 accepted Public QR/buyer pages must never expose private notes, internal pricing guidance, margin, consignor details, or seller PII.
    Done when: Public QR payloads use opaque IDs and resolve to buyer-safe pages; staff/binding views are auth-gated; internal pricing is hidden from buyers.
  • REQ-SEC-005 accepted RLS must move from MVP-permissive to owner-scoped on a documented path, and buyer tables scope by buyer_id once Auth lands.
    Done when: owner_id = auth.uid() policies are the documented upgrade for seller tables; buyer_id scoping activates with Auth.

Verify (done when)

Foundation/Authority domain (tenants, tenant_memberships, roles, permissions, sale_team_assignments) + authorization helper contract; deny-by-default, membership/permission-based RLS architecture with insert/update WITH CHECK; the additive upgrade-path stages (owner-only -> team -> sale-scoped); schema.sql current-state bootstrap + ordered-migration contract + generated types + demo-fixture parity; empty-DB + upgrade migration tests + tenant-isolation persona tests on a Supabase branch. Per spec section 58/59 (authority/RLS rows). Section 61 reconciliations tracked. **Wave-1 retro (D39):** the physical layer MUST be conformance-tested against the P5 in-memory reference (@trovesnap/ingestion-contract) — not hand-rolled — covering import-run idempotency, durable-media/temp-URL rejection, expected target item-version on merge/status/media, status-update & attach-media promotion decisions, and physical actor authz (membership/credential-scope/RLS).

Cost triggers

No paid API / infra spend triggered by this item.

Status & editing

queued   Sprint: P&C Wave 2: Core Contracts

Edit status / sprint on the ★ Live Board → — changes are logged live with who / when / why.

Human-in-the-loop

No human tasks linked.

Findings

None recorded yet.

Concerns

None recorded yet.

Risks

None recorded yet.

Tech debt

None recorded yet.

Tools used

No tool calls recorded.

Files & artifacts

No files / artifacts recorded.

Update log

No log entries yet.