MATIH Platform is in active MVP development. Documentation reflects current implementation status.
8. Platform Services
Approval Workflows

Approval Workflows

The Approval Workflow system enforces governance over configuration changes. The ApprovalWorkflowController at /api/v1/config/approvals requires changes to go through a request-review-approve cycle before they are applied. This is critical for production environments where configuration changes can impact service behavior.


Request Lifecycle

PENDING -> APPROVED -> APPLIED
    |          |
    v          v
 REJECTED   SCHEDULED (apply later)
    |
    v
CHANGES_REQUESTED -> PENDING (resubmitted)

Create a Config Change Request

Submit a proposed configuration change for review.

Endpoint: POST /api/v1/config/approvals/config/{configId}

curl -X POST http://localhost:8888/api/v1/config/approvals/config/770e8400-e29b-41d4-a716-446655440000 \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000" \
  -H "X-User-ID: 550e8400-e29b-41d4-a716-446655440001" \
  -H "X-User-Email: dev@acme.com" \
  -d '{
    "proposedValue": "180s",
    "justification": "Need higher timeout for large dataset queries in Q4 reporting"
  }'

Response:

{
  "id": "cr-001",
  "tenantId": "550e8400-...",
  "requesterId": "550e8400-...001",
  "requesterEmail": "dev@acme.com",
  "changeType": "CONFIG_UPDATE",
  "targetId": "770e8400-...",
  "currentValue": "120s",
  "proposedValue": "180s",
  "justification": "Need higher timeout for large dataset queries in Q4 reporting",
  "status": "PENDING",
  "createdAt": "2026-02-12T10:00:00Z"
}

Create a Flag Toggle Request

Request to enable or disable a feature flag.

Endpoint: POST /api/v1/config/approvals/flags/{flagId}/toggle

curl -X POST http://localhost:8888/api/v1/config/approvals/flags/880e8400-e29b-41d4-a716-446655440000/toggle \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000" \
  -H "X-User-ID: 550e8400-e29b-41d4-a716-446655440001" \
  -H "X-User-Email: dev@acme.com" \
  -d '{
    "enable": true,
    "justification": "Feature has passed QA and load testing in staging"
  }'

Approve a Request

Endpoint: POST /api/v1/config/approvals/{requestId}/approve

curl -X POST http://localhost:8888/api/v1/config/approvals/cr-001/approve \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-User-ID: 550e8400-e29b-41d4-a716-446655440002" \
  -H "X-User-Email: lead@acme.com" \
  -H "X-User-Role: approver" \
  -d '{ "comment": "Approved. Verified this aligns with the Q4 performance SLOs." }'

Reject a Request

Endpoint: POST /api/v1/config/approvals/{requestId}/reject

curl -X POST http://localhost:8888/api/v1/config/approvals/cr-001/reject \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-User-ID: 550e8400-e29b-41d4-a716-446655440002" \
  -H "X-User-Email: lead@acme.com" \
  -H "X-User-Role: approver" \
  -d '{ "comment": "Timeout of 180s is too high. Consider 120s with query optimization." }'

Request Changes

Ask the requester to modify the proposal before approval.

Endpoint: POST /api/v1/config/approvals/{requestId}/request-changes

curl -X POST http://localhost:8888/api/v1/config/approvals/cr-001/request-changes \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-User-ID: 550e8400-e29b-41d4-a716-446655440002" \
  -H "X-User-Email: lead@acme.com" \
  -H "X-User-Role: approver" \
  -d '{ "comment": "Please include load test results showing 120s is insufficient." }'

Schedule Apply Time

Schedule when an approved change should be applied.

Endpoint: POST /api/v1/config/approvals/{requestId}/schedule

curl -X POST http://localhost:8888/api/v1/config/approvals/cr-001/schedule \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -d '{ "applyAt": "2026-02-15T02:00:00Z" }'

List Pending Requests

Endpoint: GET /api/v1/config/approvals/pending

curl "http://localhost:8888/api/v1/config/approvals/pending?page=0&size=20" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000"

Get My Requests

Endpoint: GET /api/v1/config/approvals/my-requests

curl "http://localhost:8888/api/v1/config/approvals/my-requests?page=0&size=20" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000" \
  -H "X-User-ID: 550e8400-e29b-41d4-a716-446655440001"

Cancel a Request

Only the original requester can cancel a pending request.

Endpoint: DELETE /api/v1/config/approvals/{requestId}

curl -X DELETE http://localhost:8888/api/v1/config/approvals/cr-001 \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "X-User-ID: 550e8400-e29b-41d4-a716-446655440001"