Application core (entity, API, CRUD UI, status enum) #131

Open
opened 2026-06-19 13:26:24 +00:00 by james · 0 comments
Owner

Add the core Application entity so a user can record an application to a position and move it through its lifecycle.

Scope

  • New applications table: (id, user_id, company, position_name, posting_url, posting_body, status, created_at, updated_at). user_id FK to users, indexed; same per-user scoping discipline as every other domain entity. posting_url and posting_body are both nullable so a user can record an application before the posting has been fully captured.
  • status is a fixed enum stored as text for SQLite/Postgres parity. The seven values: open, started, submitted, interviewing, accepted, rejected, closed. New applications default to open.
  • Entity in db/entities/application.ts; repository in db/repositories/applications.ts; migration under db/migrations/.
  • DTO + zod schema for create / update / response in lib/dto/application.ts. Status is a zod enum so an unknown value fails validation before it reaches the DB.
  • API routes under app/api/applications/ (list, create, get, update, delete) — all session-authed by the default middleware, all scoped to the authenticated user, cross-user IDs return 404.
  • PWA routes under app/(app)/applications/ — list + create + edit using TanStack Query / Form per ADR-0012 and the pattern in app/notes/. Status renders as a labelled badge and is editable inline on the detail page.
  • Cross-engine tests for the entity round-trip, status-enum validation, per-user isolation, and the API routes.

Documents and status updates are separate tickets in this epic and ride on top of this entity.

Acceptance criteria

  • applications migration applies on startup, both engines.
  • A user can create, list, view, edit, and delete an application from the PWA; status moves freely across the seven values.
  • An unknown status value is rejected at the API layer with a validation error, not stored.
  • A request from user B for user A's application ID returns 404 (not 403, not 200).
  • Tests run on both DB engines.

Part of epic #129.

Add the core Application entity so a user can record an application to a position and move it through its lifecycle. ## Scope - New `applications` table: `(id, user_id, company, position_name, posting_url, posting_body, status, created_at, updated_at)`. `user_id` FK to `users`, indexed; same per-user scoping discipline as every other domain entity. `posting_url` and `posting_body` are both nullable so a user can record an application before the posting has been fully captured. - `status` is a fixed enum stored as text for SQLite/Postgres parity. The seven values: `open`, `started`, `submitted`, `interviewing`, `accepted`, `rejected`, `closed`. New applications default to `open`. - Entity in `db/entities/application.ts`; repository in `db/repositories/applications.ts`; migration under `db/migrations/`. - DTO + zod schema for create / update / response in `lib/dto/application.ts`. Status is a zod enum so an unknown value fails validation before it reaches the DB. - API routes under `app/api/applications/` (list, create, get, update, delete) — all session-authed by the default middleware, all scoped to the authenticated user, cross-user IDs return 404. - PWA routes under `app/(app)/applications/` — list + create + edit using TanStack Query / Form per ADR-0012 and the pattern in `app/notes/`. Status renders as a labelled badge and is editable inline on the detail page. - Cross-engine tests for the entity round-trip, status-enum validation, per-user isolation, and the API routes. Documents and status updates are separate tickets in this epic and ride on top of this entity. ## Acceptance criteria - [ ] `applications` migration applies on startup, both engines. - [ ] A user can create, list, view, edit, and delete an application from the PWA; status moves freely across the seven values. - [ ] An unknown status value is rejected at the API layer with a validation error, not stored. - [ ] A request from user B for user A's application ID returns 404 (not 403, not 200). - [ ] Tests run on both DB engines. Part of epic #129.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
james/carol#131
No description provided.