[v0.1/IPC Review] Resolve attach targets on the daemon instead of a roster snapshot #310
Labels
No labels
priority/P0
priority/P1
priority/P2
release/v0.1.0
status/blocked
status/planned
type/bug
type/design
type/test-gap
type/tracker
No milestone
No project
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
natsukium/felis#310
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Why
The design documentation says that session prefixes are resolved by the daemon, so a caller does not need to fetch a roster before operating on a session. The attach-scoped paths do not currently satisfy that contract.
The CLI and bridge perform:
Relevant paths include:
crates/felis-cli/src/cli_sessions.rs:96-107crates/felis-cli/src/cli_sessions.rs:1968-1976crates/felis-cli/src/cli_bridge.rs:1569-1575crates/felis-client-core/src/dial.rs:458-507SessionMsg::Attachaccepts au128full ID and documents that the ID came from anOps::Listedroster. This adds a round trip and makes prefix resolution and attach a non-atomic pair. A session can disappear between the list and attach, andinfocan report a stale roster row after the session has already changed or been destroyed.IDs are not reused, so this is primarily a consistency and latency problem rather than an accidental-attachment vulnerability. It nevertheless contradicts the documented IPC design and makes every non-Rust bridge consumer depend on the same client-side resolver.
Decision required before v0.1.0
Choose and freeze one of these designs:
SessionMsg::Attachto carry a validatedid_prefix, resolve it in the daemon at attach time, and return the full ID inSessionMsg::Attached.The first option is preferred while the wire is still pre-release. Internal reconnect paths may retain an exact-ID attach arm if they need to avoid a roster query.
Consider an atomic
Ops::Infoor equivalent query forsessions info, rather than derivinginfoentirely from a client-side roster snapshot.Acceptance criteria
felis.proto, conversion code, minor ledger, compatibility acknowledgment, schemas, and golden conversations are updated together.Related: #6, #52.
Direction agreed 2026-09-21 after three
soldesign-review rounds (final verdict PASS). Full plan and batch order: see the comment on #12.SessionMsg::Attachgains anid_prefixalternativeto the exact
id(reconnect and roster-driven switch keep exact ids viaLanding::AttachExact), resolved daemon-side with the existingresolve_session_prefix;Attached.info.idalready returns the full id.NoMatch/Ambiguousmap to newAttachFailurevariants (attachrefusals already close the connection through
SessionAttachFailed, whichis the right outcome for a prefix that names no single session). Add
Ops::Info { id_prefix }with a closed outcome union in theOpsSpawnedstyle:
found { SessionInfo session; string short_id }|no_match {}|ambiguous { uint32 matches }; only the successful arm carries sessiondata. The daemon computes
short_idwithshort_session_prefixagainstits pool at reply time. This is a deliberate narrowing of the
control-surfaces decision "no shortening against the daemon's whole
roster": that rejection was about the CLI owing a second round trip and
emitting an unchecked prefix; a prefix the daemon checked against the
authoritative pool in the same reply costs no round trip and is checked,
so
sessions infokeeps its documented always-presentshort_idwithoutan
Ops::List. The decision record is rewritten in place to say so.sessions infoand the bridgesessions.infouseOps::Info;capture,search,sendattach by prefix. The bridge comment that attach-scopedverbs cannot use daemon-side resolution is retired.