Summary
General awareness-to-user outbound communication channel (email + webhook in Phase 1). Item 4 in the revised pre-beta sequence (per pre-beta-plan-synthesis-2026-04-17).
In-chat Ask only works when a human is in a session. Many events don't have an attached chat — scheduled fires, edge processes, async webhooks, cross-user directives, security events. Outbound delivery is needed for those cases, plus for security notifications from the prompt-injection scanner (e.g., zero-width stripping events must surface at warning severity, never silently).
Phase 1 message types
- Consent requests — with callback URLs, response options
- Security notifications — informational or warning-level, no response needed
Phase 2+: briefing push summaries, intention-fire notifications without consent, shared-entry notifications, weekly digests.
Underlying plumbing (HMAC, signed URLs, retries, idempotency, debug mode) applies uniformly across message types.
Severity levels
- info — happened, you should know eventually. Batched. Canvas default. Email opt-in.
- warning — happened, might matter. Fires immediately. Routes to primary channel.
- alert — something is wrong. Fires immediately. Routes to primary channel (with escalation in later phases).
Severity assignments
- Zero-width character stripping → warning (any stripping means the payload arrived with adversarial shape; the rest deserves scrutiny)
- Any defensive transformation applied to user content → warning minimum
- Directive
scan_status → flagged → warning
- Directive
scan_status → cleaned → warning (inherits from stripping)
- Gate blocks on Never policies → info
- Token auth failure, single → info
- Token auth failure, repeated within window → warning (may escalate to alert)
- Kill switch triggered → alert
- Repeated warnings from same source within short window → escalate to alert
Silent Defense Principle (explicit)
Defensive actions on user content must be visible and auditable, never silent. Any defensive action means the entry is less trusted than a clean arrival. Stripping is not a full fix — it addresses the specific known-bad pattern but leaves the rest of the payload under elevated suspicion.
This principle drives:
Content arrives with hidden characters for a reason: source compromise, third-party pipeline shipping adversarial formatting, copy-paste from a compromised source, or legitimate-but-unexpected formatting. All four deserve user attention. Even the benign case reveals something about the data pipeline the user didn't know.
Consent request message type
Structured object: request_id, summary, blast_radius, reversibility, provenance, urgency, expiration, variable-length response_options (each with label, callback_url, semantic_type). Callback URLs are signed, single-use, time-limited.
Summary field must come from server-generated structured metadata, not directly from the requesting agent or compromised source (applies to both message types).
Security notification message type
Simpler than consent. No callback URLs, no response options:
message_id (stable, for dedup)
message_type: "security_notification"
severity (info | warning | alert)
summary (plain-language, short)
detail (optional context)
source (who/what caused the event)
count (for batched info-level events)
first_occurred_at, last_occurred_at
canvas_link (back to Canvas for full context)
created_at
First concrete use case: zero-width character stripping, at warning level.
Batching rules
- info — batched per source, configurable window (default 5–10 min). One delivery per batch summarizing all events.
- warning and above — no batching. Fire immediately.
- Escalation — repeated warnings from one source within short window → alert. Phase 1 default: "3 warnings within 5 minutes from a single source becomes alert."
- Rate limit — per-user hourly cap on total notification volume, regardless of severity. Hard cap prevents compromised source flooding. Limit should be generous so legitimate high-activity doesn't suppress warnings.
Routing defaults
- Consent requests → primary channel (webhook or email, whichever configured)
- Security notifications info → Canvas only; user can opt in to email
- Security notifications warning → primary channel + Canvas
- Security notifications alert → primary channel + Canvas; user can opt in to secondary channels
- Canvas always receives all messages regardless of other routing. Canvas is the source of truth; outbound channels are layers on top.
Delivery channel staircase
- Phase 1 — Email (SMTP) + Webhook as peers
- Post-beta — Web push
- Post-beta (paid) — SMS
- Far future — native apps
Webhook payload schema
Defined as a system-owned schema entry (reuses v0.18.0 schema infrastructure). Canonical schema; users build receivers to match. Receivers must handle at least message_type: consent_request and message_type: security_notification for Phase 1.
Conservative content defaults, user-configurable to more detail. Default payload is metadata only (summary, severity, source, counts, timestamps, canvas_link). No raw entry content. Users opt in to richer payloads if the receiver is trusted.
Authentication
- Outbound (awareness → receiver) — HMAC signature over payload, pre-shared secret
- Inbound (callback → awareness) — signed URLs (single-use, time-limited) for consent; optional authenticated callback for high-consequence (tier-differentiated)
- Rate limits — outbound (don't spam broken receivers), inbound (flood protection)
Delivery semantics
- Retry — 3 retries with exponential backoff, then hard-fail. Configurable.
- Fallback chain — user-configurable ("try webhook, fall back to email after 2 min, hard-fail after 10 min")
- Idempotency —
request_id or message_id enables receiver-side dedup
- Ordering — no guarantee
Debug mode
Dry-run toggle (inert callbacks, test-flagged notifications), canonical test payloads, delivery logs, signature verification tool, replay tool.
Canvas integration
Canvas always shows:
- Pending-consents view
- Security notifications log (filterable by severity, source, time)
- Delivery log (what sent to which channel, response codes)
Phase 1 scope (pre-beta minimum viable)
Deferred
- Web push, SMS, native apps
- Multi-approver consent
- User-batched consent
- Authenticated-callback tier for high-consequence
- Per-source fallback rules
- Additional message types (intention fires, briefing push, digests)
- Revocation-after-approval
Sequencing
Depends on:
Can ship without:
- Sharing
- Full event-driven intentions
- Channels beyond email and webhook
References
Summary
General awareness-to-user outbound communication channel (email + webhook in Phase 1). Item 4 in the revised pre-beta sequence (per
pre-beta-plan-synthesis-2026-04-17).In-chat Ask only works when a human is in a session. Many events don't have an attached chat — scheduled fires, edge processes, async webhooks, cross-user directives, security events. Outbound delivery is needed for those cases, plus for security notifications from the prompt-injection scanner (e.g., zero-width stripping events must surface at warning severity, never silently).
Phase 1 message types
Phase 2+: briefing push summaries, intention-fire notifications without consent, shared-entry notifications, weekly digests.
Underlying plumbing (HMAC, signed URLs, retries, idempotency, debug mode) applies uniformly across message types.
Severity levels
Severity assignments
scan_status → flagged→ warningscan_status → cleaned→ warning (inherits from stripping)Silent Defense Principle (explicit)
Defensive actions on user content must be visible and auditable, never silent. Any defensive action means the entry is less trusted than a clean arrival. Stripping is not a full fix — it addresses the specific known-bad pattern but leaves the rest of the payload under elevated suspicion.
This principle drives:
scan_statusbecomescleaned(new state, notclean)cleaneddifferently fromclean(see feat(security): prompt-injection Phase 1 — directive entry type, scan_status, execute-mode retrieval #306 for the directive execution rules)Content arrives with hidden characters for a reason: source compromise, third-party pipeline shipping adversarial formatting, copy-paste from a compromised source, or legitimate-but-unexpected formatting. All four deserve user attention. Even the benign case reveals something about the data pipeline the user didn't know.
Consent request message type
Structured object:
request_id,summary,blast_radius,reversibility,provenance,urgency,expiration, variable-lengthresponse_options(each withlabel,callback_url,semantic_type). Callback URLs are signed, single-use, time-limited.Summary field must come from server-generated structured metadata, not directly from the requesting agent or compromised source (applies to both message types).
Security notification message type
Simpler than consent. No callback URLs, no response options:
message_id(stable, for dedup)message_type: "security_notification"severity(info | warning | alert)summary(plain-language, short)detail(optional context)source(who/what caused the event)count(for batched info-level events)first_occurred_at,last_occurred_atcanvas_link(back to Canvas for full context)created_atFirst concrete use case: zero-width character stripping, at warning level.
Batching rules
Routing defaults
Delivery channel staircase
Webhook payload schema
Defined as a system-owned schema entry (reuses v0.18.0 schema infrastructure). Canonical schema; users build receivers to match. Receivers must handle at least
message_type: consent_requestandmessage_type: security_notificationfor Phase 1.Conservative content defaults, user-configurable to more detail. Default payload is metadata only (summary, severity, source, counts, timestamps, canvas_link). No raw entry content. Users opt in to richer payloads if the receiver is trusted.
Authentication
Delivery semantics
request_idormessage_idenables receiver-side dedupDebug mode
Dry-run toggle (inert callbacks, test-flagged notifications), canonical test payloads, delivery logs, signature verification tool, replay tool.
Canvas integration
Canvas always shows:
Phase 1 scope (pre-beta minimum viable)
_systemschema entry)Deferred
Sequencing
Depends on:
scan_statustransitions are a primary notification producerCan ship without:
References
out-of-band-consent-channel-2026-04(revised 2× on 2026-04-17)