System logic

Platform settings

Platform settings

Everything the platform team configures without a deploy, at /admin/settings. One section in the sidebar, several pages behind a sub-navigation rail (docs/ui-ux-spec.md §7.6). Last updated 2026-09-04.

1. Pages

PageWhat it holds
GeneralPublic name, support email, and the AI provider every copilot and AI feature routes through
Service plansThe commercial plans offered to schools and to vendors
ModulesOptional platform capabilities, each a toggle row with its own settings
EmailEvery email type: on/off, and the template with its version history (docs/email.md)
Trial creditsGuardrails on pilot economics, with live spend against the cap
Platform usersEduSpaze admin accounts
BillingHow payments work in production, and the annualised value of the configured plans

2. Where values live

Simple values live in the Setting key/value table and are described once in lib/settings/registry.ts: label, type, default, bounds and help text. The settings pages render from that registry, so adding a setting is a line there plus wherever it is read. lib/settings/index.ts provides readSettings, writeSettings, isModuleEnabled and numberSetting; a key that was never written falls back to its registry default.

Service plans are a table (ServicePlan), because a plan has several fields and a list of benefits.

3. Modules

A module is a capability that can be switched off. Switching it off hides it and stops its behaviour; nothing it already recorded is deleted, and its settings keep their values.

ModuleKeyWhat the switch doesSettings while on
Parent accessparent_access_moduleMakes the guardian portal available. Each school still has its own switch, so this only makes it possible
Engagement trackingengagement_trackingOff refuses heartbeats (/api/telemetry/heartbeat returns 503) and stops new sessions being measuredInactivity gap, launch-only minutes, heartbeat interval — the platform defaults a school inherits when it has not set its own
EduSpaze support sessionssupport_sessionsPlatform kill switch for support sessions: off, no session can start even where a school has allowed accessMaximum session length
Public registrationpublic_registrationOff closes /register/* and turns every "register" call to action on the public site into Contact us for more info, pointing at /contactSchools may register · Vendors may apply, independently
Challenge publishingchallenge_publishingOff closes the challenge channelThe mode: approve before publishing · publish immediately · let AI screen (docs/email.md §6)
Escalation alertsescalation_alertsOff stops the ageing checks emailing the platform teamA threshold per check (docs/email.md §7)

4. Service plans

A plan is the commercial description of a tier the platform already enforces (SchoolTier for schools, StartupTier for vendors), so editing a plan changes what a tier is called, what it costs and what it promises, and never introduces a second source of truth about entitlement. One plan per audience is the default assigned on signup. A plan with customers on its tier cannot be deleted.

5. Audit

Every settings write, plan change, module flip and platform-user action goes through the audited client, so it lands on the platform audit chain with the admin as actor and the before and after values (docs/audit-trail.md). Setting and ServicePlan are PLATFORM-scoped, so they appear in Admin → Audit, not in a school's log.

6. Guardrails on platform users

Everyone under Platform users has full access to every school and vendor. Two rules stop the platform locking itself out or being quietly taken over:

  • You cannot disable or reset your own login there — use Account & settings.
  • The last active admin cannot be disabled.

7. Adding a setting

  1. Add the field to lib/settings/registry.ts (a module's fields, GENERAL_FIELDS or CREDIT_FIELDS) with a label, type, default and bounds.
  2. Read it with readSettings / numberSetting / isModuleEnabled where it applies.
  3. Seed a value in prisma/seed.ts if the demo should show something other than the default.

No page changes are needed: the settings pages render from the registry.

Source: docs/platform-settings.md in the repository. Last updated with the code it describes.

Platform settings — EduSpaze