AKKO Cockpit¶
Overview¶
The AKKO Cockpit is the single entry point to the platform: a React
single-page application (SPA) that gives every user a role-aware view of the
layers they are allowed to use. It is served on demo.<domain> behind the
platform's SSO, and each service link or embedded page is gated by the same
policy source that guards the underlying tool.
The cockpit is built as a set of React islands (ADR-074, strangler-fig
migration) living in branding/cockpit-react/. It replaced the former nginx +
vanilla-JS portal; there is no more health-proxy or static index.html/app.js
to edit.
Architecture¶
Browser ──→ Traefik (:443, host demo.<domain>)
│ ForwardAuth middleware
▼
oauth2-proxy ──→ /auth-check ──→ Keycloak (SSO)
│ (200 = authenticated, identity headers injected)
▼
Cockpit React SPA (nginx serving static build)
├── src/platform/catalog.ts (layers + capabilities + roles)
├── src/features/<x>/ (one directory per page)
├── src/session/SessionProvider (canSeeCap gating)
└── src/app/App.tsx (hash routes /x/<slug>)
The nginx in the cockpit pod only serves the static build and exposes the
/auth-check bridge that converts an oauth2-proxy 401 into a 302 redirect.
It does not reverse-proxy service health endpoints anymore: per-tile health
is fetched from the cockpit backend, and access to each service is enforced by
Traefik ForwardAuth plus the service's own policy engine.
Access¶
Access the cockpit at https://demo.<domain> (for example
https://demo.akko-ai.com). The ingress host is derived from
global.domain via the akko.fqdn.cockpitReact helper (demo.<domain>) and
can be overridden with akko-cockpit-react.ingress.host.
Role-aware gating¶
Every layer and capability is declared in src/platform/catalog.ts with a
roles list and a kind (integrated = a page inside the SPA, external = a
dedicated UI opened in a new tab). Visibility is derived by
canSeeCap(cap, role, toolAccess) in src/session/SessionProvider, which reads
the same tool-access matrix that drives the OPA gate (ADR-075). The shell
sidebar (src/shell/Sidebar.tsx) and the home grid (src/features/home) both
filter their tiles through canSeeCap, so a user never sees a link to a tool
they are not entitled to use. There is no client-side role switcher: the role
comes from the verified SSO session.
Key Features¶
- Layer-first home — services grouped by layer (Compute, Query, Storage, Analytics & reporting, AI, Governance, ...), each tile carrying a health status and a direct link, filtered by role
- Integrated pages — governed features rendered inside the cockpit as React
routes: ADEN (
/x/aden), NORA (/x/nora), RAG (/x/rag), AI models (/x/litellm), monitoring (/x/monitoring), audit (/x/audit), usage (/x/usage), DevHub (/x/devhub), sources (/x/sources), data roles (/x/data-roles), platform roles (/admin/platform-roles) - Bilingual (FR/EN) — every feature ships an
i18n.tsdictionary; strings live next to the feature, never hard-coded in JSX - Two themes — light and dark, driven by the design-system tokens under
src/design-systemandsrc/theme
Helm Chart¶
The cockpit is deployed via the akko-cockpit-react sub-chart:
helm/akko/charts/akko-cockpit-react/
├── Chart.yaml
├── values.yaml
├── Dockerfile # multi-stage: vite build → nginx static image
└── templates/
├── deployment.yaml
├── service.yaml
├── configmap-nginx.yaml # static serving + /auth-check bridge
├── ingress.yaml # host demo.<domain>
├── ingress-oauth2.yaml # oauth2-proxy routes (avoid redirect loops)
└── networkpolicy.yaml # ForwardAuth round-trip + backend calls
Key Values¶
akko-cockpit-react:
image:
repository: akko-cockpit-react
tag: "2026.06"
ingress:
enabled: true
host: "" # empty → demo.<global.domain>
Troubleshooting¶
Common Issues
- Redirect loop after login/logout: the cockpit carries the platform
ForwardAuth. Ensure
ingress-oauth2.yamlroutes are applied and the Identity (Keycloak) clientakko-oauth2-proxyhas the correct redirect URI (https://demo.<domain>/oauth2/callback). - Tiles missing for a user: expected when the user's role has no access
to that tool. Visibility is derived from the tool-access matrix
(
canSeeCap, ADR-075); check the user's group→role mapping rather than the UI. - Blank page: check that the static build was produced (multi-stage Dockerfile) and that the nginx ConfigMap is mounted; the SPA uses a HashRouter so no nginx rewrite rules are required.