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 — they skip rows that already exist.

Data model

Account rows are created only for plugins with an authType (api_key, oauth_2, bot_token). A tenant is any stable ID you choose — user id, org id, workspace slug.

setupCorsair

Call it from your backend, most often on signup — 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, processOAuthCallback 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 — provision 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.