JobCache Architecture

Status (2026-08-18): the API-first architecture is implemented, migrated and live. JobCache Core's corpus/search facade and participant lifecycle run from jobcache/interface/ on a protected Alwaysdata origin; the session-private App API owns the EU jobcache-app D1 at api.jobcache.corbet.ch; and the thin MCP peer is live at mcp.jobcache.corbet.ch. The old Render service remains provider-suspended and owns neither public App host.

JobCache is one product with two runtime and privacy zones:

JobCache App
  observer-facing perspectives · session-private state
                         │
                    privacy seam
                         │
JobCache Core
  shared corpus · extraction · search · recommendations · market intelligence

“Core” is a concern boundary, not another product, brand or repository namespace. Both zones are named, deployed, logged and operated as JobCache. Core owns neither JobCache App's session_id nor CareerVector's workspace_id.

JobCache App

The App is the observer-facing edge for employers, analysts, advertisers, operators and their agents.

Layer Responsibility
perspectives MCP now; website later; status, ops, QA and wiki remain peers
public API strict role search/evidence plus saved views, snapshots and reductions scoped to one explicit session capability
local D1 session-private views, immutable snapshots, many-to-many view grants, current pointers, opaque live read-only mirrors and deletion outbox
reduction records pseudonymous observer work or a pending anonymous-cohort request; it does not mislabel one session as an aggregate
collectors/internal API strict observer delivery plus a durable participant-erasure drain, each with a distinct bearer

The App's public API and perspectives are JobCache-specific. Its store, reduction, collectors and seam-facing internal API reuse the same implementation first proven by CareerVector.

JobCache Core

Core is the shared market-intelligence substrate:

Concern Owner
ads, roles, evidence and public fact projections CrateDB corpus
normalize, disambiguate ad → role, enrich, embed and index extraction/corpus pipeline
live role search and result metadata search executor
person-only preference matching recommendation engine
anonymous cohorts and observer-facing measures metrics builder
claims, leases, delivery receipts, retries and quarantine operational store beside the internal API
authenticated product-to-Core protocol JobCache internal API

JobCache Core returns roles as the product unit and ads as supporting evidence. Stable role identity and merge/split aliases are Core responsibilities; product edges must not invent role IDs from URLs.

Operational churn does not belong in CrateDB. The corpus is the durable searchable asset; leases and retry state must not compete with its indexes.

The App/Core privacy seam

Every crossing declares its purpose and privacy class:

Class App emits Core may use it for
pseudonymous individual a versioned observer_key and allowlisted facts individualized saved state where the feature requires continuity
anonymous aggregate a thresholded cohort with no participant key market metrics and analytics

session_id, raw session state and the inverse pseudonym map stay in JobCache App. An observer_key is pseudonymous personal data, not anonymous. Observer facts never train the person recommendation engine.

The same rule applies independently at the CareerVector/Core seam with workspace_id and person_key; see System Architecture.

Perspectives and packages

JobCache perspectives remain peers under jobcache/: api/, mcp/, interface/, ingest/, ops/, qa/, status/ and wiki/. jobcache/api/ is the App boundary; jobcache/mcp/ calls only that API; jobcache/interface/ is the current Core facade and compatibility process. jobcache/shared/ owns JobCache-wide Core helpers. Cross-product seam contracts live in the repository's shared library family; The Shared Seam Package is authoritative for their exact paths.

The wikis remain product perspectives: CareerVector documents the applicant product; JobCache documents both its App and Core. Cross-product architectural contracts are linked, not duplicated.

As-built boundary

Component Current state
CrateDB corpus and JobCache extraction live
JobCache Core role-search API implemented as a strict, content-identified role contract
JobCache Core participant lifecycle implemented: monotonic tombstones, retryable cleanup, deterministic public-safe receipts and active views that exclude crash residue
CareerVector participant erasure transport live claim/apply/receipt-ack protocol with D1 and Crate lifecycle migrations applied
JobCache App public facade live Cloudflare Worker over EU D1 and protected Core
JobCache App D1/session/observer mirror implemented: opaque sessions, saved views, immutable snapshot grants, live read-only derivatives, reductions and atomic local-delete/Core-erasure outbox
shared UI/realtime foundation implemented: CareerVector and JobCache share shell actions, contribution/scraping state, awareness normalization, relay/WebRTC attachment and status projection; JobCache tab content remains product-owned
JobCache MCP live secretless thin peer over a private App Worker service binding
CareerVector seam installation live search, immutable grants, composite claim/ack, strict delivery and durable participant erasure

Direct database access and the rolling legacy public-search fallback are compatibility scaffolds. They are not valid final dependencies for CareerVector.

The legacy Crate-backed /api/sessions routes have been removed from jobcache/interface and return 404. Only jobcache/api/ owns JobCache session state. Core's runtime principal is schema-scoped; retired direct participant writers fail closed.

Source: wiki/content/architecture/JOBCACHE-ARCHITECTURE.md