Commit Graph
4 Commits
Author SHA1 Message Date
swaitsandClaude Fable 5.1 3058b5c229 feat(packaging): the trial's Linux column and the Linux packages (P11a steps 1 and 3)
The Linux half of the packaging trial, run on this machine and in Debian,
Fedora and Arch containers, and the recipes it produced (docs/packaging.md
holds the table and what it found):

- mise.toml pins cargo-packager 0.11.8 and cargo-generate-rpm 0.21.1, now
  that `just package-linux` calls them. cargo-packager-updater is a
  library, not a tool, so it is not pinned (update.rs does the checking
  with minisign-verify, which is what the updater uses).
- deploy/packaging/: packager.toml (.deb, AppImage, the pacman tarball and
  its PKGBUILD), the rpm table in crates/ledger-cli/Cargo.toml, the AUR's
  own PKGBUILD (repacks the release tarball), build-linux.sh,
  repo-indexes.sh (the apt and dnf indexes, unsigned until the signing
  step), local-release.sh (a throwaway-keyed feed to try `update`),
  test-linux-packages.sh (linux_packages_install_and_upgrade: install
  0.1.0, open books as an ordinary user, upgrade to 0.1.1, check the host
  restarted onto the new file, the books' last journal line unchanged and
  `update` refuses; passes on Debian trixie, Fedora and Arch). A package
  marks itself package-managed with share/wanderbooks/install-method.
- The icon is a placeholder square (the AppImage cannot be built without
  one).
- .github/workflows/release.yml: on a version tag, build on ubuntu-24.04
  (the oldest glibc the packages claim: a program linked on this machine
  needs GLIBC_2.43 and does not start on Debian 13), attach the packages to
  the release, and add them to the apt and dnf repositories on gh-pages.
  No signing and no macOS or Windows job yet.
- The release profile strips symbols.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
2026-10-29 15:12:18 -06:00
swaitsandClaude Fable 5.1 d8816f9ee4 docs: tokens in a file, no keyring (U0e)
Deploy recipe loses its D-Bus dance, install.sh its macOS skip, README and
site their macOS caveat; packaging, architecture and testing records follow;
U0e As built filled in (D-63).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
2026-10-29 13:31:42 -06:00
swaits c8541ea9fc fix(deploy): the tunnel's door binds loopback only (P9a)
Review finding: `--http` parsed whatever address it was given and bound
it. The door is the plaintext MCP service with a static bearer token;
plan 3.9 and the P9a model put a TLS proxy or tunnel in front of a
loopback listener, and no decision authorises exposing the books
unencrypted. `--http 0.0.0.0:7411` would have done exactly that.

`local::tunnel_address` now accepts only a loopback address
(127.0.0.0/8 or ::1; `127.0.0.1:7411` stays the default) and refuses
anything else with a message naming loopback and why. `server` refuses
while parsing, before it takes the lock or binds a socket; `serve`
refuses before it starts a host, so nothing is left half-open. The
bind-failure behaviour for a loopback address is unchanged (said, not
fatal, 3.9), as is the unit's hardening.

The test `the_tunnel_door_binds_loopback_only` refuses 0.0.0.0, a public
sample address and [::] through `server`, checks no socket or host was
left behind, refuses through `serve`, then starts a loopback listener and
reaches `books.start` with the bearer.

No accounting code, report or figure changes.
2026-10-27 09:35:36 -06:00
swaits 1441dabcca feat(deploy): self-host recipe, the enforced isolation flag, and the tunnel's door (P9a)
The books can live on a machine of the owner's own (plan 3.8, 8.2 P9a,
D-51). Three things make that honest instead of nominal:

- `--isolation same_user|enforced` sets `server::Isolation`, carried
  through `Served` and `BooksServer` to `books.start`. Locally the books
  stay `same_user (advisory)`; under the self-host unit the server is told
  `enforced` and reports `service_user (enforced)`. The server never
  guesses, and the literal it used to report is gone.
- `--http [ADDR]` binds the same MCP router on loopback (default
  127.0.0.1:7411) beside the Unix sockets, before the ready line, for the
  TLS proxy or tunnel in front of the server. It is the same bearer door
  and the same graceful close; a failed bind is reported and is not fatal
  (3.9). `serve` carries both flags through the host, so the system unit
  can ask for them once.

`deploy/wanderbooks-server.service` is the unit: a dedicated account, a
0700 data root, `ProtectSystem=strict`, no seccomp or Landlock (D-32), and
loopback-only networking. `deploy/README.md` is the recipe: install, setup,
move the books by `books adopt` with its head check (D-31: a copied book
is the transport), mint a bearer token, put Caddy or Tailscale Funnel in
front of the loopback door, and point Claude Code and Codex at it.

The two-account CI job (`.github/workflows/two-user.yml`) makes the
deployment and runs `crates/ledger-cli/tests/two_user.rs` as another
account: `agent_uid_cannot_read_tenant` proves the tenant root and its
journal are refused, then reads, writes, uploads, files, exports and
verifies over HTTP with the bearer (in a second book, so the moved books'
head is not advanced); `self_host_adopt_same_head` compares the moved
books' head and event count with the source clone's.
`isolation_label_is_enforced_under_the_unit` runs everywhere, including
the unit-file read that keeps the recipe from drifting.

Accounting reason for the shape: nothing here changes an entry, a report
or a figure. It changes who can reach them: the move is lossless and
verifiable at the head, and the boundary is the operating system's, not a
promise in our text. No journal code, kernel function, Kani harness or
Lean step is touched, so `just prove` is not required.

No go-ahead needed: no new journal feature or event; the live books are
unaffected.
2026-10-27 09:35:36 -06:00