refactor(desktop): one canonical write shape for connection_id row stamping

Reconcile #94901's API-layer row stamping with #94656's durable-owner
persistence: extract lib/session-owner-stamp.ts as THE canonical
stamp-untagged-rows write path (never clobbers an explicit owner,
never stamps `local`) and re-express api/sessions'
stampActiveConnectionOwner through it. #94656's writers (optimistic
row from the captured owner route, mergeSessionPage carry, cache
patch) are exact-owner writers and stay as-is; the helper's contract
documents why it must not overwrite them.

Credit: row-stamping concept from PR #94901 (joe-rodgers) and
PR #95007 (weismanfamily); persistence shape from PR #94656
(Zeus-Deus).

Co-authored-by: joe-rodgers <25499388+joe-rodgers@users.noreply.github.com>
This commit is contained in:
Teknium
2026-08-26 01:47:33 -07:00
parent fb393ee08b
commit 2947272233
2 changed files with 32 additions and 8 deletions
+4 -8
View File
@@ -1,4 +1,5 @@
import { isMissingRestEndpoint } from '@/lib/gateway-rpc'
import { stampRowsWithOwningConnection } from '@/lib/session-owner-stamp'
import { recordTranscriptTail } from '@/store/transcript-tail'
import type {
PaginatedSessions,
@@ -37,16 +38,11 @@ function sessionScopeQuery(scope?: ProfileScope): string {
* correctly know nothing about this Desktop-local registry id. Preserve an
* explicit owner from a multi-source response; otherwise stamp the active
* non-local source so a later resume cannot fall back to a same-named local
* profile.
* profile. Delegates to the canonical row-stamp helper so this stays the ONE
* write shape for connection_id on backend-returned rows.
*/
function stampActiveConnectionOwner(sessions: SessionInfo[]): SessionInfo[] {
const connectionId = getApiRequestConnection()?.trim()
if (!connectionId || connectionId === 'local') {
return sessions
}
return sessions.map(session => (session.connection_id ? session : { ...session, connection_id: connectionId }))
return stampRowsWithOwningConnection(sessions, getApiRequestConnection())
}
/**
@@ -0,0 +1,28 @@
import type { SessionInfo } from '@/types/hermes'
/**
* THE canonical write path for tagging backend-returned session rows with the
* registry connection that owns them (the read counterpart is
* `sessionOwnerRouteFromRow` in store/session-request-router).
*
* Every other `connection_id` writer works from an EXACT captured owner route
* (the optimistic row in upsertOptimisticSession, the cache patch in
* use-session-actions/utils, the mergeSessionPage carry) — those are
* authoritative and this helper must never clobber them, so a row that
* already names an owner is returned untouched. Only untagged rows served by
* an active NON-local source get stamped: the gateway's HTTP APIs correctly
* know nothing about Desktop-local registry ids, and an untagged remote row
* would let a later resume fall back to a same-named local profile
* ("session not found" on turn two). `local` is never stamped — a bare local
* row already routes correctly and a `local` tag would only pin it against
* the fail-closed owner resolution for no benefit.
*/
export function stampRowsWithOwningConnection(sessions: SessionInfo[], connectionId: null | string | undefined): SessionInfo[] {
const owner = String(connectionId ?? '').trim()
if (!owner || owner === 'local') {
return sessions
}
return sessions.map(session => (session.connection_id?.trim() ? session : { ...session, connection_id: owner }))
}