One admin UI for every backend
Count the backends a normal system depends on. A relational database for the data, a bucket for the files, a key-value store for the cache, a queue for the events, a secret store for the credentials, a directory for the users, and a cluster running all of it. Then count the screens: one per backend, each with a slightly different table, a slightly different filter box and the same four bugs.
The commander realm describes each of those as a source — a namespace of triples with levels — and renders all of them with one explorer. The screens disappear; what remains is a descriptor per backend and, where the connection needs one, a small adapter.

A backend is a namespace of triples
export interface ICommanderSource {
name: string; // lowercase instance namespace — the subject of every triple
label: string;
icon?: string;
permission?: string;
levels: ICommanderLevel[];
}
export interface ICommanderLevel {
label: string;
list?: {method: string; params?: object}; // the list triple for this level
open?: {method: string; params?: object}; // the detail triple, when the level has one
permission?: string; // the action a caller needs to see this level
viewer?: string; // which viewer renders a node of this level
}
Eight sources ship today: the SQL database (through the access realm's own table method, with no
dedicated adapter), Kubernetes, S3, Vault, MongoDB, Redis, Kafka and Keycloak. Each is a hierarchy
of levels whose list and open name existing triples — k8s-dev lists namespaces through the
Kubernetes adapter, redis-dev lists keys through the Redis adapter — so the explorer never learns
what a backend is. It posts {source, level, parent} to commander.branch.list, that handler
resolves the level's triple and calls it, and the rows come back.
That indirection is what makes "a new backend is a source, not a screen" literally true. A source is
one entry in config/sources.ts. If the backend needs a connection the framework does not have, it
needs an adapter too — and then a viewer only if its resources have a shape none of the existing
ones does, because viewers are keyed by resource type rather than by backend.
The explorer is one component
The shell lives in blong-browser, not in the realm, because it is not commander-specific: the
realm contributes descriptors and handlers, and the component renders whatever it is given.
- The tree is built from the source list, one root per source.
- The table comes from the level's
listtriple, and the handler flattens heterogeneous rows so the same table can show a Kubernetes object and a SQL row. - The filter is client-side over the flattened row, and the columns are derived from the data — scalar fields only. Nothing per-backend is configured for a table to appear.
- Opening a node is opt-in per level: with an
opentriple you get the fetched detail, without one you get the row you already had. - Viewers are chosen by the node's own type metadata: JSON, key/value, file, image, table, document, secret, YAML, message, pod log.

Two pictures, one component, seven backends between them — and the second one is the SQL source, which has no adapter and no per-backend code at all. It is a descriptor pointing at a method the access realm already exposed.
It lists; it does not write
This is the part of the idea that has to be said plainly, because an admin UI invites the opposite
assumption: there is no write path in the realm. No edit, update, save, delete or create handler
exists anywhere in it, and the action method offers only copyPath, open and refresh. The tool
explores.
That is a defensible place to stop — a screen that can mutate a production Kubernetes object or a Vault secret needs an authorization story this realm does not attempt — but it does mean "admin UI" is a description of the audience rather than a claim about capability. What it gives an operator is the ability to find and read anything in six systems through one page, which is the part that was missing.
Authorization is per level
A source carries a permission and so does a level, and the list method prunes the tree by the
caller's effective actions before returning it: a source a caller cannot use is not a source they
see, rather than a source that fails when clicked. The gating is fine-grained enough to be useful —
one level of the S3 source can be granted while the rest stays hidden, and the Kubernetes namespace
gates a whole subtree while its synthetic category and resource levels are deliberately ungated,
because they describe what is inside a namespace the caller already reached.
The local wiring, and a claim worth correcting
Each *Dev adapter extends the real one and supplies a local endpoint, local credentials and the
settings a local backend needs: Kafka gets a JSON codec, short session timeouts and admin mode (so
the topic list comes from metadata rather than from consuming the stream), S3 gets path-style URLs
for MinIO.
The tempting description — "the dev conveniences live in a dev-intent adapter" — is wrong, and the
code is the reason: they declare activation.default, not activation.dev, and the framework
merges the default block in every intent. A deployment that loaded this realm would get
localhost endpoints unless it overrode them. The accurate reading is "a dev-wired instance of the
adapter", which the realm's own entry decides whether to include. It is the kind of nuance that
documentation usually smooths over and that costs somebody an afternoon in an environment they
cannot explain.
Four other things in the realm are declared but not wired, and they are recorded rather than
discovered later: commander.node.viewer and commander.node.action are registered,
gateway-validated and never called by the shipped page; the commander.sources configuration
override has no provider, so the hardcoded array always wins; ICommanderLevel.model is used by no
source; and three of the eight sources — Kubernetes items, Kafka messages, Keycloak users — have no
open triple yet, so their viewers show the list row rather than fetched detail.
Yes, it works
The claim is easy to make and worth testing, so it was: all seven backends are reachable in this environment, the realm's own protocol test passes, and the Playwright suite was run source by source — the tree renders its eight roots, and drilling each one returns real rows from the real service. The two images above come from a capture spec that photographs the explorer, asserts the eight sources and a known row, and writes nothing unless it is asked to, so the pictures are regenerable rather than hand-made.
The full reference — the descriptors, the eight sources, the viewer registry, the authorization seed and the checklist for adding a source — is in the commander pattern.
