Readiness methodology
Theme

CMMC readiness, end to end

How a CMMC / NIST SP 800-171 Rev 2 readiness engagement runs, from an empty workspace to a package the client can self-attest with in SPRS or hand to a C3PAO. The client's question is am I ready to self-attest, or to pass a C3PAO assessment? Finding gaps is one step toward answering that question.

The arc of an engagement

  1. 1Scaffold
  2. 2Interview
  3. 3Scope
  4. 4Prove
  5. 5Score
  6. 6Recommend
  7. 7Deliver
  8. 8Maintain
The stack: portable containers on a dedicated host
Dedicated VPS host · Docker
NocoDB→ n8n→ runner · runner-ai
→ Claude API external service

Every piece (the database NocoDB, the orchestrator n8n, the script runners) is a Docker container on a dedicated VPS, never a local computer. An action or upload in NocoDB fires a webhook to n8n, which runs a Python script in one of two runner containers: runner for data work, runner-ai (the one container holding the AI key and internet access) for anything that calls Claude. Because every piece is a container, the whole stack is portable: it moves to another host without re-architecting. The Runs line under each phase below shows the path that phase takes.

The flow

The same process as a decision flow, where a control forks toward evidence or toward remediation, and the loop that turns a gap into coverage. Node colors match the legend below.

no

yes

No or N/A

Yes or Partial

Define

Perform

no

yes

Documentation

Implementation

new evidence

evidence goes stale

environment changes

0 Onboard: clone the per-client base, seed it, enter CAGE

1 Scaffold: create assessment, populate controls

2 Interviews: people, tech, data flows

Scope settled? Needs Review = 0

2e Directional triage: claim each control

Claimed status?

Gap: route to remediation, no evidence requested

Open evidence request

Objective type?

3 Document review: AI proposes evidence

Perform evidence: request plus vision auto-check

4 Review queue: verify, judge sufficiency

Verified AND satisfies?

Re-request (still a gap)

5 Mark and recompute: SPRS, POA&M

6 Recommend a fix

Gap kind?

Documentation gap: propose language from the library

Implementation gap: POA&M raised, propose a remediation

Client adopts, produces new evidence

7 Generate the SSP from the assessment

7 Export the package: SSP, POA&M, evidence, SPRS

Ready: self-attest, or hand to a C3PAO

8 Maintain: ConMon calendar, fresh evidence, change review

0
Onboarding minutes: mostly the clone job Consultant

Stand up the client's own isolated workspace before any data is entered. How onboarding is built

  • One Kick off engagement button on the won deal's CRM row clones the shared reference base into a new per-client base inside the self-hosted NocoDB (on the VPS): a faithful copy of all the crosswalk reference data (frameworks, controls, standards library) and every view, with the client tables empty. No client's data ever touches another client's base.
  • The same job seeds the engagement record and the client's CAGE codes (plus the parent org's HLO CAGE) from the CRM row, where an optional Enrich button looks them up on SAM.gov first. It then opens one readiness assessment per target level. The consultant checks the identifiers and adds any facility the lookup could not know about.
  • From here every automated step targets this base: the scripts, the runner, and the NocoDB action buttons are all base-aware, so a button in a client base runs the job against that base, with writes isolated to it.
How it works

Onboarding clones the template base (NocoDB's Duplicate Base) into a per-client base: reference data, views, and the empty Client_Profile / CAGE_Codes tables all come along. Every engagement script resolves its tables by title within whichever base it's told to target (NOCODB_BASE_ID), so the same scripts, runner, and n8n buttons drive any client base with no per-client code. When a reference correction lands (a NIST fix, a reworded control), push_reference_data.py propagates it out to every client base: matching rows by business key, dry-run first, and skipping-and-flagging any base that's drifted rather than overwriting it.

RunsNocoDB→n8n→runner · VPSclone · base-aware · push
1
Scaffold the assessment minutes Consultant

Declare the scope up front; every later step keys off that declaration. How the scaffold is built

  • Kickoff has already created one assessment per target level, linked its framework and populated it. To widen the scope, link another framework to the assessment.
  • Run Populate objectives → the full control checklist appears in seconds.
  • Do this first. Populating objectives looks like an assessment step, but it is the scope declaration that Phase 3's document review waits on.
How it works

populate_gap_assessment_objectives.py reads the linked framework(s) and creates a row for every assessment objective (Gap_Assessment_Objectives) and every control (Gap_Assessment_Requirements). The script is idempotent: linking another framework later only adds what's missing, so re-running is always safe.

RunsNocoDB→n8n→runner · VPS
2
Interviews the bulk of the human effort ConsultantClient

One long conversation, recorded in five passes, where each pass feeds the next.

  • 2a · People & roles: capture real people, then map the client's own job titles to the standard role taxonomy. How people and roles are recorded
  • 2b · Technology inventory: one row per tool the client runs; capture the scoping inputs in the same conversation. How the inventory is built
  • 2c · Data flows: walk each flow forward, then backward (backups & logging are what quietly drag systems into scope). How data-flow mapping is built
  • 2d · Compute the scope: sweep the inventory, then work Needs Review down to zero. Clearing Needs Review draws the assessment boundary. How the scoping engine works
  • 2e · Control-directional triage: walk each control and record a Claimed Status: do you actually do this? How triage works
Decision · the prune
claimed No / N/A

The client has already said the control is a gap. Route the control to remediation and never request evidence for it.

claimed Yes / Partial

These are the controls you'll prove. Open an evidence request for each one downstream.

Claimed ≠ assessed. A claim comes before proof; MET / NOT MET is the finding after proof, and the two live in separate fields. A scope-reducing call (CRMA, Out-of-Scope) stays provisional until the control behind the call is proven in Phase 5.

How it works: the two computed passes

2d · Scoping engine. recompute_scoping_categories.py sweeps the whole inventory and assigns each asset one of the 32 CFR 170.19 categories (CUI Asset · Security Protection · CRMA · Specialized · Out-of-Scope) or Needs Review. The engine is fail-closed: an asset with a missing input can never compute to Out-of-Scope, and lands in Needs Review with a Rationale naming the missing input. Scope-reducing calls (CRMA, Out-of-Scope) stay provisional until their control is proven MET in Phase 5.

2e · Triage. A plain-language Triage_Questions bank drives the "do you do this?" pass. The claim is pre-seeded from the tool stack (infer_claims_from_stack.py) and any existing SSP (extract_ssp_claims.py, where a model reads the plan on the runner with internet access), then check_claim_discrepancies.py flags the telltale mismatch: claimed done, but you run none of the tools this control needs. Every claim carries a provenance rank: Client-confirmed > Interview > SSP > Tech-stack inferred.

RunsNocoDB→n8n→runner · runner-aiscoping · claim inference · SSP reading
3
Documents in ClientAutomation

The client hands over policies; the automation reads them. How document review works

  • Upload each document → text is auto-extracted (spot-check the extracted text: scanned files get no OCR).
  • Queue the document → Claude proposes Evidence as verbatim quotes with a sufficiency judgment, marked AI-proposed.
Split · by objective type
Define objectives

Satisfied by documents → the automated review above proposes candidates.

Perform objectives

Need a screenshot or config export → personalized evidence request → vision auto-check → reconcile.

How it works

Upload fires a webhook → ingest_client_documents.py extracts the text and a section index (pdfplumber / python-docx; no OCR, so a scanned PDF is parked as Cannot Read with an alert). Flip to Queued and review_document.py batches the in-scope Define objectives by control family, asks Claude for verbatim quotes plus a Sufficiency judgment, locates every quote in the source itself and derives its citation from that position (a quote not found word-for-word is kept, flagged NOT FOUND IN SOURCE, so invention stays visible; check_quote_fidelity.py re-checks on demand), and writes Evidence as AI-proposed. A parallel job harvests reusable values from the document (the client's name and the like), so later drafts read with their real details instead of placeholders.

RunsNocoDB→n8n→runner-ai · VPS→Claude API
4
Work the evidence queue the judgment work: deliberately not automated Consultant

Two independent calls on every candidate artifact, worked from a “Review — start here” console and purpose-built action views that surface only the rows and fields each decision needs, with an action-first Suggested action cue on every row saying what to do next. How the evidence queue works

  • Verification Status: have I actually looked at this?
  • Sufficiency: does it satisfy the objective, or just point at where the answer lives?
Coverage gate
Human-verifiedANDSatisfies objective → counts as coverage.
anything less→ not coverage. An AI-proposed or "pointer only" quote is a lead, not proof.
How it works
  1. Receive. Client artifacts (screenshots, config exports) arrive as Evidence linked to the personalized Evidence_Request, generated by a button at the start of this phase for the controls claimed done in 2e: generate_evidence_requests.py resolves {{technology}} to the client's actual tool and led each ask with the plain-language Assessor Intent.
  2. Vision sanity check. check_evidence_vision.py sends each artifact to Claude vision and grades the artifact against the request's What It Must Show, with three checks:
    right kind of artifact?named elements present?stale vs. the freshness window?
    It returns a verdict, Likely match · Partial · Likely mismatch, plus notes. The verdict tells the reviewer where to look first; the reviewer makes the call.
  3. Human gate. You make two independent calls: Verification (have I looked?) and Sufficiency (does it satisfy the objective, or just point at where the answer lives?). Coverage needs both.
  4. Reconcile: auto-fires the moment you set a decision. Setting Accept / Reject on the request triggers reconcile_evidence.py (webhook → n8n → runner, no button to hunt for). The script propagates the decision onto the evidence, rolls the request status up, sends rejected or empty ones back to To Collect (the client sees your Reviewer Feedback beside a rejected request in the portal), and reports how many Perform objectives are now ready to mark MET.
RunsNocoDB→runner-ai · VPS→Claude APIvision auto-check
5
Mark objectives & recompute ConsultantAutomation

Record the findings; the scoring rolls itself up. How marking and scoring work

  • Mark each objective MET / NOT MET, and record why each NOT MET failed.
  • Recompute fires automatically: one confirmed NOT MET fails the whole requirement; the recompute calculates the DoD SPRS score (points only for what's proven) and opens a POA&M for each new gap the rules allow on one (refusing the rest with the reason), never touching your existing remediation notes.
How it works

Marking an objective fires recompute_gap_assessment.py automatically (webhook → n8n → runner). It rolls objectives up to requirements (one confirmed NOT MET fails the requirement, even with others unassessed), computes the DoD SP 800-171 SPRS score: 110 minus the weight of every requirement not proven MET. Unassessed requirements count against the score, so the number is the defensible floor. A requirement escapes deduction as N/A only when the system is incapable of it, never because the control is simply missing. The recompute writes the score, with the basis for every deduction, onto the assessment and into the SSP. It also auto-creates a POA&M for each newly-failing requirement, linked to the exact objectives that caused it, and never overwrites an existing POA&M, so your remediation notes survive every re-run.

RunsNocoDB→n8n→runner · VPSrecompute · SPRS · POA&M
6
Recommend, then close the loop ConsultantClient

Turn each gap into a specific fix the client can adopt. Every gap is one of two kinds. How recommendations are drafted

  • Documentation gap (a policy or procedure that isn't written) → draft a Documentation Recommendation: proposed language, placement, based on the standard library.
  • Implementation gap (a control not actually in place: setting not applied, technology not owned, coverage short) → a POA&M is recorded automatically, and a proposed remediation is drafted for it.
  • Client adopts the fix → the adopted fix produces new Evidence, which the consultant links back and marks Implemented; the score moves only when Phase 5 marks the objective MET.
How each side is proposed

Documentation side. The draft is pulled from the standard library: PPS_Statements, one atomic policy / procedure / standard statement per assessment objective. Pick the statement that satisfies the objective and propose where it goes. The language reads with the client's real values, not placeholders: {{company_name}} and the like resolve automatically, from values mined out of the client's own documents (and flagged for a human to confirm). Based On links the draft back to its source statement, so every recommendation is traceable to library language rather than free-written, and proposed text is never counted as coverage.

Implementation side. When a technical control isn't in place, the recompute opens a POA&M automatically, and a proposer drafts its fix from the data already linked to the failing requirement: target state from Evidence_Requirements, the function that evidences the objective from the same recipe (Evidence_Requirements.Function), what the client already owns from Client_Technologies, the required value from ODP Values. Each draft is typed: apply a setting to a tool the client owns, or acquire & implement one the client doesn't, with a policy-or-process fallback where no tool function applies. Both sides are one click on the assessment (Propose remediations / Propose documentation). The drafts land in a review queue for the consultant to accept or reject; a draft never marks anything satisfied.

RunsNocoDB→n8n→runner · VPSassembled from data, no model
7
Package & deliver ConsultantAutomation

Assemble the artifact that demonstrates readiness. How the deliverables are built

  • Author the SSP: build the System Security Plan from the structured assessment. Each objective gets an implementation statement (seeded from the standard library with the client's real values), alongside the client's real technologies and roles. The consultant confirms each statement; until every statement is Confirmed, the document stays marked DRAFT.
  • Export the deliverables: the SSP (carrying the SPRS score), the collected Evidence in its own package, and the POA&M as a spreadsheet, one click each, to self-attest with, or hand a C3PAO.
  • Freeze the final version: a finalized SSP is archived immutably, so the next re-freeze diffs against it and shows exactly how the readiness posture changed.
How it works

SSP: a first-class implementation-statement layer. Nothing is written from scratch. For every objective, how the control is satisfied is authored as its own implementation statement: seeded from the standard library (PPS_Statements) with the client's real values substituted in, and tied to the governing document and the implementing technology. Each statement carries a Draft → Confirmed status, and that Confirmed lock is the gate: the document renders as a DRAFT (“N of M statements confirmed”) until every assessable objective is Confirmed, then it becomes the Final SSP. Completeness is fail-closed as well: unassessed objectives, a MET without evidence, or unsettled scope each mark the consultant's working copy NOT FOR SUBMISSION and block the freeze, so an incomplete assessment can never be archived as a finished one. The SSP exports to Word (.docx) from a one-click Run Action, with the real SPRS score and its basis in the system identification up front.

Package. The client-facing SSP is lean and reads in delivery voice; the evidence and internal workpaper detail split into a companion Objective Evidence Package, with the POA&M as its own spreadsheet. Each is its own one-click export, attached to the assessment, so the set stays traceable to the same data.

Version control. A finalized SSP freezes into an immutable archive: the delivered SSP's text, a SHA-256 hash of it, and a snapshot of scope, score, and frameworks, kept as a version. The assessment is one living record per client scope, so every called milestone (a formal assessment, the annual affirmation, a POA&M closeout) re-freezes the same assessment, and the document-to-document diff is the posture-change record: what moved, what newly passed, what regressed. A called milestone also freezes the evidence behind each MET into the same version: a manifest with the SHA-256 of every artifact, and a package of the SSP, the manifest and the files for the client to keep.

RunsNocoDB→n8n→runner · VPSrendered from data, no model
8
Maintain between assessments monthly, until the next assessment ConsultantClientAutomation

Delivery starts a monthly rhythm. Each month the consultant and the client walk the ConMon calendar together, review the evidence the client refreshed, and work through what changed, so the value of staying ready shows up every month rather than every three years. How Maintain is built

  • Meet every month: one review covers what came due and got done, the refreshed evidence and the consultant's conclusion on each piece, and any change inside or outside the environment. A monthly review pack records all of it, for the client's file and for the Affirming Official's annual affirmation. The consultant writes four short notes on the month; one click assembles the rest (calendar items done and due, evidence received with our conclusion on each, key dates, score trend) into a Word pack.
  • Keep the recurring work on a calendar: every recurring activity runs at the frequency the client defined. NIST SP 800-171 Rev 2 has the client define five of these frequencies outright: risk assessments (3.11.1[a]), vulnerability scans (3.11.2[a]), security control assessments (3.12.1[a]), SSP updates (3.12.4[g]) and malicious code scans (3.14.5[a]). The client's own policies set the rest, such as account reviews and training. Those five are captured for each client as data: the standard library's value to start, replaced in Phase 3 by what the client's own documents say (kept only with a word-for-word quote), and confirmed by a person. A daily calendar keeps one open occurrence of each confirmed activity, due at its last performance plus its frequency; the consultant records each performance, its evidence and who signed it off, and the client sees what's coming in the portal.
  • Keep the evidence fresh: every evidence request carries a freshness window. Shortly before an accepted artifact's window ends, its request reads Refresh due; once past it, Stale, and the artifact stops counting toward the SSP and the milestone package, so a MET never rests on last year's screenshot. The client's new upload goes back through review, and the old one is kept as superseded. The mark and the score stay the consultant's call.
  • Keep the dates: the Affirming Official's annual affirmation of continuing compliance (32 CFR 170.22), the three-year reassessment (170.16 for a self-assessment, 170.17 for a C3PAO assessment) and the 180-day POA&M closeout (170.21). Once the consultant records the CMMC Status and its date, each deadline is worked out and shown to the client in the portal, with a countdown for the closeout, and to the consultant in the daily digest.
  • Review a new technology before it goes in: before the client adopts a tool, show its likely scope category, the requirements it touches, any N/A requirement it would make applicable, its FedRAMP status if it is a cloud service, and the SSP sections that would change. That is the impact analysis 3.4.4 asks for before a change is made. The consultant records the client's answers, one click writes the report from the catalog, the maps and the client's own assessment, and the client and their Affirming Official decide.
  • Keep the evidence trail: a refreshed artifact is a new record and the old one is kept, so the history survives from one year to the next. When the client calls a formal assessment or an affirmation, the SSP and the evidence behind every MET freeze together, with a SHA-256 hash of each artifact, into a package the client keeps for the six years 32 CFR 170 requires (170.15 and 170.16 for self-assessments, 170.17 and 170.18 for hashed artifacts in certification assessments). Calling a formal assessment moves the engagement into Maintain.
  • Handle change inside the environment: a new system, data flow, vendor or role arrives as a proposed change, re-runs scoping and updates the SSP. Change control is the client's own practice under 3.4.3 and 3.4.4, and the Affirming Official decides whether a change is significant. A new tool gets the technology review above; the rest follows the runbook by hand. Automated check not built yet
  • Handle change outside it: a rule change, a cloud provider's FedRAMP claim, a new STIG release. Daily watches catch them, and each change is routed to the clients it touches: a STIG release to clients running that product, a FedRAMP listing change to clients using that service, a rule change the consultant flags to clients whose scope includes the requirement it names. The consultant marks each one relevant or not, and the relevant ones go into that month's pack.
Decision · is this change significant?
change is Routine

Patching, or swapping a tool for a like-for-like one with the same or better security (a FIPS 140-2 firewall replaced by a FIPS 140-3 one). Update the records; no reassessment.

change makes N/A applicable

A requirement assessed as N/A now applies (adding WiFi brings the wireless requirements into play). That requirement was never assessed, so the change needs a reassessment.

In between. A change that brings systems, configurations or security tools never assessed before needs careful evaluation with the Affirming Official. Source: DoD CIO CMMC FAQ C-A12, which is guidance, not regulation.

How it works: what runs today, and what is planned

Built. Each evidence requirement carries a freshness window (30 to 365 days) that is copied onto every request, the vision check flags an artifact older than its window at grading time, and a daily sweep ages every accepted artifact against its window (Refresh due, then Stale) across all client bases. Each client's defined frequencies are data, harvested from their documents and confirmed by a person, and a daily ConMon calendar schedules from the confirmed ones. Compliance dates (closeout countdown, affirmation, reassessment) are tracked from what the consultant records. The recompute writes the 180-day closeout deadline into the score's basis and appends a snapshot to Score_History on every run. Daily watches cover the official sources, cloud providers' FedRAMP claims (checked against the GSA Marketplace data) and the DISA STIG library, and each change is routed to the clients it touches for the consultant to review. A monthly pack is built in one click; a proposed technology is reviewed in one click; a called milestone freezes the SSP and the evidence behind it with a SHA-256 hash of each artifact.

Planned. An automated significant-change check: on an accepted environment change, re-run scoping, test each not-applicable requirement for new applicability and draft the note for the Affirming Official.

RunsNocoDB→n8n→runner · VPSbuttons on the runner · daily jobs on the scheduler · no model

The loops. New evidence from an adopted recommendation flows back to Phase 4 (re-verify) and Phase 5 (re-score). In Phase 8, evidence that goes stale reopens its request in Phase 4, and a change in the environment reopens scoping in Phase 2. An unimplemented recommendation stays visibly distinct from a satisfied one, so proposed language can never be mistaken for coverage.

The outcome

A defensible readiness posture, packaged: a generated SSP, a scored SPRS self-assessment, a POA&M for every remaining gap, and verified evidence behind every MET. Enough to self-attest with confidence, or to hand a C3PAO on day one of a certification assessment. After delivery, Phase 8 keeps that posture current until the next assessment.

Who does it

Consultant: you
Client
Automation: scripts & AI

Finding states

Provisional: a call not yet proven
MET: proven & sufficient
NOT MET / gap: routes to a POA&M

Read it as

A control's journey: claimed → proven → scored → remediated.
The prune (2e) keeps the evidence hunt small.
Not built yet marks planned work; a dashed box in the flow means the same.

CMMC / NIST SP 800-171 Rev 2 readiness methodology · Updated 30 September 2026