Skip to main content

Settings module

The Settings tab — the admin surface for the operator Hub. Gated behind the settings.* permission family; staff without the right grants don't see the tab at all.

Foldersrc/modules/settings/
Migrationsmigrations/008_identity_substrate.sql, migrations/009_staff_fields.sql

What it does

Users + Staff management. Add a new staff member. Set their role. Reset their PIN. Disable an account. Re-enable one. Every action lands in the audit chain.

Read-only Permissions matrix. A matrix view showing every role × every permission key. Read-only on purpose — granular per-key editing happens through staff overrides, not bulk role rewiring. The matrix is the map of what each role can do; mutations route through specific Edit flows.

Shop config. The shop's identity (name, address, timezone, currency), branding, and integration secrets (Stripe key, Twilio creds, etc.) — anything that doesn't have a visible on-screen representation to edit in place.

Discount builder

The Discount builder is a 3-step authoring flow for customer discounts (migrations 012-014). Each rule has a name, a value (percent or fixed amount), and an applies-to target — Sales, Service, or both. Per-department assignment is validated server-side; an operator can't accidentally hand a customer a Service discount that the Sales till would also honour.

Once authored, a discount is assigned per-customer on the customer card. The Sales / Service tills (when built) read the assigned discount at checkout. This replaces the older A/B/C pricing-tier mechanism — pricing_tier is dormant in the schema; new customers start fresh with no tier mapping.

See Customers module for how the assignment renders on the customer card.

Why the matrix is read-only

The doctrine: mutations of structural things route through specific Edit flows, not through bulk-grid editing. A bulk grid invites the operator to flip a checkbox they don't fully understand, then ship a permissions change that breaks an unrelated workflow. Read-only forces the operator into the focused Edit popup for each role / each staff override, which carries the context (which permission, what does it do, what depends on it).

This is the no-inline-editing section-pill pattern applied to permissions: the matrix is the display, the per-role popup is the editor.

Permissions

The Settings module is gated by:

  • settings.read — see the tab
  • settings.staff.write — add / edit / disable staff
  • settings.permissions.write — change role grants
  • settings.shop.write — change shop-level config

These are seeded in migrations/007_permissions.sql and resolve through core/perms.ts.

How it composes with the Kernel

Same Module interface as every other module. Self-contained: index.ts registers the module; view.ts carries the markup; client.ts is the browser JS; api.ts handles the routes at /api/settings/*.

See also