August 1, 2023

Moving to 2.0

Moving to 2.0

With the latest version of our Agent, Connectifi has moved it’s API to the FDC3 2.0 interface. Going forward all of our interfaces will use FDC3 2.x and we want to share with you the good parts that we’re excited about, what the transition looks like with Connectifi, and some open questions we have for the community.

The Good Parts

Promises, promises

In FDC3 1.x, APIs were a mix of sync and async.  In the 2.0 specification, all APIs are now async and return Promises.   This change works really well with Connectifi’s cloud architecture.

With the fully async FDC3 2.0 API,  we’ve added robust offline detection.  If the connection has dropped, the promise on any FDC3 method will reject with a ‘NoConnectionAvailable’ error.  In combination with the Connectifi Agent’s connected/disconnected callbacks, this can be used to build full-featured offline support.  For example, providing end user notification, queuing actions, and replay of unsent commands.

Data Intents

Probably the most significant feature of FDC3 2.0 is the long anticipated data response on intents.  There has been a placeholder for this feature since the very first version of the FDC3 API, but the mechanism for actually delivering a response from an intent remained elusive to the standard for some time.   Intents with data results greatly expand the scope and value of use cases that FDC3 can support.  And with the determinism and observability that cloud services provide, Connectifi brings even greater value to these use cases.

raising a data intent
Raising an intent to 'GetPrice' in the Connectifi FDC3 Sandbox

Getting the data response from an intent is relatively simple

-- CODE language-js --
const intentResult = await fdc3.raiseIntent('GetSomeData', context);
const theData = await intentResult.getResult();

data result
Data result for the intent
data in use
Data can then be used by the app raising the intent

Upgrading

Moving from 1.x to 2.x of the Connectifi Agent can be done with a few simple steps:

  1. FINOS Package update. If you are using the @finos/fdc3 NPM package for FDC3 types in your App, be sure to update the package to a minimum of version 2.0.3.
  2. Async Listeners.  Convert any listener assignments using addContextHandler or addIntentHandler to async.
  3. Context and Intent handlers split.  In 1.x contextHandlers and intentHandlers were the same type.   In order to support data responses on intents, 2.x intent handlers have a different interface.  Intent handlers are now async - resolving to a void or IntentResolution type.
  4. System Channels changes.  The 1.x ‘system’ channel type becomes ‘user’ channel in 2.x.

Async Listeners

This signature:

-- CODE language-js --
const listener = fdc3.addContextListener('context', () => {});

becomes this:

-- CODE language-js --
const listener = await fdc3.addContextListener('context', () => {});

Context & Intent Handlers

This pattern:

-- CODE language-js --
const contextHandler = (context)=> {
//do something
};
fdc3.addContextListener('fdc3.instrument', contextHandler);
fdc3.addIntentListener( 'ViewChart', 'fdc3.instrument', contextHandler);

Becomes this:

-- CODE language-js --
const contextHandler = (context) => {
//do something with the context
};

const intentHandler =  async(context) => {
//do something
//return void
return;
};

const dataIntentHandler =  async(context) => {
       //do something
//return ContextData as IntentResolution
return {
            type:'sandbox.PriceResult',
            ...
        };
};

fdc3.addContextListener('fdc3.instrument', contextHandler);
fdc3.addIntentListener( 'ViewChart', 'fdc3.instrument', intentHandler);
fdc3.addIntentListener( 'GetPrice', 'fdc3.instrument', dataIntentHandler);

System Channels

The following API name changes/deprecations happen with 2.0:

  • getUserChannels is added and getSystemChannels is deprecated
  • joinChannel is deprecated for joinUserChannel

note: previously, joinChannel was agnostic to channel type.  Technically, you could join an ‘app’ channel as well as a ‘system’ channel.  2.0 makes this behavior more prescriptive.

Open Questions

Some of the changes in 2.0 are big and Connectifi is rolling them out in an incremental manner so we can get full community feedback on use cases as well as the best and safest way to implement.  Here are the open questions we currently have that we’d love to get your feedback on.

findInstances

The findInstance API allows an app to get all of the unique instance identifiers for an App from a  appId.

Since appIds are publicly knowable there are some data leakage concerns around this API. Particularly since the method makes it very easy for an app to monitor the usage of other apps in the environment.  (note: this is a general concern, more details below).  Beyond this, we are unclear on the use cases for an app retrieving the instances of another app. For now, we have opted to return instance data only for the caller’s own appId.

Private Channels

In FDC3 2.0, an intent can return either ContextData or a PrivateChannel instance as the result of its IntentResolution response.   As noted above, we have implemented the ContextData part, but are currently holding on private channels.   The main reasons are:

  1. There is a lack of clearly defined use cases for the Private Channels API and we are looking to the community to provide input.
  2. Connectifi already provides secure interoperability for restricted groups of applications using strong application identity and internet standards of security like TLS, web sockets, and OAuth.

App Identity

FDC3 2.0 adds instance identifiers for applications and a method for getting the metadata for an app from it’s identifier.

While this takes steps towards empowering apps to make some security related decisions at runtime, there are a number of open questions concerning the use of the FDC3 AppIdentifier as a security mechanism:

  • How can we mitigate the risks of data leakage of the instance data, such as with the findInstances API  above?
  • How would an app be able to make real time decisions with regards to the identity of other apps on the bus?  For example, how would an app track what apps it should (or shouldn't) initiate a private channel with at runtime?
  • How does an app establish trust with the desktop container that is brokering app identity for it?  And how does the desktop container establish (and maintain) trust with its own application endpoints?

The Global

One final change in FDC3 2.0 is the requirement that all web implementations expose window.fdc3 as a global.   In FDC3 1.x, this was a recommendation and de facto standard in desktop container environments, but never a hard requirement.

Implementing the global pattern with Connectifi is simple.  However, in order to give the community maximum optionality to application and platform owners, we have chosen to leave the last mile of how the FDC3 API is accessed up to the specific implementation.

Trying It Out

Connectifi is committed to making FDC3 as accessible and open as possible.  To that end, there are a number of free and/or open source resources we’ve made available to the community.

  • Get the Connectifi Agent on NPM
  • Try out FDC3 2.0 in our FDC3 Sandbox
  • The open source FDC3 Web Portal project on Github and NPM provides a reference implementation for using FDC3 in browser for both inter and intra page interoperability.
  • Contact us and give us your feedback!  We’d love to hear from you on any of the questions raised above or anything else FDC3 related.  info@connectifi.co