Found while executing #11741 (widening SendEmailInput/SendTemplateInput with organizationId).
Observation
packages/spec/src/contracts/email-service.ts declares on SendTemplateInput:
/** Tenant id for org-overlay resolution (when supported). */
org?: string;
Measured on claude/issue-11741-sendemail-organization-id (base dce6a019f): zero readers. @objectstack/plugin-email — the only IEmailService implementation in this repo — never consults input.org anywhere (email-service.ts, template-loader.ts, email-plugin.ts; grep for a bare org read comes back empty apart from a prose comment in template-loader.ts:69 about overlay rows). Template resolution keys on (name, locale) only.
Declared ≠ enforced (Prime Directive #10): a caller passing org today gets no org-overlay resolution and no error — the key is silently inert. The "(when supported)" hedge in the TSDoc is the declaration admitting it.
Why it matters slightly more after #11741
#11741 adds organizationId (the sys_email.organization_id delivery stamp, pass-through) beside the inert org (declared as template resolution overlay). Two org-shaped keys on one input, one of which does nothing, is exactly the shape that invites an AI author to pick the wrong one. The #11741 TSDoc cross-references the distinction, but the long-term fix is for org to be either implemented (org-overlay template rows, if there is measured pull) or retired.
Disposition options for triage
- Retire
org (ADR-0049 enforce-or-remove; it is a contracts interface key, not an authorable metadata key, so the retirement kit is lighter — no liveness ledger surface). - Implement org-overlay template resolution and make the declaration true (only with a real business pull; startup scope discipline argues against building it speculatively).
Not verified here: whether anything outside this repo (e.g. cloud) passes or reads org.
Refs: #11741 · #11303
Found while executing #11741 (widening
SendEmailInput/SendTemplateInputwithorganizationId).Observation
packages/spec/src/contracts/email-service.tsdeclares onSendTemplateInput:Measured on
claude/issue-11741-sendemail-organization-id(basedce6a019f): zero readers.@objectstack/plugin-email— the onlyIEmailServiceimplementation in this repo — never consultsinput.organywhere (email-service.ts,template-loader.ts,email-plugin.ts; grep for a bareorgread comes back empty apart from a prose comment intemplate-loader.ts:69about overlay rows). Template resolution keys on(name, locale)only.Declared ≠ enforced (Prime Directive #10): a caller passing
orgtoday gets no org-overlay resolution and no error — the key is silently inert. The "(when supported)" hedge in the TSDoc is the declaration admitting it.Why it matters slightly more after #11741
#11741 adds
organizationId(thesys_email.organization_iddelivery stamp, pass-through) beside the inertorg(declared as template resolution overlay). Two org-shaped keys on one input, one of which does nothing, is exactly the shape that invites an AI author to pick the wrong one. The #11741 TSDoc cross-references the distinction, but the long-term fix is fororgto be either implemented (org-overlay template rows, if there is measured pull) or retired.Disposition options for triage
org(ADR-0049 enforce-or-remove; it is a contracts interface key, not an authorable metadata key, so the retirement kit is lighter — no liveness ledger surface).Not verified here: whether anything outside this repo (e.g.
cloud) passes or readsorg.Refs: #11741 · #11303