Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

484 compliance info #753

Merged
merged 10 commits into from
Jul 29, 2022
114 changes: 57 additions & 57 deletions docs/api/ref/DesktopAgent.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ interface DesktopAgent {
createPrivateChannel(): Promise<PrivateChannel>;
getUserChannels(): Promise<Array<Channel>>;

// optional channel management functions
// OPTIONAL channel management functions
joinUserChannel(channelId: string) : Promise<void>;
getCurrentChannel() : Promise<Channel | null>;
leaveCurrentChannel() : Promise<void>;
Expand Down Expand Up @@ -183,6 +183,59 @@ fdc3.broadcast(instrument);

* [addContextListener](#addcontextlistener)

### `createPrivateChannel`

```ts
createPrivateChannel(): Promise<PrivateChannel>;
```

Returns a `Channel` with an auto-generated identity that is intended for private communication between applications. Primarily used to create channels that will be returned to other applications via an IntentResolution for a raised intent.

If the `PrivateChannel` cannot be created, the returned promise MUST be rejected with an error string from the [`ChannelError`](Errors#channelerror) enumeration.

The `PrivateChannel` type is provided to support synchronisation of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.

It is intended that Desktop Agent implementations:

* SHOULD restrict external apps from listening or publishing on this channel.
* MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel.
* MUST provide the `id` value for the channel as required by the `Channel` interface.

#### Example

```js
fdc3.addIntentListener("QuoteStream", async (context) => {
const channel = await fdc3.createPrivateChannel();
const symbol = context.id.ticker;

// This gets called when the remote side adds a context listener
const addContextListener = channel.onAddContextListener((contextType) => {
// broadcast price quotes as they come in from our quote feed
feed.onQuote(symbol, (price) => {
channel.broadcast({ type: "price", price});
});
});

// This gets called when the remote side calls Listener.unsubscribe()
const unsubscriberListener = channel.onUnsubscribe((contextType) => {
feed.stop(symbol);
});

// This gets called if the remote side closes
const disconnectListener = channel.onDisconnect(() => {
feed.stop(symbol);
});

return channel;
});
```

#### See also

* [`PrivateChannel`](PrivateChannel)
* [`raiseIntent`](#raiseintent)
* [`addIntentListener`](#addintentlistener)

### `findInstances`

```ts
Expand Down Expand Up @@ -359,7 +412,7 @@ await fdc3.raiseIntent(startChat.intent.name, context, selectedApp);
getCurrentChannel() : Promise<Channel | null>;
```

Optional function that returns the `Channel` object for the current User channel membership. In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.
OPTIONAL function that returns the `Channel` object for the current User channel membership. In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.

Returns `null` if the app is not joined to a channel.

Expand Down Expand Up @@ -434,59 +487,6 @@ catch (err){

* [`Channel`](Channel)

### `createPrivateChannel`

```ts
createPrivateChannel(): Promise<PrivateChannel>;
```

Returns a `Channel` with an auto-generated identity that is intended for private communication between applications. Primarily used to create channels that will be returned to other applications via an IntentResolution for a raised intent.

If the `PrivateChannel` cannot be created, the returned promise MUST be rejected with an error string from the [`ChannelError`](Errors#channelerror) enumeration.

The `PrivateChannel` type is provided to support synchronisation of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.

It is intended that Desktop Agent implementations:

* SHOULD restrict external apps from listening or publishing on this channel.
* MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel.
* MUST provide the `id` value for the channel as required by the `Channel` interface.

#### Example

```js
fdc3.addIntentListener("QuoteStream", async (context) => {
const channel = await fdc3.createPrivateChannel();
const symbol = context.id.ticker;

// This gets called when the remote side adds a context listener
const addContextListener = channel.onAddContextListener((contextType) => {
// broadcast price quotes as they come in from our quote feed
feed.onQuote(symbol, (price) => {
channel.broadcast({ type: "price", price});
});
});

// This gets called when the remote side calls Listener.unsubscribe()
const unsubscriberListener = channel.onUnsubscribe((contextType) => {
feed.stop(symbol);
});

// This gets called if the remote side closes
const disconnectListener = channel.onDisconnect(() => {
feed.stop(symbol);
});

return channel;
});
```

#### See also

* [`PrivateChannel`](PrivateChannel)
* [`raiseIntent`](#raiseintent)
* [`addIntentListener`](#addintentlistener)

### `getUserChannels`

```ts
Expand All @@ -512,7 +512,7 @@ const redChannel = userChannels.find(c => c.id === 'red');
joinUserChannel(channelId: string) : Promise<void>;
```

Optional function that joins the app to the specified User channel. In most cases, applications SHOULD be joined to channels via UX provided to the application by the desktop agent, rather than calling this function directly.
OPTIONAL function that joins the app to the specified User channel. In most cases, applications SHOULD be joined to channels via UX provided to the application by the desktop agent, rather than calling this function directly.

If an app is joined to a channel, all `fdc3.broadcast` calls will go to the channel, and all listeners assigned via `fdc3.addContextListener` will listen on the channel.

Expand Down Expand Up @@ -545,7 +545,7 @@ fdc3.joinUserChannel(selectedChannel.id);
leaveCurrentChannel() : Promise<void>;
```

Optional function that removes the app from any User channel membership. In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.
OPTIONAL function that removes the app from any User channel membership. In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly.

Context broadcast and listening through the top-level `fdc3.broadcast` and `fdc3.addContextListener` will be a no-op when the app is not joined to a User channel.

Expand Down
65 changes: 33 additions & 32 deletions docs/api/ref/Errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,39 @@ title: Errors

Some FDC3 API operations return promises that can result in errors.

## `ChannelError`

```typescript
enum ChannelError {
/** Returned if the specified channel is not found when attempting to join a
* channel via the `joinUserChannel` function of the DesktopAgent (`fdc3`).
*/
NoChannelFound = 'NoChannelFound',

/** SHOULD be returned when a request to join a user channel or to a retrieve
* a Channel object via the `joinUserChannel` or `getOrCreateChannel` methods
* of the DesktopAgent (`fdc3`) object is denied.
*/
AccessDenied = 'AccessDenied',

/** SHOULD be returned when a channel cannot be created or retrieved via the
* `getOrCreateChannel` method of the DesktopAgent (`fdc3`).
*/
CreationFailed = 'CreationFailed',
}
```

Contains constants representing the errors that can be encountered when calling channels using the [`joinUserChannel`](DesktopAgent#joinuserchannel) or [`getOrCreateChannel`](DesktopAgent#getorcreatechannel) methods, or the [`getCurrentContext`](Channel#getcurrentcontext), [`broadcast`](Channel#broadcast) or [`addContextListener`](Channel#addcontextlistener) methods on the `Channel` object.

#### See also

* [`DesktopAgent.createPrivateChannel`](DesktopAgent#createprivatechannel)
* [`DesktopAgent.joinUserChannel`](DesktopAgent#joinuserchannel)
* [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)
* [`Channel.broadcast`](Channel#broadcast)
* [`Channel.addContextListener`](Channel#addcontextlistener)
* [`Channel.getCurrentContext`](Channel#getcurrentcontext)

## `OpenError`

```typescript
Expand Down Expand Up @@ -107,35 +140,3 @@ Contains constants representing the errors that can be encountered when calling
* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener)
* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent)
* [`IntentResolution`](Metadata#intentresolution)

## `ChannelError`

```typescript
enum ChannelError {
/** Returned if the specified channel is not found when attempting to join a
* channel via the `joinUserChannel` function of the DesktopAgent (`fdc3`).
*/
NoChannelFound = 'NoChannelFound',

/** SHOULD be returned when a request to join a user channel or to a retrieve
* a Channel object via the `joinUserChannel` or `getOrCreateChannel` methods
* of the DesktopAgent (`fdc3`) object is denied.
*/
AccessDenied = 'AccessDenied',

/** SHOULD be returned when a channel cannot be created or retrieved via the
* `getOrCreateChannel` method of the DesktopAgent (`fdc3`).
*/
CreationFailed = 'CreationFailed',
}
```

Contains constants representing the errors that can be encountered when calling channels using the [`joinUserChannel`](DesktopAgent#joinuserchannel) or [`getOrCreateChannel`](DesktopAgent#getorcreatechannel) methods, or the [`getCurrentContext`](Channel#getcurrentcontext), [`broadcast`](Channel#broadcast) or [`addContextListener`](Channel#addcontextlistener) methods on the `Channel` object.

#### See also

* [`DesktopAgent.joinUserChannel`](DesktopAgent#joinuserchannel)
* [`DesktopAgent.getOrCreateChannel`](DesktopAgent#getorcreatechannel)
* [`Channel.broadcast`](Channel#broadcast)
* [`Channel.addContextListener`](Channel#addcontextlistener)
* [`Channel.getCurrentContext`](Channel#getcurrentcontext)
75 changes: 59 additions & 16 deletions docs/api/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,14 @@ Examples of endpoints include:

## Desktop Agent Implementation

The FDC3 API specification consists of interfaces. It is expected that each Desktop Agent will implement these interfaces. A typical implemention would provide instantiable classes for the following interfaces:
The FDC3 API specification consists of interfaces. It is expected that each Desktop Agent will implement these interfaces. A typical implemention would provide implementations for the following interfaces:

- [`DesktopAgent`](ref/DesktopAgent)
- [`Channel`](ref/Channel)
- [`PrivateChannel`](ref/PrivateChannel)
- [`Listener`](ref/Types#listener)

Other interfaces defined in the spec are not critical to define as concrete types. Rather, the Desktop Agent should expect to have objects of the interface shape passed into or out of their library. These interfaces include:

- [`AppIntent`](ref/Metadata#appintent)
- [`AppMetadata`](ref/Metadata#appmetadata)
- [`Context`](ref/Types#context)
- [`ContextHandler`](ref/Types#contexthandler)
- [`DisplayMetadata`](ref/Metadata#displaymetadata)
- [`Icon`](ref/Types#icon)
- [`ImplementationMetadata`](ref/Metadata#implementationmetadata)
- [`IntentHandler`](ref/Types#intenthandler)
- [`IntentResult`](ref/Types#intentresult)
- [`IntentMetadata`](ref/Metadata#intentmetadata)
- [`IntentResolution`](ref/Metadata#intentresolution)
- [`TargetApp`](ref/Types#targetapp)
Other interfaces defined in the spec are not critical to define as concrete types. Rather, the Desktop Agent should expect to have objects of the interface shape passed into or out of their library.

### API Access

Expand Down Expand Up @@ -105,6 +92,62 @@ Desktop Agent interop is supported by common standards for APIs for App discover

An actual connection protocol between Desktop Agents is not currently available in the FDC3 standard, but work on creating one for a future version of the standard is underway (see [GitHub discussion #544](https://github.com/finos/FDC3/discussions/544) for details).

### Desktop Agent API Standard Compliance

An FDC3 Standard compliant Desktop Agent implementation **MUST**:

- Provide the FDC3 API to web applications via a global accessible as [`window.fdc3`](#api-access).
- Provide a global [`fdc3Ready`](#api-access) event that is fired when the API is ready for use.
- Provide a method of resolving ambiguous intents (i.e. those that might be resolved by multiple applications) or unspecified intents (calls to raiseIntentForCOntext that return multiple options), usch as a resolver UI.
kriswest marked this conversation as resolved.
Show resolved Hide resolved
- Intent resolution MUST take into account any specified input or return context types
- Requests for resolution to apps returning a channel MUST include any apps that are registered as returning a channel with a specific type.
- Return Errors from the [`ChannelError`](ref/Errors#channelerror), [`OpenError`](ref/Errors#openerror), [`ResolveError`](ref/Errors#resolveerror) and [`ResultError`](ref/Errors#resulterror) enumerations as appropriate.
- Accept as input and return as output data structures that are compatibile with the interfaces defined in this Standard.
- Include implementations of the following [Desktop Agent](ref/DesktopAgent) API functions, as defined in this Standard:
- [`addContextListener`](ref/DesktopAgent#addcontextlistener)
- [`addIntentListener`](ref/DesktopAgent#addintentlistener)
- [`broadcast`](ref/DesktopAgent#broadcast)
- [`createPrivateChannel`](ref/DesktopAgent#createprivatechannel)
- [`findInstances`](ref/DesktopAgent#findinstances)
- [`findIntent`](ref/DesktopAgent#findintent)
- [`findIntentsByContext`](ref/DesktopAgent#findintentsbycontext)
- [`getCurrentChannel`](ref/DesktopAgent#getcurrentchannel)
- [`getInfo`](ref/DesktopAgent#getinfo)
- [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel)
- [`getUserChannels`](ref/DesktopAgent#getuserchannels)
- [`open`](ref/DesktopAgent#open)
- [`raiseIntent`](ref/DesktopAgent#raiseintent)
- [`raiseIntentForContext`](ref/DesktopAgent#raiseintentforcontext)
- Provide an ID for each [`PrivateChannel`](ref/PrivateChannel) created via [`createPrivateChannel`](ref/DesktopAgent#createprivatechannel) and prevent them from being retrieved via [`getOrCreateChannel`](ref/DesktopAgent#getorcreatechannel) by ID.
- Only require app directories that they connect to to have implemented only the minimum requirements specified in the [App Directory API Part](../app-directory/spec) of this Standard.

An FDC3 Standard compliant Desktop Agent implementation **SHOULD**:

- Support connection to one or more App Directories meeting the [FDC3 App Directory Standard](../app-directory/overview).
- Qualify `appId` values received from an app directory with the hostname of the app directory server (e.g. `myAppId@name.domain.com`) [as defined in the app directory standard](../app-directory/overview#application-identifiers).
- Adopt the [recommended set of User channel definitions](#recommended-user-channel-set).
- Ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are joined to the channel.
- Make metadata about each context message or intent and context message received (including the app that originated the message) available to the receiving application.
- Prevent external apps from listening or publishing on a [`PrivateChannel`](ref/PrivateChannel) that they did not request or provide.
- Enforce compliance with the expected behavior of intents (where Intents specify a contract that is enforceable by schema, for example, return object types) and return an error if the interface is not met.

An FDC3 Standard compliant Desktop Agent implementation **MAY**:

- Make the Desktop Agent API available through modules, imports, or other means.
- Implement the following OPTIONAL [Desktop Agent](ref/DesktopAgent) API functions:
- [`joinUserChannel`](ref/DesktopAgent#joinuserchannel)
- [`leaveCurrentChannel`](ref/DesktopAgent#leavecurrentchannel)
- [`getCurrentChannel`](ref/DesktopAgent#getcurrentchannel)
- Implement the following deprecated API functions:
- [`addContextListener`](ref/DesktopAgent#addcontextlistener-deprecated) (without a contextType argument)
- [`getSystemChannels`](ref/DesktopAgent#getsystemchannels-deprecated) (renamed getUserChannels)
- [`joinChannel`](ref/DesktopAgent#joinchannel-deprecated) (renamed joinUserChannel)
- [`open`](ref/DesktopAgent#open-deprecated) (deprecated version that addresses apps via `name` field)
- [`raiseIntent`](ref/DesktopAgent#raiseintent-deprecated) (deprecated version that addresses apps via `name` field)
- [`raiseIntentForContext`](ref/DesktopAgent#raiseintentforcontext-deprecated) (deprecated version that addresses apps via `name` field)

For more details on FDC3 Standards compliance (including the versioning, deprecation and experimental features policies) please see the [FDC3 Compliance page](../fdc3-compliance).

## Functional Use Cases

### Retrieve Metadata about the Desktop Agent implementation
Expand Down Expand Up @@ -350,7 +393,7 @@ When an app joins a User channel, or adds a context listener when already joined

It is possible that a call to join a User channel could be rejected. If for example, the desktop agent wanted to implement controls around what data apps can access.

Joining channels in FDC3 is intended to be a behavior initiated by the end user. For example: by color linking or apps being grouped in the same workspace. Most of the time, it is expected that apps will be joined to a channel by mechanisms outside of the app. To support programmatic management of joined channels and the implementation of channel selector UIs other than those provided outside of the app, Desktop Agent implementations MAY provide [`fdc3.joinChannel()`](ref/DesktopAgent#joinchannel), [`fdc3.getCurrentChannel()](ref/DesktopAgent#getcurrentchannel) and [`fdc3.leaveCurrentChannel()`](ref/DesktopAgent#leavecurrentchannel) functions and if they do, MUST do so as defined in the [Desktop Agent API reference](ref/DesktopAgent).
Joining channels in FDC3 is intended to be a behavior initiated by the end user. For example: by color linking or apps being grouped in the same workspace. Most of the time, it is expected that apps will be joined to a channel by mechanisms outside of the app. To support programmatic management of joined channels and the implementation of channel selector UIs other than those provided outside of the app, Desktop Agent implementations MAY provide [`fdc3.joinChannel()`](ref/DesktopAgent#joinchannel), [`fdc3.getCurrentChannel()`](ref/DesktopAgent#getcurrentchannel) and [`fdc3.leaveCurrentChannel()`](ref/DesktopAgent#leavecurrentchannel) functions and if they do, MUST do so as defined in the [Desktop Agent API reference](ref/DesktopAgent).

There SHOULD always be a clear UX indicator of what channel an app is joined to.

Expand Down
Loading