Goal
Let users assemble a custom compliance implementation by composing parts of existing implementations — not inheritance, composition. A single org-level module should be able to declare:
- "Include all of
slsa-l3."
- "Include
openssf-baseline levels 1 and 2."
- "From
openssf-baseline, also include only OSPS-AC-01.01, OSPS-AC-02.01, and OSPS-VM-03.01 from level 3 — nothing else."
- "Add these org-specific controls on top."
- "Override the remediation for
OSPS-AC-01.01 with our internal SOP."
The result is a single, named implementation (acme-corp-baseline) that the framework treats like any other registered implementation.
Why composition, not inheritance
Inheritance ties an implementation to a single parent and tends to grow brittle override chains. Composition lets an org cherry-pick from multiple sources (a baseline + a regulator + an internal policy) and keeps the relationship explicit and declarative. It also makes upstream changes easier to reason about — you opted into specific controls, not "whatever the parent ships next."
Proposed shape
A composite implementation declares its composition in TOML, no Python required for the common case:
```toml
acme-baseline.toml
[implementation]
name = "acme-corp-baseline"
display_name = "Acme Corp Baseline"
version = "1.0.0"
spec_version = "Acme Internal v1"
[[compose]]
from = "openssf-baseline"
include_levels = [1, 2]
[[compose]]
from = "openssf-baseline"
include_controls = ["OSPS-AC-01.01", "OSPS-AC-02.01", "OSPS-VM-03.01"]
[[compose]]
from = "slsa"
include_levels = [3]
Org-local additions
[[controls]]
id = "ACME-001"
... full control definition ...
Override an inherited control's remediation
[overrides."OSPS-AC-01.01"]
remediation = "..." # or path to a different template
```
The framework resolves composition at registration time, producing a flat list of ControlSpecs the rest of the pipeline already knows how to handle.
Open questions
- Conflict resolution: if two composed sources define the same control ID with different content, who wins? Probably "last
[[compose]] block wins" plus an explicit [overrides] table for clarity. But this needs a spec.
- Versioning: a composite pins specific versions of its sources, or floats? Pinning is safer; floating is more ergonomic. Probably pin by default with an explicit
version_constraint = \"...\".
- Discovery: composites still register via the existing
darnit.implementations entry point, right? They behave identically to non-composite implementations at runtime.
- Override scope: which fields are overridable?
remediation clearly; severity, passes, help_url less obvious. Start narrow.
- Cycles: composite A composes B which composes A. Detect and reject at registration time.
Acceptance
Out of scope (for now)
- Cross-implementation remediation merging (e.g., "run baseline's remediation for X then SLSA's remediation for Y" as a single combined fix). Defer until composition itself is stable.
- Runtime composition via CLI flags (
--compose openssf-baseline:1,2 slsa:3). Maybe later; start with declarative TOML.
Goal
Let users assemble a custom compliance implementation by composing parts of existing implementations — not inheritance, composition. A single org-level module should be able to declare:
slsa-l3."openssf-baselinelevels 1 and 2."openssf-baseline, also include onlyOSPS-AC-01.01,OSPS-AC-02.01, andOSPS-VM-03.01from level 3 — nothing else."OSPS-AC-01.01with our internal SOP."The result is a single, named implementation (
acme-corp-baseline) that the framework treats like any other registered implementation.Why composition, not inheritance
Inheritance ties an implementation to a single parent and tends to grow brittle override chains. Composition lets an org cherry-pick from multiple sources (a baseline + a regulator + an internal policy) and keeps the relationship explicit and declarative. It also makes upstream changes easier to reason about — you opted into specific controls, not "whatever the parent ships next."
Proposed shape
A composite implementation declares its composition in TOML, no Python required for the common case:
```toml
acme-baseline.toml
[implementation]
name = "acme-corp-baseline"
display_name = "Acme Corp Baseline"
version = "1.0.0"
spec_version = "Acme Internal v1"
[[compose]]
from = "openssf-baseline"
include_levels = [1, 2]
[[compose]]
from = "openssf-baseline"
include_controls = ["OSPS-AC-01.01", "OSPS-AC-02.01", "OSPS-VM-03.01"]
[[compose]]
from = "slsa"
include_levels = [3]
Org-local additions
[[controls]]
id = "ACME-001"
... full control definition ...
Override an inherited control's remediation
[overrides."OSPS-AC-01.01"]
remediation = "..." # or path to a different template
```
The framework resolves composition at registration time, producing a flat list of
ControlSpecs the rest of the pipeline already knows how to handle.Open questions
[[compose]]block wins" plus an explicit[overrides]table for clarity. But this needs a spec.version_constraint = \"...\".darnit.implementationsentry point, right? They behave identically to non-composite implementations at runtime.remediationclearly;severity,passes,help_urlless obvious. Start narrow.Acceptance
[[compose]]and[overrides]lands in the framework spec.packages/darnit-examplethat composes a subset ofdarnit-baseline.Out of scope (for now)
--compose openssf-baseline:1,2 slsa:3). Maybe later; start with declarative TOML.