Current Architecture
This file describes the careervector-cvl checkout as of 2026-05-12.
Stable Architecture
CareerVector is a SvelteKit app on Cloudflare Workers with D1/R2, a realtime Durable Object relay, MCP worker, and a Typst compile path for browser/headless CV rendering.
Workspace state is CRDT-backed and partitioned into sub-docs. This migration
branch is aligning the job-tracking sub-doc with the final jobs model.
Realtime is a relay/fanout path, not durable authority. Durable writes must go
through the api worker's op path (Hono routes in api/src/routers/).
MCP should use the same command/op model as the UI, not a parallel data model.
Data-Model Cleanup State
Final vocabulary:
role hidden shared aggregate
ad source listing for one URL/posting
job workspace-local tracked item exposed to users/APIs
workspace.jobs[job_id] { url, attributes }
Workspace ops are job.create, job.update, and job.delete. The workspace
sub-doc is jobs.
Known cleanup pressure:
lib/mutations/src/opsCatalog.ts, workspace-client routing, api routes, MCP, and dashboard code must agree onjob.*ops and thejobssub-doc.- Shared corpus writes need the ensure/outbox path for ad and role knowledge.
- Dashboard/JobDetail/DataCell need read-chain-backed resolved views.
Important Distinction
This checkout is not simply "newer main." It is a migration worktree with a partially applied model change. A green test in one package does not imply the app is coherent.
Before implementing features, decide whether the work is workspace-private job state in D1/Y.Doc or shared ad/role knowledge in CrateDB/jobcache.
Storage Boundary
D1/Y.Doc owns the private workspace rung: workspace.jobs, CVL/CL, settings,
notes, evaluations, local summaries, and collaboration state.
CrateDB/jobcache owns shared ad/role knowledge, shared work cache, embeddings,
matching, evidence, and reducer-approved aggregate outputs. (CrateDB Cloud
replaced CockroachDB as the hot DB in the 2026-06 cutover — see
architecture/CRATEDB-MIGRATION.md; the Cockroach cluster is dormant,
rollback only.)