library: the envelope — one packet shape for every protocol

A protocol is now defined through envelope.Define rather than beside it.
Every packet begins with the same 16-byte prefix: a Header of {operation,
target} for a request or event, a Status for a reply. The header is folded
into each protocol's own layout, never stacked on top of it — Define walks
a spec's types and refuses one that carries a Header or Status field, so
the rule cannot be missed by reading. Operations number from 16, leaving
describe, enumerate, subscribe and unsubscribe reserved and answerable the
same way everywhere; describe the envelope answers itself, and an unknown
verb is -ENOSYS without a provider writing a line.

The size floor becomes something protocols can compile against: 256 bytes
for a call, 64 for a push, matching the kernel's own limits, checked at the
Define call with the prefix counted in. A protocol that outgrows either
fails the build with the reason and the remedy — shrink, or move the bulk
to shared memory, because packets never fragment. Events carry the header
too and number in their own space, so appending an operation can never
renumber a shipped event.

Beside it, the client half of the model: a Channel is what opening a
/protocol name yields, wrapping the endpoint capability so a program holds
a conversation rather than a handle. Nothing speaks through either yet —
the vfs protocol gains NodeKind.protocol and the convention that an open
reply may carry a capability, and that is the whole runtime change.

Suite 107/107, unchanged: P1 converts nothing.
This commit is contained in:
Daniel Samson
2026-07-31 21:48:03 +01:00
parent ac01f627d1
commit 1ff0991452
8 changed files with 1209 additions and 6 deletions
+1
View File
@@ -39,6 +39,7 @@ fn kindFromWire(value: u32) Kind {
@intFromEnum(Kind.symbolic_link) => .symbolic_link,
@intFromEnum(Kind.fifo) => .fifo,
@intFromEnum(Kind.socket) => .socket,
@intFromEnum(Kind.protocol) => .protocol,
else => .regular,
};
}