This Forge app is the GA replacement for the Atlassian Connect webhook descriptor that Atlassian closed for new installs on March 31, 2026.
Mattermost publishes one Forge app, and every customer Confluence Cloud site installs its own private copy of it. Atlassian enforces strict isolation between those copies, so:
- Your queued Confluence events, the secret that protects your bridge, and any data the bridge holds live only inside your tenant's copy. Other Mattermost customers cannot see them, and Mattermost staff cannot read them.
- The bridge does not store Confluence page content anywhere. It only forwards events into your own Mattermost server when your Mattermost server asks for them.
- Each tenant gets its own bridge URLs. There is no single URL that could be used to read another customer's events.
- The shared secret used to authenticate Mattermost to the bridge is set once by your admin during install and is never sent to or stored by Mattermost-the-company.
Customers with strict data-residency / compliance requirements, or on-prem Mattermost deployments at a scale that would exceed the free Forge usage limits on the Mattermost-published bridge, can run the bridge themselves under their own Atlassian developer account. The Mattermost plugin treats both paths identically — the wizard accepts any valid Forge web trigger URL regardless of which Atlassian account owns the app.
- An Atlassian developer account for your organisation. Free to create; one account can host the bridge app for all your Confluence Cloud tenants.
- Node.js 22 (LTS) or newer.
- The Forge CLI:
npm install -g @forge/cli. Runforge loginonce with an API token from id.atlassian.com/manage-profile/security/api-tokens. - Confluence Cloud Site Admin on the target tenant.
- Mattermost System Admin on the target server.
Clone the plugin repository and change into the forge/ directory:
git clone https://github.com/mattermost/mattermost-plugin-confluence.git
cd mattermost-plugin-confluence/forge
npm installforge registerThe CLI will prompt for an app name (e.g. acme-mattermost-confluence-bridge)
and write the generated app ID into manifest.yml under app.id. This
ID is yours; do not share the file or the ID outside your organisation.
forge deploy --environment productionThis publishes the app to your developer account. It is not visible to anyone outside your organisation and is not listed on the Atlassian Marketplace.
In the Atlassian developer console, open the app you just deployed → Distribution → Sharing → generate a private install link. This link is what your Confluence Site Admins (or you, if you are the only tenant) will click to install the bridge.
In Mattermost: System Console → Plugins → Confluence → Forge Bridge Install URL. Paste the install link from the previous step. Save.
You only need to do this once per Mattermost server; the wizard will surface this URL to the admin running the Cloud setup.
The Confluence Site Admin clicks the install link from step 4, reviews the consent screen (read access to pages and comments, no outbound network), and approves the install. Atlassian provisions a per-tenant copy of the app: isolated storage, unique web trigger URLs, no shared state with any other tenant.
From a terminal authenticated with forge login and the same developer
account that owns the app:
forge webtrigger --environment productionPick the installed tenant when prompted. The CLI prints two URLs:
drain→ the URL Mattermost will pollregister→ a one-shot URL used to set the shared secret
In Mattermost, run /confluence install cloud. Step through the
wizard; when it reaches the Forge bridge step, click Register
bridge and paste:
drainURL from step 7 → "Drain URL"registerURL from step 7 → "Register URL"
The plugin POSTs its auto-generated shared secret to your bridge's register endpoint, stores the drain URL in plugin config, and starts polling on a 30-second tick.
In Confluence, edit a page in a space subscribed in Mattermost. Within ~30 seconds, the subscribed channel should receive the page-edit notification.
registeris one-shot. If you need to rotate the shared secret, clearmm.registeredfrom Forge storage first (useforge install --upgradeafter manually wiping the entry), then re-run the Mattermost wizard.- Forge storage values are capped at 240 KiB per entry. The bridge drops the inline page body for events that would exceed this; the channel notification still fires but @-mention DMs are skipped for that single oversized event.
- Forge web trigger throttle is 1000 req/min per app/environment. At a 30-second poll cadence that is 2 req/min per tenant, so a single self-hosted bridge accommodates ~500 Confluence Cloud tenants before throttling.
- Forge storage is wiped 28 days after the app is uninstalled. The bridge is a buffer, not a system of record; the Mattermost plugin is the durable side.
This is a pull bridge:
- The Forge app subscribes to 8 Confluence events via
triggermodules (pagecreated/updated/trashed/restored/deleted, commentcreated/updated/deleted) and enqueues each event payload into Forge storage underevt:<cloudId>:<ts>:<rand>. - The Mattermost plugin periodically POSTs to the
drainweb trigger to read queued events and ack them. Requests are HMAC-SHA256 signed using a shared secret the admin sets via the one-shotregisterweb trigger. - No
permissions.external.fetchis declared. The Forge app never makes outbound calls. This keeps the install consent screen clean and removes the per-customermanifest.ymlediting the previous push design required.
Trade-off: Atlassian's Forge trigger module already has up to 3 minutes
of delivery delay, so the additional ~30s polling latency we add on the
plugin side is small in context.
npm installin this directory.forge loginandforge register(one-time, generates the app ID — paste it intomanifest.ymlunderapp.id).forge deploy --environment production.forge install --site https://<test-tenant>.atlassian.netto verify on a test tenant.- From the Atlassian developer console, generate a private distribution
link and publish it as the
Forge Bridge Install URLplugin setting default for downstream Mattermost installs.
This is the short path for tenants installing the bridge published by Mattermost (typically used for trials, evaluation, and small deployments; self-hosting is recommended for production scale — see the "If you would rather run the bridge yourself" section above for the full runbook).
-
Confluence admin clicks the install link from the Mattermost setup wizard → app installs on their site (Atlassian creates a per-tenant install with isolated storage and unique web trigger URLs).
-
Confluence admin runs
forge webtrigger(or reads the install logs) to get theregisteranddrainURLs. We'll wrap this in a UI Kit admin page in a follow-up. -
In Mattermost System Console under Plugins > Confluence:
- Paste the
drainURL into "Forge Drain URL". - Copy the auto-generated "Forge Bridge Shared Secret".
- Paste the
-
POST the secret to the
registerURL once:curl -X POST -H 'Content-Type: application/json' \ -d '{"secret":"<paste shared secret>"}' \ '<register-web-trigger-url>'
registeris one-shot — it refuses subsequent calls so a leaked URL can't be used to repoint the bridge. To re-register (e.g. rotate the secret), clearmm.registeredfrom Forge storage first.
The Mattermost plugin then polls drain on a ticker, verifies each
event, posts to subscribed channels, and acks drained keys so Forge can
delete them.
This directory is its own Node project, independent of the plugin's
server/ and webapp/ builds. CI lives in .github/workflows/forge-ci.yml
and only fires when forge/** changes.
npm install --omit=optional # CI install path
npm install # developer install path, pulls @forge/cli
npm run typecheck
npm run validate-manifest
npm run build
npm run ci # all of the above
npm run deploy # forge deployDirect one-to-one mapping with what the legacy Atlassian Connect descriptor
used to subscribe to (page + comment lifecycle), re-validated against
the Forge Confluence events list.
Forge collapses Connect's removed onto deleted. See
server/forge_event_mapping.go on the plugin side for the explicit mapping.
- Forge
triggerdelivery is best-effort (up to ~3 min delay, occasional drops). Connect webhooks had the same property, so we are not regressing. If drops show up in production we will add a plugin-side reconciliation poll over/wiki/api/v2/pages?sort=-modified-date. - Forge storage is wiped 28 days after uninstall — the queue is buffer, not durable state. The plugin is the system of record.
- Forge web trigger limit: 1000 req/min per app/env/context. At a 30s poll cadence, that's 2 req/min per tenant → headroom for ~500 installations per environment before throttling.
- Plugin-side Cloud 3LO OAuth (lives in
server/instance_cloud.goand the Cloud branches ofserver/user.go/server/flow.go). - Plugin-side polling loop (lives in
server/forge_poller.go). - Migration of existing Connect installs (we leave those running until Atlassian's Q4 2026 EOS).