Status: Accepted · Date: 2026-08-10 (same meeting as
ADR-009) ·
Deciders: Phil, Michael, Ryan, Dmitrii
Phase 3 needs an operator surface: deploy and retire models
(TKF-53, via the
ModelDeployment API),
watch fleet status and telemetry, and eventually manage tenants. Nothing
like it exists today — the shipped Portal is entirely consumer-facing:
workspaces, members, keys, budgets, usage. There is no admin view at all.
Product's mock assumes both surfaces exist: it carries an
Admin / My account toggle and freely mixes operator screens (models,
nodes, telemetry) with customer screens (keys, usage). That raised the
architectural question this ADR answers: is the admin experience a
separate application, or a section of the Portal?
Arguments genuinely exist for separation. NeoCloud and Enterprise pull in
different directions — a NeoCloud operator console and a customer-facing
portal serve different personas with different needs, and comparable
products (Nutanix Enterprise AI, cloud provider consoles) ship them as
distinct surfaces. A separate app is also the cleaner security story on
paper.
Build the admin experience into the existing Portal as an admin
section. One application, one Helm chart, one deployment, one login.
- Non-admin users never see it. The admin section renders only for
admins (the moad-admin realm role); everyone else sees exactly today's
consumer portal. The same human can be both — the IT admin who operates
the platform is usually also a user of it.
- Admin capabilities are admin-gated at the API layer, not hidden
frontend-only: the Portal's Kubernetes access for ModelDeployment
(TKF-93) and any operator
GraphQL surface check the role server-side.
- Separation later stays cheap, by construction. The admin section gets
its own routes and components (no interleaving with consumer screens), so
splitting it into a standalone app later is an endpoint/packaging change,
not a rewrite.
- We have enough deployables. Another frontend means another Helm
chart, image pipeline, ingress, SSO client and upgrade story — pure
overhead while the admin surface is small and evolving weekly.
- The real work is the APIs. Frontends are fast to build and rebuild;
the durable investment is the GraphQL/Kubernetes surface underneath
(TKF-93,
ADR-009). That
investment is identical whether one app or two consume it.
- The split-later path is proven in-house. MKE separates the DEX UI
from the MKE UI purely by endpoint — two surfaces so visually identical
that users cannot tell they are different applications. If and when
NeoCloud needs a standalone operator console, the same move applies here
with no user-visible disruption.
- Product's mock survives intact. The mock's Admin / My account toggle
maps one-to-one onto this decision — its admin screens become the admin
section (TKF-66), its
customer screens are the Portal that already ships.
- TKF-66 (adopt the product
mock) targets the Portal, building the admin section rather than a new
app; TKF-53 model management
lands inside it.
- The Portal pod gains Kubernetes API access with narrowly-scoped RBAC
(TKF-93) — a new capability
for a previously cluster-blind application, and the reason admin gating
must be server-side.
- Chat stays separate (ADR-007)
— this ADR consolidates admin surfaces, it does not merge LibreChat.
- Revisit trigger: a NeoCloud customer needing a white-labeled operator
console for their customers, or admin/user release cadences diverging
enough to hurt — either reopens the split, via the MKE endpoint pattern.