Skip to main content

How to integratie with Marketplace

Updated this week

How to integrate with Carerix Marketplace

This article describes what is a Carerix Marketplace, what problems does it solve and how a Carerix partner can integrate their solution to become a Marketplace Feature.

What is a Carerix Marketplace

It is a system allowing Carerix customers to augment their setup by activating additional features from a supervised list. A feature might be a middleware service, a web portal, a browser extension or even a combination of those. Currently only customer’s administrators can do a feature activation.

The main purpose of the Marketplace is to standardise and automate the feature lifecycle management with regards to hundreds of customers Carerix has.

Benefits

· Customer can easily enable more functionality from trusted vendors with just two clicks;

· Carerix has a unified approach to deliver additional features to the customers;

· Vendor can advertise and deliver their own solution to hundreds of Carerix customers by implementing a Marketplace integration.

Terminology

Manifest is a definition of a component that can be installed into a tenant’s system. It describes what OAuth2Clients have to be created within a tenant, what settings a component has, who developed it and where to deliver feature lifecycle events.

A list of Manifests is supervised and maintained by Carerix.

Feature is an installation of a Manifest for a particular tenant with a certain status and (if defined by a Manifest) settings values. Tenant’s administrator can install a feature and then perform lifecycle actions on it: activate, update, deactivate and uninstall. Carerix Marketplace itself can perform other lifecycle actions: upgrade and cleanup.

Installation is a process of creating OAuth2Client(s) for a Feature within a tenant as well as provisioning all other resources necessary for it to work. If installation succeeds, a Feature moves to deactivated status. This step is where a vendor’s solution must provision all the resources necessary to accommodate a tenant, e.g.: database schema, cache entry, OAuth2Client credentials record etc.

Activation is a process of enabling a Feature for a tenant. Only Features with deactivated status might be activated. If activation succeeds, a Feature moves to activated status. If vendor’s solution is a middleware, it must perform actions with regards to a tenant (e.g. handle API requests, do any business logic) only if a Feature for such tenant is activated.

Deactivation is a process of disabling a Feature for a tenant. Only Features with activated status might be deactivated. If deactivation succeeds, a Feature moves to deactivated status. Consider activation/deactivation as a simple toggle which customer might enable if everything is ready to work or disable if he experiences any issues with a Feature.

Updating is a process of changing setting values for a Feature. Only Features with deactivated or activated statuses might be updated. If a Manifest doesn’t declare any setting, this process will never be called.

Uninstallation is a process of deleting Feature’s OAuth2Clients created within a tenant as well as deleting all tenant’s data related to a Feature from a vendor’s storage. Only Features with deactivated status might be uninstalled. If uninstallation succeeds, a Feature will be deleted, thus it will be possible to install it again.

Upgrading is a process of maintaining a Feature state according to its Manifest. This action is performed by Carerix Marketplace itself if:

· a Manifest of a Feature has a new version released;

· it has detected that an OAuth2Client for a Feature in IAM is broken and thus corresponding repairs were done.

Cleanup is a process of purging tenant’s data when tenant leaves Carerix.

Manifest

Each component in the marketplace has its own manifest declaring OAuth2Clients to be created during installation, URLs where lifecycle events will be delivered to, settings such component has etc.

Vendors have to provide a manifest YAML file to Carerix for review, which in case of approval will be added to the Marketplace’s manifests registry, thus making a new entry in the installable features list.

Here’s an example of a manifest file:

manifest:
  id: "partner"
  manifestVersion: 1
  name: "FEATURES.PARTNER.NAME"
  description: "FEATURES.PARTNER.DESCRIPTION"
  icon: "<svg ...></svg>"
  active: true
  buildInfo:
    version: "0.0.1"
    managementUri: "https://example.com/features/management"
    settingsUri: "https://example.com/features/settings"
    vendor:
      name: "Example Inc"
      code: "example"
      email: "info@example.com"
      website: "https://example.com"
  settings:
    backend:
      - type: "singleLineText"
        code: "inputExample"
        array: false
        sensitive: false
        required: false
  oauth2:
    backend:
      code: "urn:example/partnerService"
      name: "Example of backend application"
      scopes:
        provide: []
        request:
          - code: "urn:cx/cx5Wrapper:data:manage"
      resources: []
      assignedResources: []
    frontend:
      code: "urn:example/partnerUI"
      name: "Example of frontend application"
      access:
        type: "public"
        consentRequired: false
        webOrigins:
          - "example.com"
        redirectUris:
          - "example.com/redirect"
        homeUrl: "example.com/home"
      scopes:
        request:
          - code: "urn:cx/cx5Wrapper:data:manage"

Specifications for most relevant manifest properties are following:

Path relative to $.manifest

Type

Description

Example

$.id

string

Unique identifier of a feature. It will be used as an argument in API calls when performing operations on a feature.

Required, must match following regular expression: [A-Za-z][A-Za-z0-9_\-]{1,31}.

partner

$.manifestVersion

integer

Version of a manifest.

Some features might change over the time, e.g. getting more settings or requiring additional accesses to function properly. If it happens, a vendor can provide a new manifest file with incremented version and in case of approval, Carerix Marketplace will upgrade all existing feature installations and all subsequent ones will be provisioned using such incremented version.

Required. For new integrations, it is recommended to use 1.

1

$.name

string

Name of a feature. This is what displayed as a title in the Marketplace UI.

This value supports internationalisation, e.g. Marketplace will look up a translation key matching value of this property and use corresponding translation value if a key exists.

Required. It is recommended to use MARKETPLACE.<ID>.NAME where <ID> is an uppercased unique identifier of a feature.

MARKETPLACE.PARTNER.NAME

or

Cool partner feature

$.description

string

Description of a feature in HTML format. This is what displayed as a feature description in the Marketplace UI when user selects a particular feature.

This value supports internationalisation, e.g. Marketplace will look up a translation key matching value of this property and use corresponding translation value if a key exists.

Required. It is recommended to use MARKETPLACE.<ID>.DESCRIPTION where <ID> is an uppercased unique identifier of a feature.

MARKETPLACE.PARTNER.DESCRIPTION

or

Amazing feature from a <a href="https://example.com">partner</a>

$.icon

string

SVG icon of the feature. The SVG icon representing the feature. This icon is only used on the Marketplace screen.

<svg …>…</svg>

$.active

boolean

Whether a feature is active, e.g. is visible in the marketplace.

Required.

true

$.buildInfo

object

Information about the software running the feature.

Required.

version: "0.0.1"
managementUri: "https://example.com/features/management"
settingsUri: "https://example.com/features/settings"
vendor:
  name: "Example Inc"
  code: "example"
  email: "info@example.com"
  website: "https://example.com"

$.buildInfo.version

string

What software version is used to run the feature.

Though required, this is purely an informative field, vendor might use VCS commit hashcode, SemVer string or anything else.

0.0.1

$.buildInfo.vendor

string

Information about a feature vendor.

Required.

name: "Example Inc"
code: "example"
email: "info@example.com"
website: "https://example.com"

$.buildInfo.vendor.name

string

Full name of a vendor.

Required.

Example Inc

$.buildInfo.vendor.code

string

Unique short code of a vendor. Required.

This code will be used when composing codes for declared OAuth2 clients, API resources or OAuth2 scopes.

example

$.buildInfo.vendor.email

string

Contact email of a vendor.

Required.

info@example.com

$.buildInfo.vendor.website

string

Website of a vendor.

Required.

https://example.com

$.buildInfo.managementUri

string

Vendor’s URL where Marketplace will send requests about Feature lifecycle events. Must be a publicly accessible HTTPS-only endpoint.

Required.

https://example.com/features/management

$.buildInfo.settingsUri

string

Vendor’s URL where Marketplace will send requests about Feature settings changes. Must be a publicly accessible HTTPS-only endpoint.

Required.

https://example.com/features/settings

$.oauth2

object

Defines all OAuth2Clients that have to be created for a feature within a tenant.

Effectively it is a map where each client has a serviceId acting as a key and definition object as a value.

serviceId is a short string which is unique within a manifest and is used to refer to a client from other manifest sections.

Required, must contain at least one client.

backend:
  code: "urn:example/partnerService"
  name: "Example of backend application"
  scopes:
    provide: []
    request: []
  resources: []   
  assignedResources: []

$.oauth2[*].code

string

Unique code of OAuth2Client.

Required.

urn:example/partnerUI

$.oauth2[*].name

string

Displayable name of OAuth2Client.

Required.

Example of frontend application

$.oauth2[*].access

object

Access configuration for public OAuth2Client. For confidential OAuth2Client this entire section can be skipped.

type: "public"
consentRequired: false
webOrigins:
  - "example.com"
redirectUris:
  - "example.com/redirect"
homeUrl: "example.com/home"

$.oauth2[*].scopes.request

array

List of OAuth2 scopes assigned to OAuth2Client. This controls what APIs a client will have access to.

Required, but may be an empty list.

Regardless whether specified, Marketplace will always add a urn:cx/features:data/features:read scope to any client defined in the manifest.

- code: "urn:cx/cx5Wrapper:data:manage"
  optional: true

$.oauth2[*].scopes.request[*].code

string

Code of OAuth2Scope to assign to OAuth2Client.

Required.

urn:cx/cx5Wrapper:data:manage

$.oauth2[*].scopes.request[*].optional

boolean

Whether assigned scope is optional (if true) or default (if false or not specified).

false

$.oauth2[*].assignedResources

array

Permission matrix for confidential OAuth2Client’s service account. For public client this property must be skipped. For confidential client this property can be skipped or be an empty list if such client doesn’t need to have any permissions.

- code: "urn:cx/users:data/users"
  operations:
    - name: "read"
      level: "all"

$.oauth2[*].assignedResources[*].code

string

Code of API Resource to which OAuth2Client will have accesses.

Required.

urn:cx/users:data/users

$.oauth2[*].assignedResources[*].operation[*].name

string

Code of the operation on the API Resource.

Required.

read

$.oauth2[*].assignedResources[*].operation[*].level

string

Permission level for the operation on the API Resource.

Required.

all

$.settings

object

Settings adjustable by a tenant’s administrator. It is a map where each key is a serviceId (i.e. a key from $.oauth2 section) and value is a list of settings defined for an OAuth2Client referenced by serviceId.

Required. If a Feature doesn’t have to have any settings, an empty object ({}) must be specified then.

Please refer to the “Settings” section to discover more.

backend:
  - type: "singleLineText"
    code: "inputExample"
    array: false
    sensitive: false
    required: false

Feature lifecycle

Installation

This is a first step in a lifecycle: when tenant’s administrator decides to install a new feature from the Marketplace.

When “Install” button is clicked, Marketplace will create a new Feature record with installing status, create all OAuth2Clients described in the Manifest and then invoke a management endpoint provided by the vendor.

Given the example of Manifest provided in the previous section, the management endpoint request may look like this:

POST https://example.com/features/management
Authorization: Bearer <jwt_issued_to_features.apps.carerix.io_for_given_tenant>
{
  "_kind": "FeatureCreateCommand",
  "callbackUrl": "https://api.carerix.io/features/v1/callback",
  "payload": {
    "settings": {},
    "clientCredentials": {
      "backend": {
        "clientId": "partnerservicehash.apps.carerix.io",
        "clientSecret": "s3cr3t"
      }
    },
    "publicClients": {
      "frontend": {
        "clientId": "partneruihash.apps.carerix.io"
      }
    }
  }
}

The request body contains:

1. An event type: "_kind": "FeatureCreateCommand" which indicates that tenant requested feature installation;

2. A URL where to send callbacks in case if vendor goes with the asynchronous implementation;

3. Actual feature installation payload:

1. Feature settings specified by tenant’s administrator during installation, if any;

2. OAuth2Client credentials, i.e. clientId and clientSecret pair, for all confidential clients specified within the manifest;

3. clientId for all public clients specified within the manifest;

1. If manifest contains no public clients, $.payload.publicClients property will be absent.

The marketplace expects that the management endpoint will respond with either 200 OK or 202 Accepted HTTP status code. A response with any other status code will abort installation. Response body is ignored by the Marketplace.

Information about tenant who requested the installation is included into an access token from the Authorization header: tenant claim contains a unique tenant identifier and iss claim contains a URL of OpenID Connect endpoint for a tenant.

iss claim of an access token actually is a prefix for IAM token endpoint - one used to obtain tokens by confidential clients, so it has to be kept along with tenant identifier and feature status. Since Carerix tenants are hosted at different identity servers, a vendor cannot just hardcode token endpoint.

To prevent unauthorized access to management endpoint, vendor has to check that provided access token satisfies these conditions:

· iss claim contains a valid tenant URL: matches https://id<identity-server>.carerix.io/auth/realms/<tenant> template;

· azp claim is equal to features.apps.carerix.io;

· Signature is valid;

· Is not expired.

An up-to-date list of valid Carerix identity server hosts is available here.

Now, the HTTP response code affects the way in which installation will finish.

Synchronous approach

Responding with 200 OK means that a request was processed synchronously by feature vendor and the Marketplace has just to complete the installation by changing the feature status to deactivated immediately.

If a vendor expects provisioning of tenant resources to take a long time (more than 10 seconds), then installation implementation must take the asynchronous approach.

Asynchronous approach

Responding with 202 Accepted means that feature vendor needs some time to handle the request (e.g. provision a database schema, call some other APIs etc), thus installation is done in an asynchronous way. A vendor has to eventually call the Marketplace’s callback endpoint to deliver the result of installation in this case.

When everything is provisioned for a new feature on vendor’s side, a POST request has to be sent to the URL specified in callbackUrl property of the original installation request (e.g. https://api.carerix.io/features/v1/callback). Such request doesn’t need a request body, but has to:

1. Include an Authorization header with a Bearer <token> value, where a <token> is a JWT obtained for one of the confidential OAuth2Clients declared in a feature manifest, for a given tenant;

2. Include featureId query parameter being equal to id property of the original Manifest, e.g. partner from the example above;

3. Include type query parameter being equal to FeatureCreateCommand;

4. Include status query parameter being equal to SUCCESS, FAILED or IN_PROGRESS;

1. SUCCESS completes the installation, setting feature status to deactivated;

2. FAILED aborts the installation;

3. IN_PROGRESS currently has no effect.

Callback endpoint of the Marketplace will respond with 200 OK if request is valid.

Activation

Activation occurs when tenant’s administrator decides to enable an already installed feature for tenant’s users.

When “Activate” button is clicked, Marketplace will change a Feature status from deactivated to activating and then invoke a management endpoint provided by the vendor.

The management endpoint request is the same comparing to installation one, except for different _kind and an empty payload:

POST https://example.com/features/management
Authorization: Bearer <jwt_issued_to_features.apps.carerix.io_for_given_tenant>
{
  "_kind": "FeatureActivateCommand",
  "callbackUrl": "https://api.carerix.io/features/v1/callback",
  "payload": {}
}

The request body contains:

1. An event type: "_kind": "FeatureActivateCommand" which indicates that tenant requested feature activation;

2. A URL where to send callbacks in case if vendor goes with the asynchronous implementation;

3. An empty feature activation payload.

The expected response is the same as for installation: either 200 OK or 202 Accepted HTTP status code. Despite this, Carerix encourages using a synchronous way of feature activation handling, i.e. responding with 200 OK.

To prevent unauthorized access to management endpoint, vendor has to check an access token. The rules are the same as with feature installation, please refer to corresponding article section.

Synchronous approach

Responding with 200 OK means that a request was processed synchronously by feature vendor and the Marketplace has just to complete the activation by changing the feature status to activated immediately.

Since a component has all resources to support a tenant provisioned at the installation step, there’s no need to do any long-running operations during activation. Therefore a vendor is strongly advised to go with synchronous approach.

Deactivation

Deactivation occurs when tenant’s administrator decides to disable an active feature for tenant’s users. This might happen if a feature has to be additionally configured before being used, if customer wants to uninstall a feature and so on.

When “Deactivate” button is clicked, Marketplace will change a Feature status from activated to deactivating and then invoke a management endpoint provided by the vendor.

The management endpoint request is the same comparing to the activation one, except for different _kind:

POST https://example.com/features/management
Authorization: Bearer <jwt_issued_to_features.apps.carerix.io_for_given_tenant>
{
  "_kind": "FeatureDeactivateCommand",
  "callbackUrl": "https://api.carerix.io/features/v1/callback",
  "payload": {}
}

The request body contains:

1. An event type: "_kind": "FeatureDeactivateCommand" which indicates that tenant requested feature deactivation;

2. A URL where to send callbacks in case if vendor goes with the asynchronous implementation;

3. An empty feature deactivation payload.

The expected response is the same as for installation: either 200 OK or 202 Accepted HTTP status code. Despite this, Carerix encourages using a synchronous way of feature deactivation handling, i.e. responding with 200 OK.

To prevent unauthorized access to management endpoint, vendor has to check an access token. The rules are the same as with feature installation, please refer to corresponding article section.

Synchronous approach

Responding with 200 OK means that a request was processed synchronously by feature vendor and the Marketplace has just to complete the deactivation by changing the feature status to deactivated immediately.

Deactivation doesn’t imply deleting of tenant’s data. On the contrary, tenant might want to re-activate a feature again after the issue caused the deactivation is solved. So from vendor’s point of view, this has to be just a status change, after which a feature keeps the tenant’s data stored, but doesn’t process tenant’s requests.

Therefore a vendor is strongly advised to go with synchronous approach.

Updating

Updating occurs when tenant’s administrator decides to update feature’s settings. If there are no settings declared in a manifest, this lifecycle event will never happen.

When “Save” button is clicked, Marketplace will validate the supplied values, change a Feature status from activated or deactivated to updating and then invoke a management endpoint provided by the vendor.

Storing of feature setting values is responsibility of a vendor. Carerix Marketplace processes, but doesn’t store setting values.

Given the example of Manifest provided in the respective section, the management endpoint request may look like this:

POST https://example.com/features/management
Authorization: Bearer <jwt_issued_to_features.apps.carerix.io_for_given_tenant>
{
  "_kind": "FeatureUpdateCommand",
  "callbackUrl": "https://api.carerix.io/features/v1/callback",
  "payload": {
    "settings": {
      "backend": {
        "inputExample": "some value set by tenant's administrator"
      }
    }
  }
}

The request body contains:

1. An event type: "_kind": "FeatureUpdateCommand" which indicates that tenant requested feature settings update;

2. A URL where to send callbacks in case if vendor goes with the asynchronous implementation;

3. Actual feature settings update payload:

1. Feature settings specified by tenant’s administrator, grouped by serviceId.

The expected response is 200 OK HTTP status code, then settings are considered to be updated.

At the moment asynchronous feature settings update is not available.

To prevent unauthorized access to management endpoint, vendor has to check an access token. The rules are the same as with feature installation, please refer to corresponding article section.

Synchronous approach

Responding with 200 OK means that a request was processed synchronously by feature vendor and the Marketplace has just to complete the update by changing the feature status back to activated or deactivated immediately.

Vendor-side settings validation

It is possible for vendor to intentionally reject the settings update request, for example if a setting value does not pass some custom validation. In that case, vendor has to return a response with:

1. 4xx HTTP status;

2. Content-Type: application/problem+json HTTP header;

3. JSON response body like { "status": <status>, "detail": "<message>" }, where:

1. <status> is the same as in p.1;

2. <message> is a hint that will be shown to the tenant’s administrator.

As a result, instead of generic error message, tenant’s administrator will see the message from the vendor, like on screenshot below.

Uninstallation

This is a last step in a lifecycle: when tenant’s administrator decides to uninstall a deactivated feature.

When “Uninstall” button is clicked, Marketplace will change a Feature status from deactivated to uninstalling, invoke a management endpoint provided by the vendor and then delete all OAuth2Clients created for a Feature.

The management endpoint request is the same comparing to activation and deactivation ones, except for different _kind:

POST https://example.com/features/management
Authorization: Bearer <jwt_issued_to_features.apps.carerix.io_for_given_tenant>
{
  "_kind": "FeatureDeleteCommand",
  "callbackUrl": "https://api.carerix.io/features/v1/callback",
  "payload": {}
}

The request body contains:

1. An event type: "_kind": "FeatureDeleteCommand" which indicates that tenant requested feature uninstallation;

2. A URL where to send callbacks in case if vendor goes with the asynchronous implementation;

3. An empty feature uninstallation payload.

The marketplace expects that the management endpoint will respond with either 200 OK or 202 Accepted HTTP status code. A response with any other status code will abort uninstallation. Response body is ignored by the Marketplace.

To prevent unauthorized access to management endpoint, vendor has to check an access token. The rules are the same as with feature installation, please refer to corresponding article section.

Again, the HTTP response code affects the way in which uninstallation will finish.

Synchronous approach

Responding with 200 OK means that a request was processed synchronously by feature vendor and the Marketplace has just to complete the uninstallation by deleting a Feature and its OAuth2Clients immediately.

If a vendor expects decommissioning of tenant resources to take a long time (more than 10 seconds), then uninstallation implementation must take the asynchronous approach.

Asynchronous approach

Responding with 202 Accepted means that feature vendor needs some time to handle the request (e.g. drop a database schema, call some other APIs etc), thus uninstallation is done in an asynchronous way. A vendor has to eventually call the Marketplace’s callback endpoint to deliver the result of uninstallation in this case.

When resources provisioned for a feature on vendor’s side are deleted, a POST request has to be sent to the URL specified in callbackUrl property of the original uninstallation request (e.g. https://api.carerix.io/features/v1/callback). Such request doesn’t need a request body, but has to:

1. Include an Authorization header with a Bearer <token> value, where a <token> is a JWT obtained for one of the confidential OAuth2Clients declared in a feature manifest, for a given tenant;

2. Include featureId query parameter being equal to id property of the original Manifest, e.g. partner from the example given in Manifest section;

3. Include type query parameter being equal to FeatureDeleteCommand;

4. Include status query parameter being equal to SUCCESS, FAILED or IN_PROGRESS;

1. SUCCESS completes the uninstallation, deleting a feature and OAuth2 clients created for it;

2. FAILED aborts the uninstallation;

3. IN_PROGRESS currently has no effect.

Callback endpoint of the Marketplace will respond with 200 OK if request is valid.

Upgrading

If Carerix publishes a new version of a manifest provided by the vendor or if Marketplace itself notices an inconsistency in IAM setup, an upgrade operation will be executed for all tenants which have corresponding Feature in activated status.

When triggered, Marketplace will change a Feature status from activated to upgrading, create all missing OAuth2Clients and then invoke a management endpoint provided by the vendor.

The management endpoint request may look like this:

POST https://example.com/features/management
Authorization: Bearer <jwt_issued_to_features.apps.carerix.io_for_given_tenant>
{
  "_kind": "FeatureUpgradeCommand",
  "callbackUrl": "https://api.carerix.io/features/v1/callback",
  "payload": {
    "oldVersion": "1",
    "newVersion": "2",
    "clientCredentials": {
      "backend": {
        "clientId": "partnerservicehash.apps.carerix.io",
        "clientSecret": "s3cr3t"
      }
    },
    "publicClients": {
      "frontend": {
        "clientId": "partneruihash.apps.carerix.io"
      }
    }
  }
}

The request body contains:

1. An event type: "_kind": "FeatureUpgradeCommand" which indicates that feature upgrade was triggered;

2. A URL where to send callbacks in case if vendor goes with the asynchronous implementation;

3. Actual feature upgrade payload:

1. oldVersion containing manifest version the Feature had before upgrade was started;

2. newVersion containing manifest version the Feature was upgraded to;

1. Versions can be equal in case if Marketplace noticed and automatically repaired an inconsistency in IAM setup: created a missing OAuth2Client or updated a misconfigured one;

3. OAuth2Client credentials, i.e. clientId and clientSecret pair, for all confidential clients created as part of this operation;

1. If no confidential clients were created during an upgrade, $.payload.clientCredentials will be empty;

4. clientId for all public clients created as part of this operation;

1. If no public clients were created during an upgrade, $.payload.publicClients property will be absent.

The expected response is the same as for installation: either 200 OK or 202 Accepted HTTP status code. Despite this, Carerix encourages using a synchronous way of feature upgrade handling, i.e. responding with 200 OK.

To prevent unauthorized access to management endpoint, vendor has to check an access token. The rules are the same as with feature installation, please refer to corresponding article section.

Synchronous approach

Responding with 200 OK means that a request was processed synchronously by feature vendor and the Marketplace has just to complete the upgrade by changing the feature status back to activated immediately.

Cleanup

This event occurs when a customer leaves Carerix, his tenant record gets deleted and thus all his features have to be cleaned up as well.

When triggered, Marketplace will invoke a management endpoint provided by the vendor and then delete a Feature record.

The management endpoint request may look like this:

POST https://example.com/features/management
Authorization: Bearer <jwt_issued_to_features.apps.carerix.io_for_master>
{
  "_kind": "FeatureCleanupCommand",
  "callbackUrl": "https://api.carerix.io/features/v1/callback",
  "payload": {
    "tenant": "customerName"
  }
}

The request body contains:

1. An event type: "_kind": "FeatureCleanupCommand" which indicates that feature cleanup was triggered;

2. A URL where to send callbacks;

3. Actual feature cleanup payload:

1. tenant containing an identifier for a tenant for whom cleanup is being done.

The marketplace expects that the management endpoint will respond with either 200 OK or 202 Accepted HTTP status code. A response with any other status code will abort this cleanup attempt. Response body is ignored by the Marketplace.

Unlike all previous management requests, a cleanup one contains a different access token in Authorization header!

This is due to the fact that tenant doesn’t exist in IAM anymore, thus there’s no way to obtain a token for him. Instead, a token for master realm is used.

Use $.payload.tenant request body property to know which tenant was cleaned up.

To prevent unauthorized access to management endpoint, vendor has to check that provided access token satisfies these conditions:

· iss claim contains a valid tenant URL: https://id.carerix.io/auth/realms/master;

· azp claim is equal to features.apps.carerix.io;

· Signature is valid;

· Is not expired.

Now, disregarding whether 200 OK or 202 Accepted will be returned in a response for cleanup management request, Marketplace will consider cleanup as finished and will delete a Feature.

Synchronous approach

Responding with 200 OK means that a request was processed synchronously by feature vendor and the Marketplace has just to complete the cleanup by deleting a Feature immediately.

If a vendor expects decommissioning of tenant resources to take a long time (more than 10 seconds), then cleanup implementation must take the asynchronous approach.

Asynchronous approach

Responding with 202 Accepted means that feature vendor needs some time to handle the request (e.g. drop a database schema, call some other APIs etc), thus cleanup is done in an asynchronous way.

A vendor doesn’t have to call the Marketplace’s callback endpoint to deliver the result of cleanup, as there’s no way to obtain a tenant’s token because a tenant is already deleted.

Settings

Sometimes, a Feature has to be configurable, allowing tenant administrator to specify how it has to behave or pass some sensitive data such as API key to a vendor. Marketplace offers a concept of settings to handle such cases.

If vendor decides that a Feature has to have one or more settings, then:

· they must be declared in the Manifest;

· implementation for “Update” lifecycle event handling must support update of declared settings;

· settings endpoint specified in the manifest must serve settings values stored for a tenant.

Carerix recommends storing sensitive setting values in a secure storage, such as Hashicorp Vault or AWS Secrets Manager.

Usage

Feature settings solve following problems:

· help building a frontend look-and-feel for a user;

· configure a behaviour of Feature’s backend, including sensitive data (e.g. API key).

Thus, besides being stored and used by a service backing a Feature, besides being queried and updated by tenant administrator, settings are also queried by regular tenant users.

After a user is authenticated into Carerix, UI loads a list of manifests and features available for him. But for those features with at least one setting declared, UI will also request the settings values.

Here, Marketplace acts as a proxy between a tenant user and a Feature, validating Feature existence and status as well as user’s permissions. Moreover, Marketplace will filter out from the output all settings with sensitive: true configured, in case if user is not a tenant’s administrator. Thus, sensitive settings are accessible only for tenant’s administrator and a Feature service storing them.

Carerix Marketplace never stores setting values. Rather, it asks a Feature component to get or update them.

Manifest section

Each Feature setting have to be bound to an OAuth2Client declared in the same Manifest - as all settings exist to configure a certain middleware, web application, browser extension etc. Thus, declared settings have to be grouped by serviceId - a map key of an OAuth2Client also declared in a Manifest. Carerix Marketplace supports some common types of settings fields, sensitivity flag and primitive validation.

Here’s an example of settings section of a Manifest describing three setting fields:

manifest:
  id: "partner"
  manifestVersion: 1
  buildInfo:
    settingsUri: "https://example.com/features/settings"
  ...
  settings:
    backend:
      - type: "checkbox"
        code: "schedulerEnabled"
        array: false
        sensitive: false
        required: true
      - type: "singleLineText"
        code: "apiKey"
        array: false
        sensitive: true
        required: true
      - type: "radioGroup"
        code: "autoParsingMode"
        array: false
        required: true
        sensitive: false
        options:
          - code: "eachNewCandidate"
            label: "AutoParsing for each new Candidate"
          - code: "eachNewMatch"
            label: "AutoParsing for each new Match"
          - code: "specificMatchStage"
            label: "AutoParsing on specific Match Stage"
  oauth2:
    backend:
      code: "urn:example/partnerService"
      name: "Example of backend application"
      ...

Specifications for most relevant settings properties are following:

Path relative to setting object property

Type

Description

Example

$.code

string

Unique identifier of a setting per serviceId. It will be used as a property name in API calls when performing operations on a feature settings.

Required, must match following regular expression: [A-Za-z][A-Za-z0-9_\-]{1,31}.

schedulerEnabled

$.type

string

Setting type. Defines what values can be set to a setting and how a setting input will be rendered by the UI.

Required. Please refer to a table below for a list of supported values.

singleLineText

$.sensitive

boolean

Whether setting values are sensitive, which makes them hidden for all users except tenant administrators.

Optional, false by default.

true

$.array

boolean

Whether a setting supports multiple values. Currently can be set to true only if setting type is select.

Optional, false by default.

false

$.required

boolean

Whether tenant administrator has to specify the value for this setting before activating a feature.

Optional, false by default.

false

$.options

array

A list of options for a setting if type is radioGroup.

Optional.

- code: "eachNewCandidate"
  label: "AutoParsing for each new Candidate"
- code: "eachNewMatch"
  label: "AutoParsing for each new Match"

$.options[*].code

string

Code of the option selected for a radioGroup setting. This code will be used in all API calls.

Required.

eachNewCandidate

$.options[*].label

string

Label of the radioGroup option. This label will be shown to tenant’s administrator in the UI.

Required.

AutoParsing for each new Candidate

$.configuration

object

Extra configuration for select setting type.

Optional.

{}

$.configuration.entity

string

Defines what entity records to fetch in order to show in a select box.

Required only for select setting type.

CRStatusInfo

$.configuration.qualifier

string

Defines a qualifier expression to fetch only a subset of entity records to show in a select box.

Optional.

notActive = 0

Here’s a list of supported setting types:

Name

Description

JSON type

singleLineText

A simple text input. Values will be validated to not to contain line breaks.

string

multiLineText

A textarea.

string

checkbox

A simple checkbox with two states: on (true) and off (false).

boolean

radioGroup

A radio group: input where one of the static options can be picked.

string

select

A select box, where available options are dynamically loaded entity references.

object

Settings endpoint

Each feature has to implement a settings endpoint (even if no settings are declared within a Manifest) and its URL has to be specified in $.buildInfo.settingsUri property of a Manifest.

The settings endpoint request will not contain any request body and will look like this:

GET https://example.com/features/settings
Authorization: Bearer <jwt_issued_to_features.apps.carerix.io_for_given_tenant>

To prevent unauthorized access to settings endpoint, vendor has to check an access token. The rules are the same as with feature installation request sent to management endpoint, please refer to corresponding article section.

The marketplace expects that the settings endpoint will respond with 200 OK HTTP status code and a valid JSON in a response body. This JSON has to contain a single settings property which hold all Feature settings grouped by serviceId, e.g.:

{
  "settings": {
    "service1": {
      "code1": "value1",
      "code2": "value2"
    },
    "service2": {
      "code3": "value3"
    }
  }
}

If a Manifest declares no settings, then settings endpoint has to return an empty settings object in a response body, e.g.: { "settings": {} }.

Sensitive settings have to be returned as well, Marketplace will take care of whether such values will be shown or not.

Given the example of Manifest’s settings section provided above, response body returned by the settings endpoint may look like this:

{
  "settings": {
    "backend": {
      "schedulerEnabled": true,
      "apiKey": "s3cr3t_v@lu3",
      "autoParsingMode": "eachNewMatch"
    }
  }
}

Vendor should take into an account that settings endpoint will be queried often if there’s at least one setting defined in a Manifest: each time after a user logs into a system if user’s tenant has this Feature activated.

Therefore, settings endpoint should be able to serve a single API request in less than 500ms.

How to integrate

Here are the steps a vendor has to take in order to successfully integrate with Carerix Marketplace:

1. Find out what OAuth2Client(s) an integration will need, what scopes and permissions should they have;

2. Determine whether a feature has to be configurable by tenant’s administrator and if so, how;

3. Estimate what is needed to start supporting a new customer or off-boarding an existing one:

1. Are there any external API calls to be executed?

2. Is there a separate database or a database schema needed for a tenant?

3. Is there any other long-running operation needed to be done?

4. Compose a manifest providing management&settings URIs, OAuth2Clients configuration from p.1, settings from p.2 and general information about the vendor;

5. Implement a management endpoint supporting all types of lifecycle events: installation, activation, deactivation, update, uninstallation, upgrade and cleanup;

1. If answer for any of the p.3 questions is “Yes”, then implementation for installation, uninstallation and cleanup lifecycle events has to take the asynchronous approach;

2. Otherwise, all events have to be handled in synchronous way;

6. Implement a settings endpoint;

1. Even if a feature doesn’t declare any settings, implementation is needed, but in that case it’s enough to just return a JSON object with empty settings property.

Feel free to contact Carerix if any help is needed with Manifest creation or any other part of an integration.

Restricting access

Marketplace has a mechanism allowing to configure a Feature access:

· make it public, so any tenant can install and activate one;

· allow it to be installable only by a selected group of tenants (whitelist);

· allow it to be installable by any tenant except a selected group (blacklist).

This is particularly useful when a Feature is not yet ready to be released, instead undergoes development or testing on selected “dev” or “internal” systems.

Access restriction is controlled by Carerix and not by a Manifest file. Therefore, a tenant whitelist has to be defined before any integration implementation starts.

Did this answer your question?