Skip to content

Latest commit

 

History

History
698 lines (578 loc) · 38.9 KB

File metadata and controls

698 lines (578 loc) · 38.9 KB

Forge Platform Implementation Matrix

Complete mapping of every Forge API, hook, component, and platform feature against forge-sim's implementation status.

Last updated: 2026-07-19

2,526 tests across 140 test files (2,360 core / 133 files

  • 166 renderer / 7 files)

41 MCP tools + 4 resources

The stats block above is auto-generated by npm run docs:stats. Do not edit by hand; re-run the script after adding tests.

Legend

Symbol Meaning
Fully implemented and tested
⚠️ Partially implemented or stubbed
Not implemented (will error or return undefined)
🔇 Stubbed no-op (won't crash, but doesn't do anything)

@forge/api

The main backend API package. Imported by resolver/trigger/consumer functions.

Fetch & Product APIs

API Status Tests Notes
requestJira(route, options) shims.test.ts, simulator.test.ts, my-issues-e2e.test.ts Supports mock + real API proxy
requestConfluence(route, options) shims.test.ts Same as Jira
requestBitbucket(route, options) Same as Jira (no dedicated test)
asApp().requestJira() shims.test.ts
asUser().requestJira() shims.test.ts
asUser(accountId).requestJira() ⚠️ accountId param is ignored; no user impersonation
asApp().requestConfluence() shims.test.ts
asApp().requestBitbucket()
asApp().requestGraph() graphql.test.ts 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
DDL (CREATE TABLE, ALTER, INDEX) forge-sql-e2e.test.ts Real MySQL 8.4 via mysql-memory-server
JOINs, aggregation, subqueries deploy-e2e.test.ts AVG, COUNT, SUM, CASE WHEN, etc.
Foreign keys, constraints persistence.test.ts
Connection pooling / limits No simulation of Forge's connection limits

@forge/events

Async events and queue processing.

API Status Tests Notes
new Queue({ key }) shims.test.ts, queue.test.ts
queue.push(events) shims.test.ts, queue.test.ts, retro-board-e2e.test.ts Single and batch push
queue.push({ body, delayInSeconds }) queue.test.ts Delayed delivery
queue.push({ body, concurrencyKey }) concurrency.test.ts Controls parallel execution
queue.getJob(jobId) queue.test.ts
InvocationError eval11-findings.test.ts 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
objectStore.createPublicUploadUrl(body) object-store.test.ts CDN bucket variant
objectStore.createPublicDownloadUrl(key, options?) object-store.test.ts CDN bucket variant
objectStore.createCDNUrl(key, options?) object-store.test.ts CDN URL with cache options
objectStore.get(key, options?) object-store.test.ts Returns ObjectReference metadata or undefined
objectStore.delete(key, options?) object-store.test.ts Deleting an absent key succeeds (Forge parity)
errorCodes UNKNOWN_ERROR, APP_NOT_ENABLED, RATE_LIMIT_EXCEEDED (matches real @forge/object-store 2.0.0 exports)
objectStore.put(key, data, ttl?) / .download(key) ⚠️ object-store.test.ts Sim-only conveniences, marked @deprecated — real package requires the pre-signed URL flow

MCP: forge_objectstore_put, forge_objectstore_get, forge_objectstore_list, forge_objectstore_delete, forge_objectstore_create_download_url.


@forge/resolver

Resolver function registration.

API Status Tests Notes
new Resolver().define(key, handler) shims.test.ts, deployer.test.ts
resolver.getDefinitions() shims.test.ts
Multi-function resolvers deploy-e2e.test.ts Multiple define() calls

@forge/react

UIKit components and hooks. The reconciler produces ForgeDoc.

Core

Export Status Tests Notes
ForgeReconciler (default export) simulator-ui.test.ts, ui-integration.test.ts Re-exports real @forge/react reconciler
xcss() Style objects

Hooks

Hook Status Tests Notes
useProductContext() Re-exported from real package
useConfig() macro-config.test.ts, macro-inline-config.test.ts, macro-config-bridge.test.ts 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.
Tile In renderer mapping
AtlassianTile In renderer mapping
AtlassianIcon In renderer mapping
TimePicker In renderer mapping
Toggle
Tooltip ⚠️ Portal flickers under React.StrictMode due to @atlaskit/portal double-effect bug. Works correctly with StrictMode off.
ValidMessage In renderer mapping

Non-UIKit Components (from components/index.d.ts)

Component Status Tests Notes
DynamicTable Separate module, re-exported
Image
Link
UserPicker
Table / Head / Row / Cell
InlineEdit 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
router.getUrl(location) bridge-features.test.ts Resolves NavigationTarget → URL (Issue, Content, Space, Dashboard, etc.)
router.reload() Calls window.location.reload()
NavigationTarget Constant exported

Events (cross-module communication)

API Status Tests Notes
events.emit(event, payload) Local dispatch within process (in-memory listener registry)
events.on(event, callback) Registers listener, returns unsubscribe handle
events.emitPublic(event, payload) bridge-features.test.ts Dispatches locally with public: prefix + notifies server
events.onPublic(event, callback) bridge-features.test.ts Subscribes with public: prefix, returns unsubscribe handle

Realtime (pub/sub)

API Status Tests Notes
realtime.publish(channel, payload) realtime.test.ts Scoped channel pub/sub. MCP: forge_realtime_publish
realtime.subscribe(channel, callback) realtime.test.ts Returns unsubscribe handle
realtime.publishGlobal(channel, payload) realtime.test.ts Cross-experience global channel
realtime.subscribeGlobal(channel, callback) realtime.test.ts Returns unsubscribe handle

Object Store (file storage)

API Status Tests Notes
objectStore.upload(params) object-store-bridge.test.ts Upload from Custom UI / UIKit — resolver mints pre-signed PUT URLs, blobs mapped back via checksum
objectStore.download(params) object-store-bridge.test.ts Pre-signed GET round-trip; absent keys filtered from results
objectStore.getMetadata(params) object-store-bridge.test.ts Per-key metadata objects
objectStore.delete(params) object-store-bridge.test.ts Removes objects from the store

Other

API Status Tests Notes
showFlag(options) bridge-features.test.ts, eval7-f7-bridge-showflag.test.ts Renders Atlaskit-styled toast (stacking, auto-dismiss, actions, close handle) in both the UIKit renderer and the Custom UI dev bridge
rovo.open(payload) Rovo AI agent sidebar
rovo.isEnabled()
i18n.getTranslations(locale, options) Reads from I18nStore (app's LOCALES dir)
i18n.createTranslationFunction(locale) Returns t(key, defaultValue) backed by I18nStore
i18n.resetTranslationsCache() Clears translation cache and store
permissions.check() bridge-features.test.ts Always returns { hasPermission: true }
featureFlags.evaluate() 🔇 bridge-features.test.ts Returns undefined (stub; no feature flag backend)
invokeRemote(key, options) remotes.test.ts, bridge-invoke-routing.test.ts Endpoint resolution, route prefix, FIT auth, mock-first
invokeService(key, options) remotes.test.ts Same system as invokeRemote

@forge/resolver

API Status Tests Notes
new Resolver() shims.test.ts
resolver.define(key, handler) shims.test.ts, deployer.test.ts
resolver.getDefinitions() shims.test.ts

@forge/jira-bridge

Product-specific bridge APIs for Jira host UI. All no-ops in forge-sim; the host product isn't present. App code that imports these won't crash.

API Status Tests Notes
new ViewIssueModal(opts).open() 🔇 product-bridges.test.ts Logs + resolves. Stores onClose but never fires it (no host)
new CreateIssueModal(opts).open() 🔇 product-bridges.test.ts Logs + resolves. Context and onClose stored but inert
workflowRules.onConfigure(fn) 🔇 product-bridges.test.ts Registers callback (host-driven, never fires in sim)
uiModificationsApi.onInit(cb, registerCb) 🔇 product-bridges.test.ts Registers hooks for issue create/edit forms (host-driven)
uiModificationsApi.onChange(cb, registerCb) 🔇 product-bridges.test.ts Registers field-change hooks (host-driven)
uiModificationsApi.onError(cb) 🔇 product-bridges.test.ts Registers error handler (host-driven)
customFieldApi.getFieldData(cb) 🔇 product-bridges.test.ts Registers callback (host pushes data, no host in sim)
REQUEST_TYPE_CF_TYPE product-bridges.test.ts String constant: "com.atlassian.servicedesk:vp-origin"

@forge/confluence-bridge

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
action Rovo actions — manifest parsing, input schema validation, invocation via MCP
jira:workflowValidator ⚠️ 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)
app:adminPage Cross-product admin (config-only)

Platform Features

Features beyond individual APIs.

Feature Status Tests Notes
Manifest-driven deploy deployer.test.ts, deploy-e2e.test.ts Reads manifest.yml, wires everything
Module loader hooks loader-hooks.test.ts Intercepts @forge/* imports
Function contracts (calling conventions) function-contracts.test.ts Resolver, trigger, consumer, scheduled, webtrigger
Product API mock + real proxy product-api-proxy.test.ts Route-level mock priority
OAuth authentication credentials.test.ts PAT + OAuth 2.0
Persistent state (KVS) persistence.test.ts Save/restore on exit/start
Persistent state (SQL) persistence.test.ts, persistence-okr.test.ts MySQL dump/restore
Persistent state (Entities) persistence.test.ts
Concurrent queue processing concurrency.test.ts Concurrency keys, parallel execution
Multi-module UI isolation dual-panel.test.ts Separate ForgeDoc trees per module
UIKit → Atlaskit rendering Full UIKit 2 component mappings in renderer (see renderer.md)
Custom UI serving custom-ui-e2e.test.ts Vite serves resource directory
Dev server (HMR + WebSocket) forge-sim dev
Dev server proxy mode proxy-server.test.ts forge-sim dev --proxy <url> — reverse-proxy with bridge injection, WS passthrough
Stateful daemon (CLI) Auto-start, idle timeout, PID management
MCP server (stdio) mcp-server.test.ts 41 tools, 4 resources (see auto-generated stats block above)
MCP server (HTTP) StreamableHTTP transport
Egress filtering No enforcement of permissions.external
Content Security Policy No CSP enforcement
App installation lifecycle 🔇 Manifest lifecycle triggers (install/uninstall/enable/disable), not simulated
Scoped permissions enforcement No checking of permissions.scopes
Rate limiting simulation No simulation of Forge rate limits
Invocation time limits Per-function-type timeout warnings matching real Forge limits (25s resolver, 55s trigger, etc.)
Trigger event templates 143 centralized templates (76 Confluence + 56 Jira + 9 Jira Software + 2 App Lifecycle) with typed payloads via TriggerPayloadByEvent
Memory limits No simulation of 128MB heap limit
Forge Remotes remotes.test.ts Full: manifest parsing, endpoint resolution, mock routing, real HTTP with FIT JWT auth, JWKS endpoint. See remotes.md
Forge Environments ⚠️ Always returns "DEVELOPMENT"

Summary

Counts below are per package section (all sub-tables included), recounted 2026-07-19 directly from the row markers in this file.

Category Implemented Partial/Stub Not Implemented Total
@forge/api 50 14 2 66
@forge/kvs 22 0 0 22
@forge/sql 7 0 1 8
@forge/events 19 0 0 19
@forge/llm 11 1 0 12
@forge/object-store 8 1 0 9
@forge/resolver 6 0 0 6
@forge/react 104 2 1 107
@forge/bridge 40 2 3 45
@forge/jira-bridge 1 7 0 8
@forge/confluence-bridge 0 5 0 5
@forge/dashboards-bridge 0 5 0 5
Manifest modules 23 19 2 44
Platform features 20 2 5 27
Total 311 58 14 383

Coverage: 81% implemented, 15% stubbed/partial, 4% missing