diff --git a/README.md b/README.md index 1fc3507..876c24a 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,13 @@ wantlist ("crate"). IT2810 (NTNU) Project 2. Group T19: `erikhfj`, `robertky`, `evenkkl`, `rachelks`. -| | | -| ----------------- | --------------------------------------- | -| Current milestone | **M1 - spec and mockup**, due 2 October | -| Live prototype | http://it2810-19.idi.ntnu.no/project2 | -| Workflow | [`docs/WORKFLOW.md`](docs/WORKFLOW.md) | -| AI usage log | [`docs/AI-USAGE.md`](docs/AI-USAGE.md) | +| | | +| ----------------- | --------------------------------------------------------- | +| Current milestone | **M2 - PostgreSQL and GraphQL on the VM**, due 16 October | +| Live prototype | http://it2810-19.idi.ntnu.no/project2 | +| Workflow | [`docs/WORKFLOW.md`](docs/WORKFLOW.md) | +| AI usage log | [`docs/AI-USAGE.md`](docs/AI-USAGE.md) | +| Running on the VM | [`docs/VM-setup.md`](docs/VM-setup.md) | ## Getting started @@ -22,9 +23,25 @@ Requires Node.js 24+ and [pnpm](https://pnpm.io) 10+. ```bash pnpm install -pnpm dev # Vite dev server on :5173 +pnpm dev # Vite dev server on :5173 ``` +To also run the API locally you need PostgreSQL and a `DATABASE_URL` in +`server/.env`: + +```bash +pnpm --filter @t19/server db:migrate # create the catalog tables +pnpm --filter @t19/server db:seed # optional: replace the catalog with the sample albums +pnpm --filter @t19/server dev # GraphQL Yoga on :3001/graphql +``` + +`db:seed` is a reset command, not a loader. It replaces the catalog and, +through foreign-key cascades, deletes the reviews and crate items hanging +off it. Do not run it against a database holding user content you want. + +`docs/VM-setup.md` has the same steps for the group VM, plus a smoke suite +to check a deployment. + Before opening a PR: ```bash @@ -33,26 +50,47 @@ pnpm format:check && pnpm lint && pnpm typecheck && pnpm test All four must pass. CI runs the same thing. -| Command | Purpose | -| ----------------------------------- | ---------------------------------- | -| `pnpm dev` | Vite dev server | -| `pnpm build` | Type-check + production build | -| `pnpm lint` | ESLint - must pass with 0 warnings | -| `pnpm format` / `pnpm format:check` | Prettier | -| `pnpm typecheck` | `tsc --noEmit` in every workspace | -| `pnpm test` | Vitest, single run | +| Command | Purpose | +| -------------------------------------- | ---------------------------------------------- | +| `pnpm dev` | Vite dev server, client only | +| `pnpm build` | Type-check + production build, every workspace | +| `pnpm lint` | ESLint - must pass with 0 warnings | +| `pnpm format` / `pnpm format:check` | Prettier | +| `pnpm typecheck` | `tsc --noEmit` in every workspace | +| `pnpm test` | Vitest, single run | +| `pnpm --filter @t19/server dev` | GraphQL API on `:3001/graphql` | +| `pnpm --filter @t19/server db:migrate` | Apply the Drizzle migrations | +| `pnpm --filter @t19/server db:seed` | Load the sample catalog | ## Project status -| Milestone | Due | Delivers | -| --------- | ------ | ----------------------------------------------------------------------------------------- | -| M1 | 2 Oct | Spec and mockup: GraphQL schema, architecture ADRs, UI sketch, client rendering mock data | -| M2 | 16 Oct | PostgreSQL + GraphQL backend on the VM, client interaction | -| M3 | 30 Oct | Beta: search, paging, sorting, filtering, accessibility, bærekraft | -| M4 | 13 Nov | Finished prototype and the full test suite | - -`client/` currently renders mock data. `server/` (PostgreSQL + GraphQL Yoga) -arrives in M2 and `e2e/` (Playwright) in M4. +| Milestone | Due | Delivers | +| --------- | ------ | ----------------------------------------------------------------------------------------------------- | +| M1 | 2 Oct | Spec and mockup: GraphQL schema, data model, architecture ADRs, UI specification, workflow and AI log | +| M2 | 16 Oct | PostgreSQL + GraphQL backend on the VM, client interaction | +| M3 | 30 Oct | Beta: search, paging, sorting, filtering, accessibility, bærekraft | +| M4 | 13 Nov | Finished prototype and the full test suite | + +### Where the code is + +| Path | What it is | +| ---------------- | --------------------------------------------------------------------------------------------------------------- | +| `client/` | React + Vite. Still the M1 skeleton; #9 wires the search view to the API | +| `server/` | GraphQL Yoga + Drizzle over PostgreSQL. `searchAlbums` with filtering, facets and keyset paging. Live on the VM | +| `schema.graphql` | The contract both sides work against | +| `docs/` | Architecture and data model ADRs, UI specification, workflow, AI log, VM runbook | + +Implemented: the PostgreSQL schema, with tracks, simulated users, reviews +and crate items, and trigger-maintained full-text search over titles +(weight A) and artist names (weight B). On top of it, album search by word, +genre and decade facets, keyset paging, four sort modes, and the `X-User-Id` +contract for the simulated user. + +Planned: filters and sorting in the UI, the reviews and wantlist +mutations, accessibility and bærekraft (M3), then the Playwright `e2e/` +suite (M4). The GraphQL operations behind those are in `schema.graphql`, +but `searchAlbums` is the only query with a resolver so far, along with the +`Album` fields it returns. ## Infrastructure @@ -61,8 +99,13 @@ containers and not on an external service. Live at , GraphQL on port 3001 behind an Apache `ProxyPass`. PostgreSQL is local to the machine and is not exposed. -CI runs on a self-hosted runner on the same VM. Pushes to `main` build the -client and publish it to Apache. +The API is a systemd unit, `crate-api.service`, running the built `server/` +from `~/T19-Project-2`. It loads `DATABASE_URL` from that checkout's +`.env`, which is gitignored and so survives a deploy. + +CI runs on a self-hosted runner on the same VM. Pushes to `main` run the +quality gates, then deploy the client bundle to Apache and the built API to +the checkout `crate-api` runs from. ## Working in this repository diff --git a/docs/AI-USAGE.md b/docs/AI-USAGE.md index 565badd..399bc46 100644 --- a/docs/AI-USAGE.md +++ b/docs/AI-USAGE.md @@ -9,35 +9,44 @@ Everyone adds their own rows. Two rows in the middle have no tool in them on purpose: they are where a person overruled what the tool proposed, which is the part that matters most. -| Date | Who | Tool | Used for | -| ---------- | -------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 2026-09-23 | erikhfj | opencode | Stack prototype (PostgreSQL, GraphQL Yoga, Drizzle, React + Apollo) to answer two design risks early: does Postgres FTS give case-insensitive single-term search, and does keyset paging stay correct across every sort mode. Verified live on the VM. **Closed unmerged**, kept as `archive/scaffold-prototype`. | -| 2026-09-23 | erikhfj | opencode | VM bootstrap scripts: PostgreSQL role and database, Node 24 via nvm, `crate-api` systemd unit, Apache `ProxyPass /graphql` | -| 2026-09-23 | erikhfj | opencode | Smoke tests against the running API. These caught three bugs the unit tests had missed: `GenreFacet.genre` shape drift from the SDL, drizzle expanding a JS array into scalar parameters inside a `::int[]` cast, and a missing review aggregate on `album(id:)` | -| 2026-09-24 | erikhfj | opencode | Plan to retire the prototype PR and re-land the work in milestone-sized PRs | -| 2026-09-24 | rachelks | - | **Overruled the plan.** Splitting generated code into smaller PRs would only fix the git cosmetics, so each issue must be implemented from its requirements by its owner. The prototype is a reference, not a source to copy from. Taken. | -| 2026-09-24 | robertky | - | **Overruled the plan.** Dropped the plan-before-code step as process for its own sake; clear issues plus PR descriptions that say what was done and tested are what reviewers read. Also: assign issues one milestone at a time, not all up front. Taken. | -| 2026-09-27 | rachelks | Codex (ChatGPT) | Discussed the UI specification for #29 and how to translate the project requirements into the planned interface. I reviewed and adapted the specification to the group's agreed design. | -| 2026-09-27 | robertky | Codex (ChatGPT) | Assisted with drafting the M1 GraphQL schema and data model for #2. I reviewed the model, kept database/resolvers out of M1, and incorporated peer-review feedback before merge. | -| 2026-09-28 | erikhfj | opencode | Tooling for #1: pnpm workspace, ESLint 9 flat config, Prettier, strict TypeScript, `AGENTS.md` | -| 2026-09-28 | rachelks | Codex (ChatGPT) | Assisted with reviewing #32 and diagnosing a Windows-specific formatting failure. Testing with `core.autocrlf=true` exposed the LF/CRLF issue; I reported it in the review and erikhfj fixed it with `.gitattributes` before merge. | -| 2026-09-28 | erikhfj | opencode | Review fix for #1: `.gitattributes` with `* text=auto eol=lf` after `core.autocrlf` broke `pnpm format:check` on Windows | -| 2026-09-28 | erikhfj | opencode | Workflow guide and this log for #4 | -| 2026-09-28 | evenkkl | Claude | Assisted with formulating a schema for the architecture decision in #3, and served as a sparring partner to help understand why we made the decisions we did. | -| 2026-09-28 | erikhfj | opencode | CI for #27: `quality` and `deploy` jobs, self-hosted runner registered on the VM, client bundle budget | -| 2026-09-28 | rachelks | Codex (ChatGPT) | Assisted with reviewing the CI workflow in #34. Identified that the `project2` runner label was not used by the deploy job. I reported it in the review, erikhfj then pinned the deploy job to the intended runner. | -| 2026-09-29 | erikhfj | opencode | Review fix for #27: `pull_request` no longer filters on `branches: [main]`, which had silently given stacked PRs zero CI runs | -| 2026-09-30 | rachelks | Codex (ChatGPT) | Assisted with reviewing the GraphQL schema in #35. I identified a missing paginated review connection required by the specification and requested changes; robertky corrected the schema before merge. | -| 2026-09-30 | robertky | Codex (ChatGPT) | Helped me interpret Rachel's schema review on #35. | -| 2026-09-30 | evenkkl | Claude | Assisted with formulating reviews of PR #35, and identifying additional areas for improvement. | -| 2026-10-01 | erikhfj | opencode | Answers to the open design questions: UUID as an `X-User-Id` header into the GraphQL context, narrowing facet counts, `id` tie-breakers, nulls last in both directions | -| 2026-10-01 | rachelks | Codex (ChatGPT) | Assisted with diagnosing the CI deploy failure after merge. The investigation traced the API restart issue to the `crate-api.service` check, `sudo` requiring a TTY, and a race while waiting for the API to start; erikhfj then fixed the deploy workflow. | -| 2026-10-01 | erikhfj | opencode | CI deploy fix for #27 after rachelks reported it: `grep -q` SIGPIPE silently skipped a live service, `sudo` had no TTY, and `sleep 2` raced Node binding the port. All three verified against the live unit | -| 2026-10-01 | erikhfj | opencode | Simplified this log to a table at the group's request | -| 2026-10-01 | robertky | Codex (ChatGPT) | Assisted with formulating good reviews of the architecture and UI-specification PRs. The group decided to include decade filtering; Rachel implemented the corresponding schema and documentation update in #38. | -| 2026-10-10 | evenkkl | Claude | Assisted with implementing the GraphQL Yoga server with `searchAlbums` for #6, and formulated an easy to understand PR description. Guided the reset of the prototype tables in the VM database (backup taken first). | -| 2026-10-13 | evenkkl | Claude | Fixed the review feedback on #6: cursor values validated against the sort, `reviewCount` returns 0 until reviews exist. The group decided genre filters combine with AND; Claude made the filter and the genre counts match that. | -| 2026-10-09 | robertky | Codex (ChatGPT) | AI was a good sparring partner when I drafted the initial #5 PostgreSQL migration. It gave me ideas on how to structure and improve the tables, relation tables, constraints, indexes, full-text search triggers and TypeScript migration runner. | +| Date | Who | Tool | Used for | +| ---------- | -------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 2026-09-23 | erikhfj | opencode | Stack prototype (PostgreSQL, GraphQL Yoga, Drizzle, React + Apollo) to answer two design risks early: does Postgres FTS give case-insensitive single-term search, and does keyset paging stay correct across every sort mode. Verified live on the VM. **Closed unmerged**, kept as `archive/scaffold-prototype`. | +| 2026-09-23 | erikhfj | opencode | VM bootstrap scripts: PostgreSQL role and database, Node 24 via nvm, `crate-api` systemd unit, Apache `ProxyPass /graphql` | +| 2026-09-23 | erikhfj | opencode | Smoke tests against the running API. These caught three bugs the unit tests had missed: `GenreFacet.genre` shape drift from the SDL, drizzle expanding a JS array into scalar parameters inside a `::int[]` cast, and a missing review aggregate on `album(id:)` | +| 2026-09-24 | erikhfj | opencode | Plan to retire the prototype PR and re-land the work in milestone-sized PRs | +| 2026-09-24 | rachelks | - | **Overruled the plan.** Splitting generated code into smaller PRs would only fix the git cosmetics, so each issue must be implemented from its requirements by its owner. The prototype is a reference, not a source to copy from. Taken. | +| 2026-09-24 | robertky | - | **Overruled the plan.** Dropped the plan-before-code step as process for its own sake; clear issues plus PR descriptions that say what was done and tested are what reviewers read. Also: assign issues one milestone at a time, not all up front. Taken. | +| 2026-09-27 | rachelks | Codex (ChatGPT) | Discussed the UI specification for #29 and how to translate the project requirements into the planned interface. I reviewed and adapted the specification to the group's agreed design. | +| 2026-09-27 | robertky | Codex (ChatGPT) | Assisted with drafting the M1 GraphQL schema and data model for #2. I reviewed the model, kept database/resolvers out of M1, and incorporated peer-review feedback before merge. | +| 2026-09-28 | erikhfj | opencode | Tooling for #1: pnpm workspace, ESLint 9 flat config, Prettier, strict TypeScript, `AGENTS.md` | +| 2026-09-28 | rachelks | Codex (ChatGPT) | Assisted with reviewing #32 and diagnosing a Windows-specific formatting failure. Testing with `core.autocrlf=true` exposed the LF/CRLF issue; I reported it in the review and erikhfj fixed it with `.gitattributes` before merge. | +| 2026-09-28 | erikhfj | opencode | Review fix for #1: `.gitattributes` with `* text=auto eol=lf` after `core.autocrlf` broke `pnpm format:check` on Windows | +| 2026-09-28 | erikhfj | opencode | Workflow guide and this log for #4 | +| 2026-09-28 | evenkkl | Claude | Assisted with formulating a schema for the architecture decision in #3, and served as a sparring partner to help understand why we made the decisions we did. | +| 2026-09-28 | erikhfj | opencode | CI for #27: `quality` and `deploy` jobs, self-hosted runner registered on the VM, client bundle budget | +| 2026-09-28 | rachelks | Codex (ChatGPT) | Assisted with reviewing the CI workflow in #34. Identified that the `project2` runner label was not used by the deploy job. I reported it in the review, erikhfj then pinned the deploy job to the intended runner. | +| 2026-09-29 | erikhfj | opencode | Review fix for #27: `pull_request` no longer filters on `branches: [main]`, which had silently given stacked PRs zero CI runs | +| 2026-09-30 | rachelks | Codex (ChatGPT) | Assisted with reviewing the GraphQL schema in #35. I identified a missing paginated review connection required by the specification and requested changes; robertky corrected the schema before merge. | +| 2026-09-30 | robertky | Codex (ChatGPT) | Helped me interpret Rachel's schema review on #35. | +| 2026-09-30 | evenkkl | Claude | Assisted with formulating reviews of PR #35, and identifying additional areas for improvement. | +| 2026-10-01 | erikhfj | opencode | Answers to the open design questions: UUID as an `X-User-Id` header into the GraphQL context, narrowing facet counts, `id` tie-breakers, nulls last in both directions | +| 2026-10-01 | rachelks | Codex (ChatGPT) | Assisted with diagnosing the CI deploy failure after merge. The investigation traced the API restart issue to the `crate-api.service` check, `sudo` requiring a TTY, and a race while waiting for the API to start; erikhfj then fixed the deploy workflow. | +| 2026-10-01 | erikhfj | opencode | CI deploy fix for #27 after rachelks reported it: `grep -q` SIGPIPE silently skipped a live service, `sudo` had no TTY, and `sleep 2` raced Node binding the port. All three verified against the live unit | +| 2026-10-01 | erikhfj | opencode | Simplified this log to a table at the group's request | +| 2026-10-01 | robertky | Codex (ChatGPT) | Assisted with formulating good reviews of the architecture and UI-specification PRs. The group decided to include decade filtering; Rachel implemented the corresponding schema and documentation update in #38. | +| 2026-10-07 | erikhfj | opencode | Simulated user identity for #10: a `User` type and the `X-User-Id` header contract, read into a per-request GraphQL context so that no field in `schema.graphql` takes a `userId` argument | +| 2026-10-09 | robertky | Codex (ChatGPT) | AI was a good sparring partner when I drafted the initial #5 PostgreSQL migration. It gave me ideas on how to structure and improve the tables, relation tables, constraints, indexes, full-text search triggers and TypeScript migration runner. | +| 2026-10-09 | erikhfj | opencode | VM runbook for #8, and converted `~/T19-Project-2` from a hand-copied prototype into a real git clone of `main` with a deploy SSH key. The gitignored `.env` was checksummed across `git checkout --force` to prove a deploy does not wipe `DATABASE_URL` | +| 2026-10-10 | evenkkl | Claude | Assisted with implementing the GraphQL Yoga server with `searchAlbums` for #6, and formulated an easy to understand PR description. Guided the reset of the prototype tables in the VM database (backup taken first). | +| 2026-10-10 | erikhfj | opencode | Wrote out the facet-count trade-off on #13: OR within a category pairs with per-dimension exclusion, AND with global counts. Posted as an analysis for the group to settle, not as a decision | +| 2026-10-10 | erikhfj | opencode | Forced `source-map-js` to 1.2.2 through `pnpm.overrides` for #43, after the Dependabot alert | +| 2026-10-10 | erikhfj | opencode | Traced the deploy gap rachelks raised on #42 and opened #44: CI built `server/` in the runner workspace while `crate-api.service` runs `dist/index.js` out of `~/T19-Project-2/server`, so a restart kept bringing back a 23 September prototype | +| 2026-10-12 | erikhfj | opencode | **Tool output corrected by a person.** The draft identity contract said `displayName`, derived server-side from the UUID, stops one user writing as another. It does not: the client can still send any UUID. robertky caught it on review and the wording was fixed in #40 | +| 2026-10-13 | evenkkl | Claude | Fixed the review feedback on #6: cursor values validated against the sort, `reviewCount` returns 0 until reviews exist. The group decided genre filters combine with AND; Claude made the filter and the genre counts match that. | +| 2026-10-15 | erikhfj | opencode | Rachel's four review points on #45: the smoke query omitted the required `sort` field so it could never have passed, the deploy step skipped instead of failing, and the body check grepped for the word "errors" instead of parsing JSON. Two bugs in my own first attempt: a multi-line `python3 -c` cannot live inside a YAML block scalar, and `\"` in bash single quotes is a literal backslash | +| 2026-10-15 | erikhfj | opencode | Documentation pass for #48: this log and the README brought up to date with what has actually landed | +| 2026-10-15 | erikhfj | opencode | Folded #46 into the README, and added `db:migrate` to the deploy on #45 after #46 pointed out it never ran: a deploy that lands migration files without applying them leaves the schema behind the code. Also reconciled `DATABASE_URL`, which the systemd unit reads from the checkout root and the server package scripts read from `server/.env` | ## Notes