- digest.gating_changed outbound event β closes the named rev-89 next-sprint candidateRev 89's running state explicitly named 'per-recipient gating push notification' as the rev-90 candidate, citing the rev-37 closure-receipt pattern at the digest gating axis as the natural next step. Rev 90 closes that. New `digest.gating_changed` outbound event + `dispatchDigestGatingChangedWebhook()` dispatcher + private `notifyDigestGatingFlip()` helper in `src/lib/workspaces.ts` wired into `setDashboardPrefs()` via fire-and-forget `void β¦catch(() => null)` so a downstream Slack/email/webhook failure can't ripple back to block the prefs save itself. Fires only when (a) the rev-80 `digestQuietWeekends` or rev-81 `digestQuietHoursStart`/`digestQuietHoursEnd` prefs are in the patch AND (b) the today gating outcome actually flipped for the simulated-now instant in workspace TZ AND (c) the recipient is an owner/admin (so the change actually affects who would receive the digest). Activity-log entry + outbound payload include both previous and next gating outcomes (`weekendMuted`, `quietHoursMuted`, `wouldSend`) plus the evaluated instant + workspace timezone so a downstream audit trail can reconstruct exactly when the flip happened. **Strategic significance**: closes the rev-37 closure-receipt pattern at the digest gating axis. Until rev 90 downstream integrations watching the rev-80/81 quiet-window primitives (via the rev-89 v1 multi-recipient gating endpoint) had to *poll* for changes β there was no event-bus signal saying 'Maria's quiet-hours config just changed and she's now muted today.' Rev 90 closes the loop. The full digest gating axis now has read (rev 89 multi-recipient endpoint) + write (rev 79/80/81 dashboardPrefs) + closure-receipt event (rev 90) on every channel.
- GET /api/v1/workspace/digest-config β aggregate digest configuration snapshotNew bearer-auth aggregate read endpoint that returns workspace-level digest config (digestEmail bool + IANA timezone) + every owner/admin recipient's per-recipient dashboardPrefs (digestPersonalSections / digestQuietWeekends / digestQuietHoursStart-End) in one call. Until rev 90 an MCP host or audit tool wanting to render 'this workspace's full digest configuration' had to enumerate three round trips β workspace + members + per-recipient prefs β collapsing to one bearer-auth call now. Pure read-only, no side effects. Listed in the `/api/v1` self-describing index. **Strategic significance**: closes the procurement-friendly aggregate read surface for the rev-80/81/89 digest gating cluster. Pairs with the rev-86 send-test (real email) + rev-87 view-preview HTML (render only) + rev-88 simulated-date primitive (gating block in JSON) + rev-89 multi-recipient gating endpoint (per-recipient gating outcome at an instant) as the fifth instrument on the digest verification cluster β this one is the configuration *snapshot* surface. The MCP server's digest-config tooling now has nothing left to design.
- Activity-log glyph + per-kind tint for digest_gating_changeExtends the rev-35/86 glyph + tint vocabulary to cover the new rev-90 `digest_gating_change` activity-log kind. Traffic-light glyph (π¦) so operators reading the activity log see the gating-flip surface distinct from the cost-spike (β‘) and chronic-warning (β³) glyphs β gating-change is a transition signal, not an alarm. New `.ld-activity-digest_gating_change` per-kind tint uses a brand-green palette (rgba(15,118,110,*)) so it reads as state-positive (the rev-37 task.unblocked closure visual vocabulary) rather than amber/red (alarm). **Strategic significance**: closes the per-kind activity-log scannability symmetry on the new rev-90 closure-receipt kind in the same cycle the kind ships. The activity log now reads at three levels β visual (glyph + colour), categorical (chip filter), keyword (search). The dashboard-side audit trail surface for the digest gating axis is now complete.
- Visual polish β gating pill state-pulse + simulated-date persistenceTwo cumulative micro-polish pieces (every rev 22+ has carried at least one). (a) The rev-89 gating pill now rings out with a brief 0.6s 1.04Γ scale + soft brand-color glow (`@keyframes ld-digest-gating-pulse`) every render β the rev-89 `transition` rule already smoothed colour changes; the new keyframes draws the operator's eye to the pill on first render and on every re-render after a simulated-date change so the operator catches the gating-outcome flip without re-reading the surrounding copy. Matches the rev-37 task.unblocked + rev-85 reset-chip success-pulse vocabulary so all the dashboard's transition-signal affordances ring out the same way. (b) The rev-89 `<input type="datetime-local">` value now persists in localStorage under a per-workspace key so admins iterating on rev-78/79/80/81 configuration don't lose their simulated instant on every refresh. Lazy initializer keeps SSR clean. **Strategic significance**: keeps the rev-by-rev visual-hierarchy discipline alive β every chip + pill on the integrations panel now wears its own state vocabulary AND survives across refreshes. Operators iterating on configuration over a coffee break don't have to re-type the simulated-date when they come back.