Skip to content

Commit 62021b8

Browse files
committed
Add compliance mapping documentation and example input files for NDPA and CBN policies
1 parent 7527ff7 commit 62021b8

10 files changed

Lines changed: 299 additions & 0 deletions

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,42 @@ for p in sorted(Path('policies').glob('*.yaml')):
103103
for f in policies/rego/*.rego; do opa check "$f" && echo "PASS $f"; done
104104
```
105105

106+
### Try it now — run a policy decision with `opa eval`
107+
108+
```bash
109+
# CBN: block a ₦15M transfer (exceeds NIP cap)
110+
opa eval -d policies/rego/cbn-transaction-limits.rego \
111+
-i examples/inputs/cbn-deny-nip-cap.json \
112+
"data.agt_policies_nigeria.cbn.decision"
113+
# → "deny"
114+
115+
# CBN: route a ₦6.5M transfer to human approval
116+
opa eval -d policies/rego/cbn-transaction-limits.rego \
117+
-i examples/inputs/cbn-escalate-tier3.json \
118+
"data.agt_policies_nigeria.cbn.decision"
119+
# → "escalate"
120+
121+
# BVN: block BVN number exposed in agent output
122+
opa eval -d policies/rego/bvn-nin-protection.rego \
123+
-i examples/inputs/bvn-deny-output.json \
124+
"data.agt_policies_nigeria.bvn_nin.decision"
125+
# → "deny"
126+
127+
# NDPA: block data export to AWS US-East-1
128+
opa eval -d policies/rego/ndpa-data-residency.rego \
129+
-i examples/inputs/ndpa-deny-cross-border.json \
130+
"data.agt_policies_nigeria.ndpa.decision"
131+
# → "deny"
132+
133+
# NDPA: allow export to permitted af-south-1 region
134+
opa eval -d policies/rego/ndpa-data-residency.rego \
135+
-i examples/inputs/ndpa-allow-permitted.json \
136+
"data.agt_policies_nigeria.ndpa.decision"
137+
# → "allow"
138+
```
139+
140+
All example input files are in [`examples/inputs/`](examples/inputs/). See [`docs/compliance-mapping.md`](docs/compliance-mapping.md) for the full mapping of regulatory obligations → Rego rules → expected decisions.
141+
106142
---
107143

108144
## Policy Packs

docs/compliance-mapping.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# Compliance Mapping — African Regulatory Requirements → Rego Rules
2+
3+
This document maps each regulatory obligation to the exact Rego rule that enforces it,
4+
the input that triggers it, and the expected decision. Intended for compliance officers,
5+
auditors, and developers integrating these policies.
6+
7+
---
8+
9+
## Nigeria Data Protection Act 2023 (NDPA)
10+
11+
Enforcing authority: **Nigeria Data Protection Commission (NDPC)**
12+
Rego file: `policies/rego/ndpa-data-residency.rego`
13+
14+
| Section | Obligation | Rego Rule | Trigger | Decision |
15+
|---|---|---|---|---|
16+
| s.25(1) | Restrict cross-border transfer to non-adequate jurisdictions | `deny[msg]` — non-permitted region | `action` in transfer set + `destination_region` not in `{af-south-1, nigeria, NG, ng}` | `deny` |
17+
| s.25(1) | Block transfer to non-Nigerian country without consent | `deny[msg]` — non-NG country | `destination_country != "NG"` + `consent_documented != true` | `deny` |
18+
| s.24 | Data minimisation — block bulk exports | `deny[msg]` — bulk export actions | `action` in `{bulk_export, dump_database, export_all, ...}` | `deny` |
19+
| s.24 | Data minimisation — block disproportionate record exports | `deny[msg]` — record count > 1000 | `record_count > 1000` | `deny` |
20+
| Schedule 1 | Biometric data must not be transmitted without lawful basis | `deny[msg]` — biometric output | output contains fingerprint / facial recognition / iris / retina | `deny` |
21+
| s.22(5) | 72-hour breach notification obligation | `deny[msg]` — breach suppression | output contains "don't report" / "hide the breach" / "suppress alert" | `deny` |
22+
| s.25(1) | Cannot verify adequacy without destination metadata | `escalate[msg]` — missing destination | transfer action with no `destination_region` or `destination_country` | `escalate` |
23+
| s.24 | Moderate record exports require DPO approval | `escalate[msg]` — record count 100–1000 | `100 < record_count <= 1000` | `escalate` |
24+
| s.25(1) | Cross-border language in output triggers review | `escalate[msg]` — output pattern | output contains "outside Nigeria" / "cross-border" / "offshore" | `escalate` |
25+
| Schedule 1 | Health/medical data requires explicit lawful basis | `escalate[msg]` — health output | output contains medical record / HIV / mental health / disability | `escalate` |
26+
| s.30 | Accountability — log all personal data access | `audit[msg]` — PII access | `action` in `{read_user, get_customer, lookup_account, fetch_profile, ...}` | `audit` |
27+
| s.30 | Accountability — log all personal data modifications | `audit[msg]` — PII modification | `action` in `{update_user, modify_profile, patch_account, ...}` | `audit` |
28+
29+
**Try it:**
30+
```bash
31+
# NDPA s.25 — cross-border deny
32+
opa eval -d policies/rego/ndpa-data-residency.rego \
33+
-i examples/inputs/ndpa-deny-cross-border.json \
34+
"data.agt_policies_nigeria.ndpa.decision"
35+
# → "deny"
36+
37+
# NDPA — permitted region
38+
opa eval -d policies/rego/ndpa-data-residency.rego \
39+
-i examples/inputs/ndpa-allow-permitted.json \
40+
"data.agt_policies_nigeria.ndpa.decision"
41+
# → "allow"
42+
```
43+
44+
---
45+
46+
## Central Bank of Nigeria — Transaction Controls
47+
48+
Regulatory references:
49+
- **CBN Circular FPR/DIR/GEN/CIR/07/003** — Tiered KYC limits
50+
- **CBN NIP Framework** — ₦10M single-transaction cap
51+
- **CBN USSD Banking Guidelines** — ₦100,000 daily limit
52+
53+
Rego file: `policies/rego/cbn-transaction-limits.rego`
54+
55+
| Regulation | Obligation | Rego Rule | Trigger | Decision |
56+
|---|---|---|---|---|
57+
| CBN Maker-Checker | AI agent cannot self-approve financial transactions | `deny[msg]` — self-approval | `action` in `{approve_transfer, confirm_payment, auto_approve, ...}` | `deny` |
58+
| CBN NIP Framework | Single transaction cap ₦10,000,000 | `deny[msg]` — NIP cap | transfer action + `amount > 10,000,000` | `deny` |
59+
| CBN NIP Framework | Defence-in-depth: detect large amounts in output | `deny[msg]` — text pattern | output contains ₦/NGN/naira + amount > 10M | `deny` |
60+
| CBN Tiered KYC — Tier 3 | Transfers ₦5M–₦10M require human approval | `escalate[msg]` — tier 3 | transfer action + `5,000,000 <= amount <= 10,000,000` | `escalate` |
61+
| CBN Tiered KYC — Tier 2 | Tier 2 customers capped at ₦200,000 | `escalate[msg]` — tier 2 | transfer action + `amount > 200,000` + `kyc_tier == 2` | `escalate` |
62+
| CBN Tiered KYC — Tier 1 | Tier 1 customers capped at ₦50,000 | `escalate[msg]` — tier 1 | transfer action + `amount > 50,000` + `kyc_tier == 1` | `escalate` |
63+
| CBN Fraud Controls | Refunds require human approval | `escalate[msg]` — refund | `action` in `{process_refund, issue_refund, manual_refund, ...}` | `escalate` |
64+
| CBN Agent Banking | Bulk/batch payments require approval | `escalate[msg]` — bulk | `action` in `{bulk_transfer, payroll_run, batch_payment, ...}` | `escalate` |
65+
| CBN USSD Guidelines | USSD transactions require human review | `escalate[msg]` — USSD | `action` starts with `ussd_` | `escalate` |
66+
| CBN Record-Keeping | All financial actions must be logged | `audit[msg]` — financial prefix | `action` starts with `transfer_`, `payment_`, `refund_`, `reversal_`, etc. | `audit` |
67+
68+
**Try it:**
69+
```bash
70+
# CBN NIP cap — deny
71+
opa eval -d policies/rego/cbn-transaction-limits.rego \
72+
-i examples/inputs/cbn-deny-nip-cap.json \
73+
"data.agt_policies_nigeria.cbn.decision"
74+
# → "deny"
75+
76+
# CBN Tier 3 — escalate
77+
opa eval -d policies/rego/cbn-transaction-limits.rego \
78+
-i examples/inputs/cbn-escalate-tier3.json \
79+
"data.agt_policies_nigeria.cbn.decision"
80+
# → "escalate"
81+
82+
# Normal transfer — allow
83+
opa eval -d policies/rego/cbn-transaction-limits.rego \
84+
-i examples/inputs/cbn-allow.json \
85+
"data.agt_policies_nigeria.cbn.decision"
86+
# → "allow"
87+
```
88+
89+
---
90+
91+
## BVN / NIN Data Protection
92+
93+
Regulatory references:
94+
- **CBN BVN Policy Framework (2014, updated 2023)** — NIBSS BVN governance
95+
- **NIMC Act** — NIN management
96+
- **NDPA 2023 Schedule 1** — biometric data as sensitive personal data
97+
98+
Rego file: `policies/rego/bvn-nin-protection.rego`
99+
100+
| Regulation | Obligation | Rego Rule | Trigger | Decision |
101+
|---|---|---|---|---|
102+
| CBN BVN Framework | BVN must not appear in agent output | `deny[msg]` — BVN output | output matches `bvn is/bvn:/bvn= + 10–11 digits` | `deny` |
103+
| CBN BVN Framework | Contextual BVN pattern in output blocked | `deny[msg]` — BVN contextual | output matches `bank verification ... 11 digits` | `deny` |
104+
| NIMC Act | NIN must not appear in agent output | `deny[msg]` — NIN output | output matches `nin is/nin:/nin= + 10–11 digits` | `deny` |
105+
| NIMC Act | Virtual NIN (vNIN) must not appear in output | `deny[msg]` — vNIN output | output matches `vnin/virtual nin + 16 chars` | `deny` |
106+
| CBN BVN Framework | No direct BVN/NIN transmission to external systems | `deny[msg]` — transmission | `action` in `{send_bvn, transmit_nin, relay_kyc, ...}` | `deny` |
107+
| NDPA Schedule 1 | Social engineering via BVN/NIN over chat blocked | `deny[msg]` — social engineering | output contains "confirm BVN over WhatsApp/call/SMS" | `deny` |
108+
| CBN BVN Framework | BVN verification requires audit trail | `escalate[msg]` — BVN verify | `action` in `{verify_bvn, bvn_lookup, nibss_bvn_verify, ...}` | `escalate` |
109+
| NIMC Act | NIN lookup requires documented purpose | `escalate[msg]` — NIN verify | `action` in `{verify_nin, nin_lookup, nimc_nin_verify, ...}` | `escalate` |
110+
| CBN / NDPA | BVN/NIN identifier type in params requires approval | `escalate[msg]` — identifier type | `params.identifier_type` in `{BVN, NIN, bvn, nin}` | `escalate` |
111+
| NDPA s.30 / CBN BVN | All identity-related actions must be logged | `audit[msg]` — identity action | `action` contains `bvn`, `nin`, `kyc`, or `identity_verify` | `audit` |
112+
113+
**Try it:**
114+
```bash
115+
# BVN in output — deny
116+
opa eval -d policies/rego/bvn-nin-protection.rego \
117+
-i examples/inputs/bvn-deny-output.json \
118+
"data.agt_policies_nigeria.bvn_nin.decision"
119+
# → "deny"
120+
121+
# BVN verification — escalate
122+
opa eval -d policies/rego/bvn-nin-protection.rego \
123+
-i examples/inputs/bvn-escalate-verify.json \
124+
"data.agt_policies_nigeria.bvn_nin.decision"
125+
# → "escalate"
126+
```
127+
128+
---
129+
130+
## Input Schema Reference
131+
132+
All three policies share the same input structure:
133+
134+
```json
135+
{
136+
"action": "<tool or action name>",
137+
"params": { "<key>": "<value>" },
138+
"output": "<agent text output>",
139+
"context": { "<key>": "<value>" }
140+
}
141+
```
142+
143+
Key fields per policy:
144+
145+
| Policy | Key Input Fields |
146+
|---|---|
147+
| CBN | `params.amount`, `params.currency`, `context.kyc_tier` |
148+
| BVN/NIN | `params.identifier_type`, `params.bvn_present`, `output` |
149+
| NDPA | `params.destination_region`, `params.destination_country`, `params.record_count`, `context.consent_documented` |
150+
151+
Example input files are in [`examples/inputs/`](../examples/inputs/).
152+
153+
---
154+
155+
## Decision Values
156+
157+
All three policies return one of four decisions:
158+
159+
| Decision | Meaning | Action Required |
160+
|---|---|---|
161+
| `deny` | Hard block — regulation prohibits this | Stop execution immediately |
162+
| `escalate` | Route to human approval queue | Pause and await human sign-off |
163+
| `audit` | Allowed but must be logged | Execute and write to audit trail |
164+
| `allow` | No violation detected | Proceed normally |
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"action": "respond_to_customer",
3+
"params": {},
4+
"output": "Your BVN is: 22345678901. Please confirm this matches your records.",
5+
"context": {
6+
"channel": "whatsapp"
7+
}
8+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"action": "verify_bvn",
3+
"params": {
4+
"identifier_type": "BVN",
5+
"bvn_present": true
6+
},
7+
"output": "Initiating BVN verification for customer.",
8+
"context": {
9+
"purpose": "account_opening",
10+
"channel": "mobile"
11+
}
12+
}

examples/inputs/cbn-allow.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"action": "nip_transfer",
3+
"params": {
4+
"amount": 50000,
5+
"currency": "NGN",
6+
"account": "0123456789"
7+
},
8+
"output": "Initiating transfer of ₦50,000.",
9+
"context": {
10+
"kyc_tier": 3,
11+
"customer_verified": true
12+
}
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"action": "nip_transfer",
3+
"params": {
4+
"amount": 15000000,
5+
"currency": "NGN",
6+
"account": "0123456789"
7+
},
8+
"output": "Processing transfer of ₦15,000,000 to account 0123456789.",
9+
"context": {
10+
"kyc_tier": 3,
11+
"customer_verified": true
12+
}
13+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"action": "approve_transfer",
3+
"params": {
4+
"amount": 500000,
5+
"currency": "NGN"
6+
},
7+
"output": "I have approved the transfer on your behalf.",
8+
"context": {
9+
"kyc_tier": 3,
10+
"customer_verified": true
11+
}
12+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"action": "nip_transfer",
3+
"params": {
4+
"amount": 6500000,
5+
"currency": "NGN",
6+
"account": "0123456789"
7+
},
8+
"output": "Initiating transfer of ₦6,500,000.",
9+
"context": {
10+
"kyc_tier": 3,
11+
"customer_verified": true
12+
}
13+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"action": "export_data",
3+
"params": {
4+
"destination_region": "af-south-1",
5+
"destination_country": "NG",
6+
"data_type": "customer_pii",
7+
"record_count": 50
8+
},
9+
"output": "Syncing 50 customer records to af-south-1.",
10+
"context": {
11+
"purpose": "disaster_recovery",
12+
"consent_documented": true
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"action": "export_data",
3+
"params": {
4+
"destination_region": "us-east-1",
5+
"destination_country": "US",
6+
"data_type": "customer_pii",
7+
"record_count": 1500
8+
},
9+
"output": "Exporting 1,500 customer records to AWS US-East-1.",
10+
"context": {
11+
"purpose": "backup",
12+
"consent_documented": false
13+
}
14+
}

0 commit comments

Comments
 (0)