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.
bootstrap-dev that stand up four fully-populated verticals; and a page-builder Library (Templates / Widgets / Layouts / Themes) with a drag-and-drop layout canvas and live render-runtime preview. Newest: operator sessions are Valkey-backed, the MCP tools are auto-generated from the platform capability registry, and operator surfaces shipped for capability bindings and the needs ledger. Latest (June 6–11): multi-location businesses — business units with claim-sourced isolation, a team roster with hire / re-role / suspend / terminate, and per-operator console roles behind a platform PermissionGate; an "Open operator view" handoff that puts scoped operator tools (a POS widget, live tabs) on the tenant's own site; the Korell import wizard (or drag a data export onto Beth's chat); Mallow export & statement downloads; and Beth's capability coverage rebuilt in three waves after a 20-agent audit.
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 Valkey-backed; 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. - 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 the Anthropic API. 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 and defaults to Sonnet 4.6.- 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.
- Media & Sign dashboards
- Operator surfaces for the newest primitives, built on the same per-primitive client + dashboard pattern. The Media library uploads (browser → S3 presigned
PUT, 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 ECS service behind an ALB with 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, orbootstrap-devfor a whole environment) 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 (Next.js, 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/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 via SES
# 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.