# Discovery

The `@joystream/service-discovery` package provides an API for role services to publish
discovery information about themselves, and for consumers to resolve this
information.

In the Joystream network, services are provided by having members stake for a
role. The role is identified by a worker id. Resolving service information
associated with the worker id is the main purpose of this module.

This implementation is based on [IPNS](https://docs.ipfs.io/guides/concepts/ipns/)
as well as runtime information.

## Discovery Workflow

The discovery workflow provides worker id to the `discover()` function, which
will eventually return structured data.

Under the hood, `discover()` the bootstrap nodes from the runtime are
used in a browser environment, or the local ipfs node otherwise.

There is a distinction in the discovery workflow:

1. If run in the browser environment, a HTTP request to a participating node
   is performed to discover nodes.
2. If run in a node.js process, instead:

- A trusted (local) IPFS node must be configured.
- The chain is queried to resolve a worker id to an IPNS id.
- The trusted IPFS node is used to resolve the IPNS id to an IPFS
  file.
- The IPFS file is fetched; this contains the structured data.

Web services providing the HTTP endpoint used in the first approach will
themselves use the second approach for fulfilling queries.

## Publishing Workflow

The publishing workflow is a little more involved, and requires more interaction
with the runtime and the trusted IPFS node.

1. A service information file is created.
1. The file is published on IPFS, using the IPNS self key of the local node.
1. The IPNS name of the trusted IPFS node is updated to refer to the published
   file.
1. The runtime mapping from the worker ID to the IPNS name is updated.

## Published Information

Any JSON data can theoretically be published with this system; however, the
following structure is currently imposed:

- The JSON must be an Object at the top-level, not an Array.
- Each key must correspond to a [service spec](../../docs/json-signing/README.md).

## Service Info Specifications

Service specifications are JSON Objects, not Arrays. All service specifications
come with their own `version` field which should be intepreted by clients making
use of the information.

Additionally, some services may only provide an `endpoint` value, as defined
here:

- `version`: A numeric version identifier for the service info field.
- `endpoint`: A publicly accessible base URL for a service API.

The `endpoint` should include a scheme and full authority, such that appending
`swagger.json` to the path resolves the OpenAPI definition of the API served
at this endpoint.

The OpenAPI definition must include a top level path component corresponding
to the service name, followed by an API version component. The remainder of the
provided paths are dependent on the specific version of the API provided.

For example, for an endpoint value of `https://user:password@host:port/` the
following must hold:

- `https://user:password@host:port/swagger.json` resolves to the OpenAPI
  definition of the API(s) provided by this endpoint.
- The OpenAPI definitions include paths prefixed by
  `https://user:password@host:port/XXX/vYYY` where
  - `XXX` is the service name, identical to the field name of the service spec
    in the published service information.
  - `YYY` the version identifier for the published service API.

**Note:** The `version` field in the spec indicates the version of the spec.
The `YYY` path component above indicates the version of the published OpenAPI.

### Discovery Service

Publishes `version` and `endpoint` as above; the `version` field is currently
always `1`.

### Asset Service

Publishes `version` and `endpoint` as above; the `version` field is currently
always `1`.

### Example

```json
{
  "asset": {
    "version": 1,
    "endpoint": "https://foo.bar/"
  },
  "discovery": {
    "version": 1,
    "endpoint": "http://quux.io/"
  }
}
```

Here, the following must be true:

- `https://foo.bar/swagger.json` must include paths beginning with `https://foo.bar/asset/vXXX`
  where `XXX` is the API version of the asset API.
- `https://quux.io/swagger.json` must include paths beginning with `https://foo.bar/discovery/vYYY`
  where `XXX` is the API version of the asset API.