Skip to content

refactor(cdp): accept transactional sends in their own module - #128871

Merged
trunk-io[bot] merged 17 commits into
scheduled-sends/n1-job-codecfrom
scheduled-sends/n2-transactional-sends
Nov 12, 2026
Merged

trunk-io[bot] merged 17 commits into
scheduled-sends/n1-job-codecfrom
scheduled-sends/n2-transactional-sends

Conversation

@Silthus

@Silthus Silthus commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Problem

  • Scheduled email sends (Silthus/personal#303) add time rules, cancel and reschedule to transactional sends. The send logic sits inside the cdp-api route handler, so each change grows the handler.

Merge first: #128868.

Note

🔵 Merge risk: low · two-way door (merge-risk rubric)

  • Every transactional email request, in US and EU, runs the moved code.
  • Answers, idempotency calls and fingerprints, queued jobs, file checks, status rows and metrics match N1 in all 23 shadow-diff scenarios.
  • Switch-off: none: live on deploy, fix forward.

Landing: #129915 merges alone and its migration runs in US and EU first. #127745 merges next. Then one /trunk merge on #128929 lands N1 to N4.

Changes

  • Nothing user-visible changes: the PR moves code.
  • TransactionalSends.accept owns the send: idempotency, refusal checks, run row, queue insert and status row.
  • The route keeps the token check, body parsing, the team and workflow loads, and maps each outcome to its HTTP answer.
  • The CI report's comment-density warning counts moved comments. Every comment in the new module comes from the handler.
flowchart LR
  subgraph Before
    R1[send route: auth, parse, load, accept, answer]
  end
  subgraph After
    R2[send route: auth, parse, load, answer] --> T2[transactional sends: accept]
  end
  classDef phBlue fill:#1d4aff,stroke:#1d4aff,color:#fff;
  classDef phGray fill:#e5e7eb,stroke:#c7ccd1,color:#000;
  class T2 phBlue;
  class R1,R2 phGray;
Loading

How did you test this code?

  • cdp-api.serial.test.ts passes unchanged.
  • A scratch shadow run sends 14 scenarios through N1 and this PR. The answers, queued runs, fingerprints, status rows and metrics match.
Shadow run
  • Scenarios: template and code sends, a keyed send and its replay, a reused key, a key in flight, no key store, a draft workflow, sending suspended, sending paused, a suppressed recipient, quota on marketing and transactional flows, an unreachable recipient, and a failed insert with its retry.
  • Captured per scenario: each HTTP answer, each queued run, each reserve, markQueued and release call with its fingerprint, the status and result rows sent to Kafka, and the outcome and stage counters.
  • Result: the only differences are status row versions, which embed the send time. Compared by status rank, the two runs match.
  • Run at this PR's head fa5a21f against N1's head 0b6fb84.
  • The scratch test is not committed.

Release status

  • No feature flag controls this change

Docs update

  • None.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Agent: Claude Code, Claude Opus 5.5

Skills: /writing-pr-descriptions

More context for AI agents
  • Session: T3 Code stack thread for Silthus/personal#303, Claude Code.
  • Decisions: cdp-api builds the module per request from its current fields. The serial suite swaps the queue and the idempotency store on the API, and it stays unchanged.
  • Follow-ups: N3 adds scheduled_at and the time rules inside accept.
  • Read closely: nodejs/src/cdp/services/hogflows/transactional-sends.ts against the removed handler code.

🤖 Generated with Claude Code

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

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

✅ Trunk lane — non-backend lane

This PR is assigned to the non-backend lane. It does not run backend Python tests and may merge in parallel with PRs in other lanes.

✅ Duplication (Python) — clean

New Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Duplication (TypeScript) — clean

New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

⚠️ Comment density — 4% of added code lines are comments (14 of 337)

This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out.

Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See .agents/skills/writing-code-comments/SKILL.md for the house rules.

Files with the most added comment lines:

File Comment lines Added lines
nodejs/src/cdp/services/hogflows/transactional-sends.ts 14 284

This check does not block merging. It updates on every push and clears when the share drops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Silthus
Silthus marked this pull request as ready for review November 5, 2026 07:33
@parameterai

parameterai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Risk: No findings

This delta wires file attachments into transactional email sends: a new JWT-authenticated uploads endpoint that hands out checksum- and length-pinned S3 PUT URLs under a per-team daily byte quota, plus a send-path verification stage that checks the files exist, sizes the rendered message against a 40MB cap, and queues the send with verified attachment metadata. I traced auth, tenant scoping, quota atomicity, idempotency release coverage, and the render-size DoS guards end to end and found no vulnerability introduced by these changes.

Sentinel reviewed a2dd902 · Review settings

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested a review from a team November 5, 2026 07:34
…ransactional-sends

# Conflicts:
#	nodejs/src/cdp/cdp-api.ts
#	nodejs/src/cdp/services/hogflows/transactional-email.ts
…ransactional-sends

# Conflicts:
#	nodejs/src/cdp/cdp-api.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ransactional-sends

Master's attachments switch (CDP_EMAIL_ATTACHMENTS_ENABLED) and the recipient
and function id on the queued status row move into TransactionalSends, which
now owns the send that cdp-api.ts used to build.

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

veria-ai Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Reviews

Silthus and others added 2 commits November 10, 2026 08:36
…nal-sends

Master removed inline email attachments (#131567). The transactional send module no longer decodes, stores or switches on files: the strict send schema refuses them, as on master. Suppression is read with isKnownSuppressed, as on master.

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

@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.

PostHog Review · Standard · reviewed 372032e: no findings.

Silthus and others added 2 commits November 12, 2026 04:04
…nal-sends

# Conflicts:
#	nodejs/src/cdp/cdp-api.ts
#	nodejs/src/cdp/services/hogflows/transactional-email.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Silthus
Silthus added this pull request to stack #134353 November 12, 2026 09:52
@trunk-io

trunk-io Bot commented Nov 12, 2026

Copy link
Copy Markdown

This pull request is queued for merge as part of 128929, which will merge 128868, 128871, 128881, 128929.

@stamphog stamphog Bot 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.

Approved.

The risky portions have assurance through owning-team authorship and STRONG familiarity, though neither listed review covers the current head. No unresolved substantive concerns or other refusal grounds were found.

  • Author wrote 76% of the modified lines and has 22 merged PRs in these paths (familiarity STRONG).
Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✓ no deny categories matched
size ✓ 606L, 3F substantive — within ceiling
tier ✓ T1-agent / T1d-complex (606L, 3F, single-area, refactor)
stamphog 2.8.0 .stamphog/policy.yml @ a2dd902 · reviewed head a2dd902

@trunk-io
trunk-io Bot merged commit 765a8ee into master Nov 12, 2026
239 checks passed
@trunk-io
trunk-io Bot deleted the scheduled-sends/n2-transactional-sends branch November 12, 2026 10:07
@trunk-io

trunk-io Bot commented Nov 12, 2026

Copy link
Copy Markdown

This pull request was merged into master as part of stacked PR 128929.

@deployment-status-posthog

deployment-status-posthog Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-11-12 10:34 UTC Run
prod-us ✅ Deployed 2026-11-12 10:56 UTC Run
prod-eu ✅ Deployed 2026-11-12 11:07 UTC Run

This table shows the posthog release only. Hogstation shows every service that this PR reaches, Kargo services included.

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