mirror of
https://github.com/nestriness/nestri.git
synced 2026-11-09 08:52:28 +02:00
- **Guest image (#405):** carries `libvpx`, `speex`, `libtheora`, `libvdpau` and `jsoncpp`, which Proton's GStreamer plugins link. Without them, `libgstlibav` and `libgstspeex` failed to load in every box on every Proton shipped so far. Verified: every library both published Protons need is now provided. - **Billing (#406):** every Polar webhook logs its type, the team it resolved to, the plan and status, whether it changed anything, and the subscription and customer ids. Logging only. Cut from prod rather than opened from dev: after squash merges the two histories conflict, though the files differ only in these four. This branch's tree is identical to dev's. After merge, the guest image is published from this prod commit. Host agent 0.2.18 then makes hosts pull it.
apps/api
The public HTTP API for Nestri — a Hono app. One handler, run either as a Cloudflare Worker or as an ordinary HTTP server.
What it does
Exposes the JSON API consumed by frontends and other clients. Every route is a thin wrapper that
validates input, delegates to a domain function in @nestri/core,
and returns { data: ... }. All business logic lives in the core package.
Routes:
| Prefix | Purpose |
|---|---|
/ |
Health check |
/user |
Current user profile, fingerprints, linked accounts |
/steam |
Link / sync / unlink a Steam account |
/library |
Owned games with playtime |
/games |
Game catalog |
/pairing-code |
Device pairing codes |
/machine |
Host machines |
/access-token |
Short-lived access tokens |
/doc |
Generated OpenAPI spec |
Structure
app/
index.ts # The handler: middleware, routes, error handler, /doc
server.ts # The same handler behind a listening socket
middleware/auth.ts # Bearer JWT, access token or host credentials → Actor
routes/*.ts # Thin route namespaces (UserApi, SteamApi, ...)
utils/ # ErrorResponses, Result(), validator wrapping
wrangler.jsonc # Worker configuration, one environment per stage
Dockerfile # The container, built from the repository root
test/ # Route tests
Key details
- Auth:
Authorization: Bearer …, carrying either a session token verified against@nestri/author a personal access token resolved from the database; or a registered host's ownx-nestri-machine-idandx-nestri-machine-secret. There is no shared secret and no credential that stands for more than one caller, so every route resolves to a specific user or a specific host — which is what lets a route say "the caller's own library" and mean it. - Errors: centralized
VisibleError→ typed JSON responses. - Settings arrive as bindings or as environment variables, and two of them have one spelling of
each: Postgres is
HYPERDRIVEorDATABASE_URL, and the route to the issuer is anAUTHservice binding orAUTH_INTERNAL_URL. Nothing here branches on which it got. AUTH_ISSUER_URLis the issuer's public URL and never the internal one, because it is compared literally against theissclaim on every token.
Running
bun run dev # under the Workers runtime, on :3000
bun run serve # as a plain process, on $PORT (default 3000)
Needs a Postgres database and a reachable issuer. Full list and deployment steps:
docs/deploy.md.