RFC-106: Future of Forge versioning - Permissions

RFCs are a way for Atlassian to share what we’re working on with our valued developer community.

It’s a document for building shared understanding of a topic. It expresses a technical solution, but can also communicate how it should be built or even document standards. The most important aspect of an RFC is that a written specification facilitates feedback and drives consensus. It is not a tool for approving or committing to ideas, but more so a collaborative practice to shape an idea and to find serious flaws early.

Please respect our community guidelines: keep it welcoming and safe by commenting on the idea not the people (especially the author); keep it tidy by keeping on topic; empower the community by keeping comments constructive. Thanks!

Summary of Project:

This project is designed to provide customers with timely access to improvements, bug fixes, and patched security vulnerabilities for their installed apps. Meanwhile, any additional permissions or egress can be reviewed and approved by admins at their convenience.

  • Publish: 4 Aug 2025
  • Discuss: 22 Aug 2025
  • Resolve: 29 Aug 2025

Problem

A significant portion of Atlassian’s customer base is currently using outdated app versions, leading to a fragmented installation landscape. Feedback indicates that the current way Forge uses versioning to control and release changes to apps is not suitable for all use cases.

Customers

  • Discovery of updates: Customers report difficulties in discovering app updates, lack sufficient information about what has changed, and often receive no advance notification.
  • What changed: Release notes are inconsistent or missing, and audit logs lack detail. This situation makes it difficult for admins to comprehend what they might be missing by not approving an update, or even what to look out for that might break their workflow.
  • Managing changes: Enterprise customers want to manage changes to their user experience, but currently have little control over when and how app updates (including minor updates) are applied. There is also no option for customers to roll back to a previous stable version in case there are issues with the latest version.

Developers

  • Hesitation to release major versions: App developers often hesitate to release new features that necessitate major version updates, primarily due to the challenges and costs associated with maintaining support for multiple app versions over an extended period. As a result, customers miss out on new features and security updates, making it difficult to implement critical patches across the board.
  • Supporting old versions: Many customers don’t manually upgrade major versions, and as a result, app developers need to support old major versions indefinitely. While we now provide features like the ability to perform progressive rollouts and deploy changes to previous major versions, this may be a significant and unnecessary overhead for some developers who lack the resources to manage it. An approach that keeps installations current would be a better fit.

Atlassian takes a different approach with its own cloud products, offering a model where customers don’t need to think about versions and are always presented with the latest released version. This is marketed as a feature of SaaS, removing the burden of version management from customers.

Moreover, app developers want more control over the experience their customers receive. Being able to immediately patch or make cost optimizations across all customers would provide significant value, particularly when responding to security events or when Forge monetization is introduced.

The Future of App Version Management

We envision a world where managing app versions is effortless, secure, and always up to date—without the headaches of manual updates or compatibility worries. Atlassian aims to redefine the app experience reducing the need for customers to manually manage versions and updates. With our vision, every app is current, secure, and tailored to your customers’ needs.

Here’s what it would look like:

  • Always Up-to-Date, Effortlessly (Rolling Releases): No more chasing version numbers. Code updates are delivered automatically, ensuring apps are secure and high-performing, without disruption.
  • Total Control, Zero Hassle (Optional Features): Admins get granular control to approve new features (a group of permissions), while routine updates flow seamlessly in the background.
  • Ultimate Flexibility (Release Tracks): Customers will be able to set their own update policies, pre-approve features, and schedule updates to fit their business (similar to Release Tracks)—while still benefiting from protection against urgent threats.
  • Crystal-Clear Communication: Customers will receive notifications only when it matters—like new features or permission change based on preferences. Customers will never be overwhelmed, but always informed.
  • Full Transparency (Release Notes): Customers will enjoy complete visibility into the app update history, release notes and permission changes, empowering them to make informed decisions.
  • Security and Compliance, Guaranteed: Outdated or insecure apps are shortlisted for review and critical security updates are enforced to keep customers’ environment safe.
  • Developer Controlled Versioning (Semantic versions): Developers would have more control over version numbers, allowing developers to more clearly communicate the significance of the changes. eg. major version bumps when it is a workflow-breaking change.

Taking an iterative approach

We recognise that this is a complex challenge necessitating substantial investment to significantly enhance the experience for both customers and partners. We will adopt an iterative approach, with the first milestone focusing on decoupling versions from permissions. This will tackle the top reasons that major app versions are created: scope, egress and remote changes, reducing the amount of installations on older versions, in turn reducing the amount of outdated major versions that need support.

While this iteration represents a positive advancement, we acknowledge that it alone will not completely address the issues associated with app updates. We encourage you to assess this solution within the framework of our broader, ongoing investment, understanding that Atlassian is dedicated to continuous improvement in this domain.

Decoupling App Code Version from Consent

Separating the consent admins provide for app permissions (Initially, scopes, egress and remotes) from app code versioning (specifically updates, initial installations would still require all current permissions to be granted, and all permissions will need to be agreed to at once, an admin cannot opt out of a single specific permission), it would enable app developers to deploy updates to their apps without the current concerns they have today for triggering a major version upgrade for their customers and often increasing the amount of versions to support. After the changes are deployed, all installations that only have scope and egress changes (no matter how far back in Major version history) will be brought forward to the latest applicable version with no intervention from the Customer (Similar to the bulk-upgrade command).

App developers would instead need to develop their apps in a way to handle these permissions potentially not being available. This is a common pattern we see in other development frameworks, particularly in mobile app development with iOS and Android. These frameworks encourage developers to check for permissions (like camera, location, contacts, etc.) at runtime and gracefully handle the case where the permission is denied. This is inline with the direction we are proposing here for Forge app development.

Non-permission related major version changes

The process for releasing non permission related changes, changes to licensing would remain unchanged for this milestone and would still required admin approval before it would be released to customers.

Atlassian API security enforcement

Apps will still be restricted to only accessing Atlassian APIs which an Admin has granted permissions to, which may be different to the permissions defined in the manifest before an Admin has approved the new permission.

Surface app permissions to apps at runtime

To support these changes, we are proposing adding support for increased visibility of granted app permissions to apps at runtime. This would enable apps to pre-determine if an API call would be successful and provide an alternative experience within their app if it’s not available. We would be expanding on the API from the previous RFC RFC-94: Configurable Egress and Remotes to allow checks for scopes, non-configurable egress, and remotes as well.

Backend example (Non-final, illustrative only)
import { permissions } from '@forge/api';
const requiredPermissions = {
  scopes: ['write:confluence-content'],
  external: {
    fetch: {
      backend: ['https://a.com', 'https://b.com'],
      client: ['https://test.com']
    }
  }
};
const result = permissions.hasPermission(requiredPermissions);
if (result.granted) {
  // All permissions available - proceed with operation
  console.log('✅ All permissions granted');
} else {
  // Handle missing permissions
  console.log('❌ Missing permissions:', result.missing.format());
  // Output: "Scopes: write:confluence-content; External: Fetch Backend: https://api.example.com"
}
Frontend hook example (Non-final, illustrative only)
const MyComponent: React.FC = () => {
  const { hasPermission, isLoading, missingPermissions } = usePermissions({
    scopes: ['write:confluence-content'],
    external: {
      fetch: {
        frontend: ['https://api.example.com']
      }
    }
  });
  if (isLoading) return <LoadingSpinner />;
  if (!hasPermission) {
    return <PermissionDenied missingPermissions={missingPermissions} />;
  }
  return <ProtectedFeature />;
};
Frontend render-props example (non-final, illustrative only)
<PermissionGate
  requiredPermissions={{
    scopes: ['admin:confluence']
  }}
>
  {({ hasPermission, isLoading, missingPermissions }) => {
    if (isLoading) return <LoadingSpinner />;
    if (!hasPermission) return <AdminRequired missingPermissions={missingPermissions} />;
    return <AdminPanel />;
  }}
</PermissionGate>

We believe this design will allow the developer to:

  1. Minimum permission check: Put a single bulk-permission check for all required permissions at the root of their app (like illustrated above) and show a message to the user that the app needs more permissions to function.
  2. Feature based: The developer could put this wrapper around individual features to disable them and tease them if they do not have the permissions needed to work yet.

Test migrating from previous major versions

As a result of this change some customers may automatically begin interacting with new versions of apps multiple versions ahead of what they were previously using. To support developers testing these migration paths on their apps, we are proposing to provide developers with a new command in the CLI to target installation of previous major versions.

Asks

We appreciate your engagement and look for feedback on this RFC that will help shape this offering.

Specifically, the Forge team would love to get some insights on:

  • What use-cases for your apps that this offering would enable?
  • This solution will initially be opt-in (for app developers), with the objective of becoming mandatory for all applications. What do you consider to be a realistic notice period before it becomes mandatory?
  • How can Atlassian support app developers in educating customers about the new model to minimize confusion and ease the transition?
  • What tools or features could Atlassian provide to give enterprise customers more control over app updates, especially since updates will be applied as new versions are available, without admin intervention?
  • What support can Atlassian provide to help developers manage the overhead of ensuring decoupling versions from permissions won’t break the experience for customers running outdated versions?

Risks

  • While the understanding of versioning by customers is mixed at best, the concept of major and minor versions for app installations is relatively clear within Atlassian R&D teams and support. During this transition, it may create some confusion and overhead to adjust to this new concept.
  • Once an app is opted-into this feature, App updates will be deployed immediately to all customers by eligibility of the installed version vs the latest, regardless of how far back they are. Enterprise clients prefer to manage modifications to their user experience in a manner analogous to how they oversee parent product releases. Release Tracks are not presently supported for Marketplace apps, and once versions are decoupled from permissions, the risk of disruptive, frequent changes to the app user experience will escalate.
8 Likes

Overly complicated solution that doesn’t address the problem or fix the current mess. You’re forcing unnecessary and infinite complexity onto developers.

Copying the structure from iOS/Android doesn’t make any sense in the context of the Atlassian Marketplace. iOS apps are obviously 1:1 approved and managed by an individual user. Atlassian apps are approved and managed by org admins.

Please think about how much complexity this will entail for developers who will need to check and handle EVERY single possible on/off permission scope within their apps.

Opt-out automatic updates is the correct solution:

7 Likes

Hi Nathan,

Handling scope changes progressively is a common pattern on all platforms that support OAuth. In this pattern if the developer adds or removes scopes, the user is prompted to accept the scope changes. If the user does not accept them, then there is a way to query and display messages to users that some functionality is disabled.

There are numerous good examples in the industry for this, the most well documented I have found is Stripe.

This proposal does not include the ability for customers to enable or disable individual scopes. However, we are actively exploring ways for customers to disable features, where each feature represents a collection of scopes and egress permissions. The developer would be in control for defining the feature and the scopes and egress required for that feature. This would allow you to track when a customer enables or disables a feature, along with its associated scopes and egress settings.

Thanks,
James

1 Like

It’s copying from one context to another. The opt-out automatic update solution is far cleaner, simpler and less of an infinitely complex nightmare for developers to manage.

Edit: ok here’s a simple approach this RFC would enable. Forget the granular management of scopes. If large marketplace vendors wish to over-complicate their code and endure the time that will consume, sure.

For everyone else:

  1. Check if all required permissions are enabled in root render.
  2. If not, don’t render app, instead show “update app to continue” message.

Doesn’t solve the core problem since admins will still need to manually do something - which they don’t do - but ok.

4 Likes

We’ve updated the RFC to reflect the strategies for dealing with scopes differences.

3 Likes

First of all, let me say this RFC is much appreciated and the turnaround time from the previous discussion in the node18 thread is impressive!

The proposed solution is good, although I agree with Nathan, it looks like this would be a complex rollout to do all at once. I think automated major updates without scope changes would already be a great improvement.

From an admin perspective I think that controlling scopes and egress permission is crucial so I would be onboard with a more controlled approach. Whether this needs to reflect into the app code is another discussion. Personally I would feel having version transparency in the codebase (as discussed in the other thread) would suit most vendors already.

4 Likes

Thanks for finally tackling this major pain point (pun intended) for us as app vendors. The proposal felt a bit complex at first, but I believe both we and our customers will adapt quickly and the benefits are clear.

Key feedback:

  • Use cases: This change removes the fear of major updates, letting us adopt the latest Forge features sooner and implement new functionality with more flexibility.
  • Timeline: We’d love to see this as soon as possible, especially with Forge monetization coming in 2026, so that performance improvements and cost optimizations reach all customers faster.
  • Customer education: Please consider an early access program and the ability to test in staging/dev. Interviews with Org Admins could help validate the approach from their point of view. If shared, app vendors might react to those admin needs.
  • Developer support: A Forge CLI command listing used APIs and required permissions would be invaluable. API responses should clearly indicate when missing scopes are the cause, rather than returning generic “not allowed” messages.

Further suggestions:

  1. Separate Deployment from Release – gives developers control over rollout timing.
  2. Transparency – ensure release notes are included in notification emails; if deployment and release are split, this is much easier.
  3. Incremental Rollout – allow targeting updates to a subset of customers first.
  4. Semantic Versioning – support patch versions (x.x.1) so admins can make quicker, informed update decisions.
  5. Major Update Migrations – provide a way to run migration tasks (and rollbacks) for smoother transitions.
4 Likes

I think it’s great that ya’ll are looking at this.

However I fear that what you’re proposing will become a support headache for us. Don’t get me wrong, it’s a good start. But this will cause a lot of support tickets of “where is X feature” - or worse very broken experiences for the end users (think of us introducing a full page for a feature and the only thing visible is a blank page because the scopes aren’t added).

I will voice everyone else saying that looking at consumer app experiences is the wrong experience because of decoupled aspect between usage and actually administration. A lot of users don’t actually know who the administrators are…

Ideally I would love to see

  1. The same api that you’re proposing, but also the opposite. Ie if somebody doesn’t have a scope etc - let us put in a message letting them know that this is disabled due to a scope isn’t available and that they should contact the administrator to have it enabled.
  2. A frontend javascript api so that we can query programatically - again so that we can message/hide programatically - or even better perhaps guide the user in a different manner.
  3. An official permission/scope feed so that we can track installations that have adopted the scopes/permissions and do proper customer success management with them (this could include us offering meetings etc) as well as tracking churn related to feature adoption etc.
  4. An in-host-app notification bus to the administrator. If we can push messages to the admin saying “Please upgrade app X or accept scope X so that your users can get feature Z” would go a long way to solve the biggest hurdle.

Without all of that - I don’t see any other solution than us still having to brick app versions (going back to the bad consumer app experience).

More than happy to get my team to jump on a call and chat more.

/Daniel

5 Likes

Reducing the friction with major versions is a welcome change.
I also like the ability to target a version when installing an app for tests.
I feel like checking permissions at runtime is fine, and part of standard error handling when interacting with a remote api, although I would like a more descriptive error in the response when a permission scope is missing than the generic “not allowed message” like @ppasler mentioned.

How do you propose letting app developpers use semantic versioning and release notes ? Would it be through the forge cli ?

I have a meta-comment though. This feels written by AI, especially the “The Future of App Version Management” paragraph: full of super positive statements with very little to no details, and makes me distrustful with the rest of the post.

1 Like

This RFC has the following properties:

  • It contains 106 lines of text,
  • Most of this text doesn’t say what is going to happen,
  • The part which says “Here’s what it will look like” does not outline the design decisions, but the upsides of the decisions,
  • The design decisions, if present in this RFC, can be interpreted in several ways that may or may not be satisfying for us.

My colleagues have asked whether it was written with AI, because it contains a lot of information that we didn’t use and it contains very little of the important information.

In any case, I’m not saying that it lacks clarity or that it was designed in such a way that it would burry the lead. Morever, it looks like a good idea and it looks like the participants on the Atlassian side are extremely competent about their subject.

However, I am saying it lacks clarity for us to be able to have a position about it.

Thank you for the constructive and well considered feedback so far. Please keep it coming and we will begin answering some of your questions.

While i would like to take credit for turning this around that fast, this has been a collaborative effort between our product and engineering team’s which we have been working on for a little while and was not written by AI .

While my team has not published many public RFC’s in the past, we did read the communities feedback about wanting RFCs to be earlier in the cycle so that it is a true request for comment that can help us shape the solution, as apposed to an “FYI, this is what we are building”. This is also why it may be lacking some detail in certain areas.

As we attempted to convey, we wont be attempting to solve all of the versioning challenges we know we have in one go. But we wanted to give you some insight into the direction we are headed and so when we release the first feature you know this is only part of the program. We believe that decoupling the app code version from permissions will have the most impact and therefor think this makes for a good place to start.

11 Likes

Thanks for the feedback @Corentin .

I would like a more descriptive error in the response when a permission scope is missing

Are you talking about the response you receive from Jira and Confluence REST APIs or in the new permissions API above we are proposing?

How do you propose letting app developpers use semantic versioning and release notes ? Would it be through the forge cli ?

These would be addressed in subsequent stages. We don’t have detail on the implementation for these yet and would likely come in later RFCs. How would you like to see these implemented?

That sounds a bit scary, even if we can define the features and related scopes ourselves. However, it will increase complexity both in administrating apps (for customers) and developing apps (for us).

In our experience, > 99% of our customers don’t care about scopes and permissions. Our apps use a plethora of scopes and we rarely get any requests about those. The ones that care would prefer us not to have any read access at all, where “Runs on Atlassian” with disabled logs and analytics access seems to be the preferred solution. I understand that there are legal challenges involved and we cannot just add scopes without admin consent (and this RFC goes in the right direction), but not sure if we need the feature-based solution on top of this proposal.

1 Like

Thanks for continuing to Forge ahead.

With the new APIs for the backend and frontend, please make them take the same arguments to make maintaining the permission requirements for features that share frontend and backend code as easy as possible. Taking from your example snippet.

Common (Non-final, illustrative only)
export const exportFeatureRequirements = {
  scopes: ['write:confluence-content'], // Scopes as defined in the manifest
  fetch: ['https://*.example.com'], // Egress URLs as defined in the manifest (external fetch, both client end backend)
  remote: ['example-remote-key'] // Remotes by KEY as defined in the manifest
}
Backend example (Non-final, illustrative only)
import { permissions } from '@forge/bridge';
import {exportFeatureRequirements} from 'common';

async function updateConfluencePage(contents) {
  const hasPermissions = await permissions.hasPermission(exportFeatureRequirements);
  if (hasPermissions) {
      // Make call to Confluence to write page
    } else {
      // Show message to customer that the app needs more permissions for this feature
    }
}
Frontend example (Non-final, illustrative only)
import {exportFeatureRequirements} from 'common';

<App>
  <PermissionSwitch
     {...exportFeatureRequirements}
     onBlocked={<FeatureDisabledMessage />}
  >
       <ExportFeature />
  </PermissionSwitch>
</App>

One thing I didn’t get is how administrators will be informed that an app can/should be updated.

  • Will there be a way that apps can notify administrators to update the app?
  • Will there be a way to have users notify their administrators to update the app?
2 Likes

I’m talking about the response from the REST APIs.
From Connect experience, it is already incredibly difficult to diagnose and provide support to customers when a network call fails.
If I make a getPageById call, and receive a 404: Page not found error, I don’t know if:

  • The page was deleted / archived
  • The page never existed
  • The app doesn’t have permission to view the page
  • The user doesn’t have permission to view the page
    • Because the space has view permission restriction
    • Because the page has a parent with view permission restriction
    • Etc…
  • I’m calling the wrong api, and should call getFolderById instead

and now we’re adding forge permissions in the mix:

  • The user didn’t upgrade the app
  • I forgot to add the permission scope

I understand that having a different error message for each case could potentially be a security risk, but it still makes things frustrating and difficult.

In forge, there is also the added complexity that frontend network calls are made through graphql requests, and it was surprising the first time to see no error in the network tab.

What I would love is some kind of static code analysis that shows a warning when permissions scopes are missing in the manifest. I understand that it’s out of scope for this RFC.

I would like my CI to handle the release note through the forge cli or a REST api like

POST api.atlassian.com/rest/apps/{appId}

{
  version: "1.2.3",
  releaseNote: {
    title: "New feature",
    description: "", // HTML, markdown, or ADF content.
    scopeChanges: ?
  }
}
2 Likes

Hi Atlassian,

I appreciate the effort to finally tackle this part of the Forge versioning problem.

If you go this route, I suggest that this “optional permission” thing needs to be made a first-class citizen of the Forge manifest before you release it. By which I mean to say:

First-Class Front End Support

  • there should ideally be a way to query permissions from the front end without having to invoke an API that makes a round-trip to the host product. Forge already often incurs a performance penalty compared to Connect, and we do not need to make it worse. Maybe serialize all of the supported permissions automatically to front end pages for apps that might need it.

First-Class Display Conditions

  • please introduce support for these optional permissions in conditional display logic (meaning in Confluence display conditions, Jira expressions, etc). Why is this important? Nothing is worse for the end user than having a button displayed that says “Click Me”, only to have the button produce a dialog that says “we don’t support this feature”.

First-Class Manifest-Level Support

  • Even better, perhaps this feature should be supported by substantially all Forge module types at the manifest level, so that everything can be turned on or off.
  • allow this permission check to be negated as well, meaning the ability to load a separate Forge module if not all of the stated permissions are present, allowing developers to create an either/or experience
  • to simplify this when applied to multiple modules, consider having a definition section for “permission sets” in the manifest, where I can say that “permission set ‘abc’” consists of these scopes, these egresses, and so on. I can then tag individual modules by saying that module 1 is only used if permission set ABC is present, and module 2 is only used if permission set ABC is not all present.

Since a manifest is worth 1,000 words:

permissionSets:
    myConfluenceWriterPermissionSet:
      scopes:
        - confluence:foo.data:write
      egresses:
        - my.app.com
      // ...
modules:
  confluence:spacePage:
    - key: myAppSpacePage
      loadIfPermissionsPresent: myConfluenceWriterPermissionSet
  confluence:banner:
    - key: upgradeWarning
      loadIfPermissionsABSENT: myConfluenceWriterPermissionSet

Why?

  • vendors can decide to disable most of the app functionality and to instead display an admin-visible banner or something pushing the admin to upgrade (within the Atlassian allowable policy for app banners, of course).
  • vendors can avoid having charges generated by customers who are using outdated versions of the app. If a certain endpoint does not have the correct permissions, vendors do want to waste any compute cycles trying to offer something that will eventually fail.

For example, I prefer not to have customers using extremely outdated versions of my app, and I do not want to have to deal with optional scopes for a long period of time either.

As a vendor, my desire is thus to force customers to upgrade for critical functionality, and if this is not possible, I may wish to stop the app from doing anything until it is updated. This is the exact pattern used by many mobile apps, in that vendors usually give a grace period to users before finally forcing an upgrade. This idea also allows the app vendor to control how heavy-handed they want to be (if at all).

18 Likes

I think the display conditions is an excellent callout. Thanks Scott!

4 Likes

Thanks for the feedback, this is definitely something we will do. We plan on aligning arguments for the backend and frontend so they have the same structure, to ensure you only have to define the permissions once and use it in both the frontend and backend.

We envisage that there will be a new modal on the Connected Apps screen (In Admin Hub) that will allow admins to grant new requested permissions.

Hi @Corentin , I think the forge lint command should do this for you today. This will scan your code and look for product APIs you are trying to call, then looks up the required scopes for these APIs using openAPI documentation and references this against what’s declared in your manifest. If there is a gap it will show an error, with forge lint fix available to automatically add any missing scopes to your manifest.

Does this do what you are asking?

Thanks @Corentin for replying with your example. I agree that would be pretty frustrating and challenging to deal with as a developer. I am happy to ask our internal security and edge team’s if there is anything we can do here, but i suspect the answer will likely be no for security reasons as you have pointed out.

Our hope is that the permission check we are proposing here means you should know before you need to make the API call if you have the required permissions and also potentially saving you an unnecessary network call if they haven’t been granted.