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.
Awaiting your CAB vote (personal queue)
The Change Advisory Board page (TATER Ops) shows an "Awaiting your CAB vote" section - a personal queue listing the change requests where you are a board member and haven't voted yet. CAB voting doesn't route through My Approvals, so this section is your personal-scope view of what's waiting on you:
- Aggregates across all your boards - if you sit on multiple CABs, every pending change from each of them appears in the one list (minus the ones you've already voted on).
- Vote inline - Approve / Reject / Abstain buttons with an optional comment, right from the queue - no need to open each change first.
- Backed by
GET /api/cab/my-queue, which returns the pending changes on every CAB board you belong to that still need your vote.
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