Rule patterns cookbook

Use these reusable patterns when writing policy rules.

Each pattern includes:

  • when to use it
  • a rule example
  • what to verify

Pattern 1: Scope enables control

When to use:

  • A scope decision should enable a required control.
- id: WEB_APPLICATION_SERVICE_CONTINUITY_SCOPE
  target: component
  if:
    - eq: { key: type, value: webApplication }
    - eq: { key: serviceContinuity, value: inScope }
  then:
    - expect: { entity: component, control: trafficFiltering }

Verify:

  • control appears when serviceContinuity=inScope
  • control does not appear when outOfScope/notAssessed

Pattern 2: Parallel entity parity (api + webApplication)

When to use:

  • The same behavior should apply to more than one entity type.
- id: API_SERVICE_CONTINUITY_SCOPE
  target: component
  if:
    - eq: { key: type, value: api }
    - eq: { key: serviceContinuity, value: inScope }
  then:
    - expect: { entity: component, control: trafficFiltering }

- id: WEBAPP_SERVICE_CONTINUITY_SCOPE
  target: component
  if:
    - eq: { key: type, value: webApplication }
    - eq: { key: serviceContinuity, value: inScope }
  then:
    - expect: { entity: component, control: trafficFiltering }

is easier to debug and work with, even if it uses more lines in a file than:

- id: SERVICE_CONTINUITY_SCOPE
  target: component
  if:
    - eq: { key: type, value: [api, webApplication] }
    - eq: { key: serviceContinuity, value: inScope }
  then:
    - expect: { entity: component, control: trafficFiltering }

Verify:

  • both entity types trigger identical outcomes

Pattern 3: Value-based scoring map

When to use:

  • A config value should map directly to score outcomes.
- id: TRAFFIC_FILTERING_SCORE
  target: connection
  if:
    - eq: { key: type, value: apiConnection }
  then:
    - map_score:
        key: trafficFiltering
        map:
          "true": 1
          "false": -1
        default: 0
        missing: 0

Verify:

  • known values map correctly
  • missing/unknown values are deterministic

Pattern 4: Topology-aware prerequisite

When to use:

  • A control depends on upstream/downstream context.
- id: SENSITIVE_UPSTREAM_REQUIRES_AUTH
  target: component
  if:
    - eq: { entity: upstream, key: sensitiveData, value: true }
    - eq: { key: identity, value: inScope }
  then:
    - expect: { entity: component, control: hasAuthentication }

Verify:

  • only components with matching upstream context are affected

Pattern 5: Derived value before score

When to use:

  • You need a normalized derived field before scoring.
- id: DERIVE_RUNTIME_CLASS
  stage: init
  target: component
  if:
    - eq: { key: deploymentType, value: managed }
  then:
    - set: { key: runtimeClass, value: managed }

- id: SCORE_RUNTIME_CLASS
  stage: post
  target: component
  if:
    - present: { key: runtimeClass }
  then:
    - map_score:
        key: runtimeClass
        map:
          managed: 1
          unmanaged: -1

Verify:

  • derived value exists before score rule executes

Pattern 6: Specification mapping by value

When to use:

  • Implementation guidance should vary by config value.
- id: ENCRYPTION_SPEC_HINTS
  target: component
  if:
    - present: { key: encryptionInTransit }
  then:
    - map_specification:
        key: encryptionInTransit
        map:
          strong ciphers:
            - Use modern TLS configuration
          none or weak:
            - Upgrade transport encryption

Verify:

  • correct specification guidance appears for each value

Pattern 7: Rule-level reporting references

When to use:

  • You need standards traceability per rule.
- id: WEBAPP_AUTH_REFERENCE
  target: component
  if:
    - eq: { key: type, value: webApplication }
    - eq: { key: identity, value: inScope }
  then:
    - expect: { entity: component, control: hasAuthentication }
  reporting:
    references:
      - standard: NIST CSF 2.0
        requirement: PR.AA

Verify:

  • reporting output includes the expected rule-level mapping

Pattern 8: Negative guard rule

When to use:

  • You need explicit non-compliant signaling for missing values.
- id: MISSING_IDENTITY_SIGNAL
  target: component
  if:
    - eq: { key: type, value: webApplication }
    - not:
        present: { key: identity }
  then:
    - score: -1

Verify:

  • rule triggers only on genuinely missing/unset state