03 / Develop · Shell · Overview

Shell ​

The host app — authentication, routing, the app registry, and the launchpad every remote app federates into. It owns identity for the whole platform: users, organizations, roles, and the auth providers people sign in with. Repo veni-shell · Make-driven, with a Bun API and a Vite UI.

What the Shell does ​

Four responsibilities, and everything else in this section serves one of them:

  • Identity — it owns the users, organizations, and roles for the whole platform, in shell_db. A satellite has its own users table, provisioned from the Shell on first sign-in — it never reads shell_db.
  • Sign-in — people authenticate here, against whatever providers you configure. The Shell is provider-agnostic; the app never sees the provider.
  • Token issuance — on sign-in the Shell mints an RS256 JWT and publishes its public keys at the JWKS endpoint. A satellite exchanges that token for its own and verifies it against those keys — no shared secret.
  • The launchpad — it keeps the app registry and federates each satellite's UI in at /<slug>, so signed-in users move between apps without re-authenticating.

So the mental model is a hub: the Shell holds identity and hands out verifiable tokens; satellites are self-contained systems that federate into its UI and trust its tokens, but keep their own database and deployment. The platform architecture has the full picture; Build a satellite is the other side of this handshake.

The moving parts ​

What it isRuns at
APIAuth, routing, the app registry, and RS256 token issuance:3000
UIThe launchpad; every remote federates into it:5173
Databaseshell_db — users, orgs, roles, providers, the registry:15433

Architecture ​

The Shell API is a Bun + Hono + Ignis app — the same framework a satellite uses: ShellApplication extends BaseApplication wires everything in api/src/application.ts. Every caller hits one request pipeline, and satellites also verify its keys and consume its events:

The Shell owns its data — shell_db, its Redis cache, its MinIO bucket. In local dev these run from the Shell's own compose; in production they're shared platform infrastructure each app connects to (the SCS split). Beside them sit two shared, self-hosted services: Keycloak (SSO) and the event bus on Redis Streams, which the Shell publishes to and every app consumes into a local read model. Google, SMTP and Stripe are external third-party, all optional. Satellites also verify the Shell's JWKS keys.

The codebase ​

Two trees — a Bun API and a Vite UI.

API — api/src/ ​

The request path, then the cross-cutting pieces:

text
api/src/
├─ application.ts # ShellApplication — the composition root
├─ controllers/   # HTTP in, @authorize-gated (one per REST group)
├─ services/      # business logic (~50): auth, RBAC, orgs, billing
│  └─ authz/      # Casbin adapter — the Shell's own RBAC
├─ repositories/  # data access over Drizzle
├─ models/        # the Drizzle schema → Postgres
├─ strategies/    # request auth: jwt (Shell tokens) · pat
├─ grpc/          # Connect services: auth-gateway · rbac · quota
├─ events/        # Redis Streams publisher: shell:stream:*
└─ workers/       # background jobs (e.g. rag-indexer)

UI — ui/src/ ​

A React app. Beyond its own screens it hosts each satellite's UI — the Federation section walks that:

text
ui/src/
├─ main.tsx → bootstrap.tsx # deferred entry (Module Federation inits first)
├─ federation/              # host — loadRemote mounts ./ShellEntry at /<slug>
├─ pages/                   # route views: sign-in, launchpad, admin, org settings
├─ layout/                  # the shell chrome: nav rail, launchpad, top bar
├─ components/              # shared UI primitives and widgets
├─ hooks/                   # data hooks over the API
├─ api/ · services/         # the Shell API client
├─ context/ · providers/    # React context: auth/session, theme
└─ themes/ · i18n/          # theming and localisation

Where to start reading ​

Read these before you extend the Shell:

  • Sign-in — api/src/services/auth.service.ts and the provider services resolve a user and mint the RS256 token.
  • Token exchange — api/src/grpc/auth-gateway brokers a Shell token into a satellite's service token.
  • Federation — ui/src/federation/loadRemote.ts mounts a satellite's ./ShellEntry at /<slug>.

Identity, RBAC, orgs and the registry all hang off the first two.

Federation ​

The UI's defining job is to render each satellite's own UI inside the Shell — so a signed-in user moves between apps with no reload — using Module Federation. The Shell is the host; each satellite is a remote exposing one entry, ./ShellEntry, which the Shell discovers from the registry, loads, and mounts at /<slug>. How federation works → walks the full runtime path, the ShellEntry contract, and the gotchas.

Next ​

  • Run the Shell → — clone, start its services, and sign in.
  • Configure → — turn on sign-in providers, storage, email, tracing and AI.
  • Database → — the shell_db schema behind identity, RBAC and the registry.
  • API → — the endpoints, grouped, with the platform-critical ones called out.
  • Federation → — how the launchpad loads and mounts each satellite's UI.
  • Build a satellite → — build an app that federates into this Shell.