Notes from the work

One email when a tutorial or migration write-up goes live. Nothing else, and one click to leave.

LeanZero

Two people in Romania doing Atlassian migrations, Forge apps and practical AI work for teams that would rather talk to the person doing the job. Most of what we learn ends up on this site.

Services

  • Atlassian Migrations
  • Atlassian FastShift
  • Atlassian Maintenance
  • Forge App Development
  • AI Development Consultation

Topics

  • Jira
  • Jira Service Management
  • Confluence
  • Bitbucket
  • Atlassian Forge
  • Cloud Migration
  • Local AI
  • AI Coding
  • Certifications
  • Atlassian Team
  • All topics

Company

  • Blog
  • Tutorials
  • Contact

Community

  • Join Discord
  • Support this site

© 2026 LeanZero. All rights reserved.

Privacy PolicyTerms of Service24/7 SupportTrust CenterSecurityDPALegal notice
  1. Home
  2. Topics
  3. Forge
Topic hub

Atlassian Forge

Undocumented Forge platform behaviour, measured and worked around.

Read the articlesAll topics

A one-line import at the top of a resolver file makes the whole resolver stop existing, and forge lint reports no issues. That is the shape of most of what is collected here.

Egress rules the backend ignores and the client enforces. Display conditions reading app properties nobody documented. A key-value store where FAIL_IF_EXISTS gives you a real lock and a TTL lease quietly does not. Each piece names the behaviour, shows the smallest thing that reproduces it, and gives the workaround that held up in production. Where Atlassian has since documented something, that is said. Where it is still undocumented, you get how it was confirmed, so you can check it yourself.

Read in order

Building CogniRunner

4 parts

What Jira workflow validators could not do, and what it took to put an LLM behind a transition without sending your data anywhere.

  1. 1Part 1 — ArticleThe Gap Nobody Filled: AI-Powered Workflow Validation for Jira Cloud10 min
  2. 2Part 2 — TutorialBuild an LLM-Powered Atlassian Forge App for Jira12 min
  3. 3Part 3 — ArticleWhat's New in CogniRunner: Local AI, Zero-Key Models & Actions That Write Back6 min
  4. 4Part 4 — ArticleCogniRunner 3.1.0: real Jira workflow conditions17 min

Building LeanZero Management

4 parts

Notes from building a Microsoft-Project-style planner inside Jira Cloud, on Forge, against limits that are not negotiable.

  1. 1Part 1 — ArticleLeanZero Management: the Jira dependency that actually moves dates12 min
  2. 2Part 2 — TutorialLeanZero Management: two scheduling engines, one schedule14 min
  3. 3Part 3 — TutorialLeanZero Management: virtualising a 5,300-issue Gantt10 min
  4. 4Part 4 — ArticleWhat LeanZero Management does that the other Jira PPM tools don't18 min

Forge Gotchas

12 parts

Undocumented Atlassian Forge behaviour that passes lint, passes deploy, and breaks anyway.

  1. 1Part 1 — TutorialThe @forge/bridge import that kills your resolver, and why nothing warns you13 min
  2. 2Part 2 — TutorialForge egress: backend ignores your URL path, client enforces it14 min
  3. 3Part 3 — Tutorialjira:workflowCondition vs jira:workflowValidator: one runs your code14 min
  4. 4Part 4 — Tutorialforge lint cannot see your request helper: the Jira scopes it never checks14 min
  5. 5Part 5 — TutorialLocking in Forge KVS: FAIL_IF_EXISTS works, TTL leases do not14 min
  6. 6Part 6 — TutorialDark Mode Done Right in Forge Custom UI15 min
  7. 7Part 7 — TutorialHide a Forge module per project: app properties in a display condition11 min
  8. 8Part 8 — Tutorialjira:fullPage is deprecated: what global:fullPage actually changes for cross-product Forge apps14 min
  9. 9Part 9 — Tutorial/rest/api/3/search is gone: what actually breaks when you swap in /search/jql14 min
  10. 10Part 10 — TutorialFix "Disallowing path manipulation attempt" from Forge's route tag, and know which of the two causes you hit11 min
  11. 11Part 11 — TutorialI built a Forge major-version predictor on a guess, and it took a review to find the answer inside my own commit14 min
  12. 12Part 12 — TutorialMake @forge/react/jira resolve, and keep forge deploy working9 min

Running a Forge app in production

4 parts

The problems that only appear after deploy: testing against the live product, a security scan that passes wrongly, and rate limits counted in points.

  1. 1Part 1 — TutorialHow to run real end-to-end UI tests against a deployed Forge app (2026)9 min
  2. 2Part 2 — TutorialSecurity reports for Forge apps: the clean scan that isn't (2026)11 min
  3. 3Part 3 — TutorialSurviving Atlassian's points-based rate limits in a Forge app (2026)11 min
  4. 4Part 4 — ArticleAtlassian is still health-checking the Connect app you migrated to Forge7 min

Articles

41
Claude Sonnet 5.5 vs Opus 5.5 and GPT-6.1 Sol: the generalist and the specialist
ArticleLocal AIAtlassian Forge

Claude Sonnet 5.5 vs Opus 5.5 and GPT-6.1 Sol: the generalist and the specialist

Claude Sonnet 5.5 edged Claude Opus 5.5 on our general-programming benchmark, 0.7984 to 0.7926, a margin I read as level. On an Atlassian Forge app, Opus won 0.9767 to 0.5508. Every check behind both results, GPT-6.1 Sol and Sol Pro on the same two boards, how the benchmarks grade a running app, and the full bill for fine-tuning our own 27B model.

Oct 5, 202645 min read
Lock attachments in Confluence Cloud with Sentinel Vault, step by step
TutorialSentinel VaultConfluence

Lock attachments in Confluence Cloud with Sentinel Vault, step by step

Confluence Cloud has no built-in way to lock attachments. This walks one file through Sentinel Vault 6.6.0 on a real site: seal it, overwrite it as someone else, watch the sealed version come back in seconds, read both versions in the history and over the REST API, then unlock it. Plus a bug in our own app that we hit while running it.

Oct 4, 202613 min read
Jira API rate limit: read the headers, then see what CogniRunner spends each hour
TutorialCogniRunnerJira

Jira API rate limit: read the headers, then see what CogniRunner spends each hour

Jira Cloud's API rate limit is three limits at once, and Jira gives an admin no screen that says which app spends it. This walks the headers with curl, what a 429 tells you, and CogniRunner's Maintenance screen and REST report, hour by hour and by component.

Oct 3, 202613 min read
Forge App REST API with OAuth 2.0 (3LO): Scripting LeanZero Management Plans with curl
TutorialLeanZero ManagementAtlassian Forge

Forge App REST API with OAuth 2.0 (3LO): Scripting LeanZero Management Plans with curl

A Forge app REST API is called from outside Jira with an OAuth 2.0 (3LO) access token. This walks the whole path with curl against LeanZero Management: the admin switch, the integration and its scopes, consent with sns, the token exchange, rotating refresh tokens, and the four 403s I hit on the way.

Oct 3, 202614 min read
Runs on Atlassian apps with AI: Sentinel Vault reviews Confluence with no API key
ArticleSentinel VaultConfluence

Runs on Atlassian apps with AI: Sentinel Vault reviews Confluence with no API key

Sentinel Vault is one of the Runs on Atlassian apps that review Confluence content with AI. It calls Atlassian-hosted LLMs through the Forge LLMs API, so there is no API key to paste and no external data egress declared. What that buys an admin, who pays for the tokens, how the cost ceiling actually works, and the four places it is weaker than it looks.

Oct 2, 202615 min read
CogniRunner: Jira OpenAI, Claude or Forge LLMs behind one workflow validator
TutorialCogniRunnerAtlassian Forge

CogniRunner: Jira OpenAI, Claude or Forge LLMs behind one workflow validator

CogniRunner lets a Jira admin put OpenAI, Anthropic, Gemini, Bedrock, a self-hosted model or the zero-key Atlassian Forge LLMs behind the same workflow validator. This walks the setup end to end and says what actually changes when you bring your own key: where the data goes, who pays, which models you get, and what Runs on Atlassian has to do with it.

Oct 1, 202614 min read
Forge app access rule: what your app sees when a data security policy blocks it
TutorialAtlassian Forge

Forge app access rule: what your app sees when a data security policy blocks it

When an admin adds a Forge app access rule to a data security policy, your app does not get an error that says so. It gets a 404 that looks like a missing issue and a search that comes back empty. I built a small probe app, blocked it on a test Jira site, and captured every status, every event payload and the one REST call that tells your app what happened.

Sep 29, 202614 min read
Confluence Forge Delete Page Event: Why Space and Parent-Page Deletes Leak Orphaned Data
TutorialAtlassian Forge

Confluence Forge Delete Page Event: Why Space and Parent-Page Deletes Leak Orphaned Data

Confluence does not fire a page delete event for a Forge app when a space or a parent page is deleted. Atlassian only emits a delete event for the top-level entity being deleted, by design, per their own documentation. Here's the exact rule, the one exception, and the REST-based workaround that actually keeps your app's storage in sync.

Sep 28, 202611 min read
JSM Portal Request Create Property Panel Submit: Types Won't Catch a Bad Payload
TutorialAtlassian Forge

JSM Portal Request Create Property Panel Submit: Types Won't Catch a Bad Payload

Call view.submit() in a jiraServiceManagement:portalRequestCreatePropertyPanel with the wrong payload shape and it compiles, resolves, and silently stores nothing. The shipped @forge/bridge types won't catch it. Here's the real shape, where it's documented, and how to read the value back.

Sep 21, 202612 min read
"Uncaught (in promise) Error: Unable to emit ready event." in a Forge Confluence macro
ArticleAtlassian ForgeConfluence

"Uncaught (in promise) Error: Unable to emit ready event." in a Forge Confluence macro

You added emitsReadyEvent to a Confluence macro to speed up PDF export, called view.emitReadyEvent(), and every normal page view now logs "Unable to emit ready event." The shipped @forge/bridge source says why it happened, why it was harmless, and which version made it stop.

Sep 18, 20267 min read
LeanZero at Atlassian Team '26 Europe Amsterdam: no booth, here to talk Forge migrations
ArticleAtlassian ForgeLocal AI

LeanZero at Atlassian Team '26 Europe Amsterdam: no booth, here to talk Forge migrations

We're going to Atlassian Team '26 Europe in Amsterdam on 6-8 October, no sponsor booth, no speaking slot, just the two of us. Here's what we'd actually talk about: 60,000+ users migrated at a 100% delivery rate, six open-source migration toolkits anyone can take from GitHub, and thirteen published model weights on Hugging Face from training we've written up start to finish, adapters and all.

Sep 17, 20266 min read
How to fine-tune Qwen3.8-27B with LoRA on a Mac: MLX fine-tuning from scratch
TutorialLocal AIAtlassian Forge

How to fine-tune Qwen3.8-27B with LoRA on a Mac: MLX fine-tuning from scratch

Qwen3.8-27B and Qwen3.5-9B were taught Forge, Jira and Confluence on a single Mac Studio with 96 GB. This is the whole procedure with the seven scripts that do it, printed in full: a pinned MLX environment with two patches, an 8-bit base with its speculative-decoding head kept as a sidecar, a chat-JSONL dataset built from a folder of Markdown, a segmented trainer with full-state checkpoints, an adapter expander, a per-module merge into the 8-bit shards. The kit was run end to end for this page on the 9B, in 21 minutes, and its real output follows each step, including the one where the validation loss turns the wrong way.

Sep 15, 202638 min read
v0.4 of our Atlassian model: 21 of 25 apps compile, and the loop that was a diagram
ArticleLocal AIAtlassian Forge

v0.4 of our Atlassian model: 21 of 25 apps compile, and the loop that was a diagram

Three days after v0.3, the Qwen3.8-27B we teach Forge went from 12 of 25 compiling apps to 21 of 25. On the way our own release rule rejected it, correctly by its own text, over a 40-character window repeated 13 times at 32k context. The window was a line of box-drawing characters in an ASCII diagram. Here is what changed, what the metric got wrong, and what we changed so it cannot happen the same way again.

Sep 13, 202612 min read
I taught a 27B model to write Forge apps. As far as I can find, nobody had done that before
ArticleLocal AIAtlassian Forge

I taught a 27B model to write Forge apps. As far as I can find, nobody had done that before

Qwen3.8-27B knows almost nothing about Atlassian Forge: ask it for an app and it invents a manifest format and imports packages that do not exist. Over four days on one Mac Studio I trained it until 14 of 25 manifests passed Atlassian's own validator and 12 of 25 apps compiled, from zero. The weights are public. Here is what it is, what it is not, and why I think it is a first.

Sep 10, 202611 min read
Make @forge/react/jira resolve, and keep forge deploy working
TutorialAtlassian Forge

Make @forge/react/jira resolve, and keep forge deploy working

The types ship, your resolver cannot see them, and on a Forge app this is not an editor annoyance — the bundler type-checks, so it fails the build. Three TypeScript majors give three different errors, and only one setting is safe.

Sep 1, 20269 min read
Atlassian is still health-checking the Connect app you migrated to Forge
ArticleAtlassian Forge

Atlassian is still health-checking the Connect app you migrated to Forge

Cloud Fortified monitoring is bound to app versions, not to your framework. Publish a Forge version and the probes keep hitting your old Connect base URL — each one carrying its own 99.9% SLO, and redirects are not followed.

Sep 1, 20267 min read
What LeanZero Management does that the other Jira PPM tools don't
ArticleJiraAtlassian Forge

What LeanZero Management does that the other Jira PPM tools don't

A buffer task that absorbs slip until it can't, a plan that defends itself against edits made in Jira, and a write path that refuses rather than lies. Traced line by line, and set against what BigPicture and Structure.Gantt actually document.

Aug 31, 202618 min read
I built a Forge major-version predictor on a guess, and it took a review to find the answer inside my own commit
TutorialAtlassian ForgeSentinel Vault

I built a Forge major-version predictor on a guess, and it took a review to find the answer inside my own commit

Two triggers fired on the release that took us to 4.0.0, not one. I wrote a tool that knew about six of them when the docs list eleven, published a thesis that inverted the truth, and found the correct answer sitting in a comment in the same commit.

Aug 29, 202614 min read
Fix "Disallowing path manipulation attempt" from Forge's route tag, and know which of the two causes you hit
TutorialAtlassian ForgeJira

Fix "Disallowing path manipulation attempt" from Forge's route tag, and know which of the two causes you hit

The @forge/api route template throws on two different mistakes with one identical message. Six steps to tell them apart and fix each, with a probe that prints exactly which characters it rejects in a path and which it silently encodes in a query.

Aug 27, 202611 min read
Refuse an unentitled caller in a Forge resolver, and prove it with a test that goes red without the gate
TutorialSentinel VaultAtlassian Forge

Refuse an unentitled caller in a Forge resolver, and prove it with a test that goes red without the gate

A Forge resolver that takes a page id from the payload and writes with asApp() will write to any page the caller can name. Six steps to gate it, with a test suite that fails 5 of 6 before the fix and passes 6 of 6 after.

Aug 27, 202615 min read
The duplicate Forge event that deleted our spam filter
ArticleSentinel VaultAtlassian Forge

The duplicate Forge event that deleted our spam filter

Forge delivered one page edit twice, 400ms apart. The duplicate didn't post a second comment — it wiped the 24-hour window that stops second comments. Then I wrote the whole thing up backwards, and the test I built to prove it agreed with me.

Aug 27, 202613 min read
/rest/api/3/search is gone: what actually breaks when you swap in /search/jql
TutorialAtlassian ForgeJira

/rest/api/3/search is gone: what actually breaks when you swap in /search/jql

The removed Jira search endpoint fails loudly with a 410. The one-line migration to /search/jql fails quietly: HTTP 200, the right number of issues, and every field null. Measured from inside a deployed Forge app.

Aug 26, 202614 min read
CogniRunner 3.1.0: real Jira workflow conditions
ArticleCogniRunnerJira

CogniRunner 3.1.0: real Jira workflow conditions

For a year our workflow conditions evaluated a constant and gated nothing. 3.1.0 replaces that constant with ten checks that Jira runs itself. Here is what shipped, what I measured against a live Jira, and how it compares to what else is on the Marketplace.

Aug 24, 202617 min read
Sentinel Vault: you cannot block an edit in Confluence, so we undo it instead
ArticleSentinel VaultConfluence

Sentinel Vault: you cannot block an edit in Confluence, so we undo it instead

Forge gives you no veto over a Confluence save. Product events arrive after the change is already committed, which means a lock on Confluence content cannot prevent anything — it can only detect and restore. Here is what that constraint does to an app: why the restore has to ignore itself, why reverting the whole page is the wrong fix, and why a licence check in a protection app must fail open.

Aug 19, 202611 min read
LeanZero Management: virtualising a 5,300-issue Gantt
TutorialAtlassian ForgeLeanZero Management

LeanZero Management: virtualising a 5,300-issue Gantt

A 5,300-issue plan put 94,920 nodes in the DOM. Windowing the rows took it to 2,115 — and left a second full-height layer that windowing does not touch.

Aug 19, 202610 min read
Locking in Forge KVS: FAIL_IF_EXISTS works, TTL leases do not
TutorialAtlassian Forge

Locking in Forge KVS: FAIL_IF_EXISTS works, TTL leases do not

Forge does have an atomic create-if-absent, and it holds under concurrency. Add a TTL to turn it into a lease and it stops being one. Measured on a deployed app, with the manifest and code for the pattern that actually holds.

Aug 19, 202614 min read
forge lint cannot see your request helper: the Jira scopes it never checks
TutorialAtlassian Forge

forge lint cannot see your request helper: the Jira scopes it never checks

forge deploy now blocks on lint errors, so the scope linter has quietly become a gate. It only reads endpoints written inline — one request helper hides every call in your codebase. Measured on @forge/cli 13.4.0, including what the runtime actually returns when a scope is missing.

Aug 17, 202614 min read
LeanZero Management: two scheduling engines, one schedule
TutorialAtlassian ForgeLeanZero Management

LeanZero Management: two scheduling engines, one schedule

A Forge PPM app needs a live in-browser scheduler and a server-side one. They drift by a day, no test goes red, and the user believes the preview. Here is the harness that catches it — and the two mutations I ran to prove it works.

Aug 14, 202614 min read
jira:workflowCondition vs jira:workflowValidator: one runs your code
TutorialCogniRunnerAtlassian Forge

jira:workflowCondition vs jira:workflowValidator: one runs your code

We shipped both modules in CogniRunner pointing at the same handler. Only one of them ever invoked it. forge lint says No issues found, forge deploy validates the manifest and passes, and the gate you built is permanently open with zero log lines. Here is the probe app that proves it, and the two things that actually work.

Aug 14, 202614 min read
LeanZero Management: the Jira dependency that actually moves dates
ArticleAtlassian ForgeJira

LeanZero Management: the Jira dependency that actually moves dates

A blocks link in Jira records a relationship. On Free and Standard it reschedules nothing. Here's the engine we put behind it, the required-start rule that's easy to get subtly wrong, and what it still can't do.

Aug 13, 202612 min read
Surviving Atlassian's points-based rate limits in a Forge app (2026)
TutorialAtlassian Forge

Surviving Atlassian's points-based rate limits in a Forge app (2026)

Since March 2, 2026, a Forge app shares one 65,000-point hourly pool across every install. Ours spent it by 18 minutes past the hour. Here's the metering, the count tripwires and the self-imposed budget that took a 13,500-user Confluence estate down to ~2,000 points in a quiet hour — without a bigger quota.

Aug 12, 202611 min read
jira:fullPage is deprecated: what global:fullPage actually changes for cross-product Forge apps
TutorialAtlassian Forge

jira:fullPage is deprecated: what global:fullPage actually changes for cross-product Forge apps

Atlassian gave Forge developers 55 days to move off jira:fullPage and confluence:fullPage. I built the cross-product app that fails today, reproduced the lint error verbatim, then migrated it to global:fullPage and deployed it into Jira and Confluence on one installation — and found that the context no longer tells you which product you are in.

Aug 11, 202614 min read
Forge egress: backend ignores your URL path, client enforces it
TutorialAtlassian Forge

Forge egress: backend ignores your URL path, client enforces it

The same URL in two Forge permission lists means two different things. I read the shipped matcher, deployed a probe to a live site, and measured which half of the docs is wrong.

Aug 8, 202614 min read
The @forge/bridge import that kills your resolver, and why nothing warns you
TutorialAtlassian Forge

The @forge/bridge import that kills your resolver, and why nothing warns you

One unused frontend import in a shared file takes a Forge function from HTTP 200 to HTTP 424. It throws at import time, the stack trace blames the wrong function, forge lint says No issues found, and the error message changed in April so the threads you'll find on Google no longer match.

Aug 4, 202613 min read
Hide a Forge module per project: app properties in a display condition
TutorialAtlassian Forge

Hide a Forge module per project: app properties in a display condition

Connect had entity_property_contains_any_user_group. Forge has no such named condition — but it can do the same job with a jiraExpression over your app's own properties. Here is the working manifest, the endpoint that actually exists, and the one-character bug that hides your module everywhere.

Aug 1, 202611 min read
Security reports for Forge apps: the clean scan that isn't (2026)
TutorialAtlassian Forge

Security reports for Forge apps: the clean scan that isn't (2026)

Running SAST and SCA on a Forge app is easy. The hard part is that your scanner and the reviewer's will disagree about the same version, and if you don't explain why first, your report loses.

Jul 17, 202611 min read
How to run real end-to-end UI tests against a deployed Forge app (2026)
TutorialAtlassian Forge

How to run real end-to-end UI tests against a deployed Forge app (2026)

Your Forge app's unit tests pass and it still breaks inside Jira. Here's how I drive a deployed Custom UI app in a real browser with Playwright — past the iframe and past Atlassian's 2FA.

Jul 15, 20269 min read
What's New in CogniRunner: Local AI, Zero-Key Models & Actions That Write Back
ArticleAtlassian ForgeAI Coding

What's New in CogniRunner: Local AI, Zero-Key Models & Actions That Write Back

CogniRunner's latest update brings local AI inference, a zero-key Atlassian-hosted model, and declarative AI actions that write back to Jira — all configured in plain English.

Jun 18, 20266 min read
Build an LLM-Powered Atlassian Forge App for Jira
TutorialCogniRunnerAtlassian Forge

Build an LLM-Powered Atlassian Forge App for Jira

A practical, end-to-end guide to wiring large language models into Jira workflows with Atlassian Forge — using CogniRunner as the real-world case study.

Jun 18, 202612 min read
The Gap Nobody Filled: AI-Powered Workflow Validation for Jira Cloud
ArticleAtlassian ForgeCogniRunner

The Gap Nobody Filled: AI-Powered Workflow Validation for Jira Cloud

Every workflow validator on the Atlassian Marketplace requires scripting. Every AI app for Jira is an assistant that can’t block a transition. CogniRunner sits in the gap between those two worlds — plain-English prompts that evaluate Jira field content, including attachments, as a real-time workflow gate.

Mar 16, 202610 min read
Dark Mode Done Right in Forge Custom UI
TutorialAtlassian Forge

Dark Mode Done Right in Forge Custom UI

Confluence supports dark mode. Your Forge app should too. This tutorial covers the full theme implementation for a production Custom UI app -- from Forge Bridge detection to a comprehensive CSS variable system that switches automatically.

Feb 18, 202615 min read