feat: human-in-the-loop override approval for blocked promotions#72
Merged
Conversation
Adds an optional approve/deny override gate to the promote-from-quarantine
workflows. When a scanned image fails the CVE threshold and approval is
enabled, a tracking issue is filed and a Slack notification is sent; a
maintainer can /approve or /deny via issue comment (or workflow_dispatch)
to promote the image despite the failing threshold or close it out.
New reusable composite actions:
- notify-slack: post Block Kit status messages to a Slack webhook
- manage-issue: idempotent tracking-issue lifecycle (open/comment/close/get)
with embedded JSON metadata as the source of truth
- verify-approver: enforce minimum repo permission for approvers
Changes:
- attach-scan-report: record com.cssc.scan.override* provenance annotations
- _promote-from-quarantine{,-sbom}.yml: enable_approval input + slack_webhook
secret; file issue + notify Slack on blocked images
- _promote-override.yml (reusable) + promote-override.yml (caller): execute
the maintainer decision
- docs: design doc, workflow-actions, workflow-naming, workflows overview
Closes #65 #66 #67 #68 #69 #70 #71
Part of #64
There was a problem hiding this comment.
Pull request overview
Adds an optional human-in-the-loop approval/deny override path for promote-from-quarantine workflows when an image is blocked by the CVE threshold, using a GitHub tracking issue + Slack notifications as the audit/interaction surface.
Changes:
- Introduces composite actions to (a) notify Slack, (b) manage a per-image+tag tracking issue with embedded JSON metadata, and (c) verify approver permissions.
- Extends promote-from-quarantine reusable workflows with an
enable_approvalinput and (when blocked) issue+Slack creation to drive later override decisions. - Adds a new override workflow pair (
promote-override.ymlcaller +_promote-override.ymlreusable) and updates docs/design documentation accordingly.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/reference/workflow-actions.md | Documents new actions and override-related inputs (includes a duplicated input table section). |
| docs/contributing/workflow-naming.md | Adds naming guidance for the new promote override workflow. |
| docs/architecture/workflows/promote-from-quarantine-workflows.md | Updates architecture notes to reflect optional approval/notification behavior. |
| docs/architecture/workflows/promote-from-quarantine-override-approval.md | New design doc describing the override approval architecture and security posture. |
| .github/workflows/promote-override.yml | New caller workflow that triggers overrides via issue comments or manual dispatch. |
| .github/workflows/_promote-override.yml | New reusable workflow implementing approve/deny behavior, provenance recording, and notifications. |
| .github/workflows/_promote-from-quarantine.yml | Adds enable_approval + blocked-image issue/Slack notification path. |
| .github/workflows/_promote-from-quarantine-sbom.yml | Same as above for SBOM-based scanning/promotion path. |
| .github/actions/verify-approver/action.yml | New composite action to authorize override approvers based on repo permission. |
| .github/actions/notify-slack/action.yml | New composite action to post Block Kit messages to a Slack webhook. |
| .github/actions/manage-issue/action.yml | New composite action for idempotent tracking-issue lifecycle + metadata round-trip. |
| .github/actions/attach-scan-report/action.yml | Extends scan-report referrer to optionally include override provenance annotations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- docs: remove duplicated override* input rows in workflow-actions.md
- manage-issue: fail fast when open-or-update gets empty/invalid metadata-json
- attach-scan-report: require override-approver + override-issue when override=true
- _promote-from-quarantine{,-sbom}.yml: drop issues:write from the scan matrix;
persist override metadata as an artifact and open the issue + notify Slack
from a dedicated least-privilege `notify` job (only job with issues:write)
- docs: describe the notify-job split in the design doc
This was referenced Jun 10, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an optional approve/deny override gate to the promote-from-quarantine workflows. When a scanned image fails the CVE threshold and approval is enabled, a tracking issue is filed and a Slack notification is sent; a maintainer can
/approveor/denyvia issue comment (orworkflow_dispatch) to promote the image despite the failing threshold or close it out.What's included
New reusable composite actions
notify-slack— post Block Kit status messages to a Slack incoming webhook (notify-slack reusable composite action #65)manage-issue— idempotent tracking-issue lifecycle (open-or-update / comment / close / get) with embedded JSON metadata as the source of truth (manage-issue reusable composite action #66)verify-approver— enforce minimum repo permission for approvers (verify-approver reusable composite action #67)Changes
attach-scan-report— recordcom.cssc.scan.override*provenance annotations (Extend attach-scan-report with override provenance annotations #68)_promote-from-quarantine.yml/_promote-from-quarantine-sbom.yml—enable_approvalinput +slack_webhooksecret; file issue + notify Slack on blocked images (Extend _promote-from-quarantine{,-sbom}.yml: notify + open issue on block #69)_promote-override.yml(reusable) +promote-override.yml(caller) — execute the maintainer decision (New reusable workflow _promote-override.yml + caller promote-override.yml #70)Design
See promote-from-quarantine-override-approval.md.
Validation
get_errors: clean (only benignSLACK_WEBHOOK"Context access might be invalid" until the secret is configured)shellcheck -S warning: clean on all run blocksBefore enabling in production
SLACK_WEBHOOKandGHCR_DELETE_TOKEN.enable_approval: true+ passslack_webhook. Existing callers are unchanged and backward-compatible.Tracking
Closes #64
Closes #65
Closes #66
Closes #67
Closes #68
Closes #69
Closes #70
Closes #71