Emulate Seed Configs
Generate and manage seed configs for emulate (Apache-2.0) — Vercel Labs' stateful API emulation tool. Each category has individual rule files in rules/ loaded on-demand.
Paired agent: This skill pairs with the emulate-engineer subagent (subagent_type: "emulate-engineer"). When a task involves generating a full emulate config from scratch, webhook HMAC setup, CI pipeline integration, or parallel-worker port isolation, spawn the agent rather than handling it inline — it has the full 12-emulator service-port matrix and seed-rules in context.
Not mocks. Emulate provides full state machines with cascading deletes, cursor pagination, webhook delivery, and HMAC signature verification. Create a PR via the API and it appears in GET /repos/:owner/:repo/pulls. Delete a repo and its issues, PRs, and webhooks cascade-delete.
New in 2026-04 (emulate 0.4.x)
- Modular
@emulators/* packages — each service is its own package (@emulators/github, @emulators/stripe, etc.); top-level emulate re-exports createEmulator and the CLI.
- 4 new services (12 total):
mongoatlas:4007, okta:4008, resend:4009, stripe:4010 with drop-in seed YAML blocks.
- Resend local inbox —
GET http://localhost:4009/inbox returns captured emails for assertions without hitting a real provider.
- Stripe hosted checkout — real session redirect flow +
checkout.session.completed/expired webhook delivery, suitable for E2E payment tests.
- MongoDB Atlas — Admin API v2 (projects/clusters/DB users) + Data API v1 with full CRUD + aggregate.
- Okta OIDC — full discovery, JWKS,
authorize/token/userinfo/revoke/introspect plus Users/Groups/Apps CRUD.
- Entra / Apple / Slack expansions (v0.4.0) — PKCE + refresh rotation (Entra), RS256 JWKS (Apple), OAuth v2 consent UI (Slack).
@emulators/adapter-next — catch-all Next.js route handler runs emulators on the same origin as the app; fixes OAuth callback URL drift on Vercel preview deploys.
Quick Reference
| Category |
Rules |
Impact |
When to Use |
| Seed Config |
1 |
HIGH |
Setting up emulate.config.yaml for test environments |
| Service Selection |
1 |
MEDIUM |
Choosing GitHub/Vercel/Google for your tests |
| Webhook Setup |
1 |
MEDIUM |
Testing webhook delivery with HMAC verification |
| Parallel CI |
1 |
HIGH |
Running tests in parallel without port collisions |
| Auth Tokens |
1 |
MEDIUM |
Seeding tokens mapped to emulated users |
Total: 5 rules across 5 categories
Quick Start
# Install (packages published under @emulators/* scope)
npm install --save-dev emulate
# Start all services
npx emulate
# Start specific services with seed data
npx emulate --service github,stripe --seed ./emulate.config.yaml
# Generate a starter config
npx emulate init --service github
Services (0.4.1 — 12 emulators)
| Service |
Default Port |
Coverage |
| Vercel |
:4000 |
Projects, deployments, domains, env vars, teams |
| GitHub |
:4001 |
Repos, PRs, issues, comments, reviews, Actions, webhooks, orgs, teams |
| Google OAuth |
:4002 |
OAuth 2.0 authorize, token exchange, userinfo |
| Slack |
:4003 |
Chat, conversations, users, reactions, OAuth v2 with consent UI |
| Apple Auth |
:4004 |
Sign in with Apple — OIDC discovery, JWKS (RS256), auth flow, token exchange |
| Microsoft Entra |
:4005 |
OAuth 2.0/OIDC v2.0, authorization code + PKCE, refresh token rotation, v1 token endpoint, Graph /users/{id} |
| AWS |
:4006 |
S3 buckets, SQS queues, IAM users/roles, STS identity |
| MongoDB Atlas (0.4+) |
:4007 |
Admin API v2 (projects, clusters, DB users) + Data API v1 (full CRUD + aggregate) |
| Okta (0.4+) |
:4008 |
OIDC discovery, JWKS, authorize/token/userinfo/revoke/introspect, Users/Groups/Apps CRUD |
| Resend (0.4+) |
:4009 |
Send + batch (100/req), list/retrieve/cancel, domains, API keys, audiences, contacts, local inbox (GET /inbox) |
| Stripe (0.4+) |
:4010 |
Customers, payment methods, customer sessions, payment intents, charges, products, prices, hosted checkout session w/ webhook delivery |
| Clerk |
(on-demand) |
Users, sessions, organizations |
See references/api-coverage.md for full endpoint lists.
Next.js Adapter (0.4+) — @emulators/adapter-next
Runs emulators on the same origin as your Next.js app via a catch-all route handler. Fixes the OAuth callback URL drift problem on Vercel preview deploys — no more http://localhost:4001 redirect mismatches.
// next.config.js
const { withEmulate } = require('@emulators/adapter-next')
module.exports = withEmulate({ /* your next config */ })
// app/api/[...emulate]/route.ts
import { createEmulateHandler } from '@emulators/adapter-next'
export const { GET, POST } = createEmulateHandler({
services: ['github', 'stripe', 'resend'],
persistence: { /* load(), save() or built-in filePersistence */ },
})
Seed Config Structure
A seed config pre-populates the emulator with tokens, users, repos, and projects so tests start from a known state.
# emulate.config.yaml
tokens:
dev_token:
login: yonatangross
scopes: [repo, workflow, admin:org]
ci_token:
login: ci-bot
scopes: [repo]
github:
users:
- login: yonatangross
name: Yonatan Gross
- login: ci-bot
name: CI Bot
repos:
- owner: yonatangross
name: my-project
private: false
default_branch: main
topics: [typescript, testing]
vercel:
users:
- username: yonatangross
email: yonaigross@gmail.com
projects:
- name: my-docs
framework: next
# NEW in 0.4.x — drop-in seed blocks
okta:
users:
- login: alice@example.com
firstName: Alice
lastName: Smith
groups: [{ name: Everyone }, { name: Admins }]
apps: [{ name: My Web App }]
authorization_servers:
- name: default
audiences: ["api://default"]
resend:
domains: [{ name: example.com }]
api_keys: [{ name: default }]
# In tests: GET http://localhost:4009/inbox to assert captured emails
stripe:
customers:
- name: Test Customer
email: customer@example.com
products: [{ name: Pro Plan }, { name: Starter Plan }]
prices:
- { product: Pro Plan, unit_amount: 4900, currency: usd, recurring: { interval: month } }
- { product: Starter Plan, unit_amount: 1900, currency: usd, recurring: { interval: month } }
# Webhook delivery fires on checkout.session.completed / expired
mongoatlas:
projects: [{ name: my-project }]
clusters: [{ project: my-project, name: my-cluster }]
database_users: [{ project: my-project, username: app-user }]
See rules/seed-config.md for full schema and best practices.
Programmatic SDK
Service packages live under the @emulators/* scope (e.g., @emulators/github, @emulators/stripe). The programmatic API (createEmulator) is exported from the top-level emulate package.
import { createEmulator } from 'emulate'
const github = await createEmulator({ service: 'github', port: 4001 })
// github.url -> 'http://localhost:4001'
// State is real — create a PR and it appears in the list
const res = await fetch(`${github.url}/repos/org/repo/pulls`, {
method: 'POST',
headers: { Authorization: 'Bearer dev_token' },
body: JSON.stringify({ title: 'Test PR', head: 'feature', base: 'main' })
})
const prs = await fetch(`${github.url}/repos/org/repo/pulls`)
// -> includes the PR we just created
// Cleanup
github.reset() // Synchronous state wipe
await github.close() // Shut down server
See references/sdk-patterns.md for advanced patterns (multi-service, lifecycle hooks).
Webhook Delivery
Emulate delivers real webhooks with HMAC-SHA256 signatures when state changes:
import crypto from 'crypto'
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex')
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
}
See rules/webhook-setup.md for webhook receiver patterns.
CI Integration
# .github/workflows/test.yml
jobs:
test:
steps:
- uses: actions/checkout@v4
- name: Start emulate
run: npx emulate --service github --seed .emulate/ci.yaml &
- name: Wait for emulate
run: sleep 2
- name: Run tests
run: npm test
env:
GITHUB_API_BASE: http://localhost:4001
VERCEL_API_BASE: http://localhost:4000
Parallel Test Execution
Each test worker gets its own port to avoid race conditions:
// vitest.config.ts
const workerPort = 4001 + parseInt(process.env.VITEST_WORKER_ID || '0')
See rules/parallel-ci.md for full parallel isolation patterns.
Decision Matrix
| Tool |
When to Use |
Stateful? |
Platforms |
| emulate (FIRST CHOICE) |
GitHub/Vercel/Google/Slack/Apple/Entra/AWS/Okta/Resend/Stripe/MongoDB testing |
YES |
All 12 services |
| Pact |
Contract verification between services |
No |
Any |
| MSW |
In-browser/Node HTTP mocking |
No |
Any |
| Nock |
Node.js HTTP intercept |
No |
Any |
| WireMock |
HTTP stub server |
Partial |
Any |
Use emulate when:
- Testing code that calls GitHub, Vercel, Google, Slack, Apple, Entra, AWS, Okta, Resend, Stripe, or MongoDB Atlas
- You need state persistence across multiple API calls in a test
- You want webhook delivery with real HMAC signatures (GitHub, Stripe)
- You need cascading side-effects (delete repo -> PRs cascade-delete)
- You need to assert on sent emails without hitting a real provider (Resend local
/inbox)
- You need hosted Stripe checkout sessions with real redirect flow in tests
Use MSW/Nock when:
- Mocking arbitrary HTTP APIs not covered by emulate
- You need in-browser interception (MSW)
- Tests only need single request/response pairs
Related Skills
testing-integration — Integration test patterns (emulate as first choice for API tests)
testing-e2e — End-to-end test patterns with emulated backends
testing-unit — Unit test patterns (use emulate for API-dependent units)
security-patterns — Auth token patterns (emulate token seeding)
CLI Reference
See references/cli-reference.md for all CLI flags and commands.
SDK Patterns
See references/sdk-patterns.md for programmatic createEmulate() usage.
1---2name: emulate-seed3description: Generate emulate seed configs for stateful API emulation. Wraps Vercel's emulate tool for GitHub, Vercel, Google OAuth, Slack, Apple Auth, Microsoft Entra, AWS (S3/SQS/IAM), Okta, Resend, Stripe, and MongoDB Atlas APIs. Not mocks — full state machines where create-a-PR-and-it-appears-in-the-list, send-an-email-and-retrieve-from-local-inbox. Use when setting up test environments, CI pipelines, integration tests, or offline development.4---56# Emulate Seed Configs78Generate and manage seed configs for [emulate](https://github.com/vercel-labs/emulate) (Apache-2.0) — Vercel Labs' stateful API emulation tool. Each category has individual rule files in `rules/` loaded on-demand.910> **Paired agent:** This skill pairs with the [`emulate-engineer`](../../agents/emulate-engineer.md) subagent (`subagent_type: "emulate-engineer"`). When a task involves generating a full emulate config from scratch, webhook HMAC setup, CI pipeline integration, or parallel-worker port isolation, spawn the agent rather than handling it inline — it has the full 12-emulator service-port matrix and seed-rules in context.1112**Not mocks.** Emulate provides full state machines with cascading deletes, cursor pagination, webhook delivery, and HMAC signature verification. Create a PR via the API and it appears in `GET /repos/:owner/:repo/pulls`. Delete a repo and its issues, PRs, and webhooks cascade-delete.1314## New in 2026-04 (emulate 0.4.x)1516- **Modular `@emulators/*` packages** — each service is its own package (`@emulators/github`, `@emulators/stripe`, etc.); top-level `emulate` re-exports `createEmulator` and the CLI.17- **4 new services** (12 total): `mongoatlas:4007`, `okta:4008`, `resend:4009`, `stripe:4010` with drop-in seed YAML blocks.18- **Resend local inbox** — `GET http://localhost:4009/inbox` returns captured emails for assertions without hitting a real provider.19- **Stripe hosted checkout** — real session redirect flow + `checkout.session.completed`/`expired` webhook delivery, suitable for E2E payment tests.20- **MongoDB Atlas** — Admin API v2 (projects/clusters/DB users) + Data API v1 with full CRUD + aggregate.21- **Okta OIDC** — full discovery, JWKS, `authorize/token/userinfo/revoke/introspect` plus Users/Groups/Apps CRUD.22- **Entra / Apple / Slack expansions (v0.4.0)** — PKCE + refresh rotation (Entra), RS256 JWKS (Apple), OAuth v2 consent UI (Slack).23- **`@emulators/adapter-next`** — catch-all Next.js route handler runs emulators on the same origin as the app; fixes OAuth callback URL drift on Vercel preview deploys.2425## Quick Reference2627| Category | Rules | Impact | When to Use |28|----------|-------|--------|-------------|29| [Seed Config](#seed-config) | 1 | HIGH | Setting up emulate.config.yaml for test environments |30| [Service Selection](#service-selection) | 1 | MEDIUM | Choosing GitHub/Vercel/Google for your tests |31| [Webhook Setup](#webhook-setup) | 1 | MEDIUM | Testing webhook delivery with HMAC verification |32| [Parallel CI](#parallel-ci) | 1 | HIGH | Running tests in parallel without port collisions |33| [Auth Tokens](#auth-tokens) | 1 | MEDIUM | Seeding tokens mapped to emulated users |3435**Total: 5 rules across 5 categories**3637## Quick Start3839```bash40# Install (packages published under @emulators/* scope)41npm install --save-dev emulate4243# Start all services44npx emulate4546# Start specific services with seed data47npx emulate --service github,stripe --seed ./emulate.config.yaml4849# Generate a starter config50npx emulate init --service github51```5253## Services (0.4.1 — 12 emulators)5455| Service | Default Port | Coverage |56|---------|-------------|----------|57| **Vercel** | `:4000` | Projects, deployments, domains, env vars, teams |58| **GitHub** | `:4001` | Repos, PRs, issues, comments, reviews, Actions, webhooks, orgs, teams |59| **Google OAuth** | `:4002` | OAuth 2.0 authorize, token exchange, userinfo |60| **Slack** | `:4003` | Chat, conversations, users, reactions, OAuth v2 with consent UI |61| **Apple Auth** | `:4004` | Sign in with Apple — OIDC discovery, JWKS (RS256), auth flow, token exchange |62| **Microsoft Entra** | `:4005` | OAuth 2.0/OIDC v2.0, authorization code + PKCE, refresh token rotation, v1 token endpoint, Graph `/users/{id}` |63| **AWS** | `:4006` | S3 buckets, SQS queues, IAM users/roles, STS identity |64| **MongoDB Atlas** *(0.4+)* | `:4007` | Admin API v2 (projects, clusters, DB users) + Data API v1 (full CRUD + aggregate) |65| **Okta** *(0.4+)* | `:4008` | OIDC discovery, JWKS, authorize/token/userinfo/revoke/introspect, Users/Groups/Apps CRUD |66| **Resend** *(0.4+)* | `:4009` | Send + batch (100/req), list/retrieve/cancel, domains, API keys, audiences, contacts, **local inbox** (`GET /inbox`) |67| **Stripe** *(0.4+)* | `:4010` | Customers, payment methods, customer sessions, payment intents, charges, products, prices, **hosted checkout session** w/ webhook delivery |68| **Clerk** | (on-demand) | Users, sessions, organizations |6970See `references/api-coverage.md` for full endpoint lists.7172### Next.js Adapter (0.4+) — `@emulators/adapter-next`7374Runs emulators **on the same origin** as your Next.js app via a catch-all route handler. Fixes the OAuth callback URL drift problem on Vercel preview deploys — no more `http://localhost:4001` redirect mismatches.7576```typescript77// next.config.js78const { withEmulate } = require('@emulators/adapter-next')79module.exports = withEmulate({ /* your next config */ })8081// app/api/[...emulate]/route.ts82import { createEmulateHandler } from '@emulators/adapter-next'83export const { GET, POST } = createEmulateHandler({84 services: ['github', 'stripe', 'resend'],85 persistence: { /* load(), save() or built-in filePersistence */ },86})87```8889## Seed Config Structure9091A seed config pre-populates the emulator with tokens, users, repos, and projects so tests start from a known state.9293```yaml94# emulate.config.yaml95tokens:96 dev_token:97 login: yonatangross98 scopes: [repo, workflow, admin:org]99 ci_token:100 login: ci-bot101 scopes: [repo]102103github:104 users:105 - login: yonatangross106 name: Yonatan Gross107 - login: ci-bot108 name: CI Bot109 repos:110 - owner: yonatangross111 name: my-project112 private: false113 default_branch: main114 topics: [typescript, testing]115116vercel:117 users:118 - username: yonatangross119 email: yonaigross@gmail.com120 projects:121 - name: my-docs122 framework: next123124# NEW in 0.4.x — drop-in seed blocks125okta:126 users:127 - login: alice@example.com128 firstName: Alice129 lastName: Smith130 groups: [{ name: Everyone }, { name: Admins }]131 apps: [{ name: My Web App }]132 authorization_servers:133 - name: default134 audiences: ["api://default"]135136resend:137 domains: [{ name: example.com }]138 api_keys: [{ name: default }]139 # In tests: GET http://localhost:4009/inbox to assert captured emails140141stripe:142 customers:143 - name: Test Customer144 email: customer@example.com145 products: [{ name: Pro Plan }, { name: Starter Plan }]146 prices:147 - { product: Pro Plan, unit_amount: 4900, currency: usd, recurring: { interval: month } }148 - { product: Starter Plan, unit_amount: 1900, currency: usd, recurring: { interval: month } }149 # Webhook delivery fires on checkout.session.completed / expired150151mongoatlas:152 projects: [{ name: my-project }]153 clusters: [{ project: my-project, name: my-cluster }]154 database_users: [{ project: my-project, username: app-user }]155```156157See `rules/seed-config.md` for full schema and best practices.158159## Programmatic SDK160161> Service packages live under the `@emulators/*` scope (e.g., `@emulators/github`, `@emulators/stripe`). The programmatic API (`createEmulator`) is exported from the top-level `emulate` package.162163```typescript164import { createEmulator } from 'emulate'165166const github = await createEmulator({ service: 'github', port: 4001 })167// github.url -> 'http://localhost:4001'168169// State is real — create a PR and it appears in the list170const res = await fetch(`${github.url}/repos/org/repo/pulls`, {171 method: 'POST',172 headers: { Authorization: 'Bearer dev_token' },173 body: JSON.stringify({ title: 'Test PR', head: 'feature', base: 'main' })174})175176const prs = await fetch(`${github.url}/repos/org/repo/pulls`)177// -> includes the PR we just created178179// Cleanup180github.reset() // Synchronous state wipe181await github.close() // Shut down server182```183184See `references/sdk-patterns.md` for advanced patterns (multi-service, lifecycle hooks).185186## Webhook Delivery187188Emulate delivers real webhooks with HMAC-SHA256 signatures when state changes:189190```typescript191import crypto from 'crypto'192193function verifyWebhook(payload: string, signature: string, secret: string): boolean {194 const expected = 'sha256=' + crypto195 .createHmac('sha256', secret)196 .update(payload)197 .digest('hex')198 return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))199}200```201202See `rules/webhook-setup.md` for webhook receiver patterns.203204## CI Integration205206```yaml207# .github/workflows/test.yml208jobs:209 test:210 steps:211 - uses: actions/checkout@v4212 - name: Start emulate213 run: npx emulate --service github --seed .emulate/ci.yaml &214 - name: Wait for emulate215 run: sleep 2216 - name: Run tests217 run: npm test218 env:219 GITHUB_API_BASE: http://localhost:4001220 VERCEL_API_BASE: http://localhost:4000221```222223### Parallel Test Execution224225Each test worker gets its own port to avoid race conditions:226227```typescript228// vitest.config.ts229const workerPort = 4001 + parseInt(process.env.VITEST_WORKER_ID || '0')230```231232See `rules/parallel-ci.md` for full parallel isolation patterns.233234## Decision Matrix235236| Tool | When to Use | Stateful? | Platforms |237|------|------------|-----------|-----------|238| **emulate** (FIRST CHOICE) | GitHub/Vercel/Google/Slack/Apple/Entra/AWS/Okta/Resend/Stripe/MongoDB testing | YES | All 12 services |239| Pact | Contract verification between services | No | Any |240| MSW | In-browser/Node HTTP mocking | No | Any |241| Nock | Node.js HTTP intercept | No | Any |242| WireMock | HTTP stub server | Partial | Any |243244**Use emulate when:**245- Testing code that calls GitHub, Vercel, Google, Slack, Apple, Entra, AWS, Okta, Resend, Stripe, or MongoDB Atlas246- You need state persistence across multiple API calls in a test247- You want webhook delivery with real HMAC signatures (GitHub, Stripe)248- You need cascading side-effects (delete repo -> PRs cascade-delete)249- You need to assert on sent emails without hitting a real provider (Resend local `/inbox`)250- You need hosted Stripe checkout sessions with real redirect flow in tests251252**Use MSW/Nock when:**253- Mocking arbitrary HTTP APIs not covered by emulate254- You need in-browser interception (MSW)255- Tests only need single request/response pairs256257## Related Skills258259- `testing-integration` — Integration test patterns (emulate as first choice for API tests)260- `testing-e2e` — End-to-end test patterns with emulated backends261- `testing-unit` — Unit test patterns (use emulate for API-dependent units)262- `security-patterns` — Auth token patterns (emulate token seeding)263264## CLI Reference265266See `references/cli-reference.md` for all CLI flags and commands.267268## SDK Patterns269270See `references/sdk-patterns.md` for programmatic `createEmulate()` usage.