Skip to content

Fix(OTP Login): on fresh installs and load settings from the documents table - #1056

Merged
lane711 merged 9 commits into
SonicJs-Org:mainfrom
LukeSeers:fix-plugin-otp
Sep 4, 2026
Merged

Fix(OTP Login): on fresh installs and load settings from the documents table#1056
lane711 merged 9 commits into
SonicJs-Org:mainfrom
LukeSeers:fix-plugin-otp

Conversation

@LukeSeers

Copy link
Copy Markdown
Contributor

Description

Fix the OTP login plugin returning 500 errors on fresh installs. The legacy plugins and otp_codes tables were dropped from migrations when plugin settings moved to the documents table (#858), but the OTP plugin still tried to read its settings from the old plugins table. On a fresh database, every /auth/otp/* request therefore failed with D1_ERROR: no such table: plugins.

The plugins table is intentionally gone; plugin settings are now stored in the documents table (type_id='plugin', slug='otp-login'). This PR updates the OTP plugin to read its settings from the documents table, restores only the otp_codes migration that the OTP service still requires, and adds regression tests.

Fixes #

Changes

  • Updated OTP settings loading (otp-login-plugin/index.ts): added a loadOtpSettings(db) helper that reads settings from the plugin's row in the documents table (type_id='plugin', slug='otp-login', tenant_id='default', is_current_draft=1, deleted_at IS NULL). It falls back to a guarded lookup in the legacy plugins table and then to defaults, so a missing legacy table no longer causes an error. Both /auth/otp/request and /auth/otp/verify now use this helper, so settings saved through the admin UI are correctly applied.
  • Added packages/core/migrations/0005_otp_codes.sql: restores the otp_codes table and indexes used by OTPService for request, verify, and resend operations. This is the only legacy table still required by the OTP service.
  • Regenerated the migrations bundle (migrations-bundle.ts), which now contains 5 migrations, and synced the sandbox copies in my-sonicjs-app/migrations/.
  • Updated migrations.test.ts for the new migration list (00010005).
  • Added E2E regression coverage in tests/e2e/97-otp-request-route.spec.ts for the OTP request and verify flow.

Testing

Verified end-to-end against a fresh local D1 database with no plugins table:

  • POST /auth/otp/request (unknown email) → 200
  • POST /auth/otp/request (known user) → 200 + dev code
  • POST /auth/otp/verify (correct code) → 200, authenticated user returned
  • POST /auth/otp/verify (wrong code) → 401
  • POST /auth/otp/request (invalid email) → 400
  • Saved a setting in the documents table (codeExpiryMinutes: 3) → correctly honored (expiresIn: 180 instead of the 600 default)

Unit Tests

  • Added/updated unit tests (migrations.test.ts)
  • All unit tests passing — 1729 passed (1 pre-existing flaky timeout in no-event-without-dispatch-site.test.ts, which also fails on a clean base)

E2E Tests

  • Added/updated E2E tests (tests/e2e/97-otp-request-route.spec.ts)
  • All E2E tests passing — full E2E suite not run; manual curl verification completed

Screenshots/Videos

N/A — no UI changes.

Checklist

  • Code follows project conventions
  • Tests added/updated and passing
  • Type checking passes
  • No console errors or warnings (only expected guarded fallbacks)
  • Documentation updated (if needed)

@LukeSeers
LukeSeers requested a review from lane711 as a code owner August 14, 2026 15:59
@LukeSeers LukeSeers changed the title Fix(OTP Login) OTP login on fresh installs and load settings from the documents table Fix(OTP Login): on fresh installs and load settings from the documents table Aug 14, 2026
Migration 0005_otp_codes.sql was added but the migrations bundle
(migrations-bundle.ts) — the actual source MigrationService reads, not
the .sql files — was not regenerated. On a fresh install 0005 never
applied: otp_codes was never created and /auth/otp/request 500'd for a
real user with `no such table: otp_codes`, and migrations.test.ts failed
CI (bundle stopped at 0004 while the test expects 0005).

Regenerate the bundle to include 0005, and retag the OTP regression spec
@smoke so CI actually selects it (the migrations/otp change never
triggers the @auth-only selection). Also correct the stale spec
docstring (settings now come from the documents table, not `plugins`).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
loadOtpSettings hand-rolled raw SQL against the documents table and a
dead fallback to the dropped legacy `plugins` table (R4 duplication).
PluginService.getPlugin already reads the same plugin document
(type_id='plugin', slug='otp-login') and returns its settings. Reuse it
and drop the dead legacy path. Behavior unchanged: never throws, missing
document or unparseable settings resolves to DEFAULT_SETTINGS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts:
#	packages/core/src/db/migrations-bundle.ts
@lane711
lane711 merged commit ebd48c9 into SonicJs-Org:main Sep 4, 2026
2 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants