Architecture
Request flow
browser
│
├─ / → dashboard SPA (SolidJS + Vite)
├─ /v1/* → Kanidm REST API (proxied by Caddy / Vite dev server)
├─ /oauth2/* → Kanidm OAuth2 endpoints
└─ /dashboard.config.json → static deploy-time config
Source layout
src/
domain.ts Shared types: Person, Group, Application, ConsoleState
data-source.ts DashboardDataSource interface + KanidmDataSource + MockDataSource
store.tsx SolidJS context: state, auth, credential operations
kanidm-auth.ts Auth state machine: password, TOTP, passkey, backup code, security key
kanidm-mappers.ts Kanidm API response → domain model mapping
kanidm-composite.ts Multi-step create operations: groups, OAuth2 apps
kanidm-error.ts HTTP error types and auth-failure detection
seed.ts Initial state and demo fixtures
App.tsx Router, layout shells, and page components
components/ Shared UI components: ErrorBox, OptionGrid, GlassPanel, etc.
generated/ TypeScript SDK generated from Kanidm OpenAPI spec
Data source seam
The DashboardDataSource interface defines 31 CRUD methods. Two adapters
implement it:
KanidmDataSource— calls the Kanidm REST API via a generated TypeScript SDK. The SDK is generated fromspec/kanidm-openapi.jsonusing openapi-nexus.MockDataSource— in-memory state persisted tolocalStorage. Seeds fromsrc/seed.tswith demo people, groups, and applications.
Switching between them is a single config field (dataSource.mode) — no code
changes required.
Store
store.tsx provides a SolidJS context (ConsoleProvider) that wraps the data
source. It exposes:
- State — reactive
ConsoleStatewith people, groups, applications, and branding. - Auth — login flows (password, TOTP, passkey, backup code, security key).
- Mutations — CRUD operations that go through
mutateKanidm()(writes) orreadKanidm()(reads), both handling error recovery and state reload.
Auth flow
Kanidm uses a stepped authentication protocol. Each step returns an
X-KANIDM-AUTH-SESSION-ID header that must be sent with the next request.
The dashboard implements this state machine in kanidm-auth.ts:
init2— begin authentication with usernamechoose— the server responds with available mechanismsbegin— select a mechanism (password, passkey, etc.)cred— submit credentials
Credential update state machine
The credential update wizard (src/pages/reset-credentials.tsx) and
self-service update page (src/pages/enrol.tsx) use Kanidm’s multi-step
credential protocol:
_exchange_intent— exchange an admin-issued reset token for a session, or/v1/person/{id}/_credential/_update— begin an authenticated self-service session_status— query current credential state_update— stage credential changes (password, TOTP, passkeys, etc.)_commit— commit all staged changes atomically