Review workflows.
Last updated
Review plans
What it is. The approval policy attached to a datasource — it decides how a submitted query gets from "submitted" to "executed". Use it to require AI scoring, one or more human sign-offs, or both, and to auto-approve low-risk reads. Each plan is a sequence of stages; each stage names approvers (by role or specific user) and a minimum number of approvals before the query advances.
Configure it. Build plans at /admin/review-plans — start
from a built-in template or from scratch:
/admin/review-plans → caret next to Add review plan exposes four built-in templates that prefill the create modal.
/admin/review-plans → Add review plan. Stack approver rows to build multi-stage chains.- Open
/admin/review-plansand click Add review plan, or pick a built-in template from the dropdown caret next to it (Strict — writes need 2 approvals, Lenient — reads auto-approved, AI-only — no human approval, Standard — AI + 1 reviewer) to prefill the modal with sensible defaults. - Name and describe the policy — e.g. "Production writes — two reviewers".
- Pick the gates. Toggle Require AI review to score every query before it queues for humans; toggle Require human approval to demand at least one reviewer sign-off. Auto-approve LOW-risk reads lets
SELECTs skip humans entirely when AI risk is below the threshold. - Set thresholds. Minimum approvals is the number of distinct reviewers needed before the query advances; Approval timeout (hours) is when AccessFlow auto-rejects an idle
PENDING_REVIEWquery (it scans on a cadence set byACCESSFLOW_WORKFLOW_TIMEOUT_POLL_INTERVAL, defaultPT5M). - Build the approver chain. Click Add approver for each stage; each row names a role (or a specific user) and a stage number. Stages advance sequentially, and a single REJECTED decision at any stage terminates the query.
What can a review plan control?
A review plan is six settings plus an approver chain. Together they decide whether a query needs AI scoring, how many humans must sign off, which of them, and what happens if nobody does. Every setting below is per-plan, and a plan attaches to a datasource.
| Setting | What it does | When disabled / unset |
|---|---|---|
| Require AI review | Every query is scored for risk before it queues for humans. | The query skips PENDING_AI and goes straight to review. |
| Require human approval | At least one reviewer must sign off before execution. | The query is approved without a human — AI-only gating. |
| Auto-approve LOW-risk reads | SELECTs below the AI risk threshold skip human approval. |
Reads queue for review like any other statement. |
| Minimum approvals | How many distinct reviewers must approve before the query advances. | Defaults to one approval per stage. |
| Approval timeout (hours) | How long an idle PENDING_REVIEW query waits before auto-rejection. |
The query waits indefinitely for a decision. |
| Approver chain | Ordered stages, each naming a role or a specific user as approver. | No chain means no staged escalation — one flat approval step. |
Stages advance sequentially and a single Reject at any stage terminates the query. A user can never approve their own query, whatever their role.
Reviewer decisions. Reviewers can Approve, Reject, or
Request changes. Reject and Request changes both require a
non-empty comment — the server enforces this (HTTP 400 VALIDATION_ERROR),
and the UI disables the confirm button until the textarea is populated. The comment is
persisted on the decision row, rendered on the rejected stage of the timeline on
/queries/<id>, and surfaced to the submitter as a "Changes requested"
alert whenever the latest decision is REQUESTED_CHANGES and the query is
still PENDING_REVIEW. Approve still treats the comment as
optional.
Query status transitions. A query moves through these states:
PENDING_AI → PENDING_REVIEW → APPROVED → EXECUTED
↘ REJECTED (manual reviewer rejection)
↘ TIMED_OUT (approval-timeout auto-reject)
PENDING_REVIEW → CANCELLED (submitter only)
APPROVED → FAILED (execution error)
A single REJECTED decision at any stage terminates the query. If a query
sits in PENDING_REVIEW past the plan's approval timeout, AccessFlow
auto-rejects it (it scans on a cadence set by
ACCESSFLOW_WORKFLOW_TIMEOUT_POLL_INTERVAL, default PT5M).
Auto-approve reads lets SELECTs skip human approval entirely;
Require AI review still scores the read but won't block on a human.
Routing policies
What it is. Policy-as-code that decides a query's path automatically, after AI analysis and before reviewers see it. Use it to auto-approve routine reads, hard-block dangerous patterns, or escalate sensitive ones — instead of sending everything through the same review plan. Policies run in ascending priority and the first enabled one whose condition matches wins; anything unmatched falls through to the datasource's review plan exactly as before.
Configure it. Manage them at /admin/routing-policies (the
Routing policies entry in the Security nav group):
- Open
/admin/routing-policies(the Routing policies entry in the Security nav group, next to Review plans) and click Add policy. - Name the policy and optionally scope it to one datasource — leave the datasource blank for an org-wide rule. Set its priority (unique per organisation; lower runs first) and the enabled toggle.
- Build the condition with the guided builder: pick match ALL (AND) or match ANY (OR), then add leaf conditions — each can be negated (NOT). Operands include query type, referenced tables (glob, e.g.
payroll.*), AI risk level, AI risk score (with a comparison operator), requester role, requester group, time-of-day window, day-of-week, presence of aWHEREclause, presence of aLIMITclause, the transactional (BEGIN…COMMIT) flag, and the pre-flight cost estimate — estimated rows (comparison against the engine's own EXPLAIN estimate, or the exact affected-row count for UPDATE/DELETE) and scan type (glob match on the plan's root operation, e.g.Seq*) — so a policy can route a 10-million-row sequential-scan DELETE differently from a 10-row indexed one. - Choose the action. Auto-approve (skip human review), Auto-reject (block the query), Require approvals (force human review with an absolute minimum number of approvers), or Escalate (force human review, adding a delta on top of the review plan's minimum). The approver count applies only to the last two actions.
- Reorder policies any time with the per-row up/down controls — the order is the evaluation order.
QUERY_APPROVED /
QUERY_REJECTED with source: "ROUTING_POLICY"), and the query detail page
shows which policy matched. Routing policies are managed via the ADMIN-only
/api/v1/admin/routing-policies CRUD and /reorder endpoints.
/admin/routing-policies — ordered, attribute-based auto-decision rules; first match by priority wins, unmatched falls through to the review plan.Access recertification campaigns
What it is. Recurring attestation campaigns that make someone periodically
re-confirm who still needs standing datasource access — the review control SOC 2 and
ISO 27001 auditors ask for. An admin schedules an org- or datasource-scoped campaign;
when it opens it snapshots the current standing grants into one item per
grant and notifies the eligible reviewers (multi-channel, plus an
attestation.campaign_opened WebSocket event). Reviewers work a
certify / revoke worklist that reuses the review-queue patterns
(self-review blocked, bulk-certify); a revoke routes through the normal
permission-revoke path, so access is actually removed.
Configure it. Manage campaigns from /admin/attestation and
certify items from the reviewer worklist at /reviews/attestations. Two
clustered-safe jobs run the lifecycle: one opens SCHEDULED campaigns at their
scheduled_open_at, the other closes OPEN campaigns at their
due_at and applies each campaign's pending-default (KEEP or
REVOKE) to anything a reviewer never got to. A completed campaign exports as a
CSV evidence file (who reviewed what, decisions, timestamps), and every
transition — ATTESTATION_CAMPAIGN_OPENED/CLOSED,
ATTESTATION_ITEM_CERTIFIED/REVOKED — lands in the tamper-evident
audit log.
Tune it. ACCESSFLOW_ATTESTATION_OPEN_POLL_INTERVAL and
ACCESSFLOW_ATTESTATION_CLOSE_POLL_INTERVAL (open / close scan cadence, both
default PT5M) and ACCESSFLOW_ATTESTATION_MAX_EVIDENCE_ROWS (row
cap before an evidence CSV is marked truncated, default 50000).
/admin/attestation — admins schedule recurring access-recertification campaigns; reviewers certify or revoke each snapshotted grant.