From b71790070049d1cf5366a76d161caf03468a1ed4 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 21 Oct 2026 11:55:05 +0200 Subject: [PATCH 1/2] Design 62: the bookkeeping portal (ADR 0481) The operator asked for a page showing the business's income, expenses and to-do as the bookkeeping service holds them now, on their own hardware: okioki moves whole to the home server and okioki-web runs beside it, behind Keycloak, never changing what the accountant did. --- .../01-to-be/62-the-bookkeeping-portal.md | 94 +++++++++++++++++++ 03-DESIGN/01-to-be/README.md | 1 + 2 files changed, 95 insertions(+) create mode 100644 03-DESIGN/01-to-be/62-the-bookkeeping-portal.md diff --git a/03-DESIGN/01-to-be/62-the-bookkeeping-portal.md b/03-DESIGN/01-to-be/62-the-bookkeeping-portal.md new file mode 100644 index 00000000..93e9b81b --- /dev/null +++ b/03-DESIGN/01-to-be/62-the-bookkeeping-portal.md @@ -0,0 +1,94 @@ +--- +layer: to-be +status: proposed +code: [okioki] +updated: 2026-10-21 +decisions: + - "ADR 0481" + - "ADR 0440" + - "ADR 0479" +--- + +# 62 — The bookkeeping portal + +**A web page on the private network where the operator, signed in with Keycloak, sees the business's income and +expenses as the bookkeeping service holds them now, and what is still to do per quarter. The `okioki` module that +talks to the service moves, whole, from the laptop to the home server, and the page, `okioki-web`, runs beside it. +Bookkeeping data stays on hardware the operator owns.** (ADR 0481, proposed and not in force.) + +**Acceptance.** The operator, signed in on a machine of the mesh, opens the page's internal name and sees income and +expenses per month and per quarter, the same period a year before beside them, including an invoice made in the +bookkeeping service minutes before; sees the to-do of a quarter, with a quarter the accountant has submitted shown +as locked; and a browser that has not signed in, or an identity not named in `operators`, sees nothing but the +sign-in or a refusal. + +## 1. The parts + +``` +the operator's browser (a machine of the mesh) + │ HTTP through the route proxy's internal name, signed in with Keycloak + ▼ +okioki-web — renders the pages on the server, keeps no bookkeeping data + │ bookkeeping.summary · bookkeeping.todo · bookkeeping.documents · bookkeeping.transactions · bookkeeping.document + ▼ +okioki — the one session with the bookkeeping service, on the home server + │ HTTPS, the service's own web API, as its web app calls it + ▼ +the bookkeeping service (OkiOki) +``` + +`okioki` claims the seat `bookkeeping`, held once for the mesh, and serves the verbs the page calls beside the tools +it has (`okioki_todo`, `okioki_link`, …). `okioki-web` claims `bookkeeping-web` with `open` and `status`, and calls +only `bookkeeping` verbs, never a module's own tool, as the print and scan page calls only seats (ADR 0479 §1). Both +are Go, and both live in the `okioki` repository. + +## 2. Where it runs + +Both modules run on the home server, which is always on and is the operator's own hardware (ADR 0481 §1). The +laptop sleeps and travels, so a page there would be away whenever the laptop is. `okioki` runs once: the service +password is sealed on the home server alone, given once at its desk prompt, and the laptop's `okioki` is retired on +the operator's Approve once the home server's answers. + +Uploading no longer reads a folder on the laptop. `okioki_upload` takes a scan from the scanner's bucket by its key, +or a mail attachment by its account, message and name, and reads it over the bus (ADR 0481 §3); a scan made on any +machine then reaches the service without being copied between machines. + +## 3. Who may see it + +The page requires `route` with an internal reach and `oidc-client` from Keycloak, as the mail web client does (ADR +0440 §2, §3). A trusted setting `operators` names the identities let in by the ID token's user name; it is empty by +default, so nobody is let in until the operator names themself. Nothing about the page is public. + +## 4. What it shows + +- **Overview.** Income (outgoing invoices) and expenses (incoming invoices and receipts, refunds subtracted), excluding + VAT, per month and per quarter, the same period a year before beside it; wages and money in and out of the business + account from the bank, by the operator's own tags. `bookkeeping.summary` computes it in `okioki` from the service's + documents and transactions, so the page does no bookkeeping arithmetic of its own. +- **To-do.** Open payments and documents per quarter, as `okioki_todo` reads them. +- **Documents and transactions.** Searchable lists for a period; a document opens as the file the service keeps, + streamed through `bookkeeping.document`. + +The page reads live and keeps no copy (ADR 0481 §4). Keeping the history in a database of the mesh's own is the own +bookkeeping research (issue 1457), and a decision of its own. + +## 5. What the accountant has done is never undone + +Every verb of `okioki` that changes the service reads the booking or document first and refuses one the accountant +has reviewed, approved for sending or booked, naming it and why, and sends nothing (issue 1608, ADR 0481 §5). The +page shows such items as locked. This holds for the agent's calls as much as for the page's. + +## 6. In what order it is built + +1. **`okioki` on the home server**: the seat `bookkeeping` with its read verbs, uploads from the scanner's bucket and + from mail, the accountant guard (1608); assigned to the home server, its password given at its desk prompt, the + laptop's retired on the operator's Approve. +2. **The read-only page**: `okioki-web` with the overview, the to-do and the lists, behind Keycloak. +3. **Changes from the page**: linking, tagging, marking paid and closing, each through the same guarded verbs. + +## 7. Still open + +- **The route proxy on the home server** did not answer its tools on 2026-10-21; whether it serves an internal name + there is checked before step 2. +- **Changes from the page** (step 3) wait for the guard's fields to be known: which of the service's fields an + accountant's submission sets is read from the service before 1608 is built. diff --git a/03-DESIGN/01-to-be/README.md b/03-DESIGN/01-to-be/README.md index 96696e13..b6e827f5 100644 --- a/03-DESIGN/01-to-be/README.md +++ b/03-DESIGN/01-to-be/README.md @@ -61,6 +61,7 @@ document is written and this one's status becomes `implemented`. | [`59-the-mail-web-client.md`](59-the-mail-web-client.md) | **In progress.** The operator's mail, every account, in a browser on the mesh's own machines: a module of its own, `mesh-mail-web`, holds `mail-webclient`, renders pages on the server and reads and sends only through `mail-store`'s verbs under a caller granted per account; its route reaches the private network only, the operator signs in with Keycloak, and a mail goes out only on the operator's Approve; then Betterbird is removed | ADR 0440, ADR 0378, ADR 0379 | | [`60-the-brother-module.md`](60-the-brother-module.md) | **Proposed.** One module, `brother`, holds the `scanner` and `printer` seats for the Brother multifunction device: scans from the glass (cropped) or the feeder (one PDF), keeps each scan in its bucket and announces it, prints in one call, reads the admin pages and changes settings on those where a mistake cannot lock the operator out, each change recorded and told; only its device process holds the credentials | ADR 0467, ADR 0464, ADR 0468, ADR 0474 | | [`61-the-print-and-scan-page.md`](61-the-print-and-scan-page.md) | **Proposed.** A web page, behind a Keycloak sign-in and on a public name, where the people the operator names print and scan, and only managers manage the printer: a module of its own, `print-and-scan`, that calls only the printer, scanner and object-store seats, so any holder of those seats works with it; documents go from the browser to the page and by signed links to the store, never over the bus | ADR 0479, ADR 0468, ADR 0440 | +| [`62-the-bookkeeping-portal.md`](62-the-bookkeeping-portal.md) | **Proposed.** A web page on the private network, behind the operator's Keycloak sign-in, showing the business's income, expenses and to-do as the bookkeeping service holds them now; `okioki` moves whole to the home server and the page `okioki-web` runs beside it, calling only the `bookkeeping` seat; nothing the accountant reviewed or submitted is ever changed | ADR 0481, ADR 0440, ADR 0479 | ## Not yet written -- 2.54.0 From 46d6840c67f2a06a5800f334a1db41d0e3e0155f Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 21 Oct 2026 11:56:03 +0200 Subject: [PATCH 2/2] Design 62: the page is read-only and its reach internal before assignment (ADR 0481 v4) --- .../01-to-be/62-the-bookkeeping-portal.md | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/03-DESIGN/01-to-be/62-the-bookkeeping-portal.md b/03-DESIGN/01-to-be/62-the-bookkeeping-portal.md index 93e9b81b..fdcf2036 100644 --- a/03-DESIGN/01-to-be/62-the-bookkeeping-portal.md +++ b/03-DESIGN/01-to-be/62-the-bookkeeping-portal.md @@ -55,8 +55,9 @@ machine then reaches the service without being copied between machines. ## 3. Who may see it -The page requires `route` with an internal reach and `oidc-client` from Keycloak, as the mail web client does (ADR -0440 §2, §3). A trusted setting `operators` names the identities let in by the ID token's user name; it is empty by +The home server's route `reach` is set to `internal` before the page is assigned there, so the route proxy composes +only the internal name, and the page answers 404 to any other host (ADR 0440 §2, ADR 0481 §6). It requires +`oidc-client` from Keycloak, as the mail web client does (ADR 0440 §3). A trusted setting `operators` names the identities let in by the ID token's user name; it is empty by default, so nobody is let in until the operator names themself. Nothing about the page is public. ## 4. What it shows @@ -69,14 +70,14 @@ default, so nobody is let in until the operator names themself. Nothing about th - **Documents and transactions.** Searchable lists for a period; a document opens as the file the service keeps, streamed through `bookkeeping.document`. -The page reads live and keeps no copy (ADR 0481 §4). Keeping the history in a database of the mesh's own is the own +The page only reads: it calls no verb that changes the service, and keeps no copy (ADR 0481 §4). Keeping the history in a database of the mesh's own is the own bookkeeping research (issue 1457), and a decision of its own. ## 5. What the accountant has done is never undone -Every verb of `okioki` that changes the service reads the booking or document first and refuses one the accountant -has reviewed, approved for sending or booked, naming it and why, and sends nothing (issue 1608, ADR 0481 §5). The -page shows such items as locked. This holds for the agent's calls as much as for the page's. +Every tool of `okioki` that changes the service, whoever calls it, reads the booking or document first and refuses +one the accountant has reviewed, approved for sending or booked, naming it and why, and sends nothing (issue 1608, +ADR 0481 §5). The page shows such items as locked. ## 6. In what order it is built @@ -84,11 +85,12 @@ page shows such items as locked. This holds for the agent's calls as much as for from mail, the accountant guard (1608); assigned to the home server, its password given at its desk prompt, the laptop's retired on the operator's Approve. 2. **The read-only page**: `okioki-web` with the overview, the to-do and the lists, behind Keycloak. -3. **Changes from the page**: linking, tagging, marking paid and closing, each through the same guarded verbs. +3. **Changes from the page** (linking, tagging, marking paid, closing) are not part of this design: they need a decision + of their own (ADR 0481 §4), and would go through the same guarded tools. ## 7. Still open - **The route proxy on the home server** did not answer its tools on 2026-10-21; whether it serves an internal name there is checked before step 2. -- **Changes from the page** (step 3) wait for the guard's fields to be known: which of the service's fields an - accountant's submission sets is read from the service before 1608 is built. +- **The guard's fields**: which of the service's fields an accountant's submission sets is read from the service + before 1608 is built. -- 2.54.0