PURE · Consolidation · v6 · for Mike + Shattique

PURE Consolidation Master Plan v6

One review surface for the whole merge — live from the database, dictionary-correct, reversible, gate-sequenced. Sign-off drives the lanes.
0 / 9
phases approved
A working control surface, not slides. Approve a phase it records on the live board (audited, reversible with one Reset). Nothing builds until its phase is approved; Phase 0 (roles) is Shattique's first domino.
01

The one idea that shrinks everything

One permission fabric drives every surface, every org home, every upgrade gate.

We don't have 455 surfaces × 47 roles of chaos — we have three inputs that, multiplied, shape a handful of clean, permission-aware workspaces. Build the fabric once; every home, control plane and paywall derives from it. No duplication, no hardcoded per-person or per-org pages.

pure_surface_orgswhich orgs see a surface
×
pure_product_accesswhich products are bought
×
35 Roleswhat a Hat may do

Dictionary: a Hat is a person's active role context (agent, broker, client, vendor…); a Role is the permission set that Hat maps to. Org levels run Poppy 0 › PURE 1 › MLS 2 › Association 3 › Brokerage 4 › End users & parties 5 › Public 6.

1b

Five doors, one policy — how everyone gets in

The permission fabric has a human face: exactly five sanctioned, invitation- or admin-controlled doors. Public self-signup went OFF on 7/7 — no uncontrolled accounts. Underneath all five is one rule: one identity, many hats; you see only the rooms you're a party to (pure_my_rooms + RLS on auth.jwt email = party).

Door A · Staff & Agents

Admin invites set password confirm email enroll MFA choose hats home. The only door that creates a full account.

pure_admin_allowlistwelcome-hatspure_identity_hats

Door B · Leads & Marketing

Public form mcp_lead_create (anon, no account) routing agent claim. Marketing-to-orgs = Pure Growth + Morning Digest.

mcp_lead_createpure_leadspure_routing_rules

Door C · Testers (Dave's unit)

Guest Test Drive (no login) + admin-minted, revocable sandbox logins. is_demo isolation, reset-to-clean — never self-signup.

mcp_testdrive_createmcp_sandbox_mintis_demo

Door D · Clients

Their agent invites them scoped login / magic-link deep-linked into their Transaction Hub only — docs, milestones, tasks, e-sign for their deal.

pure_my_roomspure_room_partiesT-ROOM-INVITE

Door E · Vendors

Pulled into a deal as a role (title, lender, inspector…) Vendor Portal their permissioned slice only deliver work back in-system. Per-deal guest or persistent vendor org.

pure_vendor_jobspure_associationsT-VENDOR-PORTAL

The unifying primitive

Same Transaction Hub, three views — broker · client · vendor — one record, RLS-scoped per party. The grant model's clearest sales moment.

three views, one record
Full playbook: pure-access-playbook.html documents each door end-to-end. Canon: canon.user_signups · canon.auth_providers · process.client_access · process.vendor_access · process.lead_capture · process.test_users. Open build items: T-ROOM-INVITE (invite client/vendor from the deal + external-party RLS), T-VENDOR-PORTAL, T-CLIENT-BUYER-LEADFORM.
1c

Auth-window hardening — shipped this session (7/7/26)

A full pass over the auth surface — all live and documented to canon, reversible where it matters. This is the security spine the auth window sits on.

Sign-in & accounts
  • Public signups OFF invite-only (36 users, all confirmed). canon.user_signups
  • Anonymous sign-ins OFF · Confirm email ON · Manual linking ON.
  • Passkeys ON — RP acquisto.biz, prompt shows "Pure MLS Technologies".
  • OAuth Server confirmed OFF (PURE isn't a third-party IdP).
  • Providers: Email + Google on; all else off. Future: Phone/SMS, SAML/WorkOS. canon.auth_providers
Security & email
  • Leaked-password block ON. Captcha OFF pending front-end — Cloudflare Turnstile chosen (T-CAPTCHA-TURNSTILE).
  • Audit logs written to DB; auth_audit_prune cron built (jobid 208, daily 3am CT, 90-day retention, rolls a permanent daily aggregate). runbook.auth_audit_prune
  • Email hook rebuilt v14: Open Sans (canon), dedicated MFA verification-code email; Send Email hook active; repo synced (commit 12f6696e). runbook.auth_email_hook
  • Enforce SSL on DB connections — verified safe (every external conn already TLS). canon.ssl_enforcement
New DB objects this session: mcp_auth_audit_prune, pure_auth_audit_daily, cron auth_audit_prune (208). New tickets: T-ROOM-INVITE · T-VENDOR-PORTAL · T-CLIENT-BUYER-LEADFORM · T-CAPTCHA-TURNSTILE · T-PROVIDER-PHONE · T-PROVIDER-SAML. Everything logged to pure_memory + pure_board.
1d

Data exposure — anon write holes, routed to Shattique

Verify-first found the real gap behind the advisor CRITICALs: public tables are writable by anyone holding the public anon key (RLS off + a blanket write grant). Most are internal queues/logs; a handful are sensitive. Owner: Shattique — the security.rls_exposure level-down.

Sensitive — close first
loading
The fix — read-safe & reversible

Revoke anon write (INSERT/UPDATE/DELETE) on the internal tables — leaves SELECT so pages keep reading, and PURE writes ride SECURITY DEFINER RPCs that bypass grants. Not policyless RLS — that is deny-all and would break direct reads like pure_hats.

Sequence-guarded: snapshot grants confirm nothing writes these raw revoke sensitive first verify RPCs. The live count above ticks to 0 as holes close. Ticket t-rls-writeholes-45 · canon security.rls_writehole_finding.
02

Live proof — real data, not slides

loading
Every number is pulled live from the platform database at load. If it renders, it's real and in production today.
03

Every page, accounted for

You asked to find all pages — live, deployed, and not-yet-deployed — and fold them into this plan. Here's the live count from the governance registry, plus the reconciliation gap the nightly orphan sweep closes.

loading
Navigation registry — all 20 groups (live)

345 active pages across 20 groups, straight from the Full Site Index you reviewed on the call. Amber = collapses into one Transactions group · red = Reference dumping-ground to triage.

Consolidation math. Three transaction groups — Transaction Hub (20) + Transactions & Forms (4) + Transactions (1) = 25 rows — collapse into one Transactions group (Phase 4; Phase 5 folds Pure Signature in). Reference (141) is the dumping-ground dedicated triage, re-homed or parked via the Boneyard. Admin / Tech (50) one Control Plane (Phase 3). The registry also carries two overlapping taxonomies (the h-* home groups vs the functional groups) merged to one.
The gap between ~615 deployed HTML files in the repo and the registered surfaces is exactly what the orphan sweep reconciles: every deployed page must be registered (kill-switch + owner + per-hat visibility) and every registered page must resolve or be parked. Parked pages live in the Boneyard — never deleted. Admin control surface: pure-lane-control.html and the Site Control tab in the Admin Console.
04

The 9 phases — each reversible, each gates the next

Loading phases from the live board…
Sequence gate: a phase can't start until the one before it is approved. Phase 0 (roles) unlocks the rest. Every apply is reversible — Reset returns a phase to open and the board keeps the prior state in undo.
05

Pure Signature & Pure Legal Forms — best-in-class field engine

Native-first. Pure Signature (dictionary canon; "Pure Sign" is the alias) and Pure Legal Forms own the experience; BoldSign / BoldForms are swappable backup engines behind them — the same multi-provider pattern as email and SMS. Documents lock with TrustSeal (SHA-256 hash chain "TrustSeal Verified" badge). We extend the real spine already in the DB — not a rebuild.

Field types — and required vs optional is first-class
SignatureInitialDate signedName Text · number · currencyDate pickerMasked (SSN/EIN) Radio groupDropdownPick list · multi-select Checkbox · groupAttachmentFormula / calcPayment field

required vs optional — both pure_envelope_fields (placed signing fields) and pure_form_fields (data fields) already carry a required boolean, so the engine knows which each is. Conditional rules can flip it at runtime (make-required / make-optional). Radio · dropdown · pick list added per your ask.

Conditional logic — a real rule engine
WHEN field operator value THEN action on target

Operators: equals · not-equals · checked · contains · > / < · is-empty · is-filled · in-list. Actions: show · hide · require · make-optional · enable · set-value · add-signer · jump-to-page — with AND/OR grouping. Past BoldSign's checkbox-only limit: "if Buyer selected add the buyer's-agent signer and require the financing addendum" is one rule.

Two authoring modes

Manual (admin): render the PDF, drag widgets onto it, set required + rules in a panel. Automatic (Claude tool): reads a TREC/TXR form, auto-detects fields + likely conditions, confidence-scored (high auto-places; low flags for review), proposes a reusable template for approval. Templates key to all Pure Legal Forms; ESIGN/UETA certificate + TrustSeal hash for legal weight.

Signers Roles the Transaction Hub — how they map
transaction_partiesdeal_id · role · display_nameThe deal roster: who's on this transaction and in what role (buyer, seller, listing agent, lender, title…).
pure_envelope_signersseq · verify_method · party_id · deal_idWho signs which envelope, in signing order, how they verify — tied back to the party + deal.
Transaction Hubdeals + pure_roomsThe one workspace (canon; "Deal Room" is the alias) where parties, forms, signatures, dates & money for a deal live.

One deal_id threads it end-to-end: a transaction Role becomes a signer with a signing seq and verify_method, and the executed PDF files back to Doc Vault under the same deal — visible on the Transaction Hub timeline.

5b

Pure Validate — one regex layer, clean data everywhere

Bad data enters at the field — so validation is a central module, not scattered per page. Named patterns defined once and reused by Pure Legal Forms, Pure Signature, every intake RPC, and CSV imports: build once, validate everywhere. Each pattern normalizes on input (phone digits, name Title Case, currency number) so data lands clean, not just rejected. 14 patterns are live now:

loading…
Every field ties to a validator by name (data, not code) and carries required/optional. Block stops a bad save; warn flags it. Conditional rules can make a field required; the validator still governs its shape. Admins add or tune patterns with no deploy.
Recommendations
  • Regex as data — admin-editable registry + a test panel that runs sample inputs before save.
  • RE2-safe guard — cap pattern complexity so a bad regex can't hang the page (no catastrophic backtracking).
  • One evaluator (mcp_validate) in Forms + Sign + intake + import = no logic drift.
  • Nightly quality sweep over cdas / leads / listings a quality score + bad-row tickets (auto-catches the “Aproved” misspelling class).
Why a module, not a field option

A TREC license #, an MLS #, an APN, a routing number — each has a shape. Define it once and a fix or a new format propagates to every surface instantly, and Poppy can propose new patterns from the bad data it sees. Same “define once, run everywhere” spine as the conditional-rule evaluator.

contactidentitymoneyreal-estatedateweb
5c

Pure Metrics — one headless BI & ETL spine, not another dashboard

You didn't start on BI — you started everywhere on it. The recon found a sprawling, half-built reporting estate, so the fix isn't a new tool: it's one headless spine that unifies what already exists — the same registry-and-cron pattern behind the Design System and Governance.

Already built — the consolidation target, not a rebuild
~40 report / digest / status RPCsmcp_daily_rollupmcp_roi_reportmcp_comms_analyticsmcp_nav_analyticsmcp_poppy_daily_brief pure-analytics.js trackerpure-report.js libutility-bi-reports.sqlmcp-report-extract fn~14 report / dashboard pages

In flight: BI-REPORTS (open) · t-insource-analytics (retire Google Analytics) — plus 4 dashboards awaiting review: Seller · Buyer · Broker rollup · TC-close. Pure Metrics folds these together; it does not duplicate them.

The spine — five layers
1 · Registrypure_metricsEvery metric defined as data (key · source · grain · refresh · owner). Add one with no deploy.
2 · Rollups + cronspure_metrics_dailyOff-hours CT-gated refresh pre-aggregates — dashboards read cheap rows, not heavy live queries.
3 · One RPCmcp_metrics(key,params)Every surface reads one definer RPC — wrap the ~40 one-offs, don't rewrite them.
4 · Thin dashboardspure-table standardSortable / searchable renderers over the RPC. Ship the 4 in-review first.
5 · DeliveredPoppy · Morning DigestThe same metrics feed digests + email — BI is delivered, not just viewed.
Headless ETL — Edge + cron, no server

Ingestion runs as Edge Functions on a schedule, not a separate ETL box: first-party events from pure-analytics.js pure_analytics_events daily rollup (retires GA); external pulls (MLS / RETS via rets_sync_state, Zoho, connectors) normalized into fact tables. Fail-soft, audited, reversible.

Why headless is the secure choice

Because the ETL lives inside Supabase (Edge + cron), nothing connects to Postgres directly — so Network Restrictions stay fully closed and Connection Logging stays off. No BI tool, no ETL box, no open DB port. The headless path is the hardening.

Sequence. (1) Finish t-insource-analytics + land pure_analytics_events retire Google Analytics. (2) Ship the 4 in-review dashboards on mcp_metrics. (3) Register the ~40 existing RPCs into pure_metrics + add off-hours rollup crons. (4) Wire Poppy / Morning-Digest delivery. Every step reversible — approve as Phase 7 above.
5d

System of record — PURE replaces Zoho & FUB, one object at a time

The endgame: PURE is the single system of record for Acquisto Real Estate, Poppy running it — Zoho (today's SoR) and FUB retired. The danger in any cutover is losing data mid-switch, so we never flip blind: every object migrates through the same five-step play, and each external system retires independently on your word.

The play — repeated per object
1 · ParitychecklistConfirm PURE captures everything Zoho/FUB do for this object before anything moves.
2 · Mirror outPURE Zoho + FUBPURE is master; new records mirror outward. Leads: live first.
3 · Backfill inZoho PUREPull ALL existing + incoming records so nothing is missed while entry still happens outside PURE.
4 · Cutoverkill-switchFlip one destination off (config.lead_sync_targets) once PURE reaches parity — no code change.
5 · VerifyreconcileReconcile counts + spot-check, then retire the external system for that object.
Leads first — pull every Acquisto source

Zoho is the aggregator: website, Zillow, Realtor.com, FUB, referrals, campaigns, open house, sign calls, manual. We enumerate the live Lead_Source list (never hardcode) and ingest all of it into pure_leads, source-tagged and deduped against the outbound mirror so nothing loops. Both Zoho + FUB stay updated meanwhile.

Order & ownership

leads contacts/people deals tasks/follow-ups email & notes calendar. Each object is a mirror-out + backfill-in pair with its own kill-switch. Poppy orchestrates each migration and reports; you retire Zoho, then FUB, on your word.

Live parity snapshot
Loading live counts…
Phase 8 migration — dry run
Loading leads dry run...
Now. The outbound leads mirror (PURE Zoho + FUB) and the inbound pull of all Zoho lead sources are building. As parity proves out, flip destinations off one at a time. Approve the full sequence as Phase 8 above.
06

Acquisto Real Estate — real working tools, live & dynamic

Not demos. They run on ARE's real data and become the reference implementations every brokerage inherits.

CDA — learned from ARE's own history

Built on 611 real Acquisto CDAs. Offer-accept deal auto-CDA bridge is live; the payee model (referral / franchise / mentor / expenses) came from ARE's Zoho export. The CDA referrals deal assignment / routing loop runs dynamically on live data — not a static page.

cdas · liveofferdealCDAdeal routingreferral portal

Pure on Pure — Mike's business runs on it

Real ARE ops already in the platform: the Jose Landscaper equipment-loan ledger ($14,855 financed, service-income offset in Pure Books), intern logs, mow logs. People onboarding writes real identities/Hats. Phase 6 made literal — the product proves itself on the owner's own business.

Pure Books ledgerpeople onboardingdeal-completeness score
Deal-completeness score is live end-to-end as of this pass (Code + Lane C): /deals renders real artifact scores on every load — the fail-soft ship-ahead pattern proven. Recommendation: promote CDA / referrals / routing from "examples" to first-class working tools, and the ARE ledgers as the template for every brokerage's books.
07

The 4.8 gold — harvested, not lost

You said it exactly right: there's real gold in the old versions — don't lose it. The move is surface review harvest the gold into the improved version park the rest to the Boneyard (never delete), with a way to walk back through every old version.

HarvestAny feature an old page did better folds into the current twin before retirement.
Old Versions MuseumBoneyard becomes a navigable index — open any retired version, see its successor via the ribbon.
Never deletedPark records a named successor + 301; Restore un-parks in one click; 90-day cold review always asks you first.
First harvest pass = the Area Reconciliation review (CDA/CRM/MLS/LEGAL/TXN): no distinct 4.8 files remain, the current twins are canonical, one real Transaction overlap to tidy. Open that review
08

Pure Mobile — the field app

Where agents live in the field. Scoped capabilities (t-pure-app, P1):

MFA sign-inLocation + agent safetyPhoto upload listingsSign on the goDL / ID verifyNFC lockbox + showingsPush notifications
Kept honest by a nightly cross-browser/device sweep (pure_mobile_health across chromium/webkit/firefox × iPhone/Pixel/iPad) + real-user monitoring — regressions auto-file board tickets. Best use: capture-in-the-field (photos, signatures, showings) flows straight into the same live tables the desktop uses.
09

Steps & actions — what happens, in order

Shattique · now

Approve Phase 0 — role reconciliation (47 35)

The first domino. Approve on this page; reversible apply via pure_role_reconcile. Unlocks Phases 1–3.

Lane A · on P0 approval

Tag surfaces by audience, derive per-org homes

Populate pure_surface_orgs (384 untagged surfaces), then homes + control plane build themselves from tags. No new per-org pages.

Lane A + Code · Phase 4

Fold into the Transaction Hub

Pure Legal Forms · Pure Signature · Doc Vault · timeline · comms become deal-scoped tabs on the Hub; collapse 3 nav groups 1. Anchor already shipped 6/26.

Lane A + Code · Phase 5

Ship the Pure Signature field engine

Required/optional fields + radio/dropdown/pick list + conditional rules; manual + auto (Claude) authoring; formssignvault loop; BoldSign fallback.

Mike · your nod

Approve the lane-b cleanup park list

Not an emergency (see Execution). I generate the park list — each frozen lane-b page its canonical replacement — for your one-look approval, then execute through the Boneyard.

Continuous

Harvest 4.8 gold park the rest

Area-by-area, each old page's best features fold forward before it's parked into the navigable Old Versions Museum.

10

Execution — reversible, lane-owned, gate-sequenced

  • Lane A (Fable 5) — UI / nav / per-org homes / control plane / Design Studio / Pure Signature editor + auto-mapper.
  • Code (5) — RPCs / entitlements / condition evaluator (build once, run in ceremony + preview + validation) / signing / webhooks.
  • Shattique — Phase 0 role approval (35 roles) + infra. The first gate.
  • Parallel: Design Studio (Cecile) — build native with a Figma-or-native toggle; do not retire Figma.
Honest correction (Code B, this pass): the earlier "8-page 404 crisis" was overstated. Verified directly: the hubs link those pages as /lane-b/… routes that resolve fine — the only real cross-lane 404 was deal-room-spine, fixed by redirect to /transaction-room (commit 722d7e9), not by promoting 8 pages. So the lane-b subtree isn't breaking anything — what remains is methodical, sign-off-gated cleanup (~79 frozen lane-b stragglers Boneyard), not an emergency.
Every phase is reversible and additive; claim-before-edit prevents lane collisions; live-first with one-step unwind. Live admin control surface: pure-lane-control.html. Approve a phase above it records on the board and the owning lane starts. Revise I adjust before release.