I really like the Runs on Atlassian trust signal and would love to offer it to our customers on our upcoming full Forge rewrite. But in our case, that’s not easy: Our app uses the customers Confluence content and displays it as a slideshow.
It’s hard to explain why the customer can embed YouTube videos in the Confluence pages, but in our app, these are blocked “for security reasons”. Most of our customers use Confluence with embedded content - Tableau Dashboards, internal analytics systems embedded etc.
Until now, our only choice was:
either allow ALL egress in the manifest, thereby giving our customers their content, but look like a complete security nightmare from the customers perspective - OR -
Be Runs on Atlassian, the darling of all admins, and have users despair about their missing Tableau Dashboards.
Then, customer-managed egress appeared and we hoped that our customers can choose individually what content they allow. Wonderful. If not for the fact that “Runs on Atlassian” is mutually exclusive with customer-managed egress.
The resulting dilemma
Now, we have to choose the nearly same dilemma:
Do we allow our customers to choose whether their internal dashboards or YouTube videos are allowed in their presentation content but loose “Runs on Atlassian”?
OR do we pride ourselves with “Runs on Atlassian” but deny our customers their own content?
I cannot see why customer-managed egress costs the “Runs on Atlassian” badge. It makes no sense to me and puts us in a strange position. Especially in our case, since we only show content that is already inside of Confluence.
Maybe we should release our app on an additional marketplace listing - the “RoA edition” and the “with content” edition? Just joking.
Custom expectation of zero egress: this went out of the window in the meantime anyway as Analytics egress snuck in. Also, the customer - a full-grown adult admin in charge of the installation - has to approve the egress. What more do we want here?
Potential abuse: We’re not the Google Play Store here. Professional customers need working solutions from us and we shouldn’t deny them because we are afraid of some black sheep. This is a pure review process problem, the remaining problems can be caught in the approval user interface design (which could use a better overview, just saying).
Other badges: Not really an argument, is it? “Hey according to RoA we’re potentially dangerous, but look at that other badge” doesn’t work for me. I also strongly agree with Scott’s argument that customers will filter the marketplace for RoA apps and won’t see our customer-managed apps at all.
TL;DR:
Please re-consider RoA vs customer-managed egress and save us from having to choose to either disappoint customers or loose the badge.
Hard to disagree. If using the customer’s own systems and content it should be allowed. I understand why any external processing of any data is an issue, but as long as the user is in control of own data and systems being hooked up to it should be allowed.
Here is what we are planning to do for our app connecting to an external emailer and webhook servers. Our app will be ROA. We will have free app extensions that go with that app and connect to an email server or webhooks. These will not be ROA.
Here is my thinking behind this. The customer, trying to solve a problem, will look for and find our app and see that it is ROA. They will install it and see that if they want email or webhooks then they will need the free extensions.
They will see that these apps are not ROA and then they can make a decision knowing that non-ROA compliance relates to a particular feature, rather than an app. Hopefully this will mean a higher likelihood getting a sale.
I wonder how you plan to do the inter-app communication though - as far as I understood, the new App Events don’t support any custom payload, making the data exchange between the two apps very hard. Syncing mail data via hidden pages or page properties sounds ugly. And if you use a custom backend to sync, you’re out of RoA again…
Second that, App Events is the only viable construct we came up with so far and handling the communication (passing the necessary configs/data) between apps using Jira entities properties. But that’s ugly and should not be this way.
@SteffenMueller sorry for the delay in getting back to you. Below are the details of the link up. It’s not the nicest way of doing this but it is a way. The is the connection between App (which is ROA) and WebhookExt (the free NON ROA app). This was created by me and Claude.ai and hasn’t been implemented yet. Let be know if you find any issues or problems with it.
Stage 1: WebhookExt arrives and announces itself
An admin installs WebhookExt on the same site as App.
On install, WebhookExt publishes a keyless app event. No payload, since app events carry keys only.
App subscribes to that event. This is the first moment App knows WebhookExt exists at all.
Stage 2: App leaves the credential where WebhookExt can find it
App takes its static web trigger URL (created once via forge webtrigger, never minted at runtime, because dynamic triggers break RoA eligibility).
App generates a shared secret and a single use nonce.
App encrypts {url, sharedSecret, nonce} with WebhookExt’s public key, which is a build time constant compiled into App. Both apps are ours, so there is no key distribution problem. App ships an array of accepted keys so one can be retired in a release.
App writes that encrypted blob to a rendezvous issue type property, and records the nonce in its own DB.
We use the issue type property because every site has issue types, the set is small and enumerable, and it does not depend on
any Space existing or surviving.
Stage 3: WebhookExt finds it
WebhookExt enumerates the site’s issue types via /rest/api/3/issuetype.
WebhookExt walks that list looking for the rendezvous key. Finding it is how WebhookExt learns App is present and how to reach it.
WebhookExt decrypts the blob with its private key and stores the URL plus secret in its own DB.
Stage 4: The handshake closes
WebhookExt makes its first call to App’s web trigger, presenting the nonce.
App checks the nonce is unused, marks it consumed, and rejects it forever after.
App records the pairing and deletes the rendezvous property. Any unclaimed blob expires on a few minute TTL and is rewritten on WebhookExt’s next hello.
If the handshake never completes, App’s Notifications tab shows “Pairing with the free Webhook Extension app…” and after a timeout reveals a manual pairing code as the fallback.
I think we can all easily see how this is way more byzantine than simply allowing Customer-managed egress in Runs on Atlassian apps.
Moreover, if the concern is that developers might publish apps that do not work unless you set some egress rules via CME, the same concern applies to apps that do not work unless you install the free add-on.
Either your loophole has to be closed, to really ensure that Runs on Atlassian means that the app cannot exfiltrate data and cannot communicate with non-RoA apps, or the whole premise of “Customer-managed egress disqualifies from RoA” is faulty.
Quick info for everybody interested in customer-managed egress:
It is currently not supported for global:fullPage modules. We’ve stumbled across that when we moved our confluence:fullPage modules over (as they will deprecate end of this month) - and suddenly egress stopped working as expected.
I’ve already created a ticket for it and support said they want to get at it middle of September. Join the ticket if you’re interested: FRGE-2262
For now, we’ve had enough fun with that feature for no tangible benefit. We’ll release our Forge port with “*” for every egress there is and revisit customer-managed egress once things settled down, until then we simply aren’t RoA.