Files
carmanagement/docs/design/SECURITY_DESIGN_UPDATES.md
T
root 8fc88ffc14
Build & Push / Pipeline Tests (push) Failing after 59s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Failing after 51s
Test / API Unit Tests (push) Has been skipped
Test / Homepage Unit Tests (push) Has been skipped
Test / Carplace Unit Tests (push) Has been skipped
Test / Admin Unit Tests (push) Has been skipped
Test / Dashboard Unit Tests (push) Has been skipped
Test / API Integration Tests (push) Has been skipped
fix production issues
2026-08-12 16:48:41 -04:00

2.5 KiB
Raw Blame History

Security design updates (Phases 0 & 3)

Summary of application-security design changes from the production-readiness program. Full finding table lives in docs/ops/RentalDriveGo_Production_Readiness_Plan.md §3.

Closed in code (S1S15)

ID Design rule now enforced
S1 Team list/invite responses use safe presenters — never return password hashes or raw reset tokens
S2 Per-tenant Docker/Compose orchestration is out of production scope (fail-closed + ADR-001)
S3 Invite tokens hashed at rest (SHA-256)
S4 Employee email unique per company; login fails closed on ambiguity
S5 Post-login redirects limited to safe relative paths
S6 Authenticated payment/subscription return URLs allowlisted
S7 Admin company slugs validated / slugified
S8 Admin presenters strip reset/verification secrets
S9 Forwarded headers scrubbed by default; TRUSTED_FORWARD_HEADERS=true only behind a scrubbing edge (docs/ops/proxy-trust.md)
S10 Password reset token lookup is hash-only
S11 reviewToken is never returned in reservation/review API JSON (still used server-side for email links)
S12 Public booking access: read does not burn the token; payment init atomically consumes an unused token
S13 Admin money / privileged mutations require 2FA proof newer than ADMIN_FRESH_2FA_MAX_AGE_MS
S14 .gitignore present for secrets/build artifacts
S15 npm run security:static in CI

Public booking token (S12) flow

createBooking → mint publicAccessToken (hash stored)
     │
     ├─ GET booking?token=…  → validate (used or unused OK until expiry) — do not consume
     │
     └─ initPayment(token)   → require usedAt IS NULL → updateMany set usedAt → proceed
                              (second payment attempt with same token → 404)

Fresh admin 2FA (S13)

requireFreshAdmin2FA rejects when:

  • TOTP not enrolled, or
  • JWT lacks last2faAt, or
  • now - last2faAt > ADMIN_FRESH_2FA_MAX_AGE_MS (default 30 minutes)

Wired on finance/support money and high-privilege admin mutations.

Tenant isolation design

  • App-level: every company resource query includes companyId from the authenticated session
  • Regression suite: apps/api/src/tests/integration/cross-tenant-isolation.test.ts
  • Postgres RLS: deferred (ADR-002) until the app-level suite and worker/migration roles are ready

Pen-test

Scope pack: docs/security/pen-test-scope.md. Reports belong under security-reports/ (evidence, not design).