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

Commit 8059443

Browse files
authored
Merge pull request #41 from polyphony-chat/services-discoverability
Services and Discoverability
2 parents cbaa436 + f1b6e81 commit 8059443

File tree

4 files changed

+349
-1
lines changed

4 files changed

+349
-1
lines changed

docs/APIs/core/Routes: No registration needed.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,152 @@ Invalidate a session token by naming the session ID associated with it.
282282

283283
---
284284

285+
## <span class="group-h">Services</span>
286+
287+
Routes concerned with the "Services" and "Discoverability" sections of the core polyproto specification.
288+
289+
---
290+
291+
### <span clas="request-h"><span class="request request-get">GET</span> Discover services of actor</span>
292+
293+
`.p2/core/v1/services/discover/:fid`
294+
295+
Fetch a list of all services that the actor has made discoverable. Clients should not expect
296+
this list to be ordered in any particular way.
297+
298+
#### Request
299+
300+
##### Parameters
301+
302+
| Name | Type | Description |
303+
| ----- | --------------------- | -------------------------------------------------------- |
304+
| `fid` | String, Federation ID | The ID of the actor whose services should be returned. |
305+
306+
##### Body
307+
308+
| Name | Type | Description |
309+
| ----- | ---------------- | ----------------------------------------- |
310+
| limit | Unsigned Integer | The maximum number of services to return. |
311+
312+
The body is optional. Not specifying a limit will return all services.
313+
314+
```json
315+
{
316+
"limit": 5
317+
}
318+
```
319+
320+
#### Response
321+
322+
=== "200 OK"
323+
324+
##### Body
325+
326+
JSON array of [service objects](./Types/service.md). A list of all services which the actor has
327+
made discoverable.
328+
329+
```json
330+
[
331+
{
332+
"service": "example-service",
333+
"url": "https://example.com/",
334+
"primary": true
335+
}
336+
]
337+
```
338+
339+
=== "204 No Content"
340+
341+
Returned, if the actor has not made any services discoverable.
342+
343+
##### Body
344+
345+
This response has no body.
346+
347+
=== "404 Not Found"
348+
349+
Returned, if the specified actor does not exist.
350+
351+
##### Body
352+
353+
This response has no body.
354+
355+
---
356+
357+
### <span clas="request-h"><span class="request request-post">GET</span> Discover single service of actor</span>
358+
359+
`.p2/core/v1/services/discover/:fid/:service`
360+
361+
Get all service providers an actor is registered with, limited to a specific service.
362+
Clients should not expect this list to be ordered in any particular way.
363+
364+
#### Request
365+
366+
##### Parameters
367+
368+
| Name | Type | Description |
369+
| --------- | --------------------- | ------------------------------------------------------------------ |
370+
| `fid` | String, Federation ID | The ID of the actor whose discoverable entries should be returned. |
371+
372+
##### Body
373+
374+
| Name | Type | Description | Required? |
375+
| ------- | ---------------- | ----------------------------------------- | --------- |
376+
| `limit` | Unsigned Integer | The maximum number of services to return. | No |
377+
| `name` | String | The service name to filter the query by. | Yes |
378+
379+
Not specifying a limit will return all services. Specifying a limit value of `1` will return
380+
only the primary service provider.
381+
382+
```json
383+
{
384+
"limit": 5,
385+
"name": "example-service"
386+
}
387+
```
388+
389+
#### Response
390+
391+
=== "200 OK"
392+
393+
##### Body
394+
395+
JSON array of [service objects](./Types/service.md), filtered by the specified service. Will
396+
be an array, regardless of the `only_primary` parameter.
397+
398+
```json
399+
[
400+
{
401+
"service": "example-service",
402+
"url": "https://example.com/",
403+
"primary": true
404+
},
405+
{
406+
"service": "example-service",
407+
"url": "https://other.example.com/",
408+
"primary": false
409+
}
410+
]
411+
```
412+
413+
=== "204 No Content"
414+
415+
Returned, if there are no discoverable entries for the specified service.
416+
417+
##### Body
418+
419+
This response has no body.
420+
421+
=== "404 Not Found"
422+
423+
Returned, if the specified actor does not exist.
424+
425+
##### Body
426+
427+
This response has no body.
428+
429+
---
430+
285431
## <span class="group-h">Other</span>
286432

287433
Routes not fitting into another category.

docs/APIs/core/Routes: Registration needed.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,174 @@ Retrieve the maximum upload size for encrypted private key material, in bytes.
253253

254254
---
255255

256+
## <span class="group-h">Services</span>
257+
258+
Routes concerned with the "Services" and "Discoverability" sections of the core polyproto specification.
259+
260+
---
261+
262+
### <span clas="request-h"><span class="request request-post">POST</span> Add service to be discovered [:material-lock-outline:](#authorization "Authorization required")</span>
263+
264+
`/.p2/core/v1/services`
265+
266+
Add a service to the list of services discoverable by other actors.
267+
268+
#### Request
269+
270+
##### Body
271+
272+
A singular [service](./Types/service.md) object, representing the service that was added.
273+
274+
```json
275+
{
276+
"service": "example-service",
277+
"url": "https://example.com",
278+
"primary": false
279+
}
280+
```
281+
282+
#### Response
283+
284+
=== "201 Created"
285+
286+
##### Body
287+
288+
##### Body
289+
290+
An array of at minimum one, and at maximum 2 [service](./Types/service.md) objects.
291+
292+
```json
293+
[
294+
{
295+
"service": "example-service",
296+
"url": "https://example.com",
297+
"primary": false
298+
},
299+
{
300+
"service": "example-service",
301+
"url": "https://other.example.com",
302+
"primary": true
303+
}
304+
]
305+
```
306+
307+
The response will contain the updated previous primary service provider, if there was one, along
308+
with the new primary service provider.
309+
310+
=== "409 Conflict"
311+
312+
Returned, if the service and URL combination already exists in the list of discoverable services.
313+
314+
##### Body
315+
316+
This response has no body.
317+
318+
---
319+
320+
### <span clas="request-h"><span class="request request-delete">DELETE</span> Delete discoverable service [:material-lock-outline:](#authorization "Authorization required")</span>
321+
322+
`/.p2/core/v1/services`
323+
324+
Remove a service from the list of services discoverable by other actors.
325+
326+
#### Request
327+
328+
##### Body
329+
330+
| Name | Type | Description |
331+
| --------- | ----------- | ------------------------------------------------------------- |
332+
| `url` | String, URL | The base URL of the service to be removed. |
333+
| `name` | String | The service namespace for which the service is being removed. |
334+
335+
```json
336+
{
337+
"url": "https://example.com",
338+
"name": "example-service"
339+
}
340+
```
341+
342+
#### Response
343+
344+
=== "200 OK"
345+
346+
##### Body
347+
348+
| Name | Type | Description | Required? |
349+
| ------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
350+
| `deleted` | Object, [Service](./Types/service.md) | The service that was removed. | Yes |
351+
| `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 |
352+
353+
```json
354+
{
355+
"url": "https://example.com"
356+
}
357+
```
358+
359+
`new_primary` will be omitted, if the removed service was not the primary service provider or if
360+
there are no other service providers available for this service namespace.
361+
362+
=== "404 Not Found"
363+
364+
Returned, if the service URL does not exist in the list of discoverable services.
365+
366+
##### Body
367+
368+
This response has no body.
369+
370+
---
371+
372+
### <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>
373+
374+
`/.p2/core/v1/services/primary`
375+
376+
Set a primary service provider for a given service namespace. This is used to indicate, which service
377+
provider should be used by default by other actors, when multiple service providers are available
378+
for a given service namespace.
379+
380+
#### Request
381+
382+
##### Body
383+
384+
| Name | Type | Description |
385+
| ------ | ----------- | -------------------------------------------------------------------------- |
386+
| `url` | String, URL | The base URL of the service to be set as the primary service provider. |
387+
| `name` | String | The service namespace for which the primary service provider is being set. |
388+
389+
```json
390+
{
391+
"url": "https://example.com",
392+
"name": "example-service"
393+
}
394+
```
395+
396+
#### Response
397+
398+
=== "200 OK"
399+
400+
##### Body
401+
402+
An array of at minimum one, and at maximum 2 [service](./Types/service.md) objects.
403+
404+
```json
405+
[
406+
{
407+
"service": "example-service",
408+
"url": "https://example.com",
409+
"primary": false
410+
},
411+
{
412+
"service": "example-service",
413+
"url": "https://other.example.com",
414+
"primary": true
415+
}
416+
]
417+
```
418+
419+
The response will contain the updated previous primary service provider, if there was one, along
420+
with the new primary service provider.
421+
422+
---
423+
256424
TODO: Add routes concerned with account and data migration.
257425

258426
---

docs/APIs/core/Types/service.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Service
2+
3+
A resource representing information about a discoverable service for an actor. You can learn more about
4+
services and discoverability by reading [section #9](/Protocol Specifications/core#9-services) of
5+
the core protocol specification.
6+
7+
This resource contains information about the name of the service that is being made discoverable,
8+
the URL of the service provider, and whether this service provider is the primary service provider
9+
for the actor.
10+
11+
## JSON representation
12+
13+
```json
14+
{
15+
"service": "example-service",
16+
"url": "https://example.com/",
17+
"primary": true
18+
}
19+
```
20+
21+
### Fields
22+
23+
| Field | Type | Description |
24+
| --------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
25+
| `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 |
26+
| `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. |
27+
| `primary` | Boolean | Whether the service provider specified in the `url` field is the primary service provider for this service and actor. |
28+
29+
All fields are required.
30+
31+
## Glossary
32+
33+
--8<-- "snippets/glossary.md"

docs/Protocol Specifications/core.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1170,7 +1170,8 @@ more comprehensive set of features.
11701170

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

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

0 commit comments

Comments
 (0)