Skip to Content
InternalDocsArchitectureCre Rule Hierarchy

Cre Rule Hierarchy

Source: docs/architecture/cre-rule-hierarchy.md

# Compliance Rules Engine (CRE) - Rule Hierarchy Design **Source:** `_archived/services/compliance-rules-engine/README.md` **Status:** Design reference for monolith integration **Target Location:** `packages/rules-engine/` --- ## Overview The CRE defines a 6-level hierarchical rule cascade for compliance validation. This design should be adopted into `packages/rules-engine/` rather than rebuilt from scratch. --- ## Hierarchy Levels Rules cascade from general to specific. Child rules **accumulate** parent requirements (never remove them). ``` Level 0: Global (*) ↓ Level 1: Regional (EU, USMCA, ASEAN) ↓ Level 2: Country (CA, US, UK) ↓ Level 3: Province/State (ON, US-CA, TX) ↓ Level 4: Municipality (Toronto, LA) ↓ Level 5: Product Type (alcohol, dangerous_goods) ``` ### Example Cascade For a wine import to Ontario, Canada: 1. **Global** - Basic HS code format validation 2. **Regional** - (none for this case) 3. **Country (CA)** - GST required, CBSA documentation 4. **Province (ON)** - HST rate validation, LCBO requirements 5. **Municipality** - (none for this case) 6. **Product (alcohol)** - Excise license, age verification, ABV limits --- ## Rule Merging Logic 1. Rules applied in hierarchical order (global → specific) 2. Child rules **accumulate** requirements from parents 3. Child rules can **override** parent validations with `override: true` flag 4. Conflicts resolved by **severity** (error > warning > info) 5. Compiled rulesets cached for performance ### Conflict Resolution When the same field has conflicting validations: | Scenario | Resolution | |----------|------------| | Parent: warning, Child: error | Child wins (higher severity) | | Parent: required, Child: optional | Parent wins (accumulation) | | Parent: range 0-100, Child: range 10-50 | Child wins (more specific) with `override: true` | --- ## Rule Schema From the archived CRE design: ```typescript interface ComplianceRule { id: string // UUID rule_id: string // Human-readable ID (e.g., "ca-on-001") version: string // Semantic version level: HierarchyLevel // global, regional, country, province, municipality, product applies_to: { countries: string[] // ISO 3166-1 alpha-2 regions: string[] // EU, USMCA, ASEAN, etc. provinces: string[] // ISO 3166-2 subdivision municipalities: string[] // City names product_categories: string[] // alcohol, dangerous_goods, etc. } requirements: { fields: string[] // Required fields for this rule conditions: string[] // Preconditions (e.g., "gst_rate > 0") } validations: Validation[] // List of validation checks override: boolean // If true, can override parent rules description: string metadata: Record<string, unknown> effective_date: Date // When rule becomes active expiry_date?: Date // When rule expires (null = no expiry) created_at: Date updated_at: Date } // Consistency rule: // - `level` must match the most specific populated field in `applies_to`. // - Reject mismatches (e.g., level=country while provinces[] is populated). type HierarchyLevel = | 'global' | 'regional' | 'country' | 'province' | 'municipality' | 'product' ``` --- ## Validation Types The CRE supports four validation types: ### 1. Presence Field must be present and non-empty. ```json { "field": "sku", "type": "presence", "rule": "presence", "message": "SKU is required", "severity": "error" } ``` ### 2. Format Field must match regex pattern. ```json { "field": "hs_code", "type": "format", "rule": "^[0-9]{4}\\.[0-9]{2}\\.[0-9]{2}\\.[0-9]{2}$", "message": "HS code must be in format XXXX.XX.XX.XX", "severity": "error" } ``` ### 3. Range Field must be within numeric range. ```json { "field": "declared_value", "type": "range", "rule": "value > 0", "message": "Declared value must be positive", "severity": "error" } ``` ### 4. Custom Extensible validation functions. ```json { "field": "license_number", "type": "custom", "rule": "check_license_validity(license_number)", "message": "Invalid license", "severity": "error" } ``` --- ## Validation Interface ```typescript interface Validation { field: string type: 'presence' | 'format' | 'range' | 'custom' rule: string // Regex, expression, or function name message: string // Human-readable error message severity: 'error' | 'warning' | 'info' } interface ValidationResult { validation_id: string passed: boolean rules_applied: string[] // List of rule_ids that were evaluated violations: Violation[] execution_time_ms: number timestamp: Date correlation_id?: string } interface Violation { rule_id: string field: string severity: 'error' | 'warning' | 'info' message: string actual_value?: unknown expected?: string } ``` --- ## Caching Strategy The CRE uses Redis for compiled ruleset caching: ``` Cache key: rules:compiled:{region}:{country}:{province}:{product_category} Examples: - rules:compiled:USMCA:CA:ON:alcohol → Rules for alcohol in Ontario, Canada within USMCA context - rules:compiled::US:: → Rules for US (all products, no region) - rules:compiled::: → Global rules only ``` **TTL:** 1 hour (3600 seconds) **Invalidation:** On rule changes or `regulation.changed` events --- ## Integration with Detector Registry The CRE validation types map to detector patterns: | CRE Validation | Detector Pattern | |----------------|------------------| | Presence | Required field check in detector | | Format | Input validation before detection | | Range | Threshold-based detection (e.g., variance > X) | | Custom | Detector-specific logic | ### Proposed Integration ```typescript // In packages/rules-engine/src/hierarchy.ts export function compileRulesForContext(context: { country: string province?: string productCategory?: string }): CompiledRuleset { // 1. Load rules from DB ordered by hierarchy level // 2. Merge rules (child accumulates parent) // 3. Resolve conflicts by severity // 4. Return compiled ruleset } // In apps/api/src/lib/ship/detectors/ export class AmountVarianceDetector implements Detector { async detect(input, context, config) { // Load rules for this context const rules = await compileRulesForContext({ country: input.destinationCountry, productCategory: 'parcel' }) // Apply rules to detection logic // ... } } ``` --- ## Migration Path ### Phase 1.5: Adopt CRE Hierarchy 1. Add `level` and `applies_to` fields to `RuleDefinition` table 2. Implement `compileRulesForContext()` in `packages/rules-engine/` 3. Add Redis caching for compiled rulesets 4. Update detectors to load rules from hierarchy ### Schema Addition ```prisma model RuleDefinition { // ... existing fields level HierarchyLevel appliesTo Json // { countries: [], regions: [], provinces: [], ... } requirements Json // { fields: [], conditions: [] } validations Json // Array of Validation objects override Boolean @default(false) effectiveDate DateTime? expiryDate DateTime? } enum HierarchyLevel { global regional country province municipality product } ``` --- ## References - **Source design:** `_archived/services/compliance-rules-engine/README.md` - **Current rules engine:** `packages/rules-engine/` - **Data foundation strategy:** `docs/proposals/data-foundation-strategy.md`