FEP-8b32: Object Integrity Proofs

Thanks for bringing Fedify into this discussion. I took a closer look at how nested proofs interact with Fedify’s current implementation.

Fedify’s automatic inbox path currently verifies only the top-level activity proof. A nested proof remains part of the outer proof’s JCS input, but it is not independently verified against the nested object’s owner or portable id. This also means that Hollo not having encountered a problem is not evidence that nested verification already works. The nested proof was simply not being verified independently.

On the signing side, Fedify already follows the inner-first, outer-second construction: createProof() removes only the proof on the object currently being secured. If a signed Note is embedded in a Create and the Create is then signed, the outer proof covers the complete signed Note, including its proof. This is the same construction that the Data Integrity editors accepted in w3c/vc-di-eddsa#81, so I think it is the best interpretation for Fedify to follow.

For JSON-LD-aware processing, my current proposal is to require every nested secured object to carry an explicit, complete @context. Fedify could then walk the original JSON document and verify nested proofs from the deepest object outward, before any JSON-LD expansion or compaction. Each verification would remove only the proof belonging to the current object, preserving descendant proofs in the outer proof’s input.

I don’t think Fedify should recursively strip every descendant proof unless FEP-8b32 or VCDI adopts that rule. Keeping the inner proof in the outer proof’s input binds the outer activity to the exact signed assertion it embeds. Replacing the inner proof would invalidate the outer proof, but that seems appropriate for an immutable activity.

I opened fedify-dev/fedify#938 to track the implementation and the open interoperability questions. Since compound-document scoping is still being discussed in w3c/vc-data-integrity#350, we would document this behavior as an interoperability profile and revisit it if the upstream specification settles on a different rule.

I’d be interested in your thoughts, especially on requiring each nested secured object to carry its own complete @context.