wisewigdocs

Authorization

Authorization is evaluated for every command after identity resolution and before document access. Public rendering does no session lookup.

MembershipAuthorizer is the host-neutral reference implementation for this sequence. It requires a tenant-scoped identity, confirms tenant membership from the authoritative membership store, resolves current site roles, and only then evaluates the permission. It never treats a browser’s site-role claim as authorization for an arbitrary site. Agency roles can authorize within their tenant after membership is confirmed.

On Cloudflare, D1ControlPlane is the authoritative membership-store implementation. Tenant agency roles and client site roles are stored separately so a client-editor claim on one site cannot grant access to another.

Scope order

  1. Resolve the agency tenant from the request/site mapping.
  2. Resolve agency membership.
  3. Resolve site membership when the action is site-specific.
  4. Test the explicit permission required by the command.
  5. Record the actor, scope, command, and result in the audit trail.

Roles

Agency roles are agency-owner, developer, account-manager, and support. Site roles are client-owner, client-editor, and viewer.

The permission vocabulary in @wise-wig/contracts is the source of truth. Support impersonation must create an auditable, time-bound session and never silently inherit publish or domain-management authority.

Required controls

  • Short-lived signed sessions; OAuth/OIDC with PKCE for the browser extension and Studio.
  • Cookie-authenticated mutations require exact same-origin and Fetch Metadata checks before guarded command execution.
  • Every mutation has a tenant ID, site ID where applicable, actor ID, expected document version, and idempotency key.
  • Every mutation uses the shared guarded command path, checks its declared permission, records a succeeded/denied/replayed audit event, and requires confirmation for consequential effects.
  • Publish, delete, theme switch, plugin install, domain changes, and outbound effects require elevated permission and explicit confirmation.
  • A plugin receives a narrower capability set than the actor who invoked it.