Skip to content

Add An Admin Email Log Page #553

Description

@b-at-neu

Parent: the email notifications epic. Blocked by #569 (delivery events).

Why

#547 records every send; #569 makes those records tell the truth about delivery. Nothing reads either — today you'd query the database by hand to answer "did the acceptance actually reach them?"

Lookup first. This is a tool for answering a question about one recipient, with failures surfaced prominently. It is not a metrics dashboard.

Scope

Admin-only page, following the /users pattern exactly: requireAdminOr404(), a data function in prisma/data/, a DataTable-based client table. Full-bleed width tier per DESIGN.md.

  • Search by recipient address — the primary interaction. Debounced, like the applications toolbar.
  • Filters for status and template, matching the existing toolbar idiom.
  • Newest first, paginated with the offset helpers from Add Pagination to the Applications Hub #389.
  • Columns: recipient, template, subject, status, and the relevant timestamp. A bounce shows its bounceTypePermanent and Transient mean very different things and the table must not flatten them.
  • A failure strip at the top: recent bounces, complaints and failed sends. One compact summary, not a chart.
  • Read-only. No resend button, no suppression management.
  • No migration — every column ships in Email Foundation And Send Log #547.

Notes

  • The log contains OTP rows for every user. That is exactly why this page is admin-only, and why managers get the per-application view (Show Per-Application Email History To Managers #570) instead.
  • sent is not proof of receipt. The status vocabulary should make that legible rather than implying delivery — a sent row with no delivered event is genuinely unknown, not successful.
  • Empty state needed: a fresh environment has no rows at all.

Non-goals

  • No resend, no retry, no suppression list.
  • No email body preview — subject and metadata only.
  • No open or click tracking.
  • No charts or trend lines.
  • No retention or pruning policy. The table grows unbounded; that's a known follow-up.

Acceptance criteria

  • The page is admin-only; a manager and an applicant both get a 404.
  • Searching an address returns that recipient's sends, newest first.
  • Status and template filters work and participate in Clear filters.
  • Pagination round-trips through the URL like /applications.
  • A bounced row shows whether the bounce was permanent or transient.
  • The failure strip lists recent bounces, complaints and failures.
  • Loading, empty and error states all handled per ENGINEERING.md §4.
  • Nothing on the page can trigger a send.
  • No migration is added.
  • WORKFLOWS.md gains an admin entry for the page.
  • npm run prettier:check, eslint:check, tsc:check, test all pass.

Tests

  • tests/db/ — the query filters by recipient, status and template; pagination bounds are correct; a non-admin caller is refused.
  • tests/unit/ — the status-to-label mapping including bounce types; the failure-strip selection logic.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

claudeWill be worked on by ClaudeenhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions