Skip to content
This repository was archived by the owner on Aug 15, 2025. It is now read-only.

Services and Discoverability #41

Merged
merged 11 commits into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions docs/APIs/core/Routes: No registration needed.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,152 @@ Invalidate a session token by naming the session ID associated with it.

---

## <span class="group-h">Services</span>

Routes concerned with the "Services" and "Discoverability" sections of the core polyproto specification.

---

### <span clas="request-h"><span class="request request-get">GET</span> Discover services of actor</span>

`.p2/core/v1/services/discover/:fid`

Fetch a list of all services that the actor has made discoverable. Clients should not expect
this list to be ordered in any particular way.

#### Request

##### Parameters

| Name | Type | Description |
| ----- | --------------------- | -------------------------------------------------------- |
| `fid` | String, Federation ID | The ID of the actor whose services should be returned. |

##### Body

| Name | Type | Description |
| ----- | ---------------- | ----------------------------------------- |
| limit | Unsigned Integer | The maximum number of services to return. |

The body is optional. Not specifying a limit will return all services.

```json
{
"limit": 5
}
```

#### Response

=== "200 OK"

##### Body

JSON array of [service objects](./Types/service.md). A list of all services which the actor has
made discoverable.

```json
[
{
"service": "example-service",
"url": "https://example.com/",
"primary": true
}
]
```

=== "204 No Content"

Returned, if the actor has not made any services discoverable.

##### Body

This response has no body.

=== "404 Not Found"

Returned, if the specified actor does not exist.

##### Body

This response has no body.

---

### <span clas="request-h"><span class="request request-post">GET</span> Discover single service of actor</span>

`.p2/core/v1/services/discover/:fid/:service`

Get all service providers an actor is registered with, limited to a specific service.
Clients should not expect this list to be ordered in any particular way.

#### Request

##### Parameters

| Name | Type | Description |
| --------- | --------------------- | ------------------------------------------------------------------ |
| `fid` | String, Federation ID | The ID of the actor whose discoverable entries should be returned. |

##### Body

| Name | Type | Description | Required? |
| ------- | ---------------- | ----------------------------------------- | --------- |
| `limit` | Unsigned Integer | The maximum number of services to return. | No |
| `name` | String | The service name to filter the query by. | Yes |

Not specifying a limit will return all services. Specifying a limit value of `1` will return
only the primary service provider.

```json
{
"limit": 5,
"name": "example-service"
}
```

#### Response

=== "200 OK"

##### Body

JSON array of [service objects](./Types/service.md), filtered by the specified service. Will
be an array, regardless of the `only_primary` parameter.

```json
[
{
"service": "example-service",
"url": "https://example.com/",
"primary": true
},
{
"service": "example-service",
"url": "https://other.example.com/",
"primary": false
}
]
```

=== "204 No Content"

Returned, if there are no discoverable entries for the specified service.

##### Body

This response has no body.

=== "404 Not Found"

Returned, if the specified actor does not exist.

##### Body

This response has no body.

---

## <span class="group-h">Other</span>

Routes not fitting into another category.
Expand Down
168 changes: 168 additions & 0 deletions docs/APIs/core/Routes: Registration needed.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,174 @@ Retrieve the maximum upload size for encrypted private key material, in bytes.

---

## <span class="group-h">Services</span>

Routes concerned with the "Services" and "Discoverability" sections of the core polyproto specification.

---

### <span clas="request-h"><span class="request request-post">POST</span> Add service to be discovered [:material-lock-outline:](#authorization "Authorization required")</span>

`/.p2/core/v1/services`

Add a service to the list of services discoverable by other actors.

#### Request

##### Body

A singular [service](./Types/service.md) object, representing the service that was added.

```json
{
"service": "example-service",
"url": "https://example.com",
"primary": false
}
```

#### Response

=== "201 Created"

##### Body

##### Body

An array of at minimum one, and at maximum 2 [service](./Types/service.md) objects.

```json
[
{
"service": "example-service",
"url": "https://example.com",
"primary": false
},
{
"service": "example-service",
"url": "https://other.example.com",
"primary": true
}
]
```

The response will contain the updated previous primary service provider, if there was one, along
with the new primary service provider.

=== "409 Conflict"

Returned, if the service and URL combination already exists in the list of discoverable services.

##### Body

This response has no body.

---

### <span clas="request-h"><span class="request request-delete">DELETE</span> Delete discoverable service [:material-lock-outline:](#authorization "Authorization required")</span>

`/.p2/core/v1/services`

Remove a service from the list of services discoverable by other actors.

#### Request

##### Body

| Name | Type | Description |
| --------- | ----------- | ------------------------------------------------------------- |
| `url` | String, URL | The base URL of the service to be removed. |
| `name` | String | The service namespace for which the service is being removed. |

```json
{
"url": "https://example.com",
"name": "example-service"
}
```

#### Response

=== "200 OK"

##### Body

| Name | Type | Description | Required? |
| ------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| `deleted` | Object, [Service](./Types/service.md) | The service that was removed. | Yes |
| `new_primary` | Object, [Service](./Types/service.md) | The new primary service provider, if the removed service was the primary service provider, and there are other service providers available. | No |

```json
{
"url": "https://example.com"
}
```

`new_primary` will be omitted, if the removed service was not the primary service provider or if
there are no other service providers available for this service namespace.

=== "404 Not Found"

Returned, if the service URL does not exist in the list of discoverable services.

##### Body

This response has no body.

---

### <span clas="request-h"><span class="request request-put">PUT</span> Set primary service provider [:material-lock-outline:](#authorization "Authorization required") :material-eye-lock-outline:{title="This route is considered a sensitive action."}</span>

`/.p2/core/v1/services/primary`

Set a primary service provider for a given service namespace. This is used to indicate, which service
provider should be used by default by other actors, when multiple service providers are available
for a given service namespace.

#### Request

##### Body

| Name | Type | Description |
| ------ | ----------- | -------------------------------------------------------------------------- |
| `url` | String, URL | The base URL of the service to be set as the primary service provider. |
| `name` | String | The service namespace for which the primary service provider is being set. |

```json
{
"url": "https://example.com",
"name": "example-service"
}
```

#### Response

=== "200 OK"

##### Body

An array of at minimum one, and at maximum 2 [service](./Types/service.md) objects.

```json
[
{
"service": "example-service",
"url": "https://example.com",
"primary": false
},
{
"service": "example-service",
"url": "https://other.example.com",
"primary": true
}
]
```

The response will contain the updated previous primary service provider, if there was one, along
with the new primary service provider.

---

TODO: Add routes concerned with account and data migration.

---
Expand Down
33 changes: 33 additions & 0 deletions docs/APIs/core/Types/service.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Service

A resource representing information about a discoverable service for an actor. You can learn more about
services and discoverability by reading [section #9](/Protocol Specifications/core#9-services) of
the core protocol specification.

This resource contains information about the name of the service that is being made discoverable,
the URL of the service provider, and whether this service provider is the primary service provider
for the actor.

## JSON representation

```json
{
"service": "example-service",
"url": "https://example.com/",
"primary": true
}
```

### Fields

| Field | Type | Description |
| --------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `service` | String | The name of the service that is being made discoverable. Must be formatted according to [section #8.2: Namespaces](/Protocol Specifications/core#82-namespaces) in the core protocol specification |
| `url` | String, URL | The base URL of the service provider, not including `/.p2/<service_name>`. Trailing slashes are allowed. If `(/).p2/<service_name>` is added to the URL specified here, a polyproto client should be able to access the HTTP API routes provided by the service. |
| `primary` | Boolean | Whether the service provider specified in the `url` field is the primary service provider for this service and actor. |

All fields are required.

## Glossary

--8<-- "snippets/glossary.md"
3 changes: 2 additions & 1 deletion docs/Protocol Specifications/core.md
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,8 @@ more comprehensive set of features.

A namespace is a string used to identify a specific P2 extension. Used as a prefix in URLs, they
prevent route name collisions between different extensions. Namespaces should be unique
and descriptive. They should only contain lowercase letters, numbers, hyphens, and underscores.
and descriptive. They must only contain lowercase letters, numbers, hyphens, and underscores.
Namespaces must be at least 2 characters long and at most 64 characters long.

Officially endorsed P2 extensions have priority over selecting namespaces. If a namespace is already
taken by an officially endorsed extension, a different namespace must be chosen. If a namespace
Expand Down
Loading