The CAB (Change Advisory Board) workflow extends the existing ChangeRequest entity with multi-approver voting, conflict detection against other pending/approved changes, scheduled change windows, and a change calendar.
Change types
| Type | CAB review | Use for |
|---|---|---|
| Standard | Auto-approved (no CAB) | Pre-approved low-risk changes (cert renewals, routine patches) |
| Normal | CAB vote required | Most changes — config updates, app upgrades, network changes |
| Emergency | CAB vote required (expedited) | Urgent fixes that can't wait for the next scheduled CAB meeting; out-of-cycle escalation to emergencyEscalationEmail |
Setting up a CAB board
POST /api/cab/boards (Admin) or MCP create_cab_board. Required fields: name, members[]. Each member has email, role (chair / voting / observer; default voting), optional alternateEmail (delegate when primary is OOO).
Optional: meetingCadence (weekly / biweekly / monthly / on-demand), meetingDay (display string like "Tuesday 10am ET"), approvalThresholdPercent (default 50% = simple majority), emergencyEscalationEmail.
Max 20 members per board. Multiple boards per org allowed — e.g. "App CAB" for application changes, "Infra CAB" for infrastructure, "Security CAB" for security policy.
Submitting a change to CAB
POST /api/change-requests/:id/submit-to-cab (Admin) or MCP submit_change_to_cab. Required: changeType (Standard / Normal / Emergency). For Normal/Emergency: cab_board_id required. Optional: scheduled_start, scheduled_end, affected_ci_ids[] (links to CMDB).
What happens:
- Standard changes are auto-approved immediately.
cabDecision='approved',approvalStatus='Approved', no further action needed. - Normal/Emergency: conflict detection runs against other pending/approved changes:
- window-overlap — scheduled windows intersect
- same-ci — affectedCiIds intersect
- same-control — controlId matches
- Conflicts stored on the change as
cabConflicts[]for CAB review. Doesn't block submission — informs voting. - Change enters the CAB queue (
cabDecision='pending',approvalStatus='Pending CAB').
Voting
POST /api/change-requests/:id/cab-vote (Auditor+) or MCP cab_vote. Body: vote (approve / reject / abstain), optional comment.
- Voter must be a member of the assigned board. Matched by email or alternateEmail. Non-members get 403.
- Observers cannot vote. Only chair + voting roles count.
- One vote per member. Re-voting overwrites the previous vote.
Decision auto-computed after every vote:
- If approve count ≥ approve threshold (ceil(totalVoters × approvalThresholdPercent/100)) → approved
- If reject count ≥ reject threshold (ceil(totalVoters × (100 - approvalThresholdPercent)/100)) → rejected (because reaching approval is now mathematically impossible)
- If all members voted but neither threshold met → rejected (failed quorum approval)
- Otherwise: still pending, waiting on more votes
When approved or rejected, cabDecidedAt stamped, approvalStatus updated, and on approval approvedBy set to "CAB:{boardName}" (distinguishes board approval from single-approver).
For CAB members: how to cast your vote
If you've been added to a CAB board (you're a voting member or chair), here's the user-side workflow when a change request lands in your queue:
- You'll be notified — by email and via the in-app notification badge — when a change request is submitted to the CAB you sit on. The notification includes the change title, submitter, scheduled window, and conflict count (if any).
- Open the CAB queue — from the TATER Ops sidebar: Governance & Risk → CAB Queue. You'll see all changes pending decision from CABs you belong to. Sorted by scheduled-start date so the most time-sensitive items surface first.
- Click into the change to see the full details: requester, control / system affected, business justification, scheduled window (start → end), change type (Standard auto-approves; Normal and Emergency go to CAB), affected CIs (with criticality), and any conflicts detected against other pending or approved changes.
- Review conflicts carefully — the system flags three kinds:
- window-overlap — another change is scheduled at the same time
- same-CI — another change touches the same Configuration Item
- same-control — another change targets the same compliance control
- (Optional) Run
get_ci_impactvia the AI assistant or click the affected CIs to estimate blast radius before voting. For Critical-impact changes this is recommended. - Cast your vote. Click Approve, Reject, or Abstain. Add a comment if context matters (especially for reject — explain why). Comments are visible to other board members and to the change requester.
- Decision auto-finalizes when the threshold is met (approve count ≥ approve threshold, or reject count ≥ reject threshold, or all members have voted). No manual "close vote" step.
- If you change your mind before the decision finalizes, re-vote — the new vote overwrites the old. After finalization, votes are locked.
If you're a chair, your vote counts the same as any other voting member — there's no veto. The chair role is for meeting facilitation, not vote weight.
If you're an observer, you can see all changes and comments but you cannot vote. Reach out to a voting member if you have input.
If you're going to be out of office, set up an alternateEmail on your board member entry (in Settings → CAB Boards). Votes cast by the alternate email count as your vote. The alternate flag is recorded in the audit log for transparency.
CAB queue + change calendar
GET /api/cab/queue/:boardId(Viewer+) — list pending changes for one board. Use to populate CAB meeting agendas. Sorted by scheduled start.GET /api/change-requests/calendar?from=&to=(Viewer+) — all changes with scheduled windows in a date range. Use for freeze-period analysis, change forecasting, conflict scanning.
MCP tools (6, HTTP + stdio parity)
list_cab_boards(Viewer+)create_cab_board(Admin)submit_change_to_cab(Admin)cab_vote(Auditor+; members only)get_cab_queue(Viewer+)get_change_calendar(Viewer+)
Pitfalls
- CAB is fields-on-ChangeRequest, not a separate entity. CabBoards is its own container (governance setup), but the actual workflow lives on the change.
- Existing changes without
cabBoardIdwork fine. The CAB extensions are additive — old changes that weren't submitted to a CAB still use the single-approver path onapprovedBy. - Vote decision-on-each-vote. The handler re-computes decision after every vote. Don't add a "close vote" step — it would feel sluggish.
- Conflict detection is informational, not blocking. Conflicts go into
cabConflicts[]for human review. The CAB votes with the conflicts in front of them and decides whether to approve, reject, or reschedule. - Standard change auto-approval skips voting entirely. If your org wants a sanity check on Standards, model them as Normal changes with a 1-voter CAB.
Related guides
- CMDB — affected_ci_ids drives conflict detection
- Release Management — bundles approved changes into deployments
- Major Incident — emergency changes during MIs use the Emergency change type