summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/DECISIONS.md14
-rw-r--r--docs/DEPLOY.md60
-rw-r--r--docs/PROTOCOL.md13
-rw-r--r--docs/STATE.md10
-rw-r--r--docs/TUI-GUIDELINES.md7
5 files changed, 101 insertions, 3 deletions
diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md
index c18f49b..e317758 100644
--- a/docs/DECISIONS.md
+++ b/docs/DECISIONS.md
@@ -275,6 +275,20 @@ kept verbatim from the STATE.md they were pruned from (2026-09-21).
the key parts of #11 and #28; `make check` rejects F-keys, `^N` and
`^Enter` in `clients/`.
+30. **Web frontend (2026-09-23)**: bokftui runs in the browser through
+ ttyd in its own container (`bokf-web`), behind a login gate in C
+ (`bokfweb`) that authenticates with bokfd's `session.open` — no second
+ password store — and one login: the gate hands the bokfd session to
+ the TUI through a terminal handle that only works with the login's
+ cookie. Caddy in the container does the routing and `forward_auth`;
+ TLS stays with the host's existing Caddy (port 443 was taken), which
+ proxies `bokf.makandra.eu` to `127.0.0.1:8790`. Every terminal is an
+ isolated process (private HOME, limits, `BOKF_WEB=1`: no local files or
+ programs). bokfd's login limiter became per user name (it was one
+ global counter, so any 5 wrong guesses locked out everybody) and the
+ gate limits per client address. Audience: the owner and Petter first,
+ prepared for more users.
+
## Completed work formerly listed under "Pending decisions"
- Attachments are complete: download (voucher detail `f`, Underlag `Enter`,
diff --git a/docs/DEPLOY.md b/docs/DEPLOY.md
index 6fe6a53..99b7661 100644
--- a/docs/DEPLOY.md
+++ b/docs/DEPLOY.md
@@ -224,6 +224,66 @@ Agents use `token.create` instead of a password; tokens are scoped and
revocable. Only the TLS port is forwarded, and every command still requires
authentication (`meta` and `health` excepted).
+## Web frontend (`https://bokf.makandra.eu/web`)
+
+The `web` service (image `bokf-web`, built from the `web` target of the
+same Dockerfile and shipped by `scripts/deploy.sh` with the daemon) serves
+bokftui in the browser:
+
+```
+browser ──443──▶ host Caddy (TLS) ──▶ 127.0.0.1:8790 bokf-web container
+ Caddy: routing + forward_auth
+ ├─ /web, /web/login, /web/logout ─▶ bokfweb (login gate)
+ └─ /web/tty/* (gate OK only) ────▶ ttyd ─▶ bokftui-web ─▶ bokftui
+ │
+ bokfd ◀── unix socket ┘
+```
+
+- **Login gate** (`bokfweb`, `clients/bokfweb.c`): the login page checks
+ the credentials with bokfd's own `session.open` — there is no second
+ password store, and bokfd's audit and per-user lockout apply. The gate
+ limits failed logins per client address (5 per 15 min) before bokfd's
+ limit is reached. A login sets a cookie (`HttpOnly`, `Secure`,
+ `SameSite=Strict`, 12 h) and redirects to `/web/tty/?arg=<handle>`.
+- **One login**: the terminal wrapper (`deploy/bokftui-web`) trades the
+ handle for the bokfd session on the gate's internal `/redeem` (never
+ routed by Caddy) and starts `bokftui` with `BOKFD_SESSION`, so the TUI
+ opens logged in. Caddy's `forward_auth` lets a request reach ttyd only
+ with a live cookie whose session owns the handle in the URL; a leaked
+ URL is useless without the cookie. Quitting the TUI (or `/web/logout`)
+ closes the bokfd session and with it the web session.
+- **Isolation**: every browser terminal is its own bokftui process with a
+ private throwaway `HOME` (config, drafts, log), memory/CPU/file limits,
+ and `BOKF_WEB=1`: the TUI refuses everything that would read or write
+ files or start programs on the frontend (file browser, save prompts,
+ downloads, the PDF viewer). No shell is ever offered. The container runs
+ as uid 10001, read-only root, `/tmp` tmpfs, all capabilities dropped,
+ `no-new-privileges`, pids/memory limits, and it sees bokfd only through
+ the protocol socket (no database, no secrets, no certificates).
+- **TLS** is the host's reverse proxy. On the NAS, add to the existing
+ Caddy (`/mnt/data/caddy/Caddyfile`) a site block like the others and
+ reload it:
+
+ ```
+ bokf.makandra.eu {
+ tls {
+ dns inwx { ... } # as for the other sites
+ }
+ reverse_proxy 127.0.0.1:8790
+ }
+ ```
+
+ Port 443 is already forwarded for the other sites. The container
+ publishes 8790 on the host's loopback only, so it is unreachable until
+ that block exists.
+- `BOKF_WEB_MAX_SESSIONS` (default 20) caps concurrent terminals.
+ `docker compose logs web` shows logins, logouts and failed attempts
+ (never passwords).
+
+Not yet in the web version: uploading and downloading files (attachments,
+bank files, SRU/eSKD/årsredovisning files, PDFs). The TUI says so where it
+applies; use bokftui on a computer for those.
+
## Mock company
```sh
diff --git a/docs/PROTOCOL.md b/docs/PROTOCOL.md
index 709a475..3c8ba54 100644
--- a/docs/PROTOCOL.md
+++ b/docs/PROTOCOL.md
@@ -85,7 +85,11 @@ and returns an opaque, high-entropy session id:
intentional. API tokens survive restarts.
- Sliding TTL, `session_ttl` default 8 h. `session.close` ends one explicitly.
- Passwords are stored as Argon2id hashes. Failed logins are rate limited per
- peer (default: 5 failures per 15 minutes, then `RATE_LIMITED`).
+ user name (5 failures per 15 minutes, then `RATE_LIMITED` for that name
+ only): guessing one account never locks out the others. The table of
+ counters replaces expired or least-failed entries when full, so flooding
+ it with names neither disables the limiter nor lifts a block. The web
+ gate (`bokfweb`) adds its own limit per client address in front of this.
- A user changes their own password with `user.set_password` from a
password session (a token session gets `FORBIDDEN`). The current password
is required — 5 wrong ones per 15 minutes give `RATE_LIMITED` — and the
@@ -946,7 +950,10 @@ commands. Implemented screens (0.1.0-dev):
- **Inloggning** — server, user, password; org picker when several exist.
**Byt bolag** in the main menu reopens the picker during the session;
- **Byt lösenord** calls `user.set_password`.
+ **Byt lösenord** calls `user.set_password`. The same TUI runs in the
+ browser at `/web` (DEPLOY.md "Web frontend"): the login page opens the
+ session with `session.open` and the TUI reuses it; file features are
+ off there.
- **Dashboard** — status line with org, fiscal year, role and user.
- **Verifikat** — list and detail view (rows with column headers, an
underlag section separated by a rule, hash, link to corrected voucher); `c`
@@ -1122,7 +1129,7 @@ beyond the session and calls nothing but public commands.
| `session_ttl` | `8h` | sliding session lifetime |
| `max_line_bytes` | `1048576` | NDJSON line limit |
| `max_attachment_bytes` | `10485760` (10 MiB) | decoded attachment limit |
-| `auth_fail_limit` | `5/15m` | login rate limit per peer |
+| `auth_fail_limit` | `5/15m` | login rate limit per user name (fixed in the code) |
| `synchronous` | `FULL` | SQLite durability (`FULL`/`NORMAL`) |
| `audit_reads` | `false` | log read commands too |
| `allow_org_create` | `true` | any user may create an org |
diff --git a/docs/STATE.md b/docs/STATE.md
index 77ef9a4..93ade1e 100644
--- a/docs/STATE.md
+++ b/docs/STATE.md
@@ -14,6 +14,16 @@ unit tests and the docs consistency check.
## Resume here (2026-09-23)
+- **Web frontend (2026-09-23, branch `feat/web-frontend`, not deployed)**:
+ image `bokf-web` (Caddy routing + `bokfweb` login gate + ttyd +
+ bokftui in web mode) as compose service `web` on `127.0.0.1:8790`; see
+ DEPLOY.md "Web frontend" and decision #30. Tested end to end locally
+ (login, one-login handoff, foreign handle 403, logout, per-address
+ limit) and the aarch64 static build. **To go live**: deploy, then add
+ the `bokf.makandra.eu` block to the NAS Caddy
+ (`/mnt/data/caddy/Caddyfile`) and reload it. bokfd's login limiter is
+ now per user name (was global: 5 wrong guesses locked out everyone).
+ Next: file upload/download through the browser for the web mode.
- **Context menu and web-safe keys (2026-09-23, branch
`eff/context-menu`)**: `→` (or `^O`, also in table cells) opens
"Åtgärder", a box at the right edge with every action of the view and
diff --git a/docs/TUI-GUIDELINES.md b/docs/TUI-GUIDELINES.md
index 650f026..c223514 100644
--- a/docs/TUI-GUIDELINES.md
+++ b/docs/TUI-GUIDELINES.md
@@ -145,6 +145,13 @@ terminal and browser delivers (checked by `make check`):
reload — `^R` is a developer convenience and never the only way).
- Every action is reachable with arrows + `Enter` through the menu; a
letter accelerator is a shortcut, never the only path.
+- **Web mode** (`BOKF_WEB=1`, set by the browser-terminal wrapper): the TUI
+ runs on the web frontend, not on the user's machine, so a screen never
+ reads or writes a local file or starts a program there. Every such path
+ goes through `ui_web_block(title)` (`clients/ui.c`), which shows why and
+ returns 1: the file browser, `save_cache_and_open` (PDF viewer), the
+ attachment download and the SRU/eSKD/årsredovisning save prompts. New
+ file features must call it too (pty scenario `web-mode`).
### Implementation status