HTTP API: server, credential, and the list of chats #4
Notifications
Due Date
No due date set.
Blocks
#2 Exponentiation, modulo, HTTP API for chats, per-chat webhooks
sneak/simplexcalc
#5 HTTP API: a chat's recent messages, and sending a message
sneak/simplexcalc
Reference: sneak/simplexcalc#4
Reference in New Issue
Block a user
Part of #2. First of four API units; the later ones add endpoints to what this one builds.
What. The bot serves an HTTP API beside the chat client. This unit builds the server, its credential check and its hardening, and the first endpoint: the list of chats.
Decisions (reversible, taken by the repo-manager):
internal/api; routergithub.com/go-chi/chi/v5, the decided default; the standardnet/httpserver. No fx, Sentry or metrics: the bot has none and the issue does not ask for them.internal/config, under its rule that a value set but unparseable aborts startup:PORT: the API's TCP port, default8080, on all interfaces inside the container. Anything but a whole number from 1 to 65535 aborts.API_TOKEN_FILE: path of a file holding the API credential. Absent: the API still listens but refuses every request, and startup logs a warning saying so. Set: the file is read once at startup; unreadable, or shorter than 32 characters once surrounding whitespace is trimmed, aborts. The credential is never logged.Authorization: Bearer {credential}, compared withcrypto/subtle.ConstantTimeCompare. Missing, malformed or wrong gives401withWWW-Authenticate: Bearerand{"error":"unauthorized"}. Trap:ConstantTimeCompareof two empty strings returns 1, so with no credential configured the check refuses before comparing; a test sends an empty bearer to a server with none configured. No path is exempt, not even a health check.127.0.0.1:5225inside the container; the imageEXPOSEs only the API port.docs/REPO_POLICIES.md:ReadHeaderTimeout,ReadTimeout,WriteTimeoutandIdleTimeouton the server; a per-request timeout; request bodies capped withhttp.MaxBytesReaderat 64 KiB; on every responseX-Content-Type-Options: nosniff,Content-Security-Policy: default-src 'none'; frame-ancestors 'none',X-Frame-Options: DENY,Referrer-Policy: no-referrer,Strict-Transport-Security: max-age=31536000; includeSubDomains,Cache-Control: no-store. No CORS headers. An error response is a chosen sentence as JSON, never an internal error's text, which goes to the log.bot.Runstarts the API after set-up and stops it, gracefully and within a bound, when it returns. The listener failing endsRunwith an error, as the chat client failing does.GET /api/v1/chatsreturns200and{"chats":[{"id":{contactId},"display_name":"..."}]}: the bot's direct chats, which are its contacts (it never joins groups), from the chat client's/_contacts {userId}command (contactsList). Further fields are the implementer's choice, documented.EventHandlerininternal/simplex/client.go).Done when:
PORTandAPI_TOKEN_FILE. Getting Started creates the credential file on the volume,/var/lib/simplexcalc/api-token, mode 0600, from/dev/urandomwith tools the image has, and runs with-p 127.0.0.1:8080:8080 -e API_TOKEN_FILE=/var/lib/simplexcalc/api-token. A new API section documents authentication and this endpoint with acurlexample. Design mentions the API.docs/TODO.mdCompleted Steps gets a line.make checkis green.Model: opus-5-5