ADR-0007: Durable scan pipeline and stage cache keys
Status: Accepted · 2026-07-14Decision
Job hierarchy:scan_campaigns → scan_partitions → work_units → stage_attempts,
with immutable requested parameters, mutable checkpoint state, leases with
heartbeats, visibility timeouts, retry classes (transient|throttled|auth| unsupported|corrupt|policy_denied|permanent), and dead-letter rows with safe
diagnostics.
Pipeline stages (versioned independently):
observe → metadata → permissions → labels → content(hash+extract) → features → inference → project(graph/search) → risk → review
Stage cache key = (tenantId, assetId, sourceVersionId, stageName, stageImplVersion, configVersion, inputArtifactHashes). A stage first checks for a
valid cached artifact under its key and records cache_hit explicitly, so tests can
assert no content fetch/hash/extraction occurred for:
- unchanged content + new model release → features reused, inference re-run;
- permission-only change → content/features reused, exposure/risk recomputed;
- rename/move → content features reused, location/context recomputed.
Consequences
- The invalidation matrix from the reference architecture is encoded in the
per-stage cache-key composition in
scan/pipeline.ts(observe/permissions/ labels key onsourceVersion; content/features oncontentVersion+ algorithm versions + tenant config version; inference additionally on the ensemble release), exercised by the “incremental efficiency (invalidation matrix)” tests inscan/scan.test.ts. - Progress reporting uses known/estimated work counts, never fabricated percentages.