Run the broker yourself
The broker is a long-running Node service (Hono) with a Postgres pool — it wants an always-on container, not a serverless function. The dashboard is a Next.js app that talks to it over HTTPS; it never touches Postgres directly.
Topology
agent SDK ─┐
├─▶ broker (container) ──▶ Postgres (Neon)
dashboard ─┘ ▲
(Vercel) └─ verifies human sessions + agent identity tokens (JWKS)Container
docker build -t keyward-control-plane .
docker run -d --name keyward --restart=always -p 8787:8787 \
-e DATABASE_URL='postgres://…' \
-e KEYWARD_MASTER_KEY='<strong value>' \
keyward-control-planeMigrations apply at boot. Fly.io config ships in the repo (fly.toml); Railway/Render detect the Dockerfile with zero extra config. Health check: GET /healthz. Never bake secrets into the image — inject them at deploy time.
Environment reference
Dashboard (Vercel)
Deploy apps/dashboard as the project root. Set CONTROL_PLANE_URL to the broker's public URL. Humans sign in with Keyward-native accounts (the session drives every console page); the shared KEYWARD_ADMIN_TOKEN is a local-dev convenience the broker ignores once a human IdP is configured.
Auth modes
Demo / trial: KEYWARD_DEV_IDP=1 makes the broker self-sufficient — it issues end-user tokens at /idp/token and verifies them in-process, and native signup/login/2FA work out of the box. Production: turn it off and point KEYCLOAK_ISSUER (agents) and KEYWARD_HUMAN_ISSUER (humans) at your real IdPs — same JWKS verification path, no code change.