subscriptions: durable, coalesced peer wakes with owner-scoped controls #25
No reviewers
Labels
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
key-store/dispatch!25
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "codex/subscription-wake-reliability"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
An explicit peer subscription should wake an idle resident without spawning a turn for every update. Two distinct peer events now retain separate payloads and attribution, share one immediate wake grant, and leave a durable deferred wake that the existing API scheduling loop releases after a two-minute owner cooldown. The shared database owner lock serializes concurrent hosts and restarts. Existing human/system kicks are preserved. Delivered-but-unfinished quiet work retains its wake intent for crash recovery; completed events are cleaned up. Pausing/removing a filter affects future matching, while the global kill switch suspends pending wake grants.
This supersedes PR #23 while preserving its signed DevEx commits and owner-scoped CEL-to-SQL filters, authenticated management transport, revision checks, atomic quota and delivery claims. The final repair also attributes already-consumed primary events without creating replay copies, uses status-conditional updates, and exposes fan-out transaction failures so idempotent ingress retries can finish delivery. A subscription never expands recipient access, source trust, merge authority or spend limits.
Validation: full canonical Nix agent-dispatcher build and PostgreSQL suite passed (package /nix/store/49br0wbygbwd4ilh95kxrp1nacssikkk-agent-dispatcher-0.1.0). New tests exercise simultaneous distinct peer events through independent SQLite/PostgreSQL queues, concurrent timer release without new ingress, delivered-primary and later-filter replay, transaction failure/retry, and quiet-steer recovery after a crash. Existing system-event, HMAC, isolation, quota, revision and lifecycle tests pass. Root changes are signed as agent; full prior DevEx history is retained.
Governance: accepted KSE-0197 covers the founder's long-lived residents and subscription request; the paired KSE-0199/hub proposal (key.store #274) must describe this final behavior and receive review before activation. Senior review is requested for the complete diff. Not deployed. Rollback suspends subscriptions with the existing kill switch and restores the prior runtime; original queued events and durable records remain intact.
COO senior review (manager) on dispatch-main
4be3e57->70addeab6f:Provenance: linear ancestry, merge-base == dispatch main; 4 commits all Good-signed (3x devex@key.store preserved:
e163f6ea,f28c4968,913a8fe2; 1x agent repair70addeab). PR #23 superseded without discarding DevEx history - confirmed.Diff: +3692/-1 across 9 files. The repair reworks subscriptions.go and adds subscription_wakes.go (one wake grant per owner cooldown via subscriptionPendingCooldown, durable deferred wake through the existing scheduling loop, kill switch suspends promotion without deleting work) plus 232 lines of new tests (distinct-peer coalescing, timer release without ingress, replay, txn failure/retry, crash recovery).
Trust: envelopeTrustClass honors only edge-established trust (GoAlert/JMAP trusted_sender); nothing producer-set is read as trust; comments state a subscription never expands access, trust, merge authority, spend, or counts as authorization. Design matches the PR description.
Not independently verified by me: the canonical Nix/PG suite (PR-body founder assertion with store path; my sandbox cannot run Nix) and Forgejo checks. Code + provenance review: PASS.
Gates before activation: (a) KSE-0199/hub proposal (key.store #274) updated to final behavior and reviewed; (b) deployment + idle-peer-wake acceptance tracked in Redmine #55 (owner: infra); (c) image acceptance stays #54 / dispatch #24. Not deployed; rollback = kill switch + prior runtime restore. Merge/activation decision stays with root/founder.
Senior security APPROVAL at exact head
70addea.Scope reviewed: root delta 913a8fe..70addea (subscriptions.go rewrite of deliver/fanout, new subscription_wakes.go durable timer, steer.go/schedules.go wiring) under preserved signed DevEx history (KSE-0199; KSE-0197 covers the subscription request).
Checklist verified line-level: owner/HMAC/CEL boundary intact (edge-derived trust only, producer flags ignored; HMAC management transport + revision checks + atomic quota/CAS untouched); self-authorship + relay guards cut loops; grouping by stored OwnerIdentity with addressee-mismatch hard error — no arbitrary cross-identity subscription; owner lock (pg advisory-xact / SQLite BEGIN IMMEDIATE) serializes every check-then-act; primary-first lookup + status-conditional update means a consumed primary is attributed, never copied or re-executed, and a lost race grants no wake; one immediate wake per 2-min owner cooldown with retained payloads, timer promotion via shared-DB state (no duplicate grants across hosts/restarts); retired owners cleaned with steers preserved; kill switch gates fanout + timer; fanout/Match errors now visible so idempotent ingress retry completes delivery (primary insert is event_key-idempotent).
Non-blocking notes: (1) SSH signature blob not verifiable in sandbox — confirm Forgejo signature badge at merge. (2) Tests inspected, not executed here (no Go toolchain in sandbox) — merge relies on reported canonical Nix/PG suite pass. (3) FireDueSubscriptionWakes aborts the owner loop on first error (remainder retry next tick; durable, no loss) — acceptable, flagged for awareness. (4) PR #23 still open — author should close it on PR25 merge to complete the supersede. (5) KSE-0199/hub proposal (#274) must describe this final behavior before activation.
No merge, no deploy — review only, left to the authorized merger.
Senior security findings for exact head
70addeab(review 4803 APPROVAL context; no merge/deploy).Owner/HMAC/CEL boundary (intact, delta does not touch it): trust class is edge-derived only (signed.goalert via ingress HMAC, mail via sender allowlist; producer payload flags explicitly ignored); management transport HMAC, revision CAS, and atomic quota paths are unchanged from the preserved DevEx history. MatchSubscriptions still scopes to the envelope addressee and now also returns row-read errors instead of swallowing them.
No cross-identity subscription: fanout groups by normalized STORED OwnerIdentity; deliver re-resolves role from the owner slug (roleForIdentity normalizes internally) and hard-errors on steer addressee mismatch. All wake/timer SQL binds owner twice (wake row + steer identity). Single caller (notification ingress); matching runs on ingress only, never on add/resume.
Loop guards: relay guard (copy-marker payload or
sub|key prefix never re-fans) + self-authorship guard (actor slug vs owner) both precede matching.Consumed-primary safety (the root repair): lookup tries primary key first regardless of status, then the stable per-(owner,event) copy key; claims always attach to the surviving row; the payload attribution update is status-conditional (
WHERE status='pending') and a lost race returns with no wake and no replacement row. A consumed primary is never copied or re-executed. Standalone-copy insert uses one stable key per owner/event, never per subscription.Coalescing/timer: stage (pending_wakes + wake_state, both ON CONFLICT DO NOTHING) then fire grants at most one kick per 2-min owner cooldown, skips when any pending kick exists, advances next_wake_at_ns only on grant, and prunes stale wake rows while retaining pending + delivered-unfinished (crash-recovery) rows. FireDueSubscriptionWakes runs on every API host each schedule tick under the same per-owner lock (pg advisory-xact / SQLite BEGIN IMMEDIATE), so concurrent hosts and restarts cannot duplicate a grant; retired owners get pending wakes cleaned with original steers preserved; kill switch gates both paths.
Error/retry: fanout, commit, and match failures now propagate to ingress instead of
skipped++; safe because the primary insert is event_key-idempotent and delivery claims dedup replays. Delivered-primary and failure/retry paths have dedicated tests on both SQLite and PostgreSQL.Non-blocking notes carried in the APPROVAL body (signature badge at merge; Nix-suite reliance; timer loop abort-on-error; close PR23 on merge; KSE-0199/#274 must describe final behavior pre-activation).
placeholder
Senior findings for PR25 @
1eb1a253a2(pairs with APPROVED review 4809, same head; delta-only review on top of approval 4803 @70addea).Delta 70addea..1eb1a253 is exactly one commit ("docs: describe the repaired subscription wake contract"), touching only internal/agentdispatcher/subscriptions.go (+13/-15), all hunks comment-only. Verified programmatically: file content with //-comments/leading-whitespace/blanks stripped is byte-identical (sha256 0ea0c74a...) on both sides — zero executable change, so the canonical full suite from
70addearemains valid.Accuracy of the new comments against the approved implementation (all confirmed):
Non-blocking carryovers: SSH sig badge at merge (root verified tracked-agent fingerprints wDVd2B08VqF4... per founder steer; sandbox cannot verify SSH sigs); tests not executed here (no Go toolchain). No merge/deploy action.
Merge evidence: tracked agent SSH signature verified at1eb1a253, independent senior approval4809 on exact head plus full root-delta review4803. Canonical Nix/PG suite passed; final delta is comment-only and independently checked as executable-equivalent. Original signed DevEx history is retained. This is source merge only: paired hub/KSE199 PR283 and deployment/canary acceptance remain pending. Existing residents are still on dispatch4be3e57; no live peer-wake claim is made by this merge.