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:
@@ -508,7 +508,7 @@ is only harmless while the default is off. Existing subscriptions are carried ac
|
|||||||
| audience_segment_id | INT NULL | a composed segment (§5.1a). **Deliberately no FK** — see below |
|
| audience_segment_id | INT NULL | a composed segment (§5.1a). **Deliberately no FK** — see below |
|
||||||
| max_sends_per_hour | INT NOT NULL DEFAULT 100 | the hard per-rule ceiling (§7.1 Q3), counted in `engagement_sends` and enforced before an outbox row is written |
|
| max_sends_per_hour | INT NOT NULL DEFAULT 100 | the hard per-rule ceiling (§7.1 Q3), counted in `engagement_sends` and enforced before an outbox row is written |
|
||||||
| channels | JSON NOT NULL | `['email','inapp']` — a rule may span channels |
|
| channels | JSON NOT NULL | `['email','inapp']` — a rule may span channels |
|
||||||
| template_keys | JSON NOT NULL | `{ email: 'idoc-warning' }`. Keys are shape-checked, not existence-checked: templates are Phase 5 |
|
| template_keys | JSON NOT NULL | `{ email: 'idoc-warning' }`. Keys are shape-checked, not existence-checked: templates are Phase 5. Every key is one of the rule's `channels` **plus one that is not a channel at all**: `digest` names the body the digest worker renders for a rule whose email channel an individual set to digest mode, so it belongs to a mode and can never appear in `channels`. The rules validator rejected it until website#181, which made every rule shipping one — core's own Team and news rules included — unsaveable from the Rules screen |
|
||||||
| conditions | JSON NULL | a small closed and/or/not grammar over the trigger's **declared** variables |
|
| conditions | JSON NULL | a small closed and/or/not grammar over the trigger's **declared** variables |
|
||||||
| cooldown_seconds | INT NOT NULL DEFAULT 0 | 0 = no cooldown |
|
| cooldown_seconds | INT NOT NULL DEFAULT 0 | 0 = no cooldown |
|
||||||
| delay_seconds | INT NOT NULL DEFAULT 0 | the grace window (§4.2a) |
|
| delay_seconds | INT NOT NULL DEFAULT 0 | the grace window (§4.2a) |
|
||||||
|
|||||||
@@ -3852,8 +3852,15 @@ is the Phase 11b defect class staying fixed.
|
|||||||
key they never typed. The only way to save is to delete the digest body, which silently removes
|
key they never typed. The only way to save is to delete the digest body, which silently removes
|
||||||
digest support from that rule. The two validators have to agree about what `digest` is.
|
digest support from that rule. The two validators have to agree about what `digest` is.
|
||||||
|
|
||||||
Neither is fixed here: this phase's PR is the documentation of a cutover, and a core change belongs
|
**Both are fixed in website#181.** `settings.db` gained `claim(key, value)` — the same
|
||||||
in its own. Both are recorded for the org lead to place.
|
`INSERT IGNORE` as `seedDefault`, reporting its own `affectedRows`, so exactly one caller can win a
|
||||||
|
key — and both seeders now claim before inserting rather than stamping after. The trade the code
|
||||||
|
already documented is unchanged, only its order: a process that dies mid-loop leaves the group
|
||||||
|
stamped and partly seeded, which both functions already called the better failure. The stubs are
|
||||||
|
`claim`-shaped now and each suite gained a test that runs two seeders under `Promise.all`; reverting
|
||||||
|
the fix makes the module one report every rule inserted twice, which is how the fix was checked. And
|
||||||
|
`engagementRules.model.js` now admits `digest` as the one key that is a slot rather than a channel,
|
||||||
|
so the two validators agree; anything else is still refused, with a test in each direction.
|
||||||
|
|
||||||
**Also still open:** nothing else. `.profile/README.md` (step 8) landed — the org lead called the
|
**Also still open:** nothing else. `.profile/README.md` (step 8) landed — the org lead called the
|
||||||
engagement system a headline capability — and Phase 12's second finding became **Phase 14**.
|
engagement system a headline capability — and Phase 12's second finding became **Phase 14**.
|
||||||
|
|||||||
@@ -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
|
`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
|
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.
|
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.
|
- **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.
|
**`onBoot(fn)` / `onShutdown(fn)`** — §2.5.
|
||||||
|
|||||||
Reference in New Issue
Block a user