Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions docs/handoff-testing/01-persistent-identity-icons.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# 01 — Persistent clear-sign identities + logo render

**What:** the "KeepKey + identity" model. A clear-sign signer loaded with
`persist=true` survives reboot (flash storage, `STORAGE_VERSION 17→18`), and
every clear-sign now **leads with the identity's logo + alias + fingerprint**
instead of the "NOT verified by KeepKey" banner — on both the load-consent
screen and every per-tx confirm.

**Where:**
- firmware `release/7.15.0-rc7` (`BitHighlander/keepkey-firmware#299`, OPEN) —
`lib/firmware/storage.{c,h}`, `signed_metadata.c`, `fsm_msg_ethereum.h`,
`lib/board/layout.c`, `include/keepkey/board/layout.h`.
- hdwallet `keepkey/hdwallet#53` **MERGED** → pinned at `modules/hdwallet` `eccc3fa6`.
- vault `feat/clearsign-identity-icons-vault` (`keepkey/keepkey-vault#342`, OPEN).

## Test (emulator, fastest)
1. Emulator dylib from rc7 (handoff 12), reloaded in Vault; Vault has #342.
2. `cd /Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/projects/keepkey-sdk`
`KEEPKEY_API_KEY=… node tests/evm-clearsign/clearsign-signer-flows.js`
(sends the Pioneer compass icon + `persist:true`).

## Verify
- [ ] **Load screen** shows the compass logo, full "LOAD CLEARSIGNER" title,
unclipped "Trust 'Pioneer' (fp)…" body (no first-letter clipping).
- [ ] **Per-tx confirm** leads with the same logo + "Identity" + alias + fp,
then decoded pages, **no raw hex**, no "NOT verified by KeepKey" scare.
- [ ] **Persistence:** load with `persist:true` → reboot the emulator → drive a
clear-sign for the SAME `key_id` **without** re-loading → it still verifies
and renders (reads the flash slot). WipeDevice clears it.
- [ ] **Migration (brick-risk):** seed an emulator on the OLD (v17) dylib, then
swap to rc7 → wallet loads, keys/label/policies intact, identities empty
(no data loss, no reset).
- [ ] Load an icon > 384 B or dims > 64 → device rejects at load (validated).
- [ ] Load `persist:true` into all persistent slots, then one more → honest
"No free persistent identity slot" failure (not silent RAM-only).

## Status / gotchas
- Firmware unit tests 75/75 pass (storage round-trip + migration + clamp).
- Icon column is 40px; identity icons generated at 40px + centered (handoff 07).
- device-protocol pinned to fork `33521a8` (icon fields) — **upstream-pin swap
is the final-release gate**, not the rc.
- Boot click-through review of trusted identities = deferred (Stage 3).
</content>
31 changes: 31 additions & 0 deletions docs/handoff-testing/02-clearsign-allowlist-loadsigner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 02 — Clearsign vendored allowlist + LoadClearsignSigner endpoint

**What:** Pioneer's `/descriptors/decode` + `/descriptors/sign` are 404 in prod,
so the vault stopped calling them. `needsBlindSigning` is now keyed off a
**vendored `firmwareClearSigns` allowlist** that mirrors the device's own
`ethereum_contractHandled` pins (THOR/Maya router deposit, 0x proxy, standard
ERC-20 transfer/approve, addLiquidityETH). Also adds the
`POST /eth/clearsign/load-signer` REST route.

**Where:** vault `#337` (MERGED, develop) —
`/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/projects/keepkey-vault/src/bun/calldata-decoder.ts`,
`rest-api.ts`, `SigningApproval.tsx`, `engine-controller.ts`, `FirmwareDropZone.tsx`.

## Test
- Unit: `cd /Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/projects/keepkey-vault && bun test __tests__/firmware-clearsign-gate.test.ts` (7/7 — spoof guard, wrong-address rejection, ERC-20 path).
- Device (rc7): drive real EVM txs and watch the trust badge / blind-sign gate.

## Verify
- [ ] THOR/Maya router **deposit** → clear-signs (trust badge "known").
- [ ] Same deposit selector to a **different** address → blind-signs ("unknown").
- [ ] Standard 68-byte ERC-20 transfer/approve → clear-signs.
- [ ] Uniswap/1inch/relay (firmware-unknown) → blind-signs, **not** falsely "known".
- [ ] `FirmwareDropZone`: flashing against a **wallet-mode** device is blocked
until it reports `bootloaderMode=true` (no stalled HID freeze).

## Status / gotchas
- MERGED to develop but **allowlist was never device-verified** — confirm on rc7
that the vendored pins actually match what the firmware clear-signs.
- Supersedes the old `EVM_INSIGHT` flag-gated Pioneer path (removed in the #342
merge reconciliation).
</content>
27 changes: 27 additions & 0 deletions docs/handoff-testing/03-emulator-deadclick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# 03 — Emulator never-dead-click

**What:** `initEmulator()` caught every dylib-load failure and returned a normal
`EmulatorStatus{state:'error'}` object; the RPC handlers forwarded that as a
*successful* response, so the UI silently reverted (a dead click, real error
stranded in console). Now the handlers throw and the UI surfaces the error.

**Where:** vault `#338` (MERGED, develop) —
`/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/projects/keepkey-vault/src/bun/index.ts`
(`emulatorInit`/`emulatorSwitchWallet`/`emulatorImportWallet` throw),
`src/mainview/components/DeviceGrid.tsx` (`handleStartEmu` surfaces any
non-running result).

## Test (needs a FAILING emulator to see the value)
1. Install a **stale/incompatible** dylib (e.g. one missing `kkemu_start`) at
`~/.keepkey/emulator/libkkemu.dylib`.
2. Click **Start** on the emulator card in Vault.

## Verify
- [ ] A red error banner appears with the real reason (e.g. `Symbol "kkemu_start"
not found` / `kkemu_init returned N`) — **not** a silent revert.
- [ ] With a good dylib, Start still boots the emulator normally.

## Status / gotchas
- This is exactly the bug that masked the earlier `kkemu_start` mismatch —
before the fix it just dead-clicked.
</content>
33 changes: 33 additions & 0 deletions docs/handoff-testing/04-emulator-capture-seedreveal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# 04 — Emulator capture-frame + seed-reveal/version tooling

**What:** emulator-only dev tooling — grab the live OLED as a PNG (visual proof
for automated test drivers) and reveal the active flash's saved seed / show
version controls.

**Where:** vault `#339` (MERGED, develop) —
`/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/projects/keepkey-vault/src/bun/emulator-window.ts`
(`captureCurrentFrame` + `/_emu/capture` bridge), `index.ts`
(`emulatorCaptureFrame`, `emulatorRevealSeed` RPCs), `rest-api.ts`
(`POST /emulator/capture`, auth'd, `engine.isEmulator`-gated),
`DeviceSettingsDrawer.tsx`.

## Test
- Capture (used already this session to verify the identity logo):
`POST http://localhost:1646/emulator/capture` with a bearer token → returns
`{ dataUrl }` (PNG). Example driver:
`projects/keepkey-sdk/tests/evm-clearsign/_capture-load.js` pattern (removed;
reconstruct from git if needed).
- Seed reveal: DeviceSettingsDrawer → reveal seed (emulator wallet only).

## Verify
- [ ] `POST /emulator/capture` returns a valid PNG data URL of the current OLED.
- [ ] `emulatorRevealSeed` shows the active flash's saved mnemonic; **rejects on
a real device** (`engine.isEmulator` gate).
- [ ] Version/seed controls in DeviceSettingsDrawer work; the two prior
race-condition fixes hold (stale revealed seed on wallet-switch/wipe;
concurrent mutating actions mutually exclusive).

## Status / gotchas
- REST capture route is registered manually (not in tsoa swagger) — probe it,
don't expect it in `/spec/swagger.json`.
</content>
25 changes: 25 additions & 0 deletions docs/handoff-testing/05-loadsigner-confirm-button.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# 05 — LoadClearsignSigner emulator confirm button

**What:** the `/eth/clearsign/load-signer` route called `loadClearsignSigner()`
directly, unlike every other signing route which wraps in `emuWrap()`. Loading a
signer raises a mandatory on-device "Trust identity" confirm — on the emulator
that button press must be armed via `emuWrap`, or the OLED shows the trust screen
but **no green approve button ever appears and the call hangs**. Now wrapped.
`emuWrap` is a no-op on real hardware.

**Where:** vault `#341` (MERGED, develop) —
`/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/projects/keepkey-vault/src/bun/rest-api.ts`
(the `/eth/clearsign/load-signer` handler now `emuWrap(() => wallet.loadClearsignSigner(...))`).

## Test
- Emulator + rc7: run `clearsign-signer-flows.js` (handoff 01/08). The load step
hits this path.

## Verify
- [ ] On the emulator, the "Trust identity 'Pioneer'" load screen shows a
clickable **green approve button** (armed) — the load does not hang.
- [ ] Real device (rc7): physical button confirms the load as before.

## Status / gotchas
- Prerequisite for testing handoff 01 on the emulator (without it the load hangs).
</content>
30 changes: 30 additions & 0 deletions docs/handoff-testing/06-idletimeout-consecutive-sign.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 06 — Signing idle-timeout fix (consecutive signs)

**What:** `Bun.serve` had no `idleTimeout` → default 120s. A human-gated sign
blocks the response while the user confirms; on the SECOND consecutive sign the
wait exceeded the socket idle window, Bun closed the connection
(`other side closed`), aborting the in-flight sign mid-confirm (device returned
home). Set `idleTimeout: 0` — device signing must not time out at the socket.

**Where:** vault `#342` (OPEN) —
`/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/projects/keepkey-vault/src/bun/rest-api.ts`
(`Bun.serve({ idleTimeout: 0, … })`). Test helper: `CLEARSIGN_FLOW=<key>` runs a
single flow in `clearsign-signer-flows.js`.

## Test
- Emulator + rc7, Vault with #342: run the FULL 3-flow suite (no `CLEARSIGN_FLOW`):
`node tests/evm-clearsign/clearsign-signer-flows.js`.

## Verify
- [ ] All **3 consecutive** flows (aave-supply, erc20-transfer,
erc20-approve-unlimited) sign in one run — the 2nd no longer hangs /
`other side closed`.
- [ ] Each single flow via `CLEARSIGN_FLOW=<key>` also passes (already confirmed
erc20-transfer + approve-unlimited individually this session).

## Status / gotchas
- **Root cause vs symptom:** idle-timeout removes the socket-close *symptom*. If
the 2nd sign STILL hangs (no close, just stuck), there's a deeper emulator
poll-thread/transport state bug — that was the original "busy/queue" report and
is NOT yet root-caused. Confirm 3-in-a-row genuinely completes before closing.
</content>
32 changes: 32 additions & 0 deletions docs/handoff-testing/07-icon-encoder-tooling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 07 — Clear-sign icon encoder + catalog tooling

**What:** turn any protocol/identity logo into the KeepKey 1bpp mono-RLE bitmap
the OLED renders (`draw_bitmap_mono_rle`), ≤384 B, ≤64×64. The encoder owns only
the RLE codec (must match the firmware decoder byte-for-byte) and self-verifies
every output by round-tripping through a decoder mirror; ImageMagick does the
resize/center/threshold.

**Where:** vault `#342` (OPEN) —
`/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/projects/keepkey-vault/scripts/clearsign-icons/`
(`encode-icon.mjs`, `build-catalog.mjs`, `README.md`, `sources/`, `generated/`).

## Test
- Codec self-test: `cd .../scripts/clearsign-icons && bun encode-icon.mjs --self-test`.
- One image: `bun encode-icon.mjs sources/pioneer.png --json`.
- Batch: `bun build-catalog.mjs` (encodes `sources/*` → `generated/protocol-icons.json`).
- ASCII-preview to eyeball a shape: see the `rleDecode` one-liner in the README.

## Verify
- [ ] `--self-test` prints the exact expected byte stream + round-trip OK.
- [ ] Pioneer compass encodes ≤384 B at 40×40 and previews as a clean compass.
- [ ] End-to-end: the generated `identity-icons.json` icon renders correctly on
the device (covered by handoff 01) — proves the encoder matches firmware.
- [ ] An oversized/detailed logo fails with a clear ">384B" message (not silent).

## Status / gotchas
- Confirm-column width is 40px → generate confirm icons at **40px** (not the
handoff's aspirational 48). Boot-review (bigger) can use larger later.
- To add a real protocol logo: drop `sources/<key>.png`, run `build-catalog.mjs`.
- Per-tx **protocol** glyphs (Aave/Uniswap beside the method) are a separate
transient path — tooling produces them, wiring is a follow-up.
</content>
28 changes: 28 additions & 0 deletions docs/handoff-testing/08-sdk-clearsign-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# 08 — keepkey-sdk clear-sign test train

**What:** the runtime-signer clear-sign test suite (recovered from untracked
files): shared blob builder + offline parity gate + on-device flows.

**Where:** vault `#340` (MERGED, develop) —
`/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/projects/keepkey-sdk/tests/`
(`_clearsign.js`, `clearsign-offline-parity.js`,
`evm-clearsign/{clearsign-signer-flows,loadsigner-sign-flows,relay-v2-schema-flow}.js`,
`fixtures/clearsign-golden.json`).

## Test
- Offline (no device): `cd .../projects/keepkey-sdk && node tests/clearsign-offline-parity.js`.
- On-device (rc7): `KEEPKEY_API_KEY=… node tests/evm-clearsign/clearsign-signer-flows.js`
(self mode; `CLEARSIGN_MODE=pioneer` mode is dead until Pioneer /sign returns).

## Verify
- [ ] Offline parity: **51/51** catalog flows match python-keepkey @1545299
(blob sha256+len + JS sighash) — already green this session.
- [ ] On-device self mode: load signer → 3 flows sign, no raw hex (ties into
handoffs 01/06).

## Status / gotchas
- `CLEARSIGN_MODE=pioneer` calls `/api/v1/descriptors/sign` which is 404 in prod
— only `self` mode is viable now.
- The test now sends the Pioneer identity icon + `persist:true` (handoff 01/07);
`CLEARSIGN_NO_ICON=1` for the text-only path.
</content>
32 changes: 32 additions & 0 deletions docs/handoff-testing/09-perf-telemetry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 09 — Vault↔API perf telemetry

**What:** split perceived-slow portfolio loads into API vs network/client time.
Server stamps `serverMs`/`traceId` on `POST /portfolio` and exposes
`POST /api/v1/telemetry/vault`; the vault times every `GetPortfolioBalances`
(wrapped once on the pioneer client singleton) and posts
`{traceId, serverMs, clientTotalMs, outcome, …}`; backend computes
`networkMs = clientTotalMs − serverMs`.

**Where:**
- pioneer `#164` (MERGED) — server stamp + ingest.
- vault `#334` (MERGED, develop) —
`/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/projects/keepkey-vault/src/bun/perf-telemetry.ts`
+ `pioneer.ts` hook; tests `__tests__/perf-telemetry.test.ts`.

## Test
- Unit: `cd .../projects/keepkey-vault && bun test __tests__/perf-telemetry.test.ts` (11/11).
- Data-flow: run a Vault build with #334 against a pioneer that has #164 deployed
with the `/api/v1/telemetry/vault` route live; load a portfolio a few times.

## Verify
- [ ] Records batch + flush to `POST /api/v1/telemetry/vault` (fire-and-forget —
a failed flush must never block/error a load).
- [ ] Backend joins on `traceId` and reports `networkMs`/`serverMs` split.
- [ ] Outcome classification: ok / slow (>3s) / degraded / timeout / error.
- [ ] `appVersion` matches the shipped build; endpoint no-ops gracefully until
the pioneer ingest is deployed.

## Status / gotchas
- Both halves merged; the **pioneer prod deploy of the ingest endpoint** + a
dashboard read endpoint are the remaining pieces.
</content>
24 changes: 24 additions & 0 deletions docs/handoff-testing/10-ruji-dashboard-icon.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# 10 — RUJI dashboard icon (CDN)

**What:** RUJI showed a broken "?" icon on the dashboard. Two causes: (1) the
icon was never uploaded to the coin-icon CDN, and (2) `assetData.json` keyed RUJI
under the old CAIP (`cosmos:thorchain-1/slip44:ruji`) while the runtime CAIP is
`cosmos:thorchain-mainnet-v1/denom:x/ruji`. Uploaded `ruji.png` to DO Spaces
under **both** base64 keys (200 now).

**Where:** CDN only (no code change). Source PNG:
`/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-website-v7/public/images/chains/ruji.png`.
CDN keys: `coins/Y29zbW9zOnRob3JjaGFpbi1tYWlubmV0LXYxL2Rlbm9tOngvcnVqaQ.png` +
`coins/Y29zbW9zOnRob3JjaGFpbi0xL3NsaXA0NDpydWpp.png`.

## Test / Verify
- [ ] `curl -sIL https://api.keepkey.info/coins/Y29zbW9zOnRob3JjaGFpbi1tYWlubmV0LXYxL2Rlbm9tOngvcnVqaQ.png`
→ 200 image/png (both keys).
- [ ] RUJI shows its real logo on the Vault dashboard (no "?" box) — next load,
no rebuild needed.

## Status / gotchas
- Dashboard `<Image>` tags have no `onError` fallback (unlike `AssetIcon.tsx`) →
a missing CDN icon renders the browser's raw broken-image glyph. Separate
follow-up if you want a graceful letter-bubble there too.
</content>
30 changes: 30 additions & 0 deletions docs/handoff-testing/11-rujira-thornode-failover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 11 — Rujira THORNode failover

**What:** `intergrations/rujira/src/index.ts` hardcoded a single THORNode host
(`thornode.thorchain.liquify.com`) for FIN contract smart-queries. That host is
dead (connection refused) with no fallback → **every** Rujira FIN quote (RUJI,
TCY swaps) failed. Added the same 2-host failover the main `thorchain`
integration already uses.

**Where:** pioneer `#165` (MERGED) —
`.../projects/pioneer/modules/intergrations/rujira/src/index.ts`
(`THORNODE_HOSTS = [thornode.thorchain.network, rest.cosmos.directory/thorchain]`,
`smartQuery` loops hosts).

## Test
- Needs a pioneer build/deploy with #165 (`make start` in the pioneer monorepo),
then a RUJI or TCY swap quote through the vault.

## Verify
- [ ] RUJI → (USDC/BTC) and TCY swap **quotes return** (no "Unable to fetch
pools" / empty quote from the FIN path).
- [ ] Both failover hosts serve the cosmwasm smart-query (verified live this
session: `thornode.thorchain.network` returns out-of-gas simulate,
`rest.cosmos.directory/thorchain` returns `{returned,fee}`).

## Status / gotchas
- The "thorchain: Unable to fetch pools" you saw may have been this FIN-path
failure surfacing under a generic label (prod's main `/thorchain/pools` tested
healthy). Retry a RUJI swap after the pioneer deploy to confirm.
- Rujira FIN is gated behind `FEATURE_RUJIRA_SWAPS` (api-blue only).
</content>
34 changes: 34 additions & 0 deletions docs/handoff-testing/12-emulator-abi-graft.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 12 — Firmware emulator-ABI graft (testable dylib)

**What:** the clear-sign firmware line (RC6) and the emulator-dylib ABI line
(`kkemu_start`, poll thread) had **diverged** — neither branch had both, so an
emulator built from the clear-sign branch was missing `kkemu_start` (dead click,
handoff 03). Cherry-picked the 4 emulator-ABI commits (#249–252) onto the
clear-sign branch so the feature is emulator-testable. Those commits touch
`lib/emulator/*` only (no-op for device firmware).

**Where:** firmware `feat/clearsign-persistent-identity-icons` /
`release/7.15.0-rc7` (`BitHighlander/keepkey-firmware`). Submodule at
`/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/modules/keepkey-firmware`.

## Test / build
```
cd /Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11/modules/keepkey-firmware
git checkout release/7.15.0-rc7 # (or feat/clearsign-persistent-identity-icons)
cd /Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault-v11
make build-emulator # installs ~/.keepkey/emulator/libkkemu.dylib
```
then **reload the emulator in Vault**.

## Verify
- [ ] `nm -gU ~/.keepkey/emulator/libkkemu.dylib | grep kkemu_start` → present
(all 12 `kkemu_*` FFI symbols the vault requires).
- [ ] Emulator boots in Vault; clear-sign firmware (`signed_metadata.c`) is
compiled in (handoffs 01/05 exercise it).

## Status / gotchas
- This is the **prerequisite** for emulator-testing handoffs 01/03/04/05.
- The device firmware build ignores these commits (emulator-only files); they're
cleanly separable if the eventual PR wants the feature without the emu graft.
- device-protocol pinned to fork `33521a8` (msg-117 icon fields).
</content>
Loading