[v0.1/Proto Review] Freeze protobuf and IPC contracts (7 issues) #52
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
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
natsukium/felis#52
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?
Scope
This is a source-grounded pre-release review at snapshot
5077d74b. Public compatibility may still be broken, so the review focuses on contracts that become disproportionately expensive to repair after the first tag: the frozen preface semantics, protobuf shapes, correlation, connection state, minor evolution, and receiver admission.The existing release tracker #12 already chose the major architecture: keep the frozen preface bytes, protobuf framing, a separate row codec, typed correlation, effective-minor send authorization, and connection-local corruption handling. This review does not reopen those choices. It checks whether the implementation and schema actually satisfy them.
New findings
Header -> Chunk* -> Complete.Findings deliberately folded into existing issues
No duplicate issue was opened for work already isolated by the release review:
The API/UI/control-surface pass found no additional non-duplicate freeze blocker beyond those issues. In particular, unpublished Rust visibility is not treated as a public API per #12; CLI/config/bridge changes remain owned by #23, #27–#29, and the SSH review.
Cross-cutting review conclusions
Recommended dependency order
Closure criteria
felis.proto, protocol/domain types, reference/explanation twins, tests/golden conversations,CHANGELOG.md, andskills/feliswhere the public CLI/IPC surface changes.Sources reviewed
crates/felis-protocol/proto/felis.protocrates/felis-protocol/src/{preface,frame,codec,convert,messages}.rsand family modulescrates/felis-transport/src/{preface,framing,driver}.rscrates/felis-daemon/src/serve.rs,serve/session_task.rs,serve/streaming.rs,graphics.rscrates/felis-client-core/src/{connector,shadow,image_shadow}.rsdocs/reference/{spec,ipc,row-codec,cli,control-surfaces}.mddocs/explanation/{design,principles,non-goals,architecture/ipc}.mdTriage (2026-09-05): the 2026-09-05 proto review adds #139, #144, #146 as P1 children of this tracker (docs-freeze work, no wire change recommended); #147 is closed onto
f56f5529. Closure now waits on #50 plus those three.Closed (2026-09-07)
Every child of this tracker is closed and both prose closure criteria have evidence on
origin/main.Children
#45: closed by PR #56 (fix(protocol): reject preface acceptance for an unoffered major)
#46: closed by PR #84 (refactor: carry the connection's role in its phase)
#47: closed by PR #72 (refactor(protocol): make the oneof arm the routing unit)
#48: closed by PR #74 (feat(protocol): make correlation an exclusive identity), with PR #77 and PR #79 finishing the repack and the atomic create/attach
#49: closed by PR #70 (feat(protocol): admit wire claims that order a receiver's allocation)
#50: closed by PR #177 (transport: gate every send on the connection's effective minor)
#51: closed by PR #81 (feat(protocol): make image transfers canonical and stateful)
#139: closed by PR #154 (docs: state why the FRLY carrier caps are 4096 / 1 MiB)
#144: closed by PR #165 (protocol: say "no value" by absence in the session roster)
#146: closed by PR #167 (protocol: ask for a create's default grid by absence), on top of PR #165
#147: closed by decision, not by a PR —
f56f5529already implements option A (major stays 1, minor 9, ledger frozen at 0..9), so the 2.0 reset (#30) was dropped rather than landedProse criteria
#45and#49under "P0 — release blockers" and#46,#47,#48,#50,#51,#52under "P1 — freeze before the first public contract"; its recommended order reads "11. #30 after every other wire edit." followed by "12. Close #52, then run #31 after all P0/P1 work is closed." The ordering held: #30 was reached last and then closed as dropped, per the #147 triage recorded above.felis.proto, protocol/domain types, reference/explanation twins, tests/golden conversations,CHANGELOG.md, andskills/feliswhere the public CLI/IPC surface changes."felis.protoand the domain types: every oneof field carries its// arm:declaration (crates/felis-protocol/proto/felis.proto, mirrored intocrates/felis-protocol/src/generated/felis/v1/felis.v1.rs:403-412), andcrates/felis-protocol/src/messages/arm.rsholds theArmMetatable it restates. The proto comment on the image family states the state machine directly: "is Header -> Chunk* -> Complete, and no other transfer may open" (felis.proto:1117).crates/felis-protocol/src/messages.rs:886-889asserts the two against each other — "felis.proto's {kind}Msg arm declarations disagree with the ArmMeta table" — andthe_schema_spells_no_arm_into_the_prefacepins the preface half.docs/reference/spec.mdREQ-104 ("the connection then speaks the effective minor,min(client, daemon). The effective minor is a send-side contract") and REQ-113a ("The routing unit is the oneof arm, not the frame kind"), sourced toreference/ipc.md"The arm table" andexplanation/architecture/ipc.md"Kind or arm?";docs/reference/row-codec.md:178carries the same send-side rule for codec versions.CHANGELOG.md: "the correlation envelope is now an exclusive identity: aoneofnaming either arequest_idor a" (:495), "the routing unit is the oneof arm, not the frame kind" (:500), "an image transfer is canonical and stateful" (:443), and "a client closes on a preface accept that names a major it did not offer, before any frame is written" (:345).skills/felis: conditional, and none of these seven changed the public CLI or bridge surface — the CLI-side cascade belongs to #23/#29 and to the CLI review tracker.Follow-ups moved to the post-v0.1 backlog
None. No open issue is split from any child of this tracker.
All seven closure children (#45–#51) are closed and #12 lists them as P0/P1 blockers with #30 ordered after them, which satisfies the last closure criterion. Deferred residue from #50 lives on as P2 follow-ups (#164, #175, #176) and is not a freeze dependency. Per #12's dependency order, #31 runs next.