Skip to main content

Workspaces and members

Nerve isolates data by workspace. Every API key, provider credential, notification template, subscriber record, and delivery event belongs strictly to one workspace.

Tenant boundary isolation

Tenant isolation is enforced in depth across every layer of the architecture:

  • Database row-level security: The database itself enforces workspace scoping on every query; a query that is not scoped to exactly one workspace returns nothing. No application bug can expose one workspace's rows to another.
  • Namespaced caches: Rate-limit and idempotency state is partitioned per workspace, so one workspace's traffic cannot affect another's limits or deduplication.
  • Per-tenant circuit breakers: Upstream provider failures are tracked per workspace and provider, ensuring one workspace's provider error never trips breakers for another tenant.

Roles and permissions (RBAC)

Every user in a workspace holds one of three roles, governed by an immutable RBAC matrix:

ActionOwnerAdminMember
Manage Billing & Paystack SubscriptionYesNoNo
Delete Workspace / Transfer OwnershipYesNoNo
Manage Team Members & InvitesYesYesNo
Create & Revoke API KeysYesYesNo
Configure Provider Credentials & TestYesYesNo
Create, Update, & Delete TemplatesYesYesNo
View Messages, Timeline, & AnalyticsYesYesYes
Export Subscriber Data (NDPR Access)YesYesYes
Preview Template RenderingYesYesYes

Owner protection

A workspace must always have at least one owner. Demoting or removing the final owner is rejected by the control plane with 400 BAD_REQUEST.

Immediate session revocation

When a user is removed from a workspace, all active sessions for that user scoped to that workspace are immediately revoked in the database.

Inviting team members

Team members are invited via email through the dashboard or control plane:

curl -X POST https://console.nervly.io/console/invites \
-H "Cookie: nerve_session=$SESSION_COOKIE" \
-H "X-CSRF-Token: $CSRF_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "engineer@example.com",
"role": "admin"
}'
  • 7-day expiration: Invite tokens are 32 cryptographically secure random bytes valid for exactly 7 days.
  • Token hashing: Raw tokens are stored as SHA-256 hashes in PostgreSQL; tokens are never logged.
  • Acceptance flow: Invites can be accepted by existing signed-in users or newly registering users via POST /auth/invites/accept.

Next