docs(website): the seeded template set as built (engagement Phase 5a) #185

Merged
whitlocktech merged 1 commits from docs/engagement-templates into edge 2026-08-29 18:13:48 +00:00
Member

Companion to website#172 (engagement Phase 5a). §6.0b assigns this phase two documents; both land here, and the row itself is split so 5a and 5b each own theirs.

ENGAGEMENT.md — "As built — 5a"

The three decisions the org lead settled before any code, each because the tree contradicted something the plan assumed:

  • Not one existing mail had an HTML part. All six senders in mailer.js set text: only, so "renders byte-comparably" was a statement about a text body and whether 5a introduced HTML to live mail was an open choice. It did: multipart, with the text part byte-identical.
  • The server block registry has no renderer of any kind. Page blocks are drawn by React on the client and registerBlock freezes a fixed field set, so a toHtml/toText passed to it is silently dropped — §4.4's "reuse the block registry" needed a mechanism that did not exist.
  • Nine seeds, six wired, because teamNotify/teamDigestWorker are explicitly Phase 6's to rewrite.

And a correction to §4.6.1 itself: it lists auth.email-verify as "(new — Phase 9)", but Phase 1b already shipped sendEmailVerification. Six bodies moved, not five.

The section also records the things that will not be recoverable from the code six months from now: why two registries rather than one (and what one Map would have cost), why the ternaries stayed at the call site and arrive as forWhom-style variables, why the shell contributes no content, why only the accent comes from the theme, and why the seeder's customized = 0 guard is in the UPDATE's own WHERE rather than in a read-then-write.

Plus the foundRows: true note, recorded here because Phase 4a was bitten by exactly this: affectedRows on an UPDATE counts matched rows, which is harmless for the seeder and is the wanted semantics for an operator's save — now stated in the code rather than relied on.

And the two behaviour changes an operator will notice: mail is multipart/alternative, and subjects now resolve settings.getInstanceName() (the admin-set site_title) rather than BRAND_NAME alone.

BACKEND_DESIGN.md

  • engagement_templates — the column table, with the reasoning that is not recoverable from the DDL: why trigger_id has no foreign key, what the three seed columns are together, and why a missing row renders the shipped default rather than nothing.
  • The two block registries — the three reasons they are siblings, and what is shared by binding rather than by copy.
  • The token grammar{{ name }} and nothing else, the escape/re-check rules, and the four ambient brand variables that are merged over whatever a caller passes.
  • §7 gains the note that each sender now owns its recipient, headers and failure contract but not what it says, that mail is multipart with a byte-identical text part, and that subjects resolve the deployment's own name.

  • AI-assisted: written with Claude Code (Opus)

🤖 Generated with Claude Code

Companion to **website#172** (engagement Phase 5a). §6.0b assigns this phase two documents; both land here, and the row itself is split so 5a and 5b each own theirs. ## `ENGAGEMENT.md` — "As built — 5a" The three decisions the org lead settled before any code, each because the tree contradicted something the plan assumed: - **Not one existing mail had an HTML part.** All six senders in `mailer.js` set `text:` only, so "renders byte-comparably" was a statement about a *text* body and whether 5a introduced HTML to live mail was an open choice. It did: multipart, with the text part byte-identical. - **The server block registry has no renderer of any kind.** Page blocks are drawn by React on the client and `registerBlock` freezes a fixed field set, so a `toHtml`/`toText` passed to it is silently dropped — §4.4's "reuse the block registry" needed a mechanism that did not exist. - **Nine seeds, six wired**, because `teamNotify`/`teamDigestWorker` are explicitly Phase 6's to rewrite. And a correction to §4.6.1 itself: it lists `auth.email-verify` as *"(new — Phase 9)"*, but Phase 1b already shipped `sendEmailVerification`. Six bodies moved, not five. The section also records the things that will not be recoverable from the code six months from now: why two registries rather than one (and what one Map would have cost), why the ternaries stayed at the call site and arrive as `forWhom`-style variables, why the shell contributes no content, why only the accent comes from the theme, and why the seeder's `customized = 0` guard is in the UPDATE's own WHERE rather than in a read-then-write. Plus the `foundRows: true` note, recorded here because **Phase 4a was bitten by exactly this**: `affectedRows` on an UPDATE counts *matched* rows, which is harmless for the seeder and is the wanted semantics for an operator's save — now stated in the code rather than relied on. And the two behaviour changes an operator will notice: mail is `multipart/alternative`, and subjects now resolve `settings.getInstanceName()` (the admin-set `site_title`) rather than `BRAND_NAME` alone. ## `BACKEND_DESIGN.md` - **`engagement_templates`** — the column table, with the reasoning that is not recoverable from the DDL: why `trigger_id` has no foreign key, what the three seed columns are together, and why a missing row renders the shipped default rather than nothing. - **The two block registries** — the three reasons they are siblings, and what is shared by binding rather than by copy. - **The token grammar** — `{{ name }}` and nothing else, the escape/re-check rules, and the four ambient brand variables that are merged *over* whatever a caller passes. - **§7** gains the note that each sender now owns its recipient, headers and failure contract but not what it says, that mail is multipart with a byte-identical text part, and that subjects resolve the deployment's own name. --- - [x] AI-assisted: written with Claude Code (Opus) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
wtclaude added 1 commit 2026-08-29 18:10:01 +00:00
Companion to website#TBD. §6.0b assigns this phase two documents; both land here.

ENGAGEMENT.md gains an "As built — 5a" section: the three decisions the survey
forced, the argument for two registries rather than one, why the ternaries stayed
at the call site, and the two behaviour changes an operator will notice.

BACKEND_DESIGN.md gains the `engagement_templates` table, the two-block-registry
split, the token grammar, and the §7 note that mail is now multipart.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech merged commit c03dfc14ba into edge 2026-08-29 18:13:48 +00:00
whitlocktech deleted branch docs/engagement-templates 2026-08-29 18:13:49 +00:00
Sign in to join this conversation.
No description provided.