diff --git a/NOTES.md b/NOTES.md index ab319f4..afc27c8 100644 --- a/NOTES.md +++ b/NOTES.md @@ -1,4 +1,4 @@ -## Decription +## πŸ“ Description Calculator / tracker for festival diff --git a/PLAN.md b/PLAN.md index 9ee770b..990df16 100644 --- a/PLAN.md +++ b/PLAN.md @@ -1,9 +1,9 @@ -# wutzcalc β€” Implementation Plan +# πŸ—ΊοΈ wutzcalc β€” Implementation Plan Festival drink-sale tracker. 3 bars, ~10k attendees over 1 week, old iPads (iOS 12), local network only, central linux server. -## Decisions (locked for v1) +## πŸ”’ Decisions (locked for v1) - **Stack:** Preact + Vite (client), Node + Fastify (server), SQLite (better-sqlite3). - **Deployment:** single Node process serves API + static client + opens one `.db` file. @@ -17,7 +17,7 @@ local network only, central linux server. - **Undo:** only before confirming, fully local (edit the current cart). No undo of confirmed transactions in v1. - **iOS 12 target:** Vite build with `legacy` plugin β†’ ES2017 + polyfills. No CSS features past Safari 12. -## Architecture +## πŸ—οΈ Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” HTTP/JSON β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” @@ -33,7 +33,7 @@ local network only, central linux server. - Single port, single binary-ish (`node server.js`). Systemd unit for autostart. - SQLite WAL mode for concurrent reads from dashboard while writes happen. -## Data model (SQLite) +## πŸ—„οΈ Data model (SQLite) ``` bars(id, name, pfand_cents) @@ -56,7 +56,7 @@ settings(key, value) -- admin password hash etc. - `client_uuid` makes confirm idempotent against double-tap / retry. - Returns stored as separate line items with `is_return=1` and negative contribution to total. -## API surface +## πŸ”Œ API surface - `GET /api/config?bar=` β†’ bar + its drinks + pfand value. - `GET /api/bars` β†’ list of bars (for tablet first-run picker). @@ -69,7 +69,7 @@ settings(key, value) -- admin password hash etc. Server is the source of truth for prices β€” tablet sends drink IDs + qty only. -## Client (tablet) UX +## πŸ“± Client (tablet) UX - **First run:** pick which bar this tablet is. Stored in `localStorage`. - **Main screen:** grid of large buttons, one per drink served at this bar. @@ -80,7 +80,7 @@ Server is the source of truth for prices β€” tablet sends drink IDs + qty only. - All cart edits are local until confirm β€” undo = remove from cart. - Tap targets β‰₯ 64px, no hover states, no small text. -## Backoffice (v1) +## 🏒 Backoffice (v1) - `/admin` login (single password from env `ADMIN_PASSWORD`). - Pages: @@ -89,7 +89,7 @@ Server is the source of truth for prices β€” tablet sends drink IDs + qty only. 3. **Stats**: totals per bar, top drinks, crew freebie count/value. 4. **Export**: CSV of transactions and transaction_items. -## Repo layout +## πŸ“ Repo layout ``` wutzcalc/ @@ -119,7 +119,7 @@ wutzcalc/ (Admin can be a second entry in the same Vite build, or server-rendered HTML β€” leaning toward second Vite entry for consistency.) -## Implementation order +## πŸ”’ Implementation order 1. Repo scaffold: pnpm workspaces, Fastify server skeleton, Vite client skeleton, shared types package. 2. SQLite schema + migrations + seed (3 bars, a few drinks). @@ -131,7 +131,7 @@ wutzcalc/ 8. Legacy build verification on an iOS 12 Safari (or BrowserStack equivalent). 9. Systemd unit + README deploy instructions + backup cron note. -## Open risks +## ⚠️ Open risks - iOS 12 Safari is the main constraint β€” need to verify Preact + legacy plugin output actually runs there early (after step 1, before building more). - Local network reliability: if the WiFi at the venue is flaky, online-only model bites. Tracked in `TODO.md` (offline-capable client). diff --git a/README.md b/README.md index 77a4d39..15eb94b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# wutzcalc +# wutzcalc 🍺 + +wutzcalc logo > ## ⚠️ AI-generated code > @@ -8,23 +10,42 @@ > events), read the code yourself, test the edge cases that matter to you, and > assume there are bugs. Use at your own risk. -Festival drink-sale tracker. See [PLAN.md](PLAN.md) for architecture, [NOTES.md](NOTES.md) +> ## πŸ”“ No security β€” trusted networks only +> +> **This app has essentially no protection. Assume anyone who can reach it can +> read and write everything.** +> +> - 🚫 The tablet UI (`/`, `/api`) has **no authentication** β€” anyone on the +> network can record sales, return Pfand, or reset a cart. +> - πŸ”‘ The backoffice (`/admin`) is gated by a **single shared password** in +> plaintext (`ADMIN_PASSWORD`), sent and stored as-is β€” no per-user accounts, +> no rate limiting, no audit log. +> - 🌐 There is **no HTTPS** built in β€” traffic (including the admin password) is +> plaintext unless you put it behind your own TLS-terminating reverse proxy. +> - 🧱 No CSRF tokens (only a `SameSite=Lax` cookie) and no input hardening +> beyond basic request validation. +> +> Run it only on a **trusted, isolated LAN** (e.g. the bar's own Wi-Fi/VLAN), +> never exposed to the public internet. See [TODO.md](TODO.md) for the auth and +> hardening work deferred from v1. + +πŸŽͺ Festival drink-sale tracker. See [PLAN.md](PLAN.md) for architecture, [NOTES.md](NOTES.md) for the original requirements, and [TODO.md](TODO.md) for deferred work. -Source: +πŸ”— Source: -## Toolchain setup +## πŸ”§ Toolchain setup Requires Node.js 20+ and pnpm 9+. Native SQLite bindings install from prebuilt binaries on x86_64 / arm64 β€” no compiler needed for most setups. -### Nix (Linux / macOS) +### ❄️ Nix (Linux / macOS) ```sh nix develop # node 20, pnpm, sqlite, build deps ``` -### Debian / Ubuntu +### 🐧 Debian / Ubuntu ```sh # Node 20 from NodeSource @@ -36,7 +57,7 @@ sudo corepack enable # provides pnpm sudo apt install -y build-essential python3 ``` -### Fedora +### 🎩 Fedora ```sh # Node 20 + pnpm (corepack ships with the nodejs package) @@ -47,7 +68,7 @@ sudo corepack enable # provides pnpm sudo dnf install -y gcc-c++ make python3 ``` -### Windows +### πŸͺŸ Windows Install Node.js 20 LTS via the official MSI from (this also installs the optional "Tools for Native Modules"). Then in PowerShell: @@ -59,7 +80,7 @@ corepack enable # provides pnpm Use PowerShell to set env vars on the same line, e.g. `$env:ADMIN_PASSWORD="changeme"; pnpm dev:server`. -## Dev +## πŸ› οΈ Dev ```sh pnpm install @@ -70,7 +91,7 @@ pnpm dev:client # http://localhost:5173 (proxies /api Open `http://localhost:5173/` for the tablet UI and `http://localhost:5173/admin.html` for the backoffice. -## Production build +## πŸ“¦ Production build ```sh pnpm install @@ -81,7 +102,7 @@ ADMIN_PASSWORD=... DB_PATH=/var/lib/wutzcalc/wutz.db node server/dist/index.js Single Node process serves the API, both client entries (`/` tablet, `/admin` backoffice), and writes to one SQLite file. -## Run as a systemd service +## πŸš€ Run as a systemd service On Fedora, the `Makefile` automates everything below β€” from a fresh checkout, as root: @@ -127,7 +148,7 @@ Confirm `ExecStart` matches your Node path (`command -v node`) β€” it defaults t `/usr/bin/node`. The unit creates `/var/lib/wutzcalc` via `StateDirectory`, so the service user owns the database directory automatically. -## Env vars +## βš™οΈ Env vars - `PORT` (default `3000`) - `HOST` (default `0.0.0.0`) diff --git a/TODO.md b/TODO.md index 20d08cc..4b9a747 100644 --- a/TODO.md +++ b/TODO.md @@ -1,22 +1,22 @@ -# TODO +# πŸ“‹ TODO Longer-term items deferred from v1. -## Auth & access control +## πŸ” Auth & access control - Add short PIN per bar/tablet on first launch (currently no client auth). - Harden `/admin` beyond a single shared password (per-user, audit log). - Decide whether bartender identity should be tracked per transaction. -## Features +## ✨ Features - Custom price entry (free-form numpad amount as a line item, and/or per-drink price override). - Per-bar price overrides on top of the shared drink catalog (v1 is shared catalog + per-bar selection only). - Crew identification (which crew member took the freebie) beyond a flat "by crew" flag. - Backoffice: live transaction feed, per-drink charts, void/edit confirmed transactions. - Offline-capable client with sync queue (v1 is online-only). -## UX / scaling +## πŸ“± UX / scaling - Check what happens on the tablet UI when a bar has *many* drinks β€” current no-scroll grid divides the available height equally across rows, so tiles will shrink. Verify legibility/tap target size with 15–25 drinks; may need pagination, scrolling, or smaller-grid mode. -## Ops +## πŸ”§ Ops - Backup strategy for the SQLite file (cron + copy off-box). - Health check endpoint + simple status page on the tablet if server unreachable.