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

Adding application context sections, adding documentation on selectin… #290

Merged
merged 11 commits into from
Aug 23, 2024
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"devDependencies": {
"@commitlint/cli": "^17.0.3",
"@commitlint/config-conventional": "^17.0.3",
"@firebolt-js/openrpc": "3.1.0",
"@firebolt-js/openrpc": "3.1.1-next.2",
"@firebolt-js/schemas": "2.0.0",
"@saithodev/semantic-release-backmerge": "^3.2.0",
"@semantic-release/changelog": "^6.0.1",
Expand Down
113 changes: 82 additions & 31 deletions requirements/specifications/openrpc-extensions/app-passthrough-apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,20 @@ The key words "**MUST**", "**MUST NOT**", "**REQUIRED**", "**SHALL**", "**SHALL
- [2. Table of Contents](#2-table-of-contents)
- [3. Open RPC Extensions](#3-open-rpc-extensions)
- [3.1. Provided By Extension](#31-provided-by-extension)
- [3.2. Provider Selection Extension](#32-provider-selection-extension)
- [4. Routing App pass-through APIs](#4-routing-app-pass-through-apis)
- [4.1. No available providers](#41-no-available-providers)
- [4.2. Direct pass-through](#42-direct-pass-through)
- [4.4. Pass-through notifications](#44-pass-through-notifications)
- [4.3. Pass-through notifications](#43-pass-through-notifications)
- [5. Provider Candidates](#5-provider-candidates)
- [6. Best Candidate](#6-best-candidate)
- [7. Result Transformations](#7-result-transformations)
- [8. Provider Parameter Injection](#8-provider-parameter-injection)
- [9. API Gateway](#9-api-gateway)
- [10. Example: User Interest](#10-example-user-interest)
- [10.1. User Interest Pull](#101-user-interest-pull)
- [10.2. User Interest Push](#102-user-interest-push)
- [7. Application Context](#7-application-context)
- [7.1. Application Context Surfacing](#71-application-context-surfacing)
- [7.2. Application Context Selection](#72-application-context-selection)
- [8. API Gateway](#8-api-gateway)
- [9. Example: User Interest](#9-example-user-interest)
- [9.1. User Interest Pull](#91-user-interest-pull)
- [9.2. User Interest Push](#92-user-interest-push)

## 3. Open RPC Extensions

Expand Down Expand Up @@ -77,13 +79,46 @@ The provider method **MUST** provide the same capability that the platform metho

If a platform method has no provider method then it is not a valid Firebolt OpenRPC method schema, and a validation error **MUST** be generated.

### 3.2. Provider Selection Extension
Firebolt OpenRPC **MUST** support a `string` `x-provider-selection` extension property on the `capabilities` tag that denotes how to pick the best provider candidate, e.g.:

```json
{
"methods": [
{
"name": "Keyboard.standard",
"tags": [
{
"name": "capabilities",
"x-provided-by": "Keyboard.onRequestStandard",
"x-provider-selection": "appId"
"x-uses": [
"xrn:firebolt:capability:input:keyboard"
]
}
],
"parameters": [
{
"name": "appId",
"type": "string"
}
]
}
]
}
```

The value of `x-provider-selection`, if defined, **MUST** be either `"appId"` or `"focus"`.

Given the `x-provider-selection` extension has the value `"appId"`, then the method **MUST** have an `appId` `string` parameter.

## 4. Routing App pass-through APIs
App pass-through APIs may be routed in one of several ways.

When an app calls a platform method, i.e. one with an `x-provided-by` extension, the platform **MUST** use one of the routing methods defined in this section based on various properties of the method.

### 4.1. No available providers
When an app calls a platform method with an `x-provided-by` extension, the platform **MUST** return an unavailable error if there is no [candidate app](#7-provider-candidates) to execute the provider method.
When an app calls a platform method with an `x-provided-by` extension, the platform **MUST** return an unavailable error if there is no [candidate app](#5-provider-candidates) to execute the provider method.

```json
{
Expand All @@ -107,17 +142,17 @@ The platform method result schema **MUST** either:
> Match the `x-response` schema on the provider method so that the result can be passed through.
>
> or
>
>
> Have a property that matches the `x-response-name` string and `x-response` schema on the
> provider method so that the result can be composed and passed through.

The platform **MUST** call the provider method from the [best candidate](#8-best-candidate) app and acquire the result.
The platform **MUST** call the provider method from the [best candidate](#6-best-candidate) app and acquire the result.

If the platform method result schema matches the `x-response` schema on the provider method then the value **MUST** be used as-is.

Otherwise if the platform method result schema has a property that matches the `x-response` schema on the provider method then the value **MUST** be composed into an object under the corresponding property name and the platform **MUST** apply any [result transformations](#9-result-transformations) to the composed result.
Otherwise if the platform method result schema has a property that matches the `x-response` schema on the provider method then the value **MUST** be composed into an object under the corresponding property name.

### 4.4. Pass-through notifications
### 4.3. Pass-through notifications
Firebolt events have a synchronous subscriber registration method, e.g. `Lifecycle.onInactive(true)`, in addition to asynchronous notifications when the event actually happens. For events powered by an app pass-through, only the asynchronous notifications are passed in by the providing app. The initial event registration is handled by the platform, and the success response is not handled by the providing app.

This section only applies to platform methods that have an `event` tag.
Expand Down Expand Up @@ -205,11 +240,11 @@ Matching provider method:
}
```

When a provider app calls a provider method mapped to an event the platform **MUST** ignore the notification if the app is not a [candidate app](#7-provider-candidates) for this capability.
When a provider app calls a provider method mapped to an event the platform **MUST** ignore the notification if the app is not a [candidate app](#5-provider-candidates) for this capability.

If the platform method result schema matches the *last* parameter schema on the provider method then the value **MUST** be used as-is.

Otherwise if the platform method result schema has a property that matches the *last* parameter schema on the provider method then the value **MUST** be composed into an object under the corresponding property name and the platform **MUST** apply any [result transformations](#9-result-transformations) to the composed result.
Otherwise if the platform method result schema has a property that matches the *last* parameter schema on the provider method then the value **MUST** be composed into an object under the corresponding property name.

If the value was composed into the platform method result under a matching property, then any context parameter values from the provider method that correspond to a property name and schema in the platform method result **MUST** also be composed into the platform method result under those properties.

Expand All @@ -221,32 +256,48 @@ all loaded apps that have permission to provide the capability **MUST** be
considered as candidates to fulfill the method.

## 6. Best Candidate
Any provider candidates that have not registered to provide the method in
question **MUST NOT** be considered the best candidate and removed from
consideration.
A provider candidate app **MUST** include the capability in the `provide` section of the app manifest.

If a provider candidate is currently running, it **MUST** have already registered to provide the capability in
question.

If there is only one candidate left then it **MUST** be the best candidate.
If there is exactly one provider candidate then it **MUST** be the best candidate.

If there is more than one candidate left, then the candidate app that most recently had RCU input focus **MUST** be the best candidate.
If there is more than one provider candidate then the following requirements **MUST** be used to select the best candidate, in order.

If none of the candidates have had focus yet, then the candidate app that was most recently launched **MUST** be the best candidate.
> Given there is an `x-provider-selection` extension on the platform method capabilities tag, when that extension is set to the value `"appId"` then the provider candidate with an appId that matches the value of the platform method `appId` parameter **MUST** be the best candidate.
>
> Given there is an `x-provider-selection` extension on the platform method capabilities tag, when that extension is set to the value `"focus"` then the provider candidate that currently has RCU focus **MUST** be the best candidate.
>
> Given there is no `x-provider-selection` extension, or it has a value not defined in this specification, when there is a provider candidate that was launched more recently then the other candidates then that provider candidate **MUST** be the best candidate.

## 7. Application Context

Application Context provides a mechanism for applications to know the identity of the applications they are communicating with. Application Context can be given in both directions. An application that uses a capability can know which app is providing that capability. An application that provides a capability can know which app is using that capability.

### 7.1. Application Context Surfacing

## 7. Result Transformations
A platform method may be configured to insert the providing app id into composite values. This is not allowed in non-composite results to avoid collisions with the provder method sending an appId and Firebolt overriding it.
A method may be configured to surface application context by inserting the "other" appId into the request or response and is triggered by the presense of an `appId` in either the platform method or the provider method, but not both.

If a "composite result" was used to wrap the provider method value and the platform method's schema has an `appId` `string` property at the top level then the property's value **MUST** be set to the the appId of the providing app for that result.

## 8. Provider Parameter Injection
If the provider method has a parameter named `appId` and the platform method *does not*, then the appId of the app calling the platform method **MUST** be sent to the provider in the `appId` parameter.
If a platform method is an `event` and the event result is a "composite result" with an `appId` `string` property at the top level, then the property **MUST** be set to the appId that initiated the provider (push) call.

If the platform method is an `event` and the provider method has context parameters then each context parameter from the provider that has a matching context parameter in the event **MUST** have it's value passed to that parameter.
If a platform method is an `event` and the event has an `appId` `string` context parameter and the provider method *does not* have an `appId` parameter, then the `appId` context parameter **MUST** be set to the appId that initiated the provider (push) call.

If the platform method is an `event` with a "composite result" and the provider method has context parameters then each context parameter from the provider that has a matching property on the `result` object **MUST** have it's value copied into that property.
If the provider method has an `appId` `string` parameter and the platform method does not have an `appId` parameter, then the id of app that initiated the platform method call **MUST** be used to set the `appId` in the provider method request.

## 9. API Gateway
### 7.2. Application Context Selection

A method may be configured to enabled application context selection by exposing an appId parameter to allow the calling app to influence which app will provide it.

When a platform method is invoked, the gateway will find the provider using the `Provider Candidate` rules as described above. However, some Firebolt APIs allow selecting the provider that should be used. If a platform method request schema is a "composite request" with `appId` `string` parameter but the provider method request schema is not a composite request, then the given appId shall be used to select the provider.
If "appId" is a required parameter in the platform method request schema, then it must be supplied. If it is not, then the request should fail with invalid parameters. If it is an optional parameter and it is not supplied, then the gateway should use rules in "Provider Candidate" section for selecting the candidate.

## 8. API Gateway
The Firebolt API Gateway **MUST** detect app-passthrough APIs and map the `use`/`manage` APIs to the corresponding `provide` APIs by parsing the Firebolt OpenRPC Specification and following the logic outline in this document.

## 10. Example: User Interest
## 9. Example: User Interest

The following schemas are referenced by these examples:

Expand Down Expand Up @@ -287,7 +338,7 @@ The following schemas are referenced by these examples:
}
```

### 10.1. User Interest Pull
### 9.1. User Interest Pull

Platform method:

Expand Down Expand Up @@ -370,7 +421,7 @@ Provider method:
}
```

### 10.2. User Interest Push
### 9.2. User Interest Push

Provider method:

Expand Down Expand Up @@ -454,7 +505,7 @@ Platform Method:
"$ref": "https://meta.comcast.com/firebolt/entity#/definitions/EntityDetails"
}
}

}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/openrpc/content.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
{
"name": "capabilities",
"x-provided-by": "Discovery.onRequestUserInterest",
"x-provider-selection": "focus",
"x-uses": [
"xrn:firebolt:capability:discovery:interest"
]
Expand Down Expand Up @@ -95,6 +96,7 @@
{
"name": "capabilities",
"x-provided-by": "Discovery.userInterest",
"x-provider-selection": "focus",
"x-uses": [
"xrn:firebolt:capability:discovery:interest"
]
Expand Down
Loading