Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ permissions:
contents: read

env:
EMULATOR_PACKAGES: adapter-next adapter-nuxt apple aws clerk core github google linear microsoft mongoatlas okta resend slack stripe twilio vercel
EMULATOR_PACKAGES: adapter-next adapter-nuxt apple aws clerk core github google jira linear microsoft mongoatlas okta resend slack stripe twilio vercel

jobs:
check-release:
Expand Down
129 changes: 128 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ All services listen on IPv4 loopback (`127.0.0.1`) by default. No config file ne
- **Clerk** on `http://localhost:4011`
- **Linear** on `http://localhost:4012`
- **Twilio** on `http://localhost:4013`
- **Jira** on `http://localhost:4014`

Stripe webhooks configured with a secret include a `Stripe-Signature` header signed over the timestamp and raw request body.

Expand Down Expand Up @@ -251,7 +252,7 @@ afterAll(() => Promise.all([github.close(), vercel.close()]))

| Option | Default | Description |
|--------|---------|-------------|
| `service` | *(required)* | Service name: `'vercel'`, `'github'`, `'google'`, `'slack'`, `'apple'`, `'microsoft'`, `'okta'`, `'aws'`, `'resend'`, `'stripe'`, `'mongoatlas'`, `'clerk'`, `'linear'`, or `'twilio'` |
| `service` | *(required)* | Service name: `'vercel'`, `'github'`, `'google'`, `'slack'`, `'apple'`, `'microsoft'`, `'okta'`, `'aws'`, `'resend'`, `'stripe'`, `'mongoatlas'`, `'clerk'`, `'linear'`, `'twilio'`, or `'jira'` |
| `port` | `4000` | Port for the HTTP server |
| `hostname` | `127.0.0.1` | Listening address for built-in and custom emulators |
| `seed` | none | Inline seed data (same shape as YAML config) |
Expand Down Expand Up @@ -640,6 +641,43 @@ twilio:
conversations:
services:
- friendly_name: Local Conversations

jira:
site:
name: acme
users:
- email: admin@example.com
display_name: Admin User
admin: true
api_token: jira_test_token
- email: dev@example.com
display_name: Developer
api_token: jira_dev_token
projects:
- key: ENG
name: Engineering
lead: admin@example.com
statuses: [To Do, In Progress, In Review, Done]
components: [API, Web]
versions: ["1.0.0"]
sprints:
- project: ENG
name: ENG Sprint 1
state: active
issues:
- project: ENG
summary: Fix local checkout test
type: Bug
status: To Do
priority: High
assignee: dev@example.com
labels: [checkout]
sprint: ENG Sprint 1
webhooks:
- name: Local issue events
url: http://localhost:3000/api/webhooks/jira
events: [jira:issue_created, jira:issue_updated, comment_created]
jql: project = ENG
```

GitHub organization `members` are optional. Each entry references a seeded user by `login`; `role` defaults to `member`, while `admin` creates an organization administrator. Unknown users are ignored. Seeded memberships use the synthetic `members` team and grant private organization repository access.
Expand Down Expand Up @@ -735,6 +773,19 @@ linear:
actor: user
```

### Jira (Atlassian) OAuth 2.0 Apps

```yaml
jira:
oauth_apps:
- client_id: "jira_example_client_id"
client_secret: "example_client_secret"
name: "My Jira App"
redirect_uris:
- "http://localhost:3000/api/auth/callback/atlassian"
scopes: [read:jira-work, write:jira-work, read:jira-user, manage:jira-webhook, offline_access]
```

### Apple OAuth Clients

```yaml
Expand Down Expand Up @@ -1286,6 +1337,79 @@ To test inbound SMS webhooks, configure a seeded phone number `sms_url`, then ca

Current Twilio limits: no carrier delivery, A2P 10DLC, toll-free verification, real phone number purchasing, exact rate limits, Studio, Flex, TaskRouter, Video, Sync, Segment, SendGrid, Conversations SDK websocket behavior, or complete TwiML interpreter.

## Jira API

Stateful Jira Cloud REST API emulation (platform REST API v3 and v2, plus the Jira Software Agile API) with seeded users, API tokens, projects, workflows, issue types, priorities, resolutions, custom fields, components, versions, boards, sprints, issues, comments, worklogs, issue links, webhooks, and OAuth 2.0 (3LO) apps. Writes record changelog history and dispatch Jira-shaped webhooks.

Default local credentials (Basic auth `email:api_token`, the same scheme Jira Cloud API tokens use):

```text
JIRA_BASE_URL=http://localhost:4014
JIRA_EMAIL=admin@jira.local
JIRA_API_TOKEN=jira_test_token
```

The default seed also creates `dev@jira.local` / `jira_dev_token`, project `EMU` with board `1`, active sprint `1`, and issue `EMU-1`. Project and webhook changes require an admin; components and versions also accept the project lead.

### Issues

- `POST /rest/api/3/issue`, `POST /rest/api/3/issue/bulk` - create issues (v3 requires Atlassian Document Format descriptions; v2 accepts plain strings)
- `GET /rest/api/3/issue/{issueIdOrKey}` - supports `fields` (`*all`, `-comment`) and `expand` (`changelog`, `renderedFields`, `names`, `schema`, `transitions`)
- `PUT /rest/api/3/issue/{issueIdOrKey}` - edit with `fields` and `update` operations (`set`, `add`, `remove`, `issuelinks`, `comment`)
- `DELETE /rest/api/3/issue/{issueIdOrKey}` - `deleteSubtasks=true` is required for issues with subtasks
- `PUT /rest/api/3/issue/{issueIdOrKey}/assignee`
- `GET|POST /rest/api/3/issue/{issueIdOrKey}/transitions` - moving to a Done category status sets the resolution
- `GET /rest/api/3/issue/{issueIdOrKey}/changelog`, `GET /rest/api/3/issue/{issueIdOrKey}/editmeta`
- `GET /rest/api/3/issue/createmeta/{projectIdOrKey}/issuetypes[/{issueTypeId}]`
- Comments, watchers, worklogs (`timeSpent` like `1h 30m`), and issue links under `/rest/api/3/issue/{key}/...` and `/rest/api/3/issueLink`

### Search (JQL)

- `GET|POST /rest/api/3/search/jql` - enhanced search with `nextPageToken`; rejects unbounded queries like Jira Cloud
- `POST /rest/api/3/search/approximate-count`
- `GET|POST /rest/api/3/search` - legacy `startAt`/`total` search
- `GET /rest/api/3/issue/picker`

The JQL engine supports `AND`, `OR`, `NOT`, parentheses, `=`, `!=`, `~`, `!~`, `>`, `>=`, `<`, `<=`, `IN`, `NOT IN`, `IS [NOT] EMPTY`, `ORDER BY`, relative dates (`-7d`), and functions such as `currentUser()`, `now()`, `startOfDay()`, `openSprints()`, `closedSprints()`, `linkedIssues()`, `subTaskIssueTypes()`, and `unreleasedVersions()`. Unknown fields, values, and functions return Jira's error messages.

### Projects, Users, And Configuration

- `GET /rest/api/3/myself`, `/user`, `/user/search`, `/users/search`, `/user/assignable/search`, `/user/bulk`
- `GET|POST /rest/api/3/project`, `GET /rest/api/3/project/search`, `GET|PUT|DELETE /rest/api/3/project/{projectIdOrKey}`
- `GET /rest/api/3/project/{key}/statuses`, `/components`, `/versions`; `POST /rest/api/3/component`, `POST /rest/api/3/version`
- `GET /rest/api/3/issuetype`, `/status`, `/statuscategory`, `/priority`, `/resolution`, `/field`, `/label`, `/issueLinkType`, `/mypermissions`, `/serverInfo`

### Agile

- `GET|POST /rest/agile/1.0/board`, `GET /rest/agile/1.0/board/{id}/issue`, `/backlog`, `/sprint`, `/epic`, `/configuration`
- `POST /rest/agile/1.0/sprint`, `GET|POST|PUT|DELETE /rest/agile/1.0/sprint/{id}` - start and close sprints; closing returns unfinished issues to the backlog
- `GET|POST /rest/agile/1.0/sprint/{id}/issue`, `POST /rest/agile/1.0/backlog/issue`
- The same routes are served under `/rest/software/1.0`

### Webhooks

- `GET|POST /rest/webhooks/1.0/webhook`, `GET|PUT|DELETE /rest/webhooks/1.0/webhook/{id}` - admin webhooks with JQL filters, `excludeBody`, and an optional `secret` that signs deliveries with `X-Hub-Signature: sha256=<hmac>`
- `GET|POST|DELETE /rest/api/3/webhook`, `PUT /rest/api/3/webhook/refresh` - dynamic webhooks for OAuth 2.0 apps
- Events: `jira:issue_created`, `jira:issue_updated` (with `changelog` and `issue_event_type_name`), sent once per edit even when the edit also adds a comment, `jira:issue_deleted`, `comment_created`, `comment_updated`, `comment_deleted`

### OAuth 2.0 (3LO) And The API Gateway

- `GET /authorize` - Atlassian consent screen with a local user picker (`audience=api.atlassian.com`)
- `POST /oauth/token` - `authorization_code` and rotating `refresh_token` grants (refresh tokens require `offline_access`)
- `GET /oauth/token/accessible-resources`, `GET /me`
- `/ex/jira/{cloudId}/rest/...` - the `api.atlassian.com` gateway path for OAuth clients; the default cloud ID is `11111111-2222-4333-8444-555555555555`

Point clients at the emulator by replacing `https://your-domain.atlassian.net` with the emulator URL, and `https://api.atlassian.com` / `https://auth.atlassian.com` with the same URL for OAuth apps.

### Inspector

- `GET /` - tabbed inspector for issues, projects, boards and sprints, users, webhooks and deliveries, and auth
- `GET /browse/{issueKey}` - issue detail page

OAuth scope checks are relaxed by default. Set `jira.strict_scopes: true` to require granular scopes such as `read:jira-work` and `write:jira-work` for OAuth tokens. API tokens always carry the user's full permissions.

Current Jira limits: no attachments, filters, dashboards, workflow and screen scheme administration, permission schemes, groups, service management, Confluence, rate limiting, or exact search relevance. Workflows allow any status to move to any other status, like team-managed projects.

## Apple Sign In

Sign in with Apple emulation with authorization code flow, PKCE support, RS256 ID tokens, and OIDC discovery.
Expand Down Expand Up @@ -1651,6 +1775,7 @@ packages/
slack/ # Slack Web API, OAuth v2, incoming webhooks
linear/ # Linear GraphQL API, OAuth, webhooks
twilio/ # Twilio Messaging, Verify, Voice, webhooks
jira/ # Jira Cloud REST v2/v3, JQL, Agile, webhooks, OAuth 2.0
apple/ # Apple Sign In / OIDC
microsoft/ # Microsoft Entra ID OAuth 2.0 / OIDC + Graph /me
aws/ # AWS S3, SQS, IAM, STS
Expand Down Expand Up @@ -1680,6 +1805,8 @@ Tokens are configured in the seed config and map to users. Pass them as `Authori

**Twilio**: HTTP Basic auth accepts the seeded Account SID/Auth Token pair or API Key/API Secret pair. Product-host APIs are exposed under local prefixes such as `/messaging/v1` and `/verify/v2`; the 2010 API lives at `/2010-04-01`.

**Jira**: HTTP Basic auth with a seeded user's `email:api_token`, or `Authorization: Bearer <token>` with an API token or an OAuth 2.0 access token. Errors use Jira's `{ "errorMessages": [], "errors": {} }` shape. OAuth clients call the API through `/ex/jira/{cloudId}`.

**Apple**: OIDC authorization code flow with RS256 ID tokens. On first auth per user/client pair, a `user` JSON blob is included.

**Microsoft**: OIDC authorization code flow with PKCE support. Also supports client credentials grants. Microsoft Graph `/v1.0/me` available.
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/api/docs-chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const maxDuration = 60;

const DEFAULT_MODEL = "anthropic/claude-haiku-4.5";

const SYSTEM_PROMPT = `You are a helpful documentation assistant for emulate, a local drop-in replacement for Vercel, GitHub, Google, Slack, Apple, Microsoft, Okta, AWS, Resend, Stripe, MongoDB Atlas, Clerk, Linear, and Twilio APIs used in CI and no-network sandboxes.
const SYSTEM_PROMPT = `You are a helpful documentation assistant for emulate, a local drop-in replacement for Vercel, GitHub, Google, Slack, Apple, Microsoft, Okta, AWS, Resend, Stripe, MongoDB Atlas, Clerk, Linear, Twilio, and Jira APIs used in CI and no-network sandboxes.

emulate provides fully stateful, production-fidelity API emulation, not mocks. The CLI is installed as the "emulate" npm package and run via "npx emulate". It also supports a programmatic API via createEmulator, a Next.js adapter (@emulators/adapter-next), and a Nuxt adapter (@emulators/adapter-nuxt) for embedding emulators in your app.

Expand Down
1 change: 1 addition & 0 deletions apps/web/content/docs/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ packages/
slack/ # Slack Web API, OAuth v2, incoming webhooks
linear/ # Linear GraphQL API, OAuth, webhooks
twilio/ # Twilio Messaging, Verify, Voice, webhooks
jira/ # Jira Cloud REST v2/v3, JQL, Agile, webhooks, OAuth 2.0
apple/ # Apple Sign In / OIDC
microsoft/ # Microsoft Entra ID OAuth 2.0 / OIDC + Graph /me
aws/ # AWS S3, SQS, IAM, STS
Expand Down
51 changes: 51 additions & 0 deletions apps/web/content/docs/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,57 @@ twilio:
- friendly_name: Local Conversations
```

## Jira Seed Config

```yaml
jira:
site:
name: acme
users:
- email: admin@example.com
display_name: Admin User
admin: true
api_token: jira_test_token
- email: dev@example.com
display_name: Developer
api_token: jira_dev_token
projects:
- key: ENG
name: Engineering
lead: admin@example.com
statuses: [To Do, In Progress, In Review, Done]
components: [API, Web]
versions: ["1.0.0"]
sprints:
- project: ENG
name: ENG Sprint 1
state: active
issues:
- project: ENG
summary: Fix local checkout test
type: Bug
status: To Do
priority: High
assignee: dev@example.com
labels: [checkout]
sprint: ENG Sprint 1
webhooks:
- name: Local issue events
url: http://localhost:3000/api/webhooks/jira
events: [jira:issue_created, jira:issue_updated, comment_created]
jql: project = ENG
oauth_apps:
- client_id: jira_example_client_id
client_secret: example_client_secret
name: My Jira App
redirect_uris:
- http://localhost:3000/api/auth/callback/atlassian
scopes: [read:jira-work, write:jira-work, read:jira-user, manage:jira-webhook, offline_access]
strict_scopes: false
```

Users authenticate with Basic auth `email:api_token`. Issue `parent` and link references accept an issue key or a seeded summary.

## Custom emulators

Custom definitions created with `defineEmulator` from `emulate` work in the CLI, in-process tests, and both framework adapters. The same definition provides typed state, HTTP handlers, reset, versioned snapshots, and optional inspection/persistence. See [Custom emulators](/docs/custom-emulators) for the quickstart, API reference, and complete lifecycle semantics.
3 changes: 2 additions & 1 deletion apps/web/content/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Getting Started"
---

Local drop-in replacement for Vercel, GitHub, Google, Slack, Apple, Microsoft, Okta, AWS, Resend, Stripe, MongoDB Atlas, Clerk, Linear, and Twilio APIs. Built for CI and no-network sandboxes. Fully stateful, production-fidelity API emulation. Not mocks.
Local drop-in replacement for Vercel, GitHub, Google, Slack, Apple, Microsoft, Okta, AWS, Resend, Stripe, MongoDB Atlas, Clerk, Linear, Twilio, and Jira APIs. Built for CI and no-network sandboxes. Fully stateful, production-fidelity API emulation. Not mocks.

## Quick Start

Expand All @@ -26,6 +26,7 @@ All services listen on IPv4 loopback (`127.0.0.1`) by default. No config file ne
- **Clerk** on `http://localhost:4011`
- **Linear** on `http://localhost:4012`
- **Twilio** on `http://localhost:4013`
- **Jira** on `http://localhost:4014`

## CLI

Expand Down
Loading