The 3.97.0-beta.0 release PR (#899) failed its backend Tests job on
slideshowPublic.test.js: bootCrmDb's full migration chain crossed the
suite's explicit 30s beforeAll timeout argument on a slow runner. #860
raised the config default and the jest.setTimeout pins to 120s, but
hook-ARGUMENT pins override the config default and were left behind —
same time-bomb, different syntax.
Every beforeAll that boots the migration chain and pinned 30s/60s is
raised to 120000 (16 suites). Untouched on purpose: the three suites
whose pinned hooks don't run migrations (webhookDelivery,
imageProcessor.storage, storageBackend) and publicQuotes' 30s pin on
the rate-limit lockout test — neither grows with the migration chain.
No test logic changed.
Co-authored-by: Paul Nothaft <paul@MacStudio-von-Paul.local>
Previously "Continue" on the token step only checked the field was
non-empty; a wrong token wasn't caught until the final submit, after the
user had filled in email + password. Add a non-burning verify:
- backend: POST /setup/verify-token constant-time compares the token
without consuming it (createInitialAdmin still claims it atomically on
submit), gated on no-admin-exists and rate-limited like /setup/admin.
- frontend: step-1 "Continue" calls verifyToken and only advances on a
valid token; a wrong token shows the invalidToken error on the field,
429 -> too-many-attempts, 409 -> redirect to login.
Adds integration tests for accept-without-burn / reject / closed-once-set.
Blockers:
- SetupPage now mirrors the server password rule (>=8 with upper/lower/digit) so
a green client isn't bounced by the server; server errors carry a `field`
(routes/setup.js) that the client maps to a translated key instead of
rendering raw English. New i18n: setup.invalidToken, setup.passwordRequirements.
- picpeak-setup.sh: the ADMIN_CREDENTIALS.txt block no longer dead-ends on the
wizard path — when no legacy admin was seeded it prints the one-time setup
token (from data/SETUP_TOKEN / docker compose logs) and points at /setup.
Concern:
- createInitialAdmin creates the admin + burns the token in ONE transaction,
atomically claiming the token (null-if-present, expect 1 row) so a
double-submit can't create two super_admins. Cross-DB (whereNotNull, trx-only
writes). Added a concurrency test.
Nits:
- SetupPage redirects to /login when /setup/status errors (no form flash on a
configured instance).
- Dropped the unused DATABASE_URL from docker-compose.yml.
- Documented why secrets are chmod 644 (three different reader users).