docs
/
AppEngine API

Approvals

Asking for access to a screen or a guarded operation, and deciding it from a tray, through the org's workflows.

ApprovalModule handles two kinds of asking. Someone refused at a screen or menu item asks for access; someone about to publish a guarded record asks for sign-off. Either way the ask becomes a workflow task, the approvers get it in their tray and their mail, and the person who asked is told the answer. The admin screens only call in and render what comes back.

Datatypes: access_request (one ask for a screen), task (what the workflow raises and the approver decides), workflow_definition, and message for tray notices. Workflows are covered under Workflow.

Routes

POST/approval/askJWT
GET/approval/trayJWT
GET/approval/historyJWT
POST/approval/task/:taskId/approveJWT
POST/approval/task/:taskId/rejectJWT
POST/approval/request/:id/cancelJWT
POST/approval/notices/readJWT
POST/approval/notices/:id/readJWT
POST/approval/setupJWT

All take the orgid header and act as the signed-in caller, matched by email.

Asking

ask takes a target and an optional request (reason, label):

  • A screen or menu item — { kind: 'menu' | 'screen', path }. Opens an access_request and fires the workflow that lists access_request in its collections. Returns { decision: 'pending', requestId, taskId, approvers, escalatesAt }, or already-pending if the same person already has an open ask for that path. If no enabled workflow takes access_request, the request is cancelled and the call answers 422.
  • A record operation — { kind: 'record', operation: 'publish', datatype, id }. Fires whichever workflow lists that datatype. If none is enabled there is nothing to wait for and the answer is { decision: 'allowed' } — the caller just publishes.

setup seeds the shipped access-approval workflow only when the org has no workflow listing access_request; ask runs it first, so it is idempotent. After that the owner may edit or replace it — its stage rule decides who approves.

Deciding

approve and reject take { note }. Only someone the task is assigned to, or an Owner, ConfigAdmin or RootAdmin, may decide; a task no longer open answers 409.

  • The task's workflow must be a decision: it needs an Approved (or Published) stage and a Rejected stage. Anything else is work, not an approval, and answers 422 with reason not-a-decision.
  • Approving an access request must say how — grant: { via: 'role' | 'group', name }. The requester is added to that role or group; access is never granted as a one-off. Without it the call answers 400 with reason grant-required.
  • Approving a publish publishes the record: pages and posts are copied to published; other datatypes are marked state: published.
  • The task moves to the workflow's yes or no stage, the access_request records the decision in approvalChain, and the requester is notified.

request/:id/cancel lets the person who asked withdraw it while it is still pending; the approvers are told.

Tray and history

tray returns waitingOnMe (open tasks assigned to me whose workflow is a decision — workspace tasks are excluded), myRequests (my pending access requests), notices newest first, unread and counts. history returns what I decided and my requests that are no longer pending. notices/read marks all my notices read; notices/:id/read marks one, and only if it was sent to me.

AI employees

When an AI employee asks before acting, the module fires the ai-employee-approval workflow so it lands in the approver's tray like any other ask — assigned to the employee's supervisor when it has one. A decision in the tray is passed back to the employee; a decision made elsewhere cancels the tray item.

access_request

Field
requesteremail, name, userId
app, path, label, reasonWhat was asked for
statuspending · approved · rejected · cancelled
approveremails, since, escalatesAt
approvalChainEach step: round, level, approverEmail, status, assignedAt, decidedAt, decidedBy, comments, taskId
grantvia (role · group), name — set on approval
taskId, workflowName, submittedAt, decidedAt, decidedBy, comments