tenant email spec: the SMTP tenant header is X-SES-TENANT, not X-SES-TENANT-NAME
Verified at implementation and independently re-fetched in review against the live SES tenants page. The spec's guess was wrong; designing the tenant as one method on the provisioner seam is what made that a one-line correction rather than a model change. Records the precondition the same page states and that is easy to get backwards: a tenant needs a verified identity AND a configuration set associated before it can send, and SES checks that on every send. An unassociated tenant is harmless only while nothing emits the header, so the send path must not start emitting it until associations are wired.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 file changed,
+21
−8
docs/superpowers/specs/2026-08-19-tenant-email-design.md+21 −8
diff --git a/docs/superpowers/specs/2026-08-19-tenant-email-design.md b/docs/superpowers/specs/2026-08-19-tenant-email-design.md| index 8e214ff46..86d5060ba 100644 |
| --- a/docs/superpowers/specs/2026-08-19-tenant-email-design.md |
| +++ b/docs/superpowers/specs/2026-08-19-tenant-email-design.md |
| @@ -79,14 +79,27 @@ created on first use. This is what makes one account's reputation stop at |
| its own boundary and what makes a per-account pause meaningful to SES |
| itself rather than only to us. |
| -The tenant layer is **additive and seam-shaped**, not load-bearing. SES |
| -Tenant Management is recent enough that the exact attribution mechanism |
| -for an SMTP send (believed to be an `X-SES-TENANT-NAME` header) **MUST be |
| -verified against live AWS documentation at implementation time, not taken |
| -from this document**. It is designed as one method on the seam in §5 so |
| -that a wrong guess costs one function rather than the model. If tenant |
| -attribution over SMTP turns out to be unavailable, v1 ships without the |
| -tenant layer and loses nothing in §4's isolation. |
| +The tenant layer is **additive and seam-shaped**, not load-bearing. |
| + |
| +**VERIFIED 2026-08-19** (implementation, then independently re-fetched in |
| +review, against `docs.aws.amazon.com/ses/latest/dg/tenants.html`): SES |
| +tenant management is real and present in `sesv2` v1.66.6. This document's |
| +original guess of an `X-SES-TENANT-NAME` header was **WRONG** — the actual |
| +SMTP attribution header is **`X-SES-TENANT`**. Designing the tenant as one |
| +method on §5's seam is what made that a one-line correction rather than a |
| +model change. |
| + |
| +**A hard precondition the same page states, which is easy to get backwards:** |
| +a tenant must have at least one verified identity AND one configuration set |
| +associated to it (`CreateTenantResourceAssociation`) before it can send, and |
| +SES validates that association on every send. So while nothing emits |
| +`X-SES-TENANT`, an unassociated tenant is harmless — but **the send path |
| +MUST NOT begin emitting `X-SES-TENANT` until associations are wired, or |
| +every send fails.** Creating the tenant is safe and idempotent; referencing |
| +it is not, until then. |
| + |
| +If tenant attribution over SMTP had turned out to be unavailable, v1 would |
| +have shipped without the tenant layer and lost nothing in §4's isolation. |
| **Identity ↔ a domain, per region.** The default identity for an app is |
| **the app's own host** — `seapointish.bag.oncarlos.com` — not the account |