Audit Report — May 2026
Mechanical first-pass verdicts for the client/ React SPA at SHA 49d4c7d. Ownership + timelines locked at stakeholder read-out.
What R1, R2, R3 mean
The audit measures the frontend against three independent readiness axes. Each axis is a separate question with its own verdict — a finding can block one axis, two, or all three at the same time.
Can it run live trades safely today?
Full question: Can this frontend reliably command live market-making on the Qatar Stock Exchange right now?
An R1 problem could cause an unintended trade, a missed trade, capital loss, an operator getting locked out, or a frozen feed shown as if it were live.
Can we hand the product over to The Group as a clean tenant build?
Full question: When we ship to a new brand (Dimtech, future tenants), does the build come out clean — no cross-brand leakage, no hardcoded names, themes intact?
An R2 problem means the product is unsafe or embarrassing to deliver: another brand's strings or colors leak in, the bundle ships content it shouldn't, or theme tokens are missing so UI breaks under the tenant skin.
Can The Group's in-house team take this over without a rewrite?
Full question: Once Route07 hands the code to The Group's team, can they safely own, maintain, and extend it?
An R3 problem means the new team will struggle: god-modules, zero tests on the money path, unusual patterns with no ADR explaining why, deprecated dependencies that force a rewrite to update.
Severity tags — what each label means
Every finding gets one severity tag. The tag combines which axis it blocks with how hard a blocker it is: -blocker is unconditional; -conditional only blocks if a related condition holds.
Production won't ship live until this is fixed.
An unconditional R1 blocker — anything on the live-trading path that could mislead an operator or move money incorrectly. No risk-acceptance allowed on money-path items.
Becomes an R1 blocker if a specific condition holds.
The finding only blocks production if a related backend behavior, env flag, or configuration is in a certain state. Once the condition is verified, it either lifts to R1-blocker or clears.
Delivery to The Group won't ship until this is fixed.
A white-label / tenant-isolation problem: cross-brand contamination in dist/, hardcoded brand strings, missing theme tokens, or build-pipeline opacity that makes a tenant bundle untrustworthy.
Handoff to the in-house team won't happen until this is fixed.
Maintainability problem severe enough to prevent safe ownership: god-modules with no decomposition path, zero tests on critical paths, missing ADRs for the unusual patterns, dependency rot.
Becomes an R3 blocker only if a condition holds (e.g., test-gate is delivery-blocking).
Same idea as R1-conditional but for the handoff axis — typically a Quality item that promotes to R3 once another finding lands or a policy is confirmed.
Real debt, but doesn't block any of the three readiness verdicts.
Code-health problems that should be fixed during normal maintenance but don't stop production, delivery, or handoff sign-off on their own.
Worth knowing about. Doesn't block anything.
Observations, oddities, or risk-rare items recorded for context. No fix is required for any verdict.
routes.ts blocks both R1 (operator gets locked out) and R2 (the tenant build is broken on day one). Those show up tagged as R1+R2 in the Axis column.Finding IDs — what the prefix tells you
Every finding has an ID like A-TS-001, C-RT-003, or A-MONEY-002. The prefix tells you which area of the codebase the finding lives in. The number is just a counter within that area.
A-MONEYMoney pathAnything on the live-trading command flow — the screens and code that send real orders. The most sensitive area; every defect here is automatically at least R1.
A-AUTHAuthentication & sessionLogin, JWT refresh, session timeout, the warning modal that fires before you get logged out.
A-RBACRole-based access (capabilities)The capability strings in `routes.ts` and how they line up (or drift) from the backend `permissions.py`. A drift here can lock an operator out of work they should have access to.
A-TSTypeScript rigorUnchecked `as` casts on incoming WebSocket / REST data. The frontend trusts the wire format without runtime validation, which is risky on a live feed.
A-STATEState managementZustand stores, the always-mounted tab trick, the dual store system, WebSocket cursor handling — anywhere local state can go out of sync with the server.
A-ARCHArchitectureStructural problems: god-modules (`useApi.ts` at 2,296 LOC), missing ADRs for the deliberate unusual patterns, unused exports — things that hurt the next team's ability to navigate the code.
C-FEFrontend correctnessGeneric frontend correctness — error boundaries, error UX, accessibility floor, form validation. Things that bite operators during failure modes.
C-RTReal-time integrityWebSocket reliability, reconnect behavior, dropped-message detection, the WS↔REST cursor handoff. If the feed lies about being live, it's here.
C-DEPSDependenciesPackage versions, deprecations, and unmaintained libraries. Major-version lag or abandoned packages that would force a rewrite to update.
C-UXAccessibility & error UXKeyboard operability on money-path actions, focus management on the live-trade modal, `prefers-reduced-motion`, error message clarity.
C-PERFPerformanceRender performance during peak QSE hours, memory stability over an 8-hour run, WebSocket throughput at peak and 2× peak. A laggy dashboard at the wrong moment is an R1 problem.
A- come from the application-specific tracks (auth, money path, state, RBAC, TypeScript, architecture). Prefixes starting with C- come from the cross-cuttingtracks (frontend correctness, real-time, dependencies, UX, performance). It's purely an organizational distinction — both kinds can be R1 / R2 / R3 blockers.Browse the findings
All 122 findings are indexed and clickable. The Findings view lets you filter by axis or severity, search by ID or location, and drill into any single finding to see the full evidence + remediation + re-test command.
Open Findings Browser