Skip to content

chore(v1.2/P13): working-tree cleanse — email + domain + invite gate#4

Merged
DGPisces merged 5 commits into
mainfrom
chore/v1.2-working-tree-cleanse
May 19, 2026
Merged

chore(v1.2/P13): working-tree cleanse — email + domain + invite gate#4
DGPisces merged 5 commits into
mainfrom
chore/v1.2-working-tree-cleanse

Conversation

@DGPisces
Copy link
Copy Markdown
Owner

Summary

Phase 13 of v1.2 (privacy hardening) — three atomic commits, each landing one
slice of the working-tree cleanse so any single piece can be reverted alone:

  1. 5d16753 — Email scrub. Replace gaodingyun2@gmail.com with the
    GitHub noreply address (40358663+DGPisces@users.noreply.github.com)
    in README.md, README.zh-CN.md, SECURITY.md, and
    pyproject.toml.
  2. 7e822fc — Domain scrub. Substitute vocalize-api.dgpisces.com,
    vocalize.dgpisces.com, *.dgpisces.com, the dgpisces-server1
    tunnel alias, and the dgpisces design-system attributions with
    reserved-example placeholders or empty defaults. Code defaults that
    used to bake in the personal hostname (_DEFAULT_PROD_ORIGINS,
    DEFAULT_API_BASE) now require the operator to set the env var
    explicitly. tests/test_app_startup_guards.py (the only test
    touching these URLs) stays 8/8 green.
  3. 63f251a — Invite-token gate removal. Drop the v1 shared
    X-Invite-Token gate from backend (sessions.py, config.py,
    server/__init__.py), frontend (lib/api.ts), tests (delete
    test_invite_token_gate.py, update test_app_startup_guards.py),
    env templates (.env.example, infra/pi-orchestrator/.env.template),
    scripts (smoke.sh, stability-24h-driver.py), install
    (pi-install.sh), and docs (README × 2, SECURITY, architecture,
    deploy/local, deploy/pi, 24h-stability-evidence, CONTRIBUTING).
    D-08 is marked retired with a short pointer to the new
    self-deploy auth posture (operator restricts reachability at the
    network/proxy layer; per-user auth remains v1.x AUTH-01 scope).

ROADMAP success criteria

# Criterion (verbatim) Status
1 git config user.email returns the GitHub-noreply address; GitHub Keep my email addresses private and Block command line pushes that expose my email are both ON. Operator-side; not gated by this PR. gh api user already returns email: null (private email setting is on). The local git config user.email change and the command-line-push toggle are operator steps before merging this PR.
2 git ls-files | xargs grep -l "gaodingyun2@gmail.com" returns zero hits on main. ✅ verified zero hits on this branch
3 git ls-files | xargs grep -lE "dgpisces\.com|vocalize\.dgpisces" returns zero hits on main; Cloudflare Tunnel config contains placeholder values only. ✅ verified zero hits + cloudflared-config.yml now uses your-tunnel-name, api.example.com, vocalize.example.com
4 git ls-files | xargs grep -liE "x-invite-token|invite_token|invite-only|invite only" returns zero hits on main; a self-hosting user can reach /health and open a session with no invite token. ✅ verified zero hits; backend gate removed; POST /api/sessions accepts requests without any header
5 README × 2, CONTRIBUTING, SECURITY, docs/architecture.md, and docs/deploy/* describe self-deploy with no invite gate and no reference to a hosted instance.

Test plan

  • tests/test_app_startup_guards.py — 8/8 pass (CORS preflight now asserts Content-Type is the lone non-default allow_header).
  • pytest tests/ excluding the two Cluster-B files deferred from Phase 12 — 100% pass.
  • Frontend tsc --noEmit clean.
  • Module imports clean: from vocalize.server import create_app, from vocalize.server.sessions import register_session_routes.
  • CI must pass on this PR (backend / frontend / playwright-loopback / ai-merchant).

Out of scope (tracked in STATE.md)

  • Operator-side criterion chore(09): public-repo workflow setup (FLOW-01..05) #1 (local git config user.email + the two GitHub account toggles). Confirm both before / after merging this PR.
  • Phase 14 (generic-host-rename) — Pi-centric path/script/doc renames; depends on this phase.
  • Phase 15 (history-rewrite)git-filter-repo + force-push of the historical personal email/domain blobs out of git history; runs last in its own session per global policy.

DGPisces added 5 commits May 19, 2026 10:43
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
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
…d 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
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)
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)
@DGPisces DGPisces merged commit afc530c into main May 19, 2026
4 checks passed
@DGPisces DGPisces deleted the chore/v1.2-working-tree-cleanse branch May 19, 2026 19:33
DGPisces added a commit that referenced this pull request May 19, 2026
Phase 14 of v1.2 (privacy / OSS hardening). The orchestrator now sells
itself as a Linux-host deploy with Raspberry Pi positioned as one
example target rather than the assumed default.

Directory + file renames (git tracks as renames)
- infra/pi-orchestrator/ -> infra/orchestrator/
- install/pi-install.sh  -> install/install.sh
- docs/deploy/pi.md      -> docs/deploy/linux.md

Script reframing
- install/install.sh: banner becomes "VocalizeAI Linux Installer";
  docstring lists Debian 12 / Ubuntu 22.04 / Raspberry Pi OS as tested
  targets; "Pi install complete" -> "Install complete".
- infra/orchestrator/setup.sh, deploy.sh: rename `PI_HOST`/`PI_USER`
  args to `TARGET_HOST`/`TARGET_USER` (legacy PI_HOST / PI_USER still
  accepted as fallback env vars so existing operator muscle memory
  keeps working); rewrite banners + log lines + manual-steps copy to
  refer to "the remote host" instead of "the Pi"; both scripts pass
  `bash -n` and `shellcheck --severity=warning` clean.
- infra/orchestrator/cloudflared-config.yml: header comments drop
  "on Pi" qualifier.

Doc reframing (criterion #4 surfaces)
- README.md, README.zh-CN.md: status line, file-tree comment, and
  cross-reference to deploy/linux.md all reframed to "Linux host
  (Raspberry Pi is one example target)".
- CONTRIBUTING.md: reference to "live Pi orchestrator" becomes
  "Linux-host orchestrator".
- docs/architecture.md: "Pi deployment assets" -> "Linux deployment
  assets"; Further Reading entry updated.
- docs/deploy/local.md: env-table comments referring to "Pi" become
  generic ("orchestrator service port", "Linux-host orchestrator").
- docs/deploy/linux.md: full rewrite — intro, BOM, OS prep, Tailscale,
  Clone-and-Install, Environment Config, Cloudflare Tunnel, systemd,
  troubleshooting sections all reframed to "any modern Linux host
  with systemd"; the Pi-specific BOM + imaging + first-boot
  instructions are moved into a single
  "Hardware example: Raspberry Pi" subsection at the bottom.
- infra/README.md: orchestrator entry reframed.
- scripts/README.md: stability-driver description reframed.
- CHANGELOG.md: v1.0.0 bullet reframed.
- .github/ISSUE_TEMPLATE/bug_report.yml: OS examples include Debian 12;
  "Pi production" deployment mode becomes "Linux-host production";
  journalctl hint refers to "a systemd-installed host" rather than Pi.

Verification
- `git grep -nIE "pi-orchestrator|pi-install|deploy/pi\.md" -- .`
  returns zero hits — all stale paths gone.
- `shellcheck --severity=warning` clean on all three renamed shell
  scripts; `bash -n` clean too.
- `pytest tests/test_app_startup_guards.py tests/test_pipeline.py`
  still pass (no production code touched; only path strings + docs).

Phase: v1.2 / 14-generic-host-rename
Requirements: SELF-LINUX-01..05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant