Skip to content

Provisioning tenants ​

Who this is for: Platform operators
What you'll achieve: Create a blank school tenant with an owner login

Every tenant starts blank: no example school data is injected. Seeded defaults include grades, capabilities, duty types, and default notification rules/templates.

Option A: Web operator console ​

  1. Configure SSO at Operator → Configuration → SSO, and keep one admin with a password for break-glass. Use OPERATOR_AUTH_DISABLED=1 only locally.
  2. Open /operator/login and sign in with SSO or your operator account. Roles come from IdP groups or the Admins tab (platform_admin, support, readonly).
  3. Use the sidebar: Overview, Provision school, Schools & flags, Support access, Audit log, Configuration (items appear based on your role).
  4. New schools get AI assistant chat on with a daily usage allowance. To turn it off: Schools & flags → select a school → AI & helpers.
  5. Share https://{host}/t/{subdomain}/login and owner credentials.

See Operator SSO and access levels.

Option B: CLI ​

Create a named token at Operator → Configuration → API tokens, then:

bash
export OPERATOR_TOKEN=your-named-token
pnpm tenant:create -- --subdomain riverside --name "Riverside Primary" --email admin@riverside.test --plan trial --seats 50

Option C: Self-serve (Stripe) ​

Schools sign up at /signup → Stripe Checkout → webhook creates tenant and emails welcome credentials. See Sign up and start your trial and docs/BILLING_AND_HOSTING.md in the repository.

Signup supports single school and trust / MAT (multiple sites) organisation types. Trust signups create one portal with at least two school sites; each site runs its own setup wizard. See docs/MULTI_SITE_AND_ORGS.md.

Feature flags (operator) ​

Post-pilot and pilot-tier features are controlled per tenant in Schools & flags (/operator/tenants → select a school):

FlagPurposeWhen off
analyticsAnalytics nav and APIAnalytics hidden/disabled
ai_importSetup copilot, staff import mapping, board polishTools hidden
ai_assistantFloating AI assistant chat (approve-before-apply). On by default for new schools, with a daily token allowanceLauncher hidden; chat blocked
ssoSingle sign-on buttons and OIDC loginEmail/password only
scimSCIM token provisioningSCIM endpoints return 403
outlook_calendarAdmin → Outlook calendar integration. On by default for new schoolsIntegration hidden; no Graph sync
entra_profile_photosAdmin → Microsoft profile photos. On unless you turn it offIntegration hidden; initials only
google_calendarAdmin → Google Calendar integrationIntegration hidden; no Calendar API sync
multi_siteMulti-site UX (site switcher, scoped routes)Single-site behaviour
smsSMS notification channel (reserved)Not used yet

You can also pass flags when creating a tenant via API:

json
POST /api/operator/tenants
{ "featureFlags": { "outlook_calendar": true, "analytics": true, ... } }

Or toggle an existing tenant:

http
PATCH /api/operator/tenants/{tenantId}/flags
{ "outlook_calendar": true, "analytics": false }

School admins see disabled features as hidden nav items or an explanatory message - not a hard error.

Support impersonation ​

Platform operators can open a 1-hour audited session as a school user for troubleshooting. See Support impersonation.

After provisioning ​

  1. Sign in
  2. Complete Initial setup
  3. Import staff (respects seat limit)
  4. Run the go-live checklist

Subscription cancel feedback ​

When a school owner cancels from the billing portal, Stripe collects a reason and optional comment. That survey is stored on the school and shown on Schools & flags → school, under portal status. The support mailbox (and the signup notify address) also get an email. You can still open the subscription in Stripe if you need the raw event.

Plans and seats ​

  • Hard seat limit on active rota people
  • Trial: plan=trial, trialEndsAt defaults to +30 days for new tenants
  • Stripe-linked tenants: plan/seats sync via webhooks

What happens next ​

SchoolRota documentation. Every slot covered, every day.