Skip to content

feat: read the signer's at-rest report, keep capabilities across a trimmed status - #141

Merged
TheCryptoDonkey merged 6 commits into
mainfrom
feat/at-rest-status
Sep 26, 2026
Merged

TheCryptoDonkey merged 6 commits into
mainfrom
feat/at-rest-status

Conversation

@TheCryptoDonkey

Copy link
Copy Markdown
Member

Follows heartwood-esp32 #192, which added at_rest and unlock_phone_count to FIRMWARE_INFO and get_status.

  • The "After a power cut" mode now reads the signer's own report (none, pin, vault, encrypted, plus the phone count) instead of inferring it. Older firmware (released beta.17) sends neither field, so Sapwood falls back to the old inference. An unrecognised value shows as unknown. An action taken this session still wins until the next poll.
  • Over USB, the phone count now comes from FIRMWARE_INFO, which answers even while the signer is locked.
  • Fix: a trimmed low-heap get_status reply (truncated: true) no longer clears capabilities and slots. Before this, persona pairing broke until the next full poll.

Tests: vitest 1040 passed (one unrelated flake in import-link.test.ts passes on rerun), svelte-check 0 errors, check:cli clean, chromium e2e 31 passed. mobile-webkit was not run (it can't run on this Mac).

heartwood-esp32 #192 adds at_rest ("none"/"pin"/"vault"/"encrypted") and
unlock_phone_count to FIRMWARE_INFO and get_status, so Sapwood no longer
has to guess the power-cut recovery mode from side effects it happened
to witness this session. resolveUnlockMode reads the new fields when a
signer sends them, treats an unrecognised value as unknown rather than
guessing, and falls back to the existing inferUnlockMode heuristic for
firmware that predates the report (released beta.17).
applyRelayStatus overwrote capabilities and slots to empty/zero whenever
a get_status reply set truncated: true (the low-heap fallback that trims
the request log and relay lists), breaking persona pairing until the
next full poll. The truncated reply never carried those two fields to
begin with, so carry the previous poll's values forward instead of
clearing them; at_rest and unlock_phone_count need no such handling,
since the firmware sends both fresh even on a truncated reply.
resolveUnlockMode's known override was set once by a PIN, seal or
disable action and never reset, so it kept overruling a later
at_rest report for as long as the tab stayed open. Add
shouldRetireEncryptionKnown, comparing the report seen when the
override was set against the latest one, so a differing report
(a relay poll catching up, or a fresh USB read) lets the firmware's
own answer take over again.
"Unknown: no vault key held here" and "Connect by USB to check" both
blame missing information, but a firmware that sends an at_rest
value this build does not recognise has told Sapwood something, just
not something it understands yet. Add atRestUnrecognised to
DeviceSummaryInput so the power-cut row can say "update Sapwood"
instead, and update the doc comment on unlockMode, which still said
"inferred" now that a firmware report is read directly when sent.
DevicePanel's summary row fed phoneCount (UnlockPhones' enumerated
list, null until an authenticated session lists it) into
deviceSummaryRows, so a locked signer with phones enrolled read as
"(0 phones)". Pass effectivePhoneCount instead, which prefers the
firmware's own unlock_phone_count, sent even while locked.

Also wires up the two preceding fixes: encryptionKnown now records
the at_rest value it was set against and retires once a later report
disagrees (re-reading FIRMWARE_INFO after a seal or unseal, since it
is otherwise only fetched at connect), and the "After a power cut"
card shows the new unrecognised-report wording alongside the summary
row.
@TheCryptoDonkey
TheCryptoDonkey merged commit 66274f2 into main Sep 26, 2026
4 checks passed
@TheCryptoDonkey
TheCryptoDonkey deleted the feat/at-rest-status branch September 26, 2026 00:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant