In a regulated bank, an IT change is not just a risk decision — it's a compliance decision. A change to a SOX- or PCI-scoped system cannot ship on a low risk score during a change freeze; it needs a compliance sign-off, an approver of record, and an audit trail that survives an examiner. A generic ITSM scores the change's blast radius and lets a low score auto-approve. This overlay makes the compliance check a hard gate the CAB model can never override, and every state transition an immutable audit row.
The problem — and the money
The buyer is the bank's IT-risk / change-governance lead who answers to an auditor. A failed regulated
change — or one that shipped without sign-off during a freeze — is not a Sev-2, it's a finding, with
remediation cost and regulatory exposure measured in millions. A vanilla ITSM will happily auto-approve
the highest-scoring, lowest-blast change even on a payments database. The payoff here is a refusal: a
change to a regulated = true CI whose compliance_status is still pending is routed to a human as
compliance_hold — even though the CAB model said auto_approve and the blast radius was low. The
hard gate overrides the model, exactly as compliance requires. In finserv, the deterministic gate is
the feature.
This is the ITSM suite + the finserv overlay. The six base skills — core, cmdb-blast-radius, change-management and the rest — are unchanged. The overlay only adds compliance columns, one audit table, and a deterministic gate layered over the CAB verdict. Same bucket, one copy of the rows.
What finserv adds
A small, additive diff on top of the suite (skill: itsm/finserv → the
itsm/overlays/finserv contract):
- Compliance columns — on
itsm/corecis(compliance_scopesox|pci|none,regulatedboolean — the hard-gate input) andchanges(approver_role,change_freeze_override,compliance_status) — added withALTER TABLE … ADD COLUMNover the pg wire. A column-add, never a second copy. - One table —
change_audit(keyaudit_id): the immutable regulatory audit trail — one append-only row per state transition (actor, action, prev/new state, evidence). - One gate change — change-management's CAB gate still returns
{decision, risk, reason}, but a deterministic compliance hard gate layers over it:compliance_holdwhen the CI isregulatedandcompliance_status <> 'approved', regardless of the model's decision or a low blast. Onlychange_freeze_override = true+ anapprover_rolesign-off releases it. - Presets —
auto_approve_risk = nonefor regulated CIs;require_pir = true; a quarter-end freeze window seeded.
Apply the diff — the ALTERs, the audit table, and the seed that drives the gate:
In the itsm bucket, apply the finserv overlay: ALTER cis ADD compliance_scope, regulated; ALTER changes ADD approver_role, change_freeze_override, compliance_status; create change_audit; tag orders-db as sox/regulated; add CHG5001 (change to orders-db, compliance_status pending, model verdict auto_approve, low risk) and CHG5002 (change to web-storefront, non-regulated).
data_pg→data_table_create→data_table_upsertAdded compliance_scope/regulated to cis and approver_role/change_freeze_override/compliance_status to changes (ALTER over pg — the masters, not a copy). Created change_audit. Tagged orders-db sox + regulated=true; seeded CHG5001 (regulated, compliance_status pending) and CHG5002 (non-regulated) — the inputs the hard gate reads.
export BUCKET=itsm # the SAME bucket the ITSM suite built — the overlay only ADDs
# 1) compliance column-adds on the itsm/core masters — ALTER over the pg wire, never a second copy
dodil data pg -b "$BUCKET" "ALTER TABLE cis ADD COLUMN compliance_scope VARCHAR"
dodil data pg -b "$BUCKET" "ALTER TABLE cis ADD COLUMN regulated BOOLEAN"
dodil data pg -b "$BUCKET" "ALTER TABLE changes ADD COLUMN approver_role VARCHAR"
dodil data pg -b "$BUCKET" "ALTER TABLE changes ADD COLUMN change_freeze_override BOOLEAN"
dodil data pg -b "$BUCKET" "ALTER TABLE changes ADD COLUMN compliance_status VARCHAR"
# 2) the immutable regulatory audit trail
dodil data table create change_audit -b "$BUCKET" --merge-key audit_id \
--columns-json '[{"name":"audit_id","type":"string","nullable":false},{"name":"change_id","type":"long"},{"name":"actor","type":"string","nullable":true},{"name":"action","type":"string","nullable":true},{"name":"prev_state","type":"string","nullable":true},{"name":"new_state","type":"string","nullable":true},{"name":"evidence_json","type":"string","nullable":true},{"name":"ts","type":"string","nullable":true}]'
# 3) tag the regulated CI + seed the two changes the gate reads (partial merge onto existing rows)
dodil data table upsert cis -b "$BUCKET" --merge --row '{"id":8,"compliance_scope":"sox","regulated":true}'
dodil data table upsert changes -b "$BUCKET" --row '{"id":5001,"number":"CHG5001","short_description":"patch orders-db","ci_id":8,"risk":"low","approval_state":"assess","gate_verdict":"auto_approve","change_freeze_override":false,"compliance_status":"pending"}'
dodil data table upsert changes -b "$BUCKET" --row '{"id":5002,"number":"CHG5002","short_description":"tweak web-storefront banner","ci_id":1,"risk":"low","approval_state":"assess","gate_verdict":"auto_approve","change_freeze_override":false,"compliance_status":"n/a"}'Now the payoff — the compliance hard gate overriding the model's auto_approve:
In itsm, compute each change's final verdict: compliance_hold when its CI is regulated and compliance_status <> 'approved' and not overridden, else the model's gate_verdict — joining changes to their CI. Then release CHG5001 with an approver sign-off and show the verdict flip.
data_sql→data_table_upsertCHG5001 (change to regulated orders-db, compliance_status pending) = compliance_hold — routed to a human DESPITE the model's auto_approve and low risk. CHG5002 (non-regulated) = auto_approve. After change_freeze_override=true + approver_role=cab-chair + compliance_status=approved, CHG5001 flips to auto_approve. change_audit recorded both transitions.
# the deterministic COMPLIANCE HARD GATE — layered OVER the kimi-k2.6 CAB verdict
dodil data sql -b "$BUCKET" "
SELECT ch.number, ch.risk, ch.gate_verdict AS model_says, ci.regulated, ch.compliance_status,
CASE WHEN ci.regulated = true AND ch.compliance_status <> 'approved'
AND ch.change_freeze_override = false THEN 'compliance_hold'
ELSE ch.gate_verdict END AS final_verdict
FROM changes ch JOIN cis ci ON ci.id = ch.ci_id ORDER BY ch.id"
# CHG5001 | low | auto_approve | true | pending | compliance_hold <- model said auto_approve, still held
# CHG5002 | low | auto_approve | false | n/a | auto_approve
# the ONLY release path: an approver sign-off flips compliance_status -> approved
dodil data table upsert changes -b "$BUCKET" --merge \
--row '{"id":5001,"change_freeze_override":true,"approver_role":"cab-chair","compliance_status":"approved"}'
# re-run the gate -> CHG5001 final_verdict = auto_approve (released), and change_audit holds both transitionsThe CAB gate still runs on kimi-k2.6 with its {decision, risk, reason} contract unchanged — but its
verdict can never promote a regulated change past the compliance check. The hard gate is a
deterministic SQL CASE, not a model call; that's the point.
Scaffold it — the one-shot
With the DODIL MCP connected, one prompt composes the suite and this overlay:
Scaffold an ITSM for my bank — the ITSM suite plus the finserv overlay.
Base: the full itsm suite (core masters + CMDB blast-radius graph + sla / incident / problem /
change management) on one bucket.
Then apply the finserv overlay on the SAME bucket:
1. ALTER cis ADD compliance_scope, regulated; ALTER changes ADD approver_role, change_freeze_override,
compliance_status (pg wire — the masters, not a copy).
2. Create change_audit (key audit_id) — an append-only row per state transition.
3. Default change-management to auto_approve_risk=none + require_pir=true, seed a quarter-end freeze,
and layer a DETERMINISTIC compliance hard gate over the CAB verdict: compliance_hold when the CI is
regulated and compliance_status <> 'approved', regardless of the model or blast radius.
Seed the demo above and show the hard gate holding a regulated change the model wanted to auto-approve.Verify
Every result below was live-validated on 2026-09-02 (org IHDIASH, throwaway bucket, torn down after):
# columns land (nullable, over the pg wire)
dodil data pg -b "$BUCKET" "ALTER TABLE cis ADD COLUMN regulated BOOLEAN" # + compliance_scope, +3 on changes
# the hard gate holds the model's auto_approve: CHG5001 (regulated, pending) = compliance_hold
dodil data sql -b "$BUCKET" "SELECT ch.number, ch.gate_verdict, ci.regulated, ch.compliance_status
FROM changes ch JOIN cis ci ON ci.id = ch.ci_id ORDER BY ch.id"
# the audit trail captures every transition: 2 rows for CHG5001 (assess->compliance_hold->approved)
dodil data sql -b "$BUCKET" "SELECT count(*), count(DISTINCT new_state) FROM change_audit WHERE change_id = 5001"The ALTER-adds, the change_audit table, the compliance hard gate overriding the model's auto_approve,
and the approver-sign-off release path are proven live. The suitability/compliance clauses in the CAB gate
prompt reuse the kimi-k2.6 gate already proven in the base change-management skill.
Connect your tools
Everything the overlay wrote lives in the one DataK3 bucket, reachable by your own stack — a GRC / audit
tool reads change_audit and changes.compliance_status over the Postgres wire; a compliance dashboard
walks the CMDB graph over Bolt to show a regulated CI's blast radius. data connect itsm prints the
endpoints. Full, live-validated walkthrough: Connect your tools.
Composes
This page is not a fork of the ITSM — it is a composition:
- Base: the six ITSM suite skills (
itsm/core,itsm/change-management,itsm/cmdb-blast-radius, …) — the system of record, unchanged. - Overlay:
itsm/overlays/finserv— the additive diff above (the compliance columns, thechange_audittrail, the deterministic compliance hard gate over the CAB verdict).
Read the base to learn the mechanics; this overlay is the small, industry-specific diff on top.