AGPL-3.0-or-later · forever.

showcase · tier 3 · ops & support

Config drift sentinel

Builds the sanctioned baseline (RFC 7396 merge), diffs it against live prod (RFC 6902), and pages on-call only for the drift nobody approved, with a model explaining what changed.

Silence means prod matches exactly what was signed off. That is the whole alert policy. · conformance-gated in nika-spec ↗ · re-proven at every push

The whole file

8 tasks · 5 waves · the plan falls out of the bindings, nothing is scheduled by hand.

t3-config-drift-sentinel.nika.yamlsource
nika: v1workflow:  id: config-drift-sentinel  description: "live config vs sanctioned baseline → typed drift → explained alert"model: ollama/qwen3.5:4b   # local · zero key · swap for anthropic/claude-haiku-4-5 (explain is cheap)vars:  config_url: "https://api.internal.example.com/v1/config"  baseline_path: "./ops/config-baseline.json"  approved_overrides:    type: object    default: {}                      # zero approved drifts until you say otherwise    description: "Sanctioned config overrides (RFC 7396 merge-patch shape)"secrets:  oncall_webhook:    source: env    key: ONCALL_WEBHOOK_URL    egress:                       # sanction the one send · the secret IS the URL      - to: "nika:notify"        host_from_self: truetasks:  live:    invoke:      tool: "nika:fetch"      args:        url: "${{ vars.config_url }}"        mode: jq        jq: "."    retry:      max_attempts: 3      backoff_strategy: exponential  baseline:    invoke:      tool: "nika:read"      args: { path: "${{ vars.baseline_path }}" }  expected:    with:      baseline: ${{ tasks.baseline.output }}    invoke:      tool: "nika:json_merge_patch"      args:        target: "${{ with.baseline }}"        patch: "${{ vars.approved_overrides }}"  drift:    with:      expected: ${{ tasks.expected.output }}      live: ${{ tasks.live.output }}    invoke:      tool: "nika:json_diff"      args:        before: "${{ with.expected }}"        after: "${{ with.live }}"  fingerprint:    with:      live: ${{ tasks.live.output }}    invoke:      tool: "nika:hash"      args:        algo: blake3        content: "${{ with.live }}"        encoding: hex  explain:    with:      patch: ${{ tasks.drift.output }}    when: ${{ size(with.patch) > 0 }}    on_error:      recover: "(explanation unavailable · model call failed · the raw patch is attached)"    infer:      prompt: |        This RFC 6902 patch is UNSANCTIONED config drift in production ·        ${{ with.patch }}        Explain in 3 bullets · what changed · likely blast radius · first check.  alert:    with:      patch: ${{ tasks.drift.output }}      explanation: ${{ tasks.explain.output }}      live_hash: ${{ tasks.fingerprint.output }}    when: ${{ size(with.patch) > 0 }}    invoke:      tool: "nika:notify"      args:        channel: webhook        target: "${{ secrets.oncall_webhook }}"        message: "Config drift detected · ${{ with.explanation }} · live config blake3 ${{ with.live_hash }}"        severity: critical  record:    with:      patch: ${{ tasks.drift.output }}      live_hash: ${{ tasks.fingerprint.output }}    invoke:      tool: "nika:emit"      args:        event_type: "config.drift.scan"        payload:          patch: "${{ with.patch }}"          live_hash: "${{ with.live_hash }}"outputs:  drift:    value: ${{ tasks.drift.output }}    description: "RFC 6902 operations · empty when prod matches the sanctioned state"

nika inspect · engine 0.105.0 · vendored graph, never re-derived

10 declared edges · 5 waves · the plan falls out of the bindings