Skip to main content

Compliance Registry

The compliance registry is a first-class catalogue of the standards, regulations, internal SOPs, and manuals that alerts can be mapped against. Frameworks and controls live in Knowledge Engine as normal entities; alerts reference them by ID instead of embedding inline name/number/specification blocks.

Why a registry

Historically, each alert carried its own complianceControlsViolations block listing the framework name, control number, and a paraphrase of the specification text. That made it impossible to:

  • Retire or version a framework without touching every alert.
  • Ask questions like "which alerts cover ISO 27001 A.10.1.1?" without string-matching across hundreds of files.
  • Distinguish free standards (where we can legally store the full spec) from paid ones (where we can only store the control number and source URL).
  • Show per-app compliance posture in the UI.

The registry fixes all four by moving framework and control definitions into their own tables and turning the alert-side reference into a normalised foreign key.

Data model

Three entities, all in the Knowledge Engine Postgres database:

  • Framework — a standard, regulation, SOP, or manual. Has a type, publisher, version, source URL, and a coverage field indicating whether controls carry full specification text (FULL), partial text (PARTIAL), or just the control number and source URL (REFERENCE_ONLY, used for paid standards).
  • Control — a single requirement inside a framework (e.g. NIST SP 800-53 AC-1). Carries a controlNumber, optional title and specification, and a sourceURL that deep-links to the authoritative text.
  • ControlMapping — an equivalence, superset, subset, or related relationship between two controls. Used for side-by-side versioning (ISO 27001:2013 vs 2022) and for cross-framework crosswalks.

Every entity supports a nullable tenantID so customers can maintain their own SOPs alongside the shipped public standards.

Free vs paid standards

Free standards (NIST, CIS, OWASP, FedRAMP, SLSA, HIPAA, GDPR, CCPA, PCI DSS, SOC 2 TSC) are seeded with full specification text from the authoritative source. Paid standards (ISO/IEC, IATF, AS) are seeded with only controlNumber + title + sourceURL — the specification text is never copied. Coverage is marked REFERENCE_ONLY on those frameworks so the UI can hide sections that would otherwise render empty.

Authoring

Frameworks and controls are authored as GraphQL mutation files under kaleidoscope-configuration/compliance/, the same way analyzers and widgets are authored. The directory is processed alphabetically, so frameworks are created before the controls that reference them:

kaleidoscope-configuration/compliance/
├── 01-frameworks/
│ ├── nist-sp-800-53.graphql
│ ├── iso-27001.graphql
│ └── ...
└── 02-controls/
├── nist-sp-800-53/
│ └── controls.graphql
├── iso-27001/
│ └── controls.graphql
└── ...

Each file contains one or more CreateFramework or CreateControl mutations. The mutations are idempotent — re-running them updates existing rows rather than creating duplicates.

The KE bootstrap client picks up the folder automatically; no wiring is needed beyond placing files there.

Querying

query {
frameworks(filter: { types: [STANDARD, REGULATION] }) {
id
name
coverage
controls {
controlNumber
title
}
}
}

Controls can be filtered by framework and control number:

query {
controls(
filter: {
frameworkIDs: ["framework_nist-sp-800-53"]
controlNumbers: ["AC-1", "AC-2"]
}
) {
id
title
specification
sourceURL
}
}

Alerts and compliance

Alerts reference controls by ID. The insight feed joins those IDs against the registry at read time, so renaming a framework or correcting a control title propagates everywhere automatically. App-level compliance posture is derived by walking app → analyzer groups → analyzers → alerts → controls → frameworks.

Versioning

Framework versions live side-by-side. To model an upgrade from ISO 27001:2013 to ISO 27001:2022:

  1. Create a new framework framework_iso-27001-2022 (keep the old one).
  2. Create its controls under the new framework ID.
  3. Use CreateControlMapping to record EQUIVALENT, SUPERSET, SUBSET, or RELATED relationships between 2013 and 2022 controls.
  4. Set supersededBy on the old framework to point at the new one once it has been adopted.

Alerts that still reference the old controls keep working; migration is opt-in per alert.