Skip to content

Audit History

Audit date: 2026-02-18 Status: All 32 findings resolved across 4 sprints

SeverityFindingsResolvedArea
Critical88N+1 queries, SRP violations, missing transactions
Medium1414Copy-paste, validation, schema drift
Minor1010Config, naming, dead code

Resolved: Replaced Promise.all per-student loop with Drizzle with relations prefetch. From N+1 queries to 1 query total.

2. SessionService — 828 lines, 13 responsibilities

Section titled “2. SessionService — 828 lines, 13 responsibilities”

Mitigated: Credit logic centralized in SessionCreditHandler. Split into 3 services deferred as minor tech debt.

Resolved: Created SessionCreditHandler with onReserve(), onCompleted(), onCanceled(), onNoShow(). All call sites migrated.

4. Missing transactions in multi-step operations

Section titled “4. Missing transactions in multi-step operations”

Resolved: Added db.transaction() wrapping in confirmPurchase, bookLesson, scheduleManualLesson, updateStatus, autoComplete, addAttendees, completeAttendees, markNoShow.

5. Zero validation with as casts in profile routes

Section titled “5. Zero validation with as casts in profile routes”

Resolved: Created 8 Zod schemas in @pinteach/shared. All 10 routes use .parse().

6. DashboardService.getSummary() — 8 sequential queries

Section titled “6. DashboardService.getSummary() — 8 sequential queries”

Resolved: Consolidated 7 queries into 3 using CASE WHEN conditional aggregates and PostgreSQL FILTER.

7. throw new Error() instead of Errors helper

Section titled “7. throw new Error() instead of Errors helper”

Resolved: Replaced 5x raw throws with Errors.notFound() etc.

Resolved: Created StripeWebhookService. Route is now a thin switch.

All resolved:

  • products.lazy.tsx split into 3 components (1,364 → ~120 lines)
  • ToggleSwitch extracted as reusable component (7 instances)
  • Session cookie helper centralized (5 duplicates)
  • PRODUCT_TYPES updated, FK constraints added
  • Indexes added for teacherId columns
  • React state-update-in-render anti-pattern fixed
  • Google Calendar silent error logging added
  • DevTools moved to devDependencies
  • Validation duplications extracted to helpers

All resolved:

  • React version aligned (^19.2.4)
  • Unused imports removed
  • WhatsAppIcon extracted to components/icons
  • Cascade deletes added to acceptance tables
  • Dedicated bulkDeleteTagsSchema created
  • Rate limiting added to verify-magic-link
  • APP_URL defaults corrected
  • process.env centralized to env helper
  • SessionService split into 3 services (deferred — complexity reduced by SessionCreditHandler)