Rebuild the hub on Bun: Elysia API, Better Auth, Drizzle, Next.js website
CI / test (push) Successful in 30s
CI / test (push) Successful in 30s
The hub becomes a Bun monorepo: apps/api (Elysia, Better Auth for accounts, roles, bans, proxy device sign-in and JWT keys; tagline linking, presence and the console as before), packages/db (Drizzle; Postgres in production, PGlite in development and tests), and the Next.js website from apps/web. Self-hostable with docker compose; the website deploys to Vercel-style hosts, the API to any that runs Bun or containers. The first version, in Go, is removed. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
64c552330b
commit
7a06ba49c3
59 files changed
+2640
-3523
No files matched your search
+61
@@ -0,0 +1,61 @@
|
||||
# The hub's API
|
||||
|
||||
`apps/api` (Elysia on Bun). The route definitions in `apps/api/src/app.ts` are the reference: their schemas validate
|
||||
requests and type the website's client (Eden). This is the overview.
|
||||
|
||||
- `/api/auth/*`: Better Auth (accounts, sessions, device sign-in, JWT keys).
|
||||
- `/api/v1/*`: the hub's own routes.
|
||||
|
||||
The website reaches the API through its own origin (Next.js rewrites `/api` to it), so sessions are first-party
|
||||
cookies. T5DE's proxy calls it directly with `Authorization: Bearer <session token>`.
|
||||
|
||||
Errors are `{"error": "<code>", "message": "<text for people>"}` with a 4xx/5xx status; `message` can be shown as
|
||||
is. Codes: `invalid`, `signed_out`, `forbidden`, `not_found`, `no_such_imvu_account`, `already_linked`,
|
||||
`code_missing`, `expired`, `link_cap`, `rate_limited`, `imvu_unavailable`.
|
||||
|
||||
## Accounts (Better Auth)
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `POST /api/auth/sign-up/email` | `{email, password, name, username}`. Usernames 3-32 of `A-Za-z0-9_`; passwords 10-256 characters. The first account is an admin. |
|
||||
| `POST /api/auth/sign-in/username` | `{username, password}` |
|
||||
| `POST /api/auth/sign-out` | |
|
||||
| `GET /api/v1/me` | `{person}` |
|
||||
|
||||
## Proxies
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `POST /api/auth/device/code` | `{client_id: "t5de-proxy"}` → `{device_code, user_code, verification_uri, verification_uri_complete, interval, expires_in}` (RFC 8628). `verification_uri` is the website's `/device`. |
|
||||
| `POST /api/auth/device/token` | `{grant_type: "urn:ietf:params:oauth:grant-type:device_code", device_code, client_id}` → `{access_token}` (a session token, used as a bearer token) or `{error: authorization_pending \| slow_down \| expired_token \| access_denied}` |
|
||||
| `POST /api/v1/device/approve` | (website, signed in) `{code}`: signs the waiting proxy in as this person |
|
||||
| `GET /api/v1/realtime` | WebSocket, bearer token. Protocol in `apps/api/src/realtime.ts`. |
|
||||
| `GET /.well-known/jwks.json` | the Ed25519 keys JWTs are signed with |
|
||||
|
||||
## Website routes (signed in unless noted)
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `GET /api/v1/home` | (anyone) `{onlineCount, links?}` |
|
||||
| `GET /api/v1/online` | (anyone) `{online}`: accounts showing they're online (moderators see all, with `hidden`) |
|
||||
| `GET /api/v1/online/events` | (anyone) server-sent events: `online` with `{online}` now and on each change |
|
||||
| `GET /api/v1/account` | `{person, links, challenges, computers, canLink}` |
|
||||
| `POST /api/v1/account/links` | `{username}` → 201 `{challenge}` (the tagline code) |
|
||||
| `POST /api/v1/account/links/:imvu/check` | `{link, moved}` |
|
||||
| `DELETE /api/v1/account/challenges/:imvu` | cancel linking |
|
||||
| `PATCH /api/v1/account/links/:imvu` | `{showBadge?, showPresence?}` → `{link}` |
|
||||
| `POST /api/v1/account/links/:imvu/recheck` | `{link}` (age checked with IMVU again) |
|
||||
| `DELETE /api/v1/account/links/:imvu` | unlink |
|
||||
| `POST /api/v1/account/signout-computers` | signs T5DE out on all their computers |
|
||||
|
||||
## Console (moderators; roles: admins)
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `GET /api/v1/console` | `{counts, connections, online, audit}` |
|
||||
| `GET /api/v1/console/people?q=` | `{people}` |
|
||||
| `GET /api/v1/console/people/:id` | `{person, links, computers}` |
|
||||
| `POST /api/v1/console/people/:id/link-cap` | `{linkCap}` (0-1000) |
|
||||
| `POST /api/v1/console/people/:id/ban` | `{reason}`; only admins ban moderators |
|
||||
| `POST /api/v1/console/people/:id/unban` | |
|
||||
| `POST /api/v1/console/people/:id/role` | (admins) `{role}` |
|
||||
Reference in new issue
Block a user