Compliance Layer — Epics & User Stories
Last updated: 2026-04-18 Story point scale: 1 (trivial) · 2 (small) · 3 (medium) · 5 (large) · 8 (XL) · 13 (epic-sized) For Jira import: see JIRA_IMPORT.csv in this directory — ready to upload via Jira's CSV import.
Summary
| Epic ID | Epic Name | Stories | Points |
|---|---|---|---|
| EP-CE-01 | Compliance Layer — Service Foundation | 4 | 13 |
| EP-CE-02 | Compliance Layer — Rule Engine Core | 9 | 47 |
| EP-CE-03 | Compliance Layer — Hold Queue & Manual Review | 5 | 16 |
| EP-CE-04 | Compliance Layer — Rule & Blocklist Management API | 4 | 16 |
| EP-CE-05 | Compliance Layer — Tenant Scoring & Risk Tiering | 3 | 14 |
| EP-CE-06 | Compliance Layer — Reporting & Audit | 2 | 11 |
| EP-CE-07 | Compliance Layer — Observability & Production Hardening | 5 | 16 |
| EP-CE-08 | Compliance Layer — Async Pipeline Integration | 5 | 21 |
| EP-CE-09 | Compliance Layer — Local LLM Platform | 4 | 21 |
| EP-CE-10 | Compliance Layer — Tenant-Facing Web Portal Integration | 4 | 16 |
| Total | 45 | 191 |
EP-CE-01: Compliance Layer — Service Foundation
Description: Bootstrap the NestJS gRPC + HTTP service, database schema, mTLS, and baseline observability.
US-CE-001 — Scaffold NestJS application with dual transport
As a platform engineer, I want a NestJS app bootstrapped with gRPC (port 50052) and HTTP (port 3002) transports so that the Compliance Layer exposes both the evaluation API and the admin REST API.
Acceptance Criteria:
-
main.tsbootstraps both gRPC microservice and HTTP app -
src/proto/compliance.protomatches SYNC_CONTRACT definition - TypeScript types generated from proto
-
grpcurlreturns valid mock response from local service - ESLint + TypeScript compile with 0 errors
Story Points: 3 · Priority: High
US-CE-002 — Create compliance PostgreSQL schema and all tables via Prisma migrations
As a platform engineer, I want the full database schema defined as Prisma migrations so that the schema is reproducible across environments.
Acceptance Criteria:
- Migration creates schema and all enum types
- Partitioned tables (
evaluation_log,score_history) have initial monthly partitions - RLS policies on
hold_queue,evaluation_log,tenant_compliance_scoresverified via integration test - Audit log immutability rules tested — UPDATE/DELETE silently discarded
Story Points: 5 · Priority: High
US-CE-003 — Implement mTLS for gRPC transport
As a security engineer, I want gRPC connections to require mutual TLS so that only sms-orchestrator can invoke EvaluateCompliance.
Acceptance Criteria:
- gRPC server rejects connections without valid client certificate
- Cert paths read from env vars
TLS_CERT_PATH,TLS_KEY_PATH,TLS_CA_PATH - Local dev bypass via
GRPC_TLS_ENABLED=false - Integration test verifies TLS rejection with self-signed cert
Story Points: 3 · Priority: High
US-CE-004 — Health, readiness, and metrics HTTP endpoints
As a platform engineer, I want /health, /ready, and /metrics endpoints so that Kubernetes probes and Prometheus scraping work correctly.
Acceptance Criteria:
-
GET /healthreturns 200 without dependency checks -
GET /readyreturns 200 when PostgreSQL + Redis + NATS reachable; 503 otherwise -
GET /metricsreturns valid Prometheus text format - Kubernetes liveness/readiness probes pass in staging
Story Points: 2 · Priority: High
EP-CE-02: Compliance Layer — Rule Engine Core
Description: Implement all 10 rule type evaluators, rule loading/caching, and the EvaluateCompliance gRPC handler.
US-CE-005 — Implement KEYWORD rule evaluator with in-memory keyword sets
As a compliance engineer, I want KEYWORD rules to match keyword lists against message bodies.
Acceptance Criteria:
- Keyword lists loaded into process memory at startup, refreshed every 5 min
- Case-insensitive by default;
caseSensitiveflag supported - Multi-language (English, Dari/Farsi, Pashto seed lists)
-
matchAllflag — require all vs any keyword - Returns
evidencefield with redacted match preview - 15+ unit tests
Story Points: 5 · Priority: High
US-CE-006 — Implement REGEX rule evaluator with ReDoS protection
As a security engineer, I want REGEX rules evaluated with a linear-time engine so malicious patterns cannot DoS.
Acceptance Criteria:
- Uses
re2(or equivalent linear-time engine) - Regex validated at save time; invalid or oversized patterns rejected (max 500 chars)
- Hard 10 ms timeout per regex evaluation
-
negateflag inverts result - 15+ unit tests including known ReDoS patterns
Story Points: 5 · Priority: High
US-CE-007 — Implement AI_CLASSIFICATION rule evaluator with caching
As a compliance engineer, I want AI-powered content classification so sophisticated spam, phishing, and fraud can be detected.
Acceptance Criteria:
- LLM provider abstraction (LocalLLMClient / ClaudeClient / OpenAIClient / MockClient)
- Provider selection via
AI_PROVIDERenv; defaultlocal - Body anonymisation pre-processor when ANONYMIZE_BODY_BEFORE_AI=true
- Redis cache with 24 h TTL keyed by
{modelVersion}:{sha256(anonymisedBody)} - Categories returned as confidence scores 0.0–1.0
-
minConfidencethreshold check -
fallbackActionapplied when LLM unavailable (default HOLD — fail-closed) - Circuit breaker on LLM client
- Per-provider latency and error metrics
- 10+ unit tests with mocked LLM client
Story Points: 8 · Priority: High
US-CE-008 — Implement RATE_VOLUME rule with Redis sliding window
As a platform engineer, I want RATE_VOLUME rules to enforce per-account/sender/recipient frequency thresholds.
Acceptance Criteria:
- Redis sorted-set sliding window (ZADD + ZCOUNT)
- Configurable
windowSeconds,maxMessages,scope - Independent counters per scope
- Graceful degradation to HOLD when Redis unavailable (fail-closed)
- 10+ unit tests
Story Points: 5 · Priority: High
US-CE-009 — Implement DLR_ABUSE rule with sliding-window stats
As a compliance engineer, I want DLR_ABUSE rules to detect tenants with high DLR failure rates.
Acceptance Criteria:
- NATS consumer for
sms.dlr.inboundmaintainscompliance.dlr_stats - Three window types: 1h, 24h, 7d
- Rule evaluates against latest window with
minSampleSizeguard -
failureRateThresholdcomparison - 10+ unit tests
Story Points: 5 · Priority: Medium
US-CE-010 — Implement GEO_RESTRICTION and TEMPORAL rule evaluators
As a platform engineer, I want GEO and TEMPORAL rules to restrict messages by destination country and time-of-day.
Acceptance Criteria:
- GEO: longest-prefix match to ISO 3166-1 country code
- GEO:
ALLOW_ONLYandBLOCKmodes - TEMPORAL: evaluation in configured IANA timezone
- TEMPORAL:
allowedHours,allowedDaysOfWeek - 15+ unit tests across both types
Story Points: 3 · Priority: Medium
US-CE-011 — Implement SENDER_ID and RECIPIENT rule evaluators
As a compliance engineer, I want rules for sender ID patterns and recipient-specific checks.
Acceptance Criteria:
- SENDER_ID: whitelist, blacklist, regex pattern matching
- RECIPIENT: exact/prefix/regex blocklist matching
- Blocklists loaded from
compliance.blocklist_entrieswith Redis cache - 10+ unit tests
Story Points: 3 · Priority: High
US-CE-012 — Implement COMPOSITE rule evaluator with cycle detection
As a compliance engineer, I want COMPOSITE rules that combine other rules with AND/OR/NOT logic.
Acceptance Criteria:
- AND / OR / NOT operators
- Max depth 5 enforced at eval time
- Cycle detection at save time (422)
- Runtime
visited: Set<ruleId>prevents infinite loops - 10+ unit tests including cycle cases
Story Points: 5 · Priority: Medium
US-CE-013 — Implement full EvaluateCompliance gRPC handler
As sms-orchestrator NATS consumer, I want to call EvaluateCompliance and receive a verdict within 500 ms P95.
Acceptance Criteria:
- Input validation with gRPC INVALID_ARGUMENT on malformed fields
- Evaluation result dedup cache (5 min, fingerprint-keyed)
- Tenant risk state loaded from Redis cache
- Rule set loaded from Redis cache (300 s TTL); DB fallback
- ALLOW rules evaluated first (whitelist fast-path)
- SUSPENDED tenant → auto-HOLD
- BLOCK/HOLD/FLAG rules evaluated in priority order
- Budget enforcement (450 ms internal cap)
- Async side-effects (eval log write, hold queue insert, NATS publish)
- P95 latency ≤ 500 ms verified via ghz load test at 200 RPS
Story Points: 8 · Priority: High
EP-CE-03: Compliance Layer — Hold Queue & Manual Review
Description: Hold queue lifecycle — insertion, review, release, rejection, auto-expiry — plus admin REST API.
US-CE-014 — Hold queue insertion with original payload preservation
As a compliance reviewer, I want held messages stored with full original payload so I can review and release them intact.
Acceptance Criteria:
-
hold_queuerow inserted atomically with evaluation log row -
payloadJSONB contains full original message -
review_prioritycomputed per APPLICATION_LOGIC §3 -
auto_expires_atset to 24 h from creation - NATS
compliance.message.heldevent published
Story Points: 3 · Priority: High
US-CE-015 — REST endpoints for hold queue listing and detail retrieval
As a platform admin, I want REST endpoints to list and inspect held messages.
Acceptance Criteria:
-
GET /compliance/hold-queuewith pagination, filtering -
GET /compliance/hold-queue/:holdIdreturns full record - Role-based body redaction (body visible only to
platform.compliance.admin) - JWT validation + RBAC enforcement
Story Points: 3 · Priority: High
US-CE-016 — Review action (RELEASE / REJECT) with message re-injection
As a compliance reviewer, I want to release or reject held messages.
Acceptance Criteria:
-
POST /compliance/hold-queue/:holdId/reviewwithaction: RELEASE | REJECT - RELEASE: publishes
sms.outbound.retrywithskipCompliance: true; sms-orchestrator routes without re-evaluation - REJECT: status → REVIEWED_REJECTED; sms_messages → BLOCKED (terminal)
- Audit log entry with before/after, actor, IP, UA
- Optimistic lock prevents double-review
- NATS
compliance.message.released/rejectedevent published
Story Points: 5 · Priority: High
US-CE-017 — Hold queue auto-expiry background worker
As a platform SRE, I want held messages past TTL auto-expired so the queue cannot grow unbounded.
Acceptance Criteria:
- Cron runs every 5 min with Redis distributed lock
- Selects PENDING holds where
auto_expires_at <= now() - Updates status to AUTO_EXPIRED
- sms_messages state → AUTO_EXPIRED (terminal)
- Publishes
compliance.message.expiredNATS event (notification-service alerts tenant) - Writes audit log entry
- Emits metric
Story Points: 2 · Priority: Medium
US-CE-018 — Bulk-review endpoint for platform admins
As a platform admin, I want to bulk-reject held messages filtered by tenant/rule so I can clear the queue during mass-abuse incidents.
Acceptance Criteria:
-
POST /compliance/hold-queue/bulk-reviewwith filter + action - Hard limit 10,000 rows per call
- Single audit log entry summarising bulk action
- Role gated to
platform.compliance.admin
Story Points: 3 · Priority: Medium
EP-CE-04: Compliance Layer — Rule & Blocklist Management API
Description: CRUD APIs for platform admins to author rules, manage rule sets, and maintain blocklists/keyword lists.
US-CE-019 — Rule CRUD endpoints with versioning
As a compliance admin, I want to create, update, and delete rules via REST.
Acceptance Criteria:
-
POST /compliance/ruleswith schema validation per rule type -
PUT /compliance/rules/:idincrements version, createsrule_versionssnapshot -
DELETE /compliance/rules/:idsoft-delete only - COMPOSITE cycle check at save
- REGEX validation at save (compile + ReDoS screen)
- Redis cache invalidation on change
- NATS
compliance.rule.changedevent published - Audit log entry per action
Story Points: 5 · Priority: High
US-CE-020 — Rule set management and tenant assignment
As a compliance admin, I want to group rules into rule sets and assign to tenants.
Acceptance Criteria:
- Full CRUD on
rule_sets - Exactly one
is_default = truerule set (unique constraint) - Tenant assignment endpoint
- Rule set loading merges tenant-specific + default
Story Points: 3 · Priority: High
US-CE-021 — Blocklist management (sender/recipient/keyword/regex/country)
As a compliance admin, I want to maintain blocklists for various entity types.
Acceptance Criteria:
- CRUD endpoints for
blocklistsandblocklist_entries - Bulk-add endpoint (up to 10,000 entries per call)
- Per-entry TTL support
- Pattern types: EXACT, REGEX, PREFIX, CONTAINS, SUFFIX
- Redis cache for fast lookup at evaluation time
Story Points: 5 · Priority: High
US-CE-022 — Keyword list management with multi-language support
As a compliance admin, I want to manage keyword lists per language and category.
Acceptance Criteria:
- CRUD on
keyword_listsandkeyword_entries - Bulk import/export (CSV/JSON)
- Language field (ISO 639-1)
- Per-entry weight for weighted scoring
- In-process cache reload on change
Story Points: 3 · Priority: High
EP-CE-05: Compliance Layer — Tenant Scoring & Risk Tiering
Description: Continuous tenant compliance scoring, risk tier transitions, enforcement.
US-CE-023 — Tenant scoring background worker
As a platform admin, I want tenant compliance scores computed every 15 min.
Acceptance Criteria:
- Cron runs every 15 min with Redis distributed lock
- Aggregates metrics from
evaluation_log,dlr_stats - Computes 6 score dimensions per DOMAIN_MODEL §5
- Determines risk tier from overall score
- Detects tier transitions; emits
compliance.tenant.tier.changed - Upserts
tenant_compliance_scores; insertsscore_history - Updates Redis
tenant:risk:{tenantId}cache
Story Points: 8 · Priority: High
US-CE-024 — Tenant score REST endpoints
As a platform admin, I want REST endpoints for tenant ranking and score detail.
Acceptance Criteria:
-
GET /compliance/tenantsreturns ranked list -
GET /compliance/tenants/:id/scorereturns detailed breakdown -
GET /compliance/tenants/:id/score/historyreturns time-series -
GET /compliance/tenants/:id/violationsreturns violation log
Story Points: 3 · Priority: Medium
US-CE-025 — Manual tenant tier override endpoint
As a platform admin, I want to manually override a tenant's risk tier.
Acceptance Criteria:
-
POST /compliance/tenants/:id/tier-overridewith tier + reason + optional expiry - Requires
platform.compliance.admin - Writes audit log entry
- Overrides recorded separately from scoring cycle
- NATS event published
Story Points: 3 · Priority: Medium
EP-CE-06: Compliance Layer — Reporting & Audit
US-CE-026 — Compliance report generation
As a platform auditor, I want to generate compliance reports on demand or on schedule.
Acceptance Criteria:
-
POST /compliance/reportswith report type + date range - Async generation with polling endpoint
GET /compliance/reports/:id - Report types: TENANT_RANKING, VIOLATION_SUMMARY, HOLD_QUEUE_SUMMARY, TIER_TRANSITIONS, TOP_TRIGGERED_RULES, TENANT_AUDIT
- Output: JSON, CSV (PDF future)
- Daily scheduled generation at 02:00 UTC
Story Points: 8 · Priority: Medium
US-CE-027 — Audit log query endpoint
As a platform auditor, I want to query the audit log by actor, entity, date range.
Acceptance Criteria:
-
GET /compliance/audit-logwith filters - Cursor-based pagination
- Role-gated to
platform.auditorandplatform.compliance.admin - Read-only
Story Points: 3 · Priority: Medium
EP-CE-07: Compliance Layer — Observability & Production Hardening
US-CE-028 — Complete Prometheus metrics instrumentation
As a platform engineer, I want all metrics from OBSERVABILITY.md emitting correctly.
Acceptance Criteria:
- All 30+ metrics registered and emitting
- Histogram buckets match the observability spec
- Grafana dashboard
compliance-engine.jsoncommitted - Verified in staging Prometheus scrape
Story Points: 5 · Priority: High
US-CE-029 — Structured JSON logging with PII masking
As a security engineer, I want all logs structured JSON with PII masked.
Acceptance Criteria:
- All log output valid JSON (Pino)
-
tomasked as+CCNNN*** - Body never logged
-
traceId+spanIdpropagated from gRPC metadata - Log level via
LOG_LEVELenv
Story Points: 2 · Priority: High
US-CE-030 — OpenTelemetry distributed tracing
As a platform engineer, I want compliance evaluations to produce OTel traces.
Acceptance Criteria:
- Parent span
compliance-engine.EvaluateCompliance - Child spans for cache check, rule load, rules evaluate, AI classify, hold insert
- Trace context via W3C Trace Context
- Traces visible in staging tracing backend
Story Points: 3 · Priority: Medium
US-CE-031 — Alert rules and runbook
As a platform SRE, I want alerts configured for key failure modes with a runbook.
Acceptance Criteria:
- All alerts from OBSERVABILITY.md configured in Alertmanager
- Runbook entry per alert
- Routing configured (Slack + PagerDuty for HIGH/CRITICAL)
- Chaos test: induce each alert, verify paging
Story Points: 3 · Priority: High
US-CE-032 — Kubernetes deployment with HPA and rolling updates
As a platform SRE, I want compliance-engine deployed with 3+ replicas, HPA, zero-downtime rolling updates.
Acceptance Criteria:
- Deployment min 3, HPA scales to 20
- HPA on CPU + P95 latency custom metric
- PodDisruptionBudget minAvailable = 2
- NetworkPolicy restricts ingress/egress
- Graceful shutdown (SIGTERM drains in-flight gRPC calls)
- ghz load test during rolling update — zero dropped calls
Story Points: 3 · Priority: High
EP-CE-08: Compliance Layer — Async Pipeline Integration
Description: Integrate the Compliance Layer into the sms-orchestrator NATS consumer pipeline with fail-closed semantics.
US-CE-033 — sms-orchestrator ComplianceClient gRPC stub
As sms-orchestrator, I want a ComplianceClient module wrapping the Compliance Layer gRPC with retries, timeouts, mTLS.
Acceptance Criteria:
- gRPC stub generated from
compliance.proto - mTLS client certs loaded from mounted secrets
- 1 s deadline per call
- Structured logging of all calls with correlation IDs
- Metrics: call duration, error rate
Story Points: 3 · Priority: High
US-CE-034 — sms-orchestrator NATS consumer compliance integration
As sms-orchestrator, I want the NATS consumer to call the Compliance Layer between dequeue and routing.
Acceptance Criteria:
- Consumer updates message to
EVALUATINGbefore compliance call - On
ALLOW/FLAG: proceed to routing - On
BLOCK: update toBLOCKED; do not route - On
HOLD: update toON_HOLDwithholdId; do not route - Fail-closed: on error/timeout, message is NOT acked; NATS redelivers
- After max redeliveries, message moves to
sms.outbound.deadletter - New
sms_messagesstatus values: EVALUATING, BLOCKED, ON_HOLD, AUTO_EXPIRED - Integration tests cover all four verdicts and fail-closed path
Story Points: 8 · Priority: High
US-CE-035 — sms-orchestrator release flow (skipCompliance flag)
As sms-orchestrator, I want to handle re-published released messages without re-evaluating compliance.
Acceptance Criteria:
-
sms.outbound.retrymessages withskipCompliance: truebypass compliance - Routing proceeds directly
-
complianceOverriderecorded in message metadata and audit trail - Prevents release → re-hold loop
Story Points: 3 · Priority: High
US-CE-036 — billing-service integration with compliance verdicts
As billing-service, I want to skip billing for blocked/rejected messages and defer billing for held messages.
Acceptance Criteria:
- Consumes
compliance.message.blocked— emitsbilling.waivefor messageId - Consumes
compliance.message.rejected— same as above - Consumes
compliance.message.expired— same as above - Consumes
compliance.message.released— bills normally on subsequent DLR - Idempotent handling
Story Points: 5 · Priority: Medium
US-CE-037 — Phase 1 observation-mode rollout
As a platform engineer, I want the initial production rollout to use observation-only rules so that we validate the layer without affecting traffic.
Acceptance Criteria:
- Seed rule set configured with all rules
action=FLAG - 7-day observation window executed in production
- Trust & Safety signs off on rule-tuning report
- Exit criteria (P95 latency, error rate, consumer lag) met
Story Points: 2 · Priority: High
EP-CE-09: Compliance Layer — Local LLM Platform
Description: Provision and operate the self-hosted local LLM service that powers AI_CLASSIFICATION rules.
US-CE-038 — Deploy local LLM service with vLLM + Llama-3.1-8B-AWQ
As a platform engineer, I want a self-hosted LLM service deployed on GPU nodes with an OpenAI-compatible API.
Acceptance Criteria:
- vLLM deployment manifest with GPU node selector
- Model: Llama-3.1-8B-Instruct-AWQ (or equivalent)
- OpenAI-compatible API on port 8000
- 2 replicas minimum with PDB minAvailable = 1
- Liveness/readiness probes
- Service reachable from compliance-engine pods only (NetworkPolicy)
Story Points: 5 · Priority: High
US-CE-039 — Provider abstraction for LLMs (local + external failover)
As a compliance engineer, I want a provider-abstracted LLM client so the Compliance Layer can swap between local and external LLMs.
Acceptance Criteria:
-
LLMClientinterface -
LocalLLMClient,ClaudeClient,OpenAIClient,MockClientimplementations -
LLMRouterwith primary + failover chain based on env config - Circuit breaker per provider
- Grammar-constrained decoding for local LLM (guaranteed JSON output)
- Unit tests per client + router
Story Points: 5 · Priority: High
US-CE-040 — Local LLM cost and performance monitoring
As a platform engineer, I want metrics and dashboards for local LLM operations.
Acceptance Criteria:
- GPU utilisation exported via DCGM exporter
- LLM request/response latency histogram
- Cache hit rate gauge (from compliance-engine side)
- Token throughput metric
- Grafana dashboard
local-llm.json
Story Points: 3 · Priority: Medium
US-CE-041 — Classification accuracy evaluation harness
As a trust & safety engineer, I want an evaluation harness to measure classification accuracy against a labelled SMS dataset.
Acceptance Criteria:
- Curated labelled dataset of ~1000 SMS bodies per category
- Eval script computes precision, recall, F1 per category
- Results stored and comparable across model versions
- Quarterly re-run scheduled
- Alert if any category precision drops > 5 pts month-over-month
Story Points: 8 · Priority: Medium
EP-CE-10: Compliance Layer — Tenant-Facing Web Portal Integration
Description: Surface compliance state to tenants via the customer web portal so they can see holds, blocks, and compliance status without relying on synchronous API responses.
US-CE-042 — Display message states BLOCKED / ON_HOLD / AUTO_EXPIRED in portal
As a tenant, I want to see which of my messages were blocked, held, or expired so I know why they were not delivered.
Acceptance Criteria:
- Message list in portal shows new states
- Filter by compliance state
- Per-message detail view shows triggered rule(s) and rationale
-
payload.bodynot revealed — only redacted summary - State changes update in near-real-time via WebSocket or polling
Story Points: 5 · Priority: High
US-CE-043 — In-portal notifications for compliance events
As a tenant, I want to receive notifications when my messages are held, blocked, or my tenant tier changes.
Acceptance Criteria:
-
notification-serviceconsumescompliance.message.*andcompliance.tenant.tier.changedevents - Notification delivered to portal notification centre
- Optional email notification (configurable per tenant)
- Notification links to affected message / tenant settings
Story Points: 5 · Priority: High
US-CE-044 — Tenant-visible compliance score and tier
As a tenant admin, I want to see my compliance score and risk tier so I understand my standing on the platform.
Acceptance Criteria:
-
GET /portal/compliance/score(tenant-scoped) returns own score + tier - Score history chart (last 30 days)
- Explanation of tier implications (e.g. "RESTRICTED: bulk sends > 500/hr are held")
- Guidance copy: "How to improve your score"
Story Points: 3 · Priority: Medium
US-CE-045 — Appeal / dispute submission for blocked or held messages
As a tenant, I want to appeal a block/hold decision so I can request human review of a disputed case.
Acceptance Criteria:
- Appeal button on blocked/held message detail view
- Appeal form captures reason and context
- Appeal creates a support ticket tagged
compliance-appeal - Platform compliance team SLA: initial response within 1 business day
- Tenant sees appeal status in portal
Story Points: 3 · Priority: Medium
EP-CE-11 · National Default Rule-Sets (regulator-required)
Context: ATRA and the broader Afghan regulatory environment require certain rules apply to every tenant by default (no opt-out): national keyword blocklist, marketing quiet windows (e.g., 22:00–06:00 Asia/Kabul), restricted sender-IDs, and certain temporal restrictions during religious or national observances. These must ship as a
national_defaultsrule-set that is non-disable-able and version-controlled.
US-CE-046 · National default rule-set (non-disable-able)
Type: Feature | Points: 5
Description:
As a compliance officer, I need a national_defaults rule-set that is automatically merged into every tenant's evaluation context with non_disable=true so that no tenant can bypass national rules even via admin override.
Acceptance Criteria:
- Rule-set
national_defaultsseeded at first migration; version-tracked - Cannot be soft-deleted; cannot be excluded from any tenant assignment
- Admin UI shows rules read-only with "Cannot disable — national mandate"
- Schema field
compliance.rule_sets.is_national_defaultboolean enforces single national-default row
US-CE-047 · National keyword blocklist (Pashto/Dari/English)
Type: Feature | Points: 5
Description: As a compliance officer, I need a curated national-keyword blocklist covering hate speech, anti-state content, weapons trafficking terms, and known scam keywords across Pashto, Dari, and English so that the platform is regulator-defensible.
Acceptance Criteria:
- Initial seed: ≥ 200 keywords per language, classified by category (HATE, EXTREMISM, WEAPONS, FRAUD)
- Per-keyword: language, category, severity (BLOCK/HOLD/FLAG), regulator reference (ATRA letter ID)
- Updates require dual-control approval (compliance lead + legal)
- Quarterly review cron creates ticket for compliance team
US-CE-048 · Marketing quiet windows (national time-of-day rules)
Type: Feature | Points: 3
Description: As a compliance officer, I need national TEMPORAL rules that block lane=P3 marketing traffic during 22:00–06:00 Asia/Kabul on standard days, plus configurable extra quiet windows for religious/national days.
Acceptance Criteria:
- TEMPORAL rule pre-loaded; lane=P3 only; timezone Asia/Kabul
-
compliance.national_calendartable for special days (Ramadan night quiet, Independence Day, etc.) - Calendar maintained yearly by compliance team
- Verdict for matching messages: HOLD with auto-release at next allowed window
US-CE-049 · Restricted-sender-ID enforcement
Type: Feature | Points: 3
Description: As a compliance officer, I need a SENDER_ID rule that blocks any message using sender-IDs from the national restricted list (impersonation of government, banks, MNOs).
Acceptance Criteria:
- Rule consumes
sender-id-registry-servicerestricted-set (cached 5 min) - Verdict: BLOCK with reason
RESTRICTED_SENDER_ID - Tenant can request exception (KYC + regulator letter required) via sender-id-registry workflow
- Audit log entry includes restricted sender-ID category
US-CE-050 · National rule-set version control + change broadcast
Type: Feature | Points: 3
Description: As an auditor, I need the national rule-set versioned with regulatory references so I can answer "what rules were in force on date X".
Acceptance Criteria:
- Each rule-set version stored in
compliance.rule_set_versionswith snapshot, regulator ref, effective date - On change,
compliance.national_rules.changed.v1event published; consumed bynotification-serviceto email all tenants - Audit query: "rules in effect at timestamp T" returns the snapshot
EP-CE-12 · External-LLM Hard Default-Off + Per-Tenant Opt-In with DPIA Acknowledgement
Context: Per ADR-0004 and SCT-001, sending message bodies to external LLMs (cloud APIs) for AI classification is a sovereignty/PII risk. Default behaviour must be on-prem-only; external LLM is opt-in per tenant with explicit DPIA acknowledgement.
US-CE-051 · External LLM default-off enforcement
Type: Feature | Points: 3
Description:
As a security engineer, I need the AI classification provider to default to local for every tenant; external LLM access requires explicit feature flag + tenant opt-in.
Acceptance Criteria:
- Default
AI_PROVIDER=localcannot be overridden by env alone - Per-tenant
compliance.tenant_ai_config.allow_external_llm = falsedefault - Local LLM unavailable → fail-closed HOLD (do NOT silently fail-over to external)
- Migration: existing tenants set to
falseregardless of prior config
US-CE-052 · Per-tenant DPIA acknowledgement and opt-in
Type: Feature | Points: 5
Description: As a tenant admin, I want to opt-in to external LLM classification only after acknowledging a DPIA (Data Protection Impact Assessment) document.
Acceptance Criteria:
- Customer-portal page
/compliance/ai-providersshows current provider + DPIA toggle - Toggle to
externalrequires uploading signed DPIA acknowledgement PDF (template provided) - Audit event
compliance.tenant_ai.optin.v1includes signer, IP, timestamp, DPIA hash - Opt-in expires after 12 months; renewal required
US-CE-053 · External LLM call audit and PII tokenisation
Type: Feature | Points: 5
Description: Every external LLM call must be audit-logged with the (tokenised) payload sent, model used, and latency. PII must be tokenised before transmission.
Acceptance Criteria:
- Pre-send: PII fields tokenised via FF1 (HSM-held key);
to, sender names replaced with stable tokens - Audit row in
compliance.external_llm_auditwith model, tokenised body, latency, verdict - Daily report to compliance team summarising volume per tenant, per model
- Alert if any PII detected in outbound payload (regex check) → emergency disable + page security
EP-CE-13 · Trusted-Tenant Template Approval Workflow
Context: Pairs with
EP-PLAT-NB-08(trusted-tenant fast-path) andEP-ORCH-07. Trusted tenants pre-register templates; compliance reviewers approve them once; orchestrator then verifies fingerprint at submit and short-circuits compliance.
US-CE-054 · Template registration API
Type: Feature | Points: 5
Description: As a trusted tenant admin, I need to register a template with a fingerprint pattern and variable schema.
Acceptance Criteria:
-
POST /v1/compliance/templatesaccepts{ name, body, variableSchema, lane } - System computes
fingerprint_pattern(regex with variable spans masked) - Stores in
compliance.approved_templateswith statusPENDING - Cannot be used by orchestrator until status =
APPROVED
US-CE-055 · Template approval workflow (compliance reviewer)
Type: Feature | Points: 5
Description: A compliance reviewer must approve, reject, or request-info on a template before it becomes usable.
Acceptance Criteria:
- Admin UI lists pending templates per tenant with risk score (rule-engine pre-evaluates a sample render)
- APPROVE / REJECT / REQUEST_INFO actions; reason mandatory
- APPROVED → emit
compliance.template.approved.v1; orchestrator can use it - Approval expires after 12 months; re-approval required
US-CE-056 · Template tenant grant (multi-tenant template sharing)
Type: Feature | Points: 3
Description: A platform-owned template (e.g., government emergency template) can be granted to multiple tenants without per-tenant re-approval.
Acceptance Criteria:
-
compliance.template_tenant_grants(templateId, tenantId, grantedBy, expiresAt) - Grant requires platform-admin role
- Revocation propagates to orchestrator within 30 s
US-CE-057 · Template drift monitoring (1-in-1000 sample)
Type: Feature | Points: 3
Description: 1-in-1000 fast-path messages are re-evaluated in blocking mode; if verdict ≠ ALLOW, alert fires and template is auto-suspended.
Acceptance Criteria:
- Sampling deterministic (hash of messageId mod 1000 == 0)
- Drift verdict logged in
compliance.template_drift_audit - If drift rate > 0.5% over 1h → template auto-suspended; tenant notified
- Alert
ComplianceFastpathDriftpaged to T&S team