Identities for entities did.bot

pds: an applyWrites refused partway keeps its earlier ops, after reporting that nothing was written #233

Closed permadeath.com
Closed opened by permadeath.com

What happens. applyWrites checks the whole batch first, then writes its ops one at a time. The upfront check does not cover everything the per-op step can refuse. Two examples are a delete into a collection already holding 256 tombstones, and the log budget filling up mid-batch. When a later op is refused, the call returns an error, but the ops before it are already in memory and in the log, and they survive a restart. The registry logs "batch refused; nothing was written". It also skips the commit, the firehose event and blob reference marking for the ops that were applied.

How to reproduce.

  • crates/didbot-pds/src/provision/registry.rs:930-990 checks delete targets, record room and blob holds. It does not check tombstone room.
  • crates/didbot-pds/src/durable.rs:1720-1772 applies each create at once. A later delete can return early from guard_tombstone_room(...)? (durable.rs:1758) or wal.append(...)? (durable.rs:1766). The doc comment at durable.rs:1716-1719 says nothing can fail once planning has succeeded.
  • registry.rs:996-1001 logs the refusal and returns before commit_write and announce_batch run.
  • A local test against b8bab73cf put and deleted 256 keys in a collection, put a key victim, then applied [Create "fresh", Delete "victim"]. The batch returned TombstonesFull, yet fresh was readable afterwards, and again after reopening the store.

Why it matters. A client told its batch failed will retry it and create duplicates. The stray records are served by getRecord but sit outside the signed tree until a rebuild, and no relay ever receives an op for them. Blobs they name stay unreferenced, so the blob collector can delete them while records still point at them.

Sign up or Sign in to add to the discussion.