# Compass fix verification — 6 September 2026

The claimed baseline suite was reproducible, but the handoff was not a complete closure: verification found additional import data-loss paths, retry races and inaccurate analytics explanations. These and the two deferred 2FA view defects are now fixed locally. All 35 original findings have evidence below.

- Branch: `fix/review-20260905` in `/home/stevan/dev/compass-fix-all`.
- Baseline: `d6a057f9f`, exactly 52 commits ahead of main at `1ea8a8550`.
- Final tested application revision: `3cf81c1cc77add6ac25abfc4c5b24ee566fd9797`.
- Four explicitly configured **gpt-6-astra / xhigh** specialists covered auth, imports, matching/analytics and UI. The auth specialist independently reviewed the final import follow-up. Parent reviewed changes, integrated commits, ran the complete suite, captured mobile evidence, and exercised the live extraction service.
- Final suite: **2,537 examples, 0 failures, seed 10459**. All connections inspected after the suite had zero open transactions.
- Application remains local: no push, merge to main or application deployment. Main and its pre-existing tracked/untracked 2FA work were fingerprinted and preserved.

## What verification changed

### Import atomicity

Replacement imports can no longer delete existing data and then silently skip failed replacement rows. Empty and premature confirmation are also refused.

### Retry identity

A dedicated extraction_attempt counter separates retries. Old job results and exhaustion callbacks cannot overwrite a newer attempt; attachment analysis cannot invalidate it.

### 2FA and privacy

Both deferred 2FA view defects are fixed. Alternate route formats and reset HEAD requests share IP budgets; numeric OTP input follows the invalid-code path.

### Legacy lookup recovery

Old blank-currency lookups now open a correction flow for admins or return API 422 across show, CSV and PDF, preserving saved data.

### Accurate analytics

Entity rule identities and directional exclusions survive serialization. AND/OR explanations match the actual matcher; incomplete old snapshots say so, including CSV.

### Live extraction verified

CLI safe mode disables local customizations. An invented transcript passed actual extraction and clarification using the final application service.

## Corrections to the supplied handoff

- The original `fixes.md` existed only in the original checkout's untracked review folder, not on the fix branch. The original report, screenshots and handoff are now retained on this branch alongside this verification.
- The baseline diff was 111 files, +4,131 / −379 lines, not 110 files, +4,117 / −375. The harness commit explains the difference.
- The #11 correction stands: decision fields are enum radios, not free text. The original #12 report did **not** recommend Devise lockable; it recommended an atomic credential/IP budget. The separate OTP counter is still the correct implemented choice.
- Currency pairs in #21 are alternatives under the accepted matcher: one supported pair changes an all-red currency result to amber, and amber is eligible. Independent account/entity/exclusion requirements remain conjunctions. This corrects an overstatement in both earlier reports without changing matching defaults.
- There are now **two additive migrations**: OTP attempt budget (`20260906060000`) and document extraction attempt counter (`20260906090000`). Both were exercised on synthetic existing rows; run both through the normal deployment process.
- Current Codex config, global CLAUDE.md and saved model preference all name Astra at xhigh for coding. The inherited 9/8/5 model ratings are unchanged and were not independently benchmarked. Historical Fable/Codex execution claims are recorded in the handoff/memory; git alone cannot attest which model produced every earlier commit.

## Validation

| Check | Examples / failures | Seed |
|---|---:|---|
| Claimed full suite reproduced | 2,481 / 0 | 10459 |
| Final integrated full suite | 2,537 / 0 | 10459 |
| Auth focused suite | 228 / 0 | 6921 |
| Import focused suite | 327 / 0 | 17370 |
| Matching and analytics focused suite | 919 / 0 | 40475 |
| UI focused suite | 32 / 0 | 60231 |
| Additional UI browser probes | 4 / 0 | 7133; 60232 |
| Parent phone / retention captures | 2 / 0 | 46481 |

The normal full suite excludes opt-in live probes and existing ignored examples. Separately, the actual `ExtractFromTranscript` service extracted GBP from an entirely invented record, identified ambiguous USD support, then retained GBP and added USD after clarification with no errors. A separate CLI probe verified subscription auth, disabled MCP/customization behavior and zero new project-session JSONL files. No real customer or provider documents were sent.

The auth budget was also tested with 12 concurrent PostgreSQL connections: all failures preserved the five-attempt ceiling; concurrent use of one recovery code accepted exactly one request. Both migration defaults were verified. Auth and matching changed-line Ruby checks are clean, and import Lint checks passed across 14 files. Full RuboCop remains nonzero: the import files have 103 style/complexity offenses versus 100 at baseline. This is not a claim of a clean repository-wide style run.

## All 35 findings

“Strengthened” means verification added a further correction related to the finding. “Verified” means its committed fix passed the assigned checks; adjacent improvements may still be listed in the specialist report.

| ID | Area | Outcome | Evidence |
|---:|---|---|---|
| 1 | UI and accessibility | Verified | **Back navigation erases account requirements** — Edited naming, domicile and custom rows survive Back/Next and Turbo Back; changed currencies reconcile rows. |
| 2 | Authentication | Verified | **Admin email edits update an unused account column** — Credentials receive email changes through Devise reconfirmation; invalid account/credential updates roll back together. |
| 3 | Imports | Strengthened during verification | **Deselected upload rows are still imported** — Selection is honored. Empty replacement imports are refused even without the selection marker, before deletion. |
| 4 | Authentication | Verified | **Turning off 2FA calls a missing mailer** — Reset mail renders and its token is consumed under a row lock; signed-out removal and rejected tokens are covered. |
| 5 | Matching | Verified | **Wildcard capability form options cannot be saved** — Blank account currency/IBAN country and entity country normalize to the supported wildcard before validation. |
| 6 | Imports | Strengthened during verification | **Document boolean false becomes supported true** — Native false remains false; blank supported values retain the accepted true default across document and edited rows. |
| 7 | Imports | Strengthened during verification | **Failed imports commit earlier writes and deletions** — Nested transaction rollback holds. A later row persistence failure now rolls back replacement deletion and earlier writes. |
| 8 | Matching | Verified | **Either forwards accepts providers offering neither forward type** — Either forwards requires deliverable or NDF support in partner and prospect matching; neither does not qualify. |
| 9 | UI and accessibility | Verified | **Lookup details are mouse-only** — Provider disclosure uses a named native button with keyboard activation and synchronized expanded state. |
| 10 | UI and accessibility | Verified | **Rerun hides required forward fields** — Saved and rejected forward requirements immediately show populated controls; disabling forwards clears inactive fields. |
| 11 | Authentication | Verified | **Request logs retain conversation content and authentication codes** — Real request-log sentinel checks cover derived transcript fields, OTP/reset secrets and nested recovery code; decisions are enum values. |
| 12 | Authentication | Strengthened during verification | **The six-digit 2FA challenge allows unlimited guesses** — Separate atomic OTP budget survives password login. Numeric OTP input consumes budget; format and HEAD variants share IP throttles. |
| 13 | Matching | Strengthened during verification | **Country-group searches misclassify partners and ignore restrictions** — Recorded-member jurisdiction semantics and per-member entity precedence hold; snapshots now preserve distinct effective entity rules. |
| 14 | UI and accessibility | Verified | **Account row controls have no names** — Generated account controls have unique IDs and accessible names; add/remove and restore paths retain labels and focus. |
| 15 | Imports | Verified | **Failed document uploads return silently to the capability tab** — Failed extraction stays visible with a safe error and recovery action, including queue-enqueue failure. |
| 16 | Matching | Verified | **Malformed account requirements fail open or crash** — Malformed JSON, null, scalar/object shapes and invalid nested account elements return validation errors without creating a lookup. |
| 17 | Matching | Strengthened during verification | **Validate currency elements before producing lookup matches** — Empty/unknown currencies are rejected. Legacy blank-currency show/CSV/PDF now lead to correction or API 422 without changing saved data. |
| 18 | Matching | Verified | **Missing client country raises a database error** — Missing client country returns field validation and API 422 before insert; configured countries/groups remain accepted. |
| 19 | Matching | Verified | **Restricted currency pairs incorrectly receive direct prospect ranking** — Direct prospect evidence must contain an allowed requested sell/buy pair; contradictory allowed-sell restrictions cannot rank direct. |
| 20 | Matching | Verified | **Selecting no industry produces a false data-gap indicator** — Empty industry input normalizes to not requested, matching omitted input in persistence and matching. |
| 21 | Analytics | Strengthened during verification | **Gap unlocks confuse one dimension with one requirement** — Independent account/entity/exclusion rules remain conjunctive; currency pairs are alternatives. Historical missing rule detail is explicit; CSV preserves meaning. |
| 22 | Analytics | Strengthened during verification | **Jurisdiction gaps name the sending country instead of client** — Jurisdiction labels use client country or stored blocked members. All accepted groups, including EU and SEPA, have display labels. |
| 23 | UI and accessibility | Verified | **Analytics filters and lookup account rows overflow phone screens** — Wizard table scrolls within its container; analytics controls fit a 390px viewport, including the enlarged-text check. |
| 24 | Analytics | Verified | **Analytics lookup links fail for colleagues and API searches** — Any authenticated admin can read stored colleague/API snapshots; live evaluation and mutation controls remain absent and owner routes remain scoped. |
| 25 | UI and accessibility | Verified | **Autocomplete omits combobox semantics** — Autocomplete exposes combobox/listbox/option state; arrows, Enter, Escape, Tab and no-match dismissal keep ARIA state consistent. |
| 26 | Imports | Verified | **Upload selection count becomes false** — Upload selection totals update from checked rows after select-all, select-none and individual toggles. |
| 27 | Imports | Strengthened during verification | **Document failures never reach the configured retry policy** — Transient failures reach Sidekiq retries. Attempt counters isolate manual retry from stale delivery/exhaustion, including legacy jobs and attachment touches. |
| 28 | UI and accessibility | Verified | **Duplicate requirements fail without explanation** — Duplicate requirements show a specific error, identify/focus the offending row and preserve values after server rejection. |
| 29 | UI and accessibility | Verified | **Polling can navigate after leaving page** — Disconnect aborts polling; late responses cannot navigate after removal/reconnect. Requests stay serial and retry after transient HTTP failure. |
| 30 | Imports | Verified | **Accepted legacy XLS files are parsed as XLSX** — Legacy .xls is rejected before persistence with instructions to use .xlsx or CSV. |
| 31 | Authentication | Strengthened during verification | **CLI extraction retains an extra transcript copy** — CLI disables session persistence and customizations. Live synthetic probes verified auth, no MCP/session files, and actual extraction/refinement. |
| 32 | Imports | Verified | **URL extraction downloads unlimited response bodies** — URL reads enforce body size, permitted content types and deadline; transient HTTP statuses are now retryable. |
| 33 | Analytics | Verified | **Every rolodex page recomputes all recent gap matching** — Evidence is loaded once per coverage calculation with recency work skipped; uncached query count stayed 16 as synthetic volume increased. |
| 34 | UI and accessibility | Verified | **Breadcrumb landmark name is misspelled** — Breadcrumbs render the correctly spelled aria-label on their navigation landmark. |
| 35 | UI and accessibility | Verified | **Sign-in document has no language** — The sign-in document declares lang=en. |

## Performance evidence

Uncached synthetic gap coverage held at 16 SQL queries for both 1 lookup / 1 stocked prospect and 20 lookups / 10 stocked prospects. Recency queries were zero. The larger fixture took 85.39 ms and allocated 60,178 objects locally. This verifies query reuse; runtime and allocations still grow with matching work. No cache or production performance claim was added.

## Remaining work and limits

- Historical CLI sessions created before the fix remain an operations cleanup task. They were not deleted because they may include other work; the new runtime checks cover future extraction calls.
- Dropping the unused `accounts.email` column remains a separate schema cleanup. The credential email behavior is fixed.
- O1–O12 product and architecture opportunities remain deferred; this pass verifies and completes the 35 defect fixes rather than silently implementing that roadmap.
- Old analytics snapshots cannot recover entity-rule details never stored. They now disclose the missing detail without rewriting history.
- Verification used isolated local databases and synthetic data. Production deployment, production load, external SMTP delivery, external log retention, a manual screen-reader session and real-document extraction quality were not tested.
- All previous worktrees/databases remain available. Verification used additional isolated worktrees and test databases 96–100; no original worktree/database was removed.

## Evidence

- [Authentication and privacy](evidence/auth.md)
- [Import integrity](evidence/imports.md)
- [Independent import review](evidence/imports-independent-review.md)
- [Matching and analytics](evidence/matching.md)
- [UI and accessibility](evidence/ui.md)
- [Integrated full-suite output](evidence/full-suite.txt)
- [Post-suite transaction check](evidence/final-transaction-audit.json)
- [Synthetic live extraction result](evidence/live-extraction-probe.json)
- [Machine-readable verification](verification.json)
- [Original report](original/report.md)
- [Historical fixes handoff, with corrections](original/fixes.md)
