You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Mock by operation name + real API fallback via Atlassian Gateway
asUser().requestGraph()
✅
graphql.test.ts
Same as asApp
asApp().requestAtlassian()
❌
—
Generic Atlassian API not implemented
asUser().requestAtlassian()
❌
—
Generic Atlassian API not implemented
asUser().withProvider(provider, remote)
✅
external-auth.test.ts
Full ExternalAuthFetchMethods interface
.withProvider().hasCredentials(scopes?)
✅
external-auth.test.ts
Checks token existence, expiry, and scopes
.withProvider().requestCredentials(scopes?)
✅
external-auth.test.ts
Opens browser for OAuth dance if secret configured; falls back to warning
.withProvider().fetch(url, options)
✅
external-auth.test.ts
Mock routes first, then real HTTP with Bearer injection
.withProvider().getAccount()
✅
external-auth.test.ts
Returns ExternalAuthAccount from stored token
.withProvider().listAccounts()
✅
external-auth.test.ts
Lists linked accounts (max 1 per provider in sim)
.withProvider().asAccount(id)
✅
external-auth.test.ts
Returns account-scoped methods
fetch(url, options)
✅
—
Passes through to real globalThis.fetch with warning log
route\...``
✅
shims.test.ts
Template tag with encoding
routeFromAbsolute()
🔇
—
Exported but untested
assumeTrustedRoute()
🔇
—
Exported but untested
Storage (Legacy, deprecated)
API
Status
Tests
Notes
storage.get(key)
✅
shims.test.ts, storage.test.ts
Routes to sim.kvs
storage.set(key, value)
✅
shims.test.ts, storage.test.ts
Routes to sim.kvs
storage.delete(key)
✅
storage.test.ts
Routes to sim.kvs
storage.getSecret(key)
✅
storage.test.ts
storage.setSecret(key, value)
✅
storage.test.ts
storage.deleteSecret(key)
✅
storage.test.ts
storage.query()
⚠️
—
Basic query works via KVS shim, but entity-style storage.entity() from legacy API may not
storage.entity()
⚠️
—
Routes to entity store if available
storage.transact()
⚠️
—
May not fully match legacy API signature
Other APIs
API
Status
Tests
Notes
authorize(provider)
🔇
—
No-op, always resolves
invokeRemote(key, payload)
✅
remotes.test.ts
Full — RemoteProxy with mock-first routing, real HTTP fallback with FIT auth
invokeService(key, payload)
✅
remotes.test.ts
Same system as invokeRemote
webTrigger.getUrl(key)
✅
web-trigger.test.ts
Dev server running: real routable local URL (http://localhost:<port>/x1/<id>, served). Headless: Forge-shaped synthetic URL; fire the trigger with sim.fireWebTrigger(key) instead. deleteUrl/queryUrls mirrored, including the real v2-URL parse quirk.
getAppContext()
✅
shims.test.ts
Returns real values from manifest (appId, moduleKey) and connected account (cloudId). ARIs match Atlassian format. invocationRemainingTimeInMillis() returns 25s.
__getRuntime()
🔇
—
Internal, undocumented; necessary for @forge/api import chain not to explode. Returns { isEcosystemApp: false }
bindInvocationContext(fn)
🔇
—
Internal, undocumented; necessary for @forge/api import chain not to explode. Returns the function unchanged
privacy.reportPersonalData(accounts)
✅
shims.test.ts
POST /app/report-accounts via product API; batches in groups of 90
permissions.hasPermission(requirements)
🔇
shims.test.ts
Always returns { granted: true } in simulation
permissions.hasScope(scope)
🔇
shims.test.ts
Always returns true
permissions.canFetchFrom(type, url)
🔇
shims.test.ts
Always returns true
permissions.canLoadResource(type, url)
🔇
shims.test.ts
Always returns true
i18n.getTranslations(locale, options)
✅
shims.test.ts
Backed by I18nStore (reads __LOCALES__/ JSON files)
i18n.createTranslationFunction(locale)
✅
shims.test.ts
Backed by I18nStore; dot-path keys, fallback chains
i18n.resetTranslationsCache()
✅
shims.test.ts
Clears translation cache and I18nStore
createRequestStargateAsApp()
🔇
—
Internal, undocumented; necessary for @forge/api import chain not to explode. Returns same API client
__fetchProduct()
✅
forge-sql.test.ts
Internal, undocumented; necessary for @forge/api import chain not to explode. Factory behind requestJira/requestConfluence/SQL; handles { provider, remote, type } descriptors
Error Classes
Export
Status
Notes
FetchError
✅
HttpError
✅
NotAllowedError
✅
ExternalEndpointNotAllowedError
✅
ProductEndpointNotAllowedError
✅
RequestProductNotAllowedError
✅
NeedsAuthenticationError
✅
InvalidWorkspaceRequestedError
✅
ProxyRequestError
✅
FUNCTION_ERR
✅
isExpectedError()
✅
isForgePlatformError()
✅
isHostedCodeError()
✅
Re-exports from @forge/storage
Export
Status
Notes
WhereConditions
✅
FilterConditions
✅
SortOrder
✅
startsWith
✅
@forge/kvs
The primary key-value storage package.
API
Status
Tests
Notes
kvs.get(key)
✅
kvs.test.ts, shims.test.ts
kvs.set(key, value)
✅
kvs.test.ts, shims.test.ts
kvs.delete(key)
✅
kvs.test.ts
kvs.getMany(keys)
✅
kvs.test.ts
kvs.query().where().getMany()
✅
kvs.test.ts, shims.test.ts
Full query builder
kvs.query().where().cursor().getMany()
✅
kvs.test.ts
Cursor-based pagination
kvs.query().where().limit().getMany()
✅
kvs.test.ts
kvs.query().where().sortBy().getMany()
✅
kvs.test.ts
kvs.transact().set().delete().execute()
✅
kvs.test.ts, shims.test.ts
Atomic batch operations
kvs.getSecret(key)
✅
shims.test.ts
Separate secrets store
kvs.setSecret(key, value)
✅
shims.test.ts
kvs.deleteSecret(key)
✅
shims.test.ts
Entity Store: kvs.entity(name).set()
✅
entity-store.test.ts, entity-store-e2e.test.ts
Entity Store: kvs.entity(name).get()
✅
entity-store.test.ts
Entity Store: kvs.entity(name).delete()
✅
entity-store.test.ts
Entity Store: kvs.entity(name).query()
✅
entity-store.test.ts
Indexed queries, filters, sort, pagination
WhereConditions
✅
kvs.test.ts
FilterConditions
✅
kvs.test.ts
ForgeKvsError
✅
ForgeKvsAPIError
✅
MetadataField
✅
Sort
✅
@forge/sql
Forge SQL: relational data with real MySQL.
API
Status
Tests
Notes
sql.prepare(query).bindParams(...).execute()
✅
forge-sql.test.ts, forge-sql-e2e.test.ts
Parameterized queries
sql.prepare(query).execute()
✅
forge-sql.test.ts
sql._executeRaw(query)
✅
forge-sql.test.ts
migrationRunner.enqueue(migrations)
✅
forge-sql-e2e.test.ts, deploy-e2e.test.ts
Real @forge/sql migrationRunner works through shims
Returned (not thrown) by consumers to request a retry. Constructor takes RetryOptions and yields the serialized { _retry, retryOptions } form, matching @forge/events v3. Queue engine re-delivers with retryContext, capped at 4 retries; re-delivery is immediate (forge-sim does not wait out retryAfter delays)
QueueResponse / Response
✅
eval11-findings.test.ts
queueResponse.retry() also triggers a retry
event.retryContext
✅
eval11-findings.test.ts
{ retryCount, retryReason, retryData } populated on retry deliveries only
InvocationErrorCode
✅
eval11-findings.test.ts
Real FUNCTION_* enum values
JobProgress
✅
InvalidQueueNameError
✅
shims.test.ts
TooManyEventsError
✅
PayloadTooBigError
✅
NoEventsToPushError
✅
RateLimitError
✅
PartialSuccessError
✅
InternalServerError
✅
JobDoesNotExistError
✅
appEvents.publish(events)
✅
shims.test.ts
Publishes custom app events; fires matching triggers in same app with platform-generated payload shape
@forge/llm
OpenAI-shaped Anthropic LLM interface. Mock-first; falls through to the real Anthropic Messages API when ANTHROPIC_API_KEY is set (env or via forge-sim auth --llm).
API
Status
Tests
Notes
chat(prompt)
✅
llm.test.ts
Mock queue first, then real Anthropic proxy. Translates OpenAI-shaped messages ⇄ Anthropic native format.
stream(prompt)
✅
llm.test.ts
Returns full response as a single async-iterable chunk (no SSE parsing; overkill for local dev).
list()
✅
llm.test.ts
Returns the static list of supported Claude models.
Tool calls (tools[], tool_choice, tool_calls in response)
✅
llm.test.ts
Full agent-loop support; tool_use ⇄ tool_result translation.
System messages
✅
llm.test.ts
Translated to Anthropic's top-level system param.
LlmApiError
✅
llm.test.ts
Thrown with code NO_API_KEY when no mocks queued and no API key set.
Streaming SSE
⚠️
—
Implemented as one-chunk async-iterable; sufficient for tests, not for streaming UX work.
Simulator surface:
sim.llm method
Status
Notes
mockResponse(mock)
✅
Queue one FIFO mock.
mockResponses(...mocks)
✅
Queue many; spread args.
getHistory()
✅
[{ prompt, response }] for assertions.
reset()
✅
Clears queue + history.
setApiKey(key) / getApiKey()
✅
process.env.ANTHROPIC_API_KEY wins over config.
MCP:forge_llm_mock, forge_llm_history; see mcp.md.
@forge/object-store
Backend Object Store (file storage). Shimmed via loader hooks; pre-signed URLs
point at the dev server or a lazily-started ephemeral HTTP server so app code
can fetch() them for real. Default and CDN buckets, TTL, checksums, HTTP
Range requests.
API
Status
Tests
Notes
objectStore.createUploadUrl(body)
✅
object-store.test.ts
Pre-signed PUT URL; checksum (sha256/md5) verified on upload
objectStore.createDownloadUrl(key, options?)
✅
object-store.test.ts
Pre-signed GET URL; supports HTTP Range / 206 responses. Throws a helpful TypeError on non-string key
Re-exported from real package; reads extension.config from context. Dev server injects stored config from macro --config viewSubmit payloads (custom config) or submitTree='macroConfig'-tagged submits on flat inline-config macros.
useTheme()
✅
—
Re-exported from real package
usePermissions()
✅
—
Re-exported from real package
useIssueProperty(key, init)
✅
—
Re-exported from real package; routes through bridge shim → PropertyStore
useContentProperty(key, init)
✅
—
Re-exported from real package; routes through bridge shim → PropertyStore
useSpaceProperty(key, init)
✅
—
Re-exported from real package; routes through bridge shim → PropertyStore
useTranslation()
✅
—
Re-exported from real package; reads from I18nProvider context → bridge i18n → I18nStore
I18nProvider
✅
—
Re-exported from real package; calls bridge.i18n.createTranslationFunction()
useForm()
✅
—
Re-exported from real package (wraps react-hook-form)
useObjectStore()
✅
object-store-bridge.test.ts
Re-exported from real package; routes through bridge objectStore.* → SimulatedObjectStore
replaceUnsupportedDocumentNodes()
❌
—
ADF utility
UIKit Components (from ui-kit-components.d.ts)
Component
Status
Tests
Notes
Badge
✅
ui-integration.test.ts
BarChart
✅
—
Box
✅
ui-integration.test.ts
Button
✅
ui-integration.test.ts, simulator-ui.test.ts
ButtonGroup
✅
—
Calendar
✅
—
Checkbox
✅
—
CheckboxGroup
✅
—
ChromelessEditor
✅
—
Real @atlaskit/editor-core (ComposableEditor, appearance=chromeless)
Code
✅
—
CodeBlock
✅
—
CommentEditor
✅
—
Real @atlaskit/editor-core (ComposableEditor, appearance=comment) + Save/Cancel
DatePicker
✅
—
DonutChart
✅
—
EmptyState
✅
—
ErrorMessage
✅
—
In renderer mapping, not in shim re-export
FileCard
✅
—
In renderer mapping
FilePicker
✅
—
In renderer mapping
Form
✅
—
FormFooter
✅
—
In renderer mapping
FormHeader
✅
—
In renderer mapping
FormSection
✅
—
In renderer mapping
Heading
✅
—
HelperMessage
✅
—
In renderer mapping
HorizontalBarChart
✅
—
HorizontalStackBarChart
✅
—
Icon
✅
—
Inline
✅
—
Label
✅
—
In renderer mapping
LineChart
✅
—
LinkButton
✅
—
In renderer mapping
List
✅
—
In renderer mapping
ListItem
✅
—
In renderer mapping
LoadingButton
✅
—
In renderer mapping
Lozenge
✅
—
Modal
✅
—
ModalBody
✅
—
ModalFooter
✅
—
ModalHeader
✅
—
ModalTitle
✅
—
ModalTransition
✅
—
PieChart
✅
—
Pressable
✅
—
In renderer mapping
ProgressBar
✅
—
ProgressTracker
✅
—
In renderer mapping
Radio
✅
—
RadioGroup
✅
—
Range
✅
—
RequiredAsterisk
✅
—
In renderer mapping
SectionMessage
✅
ui-integration.test.ts
SectionMessageAction
✅
—
In renderer mapping
Select
✅
—
Spinner
✅
—
Stack
✅
ui-integration.test.ts
StackBarChart
✅
—
Tab
✅
—
TabList
✅
—
TabPanel
✅
—
Tabs
✅
—
Tag
✅
—
TagGroup
✅
—
Text
✅
ui-integration.test.ts
TextArea
✅
—
Textfield
✅
—
Lowercase-f only (matches real @forge/react). Note: devs frequently misimport as TextField because it's the conventional React casing. forge-sim deliberately does not alias TextField so the bug fails in tests instead of on deploy.
Re-exported from @forge/react, rendered via @atlaskit/inline-edit
Popup
⚠️
—
Portal flickers under React.StrictMode, same @atlaskit/portal bug as Tooltip. Works with StrictMode off.
Comment
✅
—
Re-exported + styled comment block with author/time
AdfRenderer
✅
—
Real @atlaskit/renderer (ReactRenderer), pixel-perfect ADF rendering
Global
✅
—
Re-exported, renders sidebar + main layout
User
✅
—
Re-exported, renders avatar + accountId badge
UserGroup
✅
—
Re-exported, renders grouped user avatars
Em
✅
—
Re-exported, renders <em>
Strike
✅
—
Re-exported, renders <s>
Strong
✅
—
Re-exported, renders <strong>
Frame
✅
—
Re-exported, renders sandboxed <iframe>
InlineDialog
✅
—
Already in shim (via Flag/InlineDialog)
Flag
✅
—
Already in shim
Types Only (no runtime needed)
Export
Status
Notes
XCSSObject
✅
Type
DocNode
✅
Type
Event
✅
Type
All *Props types
✅
Types from @atlaskit/forge-react-types
@forge/bridge
Frontend API for Custom UI apps (runs in iframe).
Core
API
Status
Tests
Notes
invoke(functionKey, payload)
✅
custom-ui-e2e.test.ts
Routes through bridge to resolver
requestJira(path, options)
✅
custom-ui-e2e.test.ts
Routes through bridge to product API
requestConfluence(path, options)
✅
—
requestBitbucket(path, options)
✅
—
requestRemote(remoteKey, options)
✅
remotes.test.ts
Direct fetch with FIT auth, mock-first routing
View
API
Status
Tests
Notes
view.getContext()
✅
custom-ui-e2e.test.ts
Full ForgeContext: accountId, cloudId, locale, timezone, theme, license, extension data. Hydrates via product API for Jira Issue + Confluence Content modules
view.submit(payload)
✅
modal-bridge.test.ts
In modal: postMessage to parent → closes overlay → fires onClose. Outside modal: RPC to backend
view.close(payload)
✅
modal-bridge.test.ts
Same as submit — postMessage in modal, RPC otherwise
view.onClose(callback)
✅
modal-bridge.test.ts
Stores callback, fires when modal closes
view.open()
🔇
—
No-op
view.refresh(payload)
✅
—
Triggers page reload to re-render module
view.createHistory()
✅
create-history.test.ts
Full history v5 interface wrapping browser pushState/replaceState/popstate. Works for both UIKit and Custom UI (both run in browser). Back/forward buttons work. Memory history fallback for headless/MCP mode. Compatible with react-router. Available in full-page modules (globalPage, projectPage, adminPage, spacePage, etc.)
view.theme.enable()
✅
bridge-features.test.ts
Sets data-color-mode=dark on document root
view.changeWindowTitle(title)
✅
bridge-features.test.ts
Sets document.title
view.emitReadyEvent()
✅
bridge-features.test.ts
Dispatches forge-sim:ready custom event
view.createAdfRendererIframeProps()
❌
—
ADF rendering setup
Modal
API
Status
Tests
Notes
new Modal(options)
✅
modal-bridge.test.ts
Full options: resource, onClose, size, context, closeOnEscape, closeOnOverlayClick, title
modal.open()
✅
modal-bridge.test.ts
Creates Atlaskit-style overlay + iframe to /module/<resource>/?_modal=true&context=<b64>
Router
API
Status
Tests
Notes
router.navigate(location)
✅
bridge-features.test.ts
Resolves NavigationTarget to product URL, navigates
router.open(location)
✅
bridge-features.test.ts
Resolves NavigationTarget to product URL, opens in new tab
Product-specific bridge APIs for Confluence editor/macro/byline. All no-ops; returns sensible defaults.
API
Status
Tests
Notes
getEditorContent()
🔇
product-bridges.test.ts
Returns { data: '' }; no Confluence editor in sim
getMacroContent()
🔇
product-bridges.test.ts
Returns { data: '' }
updateMacro(content)
🔇
product-bridges.test.ts
Returns true (no-op)
setMacroViewportHeight(height)
🔇
product-bridges.test.ts
Returns true (no-op)
updateBylineProperties(payload)
🔇
product-bridges.test.ts
No-op
@forge/dashboards-bridge
Product-specific bridge APIs for Jira Dashboard widgets. All no-ops: callback registration stubs.
API
Status
Tests
Notes
widgetEdit.onSave(cb)
🔇
product-bridges.test.ts
Registers save callback (host-driven)
widgetEdit.onProductSave(cb)
🔇
product-bridges.test.ts
Registers product-save callback (host-driven)
widgetEdit.onSaveError(cb)
🔇
product-bridges.test.ts
Registers error callback (host-driven)
widgetEdit.updateConfig(config)
🔇
product-bridges.test.ts
Pushes config to host (no-op + log)
widget.setPreviewConfig(config)
🔇
product-bridges.test.ts
Pushes preview config to host (no-op + log)
Packages Not Shimmed (direct imports will load real package or fail)
Package
Status
Notes
@forge/auth
❌
authorizeJiraWithFetch, authorizeConfluenceWithFetch. Not intercepted by loader hooks.
@forge/i18n
⚠️
Not intercepted by loader hooks, but bridge shim's I18nStore provides equivalent functionality. Real package partially works for types/constants.
@forge/egress
❌
Egress filtering rules. Not intercepted. Not commonly imported directly by apps.
@forge/manifest
❌
Manifest types. Not intercepted. Types-only usage would work at compile time.
@forge/storage
⚠️
Not directly shimmed, but @forge/api re-exports its query types. Direct import { storage } from '@forge/storage' would load the real package.
Manifest Modules
Module types recognized by forge-sim manifest parser.
Parsed & Rendered
Module Type
Status
Notes
jira:issuePanel
✅
Full: deploy, render, dev preview
jira:issueActivity
✅
Parsed and renderable
jira:issueContext
✅
Parsed and renderable
jira:issueGlance
✅
Parsed and renderable
jira:issueAction
✅
Parsed and renderable
jira:globalPage
✅
Parsed and renderable
jira:projectPage
✅
Parsed and renderable
jira:adminPage
✅
Parsed and renderable
jira:dashboardGadget
✅
Parsed and renderable
confluence:globalPage
✅
Parsed and renderable
confluence:spacePage
✅
Parsed and renderable
confluence:contentAction
✅
Parsed and renderable
confluence:contentBylineItem
✅
Parsed and renderable
confluence:contextMenu
✅
Parsed and renderable
macro
✅
Confluence macro — view + custom config sub-module (config: { resource: '...' }) with View/Config tabs in the parent shell, plus inline config (config: true / config: {} with ForgeReconciler.addConfig) rendered as in-iframe View/Config tabs from the reconciler's MacroConfig container. viewSubmit-driven config save (tagged with submitTree), useConfig() reads extension.config.
Parsed but Not Rendered
Module Type
Status
Notes
function
✅
Loaded and invocable
consumer
✅
Wired to queues
trigger
✅
Event triggers registered. 143 event templates with typed payloads.
scheduledTrigger
✅
Fireable on demand + on startup in dev mode
webtrigger
✅
HTTP endpoints at /__trigger/<key>, full request/response mapping
Config UI renders (create/edit/view resources), function invocable. No workflow transition simulation.
jira:workflowCondition
⚠️
Config UI renders, function invocable. No workflow transition simulation.
jira:workflowPostFunction
⚠️
Config UI renders, function invocable. No workflow transition simulation.
jira:customField
✅
View/edit sub-module extraction, grouped module picker, mock fieldValue in context. Jira Expressions (formatter, edit.validation.expression) not evaluated.
jira:customFieldType
✅
Same as customField. Schema validation not enforced locally.
jira:command
⚠️
Parsed, page targets, resource-based commands. No command palette simulation.
Generic Parse (limited context)
Any module type with a resource: key is parsed by the generic fallthrough at
manifest.ts:637-667 and rendered as a UI module. These get only the default
{ type } extension context: no module-type-specific fields (e.g. sprint,
board, portal request). See module-support.md for the
per-module breakdown.
Module Type
Status
Notes
jira:serviceDeskPortalRequestDetail
⚠️
JSM portal module
jira:serviceDeskPortalRequestCreate
⚠️
JSM portal module
jira:serviceDeskPortalRequestList
⚠️
JSM portal module
jira:serviceDeskQueuePage
⚠️
JSM module
jira:backlogItemAction
⚠️
Jira Software action
jira:boardIssueAction
⚠️
Jira Software action
jira:sprintAction
⚠️
Jira Software action
jira:uiModificationsOverride
⚠️
UI modifications variant
confluence:homepageFeed
⚠️
Gets default global Confluence context
confluence:spaceSidebarItem
⚠️
Confluence sidebar item
bitbucket:pipelineStep
⚠️
Bitbucket module
bitbucket:repoPullRequestOverview
⚠️
Bitbucket module
bitbucket:repoPage
⚠️
Bitbucket module
compass:component
⚠️
Compass module
compass:adminPage
⚠️
Compass module
Not Parsed
Modules with no resource: and no resolver wiring: nothing for the simulator
to load or render.
Module Type
Status
Notes
rovo:agent
❌
Rovo AI agent definition (config-only + AI; needs LLM integration)