Task
Nothing keeps a persisted profile body in step with its store's on-chain root. A root advances, no body is
persisted for the new root, and the DPB store silently becomes unservable — the publisher ends up
holding a body it would itself reject. Close that gap.
Measured on real hardware, 2026-08-21
Machine A (Windows, dig-app 12.34.0 on disk, dig-node 0.134.0), store 111eb8bc…:
- The DPB store holds one body, from Aug 16, 18 bytes, no image, at root
716513ed….
- The store's on-chain root has advanced to
371a39b0…, and no body was ever persisted for it.
- A's own node refuses its only body — "the chain is the authority" — and returns
body_b64: null
at the real root.
So there is nothing at the tip for any peer to announce or serve. A publisher that has moved its store
forward is, from the network's point of view, publishing nothing at all — and it gets no signal that this
has happened.
The guard is working correctly — that is what makes this the interesting failure
Machine B (different host, region, install, node version, provably cold — no profiles dir at all,
evidenced 01:21:12Z) was handed the same stale body and independently derived the identical tip root
371a39b0… and refused, storing nothing.
Two independent chain reads agreeing on the tip is corroboration rather than a self-consistent stub: the
AnchoredRoot guard is genuinely wired to a live chain read and fails closed. NC-9 is satisfied here.
B is peered with A and its journal shows profile-body sync (opcodes 223/224/225) up, so this is not
connectivity and not a missing opcode layer. The transport was never reached.
Why it blocks the round trip
This is the merged-but-never-composed class, found one layer earlier than expected — in publish, not
transport. put-body/get-body each anchor correctly in isolation; nothing owns the invariant between
them, which is that a store whose root advanced needs a body at the new root or it has silently
un-published itself.
Shape questions
- Who notices? A publisher whose root advanced has no error to see — the failure is the absence of a
later write. Detection has to be active, not a returned error.
- Whose job is the re-persist? Re-anchoring an existing body under a new root is not always right —
the root may have advanced because the content changed. Distinguish "same body, new root" from "root
moved on, body genuinely stale".
- What should
get-body say? Today it returns null, which is indistinguishable from "no such
profile". A publisher debugging this cannot tell an un-published store from an empty one.
- Is refusing correct at all here? Yes — do not weaken the guard to make this pass. The guard is the
only reason the two machines agreed. The fix belongs on the publish side.
Also worth a look while in here
There is no CLI surface to fetch a profile by DID — dig-node profile offers only
put-body/get-body, both keyed on <STORE_ID> <ROOT>. That leg of the round trip is untested rather
than failing, because there is no way to attempt it.
Parent
https://github.com/DIG-Network/dig_ecosystem/issues/3131 (which stays open), under
https://github.com/DIG-Network/dig_ecosystem/issues/3008.
Task
Nothing keeps a persisted profile body in step with its store's on-chain root. A root advances, no body is
persisted for the new root, and the DPB store silently becomes unservable — the publisher ends up
holding a body it would itself reject. Close that gap.
Measured on real hardware, 2026-08-21
Machine A (Windows, dig-app 12.34.0 on disk, dig-node 0.134.0), store
111eb8bc…:716513ed….371a39b0…, and no body was ever persisted for it.body_b64: nullat the real root.
So there is nothing at the tip for any peer to announce or serve. A publisher that has moved its store
forward is, from the network's point of view, publishing nothing at all — and it gets no signal that this
has happened.
The guard is working correctly — that is what makes this the interesting failure
Machine B (different host, region, install, node version, provably cold — no
profilesdir at all,evidenced 01:21:12Z) was handed the same stale body and independently derived the identical tip root
371a39b0…and refused, storing nothing.Two independent chain reads agreeing on the tip is corroboration rather than a self-consistent stub: the
AnchoredRootguard is genuinely wired to a live chain read and fails closed. NC-9 is satisfied here.B is peered with A and its journal shows
profile-body sync (opcodes 223/224/225) up, so this is notconnectivity and not a missing opcode layer. The transport was never reached.
Why it blocks the round trip
This is the merged-but-never-composed class, found one layer earlier than expected — in publish, not
transport.
put-body/get-bodyeach anchor correctly in isolation; nothing owns the invariant betweenthem, which is that a store whose root advanced needs a body at the new root or it has silently
un-published itself.
Shape questions
later write. Detection has to be active, not a returned error.
the root may have advanced because the content changed. Distinguish "same body, new root" from "root
moved on, body genuinely stale".
get-bodysay? Today it returnsnull, which is indistinguishable from "no suchprofile". A publisher debugging this cannot tell an un-published store from an empty one.
only reason the two machines agreed. The fix belongs on the publish side.
Also worth a look while in here
There is no CLI surface to fetch a profile by DID —
dig-node profileoffers onlyput-body/get-body, both keyed on<STORE_ID> <ROOT>. That leg of the round trip is untested ratherthan failing, because there is no way to attempt it.
Parent
https://github.com/DIG-Network/dig_ecosystem/issues/3131 (which stays open), under
https://github.com/DIG-Network/dig_ecosystem/issues/3008.