Drive a locker over the cable from the CLI - #70
Merged
Conversation
notecase could only reach a hardware locker from a browser: the protocol client lived in src/vault.ts but the framing lived in web/src/vaultserial.ts behind Web Serial, which is Chrome-only. So the wallet that holds the seed could not talk to the device that needs it. That produced a genuinely silly provisioning flow, shipped earlier today: device-node --force printed 64 bytes of bearer material to a terminal, and a second tool carried them to the device - through a clipboard and a shell history on the way. notecase device provision --mint <host> replaces it. The wallet derives the subtree, sends it down the cable, and raises the device's counter to match its own, in one operation with nothing rendered anywhere. device-node stays for the case the device is not on this machine. The move underneath is the substance. web/src/vaultserial.ts was 535 lines of which exactly two exports touched navigator; everything else was bytes in, messages out. That is now src/vaultwire.ts and the web file is a shim over it, so the browser and the terminal share one implementation of a wire protocol that two devices in the field depend on. The sixteen existing serial tests pass untouched, which is the evidence this was a move and not a rewrite. serialport is deliberately absent from package.json. It is a native module, a wallet should not need a compiler to install, and almost nobody installing notecase owns a locker. It is imported only when someone asks for the cable, and the failure path was checked before it was installed: a plain instruction, not a stack trace. `device ports` runs BEFORE the wallet is opened, because listing what is plugged in is a question about the machine rather than about anybody's money - and it is the first thing you reach for when a cable command misbehaves, which is when demanding a PIN is least welcome. The probe order and its retry are carried over from the measured behaviour rather than reinvented: framed first because a heartwood that receives newline JSON stops answering for the whole session while a vault recovers on the next newline, and twice before moving on because a board that has just unlocked is still booting. Bench-verified against a real heartwood: ports found it, info read it, provision set up moneyer.dev from a throwaway wallet's seed under a held-button card, mints read it back, forget removed it. Three new tests pin the seam - the frame bytes, that the web module still re-exports the same objects, and that a missing serialport explains itself. 328 pass.
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.
notecasecould only reach a hardware locker from a browser: the protocol client lived insrc/vault.tsbut the framing lived inweb/src/vaultserial.tsbehind Web Serial, which is Chrome-only. So the wallet that holds the seed could not talk to the device that needs it.That produced a genuinely silly provisioning flow, shipped earlier today:
device-node --forceprinted 64 bytes of bearer material to a terminal, and a second tool carried them to the device — through a clipboard and a shell history on the way.notecase device provision --mint <host>replaces it. The wallet derives the subtree, sends it down the cable, and raises the device's counter to match its own, in one operation with nothing rendered anywhere.device-nodestays for the case where the device is not on this machine.The move underneath is the substance
web/src/vaultserial.tswas 535 lines of which exactly two exports touchednavigator; everything else was bytes in, messages out. That is nowsrc/vaultwire.ts, and the web file is a shim over it — so the browser and the terminal share one implementation of a wire protocol that two devices in the field depend on.The sixteen existing serial tests pass untouched, which is the evidence this was a move and not a rewrite.
serialportis deliberately not a dependencyIt is a native module, a wallet should not need a compiler to install, and almost nobody installing notecase owns a locker. It is imported only when someone asks for the cable, and the failure path was checked before it was installed: a plain instruction, not a stack trace.
device portsruns before the wallet is opened, because listing what is plugged in is a question about the machine rather than about anybody's money — and it is the first thing you reach for when a cable command misbehaves, which is when demanding a PIN is least welcome.The probe order and its retry are carried over from measured behaviour rather than reinvented: framed first, because a heartwood that receives newline JSON stops answering for the whole session while a vault recovers on the next newline; and twice before moving on, because a board that has just unlocked is still booting.
Verification
Bench-verified against a real heartwood:
portsfound it,inforead it,provisionset upmoneyer.devfrom a throwaway wallet's seed under a held-button card,mintsread it back,forgetremoved it.Three new tests pin the seam — the frame bytes, that the web module still re-exports the same objects, and that a missing
serialportexplains itself. 331 pass.