The dependency
#92 splits the HKDF label the Slack notice signs under. The receiver must change to match, and until it does every notice fails with a 401 — silently and indefinitely, because a failed notice is correctly never fatal. Nothing turns red, nothing pages, and the digest simply stops arriving in the channel.
What changed on the dispatcher
Before, the verdict callback and the notice derived one key from one label. SlackVerdictPayload.origin carries channel and thread_ts — it names a destination; SlackNoticePayload deliberately cannot. One key meant a notice-key holder could sign a verdict naming any channel the bot can see, which collapses the notice's central claim that its shape is what bounds it. A shape bounds only while nothing else can sign a different shape with the same key.
| Surface |
HKDF info label |
Status |
| Verdict callback |
flare-dispatch/slack-notify/v1 |
unchanged — already-deployed receivers keep working |
| Notice |
flare-dispatch/slack-notice/v1 |
new — receiver must adopt |
Keying material is unchanged: same ikm (SLACK_NOTIFY_SECRET, else HMAC_SECRET), same salt (empty), same SHA-256, same 256 bits, same hex-string-as-HMAC-key convention. Only the info label moves.
What the receiver must do
In fractalbot#27 (feat/flare-dispatch-notify-receiver), deriveNotifyKey must derive the notice key under the exact string:
flare-dispatch/slack-notice/v1
info: enc.encode("flare-dispatch/slack-notice/v1"),
If that repo also verifies verdicts, that path keeps flare-dispatch/slack-notify/v1 — the two are now separate keys and the receiver needs both.
Deploy ordering
Receiver accepts the new label → deploy this dispatcher → run the dogfood in apps/dispatcher/specs/slack-origin.md § Dogfood: a scheduled digest reaches a channel with no thread to reply to.
Reversing that order costs a window where notices 401 and nothing reports it. Verdicts are unaffected in either order.
How a mistake surfaces
apps/dispatcher/src/slack-notify.notice.test.ts § the receiver's own verification carries the receiver's derivation verbatim and pins both label strings as literals, so a dispatcher-side rename alone is a red test. It cannot see the receiver's actual source — that is what this issue is for.
Close this when fractalbot#27 derives under the new label and the dogfood has run once.
The dependency
#92 splits the HKDF label the Slack notice signs under. The receiver must change to match, and until it does every notice fails with a 401 — silently and indefinitely, because a failed notice is correctly never fatal. Nothing turns red, nothing pages, and the digest simply stops arriving in the channel.
What changed on the dispatcher
Before, the verdict callback and the notice derived one key from one label.
SlackVerdictPayload.origincarrieschannelandthread_ts— it names a destination;SlackNoticePayloaddeliberately cannot. One key meant a notice-key holder could sign a verdict naming any channel the bot can see, which collapses the notice's central claim that its shape is what bounds it. A shape bounds only while nothing else can sign a different shape with the same key.infolabelflare-dispatch/slack-notify/v1flare-dispatch/slack-notice/v1Keying material is unchanged: same
ikm(SLACK_NOTIFY_SECRET, elseHMAC_SECRET), same salt (empty), same SHA-256, same 256 bits, same hex-string-as-HMAC-key convention. Only theinfolabel moves.What the receiver must do
In
fractalbot#27(feat/flare-dispatch-notify-receiver),deriveNotifyKeymust derive the notice key under the exact string:If that repo also verifies verdicts, that path keeps
flare-dispatch/slack-notify/v1— the two are now separate keys and the receiver needs both.Deploy ordering
Receiver accepts the new label → deploy this dispatcher → run the dogfood in
apps/dispatcher/specs/slack-origin.md§ Dogfood: a scheduled digest reaches a channel with no thread to reply to.Reversing that order costs a window where notices 401 and nothing reports it. Verdicts are unaffected in either order.
How a mistake surfaces
apps/dispatcher/src/slack-notify.notice.test.ts§the receiver's own verificationcarries the receiver's derivation verbatim and pins both label strings as literals, so a dispatcher-side rename alone is a red test. It cannot see the receiver's actual source — that is what this issue is for.Close this when fractalbot#27 derives under the new label and the dogfood has run once.