Appearance
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
- Configure SSO at Operator → Configuration → SSO, and keep one admin with a password for break-glass. Use
OPERATOR_AUTH_DISABLED=1only locally. - Open
/operator/loginand sign in with SSO or your operator account. Roles come from IdP groups or the Admins tab (platform_admin,support,readonly). - Use the sidebar: Overview, Provision school, Schools & flags, Support access, Audit log, Configuration (items appear based on your role).
- New schools get AI assistant chat on with a daily usage allowance. To turn it off: Schools & flags → select a school → AI & helpers.
- Share the school portal URL (for example
https://riverside.schoolrota.com) 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 500Option C: Self-serve (Stripe)
Schools sign up at /signup → verify their school email → create a password → activate a 30-day no-card trial. Card checkout is available later in Admin → Billing. See Sign up and start your trial, No-card trial playbook, 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):
| Flag | Purpose | When off |
|---|---|---|
analytics | Analytics nav and API | Analytics hidden/disabled |
ai_import | Setup copilot, staff import mapping, board polish | Tools hidden |
ai_assistant | Floating AI assistant chat (approve-before-apply). On by default for new schools, with a daily token allowance | Launcher hidden; chat blocked |
sso | Single sign-on buttons and OIDC login | Email/password only |
scim | SCIM token provisioning | SCIM endpoints return 403 |
outlook_calendar | Admin → Outlook calendar integration. On by default for new schools | Integration hidden; no Graph sync |
entra_profile_photos | Admin → Microsoft profile photos. On unless you turn it off | Integration hidden; initials only |
google_calendar | Admin → Google Calendar integration | Integration hidden; no Calendar API sync |
multi_site | Multi-site UX (site switcher, scoped routes) | Single-site behaviour |
sms | SMS 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.
Customer health
Schools & flags and the operator overview show whether a school has set up, and whether people are actually using it.
| Signal | Meaning |
|---|---|
| Setup stage | Not started, Setting up, Ready to go live, or Live (from the school's wizard) |
| Usage | Never signed in, In setup, Actively used (recent sign-in and published rota), Signed in with no recent rota, or Dormant |
| Needs attention | Paid but not live after 3 days, trial unused after 7 days, setup stuck after 7 days, live with no sign-in for 21 days, or a subscription that is ending |
Last sign-in comes from login audit events. Last published comes from published duty boards. Staff seats are active people against the plan limit.
Open a school for the full snapshot, then use Support impersonation if you need to help them finish setup.
See Customer health.
After provisioning
- Sign in
- Complete Initial setup
- Import staff (respects seat limit)
- 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,trialEndsAtdefaults to +30 days for new tenants - Stripe-linked tenants: plan/seats sync via webhooks

