Skip to content

feat(ses): sending-side builders — configuration set, event destinations, send grants, reputation alarms - #304

Open
laazyj wants to merge 2 commits into
mainfrom
claude/ses-send-support-154qdx
Open

feat(ses): sending-side builders — configuration set, event destinations, send grants, reputation alarms#304
laazyj wants to merge 2 commits into
mainfrom
claude/ses-send-support-154qdx

Conversation

@laazyj

@laazyj laazyj commented Jul 15, 2026

Copy link
Copy Markdown
Owner

What & why

Extends @composurecdk/ses beyond the receiving path (#279) with the outbound sending surface. Design, research, and the key decisions (each compared to two alternatives) are in #303.

A production sender needs a configuration set to track its mail, a least-privilege grant to whatever role sends, event routing so bounces/complaints can drive suppression, and an account-level reputation safety net — all raw aws-cdk-lib until now. This adds:

  • createConfigurationSetBuilder() — the unit that tracks a stream of outbound mail. Secure defaults: tlsPolicy: REQUIRE (encrypt in transit) and reputationMetrics: true (per-config-set bounce/complaint metrics), both overridable. .addEventDestination(key, { destination, events }) routes send events, with snsDestination / eventBusDestination / cloudWatchDestination helpers that accept Resolvables so a destination can ref() a sibling topic or bus (mirrors the existing receipt-actions/ helpers).
  • identityGrants — consumer-side send grants (ADR-0013). identityGrants.send(ref) delegates to the identity's native grantSendEmail (ses:SendEmail + ses:SendRawEmail); identityGrants.sendFrom(ref, addresses) scopes the grant with a ses:FromAddress condition for least privilege.
  • createReputationAlarmBuilder() — the AWS-recommended account-level alarms: Reputation.BounceRate (>= 0.05) and Reputation.ComplaintRate (>= 0.001), Average/1 hr, treatMissingData: IGNORE, per the SES reputation-alarm guidance. These metrics are account/Region-scoped and dimensionless, so this builder is deliberately independent of any configuration set (build it once per account/Region) — that's the main design decision called out in feat(ses): sending-side builders — ConfigurationSet + event destinations, send grants, account reputation alarms #303.
  • EmailIdentity builder gains a Resolvable .configurationSet() method to associate an identity with a sibling-built configuration set.

Adds @composurecdk/cloudformation and @composurecdk/cloudwatch as peer dependencies (for taggedBuilder and the shared alarm helpers). SES sending is available in all commercial Regions, so no region-gating is needed (unlike receiving).

Deferred to follow-ups (noted in #303): dedicated IP pool builder, account-level VdmAttributes, SES templates (L1-only), and production-access/quota/suppression-list domain actions (SDK-only, ADR-0016). An example stack under packages/examples/ will follow.

Refs #303.

Checklist

🤖 Generated with Claude Code


Generated by Claude Code

…ons, send grants, reputation alarms

Extend @composurecdk/ses beyond the receiving path with the outbound
sending surface:

- createConfigurationSetBuilder: the unit that tracks a stream of
  outbound mail. TLS is required and reputation metrics are enabled by
  default (both overridable). .addEventDestination(key, {destination,
  events}) routes send events, with snsDestination / eventBusDestination
  / cloudWatchDestination helpers that accept Resolvables so a
  destination can ref() a sibling topic or bus.
- identityGrants: consumer-side send grants (ADR-0013). .send delegates
  to the identity's native grantSendEmail; .sendFrom scopes the grant
  with a ses:FromAddress condition for least privilege.
- createReputationAlarmBuilder: account-level Reputation.BounceRate (>=5%)
  and Reputation.ComplaintRate (>=0.1%) alarms with the AWS-recommended
  thresholds and treatMissingData: IGNORE. The metrics are account/Region
  scoped and dimensionless, so this builder is deliberately independent of
  any configuration set.
- EmailIdentity builder gains a Resolvable .configurationSet() method to
  associate an identity with a sibling-built configuration set.

Adds @composurecdk/cloudformation and @composurecdk/cloudwatch peer
dependencies. Deferred to follow-ups: dedicated IP pools, account VDM
attributes, and SES templates.

Refs #303
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Coverage

Overall line coverage: 99.35% across 23 package(s).

Package Statements Branches Functions Lines
acm 🟢 95.34% 🟢 90.47% 🟢 100.00% 🟢 97.43%
apigateway 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
budgets 🟢 99.20% 🟢 95.55% 🟢 100.00% 🟢 100.00%
cloudformation 🟢 97.69% 🟢 95.40% 🟢 100.00% 🟢 99.16%
cloudfront 🟢 99.40% 🟢 95.14% 🟢 100.00% 🟢 100.00%
cloudwatch 🟢 95.56% 🟡 89.55% 🟢 100.00% 🟢 98.23%
core 🟢 100.00% 🟢 97.36% 🟢 100.00% 🟢 100.00%
custom-resources 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
dynamodb 🟢 98.50% 🟡 88.88% 🟢 100.00% 🟢 100.00%
ec2 🟢 98.88% 🟢 97.82% 🟢 100.00% 🟢 99.59%
eslint-plugin 🟡 89.88% 🟡 83.33% 🟢 100.00% 🟢 97.90%
events 🟢 97.50% 🟢 92.30% 🟢 100.00% 🟢 100.00%
examples 🟢 94.78% 🟡 76.66% 🟢 100.00% 🟢 99.06%
iam 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
lambda 🟢 97.88% 🟢 96.26% 🟢 100.00% 🟢 98.30%
logs 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
module-compat 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
neptune 🟢 96.00% 🟡 84.78% 🟢 100.00% 🟢 98.57%
route53 🟢 98.24% 🟢 96.04% 🟢 100.00% 🟢 99.04%
s3 🟢 98.94% 🟢 98.24% 🟢 100.00% 🟢 100.00%
ses 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
sns 🟢 98.73% 🟢 96.66% 🟢 100.00% 🟢 100.00%
sqs 🟢 99.24% 🟢 97.18% 🟢 100.00% 🟢 100.00%
Total 🟢 97.90% 🟢 94.36% 🟢 100.00% 🟢 99.35%

…isabled

createReputationAlarms short-circuited on `recommendedAlarms: false` and
`{ enabled: false }` before appending custom alarms, so an explicitly
added `.addAlarm()` alarm was silently dropped whenever the recommended
set was turned off.

Suppress only the recommended definitions when disabled and always
append custom alarms, matching the corrected pattern already used by the
split-alarm builders (cloudfront/route53/budgets, ADR-0004). Clarify the
`recommendedAlarms` / `enabled` docs and add regression tests covering
both disable paths.

Refs #303
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