5e00956236877ed187ec625fd1e4ccdeced44ceb
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5e00956236 |
test: containerized Firefox end-to-end harness (closes #184)
check / check (push) Successful in 30s
Drives the real popup in a real Firefox with dist/firefox/ installed as an unpacked MV2 temporary add-on, via geckodriver. Covers popup load, wallet creation through the UI, and the Add Token screen. Outside make check, like the Chrome suite. Zero npm dependencies: tests/e2e/firefox/driver.js is a WebDriver client over global fetch and child_process against geckodriver's HTTP API. The Dockerfile pins the node base image, the Firefox 153.0.3 tarball and geckodriver 0.36.0 by digest. Errors are read from the privileged nsIConsoleService in Marionette's chrome context, filtered to non-warning entries whose sourceName is the extension origin. BiDi log.entryAdded delivers nothing at all for extension pages, so a Playwright-BiDi or Puppeteer-BiDi harness would see nothing and report success; the code says so where someone would be tempted to simplify it. Errors logged during add-on install and background startup are drained and folded into step 1, never discarded: a throw at the top of src/background/index.js kills the background page and fails the run. Content-script capture is left as unverified, because --network none leaves no http:// page for a content script to be injected into. Each drain reads the console and clears it in ONE chrome script. Splitting the read from Services.console.reset() left a window between the two round trips in which an error was logged into a buffer about to be discarded, and destroyed unread rather than deferred to the next drain; a probe of 100 sequenced throws at 20ms spacing lost one. With the drain atomic the same probe accounts for every throw that falls inside the observed window, on two consecutive runs. No driver layer is shared with the Chrome suite and the three UI steps are written twice deliberately: the two backends have no common substrate, and three steps do not pay for a shim. Two limits are documented rather than papered over, with measurements rather than absolutes. Error capture is poll-based, so an error is attributed to a step and not to a moment within it; the drained window ends ~1.5s after the last step returns (a 500ms settle, a 1000ms sleep and two drain round trips), and that cut-off jitters run to run — three runs of throws at fixed offsets reported everything up to +1.5s and one of the three also reported +1.6s. Inside the window the atomic drain leaves no race, but nsIConsoleService keeps a ring buffer of only 250 messages, so more than 250 console messages between two drains evicts unread errors: 400 throws inside one step report as exactly the newest 250, on three runs, while occupancy in a clean run peaks at 4 of 250 at the install drain and 0 at every later drain. Nothing is stubbed; the container runs with --network none instead, which proves no request escaped, cannot report which were attempted, and runs only the failure branches of network-dependent code. |
||
|
|
86cdea5e4e |
chore: repo policy compliance sweep — test rerun, frozen lockfile, documented targets (closes #166)
check / check (push) Has been cancelled
|
||
|
|
e9fa8bec47 |
build: assert DEBUG is off in every emitted bundle as a post-build check (closes #170)
check / check (push) Successful in 18s
build.js records which emitted bundles contain src/shared/constants.js, and constants.js carries a marker constant-folded from DEBUG itself. script/verify-build cross-checks the two and fails on every way of not knowing, so deleting the __BUILD_DEBUG__ define now breaks the build instead of shipping a live debug branch. |
||
|
|
e8ad8325c8 |
test: containerized Chrome end-to-end harness that drives the real popup (closes #181)
check / check (push) Has been cancelled
Runs the real popup in a pinned containerized Chrome and fails on any uncaught page error or console.error. Also fixes the two defects it caught: the missing showView import in addToken.js and the missing addressDotHtml import in transactionDetail.js. closes #150 closes #151 |
||
|
|
f7f141a757 |
security: make DEBUG a build-time flag defaulting to off (closes #149) (#169)
check / check (push) Has been cancelled
Fixes the highest-severity item in the repo: `src/shared/constants.js` had `const DEBUG = true;`, so `generateMnemonic()` returned the publicly committed `DEBUG_MNEMONIC` for every wallet created from a build of `main`, and the real entropy path was dead code in every artifact we could produce. ## What changed **`build.js`** — `AUTISTMASK_DEBUG` is read from the environment and injected as a `__BUILD_DEBUG__` entry in the existing esbuild `define` map, next to the other `__BUILD_*__` defines. Only the exact value `1` enables it; unset, empty, `true`, or a typo all yield a release build, so the insecure direction requires a deliberate opt-in and any mistake fails safe. The build prints `Build mode: release (DEBUG off)` or `Build mode: DEBUG (INSECURE - hardcoded test mnemonic, do not ship)`. **`src/shared/constants.js`** — `DEBUG` now uses the same `typeof` guard that `src/shared/buildInfo.js` already uses for the other build-time defines, and defaults to `false` when the define is absent (jest, plain `require`). `DEBUG_MNEMONIC` stays in the tree and stays exported. **`Makefile`** — new `build-debug` target (`AUTISTMASK_DEBUG=1` + the same build) so a debug build stays a one-liner for development. **`README.md`** — new "Debug Builds" subsection under Getting Started, and the DEBUG Mode Policy section now states that `DEBUG` is build-time-only and spells out the boundary against the runtime toggle. **`tests/wallet.test.js`** — new, covering both build modes. **`TODO.md`** — refreshed in the same commit (details at the bottom). No new `if (DEBUG)` branch was added and nothing about what DEBUG *does* changed: still exactly the red banner plus the hardcoded test phrase, per the README DEBUG Mode Policy and `RULES.md:76-80`. ## The interaction with the #145 settings toggle This is the subtle part, so spelling out the reasoning. There are two distinct debug flags in the tree after #145: 1. the compile-time `DEBUG` constant from `constants.js`, and 2. the runtime `debugMode` state flag, which the settings easter egg toggles and which `settings.js:379` pushes into `log.js` via `setRuntimeDebug()`. `log.js` merges them: `isDebug()` is `DEBUG || _runtimeDebug`. That merged value feeds exactly two things — the log level threshold (`log.js:24`) and the red banner (`views/helpers.js:71`). Making the banner user-toggleable is the intended behavior of #145, and this PR leaves it alone. `generateMnemonic()` does **not** consult `isDebug()`. It reads the compile-time `DEBUG` binding directly. That distinction is what makes a release build coherent: with `__BUILD_DEBUG__` false, `DEBUG` is false in the bundle, so no amount of clicking the version ten times and flipping the toggle can reach `return DEBUG_MNEMONIC`. The user can turn the banner and verbose logging on in a release build; they cannot turn the hardcoded phrase on. The failure mode to guard against is someone later "tidying up" the two flags by routing `wallet.js` through `isDebug()`, which would silently reintroduce this exact vulnerability with the runtime toggle as the trigger. Three things now guard that: a comment at the `wallet.js` call site saying it must stay the compile-time constant and why, the same statement in the README DEBUG Mode Policy, and a regression test that calls `setRuntimeDebug(true)`, asserts `isDebug()` is genuinely true, and then asserts `generateMnemonic()` still returns fresh entropy. I considered instead making the runtime toggle unavailable in release builds, but rejected it: that removes a feature #145 deliberately added, and it defends the wrong boundary. The banner is not the dangerous part; the mnemonic path is, and that one is already unreachable. ## Verification `make check` — green, 5 suites, 55 tests, plus lint and fmt-check. It also ran via the pre-commit hook on the commit itself. The new tests, per the verification standard in the manager comment on the issue (not just `a !== b`) — with the flag off: two successive `generateMnemonic()` calls differ, both pass `isValidMnemonic`, both are 12 words, neither equals `DEBUG_MNEMONIC`, and the result derives a usable HD wallet (`xpub` + a well-formed first address), so a broken implementation returning a counter or a truncated phrase would fail. Same assertions again with the runtime toggle forced on. With the flag on (`__BUILD_DEBUG__` defined before a `jest.resetModules()` re-require): `DEBUG` is `true` and `generateMnemonic()` returns `DEBUG_MNEMONIC`, so the debug path is proven working rather than silently deleted. Build artifacts — `make build` and `make build-debug` both produce `dist/chrome` and `dist/firefox` successfully. Grepping the minified bundles for the emitted `DEBUG` export value across all four bundles (chrome popup, chrome background, firefox popup, firefox background): # after make build $ grep -roh 'DEBUG:![01]' dist/chrome dist/firefox | sort | uniq -c 4 DEBUG:!1 # after make build-debug $ grep -roh 'DEBUG:![01]' dist/chrome dist/firefox | sort | uniq -c 4 DEBUG:!0 `!1` is minified `false`, `!0` is `true`. Also checked the fail-safe path: `AUTISTMASK_DEBUG=true make build` prints `Build mode: release (DEBUG off)` and likewise yields `4 DEBUG:!1`. One thing a reviewer should know about the grep: the `DEBUG_MNEMONIC` string literal is still present in the release bundle. That is not a leak of anything (the phrase is in this public repo already) and it does not mean the branch is live — esbuild cannot tree-shake a CommonJS `module.exports` object, so the constant survives while `DEBUG` folds to `false`. The compiled function is `function PL(){return ML?UL:f_.fromEntropy(globalThis.crypto.getRandomValues(new Uint8Array(16))).phrase}` where `ML` is the `DEBUG:!1` export. So "the phrase string is absent" is *not* the right test for a release build; "the exported `DEBUG` is `!1`" is, which is what I checked. ## `TODO.md` refresh Per the manager comment: Status rewritten (no branch in flight — `feat/issue-144-settings-about` landed as #145, scripts-to-rule-them-all landed as #148, so the `scripts/` question is resolved; `make check` recorded as verified green on `main` at `23aeae4`); the completed "Verify main passes make check" Future Step removed; Future Steps rewritten against the #149-#168 backlog in rough priority order, keeping branch pruning (now #167) and the pre-1.0 security review (noting #149 and #157 are parts of it but it is broader). One deliberate deviation to flag rather than bury: the manager asked that Next Step become this issue. Taken literally against the Workflow section, this commit *completes* #149, which would normally move it into Completed Steps. I followed the repo's existing convention for in-flight work instead — the previous Next Step was phrased as "Land feat/issue-144-settings-about", so Next Step is now "Land #149 ... PR open, awaiting review", which is accurate until this merges. Whoever merges should move it to Completed Steps and promote the first Future Step. Happy to change it if the reviewer prefers the strict reading. ## Out of scope `script/lint` being `prettier --check` only and unable to catch undefined identifiers (#152) — noted in the TODO but not fixed here; I greped for `DEBUG` consumers by hand rather than relying on lint, as advised. Nothing else in the DEBUG consumer set (`log.js`, `helpers.js`, `state.js`, `settings.js`) changed behavior. Co-authored-by: sneak <sneak@sneak.berlin> Reviewed-on: #169 Co-authored-by: clawbot <clawbot@noreply.example.org> Co-committed-by: clawbot <clawbot@noreply.example.org> |
||
|
|
d046a24115 |
scripts-to-rule-them-all (#148)
check / check (push) Successful in 5s
Reviewed-on: #148 Co-authored-by: sneak <sneak@sneak.berlin> Co-committed-by: sneak <sneak@sneak.berlin> |
||
|
|
e41efc969d |
Use make targets exclusively in Getting Started
check / check (push) Successful in 11s
Add make install target wrapping yarn install. The Makefile is the authoritative interface for all repo operations. |
||
|
|
065f0eaa81 |
Add project scaffolding
check / check (push) Successful in 10s
Makefile, Dockerfile, CI workflow, prettier config, manifests for Chrome (MV3) and Firefox (MV2), source directory structure, and minimal test suite. All checks pass. |