Skip to content

Feature: composition of compliance implementations (assemble an org policy from parts of others) #233

@mlieberman85

Description

@mlieberman85

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

  • TOML schema for [[compose]] and [overrides] lands in the framework spec.
  • Reference composite implementation in packages/darnit-example that composes a subset of darnit-baseline.
  • Conflict-resolution and cycle-detection tests.
  • Docs: when to compose vs. fork an implementation.

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions