Adds two assertions to the auth-flow integration test that exercise the
audit-log path:
- after register: expect exactly 1 REGISTER row in auth.security_events
for the new user
- after login: expect exactly 1 LOGIN_SUCCESS row for the same user
This locks in the fix from the previous commit (security.ts ?? null
guard for optional fields) and catches any future regression where
security.logEvent silently swallows a SQL error and the audit log goes
into the void.
Verified by reverting security.ts to the broken pre-fix version and
re-running — the test fails with `Expected: 1, Received: 0` at the
register-audit assert in 211ms instead of taking hours of production
debugging.
Also adds an explicit DELETE FROM auth.security_events to the afterAll
cleanup. The FK from security_events.user_id to auth.users(id) is
ON DELETE CASCADE so it would clean up implicitly anyway, but listing
it explicitly makes the cleanup intent obvious from the test source.
Net: 24 → 26 expects per run. Still ~22s end-to-end on a warm cache.
Adds a 13-step integration test that exercises register → email
verification → login → JWT validation → /me/data → encryption-vault
init/key → logout against a real stack of postgres + redis + mailpit +
mana-auth + mana-notify in docker compose.
Verified locally that this catches every regression we hit on
2026-04-08 in well under a second:
- missing nanoid dependency → register endpoint 500
- missing MANA_AUTH_KEK env passthrough → mana-auth never starts
- missing encryption-vault SQL migrations → vault endpoints 500
- wrong cookie name in /api/v1/auth/login → no accessToken in response
- mana-notify SMTP misconfigured → mailpit poll times out
Files:
- docker-compose.test.yml — minimal isolated stack on alt ports
(postgres 5443, redis 6390, mailpit 1026/8026, mana-auth 3091,
mana-notify 3092). Runs alongside the dev stack without collision.
Postgres healthcheck runs a real query rather than just pg_isready
to avoid the race where pg_isready reports healthy while the docker
init scripts are still running on a unix socket.
- tests/integration/auth-flow.test.ts — bun test that drives the full
flow via fetch + mailpit's REST API. Cleans up its test user from
postgres in afterAll. Self-contained, no extra deps.
- tests/integration/README.md — what's covered, why it exists, how
to run locally + extend.
- scripts/run-integration-tests.sh — orchestrator. Brings up the
stack, pushes the @mana/auth Drizzle schema, applies the
encryption-vault SQL migrations (002, 003), restarts mana-auth so
it sees the fresh tables, runs the test, tears down on exit.
KEEP_STACK=1 to leave it up for manual mailpit inspection.
- docker-compose.dev.yml — also adds Mailpit as a regular dev service
(ports 1025/8025) so local development can have a working email
capture without spinning up the test stack.
- .github/workflows/ci.yml — new auth-integration job that runs on
every PR. Calls run-integration-tests.sh; on failure dumps
mana-auth + mana-notify logs and the mailpit message queue. Marked
as a required check via the existing PR validation pipeline.
Reproduced 3 clean runs and 1 negative-control run (removed nanoid
from package.json → mana-auth container exits → script aborts with
non-zero) before committing. Full happy path runs in ~22s on a warm
Docker cache.