Changelog
v3.3.0 (2026-03-22)
Expanded Client Credentials Scopes
invites:create— apps can programmatically create and email invites for their own users viaPOST /admin/invitesusing a service JWTusers:read— apps can list their own enrolled users viaGET /admin/users?app_id=using a service JWTusers:create— apps can create user stubs (email + display_name) viaPOST /admin/usersusing a service JWT (cannot setis_platform_admin)- All new scopes enforce own-app-only access — the service token's
sub(app_id) must match the target resource - Audit log entries from service tokens include
"source": "service_token"in detail - See Server-to-Server Guide for updated client examples (Python + Node.js)
Cleanup
- v2.0 Phase 4 complete —
UserTenantRolemodel, migration shim, and DB table removed. All tenant admin access via per-tenant Console appUserAppRoleexclusively.
v3.1.0 (2026-03-19)
Per-App Push Configuration
- Push config endpoint:
PATCH /push/config/{app_id}— enable/disable push notifications, set webhook URL, configure daily quota per app - Push status endpoint:
GET /push/config/{app_id}— returns enabled state, webhook URL, webhook secret, daily quota, device count, and today's notification count - Device listing endpoint:
GET /push/devices/{app_id}— list all registered devices for an app (admin-only) - Console UI: Notifications tab on App Detail page for managing push config
v3.0.0 (2026-03-19)
Push Notification System
- FCM-based push delivery — Keymaster brokers notifications to Android, iOS, and Web via Firebase Cloud Messaging
- PushDevice model — device registration with platform tracking (web, ios, android), deduplication on
(app_id, token_hash) - Encrypted push tokens — all FCM/APNs tokens encrypted at rest (AES-256-GCM)
- Device registration:
POST /push/devices/register— register a device (user JWT), rate limited to 10/user/hour - Device unregister:
DELETE /push/devices/{device_id}— user or app-initiated removal - Send single:
POST /push/send— send to one user's devices (service JWT,push:sendscope) - Send bulk:
POST /push/send/bulk— same message to up to 500 users - Send batch:
POST /push/send/batch— different messages in one call (up to 500) - Delivery receipts — webhook callbacks with HMAC-SHA256 signature verification
- Auto-cleanup — invalid tokens automatically removed on FCM
invalid_tokenresponse - Daily quota enforcement — 10,000 notifications/day per app (default), 429 with
Retry-Afteron exceeded
v2.4.0 (2026-03-19)
Passwordless Accounts
- Password is now optional on all registration flows: invite redeem, accept-invite, and open signup
- Users can create accounts via OAuth only and set a password later from the Account page
- New endpoint:
POST /account/set-password— allows OAuth-only users to add a password to their account
Export/Import
- App export:
GET /admin/apps/{id}/export— export app configuration as JSON - Optional
?include_users=truequery param to include user enrollments - Tenant export:
GET /admin/tenants/{id}/export— export tenant and all its apps - App import:
POST /admin/apps/import— import an app into a tenant - Body:
{ tenant_id, app, preserve_bundle_id } - Tenant import:
POST /admin/tenants/import— import a tenant and all its apps - Body:
{ tenant, apps } - Import always generates new IDs and client secrets. Users are optionally imported.
Fixes
- User delete cascade — deleting a user now properly cascades all related records (SSO sessions, TOTP secrets, backup codes, magic links, email tokens)
v2.1.0 (2026-03-17)
Console — Tiered Impersonation
- Tenant admin → app admin impersonation — tenant admins can enter any app in their tenant as app admin (Console-only, audited, session-scoped)
- Platform admin → tenant admin impersonation (introduced in v2.0.0) now stacks with app impersonation
- Amber banner with exit link for both impersonation tiers
- Audit events:
app_impersonation_started,app_impersonation_ended
Console — SSO-Based Authentication
- Console login now uses SSO session (
km_sso) directly — no app enrollment required to access the Console - Console JWT issued with audience
keymaster-console(decoupled from any specific app) - Platform Keymaster Console app serves as auth gateway only (open policy)
- Per-tenant Console apps serve as role containers (tenant admin =
adminrole on tenant Console app)
Console — Multi-Tenant UX
- Tenant picker for users who are admin on multiple tenants
- "Switch Tenant" sidebar link only shown when user has 2+ tenants
- Active tenant stored in session cookie (
km_active_tenant)
Fixes
get_user_tenant_idsnow impersonation-aware — all routes work correctly during impersonation- Platform admins auto-enrolled in Console apps on login regardless of registration policy
v2.0.0 (2026-03-17)
Per-Tenant Console Isolation
- Each tenant now gets its own Console app (
{Tenant Name} Console), auto-created on tenant bootstrap - Tenant admin access is determined by
adminrole on the per-tenant Console app (replacesUserTenantRole) - Platform admins access tenant contexts via impersonation, not enrollment
- Tenant creation now requires an admin email — no orphan tenants
Platform Admin Impersonation
- Platform admins can impersonate any tenant admin (Console-only, no SSO tokens issued)
- Session-scoped via
km_impersonatecookie (1-hour TTL) - All impersonated actions logged with
impersonated_byin audit trail - Visible to tenant admins in their audit log
SDK Developer Docs Portal
- Full SDK documentation at
/docs/(also accessible from Console sidebar) - LLM-digestible endpoints:
/llms.txt,/llms-full.txt - OpenAPI/Swagger moved to
/api/docs build-docs.shscript for regenerating docs on feature changes- Version display in Console sidebar footer
Breaking Changes
UserTenantRoletable deprecated — tenant admin access now via per-tenant Console app enrollment- Console JWT audience changed from app ID to
keymaster-console
v1.0.1 (2026-03-17)
Fixes
- Docs routing: handle
.mdextensions in URLs - Swagger/OpenAPI moved to
/api/docs(was/docs) - Landing page updated with SDK docs link
v1.0.0 (2026-03-17)
Initial public release.
Authentication
- Password + Google + GitHub + Microsoft + Apple OAuth (shared provider registration)
- Cross-app SSO via
km_ssocookie (8-hour sessions) - Magic links (passwordless email login, 15-min expiry)
- TOTP 2FA with encrypted secrets + backup codes
- OAuth invite-required flow (policy-aware routing for invite-only apps)
Tokens
- RS256 JWT access tokens (configurable TTL, default 15 min)
- Refresh token rotation with replay detection (30-day rolling window)
- Client credentials grant (
POST /auth/token,grant_type=client_credentials) - Service tokens with scope enforcement (
push:send)
User Management
- Three-tier admin: platform admin → tenant admin → app admin
- App roles:
user,manager,admin(standardized) - Manager role: invite/revoke users only, no config access
- Invite system with email delivery, per-app branding, expiration
- Password policy: 16-char minimum, configurable per tenant
Console
- Full admin Console with dark/light theme
- App configuration: branding, auth methods, token TTLs, redirect URIs
- User management: invite, roles, suspend, rate limit viewer
- Tenant admin dashboard with admin management
- Audit log viewer with filtering and pagination
- Session management (view/revoke active SSO sessions)
- In-app help system (role-scoped, searchable)
Infrastructure
- App logo upload (base64 encoded, served via public endpoint for emails)
- Outbound webhooks (HMAC-SHA256 signed, retry with backoff, SSRF protection)
- Redis session store (OAuth state, SSO cache, rate limiting)
- Health check endpoint (
GET /health) - Email infrastructure (Postfix DKIM, branded templates)
- Auto-apply migrations on startup
- OIDC discovery + JWKS endpoints
Security
- Argon2id password hashing
- TOTP secret encryption (AES-256-GCM)
- Push token encryption at rest
- Webhook URL SSRF validation (blocks private/reserved IP ranges)
- Rate limiting (Redis + in-memory fallback, auto-clear on success)
- Refresh token replay detection with automatic revocation