Implements ControlsProvider by fetching GET /api/compliance/v1/oscal/catalog from
breakpilot-compliance, snapshotting the exact bytes to disk, and mapping the
catalog into the corpus controls the mapping engine consumes. Deterministic /
offline-capable: on fetch failure it falls back to the last snapshot so scans
still run (matters for on-prem/werkbank).
- controls/oscal_provider.rs: HTTP fetch (bearer-optional) + atomic snapshot +
offline fallback + naive context ranking; ControlsProvider impl ("breakpilot-oscal")
- controls/mod.rs + lib.rs: register module
- 3 lib tests: url/path building, context ranking, snapshot round-trip + fallback
Not yet wired into startup — no ControlsProvider consumer exists until the
assessment-plan router lands. clippy -D warnings + fmt --all --check clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deserialise the OSCAL catalog served by breakpilot-compliance and flatten it
into the framework-agnostic traits::Control the mapping engine consumes. Pure
serde (no reqwest); exposes content-hash for snapshot/drift on the consumer side.
Fixture-tested against the real 40-control CRA catalog (3 lib tests).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>