diff --git a/frontend/e2e/README.md b/frontend/e2e/README.md index ea763eed..f25b6885 100644 --- a/frontend/e2e/README.md +++ b/frontend/e2e/README.md @@ -46,7 +46,8 @@ user), reset to a deterministic baseline every run by [`scripts/e2e_seed.py`](../../scripts/e2e_seed.py) (run in-container so it reuses the app's models + argon2 hasher): the top-3 organic channels subscribed, one in-progress + one watched + one saved video, prefs pinned to `language: en`. Credentials come -from `E2E_EMAIL` / `E2E_PASSWORD` (local-only defaults). Override the container name with +from `E2E_EMAIL` (default `e2e@siftlode.local`) and `E2E_PASSWORD` — **required, no default**: run +the suite through the ops wrapper, which exports it from the secret store. Override the container name with `E2E_API_CONTAINER`; skip the in-container seed with `E2E_SKIP_SEED=1`. ## Selectors diff --git a/frontend/e2e/global.setup.ts b/frontend/e2e/global.setup.ts index 9dfa571b..aa729556 100644 --- a/frontend/e2e/global.setup.ts +++ b/frontend/e2e/global.setup.ts @@ -14,7 +14,9 @@ import { fileURLToPath } from "node:url"; const STORAGE = "e2e/.auth/state.json"; const EMAIL = process.env.E2E_EMAIL || "e2e@siftlode.local"; -const PASSWORD = process.env.E2E_PASSWORD || "e2e-golden-master"; +// No default: a password committed to a public repo is not a credential. The ops wrapper +// (`siftlode e2e` / `check-full`) exports it from the secret store. +const PASSWORD = process.env.E2E_PASSWORD ?? ""; const CONTAINER = process.env.E2E_API_CONTAINER || "siftlode-api-1"; const BASE_URL = process.env.PW_BASE_URL || "http://127.0.0.1:8080"; @@ -25,6 +27,11 @@ const SEED_SCRIPT = resolve(HERE, "../../scripts/e2e_seed.py"); const isLocalTarget = /\/\/(127\.0\.0\.1|localhost)[:/]/.test(BASE_URL); setup("seed + authenticate", async ({ page }) => { + expect( + PASSWORD, + "E2E_PASSWORD is not set — run the suite through `siftlode e2e` (it reads the secret store)", + ).not.toBe(""); + // 1. Preflight: fail fast (with a useful message) if the stack isn't running. const health = await page.request.get("/healthz"); expect( diff --git a/scripts/e2e_seed.py b/scripts/e2e_seed.py index 620aeecc..975011e4 100644 --- a/scripts/e2e_seed.py +++ b/scripts/e2e_seed.py @@ -9,7 +9,8 @@ golden-master net is deterministic and never touches a real account. Self-healin spec that left the account dirty is cleaned on the next run. Prints one JSON line describing what it seeded (the wrapper / global-setup reads it). -Credentials come from env (E2E_EMAIL / E2E_PASSWORD) with local-only defaults; the account +Credentials come from env: E2E_EMAIL (default e2e@siftlode.local) and E2E_PASSWORD (REQUIRED, no +default — the ops wrapper exports it from the secret store); the account lives only in the localdev DB. """ @@ -36,7 +37,11 @@ from app.models import ( # noqa: E402 from app.security import hash_password # noqa: E402 EMAIL = os.environ.get("E2E_EMAIL", "e2e@siftlode.local") -PASSWORD = os.environ.get("E2E_PASSWORD", "e2e-golden-master") +PASSWORD = os.environ.get("E2E_PASSWORD", "") +if not PASSWORD: + sys.exit( + "e2e_seed: E2E_PASSWORD is not set (no default by design) — run it via `siftlode e2e-seed`" + ) N_SUBS = 3