Repository navigation
refactor(plugin-email): templates resolve the registry; the seed and the provenance stamp retire; organization-level editing is closed (ADR-0131 D6/D10) #15205
Description
Activity
- addedpriority:p1High: required for production / M2High: required for production / M2
on Sep 4, 2026 objectstack-fleet commented
on Oct 6, 2026 ContributorMore actionsv18 pre-opening re-verification (C4): DRIFTED. #21818 widened what §6 Q1 covers. Still waiting on that ruling
Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-06T14:38Z. ⛔ Not a claim, ⛔ not a dispatch. Read-only re-verification on objectstackmain6befe19c6e. The cut base was 2026-09-04, 3,298 commits earlier. The maintainer asked for this pre-opening preparation in the triage seat's chat: 「现在就可以处理吧」. Classes, positions and functions only. The claiming seat applies these corrections before building. The body is not rewritten.Holds:
- The loader reads rows:
createSysEmailTemplateLoader(plugin-email/src/template-loader.ts:98), with no organization filter. seedTemplates(email-plugin.ts:960-972),bootstrapDeclaredEmailTemplates(bootstrap-declared-email-templates.ts:374) andemail-template-provenance.tsare live.- The organization door is still open (
sys_email_template,unique:'organization';email_templateallowOrgOverride: true). - §6 Q1 is unruled.
Drift:
- fix(plugin-email): a metadata-door email template edit survives the next boot #21818 (
08adfeade8, 10-05) changed what the seed reads.bootstrapEffectiveEmailTemplates(bootstrap-declared-email-templates.ts:399) reads metadata in the Default Organization. Undersingle, every Studio save of a template is an org-scopedsys_metadataoverlay, projected into the sending row withcustomized:false.- So Q1's population is larger than "
customized: truerows": it includes those overlays, whose axis is C5's to retire. bootstrapEffectiveEmailTemplates/EffectiveEmailTemplateSourcesjoin the retirement list.- "Byte-identical to today's seeded row" is ambiguous under
single.
- So Q1's population is larger than "
- Notification templates have no registry source. No
notification_templatemetadata type exists;sys_notification_templateis rows only (service-messaging/src/objects/notification-template.object.ts:20, seeded fromplugin-auth/src/phone-sms-texts.ts:193).- "Notification templates likewise" therefore means retiring the seed only. A new metadata type is new surface and defaults to no, so it is not this card's.
- Inferred, not run: the loader tie-breaks by
idacross organizations (template-loader.ts:72-79), so one organization's data-door row could win for all. The "behaviour-neutral" premise assumes no organization ever edited a template.
Still blocked on: the maintainer's §6 Q1, now asked with the widened population.
Generated by Claude Code
- The loader reads rows:
objectstack-fleet commented
on Oct 6, 2026 ContributorMore actionsRuling pointer: batch #282 item 5 (decision card #22005) · ADR-0131 §6 Q1 → C · maintainer 「同意」 2026-10-06T16:01Z
Director seat, summon #35,
session_01VYToj6PQehTEKNrjGM9akg(via the relay). Record: 6020178017 on #22005, closed. This card stayspm:blockedon #15193; §6 Q1 is no longer open. Thread-read: 6018661841.- C. At the v18 upgrade the migration ceremony (C7, feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211) promotes every customer-edited email template to an environment-level Studio template: both populations, the
sys_email_templaterows stampedcustomized: trueand the organization-scopedemail_templateoverlays Studio saved undersingle(fix(plugin-email): a metadata-door email template edit survives the next boot #21818). Undersinglethe meaning is unchanged; a name conflict on a multi-organization deployment is listed and the operator chooses per row (D10 fate 4). After a verified promotion the customized rows are mirrors (D10 fate 2) and the row table retires under D13 with an ADR-0087 entry. - Not taken: A (the kept
(organization, name, locale)resolution, the door D6 closed); B (deleting customer rows, unsanctioned by D10). - Scope: email templates only; notification templates have no metadata type (6018661841), their seed retires, no new type.
- This card's corrections: the retirement list is rewritten for "promote to environment level" and gains
bootstrapEffectiveEmailTemplates/EffectiveEmailTemplateSources; the acceptance "byte-identical to today's seeded row" is read against the promoted template; a dated note under ADR-0131 §6 Q1 naming this ruling rides this card's PR (Tier H, the maintainer's approval), the ADR text otherwise unchanged.
Generated by Claude Code
- C. At the v18 upgrade the migration ceremony (C7, feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211) promotes every customer-edited email template to an environment-level Studio template: both populations, the
objectstack-fleet commented
on Oct 7, 2026 ContributorMore actionsTriage: unlocked,
pm:blocked→pm:queue. The v18 line is open: #15193 was closed on the maintainer's word. C4, dispatchable firstBlocked-by: none
Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-07T12:35Z. ⛔ Not a claim, ⛔ not a dispatch.The blocker is released:
- [gate] the v18 development line is not open — ADR-0131 execution cards are blocked on this card #15193 closed
completedin this act (6037915987), on the maintainer's words in the triage seat's chat: 「我建议直接启动 v18 开发吧」, 「你应该先解锁 v18 所有的卡片」, 「同意」. - The ruling record is decision: open v18 now and ship it in stages — release the last 17.x from main first without waiting for #21908's deny (A), skip the last 17.x (B), or keep #22009's order (C)? #22050
6037890422(B: v18 develops onmain, with no last 17.x). - This card's
Blocked-by:named [gate] the v18 development line is not open — ADR-0131 execution cards are blocked on this card #15193 alone.
At claim (as #15193 requires, because these premises were measured in 2026-09): the file surface is re-verified against the then-current
main. At this write, every repository path the body names in backticks exists onmain(879bd38c5b).- Re-verify against the newest plugin-email shape: plugin-email: the boot sweep rewrites every effective email template on every boot (4 serial statements and a full sys_email_template scan each); since 08adfeade the default org's overlays are in that loop #22062 changed
packages/plugins/plugin-email/src/bootstrap-declared-email-templates.ts(PR fix(plugin-email): the boot sweep reads stored templates in bulk and no longer rewrites an unchanged row #22065 →56bf27affb): a bulk read, and compare-before-write in the boot sweep. C4 retires that seed path, so its claim reads the landed shape, not the 2026-09 one.
The release state:
mainis not yet in Changesets pre mode; the opening card follows this unlock.- A breaking change landing before the opening is graded
minorwith its BREAKING banner and ADR-0087 disposition, under the launch-window convention. Once pre mode is in,majoris open. - ⛔ chore: version packages #21988 is not merged.
- [gate] the v18 development line is not open — ADR-0131 execution cards are blocked on this card #15193 closed
objectstack-fleet commented
on Oct 7, 2026 ContributorMore actionsClaim: PM loop round 8 · 2026-10-07T12:46Z
Session:session_01WMQprn46CND82KmY8sZWBu
Account:os-warren(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-15205-templates-resolve-registry
Worktree:objectstack-issue-15205
Domain:domain:services
Seat:domain:services#2(seat post #21118)
File surface (re-verified at claim againstorigin/maine67ba80049, as #15193 requires; every path below exists). Scope is the card as corrected by the unlock6038028392, triage's re-verification6018661841and the §6 Q1 ruling C (6020271181, #22005):packages/plugins/plugin-email/src/template-loader.ts:createSysEmailTemplateLoader(near:98) resolvesemail_templatefrom the registry (code-declared plus Studio-authored, environment level) by(name, locale), not from rows.packages/plugins/plugin-email/src/email-plugin.ts:seedTemplates(near:960) retires, along with the boot sweep's call intobootstrap-declared-email-templates.ts.packages/plugins/plugin-email/src/bootstrap-declared-email-templates.ts: retires, includingbootstrapEffectiveEmailTemplates/EffectiveEmailTemplateSources. It is read in its landed shape (PR fix(plugin-email): the boot sweep reads stored templates in bulk and no longer rewrites an unchanged row #22065,56bf27affb), not the 2026-09 one.packages/plugins/plugin-email/src/email-template-provenance.ts: retires.- The
sys_email_templatedata door: refuses an organization's create and update, with an ADR-0123 D4-style message that names the closed door. packages/plugins/plugin-auth/src/phone-sms-texts.ts:seedPhoneSmsTemplates(near:193, called fromauth-plugin.tsnear:970) retires. Email templates only get the registry: no new notification metadata type.docs/adr/0131-total-organization-ownership-no-null-organization-id.md: a dated note under §6 Q1 naming ruling C. The ADR text is otherwise unchanged. Tier H: the PR needs the maintainer's approval to merge.- The packages' tests, and one changeset. The changeset is
minorwith the BREAKING banner and an ADR-0087 disposition (launch-window convention,6038028392), and covers each retired published export of@objectstack/plugin-email.
⛔ No
packages/spec. Spec prose that still says delivery resolvessys_email_templaterows goes to thedomain:specseat as a finding. ⛔ No deletion of customized rows: promotion is C7's (#15211). ⛔ The row table is not retired: that is D13's, after C7. ⛔ The org-scopedemail_templateoverlay axis is C5's. Stop on breach; explain in the report.
Container & model:L,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate; default-tier build).
Clause-②: no (narrowing)
Responsibility:ADR-0131 execution card (C4, D6/D10), not a defect: this repository's own code in plugin-email and plugin-auth | the ruling sets the path: registry resolution, with customized rows promoted by C7 | every deployment that sends a built-in auth mail or a Studio-authored template
Thread-read: 6038028392
Serial constraints cleared: at 2026-10-07T12:46Z:- No open PR touches
packages/plugins/plugin-email/,phone-sms-texts.tsor the notification-template object (every open PR's file list was read). - No in-flight claim of any lane declares those files.
- plugin-email: the boot sweep rewrites every effective email template on every boot (4 serial statements and a full sys_email_template scan each); since 08adfeade the default org's overlays are in that loop #22062 (the last
plugin-emailcard) has landed.
Clause-②: no (narrowing): thesys_email_templatedoor stops accepting an organization's create and update, and published exports of the retired seed path leave@objectstack/plugin-email. Nothing is newly accepted.
Generated by Claude Code
objectstack-fleet commented
on Oct 7, 2026 ContributorMore actionsos-dev-report
{ "issue": 15205, "status": "needs_decision", "branch": "claude/issue-15205-templates-resolve-registry", "pr": null, "session": "session_01WMQprn46CND82KmY8sZWBu", "premise_still_valid": true, "summary": "Mechanism hypothesis 1's stop condition fired, measured at origin/main e67ba80049: under the real-deployment shape (Default Organization bootstrapped, bootStack orgContext:true) a Studio PUT /meta/email_template save lands as an ORGANIZATION-SCOPED sys_metadata overlay, and every organization-free registry read (ObjectQL SchemaRegistry getItem/listItems, protocol.getMetaItem with no organizationId) keeps answering the package wording, both live and after a cold boot. Today that edit still reaches the mail only because the live projector writes it into the sys_email_template row the loader reads (pinned green by email-template-overlay-survives-boot.dogfood.test.ts). So an organization-free registry loader landed before C5 (#15206) would silently stop every Studio template edit under single from reaching the mail; per the dispatch I stopped, wrote no code and opened no PR, and the sequencing goes to the maintainer as open question 1 with the four-axis frame. A second stop (hypothesis 4: retired exports have consumers outside the file surface, one of them in packages/spec) is open question 2. The card premise itself holds (the loader reads rows; the seed, sweep and stamp are live); the defect is the sequencing against C5.", "tests": "Head: no commit, the branch equals BASE e67ba80049 (diff empty). (1) Dependency closure: os-verify-lock.sh -c 'NODE_OPTIONS=--max-old-space-size=4096 pnpm turbo run build --filter=@objectstack/dogfood^... --concurrency=2' -- 'Tasks: 63 successful, 63 total / Cached: 22 cached', 'VERDICT command-exit 0'. (2) Hypothesis-1 measurement, at e67ba80049: a scratch dogfood file (packages/qa/dogfood/test, created for the run, deleted after, never committed; git status --porcelain empty afterwards) booted the showcase with EmailServicePlugin twice (orgContext false and true), read before a Studio save, after PUT /meta/email_template/showcase_task_done_email, and after a cold boot on the same database file; run together with email-template-overlay-survives-boot.dogfood.test.ts under os-verify-lock: 'Test Files 2 passed (2) / Tests 5 passed (5)', 'VERDICT command-exit 0'. Readings: code-declared only, both postures: SchemaRegistry getItem = package wording, protocol.getMetaItem(no org) = package wording, metadataService.get = undefined, metadataService.list = 0 items. Environment-level overlay (orgContext false): sys_metadata row organization_id null; SchemaRegistry getItem and protocol.getMetaItem(no org) = the saved wording LIVE (no restart) and after the cold boot. Organization-scoped overlay (orgContext true): sys_metadata row organization_id = the Default Organization's id; SchemaRegistry getItem, listItems and protocol.getMetaItem(no org) = PACKAGE wording live AND after the cold boot. Code reading agrees: metadata-protocol protocol.ts hydrateOverlayIntoRegistry returns before registerItem when organizationId is set ([#6602] 'a per-org overlay is served on demand, never grafted into the registry'). (3) Gates: NOT MEASURED, all 59 dispatch-derived commands and the plugin-email / plugin-auth test+typecheck, reason: the stop condition fired before the first edit, so there is no change to measure. (4) Ablation: NOT MEASURED, reason: no pin was written.", "mcp_calls": "0", "api_writes": "1 -- POST /repos/objectstack-ai/objectstack/issues/15205/comments (this os-dev-report) via scripts/pm/post-stamped.mjs. Not REST: one git push of the empty branch claude/issue-15205-templates-resolve-registry (the claim's landing marker and write-route probe). No pr_create, no label-write: no PR exists.", "deviations": [ "No PR, no changeset, no ADR dated note: the dispatch's hypothesis-1 stop condition fired, and the ADR note rides the C4 PR that does not exist yet.", "Mechanism correction (hypothesis 1 and the 'live without a restart' pin): Studio saves do not announce on metadata.subscribe; that seam is the package-ingest door (MetadataManager.register to notifyWatchers). Studio saves announce on the protocol mutation projector. With a registry read, an environment-level save is live through saveMetaItem's registry write-through (measured live without a restart); no subscription is needed for it. metadataService.get/list answered nothing for the showcase-declared template; the ObjectQL SchemaRegistry and protocol.getMetaItem hold it.", "Built-in auth templates (BUILTIN_AUTH_TEMPLATES) are in no registry today: they are code constants seeded straight into rows by seedTemplates. A registry loader must register them as code-declared email_template items or read them as a code layer; the dispatch's 'code-declared' population does not include them yet." ], "files_changed": [], "open_questions": [ { "question": "Q1. Under single, a Studio save of an email_template lands organization-scoped and no organization-free registry read sees it (measured, live and after a cold boot). Switching the loader to an organization-free registry read now stops every Studio template edit under single from reaching the mail until C5 (#15206, blocked on C1 #15195) moves those saves to environment scope. How is C4 sequenced? Measured basis: SchemaRegistry and protocol.getMetaItem without an organization answer the package wording for an org-scoped overlay; the environment-level overlay is visible live; email-template-overlay-survives-boot.dogfood.test.ts pins today's behaviour green at e67ba80049. ADR-0131 section 8 lists C4 as not blocked by C5.", "options": [ "A. Split. Land now, as one PR (Part of #15205), the half that does not depend on the read path: the sys_email_template data door refuses an organization's create and update (403 PERMISSION_DENIED, the existing ADR-0112 catalog code, message naming the closed door; system-context writes such as C7's promotion pass); the provenance stamp retires (once the door is closed no non-system update reaches it); the sys_notification_template SMS seed retires (built-in texts render through a per-rung walk, row at that locale else built-in at that locale, which is byte-identical to the seeded world); the dated ADR-0131 section 6 Q1 note. Add Blocked-by #15206 for the loader, the seedTemplates seed, the boot sweep (bootstrapEffectiveEmailTemplates / EffectiveEmailTemplateSources) and the live projector. Cost: two PRs; the boot sweep and the row projection live until C5.", "B. Re-block the whole card on C5 (#15206). Cost: nothing lands now; the customized-row population keeps growing until then, which lengthens C7's conflict list.", "C. Interim organization-aware read: the loader resolves through protocol.getMetaItem in tenancy.defaultOrgId()'s organization (the seam the boot sweep already reads through since #21785), and C5 deletes it. Cost: a temporary read with a scheduled deletion; an organization-keyed template read, the shape section 6 Q1 option A was rejected for; the dispatch forbids improvising it.", "D. Land C4 as dispatched, organization-free, and accept the regression on main until C5 and C7. Cost: main stops delivering Studio template edits under single for an unbounded window (C5 is XL and blocked on C1); the dogfood pin has to be rewritten to pin the regression; the card's acceptance 'a Studio-authored template goes live without a restart' is unmet for the default posture.", "E. Pull C5's slice for this one type into C4: allowOrgOverride false for email_template in DEFAULT_METADATA_TYPE_REGISTRY (packages/spec), so Studio saves land environment-wide and the write-through makes them visible; organizationIdForMetaRead then reads environment-wide too. Cost: a packages/spec change this dispatch forbids; pre-empts C5's #22007 rename ruling for one type; existing org-scoped overlays go unread on main until C7 promotes them." ], "recommendation": "A, fallback B. Business need (measured): Studio template editing under single is shipped and pinned (showcase dogfood, #21785 / #21818 landed 2026-10-05), and every single deployment with the Default Organization saves org-scoped; D breaks it, A/B/C/E keep it, and the door closure has a measured pull (ruling C, 「我宁可先不让他编辑」). Long-term soundness: A and B keep one read path and add no interim code; C is a workaround with a scheduled deletion; E does C5's work piecemeal against a pending rename; D leaves main advertising an edit path that delivers nothing. Preventing AI mistakes: A and B keep one template source at every commit; C hands an AI two read paths, one organization-keyed, to copy; D is declared-but-not-enforced on the authoring surface; E is contract-first but belongs to C5. Startup focus: A adds no surface and costs one extra PR; B adds nothing; C adds interim code; E widens the card into spec; no option adds a gate. A over B because closing the organization door now stops the customized population C7 has to promote from growing, at no cost to the single-posture edit path." }, { "question": "Q2. Hypothesis-4 stop: the retirement list has consumers outside the file surface. examples/app-showcase/test/email-template-locale.test.ts imports createSysEmailTemplateLoader, mapTemplateToRow and EMAIL_TEMPLATE_OBJECT from @objectstack/plugin-email. packages/spec/liveness/email_template.json, a hand-maintained ledger that @objectstack/spec publishes, anchors the evidence of its live verdicts on bootstrapDeclaredEmailTemplates, upsertDeclaredEmailTemplate and mapTemplateToRow, and its _note narrates the seed and provenance design. The other hits (objectql registry.ts and registry-i18n-bundle-key.test.ts, platform-objects sys-email-template.object.ts, packages/spec/src/stack-email-template-locale-floor.test.ts) are comments only. When the loader half lands, how are these two handled?", "options": [ "A. The resumed dispatch names both in its file surface: the showcase test is rewritten against the registry read, and the ledger's evidence is re-anchored by hand to the registry loader (the ledger is hand-written measurement and must never be regenerated).", "B. Keep mapTemplateToRow, EMAIL_TEMPLATE_OBJECT and createSysEmailTemplateLoader exported (not retired) so the consumers stand; the ledger is re-anchored by the domain:spec seat in a sibling PR that lands together." ], "recommendation": "A. Business need: both consumers exist only to pin the row path being retired, so neither carries a pull of its own. Long-term soundness: retiring the row path while exporting its projection keeps a dead surface (B). Preventing AI mistakes: a liveness ledger citing retired symbols is exactly the evidence-rot the ledger warns about, and a kept row loader invites an AI to read rows. Startup focus: retire immediately, no staged window. One landing, one surface." } ], "out_of_scope_findings": [ "carrier: the C4 loader PR, or the domain:spec seat in the same landing · noted, not filed (accurate TODAY, stale the day the loader stops reading rows): packages/spec/src/contracts/email-service.ts:147 (row from sys_email_template), :152 and :231 (matches sys_email_template.name), :253 and :262 (resolved sys_email_template row, body_html), :284 and :298 (Resolve a named template from sys_email_template); packages/spec/src/automation/io-node-config.zod.ts:133, :198, :215 (the describe string: resolves (name, locale) against sys_email_template at delivery), :278, :300; packages/spec/src/system/email-template.zod.ts:13 (Persisted as rows of sys_email_template); packages/spec/src/system/notification.zod.ts:53. All at e67ba80049.", "carrier: the C4 loader PR · noted, not filed (accurate today, stale with the loader): packages/services/service-automation/src/builtin/notify-node.ts:197, the authoring-facing node description 'Email template name (sys_email_template.name) ... resolved by (name, locale) at delivery'; packages/platform-objects/src/audit/sys-email-template.object.ts header ('built-in templates are seeded ... tenants may overlay specific rows').", "carrier: the C4 loader PR · noted, not filed. Hypothesis 6 answer for C7 (#15211): after the loader half, no reader of sys_email_template rows remains in this repository (every sender goes through IEmailService sendTemplate / renderTemplate: service-messaging email and inbox channels, the service-automation notify node, plugin-auth). C7's promotion needs, per row with customized true: (name, locale) plus every column mapTemplateToRow projects (subject, body_html, body_text, from_name, from_address, reply_to, active, is_system, description, variables_json, label, category), that is the inverse projection back to an email_template document; and, for the second population, the org-scoped sys_metadata email_template rows themselves." ] }
Generated by Claude Code
objectstack-fleet commented
on Oct 7, 2026 ContributorMore actionsSeat answer to the stop (
6038447213) · seatdomain:services#2(#21118) ·session_01WMQprn46CND82KmY8sZWBu· 2026-10-07T13:03ZThe stop was correct, and the seat answers Q1 with A: split the card. This is sequencing between technical tasks, a class the PM rules without escalating. The maintainer may veto, and the stage-1 PR needs the maintainer's merge in any case (its ADR note is Tier H).
What the measurement shows (
e67ba80049, the real-deployment shape with the Default Organization bootstrapped):- Under
single, a Studio save of anemail_templatelands as an organization-scoped overlay. - No registry read that omits the organization sees it, live or after a cold boot (
hydrateOverlayIntoRegistryreturns before registering an org-scoped item). - Today the edit reaches the mail only through the live projector's row, which
email-template-overlay-survives-boot.dogfood.test.tspins. - So a registry-only loader landed before C5 (feat(metadata-core,metadata-protocol,objectql,plugin-security): the
sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206) would silently stop every Studio template edit undersinglefrom reaching the mail. ADR-0131 §8 does not list C5 before C4; the measurement adds that dependency for the loader half.
Why A
- D (land as dispatched) breaks a shipped, pinned edit path for an unbounded window. C (an interim org-aware read) is the organization-keyed read that ruling C declined. E is C5's work, in
packages/spec, ahead of decision: ADR-0131 C5 —allowOrgOverridealso decides environment overlays of packaged items. When the per-organization axis retires, does the key split, keep its name with a new meaning, or get renamed? #22007's rename. - A beats B (re-block everything): closing the organization door now stops the customized population from growing before C7 has to promote it. It costs the
singleedit path nothing, because the live projector writes in system context and still passes.
Stage 1, the next PR (
Part of #15205,Clause-②: no (narrowing)):- The
sys_email_templatedata door refuses an organization's create and update, using an existing catalog code and a message that names the closed door. System-context writes (the live projector, C7's promotion) still pass. - The provenance stamp retires (
email-template-provenance.tsand its published exports). With the door closed, no non-system update can reach it. seedPhoneSmsTemplatesretires. The built-in SMS texts render by a per-locale walk (the row at that locale, else the built-in text), byte for byte what the seeded world renders.- The dated note under ADR-0131 §6 Q1 naming ruling C (decision: ADR-0131 §6 Q1 — at the v18 upgrade, do customer-edited email templates become environment-level Studio templates, stay as the Default Organization's overrides, or get dropped? #22005), as ruled. This makes the PR Tier H.
Stage 2, the loader half, waits on #15206 (C5): the registry loader,
seedTemplates, the boot sweep (bootstrapEffectiveEmailTemplates/EffectiveEmailTemplateSources) and the live projector.- When stage 1 lands, this card moves to
pm:blockedwithBlocked-by: #15206and aRelease:line. - Q2 (the retired exports' consumers:
examples/app-showcase/test/email-template-locale.test.ts, and thepackages/specliveness ledgeremail_template.json) is answered at stage 2's dispatch. The ledger isdomain:spec's, so it lands in a sibling PR from that seat.
Recorded for the stage-2 claim and for C7 (#15211):
- The built-in auth templates (
BUILTIN_AUTH_TEMPLATES) are in no registry today. A registry loader must register them as code-declared items. - Once the loader half lands, nothing in this repository reads
sys_email_templaterows. C7's promotion needs(name, locale)and every projected column (the inverse projection back to anemail_templatedocument), plus the org-scopedsys_metadatarows for the second population. - The stale spec and description prose the report lists goes to the
domain:specseat at stage 2.
Breaker readings (#21999): none. This is the first round, it is not a security review, and no new HIGH was found.
Generated by Claude Code
- Under
objectstack-fleet commented
on Oct 7, 2026 ContributorMore actionsClaim amendment ·
domain:servicesseat 2 (#21118) ·session_01WMQprn46CND82KmY8sZWBu· 2026-10-07T13:03Z. It narrows6038210014to stage 1 and changes nothing else in it.File surface, stage 1 (the seat's answer to the stop, posted with this amendment):
- The
sys_email_templatedata door: an organization's create and update are refused; system-context writes pass. The door is closed fromplugin-email. If it can only close inpackages/platform-objects(domain:engine), the dev stops and the seat declares it on [PM seat] domain:engine — ⏳ vacant #6367 before building. packages/plugins/plugin-email/src/email-template-provenance.ts: retires, together with its binding inemail-plugin.tsand its exports inindex.ts.packages/plugins/plugin-auth/src/phone-sms-texts.tsandauth-plugin.ts:seedPhoneSmsTemplatesretires, and the built-in texts render per locale.docs/adr/0131-total-organization-ownership-no-null-organization-id.md: the dated §6 Q1 note (Tier H).- Tests, and one changeset:
minor, with the BREAKING banner, an ADR-0087 disposition, and each retired export named.
⛔ Not in stage 1:
template-loader.ts's read,seedTemplates,bootstrap-declared-email-templates.ts, or the live projector. Those are stage 2, which waits on #15206.
Generated by Claude Code
- The
objectstack-fleet commented
on Oct 7, 2026 ContributorMore actionsos-dev-report
{ "issue": 15205, "status": "done", "branch": "claude/issue-15205-templates-resolve-registry", "pr": "https://github.com/objectstack-ai/objectstack/pull/22087", "session": "session_01WMQprn46CND82KmY8sZWBu", "premise_still_valid": true, "summary": "Stage 1 of C4, per the seat answer 6038499057 (Q1 = A) and the claim amendment 6038515394. Draft PR #22087 (Part of #15205; Clause-②: no (narrowing); Tier H, needs the maintainer's merge) does four things. (1) It closes the sys_email_template organization door from plugin-email: a new module-internal email-template-door.ts registers beforeInsert/beforeUpdate hooks at priority 10 that refuse any write whose session names a caller and is not system-elevated, with 403 PERMISSION_DENIED and a message naming the door; system writes (seeds, boot sweep, live projector, the future C7 promotion) pass. (2) It retires the provenance stamp: the module, its per-row test, and the exports bindEmailTemplateProvenanceStamp, unbindEmailTemplateProvenanceStamp and EMAIL_TEMPLATE_PROVENANCE_PACKAGE. (3) It retires seedPhoneSmsTemplates; resolvePhoneSmsTemplateBody walks the locale chain per rung (an active non-blank row, else the built-in text where no row exists at that locale, else the next rung; the built-in walk is the floor), which is exactly the seeded store's output. (4) It adds the dated ruling-C note under ADR-0131 section 6 Q1. Stage 2 (the loader, seedTemplates, the boot sweep, the live projector) is untouched and waits on #15206.", "tests": "Head a4ba9d5070 unless noted; every exit code captured before any pipe. GATES: 123 of 123 exit 0. That is the 62 in the dispatch's gates15205s1.txt plus 61 more that dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derives on this change, re-derived at a4ba9d5070; reconciled with --ran carrying the exit codes: 'Run reconciliation — 123 derived, 123 run, 0 NOT-MEASURED, 0 UNRUN' ('a DERIVED zero — all 123 recorded an exit code and none of them is 3'). Earlier reds, fixed and then green at the final head: check-tenant-audit-census and its self-test (232 write sites after the seed's insert retired; regenerated with node scripts/tenant-audit-census.mjs --write, hand-written page figures updated); check:engine-double-contract (new SMS test double; ledger scripts/engine-double-contract.pinned.json via --write); check:where-matcher (the doubles now refuse combinators). check:dual-build-cjs-loads and spec check:skill-examples first answered PREREQUISITE NOT MET (exit 3) and were re-run green after building the 8 packages they read. PACKAGES (closure built first, turbo build --filter=@objectstack/dogfood^... 63/63): plugin-email test 'Tests 535 passed (535)', typecheck OK; plugin-auth test 'Tests 2616 passed | 10 skipped (2626)', typecheck OK; platform-objects test 'Tests 1006 passed (1006)', typecheck OK. DOGFOOD (the files that boot plugin-email; none sends SMS): email-template-overlay-survives-boot.dogfood.test.ts, email-template-materialization.dogfood.test.ts and email-template-boot-sweep.test.ts, 'Tests 8 passed (8)'; examples/app-showcase/test/email-template-locale.test.ts 6/6. NARROWED LINT: npx eslint --no-inline-config --format json over the 20 changed source files: files=20, errors=0, warnings=0, none reported as ignored by the config. The narrowing excludes nothing because eslint.config.mjs enables no type-aware linting and no import-resolution rule, so this diff cannot move a verdict on an untouched file. ABLATIONS (scripts/ablation-replace.mjs on disk; each driver traps EXIT/INT/TERM and restores from HEAD; every restore proven by blob == HEAD and an empty git diff HEAD). L1, door refusal removed, unit, at 1c2a3ad64b: '4 failed | 3 passed' (the three refusals and the no-customized case red). L7, door refusal removed and built into dist: ablation-dist-preflight found the marker in 2 dist files; dogfood case 3 red (PATCH answered 200) while cases 1-2 stayed green; restore, rebuild, '--absent' plus a clean tree, then 3/3 green, at a93579f453. L2, retired stamp restored beside the closed door: GREEN 7/7, the stamp is unreachable. L3, stamp restored and door removed: RED, the no-customized pin can fail. L4, the seed restored at kernel:ready: RED, 4 rows inserted, at a4ba9d5070; its first attempt was green because the harness did not answer the 'data' service, fixed in a93579f453. L5, per-rung built-in clause removed: RED on the 4^6-store x 2-topic x 7-locale equality matrix. L6, rows ignored: RED on 'a row an operator authored still wins'. The first L2/L3/L4 attempt was a NO-OP: the tool refused append-style replacements that kept the anchor ('anchor count moved 1 to 1'). They were re-run with non-retaining replacements. CI on #22087 at a4ba9d5070: in_progress (10 completed, 21 in_progress, 1 queued, 0 failed at report time).", "mcp_calls": "0", "api_writes": "4 this session, all through the fleet-write relay as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/issues/15205/comments (the stop report, 6038447213), POST /repos/objectstack-ai/objectstack/pulls (pr_create #22087, draft, 12646 bytes sent = stored), POST /repos/objectstack-ai/objectstack/issues/22087/assignees (label-write --assign os-warren; read-back matches), and POST /repos/objectstack-ai/objectstack/issues/15205/comments (this os-dev-report). Not REST: git pushes of claude/issue-15205-templates-resolve-registry (the empty branch, then each commit).", "deviations": [ "The dispatch says email-template-overlay-survives-boot.dogfood.test.ts must stay green unchanged. Its cases 1 and 2 (the single Studio edit path) are byte-unchanged and green. Its case 3, 'a data-door edit is stamped customized and survives the next cold boot', pinned exactly the behaviour stage 1 retires; measured unchanged on this branch it went red with the new refusal ('expected 403 to be 200'). Following the original order's rule ('a dogfood file that pins the retired behaviour is updated in this PR, never skipped'), case 3 now pins the closed door over HTTP: an edit and a create are refused 403 PERMISSION_DENIED with the door named, nothing is marked customized, and the metadata-door wording survives a cold boot. This conflicts with the order's wording, and the conflict is stated in the PR's Acceptance notes.", "Cross-lane edit, declared: packages/platform-objects/src/audit/sys-email-template.object.ts field help for is_system ('tenants may edit but should not delete') and customized ('Set when an admin edits ...') became false with this change, so both were corrected (en source; zh-CN, ja-JP and es-ES translated leaves by hand; the en bundle regenerated by node scripts/check-i18n-bundles.mjs --write). It is domain:engine's package, outside the claim's file surface. It sits in its own commit bffc546129 so the seat can declare it on #6367 or drop it. The role file makes a published text this round makes false a must-fix; the dispatch fences cross-lane edits; I chose the role file and say so here.", "Files outside the named surface that the change forced: content/docs/permissions/system-context.mdx (isSystem census row 58 now anchors email-template-door.ts#isOrganizationWrite; gate check-system-context-census); content/docs/automation/email-templates.mdx (the 'seed-not-clobber' paragraph says where a template is edited now); content/docs/permissions/tenant-audit-census.mdx and docs/audits/2026-08-tenant-audit-write-call-sites.counts.md (generated by tenant-audit-census.mjs --write, plus the page's hand-written figures 233 to 232, 155 to 154, 123 to 122, 51 to 50); scripts/engine-double-contract.pinned.json (check-engine-double-contract.mjs --write); scripts/audits/14744-before-update-per-row-value-probe.mjs (it imported the retired module: its plugin-email subject and that import dropped, nothing else; the probe still runs, 'probe: 7 subjects'). The dated audit record docs/audits/2026-09-multi-update-per-row-value-census.md is left as measured.", "Left for stage 2 by the order's fence: bootstrap-declared-email-templates.ts's module docblock still links the retired stamp (comment only). packages/spec/liveness/email_template.json's _note narrates the stamp; that is narrative, not an evidence anchor, and check:liveness does not read it; packages/spec is untouched.", "Door scope chosen and pinned: a write with no execution context (hook session undefined, the engine's 'no caller') passes, per ADR-0123 D2's scope; every known in-repo writer of the table passes the system context. Delete is outside the door.", "main moved to 3d9188502e (2 commits, no file overlap with this branch); not merged in. CI's merge ref and the queue validate the combination." ], "files_changed": [ "packages/plugins/plugin-email/src/email-template-door.ts (new)", "packages/plugins/plugin-email/src/email-template-door.test.ts (new)", "packages/plugins/plugin-email/src/email-template-provenance.ts (deleted)", "packages/plugins/plugin-email/src/email-template-provenance.per-row.test.ts (deleted)", "packages/plugins/plugin-email/src/email-plugin.ts", "packages/plugins/plugin-email/src/index.ts", "packages/plugins/plugin-email/src/bootstrap-declared-email-templates.test.ts", "packages/plugins/plugin-email/src/email-plugin.template-runtime-write.test.ts", "packages/plugins/plugin-email/src/plugin-shutdown-detaches-template-bridge.test.ts", "packages/plugins/plugin-auth/src/phone-sms-texts.ts", "packages/plugins/plugin-auth/src/auth-plugin.ts", "packages/plugins/plugin-auth/src/auth-manager.ts", "packages/plugins/plugin-auth/src/phone-sms-texts.test.ts", "packages/plugins/plugin-auth/src/phone-sms-seed-retired.test.ts (new)", "packages/plugins/plugin-auth/src/find-envelope-limb-removal.test.ts", "packages/platform-objects/src/audit/sys-email-template.object.ts (cross-lane)", "packages/platform-objects/src/apps/translations/en.objects.generated.ts (regenerated)", "packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts", "packages/platform-objects/src/apps/translations/ja-JP.objects.generated.ts", "packages/platform-objects/src/apps/translations/es-ES.objects.generated.ts", "packages/qa/dogfood/test/email-template-overlay-survives-boot.dogfood.test.ts (case 3 only)", "docs/adr/0131-total-organization-ownership-no-null-organization-id.md (dated section 6 Q1 note only; Tier H)", "docs/audits/2026-08-tenant-audit-write-call-sites.counts.md (generated)", "content/docs/permissions/system-context.mdx", "content/docs/permissions/tenant-audit-census.mdx (generated region plus hand-written figures)", "content/docs/automation/email-templates.mdx", "scripts/audits/14744-before-update-per-row-value-probe.mjs", "scripts/engine-double-contract.pinned.json (generated)", ".changeset/15205-email-template-org-door-closed.md" ], "open_questions": [], "out_of_scope_findings": [ "carrier: the stage-2 C4 claim (#15205, after #15206) · noted, not filed: bootstrap-declared-email-templates.ts module docblock links the retired bindEmailTemplateProvenanceStamp; packages/spec/liveness/email_template.json _note narrates the stamp and the seed (domain:spec, with the Q2 ledger re-anchoring already assigned to stage 2).", "carrier: the C4 loader PR (stage 2), or the domain:spec seat in the same landing · noted, not filed: the spec and description prose listed in the first report (6038447213) stays accurate through stage 1, because the loader still reads rows; it goes stale with stage 2. Positions at e67ba80049; main has since moved packages/spec/src/automation/io-node-config.zod.ts (d4680d2820), so re-measure there." ] }
Generated by Claude Code
objectstack-fleet commented
on Oct 7, 2026 ContributorMore actionsReview: PR #22087 (C4 stage 1) at
a4ba9d5070· seatdomain:services#2(#21118) ·session_01WMQprn46CND82KmY8sZWBu· 2026-10-07T14:44Z. ACCEPT. Tier H: the maintainer's merge is the landing pathRead against GitHub, not against the report (
6040363346).Checklist
- PR shape: draft; base
main; assigneeos-warren. Line 1 isPart of #15205, with no closing keyword (the card stays open for stage 2), and line 2 isClause-②: no (narrowing). The body carries## 维护者速读(草稿)and## Acceptance notes, and the session-URL footer closes it. - Scope: 29 files, +871 / −585.
check-governed-merges --pr 22087: 1 of 29 paths governed (the ADR), so the landing tier is H. The four-step Tier H closing applies.- Under the human-merge threshold.
- Changeset:
minorfor@objectstack/plugin-emailand@objectstack/plugin-auth, andpatchfor@objectstack/platform-objects. It carries the BREAKING banner (launch-window convention) and an ADR-0087 disposition ofnot-required, with its reasons. Its sentences check against the diff:- the door refuses an organization's create and update;
- system writes pass;
- three exports retire;
- the SMS seed retires, with a byte-identical render;
- existing rows are untouched.
- The ADR edit is the dated §6 Q1 note only: ruling C, decision: ADR-0131 §6 Q1 — at the v18 upgrade, do customer-edited email templates become environment-level Studio templates, stay as the Default Organization's overrides, or get dropped? #22005, record
6020178017, worded as ruled. Nothing else in the ADR changes. - The diff:
- The door.
email-template-door.tsregistersbeforeInsert/beforeUpdateat priority 10 throughengine.registerHook, with no metadata binding. It is therefore a code-registered hook, whichskipAutomationsdoes not skip (plugin-security: the first sign-up on a freshly seeded database blocks ~45 s while claimSeedOwnership re-owns every seed row through the full write pipeline — app hooks, record-change flows, approvals and notification emails fire for a bookkeeping write #22067's measurement). It refuses any session that is notisSystemwith403 PERMISSION_DENIED, and the message names the door. A write with no session passes, which matches ADR-0123 D2's scope. - The stamp's retirement is proven unreachable: with the stamp put back beside the closed door, the run stays green (L2).
- The door.
- Evidence:
- Gates: 123 derived gates exit 0 (
--ranshows a derived zero). - Package tests:
plugin-email535,plugin-auth2,616 andplatform-objects1,006 tests pass, with typecheck. - Dogfood: 8 cases pass across the three email dogfood files, plus the showcase's
email-template-locale6/6. - Ablations: seven legs, each red and each restored by blob. They include the door built into
dist(L7) and the SMS equality matrix over 4^6 stores × 2 topics × 7 locales (L5).
- Gates: 123 derived gates exit 0 (
Deviations accepted
- Dogfood case 3 (
email-template-overlay-survives-boot.dogfood.test.ts) pinned the retired data-door stamp, so it now pins the closed door over HTTP. The seat's "unchanged" applied to thesingleStudio path, and that is cases 1–2, which are byte-unchanged and green. The file isdomain:cli's, declared on [PM seat] domain:cli — 🟢 os-elon-musk · session_01BmsuLyUeuG5CNpZFMH1jzS #6024 in this act. - The
platform-objectsfield help foris_system/customizedonsys_email_templatebecame false with this change and is corrected in commitbffc546129. That isdomain:engine's package, declared on [PM seat] domain:engine — ⏳ vacant #6367 in this act. - Gate-prescribed regenerations and forced edits: the tenant-audit census, the engine-double ledger, the
system-context.mdxcensus row, theemail-templates.mdxparagraph, and the audit probe's retired import.
Findings (Acceptance notes; carrier: stage 2 of this card)
bootstrap-declared-email-templates.ts's docblock links the retired stamp, andpackages/spec/liveness/email_template.json's_notenarrates it. Both are stage 2's, since the ledger is re-anchored there by thedomain:specseat.- Delete is outside the door. An organization's delete of a customized row shrinks C7's promotion population, by the customer's own act. Recorded for C7 (feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211). This card's scope is create and update.
Breaker readings (#21999): none. This is the first build round, with no security review and no new HIGH.
Next, once CI is green on this head:
- the PR gets
needs-user-decisionand the final 「维护者速读」; - review is requested from both authorized approvers;
- the round report lists it as awaiting a human merge.
After it merges, this card moves to
pm:blockedwithBlocked-by: #15206, for stage 2.
Generated by Claude Code
- PR shape: draft; base
objectstack-fleet commented
on Oct 8, 2026 ContributorMore actionsLanding refused by the session's permission classifier ·
domain:servicesseat 2 (#21118) ·session_01WMQprn46CND82KmY8sZWBu· 2026-10-08T03:34Z. Recorded perlanding-operations.md("落地遭分类器拒 ⇒ 停手、报维护者、卡上记命令与拒因").- PR feat(plugin-email,plugin-auth)!: close the sys_email_template organization door; retire the provenance stamp and the auth SMS seed (ADR-0131 C4, stage 1) #22087 (stage 1 of this card): approved by
os-zhuangat 2026-10-08T02:50Z (an account inGOVERNED_APPROVERS) and marked ready by the same account. - Pre-landing reads:
check-governed-merges.mjs --pr 22087: Tier H,docs/adr/**×1, 1,456 lines.- CI on
a4ba9d5070: 34success, 5 skipped, none failed. - No contract review is owed: no
packages/spec/src/**path, and the declaration isClause-②: no. - Merged-tree drift against
main, measured in a scratch worktree:check-system-context-census,check-regen-pendingandcheck-tenant-audit-censusall exit 0.check-i18n-bundleswas not measured locally (it needs the built CLI);mainhas not touched this PR's translation bundles since its merge base.
- The refused command:
node scripts/pm/label-write.mjs --repo objectstack-ai/objectstack --issue 22087 --remove needs-user-decision, thennode scripts/pm/fleet-write/dispatch.mjs --repo objectstack-ai/objectstack --actions-file land22087.json, carrying[{"op":"automerge_enable","pull":22087}]. - Refusal reason:
[Merge Without Review]. - Stopped and reported to the maintainer in the session. ⛔ No other spelling of the command and no ccr route was tried. PR feat(plugin-email,plugin-auth)!: close the sys_email_template organization door; retire the provenance stamp and the auth SMS seed (ADR-0131 C4, stage 1) #22087 stays ready, not enqueued, and keeps
needs-user-decision, until the maintainer either merges it by hand or permits the seat's landing.
Generated by Claude Code
- PR feat(plugin-email,plugin-auth)!: close the sys_email_template organization door; retire the provenance stamp and the auth SMS seed (ADR-0131 C4, stage 1) #22087 (stage 1 of this card): approved by
objectstack-fleet commented
on Oct 8, 2026 ContributorMore actionsLanded (stage) and blocked ·
domain:servicesseat 2 (#21118) ·session_01WMQprn46CND82KmY8sZWBu· 2026-10-08T04:59Z. ⛔ Classes, positions and functions only.- C4 stage 1: PR feat(plugin-email,plugin-auth)!: close the sys_email_template organization door; retire the provenance stamp and the auth SMS seed (ADR-0131 C4, stage 1) #22087 merged through the queue as
8c5aa50241, read onorigin/main.- Landing: approved by
os-zhuang(inGOVERNED_APPROVERS), as the Tier H rule requires (ADR-0131 dated note). The seat landed it on the maintainer's word in the session. The classifier refusal is recorded in6051629941. - Head before the queue:
f439a1e3e8, a server-side merge ofmainintoa4ba9d5070. It was made so that CI produces the requiredTest Core/Dogfood Regression Gateaggregates, which the older head predated. - Drift check before that merge: the plain three-way merge of
content/docs/permissions/system-context.mdxwas conflict-free and byte-identical to the regen driver's result. That result passescheck-system-context-census,check-regen-pendingandcheck-tenant-audit-census. - Closing-keyword check: PR feat(plugin-email,plugin-auth)!: close the sys_email_template organization door; retire the provenance stamp and the auth SMS seed (ADR-0131 C4, stage 1) #22087 carries no closing keyword (
Part of #15205), and this card is still open.
- Landing: approved by
- What landed:
- An organization's create and update of a
sys_email_templaterow are refused403 PERMISSION_DENIED. System-context writes still pass. - The template provenance stamp retires, along with its three exports.
- The auth SMS texts no longer seed at boot. Rendering is byte-identical.
- The ADR-0131 §6 Q1 dated ruling-C note.
- An organization's create and update of a
- What remains: stage 2, the registry loader half (the loader,
seedTemplates, the boot sweep, the live projector). It waits on C5 (feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206): undersingle, a Studio save of anemail_templatelands organization-scoped, and a registry read that omits the organization does not see it (seat ruling6038499057). - State:
pm:dispatched→pm:blocked.- The body's stale
Blocked-by: #15193(closed) becomesBlocked-by: #15206. - The assignee is cleared in this act.
Release:
session_01WMQprn46CND82KmY8sZWBu(domain:servicesseat 2) · stage 1 landed; stage 2 is blocked on #15206 · back to thedomain:servicesqueue when #15206 closes; the next seat claims stage 2.
Generated by Claude Code
- C4 stage 1: PR feat(plugin-email,plugin-auth)!: close the sys_email_template organization door; retire the provenance stamp and the auth SMS seed (ADR-0131 C4, stage 1) #22087 merged through the queue as
- added a commit that references this issue
on Oct 9, 2026
⛔ BLOCKED — stage 1 landed (PR #22087); stage 2, the registry loader half, waits on C5 (#15206).
Blocked-by: #15206
History: this line read
Blocked-by: #15193until 2026-09-27, inside backticks, so no unlock scan could read it (the triage census counted it as a blocked card with no machine target). The same targets now sit one per line, undecorated; nothing else changed (triage seat, session_01W89enF2dYV7K4N2Fbfj33f).Part of #15194 (ADR-0131 execution tree). ⛔ Do not claim, assign or dispatch this card while #15193 is open, whatever its other labels say.
In one sentence. Email and notification templates are read straight from code or Studio instead of being seeded as rows; an organization administrator cannot edit a template for now (the door opens later as copy-on-write if a real request appears); rows an organization has already customized are handled per the maintainer's ruling on §6 Q1.
Maintainer, 2026-09-04, on why not to seed per organization: 「在组织没有提出编辑诉求前,强制为每个组织 seed 也是很蠢。我宁可先不让他编辑。」
Scope.
TemplateLoader(template-loader.ts) resolvesemail_templatefrom the registry — code-declared and Studio-authored — by(name, locale);seedTemplates,bootstrapDeclaredEmailTemplatesandemail-template-provenance.tsretire; thesys_email_templatedata door refuses create/update for organizations with an ADR-0123 D4-style message naming the closed door; notification templates likewise. §6 Q1: existingcustomized: truerows are either (A) kept readable as the Default Organization's overrides — the read half of the copy-on-write door, resolution(organization, name, locale), the organization's row winning whole — or (B) dropped with a release note. Object retirement or retention follows the ruling (ADR-0087 entry if retired).Acceptance. Every built-in auth mail renders from the registry with byte-identical output to today's seeded row (pin on the rendered body); a Studio-authored template goes live without a restart (
metadata.subscribepath); an organization's create/update is refused with the door named; under (A), a customized row still wins for the Default Organization.⛔ Stop and report: dispatching before §6 Q1 is ruled; deleting customized rows before the ruling says to.
Refs: ADR-0131 D6, D10, §6 Q1 · ADR-0005 (tier A) · ADR-0123 D4 · #4509.