Skip to content

Commit

Permalink
Cleanup + openapi descriptor for the internal API
Browse files Browse the repository at this point in the history
  • Loading branch information
achouippe committed Jul 23, 2024
1 parent a8dedeb commit 4cd47f9
Show file tree
Hide file tree
Showing 2 changed files with 249 additions and 1 deletion.
248 changes: 248 additions & 0 deletions neurow/priv/internal_api_v1_openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
openapi: 3.0.3
info:
title: Neurow Internal API
version: '1.0'
description: |
The Neurow internal API is in charge of receiving messages sent by backends and to push them to frontends that subsribed to them.
It for now provides one single resource: `POST /publish`.
## Authentication
For authentication, the internal API expects a JWT passed in the `authorization` request header as a Bearer Token:
`Authorization: Bearer <JWT>`
The expected properties of this JWT token are:
- Signature algorithm: "HS256", for now only this symmetric algorithm is supported, an asymmetric algorithms like RS256
will be supported later.
- Required claims:
- "aud": Must be equal to the value configured by `internal_api_authentication.audience` in `runtime.exs`
- "iss": Must equal the name of an issuer configured by `internal_api_authentication.issuers` in `runtime.exs`
- "iat": Must be in the past,
- "exp": Defines a lifetime for the token that cannot be higher than the max lifetime defined by `internal_api_jwt_max_lifetime` in `runtime.exs`
For testing purposes, JWT token can be generated with the following mix task:
```
mix generate_jwt_token --api=internal --issuer=<issuer_name>
```
## Publishing messages
A message is defined by a type and a text payload:
```json
{
"type": "hello",
"payload": "Hello world !"
}
```
A message can be published to one or multiple topics. To receive messages, frontends need to open a SSE connection on the public API
and to subsribe to the topic where messages were sent.
All topics are automatically namespaced by the issuer defined in the JWT used to authenticate to the internal API and the public API.
For example, if a backend publish a message using the internal API with a JWT with the issuer "my_backend_1", to receive its messages, the frontend
must authenticate with an JWT with the issuer "my_backend_1".
This way of isolating issuers allows the usage of the same Neurow cluster from multiple backends without any risk of collision of between message types,
and by preventing the security risk of having a frontend that subscribes to messages sent by another backends.
Messages are published by sending a JSON payload with a POST on `/subscribe`:
```json
{
"topic": "user:123",
"message": {
"type": "hello",
"payload": "Hello world !"
}
}
```
A message can be posted to one single topic, or posted to multiple topics with one single call to the `/publish` resource. Just pass the list
of topics as an array:
```json
{
"topics": ["user:123", "user:456"]
"message": {
"type": "hello",
"payload": "Hello world !"
}
}
```
It also possible to publish multiple messages in one HTTP call to `/publish`. Just pass an array of messages:
```json
{
"topics": ["user:123", "user:456"]
"messages": [
{
"type": "hello",
"payload": "Hello world !"
},
{
"type": "welcome",
"payload": "Welcome on Neurow"
}
]
}
```
Here, the two messages are published on two topics.
In response, the internal API return a simple JSON response with the number of message publications:
```json
{"nb_published": 4}
```
## Timestamping
By default, messages are timestamped with timestamps generated by the internal API when it receives messages.
Message timestamps are forwarded to frontend and can be used in the frontend to decide how to react messages from Neurow
it is has a newer version of the impacted data.
The internal API also allow to define a timestamp (in milliseconds) for each published message:
```json
{
"type": "hello",
"payload": "Hello world !",
"timestamp": 1516239022123
}
```
This timestamp is also used for messages retentions.
## Error management
All errors are described as JSON responses. On errors, the internal API returns an array of errors:
```json
{
errors: [
{"error_code": "code1", "error_message": "Description message 1"},
{"error_code": "code2", "error_message": "Description message 2"},
]
}
```
Error codes are stable and can be used for error management in the system that call the internal API. Error messages give
more detailed about the problem and are
provided for investigation, they should not be used to implement error management in the system that calls the internal API.
servers:
- url: http://localhost:3000/v1
description: Default local development environment whe Neurow is started locally

paths:
/publish:
post:
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PublishRequest'
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/PublishResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/StandardError'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/StandardError'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
StandardError:
type: object
description: Common structure for all errors. All errors are described with this data structured
properties:
errors:
type: array
items:
type: object
properties:
error_code:
description: Error codes are stable and can be used for error management in the system that call the internal API
type: string
error_message:
description: Error messages give more detailed about the problem and are provided for investigation
type: string
required:
- error_code
- error_message

PublishResponse:
description: Response returned by the /publish resurce
type: object
required:
- nb_published
properties:
nb_published:
description: Number of messages that was published in Neurow
type: integer

PublishRequest:
type: object
allOf:
- oneOf:
- required:
- topic
properties:
topic:
type: string
description: Name of the topic where messages are published
- required:
- topics
properties:
topics:
type: array
description: List of topic names where messages are published
items:
type: string
- oneOf:
- required:
- message
properties:
message:
$ref: '#/components/schemas/Message'
- required:
- messages
properties:
messages:
type: array
items:
$ref: '#/components/schemas/Message'
Message:
type: object
required:
- type
- payload
properties:
type:
type: string
payload:
type: object
timestamp:
type: integer





2 changes: 1 addition & 1 deletion neurow/test/neurow/internal_api/endpoint_test.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Neurow.InternalApiUnitTest do
defmodule Neurow.InternalApi.EndpointTest do
use ExUnit.Case
use Plug.Test
import JwtHelper
Expand Down

0 comments on commit 4cd47f9

Please sign in to comment.