diff --git a/.agents/aw/environments.yml b/.agents/aw/environments.yml new file mode 100644 index 000000000..d6603a01a --- /dev/null +++ b/.agents/aw/environments.yml @@ -0,0 +1,98 @@ +# .agents/aw/environments.yml — where the verification suite runs. Committed; no secrets. +# Field reference: the aw-verify skill's rules/config.md. Written by /aw-verify setup. +# Read .agents/aw/notes.md before a run: local `web` talks to PRODUCTION Supabase, +# and the local Supabase stack runs on a developer machine only. +version: 1 +environments: + local: + url: http://localhost:3000 + stack: + driver: command + commands: + # Local Supabase (Postgres + Auth + Edge Functions) — LOCAL MACHINE ONLY. + # The script exits 78 when no Docker daemon is reachable (the Agent0 / + # cloud sandbox), and the run carries on with `web` against the hosted + # backend. Listed before `web` so it is ready when `web` picks its mode. + # No `port`: Docker owns 54321, and its listener would read as foreign. + - name: supabase + run: sh .agents/aw/scripts/stack/supabase-local.sh + ready_url: http://127.0.0.1:54321/functions/v1/health + # The dashboard. web.sh serves it against the local Supabase while + # supabase-local.sh runs, otherwise against the hosted project in + # .env.local (production). + - name: web + run: sh .agents/aw/scripts/stack/web.sh + ready_url: http://localhost:3000 + port: 3000 + component_map: + packages/web/: [web] + packages/schemas/: [web] + packages/feature-flags/: [web] + supabase/: [supabase, web] + scripts/seed/: [supabase, web] + default: [web] + hot_reload: [packages/web/src/] + config_files: [.env.local, packages/web/.env.local, supabase/config.toml] + ready_timeout_seconds: 300 + auth: + strategy: storage-state + storage_state: .auth/local.json + # Present only when signed in (the Sidebar's user-settings link). + authed_check: '{role: "link", name: "User settings for"}' + refresh: + when: missing-or-expired + env: [LOREKIT_TESTING_USER_NAME, LOREKIT_TESTING_USER_PW] + # Reuses the repo's own headless login (scripts/auth-bootstrap-credentials.mjs). + # The runner exports PREVIEW_URL as this environment's url. + command: | + set -a + [ -f .env.local ] && . ./.env.local + [ -f packages/web/.env.local ] && . ./packages/web/.env.local + set +a + AUTH_LOGIN_URL="${PREVIEW_URL:-http://localhost:3000}/login" \ + AUTH_STORAGE_STATE=./.auth/local.json \ + AUTH_POST_LOGIN_URL_PATTERN='/lore' \ + AUTH_AUTHED_ROLE='link' \ + AUTH_AUTHED_NAME='User settings for' \ + node scripts/auth-bootstrap-credentials.mjs + timeout_seconds: 120 + # The email is the LOREKIT_TESTING_USER_NAME env var, never committed. + identity: { email: env:LOREKIT_TESTING_USER_NAME, role: user } + fixtures: + seed: null + preview: + url: + # GitHub deployments here are main's staging/production deploys only, so the + # PR preview comes from the sticky `lorekit-web-preview` comment that + # web-preview-deploy.yml posts (stable `pr-` alias). + from: pr-deployment + comment: + authors: [github-actions] + host_pattern: 'lorekit-pr-\d+-[a-z0-9-]+\.vercel\.app' + template: 'https://lorekit-pr-{pr}-mads-thines-projects.vercel.app' + auth: + strategy: storage-state + # Outer wall: Vercel Deployment Protection on every preview request. + bypass_header: { name: x-vercel-protection-bypass, env: VERCEL_AUTOMATION_BYPASS_SECRET } + # Separate from local.json: the Supabase session cookie is host-scoped. + storage_state: .auth/preview.json + authed_check: '{role: "link", name: "User settings for"}' + refresh: + when: always + env: [LOREKIT_TESTING_USER_NAME, LOREKIT_TESTING_USER_PW, VERCEL_AUTOMATION_BYPASS_SECRET] + command: | + set -a + [ -f .env.local ] && . ./.env.local + [ -f packages/web/.env.local ] && . ./packages/web/.env.local + set +a + : "${PREVIEW_URL:?PREVIEW_URL is set by the runner to the resolved preview origin}" + AUTH_LOGIN_URL="$PREVIEW_URL/login" \ + AUTH_STORAGE_STATE=./.auth/preview.json \ + AUTH_POST_LOGIN_URL_PATTERN='/lore' \ + AUTH_AUTHED_ROLE='link' \ + AUTH_AUTHED_NAME='User settings for' \ + node scripts/auth-bootstrap-credentials.mjs + timeout_seconds: 120 + identity: { email: env:LOREKIT_TESTING_USER_NAME, role: user } + fixtures: + seed: null diff --git a/.agents/aw/notes.md b/.agents/aw/notes.md new file mode 100644 index 000000000..ec43dfd4c --- /dev/null +++ b/.agents/aw/notes.md @@ -0,0 +1,48 @@ +# LoreKit — repo facts for the verification suite + +Read by `aw-verify`, `ui-verify`, `telemetry-verify`, `aw-tester` and `aw` on every run. +Values live in the sibling `environments.yml`, `ui.yml` and `telemetry.yml`; this file says what they cannot. + +## Local stack + +- Two modes, one URL (`http://localhost:3000`). `web` alone serves the dashboard against the hosted Supabase project in `.env.local`. When the diff touches `supabase/**` or `scripts/seed/**`, the `supabase` component starts first and `web` switches to it (`nx serve-local web` → `http://127.0.0.1:54321`). `AW_WEB_BACKEND=local|hosted` forces a mode. +- **The hosted backend is production** (`pqokxlhvnosogizsjztg`). A probe that creates, edits or deletes a record in `web`-only mode writes real production rows under the shared test account. Name every record a run creates with `aw-verify` or `ui-verify-adv` in its key or title and delete it in the same run. Run write-heavy ACs (Concurrency rows, bulk edits) in local-Supabase mode or on the preview. +- **The local Supabase stack runs on a developer machine only.** `supabase-local.sh` exits `78` with an `aw: local Supabase skipped (…)` line when no Docker daemon or Supabase CLI is reachable. That happens in every Agent0 / cloud sandbox (no Docker socket). Treat it as `skipped`, not a failure: carry on with `web`, and mark ACs that need the PR's backend code `skipped (supabase runs locally only — verify on the preview)`. +- An Agent0 sandbox also starts without `.env.local`, so `web` has no Supabase URL and authed pages fail. There, prefer `run preview`. +- `supabase-local.sh` seeds the test account into the local auth from the same `LOREKIT_TESTING_USER_*` variables, so the login is identical in both modes. Stopping its process group stops the functions server only; `pnpm nx stop supabase` stops the containers. Studio: `http://127.0.0.1:54323`. +- `pnpm --filter @lorekit/web dev` runs `vercel env pull` first and needs a linked Vercel CLI; the stack uses `pnpm nx serve web` instead. + +## Login + +- One shared test account: email `LOREKIT_TESTING_USER_NAME`, password `LOREKIT_TESTING_USER_PW` (from `.env.local` locally, the shell elsewhere). Never commit either value. +- `/login` opens on a provider-choice screen; the email form appears after "Continue with email". `scripts/auth-bootstrap-credentials.mjs` handles that and lands on `/lore`. Never script the GitHub OAuth path. +- Signed in = the sidebar link "User settings for ". It shows the account's display name and has no `data-testid` to mask in screenshots. +- Sessions are host-scoped: `.auth/local.json` never authenticates the preview, and the preview session is recaptured every run. + +## Preview + +- CI deploys the dashboard preview (`web-preview-deploy.yml`) only when web paths changed (`scripts/ci/web-preview-filter.mjs`). Comment `/web-preview` on the PR to force one. +- The URL is in the sticky `