From 5b954a7f6cd6ef54c8d73556c6e78c8ac5976659 Mon Sep 17 00:00:00 2001 From: Drewry Pope Date: Tue, 3 Nov 2026 09:03:39 -0600 Subject: [PATCH] docs(aggregator): state the alert throat's truth contract in the alerts.ts header (#3703, #3702) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 3 of design #3702: the contract the throat's records and responses must keep — transitions recorded only when the named event happened (delivered/escalated need an accepted send, gone is not a send), key material never leaves the server and HTTP surfaces project, preferences validated as values with per-field fallback to default. Comment-only: no behaviour changes. --- pm-stack/aggregator/src/alerts.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pm-stack/aggregator/src/alerts.ts b/pm-stack/aggregator/src/alerts.ts index 375d24643..26af109d7 100644 --- a/pm-stack/aggregator/src/alerts.ts +++ b/pm-stack/aggregator/src/alerts.ts @@ -9,6 +9,17 @@ // immediately, quiet hours or not, because the sentinels are // external to the thing that might be down. Warnings never push in // v1 (page + ledger only). +// +// The throat's truth contract (#3702 Phase 3, 2026-11-03): the alert +// throat's records and responses tell the truth and keep its secrets. +// A state transition is recorded only when the event it names happened +// (delivered / escalated require at least one accepted send; `gone` is +// not a send). Subscription key material (`p256dh`, `auth`) never +// leaves the server: store rows are internal, any HTTP surface +// projects — the page's projection is the only read shape. Subscription +// preferences are validated as values, not shapes, and an invalid value +// falls back per-field to the default — never stored, never +// reinterpreted. import type { Config } from "./config.ts"; import { sendPush, type PushOutcome, type PushTarget } from "./push.ts"; import { getSupabaseClient, sqlInt, sqlJson, sqlStr, type SupabaseClient } from "./supabase.ts";