MalloryEstate Briefing
M·055Design agreed in conversation. Not yet built.
← All briefings

Reliability & Ops

Response SLA Connections

Dual-source ball-in-court: work Slack via the runtime's Claude integration, personal Slack via the edge poller — one engine, one surface.

Dated 2026-07-12Programme Reliability & Ops

Situation

Follow-on to the v1 Response SLAs spec (merged to main, not yet deployed). The operator's real setup splits Slack in two: work Slack stays on the runtime-side Claude integration ("as me", company-appropriate) which now also POSTs its set to the edge; personal Slack runs on the edge poller with a personal user token.

This spec introduces a first-class connection as a tagged source of ball-in-court items, so resolution, config, and surfacing are naturally scoped per-source and never cross-contaminate — and is deliberately shaped as the seed for the future connector admin console (Workstream D), flagged to that owner before it's built.

Key decisions

A connection is a first-class, tagged source

{id, label, method, transport: 'edge-poll'|'ingest', enabled, tokenSecret|producerCn, clock/slaMinutes/windows overrides} — everything keys off its id so scoping is automatic.

No schema change needed

channel_pending.channel (v1 migration 023) already holds an adapter id; it now simply stores the connection id (slack-personal / slack-work). Since v1 isn't deployed, the column is optionally renamed channel→connection pre-deploy with no live-data migration.

Reconciliation is per-connection

The poll cron resolves only its own connection's rows; ingest connections carry a mode ('full' vs 'delta') so a full re-emit safely resolves that connection's rows without touching another's.

Auth is per-connection

Edge-poll reads env[connection.tokenSecret] and skips cleanly if unset; ingest validates the JWT common_name against the connection's registered producerCn, rejecting unknown connections or CN mismatches with 403.

Minimal runtime delta, coordinated with the OpenRouter migration

The only mallory-runtime change is a new post_pending call (mirroring the existing post_nudge) in slack-email-monitor, POSTing the full current work-Slack set to /ingest/pending.

Architecture

resolveConnection merges connection-level and method-level defaults into the effective settings the evaluator already consumes; adapters and the evaluator are otherwise unchanged, just parameterised by the registry.

Connection registry (KV config:response-slas.connections)
Seeds one default connection (slack-personal, edge-poll); slack-work (ingest) is added when the operator enables it.
resolveConnection(cfg, connectionId)
Pure, unit-tested merge of connection + method defaults into the settings computeItem/resolveChannelSettings consume.
Poll cron (per edge-poll connection)
Iterates enabled edge-poll connections, dispatches to the method adapter, tags upserts with connection.id, reconciles only that connection's rows.
POST /ingest/pending ({connection, items, mode})
mode:'full' upserts and resolves missing rows within that connection (so replying in work Slack clears the work item); mode:'delta' upserts only.
mallory-runtime post_pending
New call in slack-email-monitor POSTing {connection:'slack-work', mode:'full', items} with CF-Access, mirroring post_nudge.
Settings → Response SLAs → Connections
Lists registered connections with label, transport badge, enable toggle, and per-connection clock/SLA defaults; full connection management deferred to the Workstream D console.
Waiting card/view source badge
Each item carries a small badge identifying its connection, so work vs personal is legible at a glance.

Risks & guardrails

The work/personal cancel-each-other bug

Explicitly the core correctness concern this spec fixes — without per-connection scoping, resolving one Slack's items could wrongly clear the other's. A dedicated dual-source regression test seeds both and asserts each is untouched by the other's poll/ingest.

Sequencing vs the v1 deploy

v1 is merged but not deployed (blocked on wrangler re-auth); folding connections in before first deploy is preferred (one deploy, no legacy channel='slack' data) but depends on the runtime post_pending + migration coordination happening promptly.

Convergence with the future connector console

This registry is deliberately a seed, not a parallel model — needs explicit hand-off to the Workstream D owner so the eventual admin console adopts it rather than reinventing it.

Delivery

Backend

Connection type + resolveConnection in src/lib/responseSla.ts; per-connection poll/reconcile in the poll cron; /ingest/pending gains {connection, mode} + per-connection CN validation; config GET/POST includes connections.

Runtime

post_pending added to the existing slack-email-monitor job — the only mallory-runtime file touched, coordinated in timing with the OpenRouter migration.

Web

Connections list + source badge across web/src/lib/api.ts, settings/+page.svelte, WaitingCard.svelte, WaitingView.svelte.

Testing

resolveConnection defaults/fallback; two edge-poll connections don't resolve each other's rows; full vs delta ingest behaviour; wrong producer CN → 403; the dual-source regression test.

Out of scope

The full OAuth/integration connector admin console (this seeds it, doesn't build it)New method adapters (WhatsApp/Discord/Gmail) beyond SlackPer-channel posture editor (carried over from v1)LLM triage call (carried over from v1)
spec · docs/superpowers/specs/2026-07-12-response-sla-connections-design.md
plan · docs/superpowers/plans/2026-07-12-response-sla-connections.md
Mallory · Estate briefing