Repository navigation
A public page, the press kit, and the Flipper tap - #18
Merged
Merged
Conversation
Background jobs started from a shell die with their parent, which meant the hub kept vanishing between sessions and the phone would suddenly fail to connect for no visible reason. nohup plus disown orphans it to init instead. ./scripts/start-hub.sh Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The start script carried the agent and relayer keys as inline defaults. The repo checks testnet keys in on purpose, so this is not a leak — but a default in a script is silently wrong in a way a missing variable is not. You cannot tell whether you are running with your own key or one that shipped with the repo, and the same shape would quietly accept a mainnet key later. It now reads .env and refuses to start without SEPOLIA_RPC_URL, AGENT_KEY and RELAYER_KEY, naming the file to fix. Consistent with the repo's own rule that errors should be loud rather than degrade quietly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This is the interaction the project was always for, and it turns out to need no Apple Developer account at all — because the Flipper reads the tag, not the phone. Core NFC needs a paid entitlement; the Flipper needs a USB cable. It also needs no app on the device. The Flipper's CLI exposes NFC over USB, so the laptop drives the read: no C app, and no need for an NFC module in the JS engine, which does not have one. That was the blocker recorded in DECISIONS #17 and it turns out to be avoidable. SIGNER_KIND=nfc shows the proposal, runs the read, and signs when a tag lands. ALLOWED_UIDS restricts which tags count; empty accepts any, which is the right default before anyone has registered one. What a tap proves is physical presence, not identity — a UID is readable and cloneable by anyone who can hold a reader near it. It stands exactly where a button press would. The comment says so, and the pitch should too. The CLI verb and the UID format differ across firmware, so `nfc:probe` asks the device rather than guessing: it prints the real `nfc` help, runs a read, and dumps the raw bytes when a tag is tapped. flipper-check.sh now runs it as step 5. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A restart silently did nothing: sourcing .env overwrote keys passed on the command line with its own empty values, which then failed the required-variable check and left the previous server running on the previous gate.
Screenshots are captured from the running app against the live Sepolia deployment rather than mocked, so the balances, the proposal id and the agent's replies are all real. Getting them exposed two genuine bugs. The app only knew about proposals created during its own session, so relaunching while one was awaiting approval showed nothing at all and the request sat invisible until it expired — it now takes the hub's list as the source of truth. And the chat had no history, so every relaunch looked like the agent had amnesia; the hub already kept the transcript and the app now loads it. The mark is three rings closing on a point of contact: something was touched, and only then did it happen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
site/ is plain HTML, CSS and ES modules with no build step, published to GitHub Pages by .github/workflows/pages.yml on pushes to main. The hero is the argument rather than a picture of it: site/digest.js is a from-scratch keccak256 and EIP-712 encoder, so editing the transaction recomputes the real proposal hash live. "Load the frozen vector" fills in vectors/execute.json's inputs and reproduces its digest byte for byte, and "Let the server lie" sends a hash for a different recipient so the panel refuses the way the phone does. It also shows sha256(digest), which is what the Enclave actually signs, and that matches vectors/p256.json. digest.js is not a third implementation of the protocol to keep in sync — it is checked against the frozen vector in front of the visitor. If that check ever goes red, the page is wrong. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Everything on
b/flipper-and-recoverythat landed after #17, replayed ontomainso the diff is only the new work.The site
site/is a plain HTML/CSS/ES-module page — no build step, no dependencies — published to GitHub Pages by.github/workflows/pages.ymlon pushes tomainthat touch it.The hero is the argument rather than a picture of it.
site/digest.jsis a from-scratch keccak256 and EIP-712 encoder, so editing the transaction recomputes the real proposal hash in the visitor's browser:vectors/execute.json's inputs and reproduces its digest byte for byte, live.sha256(digest)— what the Enclave actually signs — which matchesvectors/p256.json.digest.jsis not a third implementation of the protocol to keep in sync; it is checked against the frozen vector in front of the visitor. If that check ever goes red, the page is wrong.The rest: the custody chain marked by how many of the two signatures exist at each step, the four real screenshots with the press-kit captions, the prompt-injection scene, four claims linking into the repo, and an honest "what this is not, yet".
Also in here
start-hubreading keys from.env, and not letting a blank line clobber an exported value.Before this is live
Pages has to be switched on once: Settings → Pages → Source → GitHub Actions. Then it deploys to https://ryannzander.github.io/Tappy/.
Checks
pnpm --filter @tappy/protocol test(19 passed) andpnpm typecheckboth green locally.site/is outside the pnpm workspace, so CI does not touch it.🤖 Generated with Claude Code