Skip to content

refactor(auth): extract userId and userRole into AppEnv vars instead of c.get(jwtPayload) #213

Description

@masch

Problem

Currently, every route that needs authentication info does this:

const payload = c.get("jwtPayload") as { sub: string; role: UserRole };
// then uses payload.sub, payload.role

This has several issues:

  1. JWT-coupled — switching auth mechanisms breaks every single route
  2. Repetitive boilerplate — every handler casts and destructures manually
  3. Unsafe typing — the as cast bypasses compile-time safety
  4. Already propagating — PR 2 (reservations.ts) has 4 occurrences of the same pattern

Proposed Solution

1. Extend AppEnv.Variables in apps/backend/src/config/env.ts

export interface AppEnv {
  Variables: {
    db: Db;
    userId: string;
    userRole: UserRole;
  };
  // ... Bindings unchanged
}

2. Update authMiddleware in apps/backend/src/middleware/auth.ts

After JWT verification, set typed variables instead of only c.set("jwtPayload", payload):

c.set("userId", payload.sub as string);
c.set("userRole", payload.role as UserRole);

3. Update roleGuard

Read c.var.userRole instead of c.get("jwtPayload").

4. Update all routes

Replace in every route that uses jwtPayload:

// BEFORE
const payload = c.get("jwtPayload") as { sub: string; role: UserRole };
const userId = payload.sub;
const role = payload.role;

// AFTER
const userId = c.var.userId;
const role = c.var.userRole;

Files affected

  • apps/backend/src/config/env.ts — add userId and userRole to AppEnv.Variables
  • apps/backend/src/middleware/auth.ts — set vars in authMiddleware, update roleGuard
  • apps/backend/src/routes/reservations.ts — 4 jwtPayload occurrences

Note: Other routes (ventures, projects, products, services, auth, health) currently use c.var.db only and do NOT reference jwtPayload — no changes needed there.

Acceptance Criteria

  • c.var.userId returns string (typed, no cast needed)
  • c.var.userRole returns UserRole (typed, no cast needed)
  • roleGuard uses c.var.userRole instead of c.get("jwtPayload")
  • Reservations routes use c.var.userId and c.var.userRole
  • make check passes
  • No more c.get("jwtPayload") calls in route files

Priority

Low — non-blocking refactor. Cleanup before adding more routes that would repeat the pattern.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions