Skip to content

feat: PAT expiry alert emails with configurable templates#1543

Open
AmanGIT07 wants to merge 4 commits intomainfrom
feat/pat-expiry-email-alerts
Open

feat: PAT expiry alert emails with configurable templates#1543
AmanGIT07 wants to merge 4 commits intomainfrom
feat/pat-expiry-email-alerts

Conversation

@AmanGIT07
Copy link
Copy Markdown
Contributor

Summary

  • Send email alerts before and after PAT expiry via a cron job
  • Pre-expiry reminder (pat.expiry_reminder) and post-expiry notice (pat.expired_notice)
  • Configurable schedule, days-before threshold, and HTML email templates via YAML config
  • Tracks sent alerts in PAT metadata (expiry_reminder_sent_at, expired_notice_sent_at) to prevent duplicates
  • Multi-pod safe via Postgres advisory lock (pg_try_advisory_lock)
  • Creates audit records for each alert sent
  • Uses robfig/cron/v3 with SkipIfStillRunning + Recover chains (same pattern as billing sync jobs)

Available template variables

Variable Description Example
{{.PatID}} PAT UUID 34b04e9e-14ee-4bd6-9175-9787d77c1295
{{.Title}} PAT title My Deploy Token
{{.ExpiresAt}} Formatted expiry April 18, 2026 at 3:00 PM UTC
{{.DaysLeft}} Days until expiry 3
{{.User.ID}} User UUID
{{.User.Name}} User slug jdoe
{{.User.Title}} User display name (may be empty) John Doe
{{.User.Email}} User email jdoe@example.com
{{.Org.ID}} Organization UUID
{{.Org.Name}} Organization slug acme-corp
{{.Org.Title}} Organization display name Acme Corp

Config example

app:
  pat:
    alert:
      enabled: true
      schedule: "@every 1h"
      days_before: 3
      expiry_reminder_body: |
        {{if .User.Title}}<p>Hi {{.User.Title}},</p>{{else}}<p>Hi,</p>{{end}}
        <p>Your token <b>{{.Title}}</b> in <b>{{.Org.Title}}</b> expires on <b>{{.ExpiresAt}}</b>.</p>
        <p><a href="https://console.example.com/{{.Org.Name}}/tokens">Manage tokens</a></p>

Test plan
- Unit tests for alert service (12 tests: init, lock, reminders, notices, templates, errors)
- Local testing with Mailpit: emails received, HTML renders, metadata set, no duplicates on re-run

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 15, 2026

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

Project Deployment Actions Updated (UTC)
frontier Ready Ready Preview, Comment Apr 15, 2026 11:41am

@coveralls
Copy link
Copy Markdown

Coverage Report for CI Build 24452521350

Coverage increased (+0.09%) to 41.816%

Details

  • Coverage increased (+0.09%) from the base build.
  • Patch coverage: 117 uncovered changes across 3 files (138 of 255 lines covered, 54.12%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
internal/store/postgres/userpat_repository.go 66 0 0.0%
core/userpat/alert_service.go 179 138 77.09%
cmd/serve.go 10 0 0.0%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 36895
Covered Lines: 15428
Line Coverage: 41.82%
Coverage Strength: 11.81 hits per line

💛 - Coveralls

@AmanGIT07 AmanGIT07 enabled auto-merge (squash) April 15, 2026 12:18
@AmanGIT07 AmanGIT07 requested a review from rohilsurana April 15, 2026 12:22
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