fix(core): harden scan durability and idempotency (#303) - #325
fix(core): harden scan durability and idempotency (#303)#325SHAURYAKSHARMA24 wants to merge 9 commits into
Conversation
Signed-off-by: Shaurya K Sharma <shauryaksharma24@gmail.com>
Signed-off-by: Shaurya K Sharma <shauryaksharma24@gmail.com>
Signed-off-by: Shaurya K Sharma <shauryaksharma24@gmail.com>
Signed-off-by: Shaurya K Sharma <shauryaksharma24@gmail.com>
Signed-off-by: Shaurya K Sharma <shauryaksharma24@gmail.com>
Signed-off-by: Shaurya K Sharma <shauryaksharma24@gmail.com>
Signed-off-by: Shaurya K Sharma <shauryaksharma24@gmail.com>
Signed-off-by: Shaurya K Sharma <shauryaksharma24@gmail.com>
Signed-off-by: Shaurya K Sharma <shauryaksharma24@gmail.com>
|
@SHAURYAKSHARMA24, this is the canonical track for #303’s durability layer: transaction recovery, leases/fencing, idempotent admission and writes, durable enrichment, and worker telemetry. One integration boundary must be resolved before lead review: migration |
Summary
This draft PR implements the complete #303 hardening contract: transaction recovery, fenced scan leases, idempotent result persistence, durable scan admission, durable CVE enrichment, and bounded operational signals.
Problems fixed
Architecture
ON CONFLICT; rule evaluations are uniquely keyed by scan, rule, and resource and are upserted.pending/runningscan per subscription and a unique subscription/idempotency-key pair. Same semantics replay the logical scan; changed semantics conflict.OPENSHIELD_MAX_SCANS_PER_SUBSCRIPTION_PER_HOURprovides an explicit optional time-window policy; one active scan remains the enforced concurrency quota.totalResultsthrough every page./metricsreads bounded PostgreSQL aggregates; labels are onlyqueue(scan/enrichment) andworker_type.Database migrations
e4f7a9b2c6d8— renewable scan leases and fencing tokens.f2b6d8e1a4c9— finding identities and rule evaluations. Existing findings receive distinctlegacy:<id>keys; no legacy rows are silently collapsed.a7c5e9d2f1b4— durable scan admission/idempotency indexes.c9e1a5b7d3f2— durable fenced enrichment jobs.d4a8c1e6b2f9— worker heartbeat storage for operational metrics.There is one Alembic head. Clean base-to-head, #325's original
e4f7a9b2c6d8-to-head, and downgrade/upgrade paths were validated on PostgreSQL.Concurrency guarantees
All authoritative scan-result writes re-check lease owner, fencing token,
runningstate, and unexpired lease underFOR UPDATEin the same transaction as persistence. Once worker A loses its lease and worker B reclaims with a newer token, A cannot update scan state, findings, evaluations, or enrichment progress. PostgreSQL unique constraints and upserts make duplicate API/result/job delivery converge on one logical record.Deployment
d4a8c1e6b2f9.scanner/worker.pyprocess. The worker now processes both scan and enrichment jobs./metricsfor worker liveness, queue age, lease age, retries, and last successful scan.Tests
postgres:16-alpine: 150 passed, 0 skipped.test_vector_store_purity, because this checkout has anai/vectorstoredirectory without its BM25 index. This PR does not alter AI/RAG code.ruff check .: passed.ruff format --check .: passed.Acceptance criteria
Related
Closes #303