You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(home): withdraw the adoption mechanism; keep election and honest reporting (#449)
Codex review of 4629117 raised three P1s and two P2s. All three P1s are
properties of the Home adoption mechanism rather than bugs in it, so the
mechanism is withdrawn rather than patched. What remains is wire-compatible
and does NOT claim to fix#449.
P1 — signed-record compatibility (owner_sync.rs:250). `HomeInvite` was inserted
BEFORE `IssuanceJournal`, shifting its bincode discriminant 3 -> 4. JSON-
persisted records still load, but `verify()` reconstructs different signed
bytes, invalidating pre-upgrade issuance signatures even after both devices
upgrade. Appending would fix the ordering, but any change to a signed value's
shape sits in this hazard class and needs an old-record fixture.
P1 — protocol compatibility (owner_sync.rs:183). A fifth closed-enum kind rode
an unchanged protocol version 2, so an older peer cannot decode the version
vector and aborts the entire owner-sync session — including unrelated names,
profile and journal sync. The kind needs negotiation or a staged rollout.
P1 — no trustworthy cross-device device/rider signal (sync.rs:316). The rider
exclusion trusted `OwnerIssuedCert.mode`, but `apply_journal_line` materializes
synced issuance records with `mode: Acp, not_after: None`
(owner_sync.rs:2567-2577), and `owner_issued_certificates()` treats journal
records as authoritative on ties. A Rider issued on device A therefore arrives
on device B indistinguishable from a device agent and would have received an
automatic Home invite — the filter was defeated in exactly the multi-device
case it existed for. The certificate carries no hosting mode either, so no
sound basis for a device-only auto-invite exists today, and inventing one here
would have silently amended ADR-0039's mode-agnostic Home eligibility and
deny-by-default rider scope.
Removed: SyncKind::HomeInvite (Tier-1 returns to FOUR kinds, restoring
IssuanceJournal's discriminant), SyncValue::HomeInvite, its apply arm,
home_invite_is_actionable, SyncDaemonView::{apply_home_invite,
reconcile_home_invites} and their DaemonView impls, mint_home_invite,
is_owner_device_cert, and the associated tests.
P2 FIXED — withdrawn canonical Home pointer (sync.rs:179). The publisher now
carries the same `!withdrawn` guard as `find_home`. Withdrawal keeps `home`
and `members_v2` populated, so a retired Home could be republished as
canonical; because provisioning yields to a named canonical Home, every device
would then refuse a replacement while GET /home reported `elsewhere` — the
owner left with no Home and no way to get one. Regression test added.
P2 MOOT — deferred invite retry: removed with the mechanism.
CI — rustdoc failed on a private intra-doc link from the public
HOME_POINTER_KEY; reproduced locally under RUSTDOCFLAGS="-D warnings" and
fixed. The treekem_home_rename e2e failure is #316/#311-class load flakiness,
not attributed to this diff.
ADR-0060 rewritten (still Proposed): amends ADR-0038 only — NO ADR-0041
amendment (Tier-1 stays at four kinds) and NO ADR-0039 change. Adoption,
retirement and any device-vs-rider Home eligibility rule are recorded as
explicitly undecided, to be reconciled with ADR-0039 rather than bypassed.
WHAT THIS DOES NOT DO: #449 is NOT fixed. A second device still holds its own
Home and reports `adoption_pending`; it does not join the owner's Home, and
the duplicate persists. #449 stays open.
Gates on this exact tree, separate commands, actual exits:
cargo fmt --all -> 0
cargo clippy --all-features --all-targets -- -D warnings -> 0
cargo clippy --all-features --lib --bins -- -D warnings
-D clippy::panic -D clippy::unwrap_used -D clippy::expect_used -> 0
cargo check --workspace --all-targets -> 0
RUSTDOCFLAGS="-D warnings" cargo doc --all-features --no-deps -> 0
cargo nextest run --workspace --all-features --no-fail-fast -> 0
(3319 passed, 0 failed, 295 skipped)
Refs #449
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ovKUXBeg5GZ51YECS9p51
Copy file name to clipboardExpand all lines: docs/adr/README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -67,7 +67,7 @@ This directory contains architecture decision records for x0x.
67
67
-[ADR 0057: Local Apps Reach the Daemon via REST/WS with Filesystem Discovery; `serve()` Is the Embedded Form](./0057-embedded-serve-library-local-apps.md) (proposed 2026-08-29) — `api.port`/`api-token` discovery over the ADR-0044 plane; embedded `server::serve()` disables self-update and hands `ServerHandle` to the caller; `/apps` static hosting remains proposal-only
68
68
-[ADR 0058: The Constitution Is Embedded Compile-Time in Every Binary](./0058-compile-time-embedded-constitution.md) (proposed 2026-08-29) — `include_str!` constants in the shared library surfaced via `GET /constitution`, `GET /constitution/json`, and `x0x constitution`; status constant (currently Draft) is the stage of record
69
69
-[ADR 0059: Invite Authentication and Seating Provenance](./0059-invite-authentication-and-seating-provenance.md) (proposed 2026-09-02) — InviteV4 signs the whole invite minus signatures with inline id-bound inviter/owner keys; Home-join mode pins the admission owner; every invite-derived seat records local, bootstrap-stripped `invite_lineage` with deduplicated authenticated fork evidence (observability only, no eviction); amends ADR 0016 §7; the stale-base residual and old-admin-key caveat are deferred to #472
70
-
-[ADR 0060: One Home Per Owner — Cross-Device Election and Adoption](./0060-one-home-per-owner.md) (proposed 2026-09-05) — the unit of Home is the OWNER, not the install (#449): auto-provisioning becomes optimistic and subject to election on the Tier-1 `("home")` register, `GET /home` reports `local`/`adoption_pending`/`elsewhere` instead of a bare 404, and adoption is winner-driven over a new fifth Tier-1 kind `SyncKind::HomeInvite` (a group id alone cannot admit a device, so `HomePointer` could elect but never seat); a deferred admission retries and never falls back to minting a second Home; amends ADR 0038 (unit of Home) and ADR 0041 (Tier-1 widened to five kinds); retirement of the losing duplicate is gated and still open
70
+
-[ADR 0060: The Owner's Home Is Elected, Not Per-Install](./0060-one-home-per-owner.md) (proposed 2026-09-05) — the unit of Home is the OWNER, not the install (#449): auto-provisioning becomes optimistic and subject to election on the Tier-1 `("home")` register, publisher and resolver share one `!withdrawn` predicate, and `GET /home` reports `local`/`adoption_pending`/`elsewhere` instead of a bare 404. Amends ADR 0038 (unit of Home) ONLY — no Tier-1 surface change (ADR 0041 stays at four kinds) and no change to ADR 0039 Home eligibility. How a losing device JOINS the winner's Home, retirement of the duplicate, and any device-vs-rider eligibility rule are explicitly deferred: review of PR #507 showed the first implementation broke signed-record and protocol compatibility and had no trustworthy cross-device device/rider signal. #449 stays open.
71
71
72
72
## Errata (Accepted ADRs are immutable; corrections recorded here)
0 commit comments