Fibretrace Monet docs/Start here/Master Report

Master report — 2026-08-19: Lovable sync, QC script analysis, business-logic knowledge base

Written by the coordinating session (monet-master) after collecting debriefs from both worker sessions (qc-script-analysis, biz-logic-kb) via direct session messaging and independently re-reading every deliverable on disk. Where a session’s claim and the files disagreed, the files won and the disagreement is recorded below. A reader who has seen none of the underlying documents can read this top to bottom and be fully caught up.

Update 2026-08-20 (session monet-003): two items from the list below were checked directly. T88 is closed — the revoked CHECK bug is real and is now Rank 7 as a finding. The security item was rewritten and escalated from Rank 7 to Rank 2: the exposure is Lovable’s Supabase RLS being open to anon for read and write, which voids the public-token gate; it is tracked as the new task T91 and leads the T86 question list. Section 5 ranks were renumbered accordingly; KB 06-open-questions.md Q10/Q12 carry the full evidence.

1. What happened today, in order

Three bodies of work landed on 2026-08-19, each building on the previous one.

First, in the morning (06:41 UTC), the scheduled Lovable sync ran (flow-ft-lovable-sync, run wf_70fb9c32-51f, 44 agents, clean git-first pull): it analyzed 781 Lovable commits (2.5 days of autosave, 2026-08-16 to 2026-08-19) against monet’s port cursor and produced a 29-unit port plan. Deliverables: .local/lovable/sync-20260819/port-plan.md, RUN-SUMMARY.md, plus updated cursors in .local/lovable/state.json and a new top entry in .local/lovable/CHANGELOG.md.

Second, in the evening, a dedicated session analyzed the FibreTrace QC Test Script v1.0 that Malcolm sent the same day (a 50-case, 6-section test script for the platform). Deliverables: .local/qc-test-script/test-cases.md (faithful condensed cases), analysis.md (route census, business-rule cross-check, test-environment build order, script defects, tester split, 11 questions for Malcolm), and the raw extracted.txt/fibretrace-qc-test-script.docx.

Third, late evening, a second session re-derived the entire FibreTrace business logic from scratch, treating every prior document (July walkthroughs, ~195 memory records, backend specs, the QC analysis, the sync plans) as a prior to be re-verified against code — the Lovable clone at origin/main (ffab85ca), the Supabase migrations, apps/dashboard’s adapter, frontend-canvas, and apps/sat. Deliverable: a 15-file knowledge base at .local/business-logic/knowledge-base/ (overview, domain model with ERD, lifecycles with state-machine SVGs, glossary with 8 terminology collisions, 45 rules and invariants, per-persona files, implementation-state matrix, 20 ranked open questions) plus a self-contained offline portal.html. Every claim carries a confidence marker: 343 VERIFIED (code/migration citation), 63 STATED (asserted, uncited in code), 11 INFERRED, 16 UNKNOWN.

Both worker sessions answered the coordinator’s debrief request directly, and their off-disk knowledge (method, mid-run corrections, what they could not verify) is folded into section 7.

2. The Lovable sync result and what it means for porting

The window 0df29e60 -> f0d02a28 resolved to 29 units: 7 PORT, 14 REVIEW, 8 SKIP, 0 ALREADY_DONE (.local/lovable/sync-20260819/RUN-SUMMARY.md). The headline is the API resolution: of 12 data-bearing specs, EXISTS = 0, GAP = 9, PARTIAL = 3 — nothing data-touching in this window can be wired to the real backend today. All portable value this pull is visual/structural.

Ready to port now, in dependency order (all tracked as tasks, section 6): the button.tsx design-system rebrand (new tertiary variant, white table pill, radius 8 to 10px, unified h-9 CTA heights, action variant green to primary — a global change, Button renders in ~86 files), then tabs.tsx pill restyle plus a brand-new shared table-pagination.tsx, then three pure-UI units: Partners moves out of Settings into main nav (/partners with redirect), SDU page polish, and supply-chain copy/chip alignment (.local/lovable/sync-20260819/port-plan.md units 1-5).

The nine GAP units all cluster in the claims/PO/nominations domain (Ready-to-Claim rewrite, Nominations rewrite, ClaimPosition redesign, owner dashboard, reservation expiry model, etc.). Porting their visuals would only add more toast-guarded empty shells on top of the five tracked since June — a deliberate scoping decision, not a default (RUN-SUMMARY gap 2, now task T90). Each GAP unit carries a ready-to-file beSpecForGap for the backend team.

One real defect was found in the sync run itself: the plan claims index.css shows no diff, but monet is missing the .tier0-quiet typography demotion block and the Mona Sans 800 font weight — drift from Lovable commit 90b49e35 (2026-06-27) that PRE-DATES the sync baseline, appears in no future commit window, and has no known_unported entry. The window-independent completeness pass is the only mechanism that can ever surface it, and this run’s pass compared only colour tokens, so the item was at risk of permanent silent loss (RUN-SUMMARY gap 1). It is now task T80 (port it, ~7 lines, no BE dependency) and T89 (harden the completeness pass so this class of drift cannot slip again).

Cursor state after the run (.local/lovable/state.json): last_fetched_sha = f0d02a28, last_ported_sha = 2b52a608 (auto-advanced 67 commits over an evidence-verified prefix; independently re-verified in the RUN-SUMMARY), 10 known_unported entries. The suggested full advance to f0d02a28 should be accepted only after port-plan units 1-5 actually land.

3. The QC script analysis and its consequences for the QC round

Malcolm’s QC Test Script v1.0 contains 50 cases across 6 sections (FT Admin, Program Owner, Producer, Manufacturer, Retailer, cross-cutting) plus sign-off, with 6 stated business rules and a test-environment checklist (.local/qc-test-script/test-cases.md).

The single most important verdict: the script targets the live Lovable MVP, full stop — 30 of its 31 routes exist at Lovable origin/main; monet has only 7 routes with any wired data, 14 empty shells, and 10 routes absent entirely, and every write through monet’s adapter throws MutationNotImplementedError (.local/qc-test-script/analysis.md sections a-b). Zero of the 50 cases pass end-to-end on monet today; anyone running the script there would file false bug reports duplicating known, already-documented BE gaps. The QC round must run against the Lovable app.

Three cases are untestable even on Lovable at HEAD: A-08 and R-13 test an Insights module that exists nowhere (no route, no module flag — in Lovable, monet, or canvas; and R-13 names Walmart, a demo-modal company testers are forbidden to touch), and A-13 asks to “add an override” on /admin/overrides, which is a read-only calibration report with no add form (analysis.md sections d-e).

The test-environment build is the real bottleneck, not persona switching: 7 of the 11 object types in the env checklist are FT-Admin-gated (product categories, programme, registrations, reservations, licences, scanners, SDUs). Malcolm’s offered “QC account-switcher tab” only removes login friction between personas — it does not remove the admin-gated creation spine, and admin Impersonate already exists (analysis.md section d). This reframes his offer and is question 8 on the Thursday list.

The script also contains internal defects that will produce false failures: rule 1 omits the internal loss multiplier the app applies to CU math (testers hand-computing qty x weight x blend will mismatch wherever the multiplier is not 1, and it is deliberately hidden from them); A-01 expects a blend field on the programme form that does not exist (blend lives in product categories); A-04 expects negative CU entries at /admin/reservation-requests, a queue that actively rejects them (negatives live only on the programme panel); and “run sections in order” breaks at M-05, which needs a nomination that only R-01 in a later section creates — the workable order is A, then R-01/R-02, then M, then the rest of R, then O, then X (analysis.md section e). The proposed tester split is roughly 4.5 tester-days per full pass across three testers plus a floater, with the FT Admin holder building the environment first (analysis.md section f, with the 11 Thursday questions).

4. The business-logic knowledge base: what it is and how much to trust it

The KB (.local/business-logic/knowledge-base/, entry points README.md and portal.html) is a from-scratch re-derivation, not a compilation: nine parallel research passes were synthesized with conflicts resolved by code first, then migrations, then newest document, and everything unresolvable was marked down rather than guessed. Its confidence profile — 343 VERIFIED against 63 STATED, 11 INFERRED, 16 UNKNOWN — means the core mechanics (capacity ledger, PO state machine, claim lifecycle, obfuscation, persona derivation, DB guards) are code-proven at Lovable ffab85ca, while the stated-only layer is mostly Malcolm’s business intent from the July walkthroughs.

The persona set: five QC personas each get a full file — FT Admin (persona-01, owns the entire provisioning spine), Program Owner (persona-02, a company-level fact with two independent gates, credentials/wording mini-CMS), Tier 4 Fibre Producer (persona-03, registration-derived, raises the programme’s Activated pool), Tier 1 Manufacturer (persona-04, activity-derived — having incoming nominations IS the persona — owns linking and proposal amounts), Tier 0 Retailer/Brand (persona-05, type+participation derived, owns nominations, confirmation, evidence). persona-06 adds the four actors the QC script omits: the auditor (scan-only, force-signed-out of the dashboard), the neutral Tier 2/3 “scanner” persona (the quiet load-bearing actor whose scans build chain of custody but never claims), the public verifier (token-gated /c/:token pages), and the team-role axis. persona-00-map.md draws who provisions whom and who blocks whom.

The implementation-state matrix (05-implementation-state.md) is the one-page reality check: the business logic is demonstrable in exactly one place, the Lovable MVP. Monet genuinely covers the operational rim (auth, company, team, partners, facilities, scanners, invoices, collections, SAT scanning) while the entire commercial core (programmes, capacity, nominations, claims, evidence) renders as intentional empty shells; the real backend has started from the aggregate end (funnel reads, single-step claim create) but has never modeled the PO-centric propose/confirm machine the UI and the QC script both assume.

The KB’s Lovable citations are verified at ffab85ca specifically; the app changes daily, so the fastest re-verification path is git -C .local/lovable-source show origin/main:<path> after a fresh fetch (never the clone’s on-disk working tree, which is ~4,300 commits stale — see section 7).

5. Contradictions and open questions across all three bodies, deduplicated and ranked by blocking power

The KB’s 06-open-questions.md already merges and ranks the 20 open questions across all sources; this section is the cross-body dedupe with owners. Rank 1 blocks the most.

Rank 1 — the claim-model schism (KB Q1, task T87). Lovable and the QC script implement a two-party machine: manufacturer proposes against a PO, retailer confirms/rejects, DB triggers meter everything. The deployed real backend (2026-08-03) is a different, single-step model: POST /api/monet/v1/claims with a validate step that is itself still 404 on DEV. Three independent memory records call these parallel and unreconciled. This one ruling decides the BE build for all 9 GAP units, whether monet ports the propose/confirm UI as more than a shell, whether QC sections 4-5 test the product or a prototype, and the fate of the direct non-PO claim path (KB Q13, same conversation). Owner: Malcolm + BE team. Everything else on this list is smaller than this.

Rank 2 — the Lovable MVP’s Supabase is open to anonymous read AND write (KB Q12, task T91). Verified 2026-08-20. The tokenless webhook route is only the visible symptom: ClaimWebhookPreview is a client-side page querying Supabase directly, so exposure is decided by RLS, not by the route. production_claims and public_verification_tokens both carry FOR ALL USING (true) WITH CHECK (true) with no TO clause, which defaults to role public and therefore includes anon (SQL 20260421164336:40-44 and 20260611094428:79-80); this is the house style, not a slip — 79 occurrences of USING (true) across 33 migration files. The consequence not previously recorded: public_verification_tokens is anonymously readable, so a claimId yields that claim’s tokens and opens the public Evidence Pack even when enabled = false — the public-token gate is void, not merely routed around — and WITH CHECK (true) means anon can write. Scope: this is Lovable’s own Supabase, never monet’s production backend (monet reaches Laravel through apiAdapter.ts), so nothing in this repo fixes it — but it is exactly the instance the QC round is about to run against and the one Malcolm demos. Owner: Malcolm to be told before QC starts, then Lovable/BE to remediate. This sits above the QC-start question because it is a data-safety fact, not a scoping decision.

Rank 3 — can the QC round even start (QC analysis d/f; KB Q5, Q20; task T86). Three sub-questions for Malcolm: does Insights exist or get dropped (A-08/R-13, plus the Walmart conflict); who gets FT Admin access for the 7-of-11 admin-gated env build (the switcher does not solve this); and the companion results CSV was never sent. These decide the Thursday plan.

Rank 4 — the two terminology renames (KB Q2, Q3; glossary collisions C1, C2). CU label (“Claim Unit” vs “credit units”): open since 2026-08-18, the QC script uses BOTH and canonises the pair, Lovable’s own copy sweep is incomplete at HEAD; blocks the platform-wide sweep (port-plan unit 9) and makes QC X-02 untestable as written. PO to Nomination: display wording is settled by X-02, whether the domain/tables rename is not. Owner: Malcolm (naming), BE (contract).

Rank 5 — the reservation model on the real backend (KB Q6, Q7). Lovable’s final form (per-adjustment ledger, expires_at NOT NULL defaulted to created+18 months, negative releases capped at active reserved — migrations 20260816203909/20260818202335) is newer than everything in .local/backend-specs/; the real backend has no expiry concept and no row-level reservation GET at all. BE must choose: return expires_at per row, or fold expiry exclusion into the funnel server-side. Owner: BE team. Note the ledger model itself is now settled product intent (section 6).

Rank 6 — script-vs-code divergences Malcolm must rule on individually (QC analysis e; KB Q4, Q8, Q14-Q18): A-04’s negative-entry surface (queue rejects by design), the loss multiplier’s place in QC math, A-13’s nonexistent add-override form, M-02’s mailto scanner request, licence cost-vs-count (A-12/M-01 expect currency; the model is count-only), P-01’s SDU nav item (an SDU-only company still sees Device Status — the nav gates on device count, not registration), P-06’s missing client-side production-limit error, R-07’s bulk approval having no batch rollback, and the tier-label drift in the signup wizard. All merged into the T86 question list.

Rank 7 — resolved this pass, now a finding rather than a question (KB Q10, task T88, closed). The app writes production_claims.status = "revoked" but production_claims_status_check allows only proposed/confirmed/rejected. The check was run: that constraint is created exactly once (SQL 20260618105531:20-24), is the only migration of 132 touching the name, no DROP CONSTRAINT on production_claims exists, and no migration ever widens that CHECK to include revoked — while SQL 20260811125616:1-4 deliberately added revoked_at/revoked_by_user_id/revoke_reason and EvidencePackDetail.tsx:137-157 writes them. So admin claim revoke throws at the DB, the “Could not revoke this record” toast fires, and the public Revoked banner (PublicClaim.tsx:64,86) is unreachable code — a half-migration: columns landed, constraint forgotten. Not systemic: the other revoke site (OwnerCertificates.tsx:152) writes program_certificates, whose CHECK was written correctly as (status IN ('active','revoked')) from day one (SQL 20260606025632:77-78), and works. Goes on the Malcolm list.

Rank 8 — long-standing product residue: non-partner supply-chain visibility (mask vs omit, KB Q9, open since July); certificate 1:N and sub-tier inheritance (KB Q19); company-vs-facility tier (KB Q11); and the “webhook” that is still only a preview page with no outbound push while Connections copy promises otherwise.

Claims-vs-files disagreements found during this consolidation: (1) the sync RUN-SUMMARY states “20 nf-tasks-compatible task drafts emitted”, but .local/tasks/drafts/ contains no draft files (only June-era consumed ones) — the drafts never landed on disk; the coordinator created the tasks directly instead (section 6). (2) port-plan.md’s design-system paragraph states index.css shows no diff; the RUN-SUMMARY’s own gap 1 corrects this — the plan text is wrong, the gap note is right. (3) The QC session analyzed at ffab85ca while the port-plan’s API numbers cover the window ending 2 commits earlier at f0d02a28 — immaterial to any verdict, noted for citation hygiene.

6. Decided versus still open, and the task ledger

Settled today (by the QC script as newest product statement, or by code verification): the reservation per-adjustment ledger including negative releases is the product decision, closing the reservation memory’s open question 3; the producer persona is registration-derived only (usePersonaContext canonical; the old usePersona SDU-OR clause is officially retired code); display terminology is “Nominations”, “Verification Records”, “Scan History”, “Claim” never “Activate” (display level only — table/domain names still open); obfuscation is server-side in Lovable’s Supabase (masking views + REVOKE, resolving July’s server-vs-client question for the MVP; what the real BE does remains open); reserved >= nominated >= claimed is now a first-class stated invariant, with the code enforcing only the claimed leg hard; and the QC script’s target is the live Lovable MVP, making a monet QC run a category error.

Task manifest changes made by this session (all via the nf-tasks tooling, manifest at .local/tasks/ACTIVE.md): T74 (understand the Lovable business logic) closed as done — the KB is exactly that work completed to the code-resolvable limit, with the residue externalized (rationale in the task journal); T45’s blocker updated to name the claim-model ruling (T87) as the gate on WHAT BE builds; a journal note attached to T20 recording that port-plan units 7/12 supersede parts of its guidance (usePartners rewrite first; scanner_facility_assignments permanently superseded). Eleven new tasks created: T80 (port the pre-baseline index.css tier0-quiet drift — the silent-loss item), T81 (button.tsx rebrand), T82 (tabs + shared table-pagination, deps T81), T83 (Partners to main nav), T84 (supply-chain copy/chip, deps T83), T85 (SDU polish), T86 (merge QC + KB question lists into one ranked ask for Malcolm before Thursday), T87 (claim-model ruling, manual, blocked on Malcolm+BE), T88 (Q10 revoked-CHECK code check), T89 (harden the sync completeness pass), T90 (decide shells-now vs wait-for-BE for the 9 GAP units, manual). Each carries a full brief at .local/tasks/tasks/T<NN>.md. Changed on 2026-08-20: T88 closed as done (answer recorded in KB Q10 — the constraint was never widened, so admin claim revoke is broken at the DB); T91 created for the RLS exposure (report-to-Malcolm task, since remediation is not monet’s to make); T86 extended to carry both findings, with RLS as the first item on the list.

7. Provenance and reliability notes (what the worker sessions reported that is not in their files)

The one scar every future session must inherit: the Lovable clone’s on-disk working tree sits ~4,300 commits behind origin/main because the sync protocol is fetch-only. Both QC research agents initially reported from the stale tree and concluded that signup, reservation requests, overrides, and claim-verifications did not exist — all wrong at HEAD. Every published citation was subsequently re-verified via git show/git grep against the ref. Read the clone ONLY via git -C .local/lovable-source show origin/main:<path>; the QC session was saving this as a reference memory at debrief time.

What could NOT be verified, per the sessions’ own accounting: whether Insights is being built inside Lovable right now (no list_edits query was made for today’s unpushed work — Malcolm said he is bug-fixing today, so HEAD may move before Thursday); whether P-06’s allocation limit has a server-side guard (none client-side); whether anything server-side checks the demo login password; the server’s own funnel formulas (the 2026-08-03 DEV probe used an account with zero programmes, so populated /claim-positions/{id} and /fibre-programs/{id} responses have never been seen — including whether default_reservation_term_months is returned); whether the /owner/programme-uptake 404 link survived the August HIG rewrites; and the July “Tier 4 tiles read 0 vs 274 MT” observation. The live Lovable app is unreachable headless (auth-bridge), so everything “live” is code-derived at ffab85ca.

Mid-run corrections the sessions made (already reflected in the published files): the stale-tree fix above; A-04 upgraded from “route mislabel” to “contradicts the implementation”; po_status “closed” corrected from app-level to a real DB enum addition (migration 20260814091422); the July “masking should be server-side” open question reframed to a verified implemented fact; and an md2html linkifier bug that turned .md:line citations into live http:// links (.md is Moldova’s TLD) was caught and fixed in both the portal builder and the standalone renders — without it the “offline” portal would have carried 18 outbound links.

Deliberately left undone, now owned by tasks or future passes: ~15 stale memory files flagged for a hygiene pass (a flow-dream job, not a side effect); the July Vietnamese flow-explainer not reconciled with the new findings (left as a cited prior); no JIRA writes; and neither session drafted tasks (by design — this consolidation owns the manifest, section 6).

8. Recommended next actions, with owners

First, the user (with Malcolm and BE): put the claim-model ruling (T87) at the top of every ask — it gates 9 GAP units, the whole BE PO domain, T45’s wiring pass, and the meaning of QC sections 4-5. Second, before the Thursday call: review and send the merged question list T86 will produce (the QC session’s 11 questions plus the KB’s extra divergences, deduplicated) — the Insights and env-build/admin-access answers decide whether the QC round can start at all. Put the RLS exposure (T91) at the top of that same message: QC is about to point testers at the very instance whose tables anon can read and write, and Malcolm demos it to business stakeholders, so he needs the fact before either happens — not after. Third, the user alone: decide T90 (port the 9 GAP units’ visuals as shells now, or wait) — preferably after the T87 ruling, since restyling a propose/confirm UI that may be dropped is the worst outcome.

Agent-executable now, in order: T80 (index.css drift — removes the silent-loss risk), T81 then T82 (design-system rebrand), T83 then T84, and T85 (pure-UI ports; after these land, accept the cursor advance with python3 .claude/skills/monet-dashboard-lovable/scripts/state.py set-ported f0d02a28... per the RUN-SUMMARY); T89 (harden the completeness pass before the next sync runs). T88 is already done — its answer is in Rank 7 above and on the Malcolm list.

BE team, once T87 is ruled: the beSpecForGap blocks in .local/lovable/sync-20260819/port-plan.md units 6-20 are ready to file, and the reservation expiry decision (KB Q6/Q7) plus the masked-at-API obfuscation ask (session_code_masked) should ride the same ticket batch.

The single most important thing to decide next: the claim-model ruling (T87). Every other blocked thread — BE tickets, shell-porting scope, QC sections 4-5, T45 — unblocks or re-scopes the moment it lands.