aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/mod.rs
Commit message (Collapse)AuthorAgeFilesLines
* api: a stream opened with a token ends with ittv47 hours1-0/+5
| | | | | | | | | | | | | | | | | | | | A token was checked when a request came, and a stream answered to it (the dashboard's events, a subscription's links and messages, the store's streams) then went on for as long as the client kept it open: past the token's expiry, past its user's tokens being revoked, its user disabled or removed, its session ended. Now a middleware inside `login::bearer` (`login::streams_end`) ends a streaming answer (`text/event-stream`, `application/x-ndjson`) to a request with a token at the token's deadline, its expiry, or as soon as the document no longer takes it (`token::still_taken`, the checks `verify` makes of the document, now its own function): looked at when a change touches protocol data (the root, a switch, among it), and when a session ends on the node itself in a swarm without a registry (`AppState::session_ended`). No polling: a timer for the expiry, and the changes as they come. The client reconnects with the token it has then; a refreshed token is a new one, so a stream lasts a token's lifetime at most (12 hours by default). `futures` is a dependency of every build now (for `take_until`), not only of libp2p's and Tor's.
* dashboard: going to another node's dashboard without its login page in betweentv47 hours1-1/+14
| | | | | | | | | | | | | | | Going to another member's dashboard showed its login page for a moment: a browser without a session there was sent from `/admin/dashboard` to `/login` (by `auth::basic_auth`), which began a session with the token handed over and went on to the dashboard. Now the dashboard's page is served without authentication, as the login page is (it holds nothing: what it shows it reads with the browser's session). Opened with a token handed over, the page begins the session with it (`POST /auth/session`) before it reads anything; without a session, `obtainTokens` goes to the login page, as the redirect did. A request without credentials is refused at once rather than after the 1.5 s that slow down guessing passwords: nothing is guessed there, and a page without a session goes to the login page without waiting twice for it.
* api: a log line per HTTP requesttv2 days1-0/+4
| | | | | | | | | | | | | Requests weren't logged at all, short of what a handler logs itself. Now a middleware, outermost on the API (and on a relay-only node's), logs a line per request as web servers do: method and path (with the query), status, the milliseconds until the answer began (a stream goes on after), where it came from (the address, or `unix`), and the user (`-` where none was authenticated). The user comes back on the response: `basic_auth` puts it there, for a token as for a password or a trusted proxy's header. At debug, under the target `http` (`RUST_LOG=info,http=debug`, or `PUT /admin/log`): an open dashboard alone would fill the log at info. With the target off, the request passes untouched.
* dashboard: keys edited, the last removed with a password, failures kepttv2 days1-1/+6
| | | | | | | | | | | | | | | | | | | | | The credentials dialog listed a user's keys whole, to add one or remove one but the last, and any failure replaced the dialog with the error, the form lost. * A key is shown short: its type, the first and last four characters of what tells it apart (an Ed25519 key's base64 after the part all of them share), its comment; the whole line in its tooltip. * A key can be edited, its name and its line: saved under the name, a new name written first and the old one removed. * A user with a password on this node (`--htpasswd`) may remove its last key: it logs in by the password. GET /auth/keys says so (`password`), and DELETE /auth/keys/{id} takes it then; the rules no longer keep the last key on every node (no other node can tell who has a password where; under a strict policy the signed entry keeps one still). * What fails says why beside where it was asked (the add form, the edited row, the removed one), which stays as it was, to be set right and tried again.
* state: limit refused writes per usertv3 days1-0/+1
| | | | | | | | | | A write every node would refuse is rolled back by forking the document at the heads before it, under the write lock, at a cost that grows with the document's history. A user could ask for such writes in a loop. Count each user's refused writes over the last minute. Past --refused-writes-per-minute (default 10), its writes are answered 429 without being tried, until the oldest refusal leaves the minute.
* users: a user manages its own keystv3 days1-0/+5
| | | | | | | | | | | | | | | | | Only a user who may manage users could change a user's keys: a user couldn't add a new laptop's key, or remove a lost one. A user now manages its own keys, whatever else it may do: * GET /auth/keys: its keys, its entry, and the envelope holding it under a strict policy (`signed`), to sign against. * PUT /auth/keys/{id} with an authorized_keys line, DELETE /auth/keys/{id}: one change, as the user. The rules take a write of _continuum/users/<name>/keys/… from the user it names. * Under a strict policy, the user signs its entry with only its keys changed, with a key it holds already (envelope::check takes that from the user itself), PUT to its own entry even without write on the registry; continuum-signed key-add and key-remove do so.
* access: a node judges its own changes before they leavetv3 days1-0/+1
| | | | | | | | | | | | | | | | | | | | The API checks the path a request asks for; the rules judge everything the change does. Where they disagreed, the honest node's change was refused by every other node, and with signatures required the node was refused as a whole. The plan had both gates run the same judgement. Under a policy, each change a node makes (its own writes and those through the API) is now judged by rules::judge as receivers will judge it, before it is signed or sent; one every node would refuse is rolled back (the document forked at the heads before it, same actor: the change never left) and the request refused with 403 (StoreError:: Refused). rules::judge_held, judging a change the document holds, moves from swarm::refusals to access::rules for both. The simulations that play a member past its own checks write with a helper that bypasses them (forge). Review finding 3 (the same judgement at both gates).
* auth: a login page and browser sessionstv4 days1-0/+18
| | | | | | | | | GET /login without authentication: log in by password or with a token (from a login by key). POST/DELETE /auth/session keep the token as an HttpOnly, SameSite=Strict cookie; the dashboard sends a browser without a user there and renews the session while open. Auth plan M2/M3 (browsers).
* auth: logging in by keytv4 days1-1/+5
| | | | | | | | POST /auth/challenge and /auth/login/key: a node-signed challenge, valid five minutes and taken once, signed with one of the user's SSH keys (ssh-keygen -Y sign -n continuum-login), for a token. Auth plan M7 (key login, M2b).
* access: the policy enforcedtv4 days1-0/+2
| | | | | | | | _continuum/access/policy ({"version": 1}) has every node screen every change it receives, on every path changes come in. A policy a node doesn't know stops its writes through the API. GET /admin/refused. Auth plan M6.
* dashboard: own links over the API, and CORStv4 days1-0/+4
| | | | | | | | | GET /admin/dashboard/links/own and its event stream: a node's own links, as LINKS_REPLY carried them, for other members' dashboards with a token. CORS for the members' dashboard origins and --cors-origins, without credentials. Auth plan M3.
* auth: logging in, and tokens as bearerstv4 days1-0/+8
| | | | | | | | | POST /auth/login (by htpasswd or the proxy), /auth/refresh, /auth/logout, GET /auth/whoami; every request may bring Authorization: Bearer instead of a password. --token-lifetime and --session-lifetime. Auth plan M2.
* access: the users endpointstv4 days1-0/+15
| | | | | | | | /admin/users: list, add (one or several), remove, disable, grant and revoke capabilities; each one change, refused if it would lock its writer out. Capabilities as the store's paths name them. Auth plan M1.
* access: authorization at the APItv4 days1-15/+20
| | | | | | | | | Every request is judged by the registry the node holds: store reads pruned to what the user may read, writes refused where it may not, admin endpoints by protocol capabilities. Without a registry, as before (--protocol-writers for protocol data). Auth plan M1.
* api: allow listening to Unix socketstv9 days1-0/+1
|
* api: support serving under a path prefixtv9 days1-1/+74
|
* api: /stream & dashboard send X-Accel-Bufferingtv9 days1-0/+7
|
* api: add type caststv9 days1-1/+2
|
* api: types are stickytv9 days1-1/+2
|
* api: add application/vnd.continuum.* scalar typestv9 days1-0/+7
|
* api: add support for counterstv10 days1-3/+4
|
* api: allow reading past versionstv10 days1-1/+1
|
* api: introduce /admin/changestv10 days1-0/+3
|
* document: reject writes during rejointv10 days1-0/+1
|
* api: add clocks to /healthtv11 days1-1/+1
|
* api: unify media-type strippingtv11 days1-0/+6
|
* api: unify error responsestv11 days1-6/+35
|
* move /admin/config handler to own moduletv11 days1-18/+3
|
* move store helpers to store moduletv11 days1-93/+4
|
* unify closing logictv11 days1-11/+2
|
* add support to insert values at list indextv12 days1-0/+2
|
* dasboard cannot block shutdowntv12 days1-2/+11
|
* add dashboardtv12 days1-0/+7
|
* introduce relay only modetv14 days1-0/+23
|
* show interpolated values in GET /admin/configtv2026-10-261-3/+13
|
* replace utoipa by static openapi.yamltv2026-10-261-43/+16
|
* add unauthenticated /health and /ready endpointstv2026-10-261-1/+5
|
* add GET /stream endpointtv2026-10-261-0/+1
|
* remove /debug/blacklist endpinttv2026-10-261-7/+5
|
* unify API error responsestv2026-10-261-4/+60
|
* move protocol paths to dedicated moduletv2026-10-261-4/+3
|
* put swarm ID into the documenttv2026-10-251-2/+5
|
* only protocol-writers may modify _continuumtv2026-10-241-1/+26
|
* add API and CLI to print effective configtv2026-10-241-1/+9
|
* add endpoint to export the documenttv2026-10-241-0/+2
| | | | GET /admin/document to retrieve the automerge document.
* add throughput statstv2026-10-241-0/+1
|
* add per peer incident statstv2026-10-241-0/+1
|
* expose stats via the APItv2026-10-241-0/+2
| | | | GET /admin/stats to retrieve all stats.
* add traffic countertv2026-10-241-0/+3
| | | | | | | | | | This introduces a new wrapper that counts messages and payload bytes per peer, split by kind (hello, helloReply, sync, ping, pong), each sent, received and refused. The traffic counter goes around the firewall, which means messages dropped outbound are still counted as sent, and messages dropped inbound don't count as received.
* allow changing log filtering while node runstv2026-10-231-0/+5
| | | | This also changes the default to tracing-subscriber.