Skip to content

v1.8.0 — CdefMutationService + back-matter promotion + bulk Converter→CDEF

Choose a tag to compare

@clem-field clem-field released this 27 May 16:47

v1.8.0 — CdefMutationService + back-matter promotion + bulk Converter→CDEF

Minor release. Headline change: every CDEF mutation now funnels through
CdefMutationService, which validates the post-mutation OSCAL against
the NIST component-definition v1.1.2 schema before the transaction
commits. A mutation that would produce an invalid OSCAL hash is
rejected pre-commit instead of silently persisting. OSCAL back-matter
is promoted out of the legacy import_metadata["back_matter"] stash
to first-class BackMatterResource rows across every document type.

Six closed issues bundled into this release:

  • #498 — CdefMutationService + first-class CDEF back-matter
  • #581 — BackMatterResourceChange audit rows on BMR mutations
  • #582 — Deterministic CdefControlStatement UUIDs on clone
  • #583 — Back-matter promotion (stash → first-class) for SSP / SAR /
    SAP / Profile / POAM
  • #584 — AWS Labs validate:false opt-out removed; underlying schema
    gap root-caused (two local bugs, not upstream)
  • #499 — Bulk-apply Converter output to a CDEF clone, with NIST
    Rev 4 ↔ Rev 5 helper

Headline features

#498 — CdefMutationService

Single contract for all CDEF mutations. Wraps writes in a database
transaction; validates the post-mutation OSCAL via
OscalComponentDefinitionExportService.validation_result before
commit. Used by API #create / #update, web
#update_metadata / #update_field / #update_statement, clone via
DocumentDuplicationService, parser write-through, profile-derived
construction, and #create_control_resource. Raises
CdefMutationService::ValidationError on invalid OSCAL — caller sees
a clean 422 with the schema failure detail.

#583 — Back-matter promotion to first-class

Every doc-type parser (CDEF, SSP, SAR, SAP, Profile, POAM) now
writes BackMatterResource rows (source: "imported") instead of
stashing the OSCAL back-matter.resources array in
import_metadata["back_matter"]. Idempotent data migrations
backfill existing documents. BackMatterBuilder#deduplicated_imports
is now removed — the exporter reads from a single source.

#499 — Bulk-apply Converter → CDEF

Preview-then-confirm workflow takes a Converter (AWS Security Hub,
AWS Config, DISA CCI, CIS, SCAP) and applies its NIST 800-53 output
in bulk to a CDEF clone. Two API endpoints + a Hotwire UI on the
CDEF show page. Preview returns a HMAC-signed (15-min TTL) token
the confirm endpoint replays via CdefMutationService. Refuses
AWS-Labs-sourced CDEFs (clone first). NIST Rev 4 ↔ Rev 5
ControlMapping seeded from the official NIST CSRC
sp800-53r4-to-r5-comparison-workbook.xlsx; ControlIdNormalizer
translates ids across revisions automatically when a Rev-4
converter is applied with target_rev=5 (or vice versa). Every
successful apply cites the source Converter (and the rev mapping
when used) as BackMatterResource rows on the CDEF — the OSCAL
export carries auditable provenance.

  • Bulk-apply gated on admin OR converters.write RBAC.
  • Idempotent: re-applying the same converter is a no-op.
  • Two new AuditEvent actions registered:
    cdef_bulk_apply_converter_previewed,
    cdef_bulk_apply_converter_applied.

Supporting fixes

#582 — Deterministic statement UUIDs on clone

Re-exporting a cloned CDEF previously gave statement UUIDs fresh
random values each time. Now derived from
(new_control.uuid, "cdef-statement", statement_id) — same shape
the parser already uses for fresh imports — so re-exports
byte-compare cleanly. CdefControl-level derivation deferred (needs
a schema addition; control_id isn't unique within a CDEF).

#581 — BMR audit rows

BackMatterAudit.record_create emits one BackMatterResourceChange
per BMR create from CDEF write paths (parser promotion +
#create_control_resource), with batch_uuid grouping for
multi-resource transactions and explicit user: capture.

#584 — AWS Labs OSCAL validation re-enabled

Investigated the validate: false opt-out added in #580: not an
upstream problem. Two local bugs were masked — one bad placeholder
UUID in a test fixture, and the AwsLabsCdefImportService writing
the string "true" into published (which the exporter blindly
emitted into OSCAL metadata.published, failing the datetime
pattern). Both fixed; validate: false removed.

Compliance

  • docs/compliance/nist-sp800-53-rev5-mapping.md updated:
    • AU-2: notes the two new bulk-apply audit event types
    • CM-3: documents the preview-then-confirm workflow as a
      change-control pattern
  • Per-CDEF back-matter citations of converter source + rev mapping
    surface in the OSCAL export (CDEF back-matter is the audit
    trail of where each control came from).

Migrations

Two new migrations (both IrreversibleMigration, idempotent on
re-run):

  • 20260526120000_promote_cdef_back_matter_imports
    (shipped in #580, listed here for completeness)
  • 20260526200000_promote_remaining_back_matter_imports

Seed bumps (re-run on existing deployments):

  • converters → 1.4.0 (target_rev backfill on existing seeds)
  • nist_rev4_rev5_mapping → 1.0.0 (new section)

Test result

bundle exec rspec 2517 examples, 0 failures, 2 pending
(+~75 net new across the train)
bin/rubocop 0 offenses

Upgrade notes

  • No env var or config changes required.
  • The two data migrations run automatically via bin/rails db:migrate
    and are forward-only.
  • Operators on the v1.7.x line can upgrade in place.
  • The new bulk-apply UI is gated on the existing converters.write
    permission. Operators who can already use the AWS Labs refresh
    button can use bulk-apply.

🤖 Generated with Claude Code