Files
GearBox/docs/superpowers/specs/2026-04-03-codebase-improvements-design.md

4.4 KiB

Codebase Improvements Design

Date: 2026-04--03 Scope: General code quality, error handling, resilience, and maintainability improvements

1. Server Hardening

1a. Explicit DB Context Middleware

File: src/server/index.ts

Add middleware that explicitly sets c.set("db", prodDb) for all API routes. Currently routes call c.get("db") but nothing sets it in production — services silently fall back to prodDb via default parameters. This makes production behavior match the test pattern.

import { db as prodDb } from "../db/index.ts";

app.use("/api/*", async (c, next) => {
  c.set("db", prodDb);
  return next();
});

Place this before the auth middleware so db is available when auth checks run.

1b. Route Parameter Validation

New file: src/server/lib/params.ts

Create a helper that validates numeric route params:

export function parseId(raw: string): number | null {
  const id = Number(raw);
  if (!Number.isInteger(id) || id <= 0) return null;
  return id;
}

Update all route files (items.ts, threads.ts, categories.ts, setups.ts) to replace Number(c.req.param("id")) with parseId(), returning 400 for invalid IDs.

1c. Centralized Error Handling

File: src/server/index.ts

Add Hono's onError handler:

app.onError((err, c) => {
  console.error(`[${c.req.method}] ${c.req.path}:`, err);
  const status = err instanceof HTTPException ? err.status : 500;
  const message = process.env.NODE_ENV === "production"
    ? "Internal server error"
    : err.message;
  return c.json({ error: message }, status);
});

1d. Auth Comment Fix

File: src/server/index.ts

Change comment from:

// Auth middleware for write operations (POST/PUT/DELETE) on non-auth routes

To:

// Auth middleware for write operations (POST/PUT/PATCH/DELETE) on non-auth routes

1e. Rate Limiting on Auth Endpoints

New file: src/server/middleware/rateLimit.ts

In-memory rate limiter using a Map<string, { count: number; resetAt: number }>:

  • Tracks by IP (c.req.header("x-forwarded-for") || "unknown")
  • 5 attempts per 15-minute window
  • Returns 429 with { error: "Too many attempts. Try again later." } and Retry-After header
  • Stale entries cleaned on each check
  • Applied to POST /api/auth/login and POST /api/auth/setup

2. Client Resilience

Error Boundary

File: src/client/routes/__root.tsx

Add errorComponent to the root route definition:

export const Route = createRootRoute({
  component: RootLayout,
  errorComponent: RootErrorBoundary,
});

RootErrorBoundary renders a centered error message with:

  • "Something went wrong" heading
  • Error message in dev mode
  • "Try again" button that calls router.invalidate() + reset()

Uses TanStack Router's ErrorComponentProps which provides error and reset.

3. Client Refactor

Split collection/index.tsx

Extract the three tab-level functions into separate component files:

Source function New file Approx lines
CollectionView() src/client/components/CollectionView.tsx ~260
PlanningView() src/client/components/PlanningView.tsx ~190
SetupsView() src/client/components/SetupsView.tsx ~110

collection/index.tsx keeps:

  • Route definition with searchSchema and validateSearch
  • CollectionPage function (tab switcher + AnimatePresence)
  • TAB_ORDER and slideVariants constants
  • Imports from the three new component files

Each extracted component is a named export, self-contained with its own hooks and local state.

4. Docs Cleanup

PROJECT.md

File: .planning/PROJECT.md

Update Constraints section line:

- **Scope**: No auth, single user for v1

To:

- **Scope**: Single user with cookie/API key auth

Commit Strategy

Group into 3-4 commits by area:

  1. Server hardening: DB middleware, param validation, error handler, rate limiter, comment fix
  2. Client resilience + refactor: Error boundary, split collection route
  3. Docs cleanup: PROJECT.md update

Testing

  • All 183 existing tests must continue to pass
  • Rate limiter: manual verification (no automated test needed for in-memory rate limiting in a single-user app)
  • Error boundary: manual verification by triggering a render error
  • Param validation: existing route tests cover happy paths; invalid IDs are a new edge case but won't break existing tests