docs: record the in-app accept, the update notice and translocation (P11a)
The interface spec gains `books.start`'s allocated `update_waiting` field and says only the owner can accept it. The packaging and architecture notes now describe the lease intent, the viewer's notice and "Check for updates", and the translocated-app refusal instead of listing them as not built. The testing record names each new test and the mutation targets it gives P12. The plan's P11a status and As-built block record what landed and what still waits: the Mac trial, the Windows installer (P11c's) and signing (D-64).
This commit is contained in:
1 parent
e2754898d8
commit
7b1774512b
5 files changed
+98
-9
No files matched your search
+15
-1
@@ -417,7 +417,19 @@ downgrading is theirs). Anything else (an AppImage, whose file is named by
|
||||
call is cut off), after a second check against the key, or by
|
||||
`wanderbooks update`, the owner's say-so, which reuses the staged copy. A
|
||||
local release is named in `<root>/updates/feed` (a `file://` address, then
|
||||
the key file), the same rule as `--trusted-key`.
|
||||
the key file), the same rule as `--trusted-key`;
|
||||
- **the owner accepts one in the app**: the viewer reads the staged
|
||||
`meta.json` (`Owner::update_waiting`) and shows a notice with "Update
|
||||
now", and Books has "Check for updates" (`Owner::check_for_updates`) and
|
||||
"Update to X"; accepting is the host's lease intent `apply_update`, which
|
||||
installs the staged copy as `update` does and lets the host's own
|
||||
replaced-program watch restart onto it once no call runs. `books.start`
|
||||
carries the same notice to an agent as `update_waiting`, with a next step
|
||||
to tell the human; no tool accepts it;
|
||||
- **a translocated macOS app refuses to connect agents**
|
||||
(`start::translocation_refusal`): a quarantined download runs from a
|
||||
read-only copy under `AppTranslocation` that vanishes with the app, so
|
||||
the person moves it out of Downloads first.
|
||||
|
||||
`deploy/packaging/` holds the Linux packaging: `packager.toml`
|
||||
(cargo-packager: `.deb`, AppImage, the pacman tarball with its PKGBUILD),
|
||||
@@ -428,6 +440,8 @@ throwaway-keyed feed on this machine) and `test-linux-packages.sh`.
|
||||
`.github/workflows/release.yml` builds them on a version tag. The macOS
|
||||
bundle is `packager-macos.toml`, `Info.plist` and `build-macos.sh` (an
|
||||
unsigned `.dmg` from CI's `macos` job; signing and notarization are step 5).
|
||||
A translocated app (Gatekeeper's copy of a quarantined download) may run
|
||||
but refuses to connect an agent, saying how to move it out of Downloads.
|
||||
|
||||
## The result envelope and the guards (`ledger-mcp`, P5)
|
||||
|
||||
|
||||
@@ -124,7 +124,8 @@ settings-and-conventions section says how to use them.
|
||||
codes), backup: { last_at, through_seq, stale }, prompts: [{ name, args
|
||||
}], needs_attention: { items: [{ id, severity, kind, title, tool?, args?
|
||||
}], counts: { kind: n } }, truncated?, handbook_sections,
|
||||
format_upgrade?: { guard, format, adds, how }, next_steps: [{ tool |
|
||||
format_upgrade?: { guard, format, adds, how }, update_waiting?: { version,
|
||||
staged_at, how }, next_steps: [{ tool |
|
||||
prompt, args?, why, required }], isolation }`. The connect text names it
|
||||
as the first call. `book.url` is the book's path on this server
|
||||
(`/b/ID/mcp`), never a path on a disk. `you` is the token's own facts
|
||||
@@ -145,6 +146,12 @@ settings-and-conventions section says how to use them.
|
||||
(below); its next step comes first, before anything else, at every
|
||||
start until it is done: `books.handbook {section: "format-upgrade"}`,
|
||||
"Tell the human first: …".
|
||||
`update_waiting` is there only while the host has downloaded and checked
|
||||
a newer version of wanderbooks (`<root>/updates/staged/`): its version,
|
||||
when it was staged (UTC, RFC 3339) and how it may be accepted. Only the
|
||||
owner can accept it, in the app (Books, then Update) or with
|
||||
`wanderbooks update` at a terminal; no tool can. Its next step asks the
|
||||
agent to tell the human, and nothing changes until they accept.
|
||||
`isolation` is `same_user (advisory)` locally (D-32): the books are
|
||||
hidden from agents in the owner's own account, not locked against them.
|
||||
On the owner's own machine, where the server runs as a separate account
|
||||
|
||||
+28
-5
@@ -135,8 +135,17 @@ subset. **Not checked: that the `.dmg` builds, mounts or runs**: that needs
|
||||
the CI run (Actions, release, Run workflow, this branch) and then a Mac.
|
||||
Open items for the trial on a Mac: whether `wanderbooks update` replacing
|
||||
the program inside a signed `.app` breaks its signature (it will: step 5
|
||||
must decide, probably by updating a whole `.app`); the translocated-app
|
||||
check (`translocated_app_refuses_to_connect`) is not built.
|
||||
must decide, probably by updating a whole `.app`). **Translocation
|
||||
(P11a step 6):** a `.dmg` downloaded from the internet keeps its
|
||||
quarantine bit, so Gatekeeper may run the app from a read-only copy under
|
||||
`/private/var/folders/…/AppTranslocation/…` that goes away when it
|
||||
closes. `wanderbooks connect` (and the viewer's Connect, which is the same
|
||||
function) refuses there, before a token is made or an agent's list is
|
||||
touched, and says to move the app out of Downloads and open it again:
|
||||
`ledger_host::start::translocation_refusal` reads the path the program
|
||||
would give the agent. Checked on Linux by standing in for that path
|
||||
(`translocated_app_refuses_to_connect`, `only_a_translocated_path_refuses_an_agent`);
|
||||
the real Gatekeeper copy still needs the trial on a Mac.
|
||||
|
||||
## Updates staged by the host (step 4)
|
||||
|
||||
@@ -148,9 +157,23 @@ first; `wanderbooks update` applies it too and reuses the staged copy;
|
||||
`update --check` says "already downloaded". A local release is named by
|
||||
`<root>/updates/feed` (a `file://` address, then the key file). Without a
|
||||
compiled-in release key and without that file, the look does nothing but
|
||||
log why. Not built: the in-app "restart now to update" choice and the
|
||||
viewer's notice, which need an admin-socket intent and a place in the
|
||||
viewer (see the unit's As-built block).
|
||||
log why.
|
||||
|
||||
The owner accepts a staged update **in the app** (P11a step 4). The
|
||||
viewer reads `<root>/updates/staged/meta.json` every few seconds
|
||||
(`Owner::update_waiting`) and shows a standing notice above the page,
|
||||
"Version X of wanderbooks is ready", with "Update now"; Books also has
|
||||
"Check for updates" (`Owner::check_for_updates`, which looks at the feed
|
||||
at once whatever the daily look did) and "Update to X" while one waits.
|
||||
Accepting sends the host's lease intent `apply_update`; the host installs
|
||||
the staged copy exactly as `wanderbooks update` does and its existing
|
||||
watch for a replaced program (host.rs INVARIANT 7) restarts onto it once
|
||||
no call is running, the books staying open and every holder's session
|
||||
carrying on. With no host running there is no call to cut off, so the
|
||||
viewer applies it itself. `books.start` tells an agent the same thing
|
||||
(`update_waiting`) and adds a next step to tell the human; no tool can
|
||||
accept it. The accepted update replaces the program file, not a whole
|
||||
`.app`, which step 5 must revisit for a signed bundle.
|
||||
|
||||
## What `update` and `rollback` need from a release
|
||||
|
||||
|
||||
@@ -3823,6 +3823,51 @@ add), `swap_in`'s temporary-then-rename (`update_is_atomic`), `healthy`
|
||||
(`failed_update_rolls_back`), `install_kind` (the marker test), and
|
||||
`parse_version`'s rejections.
|
||||
|
||||
## P11a steps 4 and 6: the in-app accept, the viewer's notice, translocation (2026-11-05)
|
||||
|
||||
The accept is the host's lease intent `apply_update` (the name
|
||||
`plan/served.md` 8.0.3 allocates); the viewer's names are
|
||||
`Owner::update_waiting`, `Owner::check_for_updates` and `Owner::apply_update`,
|
||||
and the agent's is `books.start`'s `update_waiting`.
|
||||
|
||||
- `crates/ledger-cli/tests/update.rs` (Linux):
|
||||
`books_start_says_an_update_waits` — a quiet `books.start` has no
|
||||
`update_waiting`; after the host stages a signed 9.0.0, `books.start`
|
||||
names its version and staged time and says only the owner accepts it,
|
||||
its next step says to tell the human, and no path appears in the answer;
|
||||
`the_owner_accepts_a_staged_update_in_the_app` — accepting with nothing
|
||||
staged is refused and changes nothing; once 9.0.0 is staged, the same
|
||||
intent (`opener::ask_once_within` with `Intent::ApplyUpdate`, what the
|
||||
viewer's `apply_update` sends) installs it, the program becomes the
|
||||
release's bytes, the old version is kept under `updates/previous/`, and
|
||||
an agent's bridge writes all through the host's restart onto it: every
|
||||
account is in the chart exactly once.
|
||||
- `crates/ledger-gui/tests/update_notice.rs`:
|
||||
`the_menu_checks_for_updates_and_a_waiting_update_shows_a_notice_that_accepts`
|
||||
(Books, Check for updates asks the owner and its words show; the standing
|
||||
notice names the version; Update now asks the owner to apply it, and the
|
||||
notice goes once it is installed) and
|
||||
`books_outside_a_data_root_have_no_update_notice`.
|
||||
- `crates/ledger-cli/tests/translocation.rs`:
|
||||
`translocated_app_refuses_to_connect` — with the program's path standing
|
||||
in for Gatekeeper's copy (`APPIMAGE` names a file under
|
||||
`AppTranslocation`), `connect claude` is refused before a token is made
|
||||
or a home is made, and the stand-in agent never runs; the same program at
|
||||
an ordinary path connects. `crates/ledger-host/src/start.rs`:
|
||||
`only_a_translocated_path_refuses_an_agent` (the marker is a path part,
|
||||
not letters in a name).
|
||||
|
||||
Not checked here: the real Gatekeeper copy and the `.dmg` (needs a Mac,
|
||||
the owner's trial); the Windows installer job is P11c's, not on this branch.
|
||||
|
||||
**For P12 (mutation targets, none run, D-33):** `update_waiting`'s
|
||||
"newer than this program" comparison (a mutant that offers the running
|
||||
version must die on `books_start_says_an_update_waits`'s quiet first
|
||||
call), `staged_update_in`'s plausibility check (a staged version with a
|
||||
path separator must not become a notice), and `translocation_refusal`'s
|
||||
component comparison (a part that merely contains the word must not
|
||||
refuse).
|
||||
|
||||
## P5: the agent surface (2026-10-29)
|
||||
|
||||
Every tool result carries the envelope (`next_steps`, `guards`, `warnings`,
|
||||
|
||||
Reference in new issue
Block a user