FDC3 icon indicating copy to clipboard operation
FDC3 copied to clipboard

Introduce a new `fdc3.applications()` method

Open ggeorgievx opened this issue 3 years ago • 26 comments

Enhancement Request

Introduce a new fdc3.applications() method that returns a promise that resolves with the application definitions that the FDC3 API implementation is aware about (obtained from the application directories the implementation is connected to).

The signature of the method would be:

applications(): Promise<AppMetadata>;

Use Case:

Let's say we want to create a Toolbar that launches FDC3 applications using the fdc3.open() method. Currently the only way to discover some of the available applications is via the fdc3.findIntent() and fdc3.findIntentByContext() methods. The issue is that these return subsets of all available applications and we want our Toolbar to display all FDC3 applications.

It would be convenient if there was a FDC3 method that returned all FDC3 applications.

Workflow Description

A developer could use the method to get the list of all FDC3 applications and then iterate over them to:

  • Filter on additional fields besides Intents
  • Display UI elements for each application e.g. going back to the Toolbar example described above - a button for each application that launches it

Workflow Examples

Below is a short snippet of how the code of the Toolbar example described above could look like using FDC3 methods only.

const apps = await fdc3.applications();
const appDiv = document.createElement('div');

apps.reduce((appsDiv, { name }) => {
    const appButton = document.createElement('button');
    appButton.innerText = name;
    appButton.onclick = () => fdc3.open(name);

    appsDiv.appendChild(appButton);

    return appsDiv;
}, appDiv);

document.body.appendChild(appDiv);

Additional Information

A PR for this issue would include only the addition of the method as no new interfaces would be required.

ggeorgievx avatar Jan 28 '21 14:01 ggeorgievx

@ggeorgievx the intention was always that full AppD data isn't made available via the FDC3 API, only the pieces required for interoperability.

That is why the AppMetadata interface, for example, doesn't include all the properties from the app directory schema.

The FDC3 API is intended for application interop, not building launchers.

However, it is really easy to just use the AppD REST API from your launcher directly, e.g.:

const applications = await fetch(
  "https://my-app-directory/v1/apps/search"
);

This has the added benefit of being desktop agent agnostic, and allowing for standard HTTP authentication mechanisms that handles apps users aren't meant to see etc.

If this API doesn't work for your purposes, we should investigate amending the AppD OpenAPI schema, but I don't think it's a good idea to add an application retrieval API function to the FDC3 API which will then by usable by all apps without authentication.

rikoe avatar Jan 28 '21 18:01 rikoe

@ggeorgievx any further views on my comment above?

Are there use cases that this API call would solve that fetch("https://my-app-directory/v1/apps/search") wouldn't?

rikoe avatar Apr 15 '21 16:04 rikoe

@rikoe yes there are use cases where this is necessary, because the set of Applications available is defined by the Desktop Agent, so an application can not know which App Directories a Desktop Agent may connector to, and it is also the case that a Desktop Agent may have other ways of defining applications, for example Glue42 allows local application definition files in addition to working with App Directory servers.

So yes, there is a difference between a call to the Desktop Agent, and a call to some random App Directory service, or possibly services.

(BTW I think we should rename 'Desktop Agent'. For example, we have a pure browser implementation, so it's not a Desktop Agent)

lspiro-Tick42 avatar Apr 15 '21 18:04 lspiro-Tick42

Thank you for the explanation @lspiro-Tick42 - the thing is I still don't understand the use case where one application needs to obtain a list of applications that the desktop agent knows about to facilitate an interop workflow.

To my mind such an operation would be against the spirit of FDC3 - the API is purely for end user application interoperability, and is all about late binding and agnostic communication between application workflows where they only know about intents and channels, and not about other applications directly.

In addition, there are significant security concerns here - since the operation would bypass the authentication and authorisation constraints inherent in contacting a REST service in the cloud for a list of applications, which is the domain of the app directory, and the implementation code of desktop agents.

so an application can not know which App Directories a Desktop Agent may connector to

This is by design, applications themselves shouldn't know, or care - the whole point of intents and channels are to abstract them from this knowledge.

it is also the case that a Desktop Agent may have other ways of defining applications, for example Glue42 allows local application definition files in addition to working with App Directory servers.

I understand that this is driving this request in part, but I would like to stress here that requirements or features of Glue42 is in now way a determinant for what should be in FDC3. As a standard, the bar is high, and what we add has always been driven by end user use cases, and that alone, and I don't think we should change that.

Glue42 can always add the above operation to its agent, as a differentiator, if you believe it is something valuable to offer to application workflows. If you do want to push for this to be in the standard, you will need to gather some wider consensus for this feature, as so far only Glue42 has asked for it, and it will need to pass a vote by the Standards Working Group.

We will definitely include this request when we next discuss API additions to FDC3 2.0 though, and I would encourage you to bring a real-world use case along to aid that discussion.

rikoe avatar Apr 15 '21 20:04 rikoe

@rikoe I'm still on the fence about this request and will discuss it with our team here. We've certainly have similar functionality in FInsemble and have found it useful in the past.

In addition, there are significant security concerns here - since the operation would bypass the authentication and authorisation constraints inherent in contacting a REST service in the cloud for a list of applications, which is the domain of the app directory, and the implementation code of desktop agents.

Regarding the security concerns, The desktop agent would have had to pass auth and authorisation (presumably in the context of the user) in order to retrieve the list of applications from the AppD(s) itself. Hence, if it releases a security constraint, it's cross-site scripting in that it would allow an externally hosted application to retrieve the list of apps the user has access to through the desktop agent. That could, I suppose, be abused to return those details to the author of the offending app. On the other hand, making the information available might allow app developers the ability to adapt UI/UX to the other applications that are available.

We'll report back when we've discussed it this end.

kriswest avatar Apr 16 '21 11:04 kriswest

There is an FDC3 call Open(), this is about being able to find the list of valid values. An example use case is an FDC3 Toolbar/launchpad.

This is nothing to do with supporting Glue42 specific features. Say an ISV wished to offer a launcher UI and wanted to be able to run in multiple containers, and they wanted to allow the launcher to run any of the FDC3 apps available, because they want to keep user focus, how would you suggest they do that without the applications() method, or are you saying this is not a use case we should try and support?

I don't understand the security concerns. Once we have an application that is able to use the FDC3 API, it can listento all context/channel changes, which may contain interesting (commercially sensitive or PI data). I fail to see how getting a list of application names (to use with the FDC3 open call) is a larger security risk.

lspiro-Tick42 avatar Apr 16 '21 12:04 lspiro-Tick42

This is nothing to do with supporting Glue42 specific features. Say an ISV wished to offer a launcher UI and wanted to be able to run in multiple containers, and they wanted to allow the launcher to run any of the FDC3 apps available, because they want to keep user focus, how would you suggest they do that without the applications() method, or are you saying this is not a use case we should try and support?

@lspiro-Tick42 building a launcher is separate from application interoperability, which FDC3 is aimed at. Building a launcher involves more things than just retrieving a list of applications, and would probably require connecting to an app directory directly via REST anyway, which is why the AppD OpenAPI spec is part of FDC3.

FDC3 is not a standard to provide a common surface to build desktop agents, vendor ecosystems or launchers against, it is a lightweight set of operations for app developers that they can use in a vendor-agnostic way. If building launchers is part of the use cases FDC3 needs to cover, the community will need to decide about that, and we then need to get it added to the set of in scope uses cases first - that is how the FDC3 standard has always been driven.

In addition, if FDC3 just becomes an API for retrieving lists of applications and opening them, or targeting them directly, what are we even doing! The whole point we expend so much effort on intent and channel workflows is to facilitate late binding, and the ability for applications to trigger workflows in an agnostic way, without knowing the applications involved. Retrieving a list of applications just encourages people to circumvent those models and create tightly coupled, non-transferable workflows again.

The above is just my opinion, and we can discuss this at a future Standards Working Group meeting, but until we have a proper business use case to base this feature on, I am discouraged from adding it to the standard. As I said previously though, this is why we have a voting process 👍

rikoe avatar Apr 16 '21 12:04 rikoe

By the way, the fact that open() accepts a target parameter is a good argument. Where do you get that target from? I have always just thought of it as special cases where you know the app id before hand, not dynamically getting a list of apps and then choosing one.

It is worth thinking about and discussing.

rikoe avatar Apr 16 '21 12:04 rikoe

I proposed something similar to fdc3.applications() in one of my issues (https://github.com/finos/FDC3/issues/247) to help you search for apps that will work with one you are using:

enum Operation{
  Broadcast = "broadcast",
  Listen = "listen"
}
findAppsByContext(context: Context, operation?: Operation): Promise<Array<AppMetadata>>;

Although that could perhaps be handled better by adding new arguments to the appD's search call.

kriswest avatar Apr 16 '21 13:04 kriswest

Kris, if you did this by extending an appD search call, then I think you need to add a method to FDC3 to get a list of the appD directories that the desktop agent is connected to

lspiro-Tick42 avatar Apr 16 '21 13:04 lspiro-Tick42

Kris, if you did this by extending an appD search call, then I think you need to add a method to FDC3 to get a list of the appD directories that the desktop agent is connected to

Why @lspiro-Tick42? Is a desktop agent connected to multiple app directories a concern of the standard, seems like an implementation detail/architectural decision of a particular framework or launcher...

Don't think this should leak into app code or the standard.

rikoe avatar Apr 16 '21 15:04 rikoe

Rikoe, Try and think about an appliications that wants to be container agnostic. We proposes a new method to allow applications to find out about their envirinment. In this case the set of FDC3 Applications available to start (fdc3.open() call). Maybe that want this info for a toolbar, maybe for a restore layout call, it doesn't really matter.

Kris suggested that this info was already available via a REST call to an AppD server, and therefore the information could be obtained without a new FDC3 method. I am pointing out, in response to Kris' suggestion, that in order to use the REST call, the applications would need to know which AppD servers to connect to, and that finding this out would require the addition of a new FDC3 call to retrieve the list of 0 or more AppD servers the Desktop Agent was connecting to.

So I do not regard this as a leakage, I regard it as a way to allow applications to be responsive to their environments, and that adding an appliciations() call to FDC3 is a similar extension to adding the info method that was added as part of 1.2.

@rikoe does that answer your question ?

lspiro-Tick42 avatar Apr 17 '21 11:04 lspiro-Tick42

I think an API like this fdc3.applications() should only deal with applications that are already installed on the system as opposed trying to connect to an app directory. Also we should be very clear that it only deals with installed applications fdc3.getInstalledApplications. As soon as we connect to an app directory, we are opening the door to all kinds of API to manage installing/uninstalling/upgrading etc.

And if that is the path we choose to take, I don't think we should put all of this on the fdc3 object. We should make a whole new API.

List<AppMetaData> fdc3.ApplicationManager.getInstalledApplications(intent?, context?)
List<AppMetaData> fdc3.ApplicationManager.getAllApplications(intent?, context?)
fdc3.ApplicationManager.installApplication(appID)
fdc3.ApplicationManager.uninstallApplication(appID)

etc. etc.

sgd2z avatar Apr 19 '21 12:04 sgd2z

Personally, I think application management is beyond the scope of the Desktop Agent, and definitely, an area where container implementations can differentiate themselves by offering UI or API based facilities to do that management. DesktopAgent implementors should be free to determine if they will work with an AppD, multiple AppDs or an alternative system of specifying applications (as the Finsemble 4/5 add-on for FDC3 does, I believe Glue42 also has such a system for file-based apps - can you confirm @lspiro-Tick42 ?). They might also provide the user with control over which applications from those sources are available to the Desktop Agent (i.e. providing the ability for user to 'install' apps from one or more AppDs).

With that in mind, it does actually make sense to me to give the Desktop Agent the ability to return a list of applications that it is currently working with, rather than having applications hit the appD's directly. As @lspiro-Tick42 points out, to do that you end up needing an API call to ask the Desktop agent what AppD's its connected to and you are being prescriptive about the use of an AppD in the first place, which shouldn't necessarily be a given. Finally, we already provide partial access to this data through the desktop agent as "findIntent is effectively granting programmatic access to the Desktop Agent's resolver."

Regarding use-cases, I would put forward:

  • Implementing a launcher or application menu (as a vendor of a container we do already provide these but also encounter clients that wish to build their own)
  • Providing a list of applications that 'work with' an app, via metadata on the context types they broadcast or listen for (see #247 re: that data being added to the AppD). Either additional parameters would need to be added to the call or additional metadata added to AppMetadata to support this.

All that being said, I don't consider this the most pressing issue ahead of us. We might even consider the proposed function as 'optional' (where other Desktop Agent functions are required for full support of the standard).

kriswest avatar Apr 19 '21 14:04 kriswest

P.S. happy to revise that opinion if there are further use-cases put forward, beyond those above.

kriswest avatar Apr 19 '21 14:04 kriswest

All this discussion leads to me to think that the presence of fdc3.open is what is opening the door. I don't think implementing launchers/menus inside containers should be a function of fdc3 at all - or something that fdc3 should encourage development of using the spec. Maybe we need to re-evaluate the existence of open in the spec?

sgd2z avatar Apr 19 '21 18:04 sgd2z

@sgd2z you are right, that the requirement for the applications() method, comes from the existence of the open method, but why do you think 'open' should not be part of FDC3 ?

lspiro-Tick42 avatar Apr 19 '21 18:04 lspiro-Tick42

It is different than all the others. Let's say I'm an app developer making an app which will run in a container like Finsemble or Glue. Let's take for example, I'm a developer at factset. Now I make my app, put it in an app directory. What should my app be able to do? Should it be able to open any arbitrary app on the system? Should it care or know about those apps? Or should it behave more along the lines of how intents operate? where anything beyond what the user intends is taken care of by the container. It will broadcast some data, raise some intents, handle some intents and listen for data. That should be about it. Is developing a menu that opens applications for the container a valid use case for the API? Is that even part of the intention of the FDC3 API?

sgd2z avatar Apr 19 '21 20:04 sgd2z

I am with @sgd2z on this one. I think the open() method is a distraction in the current FDC3 API, and leads people down the wrong path (i.e. non-channel and intent workflows).

Let me clarify where I stand:

  • FDC3 is an API for application interop, not building launchers or frameworks, and that is important. We want to keep the focus narrow. (This is not just me saying it, the charter etc. makes this clear.)
  • While the open() method is not useful in this sense, I don't think we can remove it now that it's there.
  • If someone wants to use open(), and they are looking for the target app details to use, they should speak to the team in question (just like it would be with raiseIntent() and the intent name). FDC3 is not meant to be a generic app discovery and launching API.
  • Building a launcher is still the only use case I have heard so far for the fdc3.applications() method, and that is in my opinion not enough justification to add it:
    • Calling fetch() against the FDC3 Rest API is already standardised for building launchers, we would now have two ways to do the same thing, which will be confusing - which one should people use?
    • There are still unresolved security considerations, as @kriswest also points out.
    • If you are building a launcher, I would have to assume that the launcher developers would have to have intimate knowledge of the app ecosystem anyway, including which AppD URLs it is connecting to, what other ways there are to define or locate applications, etc. - so I do not see how abstracting behind a generic applications call actually helps in this case.
    • Ultimately, building launchers and how to do application discovery is not the domain of the FDC3 API specification, which is an API for apps to hook into interoperability. Defining and discovering applications is part of the App Directory specification, and it is useful to have this distinction.

Given that there is still quite a bit of disagreement about this issue, I would propose that we park it for now, and as @kriswest says focus on the most pressing issues in front of us, especially as there is already a way to do this in FDC3 today.

rikoe avatar Apr 22 '21 11:04 rikoe

In regard to voting, my upcoming proposal will describe a way to provide this feature without expanding the API. My recommendation is to defer voting until after that proposal has been offered and thoroughly discussed.

thorsent avatar Jul 05 '21 22:07 thorsent

Leaving in 2.0 candidates as vote was inconclusive. See #413 for vote details.

kriswest avatar Oct 22 '21 12:10 kriswest

@rikoe said:

  • While the open() method is not useful in this sense, I don't think we can remove it now that it's there.

I would agree that allowing apps to open other apps is a mistake. Surely, given that this is FDC2.0 this is the time to remove/deprecate this method?

robmoffat avatar May 03 '22 13:05 robmoffat

Considering @nkolba's use case: a developer is building an app which is a launcher.

  • I think this is an odd case, where the launcher would need to know about app directories, if it is going to provide a list of apps to launch.
  • Also, I think adding apps to the environment is a concern of the agent. I don't think launchers should really be apps, tbh,

robmoffat avatar May 03 '22 13:05 robmoffat

I strongly disagree with Rob's view. First off, we use the ability to run an app via an FDC3 call, where the app definition is loaded from an App Directory, as a useful way to pilot new versions to limited sets of users.

It is not just 'launchers' that need to do this, sometimes a collection of apps need to work together, and Open relevant apps via a button. I realise this could be done via an Intent but it doesn't seem useful.

Also I think that creating launchers, could be a useful opportunity for developer's to add value. We certainly allow multiple launchers on our Platform.

Therefore I think Open should remain.

lspiro-Tick42 avatar May 03 '22 14:05 lspiro-Tick42

I'm sympathetic to the view that open() is problematic, but I think it's widely used in existing implementations and is actually helpful in getting developers onboarded to FDC3 before fully grokking the data driven approach. Plus, there are some legitimate edge uses such as in app suites as Leslie points out.

So I would argue for no change. Leave open() as is but don't add applications(). It can always be revisited and added in a minor release if there's a swell of demand.

thorsent avatar May 03 '22 15:05 thorsent

@nkolba also made a point about security that I think worth recording (will be in minutes when published). App Directories support authentication and this API call would bypass that (to a certain extent) by forwarding on the information gathered under the auth that the Destkop Agent had used.

This lead to one other proposal today: add an API call to retrieve the list of App Directories that are in use. That would resolve the question about authentication, but it probably also negates any utility (where auth is in use) as an app that retrieves the list of directories and queries them directly can't expect to receive the same data as the desktop agent did.

I'm also content with the status quo as I think a launcher could be built (using fdc3.open) by giving it the same AppD URLs (and auth as appropriate) as the platform so it can independently retrieve the same data. I'd be open to rethinking that if further use cases or requests for this functionality arise.

kriswest avatar May 03 '22 20:05 kriswest

Agreed to close this issue at meeting #802

kriswest avatar Aug 26 '22 13:08 kriswest