Generated from source at build time — this page cannot drift from the running service.

Scopes

Inbox has 6 scopes. They are granted in Axis Accounts under the inbox: prefix and mapped onto a shorter local vocabulary inside the service — the prefix exists because an Accounts key is not app-exclusive, so inbox:threads must not collide with another app's scopes.

Accounts scope Local scope Routes What it grants
inbox:connections connections 22 Connect, list, disconnect and reconnect social accounts
inbox:threads inbox 139 Read inbox threads and entries; reply and moderate
inbox:publish publish 7 Create, schedule and cancel posts
inbox:admin admin 25 Webhook endpoints, webhook inbox and break-glass operations
inbox:stats stats 8 Read-only CROSS-TENANT operator/admin figures (dashboard operator view). No tenant scope; grants no access to any tenant-scoped resource.
inbox:connections:write operator:connections:write CROSS-TENANT operator WRITE: action connection requests from the dashboard — approve/reject, enter provider credentials, run a test. Requires inbox:stats for reachability; not implied by inbox:admin.

Scopes Accounts grants that Inbox does not recognise are ignored, not rejected. A key that also carries intelligence:* works fine here; those scopes simply grant nothing.

The two rules that surprise people

admin is a superset — but only on tenant-scoped routes. ScopeGuard treats admin as satisfying every @RequireScopes check. OperatorGuard does not: a cross-tenant route needs stats explicitly, because an admin key confined to one workspace must never be able to read the whole estate's figures.

operator:connections:write is meaningless on its own. It is checked on top of the stats reachability check, so a key needs both. Grant them together or not at all.

Registering the catalogue

A scope must exist in Accounts before a key can be issued with it. The service publishes its own catalogue:

cd apps/service && yarn register-scopes --app <appId|slug>

This is a full replace of the app's catalogue, so it always sends the whole list. It needs INBOX_ACCOUNTS_SERVICE_KEY to hold the native app-scopes:write scope, plus stats:read if you pass a slug rather than a UUID.