Review flagged two soft spots; this addresses them per the finding.
#1 (fixed) — `unreadable_by` compared grant ids by exact identity, so a reader
holding a BROADER grant that actually covers a source's read was still flagged
unreadable. Whether a reader may open a source is an authorization question, and
only the caller — who resolves a grant_id to its capability and knows the
reader's own held authority — can answer it correctly. Added
`unreadable_by_with(predicate)`: the general, correct form, where the caller
supplies the decision (a true capability-subset check backed by the runtime).
`unreadable_by` is retained as the conservative exact-grant shorthand,
reimplemented in terms of the predicate, and documented as pessimistic. The crate
stays a pure provenance record with no dependency on the decision engine. New
test proves a broader grant is authorized under the predicate where exact-match
rejects it.
#2 (won't fix, by design) — reusing `FrameKind::ToolCall` + `action: "retrieve"`
rather than adding `FrameKind::Retrieval` is correct, not a shortcut. FrameKind's
axis is message shape (tool|agent × request|reply); a retrieval request is a tool
request, and the sources it reads back are ToolResult/Data. Operation identity
belongs in the action field, which is where a consumer filters retrievals. A
dedicated kind would fold operation semantics into the request/reply axis — a
category error — so it is deliberately not added.
jcp-cite suites green, clippy clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>