feat: per-subnet scan profiles (P2-05 / 26.15) — closes P2 batch#18
Merged
Conversation
Operators can now run aggressive hourly deep scans on critical
infrastructure while leaving the guest network on a lazy daily
liveness sweep — all from one config, one agent process.
New config shape:
scanner:
profiles:
- subnet: 10.0.0.0/24
scan_interval: 1h
deep_probe: true
deep_probe_ports: [443, 22, 3306, ...]
- subnet: 192.168.1.0/24
scan_interval: 24h
scan_interval: 5m # global default for any inherited fields
timeout: 2s
workers: 50
Existing scanner.subnets flat-list deployments keep working —
mutually exclusive with profiles, validated at boot.
Implementation:
- config.SubnetProfile with *bool fields so profiles can explicitly
disable a globally-enabled flag.
- config.ScannerConfig.Resolve() flattens into ResolvedProfile with
every field populated; agent's runtime has no further fallback.
- scanner.Scan(ctx, subnet) becomes Scan(ctx, subnet, SubnetOptions).
Scanner-level fields remain as defaults consulted by resolve().
- Agent ticks at the SHORTEST per-profile interval; each profile
keeps its own nextDue timestamp; only due profiles get scanned on
each tick. Housekeeping (prune, diff, tracker) runs every tick.
- Tick interval safety floor of 1s prevents 1ns config typos from
CPU-pegging the agent.
- agent.New now returns (*Agent, error) — Resolve runs at
construction so duplicate-subnet / mutually-exclusive errors
surface at boot, not on the first tick.
7 new config tests covering legacy path, override semantics,
pointer-bool False-beats-global-True, duplicate detection,
mutual-exclusion validation, empty-profile rejection, zero-profile
happy path (watchdog-only mode).
Closes the operator-feedback P2 batch — all five items shipped
across 26.11–26.15.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Operators can now run aggressive hourly deep scans on critical infrastructure while leaving the guest network on a lazy daily liveness sweep — all from one config, one agent process.
```json
{
"scanner": {
"profiles": [
{ "subnet": "10.0.0.0/24", "scan_interval": "1h", "deep_probe": true },
{ "subnet": "192.168.1.0/24", "scan_interval": "24h" }
],
"scan_interval": "5m",
"timeout": "2s",
"workers": 50
}
}
```
Existing `scanner.subnets` flat-list deployments keep working — mutually exclusive with `profiles`, validated at boot.
Architecture
Breaking changes (in-tree only)
Test plan
Closes the P2 operator-feedback batch
All five items shipped across 26.11–26.15:
🤖 Generated with Claude Code