Industry Scenarios
Four production-ready governance scenarios from edictum-demo covering pharma, fintech, customer support, and DevOps.
Right page if: you need production-ready contract examples for pharma (HIPAA), fintech (SOX/MiFID II), customer support (GDPR), or DevOps (SOC 2) from edictum-demo. Wrong page if: you need to write contracts from scratch -- see https://docs.edictum.ai/docs/guides/writing-contracts. For Python decorator contracts specifically, see https://docs.edictum.ai/docs/guides/python-contracts. Gotcha: the DevOps scenario uses Python decorator contracts while the other three use YAML. Claims-based authorization (principal.claims.trade_approval) gates actions without changing the user's role -- useful for temporary approvals.
Four production-ready governance scenarios ship in the edictum-demo repository. Each includes complete contracts, mock tools, principal configurations, and runnable agent code. Use them as starting points for your own contracts.
Pharmacovigilance
Path: scenarios/pharma/ | Framework: LangChain + LangGraph | Compliance: HIPAA, 21 CFR 11, ICH-E6
A clinical-trial agent governed by 7 contracts across access control, change control, and data protection.
Contracts
| Contract | Type | What it enforces |
|---|---|---|
restrict-patient-data | pre | Role-based access: only pharmacovigilance, clinical_data_manager, and medical_monitor roles can query clinical datasets |
no-unblinding | pre | Blocks unblinding queries during active trials |
case-report-requires-ticket | pre | CAPA/deviation ticket required for case report updates |
case-report-authorized-roles | pre | Only pharmacovigilance and clinical_data_manager roles can update case reports |
pii-in-any-output | post | Detects SSN, patient IDs, email, phone, DOB via regex |
regulatory-export-pii | post | Enhanced PII detection for regulatory document exports |
session-limits | session | Max 20 calls, 3 case reports, 2 exports per session |
Key patterns demonstrated
- Multi-role RBAC: Four roles (
researcher,pharmacovigilance,clinical_data_manager,medical_monitor) with different access levels - Change control: Ticket reference required for state-mutating operations
- Postcondition PII scanning: Regex-based detection for SSN (
\b\d{3}-\d{2}-\d{4}\b), patient IDs, email, phone - Per-tool session limits: Different caps for different tool sensitivity levels
Running it
cd scenarios/pharma
python pharma_agent.py --role pharmacovigilance
python pharma_agent.py --role researcher # denied access to clinical dataFintech / Trading Compliance
Path: scenarios/fintech/ | Framework: LangChain + LangGraph | Compliance: SOX, MiFID II, PCI-DSS
A trading compliance agent governed by 7 contracts covering trade limits, account access, and data protection.
Contracts
| Contract | Type | What it enforces |
|---|---|---|
trade-size-limit | pre | Trades >1000 shares denied unless principal.claims.trade_approval is true |
account-access-control | pre | Full account data restricted to senior_trader, compliance_officer, risk_manager |
no-restricted-accounts | pre | Blocks access to frozen/under-investigation accounts (FROZEN, RESTRICTED prefix) |
compliance-report-requires-ticket | pre | Audit ticket required for compliance report generation |
pii-in-output | post | Warns on SSN, account numbers, email, phone in output |
pii-in-compliance-report | post | Enhanced PII detection for compliance report outputs |
session-limits | session | Max 15 calls, 5 trades, 2 compliance reports |
Key patterns demonstrated
- Claims-based authorization:
principal.claims.trade_approval: truegates high-value trades without changing the user's role. See Principals for how claims work.
when:
all:
- args.quantity: { gt: 1000 }
- principal.claims.trade_approval: { not_equals: true }- Pattern-based blocking: Account IDs containing
FROZENorRESTRICTEDmarkers are denied viacontains_any - Quantitative thresholds: Numeric comparison operators (
gt) for trade size limits - Tiered roles:
analyst<senior_trader<compliance_officer<risk_manager
Running it
cd scenarios/fintech
python fintech_agent.py --role analyst # denied large trades
python fintech_agent.py --role senior_trader # allowed with trade_approval claimCustomer Support
Path: scenarios/customer-support/ | Framework: LangChain + LangGraph | Compliance: GDPR, PCI-DSS
A support-ticket agent governed by 7 contracts covering access control, refund limits, escalation rules, and PII redaction.
Contracts
| Contract | Type | What it enforces |
|---|---|---|
billing-access-control | pre | Billing data restricted to senior_agent, supervisor, billing_specialist |
refund-limit | pre | Refunds >$500 require supervisor or billing_specialist role |
escalation-requires-reason | pre | Escalations must include a documented reason |
ticket-update-authorized-roles | pre | Only senior agents and supervisors can close tickets |
pii-in-output | post | Warns on email, phone, address, partial card numbers |
pii-in-customer-lookup | post | Enhanced PII detection for customer lookup results |
session-limits | session | Max 20 calls, 5 lookups, 3 refunds, 2 escalations |
Key patterns demonstrated
- Financial thresholds: Refunds above $500 gated by role
- Operational workflow enforcement: Escalations require a reason field (not just RBAC)
when:
any:
- args.reason: { exists: false }
- args.reason: { equals: "" }- Data minimization: PII detection includes partial credit card numbers (
****1234pattern) - Ticket lifecycle control: Only authorized roles can transition tickets to closed state
Running it
cd scenarios/customer-support
python support_agent.py --role support_agent # limited access
python support_agent.py --role supervisor # full accessDevOps / File Organizer
Path: scenarios/devops/ | Framework: OpenAI SDK (via OpenRouter) | Compliance: SOC 2
A file-organizer agent governed by Python-based contracts (not YAML). This scenario demonstrates the decorator contract API.
Contracts (Python)
| Contract | Type | What it enforces |
|---|---|---|
deny_sensitive_reads() | pre (built-in) | Blocks reads of .env, .ssh, kubernetes secrets, and other sensitive paths |
no_destructive_commands | pre (custom) | Blocks rm, rmdir, shred commands |
require_target_dir | pre (factory) | Confines mv targets to /tmp/ |
limit_total_operations | session | Caps at 25 bash operations per session |
check_bash_errors | post | Warns when bash output contains error indicators (No such file, Permission denied) |
Key patterns demonstrated
- Python decorator API: Contracts defined with
@precondition,@postcondition, and@session_contractdecorators instead of YAML - Built-in contract:
deny_sensitive_reads()provides instant secret-file protection with no configuration - Factory pattern: Parameterized preconditions for reuse across different base paths
from edictum import precondition, Verdict
@precondition("Bash")
def no_destructive_commands(envelope):
cmd = envelope.bash_command
if any(d in cmd.split() for d in ["rm", "rmdir", "shred"]):
return Verdict.fail(f"Destructive command denied: {cmd}")
return Verdict.pass_()- Self-correction: When the agent is denied, it reads the denial message and adjusts its approach (e.g., uses
cpinstead ofmvto a restricted target) - Compared with unguarded baseline:
demo_without.pyshows the same agent reading.envfiles and runningrm -rfwithout governance
Running it
cd scenarios/devops
python demo_with.py # governed: destructive commands denied
python demo_without.py # unguarded: reads .env, runs rm -rfWhen to use YAML vs Python contracts
The pharma, fintech, and customer-support scenarios use YAML contracts. The DevOps scenario uses Python decorators. Both approaches enforce identically -- the choice depends on your workflow:
| Factor | YAML | Python |
|---|---|---|
| Managed by | Security/compliance team | Development team |
| Hot-reloadable | Yes (via console SSE) | No (requires restart) |
| Custom logic | Limited to operators and expressions | Full Python (envelope introspection, external API calls) |
| Testable with CLI | edictum validate, edictum test | Standard pytest |
| Version control | Standalone YAML files | In-code with application |
Most teams start with YAML and add Python contracts only for logic that cannot be expressed with built-in operators.
Running all scenarios
All scenarios support a --role flag and an observe mode flag. The observe mode flag varies between scenarios:
python <scenario>.py --role <role> # set the principal role
# DevOps and Pharma scenarios:
python <scenario>.py --observe # log but don't deny
# Fintech and Customer-Support scenarios:
python <scenario>.py --mode observe # log but don't denySee the edictum-demo README for setup instructions and environment variables.
Last updated on