Skip to content

Build Backlog

All confirmed and planned work items across every feature. Items are added here as each feature is documented. Check the box to confirm a task is ready to build.


πŸ”΄ Critical β€” Security (fix before anything else)

Section titled β€œπŸ”΄ Critical β€” Security (fix before anything else)”
  • Fix JWT secrets in wrangler.toml Remove JWT_SECRET and REFRESH_SECRET_KEY from backend/wrangler.toml and move to Cloudflare secrets via wrangler secret put. Generate new values β€” the current ones are burned. File: backend/wrangler.toml

  • Add server-side VFS permission enforcement PUT /api/documents/:id/status accepts any status from any authenticated agent. Mirror the checkCanManageTickets() pattern from tickets.js into a checkCanUpdateVfsStatus() function that validates the caller’s agent type permission against the target status. File: backend/routes/documents.js

  • Add rate limiting to auth endpoints express-rate-limit is installed but never applied. Add to /api/auth/login and /api/auth/register. File: backend/index.js


  • Add userTier column to users Distinguish Shanvi internal staff (INTERNAL) from external partners (EXTERNAL). Currently both use role=AGENT, making it impossible to cleanly separate staff from partners without string-matching agentType names. File: DB migration + backend/routes/admin.js

  • Migrate agentType to agentTypeId FK users.agentType stores a name string. Renaming an agent type silently breaks all users assigned to it. Add agentTypeId INT column referencing agent_types.id and migrate existing data. File: DB migration + all routes that read agentType

  • Add trustLevel column to users Values: STANDARD | HIGH. Controls FD upload behaviour β€” STANDARD uploads go to Pending Review, HIGH uploads publish immediately. Default: STANDARD. File: DB migration + backend/routes/tickets.js

  • Add UPLOAD_FD_INVENTORY permission to permission set New permission that can be granted to agents. Unlocks the FD inventory upload section in their dashboard. Not a separate role β€” an additional permission on the Agent role. Files: backend/routes/admin.js, frontend permission checks

  • Add uploadedBy FK to fd_tickets Track which user uploaded which FD ticket. Required for the marketplace model where external sellers manage their own inventory. File: DB migration + backend/routes/tickets.js

  • FD upload approval queue Admin view listing all fd_tickets with status PENDING_REVIEW. Admin can approve (make live) or reject. Only affects uploads from trustLevel = STANDARD sellers. Files: backend/routes/tickets.js, frontend admin dashboard

  • Duplicate detection on FD upload Before inserting a new FD ticket, check for existing active ticket with same route + date + airline. Return a 409 conflict if duplicate found. File: backend/routes/tickets.js

  • Add SUPER_ADMIN role Currently only one admin level. SUPER_ADMIN can manage other admins, access full audit logs, and configure system-wide settings. Regular ADMIN cannot demote or delete a SUPER_ADMIN. Files: backend/middleware/auth.js, backend/routes/admin.js


  • Dispatch batch model Create dispatch_batches and batch_documents tables. One batch = one courier trip with multiple documents. Schema is defined in the VFS tracking docs. Files: DB migration + backend/routes/documents.js

  • Batch creation endpoint + bulk status update POST /api/documents/batches β€” Shanvi staff creates a batch, assigns document IDs, triggers bulk status update to DISPATCHED_TO_SHANVI or VFS_AFTER_SHANVI. File: backend/routes/documents.js

  • Batch UI for Shanvi staff Screen to select multiple pending documents, enter courier name + handoff date, and create a batch. Should show batch history. File: frontend/src/components/Dashboard/VFS/

  • Add vfsOutcome column to documents Track APPROVED / REJECTED as a separate column so the pipeline status can continue flowing after VFS returns the passport. Currently REJECTED is used as a pipeline status which blocks the flow. File: DB migration + backend/routes/documents.js

  • Fix duplicate stage labels in UI Stages 2 and 6 both display β€œDocument on Way”. Stages 3 and 5 both display β€œDocument at Shanvi”. Make labels unique β€” e.g., β€œAt Shanvi (Pre-VFS)” / β€œAt Shanvi (Post-VFS)”. File: frontend/src/components/Dashboard/VFS/VfsTrackingFlow.tsx


  • Fix file URLs broken in production (R2) getFileUrl() returns /uploads/filename which only works in local dev. In the Cloudflare Worker environment this path doesn’t exist. Set R2 bucket to public, configure custom domain, update getFileUrl. File: backend/utils/storage.js

  • Fix unauthenticated /submit-payment endpoint Replaced POST /:id/submit-payment (guessable integer ID) with POST /pay/:paymentToken. Token (48-char hex) is generated at submission creation and returned in the response. Token is nulled out after use so it can’t be reused. Rate limited to 5 attempts per IP per 15 minutes. DB migration adds paymentToken column on startup. Files: backend/routes/submissions.js, backend/index.js

  • Fix agent type stored by name instead of ID users.agentType stores the name string. If an admin renames an agent type, all assigned users silently break. Add agentTypeId INT column and migrate. File: DB migration + backend/routes/admin.js


  • Extract transit detail normalization in tickets.js ~50 lines of airport lookup + JSON normalization are copy-pasted between POST / and PUT /:id. Extract to normalizeTransitDetails(). File: backend/routes/tickets.js

  • Move db promise wrappers to shared utility all(), run(), get() wrappers are copy-pasted across route files. Move to backend/utils/db-helpers.js.

  • Store displayId at creation time Currently computed from id on every response. If records are deleted and IDs recycled, display IDs could repeat. Store as a unique column. Files: DB migration + affected routes

  • Break up Dashboard.tsx Holds state and fetches data for every tab on mount regardless of active tab. Refactor to lazy-loaded tab panels or per-feature data fetching hooks. File: frontend/src/pages/Dashboard.tsx

  • Adopt a database migration tool Schema changes currently happen via runtime ALTER TABLE guards scattered in route files. Adopt Drizzle ORM + Drizzle Kit for versioned, rollback-capable migrations.

  • Set up staging environment No staging environment β€” all changes go straight to production. Set up a staging Worker + D1 + Cloudflare Pages preview branch.