| # | Reviewer | Method | Verdict |
|---|---|---|---|
| 1 | Codex GPT-5.5 | R1: 110 findings, 6 categories | NO-GO |
| 2 | Grok 4.3 | R1: 5 blockers + 5 systemic risks → R3 binding | GO-W/C (R1) → NO-GO (R3) |
| 3 | Claude main session | R1: manual security red-team | GO-WITH-CONDITIONS |
| 4 | code-quality agent | arch + type safety + schema | defects |
| 5 | test-coverage agent | 80-file suite vs 598-file codebase | defects |
| 6 | deploy-infra agent | Dockerfile + fly + Sentry + DB | defects |
| 7 | Gemini 2.5-pro | — | BLOCKED (monthly cap) |
| 8 | feature-readiness agent | FEATURES_STATUS.md vs reality (retry) | defects |
| 9 | /red-team Agent 1 | Input validation & injection | 5C / 7H |
| 10 | /red-team Agent 2 | Process & resource safety | 5C / 7H |
| 11 | /red-team Agent 3 | Trust boundary & identity (6 verified + 19 new) | defects |
| 12 | /red-team Agent 4 | Dependency & supply chain | 3C / 8H |
| 13 | deepseek-r1:32b (local) | Replaced Gemini quota | NO-GO |
| — | R3 Codex co-CTO binding | All 21 blockers bound | NO-GO |
| — | R3 Grok co-CTO binding | All 21 blockers bound | NO-GO |
Each blocker bound by both co-CTOs independently. Where they disagreed on severity, the higher severity is taken (most-conservative rule for a regulated financial product). All file:line citations source-verified.
app/api/v2/transfers/[id]/route.ts:62-63, 186-188 — findById(id, environment) with no owner check. Any API key with transfers:read can read any transfer in the same environment; transfers:write can accept/reject/retry any transfer.app/api/v2/customers/[id]/erase/route.ts:83-93, 123 — irreversible KYC destruction authorized by transfers:write; LegalHold model never consulted. grep confirms zero LegalHold references in the entire file.app/api/system/trp/veriscope/incoming/route.ts:391-421 mutates KYC templates without sender verification; middleware.ts:96-97 + csrf.ts:151-153 bypass both auth and CSRF; attestation-decoder.ts uses unbounded inflateSync on attacker payload (zip-bomb DoS with worker concurrency-1 → entire compliance pipeline stalls).app/lib/jobs/transfer-queue.ts:211-213 — the engineer's own comment: "Compliance checks do NOT run here. They run after both IVMS are exchanged." Originator PII transmits to counterparty BEFORE sanctions screening. If a transfer would be sanctions-blocked, the disclosure already happened.middleware.ts:184-193 gates non-existent /api/v1/*, (b) rbac.ts:91-95 returns allowed:true for unmapped paths (17 routes in ROUTE_PERMISSIONS vs 22 admin sections + 17 API routes), (c) admin server components call only requireAuth(). Net effect: a viewer-role user can read every admin page.prisma/schema.prisma — TravelRuleTransfer and Customer have NO userId ownership field. ATRSA's authorization model assumes ONE trust domain per environment. This is the structural gap behind every IDOR finding. B1, B14, B2 cannot be fixed correctly without B10 first.prisma/schema.prisma:194-211 — no prevHash / recordHash / signature columns. AUDIT_SIGNING_KEY + AUDIT_PUBLIC_KEY declared in env but never used (grep: 0 hits outside env.ts). /api/v2/** — 10 of 10 v2 routes write only Activity, not AuditLog. FEATURES_STATUS.md falsely claims "Immutable Audit Trail — Hash chain, content hashing, auto-lock" + "Digital Signatures — RSA-SHA256 signed audit exports."app/lib/adapters/veriscope/webhook-dispatcher.ts:94 — outbound peer dispatcher SKIPS the SSRF guard that webhook-service.ts:76-135 applies. A peer who publishes a TrustAnchor API_URL pointing at 169.254.169.254 (AWS metadata service) extracts encrypted IVMS via the outbound webhook. The encryption is irrelevant — the attacker controls the destination.app/lib/adapters/veriscope/transition-validation.ts:299-301 — when the external Python verifier process is unavailable (likely on fly.io alpine container), the code silently APPROVES every BE_CRYPTO_PROOF_VERIFIED transition. Combined with B16 (env-leak via execFile), this is a compound failure: validator present = secrets leak; absent = validation fail-open.app/api/v2/customers/[id]/deactivate/route.ts + reactivate/route.ts — parallel pattern to B2. transfers:write scope, no owner filter, environment-only lookup.app/lib/utils/key-rotation.ts:519-537 — performKeyRotation covers TravelRuleProvider config, Integration config, User 2FA, TravelRuleTransfer IVMS. NOT covered: Customer.keys (per-customer secp256k1), webhook signing secrets, CTR regulatory fields (customerName, customerDob, customerIdNumber, conductingPersonName). After rotation + old-key removal, all customer veriscope keypairs become permanently undecryptable. Script reports success.app/lib/actions/auth.ts:127,134 signs with NEXTAUTH_SECRET; :184 verifies with TWO_FA_JWT_SECRET || NEXTAUTH_SECRET. In production where TWO_FA_JWT_SECRET is required AND different from NEXTAUTH_SECRET, sign uses key A and verify expects key B → tokens fail. Source-verified via direct read. NOTE: auth/config.ts:48-92 has a parallel 2FA path with consistent secret usage — two code paths exist.csrf.ts:197-202start.sh:27-40auth/config.ts:297-306 — limiter has DB fallback per Agent 2 correction; fix the auth-route .catch(()=>null), not the limiter.instrumentation-client.ts:11 — captures IVMS PII forms on every error event. No DPIA.| Codex GPT-5.5 | Grok 4.3 | Convergence | |
|---|---|---|---|
| #1 must-fix | B10 (tenant model) | B10 (tenant model) | B10 ✓ unanimous |
| #2 must-fix | B3 (Veriscope) | B1 (IDOR) | split — both bound CRITICAL |
| #3 must-fix | B5 (compliance order) | B12 (SSRF) | split — both bound CRITICAL |
document.cookie in dev session)userId ownership to TravelRuleTransfer, Customer, Wallet, Webhook. Backfill rows.findById after B10 landscustomers:erase scope + consult LegalHold modelwithRBAC default to fail-CLOSED; register every route; remove viewer from adminUiRoleswebhook-dispatcher.tsencryptSecret( call site + regression testmiddleware.ts branch tests (231 LOC currently untested)coverage.all: true in vitest, coverage.include: ['app/**/*.ts']web and workerPII_ENCRYPTION_KEY from CONFIG_ENCRYPTION_KEYtransfer-workflow.ts (1862 LOC) into per-workflow modulesveriscope/incoming/route.ts (1334 LOC) into thin route + service/api/v2/transfers POST to createOutgoingas any on session.user.roledb:push with proper Prisma migrationsAUDIT_SIGNING_KEY to AuditLog hash-chain (B11 completion)isUnhosted flagtransfer-workflow.ts. PATCH route already migrated.coverage.all: false excludes untested files. 1-line fix.web and worker for independent scaling.ATRSA is technically impressive for one engineer. The defects are not laziness — they are the architectural drift that happens when one person writes 125K LOC over months without a second pair of eyes. However, the multi-reviewer convergence surfaced systemic gaps that the engineer's own FEATURES_STATUS.md does NOT acknowledge:
These are not polish items. They are structural decisions that need a 1-2-week sprint to fix correctly before any external user touches the system. The good news: most fixes are well-scoped. The bad news: B10 requires a schema change that ripples through every repository.