diff --git a/.cspell-repo-terms.txt b/.cspell-repo-terms.txt index fc2f7b3ed..c348eb7bb 100644 --- a/.cspell-repo-terms.txt +++ b/.cspell-repo-terms.txt @@ -939,3 +939,21 @@ spanid parentspanid agtsignature agtsignaturealg + +# --- UK regulatory policy terms --- +DUAA +PRIN +PECR +DSPT +Caldicott +SYSC +Organisations +vulnerabilit +foreseeably +DPIA +dpia +minimisation +ukgdpr +organisational +Minimisation +IDTA diff --git a/examples/policies/african-regulatory/rego/jurisdiction-router.rego b/examples/policies/african-regulatory/rego/jurisdiction-router.rego index afc328c43..11778d7d3 100644 --- a/examples/policies/african-regulatory/rego/jurisdiction-router.rego +++ b/examples/policies/african-regulatory/rego/jurisdiction-router.rego @@ -10,7 +10,7 @@ # 1. Universal agent safety controls — apply to ALL agents regardless of country # (prompt_injection, pii_leakage, tool_permissions, human_approval, model_routing) # 2. Jurisdiction-specific regulatory packs — apply based on customer_country -# (cbn, bvn_nin, ndpa, nfiu for NG; kdpa for KE; popia for ZA) +# (cbn, bvn_nin, ndpa, nfiu for NG; kdpa for KE; popia for ZA; dpdp, certin, rbi, sebi, aadhaar for IN; uk_gdpr, ico_adm, fca_conduct for GB) # # Input schema expected: # { @@ -51,6 +51,7 @@ jurisdiction_policies := { "TZ": {"tanzania_pdpa"}, "ET": {"ethiopia_pdp"}, "IN": {"dpdp", "certin", "rbi", "sebi", "aadhaar"}, + "GB": {"uk_gdpr", "ico_adm", "fca_conduct"}, } # ── Policy pack → OPA query path ───────────────────────────────── @@ -70,6 +71,9 @@ policy_queries := { "rbi": "data.agt_policies_india.rbi.decision", "sebi": "data.agt_policies_india.sebi.decision", "aadhaar": "data.agt_policies_india.aadhaar.decision", + "uk_gdpr": "data.agt_policies_uk.uk_gdpr.decision", + "ico_adm": "data.agt_policies_uk.ico_adm.decision", + "fca_conduct": "data.agt_policies_uk.fca_conduct.decision", "prompt_injection": "data.agt_policies_agent.prompt_injection.decision", "pii_leakage": "data.agt_policies_agent.pii_leakage.decision", "tool_permissions": "data.agt_policies_agent.tool_permissions.decision", diff --git a/examples/policies/uk-regulatory/README.md b/examples/policies/uk-regulatory/README.md new file mode 100644 index 000000000..1cbca3046 --- /dev/null +++ b/examples/policies/uk-regulatory/README.md @@ -0,0 +1,75 @@ +# UK Regulatory Policy Pack + +Reference Policy-as-Code for governing AI agents under UK regulation: data protection, +automated decision-making, and financial-sector principles-based controls. + +> Community-maintained governance starter policies. NOT certified legal compliance instruments. +> Perform your own assessment with qualified advisors before deploying in regulated environments. +> Regulatory status is noted per file (binding vs advisory/draft). + +## Coverage + +| Policy file | Regulation | Authority | Status | +|---|---|---|---| +| `uk-gdpr-data-protection.yaml` | UK GDPR + DPA 2018 + DUAA 2025 (transfer/complaints reforms) | ICO | Binding | +| `ico-automated-decisions.yaml` | UK GDPR Arts. 22A–22D (DUAA 2025 s.80, in force 5 Feb 2026) | ICO | Binding; ICO ADM guidance draft (final expected summer 2026) | +| `fca-financial-conduct.yaml` | FCA Handbook PRIN 2A (Consumer Duty), SM&CR | FCA | Principles-based — no AI-specific binding rules as of 2026 | + +## Regulatory context (2026) + +- **Data (Use and Access) Act 2025 (DUAA)** received Royal Assent on 19 June 2025. Key data-protection reforms commenced 5 February 2026, including replacement of UK GDPR Art. 22 with Arts. 22A–22D (safeguard-led automated decision-making) and updated international transfer rules using the **"not materially lower"** data protection test. +- **Breach notification** remains UK GDPR Art. 33: notify the ICO without undue delay and, where feasible, within **72 hours** when a breach is **likely to result in a risk** to rights and freedoms. Inform individuals without undue delay where the breach poses **high risk** (Art. 34). +- **Complaints procedure**: DPA 2018 s.164A (inserted by DUAA s.103) requires all controllers to maintain a formal data protection complaints procedure by **19 June 2026**. Data subjects must raise complaints with the controller before escalating to the ICO. +- **FCA**: No AI-specific binding regulation as of 2026. The FCA applies its existing principles-based framework (Consumer Duty, SM&CR, operational resilience). The Mills Review reports to the FCA Board in summer 2026. + +## What these rules detect (and what they do not) + +Output-side rules match intent phrases (for example "store PII unencrypted", "don't report the breach", "no human review"). YAML policies use `block` for review/hold tiers (the Agent-OS schema supports `allow`, `deny`, `audit`, and `block` only); the Rego reference implementations may use an independent `escalate` decision tier for OPA pipelines. They catch an agent that narrates or proposes a violation in its output; they do not observe the underlying system action. Treat them as a starting point, pair them with real action-level enforcement, and run your own compliance assessment. + +## Not covered (known gaps) + +Material obligations the pack does not represent yet: + +- **UK GDPR**: Art. 13–14 privacy notices; Art. 15–22 full data-subject rights workflow; Art. 27 UK representative requirement; children's code (Age Appropriate Design Code). +- **DUAA**: Recognised legitimate interests lawful basis; full cookie/PECR reforms; ICO statutory objectives. +- **NIS2 / UK cyber**: Network and information security incident reporting for in-scope entities. +- **Online Safety Act 2023**: Platform duties for user-generated content (out of scope for generic agent policies). +- **NHS / healthcare**: NHS DSPT, Caldicott principles, and health-sector-specific controls. +- **FCA**: Detailed SYSC mapping, operational resilience impact tolerances, and forthcoming AI good/poor practice benchmarks (expected 2026). + +## Two layers + +Universal agent-safety controls (prompt_injection, pii_leakage, tool_permissions, human_approval, model_routing) apply to all agents and are evaluated via the shared jurisdiction router in `../african-regulatory/rego/jurisdiction-router.rego`. These UK national packs add jurisdiction-specific regulatory controls, selected by `context.customer_country = "GB"`. + +## Rego + +`rego/` holds OPA reference implementations (NOT loaded by the Agent-OS Python runtime). Each pack exposes `data.agt_policies_uk..decision`. The shared router maps `GB` to `uk_gdpr`, `ico_adm`, and `fca_conduct`. + +To evaluate with OPA: + +```bash +# Run all UK Rego tests (includes jurisdiction router checks) +./examples/policies/uk-regulatory/rego/run_tests.sh + +# Or manually: +opa test examples/policies/african-regulatory/rego examples/policies/uk-regulatory/rego -v + +# Evaluate applicable policies for GB +opa eval \ + -d examples/policies/african-regulatory/rego/ \ + -d examples/policies/uk-regulatory/rego/ \ + -i '{"context": {"customer_country": "GB"}}' \ + "data.agt_policies.router.applicable_policies" +``` + +## Loading policies in Agent-OS + +```python +from agent_os.policies.schema import PolicyDocument + +policy = PolicyDocument.from_yaml("uk-gdpr-data-protection.yaml") +``` + +## Disclaimer + +These policies are community-maintained governance starter packs. They are **not certified legal compliance instruments**. Organisations must perform their own compliance assessments with qualified legal and regulatory advisors before deploying in regulated environments. diff --git a/examples/policies/uk-regulatory/fca-financial-conduct.yaml b/examples/policies/uk-regulatory/fca-financial-conduct.yaml new file mode 100644 index 000000000..eae27ae36 --- /dev/null +++ b/examples/policies/uk-regulatory/fca-financial-conduct.yaml @@ -0,0 +1,112 @@ +# agt-policies-uk +# FCA Principles-Based AI Governance Policy +# +# Regulatory reference: FCA Handbook PRIN (Principles for Businesses); Consumer Duty (PRIN 2A); +# Senior Managers and Certification Regime (SM&CR); FCA AI Update 2024 +# Enforcing authority: Financial Conduct Authority (FCA) +# Status: Binding (existing principles-based framework); FCA has no AI-specific binding rules +# as of 2026 — Mills Review reporting summer 2026; AI good/poor practice publication expected 2026 +# +# Community-maintained governance starter policy. NOT a certified legal compliance instrument. +# Perform your own compliance assessment with qualified advisors before deploying. +# +# Key obligations encoded (principles-based, not AI-specific statute): +# PRIN 2A Consumer Duty — good outcomes, fair value, appropriate support +# SM&CR Senior manager accountability for AI risks and customer outcomes +# SYSC Systems and controls for AI-influenced customer journeys +# +# Rego reference implementation: rego/fca-financial-conduct.rego (NOT loaded at runtime) + +version: "1.0" +name: fca-financial-conduct +description: > + FCA principles-based governance policy for AI agents in UK financial services. + Enforces Consumer Duty outcome checks, SM&CR accountability signals, and audit + requirements for AI-influenced pricing, eligibility, and customer communications. + +metadata: + source_regulation: "FCA Handbook PRIN (incl. PRIN 2A Consumer Duty); SM&CR; FCA AI Update 2024" + jurisdiction: "GB" + enforcing_authority: "Financial Conduct Authority (FCA)" + regulatory_status: "principles-based — no AI-specific binding rules as of 2026" + +rules: + + # ========================================================================= + # PRIN 2A — Consumer Duty: Good Outcomes + # ========================================================================= + + - name: fca-consumer-harm-deny + condition: + field: output + operator: matches + value: "(?i)(mislead\\s+(the\\s+)?customer|hide\\s+(fees|charges|risks)|exploit\\s+vulnerabilit|target\\s+vulnerable\\s+customer|dark\\s+pattern|push\\s+unsuitable\\s+product)" + action: deny + priority: 1 + message: "FCA Consumer Duty (PRIN 2A): agent cannot propose actions that foreseeably harm customers or obscure material information" + + - name: fca-fair-value-bypass-deny + condition: + field: output + operator: matches + value: "(?i)(skip\\s+fair\\s+value|bypass\\s+value\\s+assessment|no\\s+need\\s+to\\s+(check|assess)\\s+(fair\\s+)?value|ignore\\s+consumer\\s+duty)" + action: deny + priority: 1 + message: "FCA Consumer Duty (PRIN 2A.4): firms must ensure products and services provide fair value — agent cannot bypass value assessment" + + # ========================================================================= + # SM&CR — Senior Manager Accountability + # ========================================================================= + + - name: fca-accountability-delegation-deny + condition: + field: output + operator: matches + value: "(?i)(the\\s+ai\\s+(decides|is\\s+responsible)|algorithm\\s+accountable|no\\s+senior\\s+manager\\s+(needed|required)|delegate\\s+accountability\\s+to\\s+(the\\s+)?(model|ai|algorithm))" + action: deny + priority: 1 + message: "FCA SM&CR: senior managers remain accountable for AI risks and outcomes — delegating to an algorithm does not transfer regulatory responsibility" + + # ========================================================================= + # AI-Influenced Customer Journeys — Audit + # ========================================================================= + + - name: fca-pricing-decision-audit + condition: + field: action + operator: matches + value: "^(set_price|adjust_rate|calculate_premium|score_creditworthiness|determine_eligibility)$" + action: audit + priority: 2 + message: "FCA Consumer Duty: AI-influenced pricing or eligibility decision — document testing for fairness, suitability, and foreseeable harm" + + - name: fca-customer-communication-audit + condition: + field: action + operator: matches + value: "^(send_financial_advice|generate_customer_communication|draft_product_recommendation|create_marketing_content)$" + action: audit + priority: 2 + message: "FCA Consumer Duty: AI-generated customer communication — verify clarity, accuracy, and alignment with target customer information needs" + + - name: fca-third-party-ai-audit + condition: + field: action + operator: matches + value: "^(invoke_external_ai|call_third_party_model|use_vendor_ai|deploy_critical_third_party_ai)$" + action: audit + priority: 2 + message: "FCA operational resilience / outsourcing: third-party AI component — map to governance, testing, and critical third-party risk requirements" + + # ========================================================================= + # Agentic / Autonomous Trading — Block without approval + # ========================================================================= + + - name: fca-autonomous-trading-block + condition: + field: action + operator: matches + value: "^(autonomous_trade|execute_trade_without_approval|self_directed_trading|agent_place_order)$" + action: block + priority: 1 + message: "FCA market conduct: autonomous agent trading requires documented governance, testing, and senior manager approval before execution" diff --git a/examples/policies/uk-regulatory/ico-automated-decisions.yaml b/examples/policies/uk-regulatory/ico-automated-decisions.yaml new file mode 100644 index 000000000..ecfbd6d81 --- /dev/null +++ b/examples/policies/uk-regulatory/ico-automated-decisions.yaml @@ -0,0 +1,131 @@ +# agt-policies-uk +# UK GDPR Arts. 22A–22D — Automated Decision-Making Policy +# +# Regulatory reference: UK GDPR Arts. 22A–22D (substituted by DUAA 2025 s.80, in force 5 Feb 2026); +# ICO draft guidance on automated decision-making and profiling (consultation closed 29 May 2026) +# Enforcing authority: Information Commissioner's Office (ICO) +# Status: Binding (Arts. 22A–22D); ICO ADM guidance draft (final expected summer 2026) +# +# Community-maintained governance starter policy. NOT a certified legal compliance instrument. +# Perform your own compliance assessment with qualified advisors before deploying. +# +# Key obligations encoded: +# Art. 22A Solely automated decisions with legal or similarly significant effects +# Art. 22B Restrictions on automated decision-making using special category data +# Art. 22C Safeguards: information, representations, human intervention, contest +# Art. 35 DPIA for high-risk processing (including agentic orchestration chains) +# +# Agentic AI note (ICO tech futures / March 2026 recruitment statement): safeguards apply at +# every pipeline step that takes a solely automated significant decision, not only the final output. +# +# Rego reference implementation: rego/ico-automated-decisions.rego (NOT loaded at runtime) + +version: "1.0" +name: ico-automated-decisions +description: > + UK GDPR automated decision-making policy for AI agents. Enforces Art. 22C safeguards + (transparency, representations, human intervention, contest) for solely automated + significant decisions, including multi-agent orchestration steps. + +metadata: + source_regulation: "UK GDPR Arts. 22A–22D (DUAA 2025 s.80); ICO ADM guidance (draft, 2026)" + jurisdiction: "GB" + enforcing_authority: "Information Commissioner's Office (ICO)" + +rules: + + # ========================================================================= + # Art. 22C — Safeguard: Information about the decision + # ========================================================================= + + - name: adm-withhold-explanation-deny + condition: + field: output + operator: matches + value: "(?i)(don'?t\\s+explain|no\\s+explanation|withhold\\s+(the\\s+)?(reason|rationale)|hide\\s+how\\s+(the\\s+)?decision|refuse\\s+to\\s+explain)" + action: deny + priority: 1 + message: "UK GDPR Art. 22C(1): individuals must receive decision-specific information explaining how and why the outcome was reached" + + # ========================================================================= + # Art. 22C — Safeguard: Representations and human intervention + # ========================================================================= + + - name: adm-block-human-review-deny + condition: + field: output + operator: matches + value: "(?i)(no\\s+human\\s+(review|intervention|oversight)|refuse\\s+human\\s+review|cannot\\s+request\\s+human|deny\\s+human\\s+intervention|automated\\s+only\\s+—\\s+no\\s+appeal)" + action: deny + priority: 1 + message: "UK GDPR Art. 22C(2)-(3): individuals must be able to make representations and obtain genuine human intervention with authority to change the outcome" + + - name: adm-block-contest-deny + condition: + field: output + operator: matches + value: "(?i)(cannot\\s+contest|no\\s+(right\\s+to\\s+)?(appeal|challenge)|final\\s+decision\\s+—\\s+no\\s+recourse|waive\\s+(the\\s+)?right\\s+to\\s+contest)" + action: deny + priority: 1 + message: "UK GDPR Art. 22C(4): individuals must be able to contest the decision through an accessible process" + + # ========================================================================= + # Art. 22A — Solely Automated Significant Decisions + # ========================================================================= + + - name: adm-significant-decision-audit + condition: + field: action + operator: matches + value: "^(run_automated_decision|automated_credit_decision|automated_hiring_decision|automated_eligibility|profile_for_decision|deploy_scoring_model)$" + action: audit + priority: 2 + message: "UK GDPR Art. 22A: solely automated decision with legal or similarly significant effect — verify Art. 22C safeguards and lawful basis are in place" + + - name: adm-recruitment-decision-block + condition: + field: output + operator: matches + value: "(?i)(reject\\s+(the\\s+)?(candidate|applicant)|hire\\s+decision|shortlist|score\\s+(the\\s+)?(candidate|applicant)).{0,40}(automated|without\\s+human|ai\\s+only)" + action: block + priority: 2 + message: "ICO March 2026: automated recruitment decisions are in scope of Art. 22A — review safeguards and human oversight before proceeding" + + # ========================================================================= + # Art. 22A — Agentic orchestration (multi-step ADM) + # ========================================================================= + + - name: adm-agentic-delegation-audit + condition: + field: action + operator: matches + value: "delegate_decision|spawn_sub_agent|orchestrate_agent|chain_automated_step" + action: audit + priority: 2 + message: "UK GDPR Art. 22A (agentic AI): each orchestration step that takes a solely automated significant decision must meet Art. 22C safeguards and Art. 28 processor contracts" + + # ========================================================================= + # Art. 9 + 22A — Special category data in ADM (stricter conditions) + # ========================================================================= + + - name: adm-special-category-deny + condition: + field: action + operator: matches + value: "^(automated_decision_on_health|automated_decision_on_biometric|automated_decision_on_special_category)$" + action: deny + priority: 1 + message: "UK GDPR Art. 22B: automated decisions based on special category data require explicit consent or legal authorisation — human review alone is insufficient" + + # ========================================================================= + # Art. 35 — DPIA for high-risk ADM + # ========================================================================= + + - name: adm-dpia-required-audit + condition: + field: action + operator: matches + value: "^(deploy_model|deploy_agent|launch_automated_system|scale_automated_decisions)$" + action: audit + priority: 3 + message: "UK GDPR Art. 35: data protection impact assessment required before deploying high-risk automated decision-making (including agentic orchestration)" diff --git a/examples/policies/uk-regulatory/rego/fca-financial-conduct.rego b/examples/policies/uk-regulatory/rego/fca-financial-conduct.rego new file mode 100644 index 000000000..91e5f31ac --- /dev/null +++ b/examples/policies/uk-regulatory/rego/fca-financial-conduct.rego @@ -0,0 +1,100 @@ +# agt-policies-uk - FCA Principles-Based AI Governance (Rego reference) +# FCA has no AI-specific binding rules as of 2026 — principles-based framework applies. +# NOT loaded by the Agent-OS Python runtime. +# +# Input schema: +# { "action": "set_price", +# "params": { "consumer_duty_assessed": false, "senior_manager_approved": false }, +# "output": "agent output text" } + +package agt_policies_uk.fca_conduct + +import rego.v1 + +_output_text := v if { + is_string(input.output) + v := input.output +} else := "" + +pricing_actions := { + "set_price", "adjust_rate", "calculate_premium", + "score_creditworthiness", "determine_eligibility", +} + +communication_actions := { + "send_financial_advice", "generate_customer_communication", + "draft_product_recommendation", "create_marketing_content", +} + +third_party_ai_actions := { + "invoke_external_ai", "call_third_party_model", + "use_vendor_ai", "deploy_critical_third_party_ai", +} + +autonomous_trading_actions := { + "autonomous_trade", "execute_trade_without_approval", + "self_directed_trading", "agent_place_order", +} + +# PRIN 2A: consumer harm language +deny contains msg if { + regex.match(`(?i)(mislead\s+(the\s+)?customer|hide\s+(fees|charges|risks)|exploit\s+vulnerabilit|target\s+vulnerable\s+customer|dark\s+pattern|push\s+unsuitable\s+product)`, _output_text) + msg := "FCA Consumer Duty (PRIN 2A): agent cannot propose actions that foreseeably harm customers" +} + +# PRIN 2A: fair value bypass +deny contains msg if { + regex.match(`(?i)(skip\s+fair\s+value|bypass\s+value\s+assessment|no\s+need\s+to\s+(check|assess)\s+(fair\s+)?value|ignore\s+consumer\s+duty)`, _output_text) + msg := "FCA Consumer Duty (PRIN 2A.4): firms must ensure products and services provide fair value" +} + +# SM&CR: accountability delegation to AI +deny contains msg if { + regex.match(`(?i)(the\s+ai\s+(decides|is\s+responsible)|algorithm\s+accountable|no\s+senior\s+manager\s+(needed|required)|delegate\s+accountability\s+to\s+(the\s+)?(model|ai|algorithm))`, _output_text) + msg := "FCA SM&CR: senior managers remain accountable for AI risks — delegating to an algorithm does not transfer responsibility" +} + +# Market conduct: autonomous trading without approval +deny contains msg if { + input.action in autonomous_trading_actions + not input.params.senior_manager_approved == true + msg := "FCA market conduct: autonomous agent trading requires documented governance and senior manager approval" +} + +# Consumer Duty: pricing without assessment +escalate contains msg if { + input.action in pricing_actions + not input.params.consumer_duty_assessed == true + msg := "FCA Consumer Duty: AI-influenced pricing or eligibility decision — document testing for fairness and foreseeable harm" +} + +# Consumer Duty: customer communications +audit contains msg if { + input.action in communication_actions + msg := "FCA Consumer Duty: AI-generated customer communication — verify clarity, accuracy, and information needs" +} + +# Outsourcing / operational resilience: third-party AI +audit contains msg if { + input.action in third_party_ai_actions + msg := "FCA operational resilience: third-party AI component — map to governance, testing, and critical third-party risk" +} + +decision := "deny" if count(deny) > 0 + +decision := "escalate" if { + count(deny) == 0 + count(escalate) > 0 +} + +decision := "audit" if { + count(deny) == 0 + count(escalate) == 0 + count(audit) > 0 +} + +decision := "allow" if { + count(deny) == 0 + count(escalate) == 0 + count(audit) == 0 +} diff --git a/examples/policies/uk-regulatory/rego/fca-financial-conduct_test.rego b/examples/policies/uk-regulatory/rego/fca-financial-conduct_test.rego new file mode 100644 index 000000000..80e8018c4 --- /dev/null +++ b/examples/policies/uk-regulatory/rego/fca-financial-conduct_test.rego @@ -0,0 +1,71 @@ +# agt-policies-uk - FCA Principles-Based AI Governance (OPA tests) +package agt_policies_uk.fca_conduct_test + +import data.agt_policies_uk.fca_conduct as policy +import rego.v1 + +test_allow_benign_action if { + policy.decision == "allow" with input as { + "action": "draft_internal_note", + "output": "Summarise the Consumer Duty good outcomes framework.", + } +} + +test_deny_consumer_harm if { + policy.decision == "deny" with input as { + "action": "draft_message", + "output": "Hide fees from the customer in this renewal letter.", + } +} + +test_deny_fair_value_bypass if { + policy.decision == "deny" with input as { + "action": "draft_policy", + "output": "Skip fair value assessment — no need to check value for this product.", + } +} + +test_deny_delegate_accountability if { + policy.decision == "deny" with input as { + "action": "draft_memo", + "output": "The AI is responsible for this decision so no senior manager is needed.", + } +} + +test_deny_autonomous_trading_without_approval if { + policy.decision == "deny" with input as { + "action": "autonomous_trade", + "params": {"senior_manager_approved": false}, + "output": "", + } +} + +test_allow_autonomous_trading_with_approval if { + policy.decision == "allow" with input as { + "action": "autonomous_trade", + "params": {"senior_manager_approved": true}, + "output": "", + } +} + +test_escalate_pricing_without_consumer_duty_assessment if { + policy.decision == "escalate" with input as { + "action": "set_price", + "params": {"consumer_duty_assessed": false}, + "output": "", + } +} + +test_audit_customer_communication if { + policy.decision == "audit" with input as { + "action": "generate_customer_communication", + "output": "", + } +} + +test_audit_third_party_ai if { + policy.decision == "audit" with input as { + "action": "invoke_external_ai", + "output": "", + } +} diff --git a/examples/policies/uk-regulatory/rego/ico-automated-decisions.rego b/examples/policies/uk-regulatory/rego/ico-automated-decisions.rego new file mode 100644 index 000000000..9a97c83c5 --- /dev/null +++ b/examples/policies/uk-regulatory/rego/ico-automated-decisions.rego @@ -0,0 +1,117 @@ +# agt-policies-uk - UK GDPR Arts. 22A–22D Automated Decision-Making (Rego reference) +# DUAA 2025 s.80 in force 5 February 2026. ICO ADM guidance draft (final expected summer 2026). +# NOT loaded by the Agent-OS Python runtime. +# +# Input schema: +# { "action": "run_automated_decision", +# "params": { "human_review_available": false, "explanation_provided": false }, +# "output": "agent output text" } + +package agt_policies_uk.ico_adm + +import rego.v1 + +_output_text := v if { + is_string(input.output) + v := input.output +} else := "" + +significant_decision_actions := { + "run_automated_decision", "automated_credit_decision", + "automated_hiring_decision", "automated_eligibility", + "profile_for_decision", "deploy_scoring_model", +} + +agentic_actions := { + "delegate_decision", "spawn_sub_agent", "orchestrate_agent", "chain_automated_step", +} + +special_category_adm_actions := { + "automated_decision_on_health", "automated_decision_on_biometric", + "automated_decision_on_special_category", +} + +deployment_actions := { + "deploy_model", "deploy_agent", "launch_automated_system", "scale_automated_decisions", +} + +# Art. 22C(1): withhold explanation +deny contains msg if { + regex.match(`(?i)(don'?t\s+explain|no\s+explanation|withhold\s+(the\s+)?(reason|rationale)|hide\s+how\s+(the\s+)?decision|refuse\s+to\s+explain)`, _output_text) + msg := "UK GDPR Art. 22C(1): individuals must receive decision-specific information explaining how and why the outcome was reached" +} + +# Art. 22C(2)-(3): block human review +deny contains msg if { + regex.match(`(?i)(no\s+human\s+(review|intervention|oversight)|refuse\s+human\s+review|cannot\s+request\s+human|deny\s+human\s+intervention)`, _output_text) + msg := "UK GDPR Art. 22C(2)-(3): individuals must be able to make representations and obtain genuine human intervention" +} + +# Art. 22C(4): block contest right +deny contains msg if { + regex.match(`(?i)(cannot\s+contest|no\s+(right\s+to\s+)?(appeal|challenge)|final\s+decision\s+—\s+no\s+recourse|waive\s+(the\s+)?right\s+to\s+contest)`, _output_text) + msg := "UK GDPR Art. 22C(4): individuals must be able to contest the decision through an accessible process" +} + +# Art. 22B + Art. 9: special category ADM — explicit consent or legal authorisation required +deny contains msg if { + input.action in special_category_adm_actions + msg := "UK GDPR Art. 22B: automated decisions based on special category data require explicit consent or legal authorisation — human review alone is insufficient" +} + +# Art. 22A: significant decision without safeguards metadata +escalate contains msg if { + input.action in significant_decision_actions + not input.params.human_review_available == true + msg := "UK GDPR Art. 22A: solely automated significant decision — verify Art. 22C safeguards (information, representations, human intervention, contest)" +} + +# Art. 22A: significant decision without explanation +escalate contains msg if { + input.action in significant_decision_actions + not input.params.explanation_provided == true + msg := "UK GDPR Art. 22C(1): decision-specific explanation must be available to the individual" +} + +# ICO March 2026: recruitment ADM language +escalate contains msg if { + regex.match(`(?i)(reject\s+(the\s+)?(candidate|applicant)|hire\s+decision|shortlist|score\s+(the\s+)?(candidate|applicant)).{0,40}(automated|without\s+human|ai\s+only)`, _output_text) + msg := "ICO March 2026: automated recruitment decisions are in scope of Art. 22A — review safeguards before proceeding" +} + +# Art. 22A: agentic orchestration step +escalate contains msg if { + input.action in agentic_actions + msg := "UK GDPR Art. 22A (agentic AI): each orchestration step taking a solely automated significant decision must meet Art. 22C safeguards and Art. 28 processor contracts" +} + +# Art. 35: DPIA for deployment +audit contains msg if { + input.action in deployment_actions + msg := "UK GDPR Art. 35: data protection impact assessment required before deploying high-risk automated decision-making" +} + +# Art. 22A: significant decision audit trail +audit contains msg if { + input.action in significant_decision_actions + msg := "UK GDPR Art. 22A: solely automated significant decision logged — verify lawful basis and Art. 22C safeguards" +} + +decision := "deny" if count(deny) > 0 + +decision := "escalate" if { + count(deny) == 0 + count(escalate) > 0 +} + +decision := "audit" if { + count(deny) == 0 + count(escalate) == 0 + count(audit) > 0 +} + +decision := "allow" if { + count(deny) == 0 + count(escalate) == 0 + count(audit) == 0 +} diff --git a/examples/policies/uk-regulatory/rego/ico-automated-decisions_test.rego b/examples/policies/uk-regulatory/rego/ico-automated-decisions_test.rego new file mode 100644 index 000000000..f4459ba6b --- /dev/null +++ b/examples/policies/uk-regulatory/rego/ico-automated-decisions_test.rego @@ -0,0 +1,83 @@ +# agt-policies-uk - ICO Automated Decision-Making (OPA tests) +package agt_policies_uk.ico_adm_test + +import data.agt_policies_uk.ico_adm as policy +import rego.v1 + +test_allow_benign_action if { + policy.decision == "allow" with input as { + "action": "web_search", + "output": "Summarise ICO guidance on data protection impact assessments.", + } +} + +test_deny_withhold_explanation if { + policy.decision == "deny" with input as { + "action": "respond", + "output": "Don't explain how the credit decision was reached.", + } +} + +test_deny_refuse_human_review if { + policy.decision == "deny" with input as { + "action": "respond", + "output": "No human review is available for this automated eligibility outcome.", + } +} + +test_deny_block_contest_right if { + policy.decision == "deny" with input as { + "action": "respond", + "output": "Final decision — no appeal or challenge is permitted.", + } +} + +test_deny_special_category_adm if { + policy.decision == "deny" with input as { + "action": "automated_decision_on_health", + "output": "", + } +} + +test_escalate_significant_decision_without_safeguards if { + policy.decision == "escalate" with input as { + "action": "run_automated_decision", + "params": { + "human_review_available": false, + "explanation_provided": false, + }, + "output": "", + } +} + +test_escalate_recruitment_adm_language if { + policy.decision == "escalate" with input as { + "action": "draft_summary", + "output": "Reject the candidate using an automated AI-only score.", + } +} + +test_escalate_agentic_delegation if { + policy.decision == "escalate" with input as { + "action": "spawn_sub_agent", + "output": "", + } +} + +test_audit_model_deployment if { + policy.decision == "audit" with input as { + "action": "deploy_model", + "output": "", + } +} + +test_audit_significant_decision_with_safeguards if { + policy.decision == "audit" with input as { + "action": "automated_credit_decision", + "params": { + "human_review_available": true, + "explanation_provided": true, + }, + "output": "", + } +} diff --git a/examples/policies/uk-regulatory/rego/jurisdiction-router_gb_test.rego b/examples/policies/uk-regulatory/rego/jurisdiction-router_gb_test.rego new file mode 100644 index 000000000..f17eebdc8 --- /dev/null +++ b/examples/policies/uk-regulatory/rego/jurisdiction-router_gb_test.rego @@ -0,0 +1,54 @@ +# agt-policies-uk - GB jurisdiction routing (OPA tests) +# Requires both uk-regulatory/rego and african-regulatory/rego on the OPA load path. +package agt_policies_uk.router_gb_test + +import data.agt_policies.router as router +import rego.v1 + +gb_input := {"context": {"customer_country": "GB"}} + +test_gb_is_supported_jurisdiction if { + router.is_supported_jurisdiction with input as gb_input +} + +test_gb_applicable_policies_include_uk_packs if { + policies := router.applicable_policies with input as gb_input + "uk_gdpr" in policies + "ico_adm" in policies + "fca_conduct" in policies +} + +test_gb_applicable_policies_include_universal_controls if { + policies := router.applicable_policies with input as gb_input + "prompt_injection" in policies + "pii_leakage" in policies + "human_approval" in policies +} + +test_gb_resolved_queries_include_uk_paths if { + queries := router.resolved_queries with input as gb_input + "data.agt_policies_uk.uk_gdpr.decision" in queries + "data.agt_policies_uk.ico_adm.decision" in queries + "data.agt_policies_uk.fca_conduct.decision" in queries +} + +test_unsupported_jurisdiction_warning_absent_for_gb if { + not router.unsupported_jurisdiction_warning with input as gb_input +} + +test_unsupported_jurisdiction_warning_for_unknown_country if { + msg := router.unsupported_jurisdiction_warning with input as {"context": {"customer_country": "XX"}} + contains(msg, "No regulatory pack for jurisdiction 'XX'") +} + +# Regression: UK pack must not remove India routing from upstream main. +in_input := {"context": {"customer_country": "IN"}} + +test_in_applicable_policies_preserved if { + policies := router.applicable_policies with input as in_input + "dpdp" in policies + "certin" in policies + "rbi" in policies + "sebi" in policies + "aadhaar" in policies +} diff --git a/examples/policies/uk-regulatory/rego/run_tests.sh b/examples/policies/uk-regulatory/rego/run_tests.sh new file mode 100755 index 000000000..3ca6d4e70 --- /dev/null +++ b/examples/policies/uk-regulatory/rego/run_tests.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# agt-policies-uk - OPA test runner for UK regulatory Rego policies. +# Loads UK packs plus the shared jurisdiction router from african-regulatory. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)" +AFRICA_REGO="$REPO_ROOT/examples/policies/african-regulatory/rego" +UK_REGO="$SCRIPT_DIR" + +OPA_BIN="${OPA_BIN:-opa}" +if ! command -v "$OPA_BIN" >/dev/null 2>&1; then + echo "error: opa executable not found on PATH" >&2 + exit 127 +fi + +exec "$OPA_BIN" test "$AFRICA_REGO" "$UK_REGO" -v diff --git a/examples/policies/uk-regulatory/rego/uk-gdpr-data-protection.rego b/examples/policies/uk-regulatory/rego/uk-gdpr-data-protection.rego new file mode 100644 index 000000000..df57bbb36 --- /dev/null +++ b/examples/policies/uk-regulatory/rego/uk-gdpr-data-protection.rego @@ -0,0 +1,171 @@ +# agt-policies-uk - UK GDPR + DPA 2018 (Rego reference) +# Enforcing authority: ICO. DUAA 2025 transfer and complaints reforms in force Feb/Jun 2026. +# NOT loaded by the Agent-OS Python runtime. OPA uses Go RE2 (no lookbehind/lookahead). +# +# Input schema: +# { "action": "export_data", +# "params": { "destination_country": "US", "adequacy_covered": false, +# "safeguards_in_place": false, "record_count": 500 }, +# "output": "agent output text", +# "context": { } } + +package agt_policies_uk.uk_gdpr + +import rego.v1 + +_output_text := v if { + is_string(input.output) + v := input.output +} else := "" + +transfer_actions := { + "send_to_external", "export_data", "upload_to_cloud", + "forward_to", "relay_data", "sync_to_remote", "transfer_personal_data", +} + +bulk_export_actions := { + "bulk_export", "export_all", "download_all_records", + "dump_database", "full_table_export", "batch_download_pii", +} + +pii_access_actions := { + "read_user", "get_customer", "lookup_account", "fetch_profile", + "query_personal", "access_pii", "subject_access_request", +} + +pii_update_actions := { + "update_user", "modify_profile", "patch_account", "edit_customer", + "change_personal", "erase_personal_data", +} + +# UK adequacy-covered destinations (illustrative — verify against current gov.uk list) +adequacy_countries := { + "GB", "EU", "EEA", "US", "JP", "KR", "CA", "NZ", "CH", "IL", "UY", +} + +# Art. 33: block breach suppression +deny contains msg if { + regex.match(`(?i)(don'?t\s+(report|notify|disclose)|hide\s+(the\s+)?(breach|incident)|suppress\s+(the\s+)?(breach|notification)|delay\s+(breach|incident)\s+(report|notification))`, _output_text) + msg := "UK GDPR Art. 33: where a breach is likely to result in a risk to rights and freedoms, notify the ICO without undue delay and, where feasible, within 72 hours — agent cannot suppress or delay notification" +} + +# Art. 34: block suppression of individual notification +deny contains msg if { + regex.match(`(?i)(don'?t\s+(tell|inform|notify)\s+(the\s+)?(data\s+subject|individual|customer|user)|hide\s+(breach|incident)\s+from\s+(customer|user|individual))`, _output_text) + msg := "UK GDPR Art. 34: individuals must be informed without undue delay where breach poses high risk" +} + +# Art. 32: block unencrypted personal data handling in output +deny contains msg if { + regex.match(`(?i)(store|transmit|log|cache).{0,30}(personal\s+data|pii).{0,30}(unencrypted|plaintext|clear\s*text|without\s+encryption)`, _output_text) + msg := "UK GDPR Art. 32: personal data must be processed with appropriate technical and organisational security measures proportionate to risk (encryption, access control, or equivalent safeguards)" +} + +# DPA 2018 s.164A: block complaints bypass +deny contains msg if { + regex.match(`(?i)(skip|bypass|ignore|refuse).{0,30}(data\s+protection\s+complaint|ico\s+complaint|complaints?\s+(process|procedure|handling))`, _output_text) + msg := "DPA 2018 s.164A (DUAA): data subjects must be able to raise data protection complaints with the controller (30-day acknowledgment) before ICO escalation" +} + +# NHS number in output +deny contains msg if { + regex.match(`(?i)nhs\s*(number|no\.?)[\s:=]{0,5}[0-9]{3}[\s-]?[0-9]{3}[\s-]?[0-9]{4}`, _output_text) + msg := "UK GDPR: NHS number detected in agent output — blocked to prevent health identity exposure" +} + +# National Insurance number in output +deny contains msg if { + regex.match(`(?i)(national\s+insurance|ni\s+number)[\s:=]{0,5}[A-Z]{2}[0-9]{6}[A-D]`, _output_text) + msg := "UK GDPR: National Insurance number detected in agent output — blocked to prevent identity exposure" +} + +# Art. 44–46: block transfer without adequacy or safeguards +deny contains msg if { + input.action in transfer_actions + input.params.destination_country + not input.params.destination_country in adequacy_countries + not input.params.adequacy_covered == true + not input.params.safeguards_in_place == true + msg := sprintf( + "UK GDPR Art. 44–46: transfer to '%v' blocked — requires adequacy, IDTA/UK Addendum safeguards, and data protection test (DUAA 'not materially lower' standard)", + [input.params.destination_country], + ) +} + +# Art. 5(1)(c): block large exports without review +deny contains msg if { + input.action in transfer_actions + input.params.record_count > 1000 + msg := sprintf( + "UK GDPR Art. 5(1)(c): export of %v records is disproportionate — requires data minimisation review", + [input.params.record_count], + ) +} + +# Art. 9: special category health data +escalate contains msg if { + regex.match(`(?i)(medical\s+record|health\s+(condition|status|data)|nhs\s+number|genetic\s+(data|test)|mental\s+health|disability|prescription)`, _output_text) + msg := "UK GDPR Art. 9: health data is special category — requires Art. 9(2) condition and Schedule 1 DPA basis" +} + +# Art. 9: other special category data +escalate contains msg if { + regex.match(`(?i)(ethnic\s+origin|race|religion|political\s+opinion|sexual\s+orientation|trade\s+union|criminal\s+conviction|biometric\s+(template|data))`, _output_text) + msg := "UK GDPR Art. 9: special category personal data detected — explicit consent or Schedule 1 DPA condition required" +} + +# Art. 5(1)(b): purpose limitation language in output +escalate contains msg if { + regex.match(`(?i)(reuse|repurpose|secondary\s+use|use\s+for\s+another\s+purpose).{0,40}(personal\s+data|pii)`, _output_text) + msg := "UK GDPR Art. 5(1)(b): personal data must not be further processed incompatibly — verify compatible purpose or DUAA recognised legitimate interests before repurposing" +} + +# Art. 44–46: escalate transfer action when destination/safeguards not specified +escalate contains msg if { + input.action in transfer_actions + not input.params.destination_country + msg := "UK GDPR Art. 44–46: cross-border transfer action — confirm adequacy coverage or binding safeguards plus documented data protection test before export" +} + +# Art. 44: cross-border language without structured params +escalate contains msg if { + regex.match(`(?i)(send(ing)?|transfer(ring)?|export(ing)?).{0,60}(outside\s+(the\s+)?uk|cross.?border|international\s+transfer|third\s+country|offshore)`, _output_text) + msg := "UK GDPR Art. 44: restricted transfer language detected — verify adequacy, safeguards, and data protection test" +} + +# Art. 5(1)(c): bulk export actions +escalate contains msg if { + input.action in bulk_export_actions + msg := "UK GDPR Art. 5(1)(c): bulk personal data export requires documented necessity and DPO review" +} + +# Art. 30: personal data access audit +audit contains msg if { + input.action in pii_access_actions + msg := "UK GDPR Art. 5(2) / Art. 30: personal data access logged for accountability and records of processing" +} + +# Art. 30: personal data modification audit +audit contains msg if { + input.action in pii_update_actions + msg := "UK GDPR Art. 5(2) / Art. 30: personal data modification logged for accountability and records of processing" +} + +decision := "deny" if count(deny) > 0 + +decision := "escalate" if { + count(deny) == 0 + count(escalate) > 0 +} + +decision := "audit" if { + count(deny) == 0 + count(escalate) == 0 + count(audit) > 0 +} + +decision := "allow" if { + count(deny) == 0 + count(escalate) == 0 + count(audit) == 0 +} diff --git a/examples/policies/uk-regulatory/rego/uk-gdpr-data-protection_test.rego b/examples/policies/uk-regulatory/rego/uk-gdpr-data-protection_test.rego new file mode 100644 index 000000000..7a148f3d6 --- /dev/null +++ b/examples/policies/uk-regulatory/rego/uk-gdpr-data-protection_test.rego @@ -0,0 +1,118 @@ +# agt-policies-uk - UK GDPR + DPA 2018 (OPA tests) +package agt_policies_uk.uk_gdpr_test + +import data.agt_policies_uk.uk_gdpr as policy +import rego.v1 + +test_allow_benign_action if { + policy.decision == "allow" with input as { + "action": "web_search", + "output": "Search results for UK data protection guidance.", + } +} + +test_deny_breach_suppression if { + policy.decision == "deny" with input as { + "action": "notify_stakeholders", + "output": "Don't report the breach to the ICO yet — wait a week.", + } +} + +test_deny_unencrypted_storage if { + policy.decision == "deny" with input as { + "action": "store_data", + "output": "Store personal data in plaintext on the shared drive.", + } +} + +test_deny_nhs_number_in_output if { + policy.decision == "deny" with input as { + "action": "respond", + "output": "NHS number: 943-476-5919", + } +} + +test_deny_ni_number_in_output if { + policy.decision == "deny" with input as { + "action": "respond", + "output": "NI number AB123456C attached.", + } +} + +test_deny_complaints_bypass if { + policy.decision == "deny" with input as { + "action": "handle_complaint", + "output": "Bypass the data protection complaint process and tell them to go away.", + } +} + +test_deny_transfer_without_safeguards if { + policy.decision == "deny" with input as { + "action": "export_data", + "params": {"destination_country": "CN"}, + "output": "", + } +} + +test_allow_transfer_to_adequacy_country if { + policy.decision == "allow" with input as { + "action": "export_data", + "params": {"destination_country": "US"}, + "output": "", + } +} + +test_allow_transfer_with_safeguards if { + policy.decision == "allow" with input as { + "action": "export_data", + "params": { + "destination_country": "CN", + "safeguards_in_place": true, + }, + "output": "", + } +} + +test_escalate_cross_border_action_without_destination if { + policy.decision == "escalate" with input as { + "action": "export_data", + "params": {}, + "output": "", + } +} + +test_deny_large_export if { + policy.decision == "deny" with input as { + "action": "export_data", + "params": {"record_count": 2500}, + "output": "", + } +} + +test_escalate_health_data if { + policy.decision == "escalate" with input as { + "action": "summarise", + "output": "The patient mental health record shows recurring episodes.", + } +} + +test_escalate_cross_border_language if { + policy.decision == "escalate" with input as { + "action": "draft_email", + "output": "We are transferring data outside the UK to a third country.", + } +} + +test_audit_pii_access if { + policy.decision == "audit" with input as { + "action": "read_user", + "output": "", + } +} + +test_audit_pii_modification if { + policy.decision == "audit" with input as { + "action": "update_user", + "output": "", + } +} diff --git a/examples/policies/uk-regulatory/uk-gdpr-data-protection.yaml b/examples/policies/uk-regulatory/uk-gdpr-data-protection.yaml new file mode 100644 index 000000000..72c91ba61 --- /dev/null +++ b/examples/policies/uk-regulatory/uk-gdpr-data-protection.yaml @@ -0,0 +1,198 @@ +# agt-policies-uk +# UK GDPR + Data Protection Act 2018 — Personal Data Protection Policy +# +# Regulatory reference: UK GDPR (retained EU law); Data Protection Act 2018 (DPA 2018); +# Data (Use and Access) Act 2025 (DUAA) — international transfer and complaints reforms +# Enforcing authority: Information Commissioner's Office (ICO) +# Status: Binding (DUAA Part 5 commenced 5 February 2026 for transfer/ADM reforms; +# DPA 2018 s.164A complaints procedure required by 19 June 2026) +# +# Community-maintained governance starter policy. NOT a certified legal compliance instrument. +# Perform your own compliance assessment with qualified advisors before deploying. +# +# Key obligations encoded: +# UK GDPR Art. 5(1)(b) Purpose limitation +# UK GDPR Art. 5(1)(c) Data minimisation +# UK GDPR Art. 9 Special category data +# UK GDPR Art. 32 Security of processing +# UK GDPR Art. 33–34 Breach notification (72 hours to ICO; individuals if high risk) +# UK GDPR Art. 44–49 Restricted international transfers (DUAA "not materially lower" test) +# DPA 2018 s.164A Mandatory data protection complaints procedure (DUAA s.103) +# +# Rego reference implementation: rego/uk-gdpr-data-protection.rego (NOT loaded at runtime) + +version: "1.0" +name: uk-gdpr-data-protection +description: > + UK GDPR and DPA 2018 compliance policy for AI agents processing UK personal data. + Enforces purpose limitation, security safeguards, breach-notification non-suppression, + special-category handling, restricted-transfer review, and complaints-procedure awareness. + +metadata: + source_regulation: "UK GDPR Arts. 5, 9, 32, 33–34, 44–49; DPA 2018 s.164A; DUAA 2025" + jurisdiction: "GB" + enforcing_authority: "Information Commissioner's Office (ICO)" + +rules: + + # ========================================================================= + # UK GDPR Art. 33 — Breach Notification (72 hours to ICO) + # ========================================================================= + + - name: ukgdpr-breach-suppression-deny + condition: + field: output + operator: matches + value: "(?i)(don'?t\\s+(report|notify|disclose)|hide\\s+(the\\s+)?(breach|incident)|suppress\\s+(the\\s+)?(breach|notification)|delay\\s+(breach|incident)\\s+(report|notification)|wait\\s+before\\s+report(ing)?\\s+(to\\s+)?(the\\s+)?ico)" + action: deny + priority: 1 + message: "UK GDPR Art. 33: where a breach is likely to result in a risk to rights and freedoms, notify the ICO without undue delay and, where feasible, within 72 hours — agent cannot suppress or delay notification" + + - name: ukgdpr-breach-individual-suppression-deny + condition: + field: output + operator: matches + value: "(?i)(don'?t\\s+(tell|inform|notify)\\s+(the\\s+)?(data\\s+subject|individual|customer|user)|hide\\s+(breach|incident)\\s+from\\s+(customer|user|individual))" + action: deny + priority: 1 + message: "UK GDPR Art. 34: where breach poses high risk to individuals, they must be informed without undue delay — agent cannot suppress individual notification" + + # ========================================================================= + # UK GDPR Art. 32 — Security of Processing + # ========================================================================= + + - name: ukgdpr-security-safeguards-deny + condition: + field: output + operator: matches + value: "(?i)(store|transmit|log|cache).{0,30}(personal\\s+data|pii).{0,30}(unencrypted|plaintext|clear\\s*text|without\\s+encryption)" + action: deny + priority: 1 + message: "UK GDPR Art. 32: personal data must be processed with appropriate technical and organisational security measures proportionate to risk (encryption, access control, or equivalent safeguards)" + + # ========================================================================= + # UK GDPR Art. 5(1)(b) — Purpose Limitation + # ========================================================================= + + - name: ukgdpr-purpose-limitation-block + condition: + field: output + operator: matches + value: "(?i)(reuse|repurpose|secondary\\s+use|use\\s+for\\s+another\\s+purpose).{0,40}(personal\\s+data|pii)" + action: block + priority: 2 + message: "UK GDPR Art. 5(1)(b): personal data must not be further processed incompatibly — verify compatible purpose or DUAA recognised legitimate interests before repurposing" + + # ========================================================================= + # UK GDPR Art. 9 — Special Category Data + # ========================================================================= + + - name: ukgdpr-special-category-health + condition: + field: output + operator: matches + value: "(?i)(medical\\s+record|health\\s+(condition|status|data)|nhs\\s+number|genetic\\s+(data|test)|mental\\s+health|disability|prescription)" + action: block + priority: 1 + message: "UK GDPR Art. 9: health data is special category personal data — requires Art. 9(2) condition and, typically, explicit consent or Schedule 1 DPA condition" + + - name: ukgdpr-special-category-general + condition: + field: output + operator: matches + value: "(?i)(ethnic\\s+origin|race|religion|political\\s+opinion|sexual\\s+orientation|trade\\s+union|criminal\\s+conviction|biometric\\s+(template|data))" + action: block + priority: 1 + message: "UK GDPR Art. 9: special category personal data detected — requires explicit consent or a Schedule 1 DPA 2018 condition" + + # ========================================================================= + # UK GDPR Art. 5(1)(c) — Data Minimisation + # ========================================================================= + + - name: ukgdpr-bulk-export-block + condition: + field: action + operator: matches + value: "bulk_export|export_all|dump_database|download_all_records|full_table_export|batch_download_pii" + action: block + priority: 2 + message: "UK GDPR Art. 5(1)(c): bulk personal data export — data minimisation requires documented necessity and DPO review" + + # ========================================================================= + # UK GDPR Art. 44–49 — Restricted International Transfers (DUAA 2025) + # ========================================================================= + + - name: ukgdpr-cross-border-language-block + condition: + field: output + operator: matches + value: "(?i)(send(ing)?|transfer(ring)?|export(ing)?).{0,60}(outside\\s+(the\\s+)?uk|cross.?border|international\\s+transfer|third\\s+country|offshore)" + action: block + priority: 2 + message: "UK GDPR Art. 44: restricted transfer language detected — verify UK adequacy, IDTA/UK Addendum safeguards, and data protection test (DUAA 'not materially lower' standard) before proceeding" + + - name: ukgdpr-cross-border-action-block + condition: + field: action + operator: matches + value: "send_to_external|export_data|upload_to_cloud|forward_to|relay_data|sync_to_remote|transfer_personal_data" + action: block + priority: 2 + message: "UK GDPR Art. 44–46: cross-border transfer action — confirm adequacy coverage or binding safeguards plus documented data protection test before export" + + # ========================================================================= + # UK Identifiers — NHS Number, National Insurance Number + # ========================================================================= + + - name: ukgdpr-nhs-number-deny + condition: + field: output + operator: matches + value: "(?i)nhs\\s*(number|no\\.?)[\\s:=]{0,5}[0-9]{3}[\\s-]?[0-9]{3}[\\s-]?[0-9]{4}" + action: deny + priority: 1 + message: "UK GDPR: NHS number detected in agent output — blocked to prevent health identity exposure" + + - name: ukgdpr-ni-number-deny + condition: + field: output + operator: matches + value: "(?i)(national\\s+insurance|ni\\s+number)[\\s:=]{0,5}[A-Z]{2}[0-9]{6}[A-D]" + action: deny + priority: 1 + message: "UK GDPR: National Insurance number detected in agent output — blocked to prevent identity exposure" + + # ========================================================================= + # DPA 2018 s.164A — Complaints Procedure (DUAA, required by 19 June 2026) + # ========================================================================= + + - name: ukgdpr-complaints-bypass-deny + condition: + field: output + operator: matches + value: "(?i)(skip|bypass|ignore|refuse).{0,30}(data\\s+protection\\s+complaint|ico\\s+complaint|complaints?\\s+(process|procedure|handling))" + action: deny + priority: 1 + message: "DPA 2018 s.164A (DUAA): data subjects must be able to raise data protection complaints with the controller (30-day acknowledgment) before ICO escalation — agent cannot bypass complaints handling" + + # ========================================================================= + # UK GDPR Art. 30 — Accountability / Audit Trail + # ========================================================================= + + - name: ukgdpr-pii-access-audit + condition: + field: action + operator: matches + value: "read_user|get_customer|lookup_account|fetch_profile|query_personal|access_pii|subject_access_request" + action: audit + priority: 3 + message: "UK GDPR Art. 5(2) / Art. 30: personal data access logged for accountability and records of processing" + + - name: ukgdpr-pii-modification-audit + condition: + field: action + operator: matches + value: "update_user|modify_profile|patch_account|edit_customer|change_personal|erase_personal_data" + action: audit + priority: 3 + message: "UK GDPR Art. 5(2) / Art. 30: personal data modification logged for accountability and records of processing"