diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20dc635..7595631 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,6 @@ name: CI on: - pull_request: workflow_dispatch: jobs: @@ -43,6 +42,3 @@ jobs: - name: Run compiler linker end-to-end tests run: npm run test:e2e:compiler - - - name: Run Firefox packaging smoke - run: npm run test:browser:firefox diff --git a/.github/workflows/release-on-version-change.yml b/.github/workflows/release-on-version-change.yml index 1468561..45f3237 100644 --- a/.github/workflows/release-on-version-change.yml +++ b/.github/workflows/release-on-version-change.yml @@ -65,10 +65,6 @@ jobs: if: steps.detect_version.outputs.changed == 'true' run: npm run test:e2e - - name: Run Firefox packaging smoke - if: steps.detect_version.outputs.changed == 'true' - run: npm run test:browser:firefox - - name: Package release artifacts if: steps.detect_version.outputs.changed == 'true' run: npm run package:release diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ab5fcc3..6c63cdc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -81,25 +81,6 @@ jobs: node-version-file: .nvmrc cache: npm - - name: Validate Firefox signing credentials - env: - AMO_JWT_ISSUER: ${{ secrets.AMO_JWT_ISSUER }} - AMO_JWT_SECRET: ${{ secrets.AMO_JWT_SECRET }} - run: | - missing=0 - case "$AMO_JWT_ISSUER" in - (*[![:space:]]*) ;; - (*) echo "::error title=Missing Firefox signing secret::AMO_JWT_ISSUER is not configured for the protected release workflow."; missing=1 ;; - esac - case "$AMO_JWT_SECRET" in - (*[![:space:]]*) ;; - (*) echo "::error title=Missing Firefox signing secret::AMO_JWT_SECRET is not configured for the protected release workflow."; missing=1 ;; - esac - if [ "$missing" -ne 0 ]; then - echo "Configure both protected AMO Actions secrets before rerunning the release." - exit 1 - fi - - name: Install dependencies run: npm ci @@ -124,18 +105,9 @@ jobs: - name: Run end-to-end tests run: npm run test:e2e - - name: Run Firefox packaging smoke - run: npm run test:browser:firefox - - name: Package release artifacts run: npm run package:release - - name: Sign Firefox unlisted XPI - env: - AMO_JWT_ISSUER: ${{ secrets.AMO_JWT_ISSUER }} - AMO_JWT_SECRET: ${{ secrets.AMO_JWT_SECRET }} - run: npm run sign:firefox:unlisted - - name: Publish GitHub release assets env: GH_TOKEN: ${{ github.token }} diff --git a/README.md b/README.md index b39fb94..b2711fe 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ An in-browser **C++20 IDE** delivered as a Chrome / Chromium extension. |---------|--------| | Editor | Monaco Editor (the engine behind VS Code) | | Compiler | WASM-native Clang (runs entirely in the browser, offline) | -| Terminal | xterm.js with a bash-like shell and live line input on Chromium and Firefox 153+ | -| File access | File System Access API on Chromium, fallback open/save/folder flows on Firefox | +| Terminal | xterm.js with a bash-like shell and live line input on Chromium; Firefox support is deprecated | +| File access | File System Access API on Chromium; Firefox fallback flows are deprecated | | File I/O | `fstream` / `ifstream` / `ofstream` – read and write workspace files at runtime | | Standards | C++14 · C++17 · **C++20** (selectable in the toolbar) | @@ -239,7 +239,9 @@ Full feature parity is supported for desktop Chrome, Edge, Brave, and Chromium when the browser is based on Chromium 105 or newer. Latest stable is recommended for release testing. -Firefox desktop can load the extension, but support remains experimental: +Firefox desktop support is deprecated. Existing Firefox users may still load the +extension while migrating to a Chromium-family browser, but Firefox is not a +supported release or deployment target: - compile/run, Monaco, and extension-runtime flows are supported - Firefox 153+ uses WebAssembly JSPI for live, line-buffered `std::cin`, @@ -249,8 +251,7 @@ Firefox desktop can load the extension, but support remains experimental: Chromium File System Access APIs - persistent folder write-back and directory-handle session restore may be reduced compared with Chromium-family builds -- public AMO publication is manual; the protected release workflow generates the - Mozilla-signed unlisted XPI for self-distribution +- Firefox deployment, AMO publication, and automated XPI signing are disabled Full parity requires: @@ -290,7 +291,7 @@ npm run test:browser:brave npm run test:browser:chromium ``` -Run the Firefox packaging smoke separately: +Firefox smoke validation is manual-only during the deprecation period: ```bash npm run test:browser:firefox @@ -370,18 +371,17 @@ npm run package:release This writes: - `release/browser-cpp-chromium-family-v.zip` for Chrome, Edge, Brave, and Chromium -- `release/firefox-unlisted/*.xpi` after the protected release workflow signs the Firefox unlisted build - `release/SHA256SUMS-v.txt` - `release/release-manifest-v.json` The release manifest tracks the browser package matrix: - Chrome, Edge, Brave, and Chromium map to the same Chromium-family ZIP -- Firefox has its own manifest, background entry, smoke-tested temporary package, and signing metadata +- Firefox remains in release metadata as a deprecated, non-publishable target Chrome, Edge, Brave, and Chromium still share the same MV3 payload. Firefox is -built from `dist-firefox/` as a separate payload because its manifest and -background model differ from Chromium; release distribution uses the signed XPI. +still built from `dist-firefox/` for transition testing because its manifest and +background model differ from Chromium, but no Firefox artifact is deployed. Store submission notes should state: @@ -402,16 +402,13 @@ Use `.github/workflows/release.yml` to publish one GitHub Release per 4. Cleans `dist/` and `release/` 5. Fetches the Clang toolchain 6. Runs lint, build, release validation, and E2E checks -7. Runs Firefox packaging smoke validation -8. Produces one Chromium-family ZIP plus checksums and release metadata -9. Signs the Firefox unlisted XPI with protected AMO credentials -10. Creates or updates GitHub Release `v` and uploads all files under `release/` +7. Produces one Chromium-family ZIP plus checksums and release metadata +8. Creates or updates GitHub Release `v` and uploads the maintained artifacts under `release/` Use `workflow_dispatch` with `force=true` to rebuild and re-upload assets for an existing release. The workflow does **not** publish directly to browser stores. Store publication and Chromium distribution remain human-owned steps. -Public AMO publication also remains human-owned even though the unlisted Firefox -XPI is signed automatically during release. +Firefox deployment is deprecated and is not part of this workflow. ### Human-owned deployment instructions @@ -471,19 +468,13 @@ Store compatibility plus Brave-specific validation. There is no official Chromium extension store in this workflow; Chromium is a manual/GitHub-distributed channel. -#### Firefox - -1. Run `npm run test:browser:firefox`. -2. Review `amo/metadata/listed.json` and update it if the release changes - Firefox-facing product behavior or listing copy. -3. For public AMO publication, build the Firefox package from `dist-firefox/`, then upload it with the metadata manually - through the owner-managed listing workflow. -4. For self-distribution, verify that the protected release workflow produced a - signed artifact under `release/firefox-unlisted/`. -5. Install the signed XPI in Firefox and complete the manual QA checklist - in `docs/firefox-stdin-runtime-acceptance.md`, paying special attention to - JSPI live stdin and the documented - workspace-persistence limitations. +#### Firefox (deprecated) + +Firefox deployment is suspended. Do not publish to AMO, configure AMO signing +secrets for normal releases, or distribute a Firefox XPI. If migration or +removal work requires a final compatibility check, run +`npm run test:browser:firefox` manually and use `dist-firefox/`; this is not a +release gate. ### Manual release QA checklist diff --git a/docs/release-playbook.md b/docs/release-playbook.md index 2333061..a0462c7 100644 --- a/docs/release-playbook.md +++ b/docs/release-playbook.md @@ -15,45 +15,53 @@ - cleans the release workspace - fetches the Clang WASM toolchain - runs lint, build, and E2E checks - - runs Firefox packaging smoke checks - packages one shared Chromium-family release ZIP and target metadata - uploads the artifacts for review ## Manual Release Flow - Review the uploaded artifacts and confirm the version bump is intentional. -- For Firefox, confirm the Firefox build and AMO/manual-submission metadata are ready before owner handoff. - Use the existing tag/manual release workflow for final publication. - Publish browser store listings and verify installed updates as required by the target browser. -- The protected release workflow signs the Firefox unlisted XPI with AMO credentials and uploads it with the other release assets. +- Firefox support and deployment are deprecated; it is not included in release artifacts or release gates. -### Firefox unlisted-signing credentials +### Firefox deprecation notice -The protected release workflow requires two GitHub Actions secrets before it -starts the release build: +**Status:** Deprecated as of 2026-09-05 -- `AMO_JWT_ISSUER` -- `AMO_JWT_SECRET` +**Replacement:** Chrome, Edge, Brave, or Chromium builds -Create the AMO API credential pair in Mozilla Add-ons, then store the values as -repository or protected release-environment secrets with these exact names. -Keep them unavailable to pull-request workflows, do not put them in source, -local release artifacts, or logs, and grant only the permissions required for -Firefox signing. The workflow checks only that each value is present and -non-blank; it never prints either value. +**Removal date:** Advisory; Firefox runtime/build code remains temporarily while +existing users migrate and ownership is assessed. -Rotate both secrets through Mozilla and GitHub when the credential expires or -is suspected to be exposed. After updating them, use -`workflow_dispatch` with `force=true` to rerun the protected release. The -workflow must fail before dependency installation when either secret is absent; -do not bypass signing or publish an unsigned XPI. If the preflight passes but -signing fails, inspect the protected workflow's AMO/web-ext error, correct the -credential or AMO configuration, and rerun the forced release. +Firefox is no longer a supported deployment target. Do not configure AMO +credentials for the normal release workflow, publish a Firefox package, or +expect a signed XPI in GitHub Releases. The existing Firefox build and signing +commands are transition tooling only and are not automated release steps. -## Firefox Verification Test Plan +If a maintainer needs a final compatibility check during migration, run +`npm run test:browser:firefox` manually. It is not a CI or release gate. -Use this plan before declaring Firefox support release-ready or bumping the -project version for a Firefox-supporting release. +The future removal follow-up must verify active Firefox usage and ownership, +provide migration guidance, then remove the Firefox runtime/build paths, tests, +signing tools, and documentation together. + +### General CI + +The general CI workflow is manual-only (`workflow_dispatch`) during this +transition. It does not run automatically on pull requests and does not run the +deprecated Firefox smoke test. Run it manually when validating a branch. + +### Deprecated Firefox signing credentials + +No AMO credentials are required by the normal release workflow. If the +transition tooling is used manually, keep any credentials outside the repository +and never expose them in pull-request workflows, source, artifacts, or logs. + +## Deprecated Firefox Verification Test Plan + +Use this only for migration or eventual removal work. It does not qualify +Firefox for release. ### Automated gates @@ -67,13 +75,10 @@ Run these commands from a clean checkout in order: 6. `npm run test:preflight-clang` 7. `npm run version:check` 8. `npm run release:check-version` -9. `npm run test:browser:firefox` -10. `npm run package:release` +9. `npm run package:release` Passing these gates proves that: -- Firefox-specific manifest generation succeeds -- the Firefox extension package passes `web-ext` lint/build smoke - release packaging emits one Chromium-family ZIP and a release manifest that maps Chrome, Edge, Brave, and Chromium to it - manifest/package metadata stay version-synchronized @@ -97,27 +102,25 @@ real Firefox desktop build: persistence behavior matches reality. 8. Restart Firefox and verify session/workspace restore behavior matches the documented limitations. -9. Install the signed Firefox XPI and repeat the compile/run sanity check. +9. Do not install or distribute a signed Firefox XPI; deployment is deprecated. ### Release decision -The Firefox release gate passes only when: +The deprecated Firefox migration check passes only when: -- every automated gate above succeeds +- every applicable automated gate above succeeds - manual Firefox runtime QA succeeds -- no new Firefox-only regressions are found in startup, compile/run, file - flows, or packaging +- no migration-blocking Firefox regressions are found in startup, compile/run, + or file flows - remaining Firefox limitations are already documented and match observed behavior -Do **not** cut the version bump for a Firefox-supporting release if only the -packaging smoke passes. Runtime validation in Firefox is still required. +Do **not** present this validation as evidence that Firefox is release-supported. ## Validation - `npm run lint` - `npm run build` - `npm run test:e2e` -- `npm run test:browser:firefox` - `npm run release:check-version` - `npm run package:release` diff --git a/manifest.json b/manifest.json index aadf546..f50295f 100644 --- a/manifest.json +++ b/manifest.json @@ -3,7 +3,7 @@ "name": "browser.cpp", "short_name": "browser.cpp", "description": "In-browser C++20 IDE powered by Monaco Editor and WASM Clang", - "version": "0.4.7", + "version": "0.4.8", "minimum_chrome_version": "105", "icons": { "16": "icons/icon16.png", diff --git a/package-lock.json b/package-lock.json index 255c6a4..8033747 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "browser.cpp", - "version": "0.4.7", + "version": "0.4.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "browser.cpp", - "version": "0.4.7", + "version": "0.4.8", "dependencies": { "@xterm/addon-fit": "^0.11.0", "@xterm/addon-web-links": "^0.12.0", diff --git a/package.json b/package.json index 045c8c7..2e5f5c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "browser.cpp", - "version": "0.4.7", + "version": "0.4.8", "description": "In-browser C++20 IDE with WASM Clang toolchain", "private": true, "scripts": { diff --git a/scripts/e2e-release-packaging.test.mjs b/scripts/e2e-release-packaging.test.mjs index 835d37c..a80c1e9 100644 --- a/scripts/e2e-release-packaging.test.mjs +++ b/scripts/e2e-release-packaging.test.mjs @@ -34,6 +34,20 @@ const releaseWorkflowPath = path.join( 'workflows', 'release.yml' ); +const ciWorkflowPath = path.join( + path.dirname(fileURLToPath(import.meta.url)), + '..', + '.github', + 'workflows', + 'ci.yml' +); +const releaseCandidateWorkflowPath = path.join( + path.dirname(fileURLToPath(import.meta.url)), + '..', + '.github', + 'workflows', + 'release-on-version-change.yml' +); function writeJson(filePath, value) { fs.mkdirSync(path.dirname(filePath), { recursive: true }); @@ -124,6 +138,17 @@ test('e2e: release workflow uploads files from nested release directories', () = assert.doesNotMatch(workflow, /gh release (?:upload|create)[\s\S]*release\/\*/); }); +test('e2e: deprecated Firefox is excluded from automated release workflows', () => { + const releaseWorkflow = fs.readFileSync(releaseWorkflowPath, 'utf8'); + const releaseCandidateWorkflow = fs.readFileSync(releaseCandidateWorkflowPath, 'utf8'); + const ciWorkflow = fs.readFileSync(ciWorkflowPath, 'utf8'); + + assert.doesNotMatch(releaseWorkflow, /AMO_JWT_|sign:firefox|test:browser:firefox/); + assert.doesNotMatch(releaseCandidateWorkflow, /test:browser:firefox/); + assert.match(ciWorkflow, /on:\n {2}workflow_dispatch:/); + assert.doesNotMatch(ciWorkflow, /pull_request:|test:browser:firefox/); +}); + test('e2e: release version sync fails on source manifest mismatch', () => { const repoRoot = makeRepoFixture(); writeJson(path.join(repoRoot, 'manifest.json'), { @@ -255,14 +280,15 @@ test('e2e: release packaging creates one Chromium-family artifact and target map const firefoxTarget = manifest.targets.find((target) => target.target === 'firefox'); assert.equal(firefoxTarget.publishable, false); + assert.equal(firefoxTarget.deprecated, true); assert.equal(firefoxTarget.packageStrategy, 'distinct'); assert.equal(firefoxTarget.fileName, null); assert.equal( firefoxTarget.blockReason, - 'Firefox unsigned ZIP generation is disabled; use the signed unlisted XPI.' + 'Firefox support and deployment are deprecated; no release artifact is generated.' ); - assert.equal(firefoxTarget.signing.listed, 'manual-owner-submission'); - assert.equal(firefoxTarget.signing.unlisted, 'required-release-artifact'); + assert.equal(firefoxTarget.signing.listed, 'deprecated'); + assert.equal(firefoxTarget.signing.unlisted, 'deprecated'); const chromiumTargets = ['chrome', 'edge', 'brave', 'chromium']; for (const targetKey of chromiumTargets) { diff --git a/scripts/package-extension-release.js b/scripts/package-extension-release.js index b0aa187..9a50040 100644 --- a/scripts/package-extension-release.js +++ b/scripts/package-extension-release.js @@ -293,6 +293,7 @@ function createReleaseArtifacts(options = {}) { artifactKey: target.artifactKey, payloadGroup: target.payloadGroup, publishable: target.publishable, + deprecated: target.deprecated || false, blockReason: target.blockReason || null, notes: target.notes, signing: target.signing || null, diff --git a/scripts/release-targets.js b/scripts/release-targets.js index 35c97e9..0818b45 100644 --- a/scripts/release-targets.js +++ b/scripts/release-targets.js @@ -24,18 +24,19 @@ const TARGETS = Object.freeze([ { key: 'firefox', label: 'Firefox', - channel: 'Firefox Add-ons / signed XPI', + channel: 'Deprecated Firefox support', packageStrategy: 'distinct', artifactKey: null, payloadGroup: 'firefox-webext', publishable: false, - blockReason: 'Firefox unsigned ZIP generation is disabled; use the signed unlisted XPI.', + deprecated: true, + blockReason: 'Firefox support and deployment are deprecated; no release artifact is generated.', signing: { - listed: 'manual-owner-submission', - unlisted: 'required-release-artifact', + listed: 'deprecated', + unlisted: 'deprecated', }, notes: - 'Firefox uses a browser-specific manifest, background script entry, and a separate packaging/signing flow.', + 'Firefox code and local validation remain temporarily for migration and possible future removal.', }, { key: 'brave', diff --git a/specs/issue-untracked-20260905-sdlc_planner-disable-firefox-deployment.md b/specs/issue-untracked-20260905-sdlc_planner-disable-firefox-deployment.md new file mode 100644 index 0000000..911afc3 --- /dev/null +++ b/specs/issue-untracked-20260905-sdlc_planner-disable-firefox-deployment.md @@ -0,0 +1,264 @@ +# Feature: Deprecate Firefox support and disable deployment + +## Feature Description + +Mark Firefox support as deprecated and remove it from automated release and CI +paths. Firefox-specific code and local validation may remain temporarily for +existing users and a possible future removal, but Firefox is no longer a +supported deployment target or a normal pull-request quality gate. Chromium- +family release artifacts and deployment behavior must remain unchanged. + +The repository's general CI workflow will become manually triggered only. The +release-candidate workflow must also stop treating Firefox validation as a +release gate. + +## User Story + +As a release maintainer +I want Firefox support and deployment clearly marked as deprecated +So that releases and routine CI focus on maintained Chromium-family targets +without implying Firefox receives ongoing support. + +## Problem Statement + +The protected release workflow currently requires `AMO_JWT_ISSUER` and +`AMO_JWT_SECRET`, runs Firefox packaging smoke validation, and signs an unlisted +XPI before uploading every release directory. The general CI workflow runs on +pull requests and includes Firefox smoke validation. README and the release +playbook describe Firefox as an active distribution channel. + +The release metadata already excludes Firefox from the publishable ZIP artifact +set, but the workflow still performs Firefox signing and publishes the resulting +XPI. This creates an unnecessary release dependency and leaves the deployment +state inconsistent across workflows, scripts, tests, and documentation. + +## Solution Statement + +1. Remove Firefox signing and Firefox deployment-specific steps from the + protected release workflow. +2. Change `.github/workflows/ci.yml` to `workflow_dispatch` only, removing its + automatic pull-request trigger and Firefox smoke step from routine CI. +3. Remove Firefox smoke validation from the release-candidate workflow so a + version-bump PR is not gated by deprecated Firefox support. +4. Update release metadata, tests, and documentation to identify Firefox as + deprecated and ensure releases contain only Chromium-family artifacts. +5. Retain Firefox source/runtime code and local commands temporarily, with a + documented follow-up path for complete removal after usage/ownership review. + +## Relevant Files + +- `.github/workflows/release.yml` - Remove AMO secret validation, Firefox signing, + and any release-upload assumptions tied to the signed XPI. +- `.github/workflows/release-on-version-change.yml` - Remove Firefox smoke + validation from release-candidate gating and keep candidate uploads limited to + maintained Chromium-family artifacts. +- `.github/workflows/ci.yml` - Change the trigger to `workflow_dispatch` only and + remove the Firefox smoke step from the manually run general CI workflow. +- `scripts/release-targets.js` - Represent Firefox as disabled for deployment with + an explicit stable reason and no publishable artifact contract. +- `scripts/package-extension-release.js` - Ensure release manifests, checksums, + stale-artifact cleanup, and payload handling cannot include Firefox deployment + artifacts. +- `scripts/e2e-release-packaging.test.mjs` - Update regression assertions for the + disabled deployment state and verify no Firefox asset is emitted. +- `scripts/sign-firefox-unlisted.mjs` and `scripts/sign-firefox-listed.mjs` - + Retain temporarily only as deprecated/manual tools, or remove them in a later + cleanup once Firefox users and maintainers have been assessed. +- `scripts/firefox-webext.js` - Retain shared Firefox build/smoke helpers if + Firefox validation remains supported. +- `package.json` - Keep Firefox commands only as explicitly deprecated/manual + commands during the transition; do not invoke them from automated release or + routine CI. +- `README.md` - Revise release workflow and Firefox deployment instructions to + state that automated deployment is disabled and remove obsolete AMO/XPI + release steps. +- `docs/release-playbook.md` - Document the disabled state, deferred re-enable + requirements, and the remaining Firefox validation path. + +### New Files + +None expected. + +## Implementation Plan + +### Phase 1: Foundation + +- Confirm the deprecation status, effective date, owner, and whether a future + removal date is advisory or compulsory. +- Identify the GitHub Issue that will be the source of truth. If none exists, + create one before implementation and link the eventual PR with `Closes #`. +- Inventory active Firefox consumers/owners as far as the repository can show and + document the migration target: Chromium, Edge, Brave, or Chromium builds. +- Assert the desired post-change contract: one Chromium-family ZIP, checksums, + and release manifest; no signed Firefox XPI or Firefox deployment metadata in + uploaded release directories. + +### Phase 2: Core Implementation + +- Update `.github/workflows/release.yml` to remove AMO credential validation, + Firefox smoke validation, and the `sign:firefox:unlisted` step. Keep the + normal build/package/release flow fail-closed for missing Chromium artifacts. +- Update `.github/workflows/ci.yml` so its only event is `workflow_dispatch` and + remove its Firefox smoke step. +- Update `.github/workflows/release-on-version-change.yml` to remove its Firefox + smoke step and ensure candidate uploads contain only maintained artifacts. +- Update release target metadata and packaging logic so Firefox is represented as + disabled/non-publishable without requiring `dist-firefox` for a deployable + release, while preserving Chromium-family payload generation. +- Add or revise release-package tests covering the absence of Firefox artifacts, + absence of AMO-signing requirements, and preservation of Chromium artifacts. +- Mark retained Firefox signing and smoke commands as deprecated/manual in + documentation and avoid adding new Firefox features during the deprecation + period. + +### Phase 3: Integration + +- Update the release-candidate workflow to match the deployment contract and + ensure artifact upload contains no Firefox deployment output. +- Do not run Firefox smoke testing in normal CI or release-candidate validation. + If a maintainer needs a final compatibility check, run it manually using the + existing command before removing the deprecated path. +- Update README and the release playbook, including the future re-enable checklist: + AMO credentials, signing workflow, artifact assertions, owner-managed AMO + submission, and manual Firefox runtime QA. +- Review generated release metadata and workflow logs for secret references, + stale XPI paths, and contradictory claims. + +## Step by Step Tasks + +### Step 1: Confirm scope and create the GitHub Issue + +- Confirm Firefox is deprecated, not merely deployment-disabled, and record the + deprecation date, owner, migration guidance, and any planned removal date. +- Confirm whether local `sign:firefox:*` commands remain temporarily available + as deprecated/manual tools or are removed in this change. +- Create or identify the GitHub Issue and record this plan and the decision + history there before implementation. + +### Step 2: Remove automated Firefox deployment + +- Remove the AMO secret preflight, Firefox smoke step, and protected `Sign Firefox + unlisted XPI` step from `.github/workflows/release.yml`. +- Remove assumptions that a signed XPI must be present for a normal release. +- Preserve release permissions and the GitHub Release publication for the + Chromium-family artifacts. + +### Step 3: Change CI and release-candidate triggers + +- Change `.github/workflows/ci.yml` from pull-request plus manual execution to + `workflow_dispatch` only. +- Remove the Firefox smoke step from `.github/workflows/ci.yml`. +- Remove the Firefox smoke step from `.github/workflows/release-on-version-change.yml`. +- Verify no automatic workflow still treats Firefox as a required quality gate. + +### Step 4: Align release metadata and packaging + +- Keep Firefox marked non-publishable with an explicit reason such as deployment + being suspended, not an obsolete reason about unsigned ZIP generation. +- Ensure `package:release` generates no Firefox ZIP/XPI and does not require + Firefox output solely for deployment. +- Prevent stale Firefox artifacts from being accidentally included in checksums + or uploaded release assets. + +### Step 5: Update regression tests + +- Revise `scripts/e2e-release-packaging.test.mjs` to assert the new disabled + deployment contract. +- Retain tests for Chromium artifact naming, checksums, release manifest + generation, and version synchronization. +- Retain Firefox compatibility/build tests only as local/deprecation coverage if + they still provide value; they must not be wired into automatic CI or release + gates. + +### Step 6: Update operator documentation + +- Add a clear Firefox deprecation notice to README and the release playbook, + including status, reason, effective date, owner, migration target, and whether + removal is planned. +- Remove instructions presenting Firefox as an active automated or owner-managed + deployment channel. +- Document that general CI is manually triggered and no longer validates Firefox + automatically. +- Ensure no documentation instructs maintainers to configure AMO secrets for the + normal release workflow while Firefox is deprecated. + +### Step 7: Validate the complete change + +- Run every command in the Validation Commands section. +- Inspect the release directory and generated release manifest to confirm no + Firefox deployment artifact is present. +- Review the workflow diff for removed secret exposure and unchanged Chromium + release behavior. +- Update the GitHub Issue with the implementation summary and open a PR linked + to the issue for human review. + +## Testing Strategy + +### Unit and integration tests + +- Release target metadata identifies Firefox as disabled/non-publishable. +- Release packaging emits only the Chromium-family ZIP, checksums, and release + manifest. +- Generated release metadata does not list Firefox as an emitted artifact. +- Chromium release targets, shared payload mapping, and version checks remain + unchanged. +- Firefox manifest generation and smoke/compatibility tests continue to pass if + runtime support remains active. + +### Edge Cases + +- A stale `release/firefox-unlisted/` directory exists before packaging. +- AMO secrets are absent: the release must no longer fail solely for that reason. +- A manually generated Firefox XPI exists locally: it must not be picked up by + automatic release upload or checksum generation. +- Release-candidate artifact upload must match production release artifact scope. +- Re-enabling deployment later must have an explicit, reviewable path rather than + relying on undocumented workflow restoration. + +## Acceptance Criteria + +- The protected release workflow completes without AMO secrets when all + Chromium-family release prerequisites are valid. +- Normal GitHub Releases contain no automated Firefox XPI or Firefox deployment + asset. +- Release checksums and manifests contain only approved Chromium-family + deployment artifacts. +- Firefox is explicitly marked deprecated in README and + `docs/release-playbook.md`, with migration guidance and ownership. +- `.github/workflows/ci.yml` runs only on manual `workflow_dispatch` and no + automatic workflow runs Firefox validation as a required gate. +- README and `docs/release-playbook.md` do not instruct maintainers to deploy + Firefox as part of normal release. +- Existing Chrome, Edge, Brave, and Chromium release behavior remains intact. +- The implementation is delivered through a feature branch and PR linked to a + GitHub Issue. + +## Validation Commands + +```bash +npm ci +npm run lint +npm run build +npm run test:e2e +npm run test:e2e:compiler +npm run release:check-version +npm run package:release +git diff --check +``` + +After packaging, inspect `release/` and the generated +`release/release-manifest-v.json`; assert that no Firefox XPI or Firefox +deployment artifact is present and that the Chromium-family ZIP exists. If the +deprecated Firefox path is being retained temporarily, run +`npm run test:browser:firefox` manually as an optional smoke check. + +## Notes + +- Firefox support is deprecated rather than immediately deleted; the follow-up + removal decision should verify active usage and ownership before deleting + Firefox runtime/build code. +- No repository changes beyond this plan document have been implemented. +- Existing unrelated/untracked files in `specs/` must be preserved. +- If a removal date is later approved, create a follow-up migration/removal plan + covering Firefox runtime compatibility, manifests, smoke tests, signing tools, + dependencies, and remaining user-facing claims.