P2 slice 8: the viewer's menu, setup, no confinement (D-32)
No Landlock, no seccomp, no helper: isolation is "same_user (advisory)". The lease socket keeps two intents (close, format-upgrade consent). The viewer holds the books open while it runs and gains a Books menu: New books, Back up now, Restore (preview, then confirm), Close, Connect Claude Code / Codex. New commands `wanderbooks books back-up` and `wanderbooks connect claude|codex`. The scaffold (`new`/`init` and its templates) is gone; install.sh needs no sudo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj
This commit is contained in:
1 parent
019d8d76a3
commit
3cf359a0cd
28 files changed
+1976
-1931
No files matched your search
+9
-1
@@ -343,6 +343,14 @@ The books are open while something holds them; there is no background service. T
|
||||
|
||||
**Format changes are the server's gate, not the updater's.** A server that would write a newer journal format than a book has opens that book read-only, with guard `format_upgrade_pending`, until the owner consents in the app (or on a `/h/` page). Before it asks, it makes a verified local backup that includes the keys (`legacy.key` until P7). Consent comes only from the owner (the passphrase, through the viewer's `consent_format_upgrade` or a `/h/` page), never from an agent. Declining leaves the book as it was, and before consent the way back to a version that can write it is always there: a self-updating install keeps the previous verified app and offers "Go back to version X" (`wanderbooks rollback`); a package-managed one downgrades through its package manager (our apt and dnf repositories keep every release, and the AUR keeps old PKGBUILDs). This holds however the new version arrived: our updater, a package manager, or a hand install. **After consent** the previous version can no longer open that book, so "Go back to version X" refuses for it; the only way back is restoring the pre-upgrade backup, which would drop every entry since, so that restore says how many entries would be lost, arrives as its own book beside the current one (never replacing it), and needs the passphrase.
|
||||
|
||||
**As built (P2 slice 8), and where it departs (D-32):**
|
||||
- **No confinement, no helper.** No mode confines itself (no Landlock, no seccomp), so the helper is gone (`wanderbooks helper`, `ledger-host` helper.rs): the bridge, like every holder, starts the host itself with the clean start (start.rs). The host still refuses to run when it finds itself confined (started from a sandboxed app). Isolation is said as `same_user (advisory)` in `books.start` (`isolation`) and `wanderbooks doctor`.
|
||||
- **The lease socket's intents are two:** `close` and `consent_format_upgrade`. Backing up, restoring and new books were intents only so a confined viewer could hand them over; the viewer now does them as the command line does, through the server's admin socket (`back_up_now`, `restore`, `create`), holding a lease while it asks.
|
||||
- **The viewer holds the books open** (a lease of kind app) while it shows books of the data root, on a thread of its own, taken only once its own flags are good and its book is found (the window never waits; with no server it still opens and follows the books from disk). It lets go only when the owner closes the books; books that stop or won't open are tried again (a fresh try every 30 s after five failures). Its **Books** menu (ledger-gui owner.rs, beside Export): Back up now; Restore… (the backup's address or folder typed, checked first: what it would do is shown, then done for that backup at that head); New books…; Connect Claude Code, Connect Codex; Close the books (asked first). Each is done off the UI thread by the `Owner` ledger-cli gives the viewer, over the same ledger-host functions the command line uses; the viewer writes nothing of the books; the menu waits while one runs, and a restore's fields can't change while it is checked (a result for anything since edited is dropped). Older books dirs and the demo have no Books menu.
|
||||
- **New commands:** `wanderbooks connect claude|codex --book ID` (the books' agent token kept in the keyring, made if none is, replacing the server's, which no one can be using; then the agent's own `claude mcp add --scope user` or `codex mcp add` of `wanderbooks-<book>` running `wanderbooks mcp --book <book>`; the agent's command found on the PATH, else where its installers put it under `$HOME`, or `/usr/local/bin`, `/opt/homebrew/bin`: a viewer started from the desktop has a short PATH), and `wanderbooks books back-up ID [--new-disk]` (the admin socket's `back_up_now`).
|
||||
- **Scaffold deleted:** `wanderbooks new`/`init` and its templates (justfile, AGENTS.md, CLAUDE.md, wanderbooks.toml, .gitignore, .mcp.json, Claude and Codex settings), and its tests; the settings file's own export is ledger-config's (`books.export_settings`). `wanderbooks new`/`init` now says it is gone and what to run instead. `install.sh` installs the one executable, runs `setup`, and given a name starts those books and connects Claude Code: three commands to the first post, no sudo. The website (`site/index.html`) says the same; its built copy must be redeployed (`just deploy`) when this change is pushed: the old installer runs `wanderbooks new`. The first company's own books dir keeps its files until the cutover (slice 9).
|
||||
- **Tests:** `ledger-gui/tests/owner_menu.rs` (each item through a fake owner, the restore checked first, nothing of the books written; busy states and a restore's fields frozen while checked; no menu for an older books dir; screenshots), `open_while_held.rs` (connect with fake agents and the command it registers reaching the books, a token the keyring lost, an agent that refuses; back up now from the command line, `--new-disk`; the viewer's hold, new books and close through the owner's functions; the two intents), `one_executable.rs` (the gone scaffold), `spec_kept.rs` (`isolation`).
|
||||
|
||||
## 4. The MCP surface after the change
|
||||
|
||||
### 4.1 Connect instructions (composed in `get_info`; replaces `INSTRUCTIONS` S:57 and the string replace at S:8179)
|
||||
@@ -1248,7 +1256,7 @@ The owner decisions of 2026-10-16 (at the top of this document) replace the form
|
||||
| D-29 | The full-TIN outputs, from both doors (owner, 2026-10-19, asked whether the agent's CPA export should go away once the viewer has one: "Both WITH TINs. Stop acting like TINS MATTER SO MUCH THEY DONT") | **The agent and the viewer both make them, TINs included.** `books.export_cpa_package` (TINs by default), `books.vendor_1099` with `include_tins` and `books.get_w9` keep working for the agent; their files are made by the server and handed over by a command, `wanderbooks download`, like a receipt too large for a call (no path parameter, nothing in the agent's context). The viewer's menu makes the same files into Downloads. Over stdio (the development transport) the file comes back inline. TINs get no handling beyond the vault: no passphrase, no extra prompts, no special cleanup. |
|
||||
| D-30 | Q-1 answered: where the backups go (owner, 2026-10-19, asked "Where should the books' automatic backups go?" with a private git repo, a folder or other disk, or both: chose "Both") | **Two targets.** The archive pushes to a private git repository the owner names and also copies to a folder the owner names (an external disk or a synced folder); both hold the archive (not encrypted since D-31). The repository's address and the folder are asked for when backups are first set up (slice 7, or at the cutover for the first company), and kept as the book's backup settings. |
|
||||
| D-31 | Backups are not encrypted (owner, 2026-10-19, asked where to keep the backup's recovery key: "Why encrypt them? How about we let the backup system handle the security???? You're over complicating everything.") | **A backup is the book as it is, in git.** No age encryption, no archive key, no recovery key: the archive is a plain git repository of the book's journal, receipts, vault (as the vault keeps it) and keys, one commit per backup, pushed to the owner's private git repository and to a git repository in the owner's folder (D-30). The destinations are trusted to keep it private. This replaces 3.7's and 3.4's age encryption on push and 3.5's archive key. |
|
||||
| D-32 | No self-confinement (owner, 2026-10-20, asked how much of the planned Landlock/seccomp sandboxing of the server and the viewer, with the viewer's helper process, to build now that the server runs git for its backups: chose "None") | **No Landlock, no seccomp, no helper process for confinement.** The viewer stays read-only by design and by test (it never writes the books; its menu hands work to the server through the lease socket); agents still reach the books only through the MCP. Isolation is reported everywhere as `same_user (advisory)`. This replaces the self-confinement of P2's scope, 3.9's confined modes and their helper, and the archive-vs-Landlock decision row. |
|
||||
| D-32 | No self-confinement (owner, 2026-10-20, asked how much of the planned Landlock/seccomp sandboxing of the server and the viewer, with the viewer's helper process, to build now that the server runs git for its backups: chose "None") | **No Landlock, no seccomp, no helper process for confinement.** The viewer stays read-only by design and by test (it never writes the books; its menu hands work to the server, through its admin socket as the command line does); agents still reach the books only through the MCP. Isolation is reported everywhere as `same_user (advisory)`. This replaces the self-confinement of P2's scope, 3.9's confined modes and their helper, and the archive-vs-Landlock decision row. |
|
||||
|
||||
### 10.2 Deferred
|
||||
|
||||
|
||||
Reference in new issue
Block a user