Skip to content

Add the Job data model, its invariants, and a believable seed - #17

Open
shiftyp wants to merge 1 commit into
mainfrom
week-01/data-model-and-seed
Open

Add the Job data model, its invariants, and a believable seed#17
shiftyp wants to merge 1 commit into
mainfrom
week-01/data-model-and-seed

Conversation

@shiftyp

@shiftyp shiftyp commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

What & why

The skeleton gains its domain. Two tables and three promises — a User,
their Jobs, and an append-only JobEvent history, with the ground rules
every later feature leans on: every query scoped by the current user, soft
delete via deletedAt, and history written in the same transaction as the
change it records. Plus a seed that reads like a real six-week job search,
because the data model demos as well as its data.

Closes #1

Docs rode along

  • Spec created (docs/specs/jobs/data-model.md,
    docs/specs/jobs/seed.md) — evergreen, present tense,
    no issue numbers or history inside the spec

Verified

  • pnpm test and pnpm typecheck pass locally
  • The spec's Verify section is true after this change (seed twice →
    identical counts; browse Job/JobEvent in Prisma Studio)
  • Every touched query is scoped by the current user; no client-supplied
    ids trusted; foreign resources resolve to nothing

For the reviewer

Start with the two specs — they state the three promises the tests then
exercise. The schema deliberately has no auth tables (dev-identity era)
and no [userId, followUpDate] index (no query reads by follow-up date
yet; indexes arrive with the queries that earn them). The seed is
skip-if-present idempotent — run it twice and check the counts.

The least-sure spot: CreateJob's salary refine puts the error on
salaryMin — argue for salaryMax if you feel strongly.

The skeleton gains its domain: User, Job, and an append-only JobEvent
history, plus the three promises every later feature leans on — every
query scoped by userId, soft delete via deletedAt, and history written
in the same transaction as the change it records.

- schema + 0001_init migration (enums, indexes, cascades)
- domain: CreateJob validation at the boundary; listJobs/getJob/createJob
  (createJob writes Job + CREATED event atomically)
- seed: idempotent six-week job search — statuses across the pipeline,
  events spread over weeks, follow-ups due soon and overdue
- specs: docs/specs/jobs/data-model.md and docs/specs/jobs/seed.md
- tests: integration suite exercising all three promises on PGlite

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BEm9bvh3JdTEnbsQaddiid
// complete: every later feature deepens a table that already exists.
//
// Three promises every query keeps (see docs/specs/jobs/data-model.md):
// 1. Every read and write is scoped by userId.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this, please explain more in the comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The data model and its invariants

1 participant