Agent Wranglers

APP-47Recommended

Let the server say what each user may do

Send the actions the user may take on each record with the record, and show controls from that list. Never rebuild the permission rules in the client.

How to do it

Add a field such as "allowedActions": ["edit", "send"] to each record, computed by the same code that enforces access. The screen shows a control only when its action is listed. Hide actions the user can never take. Show actions they could take after a change, such as a plan upgrade, with the reason. The server computes them from permissions, as check permissions instead of role names says.

Examples

Python example

def invoice_json(invoice: Invoice, user: User) -> dict:
    return {
        "id": invoice.id,
        "number": invoice.number,
        "status": invoice.status,
        "allowedActions": [action for action in ("edit", "send", "delete") if policy.allows(user, action, invoice)],
    }

TypeScript example

export function InvoiceActions({ invoice }: { invoice: Invoice }) {
  const can = (action: InvoiceAction) => invoice.allowedActions.includes(action);
  return (
    <div className="invoice-actions">
      {can('edit') && <LinkButton href={`/invoices/${invoice.id}/edit`}>Edit</LinkButton>}
      {can('send') && <SendButton invoice={invoice} />}
      {can('delete') && <DeleteButton invoice={invoice} />}
    </div>
  );
}

How to check

Search the client for role names, such as 'admin' or role ===. There are no matches outside the sign-in code.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/app-ui/sessions-and-permissions/capabilities-from-server">Agent Wranglers web app interface playbook</a>. In code you write, add a comment next to it with the same link.