Skip to content

2026-07-31 — XP-151 pre-auth email placeholders use a reserved example domain

/login and /forgot-password both rendered admin@xprivateducation.id — the live Superuser address — as their email-input placeholder, i.e. a free username-enumeration hint on the only two pages a signed-out visitor can reach. Both now read nama@example.com. Plus a new regression gate, apps/web/e2e/pre-auth-placeholder-visual.spec.ts (10 tests): placeholder-value assertions, a rendered-document regex guard against the production mail domains, and 3-viewport screenshots of both pages. Merge 7d95ccc.

example.com over the ticket’s suggested contoh.com: RFC 2606 reserves example.com so it can never resolve to a real account, while contoh.com is a registerable real domain that carries no such guarantee. nama@ keeps the Indonesian voice without naming a staff member. Non-rendered occurrences of the real bootstrap address (.env.example, scripts/seed.ts, playwright.config.ts BOOTSTRAP_ADMIN_EMAILS, wrangler.jsonc, e2e fixtures) were deliberately left alone — they configure auth, and none ships to an unauthenticated page.

Prose alone would let this regress, so the AC became executable: the spec asserts the rendered pre-auth document matches no production mail domain. If a pre-auth page ever legitimately needs the production domain (a support mailto:), carve it out of the regex rather than deleting the guard. Fresh worktree also re-hit the apps/docs TS18003 typecheck trap (needs astro sync first) — now a skill instead of a buried STATE.md note.

New rule .claude/rules/sample-copy-example-domain.md (sample identifiers in UI copy must use RFC-2606 reserved domains; pre-auth is a security surface, not a style one) — indexed in CLAUDE.md. New skill .claude/skills/fresh-worktree-bootstrap/SKILL.md. No locked doc (plans/ARCHITECTURE.md, plans/scope/*.md) changed.