Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
0ff7b86
feat(messaging): add `scion server attribution-report` command (G1)
Aug 30, 2026
12d7e22
fix(messaging): attribution-report G1-a/b/c amendments
Aug 30, 2026
17abd8e
G4: DEF-58 negative gate, DEF-79 path trace test, DEF-80 divergence c…
Aug 30, 2026
731839a
G4-d/e: document path trace coverage boundary, add sampling window ca…
Aug 30, 2026
2948be2
fix(messaging): remove read-switch fallback, return typed 409 error (G3)
Aug 30, 2026
295bdc6
fix(messaging): preserve channel constraint, add switch bypass counte…
Aug 30, 2026
a25157f
fix(messaging): prevent thread-on-projectless-agent → DM misroute (G3-f)
Aug 30, 2026
461a674
fix(messaging): correct G3-f comment — threadID!="" not threadID=""
Aug 30, 2026
7687880
fix(messaging): G2 — make write-path conversation resolution fatal
Aug 30, 2026
2717deb
fix(messaging): G2-f/g — add ConversationWriteDenySwitch + write-deni…
Aug 30, 2026
d98d58e
fix: align NotificationDispatcher struct fields for gofmt
Aug 30, 2026
981c12c
fix(messaging): G2 write-deny → typed 409 conversation_not_resolved
Aug 30, 2026
17376c0
fix: remove duplicate ErrCodeConversationNotResolved (already in G3 b…
Aug 30, 2026
fdef77b
fix(webchat): remove DDL-block index on conversation_id that breaks p…
Aug 31, 2026
36b5a7a
feat(messaging): admin API to read/set conversation migration switches
Aug 31, 2026
6f6228f
fix(hub): nil-pointer panic in broker inbound fail-open path + CI lin…
Aug 31, 2026
6ac1a50
fix(settings): remove postgres gate on OperationalSettings init, fail…
Aug 31, 2026
ecf9abc
fix(webchat): CreateTopic auto-generates conversation when table exis…
Aug 31, 2026
93916ca
fix(webchat): extend DEF-89 ConversationID generation to pgWebChatStore
Aug 31, 2026
85f25c1
fix(messaging): add topic-lookup intercept to read-path resolver (DEF…
Sep 1, 2026
40b6508
test(messages): add byte-identity guard for FormatForDelivery (AC-9-1)
Sep 2, 2026
683ba14
fix(settings): add Malformed flag to sectionState, log parse errors a…
Sep 2, 2026
9e67fbd
feat(messaging): consolidate two messaging switches into one default-…
Sep 2, 2026
41f84ec
fix(settings): detect type-mismatch at ingest, fix nil-ops GET diverg…
Sep 2, 2026
45c440b
test(messaging): add Phase 9a upgrade-cutover integration tests
Sep 2, 2026
ba15295
feat(messaging): add DeliveryText field and broker preference logic (…
Sep 2, 2026
2f8567f
feat(messaging): enrich ConversationResult and add shared rendering h…
Sep 2, 2026
643a38b
feat(hub): stamp DeliveryText at all five send paths behind envelope …
Sep 2, 2026
ebdc069
fix(messaging): use cfg.surface in topic-lookup branch, fix comment j…
Sep 2, 2026
426db07
fix(messaging): use real persisted identifiers, stop fabricating IDs …
Sep 2, 2026
6efbc45
refactor(messaging): extract validateStructural, eliminate duplication
Sep 2, 2026
36f48a5
fix(messaging): make Conversation optional, delete synthesizer (DEF-102)
Sep 2, 2026
969a4f3
feat(messaging): add Urgent field to Message and DeliveryEnvelope (OQ…
Sep 2, 2026
7f12309
fix(messaging): update render_delivery.go to use PersistedIdentity an…
Sep 2, 2026
b350730
fix(messaging): enrich caller-supplied ConversationResult with Kind, …
Sep 2, 2026
30019f1
fix(messaging): stamp DeliveryText in handleGroupMessage agent send path
Sep 2, 2026
15707e5
test(messaging): add Phase 9e tests for group DeliveryText and pre-re…
Sep 2, 2026
07bad45
fix(messaging): correct observer-copy comment to state actual disclosure
Sep 2, 2026
c98a2b5
fix(messaging): map Urgent and ConversationID in NewEnvelopeToLegacy,…
Sep 2, 2026
13a9ed7
fix(messaging): stamp DeliveryText in scheduler message delivery path
Sep 2, 2026
e61a399
fix(messaging): stamp DeliveryText in notification dispatch path
Sep 2, 2026
e132380
test(messaging): add Phase 9f tests for scheduler and notification De…
Sep 2, 2026
6a1837b
fix(messaging): propagate key-derivation failure reason out of backfi…
Sep 2, 2026
9ca8a30
test(messaging): pin exact attributed message IDs in mixed-derivation…
Sep 2, 2026
36b5eda
fix(messaging): add unclassified bucket and sum-checking invariant (D…
Sep 2, 2026
dcaf010
feat(store): add LockDataMigrations advisory lock key (M1)
Sep 2, 2026
3787c46
feat(cmd): add migration marker helpers for hub_settings (M2)
Sep 2, 2026
e29aace
feat(cmd): add scion server migrate-dm-keys CLI (M3)
Sep 2, 2026
23a2a11
fix: address review fixes F1-F4 for migration markers
Sep 2, 2026
567be89
fix(backfill): surface DeriveFailures, HazardAEmailCount, and write f…
Sep 2, 2026
2912048
fix(backfill): structural error classification — close the resolveGro…
Sep 2, 2026
8f3836a
feat(cmd): add boot-time DM key migration hook (M4)
Sep 2, 2026
e8e4cc3
fix(cmd): make AC-2b test non-tautological (M4 review fix)
Sep 2, 2026
4da916c
feat(cmd): add boot-time message backfill with per-project markers (M5)
Sep 2, 2026
f667e2e
fix(cmd): add panic containment to boot data migrations (M5 review fix)
Sep 2, 2026
1bbb0be
feat(cmd): split residual attribution report into reachable/unreachab…
Sep 2, 2026
d10ba2a
test(cmd): add steady-state reachable WARN gate (M6 review fix)
Sep 2, 2026
a666c74
refactor(messaging): rename stepMergeOrRekeyEmptyRef to stepSkipEmpty…
Sep 2, 2026
b0990a3
test(cmd): add DEF-112 consistency gate for reachable-count invariant…
Sep 2, 2026
f1ce7ee
test(store): add source-scan guard for ListProjects unconditional fil…
Sep 2, 2026
cbd4f8b
Merge commit 'f1ce7ee42846a8955d9f0c3abe8a075516f45fd5' into HEAD
Sep 2, 2026
edad66d
feat(cmd): add third residual bucket for permanently unattributable m…
Sep 2, 2026
c02ad42
fix(cmd): rework M9 residual report per orchestrator review (A-H)
Sep 2, 2026
5ca3e40
fix(cmd): discharge Gate C with real-log identity gate (item C rework)
Sep 2, 2026
bc30057
fix(cmd): reset total_residuals accumulator on fresh pass (M9a)
Sep 2, 2026
98543da
fix(cmd): promote pre-M9 mid-pass markers to fresh pass (M9a follow-up)
Sep 2, 2026
97c3462
test(messaging): add adversarial fixture-class tests F-1..F-9 for DM …
Sep 2, 2026
116db40
fix(messaging): DEF-126 cardinality guard and exact user resolution
Sep 2, 2026
f250ea2
fix(messaging): DEF-126 review fixes — ADDR_AMBIGUOUS, error classifi…
Sep 2, 2026
43be4ba
merge: DEF-126 exact user resolution (scion/ca-msg-fix1)
Sep 2, 2026
bda4cbf
fix(hub,messaging): DEF-127/127a/128a/128b read-path and fallback fixes
Sep 2, 2026
037268b
fix(hub): DEF-128b defects — fail-closed guard, authz denial log, unc…
Sep 2, 2026
c4f216d
test(hub): add mutation-catching tests for DEF-128b MUT-A and MUT-B
Sep 2, 2026
07d816d
refactor(hub): extract resolveSenderUserID and resolvePhase5Conversation
Sep 2, 2026
bb82204
fix(hub): hoist conversation resolution above delivery-envelope render
Sep 2, 2026
91c5d91
test(hub): DEF-135 acceptance tests for conversation envelope hoist
Sep 2, 2026
15498d7
docs: DEF-135 tranche-g note for envelope hoist drift
Sep 2, 2026
ea8040e
fix(hub): DEF-135 rework — F2 validate effectiveConv, F3 nil broadcasts
Sep 2, 2026
8ae02b5
test(hub): DEF-135 rework — extend AC-3, clean AC-5, cover F2/F3
Sep 2, 2026
f91ea41
docs: DEF-135 rework — add broadcast envelope drift and Phase 11 trip…
Sep 2, 2026
8f65e46
merge: ca-msg-fix2 — DEF-127/127a/128a/128b read-path and fallback fixes
Sep 2, 2026
0cff20a
merge: ca-msg-fix3 — DEF-135 conversation id in the delivery envelope
Sep 2, 2026
e497a30
fix(messaging): DEF-139 — expose tautological routing-key comparison …
Sep 3, 2026
222775e
test(hub): DEF-139 — structural guard against re-discarding CheckConv…
Sep 3, 2026
f7687e2
merge: ca-msg-d139 — DEF-139 divergence detector made capable of failing
Sep 3, 2026
ee75cc4
fix(hub,cmd): DEF-138 — explicit conversation routing on the outbound…
Sep 3, 2026
3edf96d
fix(hub): DEF-138 review — explicit-routing divergence outcome, remov…
Sep 3, 2026
a026a3b
fix(hub): DEF-138 — surface explicit_routes on admin divergence board
Sep 3, 2026
c316b08
merge: ca-msg-d138 — DEF-138 explicit conversation routing
Sep 3, 2026
6fc8204
fix(messaging): DEF-140 — thread conversations stamped with originati…
Sep 3, 2026
63d20e2
fix(messaging): DEF-140 — validate channel→surface at boundary, harde…
Sep 3, 2026
77cc53e
fix(messaging): DEF-140 — cross-check validSurfaces against ent enum,…
Sep 3, 2026
94fc5ee
fix(messaging): DEF-140 — replace hand-listed enum with source-scanni…
Sep 3, 2026
eb59ea9
merge: ca-msg-d140 — DEF-140 stamp conversation surface from originat…
Sep 3, 2026
cc5047f
fix(messaging): DEF-141 — distinguish caller assertion from hub deriv…
Sep 4, 2026
7672a12
fix(messaging): DEF-141 P6 — json:"-" tag prevents ConversationAssert…
Sep 4, 2026
d8d4dbc
fix(messaging): DEF-142 P1 — resolveThread fails closed on ambiguous …
Sep 4, 2026
b51f1b7
fix(messaging): DEF-142 P1 fix — deterministic IDs in cross-page ambi…
Sep 4, 2026
64938d7
feat(messaging): DEF-142 P2/P3 — add ConversationRef to send path, wi…
Sep 4, 2026
6977ced
fix(messaging): DEF-142 AC-3 + AC-6 — collapse disclosure errors, tes…
Sep 4, 2026
98eeb6b
fix(messaging): DEF-142 AC-3 — invert disclosure switch to allowlist
Sep 4, 2026
b4f7316
fix(messaging): DEF-142 P5 — delete ResolveConversation, CLI uses con…
Sep 4, 2026
a9bdd63
fix(messaging): DEF-142 AC-3 rework — extract disclosableResolutionRe…
Sep 4, 2026
270269c
test(hub): DEF-142 P6 AC-7 — real mux integration test for conversati…
Sep 4, 2026
8795a70
test(hub): DEF-142 G1 — strengthen provenance test with competing pro…
Sep 4, 2026
b4d78c0
merge: main (2ac554cb0) into tranche-g
Sep 5, 2026
42b4e6a
style: gofmt 14 files to restore `make fmt-check`
Sep 5, 2026
a29d75f
fix(hub): rename createProjectMembersGroupAndPolicy call sites after …
Sep 5, 2026
ffe96f0
fix(hub): allow conv:<uuid> and #thread refs without explicit recipie…
Sep 7, 2026
6e061e7
test(hub): add mutation-killing tests for DEF-152 addressee derivation
Sep 7, 2026
a18ca34
feat: remove --broadcast and --all flags from scion message
Sep 7, 2026
92799a9
fix: make broadcast/all refusal mode-aware for agent context
Sep 7, 2026
6f6dbe9
test: pin broadcast exclusion from agent-mode allowlist
Sep 7, 2026
ef12efe
Merge scion/ca-msg-bcast: remove --broadcast/--all from 'scion message'
Sep 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions changelog/2026-09-02-def135-envelope-hoist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# DEF-135 — Delivery envelope now carries conversation id on broker inbound

**Tranche:** G
**Branch:** `scion/ca-msg-fix3`
**Date:** 2026-09-02

## Summary

The delivery envelope rendered for broker-inbound messages (Discord, Telegram,
and any plugin that does not supply `surface` + `external_ref`) now carries the
resolved conversation id. Previously the conversation was resolved *after* the
envelope was rendered and dispatched, so the agent received an envelope with no
`conversation` key despite the message being persisted with a conversation_id.

The fix hoists sender resolution and Phase 5 conversation resolution above the
delivery-envelope render. A single `effectiveConv` value, computed once, is used
for both the envelope and the persisted `storeMsg.ConversationID`.

## Tracked Drift

### 1. Write-deny 409 now fires before dispatch (behaviour change)

Previously, a conversation-resolution failure under write-deny returned 409
*after* `dispatchWithBrokerRetry` had already delivered the message — the agent
had the message and the caller had a failure, making client retries unsafe
(double-delivery).

After the hoist, a 409 means nothing was delivered and a retry is safe. This is
fail-closed, consistent with the standing rule that messaging switches fall back
to refusal (*under-granting is recoverable, over-granting is not*).

**Impact:** Messages that today are delivered-then-409'd will instead be refused
outright. The direction is strictly safer.

### 2. Dispatch failure can leave a conversation row with no messages

Resolution writes a conversation row. Hoisting it above dispatch means a
conversation row may be created for a message that is subsequently never
delivered (dispatch timeout, 502, etc.) and never persisted.

This is accepted because DM and thread conversations are **resolved by
deterministic key** — the next message from the same user to the same agent
resolves the identical conversation and uses it. An empty conversation is inert
and self-healing, not an orphan requiring cleanup.

### 3. Broadcasts with surface + external_ref no longer carry a conversation in the envelope

Base rendered the Phase 11 conversation into the broadcast envelope while
persisting no conversation_id on the row — exactly the envelope/row disagreement
this defect exists to remove. The fix unifies on no-conversation-for-broadcasts,
matching the documented invariant at `handlers_agent_messaging.go:1898`
("broadcasts deliberately skip conversation resolution"). Phase 11 still creates
the conversation row; it is simply not stamped on the broadcast.

### 4. Tripwire: Phase 11 unification changes which conversation messages persist into

When both Phase 11 (explicit `surface` + `external_ref`) and Phase 5 (inferred
DM/thread) produce a result, the precedence rule selects Phase 11. Phase 11
produces a **group** conversation keyed on the external ref; Phase 5 produces a
**direct** conversation keyed on the sender/agent pair.

No live caller sets `surface` + `external_ref` on this endpoint today, so
nothing changes in practice. **The day anyone enables Phase 11 on a plugin that
also resolves DM conversations, Discord messages will move from DM conversations
into group conversations.** This is Alternative B from the design, which was
explicitly rejected because it splits every user's history at the deploy
boundary. It must not happen as a side effect of enabling Phase 11; it requires a
deliberate product decision and migration plan.
Loading
Loading