diff options
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 94 |
1 files changed, 0 insertions, 94 deletions
diff --git a/README.md b/README.md deleted file mode 100644 index 70de28d..0000000 --- a/README.md +++ /dev/null @@ -1,94 +0,0 @@ -# 🐧 penguins.lan - -A little intranet for a battery-powered LAN with no internet. The successor to -`inetravel` — same "have fun on the network" spirit, but a real Go app instead -of PHP includes, and actually fun stuff: live chat now, an r/place-style shared -canvas next. - -## Stack - -- **Go** standard-library HTTP server, no framework. -- **SQLite** (`mattn/go-sqlite3`) for persistence. -- **gorilla/websocket** for the realtime hub. -- `html/template` for server-rendered pages. - -## Architecture - -Requests flow through a small continuation-passing pipeline. Each route in -[`api/serve.go`](api/serve.go) reads as a flat chain of `Continuation`s, where -every link gets a `(success, failure)` pair and decides which to call. Shared -state for a request lives on `types.RequestContext`. - -``` -LogRequest -> ResolveSession -> RequireUser -> <feature continuations> -> Template -> LogTime -``` - -Layout: - -| path | what | -|------------------|-------------------------------------------------------------| -| `main.go` | entrypoint: load env, open db, migrate, serve | -| `args/` | flag parsing | -| `database/` | sqlite conn, migrations, per-feature queries | -| `adapters/arp/` | resolves a client IP -> MAC from the host's ARP table | -| `api/` | server wiring (`serve.go`) + feature packages | -| `api/auth/` | **MAC-based identity** — sessions, portal, reclaim | -| `api/ws/` | **websocket hub** — broadcast chat, foundation for realtime | -| `api/template/` | html/template rendering + 404 handling | -| `templates/` | server-rendered pages, wrapped in `base.html` | -| `static/` | css / js / images | - -## Identity (`api/auth` + `adapters/arp`) - -No passwords — on a trust-based LAN your **MAC address is your credential**. The -router (nodogsplash) keeps every client on one L2 segment, so the server reads -each visitor's MAC from the ARP table (`arp -an`). - -- **First visit** → the portal asks for a handle; claiming it creates a `user`, - binds your current MAC, and sets a session cookie. -- **Return visit** → a live session cookie logs you in; if it's gone, a - recognised MAC logs you straight back in. -- **Rotated MAC** (privacy randomization) → you show up as a new device. The - portal reports when that handle was *last online* and lets you **log back in** - to reclaim it, re-binding your new MAC to the existing account. - -One user can own many MACs (`macs` table). Chat messages reference `user_id` -(not a name), so identity survives MAC rotation and renames. - -> **Local dev:** the browser is on loopback and never appears in the ARP table, -> so set `DEV_MAC=aa:bb:cc:dd:ee:ff` to force a MAC and exercise the whole flow. -> Never set it in production — it would make every visitor one shared identity. - -## Realtime (`api/ws`) - -The `Hub` owns the set of connected clients and a broadcast channel; all client -set mutations happen in its single `Run()` goroutine, so no locks. Each `Client` -has a `readPump` and `writePump`. Messages are JSON tagged by `type` -(`chat` / `system` / `history`). To add a new realtime feature (e.g. the canvas), -add a `type` and handle it in the hub + client — no new connection plumbing. - -## Run it - -```sh -go mod download -go run . --server --migrate -# -> http://localhost:8080 -``` - -Flags: `--server`, `--migrate`, `--port 8080`, -`--database-path ./db/penguins.db`, `--template-path ./templates`, -`--static-path ./static`. - -### Docker - -```sh -docker compose up --build -``` - -## Roadmap - -- [x] base framework + live chat over websockets -- [x] MAC-based accounts + portal with reclaim -- [ ] r/place-style shared canvas -- [ ] presence / who's online -- [ ] more LAN games |
