ADR-005: Task Granularity
Status: PROPOSED.
Context
CURRENT: backend/internal/scans/worker.go processes an entire scan in one Worker process. It resolves scope, creates scan_jobs, executes each plugin, persists results, enriches runtime scope, and updates final scan state.
Key references:
- scan execution starts in
backend/internal/scans/worker.go:382; - plugin job creation starts at
backend/internal/scans/worker.go:505; - plugin execution happens at
backend/internal/scans/worker.go:538; - result processing happens at
backend/internal/scans/worker.go:588; - scope enrichment for later plugins happens at
backend/internal/scans/worker.go:592.
Decision
Represent one scanner plugin execution as one durable Worker task.
The task is associated with one scan_jobs row. The scan remains the aggregate user-visible operation.
Alternatives
Option A: Entire scan task
Pros:
- closest to the current Worker loop;
- fewer task rows.
Cons:
- remote Worker would need too much scan orchestration and persistence logic;
- harder to centralize ingestion;
- cancellation/retry is coarse;
- not suitable for future cross-Worker scheduling.
Option B: Scan job task
Pros:
- matches existing
scan_jobs; - supports plugin-level retry and progress;
- keeps Gateway in control of ingestion and sequencing.
Cons:
- requires central orchestration between plugin tasks;
- needs task state in addition to
scan_jobs.
Option C: One scanner plugin execution
This is effectively Option B for scanner tasks, because each current scan_jobs row represents a plugin execution.
Option D: Hybrid/hierarchical tasks
Pros:
- can support future scan orchestration and AI tasks.
Cons:
- more complex than needed for the first scanner implementation.
Consequences
- Scanner Workers execute plugins, not full scan orchestration.
- Gateway can preserve sequential plugin order and runtime scope enrichment.
- Result ingestion stays centralized.
- Parallel plugin execution can be introduced later only when dependencies are explicitly modeled.
Migration impact
The current scan Worker code must be separated into:
- central scan orchestration;
- plugin task payload creation;
- remote/local plugin execution;
- centralized result ingestion.