Cross-backend parity suite for possession-gated cell ref admission — a
non-admin cell_create / cell_update / cell_clone may introduce a fact
ref only to a fact its acting actor holds (a fact_holder row, recorded on
every put that names the actor), else 403 with reason
cell_ref_not_held. Twins the Rust fuz_cell_actions cell_authz cases of
the same names, over real HTTP:
- create admits a new ref only for a holder — a stored fact the caller
never put and a hash nothing is stored under are refused with one
identical answer (status + error body — no existence oracle), as is a
system-put fact; the uploader's public cell serves the bytes to anyone; a
second actor putting identical bytes becomes a holder;
- update keeps existing refs — an editor keeps refs another writer
introduced, and adding an unheld one (or dropping a ref and adding it
back) is refused;
- clone carries source refs per row — a shallow and a deep clone carry
each row's source refs without holding them; a patch adding an unheld
ref, or carrying a child's ref onto the root, is refused;
- a global admin is not gated;
- a revoked grantee can't re-reference — a reader who saw a hash through
a granted cell can't name it in a cell of its own, before or after the
revoke (a known hash is not a read capability);
- extraction parity — a ref is a whole string value exactly matching
blake3: + 64 lowercase hex: a hash in prose or markup, blake3:zz, an
uppercase digest, and an object key are not refs on either spine; - admission answers after the masks — an update of a hidden cell, a
create under a hidden parent, and a clone of a hidden source answer
404
whatever their data names.
Facts are put through _testing_put_fact, with holder naming the actor a
real upload would record. Gated on capabilities.fact_serving (the
seeder + the serve routes), and the cases driving a grant, item, or clone
verb on capabilities.cell_relations as well; runs under every
cross_backend_* project.