Some checks failed
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Has been cancelled
joule-code conformance gate / joule-moq-relay, every target (pull_request) Has been cancelled
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (pull_request) Has been cancelled
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Has been cancelled
joule-moq-remote host agent / joule-moq-remote · does this change touch it (pull_request) Has been cancelled
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (pull_request) Has been cancelled
joule-moq-remote host agent / joule-moq-remote, every target (macos) (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
wai-app and Create / wai-app · does this change touch it (pull_request) Has been cancelled
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (pull_request) Has been cancelled
wai-app and Create / wai-app · Create, browser end-to-end (macos) (pull_request) Has been cancelled
wai-audit collector and player integration / does this change touch it (pull_request) Has been cancelled
wai-audit collector and player integration / collector · linux (pull_request) Has been cancelled
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Has been cancelled
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (pull_request) Has been cancelled
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (pull_request) Has been cancelled
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (pull_request) Has been cancelled
WAI operation catalogue / does this change touch it (pull_request) Has been cancelled
WAI operation catalogue / the catalogue and every door · linux (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / fast integer kernels, every x86_64 kernel set (AVX-512 silicon) (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / faces from keypoints under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
WAI energy receipts / does this change touch it (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI examples / WAI examples · does this change touch them (pull_request) Has been cancelled
WAI examples / WAI examples · portable · linux (pull_request) Has been cancelled
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Has been cancelled
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Has been cancelled
WAI HTTP delivery / WAI HTTP · does this change touch it (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Has been cancelled
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Has been cancelled
wai-key-proxy / does this change touch it (pull_request) Has been cancelled
wai-key-proxy / proxy · linux (pull_request) Has been cancelled
wai-ledger service / does this change touch it (pull_request) Has been cancelled
wai-ledger service / service · linux (pull_request) Has been cancelled
wai-ledger service / service · macos (pull_request) Has been cancelled
WAI neural sink gates / does this change touch it (pull_request) Has been cancelled
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Has been cancelled
wai-pack / wai-pack · does this change touch it (pull_request) Has been cancelled
wai-pack / wai-pack · linux (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · macos (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
wai-quantum studio and desktop / does this change touch it (pull_request) Has been cancelled
wai-quantum studio and desktop / studio · browser (pull_request) Has been cancelled
wai-quantum studio and desktop / desktop app · macos (pull_request) Has been cancelled
wai-quantum WebGPU member / does this change touch it (pull_request) Has been cancelled
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Has been cancelled
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Has been cancelled
wai-sink-android native sink library / does this change touch it (pull_request) Has been cancelled
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Has been cancelled
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Has been cancelled
wai-sink-swift native sink package / does this change touch it (pull_request) Has been cancelled
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Has been cancelled
WAI mbt2018_mean integer decode (regenerated vectors) / does this change touch it (pull_request) Has been cancelled
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Has been cancelled
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Has been cancelled
wai-web wasm32 / does this change touch it (pull_request) Has been cancelled
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been cancelled
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Has been cancelled
Merged #508 (wai/create-2, stacked on #505) before they reach main, as the coordinator directs: they merge before this branch, which builds the catalogue over them. - The catalogue holds every operation they add: mcp.start (wai mcp; it was agent.mcp), agent.setup, app.guide, app.check, app.export (wai app export, also wai create --from), app.stream, registry.show, docs.search, dev.stop, room.join, room.leave, session.show (it was room.session), and the room service's 40 operations at their routes. - Renamed to the verb rule: the MCP tool package_build is envelope_wrap (it does what wai wrap does; package.build stays for real packaging); the room service's challenges are watch.setup, conversation.setup and call.setup (no compound nouns); in the OpenAPI document, its contract test, the MCP table and tests, the docs. - wai::ops is folded into wai::catalogue: the tool table's tests hold it to the catalogue both ways (every tool an operation the catalogue says wai mcp serves, in its toolset, and every such operation a tool; a tool of MCP alone takes the catalogue's input), and the room service's contract test holds its OpenAPI the same way. - wai setup-agent and wai app check answer in the one envelope (wai: envelope/1, data), JSON with --json; wai mcp and setup-agent take --dry-run through the door; the binaries wai-relay and wai-room in the MCP dev room and Create's end-to-end script. Co-Authored-By: Claude Opus 5.5 <[email protected]>
3838 lines
113 KiB
JSON
3838 lines
113 KiB
JSON
{
|
|
"openapi": "3.1.0",
|
|
"info": {
|
|
"title": "WAI room service",
|
|
"version": "0.1.0",
|
|
"license": {
|
|
"name": "Apache-2.0",
|
|
"identifier": "Apache-2.0"
|
|
},
|
|
"description": "The HTTP API of the room service (`joule-moq-room`), which keeps WAI live rooms (`wai/extensions/live-rooms.md`) over a relay: it issues grants, authors each room's lifecycle on its clock's events track, and serves the signed room. A configuration turns on the modes a room keeps: end-to-end encryption (`[room] e2ee`), admission by age (`[age]`), co-performance (`[co]`), a watch room (`[room] watch_source`), a remote desktop room (`[remote]`), a conversation (`[messaging]`) or calls (`[call]`). Each mode's paths answer 404 in a service that does not keep it.\n\nEvery answer but a watch room's source is JSON with `Cache-Control: no-store`. Each operation's `operationId` is its name in the WAI toolchain's catalogue, `noun.verb` (`room.grant`), the name every other door derives its own from: the MCP tool `room_grant`, the command `wai room grant`. A path answers 405 to a method it does not take (`/msg/*` and `/call/*` paths answer 404). The statuses listed for each operation are those its handler can return; `tests/openapi_contract.rs` holds this description to the service, route by route and status by status.\n\nRequests that a principal authorises carry its grant as `Authorization: Bearer <the grant's record in base64url>` and a proof of possession of the grant's key in `WAI-Room-Proof`, made over a challenge the service issued in `WAI-Room-Challenge` (live-rooms §10.5.3); a request that proves only a key carries the proof alone, naming no grant. The service listens on loopback behind a front that serves it under `public_prefix`; a proof names the path the client addressed."
|
|
},
|
|
"servers": [
|
|
{
|
|
"url": "http://127.0.0.1:9682",
|
|
"description": "the example configuration's address (`room.example.toml`)"
|
|
},
|
|
{
|
|
"url": "http://127.0.0.1:8080/room-api",
|
|
"description": "the service behind `wai dev`'s front, on its default port"
|
|
}
|
|
],
|
|
"tags": [
|
|
{
|
|
"name": "room",
|
|
"description": "every room"
|
|
},
|
|
{
|
|
"name": "age",
|
|
"description": "admission by age (age-assurance §5.6)"
|
|
},
|
|
{
|
|
"name": "e2ee",
|
|
"description": "end-to-end encrypted rooms (confidentiality)"
|
|
},
|
|
{
|
|
"name": "co-performance",
|
|
"description": "co-performance"
|
|
},
|
|
{
|
|
"name": "watch",
|
|
"description": "watch rooms (co-watch)"
|
|
},
|
|
{
|
|
"name": "remote",
|
|
"description": "remote desktop rooms (remote-desktop)"
|
|
},
|
|
{
|
|
"name": "messaging",
|
|
"description": "a conversation (live-messaging)"
|
|
},
|
|
{
|
|
"name": "calls",
|
|
"description": "calls (live-messaging §10)"
|
|
}
|
|
],
|
|
"paths": {
|
|
"/": {
|
|
"get": {
|
|
"operationId": "service.show",
|
|
"tags": [
|
|
"room"
|
|
],
|
|
"summary": "The service's health",
|
|
"description": "As `GET /health`.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"relay": {
|
|
"type": "boolean",
|
|
"description": "the clock's session on the relay is open"
|
|
},
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"relay",
|
|
"room"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/health": {
|
|
"get": {
|
|
"operationId": "service.check",
|
|
"tags": [
|
|
"room"
|
|
],
|
|
"summary": "The service's health",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"relay": {
|
|
"type": "boolean",
|
|
"description": "the clock's session on the relay is open"
|
|
},
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"relay",
|
|
"room"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/room": {
|
|
"get": {
|
|
"operationId": "room.show",
|
|
"tags": [
|
|
"room"
|
|
],
|
|
"summary": "The current room",
|
|
"description": "The room a page verifies before it enters (live-rooms §9): its id, `t0_us`, the signed descriptor and composition descriptor, the publishers' grants, how many publish and may, and the record of each mode the room keeps (end-to-end encryption, remote desktop, admission by age, co-performance, watch, shared world), with the service's clock in `now_us`.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Room"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/grant": {
|
|
"post": {
|
|
"operationId": "room.grant",
|
|
"tags": [
|
|
"room"
|
|
],
|
|
"summary": "A grant for a key",
|
|
"description": "A short-lived WRG1 grant for the key, which a relay honours only beside a proof of possession made with that key (live-rooms §10.5). The body is at most 1 KiB. In a room that admits by age the request carries `Authorization: PrivateToken token=\"…\"` (RFC 9577): without one the answer is 401 with a `WWW-Authenticate: PrivateToken` challenge for each key of the room's policy. A call room's grants come with its call (`/call/place`, `/call/answer`): there it is 403.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"principal": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"role": {
|
|
"type": "string",
|
|
"enum": [
|
|
"publisher",
|
|
"viewer",
|
|
"host",
|
|
"controller"
|
|
],
|
|
"description": "publisher or viewer; in a remote desktop room host, controller or viewer"
|
|
},
|
|
"ai": {
|
|
"$ref": "#/components/schemas/Hex32",
|
|
"description": "a publisher's, in a room with co-performance that takes AI participants: the digest of the model that acts for it (live-rooms §4.4)"
|
|
},
|
|
"invitation": {
|
|
"type": "string",
|
|
"description": "a remote desktop room's host without a configured key: an invitation the room's authority signed"
|
|
}
|
|
},
|
|
"required": [
|
|
"principal",
|
|
"role"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/GrantAnswer"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "a room that admits by age, and no token: `{\"error\": \"token_required\", \"age\"}` with its challenges",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "a token refused (age-assurance §11's reason), a remote desktop room's host or controller refused (`not_the_host`, `invitation_required`, `invitation_used`, `invitation_expired`, `invitation_bad_signature`, `control_not_allowed`), or a call room",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "`full` (the room has its publishers), `busy` (it has taken its grants), or `hosted` (a remote room's host holds its place)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "past the client's rate: retry after retry_after_s",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "`relay`: the clock's session on the relay is not open; or, admitting by age, the window's nonces are at their bound",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/age/receipt": {
|
|
"get": {
|
|
"operationId": "admission.show",
|
|
"tags": [
|
|
"age"
|
|
],
|
|
"summary": "The room's admission receipt so far",
|
|
"description": "In a room that admits by age (`[age]`); 404 in any other.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"receipt": {
|
|
"type": "object",
|
|
"description": "the wai-age-admissions receipt (age-assurance §7), signed by the room's clock, every count under 50 suppressed"
|
|
},
|
|
"policy": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "past the client's rate: retry after retry_after_s",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/mls": {
|
|
"get": {
|
|
"operationId": "mls.tail",
|
|
"tags": [
|
|
"e2ee"
|
|
],
|
|
"summary": "The room's log of MLS messages",
|
|
"description": "An end-to-end encrypted room's log (confidentiality §5.1, §15.2) from entry `from`: the clock's lifecycle records (`event`) and every GroupInfo, commit and Welcome carried (`mls`), in the order the clock took them; 404 in a room that is not end-to-end encrypted.",
|
|
"parameters": [
|
|
{
|
|
"name": "room",
|
|
"in": "query",
|
|
"required": true,
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"description": "the room's id"
|
|
},
|
|
{
|
|
"name": "from",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"description": "the first entry wanted (default 0)"
|
|
},
|
|
{
|
|
"name": "wait_ms",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 8000
|
|
},
|
|
"description": "how long to hold the request while the log has nothing past `from` (default and most 8000)"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"entries": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"seq": {
|
|
"type": "integer"
|
|
},
|
|
"event": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"mls": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"next": {
|
|
"type": "integer"
|
|
},
|
|
"end": {
|
|
"type": [
|
|
"integer",
|
|
"boolean"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"410": {
|
|
"description": "a room since replaced",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/mls/key-package": {
|
|
"post": {
|
|
"operationId": "mls.import",
|
|
"tags": [
|
|
"e2ee"
|
|
],
|
|
"summary": "A KeyPackage for a granted principal's Add",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"key_package": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
},
|
|
"required": [
|
|
"room",
|
|
"key_package"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"principal": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "`not granted`: the KeyPackage's principal holds no grant of the room",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"410": {
|
|
"description": "a room since replaced",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/mls/post": {
|
|
"post": {
|
|
"operationId": "mls.update",
|
|
"tags": [
|
|
"e2ee"
|
|
],
|
|
"summary": "A GroupInfo, or a commit and its Welcome",
|
|
"description": "Checked by the room's clock (confidentiality §5.5), then carried in the log. The body is at most 128 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"frames": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"minItems": 1
|
|
}
|
|
},
|
|
"required": [
|
|
"room",
|
|
"frames"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"seq": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "the clock refuses it (its reason); it is not carried",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"410": {
|
|
"description": "a room since replaced",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/co/objects": {
|
|
"get": {
|
|
"operationId": "performance.list",
|
|
"tags": [
|
|
"co-performance"
|
|
],
|
|
"summary": "The clock's log of objects",
|
|
"description": "Co-performance §9.1, from entry `from`, at most 5000 an answer; 404 in a room without co-performance.",
|
|
"parameters": [
|
|
{
|
|
"name": "from",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"description": "the first entry wanted (default 0)"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"objects": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"next": {
|
|
"type": "integer"
|
|
},
|
|
"end": {
|
|
"type": "boolean"
|
|
},
|
|
"unlogged": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/co/state": {
|
|
"get": {
|
|
"operationId": "performance.show",
|
|
"tags": [
|
|
"co-performance"
|
|
],
|
|
"summary": "The room's co-performance as the clock holds it",
|
|
"description": "Its windows, the marks it signed and those it owes, its log's length and its own records, at room-clock `now`.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/co/schedule": {
|
|
"post": {
|
|
"operationId": "schedule.create",
|
|
"tags": [
|
|
"co-performance"
|
|
],
|
|
"summary": "A turn schedule the clock signs",
|
|
"description": "Co-performance §6.1, for a grant with the direct power; `from_us` at least `lead_ms` ahead. Authorised by a grant of the room (`Authorization: Bearer` and the grant's record in base64url) and its proof of possession (`WAI-Room-Proof`) over a challenge the service issued in `WAI-Room-Challenge`, on a 401 and on every answer it accepts (live-rooms §10.5.3); the proof's context is the method and the path the client addressed. The body is at most 4 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"mode": {
|
|
"type": "string",
|
|
"enum": [
|
|
"mark",
|
|
"refuse"
|
|
]
|
|
},
|
|
"from_us": {
|
|
"type": "integer"
|
|
},
|
|
"beat_us": {
|
|
"type": "integer"
|
|
},
|
|
"beats_per_bar": {
|
|
"type": "integer"
|
|
},
|
|
"segments": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"start_us": {
|
|
"type": "integer"
|
|
},
|
|
"length": {
|
|
"type": "integer"
|
|
},
|
|
"turns": {
|
|
"type": "integer"
|
|
},
|
|
"pairs": {
|
|
"type": "boolean"
|
|
},
|
|
"holders": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"required": [
|
|
"mode",
|
|
"segments"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"event": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"t": {
|
|
"type": "integer"
|
|
},
|
|
"statement": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "the grant's powers do not allow it",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the clock could not sign it now",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/co/handover": {
|
|
"post": {
|
|
"operationId": "handover.create",
|
|
"tags": [
|
|
"co-performance"
|
|
],
|
|
"summary": "A handover the clock signs",
|
|
"description": "Co-performance §6.3, for the holder of the turn at `at_us` (now and `lead_ms` when left out) or a grant with the direct power. Authorised by a grant of the room (`Authorization: Bearer` and the grant's record in base64url) and its proof of possession (`WAI-Room-Proof`) over a challenge the service issued in `WAI-Room-Challenge`, on a 401 and on every answer it accepts (live-rooms §10.5.3); the proof's context is the method and the path the client addressed. The body is at most 4 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"to": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"at_us": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"to"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"event": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"t": {
|
|
"type": "integer"
|
|
},
|
|
"statement": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "the grant's powers do not allow it",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the clock could not sign it now",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/co/window": {
|
|
"post": {
|
|
"operationId": "window.create",
|
|
"tags": [
|
|
"co-performance"
|
|
],
|
|
"summary": "A selection window the clock signs",
|
|
"description": "Co-performance §7.2, for a grant with the direct power; a draw's seed is drawn by the clock and kept until its selection. Authorised by a grant of the room (`Authorization: Bearer` and the grant's record in base64url) and its proof of possession (`WAI-Room-Proof`) over a challenge the service issued in `WAI-Room-Challenge`, on a 401 and on every answer it accepts (live-rooms §10.5.3); the proof's context is the method and the path the client addressed. The body is at most 4 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"rule": {
|
|
"type": "string",
|
|
"enum": [
|
|
"plurality",
|
|
"reactions",
|
|
"draw"
|
|
]
|
|
},
|
|
"types": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"enum": [
|
|
"prompt",
|
|
"sketch",
|
|
"vote",
|
|
"movement"
|
|
]
|
|
}
|
|
},
|
|
"options": {
|
|
"type": "integer"
|
|
},
|
|
"k": {
|
|
"type": "integer"
|
|
},
|
|
"close_us": {
|
|
"type": "integer"
|
|
},
|
|
"seconds": {
|
|
"type": "integer"
|
|
},
|
|
"question": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"rule"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"event": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"t": {
|
|
"type": "integer"
|
|
},
|
|
"statement": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "the grant's powers do not allow it",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the clock could not sign it now",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/co/fidelity": {
|
|
"post": {
|
|
"operationId": "fidelity.create",
|
|
"tags": [
|
|
"co-performance"
|
|
],
|
|
"summary": "A fidelity statement now",
|
|
"description": "Co-performance §5.6, for a grant with the direct power; `{\"ok\": false, \"reason\"}` while no intent is covered yet. Authorised by a grant of the room (`Authorization: Bearer` and the grant's record in base64url) and its proof of possession (`WAI-Room-Proof`) over a challenge the service issued in `WAI-Room-Challenge`, on a 401 and on every answer it accepts (live-rooms §10.5.3); the proof's context is the method and the path the client addressed. The body is at most 4 KiB.",
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"oneOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"event": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"t": {
|
|
"type": "integer"
|
|
},
|
|
"statement": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"const": false
|
|
},
|
|
"reason": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "a body that is not JSON",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "the grant's powers do not allow it",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "the service could not read its own record",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the clock could not sign it now",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/watch/time": {
|
|
"get": {
|
|
"operationId": "time.show",
|
|
"tags": [
|
|
"watch"
|
|
],
|
|
"summary": "The service's clock",
|
|
"description": "For a page's estimate of the room clock (co-watch).",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"now_us": {
|
|
"type": "integer"
|
|
},
|
|
"t0_us": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/watch/source": {
|
|
"get": {
|
|
"operationId": "source.fetch",
|
|
"tags": [
|
|
"watch"
|
|
],
|
|
"summary": "The watch room's source, whole",
|
|
"description": "The source's bytes, of its media type; a page checks them by their SHA-256, the content hash its policy names (co-watch §3.5). 404 in a room that watches nothing.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "the source's bytes",
|
|
"content": {
|
|
"*/*": {
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "binary"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/watch/challenge": {
|
|
"get": {
|
|
"operationId": "watch.setup",
|
|
"tags": [
|
|
"watch"
|
|
],
|
|
"summary": "A challenge for a join's proof",
|
|
"description": "Single use, good for a minute (live-rooms §10.5.3).",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"challenge": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/watch": {
|
|
"get": {
|
|
"operationId": "watch.tail",
|
|
"tags": [
|
|
"watch"
|
|
],
|
|
"summary": "The watch room's log",
|
|
"parameters": [
|
|
{
|
|
"name": "room",
|
|
"in": "query",
|
|
"required": true,
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"description": "the room's id"
|
|
},
|
|
{
|
|
"name": "from",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"description": "the first entry wanted (default 0)"
|
|
},
|
|
{
|
|
"name": "wait_ms",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 8000
|
|
},
|
|
"description": "how long to hold the request while the log has nothing past `from` (default and most 8000)"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"entries": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"seq": {
|
|
"type": "integer"
|
|
},
|
|
"event": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"mls": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"next": {
|
|
"type": "integer"
|
|
},
|
|
"end": {
|
|
"type": [
|
|
"integer",
|
|
"boolean"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"410": {
|
|
"description": "a room since replaced",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/watch/room": {
|
|
"get": {
|
|
"operationId": "watch.show",
|
|
"tags": [
|
|
"watch"
|
|
],
|
|
"summary": "The room as a co-watch verifier is given it",
|
|
"description": "Co-watch §11.1, with the latest skew statements read.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/watch/join": {
|
|
"post": {
|
|
"operationId": "watch.join",
|
|
"tags": [
|
|
"watch"
|
|
],
|
|
"summary": "A viewer enters by a proof of its key",
|
|
"description": "The proof over a challenge from `GET /watch/challenge` for `POST //<host><prefix>/watch/join`; the clock signs the viewer's `join`. The body is at most 4 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"grant": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"proof": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
},
|
|
"required": [
|
|
"room",
|
|
"grant",
|
|
"proof"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"t": {
|
|
"type": "integer"
|
|
},
|
|
"again": {
|
|
"type": "boolean"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "a proof that fails (its reason)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"410": {
|
|
"description": "a room since replaced",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the clock could not sign the join now",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/watch/post": {
|
|
"post": {
|
|
"operationId": "watch.update",
|
|
"tags": [
|
|
"watch"
|
|
],
|
|
"summary": "A viewer's events, checked and carried in order",
|
|
"description": "Each event checked as co-watch §10 has it. The body is at most 16 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"events": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"minItems": 1,
|
|
"maxItems": 8
|
|
}
|
|
},
|
|
"required": [
|
|
"room",
|
|
"events"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"carried": {
|
|
"type": "integer"
|
|
},
|
|
"log": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "the first event refused (its reason, and `carried`: how many before it were carried)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"410": {
|
|
"description": "a room since replaced",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/remote/control": {
|
|
"post": {
|
|
"operationId": "control.grant",
|
|
"tags": [
|
|
"remote"
|
|
],
|
|
"summary": "The host hands control over",
|
|
"description": "A grant exchange (remote-desktop §7.1), the host's grant and proof presented as a co-performance request presents them; it takes effect at the first tick at least `lead_ms` ahead.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"to": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"control": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 15,
|
|
"description": "classes: 1 pointer, 2 keys, 4 touch, 8 clipboard"
|
|
}
|
|
},
|
|
"required": [
|
|
"to",
|
|
"control"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"grant": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"digest": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"effective": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "a grant that is not the room's host's",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "the exchange is refused (its reason, `not_present` among them)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"410": {
|
|
"description": "a room since replaced",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the exchange could not be signed at its tick",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/remote/room": {
|
|
"get": {
|
|
"operationId": "remote.show",
|
|
"tags": [
|
|
"remote"
|
|
],
|
|
"summary": "The session as the clock holds it",
|
|
"description": "What a verifier is given (remote-desktop §11.1). To a grant this room issued and its proof, presented as a co-performance request presents them; bounded per client.",
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"descriptor": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"grants": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
},
|
|
"key_log": {
|
|
"type": "null"
|
|
},
|
|
"chains": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "a grant of another room",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"410": {
|
|
"description": "a room since replaced",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "past the client's rate: retry after retry_after_s",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/remote/state": {
|
|
"get": {
|
|
"operationId": "remote.verify",
|
|
"tags": [
|
|
"remote"
|
|
],
|
|
"summary": "That session verified",
|
|
"description": "Remote-desktop §11.3: the outcome, the floor's changes and the floor statements refused, each input's fate, the latencies and each host's totals, with the clock's own floor and the principals it cut. To a grant this room issued and its proof, presented as a co-performance request presents them; bounded per client.",
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "a grant of another room",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"410": {
|
|
"description": "a room since replaced",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "past the client's rate: retry after retry_after_s",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/msg": {
|
|
"get": {
|
|
"operationId": "conversation.show",
|
|
"tags": [
|
|
"messaging"
|
|
],
|
|
"summary": "The conversation",
|
|
"description": "Its descriptor, records and members (live-messaging); 404 when the service keeps no conversation.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/msg/challenge": {
|
|
"get": {
|
|
"operationId": "conversation.setup",
|
|
"tags": [
|
|
"messaging"
|
|
],
|
|
"summary": "A challenge for a proof",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"challenge": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/msg/join": {
|
|
"post": {
|
|
"operationId": "conversation.join",
|
|
"tags": [
|
|
"messaging"
|
|
],
|
|
"summary": "A key that proves itself is admitted",
|
|
"description": "A proof of possession naming no grant (live-rooms §10.5.3); the conversation's first member owns it. The clock signs its `join` (live-messaging §3.4).",
|
|
"security": [
|
|
{
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"grant": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"digest": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"exp": {
|
|
"type": "integer"
|
|
},
|
|
"role": {
|
|
"type": "string",
|
|
"enum": [
|
|
"owner",
|
|
"member"
|
|
]
|
|
},
|
|
"conversation": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "`not_listed` or `removed`",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "`full`",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "past the client's rate: retry after retry_after_s",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "the service could not read its own record",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the history store could not take it",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/msg/log": {
|
|
"get": {
|
|
"operationId": "conversation.tail",
|
|
"tags": [
|
|
"messaging"
|
|
],
|
|
"summary": "The log as it is owed to the caller",
|
|
"description": "Live-messaging §9.3, from position `from`, at most 256 entries, held up to 8 s while there is nothing new.",
|
|
"parameters": [
|
|
{
|
|
"name": "from",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"description": "the first entry wanted (default 0)"
|
|
},
|
|
{
|
|
"name": "wait_ms",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 8000
|
|
},
|
|
"description": "how long to hold the request while the log has nothing past `from` (default and most 8000)"
|
|
}
|
|
],
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"entries": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"withheld": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"next": {
|
|
"type": "integer"
|
|
},
|
|
"end": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "`not_a_member`",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/msg/key-package": {
|
|
"post": {
|
|
"operationId": "conversation.import",
|
|
"tags": [
|
|
"messaging"
|
|
],
|
|
"summary": "A member's KeyPackage",
|
|
"description": "Kept for the member's Add. A member's request: its grant (`Authorization: Bearer`, the record in base64url) and its proof (`WAI-Room-Proof`) over a challenge the service issued; every answer carries a fresh one in `WAI-Room-Challenge`. The body is at most 128 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"key_package": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
},
|
|
"required": [
|
|
"key_package"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"seq": {
|
|
"type": "integer"
|
|
},
|
|
"end": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "`not_a_member`",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the history store could not take it",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/msg/mls": {
|
|
"post": {
|
|
"operationId": "conversation.update",
|
|
"tags": [
|
|
"messaging"
|
|
],
|
|
"summary": "A GroupInfo, or a commit and its Welcome",
|
|
"description": "Checked by the clock and carried; it then signs an epoch statement (live-messaging §7.3). A member's request: its grant (`Authorization: Bearer`, the record in base64url) and its proof (`WAI-Room-Proof`) over a challenge the service issued; every answer carries a fresh one in `WAI-Room-Challenge`. The body is at most 128 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"frames": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"minItems": 1
|
|
}
|
|
},
|
|
"required": [
|
|
"frames"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"seq": {
|
|
"type": "integer"
|
|
},
|
|
"end": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "`not_a_member`",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "the clock refuses it (its reason)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the history store could not take it",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/msg/post": {
|
|
"post": {
|
|
"operationId": "message.create",
|
|
"tags": [
|
|
"messaging"
|
|
],
|
|
"summary": "A message",
|
|
"description": "Its sealed object and receipts, taken after the checks of live-messaging §9.2, once on stable storage. A member's request: its grant (`Authorization: Bearer`, the record in base64url) and its proof (`WAI-Room-Proof`) over a challenge the service issued; every answer carries a fresh one in `WAI-Room-Challenge`. The body is at most 128 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"group": {
|
|
"type": "integer"
|
|
},
|
|
"properties": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"payload": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"receipts": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
},
|
|
"required": [
|
|
"group",
|
|
"properties",
|
|
"payload",
|
|
"receipts"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"seq": {
|
|
"type": "integer"
|
|
},
|
|
"end": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "`not_a_member`",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "refused by §9.2 (its reason)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the history store could not take it",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/msg/ack": {
|
|
"post": {
|
|
"operationId": "acknowledgement.create",
|
|
"tags": [
|
|
"messaging"
|
|
],
|
|
"summary": "An acknowledgement",
|
|
"description": "The caller's own (live-messaging §9.1). A member's request: its grant (`Authorization: Bearer`, the record in base64url) and its proof (`WAI-Room-Proof`) over a challenge the service issued; every answer carries a fresh one in `WAI-Room-Challenge`. The body is at most 128 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ack": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
},
|
|
"required": [
|
|
"ack"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"seq": {
|
|
"type": "integer"
|
|
},
|
|
"end": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "`not_a_member`, or another member's acknowledgement",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "refused (its reason)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the history store could not take it",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/msg/leave": {
|
|
"post": {
|
|
"operationId": "conversation.leave",
|
|
"tags": [
|
|
"messaging"
|
|
],
|
|
"summary": "The caller leaves",
|
|
"description": "The clock signs its `leave` (reason 1). A member's request: its grant (`Authorization: Bearer`, the record in base64url) and its proof (`WAI-Room-Proof`) over a challenge the service issued; every answer carries a fresh one in `WAI-Room-Challenge`. The body is at most 128 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"seq": {
|
|
"type": "integer"
|
|
},
|
|
"end": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "a body that is not JSON",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "`not_a_member`",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "the service could not read its own record",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the history store could not take it",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/msg/remove": {
|
|
"post": {
|
|
"operationId": "member.delete",
|
|
"tags": [
|
|
"messaging"
|
|
],
|
|
"summary": "The owner removes a member",
|
|
"description": "The clock signs its `leave` (reason 2). A member's request: its grant (`Authorization: Bearer`, the record in base64url) and its proof (`WAI-Room-Proof`) over a challenge the service issued; every answer carries a fresh one in `WAI-Room-Challenge`. The body is at most 128 KiB.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"principal": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
}
|
|
},
|
|
"required": [
|
|
"principal"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"seq": {
|
|
"type": "integer"
|
|
},
|
|
"end": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "`not_a_member`, or `power_not_granted`",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "`not_present`",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "the service could not read its own record",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "the history store could not take it",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/call/challenge": {
|
|
"get": {
|
|
"operationId": "call.setup",
|
|
"tags": [
|
|
"calls"
|
|
],
|
|
"summary": "A challenge for a proof",
|
|
"description": "In a call room (`[call]`); 404 in any other.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"challenge": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/call/place": {
|
|
"post": {
|
|
"operationId": "call.create",
|
|
"tags": [
|
|
"calls"
|
|
],
|
|
"summary": "Place a call",
|
|
"description": "A key proves itself (a proof naming no grant) and names its invitees; the authority signs the call descriptor (WCT1) for the room, and the caller's publisher grant (live-messaging §10). In a call room (`[call]`); 404 in any other.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"invitees": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"minItems": 1
|
|
}
|
|
},
|
|
"required": [
|
|
"invitees"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "`busy` (a call is in progress) or `full`",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/call/ring": {
|
|
"post": {
|
|
"operationId": "call.invite",
|
|
"tags": [
|
|
"calls"
|
|
],
|
|
"summary": "Ring invitees",
|
|
"description": "The caller's invitations (WCI1), with its grant and proof; each is checked (§10.2) and held in its callee's inbox. In a call room (`[call]`); 404 in any other.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"invitations": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"minItems": 1
|
|
}
|
|
},
|
|
"required": [
|
|
"invitations"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomGrant": [],
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"rung": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "not the caller",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "an invitation refused (its reason and `at`)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"410": {
|
|
"description": "no call in this room",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/inbox": {
|
|
"get": {
|
|
"operationId": "inbox.show",
|
|
"tags": [
|
|
"calls"
|
|
],
|
|
"summary": "The caller's inbox",
|
|
"description": "On a proof of the key (§10.4). In a call room (`[call]`); 404 in any other.",
|
|
"security": [
|
|
{
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"principal": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"invitations": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"now_us": {
|
|
"type": "integer"
|
|
},
|
|
"t0_us": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/call/answer": {
|
|
"post": {
|
|
"operationId": "answer.create",
|
|
"tags": [
|
|
"calls"
|
|
],
|
|
"summary": "Accept, decline or cancel",
|
|
"description": "A callee's accept or decline, or the caller's cancel (WCA1, §10.3); on an accept the callee's publisher grant. In a call room (`[call]`); 404 in any other.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"answer": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
}
|
|
},
|
|
"required": [
|
|
"answer"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "the request does not read",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "an answer of another key, or a missed call (the clock's)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "this service keeps no such room, or nothing at that path in this service's mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "the answer refused (its reason)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"410": {
|
|
"description": "no call in this room",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "the body is larger than the request takes",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/call": {
|
|
"get": {
|
|
"operationId": "call.show",
|
|
"tags": [
|
|
"calls"
|
|
],
|
|
"summary": "The current call",
|
|
"description": "To a party to it, on a proof of its key: the call's records, which a party verifies offline (§10). In a call room (`[call]`); 404 in any other.",
|
|
"security": [
|
|
{
|
|
"roomProof": []
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "no proof of possession that passes; a fresh challenge is in WAI-Room-Challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "not a party to the call",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "no call, or not a call room",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"components": {
|
|
"securitySchemes": {
|
|
"roomGrant": {
|
|
"type": "http",
|
|
"scheme": "bearer",
|
|
"description": "a grant of the room: its WRG1 record in base64url"
|
|
},
|
|
"roomProof": {
|
|
"type": "apiKey",
|
|
"in": "header",
|
|
"name": "WAI-Room-Proof",
|
|
"description": "a proof of possession over the service's challenge (live-rooms §10.5.3), in base64url"
|
|
}
|
|
},
|
|
"schemas": {
|
|
"Hex": {
|
|
"type": "string",
|
|
"pattern": "^([0-9a-fA-F]{2})*$",
|
|
"description": "bytes in hexadecimal"
|
|
},
|
|
"Hex32": {
|
|
"type": "string",
|
|
"pattern": "^[0-9a-f]{64}$",
|
|
"description": "32 bytes, 64 lowercase hexadecimal digits"
|
|
},
|
|
"Error": {
|
|
"type": "object",
|
|
"properties": {
|
|
"error": {
|
|
"type": "string",
|
|
"description": "a reason code or a short statement of what is wrong"
|
|
},
|
|
"reason": {
|
|
"type": "string"
|
|
},
|
|
"retry_after_s": {
|
|
"type": "number"
|
|
}
|
|
},
|
|
"required": [
|
|
"error"
|
|
]
|
|
},
|
|
"Room": {
|
|
"type": "object",
|
|
"properties": {
|
|
"room": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"generation": {
|
|
"type": "integer"
|
|
},
|
|
"t0_us": {
|
|
"type": "integer"
|
|
},
|
|
"now_us": {
|
|
"type": "integer"
|
|
},
|
|
"descriptor": {
|
|
"$ref": "#/components/schemas/Hex",
|
|
"description": "the signed WRD1 descriptor"
|
|
},
|
|
"compose": {
|
|
"$ref": "#/components/schemas/Hex",
|
|
"description": "the signed WCD1 composition descriptor"
|
|
},
|
|
"grants": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Hex"
|
|
},
|
|
"description": "the publishers' WRG1 grants"
|
|
},
|
|
"present": {
|
|
"type": "integer"
|
|
},
|
|
"publishers": {
|
|
"type": "integer"
|
|
},
|
|
"max_publishers": {
|
|
"type": "integer"
|
|
},
|
|
"e2ee": {
|
|
"type": [
|
|
"object",
|
|
"null"
|
|
]
|
|
},
|
|
"remote": {
|
|
"type": [
|
|
"object",
|
|
"null"
|
|
]
|
|
},
|
|
"age": {
|
|
"type": [
|
|
"object",
|
|
"null"
|
|
]
|
|
},
|
|
"co": {
|
|
"type": [
|
|
"object",
|
|
"null"
|
|
]
|
|
},
|
|
"watch": {
|
|
"type": [
|
|
"object",
|
|
"null"
|
|
]
|
|
},
|
|
"world": {
|
|
"type": [
|
|
"object",
|
|
"null"
|
|
]
|
|
}
|
|
},
|
|
"required": [
|
|
"room",
|
|
"t0_us",
|
|
"descriptor",
|
|
"grants"
|
|
]
|
|
},
|
|
"GrantAnswer": {
|
|
"type": "object",
|
|
"properties": {
|
|
"grant": {
|
|
"$ref": "#/components/schemas/Hex",
|
|
"description": "the WRG1 record"
|
|
},
|
|
"digest": {
|
|
"$ref": "#/components/schemas/Hex32"
|
|
},
|
|
"exp": {
|
|
"type": "integer"
|
|
},
|
|
"role": {
|
|
"type": "string"
|
|
},
|
|
"room": {
|
|
"$ref": "#/components/schemas/Room"
|
|
}
|
|
},
|
|
"required": [
|
|
"grant",
|
|
"digest",
|
|
"exp",
|
|
"role",
|
|
"room"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|