Docs
/

Leumas Admin

@leumas/admin

Leumas Admin — the CONTROL PLANE. Leumas staff only: licence issuing, EXE distribution, the customer fleet, platform trust & safety. Never ships to a customer; runs only where LEUMAS_ROLE=control.

Leumas Admin — @leumas/admin

The control plane. Leumas staff only. Every Leumas user, contact, licence, install, submission and job — one console.

admin.leumas.tech · LEUMAS_ROLE=control · dev port 5100 · never ships to a customer. Architecture: CONTROL-PLANE.md · APPLIANCES.md §6


Core functionality

  1. Overview — the pulse on one screen: MRR, active installs, DAU, pending reviews, failed

webhooks, incidents.

  1. Accounts — every Leumas user, their memberships and Stripe state, their licences. Comp a plan,

run a trial, replay a failed webhook, revoke a licence.

  1. Fleet — every Studio install: version spread, last-seen, storage, health. The opt-in studio

directory and the studio-to-studio relay log.

  1. Marketplace — the app store review desk: submissions, approve/reject, sign & publish, listings,

publishers and payouts.

  1. Distribution — releases: Studio EXE channels and rollout %, iOS release records, the

minimum-supported-version gate, the update feed.

  1. Analytics — traffic across the whole ecosystem. Full detail for Leumas's own sites; aggregates

for customer instances.

  1. Trust & safety — moderate what people publish to Leumas: Social, Marketplace, rooms, and

the accounts behind them. Contact inbox and job requests.

What it must never do

NeverBecause
Be loaded by a customer's browser or Studioit's staff infrastructure. Customer-facing pages live on leumas.tech and call api.leumas.tech
Edit a site's contentthat's a tenant-admin action → Studio. Deep-link out instead
Put three on the EAGER graphthe domain rooms are real 3D (owner call, 2026-08-11 — this console gets full Studio parity), but the renderer stays behind @leumas/domain-kit/room's lazy boundary. pnpm check:deck and the entry-graph check in §Verify are what keep it there
Mount the Leviathan widgetassistant={false} in App.jsx. Its page-capability tools drive the page they are on, and the pages here revoke customer licences
Grow bespoke componentsfour in _shared/, everything else from @leumas/ui
Gate on role === 'control'gate on caps.staffPlane, or that property quietly dies

Security — four independent layers

LayerMechanismCost
1 EdgeCloudflare Access / IP allowlist / mTLS. A non-staff request never reaches Nodeinfra config
2 Separate staff sessionLEUMAS_COOKIE_NAME=leumas_staff and no LEUMAS_COOKIE_DOMAIN → a host-only cookie under a different name. A stolen customer session is not a staff sessiontwo env vars
3 Role + planeisStaff = roles.includes('leumas_staff') && isControlPlane(). Both halves requiredexists
4 Grant lockgrantRole refuses leumas_staff off-planeexists
# admin.leumas.tech only
# LEUMAS_COOKIE_DOMAIN deliberately UNSET
LEUMAS_COOKIE_NAME=leumas_staff
LEUMAS_SESSION_TTL_HOURS=8

Same Login component, same users table, a cookie that exists nowhere else. That is the "separate admin login", and it costs no code.

Design language

  • One UI kit@leumas/ui (st- kit). pnpm check:ui-kit ratchets regrowth.
  • One theme@leumas/theme. Never a literal near-black/near-white — pnpm check:theme.
  • Command Deck home — 7 tiles, each with a live number. The home screen is the status page.
  • Cmd/KnavToCommands(resolveNav(VENDOR_NAV)). Already exists, free.
  • One table, one drawer — every list is VendorTable, every row opens the same drawer. Learn it

once, use it seven times. The single biggest lever on "feels light".

  • One customer, one pageCustomerCard shows account + membership + licences + instances +

purchases together. Four surfaces, one component.

  • Density over decoration — numbers, tables, one accent colour for "needs you".

Composes

@leumas/ui  @leumas/theme        the st- kit + tokens
@leumas/features                 RequireStaff · providers · guards · RouteTabs
@leumas/api-client               every HTTP call
@leumas/config-registry          defineNavManifest · resolveNav · navToCommands
@leumas/domain-kit               the domain DOOR: routes, aside, crumbs, ⌘K, the overview HUD
@leumas/entity-kit               the room's body/idle/approach vocabulary

Six packages, and the fifth is the one that matters: this console does not own its own admin shell. @leumas/domain-kit is the same code Leumas Studio renders, so a staff member moving between admin.leumas.tech and a customer's install is using one console with two sets of contents. If a control-plane surface needs something the door cannot express, the fix goes in the package and Studio gets it too.

The shape of a domain

/                     Overview — the pulse deck
/d/fleet              the DOOR: a deck of Fleet's sections over a room of live installs
/d/fleet/overview     the tile grid, kept as a place you can go
/fleet                FleetHub, tab '' → surfaces/fleet/Instances.jsx
/fleet/directory      FleetHub, tab 'directory'
/fleet/relay          FleetHub, tab 'relay'

Five files own a domain, and node ops/tools/domain-scaffold/index.mjs --product admin --domain <id> writes four of them from the manifest:

FileWhat it is
<domain>/model/tabs.jsTHE tab list. Pure data — the manifest, the strip, the deck and the aside all read it
<domain>/hud/overview.jsthe door's spec, pure data. check:huds imports it in bare Node
<domain>/hud/<domain>Populators.jsthe room's cast. Contracted never to reject
<domain>/hud/<Domain>Hud.jsxthe door
<domain>/pages/<Domain>Hub.jsxthe tab strip + the panels, which are the untouched surfaces/ pages

Then one manifest entry (hub(...)) and one LANDINGS line in AdminRoutes.jsx.

File tree

products/leumas-admin/
├── package.json [done] [warning] UNTRACKED IN GIT
├── vite.config.js [done] port 5100 · narrow proxy (NO /leviathan /mcp /library)
├── index.html [done]
├── README.md [done] this file
└── src/
 ├── main.jsx [done]
 ├── App.jsx [done] every route behind <RequireStaff> + a standing PlaneBadge
 ├── WrongDeployment.jsx [done] provider-free fallback on the wrong role
 ├── nav.manifest.js [partial] VENDOR_NAV: 4 domains → 7
 ├── AdminRoutes.jsx [todo] derived from the manifest, same pattern as Studio
    ├── _shared/
 │ ├── VendorTable.jsx [todo] list + filter + drawer. THE table
 │ ├── CustomerCard.jsx [todo] account+membership+licences+instances. Used by 4 surfaces
 │ ├── ReviewPanel.jsx [todo] approve/reject + reason. Submissions and Trust
 │ └── useVendor.js [todo] the 3 fetch hooks (list / detail / act)
    └── surfaces/
 ├── Overview.jsx [todo] the pulse deck
        ├── accounts/
 │ ├── Directory.jsx [partial] from Accounts.jsx
 │ ├── Memberships.jsx [todo] comp · trial · replay a failed webhook
 │ └── Licences.jsx [partial] from IssuedLicences.jsx
        ├── fleet/
 │ ├── Instances.jsx [todo] version · last-seen · storage · health
 │ ├── Directory.jsx [todo] opt-in studio directory
 │ └── Relay.jsx [todo] studio<->studio envelope log + rate limits
        ├── marketplace/
 │ ├── Submissions.jsx [todo] the review queue
 │ ├── Listings.jsx [todo] published apps · unpublish · pricing
 │ └── Payouts.jsx [todo] publisher earnings
        ├── distribution/
 │ ├── Releases.jsx [done] Studio EXE builds
 │ └── Channels.jsx [todo] stable/beta · rollout % · min iOS version
 ├── Analytics.jsx [todo] ecosystem · sites · instances
 └── TrustSafety.jsx [done] moderation queue

~20 files, 4 shared components. That's the whole console.

Backing service

shared/services/control/ [todo] @leumas/control — mounted at /control when caps.staffPlane
└── src/
    ├── router.js                   ALL behind requireStaff
    ├── overview.js                 the pulse aggregation (one query set, cached 30s)
    ├── fleet.js                    instances · opt-in directory · relay log
    ├── analytics.js                ecosystem + rollup reads
    └── moderation.js               thin — delegates to router-kit's social-moderation

Roadmap

[todo] V0 · Commit it

  • Status: todo — git add products/leumas-admin — every file is ?? today. A git clean deletes it

[todo] V1 · Deploy the plane (roadmap A2)

  • Status: todo — admin.leumas.tech at LEUMAS_ROLE=control + this SPA
  • Status: todo — The two cookie env vars above
  • Status: todo — Edge restriction: Cloudflare Access / IP allowlist / mTLS

[todo] V2 · The 7-domain shell (roadmap A4)

  • Status: todo — VENDOR_NAV → 7 domains; AdminRoutes.jsx; the four _shared/ components
  • Status: todo — Reorganize surfaces into accounts/ fleet/ marketplace/ distribution/
  • Status: todo — Overview.jsx with live numbers
  • Status: todo — [warning] Route names must not collide with API namespaces: /licences not /licensing,

/market not /marketplace — the dev proxy forwards those, so a navigation gets the API's 404

  • Status: todo — @leumas/control service

[todo] V3 · Fleet (roadmap A3)

  • Status: todo — license_activations += tenantId · report · lastReportAt · mailboxCursor · listed
  • Status: todo — Instances.jsx — version spread, last-seen, storage, per-tenant
  • Status: todo — [warning] Label it honestly: the fleet only ever sees licensed installs. A dev checkout or an

install with no LEUMAS_LICENSE_SERVER has no central row at all

[todo] V4 · Marketplace review (roadmap C1, C3)

  • Status: todo — Submissions.jsx — manifest validity, permissions vs description, bundle hash, origin ownership
  • Status: todo — Approve → sign (Ed25519, reuse @leumas/licensing) → publish → **write the PassNode rule

from the manifest's declared pricing**

  • Status: todo — Listings.jsx, Payouts.jsx

[todo] V5 · Distribution + Analytics (roadmap D3)

  • Status: todo — Channels.jsx — stable/beta, rollout %, per-customer channel pinning
  • Status: todo — iOS release records + the minimum-supported-version gate
  • Status: todo — Analytics.jsxdesign for the aggregate tier; let Leumas's own sites be the richer special

case, or every chart breaks when a third-party instance appears

[todo] V6 · Support

  • Status: todo — Contact inbox for leumas.tech + job requests
  • Status: todo — Escalations from the Trust queue

Run

pnpm dev:admin

Port 5100. Requires a control or dev role API — WrongDeployment.jsx catches the mistake.

Verify

pnpm check:huds        # both consoles' doors: spec, shell, populator, no renderer in a console
pnpm check:nav         # every route in exactly one domain, in all three manifests
pnpm check:admin       # every surface goes through AdminSurface; the CSS/inline ratchets
pnpm --filter @leumas/admin build

Then prove the renderer is still lazy — the one thing a browser will not show you:

grep -c WebGLRenderer products/leumas-admin/dist/assets/index-*.js   # must be 0
ls products/leumas-admin/dist/assets/three.module-*.js               # its own chunk, unreferenced by the entry
Generated from the Leumas repository. Every page cites the file it came from.leumas.techllms.txt