Skip to content

fix(update): bind installed updater bytes and version to the journal (W3-02h) - #457

Merged
mergify[bot] merged 1 commit into
mainfrom
claude/w3-02h-bind-candidate
Oct 5, 2026
Merged

mergify[bot] merged 1 commit into
mainfrom
claude/w3-02h-bind-candidate

Conversation

@Cuarroc

@Cuarroc Cuarroc commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Dieses Paket schließt eine Lücke im Update-Ablauf: Das Protokoll (Journal) gilt jetzt für genau die heruntergeladenen Update-Bytes und die angekündigte Version. Ein Protokoll für Version A kann damit keine Update-Datei von Version B mehr freigeben. Eine Lücke bleibt offen (siehe "Open"): Der Neustart-Abgleich kann den Hash der installierten Datei noch nicht mit dem Update-Hash vergleichen und braucht eine Entscheidung von dir.

Report

Changed (3 files, +155/-28, base afd937d)

Tests (red-first, new at merge base)

  • install_refuses_updater_bytes_whose_digest_or_version_differ_from_the_journal: other bytes / other version -> refused, installer never called, journal stays BackupVerified.
  • journal_carries_the_digest_of_the_exact_updater_bytes.

Evidence

  • bash scripts/ci/red-first.sh --plan -> exit 0 (count=2, specs=2)
  • bash scripts/ci/gates.sh lane prepush at bb5649c -> exit 0
  • cargo test --bin projecta delivery_recovery -> 42 passed before the second test; install module 14 passed

Architecture drift: no new findings, allowlist untouched.

Open (needs decision): post-restart validation. LiveEffects::validate (startup.rs:99) reports sha256(running exe), while the journal's candidate.binary.sha256 is the digest of the updater payload (archive/installer), never equal to the installed exe's hash. accept_handshake (delivery_recovery.rs:497) therefore cannot succeed for a real update. Fixing it means either recording the installed-exe digest by another route or changing the handshake identity, a seam/design decision I did not make silently. Weakening the handshake test was ruled out. The journal itself now carries the right digest, so promotion (signed_artifact_sha256) is bound to the real bytes.

NICHT ABGEDECKT

  • #[cfg(windows)] tests and the Windows half of clippy (merge queue runs Windows).
  • No real updater download/install was run (no app launch); main.rs wiring is covered by compile and gates only.
  • Post-restart exe-vs-payload binding (see Open).

Review disposition

Candidate SHA: bb5649c. Tier A. Reviewers (Ollama Cloud, author family claude): kimi-k3 (kimi-k3:cloud) -> approve; glm-5.2 (glm-5.2:cloud) -> approve. Both checked against the code by the driver.

ID Source Severity Finding Decision
K1 / G1 kimi-k3, glm-5.2 low main.rs:1264-1271: download now precedes produce_journal, so a refused precondition (require_live_evidence, install.rs:77) costs a full download. Rejected: confirmed true, but unavoidable (the journal digest needs the real bytes); no journal or install exists in the crash window, so it is harmless. Follow-up only if retries become common.
K2 kimi-k3 low install.rs:91: sha_hex(announced.bytes) runs on the async runtime thread. Rejected: confirmed, but one hash of the archive next to an existing synchronous fs::read in the same function; negligible. The second hash runs inside spawn_blocking.
G2 glm-5.2 low install.rs:179-181 / require_staged_matches runs twice. Rejected: intentional; the check in InstallOnly::install guards the effect itself, the first one refuses before begin_install.

Architecture drift: none found by either reviewer; no second pattern for state, errors (Fx<T> as before), store or IPC introduced. No code change, candidate unchanged.

The journal is now produced after the download and carries the digest of
the exact bytes update.install receives. The install gate compares those
bytes and the announced version with the journal's candidate before
begin_install, and the install effect repeats the check.

Test-First: src-tauri/src/delivery_recovery/install.rs::delivery_recovery::install::tests::install_refuses_updater_bytes_whose_digest_or_version_differ_from_the_journal
Test-First: src-tauri/src/delivery_recovery/install.rs::delivery_recovery::install::tests::journal_carries_the_digest_of_the_exact_updater_bytes

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@Cuarroc
Cuarroc marked this pull request as ready for review October 5, 2026 05:40
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@Cuarroc Cuarroc added the review-ok Pipeline: review disposition complete, no open high finding label Oct 5, 2026
@Cuarroc

Cuarroc commented Oct 5, 2026

Copy link
Copy Markdown
Owner Author

@Mergifyio queue

@mergify mergify Bot added the queued label Oct 5, 2026
@mergify
mergify Bot merged commit 7336595 into main Oct 5, 2026
10 checks passed
@mergify
mergify Bot deleted the claude/w3-02h-bind-candidate branch October 5, 2026 06:09
@mergify

mergify Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

This pull request spent 18 minutes 33 seconds in the queue, including 13 minutes 42 seconds running CI.

Required conditions to merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-ok Pipeline: review disposition complete, no open high finding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant