feat(simulator): v0.5.0 — BTC scenarios + firmware matrix + conventional-commits auto-tag#5
Conversation
…narios - BtcXpubZpubMainnet: BIP-84 native segwit zpub shape - BtcAddressP2WPKHMainnet: bech32 bc1q P2WPKH derivation - BtcAddressP2TRTaproot: bech32m bc1p P2TR derivation - BtcSignMessageMainnet: 64-byte sig + 65-byte electrum envelope - RootFingerprintDeterministic: pins 4c00739d (upstream fixture seed) - EthSignLegacyPolygonMultiByteV: actually exercises CC-5 v-byte path (the existing chainId=137 address probe never did — addresses don't depend on chainId) Plus simulator.Connect helper (extracted from cmd/bitbox-simulator-check) so the integration test, CLI, and any future consumer share the exact Noise XX + channel-hash-verify bring-up. Integration test now runs the full BaselineScenarios set on every push, surfacing any firmware drift or scenario regression at testkit CI time instead of consumer time. Fake TS proxy: add clearCalls, ignore symbol-keyed lookups, return undefined for then/catch/finally so awaiting the proxy does not infect chains as thenable. quirks.test.ts now reads quirks.json directly to stay self-consistent across releases instead of needing a hardcoded count bump every time.
The umlaut-rejection scenario's payload had three literal non-ASCII bytes (ü, ß, ü) in a raw-string Go const, which the audit's quirk-E1 regex flagged as a critical finding when self-auditing the testkit. Encoding them as JSON ü / ß keeps the SOURCE pure ASCII while the JSON parser inside the BitBox SDK still resolves them to the exact same UTF-8 bytes a literal "ü" would produce — the scenario still exercises the firmware reject path. Removes 3 false-positive critical findings from the testkit's own action-selftest job, and from any consumer who ever decides to point their bitbox-audit at the testkit source tree.
…RDING - bitbox-simulator-check gains --firmware <name|all>; LaunchVersion + ErrSimulatorNotFound let any caller pin a specific embedded build. - New CI job go-simulator-matrix drives the 14-scenario baseline against all 8 embedded firmwares (v9.19.0 → v9.26.1) in parallel on every push. Catches regressions that only surface on older firmwares still in the production tail — BitBox02 only auto-updates when the user opens the BitBoxApp. - bitbox-simulator composite action exposes firmware: input; slash template parses firmware=X and ref=Y modifiers + 'fail' shorthand. - Composite action defaults: bitbox-audit testkit-ref v0.2.0 → v0.5.0, bitbox-simulator v0.4.2 → v0.5.0. Workflow-templates bumped to match. - CHANGELOG backfilled for every version between v0.3.1 and v0.4.4 (previously only the v0.1.0/v0.2.0/v0.3.0/v0.3.1 entries existed) and the new v0.5.0 entry. - ONBOARDING gains a §6 simulator section covering the 14 baseline scenarios, matrix mode, slash trigger, and what the simulator validates vs. doesn't (transport still needs a real device).
- Drop the JSON \u-escape workaround in scenarios.go; the audit-skip-file marker TaprootFreak added in PR DFXswiss#2 is the right per-file opt-out for intentional non-ASCII test fixtures, and matches the pattern already used in core/guards/*.go. - Backfill CHANGELOG entries for v0.4.5 (Go module rename) and v0.4.6 (auto-tag + auto-release-pr + audit-skip-file). v0.5.0 entry now points at the DFXswiss release URL and references test.yaml (not test.yml). - ONBOARDING simulator example and ts/src/index.ts JSDoc now reference DFXswiss/bitbox-testkit consistently (ts/package.json was already at @DFXswiss).
Replaces the hardcoded PATCH+1 logic in .github/workflows/auto-tag.yaml with a small testable Go tool at go/cmd/release-version. The tool reads every commit subject + body between the last release tag and HEAD, parses them as Conventional Commits 1.0, and picks the highest bump: feat! / <type>! / BREAKING CHANGE: footer -> MAJOR feat: -> MINOR fix:, perf:, refactor:, revert: -> PATCH chore:, ci:, docs:, test:, style:, build: -> PATCH non-conventional subjects -> PATCH + warning A single feat! anywhere in the range promotes the whole release to a major bump; a single feat: promotes to minor. The aggregator is pure: 31 table-driven tests in main_test.go lock every classification arm + the SemVer math + the report shape consumers parse. The auto-tag workflow now surfaces the per-commit breakdown as a CI group so reviewers can see exactly which commit voted which way, and short-circuits cleanly (exit code 4) when the range is empty. CONTRIBUTING.md "Releases" rewritten with the new policy: a commit-message -> bump table, the local preview command, and the manual-release escape hatch for hotfixes. Practical effect for v0.5.0: the feat(simulator): commit in this PR will cause the auto-tagger to emit v0.5.0 (not v0.4.7) when the develop -> main release PR merges, with no manual tag intervention.
Maintainer-ReviewJoshua nicht erreichbar — Review + Maintainer-Edit selbst durchgeführt. Maintainer-Edit angewendetPR-Base von Lokale Validierung (vor Base-Switch)
Code-Review-ErgebnisStark — gehört in den Stack:
Minor observations (kein Blocker):
EmpfehlungMerge-Ready. PR ist auf dem Niveau, das wir für den BitBox-Stack haben wollen — Conventional-Commits-Auto-Tag wird ab v0.5.0 die Release-Mechanik korrekt steuern, Firmware-Matrix gibt uns Regression-Coverage über die echte Production-Verteilung. |
CHANGELOG had 13 release links pointing at github.com/joshuakrueger-dfx/bitbox-testkit/releases/tag/vX.Y.Z, but that account no longer hosts releases — every linked page 404s. The v0.4.5 entry also pointed at DFXswiss for a release that doesn't exist yet. All historical release links now point at DFXswiss/bitbox-testkit consistently; the actual GitHub-Release backfill for v0.3.2 → v0.4.5 is a separate maintenance task and doesn't gate the v0.5.0 cut. auto-tag.yaml now uses `git push --atomic` for the vX.Y.Z + go/vX.Y.Z pair. Without it, a partial push (server-side ref protection trip, network blip on the second ref) could leave the repo with one tag present and the other missing — and the next auto-tag run would fail the "tag exists" check while consumers' `go install ...@vX.Y.Z` would still 404 on the missing submodule tag. The --atomic flag tells the server to apply both updates as a single transaction or neither.
Tieferer Critical-Review — zwei zusätzliche Inkonsistenzen gefixtNach noch kritischerem Durchgang sind zwei reale Konsistenz-Probleme aufgefallen, die ich gleich mit-gefixt habe (Commit 1. CHANGELOG: 13 broken Release-Links → DFXswiss-Mirror konsolidiertCHANGELOG enthielt:
Sed-Replace auf Follow-up: Tags v0.3.2..v0.4.5 brauchen rückwirkende GitHub-Releases im DFXswiss-Mirror damit die Links auch wirklich funktionieren. Nicht Blocker für v0.5.0, separater Maintenance-Task. 2.
|
| Check | Result |
|---|---|
| YAML lint (9 files) | 9/9 ok |
| Go race tests | alle Pakete pass |
| TS tests | 40/40 |
| audit self-test | 0 findings |
CI auf 791f3db läuft.
Summary
Grows the simulator baseline from 9 to 14 scenarios, adds full Bitcoin coverage, pins the simulator's deterministic identity, exercises the actual EIP-155 multi-byte v path, introduces a firmware-matrix runner, and replaces the patch-only auto-tag bumper with a tested Conventional-Commits engine.
New scenarios
root_fingerprint_deterministic— pins simulator BIP-32 fingerprint to0x4c00739d. Acts as the canonical "seed drifted" signal so downstream pinned-output failures aren't N derived symptoms of one root cause.eth_sign_legacy_polygon_multibyte_v— actually drivesETHSign(chainId=137)to exercise EIP-155 multi-byte v (quirk CC-5). The pre-existingeth_address_polygon_multibyte_vonly queried an address, which is chain-id-independent and never tested the v-byte path.btc_xpub_zpub_mainnet— BIP-84 native-segwit ZPUB shape (zpub prefix + base58 length envelope).btc_address_p2wpkh_mainnet— bech32bc1q…atm/84'/0'/0'/0/0.btc_address_p2tr_taproot— bech32mbc1p…atm/86'/0'/0'/0/0(distinct firmware codepath: BIP-341 key tweak).btc_sign_message_mainnet— 64-byte R||S, recId 0..3, 65-byte Electrum envelope with header 31..34.New testkit API
simulator.LaunchVersion(cacheDir, name)+ErrSimulatorNotFoundto pin a specific embedded build.simulator.Connect(inst, ConnectOptions{HandshakeTimeout, Logger})— shared bring-up helper used by both the CLI and the integration test, replacing the per-callsite Noise+channel-hash dance.bitbox-simulator-check --firmware <name|all>flag andMatrixReportwire format. Single-firmware runs remain shape-compatible (MatrixReport.Reports[0]).New CI
go-simulator-matrixjob drives the 14-scenario baseline against all 8 embedded firmwares (v9.19.0 → v9.26.1) in parallel on every push. Catches regressions that only surface on older firmwares still in the production tail — the BitBox02 only auto-updates when the user opens the BitBoxApp.TestSimulatorBaselineScenariosintegration test runs the full baseline (was: Launch-only smoke test).Conventional-Commits auto-tag
go/cmd/release-versiontool (31 table-driven tests) parses every commit subject + body between the last tag and HEAD as Conventional Commits and picks the highest bump:feat!/BREAKING CHANGE:→ MAJOR,feat:→ MINOR, everything else → PATCH.auto-tag.yamlreplaces the hardcodedPATCH+1with the tool. Per-commit breakdown is surfaced as a CI log group so reviewers see exactly which commit drove the bump.develop→main, the auto-tagger sees thefeat(simulator):andfeat(release):commits and emitsv0.5.0automatically — no manual tag intervention needed.Action surface
bitbox-simulatorcomposite gainsfirmware:input.firmware=Xandref=Ymodifiers +failshorthand.v0.5.0; workflow-templates bumped to match.Hygiene
FakePairedBitBox: proxy ignores symbol-keyed lookups and returnsundefinedforthen/catch/finally, so awaiting the proxy doesn't infect the chain as thenable. NewclearCalls()resets the recorded call log mid-flight.Docs
Test plan
go test ./cmd/release-version/...— 31/31 greengo run ./cmd/release-version --base v0.4.6 --reportcorrectly picksv0.5.0from the actual commit range