feat(protocol): admit wire claims that order a receiver's allocation #70
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!70
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/receiver-admission-49-v2"
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 #49.
A scalar that tells a receiver how much memory to reserve was not bounded
by anything on the wire: a twenty-byte
GridMsg::Sizeannouncing65535 × 65535, or an
ImageMsg::Headerclaimingu64::MAXdecoded bytes,is a legal small frame that orders an allocation nothing on the wire pays
for. The frame-body cap bounds a length, never a claim.
This branch admits those claims where they are decoded, before anything
downstream allocates against them:
felis-protocolgainsMAX_IMAGE_BYTES(64 MiB),MAX_SESSION_IMAGE_BYTES(256 MiB) and
MAX_IMAGE_FRAMES(4096), and admits announced geometry andimage headers in the
TryFrom<v1::*>conversion; an image geometry ispriced without overflowing it, and a wire limit is reported in the unit it
counts.
felis-client-core's image mirror refuses a claim before it allocates,bills a frame claim for the slots it fills, and grows the shadow only to a
geometry a peer may announce.
felis-gridcaps one image at 4096 animation frames and prices areplacement before the old image is dropped.
felis-daemonannounces the image store's own evictions, and trims anoversize
RegionMsg::Replyto the youngest bytes a reader can resume atrather than handing the writer a body it must refuse — a whole-scrollback
pipe is an in-spec request, so refusing the write would cost the subscriber
its connection.
SpawnArgs.env_baseis left to REQ-912a's spawn refusal instead of adecode-side check, which cost the whole connection for one over-cap
environment snapshot.
felis-cli's bridge refuses an over-limitsessions.sendbefore itresolves a session, and its line accounting saturates rather than wrapping.
Verification beyond the unit boundaries:
felis-client-core'stests/hostile_claims.rsdecodes hand-encoded protobuf frames under 64 bytescarrying maximal scalars under a
dhatglobal allocator and asserts the run'speak heap stays under 1 MiB — an allocation proportional to a claim is what no
Resultinspection can catch.Doc cascade:
docs/reference/ipc.md(the "Semantic limits" table gains aCheckedcolumn and the claim rows, plus the sender-only region row),docs/reference/spec.md(REQ-105 / REQ-105a),docs/reference/testing.md(a "Receiver-side claims" layer),
docs/reference/protocols/kitty-graphics.md,docs/explanation/architecture/ipc.md("A claim is not a length"),docs/explanation/security-model.md("Client-side admission"),docs/explanation/protocols/kitty-graphics.md, andCHANGELOG.md.Rebased onto
mainafter #16 merged; the parent's patches were dropped andthree commits superseded by #16's own review (the paste-disposition and
search-refusal refactors, and the pre-dial
plantest) were skipped. Thisbranch replaces #67, which went unmergeable when #68 landed a conflicting
edit to
docs/explanation/security-model.md; the two entries now sit sideby side.
It also carries one unrelated CI fix, without which no PR can go green:
.forgejo/actions/cargo-envparksCARGO_TARGET_DIRoutside the workspace,but the bench orchestrator still read the literal
target/criterion, so theregression gate failed every run with "nothing to check".
Verified: just check green (fmt, clippy, nextest — 3110 passed, deny),
pi review not run this session (the branch's own review ran before the rebase).