refactor(protocol): make the oneof arm the routing unit #72
No reviewers
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!72
Loading…
Reference in a new issue
No description provided.
Delete branch "refactor/arm-meta-routing-47"
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?
Fixes #47.
The documented growth rule — a new one-shot or push rides a new frame
kind, and a mode admits or refuses a whole kind — had already come apart
from the schema (
OpsgrewTagandStatusas arms,Pushgroupsarms whose recipients differ by mode,
Regioncarries both a point replyand a row stream). Rather than split a family per verb, the routing unit
becomes the oneof arm before the protocol freezes its numbering.
ArmMetatable holds each arm's direction,correlation class, mode set, phase set, and introducing minor.
Kind-level admission survives only as the fold of that table
(
MessageKind::modes/::phases/::sole_direction/::admissible) — a pre-decode filter on the header word — and a testasserts the fold against the arms so the two cannot drift.
felis.protorestates every arm's row in an// arm:comment so anon-Rust peer can implement the same matrix; a test compares the two,
since
buf lintdoes not read comments.Phasemoves here fromfelis-transport (re-exported there) so the table and its enforcement
cannot drift apart.
admit_armis the single authority — it appliesthe decoded arm's direction, phase and mode columns, replacing the
daemon's separate
ops_deniedpolicy.account_fornow enforces thecorrelation column instead of reading it as a label, so a reply with no
request_id, a request carrying a stream id, or an uncorrelated armcarrying either ends the connection (REQ-114); previously any frame
without a
stream_idwas delivered unchecked. A mode denial surfaces asDriverError::ArmDeniedso the caller picks the wire shape the phaserequires (pre-attach: typed
Conn::Refusedand close; attached: refusethrough the request envelope and keep streaming). A refused stream
opener advances
next_streamwithout taking a slot, so neither endmisnumbers nor leaks.
and the
sessionsdrain loop skipped frames outside its family, so themode column never ran where pushes actually arrive.
admit_discardedputs the arm's row in front of the drop, envelope shape included.
Opsconnection refuses aPush::Reattachinstead ofacting on a window-management push, and the connector reads its session
round trip through the driver rather than decoding the body itself.
The wire format is unchanged and a well-behaved daemon sends nothing new;
what changes is that a misroute is reported under the
protocolerrorkind instead of passing unnoticed.
Doc cascade:
docs/reference/ipc.mdgains the normative arm table andstates that the kind gate is its fold, and its modes table splits into
admission (the arms'
modescolumn) versus the daemon's output shaping,so a peer implementing routing from the schema does not read a refusal
into a message the daemon merely never composes;
docs/explanation/architecture/ipc.mdcarries the kind-versus-armcriterion, the worked examples, and the rejected alternative (splitting
families until whole-kind admission is literally true); REQ-114 in
docs/reference/spec.mdnames the mode column alongside phase, directionand correlation;
docs/reference/glossary.md,docs/reference/testing.md, anddocs/explanation/architecture/control-surfaces.mdfollow.CHANGELOG.mdrecords the user-visible half.
Verified: just check green (fmt, clippy, nextest, deny); reviewed by
plan/correctness/docs lenses and pi sol
ead7faad1e18d2fcae36