Firefox demo launcher release

The LandWeave Demo Launcher is distributed as a Mozilla-signed, unlisted Firefox extension. It is not discoverable through AMO search. Managed demos distribute the reviewed XPI from /auth/demo-launcher-extension/; the login page shows the install link only in desktop Firefox when both LMSTOOL_DEMO and DEMO_MULTI_ACCOUNT_LAUNCHER_ENABLED are true. The route returns HTTP 404 in other installations. Other browsers receive a link to install desktop Firefox. Firefox still requires the user to approve its installation prompt.

Release inputs

Prepare releases from the exact clean commit intended for deployment. Confirm that manifest.json and package.json have the same new version. The Firefox extension source is in tools/firefox-demo-launcher/.

Mozilla API credentials are owner-private workstation data. Store them at ~/.local/state/lmstool-demo/amo-signing.json with mode 0600:

{
  "api_key": "JWT issuer",
  "api_secret": "JWT secret"
}

Never put these values, a reviewer ticket, or a one-time login URL in Git, shell arguments, issue reports, or release notes.

1. Validate and build

From tools/firefox-demo-launcher/ run:

npm test
npm run lint
npm audit --omit=dev --audit-level=high
npm run build
unzip -l web-ext-artifacts/lmstool_demo_launcher-VERSION.zip
sha256sum web-ext-artifacts/lmstool_demo_launcher-VERSION.zip

The archive must contain only the manifest, extension source, and icon. Record lint warnings and both runtime-only and full dependency-audit boundaries. Do not use npm audit fix --force.

Before submission, repeat the real visible Firefox ESR acceptance against a disposable managed HTTPS demo. Verify role order, separate containers, reload, one-role sign-out isolation, container reuse, malformed and invalid tickets, permission denial, token replay and expiry, extension storage, and safe logs. Record the known browser-history behavior rather than claiming that token URLs are removed.

2. Prepare reviewer access

Create a bounded reviewer ticket on a synthetic managed demo. Seven days and ten launches are suitable defaults:

./.venv/bin/python -m ops.demo.manager \
  --host ADMIN@DEMO_HOST \
  ticket create demo_NAME \
  --accounts viewer,editor_1,reviewer,approver \
  --label "Mozilla AMO review VERSION" \
  --expires-minutes 10080 \
  --max-launches 10

Save AMO metadata in an owner-private 0600 JSON file outside the repository. Its version.approval_notes must provide the exact HTTPS demo origin, raw reviewer ticket, role order, expected container behavior, expiry and launch limit. It must also disclose that the ticket is sent to the selected demo, only the last successful origin is retained by extension storage, and Firefox history may retain consumed one-time login URLs.

{
  "version": {
    "approval_notes": "Reviewer instructions and private ticket"
  }
}

3. Submit once

Read the credential JSON in a short Python wrapper, place api_key and api_secret only in the child process environment as WEB_EXT_API_KEY and WEB_EXT_API_SECRET, and execute:

./node_modules/.bin/web-ext sign \
  --channel unlisted \
  --source-dir . \
  --artifacts-dir web-ext-artifacts \
  --amo-metadata /PRIVATE/PATH/amo-review-metadata.json \
  --ignore-files tests package-lock.json package.json README.md \
  --no-input \
  --no-config-discovery \
  --approval-timeout 120000

Do not pass API credentials as command-line arguments. A timeout while waiting for approval does not mean submission failed. Record the AMO add-on and version IDs, then inspect that existing version before retrying. Never submit the same version again while it is pending.

4. Confirm and retrieve approval

Approval is complete only when the AMO version has a non-null review timestamp and its file status is public. The developer version page is the primary operator check. The API download URL for an unlisted file may return HTTP 404 without the developer JWT; download through the authenticated developer page or an authenticated API request.

Compare the downloaded bytes with the API's SHA-256. Inspect the XPI as a ZIP and require Mozilla signature entries, including META-INF/cose.sig and META-INF/mozilla.rsa:

sha256sum /PRIVATE/PATH/launcher-signed.xpi
unzip -l /PRIVATE/PATH/launcher-signed.xpi | grep META-INF

Copy the verified file to tools/firefox-demo-launcher/releases/landweave_demo_launcher-VERSION-signed.xpi. Update DEMO_LAUNCHER_EXTENSION_FILENAME and the expected SHA-256 assertion in apps/authentication/tests/test_views.py. Keep only reviewed signed releases in that directory.

5. Validate and deploy

Run the authentication view tests and extension tests. Install the repository release XPI normally, not as a temporary add-on, in the supported Firefox ESR and repeat the visible container acceptance. Only then merge and deploy the application release to the managed demo.

On the deployed demo login page in desktop Firefox, confirm the install link is visible and opens Firefox's installation confirmation instead of downloading an ordinary attachment. In another browser, confirm that Firefox installation guidance replaces the XPI link. Download /auth/demo-launcher-extension/, compare its SHA-256 with the reviewed file, and install that downloaded copy in Firefox ESR. Confirm that the same route is HTTP 404 on a non-demo installation and on a demo where the multi-account launcher is disabled.

For version 0.1.0, AMO version 6488526 was approved at 2026-09-15 20:06:18 UTC. Its reviewed XPI SHA-256 is 847d0294ce7ba8213455eb48172b33bf0a52e7716122f2fd7d012690b3f50e83.

Version 0.1.1 introduced the LandWeave display name while retaining the stable extension ID for upgrades. Mozilla approved its unlisted signed XPI on 2026-09-16. Its reviewed SHA-256 is 0980b567f31c6e2947a82a3a32668b107e5bc508970d3197e1215bc99a73b482.