test(storage): argue the V20 bump, and assert 18/19 stay unreadable - #50
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
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_NONEandstorage_initresets 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
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.