Skip to content

core: harden scan transactions, leases, idempotency, and durable background work #303

Description

@m-khan-97

Why this is needed

The worker reuses one database connection indefinitely. A failed PostgreSQL transaction is not rolled back before failure status is written, so one database error can poison the worker loop permanently.

Long scans use a fixed 60-minute stale threshold with no heartbeat, lease owner or fencing token. A second worker can reclaim a still-running scan and both can persist duplicate results. CVE enrichment runs in a Gunicorn daemon thread and can disappear on restart.

Evidence: api/models/finding.py:160-231,367-450, scanner/worker.py:40-101, and api/routes/scans.py:160-198.

Acceptance criteria

  • All transactions rollback on failure and discard/reacquire broken connections.
  • Claims use renewable leases with owner, expiry and fencing token.
  • Heartbeat and completion updates require the current fencing token.
  • Evaluation/finding persistence is idempotent using stable unique keys/upserts.
  • Scan admission has per-subscription quotas, one-active-scan deduplication and idempotency keys.
  • Enrichment is a durable claimed job with retries, stale recovery and complete pagination.
  • PostgreSQL-backed fault-injection tests cover abort, restart, duplicate delivery, lease expiry and two-worker races.
  • Metrics include worker heartbeat, oldest queue age, lease age, retry count and last successful complete scan.

Metadata

Metadata

Labels

bugSomething isn't workingcoreCore team ownership not for studentspriority: highImportant, should be fixed in the current sprint

Type

No type

Projects

Status
🔨 In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions