---
title: "Let the server say what each user may do · Agent Wranglers"
url: https://agentwranglers.se/playbook/app-ui/sessions-and-permissions/capabilities-from-server
id: APP-47
level: Recommended
applies: accounts
updated: 2026-10-22
build: a2a6bdfed830
tokens: 937
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Let the server say what each user may do

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Sessions and permissions](https://agentwranglers.se/playbook/app-ui/sessions-and-permissions.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-22.

- ID: APP-47
- Level: Recommended
- Chapter: [Sessions and permissions](https://agentwranglers.se/playbook/app-ui/sessions-and-permissions.md)
- Rule: 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.
- Check: Search the client for role names, such as `'admin'` or `role ===`. There are no matches outside the sign-in code.
- Applies when: The project has user accounts.
- How: 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](https://agentwranglers.se/playbook/app-ui/data-views/disabled-with-reason.md). The server computes them from permissions, as [check permissions instead of role names](https://agentwranglers.se/playbook/accounts/roles-and-permissions/permissions-not-roles.md) says.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### Python example

```python
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

```tsx
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>
  );
}
```

## Sources

- [OWASP Authorization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html#verify-that-authorization-checks-are-performed-in-the-right-location)

## Related rules

- ACC-34 [Check a named permission on the server for every action](https://agentwranglers.se/playbook/accounts/roles-and-permissions/permissions-not-roles.md) in Accounts and identity
- APP-11 [Say why a control is unavailable](https://agentwranglers.se/playbook/app-ui/data-views/disabled-with-reason.md) in Web app interface
- UXD-2 [Build the setup checklist from what the account has done](https://agentwranglers.se/playbook/ux-design/onboarding/setup-checklist-from-data.md) in UX and deceptive design

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/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.

- Next: [Survive an expired session](https://agentwranglers.se/playbook/app-ui/sessions-and-permissions/session-expiry.md)
- [Sessions and permissions](https://agentwranglers.se/playbook/app-ui/sessions-and-permissions.md)
