tenant email spec: platform names are NOT account-scoped by construction
Section 4a asserted that platform-suffixed domains needed no ownership check because the names are account-scoped. They are not: DomainKindFor matches only the suffix and nothing compares the sqid label to the caller. Review demonstrated one account claiming another's platform name and obtaining a verified identity and a sending policy for it. It is worse than the custom-domain case the section was written for, because CARLOS owns the zone and publishes the DKIM and MAIL FROM records on the attacker's behalf — no DNS control required. The platform apex was accepted too, with a DMARC record written at the platform's own zone apex. Platform names now need both gates: the claim, and an ownership check that the label left of the suffix equals the calling account, with the bare suffix refused outright.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 file changed,
+24
−4
docs/superpowers/specs/2026-08-19-tenant-email-design.md+24 −4
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 cbcb8fe70..2c5d9ec8f 100644 |
| --- a/docs/superpowers/specs/2026-08-19-tenant-email-design.md |
| +++ b/docs/superpowers/specs/2026-08-19-tenant-email-design.md |
| @@ -176,10 +176,30 @@ Order matters and is the same lesson `domainattach.go` records: claim |
| first, then provision. The reverse ordering lets two accounts each create |
| an identity and discover the conflict from the fleet. |
| -A platform-suffixed domain (`<app>.<sqid>.oncarlos.com`) is not exempt. |
| -It is not *more* exposed — the names are account-scoped by construction — |
| -but the claim costs nothing there and a single code path is worth more than |
| -a special case. |
| +**A platform-suffixed domain is not exempt, and the reason first given here |
| +was WRONG.** This section originally said platform names are "account-scoped |
| +by construction". They are not: `DomainKindFor` matches only the *suffix*, |
| +and nothing compares the `<sqid>` label to the calling account. Review |
| +demonstrated account `bbb` claiming `seapointish.aaa.oncarlos.com` and |
| +obtaining a verified identity plus a policy for `*@` that name. |
| + |
| +That is **strictly worse** than the custom-domain case, because CARLOS owns |
| +the zone: it publishes the DKIM, MAIL FROM and DMARC records *on the |
| +attacker's behalf*, so the attacker needs **no DNS control at all**. The |
| +platform apex itself (`oncarlos.com`) was likewise accepted, with CARLOS |
| +writing a DMARC record at its own zone apex. |
| + |
| +So a platform domain needs BOTH gates: |
| + |
| +1. The claim in this section, and |
| +2. **an ownership check on the name**: for `KindPlatform`, the label |
| + immediately left of the platform suffix MUST equal the calling account's |
| + sqid, and the bare suffix itself must be refused outright. A name inside |
| + the platform zone is only that account's to ask for if the name says so. |
| + |
| +The claim alone is first-come-first-served, which is adequate where DNS |
| +control is the real proof, and inadequate where CARLOS itself supplies the |
| +proof. |
| ## 5. The provisioner seam |