Skip to content

test(storage): argue the V20 bump, and assert 18/19 stay unreadable - #50

Merged
BitHighlander merged 1 commit into
masterfrom
feat/u5-storage-v20
Aug 22, 2026
Merged

test(storage): argue the V20 bump, and assert 18/19 stay unreadable#50
BitHighlander merged 1 commit into
masterfrom
feat/u5-storage-v20

Conversation

@BitHighlander

Copy link
Copy Markdown
Owner

U5 asserted 17. 7.16 needs a format bump for passkey credentials, so the test has to move — and the whole reason it asserts a literal is that moving it must cost somebody an argument. Here is the argument, in the docstring where the next person finds it.

Why 20 and not 18

18 was the clear-sign identity block, 19 the PIN-KDF migration. Both were active, not drafted:

e109404ee  made 19 live
6bebde7b2  reverted the format to V17 for 7.15

Devices that ran alpha builds in that window carry blobs stamped 18 or 19 whose layout has nothing to do with passkeys. Reusing 18 would make 7.16 parse one as CTAP2 state — not refuse it, not wipe it, misread it. 20 is unburned.

Reader chain

V17 → storage_readV17, restamped. V20 → storage_readV20. No reader for 18 or 19 — they stay in the ladder because the enum is positional, but a blob stamped with either falls to the default and the device wipes. Documented behaviour for an unrecognised format, and strictly better than misparsing one.

Anti-rollback

Once a device writes V20, installing 7.15 maps the blob to StorageVersion_NONE and storage_init resets it. The device wipes. Normal downgrade behaviour, stated so it is a known consequence rather than a field report.

Release note, drafted now rather than under time pressure at tag

7.16 changes the on-device storage format to hold passkey credentials. Upgrading preserves your wallet. Downgrading to 7.15 or earlier will erase it — back up your recovery phrase before downgrading.

New: U5b

Asserts 18 and 19 have no dispatch case. The absence is what sends a burned blob to the wipe path, and an absence is exactly what gets undone by someone tidying a switch statement. Asserted rather than assumed.

Pairs with firmware #505 (takes V20) and unblocks #504.

U5 asserted 17. 7.16 needs a format bump for passkey credentials, so the test
has to move -- and the whole reason it asserts a LITERAL is that moving it must
cost somebody an argument. Here is the argument, in the docstring where the
next person will find it.

WHY 20 AND NOT 18. 18 was the clear-sign identity block, 19 the PIN-KDF
migration. Both were ACTIVE, not drafted: e109404ee made 19 live and 6bebde7b2
reverted the format to V17 for 7.15. Devices that ran alpha builds in that
window carry blobs stamped 18 or 19 whose layout has nothing to do with
passkeys. Reusing 18 would make 7.16 PARSE one as CTAP2 state -- not refuse it,
not wipe it, misread it. 20 is unburned.

READER CHAIN. V17 -> storage_readV17, restamped. V20 -> storage_readV20. No
reader for 18 or 19: they stay in the ladder because the enum is positional and
removing an entry renumbers everything after it, but a blob stamped with either
falls to the default and the device wipes. Documented behaviour for an
unrecognised format, and strictly better than misparsing one.

ANTI-ROLLBACK. Once a device writes V20, installing 7.15 -- which knows only to
V17 -- maps the blob to StorageVersion_NONE and storage_init resets it. The
device wipes. Normal downgrade behaviour, stated here so it is a known
consequence rather than a field report. A signed upgrade never wipes.

RELEASE NOTE, drafted so it is not invented under time pressure at tag:
  "7.16 changes the on-device storage format to hold passkey credentials.
   Upgrading preserves your wallet. Downgrading to 7.15 or earlier will ERASE
   it -- back up your recovery phrase before downgrading."

New test U5b asserts 18 and 19 have NO dispatch case. The absence is what sends
a burned blob to the wipe path, and an absence is exactly what gets undone by
someone tidying a switch statement. Asserted rather than assumed.
@BitHighlander
BitHighlander merged commit fa4898d into master Aug 22, 2026
1 of 3 checks passed
@BitHighlander
BitHighlander deleted the feat/u5-storage-v20 branch August 22, 2026 00:49
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