Skip to content

feat: add the emails capability spec - #159

Merged
mayteio merged 4 commits into
mainfrom
posthog/add-emails
Oct 29, 2026
Merged

mayteio merged 4 commits into
mainfrom
posthog/add-emails

Conversation

@mayteio

@mayteio mayteio commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Transactional email ships in posthog-node (PostHog/posthog-js#5418) and posthog-python (PostHog/posthog-python#1093), but the shared contract lives only in a comment on PostHog/posthog#120921. Other server SDKs have nothing to implement against, and the compliance audit does not track email.

Changes

  • New capability spec openspec/specs/emails/spec.md, for server SDKs only, with 20 requirements:
    • the public surface (send, get) and the email options;
    • the secret key, the app host mapping, and the refusal to send the key to a custom host;
    • the send request and its headers, argument checks, and the idempotency key;
    • which responses retry, and the retry timing;
    • the send result, error fields, category error names, and the error channel;
    • the status read and its record;
    • disabled and shut-down clients.
  • Prose sections for the purpose, applicability, public surface, HTTP mapping, and the error names table.
  • acceptance/public/emails.feature: server scenarios for the request, the host refusal, the missing key, idempotency across retries, which responses retry, Retry-After, error names, the status read, and a disabled client. They carry the legacy @server tag and are not opted into the integration suite, because no harness binding exists yet.
  • The archived change openspec/changes/archive/2026-10-29-add-emails/ (proposal, design, tasks, delta), and the capability added to the README index and project.md.

Decisions where the two SDKs differ (details in the archived design.md):

  • Error channel: the language's idiomatic channel, and only that one. posthog-node resolves to { data, error }, and posthog-python raises.
  • Local argument checks: before any request. An SDK may report a validation error or raise the language's argument error.
  • Per-send max_retries: canonical, because the shared contract named it. posthog-python does not have it yet.
  • Status times: native date-times or ISO 8601 strings.

Not covered: the code-content form and capture_engagement, which the send API does not accept yet.

Validation

  • openspec validate --specs --strict --no-interactive with 1.4.1, the CI version: 68 passed, 0 failed.
  • openspec validate add-emails --strict with 1.15.0 before archive: valid.
  • Each requirement traces to code in the two SDK PRs or the PostHog backend send and status views.

Agent context

Autonomy: Human-driven (agent-assisted)

Tools: PostHog Desktop (Claude Code, Claude Opus 5.5), OpenSpec CLI, Git

🤖 Generated with Claude Code


Created with PostHog Desktop

Adds the canonical contract for server-side transactional email: send from a template and read an email's status. Derived from posthog-node and posthog-python. Includes the archived add-emails change, an acceptance feature, and the README index row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be
@mayteio mayteio self-assigned this Oct 29, 2026
@posthog

posthog Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

PostHog Review · Deep · reviewed 0584866

Posted 7 findings: 6 Should fix, 1 Consider.

Step Status Result
Prepare the diff done 9 files, 3 chunks
Pick perspectives done 3 perspectives
Run review passes done 8 issues (+2 blind-spot)
Merge overlapping findings done 10 → 8
Validate findings done 7 kept, 1 dismissed
Publish done 7 posted (view review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be
@mayteio
mayteio marked this pull request as ready for review October 29, 2026 12:24
@mayteio
mayteio requested a review from a team as a code owner October 29, 2026 12:24

@posthog posthog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

See this review and its findings in PostHog Review.

Comment thread openspec/specs/emails/spec.md Resolved
Comment thread openspec/specs/emails/spec.md Resolved
Comment thread openspec/specs/emails/spec.md Resolved
Comment thread openspec/specs/emails/spec.md Resolved
- Name a local invalid_* argument error validation_error.
- Keep native argument exceptions alongside the single raised email error type.
- Bound email draining by the remaining shutdown timeout.
- Treat a 2xx without a message ID as api_error, without a retry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be

@dustinbyrne dustinbyrne left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The template-send and status contract is coherent, and the previous review concerns are addressed. Two non-blocking documentation accuracy suggestions are inline.

AI-assisted review.

Comment thread openspec/specs/emails/spec.md Resolved
- The purpose says one key per call lets PostHog deduplicate retries, instead of promising a send never goes out twice. The design records the pending-reservation gap.
- The conformance table pins the assessed revisions, marks Python's per-send max_retries as passing from 5abcf29, and records synchronous Python shutdown draining as a gap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be
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