Manage Waivers
A waiver exempts a specific rule from gate enforcement for a given scope. Unlike tuning thresholds, waivers preserve your global policy while acknowledging specific, justified exceptions.
Scope Ladder
Each waiver has a scope. Most-specific match wins during evaluation:
- PR-scoped -
(org_id, repo_id, pr_number, rule)- applies only to that one PR - Repo-scoped -
(org_id, repo_id, rule)- applies across all PRs in that repo - Org-scoped -
(org_id, rule)- applies across all repos in the org
Missing fields = broader scope. Create an org waiver by leaving repo_id and pr_number null. Create a repo waiver by setting repo_id only.
Creating a Waiver
Example Waivers
PR-specific - emergency merge
POST /api/quality/gates/waivers
{
"rule": "new_critical_max",
"reason": "Hotfix for PROD-5512. Vulnerability in third-party SDK, upstream fix tracked in #7812. Rolling back to previous version via separate PR immediately after merge.",
"repo_id": 42,
"pr_number": 1087,
"expires_at": "2027-04-20T00:00:00Z"
}Repo-specific - known issue, scheduled remediation
{
"rule": "duplication_pct_max",
"reason": "Legacy monolith has 12% duplication. Refactor to shared utilities tracked in Q2 OKR. Gate disabled until 2027-07-01 scheduled review.",
"repo_id": 42,
"expires_at": "2027-07-01T00:00:00Z"
}Org-wide - temporarily lenient during rollout
{
"rule": "new_coverage_min",
"reason": "Org-wide testing push in progress. Coverage gates suspended until coverage baseline is established across all repos. Revisit 2027-06-01.",
"expires_at": "2027-06-01T00:00:00Z"
}How Waivers Affect Evaluation
When the gate runs, waived rules’ violations are stripped from the primary violations list and moved into a separate waived_violations field. The gate still passed if only waived rules are violating:
{
"status": "passed",
"violations": [],
"waived_violations": [
{ "rule": "duplication_pct_max", "threshold": 3, "actual": 4.2,
"severity": "high", "waived": true }
]
}The PR comment, Check Run, and dashboard widget all surface waived violations separately - with the reason - so reviewers know the exception is active and deliberate.
Viewing + Revoking
- List active:
GET /api/quality/gates/waivers- default hides expired + revoked - List all:
GET /api/quality/gates/waivers?include_expired=true&include_revoked=true - By repo:
GET /api/quality/gates/waivers?repo_id=42 - Revoke:
POST /api/quality/gates/waivers/{id}/revoke- soft-delete; stops honoring on next scan
In the UI, open Settings → Quality Gates → Manage waivers, then enable Include expired/revoked to see history. The revoke action on each row preserves the historical record.
Audit Trail
Every waiver stores:
created_by_user_id- who created itcreated_at- when createdrevoked_at- when revoked (null if active or expired)expires_at- scheduled expiry (null if permanent)reason- required text
No delete path. Revocation is soft. Records are preserved for audit.
Common Patterns
| Situation | Scope | Expiry |
|---|---|---|
| One-off emergency merge | PR | 24h |
| Known repo-level tech debt | Repo | Tied to remediation deadline |
| Awaiting upstream CVE fix | Repo or org | Tied to upstream release ETA |
| Vendor-mandated compensating control | Repo | Permanent (no expiry) + documented |
| Policy rollout easing | Org | Tied to full-enforcement date |
Related
- Set Up Quality Gates
- Policy as Code - for structural exemptions, prefer repo YAML over waivers
- Quality Gate API -
POST /quality/gates/waiversreference