Browse documentation
Getting started

Organizations & roles

The tenant boundary, the five roles and what each one can do, per-member overrides, and how an invitation actually works.

An organization is the tenant boundary. Stores, billing, credits, conversations and audit logs all belong to one, and nothing crosses between two.

A user can belong to several. The URL says which one you are in: /<orgSlug>/... for the organization, /<orgSlug>/<storeSlug>/... for one of its stores.

The five roles

| Role | Stores | Billing | Members | AI | |---|---|---|---|---| | Owner | read, create, edit, delete | read + manage | read, invite, remove | run, approve tools | | Admin | read, create, edit | read | read, invite | run, approve tools | | Member | read, edit | read | read | run, approve tools | | Viewer | read | read | read | — | | Delegate | nothing by default | | | |

Two rows deserve a sentence each.

Viewer cannot use the AI. It is the only role without ai.use, and that is the point of the role: a stakeholder who should see the numbers without being able to spend the credit balance.

Delegate has an empty baseline, by construction. It is the role for a mandated outside party: an agency, a freelancer working inside a client's organization. It holds exactly what an explicit grant gives it and nothing by virtue of existing. A guard checks every registry entry for this, because the tempting change is to add one permission "for consistency", and that is the change that would quietly open the door.

Per-member overrides

The role is a baseline, not a ceiling. OrganizationMember.permissions carries { allow: [...], deny: [...] }: allow adds on top of the baseline, deny strips from it. An admin edits this from the member matrix.

Permissions are dotted strings (store.read, billing.manage, members.invite, agent.run, ai.use, workspace.write), and the list is open: a new one needs a registry row, not a migration.

Two families the baselines do not carry

studio.* — the creative production chain. An organization that does not do Studio work should not hand creative powers to its members just because they are members, so no non-owner baseline includes them. They arrive through a Studio role preset or an explicit per-member allow. The owner keeps them: the production is the product, and the owner owns the brands.

agency.* — seven permissions covering prospecting, Go/No-Go gates, production verdicts and per-brand margin. These are how BoostEcom operates brands on behalf of third parties, not something sold to a merchant. They are the only family excluded from the owner short-circuit and absent from the owner baseline. Both are needed: removing one without the other is a silent no-op, because an owner stripped of the short-circuit would fall back to the baseline and get the permission back.

Invitations

An invitation is a durable row, not a link you can forge.

  • The email carries a one-shot token; only its sha256 hash is stored.
  • It expires after 7 days.
  • It is revocable instantly (DELETE /api/organizations/invite), which kills the link.
  • The token is not enough. Accepting requires a signed-in session whose email matches the invited address, so a forwarded link is useless to anyone but the intended recipient.

Re-inviting the same address refreshes the row (new token, new expiry, accepted/revoked state reset — rather than piling up invitations.

The landing page is /invite, reached with ?token=.

What this replaced

The previous scheme was a tokenless ?org=&email= link. Anyone could construct one, and there was no acceptance endpoint at all.

Built on these docs?

Drop into the forum if something's unclear or wrong. Docs improve faster when readers flag the gaps.

Open the forum