JobCache ↔ CareerVector relationship
Status (2026-08-17): both edge installations and the relevant Core boundaries exist in code. CareerVector is the first deployed installation. JobCache App's Worker/D1/MCP and the new participant-lifecycle credentials/migrations still require production provisioning.
There are two product domains:
- CareerVector serves one applicant and their private workspace.
- JobCache serves the eagle-eyed market view. It contains an observer-facing JobCache App zone and the shared JobCache Core zone.
The diagram separates App from Core to expose the privacy and runtime boundary. It does not create a third product.
Ownership
| Concern | Owner |
|---|---|
| workspace identity, CV/CL, notes, evaluations and applicant-local state | CareerVector |
| session identity, saved observer views and dashboard-local state | JobCache App |
| ads, roles, public evidence, extraction, shared search and market intelligence | JobCache Core |
| person recommendation | JobCache Core, using only purpose-approved person facts |
| product public APIs and perspectives | their respective product edge |
| seam contracts, reduction mechanics, collectors and protocol algorithms | shared libraries, installed by both edges |
JobCache Core belongs operationally and conceptually to JobCache. Its neutrality is about
identity: it owns neither workspace_id nor session_id and never receives either.
What crosses each seam
| Direction | Privacy class | Payload |
|---|---|---|
| CareerVector → JobCache Core | pseudonymous individual | versioned person_key, reduced vector/state and allowlisted person facts |
| CareerVector → JobCache Core | anonymous aggregate | thresholded cohort facts with no participant key |
| JobCache Core → CareerVector | product result | immutable role search or recommendation snapshot plus provenance |
| JobCache App → JobCache Core | pseudonymous individual | versioned observer_key and allowlisted individualized observer state |
| JobCache App → JobCache Core | anonymous aggregate | thresholded metrics input with no participant key |
| JobCache Core → JobCache App | product result | immutable role/metric snapshot plus provenance |
The emitting edge selects the privacy class from the endpoint and purpose. It is never guessed from the presence of a field. Raw workspace/session identity, inverse pseudonym maps and private document state do not cross.
Person and observer are load-bearing graph kinds. Observer activity cannot train the person recommendation engine. Pseudonymous facts remain linkable data with retention, erasure and key-version requirements; anonymous aggregates remain only if their threshold and cohort dimensions prevent singling out.
Runtime relationship
JobCache Core exposes scoped authenticated internal APIs to both product edges. The fast
CareerVector path is bearer-gated POST /api/corpus/search; the public legacy
GET /api/search remains a separate ad-browsing compatibility surface. The fast path
answers a waiting product request. The slow path pulls product facts with claim/ack and
delivers immutable snapshots back idempotently. No product receives corpus credentials and
JobCache Core never reads a product's D1 directly.
CareerVector remains usable from its committed local snapshots while JobCache Core is temporarily unavailable. First use without a compatible snapshot is unavailable, not mislabelled as stale. The JobCache App implementation follows the same rule; it becomes operational once its Worker and D1 are deployed.
Code relationship
The products share one repository today. Co-location enables shared package imports but does not merge product domains:
| Shared | Product-specific |
|---|---|
| privacy envelopes and participant profiles | CareerVector workspace public API |
| request keys and immutable result IDs | JobCache session public API |
| reduction, collector and claim/ack mechanics | RADAR and JobCache UI/MCP perspectives |
| seam-facing route installers | local workspace/session authorization and copy |
jobcache/shared/ remains JobCache's internal shared home for corpus/search/extraction
code. Cross-product contracts live in @cv/corpus-shared; seam route/store installers
belong in a platform package once their ports are proven. This is repository naming, not a
claim that the JobCache Core domain belongs to CareerVector.
As-built boundary
CareerVector still contains interim direct-CrateDB and JobCache-public gateways. Those are
compatibility scaffolds. The scoped Core search and participant-erasure APIs now exist, as
do CareerVector's outbox and JobCache's claim/apply/receipt-ack worker. jobcache/api/
implements the session-private observer mirror and jobcache/mcp/ its thin agent peer.
They are not production-active until canonical IaC provisions the App D1, service binding,
scoped credentials and coordinated domain cutover.