cui-control-plane

One control inventory for a DoD CUI boundary. Five NDAA-driven regimes attach as crosswalk edges, not five programs. The pipeline withholds a control rather than reporting 0 of 0 when no collector can speak. This page is how you run it, and how you point it at a real estate.

Run it in your browser — no install → A hosted demo runs the real pipeline against fixtures: one control inventory, five NDAA regimes as crosswalk edges, OSCAL O1–O5 emitted and the SPRS score derived from assertion records.

What it does

“NDAA compliance” is not a program. It resolves to CMMC Level 2, DFARS 7012 incident reporting, Section 889 telecom representation, the 1260H Chinese Military Companies list, and forthcoming FY2026 harmonization — plus FASCSA sitting adjacent and routinely conflated with them. Building five parallel programs produces five populations of the same assets and no way to answer “how exposed are we.”

This repository keeps one inventory. Each regime is a crosswalk: an identifier, a confidence, and a written basis. Never framework text. The pipeline collects, loads a local DuckDB warehouse, asserts every control, and emits OSCAL O1–O5 with deterministic v5 UUIDs. Variance Frequency and Variance Duration come off the assertion history, which is what makes it a risk instrument rather than a compliance cost center. SPRS is derived from those same records — and refused when the weight table is empty.

When and where to use it

Use it when

  • You handle CUI and need one system of record for CMMC L2, 7012, 889, and 1260H — not four binders.
  • You are a DIB subcontractor who has been told to “automate NDAA compliance” and need a place to start that will not invent a pass.
  • You need OSCAL that re-exports byte-identically, so the package is a git diff, not a blob that changes every run.
  • You want GRC engineers to practice the discipline of withholding: no collector, no claim.

Do not use it when

  • You need a FedRAMP 20x continuous-monitoring harness. That is ksi-harness. CMMC is out of scope there on purpose.
  • You want a submitted SPRS score out of the box. The real weight table ships empty. A guessed weight is a wrong score in a Government system of record.
  • You expect six operating controls on day one. status is lifecycle in the environment. Nothing here is operating until it is instrumented against real telemetry and observed holding.

How to use it

Node 22+. No Python, no warehouse product, no credentials, nothing contacts a real system. Read time for the guided setup is about fifteen minutes; the first real run is an afternoon.

0. Run it before you change anything.

git clone https://github.com/RootCawsLLC/cui-control-plane.git
cd cui-control-plane
npm install
npm run pipeline

That collects from bundled fixtures, builds a local DuckDB warehouse, evaluates every control, and writes assertion records. You should see five controls asserted and one withheld. The withheld one is the lesson: no collector populates its source, so the tool refuses to say anything rather than reporting 0 of 0 passing.

Then walk the rest of the chain:

npm run emit -- --assertions .evidence
npm run variance
npm run coverage
npm run demo

demo is the eight-step walkthrough: validate, coverage, SPRS against the empty real weights (it refuses), SPRS against fixture weights (arithmetic runs; the result is never called submittable), variance, policy (generates nothing while no control is operating), the 889 representation (blocked by unresolved manufacturers), and OSCAL emit. Every refusal is the point of the step.

1. Make it yours. Twelve questions, every one with a working default.

npm run init      # writes gitignored ccp.config.yaml — the only file you edit
npm run doctor    # what is configured, what is missing, which controls will be withheld

doctor is the command you will run most. It is the answer to “am I set up yet?”

2. The three decisions only you can make.

DecisionDefault, and why
CUI boundaryPick enclave unless leadership has funded enterprise scope. If you do not know, that is a finding, not a config value to guess.
Supplier masterOne CSV of every supplier. Population for both 1260H and 889. You do not need an API.
1260H listThis repo will not ship it. A stale copy reads as “screened” when it is not. Export the current DoD list on a calendar.

3. Wire the first real source. Do CSV today. Drop exports in inbox/. The asset inventory needs two sources — CMDB and cloud — because the control is a reconciliation. Cloud-only reports every asset as unmanaged; CMDB-only can never find an unmanaged asset. Both look like measurements. Neither is one.

The full walkthrough — Entra, Okta, AWS Identity Center, AWS IAM, Azure — is docs/SETUP.md.

Take it into your organization

  1. One inventory. Do not stand up a CMMC program, an 889 program, and a 1260H program. Write the control once. Attach regimes as edges.
  2. Split by layer when owner, cost, threat model, or failure mode differs. The MFA pair is the worked example: enclave MFA is in the assessment boundary; corporate-IT MFA is not, and claims no 800-171 requirement. One “MFA” record spanning both is the munged control that makes an SSP indefensible.
  3. Absent data is recorded as absent. Unresolved manufacturer fails. Superseded list edition fails. “Could not determine” is never a pass. Fixture evidence stamps every downstream artefact NOT REAL EVIDENCE.
  4. Policy last. ccp policy generates nothing until a control is operating — observed holding, not planned. A policy for a control that is not yet holding is documented misalignment.
  5. Keep real evidence out of the repo. Bundles name accounts, roles, and failing resources. Point collection at a private store. The fixture path is how you learn the tool.

Six controls ship as the spine, not as a finished CMMC L2 set. npm run coverage prints the backlog against 110 requirements. Adding a control is: write the YAML with a population definition from the start, write the dbt model, union it, add a stamped fixture, validate. See AGENTS.md.

What the fixture run shows

You cannot press a button on this page and get a live warehouse — the tool is a CLI. What you can do is run the same fixture path the documentation claims, on your laptop, in five minutes, and get the same refusals.

Five asserted, one withheld
The withheld control is the demonstration. No collector, no population, no 0-of-0 pass.
SPRS refuses on the real weight file
The 5/3/1 scheme is encoded. The per-requirement weights are not guessed. Fixture weights produce a number that is never called submittable.
Policy generates nothing
Zero controls are operating. The command names every control it skipped and why.
889 representation blocked
Unresolved manufacturers. False Claims Act exposure attaches to the representation itself, so “we could not determine three components” is a basis for representing nothing yet.
OSCAL O1–O5, byte-identical on re-export
Deterministic v5 UUIDs. All eight artefacts validate against NIST’s oscal-cli in CI. Title and remarks say NOT REAL EVIDENCE.

What it refuses

Never emit a claim the evidence does not support. That is the one rule. Unresolved manufacturers fail. A supplier screened against a superseded list fails. OSCAL findings are never rounded up — three failures out of 1,842 is not-satisfied. Fixture stamps travel into every artefact. Near-zero overlap between two sources that claimed to describe the same estate is reported as a source error, not 81 unmanaged assets. The full list of refusals is in the README, and each one is a test.