Authorization — permissions and roles
What your application declares, what Connect resolves, and why Connect never enforces your permissions for you.
Connect answers two different authorization questions, and it is worth being precise about which is which:
- May this workspace use this application at all? Connect answers that itself — audience, verification, subscription state, sign-off. You read the answer from the readiness endpoint or the SDK's access gate.
- May this member do this thing inside your product? Connect resolves the answer and hands it to you. It never enforces it. Your backend does.
That second sentence is the whole contract. Connect does not know what
campaign:publish means, and it never checks it — most applications on the
platform are external products with their own datastores.
Permissions
A permission is a capability your application can grant, declared in its own catalogue and namespaced by the application key:
pulse_email:campaign:manage
pulse_email:template:read
pulse_email:domain:verifyThe convention is <key>:<resource>:<action>. The <key>: prefix is added for
you; you declare the rest.
Permission ids are free-form after the prefix, with two reservations:
platform:* is refused, and so is any collision with a Connect built-in.
Roles
A role is a named subset of your permission catalogue that a workspace can
assign to a member: app:<key>:<roleKey>.
admin is reserved and always exists. It is synthesised rather than
stored, and it resolves to your entire catalogue — including permissions you
add later. That last part matters: a customer's admin gets a new permission the
moment you declare it, with no action on their side.
Every other role is one you define. A role key is permanent for the same reason a feature key is: renaming it orphans every member already assigned it.
What arrives at sign-in
The token exchange carries the resolved list:
const session = await getConnectSession();
if (!session.permissions.includes("pulse_email:campaign:manage")) {
return new Response("Forbidden", { status: 403 });
}granted is already flattened — Connect has resolved the member's role, the
admin synthesis, and any custom workspace role scoped to your application,
and handed you the final list. You do not walk roles; you check permissions.
Check on the server, on every request that matters. The granted list is a statement about what the user may do, not a guarantee that they only tried those things. Hiding a button is a courtesy; the check behind it is the control.
What a workspace controls, and what you control
You declare the vocabulary. The workspace decides who gets what.
| Declared by | Changed in | |
|---|---|---|
| Permission catalogue | you (the application) | Console → your application → Authorization |
| Roles beyond Admin | you (the application) | Console → your application → Authorization |
| Which member has which role | the customer | their workspace's Team page |
A workspace cannot invent a permission you have not declared, and a member's grant can never exceed what the person granting it already holds.
Deleting a permission
Deleting one removes it from every role that references it, in the same write — there is no window in which a role points at a permission that no longer exists. Members holding an affected role lose the capability the next time their access is resolved, which is at their next sign-in, not immediately.
Plan for that gap. If a permission is being removed for a security reason rather than a tidy-up, revoking sessions is the mechanism that takes effect now.
Not to be confused with
- Features — unlocked for a subscription, not a member. A member without
campaign:manageon a plan that bundlescampaign_buildersees a product that has the feature and a person who may not use it. Both checks are real and neither substitutes for the other. See Capabilities. - Connect's own platform permissions — what a CosmoOps console operator can
do. Nothing to do with your application's catalogue, which is why
platform:*is a refused prefix.
Capabilities — features, limits and add-ons
What a plan unlocks, how much of it a tier allows, what a customer can buy on top, and why behaviour lives on the application while price lives on the plan.
Deletion policy
What your application declares it keeps when a customer deletes their workspace, who answers for it, and what your integration has to do about it.