Skip to content

upgrade production ePDS to v0.7.0#210

Merged
aspiers merged 31 commits into
productionfrom
dev
Jul 21, 2026
Merged

upgrade production ePDS to v0.7.0#210
aspiers merged 31 commits into
productionfrom
dev

Conversation

@aspiers

@aspiers aspiers commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Promote the tested dev deployment to production, upgrading certified.one and auth.certified.one from v0.6.5 to v0.7.0.

Release highlights

  • Operators: OTP completion logs now include handoff timing, provider message IDs, and SMTP responses, with consistent recipient fields across email paths.
  • Operators using Resend: verified delivery, open, complaint, suppression, and scheduling events can optionally be logged without persisting webhook data.
  • Client integrations: OAuth authorization now uses permission-set scopes in place of transition:generic.

Full release notes: https://github.com/hypercerts-org/ePDS/releases/tag/ePDS%400.7.0

Verification

  • dev package version: 0.7.0
  • https://dev.certified.app/health: 0.7.0+904c871d
  • https://auth.dev.certified.app/health: 0.7.0+904c871d
  • Current production core: 0.6.5+43bb4ff0
  • Current production auth: 0.6.5+43bb4ff0

Ashex and others added 30 commits July 7, 2026 16:30
The client-branded OTP delivery log exposed its recipient under the generic to field, while related authentication logs use email. This made structured log queries inconsistent.\n\nPublish the same recipient value under email and document the operator-facing field rename.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>
The first pass updated only the client-branded delivery log and overlooked the three other sendMail call sites. That left standard sign-in, welcome, and backup verification deliveries without the same structured recipient context.\n\nAdd an email field to the delivery log for every sendMail path while retaining Nodemailer's required to envelope property.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>
fix(auth-service): log email recipients consistently
Store Resend email lifecycle events idempotently by Svix ID and expose delivery latency and outcome metrics. Share the ten-minute OTP lifetime between Better Auth and the latency threshold so the two cannot drift.

Refs #185

Co-authored-by: OpenAI Codex <noreply@openai.com>
Add a raw-body webhook endpoint that verifies Svix signatures before validating and persisting supported Resend email events. Retries are acknowledged idempotently and delayed-delivery events are surfaced in logs.

Refs #185

Co-authored-by: OpenAI Codex <noreply@openai.com>
Document the webhook URL, event subscriptions, signing secret, metrics output, and the required live SMTP verification. Propagate RESEND_WEBHOOK_SECRET into generated auth-service environments and add release notes.

Refs #185

Co-authored-by: OpenAI Codex <noreply@openai.com>
Clarify that ePDS supports any SMTP provider and expose the Resend route and metrics only after an operator opts in with a webhook secret. Bound the optional integration with dedicated rate limiting, 30-day retention, and reduced persisted payload data.

Refs #185

Co-authored-by: OpenAI Codex <noreply@openai.com>
Remove the webhook database schema and in-process delivery metrics. The optional signed receiver now emits structured event logs with Svix IDs so external log analysis can deduplicate retries, order events, and calculate latency without ePDS retaining webhook data.

Refs #185

Co-authored-by: OpenAI Codex <noreply@openai.com>
Ignore only missing temporary database directories during teardown instead of swallowing every filesystem error.

Co-authored-by: OpenAI Codex <noreply@openai.com>
Include the verified email subject in structured delivery event logs so operators can distinguish messages during incident analysis.

Refs #185

Co-authored-by: OpenAI Codex <noreply@openai.com>
Set Express trust-proxy configuration immediately after app creation so webhook rate-limit request IP handling is unambiguous.

Co-authored-by: OpenAI Codex <noreply@openai.com>
Introduce Resend as a third-party email service in the release summary and state that ePDS continues to support other email providers.

Co-authored-by: OpenAI Codex <noreply@openai.com>
Follow the auth-service import convention by placing external dependencies before the internal shared package.

Co-authored-by: OpenAI Codex <noreply@openai.com>
Map Resend webhook payloads into provider-neutral delivery fields so future provider adapters can emit the same log schema. Centralize the Resend webhook path while leaving provider-specific verification in place.

Refs #185

Co-authored-by: OpenAI Codex <noreply@openai.com>
Parse each webhook sender and log only events whose address exactly matches the instance SMTP_FROM. Unrelated account-wide events are acknowledged without exposing their payload, allowing multiple ePDS domains to share one Resend account when they use distinct sender addresses.

Refs #185

Co-authored-by: OpenAI Codex <noreply@openai.com>
Resend models recipients as an array, which made Railway display the single ePDS recipient as recipients[0]. Webhook subjects also include the sign-in code and would expose it in logs.\n\nNormalize the recipient to the existing email field and redact only OTP tokens matching the configured length and charset while preserving the rest of the subject.\n\nFollow-up to #185.\n\nCo-authored-by: OpenAI <noreply@openai.com>
Use concise digit character classes so SonarCloud accepts the OTP subject sanitizer added for #185.\n\nCo-authored-by: OpenAI <noreply@openai.com>
SonarCloud reports intentional localhost, Docker, and Railway-private HTTP URLs as clear-text protocol vulnerabilities. Mark those exact lines with justified NOSONAR annotations because the traffic never crosses the public network.\n\nCo-authored-by: OpenAI <noreply@openai.com>
Closes #183. The per-send completion line previously carried only the
recipient, so a slow-but-successful SMTP handoff was indistinguishable
from a fast one and app logs could not be joined to Resend's per-message
delivery events.

Wrap every sendMail() in a timedSendMail() helper that measures the
handoff, captures the result, and folds elapsedMs, messageId and
smtpResponse into the existing success line — one enriched line per
send across all four paths (client-branded, sign-in, welcome, backup).
On failure it stamps elapsedMs onto the thrown error so the existing
"failed to send OTP email" line carries the duration without adding a
second failure line.

The explicit-SMTP-timeouts part of #183 is intentionally deferred: it
would change send behaviour (a slow-but-successful handshake could start
failing) and the right values need to be chosen from real latency data,
which the elapsedMs logging added here will itself provide. Tracked
separately.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
feat(auth-service): log OTP send duration, messageId and SMTP response
Operators using Resend open tracking could see delivery outcomes but not whether the message's tracking pixel was fetched.\n\nAccept email.opened webhooks, normalize them to opened, and document the required tracking opt-in and reliability caveats. The event uses the existing sender filter and sanitized provider-neutral log fields.\n\nFollow-up to #185.\n\nCo-authored-by: OpenAI <noreply@openai.com>
…ooks

Add optional Resend delivery event logging
Resend complaint, suppression, and scheduling events provide useful operational context but were rejected by the original delivery-focused allowlist. Known click and inbound events also caused pointless retries when subscribed accidentally.\n\nNormalize and log complained, suppressed, and scheduled events; acknowledge clicked and received events without logging their payloads. Document the expanded subscriptions and ratchet line coverage.\n\nCo-authored-by: OpenAI <noreply@openai.com>
…ional-events

auth: expand Resend email event handling
Replace transition:generic with permission sets scopes
upgrade dev.certified.app to v0.7.0
Copilot AI review requested due to automatic review settings July 20, 2026 16:57
@vercel

vercel Bot commented Jul 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
epds-demo Ready Ready Preview, Comment Jul 20, 2026 4:57pm

Request Review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@railway-app
railway-app Bot temporarily deployed to ePDS / ePDS-pr-210 July 20, 2026 16:57 Destroyed
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f8b61367-9fb9-43ce-8813-b9abe2b07990

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

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.

@changeset-bot

changeset-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 904c871

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@sonarqubecloud

Copy link
Copy Markdown

@railway-app

railway-app Bot commented Jul 20, 2026

Copy link
Copy Markdown

🚅 Deployed to the ePDS-pr-210 environment in ePDS

Service Status Web Updated (UTC)
@certified-app/demo untrusted ✅ Success (View Logs) Web Jul 20, 2026 at 4:58 pm
@certified-app/pds-core ✅ Success (View Logs) Web Jul 20, 2026 at 4:58 pm
@certified-app/auth-service ✅ Success (View Logs) Web Jul 20, 2026 at 4:58 pm
@certified-app/demo ✅ Success (View Logs) Web Jul 20, 2026 at 4:57 pm

@aspiers
aspiers merged commit ee1a2eb into production Jul 21, 2026
32 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.

3 participants