Skip to content

feat: full WorkOS API emulator (emulate, dev, RBAC, webhooks, events, 84% API coverage)#100

Merged
nicknisi merged 22 commits intomainfrom
nicknisi/workos-emulate
Mar 26, 2026
Merged

feat: full WorkOS API emulator (emulate, dev, RBAC, webhooks, events, 84% API coverage)#100
nicknisi merged 22 commits intomainfrom
nicknisi/workos-emulate

Conversation

@nicknisi
Copy link
Copy Markdown
Member

@nicknisi nicknisi commented Mar 24, 2026

Summary

Adds a full local WorkOS API emulator to the CLI, enabling developers to test WorkOS integrations without hitting the live API. Covers ~84% of the OpenAPI spec surface.

Three runtime contexts:

  • workos emulate — standalone server for CI/ephemeral use
  • workos dev — process orchestrator (emulator + your app in one command)
  • Programmatic APIimport { createEmulator } from 'workos/emulate' for test suites

What's included

Core infrastructure (src/emulate/core/)

  • In-memory store with field indexing and cursor pagination
  • JWT signing/verification with JWKS endpoints
  • Hono-based HTTP server with CORS, rate limiting, API key auth
  • Collection hooks for automatic event emission

Phase 1: Auth Completeness

  • Token refresh with rotation
  • Multi-user authorize (login_hint)
  • Impersonation support
  • Sealed sessions (AES-256-GCM)
  • MFA challenge/verify (TOTP)
  • Device authorization flow
  • 7 grant types (authorization_code, password, magic-auth, email-verification, refresh_token, mfa-totp, organization-selection, device_code)
  • /x/authkit/users/authenticate alias for SDK compatibility

Phase 2: User Management

  • Invitations CRUD (create, accept, revoke, resend, get by token)
  • Config endpoints (redirect URIs, CORS origins, JWT template)
  • User authorized apps, connected accounts, data providers
  • Widget token generation

Phase 3: Authorization (RBAC + FGA)

  • Environment roles and org roles with priority ordering
  • Permissions CRUD with role-permission management
  • Authorization resources (fine-grained access)
  • Permission checks and role assignments
  • JWT tokens include role and permissions claims for org-scoped sessions

Phase 4: CRUD Domains (9 domains)

  • Directory Sync (list/get/delete directories, users, groups)
  • Audit Logs (actions, schemas, events, exports, org config)
  • Feature Flags (enable/disable, targets, org/user evaluations)
  • Connect (applications, client secrets)
  • Data Integrations (OAuth authorize + token exchange)
  • Radar (attempts, allow/deny lists)
  • API Keys (validate, delete, list by org)
  • Portal (admin portal link generation)
  • Legacy MFA (enroll, challenge, verify)

Phase 5: Events & Webhooks

  • Event bus with store-level collection hooks (auto-emits on entity CRUD)
  • Webhook endpoint CRUD with auto-generated secrets and masking
  • HMAC-SHA256 signed webhook delivery (fire-and-forget, 5s timeout)
  • Paginated events API with type filtering
  • Hybrid route-level emission for action-specific events (invitation accept/revoke, auth succeeded)

Developer tools

  • pnpm gen:routes <openapi-spec> — codegen script for scaffolding new routes
  • pnpm check:coverage <openapi-spec> — coverage checker comparing emulator vs OpenAPI spec
  • Seed config (YAML/JSON) for users, orgs, connections, roles, permissions, invitations, webhook endpoints

Test plan

  • pnpm build passes
  • pnpm test passes (1509 tests)
  • pnpm typecheck passes
  • pnpm lint passes (0 warnings)
  • pnpm check:coverage reports 84% coverage against OpenAPI spec
  • Manual testing: refresh token flow via SDK's authenticateWithRefreshToken
  • Manual testing: workos dev with AuthKit client page
  • Manual testing: full AuthKit sign-in/sign-out flow
  • Manual testing: webhook delivery to local HTTP listener

nicknisi added 20 commits March 25, 2026 19:32
Port the WorkOS emulator from vercel-labs/emulate into the CLI as a
`workos emulate` command with a `workos/emulate` programmatic API.

Core infrastructure (store, ID generation, cursor pagination, JWT,
Hono server factory, auth/error middleware) lives in src/emulate/core/.
WorkOS-specific plugin (12 route files covering organizations, users,
memberships, connections, SSO, auth flows) lives in src/emulate/workos/.

The emulator supports:
- CLI: `workos emulate --port 4100 --seed config.yaml --json`
- Programmatic: `createEmulator({ port: 0, seed: { users: [...] } })`
- Health check at /health
- Seed config via YAML/JSON (auto-detected or explicit path)
- Store reset for test isolation
- Random port assignment (port: 0) for parallel test suites

New dependencies: hono, @hono/node-server, jose
Developer tool that reads a WorkOS OpenAPI spec (YAML/JSON) and generates
TypeScript entity types, store registrations, formatter helpers, and route
stubs matching the hand-written emulate patterns. Includes 46 unit tests
covering parsing, code generation, and idempotency.
Document workos emulate, workos dev, seed configuration, programmatic
API, and emulated endpoint coverage.
authkit-nextjs (and the @workos-inc/node SDK) read WORKOS_API_HOSTNAME,
WORKOS_API_PORT, and WORKOS_API_HTTPS — not WORKOS_API_BASE_URL.

buildDevEnv now sets both styles so the emulator works with authkit SDKs
and direct consumers.
workos dev now seeds a default user (test@example.com / password) and
organization so the AuthKit login flow works out of the box. The banner
prints the credentials for easy copy-paste.

Skipped when the user provides --seed or a workos-emulate.config.* file
is auto-detected in the project directory.
…redirects)

- Expose apiKey on Emulator interface; use it in dev/emulate CLI output
  and buildDevEnv() so custom seed apiKeys propagate correctly
- Update JWT issuer to actual bound URL after port resolution, fixing
  iss mismatch when using port: 0
- Clean up password resets, email verifications, and magic auths on
  user deletion; harden password_reset/confirm to return 404 if user
  was deleted
- Restrict redirect_uri in authorize endpoints to localhost origins,
  preventing open-redirect abuse
- Remove unused jose dependency
Add token refresh with rotation, logout redirects, multi-user authorize
(login_hint), impersonation, sealed sessions (AES-256-GCM), MFA
challenge/verify, device authorization, and AuthKit OAuth complete flow.

New grant types: refresh_token, mfa-totp, organization-selection, device_code.
Includes shared entity/store/helper infrastructure for all 4 API parity phases.
Add invitations CRUD (create/accept/revoke/resend/by-token), config
endpoints (redirect URIs, CORS origins, JWT template), user features
(authorized apps, connected accounts, data providers), and widget
token generation.
Add environment roles, org roles with priority ordering, permissions
CRUD, role-permission management, authorization resources, permission
checks, and role assignments. JWT tokens now include role and
permissions claims for org-scoped sessions.
…gs, and more

Add 9 CRUD domains: Directory Sync, Audit Logs, Feature Flags, Connect,
Data Integrations, Radar, API Keys, Portal, and Legacy MFA. Each domain
follows the entity/store/helper/route pattern with full test coverage.
…ok delivery

Add cross-cutting event system with webhook delivery. Collection-level
hooks (Option A) auto-emit events on insert/update/delete for all major
entities. Hybrid route-level emission for action-specific events
(invitation accept/revoke, authentication succeeded).

Webhook endpoints CRUD with HMAC-SHA256 signed delivery (fire-and-forget,
5s timeout). Events API with paginated listing and type filtering.

Review: 2 cycles (6 findings in cycle 1, all resolved in cycle 2).
Remove unused variables and imports flagged by oxlint:
- sessions.spec.ts: remove unused `req` helper and `headers` constant
- auth.spec.ts: remove unused `user` variable in impersonator test
- data-integrations.spec.ts: remove unused `getWorkOSStore` import and `store` variable
- event-bus.spec.ts: use non-null assertion instead of optional chaining
Compares the WorkOS OpenAPI spec against emulator route registrations
to report missing endpoints, extra endpoints, and coverage percentage.

Usage: pnpm check:coverage ~/Developer/workos/packages/api/open-api-spec.yaml
…ation

The refresh token handler now reads organization_id from the request
body, falling back to the stored token's org. This enables the SDK's
switchToOrganization flow during token refresh.
The AuthKit SDK sends refresh_token grants to /x/authkit/users/authenticate
rather than /user_management/authenticate. Register the same handler on
both paths so the SDK's refreshTokens() and switchToOrganization() work
against the emulator.
@nicknisi nicknisi force-pushed the nicknisi/workos-emulate branch from 2b47266 to 3494dde Compare March 26, 2026 00:33
@nicknisi nicknisi marked this pull request as ready for review March 26, 2026 00:34
@nicknisi nicknisi changed the title feat: add local WorkOS API emulator (workos emulate, workos dev, pipes, codegen) feat: full WorkOS API emulator (emulate, dev, RBAC, webhooks, events, 84% API coverage) Mar 26, 2026
Add all new endpoint groups from auth completeness, user management,
authorization, CRUD domains, and events/webhooks phases. Add seed
config examples for roles, permissions, and webhook endpoints.
@nicknisi nicknisi merged commit 55371a9 into main Mar 26, 2026
5 checks passed
@nicknisi nicknisi deleted the nicknisi/workos-emulate branch March 26, 2026 00:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant