# Exception Approval Workflow ## Overview The Exception Approval Workflow describes how StellaOps handles policy exception requests, from initial submission through multi-level approval, time-limited grants, and expiration tracking. This flow ensures exceptions are documented, justified, and automatically expire. **Business Value**: Maintain security governance while allowing controlled exceptions for legitimate business needs, with full audit trail and automatic expiration. ## Actors | Actor | Type | Role | |-------|------|------| | Developer | Human | Requests exception | | Team Lead | Human | First-level approval | | Security Team | Human | Security review and approval | | CISO | Human | Final approval (high severity) | | Policy Engine | Service | Enforces exception | | Scheduler | Service | Tracks expiration | | Notify | Service | Sends alerts | ## Prerequisites - Policy violation detected - Exception workflow configured - Approval chain defined - Notification channels configured ## Exception Types | Type | Description | Max Duration | Approval Level | |------|-------------|--------------|----------------| | Temporary | Time-limited deferral | 30 days | Team Lead | | Extended | Business justification | 90 days | Security Team | | Permanent | Architectural constraint | Indefinite | CISO | | Emergency | Incident response | 7 days | Security Team | ## Flow Diagram ``` ┌─────────────────────────────────────────────────────────────────────────────────┐ │ Exception Approval Workflow │ └─────────────────────────────────────────────────────────────────────────────────┘ ┌───────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ ┌───────────┐ │ Developer │ │ Team Lead│ │ Security │ │ Policy │ │Scheduler│ │ Notify │ └─────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └───┬────┘ └─────┬─────┘ │ │ │ │ │ │ │ Request │ │ │ │ │ │ exception │ │ │ │ │ │───────────────────────────────────────> │ │ │ │ │ │ │ │ │ │ │ │ Validate │ │ │ │ │ │ request │ │ │ │ │ │───┐ │ │ │ │ │ │ │ │ │ │ │ │ │<──┘ │ │ │ │ │ │ │ │ │ │ │ │ Notify │ │ │ │ │ │ approvers │ │ │ │ │ │──────────────────────────> │ │ │ │ │ │ │ │ Approval │ │ │ │ Send │ │ request │ │ │ │ email │ │<────────────────────────────────────────────────── │ │ │ │ │ │ │ │ Review & │ │ │ │ │ │ approve │ │ │ │ │ │───────────────────────────> │ │ │ │ │ │ │ │ │ │ │ │ [If high │ │ │ │ │ │ severity] │ │ │ │ │ │───────────────────────────> │ │ │ │ │ │ │ │ │ Approval │ │ │ │ │ │ request │ │ │ │ │ │<────────────────────────────────────── │ │ │ │ │ │ │ │ │ Review & │ │ │ │ │ │ approve │ │ │ │ │ │───────────>│ │ │ │ │ │ │ │ │ │ │ │ │ Grant │ │ │ │ │ │ exception │ │ │ │ │ │───┐ │ │ │ │ │ │ │ │ │ │ │ │ │<──┘ │ │ │ │ │ │ │ │ │ │ │ │ Schedule │ │ │ │ │ │ expiration│ │ │ │ │ │──────────>│ │ │ │ │ │ │ │ │ │ │ │ │ Schedule │ │ │ │ │ │ reminders │ │ │ │ │ │───┐ │ │ │ │ │ │ │ │ │ │ │ │ │<──┘ │ │ │ │ │ │ │ │ Exception │ │ │ │ │ │ granted │ │ │ │ │ │<─────────────────────────────────────────────────────────────── │ │ │ │ │ │ │ │ │ │ │[7d before] │ │ │ │ │ │ expiration │ │ │ │ │ │────────────> │ │ │ │ │ │ │ Expiration │ │ │ │ │ Notify │ warning │ │ │ │ │ owner │<────────────────────────────────────────────────────────────── │ │ │ │ │ │ ``` ## Step-by-Step ### 1. Exception Request Developer submits exception request: ```json { "request_id": "exc-req-123", "requester": "developer@acme.com", "created_at": "2024-12-29T10:00:00Z", "finding": { "scan_id": "scan-abc123", "cve": "CVE-2024-1234", "package": "pkg:npm/lodash@4.17.20", "severity": "high", "policy_violation": "no-high-production" }, "exception_type": "temporary", "requested_duration": "30d", "justification": { "business_reason": "Upgrading lodash breaks critical authentication flow. Need time to refactor.", "risk_acceptance": "Vulnerability requires prototype pollution which is not exploitable in our usage pattern.", "mitigation_plan": "WAF rule deployed to block exploitation vectors. Ticket JIRA-1234 tracks fix.", "remediation_deadline": "2025-01-28" }, "scope": { "images": ["docker.io/myorg/auth-service:*"], "environments": ["production"] } } ``` ### 2. Request Validation Policy Engine validates the request: ```json { "validation": { "request_id": "exc-req-123", "valid": true, "checks": [ {"check": "cve_exists", "passed": true}, {"check": "policy_violation_active", "passed": true}, {"check": "requester_authorized", "passed": true}, {"check": "scope_valid", "passed": true}, {"check": "duration_within_limits", "passed": true} ], "required_approvers": [ {"role": "team_lead", "required": true}, {"role": "security_team", "required": true, "reason": "high_severity"} ], "approval_deadline": "2024-12-31T10:00:00Z" } } ``` ### 3. Approval Chain Notification Notify sends approval requests: ```json { "notification": { "type": "exception_approval_request", "recipients": [ {"email": "team-lead@acme.com", "role": "team_lead"}, {"channel": "slack", "target": "#security-approvals"} ], "content": { "request_id": "exc-req-123", "requester": "developer@acme.com", "cve": "CVE-2024-1234", "severity": "high", "justification_summary": "Upgrading breaks auth flow. WAF mitigation in place.", "approval_url": "https://console.stellaops.local/exceptions/exc-req-123/approve" } } } ``` ### 4. First-Level Approval (Team Lead) Team Lead reviews and approves: ```json { "approval": { "request_id": "exc-req-123", "approver": "team-lead@acme.com", "role": "team_lead", "decision": "approved", "approved_at": "2024-12-29T11:00:00Z", "conditions": [ "Must have JIRA ticket for remediation", "Weekly status update required" ], "notes": "Verified WAF rule is active. Approve with conditions." } } ``` ### 5. Security Review (Second Level) Security team reviews high-severity exceptions: ```json { "security_review": { "request_id": "exc-req-123", "reviewer": "security-analyst@acme.com", "role": "security_team", "review_date": "2024-12-29T14:00:00Z", "assessment": { "risk_rating": "medium", "exploitation_likelihood": "low", "mitigation_effectiveness": "high", "recommendation": "approve_with_monitoring" }, "decision": "approved", "conditions": [ "Enable runtime monitoring for auth-service", "Review exception at 15-day mark" ], "approved_duration": "30d" // May reduce requested duration } } ``` ### 6. Exception Grant Policy Engine activates the exception: ```json { "exception": { "exception_id": "exc-456", "request_id": "exc-req-123", "status": "active", "granted_at": "2024-12-29T14:30:00Z", "granted_by": ["team-lead@acme.com", "security-analyst@acme.com"], "finding": { "cve": "CVE-2024-1234", "package": "pkg:npm/lodash@4.17.20" }, "scope": { "images": ["docker.io/myorg/auth-service:*"], "policy_rules": ["no-high-production"] }, "validity": { "starts_at": "2024-12-29T14:30:00Z", "expires_at": "2025-01-28T14:30:00Z", "duration": "30d" }, "conditions": { "require_jira_ticket": true, "weekly_status_update": true, "runtime_monitoring": true, "mid_point_review": "2025-01-13T14:30:00Z" } } } ``` ### 7. Exception Enforcement During policy evaluation, exception is applied: ```yaml # Policy evaluation with exception finding: cve: CVE-2024-1234 package: pkg:npm/lodash@4.17.20 severity: high exception_check: exception_id: exc-456 scope_match: true still_valid: true conditions_met: true verdict: original: FAIL with_exception: PASS reason: "Exception exc-456 active until 2025-01-28" ``` ### 8. Expiration Tracking Scheduler manages exception lifecycle: ```json { "exception_schedule": { "exception_id": "exc-456", "events": [ { "type": "mid_point_review", "scheduled_at": "2025-01-13T14:30:00Z", "notify": ["requester", "approvers"] }, { "type": "expiration_warning", "scheduled_at": "2025-01-21T14:30:00Z", "days_before": 7, "notify": ["requester", "team_lead"] }, { "type": "expiration_final_warning", "scheduled_at": "2025-01-27T14:30:00Z", "days_before": 1, "notify": ["requester", "team_lead", "security_team"] }, { "type": "expiration", "scheduled_at": "2025-01-28T14:30:00Z", "action": "deactivate_exception" } ] } } ``` ### 9. Renewal Request (If Needed) Before expiration, requester can request renewal: ```json { "renewal_request": { "exception_id": "exc-456", "requested_extension": "30d", "reason": "Refactoring taking longer than expected. PR in review.", "progress_update": { "jira_ticket": "JIRA-1234", "status": "In Review", "completion_percentage": 75 }, "new_deadline": "2025-02-27" } } ``` ## Approval Matrix | Severity | Exception Type | Required Approvers | |----------|---------------|-------------------| | Low | Temporary | Team Lead | | Medium | Temporary | Team Lead | | High | Temporary | Team Lead + Security | | Critical | Any | Team Lead + Security + CISO | | Any | Extended | Team Lead + Security | | Any | Permanent | Security + CISO | | Any | Emergency | Security (expedited) | ## Data Contracts ### Exception Request Schema ```typescript interface ExceptionRequest { request_id: string; requester: string; created_at: string; finding: { scan_id: string; cve: string; package: string; severity: 'critical' | 'high' | 'medium' | 'low'; policy_violation: string; }; exception_type: 'temporary' | 'extended' | 'permanent' | 'emergency'; requested_duration?: string; justification: { business_reason: string; risk_acceptance: string; mitigation_plan: string; remediation_deadline?: string; }; scope: { images?: string[]; environments?: string[]; tenants?: string[]; }; } ``` ### Exception Status Schema ```typescript interface Exception { exception_id: string; request_id: string; status: 'pending' | 'approved' | 'rejected' | 'active' | 'expired' | 'revoked'; finding: { cve: string; package: string; }; scope: { images: string[]; policy_rules: string[]; }; validity: { starts_at: string; expires_at: string; duration: string; }; approvals: Array<{ approver: string; role: string; decision: 'approved' | 'rejected'; timestamp: string; conditions?: string[]; notes?: string; }>; audit_trail: AuditEntry[]; } ``` ## Error Handling | Error | Recovery | |-------|----------| | Approval timeout | Escalate to next level or reject | | Approver unavailable | Route to backup approver | | Scope too broad | Request scope refinement | | Missing justification | Request additional details | | Exception conflict | Flag for manual review | ## Observability ### Metrics | Metric | Type | Labels | |--------|------|--------| | `exception_requests_total` | Counter | `type`, `severity` | | `exception_approvals_total` | Counter | `decision`, `approver_role` | | `exception_active_count` | Gauge | `severity` | | `exception_approval_duration_hours` | Histogram | `severity` | | `exception_expiring_7d` | Gauge | - | ### Key Log Events | Event | Level | Fields | |-------|-------|--------| | `exception.requested` | INFO | `request_id`, `cve`, `requester` | | `exception.approved` | INFO | `exception_id`, `approver`, `duration` | | `exception.rejected` | INFO | `request_id`, `approver`, `reason` | | `exception.activated` | INFO | `exception_id`, `scope` | | `exception.expiring` | WARN | `exception_id`, `days_remaining` | | `exception.expired` | INFO | `exception_id` | ## Related Flows - [Policy Evaluation Flow](04-policy-evaluation-flow.md) - Exception enforcement - [Notification Flow](05-notification-flow.md) - Approval notifications - [Multi-Tenant Policy Rollout Flow](14-multi-tenant-policy-rollout-flow.md) - Policy context