Skip to main content

Approval Workflow

FastGateway implements a unified multi-stage approval system for all change requests. Both route changes and client attachments go through the same approval pipeline with configurable stages.

Unified Approval Flow

┌────────────────────────────────────────────────────────────────────────────┐
│ UNIFIED APPROVAL SYSTEM │
├────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ Entity │ Route create/update/delete │
│ │ Change │ Client attachment attach/detach │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Stage 1 │────▶│ Stage 2 │────▶│ Stage N │ │
│ │ Approval │ │ Approval │ │ Approval │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ │ Reject │ Reject │ All Approved │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ REJECTED │ │ REJECTED │ │ APPROVED │ │
│ └─────────────┘ └─────────────┘ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Deploy │ (Routes only) │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ ACTIVE │ │
│ └─────────────┘ │
└────────────────────────────────────────────────────────────────────────────┘

Approval Entities

The unified system handles two entity types:

Entity TypeActionsDefault Stages
Routecreate, update, delete1 stage: route.approve permission
Client Attachmentattach, detach2 stages: cross-team approval

Route Statuses

StatusDescription
pending_createNew route submitted, awaiting approval
pending_updateRoute update submitted, awaiting approval
pending_deleteRoute deletion submitted, awaiting approval
approvedAll approval stages passed, ready for deployment
pending_deployApproved and awaiting deployment to Kubernetes
activeDeployed and running in Kubernetes
rejectedApproval denied with reason

Attachment Statuses

StatusDescription
pending_attachNew attachment submitted, awaiting approval
pending_detachDetachment requested, awaiting approval
approvedAll approval stages passed
activeAttachment is live (route deployed with this client)
rejectedApproval denied
removedAttachment has been detached

Approval Stages

Each approval consists of one or more stages that must be completed sequentially:

┌────────────────────────────────────────────────────────────────┐
│ Approval Stages │
├────────────────────────────────────────────────────────────────┤
│ │
│ Stage 1 Stage 2 Stage N │
│ ┌──────────────────┐ ┌──────────────────┐ ┌────────┐ │
│ │ required_perm: │ │ required_perm: │ │ ... │ │
│ │ route.approve │───▶│ client.approve │───▶│ │ │
│ │ │ │ │ │ │ │
│ │ team_scope: any │ │ team_scope: │ │ │ │
│ │ │ │ other_team │ │ │ │
│ └──────────────────┘ └──────────────────┘ └────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘

Stage Configuration

Each stage has:

FieldDescription
orderSequential order (1, 2, 3...)
required_permissionPermission needed to approve (e.g., route.approve)
team_scopeWhich team(s) can approve

Team Scope Values

ScopeDescription
anyAny user with the required permission in the project
other_teamUser must be from a different team than the submitter
submitter_teamUser must be from the submitter's team

Default Approval Policies

When a project is created, these default policies are seeded:

Route Approvals (Single Stage)

[
{
"order": 1,
"required_permission": "route.approve",
"team_scope": "any"
}
]

Any user with route.approve permission can approve route changes.

Client Attachment Approvals (Dual Stage)

[
{
"order": 1,
"required_permission": "client.approve",
"team_scope": "other_team"
},
{
"order": 2,
"required_permission": "client.approve",
"team_scope": "any"
}
]
  1. Stage 1: A member from a different team must approve (cross-team validation)
  2. Stage 2: Any approver finalizes the request

Approval Rules

Submitter Constraint

Users cannot approve their own submissions, even if they have the required permission. This ensures separation of duties.

Sequential Approval

Stages must be approved in order. Stage N cannot be approved until all stages 1 through N-1 are approved.

Rejection Behavior

  • Any rejection fails the entire approval — the overall status becomes rejected
  • Remaining pending stages stay as-is (not auto-rejected)
  • A rejected request must be re-submitted as a new request

Owner Bypass

System owners (role: owner) can approve any stage regardless of team restrictions, but still cannot self-approve.

Permission Matrix

ActionViewerEditorApproverAdminOwner
Submit route change--
Approve route (others')--
Approve own route-----
Deploy approved route-
Submit attachment--
Approve attachment (others')--
Approve own attachment-----

API Endpoints

List Approvals

GET /api/v1/projects/:projectId/approvals?status=pending&entityType=route

Filters:

  • status: pending, approved, rejected
  • entityType: route, client_attachment

Approve a Stage

POST /api/v1/projects/:projectId/approvals/:approvalId/stages/:stageId/approve

Reject a Stage

POST /api/v1/projects/:projectId/approvals/:approvalId/stages/:stageId/reject
Body: { "comment": "Reason for rejection" }

Benefits

  • Unified workflow: Single approval system for all entity types
  • Configurable stages: Projects can customize approval requirements
  • Cross-team validation: Client attachments require multi-team approval
  • Audit trail: Full history of submissions, approvals, and rejections
  • Separation of duties: Submitters cannot self-approve
  • Permission-based: Fine-grained control over who can approve what