docs(engagement): the two walk defects, fixed -- and what digest is

Follows docs#203, which recorded the two defects Phase 13's acceptance walk found
and left them for placing. They are fixed in website#181, so Phase 13's as-built
says so and says what the fix was rather than leaving a reader to find the PR.

Two other files were describing a contract the code did not honour, which is why
the second defect could exist at all:

  * BACKEND_DESIGN's `template_keys` column row said only that keys are
    shape-checked. It now says the one thing that was actually load-bearing --
    `digest` is a key that is NOT a channel, because it names a MODE's body --
    and that the rules validator rejected it until website#181, which made every
    rule shipping one unsaveable from the Rules screen, core's own included.
  * MODULE_API 2.4 already told modules they may point `template_keys` at
    `notify.digest` and never said what `digest` was. A module author reading it
    would reasonably have expected it to be a channel. One bullet, next to the
    generic-bodies one that sends them there.

No contract changed; the docs were right and the code was wrong. No
MODULE_API_VERSION bump for the same reason.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-09-01 14:31:00 -05:00
parent 924204f8ba
commit b3dd2c7cbb
3 changed files with 13 additions and 3 deletions

View File

@@ -856,6 +856,9 @@ are in §1.1 under **1.9.0**; four things are contract rather than implementatio
`notify.event` / `inapp.event` / `notify.digest` and author nothing — §4.6.1 property 1. Ship a
bespoke body when the message has something to say that the structural projection cannot; a trigger
whose message is "this happened, here is the link" should not have one.
- **`digest` is a slot, not a channel.** It names the body the digest worker renders for a rule whose
email channel an individual set to digest mode, so it is legal in `template_keys` and never appears
in `channels`. Every other key must be one of the rule's channels.
- **It is not a send path.** Every value on the object is data. Core still decides who is told.
**`onBoot(fn)` / `onShutdown(fn)`** — §2.5.