Skip to content

engine: tighten three residual verdicts on the accept and rotation paths #1359

Description

@FSM1

What

Three smaller findings from #1346's security and crypto-privacy passes, each deliberately left out of that diff because the fix lands outside the arms it wired.

1. The idempotent-ack short-circuit does not cross-check the bookmark's sharer

crates/engine/src/grants/accept.rs, the SequenceNotNewer branch: the stored bookmark is found by scope_root_name alone and its permission returned, without asserting stored.sharer_identity_pk == contact.identity_pk().to_sec1().

Not exploitable today — the path is reached only after the blinded-tag self-location and the owner-committed-tag check have both passed under this contact's ECDH — but the equality is cheap defense in depth on a path that acks and returns.

2. EngineError::TrustViolation and Seam are carrying verdicts their docs do not describe

EngineError::TrustViolation documents "a fail-closed trust violation on the read path", and Seam documents "a host seam failed (durable op-queue I/O)". The rotation classifier added in #1346 now routes through them:

  • WriteRotateError::{ResumedSeedNotAtItsRoot, ResumedWaveAtAnotherEpoch, WriteEpochNotAdvancing, IdentityRepoint} and RotationPublishError::RejectedTrustViolation. These are local encoder/resume verdicts on the owner's own material, not verdicts about a peer.
  • ResolveFailure::ConflictingChildLabelSeam, which is a cross-parent index disagreement, not host I/O.

Both are on the correct retryable-vs-trust axis and fail closed, so this is a labelling problem, not a safety one — but a host cannot distinguish "your own vault is mid-rotation" from "someone forged a record". Wants either a distinct variant or widened variant docs.

3. An over-cap head block on the accept path reads as retryable availability

Engine::accept_share maps a None from fanout_get_verify to ContentUnavailable, and map_read_error (crates/engine/src/net/adopter.rs) maps an over-cap head block to GateError::SeamContentUnavailable. A hostile contact naming a scope root that serves an oversize head therefore looks permanently retryable. Pre-existing convention rather than new behaviour; the item stays un-acked either way.

Acceptance

  • The ack short-circuit asserts the stored bookmark's sharer, with a test that a bookmark under a different sharer is not silently re-acked.
  • The rotation verdicts a host acts on are distinguishable from a peer trust verdict — by variant or by documented widening, with the classifier's tests pinned to whichever is chosen.
  • A size refusal on a gated read is its own verdict rather than availability.

Part of #635

Metadata

Metadata

Assignees

No one assigned

    Labels

    comp:enginecrates/engine — the stateful client brainv2-buildv2 rewrite build slice

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions