Skip to content

server changes for email cli (2/3)#2719

Open
drew-harris wants to merge 4 commits into
mainfrom
drewh/server-email-cli
Open

server changes for email cli (2/3)#2719
drew-harris wants to merge 4 commits into
mainfrom
drewh/server-email-cli

Conversation

@drew-harris
Copy link
Copy Markdown
Contributor

@drew-harris drew-harris commented Jun 1, 2026

Includes migration to drop user_id field from custom senders table.
Need to run migration before deploying.

Purpose of this pr is to remove the restriction against superuser tokens for auth email routes.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Removes user-id from app email sender storage and sync paths, permits NULL in app_email_senders.user_id via migration, extracts default magic-code email/template helpers, and updates dashboard routes to use app-level (superadmin/ref-token) authorization and new endpoints for default template and email status.

Changes

Email Sender Refactoring and Default Template Extraction

Layer / File(s) Summary
Database schema: allow null user_id in app_email_senders
server/resources/migrations/112_allow_null_sender_user_id.up.sql, server/resources/migrations/112_allow_null_sender_user_id.down.sql
Removes and reinstates the NOT NULL constraint on app_email_senders.user_id in up/down migrations; down migration adds operator guidance before re-applying SET NOT NULL.
Server-side email parameter generation helpers
server/src/instant/runtime/magic_code_auth.clj
Adds default-email-params and default-email-template-params and updates send! to use the extracted defaults for non-template magic-code emails.
App email sender model: remove user-id dependency
server/src/instant/model/app_email_sender.clj
Changes put! upsert to stop writing user_id and narrows sync-sender! signature to exclude user-id; updates internal put! calls accordingly.
Dashboard API endpoints and authorization updates
server/src/instant/dash/routes.clj
Renames magic-code-auth require alias, adds default-email-template-get and email-status-get, switches several handlers to app-level/superadmin-ref-token authorization, removes user-id argument from sync-sender! calls, and registers GET /dash/default-email-template and GET /dash/apps/:app_id/email_status.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • instantdb/instant#2406: Overlaps on magic-code default email/template parameter construction in magic_code_auth.clj.
  • instantdb/instant#2647: Both PRs modify server/src/instant/model/app_email_sender.clj’s sender sync flow (put!/sync-sender!).
  • instantdb/instant#2679: Related changes migrating sender/verification backend toward app-level handling and adjusting app_email_sender.clj.

Suggested reviewers

  • dwwoelfel
  • stopachka
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'server changes for email cli (2/3)' is vague and generic, using non-descriptive terms that don't convey meaningful information about the specific changeset. Replace with a more specific title that describes the main change, such as 'Remove user_id constraint from app_email_senders table' or 'Make email sender user_id optional for superadmin tokens'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description is related to the changeset, mentioning the migration to drop user_id and the purpose of removing superuser token restrictions for auth email routes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch drewh/server-email-cli

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@drew-harris drew-harris changed the title server changes for email cli server changes for email cli (2/3 Jun 1, 2026
@drew-harris drew-harris changed the title server changes for email cli (2/3 server changes for email cli (2/3) Jun 1, 2026
@drew-harris drew-harris force-pushed the drewh/validate-senders-app-level branch from ebc9b81 to fdf06ca Compare June 1, 2026 18:11
@drew-harris drew-harris force-pushed the drewh/server-email-cli branch from d552476 to d645fb6 Compare June 1, 2026 18:11
@drew-harris drew-harris force-pushed the drewh/server-email-cli branch from d645fb6 to 16eb40b Compare June 1, 2026 18:20
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

View Vercel preview at instant-www-js-drewh-server-email-cli-jsv.vercel.app.

Base automatically changed from drewh/validate-senders-app-level to main June 1, 2026 19:48
Comment thread client/packages/platform/src/email.ts Outdated
Comment thread server/src/instant/dash/routes.clj
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
server/src/instant/model/app_email_sender.clj (1)

85-88: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove unexpected :app-id parameter from put! call.

The put! function signature at line 21 only accepts {:keys [email name postmark-id]}, but this call is passing :app-id app-id. The put! function will silently ignore the extra key, but this is misleading and could cause confusion.

🔧 Proposed fix
-        sender (put! {:email email
-                      :name name
-                      :app-id app-id
-                      :postmark-id postmark-id})
+        sender (put! {:email email
+                      :name name
+                      :postmark-id postmark-id})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/src/instant/model/app_email_sender.clj` around lines 85 - 88, The map
passed to put! in the sender binding includes an unexpected :app-id key which is
not accepted by put! (its signature only uses {:keys [email name postmark-id]}).
Remove the :app-id app-id entry from the map passed to put! (in the sender
binding) so the call only sends :email, :name and :postmark-id to put!.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@client/packages/platform/src/email.ts`:
- Around line 1-23: The HTML template defaultMagicCodeEmailHtml contains
duplicated nested container divs with identical styles; remove the redundant
inner wrapper so there is a single outer container (retain one set of the style
attributes: background, font-family, line-height, font-size and the
max-width/white background/padding block) and ensure all inner content (the
welcome paragraph, {app_title}, {code}, and notes) remains inside that single
container with matching closing tags; update the string literal accordingly so
the markup is not double-wrapped.

In `@server/resources/migrations/112_allow_null_sender_user_id.down.sql`:
- Line 1: The down migration will fail if any app_email_senders.user_id rows are
NULL; modify 112_allow_null_sender_user_id.down.sql to handle NULLs before
running ALTER TABLE by either (A) adding a data migration step that updates rows
WHERE user_id IS NULL to a safe sentinel/owner user id (e.g., a known system
user) and then performing ALTER TABLE, or (B) adding a conditional check that
aborts with a clear error instructing manual cleanup if NULLs exist; reference
the table app_email_senders and column user_id when implementing this safeguard.

---

Outside diff comments:
In `@server/src/instant/model/app_email_sender.clj`:
- Around line 85-88: The map passed to put! in the sender binding includes an
unexpected :app-id key which is not accepted by put! (its signature only uses
{:keys [email name postmark-id]}). Remove the :app-id app-id entry from the map
passed to put! (in the sender binding) so the call only sends :email, :name and
:postmark-id to put!.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 58ff8ea7-d985-453a-9161-e3e375e48907

📥 Commits

Reviewing files that changed from the base of the PR and between 23a9f14 and 2df5beb.

📒 Files selected for processing (8)
  • client/packages/platform/src/email.ts
  • client/packages/platform/src/index.ts
  • client/www/components/dash/auth/Email.tsx
  • server/resources/migrations/112_allow_null_sender_user_id.down.sql
  • server/resources/migrations/112_allow_null_sender_user_id.up.sql
  • server/src/instant/dash/routes.clj
  • server/src/instant/model/app_email_sender.clj
  • server/src/instant/runtime/magic_code_auth.clj

Comment thread client/packages/platform/src/email.ts Outdated
Comment thread server/resources/migrations/112_allow_null_sender_user_id.down.sql
@drew-harris drew-harris force-pushed the drewh/server-email-cli branch 2 times, most recently from 2d84eec to 9a8de03 Compare June 1, 2026 22:10
Copy link
Copy Markdown
Contributor

@stopachka stopachka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
server/src/instant/runtime/magic_code_auth.clj (1)

126-134: ⚡ Quick win

Compute expiration once per request.

friendly-expiration is now evaluated twice on the no-template path: once while building template-params and again inside default-email-params. Since send! is on the auth path, keep the derived expiration lazy or pass it into the helper so the default flow only does the lookup once.

♻️ Proposed fix
-(defn default-email-params [app code]
+(defn default-email-params [app code expiration]
   (let [{default-sender-email :email} (config/app-email-sender)
         template-params {:code code
                          :app_title (:title app)
-                         :expiration (friendly-expiration app)}]
+                         :expiration expiration}]
     {:sender-name (:title app)
      :sender-email default-sender-email
      :subject (str code " is your verification code for " (:title app))
      :body (default-body template-params)}))
-        template-params {:user_email email
-                         :code code
-                         :app_title (:title app)
-                         :expiration (friendly-expiration app)}
+        expiration      (friendly-expiration app)
         {default-sender-email :email} (config/app-email-sender)
@@
-        email-params    (if template
-                          {:sender-email sender-email
-                           :sender-name (or (:name template) (:title app))
-                           :subject (template-replace (:subject template) template-params false)
-                           :body (template-replace (:body template) template-params true)}
-                          (default-email-params app code))
+        email-params    (if template
+                          (let [template-params {:user_email email
+                                                 :code code
+                                                 :app_title (:title app)
+                                                 :expiration expiration}]
+                            {:sender-email sender-email
+                             :sender-name (or (:name template) (:title app))
+                             :subject (template-replace (:subject template) template-params false)
+                             :body (template-replace (:body template) template-params true)})
+                          (default-email-params app code expiration))

Also applies to: 151-172

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/src/instant/runtime/magic_code_auth.clj` around lines 126 - 134, The
function default-email-params is calling friendly-expiration twice via
template-params and again inside default-body; compute the expiration once at
the top of the request and reuse it: bind a local expiration value (e.g., let
[expiration (friendly-expiration app)]) and use that in template-params and when
calling default-body (or change default-body to accept an expiration argument),
so default-email-params (and related call sites like send!) only perform the
lookup a single time; update references to
template-params/default-body/friendly-expiration accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@server/src/instant/runtime/magic_code_auth.clj`:
- Around line 126-134: The function default-email-params is calling
friendly-expiration twice via template-params and again inside default-body;
compute the expiration once at the top of the request and reuse it: bind a local
expiration value (e.g., let [expiration (friendly-expiration app)]) and use that
in template-params and when calling default-body (or change default-body to
accept an expiration argument), so default-email-params (and related call sites
like send!) only perform the lookup a single time; update references to
template-params/default-body/friendly-expiration accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 755cd079-22bc-4c79-99b8-d087e6b7744f

📥 Commits

Reviewing files that changed from the base of the PR and between 795d026 and e951a8b.

📒 Files selected for processing (5)
  • server/resources/migrations/112_allow_null_sender_user_id.down.sql
  • server/resources/migrations/112_allow_null_sender_user_id.up.sql
  • server/src/instant/dash/routes.clj
  • server/src/instant/model/app_email_sender.clj
  • server/src/instant/runtime/magic_code_auth.clj
🚧 Files skipped from review as they are similar to previous changes (4)
  • server/resources/migrations/112_allow_null_sender_user_id.down.sql
  • server/resources/migrations/112_allow_null_sender_user_id.up.sql
  • server/src/instant/model/app_email_sender.clj
  • server/src/instant/dash/routes.clj

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