Fix TOCTOU race, protect read endpoints, test production JWT code
1. TOCTOU race in assertCanActOnTarget:
- verify/unverify batch UPDATE now includes systemAdmin=false in
WHERE clause (when acting admin is not system admin), making the
check atomic with the action — if target is promoted to system
admin between check and update, the UPDATE simply matches 0 rows
2. Read endpoint protection:
- Add assertCanActOnTarget to 3 admin GET endpoints that return
user-specific data: [id]/index.get.ts, [id]/bookings.get.ts,
[id]/repremands/index.get.ts — regular admins can no longer view
a system admin's profile, bookings, or repremands via the API
3. Unit tests import production JWT code:
- Extract pure JWT logic (signing, verification, audience selection,
role derivation) into server/lib/jwt-core.ts — no Nuxt dependencies
- jwt.ts now wraps jwt-core.ts with runtime config for the secret key
- Tests import from jwt-core.ts directly, testing the actual
production code instead of a reimplementation
- Added audience selection tests (getAccessAudience, getRefreshAudience)
- 18 tests (up from 15), all passing
Fix TOCTOU race, protect read endpoints, test production JWT code
1. TOCTOU race in assertCanActOnTarget:
- verify/unverify batch UPDATE now includes systemAdmin=false in
WHERE clause (when acting admin is not system admin), making the
check atomic with the action — if target is promoted to system
admin between check and update, the UPDATE simply matches 0 rows
2. Read endpoint protection:
- Add assertCanActOnTarget to 3 admin GET endpoints that return
user-specific data: [id]/index.get.ts, [id]/bookings.get.ts,
[id]/repremands/index.get.ts — regular admins can no longer view
a system admin's profile, bookings, or repremands via the API
3. Unit tests import production JWT code:
- Extract pure JWT logic (signing, verification, audience selection,
role derivation) into server/lib/jwt-core.ts — no Nuxt dependencies
- jwt.ts now wraps jwt-core.ts with runtime config for the secret key
- Tests import from jwt-core.ts directly, testing the actual
production code instead of a reimplementation
- Added audience selection tests (getAccessAudience, getRefreshAudience)
- 18 tests (up from 15), all passing
Fix TOCTOU race, protect read endpoints, test production JWT code
1. TOCTOU race in assertCanActOnTarget:
- verify/unverify batch UPDATE now includes systemAdmin=false in
WHERE clause (when acting admin is not system admin), making the
check atomic with the action — if target is promoted to system
admin between check and update, the UPDATE simply matches 0 rows
2. Read endpoint protection:
- Add assertCanActOnTarget to 3 admin GET endpoints that return
user-specific data: [id]/index.get.ts, [id]/bookings.get.ts,
[id]/repremands/index.get.ts — regular admins can no longer view
a system admin's profile, bookings, or repremands via the API
3. Unit tests import production JWT code:
- Extract pure JWT logic (signing, verification, audience selection,
role derivation) into server/lib/jwt-core.ts — no Nuxt dependencies
- jwt.ts now wraps jwt-core.ts with runtime config for the secret key
- Tests import from jwt-core.ts directly, testing the actual
production code instead of a reimplementation
- Added audience selection tests (getAccessAudience, getRefreshAudience)
- 18 tests (up from 15), all passing