Files
krow_talent_app/src/api/demoUser.ts
Aravind 3ddacf269a fix(seed): emit the users array the backend seeder reads
The fixture generator was a version behind the seeder, and the gap was
the `users` key.

`internal/seeder` unmarshals `seed.json` into `{demoUser, users,
entities}` and writes every account in `users`, falling back to
`demoUser` alone when the key is absent. `fixtureFrom` never emitted it —
its comment still claimed the Go loader "ignores the rest", which stopped
being true when the seeder gained the field. So `npm run seed:check`
reported stale on every run, and that is the seventh suite failure, the
one that pre-dates the TypeScript migration.

What made this worth investigating rather than regenerating: the
committed fixture was NOT wrong. It carries two accounts — the demo
administrator and `employer@krow.app` — and running `npm run seed:fixture`
against the old generator would have written a fixture without them.
`krow-backend/docs/deploy-9d3192a.md` says so in as many words, and tells
anyone deploying not to run it.

The accounts are not deleted from a live database by that — the only
DELETE in the seeder is the shift-record prune, and `upsertUser`'s ON
CONFLICT deliberately leaves `password_hash` alone. The damage lands on
the next fresh environment, where `user_employer` would simply never be
created, leaving nobody to sign in as to reach the employer console —
which is the exact gap `seeder.go` records the account as having been
added to close.

The matching frontend half already existed, unmerged, on
`feat/krow-employee-pages` (7a4b61d). That branch is a 53-file console
restructure that renames the same files this migration renamed, so it is
not mergeable here. Only the three files that carry the contract are
taken: `EMPLOYER_USER`, `seedData.User` naming both accounts, and the
generator emitting `users`.

The proof is that nothing had to be written. With the generator corrected
its output is byte-identical to the fixture already committed in
krow-backend — 168,293 bytes, `cmp` clean — so `seed.json` was never
opened for writing, and its md5 and mtime are untouched.

  typecheck     0 errors
  seed:check    "seed.json is in step with src/api/seed.js", exit 0
  npm test      1685/1691, up from 1684 — the fixture check now reads
                "24 applications, byte-identical". The remaining 6 are
                exactly the documented dca1842 baseline failures.
  lint          exit 0, 0 errors, 289 warnings
  build         exit 0, bundle 74d17e2d… unchanged

The bundle being unchanged is itself a check: `demoUser.ts` IS in the
production bundle, and `EMPLOYER_USER` is a new export of it. Nothing in
the app imports it, so it is tree-shaken out and not one byte reaches the
shipped code.

No baseline artifact touched. krow-backend not modified.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HBG1wnuRfJKCstGB8Fekr8
2026-09-19 23:54:36 +05:30

68 lines
2.7 KiB
TypeScript

import type { User } from '@/types/user';
/**
* The shape of a signed-in user, before the server has answered.
*
* This is a **default shape, not a record**. The user lives in PostgreSQL and
* arrives from `GET /me`; what is here is the set of keys that must resolve
* during the first render, in the fraction of a second before that response
* lands.
*
* It exists as its own module for one reason: `base44Client.js` needs exactly
* this, and it used to reach into `api/seed.js` to get it — a 1,900-line
* fixture of demo positions, candidates, interviews, staff and shift records,
* every byte of which was then in the production bundle so that three booleans
* could be defaulted. The fixture is still the right thing for the test scripts
* that read it (`scripts/skill-check.mjs`, `scripts/owliver-capture.mjs`); it
* was never the right thing for the running app. `seed.js` re-exports this
* constant, so those scripts are unchanged and the production import chain no
* longer reaches them.
*
* Nothing here is a source of truth for anything. `preferences` is the one part
* that is read: `auth.preferences()` is synchronous — `AssistantPanelContext`
* decides whether Owliver starts open in a `useState` initialiser — so a key
* the server has never stored still has to resolve to something rather than to
* `undefined`.
*/
export const DEMO_USER: User = {
id: 'user_demo',
full_name: 'Alex Rivera',
email: 'demo@krow.app',
role: 'admin',
account_type: 'employer',
created_date: '2026-06-01T09:00:00.000Z',
/* Product preferences travel with the account rather than in a store of their
own, so there is one record to persist and one thing to read. */
preferences: {
owliverDefault: true,
compactDensity: false,
emailDigest: true,
},
};
/**
* The employer account, and the reason there is a second one at all.
*
* `policy.go` has always had three roles — admin, employer, talent — and the
* fixture had one administrator, so two thirds of the authorization table was
* never exercised and there was nobody to sign in as to reach the employer
* console. This account is what makes that path reachable.
*
* Unlike `DEMO_USER` this is not a default shape for the first render: nothing
* in the running app reads it. It exists so that `seedData.User` names both
* accounts, which is what the backend seeder writes. See `seed.ts`.
*/
export const EMPLOYER_USER: User = {
id: 'user_employer',
full_name: 'Jordan Blake',
email: 'employer@krow.app',
role: 'employer',
account_type: 'employer',
created_date: '2026-06-01T09:00:00.000Z',
preferences: {
owliverDefault: true,
compactDensity: false,
emailDigest: true,
},
};