# Exception Effect Registry (Type-to-Effect Mapping) ## Module Policy ## Status IMPLEMENTED ## Description Registry mapping (ExceptionType + ExceptionReason) pairs to policy effects (Suppress, Defer, RequireControl). Covers 11 predefined mappings including false_positive, wont_fix, vendor_pending, compensating_control, license_waiver, etc. Extensible via DI configuration with max-duration constraints. ## Implementation Details - **ExceptionEffectRegistry**: `src/Policy/StellaOps.Policy.Engine/Adapters/ExceptionEffectRegistry.cs` (sealed class implements `IExceptionEffectRegistry`) - Uses `FrozenDictionary<(ExceptionType, ExceptionReason), PolicyExceptionEffect>` for immutable O(1) lookups - `GetEffect(type, reason)` returns effect for type+reason pair; falls back to `defer-default` effect if unmapped - `GetAllEffects()` returns all registered effects - `GetEffectById(effectId)` returns effect by ID (case-insensitive lookup) - 8 distinct effect templates: suppress, defer, require-control, downgrade-low, downgrade-medium, defer-vendor, suppress-deprecation, suppress-license - 40 total mappings across 4 ExceptionTypes (Vulnerability, Policy, Unknown, Component) x 10 ExceptionReasons - `PolicyExceptionEffectType` enum: Suppress, Defer, Downgrade, RequireControl - MaxDurationDays per effect: suppress=365, defer=90, require-control=180, downgrade=365, defer-vendor=180, suppress-deprecation=90, suppress-license=365, defer-default=30 - RoutingTemplate per effect for workflow routing (e.g., "deferred-review", "control-verification", "vendor-tracking", "legal-review", "manual-review") - **ExceptionType enum**: `src/Policy/__Libraries/StellaOps.Policy.Exceptions/Models/ExceptionObject.cs` - Vulnerability, Policy, Unknown, Component - **ExceptionReason enum**: same file - FalsePositive, AcceptedRisk, CompensatingControl, TestOnly, VendorNotAffected, ScheduledFix, DeprecationInProgress, RuntimeMitigation, NetworkIsolation, Other ## E2E Test Plan - [ ] `GetEffect(Vulnerability, FalsePositive)` returns effect with Id="suppress", Effect=Suppress, MaxDurationDays=365 - [ ] `GetEffect(Vulnerability, CompensatingControl)` returns effect with Id="require-control", Effect=RequireControl, RequiredControlId="compensating-control-verification" - [ ] `GetEffect(Vulnerability, RuntimeMitigation)` returns effect with Id="downgrade-low", Effect=Downgrade, DowngradeSeverity=Low - [ ] `GetEffect(Vulnerability, NetworkIsolation)` returns effect with Id="downgrade-medium", DowngradeSeverity=Medium - [ ] `GetEffect(Vulnerability, ScheduledFix)` returns effect with Id="defer", Effect=Defer, MaxDurationDays=90 - [ ] `GetEffect(Component, DeprecationInProgress)` returns effect with Id="suppress-deprecation", MaxDurationDays=90 - [ ] `GetEffect(Component, Other)` returns effect with Id="suppress-license", RoutingTemplate="legal-review" - [ ] `GetEffect(Vulnerability, VendorNotAffected)` returns effect with Id="suppress" - [ ] `GetEffectById("require-control")` returns non-null effect with matching ID - [ ] `GetAllEffects()` returns exactly 8 distinct effects (suppress, defer, require-control, downgrade-low, downgrade-medium, defer-vendor, suppress-deprecation, suppress-license) - [ ] Unmapped type/reason pair (if any) returns defer-default with MaxDurationDays=30, RoutingTemplate="manual-review"