Goal
Autosave from the application form persists to Mongo. Reloading the form pulls back the saved draft and rehydrates the inputs.
Tasks
Set up the Mongo data shape
Implement getDraft(userId)
Implement saveDraft(userId, payload)
Wire the API endpoints
Test with the running frontend
Unit tests
Definition of done
Goal
Autosave from the application form persists to Mongo. Reloading the form pulls back the saved draft and rehydrates the inputs.
Tasks
Set up the Mongo data shape
applicant_data. Each applicant has one document keyed byuserId(oremail). The shape should include at minimum:userId,email,applicationResponses(an object whose keys are question IDs),applicationStatus('not-started' | 'in-progress' | 'submitted'),lastSavedAt(Date), andappSubmissionTime(Date, null until submitted).src/lib/application/service.ts.Implement
getDraft(userId)getDraft(userId: string): Promise<ApplicationDraft | null>tosrc/lib/application/service.ts.src/lib/db.tsto queryapplicant_databyuserId.{ responses: doc.applicationResponses, status: doc.applicationStatus, lastSavedAt: doc.lastSavedAt }.Implement
saveDraft(userId, payload)saveDraft(userId: string, payload: { responses: Record<string, unknown> }): Promise<void>to the same service file.updateOnewithupsert: true. SetapplicationResponsesfrom the payload, setapplicationStatusto'in-progress'(only if it isn't already'submitted'), setlastSavedAttonew Date(). On insert, also setuserIdandemail.applicationStatusif it's already'submitted'. Use$setfor the responses andlastSavedAt, but use$setOnInsertfor any field that shouldn't be touched after the first write.Wire the API endpoints
src/app/api/v1/registration/route.ts. Implement theGEThandler: readuserIdfrom the query string (or from a placeholder header — auth wiring comes in sprint 4), callgetDraft, return JSON.POSThandler: readuserIdfrom query string, readpayloadfrom the request body, callsaveDraft, return{ ok: true, savedAt: <ISO timestamp> }.PUThandler returning 501 for now — submit is a future ticket.userIdsource for now (a?userId=query param orx-user-idheader). Add a comment// TODO: replace with session lookup once Ticket 1's helpers exist.Test with the running frontend
/application, type into a field, wait for autosave to fire, refresh the page, confirm the typed value is still there.Unit tests
getDraftagainst a freshly seeded user with no document, expects null.saveDraftthengetDraft, expects to read back what was written.saveDraftdoesn't downgrade'submitted'back to'in-progress'.Definition of done
getDraft,saveDraft, and the no-downgrade rule.