ADR-066: Compliance Patterns for Pattern Providers
Status
Status: Proposed Created: 2026-04-19 Updated: 2026-04-19 Author: Jacob Repp Deciders: Core Team
Context
Compliance Requirements from Security Plan
As outlined in docs-cms/plans/security.md (lines 179-216), Prism requires compliance patterns for pattern providers:
-
Right to Deletion (GDPR) — Implement data deletion patterns
- Remove user data from all backing stores
- Log deletion event for audit
- Provide deletion confirmation
-
Data Residency — Control data location
- Geographic routing for namespace assignments
- Cross-region replication policies
- Data sovereignty requirements
-
Retention Policy — Automatic data expiration
- TTL enforcement on all stored data
- Soft-delete with configurable retention
- Hard-delete after retention period
Current security plan (P2 priority) indicates: "Pattern Provider implementation required" for compliance features.
Current State
- Pattern providers implement
Plugininterface (lifecycle management) - Backend drivers implement specific data interfaces (KeyValueBasicInterface, PubSubBasicInterface, etc.)
- No standardized compliance interface exists
- Compliance functionality is ad-hoc or missing
What This ADR Solves
This ADR proposes a uniform compliance interface that pattern providers can implement to support:
- GDPR right to deletion
- Data residency controls
- Automatic retention/enforcement
Pattern providers should be able to:
- Mark user-identifiable data for deletion
- Enforce retention policies automatically
- Support geographic routing for data residency
Decision
1. Create CompliantBackend Trait Interface
Introduce CompliantBackend as an optional interface extension that pattern providers can implement:
// pkg/plugin/compliance_interfaces.go
type CompliantBackend interface {
// Retain Plugin interface for lifecycle compatibility
Plugin
// DeleteUserData removes all user-identifiable data
// Returns count of deleted items and audit log entry
DeleteUserData(ctx context.Context, userID string, policy RetentionPolicy) (DeletedItems, AuditLogEntry, error)
// EnforceRetention applies retention policies to data
// Returns batch of enforced items and any errors
EnforceRetention(ctx context.Context, namespace string, policy RetentionPolicy) (EnforcedItems, []error, error)
// GetDataResidency returns geographic location of data
// Used for compliance validation and routing
GetDataResidency(ctx context.Context, key string) (string, error)
// SetDataResidency marks data with geographic location
// Used for residency enforcement
SetDataResidency(ctx context.Context, key string, region string) error
}
2. Define RetentionPolicy DSL
Create a structured policy type for compliance operations:
type RetentionPolicy struct {
softDelete bool
retentionPeriod time.Duration
hardDeleteAfter time.Duration
auditEnabled bool
regions []string // Geographic restrictions
}
3. Generic Compliance Service
Build a service layer that pattern providers can use:
// pkg/plugin/compliance_service.go
type ComplianceService struct {
backend CompliantBackend
logger *slog.Logger
}
func (cs *ComplianceService) DeleteUserData(ctx context.Context, userID string, policy RetentionPolicy) error
func (cs *ComplianceService) EnforceRetention(ctx context.Context, namespace string, policy RetentionPolicy) error
func (cs *ComplianceService) AuditLog(ctx context.Context, event AuditEvent) error
4. Pattern Provider Implementation
Pattern providers that use compliant backends should:
- Implement
CompliantBackendinterface (or embed it) - Use
ComplianceServicefor common operations - Register compliance capabilities in interface declarations
Example for patterns/keyvalue:
type KeyValue struct {
driver CompliantBackend // Optional: use type assertion if not all backends support compliance
compliance *ComplianceService
}
func (kv *KeyValue) DeleteUserData(ctx context.Context, userID string, policy RetentionPolicy) (DeletedItems, AuditLogEntry, error) {
// Use driver's compliance implementation or fallback
if compliant, ok := kv.driver.(CompliantBackend); ok {
return compliant.DeleteUserData(ctx, userID, policy)
}
// Fallback: implement deletion for this pattern
return kv.compliance.DeleteUserData(ctx, userID, policy)
}
5. Backend Driver Implementations
Backend drivers implement the compliance trait:
// pkg/drivers/memstore/memstore.go
func (m *MemStore) DeleteUserData(ctx context.Context, userID string, policy RetentionPolicy) (DeletedItems, AuditLogEntry, error) {
var deleted DeletedItems
var entries []string
// Scan for user-related keys
m.data.Range(func(key, value interface{}) bool {
keyStr := key.(string)
if strings.Contains(keyStr, userID) {
m.data.Delete(key)
deleted.Count++
deleted.Keys = append(deleted.Keys, keyStr)
entries = append(entries, fmt.Sprintf("Deleted: %s", keyStr))
}
return true
})
audit := AuditLogEntry{
Event: "user_deletion",
UserID: userID,
Policy: policy,
Entries: entries,
Timestamp: time.Now(),
}
return deleted, audit, nil
}
Rationale
Why This Approach?
Benefits:
- Opt-in: Pattern providers can implement compliance only where needed
- Testable: Real backend verification (no mocks)
- Consistent: Single interface for all compliance operations
- Extendable: New compliance features added as interface methods
- Backward compatible: Existing patterns work unchanged
Trade-offs:
- Complexity: Additional interfaces to understand
- Mitigation: Clear documentation, minimal required methods
- Performance: Compliance operations may be expensive
- Mitigation: Async options, bulk operations, context timeouts
- Backend Variance: Not all backends support all compliance features
- Mitigation: Optional interface, fallback implementations, clear error messages
Alternatives Considered
Alternative 1: Separate Services
- Create
UserService(deletion),RetentionService,ResidencyServiceseparately - Rejected: Creates fragmentation, duplicate logic across services
Alternative 2: Middleware Pattern
- Wrap all operations with compliance middleware
- Rejected: Too complex for pattern providers, harder to test
Alternative 3: Embedded in Plugin Interface
- Add compliance methods to core
Plugininterface - Rejected: Breaks backward compatibility, forces compliance on all plugins
Consequences
Positive
- GDPR Compliance: Pattern providers can implement user deletion
- Audit Trail: Standardized audit logging for compliance
- Data Residency: Geographic controls built into architecture
- Retention Automation: Automatic enforcement reduces manual work
- Pattern Provider Flexibility: Implement only what's needed
Negative
- Implementation Effort: Pattern providers must add compliance support
- Testing Complexity: Real backend compliance testing required
- Performance Overhead: Compliance operations may slow data access
Neutral
- Documentation Burden: Needs comprehensive docs for pattern provider adoption
- Migration Path: Existing patterns require gradual adoption
Implementation Plan
Phase 1: interfaces + ADR (pkg/plugin/)
- Create
pkg/plugin/compliance_interfaces.go - Create
pkg/plugin/compliance_service.go - Update
pkg/plugin/plugin.goto reference compliance interfaces - Add tests with 80%+ coverage target
Phase 2: Pattern Provider Support
- Update
patterns/keyvalue/keyvalue.goto supportCompliantBackend - Update
patterns/producer/producer.gofor audit logging - Update
patterns/consumer/consumer.gofor retention enforcement
Phase 3: Backend Driver Implementations
- Update
pkg/drivers/memstore/memstore.go - Update
pkg/drivers/redis/redis.go - Update
pkg/drivers/postgres/postgres.go(if applicable)
Phase 4: Documentation
- Add
docs-cms/guides/compliance-patterns.md - Update
docusaurus/docs/compliance section - Add changelog entry
Phase 5: Security Plan Update
- Update
docs-cms/plans/security.mdcompliance section - Mark patterns as "In Progress" or "Completed"
- Add implementation status table
Testing Strategy
Test Coverage (80%+ target)
- Unit tests for
ComplianceServicemethods - Integration tests with real backends (MemStore, Redis)
- Compliance scenario tests (GDPR deletion, retention enforcement)
- Error handling tests (backend compatibility, fallbacks)
Test Commands
# Run compliance tests
task test-compliance
# Test memstore compliance
task test-compliance-memstore
# Test redis compliance
task test-compliance-redis
# Coverage
go test ./pkg/plugin/... -coverprofile=coverage.out
go tool cover -func=coverage.out
Verification Checklist
Before submitting PR:
-
pkg/plugin/compliance_interfaces.gocreated withCompliantBackend -
pkg/plugin/compliance_service.goimplemented - Tests pass with 80%+ coverage (
go test ./pkg/plugin/... -cover) - Pattern providers updated to support compliance
- Backend drivers implement compliance trait
- Documentation added:
-
docs-cms/guides/compliance-patterns.md -
docusaurus/docs/updated -
docusaurus/docs/changelog.mdupdated
-
- Security plan (
docs-cms/plans/security.md) updated -
uv run tooling/validate_docs.pypasses
Related Documents
docs-cms/plans/security.md(lines 179-216)- ADR-005: Backend Plugin Architecture
- RFC-033: Consumer Pattern
- RFC-031: Message Envelope Protocol
Revision History
- 2026-04-19: Initial draft (Jacob Repp)
- 2026-04-19: ADR-066 created for compliance patterns
- 2026-04-19: Proposed pattern for
CompliantBackendinterface