Delete console.log({ payload }) and console.log({cachedResult})
2 min
14
New
Add user status check in contextMiddleware
contextMiddleware.ts (after loading fullUser)
Add: if (fullUser.status !== 'active') return next(new ApiError(403, "Account not active"));
10 min
15
#76 (PRE-1)
Add allPermissionAssignToAdmin() to seed pipeline
seed.ts (after permissionSeed(), before seedSuperAdmin())
Add: await PermissionService.allPermissionAssignToAdmin(); — without this, super_admin has ZERO permissions in role_permission table, v2 middleware blocks super_admin
1 min
16
#76 (PRE-2)
Add super_admin bypass to v2 permission() middleware
permissionMiddleware.ts (before has() check)
Add: if (req.user.role === 'super_admin') return next(); — belt-and-suspenders for new permissions not yet in role_permission
2 min
17
#76 (PRE-3)
Add null-safety for req.user.permissions in v2 middleware
permissionMiddleware.ts (before has() check)
Add: if (!req.user?.permissions) throw new ApiError(401, "Unauthorized"); — prevents TypeError when contextMiddleware fails
Timeline: ~7 hours, 1 developer
North Star: A non-super_admin user with appropriate permissions can perform all CRUD operations.
Exit criteria: Log in as "admin" role (not super_admin), verify all Users/Roles/Permissions/Invites pages work.
#
Issue(s)
Description
File(s)
Effort
S1-1
#8, #9
Unify permission system. Delete middleware v1 (hasPermission.ts), keep v2 (permissionMiddleware.ts). Move GET /payments check to permission("payment.view") using v2, then delete v1. Fix hasAnyPermission bug (#69).
CORRECTED: Restructure contextMiddleware pipeline. The global contextMiddleware in middleware.ts is a no-op for JWT-auth (runs before auth(), req.user is undefined → short-circuits). The per-route registrations are the ONLY effective invocation — do NOT remove them. Instead: either (a) remove the useless global registration from middleware.ts:77, or (b) move auth() into middleware.ts before contextMiddleware so global registration works, then remove per-route duplicates. Option (b) is cleaner but higher risk.
middleware.ts, route files
1.5 hr
S1-3
#18
CORRECTED: Depends on S1-2 decision. If S1-2 option (b) is chosen (global auth+context), then per-route auth(), contextMiddleware on individual permission routes become truly redundant and should be removed. If S1-2 option (a), these stay because they're the only effective invocation. The router.use(auth(), contextMiddleware) at line 9 already handles routes after it, but individual routes re-apply it — those ARE redundant even with option (a).
permission.routes.ts
30 min
S1-4
#22
Delete permissionNormalizer. Remove file + remove imports from helper/hasPermission.ts. Simplify checkPermissionInRoles to direct string match.
Delete UserRole entity. Remove file + dead import from seed.ts.
UserRoles.ts (DELETE), seed.ts
5 min
S1-6
#14
Fix duplicate userRoles validation. Remove the unconditional second validation block (lines 352-363) in updateUser.
user.service.ts:352-363
15 min
S1-7
#3
REDUCED PRIORITY (Low). Fix permission route ordering — move GET /user-permissions before GET /:permissionId. Downgraded: frontend never calls this endpoint (permissions come from GET /users/profile). Dead backend code. Consider moving to backlog.
permission.routes.ts:11-13
5 min
S1-8
#2
REDUCED SCOPE: Remove 3 broken hooks + buttons (not 5). Users bulk-permanent-delete button is already commented out (dead code). Resend button hidden by case mismatch #75 (dormant). Active bugs: roles, permissions, invited-users bulk-permanent-delete → 404 with error toast. Also fix case mismatch #75 ("pending" vs "PENDING") to surface the resend issue.
Fix permissions page gate (Medium — downgraded after challenge). Change permission="role.view" to permission="permission.view". Edge case — both permissions typically assigned together. Only affects rare "Permission Auditor" role. Still a 5-min fix, keep in Sprint 1.
permissions-page.jsx
5 min
S1-10
#29
Remove duplicate ConfirmationModal.
permissions-page.jsx (near end of file)
5 min
S1-11
#31
Remove debug console.log in roles API hook.
api/roles/index.js:71
1 min
S1-12
#58
Add permission gate to useGetUsers (upgraded to Medium). Add useCheckPermission(["user.view"]) and enabled: hasPermission. Unnecessary failed API call visible in dev tools.
api/users/index.js
5 min
S1-13
#24
Fix upsertRole for seed. Create createRoleInternal() without permission check, called by upsertRole and seed. Keep createRole() with permission check for API.
role.service.ts
30 min
S1-14
#19
Fix mixed soft-delete. Replace isDeleted: false queries with TypeORM default deletedAt IS NULL filtering.
1. yarn seed → Seeds roles, permissions, super_admin
2. Login as super_admin → Create "admin" role with user.*, role.*, permission.*, invite.* permissions
3. Create user with "admin" role → User created successfully
4. Logout, login as new admin user → Dashboard loads, sidebar shows all admin sections
5. Navigate to Users page → User list loads, CRUD works
6. Navigate to Roles page → Role list loads, can edit permissions
7. Navigate to Permissions page → Permission list loads, can create/delete
8. Navigate to Invited Users page → Invite list loads, can create invites
9. All trash/restore/permanent-delete → Works without 404 errors
10. No console errors in browser → Clean
Fix stale JWT role in contextMiddleware — use DB-loaded fullUser.role.name instead of req.user.role.
30 min
S2-8
#21
Clean up permission cache: remove variant matching, use direct dot-notation match only.
30 min
S2-9
#11
Fix backup code storage (downgraded to Medium) — use JSON array or delimiter-separated hashes instead of concatenation. SHA-512 collision risk is theoretical (~2^-512) but replace() removal is fragile.
1 hr
S2-10
#36
Fix contextMiddleware silent failure — reject request on DB error instead of continuing without context.
Update api.md with undocumented endpoints.RESOLVED — api.md was completely rewritten in a separate review (94 findings, all resolved). Now documents ~210 endpoints across 30 modules.
1 hr 0
S2-19
#46
Fix database.md UserRoles entity docs (wrong class name, missing relations).
Set up test framework (Jest + ts-jest for backend). Create first integration test: non-super_admin user CRUD lifecycle through User/Role/Permission modules. This is the single most important preventive measure.