chore: bump Actions to Node-24 majors + repair Playwright loopback / takeover test debt#3
Merged
Merged
Conversation
GitHub forces all Node 20 actions to Node 24 on 2026-06-02. Updating every `uses:` reference in `.github/workflows/ci.yml` to a major that already ships `using: node24` (verified via `repos/<action>/contents/ action.yml?ref=<tag>`), so CI emits zero Node 20 deprecation warnings and won't break at the cutover. - actions/checkout@v4 -> @v6 (4x) - actions/setup-python@v5 -> @v6 (4x) - actions/setup-node@v4 -> @v6 (2x) - actions/upload-artifact@v4 -> @v7 (1x) Job `name:` lines untouched -> branch-protection required checks (`Backend lint and scoped tests`, `Frontend type and unit tests`, `Playwright loopback`, `AI merchant scenarios`) remain intact. Phase: v1.2 / 11-ci-node-upgrade Plan: 11-01 Requirements: TECH-NODE-01, TECH-NODE-02
…uster A) src/vocalize/dialogue/user_channel.py:597 now enqueues (text, lang, passthrough_id), but three test assertion sites still compared against the legacy 2-tuple and failed locally + in CI: - tests/test_dialogue_user_channel.py::test_user_takeover_text_routes_to_takeover_queue - tests/test_dialogue_user_channel.py::test_takeover_text_emits_takeover_passthrough_transcript - tests/test_server_ws_integration.py::test_user_takeover_text_reaches_runner_takeover_queue Replace the 2-tuple equality with an explicit unpack so the new contract is named (not silently discarded with `_`), plus a non-empty-string assertion on passthrough_id where the test sees it. Phase: v1.2 / 12-test-debt-repair / 12-01-PLAN Requirements: TECH-PY-01
…r C)
Under Playwright the loopback runner (tests/integration/b2_loopback_server.py)
hit `DialogueOrchestratorError('illegal transition collecting → task_planning:
loopback-e2e')` in many parallel browser contexts, cascading the
`playwright-loopback` CI job. Pytest exercises a different code path
(`task_description` pre-set ⇒ `_run_audio_loopback` direct assignment)
so the issue did not reproduce locally.
The driver is a test scaffold whose sole purpose is to push `phase_change`
events to the client UI. Making `_transition` swallow `DialogueOrchestratorError`
keeps the UI driven forward without weakening the production state
invariant (which still raises on illegal transitions wherever it matters).
Production source unchanged.
Phase: v1.2 / 12-test-debt-repair / 12-02-PLAN
Requirements: TECH-PW-01, TECH-PW-03
DGPisces
added a commit
that referenced
this pull request
May 19, 2026
) * chore(13): scrub personal email from tracked files Replace gaodingyun2@gmail.com with the GitHub noreply address (40358663+DGPisces@users.noreply.github.com) across the four tracked files where it appeared: - README.md (invite-request line; full invite section removed later in this phase) - README.zh-CN.md (mirror of above) - SECURITY.md (vulnerability-report backup channel) - pyproject.toml (package authors metadata) The noreply address routes through GitHub without exposing the real mailbox, which is the standard OSS-maintainer privacy pattern. The real address is already hidden at account level (GitHub `Keep my email addresses private` is on; `gh api user` returns email: null). Phase: v1.2 / 13-working-tree-cleanse (cluster 1/3 — email scrub) Requirements: PRIV-NOW-01, PRIV-NOW-02 * chore(13): scrub personal domain from tracked files Replace every reference to the personal Cloudflare-tunneled hostname (vocalize.dgpisces.com / vocalize-api.dgpisces.com / *.dgpisces.com) and the personal tunnel alias (dgpisces-server1) with reserved-example placeholders, so the public working tree contains no personal-domain identifiers (PRIV-NOW criterion #3 + 'Cloudflare Tunnel config contains placeholder values only'). Substitution rules - api.example.com ← vocalize-api.dgpisces.com (reserved per RFC 2606) - vocalize.example.com ← vocalize.dgpisces.com - your-tunnel-name ← dgpisces-server1 (Cloudflare alias) - shared design system ← dgpisces design system (CSS attribution) - Apple-style design tokens ← dgpisces Apple-style tokens Code defaults turned empty (env required) - `_DEFAULT_PROD_ORIGINS` in `src/vocalize/server/__init__.py` is now `[]`; non-localhost deployments MUST set `VOCALIZE_CORS_ORIGINS`. Docstring updated. Existing CORS-wildcard guard already raises if the operator sets a permissive value, so behavior on misconfiguration is fail-closed. Pytest sanity check - `tests/test_app_startup_guards.py` (the only test touching these URLs) still passes locally (8/8 green) after the substitution. Phase: v1.2 / 13-working-tree-cleanse (cluster 2/3 — domain scrub) Requirements: PRIV-NOW-03, PRIV-NOW-04, PRIV-NOW-05 * chore(13): remove invite-token gate from backend, frontend, tests, and docs v1's shared `X-Invite-Token` gate (D-08) was a private-beta access control that no longer fits a public self-deploy posture. Self-deploy operators now restrict reachability at the network/proxy layer; per-user authentication remains v1.x scope (requirement AUTH-01). Backend - src/vocalize/server/sessions.py: drop `_check_invite_token` and the `Depends(_check_invite_token)` on `POST /api/sessions`; drop now-unused imports (`Depends`, `Header`, `secrets`, `status`). - src/vocalize/config.py: drop `invite_token` field and its env wiring. - src/vocalize/server/__init__.py: drop `VOCALIZE_INVITE_TOKEN` from the docstring; drop `X-Invite-Token` from `allow_headers`. Frontend - frontend/lib/api.ts: drop `inviteToken()` + `X-Invite-Token` injection in `createSession`; bundle no longer reads `NEXT_PUBLIC_VOCALIZE_INVITE_TOKEN`. `tsc --noEmit` is clean. Tests - tests/test_invite_token_gate.py: deleted (160 LOC) — entire suite validated the now-removed gate. - tests/test_app_startup_guards.py: drop `VOCALIZE_INVITE_TOKEN` envvar monkeypatch in 4 fixtures; update CORS preflight tests to assert `Content-Type` (the remaining `allow_header`). Env / scripts / install - .env.example, infra/pi-orchestrator/.env.template: drop `VOCALIZE_INVITE_TOKEN` and `NEXT_PUBLIC_VOCALIZE_INVITE_TOKEN` lines. - scripts/smoke.sh: drop `TOKEN` resolution and `X-Invite-Token` header on `POST /api/sessions`. - scripts/stability-24h-driver.py: drop `invite_token` arg threading across `one_cycle`, `fetch_metrics_snapshot`, and `main`; drop env resolution and the non-localhost requirement check. - install/pi-install.sh: drop `VOCALIZE_INVITE_TOKEN` from the operator reminder; advertise `VOCALIZE_CORS_ORIGINS` instead. Docs - README.md / README.zh-CN.md: remove the "Why VocalizeAI is invite-only" section entirely; remove the `VOCALIZE_INVITE_TOKEN` env table row. - SECURITY.md: rewrite "Access posture" to describe the self-deploy expectation (operator-managed network restriction). Drop the shared-invite-token "Known limitations" subsection. Drop invite-token steps from the emergency-rollback runbook. - docs/architecture.md: drop `X-Invite-Token` from the end-to-end flow, REST surface, and design-decisions sections; mark D-08 as retired with a short pointer to the new self-deploy posture. - docs/deploy/local.md, docs/deploy/pi.md: drop the `VOCALIZE_INVITE_TOKEN` / `NEXT_PUBLIC_VOCALIZE_INVITE_TOKEN` env table rows, the localhost-dev shortcut paragraph, and the curl example that injected a token; replace with a short note about the v1 self-deploy auth posture. - docs/release/24h-stability-evidence.md: drop the `export VOCALIZE_INVITE_TOKEN=<token>` line from the historical driver-command record. - CONTRIBUTING.md: drop the `add X-Invite-Token gate` example commit message. Verification - `git ls-files | xargs grep -liE "x-invite-token|invite_token|invite-only|invite only"` returns zero hits — P13 success criterion #4 satisfied verbatim. - pytest tests/ (excluding the two known-red Cluster B files left for a later session) passes 100%; tests/test_app_startup_guards.py 8/8 green after the gate removal. Phase: v1.2 / 13-working-tree-cleanse (cluster 3/3 — invite gate removal) Requirements: SELF-INVITE-01..07 * chore(13): drop noreply email entirely; route contact through GitHub Even GitHub-noreply addresses surface a numeric account ID and create a mail relay. Per maintainer preference, the public repo should not expose any email at all — security and general contact route through GitHub's own channels. - pyproject.toml: drop `email = "<noreply>"` from `authors`; PEP 621 treats email as optional on author entries. - SECURITY.md: rewrite "Reporting a vulnerability" to make GitHub Private Vulnerability Reporting the sole private channel. When PVR is not yet enabled, instruct reporters to open a public issue titled exactly "Private security contact request" (no technical details) so the maintainer can respond with a private channel out-of-band. The shared-token recovery runbook lower in the file was already cleaned up in the gate-removal commit (`63f251a`). Net effect: `git grep -E "gaodingyun|noreply\.github\.com|40358663"` on the working tree returns zero hits. Phase: v1.2 / 13-working-tree-cleanse (follow-up to 5d16753) * chore(13): drop SECURITY.md; route all contact through GitHub Issues VocalizeAI is a self-deploy project — every operator runs their own backend on their own infrastructure, so there is no central instance to defend and no maintainer-side embargo window that needs a private disclosure channel. Each operator is responsible for their own deployment's security; security-relevant findings should be public so every operator can pick up the fix. Removes: - SECURITY.md (its content has been superseded by the self-deploy posture; the threat-model summary it carried is already mirrored in docs/architecture.md "Security Posture"). - install/public-allowlist.md: SECURITY.md entry. Updated references → GitHub Issues: - README.md / README.zh-CN.md "Security" section: rewrite to explain the self-deploy posture and direct reporters to GitHub Issues. - CONTRIBUTING.md: (a) security-related contribution intro now says "flag in the PR description"; (b) "Issue triage / vulnerability reporting" section says self-deploy ⇒ all reports go via Issues; (c) Code-of-Conduct dispute escalation now routes through Issues instead of email-via-SECURITY. - docs/architecture.md: drop the "see SECURITY.md" pointers in the REST surface, Security Posture intro, and Further Reading list. - .github/ISSUE_TEMPLATE/bug_report.yml: the "for security vulnerabilities, see SECURITY.md" preamble becomes "self-deploy ⇒ file here". Note: also disabled GitHub Private Vulnerability Reporting via `gh api -X DELETE repos/.../private-vulnerability-reporting`. It was briefly enabled earlier in this session before the self-deploy decision was confirmed. CHANGELOG.md retains the historical line listing "OSS launch with SECURITY.md, ..." — that is a record of what shipped in a past tag and is intentionally left intact. Phase: v1.2 / 13-working-tree-cleanse (follow-up)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bundles two phases of v1.2 work needed to land Phase 11 before GitHub's 2026-06-02 forced Node-24 migration:
Phase 11 — ci-node-upgrade
Every action in
.github/workflows/ci.ymlis bumped to the latest major that shipsusing: node24(verified againstrepos/<action>/contents/action.yml?ref=<tag>):actions/checkout@v4@v6actions/setup-python@v5@v6actions/setup-node@v4@v6actions/upload-artifact@v4@v7Job
name:values are untouched — branch-protection required checks (Backend lint and scoped tests,Frontend type and unit tests,Playwright loopback,AI merchant scenarios) remain intact.Phase 12 — test-debt-repair (partial: clusters A + C)
src/vocalize/dialogue/user_channel.py:597now enqueues(text, lang, passthrough_id). Three test assertion sites still compared against the legacy 2-tuple and failed in CI. They now explicitly unpack three elements and assertpassthrough_idis a non-emptystr.LoopbackRunner._transitionintests/integration/b2_loopback_server.pyraisedDialogueOrchestratorError('illegal transition collecting → task_planning: loopback-e2e')across many parallel browser contexts, cascading theplaywright-loopbackjob. The driver now catches the error and still emitsphase_changeso the client UI continues to advance. Production state-machine invariants are unchanged.Cluster B (7 deeper
test_server_ws_integration.py::test_runner_*/test_ws_integration_*failures) is deferred — these tests are excluded from CI today by the backend job's-kfilter, so they do not gate this PR. Phase 12 success criteria around removing the-kfilter and re-addingplaywright-loopbackto required-status checks are tracked for follow-up.CI evidence (run
26083731795)All four required jobs pass:
1m41s)Zero
Node.js 20 actions are deprecatedannotations on the run.Hard deadline
2026-06-02 — GitHub forced Node-20→Node-24 migration. This PR must merge before then.
Test plan
mainpush CI run.