Found by the pre-1.0 deployability audit (#303). Blocker: there is no path by which the owner installs this once and keeps using it.
Checked exhaustively, all negative:
.gitea/workflows/ holds only check.yml and e2e.yml; neither uploads an artifact.
No zip/crx/xpi/pack target in Makefile, script/, package.json or Dockerfile.
git grep -niE '(web-ext|xpi|crx|\.pem|amo|addons\.mozilla|chrome web store|update_url|code.?sign)' returns exactly one hit: a comment at tests/e2e/firefox/driver.js:166 saying no XPI and no signing are involved.
manifest/chrome.json has no key and no update_url.
One tag exists, v0.1.0, and it is not an ancestor of HEAD — 246 commits back; git describe --tags fails outright.
Chrome
README.md:44-45 documents Load unpacked from dist/chrome/. With no key in the manifest, the extension ID is derived from the absolute directory path, so moving or re-cloning the checkout yields a different ID and therefore a different chrome.storage.local partition — the wallet silently reads as empty. No update channel, and a Developer-mode nag on every browser start. (Absence of key verified directly; the ID-derivation consequence is documented Chrome behaviour, not tested here — see the DoD.)
Firefox
README.md:46-47 documents Load Temporary Add-on as the only route. Release Firefox and ESR enforce signing with no working override, and this repo produces no XPI and has no signing key or AMO tooling, so on release Firefox this cannot be permanently installed at all. A temporary add-on is unloaded when Firefox exits — the repo says so itself at tests/e2e/firefox/driver.js:167 ("the add-on dies with the profile"). Daily use means re-adding it by hand from about:debugging on every browser start.
manifest/firefox.json:22-26 does carry a stable gecko.id, which is the right shape for storage to survive a re-add, but no test asserts that the vault survives an add-on removal and re-add — and that is exactly the property that must hold before real money goes in.
Related: dist/constants-bundles.txt and dist/styles.css sit at dist/ root, outside both browser directories, so a naive zip of dist/chrome/ would miss them. Version is triplicated and unwired — manifest/chrome.json:4 and manifest/firefox.json:4 (both hardcoded 0.1.0, copied verbatim by build.js:198-205) and package.json:3 (a separate source feeding the About screen); nothing checks they agree. BUILD_COMMIT (build.js:63,71) has no dirty check, so a build from a modified tree stamps a clean hash.
Definition of done
A release entrypoint produces a versioned, self-contained artifact per browser, with everything the browser needs inside the archive.
manifest/chrome.json carries a fixed key, so the extension ID and its storage partition are stable across checkout moves and re-clones.
Firefox ships a signed XPI (AMO self-distribution is sufficient), or the README states plainly that Firefox requires Developer Edition or Unbranded and that a temporary add-on does not survive a restart.
One version source of truth; the build fails if the manifests and package.json disagree. BUILD_COMMIT marks a dirty tree as dirty.
Test on the pinned Firefox harness: install, create a wallet, uninstall, re-install, assert the vault is still there.
Test: two unpacked Chrome loads from different paths in one profile, asserting whether storage is shared — documenting the real behaviour either way.
make check green.
Note: tagging a release and publishing to AMO are outward-facing acts and are sneak's call, not the implementer's. This issue covers producing and verifying the artifact, not publishing it.
Found by the pre-1.0 deployability audit (https://git.eeqj.de/sneak/AutistMask/issues/303). **Blocker: there is no path by which the owner installs this once and keeps using it.**
Checked exhaustively, all negative:
- `.gitea/workflows/` holds only `check.yml` and `e2e.yml`; neither uploads an artifact.
- No zip/crx/xpi/pack target in `Makefile`, `script/`, `package.json` or `Dockerfile`.
- `git grep -niE '(web-ext|xpi|crx|\.pem|amo|addons\.mozilla|chrome web store|update_url|code.?sign)'` returns exactly one hit: a comment at `tests/e2e/firefox/driver.js:166` saying no XPI and no signing are involved.
- `manifest/chrome.json` has **no `key`** and no `update_url`.
- One tag exists, `v0.1.0`, and it is **not an ancestor of HEAD** — 246 commits back; `git describe --tags` fails outright.
## Chrome
`README.md:44-45` documents Load unpacked from `dist/chrome/`. With no `key` in the manifest, the extension ID is derived from the absolute directory path, so **moving or re-cloning the checkout yields a different ID and therefore a different `chrome.storage.local` partition — the wallet silently reads as empty.** No update channel, and a Developer-mode nag on every browser start. (Absence of `key` verified directly; the ID-derivation consequence is documented Chrome behaviour, not tested here — see the DoD.)
## Firefox
`README.md:46-47` documents **Load Temporary Add-on** as the only route. Release Firefox and ESR enforce signing with no working override, and this repo produces no XPI and has no signing key or AMO tooling, so **on release Firefox this cannot be permanently installed at all.** A temporary add-on is unloaded when Firefox exits — the repo says so itself at `tests/e2e/firefox/driver.js:167` ("the add-on dies with the profile"). Daily use means re-adding it by hand from `about:debugging` on every browser start.
`manifest/firefox.json:22-26` does carry a stable `gecko.id`, which is the right shape for storage to survive a re-add, but **no test asserts that the vault survives an add-on removal and re-add** — and that is exactly the property that must hold before real money goes in.
Related: `dist/constants-bundles.txt` and `dist/styles.css` sit at `dist/` root, outside both browser directories, so a naive zip of `dist/chrome/` would miss them. Version is triplicated and unwired — `manifest/chrome.json:4` and `manifest/firefox.json:4` (both hardcoded `0.1.0`, copied verbatim by `build.js:198-205`) and `package.json:3` (a separate source feeding the About screen); nothing checks they agree. `BUILD_COMMIT` (`build.js:63,71`) has no dirty check, so a build from a modified tree stamps a clean hash.
## Definition of done
- [ ] A release entrypoint produces a versioned, self-contained artifact per browser, with everything the browser needs inside the archive.
- [ ] `manifest/chrome.json` carries a fixed `key`, so the extension ID and its storage partition are stable across checkout moves and re-clones.
- [ ] Firefox ships a signed XPI (AMO self-distribution is sufficient), **or** the README states plainly that Firefox requires Developer Edition or Unbranded and that a temporary add-on does not survive a restart.
- [ ] One version source of truth; the build fails if the manifests and `package.json` disagree. `BUILD_COMMIT` marks a dirty tree as dirty.
- [ ] Test on the pinned Firefox harness: install, create a wallet, uninstall, re-install, assert the vault is still there.
- [ ] Test: two unpacked Chrome loads from different paths in one profile, asserting whether storage is shared — documenting the real behaviour either way.
- [ ] `make check` green.
Note: tagging a release and publishing to AMO are outward-facing acts and are sneak's call, not the implementer's. This issue covers producing and verifying the artifact, not publishing it.
clawbot
added this to the 1.0.0 milestone 2026-08-20 11:59:45 +02:00
Implementation requirements, so the implementer does not stall on the two choices in here.
Chrome key. Generate an RSA keypair; commit only the public key as manifest/chrome.json's key field — that alone pins the extension ID and its chrome.storage.local partition across checkout moves, which is the DoD item. The private .pem is a credential: it must NOT be committed, must not be generated into the working tree by any build target, and CRX packing/publishing is sneak's call, not this unit's. Say in the PR body where a packer would expect the private key to come from.
Firefox. Do not attempt AMO — self-distribution needs credentials this unit does not have. Take the documented fallback: produce an unsigned XPI as the artifact, and state plainly in README.md that release Firefox and ESR will refuse it, that Developer Edition or Unbranded is required, and that a temporary add-on does not survive a browser restart. If AMO signing is wanted for 1.0, that is a separate issue and sneak's decision — flag it in your return message rather than filing it yourself.
Everything else on the DoD is unambiguous. Two things not to lose: the artifact must be self-contained, so dist/constants-bundles.txt and dist/styles.css living at dist/ root outside both browser directories must be handled rather than silently dropped by a naive zip; and the version unification must actually fail the build when manifest/chrome.json, manifest/firefox.json and package.json disagree, not merely read from one place.
Implementation requirements, so the implementer does not stall on the two choices in here.
**Chrome `key`.** Generate an RSA keypair; commit **only the public key** as `manifest/chrome.json`'s `key` field — that alone pins the extension ID and its `chrome.storage.local` partition across checkout moves, which is the DoD item. The private `.pem` is a credential: it must NOT be committed, must not be generated into the working tree by any build target, and CRX packing/publishing is sneak's call, not this unit's. Say in the PR body where a packer would expect the private key to come from.
**Firefox.** Do not attempt AMO — self-distribution needs credentials this unit does not have. Take the documented fallback: produce an **unsigned** XPI as the artifact, and state plainly in `README.md` that release Firefox and ESR will refuse it, that Developer Edition or Unbranded is required, and that a temporary add-on does not survive a browser restart. If AMO signing is wanted for 1.0, that is a separate issue and sneak's decision — flag it in your return message rather than filing it yourself.
Everything else on the DoD is unambiguous. Two things not to lose: the artifact must be self-contained, so `dist/constants-bundles.txt` and `dist/styles.css` living at `dist/` root outside both browser directories must be handled rather than silently dropped by a naive zip; and the version unification must actually fail the build when `manifest/chrome.json`, `manifest/firefox.json` and `package.json` disagree, not merely read from one place.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found by the pre-1.0 deployability audit (#303). Blocker: there is no path by which the owner installs this once and keeps using it.
Checked exhaustively, all negative:
.gitea/workflows/holds onlycheck.ymlande2e.yml; neither uploads an artifact.Makefile,script/,package.jsonorDockerfile.git grep -niE '(web-ext|xpi|crx|\.pem|amo|addons\.mozilla|chrome web store|update_url|code.?sign)'returns exactly one hit: a comment attests/e2e/firefox/driver.js:166saying no XPI and no signing are involved.manifest/chrome.jsonhas nokeyand noupdate_url.v0.1.0, and it is not an ancestor of HEAD — 246 commits back;git describe --tagsfails outright.Chrome
README.md:44-45documents Load unpacked fromdist/chrome/. With nokeyin the manifest, the extension ID is derived from the absolute directory path, so moving or re-cloning the checkout yields a different ID and therefore a differentchrome.storage.localpartition — the wallet silently reads as empty. No update channel, and a Developer-mode nag on every browser start. (Absence ofkeyverified directly; the ID-derivation consequence is documented Chrome behaviour, not tested here — see the DoD.)Firefox
README.md:46-47documents Load Temporary Add-on as the only route. Release Firefox and ESR enforce signing with no working override, and this repo produces no XPI and has no signing key or AMO tooling, so on release Firefox this cannot be permanently installed at all. A temporary add-on is unloaded when Firefox exits — the repo says so itself attests/e2e/firefox/driver.js:167("the add-on dies with the profile"). Daily use means re-adding it by hand fromabout:debuggingon every browser start.manifest/firefox.json:22-26does carry a stablegecko.id, which is the right shape for storage to survive a re-add, but no test asserts that the vault survives an add-on removal and re-add — and that is exactly the property that must hold before real money goes in.Related:
dist/constants-bundles.txtanddist/styles.csssit atdist/root, outside both browser directories, so a naive zip ofdist/chrome/would miss them. Version is triplicated and unwired —manifest/chrome.json:4andmanifest/firefox.json:4(both hardcoded0.1.0, copied verbatim bybuild.js:198-205) andpackage.json:3(a separate source feeding the About screen); nothing checks they agree.BUILD_COMMIT(build.js:63,71) has no dirty check, so a build from a modified tree stamps a clean hash.Definition of done
manifest/chrome.jsoncarries a fixedkey, so the extension ID and its storage partition are stable across checkout moves and re-clones.package.jsondisagree.BUILD_COMMITmarks a dirty tree as dirty.make checkgreen.Note: tagging a release and publishing to AMO are outward-facing acts and are sneak's call, not the implementer's. This issue covers producing and verifying the artifact, not publishing it.
Implementation requirements, so the implementer does not stall on the two choices in here.
Chrome
key. Generate an RSA keypair; commit only the public key asmanifest/chrome.json'skeyfield — that alone pins the extension ID and itschrome.storage.localpartition across checkout moves, which is the DoD item. The private.pemis a credential: it must NOT be committed, must not be generated into the working tree by any build target, and CRX packing/publishing is sneak's call, not this unit's. Say in the PR body where a packer would expect the private key to come from.Firefox. Do not attempt AMO — self-distribution needs credentials this unit does not have. Take the documented fallback: produce an unsigned XPI as the artifact, and state plainly in
README.mdthat release Firefox and ESR will refuse it, that Developer Edition or Unbranded is required, and that a temporary add-on does not survive a browser restart. If AMO signing is wanted for 1.0, that is a separate issue and sneak's decision — flag it in your return message rather than filing it yourself.Everything else on the DoD is unambiguous. Two things not to lose: the artifact must be self-contained, so
dist/constants-bundles.txtanddist/styles.cssliving atdist/root outside both browser directories must be handled rather than silently dropped by a naive zip; and the version unification must actually fail the build whenmanifest/chrome.json,manifest/firefox.jsonandpackage.jsondisagree, not merely read from one place.