Skip to content

Audit remediation: security, correctness, billing, UX (Phases 0–5) - #4

Merged
createpjf merged 62 commits into
mainfrom
fix/audit-remediation
Jun 11, 2026
Merged

createpjf merged 62 commits into
mainfrom
fix/audit-remediation

Conversation

@createpjf

@createpjf createpjf commented Jun 11, 2026 •

Copy link
Copy Markdown
Owner

Remediates findings from a three-dimension audit (security / code-quality / UX), executed in six phases. Each phase went plan → implementation → independent review; plans live in docs/superpowers/plans/, specs in docs/superpowers/specs/.

Phase 0 — Security hardening

  • Gateway binds 127.0.0.1 (was 0.0.0.0, LAN-exposed) (C1)
  • Auth token: masked in logs, encrypted at rest, constant-time compare; gateway stdout discarded (C2a/b/c, C3)
  • SSRF allowlist (loopback/RFC1918) + no-redirect on local-provider URLs (H2-sec)
  • Cloud CORS no longer reflects * for no-origin requests (H3-sec)
  • Tauri entitlements narrowed (removed unused file access) (H4-sec)
  • Provider API keys AES-256-GCM encrypted at rest in both gateways; key provisioned from macOS keychain (M4-sec)

Phase 1 — packages/llm-core

Shared mechanism (types, pricing algorithm, alias resolver) extracted; each app keeps its own registry/pricing data (legitimately divergent). Zero behavior change, verified line-by-line.

Phase 2 — Streaming & routing correctness

  • 2a: fallback records the provider that actually served it (H1); fallback only succeeds on 2xx (M4); downed providers self-heal via recovery cooldown (H3)
  • 2b: SSE transformers hardened (guarded enqueue, once-latch, no-crash overflow, idle timer) (H4); TTFB timeout + client-abort propagation so long streams aren't killed (H2, M8); cloud clears overall timeout once streaming begins (H2)

Phase 3 — Cloud accounting correctness

  • Bill the actually-served model after routing fallback (M1)
  • Prometheus label cardinality bounded + values escaped (M5)
  • Starter quota rolled back on upstream 4xx (L5)
  • Transaction idempotency constraints + idempotent deposit crediting

Phase 4 — UX

Onboarding/Settings point to the correct Account tab and navigate (H1); two-step delete confirm + visible errors (H2); tappable gateway-failed banner (H5); balance polling pauses when panel hidden (M5); bounded provider startup retry (M6); web-search save error surfaced (L6); Activity search by provider/status (L4).

Phase 5 — Product items

Landing Pro/Max CTAs point to #download (were looping to self) (H3-ux); admin panel mobile-responsive + dead duplicate removed (M2-ux); tray status tooltip + Start/Stop/Copy-Endpoint menu driven by gateway state.

Verification

  • Gateway: bun test 68/0. Desktop: tsc --noEmit clean, vitest 30/30. llm-core: 12/12.
  • Not compiler-verified (please run locally): Rust changes (Phase 0 stdout/keychain, Phase 5 tray) were read-back reviewed only — the dev volume couldn't run cargo. Run cd apps/desktop/src-tauri && cargo check and cd apps/desktop && pnpm tauri dev to confirm the tray end-to-end.
  • apps/cloud-gateway/node_modules was removed during development to free disk; run pnpm install to restore cloud-gateway tests.

🤖 Generated with Claude Code


Open in Devin Review

createpjf and others added 30 commits June 10, 2026 23:29
Captures the full fix plan from the security/code-quality/UX audit:
Phase 0 security hardening, Phase 1 packages/llm-core extraction,
Phase 2 streaming/routing correctness, Phase 3 billing accounting,
Phase 4 cheap-high-value UX, Phase 5 large product items.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
12 bite-sized TDD tasks covering C1 loopback bind, C2a/b/c token
hygiene, C3 timing-safe compare, H2 SSRF allowlist, H3 CORS, H4
entitlements, M4 AES-256-GCM at-rest encryption for provider keys
(both gateways) + keychain-provisioned ROUTEBOX_DB_KEY.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sec)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rod (M4-sec)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Share types + pricing algorithm + alias resolver; each app keeps its
own registry list and pricing table (data is legitimately divergent,
not drift). Zero behavior change. Adapter/SSE unification deferred to
Phase 2 where they're fixed with tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…est accessor

verifyToken reads ROUTEBOX_TOKEN at call time so sibling test files
can't leak a stale token across the shared module singleton; db.ts
gains a test-only __rawProviderKeyForTest so encryption assertions read
the real DB singleton regardless of import order. Full gateway suite
now passes 63/0 (was order-dependent).
…avior change)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
H1 fallback-route bug (catch-retry records wrong provider), M4
(4xx fallback returned as 200), H3 (provider never recovers after
3-strike down). TDD where cleanly testable; H3 via pure computeProviderUp
helper to avoid mutating the shared metrics singleton. Streaming
robustness (H2/H4/M8 + SSE extraction) deferred to Phase 2b.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…(H3)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…or (M4)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…er is recorded (H1)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
createpjf and others added 28 commits June 11, 2026 10:40
H1 wrong-tab onboarding/settings copy + real navigation, H2 two-step
delete confirm + visible errors, H5 tappable gateway-failed banner,
M5 pause balance polling while panel hidden, M6 provider startup
retry, L6 web-search save error surface, L4 activity search by
provider/status. Frontend-only, low-risk. M7 (pricing) dropped pending
a price decision.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…elf (H3-ux)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tate (tray-ux)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…mages

Phase 1 made both gateways import @routebox/llm-core via tsconfig paths,
but the images were built with context=apps/<x>, so packages/llm-core was
absent and the import crashed at runtime (gateway smoke test caught it;
cloud's lenient '|| true' smoke masked the same break). Gateway now bundles
to a self-contained file (like the desktop ships); cloud preserves the
monorepo layout + copies packages/. Workflows build with context=root.
@createpjf
createpjf merged commit b1f7401 into main Jun 11, 2026
9 of 10 checks passed

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant