Skip to main content
Provisioning creates the database rows, DEKs, and credential slots Corsair needs before a tenant can connect. The same logic runs two ways: setupCorsair from your backend (on signup, in production) and pnpm corsair setup from the CLI (local and ops). Both are idempotent, so they skip rows that already exist.

Data model

Account rows are created only for plugins with an authType (api_key, oauth_2, bot_token, managed). A tenant is any stable ID you choose: user id, org id, workspace slug. Provisioning touches only these two credential tables. The other three (entities, events, permissions) are covered under Database and Permissions.

setupCorsair

Call it from your backend, most often on signup, with no deploy per tenant.
onboarding.ts
The same call covers single-tenant, credentials, and backfill:
It returns a log string and skips existing rows.

What it creates

CLI

Same provisioning from the terminal, for local setup and ops:

Credentials

Integration-level: shared OAuth app creds, one per plugin:
Account-level: per tenant, for api_key / bot_token fields and OAuth tokens:
keys.set_*() needs an account row first. Run setupCorsair({ tenantId }) before setting API keys.
Multi-tenant: passing integration fields together with a tenantId in setupCorsair({ credentials }) throws. Set integration creds without a tenantId.

Multi-tenant

corsair.ts
Every runtime call goes through corsair.withTenant(id). See Multi-tenancy.

OAuth

Provisioning does not run OAuth; it prepares the rows. Tokens arrive when a user connects. After integration creds are set:
Or in app code, corsair.manage.connect.oauthCallback stores the tokens and creates the account row lazily if missing. This is the OAuth-only path. You can skip setupCorsair({ tenantId }) on signup and let the first connect provision the row. API keys still need setupCorsair first.

Adding a plugin later

Plugins come from createCorsair({ plugins: [...] }), so adding one is a code change and deploy. After deploying:
Multi-tenant provisioning of the new plugin for existing tenants (each still authorizes it separately; rows are not copied):
Removing a plugin from code does not delete its database rows.
corsair.manage.tenants.create() records a tenant but does not create account rows. Use setupCorsair or the CLI to provision.