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.
| Folder | src/modules/settings/ |
| Migrations | migrations/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 tabsettings.staff.write— add / edit / disable staffsettings.permissions.write— change role grantssettings.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
- Three strata — Kernel · Meta · Modules
- Customers module — the first business module
- Permission entity — the domain model
- Staff entity — the role grants hang off this
- Audit everything — every staff/permission mutation lands in the chain