Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.zenable.io/llms.txt

Use this file to discover all available pages before exploring further.

Approval workflows are available on Professional and Enterprise plans.

Overview

Approval workflows let you gate requirements or guardrail changes. Configure multi-phase flows with flexible approval criteria based on specific users, roles, or permissions. Without an active approval flow, requirements and guardrail regenerations are auto-approved immediately. With a flow configured, submissions enter a pending state and require explicit approval before proceeding.

Key Concepts

ConceptDescription
Approval FlowA reusable workflow definition with one or more sequential phases
PhaseA step in the flow with its own approval expression (who must approve)
Approval ExpressionA logical tree (AND/OR/NOT) of criteria that must be satisfied
Approval RequestA specific instance of a submission awaiting review
FeedbackVotes (upvote/downvote) and comments on pending requests

Target Types

Approval flows can be configured for these submission types. Create / update / delete are split per entity so different policies can apply to each (e.g. a flow could require approval on delete but not on create):
Target TypeDescription
new_requirementNew requirement proposals
requirement_versionUpdates to existing requirements
requirement_deleteDeletion of a requirement family (cascades to the requirement’s guardrails)
requirement_override_createCreating a tenant override for a marketplace requirement
requirement_override_updateModifying an existing tenant override
requirement_override_deleteRemoving a tenant override
guardrail_regenerationGuardrail code regeneration requests
guardrail_custom_createAuthoring a new tenant-owned custom guardrail
guardrail_custom_updateModifying an existing custom guardrail
guardrail_deleteDeleting a custom guardrail
scope_createAuthoring a new scope definition
scope_updateModifying an existing scope definition
scope_deleteDeleting a scope definition
target_selector_createAuthoring a new approval-flow target selector
target_selector_updateModifying an existing target selector
target_selector_deleteDeleting a target selector

Pending state and final disposition

Approval-gated actions never reach their final state until the request is approved.
  • Creates and updates stage the proposed data in the affected table itself, marked PROPOSED (overrides) or PROPOSED lifecycle (requirements). Read paths filter these out so users only see live state.
  • Deletes carry no pending state on the row — the open approval request itself is the pending marker. On approve the row is soft-deleted via deleted_at; on reject the row is untouched. Soft delete keeps the audit trail intact and makes restoration trivial.
  • An override update writes a new PROPOSED row whose supersedes_id points at the existing ACTIVE row. On approve, the superseded row is soft-deleted and the proposed row flips to ACTIVE. On reject, the proposed row is soft-deleted and the active row stays live.

Specific-user criteria

SPECIFIC_USER criterion values are stored as user_uid (the stable 5-word identifier). The UI surfaces and accepts login_identifier (email / UPN / SSO sub) so authors and approvers see human-readable handles; the form picker stores the corresponding user_uid under the covers. Even when an approver holds requirements:approve or guardrails:approve, they can only decide on a request if they satisfy the active phase’s expression — being named in a SPECIFIC_USER rule, for example.

Creating an Approval Flow

Navigate to Approval Management and select the Workflows tab.

Flow Configuration

  1. Name and description - Give the flow a meaningful name
  2. Target types - Select which submission types trigger this flow
  3. Phases - Define one or more sequential approval phases
  4. Default flow - Optionally mark as the default for its target types

Approval Expressions

Each phase defines an approval expression using a logical tree:
  • Specific User - A named user must approve (matched by user UID)
  • Role - Any user with the specified role can approve
  • Permission - Any user with the specified permission can approve
Combine criteria with AND (all must be satisfied), OR (any one suffices), or NOT (exclusion) operators. Expressions can be nested for complex approval requirements. Example: “Requires approval from any Admin OR both the Security Auditor AND a Contributor”
OR
├── Role: Admin
└── AND
    ├── Role: Security Auditor
    └── Role: Contributor

Multi-Phase Flows

Phases execute sequentially. Each phase must be fully approved before the next begins. If any phase is rejected, the entire request is rejected. Example: A two-phase flow for new requirements:
  1. Technical Review - Any contributor approves
  2. Compliance Sign-off - Security auditor approves

Reviewing Approval Requests

Navigate to the Pending Reviews tab in Approval Management. Each request shows:
  • The submitted entity (requirement name, guardrail code snippet)
  • Current phase and progress
  • Approve / Reject buttons (visible only if you have the required permission)

Decisions

  • Approve - Records your approval for the current phase. If the phase’s approval expression is now satisfied, the flow advances to the next phase (or completes).
  • Reject - Immediately rejects the entire request regardless of phase. The submitter is notified.

Feedback

You can provide feedback on any pending request without making an approval decision:
  • Vote - Upvote or downvote (one vote per user per request, toggleable)
  • Comment - Up to 280 characters. Edits are tracked; the last 12 versions are stored.

What Happens After Approval

Target TypeOn ApprovalOn Rejection
New requirementTransitions from PROPOSED to BETA; guardrail generation triggersTransitions to DECLINED
Requirement versionTransitions from PROPOSED to BETA; guardrail update triggersTransitions to DECLINED
Requirement deleteRequirement soft-deleted; cascades to its guardrailsSubmitter notified; no delete
Requirement override create / updateNew row activates (PROPOSED → ACTIVE); for updates, the superseded ACTIVE row is soft-deletedPROPOSED row soft-deleted
Requirement override deleteOverride row soft-deletedSubmitter notified; no delete
Guardrail regenerationRegeneration proceeds with stored parametersSubmitter notified; no regeneration
Custom guardrail createNew row becomes is_latest=truePROPOSED row soft-deleted
Custom guardrail updateNew row becomes is_latest=true; prior version flips to is_latest=falsePROPOSED row soft-deleted
Custom guardrail deleteGuardrail soft-deletedSubmitter notified; no delete
Scope create / updateNew row activates (PROPOSED → ACTIVE); for updates, the superseded ACTIVE row is soft-deletedPROPOSED row soft-deleted
Scope deleteScope soft-deletedSubmitter notified; no delete
Target selector create / updateNew row activates (PROPOSED → ACTIVE); for updates, the superseded ACTIVE row is soft-deletedPROPOSED row soft-deleted
Target selector deleteSelector soft-deletedSubmitter notified; no delete

Notifications

Users receive notifications for approval events based on their notification preferences:
EventDeliveryRecipients
Approval requestedImmediateEligible approvers for phase 1
Decision madeImmediateSubmitter
Phase completedImmediateNext phase’s eligible approvers
Fully approved/rejectedImmediateSubmitter
Feedback receivedDaily digestSubmitter
All notification types can be individually enabled or disabled in user preferences.

Required Permissions

Approvals are fully transparent: anyone with approvals:read can see every request, every decision, every comment, and who voted which way. There is no per-record permission gating beyond approvals:read.
PermissionDescription
approvals:readView approval flows, pending requests, decisions, and the feedback thread
approvals:feedbackSubmit non-binding feedback (vote + comment) on an approval request
approvals:manageCreate, edit, and archive approval flow definitions
requirements:approveCast a binding approve/reject decision on requirement proposals
guardrails:approveCast a binding approve/reject decision on guardrail regeneration requests
See Roles and Permissions for which roles include these permissions.

API Reference

Approval Flows

MethodEndpointDescriptionPermission
GET/api/data/approval-flowsList flows (pass ?include_archived=true to include archived)approvals:read
POST/api/data/approval-flowsCreate a new flowapprovals:manage
PUT/api/data/approval-flows/{id}Update a flowapprovals:manage

Approval Requests

MethodEndpointDescriptionPermission
GET/api/data/approval-requestsList approval requests (filterable by status, target_type, submitted_by)approvals:read
GET/api/data/approval-requests/{id}Get request detail with phase instancesapprovals:read
POST/api/data/approval-requests/{id}/decideSubmit approve/reject decision on a requestrequirements:approve for requirement-related target types (new_requirement, requirement_version, requirement_delete, requirement_override_create, requirement_override_update, requirement_override_delete); guardrails:approve for guardrail-related target types (guardrail_regeneration, guardrail_custom_create, guardrail_custom_update, guardrail_delete); approvals:manage for scope/selector target types (scope_create, scope_update, scope_delete, target_selector_create, target_selector_update, target_selector_delete). The phase rule may also require a specific user / role / permission.
Decision request body:
{
  "decision": "approve",
  "comment": "Looks good to me"
}
The decision field accepts approve or reject. The optional comment field (max 280 characters) is recorded with the decision.

Approval Feedback

MethodEndpointDescriptionPermission
GET/api/data/approval-requests/{id}/feedbackList all feedback for a requestapprovals:read
POST/api/data/approval-requests/{id}/feedbackSubmit or update your feedbackapprovals:feedback
Feedback request body:
{
  "vote": "upvote",
  "comment": "I agree with this change"
}
The vote field accepts upvote or downvote (mutually exclusive, toggleable). Both fields are optional; you can vote without commenting or comment without voting. Feedback is upserted per user per request — submitting again updates your existing feedback. Comment edits are versioned (last 12 versions retained).

Audit Logging

All approval actions are recorded in the audit log:
  • Flow created, updated, or archived
  • Decision made (approve/reject)
  • Request created or resolved
  • Feedback submitted or edited
Access audit logs via the Audit section in the management console.
Need help? Contact us at hello@zenable.io