Skip to content

Console ​

The web console is the operator surface for everything below the data plane: connectors, identity sources, tenants, regions, licensing, audit. It's a single Nuxt application served alongside the webserver, gated by console RBAC.

This page is the tour — what each section does and how operators move through it. For the underlying permission model (roles, scope, decision matrix), see the console-RBAC concept page.

Layout ​

The left navigation groups every page into five operational areas:

GroupPagesPurpose
QuerySearch, DocumentsInteractive search preview against the live corpus. Gated by search:query + documents:read and still filtered by OpenFGA, so what an operator sees in the preview matches what end-users would see.
IngestSources, Identity, Identity sources, Pipeline, SupersessionConnector + identity-source administration. The Pipeline page renders the live data flow; Supersession exposes the deduplication policy + recent decisions.
PlatformTenants, Regions, Secret providers, LicenseCluster-wide configuration: per-tenant provisioning, residency regions, the secret-provider registry, license status + seat usage.
AccessUsers, RolesConsole-side identity + RBAC. Distinct from the Identity page under Ingest — see below.
AuditAudit logSearchable audit trail. Every privileged action lands here, including bootstrap-admin break-glass operations.

The nav adapts to the caller's role: pages the caller has no permission for are hidden rather than 403'd, so a viewer sees only Query + Audit, a connector_admin sees Query + Ingest + Audit, and so on.

People vs Users — two distinct populations ​

The console has two identity surfaces that operators routinely confuse:

PagePopulationAuthoritative storeRole
Ingest → IdentityThe corpus's subject set — every person who appears as a principal on an ACL tuple in the corpusOpenFGA tuples (projected from connector ACL events)This is what the source-data ACL evaluator answers against.
Access → UsersConsole administrators — the humans who can sign into the console at allPostgres admin_users + their console_role_bindings rowsThis is what console RBAC gates on.

A person can appear in one, both, or neither:

  • A Confluence reader who's never signed into the console: appears in Identity, never in Users.
  • A platform operator with no source-system access: appears in Users (with some role), never in Identity.
  • A platform operator who also has Confluence access: appears in both, mapped via canonical email.

The two never share rows. Conflating them is the most common operator mistake when interpreting "this user can't see anything" reports — the right question is "which surface is the user actually on?".

First sign-in: bootstrap break-glass ​

Every fresh cluster ships with a bootstrap-admin account with global-admin capability. It exists so the first operator can sign in before any OIDC identities are configured. To use it:

  1. Set MOOLELO_ADMIN_BOOTSTRAP_TOKEN=<random-32-bytes> on the webserver deployment.
  2. Browse to the console — you'll land on the sign-in screen.
  3. Click Use bootstrap token and paste the token.
  4. The console drops you into the dashboard with a persistent yellow banner: "Break-glass admin — every action is recorded as a privileged operation."

While bootstrap is in use, every API call is audited as a break-glass event and the console UI surfaces the banner on every page. Treat it like sudo: short-lived, witnessed.

Provisioning the first real admin ​

The bootstrap token isn't a long-term identity — it's the path to one. Once your OIDC provider is wired:

  1. Have the human admin sign in once via OIDC. The first-login behavior is per-tenant; the default (reject) means they'll land on a "no access yet" screen but a row appears in admin_users with their OIDC subject.
  2. As the bootstrap admin, open Access → Users, find the newly-created row, and click Assign role → pick global_admin → scope *.
  3. The admin signs out and back in. They now have full console access via their own identity.
  4. Once at least one human OIDC global_admin exists, rotate the bootstrap token out of the deployment (or set MOOLELO_BOOTSTRAP_DISABLED=true). The persistent banner disappears and break-glass is no longer reachable without a config change.

The bootstrap account never auto-disables; removing your last escape hatch is a deliberate operator action.

Per-tenant operators ​

For deployments with more than one tenant, the typical pattern is:

  • One or two global_admin operators (platform team).
  • One tenant_admin per tenant, scoped to that tenant only.
  • Per-functional-role admins (connector_admin, user_admin, billing_admin) layered on as the team grows.

A tenant_admin can do everything inside their tenant — wire connectors, manage identity sources, see audit rows, run the search preview — but the platform pages (Tenants, Regions, License) stay hidden. They can also delegate further by binding other admins as tenant_admin or any per-tenant role within the same tenant; they cannot grant a binding outside their tenant.

API surface ​

Everything the console UI does goes through /api/console/*. The endpoints are documented inline in the binary and gated by the same RBAC middleware the UI consumes. Highlights:

EndpointPermission requiredNotes
GET /api/console/me(none — bootstrap allowed)Returns the caller's capability set. The UI reads this on every page load to drive nav visibility.
GET /api/console/roles(none)The 7-role catalog.
GET /api/console/role-bindingsroles:readEvery binding visible to the caller.
POST /api/console/role-bindingsroles:assignBind { admin_id, role, scope }.
DELETE /api/console/role-bindings/{id}roles:manageRevoke.
GET /api/console/identity/peopleidentity:readPaginate the ingested-person population (OpenFGA-sourced).
GET /api/console/identity/people/{canonical}identity:readPer-person attributes + alias rows.

Direct API use is supported but not the recommended operator path — the console UI exists so that operators don't need to remember endpoint shapes.

Where to go next ​

Moʻolelo — self-hosted federated enterprise knowledge platform.