The previous commit's "Auth e2e pack" job failed: auth.spec.ts's own
logins already spend a good chunk of the 10/min/IP login rate limit
(operations.md), leaving content.spec.ts's five more logins to hit it
mid-pack. Reproduced locally against a fresh throwaway database
(migrate + seed + both Playwright runs back to back, exactly the job's
steps) and confirmed a DELETE on rate_limits between the two runs
fixes it.
Follow-up to #32, not a new issue — the pack itself was already
correct, this is a test-infrastructure fix.
Seed script extends the fixture matrix with a shared "Content Fixtures"
pond (owned by fixture-user): an "Every Element" page covering every
editor schema node and mark (#24), and a "Fixture Image" page with one
real, servable uploaded image. "Every Element" loads a checked-in Yjs
snapshot (prisma/fixtures/content-page.yjs) generated from a
human-readable Markdown source (content-page.md) via a deterministic
regeneration script (pinned Y.Doc clientID; refuses to write a
snapshot that isn't a fixed point of the Markdown round-trip).
New apps/web/e2e/content.spec.ts consolidates the M2 content
regression pack: page lifecycle, editor basics, image paste, trash,
and — the pack's actual regression pin — a byte-for-byte comparison of
the fixture page's exported Markdown against the checked-in fixture.
Verified this catches regressions: temporarily mutated
docToMarkdown's heading serializer, rebuilt, re-seeded, confirmed the
comparison failed, then reverted.
This pack now runs in CI (a second step in the existing auth-e2e job,
reusing its already-built-and-seeded stack) alongside the existing
local-only feature packs.
Closes#32
The Vite dev server died mid-run on the CI runner (memory pressure),
failing every remaining test with connection refused. The auth-e2e
job now serves apps/web/dist through a dependency-free static server
with SPA fallback and /api proxy (scripts/e2e-static-server.mjs) —
matching the production nginx/Caddy layout and testing the real
build. Server logs are dumped when the job fails. Verified locally:
six of six against the static server.
Part of #20
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Playwright's request context resolves localhost to ::1 while Vite in
the CI container listened on IPv4 only — the fixture-login helper got
ECONNREFUSED. Vite now starts with --host in the auth-e2e job. The
redirect test also reports the server's error message instead of a
bare URL mismatch when a login fails.
Part of #20
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The fixtures seed ran against an empty database; migrate deploy now
precedes it (the api start re-checks idempotently).
Part of #20
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The seed script now provisions the documented fixture matrix
(fixture-admin / fixture-user / fixture-pending, idempotent upserts,
rate-limit reset for disposable databases). A six-test Playwright pack
drives the real UI against a full local stack with Mailpit: complete
signup→mail→verify→first-login journey, wrong-password error, guarded
route redirect honoring ?next (race between the login page and the
anonymous guard fixed by teaching the guard about ?next), menu logout,
site-admin gating, and a profile rename reflected in the top bar. The
pack self-skips without E2E_MAILPIT_URL, so the CD smoke stage (now
pinned to smoke.spec.ts) stays untouched; a new CI job boots api +
web dev server against postgres/mailpit service containers and runs
the pack on every PR and push. Also fixed: the web api client choked
on empty 201 bodies. e2e/README.md documents targets and fixtures.
Closes#20
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Prisma models per data-model.md: users (status enum, site-admin flag),
user_identities (password provider now, OIDC later — subject is the
stable user id), sessions (hashed ids), auth_tokens (hashed, single-
use), plus rate_limits and mail_outbox for the upcoming M1 stories.
UsersService creates accounts transactionally with Argon2id-hashed
password identities (OWASP parameters, rehash detection) and maps
uniqueness violations to field-level conflicts. Database-backed suites
run when TEST_DATABASE_URL is set — locally against the dev db, in CI
via a new postgres service container; shared auth schemas (username,
password policy incl. common-password blocklist) ship with tests.
Closes#10
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pnpm/action-setup reads the version from package.json packageManager —
the explicit `version: 11` input made it fail on the mismatch. The
registry login now strips whitespace from the stored token before
docker login (the secret carried a trailing newline).
Part of #8
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On every push to main: build both images once (SHA + moving `test`
tag), push to the Gitea registry, SSH-deploy the Test stage, wait for
readiness, run the new Playwright smoke suite (SPA shell, web
liveness, api healthz/readyz) against https://test.dorfteich.cloud,
and on green retag the identical SHA images as `int` and deploy Int.
The CI image-build job becomes PR-only to avoid double builds on main.
Part of #8
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Gitea Actions workflow running on every PR and push to main: pnpm
install with caching, workspace build, ESLint+Prettier, tsc, Vitest,
translation key parity, and docker builds of both images (build-only —
pushing is the CD workflow's job). Live verification of the red/green
PR gate follows once the act_runner from issue #9 is registered;
issue #7 stays open until then.
Part of #7
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>