Primitive spec
Demerzel
The operator console. Demerzel is the human (and AI) interface to every other primitive — operator sign-in through Mannix, an MCP tool registry over the full platform, a visual asset editor with in-editor AI chat, multi-page tenant-facing sites, and an admin grid for Trantor, Terminus, Seldon, Hardin, Hober, and Mallow.
What it owns
Demerzel owns the surface where humans and AI agents see and edit Foundation state. Operator sign-in (now a Mannix relying party), the operator dashboard, the asset-authoring workflow, the AI chat loop with platform-wide tool calls, and the tenant-facing rendered sites that read from Radiant ui_view assets all live here.
Demerzel does not own domain state. It calls every other primitive's REST API (and MCP tools that wrap them) to read and write — Radiant for asset versions, Terminus for people and consent, Seldon for offers and bookings, and so on. Operator changes go through the same APIs an external integration would use.
Concepts
- Auth (Mannix relying party)
- Operator authentication moved to Mannix in a clean cutover: the console verifies Mannix-issued RS256 tokens and operators sign in with a password (plus optional TOTP MFA and passkeys) instead of the old magic-link-only flow. An Account → Security nav surfaces passkey + MFA enrollment, and act-as is a Mannix-issued scoped token. The legacy
User/AuthSession/ self-service-magic-link path is retired. Operator sessions are held in a fast shared store; staff can manage operators and invite an email to an existing tenant. - Tenant + Invitation
- A Demerzel
Tenantties an operator to a Foundation tenant id. Invitations are the on-ramp: someone on the waitlist gets an Invitation, and accepting it binds their Mannix principal to the tenant context. The waitlist endpoint accepts the form from latticekit.app/waitlist. - Signup
- The pre-tenant record of a self-serve signup: the email is proven by a single-use link, a card is put on file through the processor's hosted page, and the terms are accepted with a version stamp — only then are the Tenant, its billing profile and the owner created, in one step. The front door is a platform switch, invite-only by default, that staff flip at runtime without a deploy.
- Account + API keys
- A tenant reads its own plan, status and card on file and updates the card through the same hosted flow. An owner mints an API key for an MCP client — shown once, scoped, with an expiry and a daily call cap — which is what connects that client to Gaal.
- MCP tool registry
- A registry of Model Context Protocol tool providers, one per primitive. Each provider exposes the primitive's primary write and query operations as named MCP tools (
radiant_create_asset,terminus_search_persons,seldon_query_availability, …). The AI chat invokes them in a tool loop; operators get the same tools through the dashboard's command palette. Coverage spans the platform, and the tools are now auto-generated from the platformCapabilityRegistrythrough an MCP bridge rather than hand-written per primitive — the nine bespoke providers were retired onto it — with an exposure matrix gating which surface (customer, operator, staff, or AI) may call each capability. A 20-agent coverage audit then rebuilt Beth's primitive catalogue and exposed safe, non-sensitive reads across 18 primitives, so she can answer from live data nearly anywhere. - AI chat
Conversation+Message+ToolInvocationentities with a tool loop that calls a large language model. Conversation context probes tenant state, the user's current dashboard journey, and the open editor target to compose a system prompt. "Apply to editor" pipes a model proposal into the liveui_viewbeing authored. The assistant presents as Beth in the console.- Explorer (conversational onboarding)
- A guided first-run flow where Beth chats through what the business does, reads back the customer-facing details (subdomain, public URL, business + offer names) for explicit confirmation, then provisions the tenant from the captured blueprint and walks the operator through sandbox, branches + PRs, and experiments. Re-enterable any time from the side rail; an already-provisioned "Confirm & build" hands over to Beth's walkthrough rather than dead-ending. The build loop itself is now agentic: hard validation relaxed to integrity-only checks so Beth has design room, Beth triggers the build herself when the blueprint is ready, a second AI build critic confirms the design before provisioning, and a failed build routes back to Beth to fix and retry. She also recognizes stays / rentals / variable-length businesses and knows a duration from a cadence.
- The front door: describe, preview, demo, keep
- The public concierge at
/start. Someone describes their business in a chat; the concierge asks what it still needs and drafts a preview — the offers, hours, resources, staff and prices it would be set up with — shown as a website in a browser frame. From there they can have a live demo built: a real business at its own address, bookable, in about a minute, from one of the ten starters. It winds down after a week, or, if they create an account, it is promoted in place — the demo becomes the business, nothing copied and nothing rebuilt. The same door is an MCP surface for an outside assistant: the concierge, the preview, the demo, the signup and the grant are tools onPOST /agent/v1/signup(see the Agent API). - Media & Sign dashboards
- Operator surfaces for the newest primitives, built on the same per-primitive client + dashboard pattern. The Media library uploads (browser → signed
PUTstraight to storage, never proxied), browses, copies URLs, and deletes; the Sign console composes envelopes from a Media PDF, tracks signers, and manages provider configs. - Engineering Handbook
- A staff-only, codebase-derived handbook (every doc cites real file paths) rendered behind the staff gate at
/dashboard/admin/handbook— a section sidebar over a frontmatter-driven tree, with internal cross-links routed through a slug reader so they never 404. - Library + Sites + Pages
LibraryServiceindexes the tenant's Radiant assets. The dashboard's Library tab is the asset browser; opening one lands in a compose-preview editor with the in-editor chat.Site+Pageentities composeui_viewassets into multi-page tenant-facing surfaces, published viaPublishedSiteentries.- Render runtime
- Tenant-facing pages are served by a separate render runtime behind wildcard DNS. The runtime fetches the
PublishedSitegraph, resolves each Page'sui_viewvia Radiant, and SSRs the result with a built-in component catalog and server-side${binding.…}resolution + data-loader. Beyond the layout primitives it now ships data-bound components —booking_calendar(live Seldon surface),menu(live Hardin menu), and a no-JSdisclosure— and evaluatesifconditions as CEL. Operator authoring (Demerzel) and end-user rendering (render-runtime) are deliberately separate processes. - Demo businesses & dogfooding
- One command (
seed-demo-business) provisions four fully-populated verticals — salon, restaurant, fitness, courier — at stable subdomains, markedisDemo. A sharedActivitySeederdrives synthetic customers through the full Seldon lifecycle into Mallow invoices + double-entry ledger, MOCK-processor Payments, and consent-gated Speaker comms, so every real pipeline runs end-to-end (a seeded salon tenant lands ~880 bookings / ~477 paid invoices). ASiteBuildergives each demo business a real customer-facing home page — theme, hero, hours, and a live booking widget bound to its provisioned offer. - Page builder & layouts
- The Library is split into Templates / Widgets / Layouts / Themes, with a drag-and-drop canvas that composes Radiant
view_reflayouts from picked widgets, browse / Use / Fork over the platform template library, and a preview rendered by the real render-runtime. "Save as template" promotes a plain view into a parameterizable template, a reverse "used-by" lists the layouts that embed a widget, and CLI equivalents (compose-layout,attach-page) script the same operations. - Capability console & needs ledger
- Two operator surfaces over the newest platform plumbing. A staff capability console browses every registered capability; a tenant binding authoring UI wires an event straight to an outcome (the Daneel event→outcome bindings) with no workflow to write. And a needs-ledger view collects deferred obligations — approvals to grant, payments still pending, obligations outstanding — with the scheduled-timer and compensation history visible alongside.
- Business units, team & roles
- Multi-location support. Admins manage business units (CRUD over
settings.businessUnits) with a per-location activity breakdown, and hire from/dashboard/team— the roster drives the Terminus employee provisioner (hire / re-role / suspend / terminate). Underneath sits the platform role/permission keystone: per-operator console roles ride on the Mannix token, aPermissionGatewraps operator and per-location admin surfaces, and aSubTenantQueryScoperconfines a location-scoped operator's Person / Booking / Order / Invoice / subscription reads to their unit — sourced from the verified token claim, not a header. - Operator view on the public site
- An "Open operator view" button hands a console operator over to the tenant's own rendered site with a revocable render session (and an explicit exit). The render-runtime enforces server-side, view-level gating behind an airtight operator-mode boundary — public visitors and operators are split at the origin — and operator-gated components light up in place: a POS widget (a
posui_view component scoped to theRENDER_OPERATORfront-end class) and alive_tabswidget fed by Palver-pushed reads over an operator realtime token. - Data import & export
- The operator on-ramp to Korell: an import wizard with upload, AI-proposed per-file targets + mappings (editable), dry-run preview, and an inline run-in-chat card — or drag a data export straight onto Beth's chat and she proposes the plan. The export side is the Mallow export & statements UI: CSV, QBO journal, and PDF statement downloads behind per-capability gating.
- Admin grids
- Per-primitive table-style UIs for Trantor, Terminus, Seldon, Hardin, Hober, Mallow. Generated against the same DTOs the REST endpoints return; PATCH editor with echoed values on validation failure, schema visibility, and a JSON view per row.
- Tenant admin, act-as & demo tenants
- Staff can act as a tenant to debug or support it — a scoped, audited, time-boxed session (60-minute default, 240 max) carried on an opaque cookie and gated by a real JWT-backed staff check. It does not bypass Terminus consent or tenant policy. Staff can also spin up a throwaway demo tenant (
demo-…slug, 7-day TTL) and drop straight into it over the same act-as path. The admin surface includes a waitlist queue with status and free-text (?q=) search. - Sherpa autopilot
- The AI chat can drive the dashboard, not just describe it. A browser-tool transport (WebMCP) advertises UI tools —
ui_list_forms,ui_open_form,ui_fill_form,ui_submit_form,ui_navigate— to the model as native tool calls; the panel executes them and returns results. Three modes set how much autonomy it gets: Manual (confirm each step), Auto (fill and navigate, pause before submit), and On-rails (hands-off). The console's existing forms are wired touseSherpaForm, so Beth drives the real form — same validation, same submit path — rather than a parallel API. - Performance-review agent
- An on-demand or scheduled agent that reads recent Pelorat report runs, summarizes them to the model, and opens
DRAFTRadiant proposals (authorKind=AI) for the opportunities it finds. APerformanceReviewRunrecords the summary and the proposal ids; nothing applies until a human approves it on the standard review surface. - Live Activity
- A dashboard page that subscribes to Palver with the Centrifuge client and renders the tenant's real-time event stream — bookings, orders, invoices, and the rest — as they happen.
- Proactive insights & the feedback loop
- Beth doesn't only answer — it raises evidence-backed nudges from what it notices in a tenant's data. Operator feedback is captured as signals and clustered into Signal Themes, a ranked backlog the LatticeKit team works from, and a failure console pulls CI, nightly-tester, and production
HealthSignals into one dashboard so a regression surfaces in a single place instead of scattered logs.
API surface
Demerzel exposes both browser-facing routes (under /dashboard/…) and server-facing endpoints versioned under /demerzel/v1/. The headline ones:
| Method | Path | Purpose |
|---|---|---|
| POST | /demerzel/v1/waitlist | Accept a waitlist signup. Validates, stores, and acknowledges. |
| GET | /demerzel/v1/waitlist?status=&q= | List and filter the waitlist queue by status or free-text search (staff). |
| POST | /demerzel/v1/invitations | Issue an invitation for a waitlist entry; triggers magic-link email via Speaker. |
| GET | /accept?token=… | Route handler that exchanges a magic-link token for a JWT cookie. |
| GET | /demerzel/v1/signup/mode | Whether the front door is invite-only or self-serve. Public. |
| POST | /demerzel/v1/signup | Start a self-serve signup (business name, address, email) and send the verification link. 403 while the door is invite-only. |
| POST | /demerzel/v1/signup/verify | Redeem the emailed link; returns the continuation the later steps present. |
| POST | /demerzel/v1/signup/{id}/payment-method | Begin the processor-hosted card step; the browser is sent to the processor and back. |
| POST | /demerzel/v1/signup/{id}/complete | Confirm the card session and create the Tenant, its billing profile and the owner in one step; signs the browser in. |
| GET / POST | /demerzel/v1/account/billing[/payment-method] | The tenant's own plan, status and card on file; start and confirm an update of the card. |
| POST | /agent/v1/signup | Pre-tenant MCP endpoint: an AI assistant starts a signup for a person and, once the business exists, claims a scoped connection to it. See the Agent API. |
| GET / POST | /demerzel/v1/agent-grants | List the tenant's agent grants; mint an API-key grant for an MCP client (the key is shown once). |
| GET | /demerzel/v1/me | Current user + tenant context. |
| POST | /demerzel/v1/conversations | Open a new AI chat conversation. |
| POST | /demerzel/v1/conversations/{id}/messages | Append a message; the tool loop fires automatically. |
| GET | /demerzel/v1/mcp/tools | List registered MCP tools (introspection + AI chat input). |
| POST | /demerzel/v1/mcp/tools/{name}/invoke | Server-to-server invoke of a registered tool. |
| POST / GET | /demerzel/v1/sites | Create + list tenant Sites. |
| POST / GET / PATCH | /demerzel/v1/sites/{id}/pages | Manage Pages on a Site. |
| POST | /demerzel/v1/sites/{id}/publish | Snapshot a Site to a PublishedSite; the render-runtime serves from there. |
Example: invite from the waitlist
An operator pulls a waitlist entry into an invitation; Speaker sends the magic link; the invitee accepts and lands in the dashboard.
POST /demerzel/v1/invitations
Content-Type: application/json
Authorization: Bearer <operator-jwt>
{
"waitlistEntryId": "wl_01JAZB…",
"tenantId": "t_01J8K2…",
"role": "operator"
}
→ 201 Created Invitation inv_01JAZC…
Speaker queues the invitation email to the invitee
# Invitee accepts, sets a password, and signs in through Mannix
GET /accept?token=eyJ…
→ 302 /dashboard
Set-Cookie: LK_SESSION=<mannix-issued>
How it fits with the rest
flowchart LR
Op[Operator / AI agent] --> De(Demerzel)
De -- MCP tools --> R[Radiant]
De -- MCP tools --> S[Seldon]
De -- MCP tools --> T[Trantor]
De -- MCP tools --> Te[Terminus]
De -- invitation email --> Sp[Speaker]
De -- publish --> RR[Render runtime]
RR -- resolve ui_view --> R
Demerzel calls every primitive's REST API, packaged as MCP tools so an AI agent can compose them. Outbound auth email goes through Speaker (the sign-in path is a recorded exception to the consent gate; everything else respects it). Published tenant sites live in Radiant as ui_view assets and are SSR'd by the render-runtime — Demerzel doesn't render end-user pages itself.