feat(relationships): default to a pairwise R-DID, and say what the choice costs - #254
Merged
Conversation
…oice costs The persona DID is a published, resolvable `did:webvh` that often carries a verified agent name. Reusing it across contacts makes correlation a lookup rather than an inference — two counterparties compare a string and resolve it to a named identity. Yet pairwise was opt-in, on a decision whose consequences were invisible at the moment it was made: the request form defaulted to `No`, and in the inbox the convenient unshifted `a` was the linkable accept while the private one hid behind Shift+A. Flip both. A new request mints an R-DID unless the operator turns it off, and `a` now accepts pairwise. `A` stays wired to the pairwise accept too, so anyone with the old muscle memory keeps getting the private outcome they always got; the persona-DID accept moves to `p`, where it names itself. Neither surface makes the choice silently. The request form's toggle reads "Contact you as: Pairwise R-DID / Your persona DID" and spells out the consequence of whichever is selected; the inbox detail states both outcomes above the footer. The docs gain a comparison table, and lose the `--generate-did` invocation for a CLI subcommand that has not existed since the v0.2.0 TUI rewrite. Also guards the property the default depends on: an established relationship must never revert to the persona DID. That holds today and nothing tested it — `established_pairwise_relationship_never_pings_from_the_persona_did` pins the message `from`, the recipient and the listener to the relationship record. Scope, deliberately: this does not make two counterparties unable to correlate you. The three handshake messages are routed persona-to-persona because the mediator must route them before a pairwise channel exists, and the VRC issuer must be the persona DID because the VTC's `relationships.rego` requires issuer and subject to be current ACL-listed members. Full pairwise operation is a protocol change, tracked in OpenVTC/verifiable-trust-infrastructure#1054. Refs #241 Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
This was referenced Aug 23, 2026
stormer78
added a commit
that referenced
this pull request
Aug 23, 2026
…he persona (#255) The last half of #241, and the half that mattered most. Relationship communication has defaulted to a pairwise R-DID since #254, but the credential it produces did not. `prepare_accept_vrc_request` minted the VRC with `issuer = persona_did`, signed with the persona key. The subject was already the peer's R-DID, so only the issuer half was persona-attributed — and that was enough: the pairwise channel led straight back to the persona. It is the worst place to leak it. The handshake DIDs are observed once, by the mediator, at establishment. The VRC is the durable artifact both parties retain and may publish to a community trust graph, where it correlates every relationship a persona holds for as long as anyone keeps a copy. #241 said the same: "The handshake persona DID is observed once; a published VRC correlates indefinitely." This could not be fixed here before now. The VTC pinned a published VRC's issuer to the authenticated session DID, so a VRC issued under a relationship DID was rejected outright — the only enforcement that existed forbade pairwise identifiers rather than requiring them. Lifted in OpenVTC/verifiable-trust-infrastructure#1061, which separates membership (proven by the session) from the identifier the credential carries. Both ends move together, so this is breaking on the wire: - **Issuance** signs as whichever identity the relationship uses, keyed on `is_persona_did` — the same discriminator `listener_id_for_did` routes sends on. A relationship established without a dedicated R-DID still signs with the persona key, unchanged. - **`vet_vrc_issued` gate 2** now requires the issuer to be the sender's DID in *this* relationship rather than their persona DID. That is strictly tighter as well as more private: gate 1 already matched the authenticated DIDComm sender against the same field, so the credential is pinned to the channel it arrived on instead of to a persona that could have issued it anywhere. Relationships with no R-DID are unaffected — `remote_did` equals `remote_p_did` there, and a test pins that. The `#key-1` verification-method convention that `generate_did_peer_from_secrets` imposes was already load-bearing in two places and spelled out longhand in both. It is now named — `relationship_signing_vm_id` — with the secret lookup beside it in `openvtc-core`, so the TUI crate does not reach into the secrets resolver directly. Docs: the note deferring "full pairwise operation, including the VRC issuer field" to upstream work is replaced by what actually happens, including why the issuer field mattered more than the handshake routing does. The example credential showed a `did:webvh` issuer; it now shows the `did:peer` one it would really carry. What #241 leaves open after this is the handshake routing itself, which is intrinsic — the mediator must route request/accept/finalise before a pairwise channel exists — and worth closing as accepted rather than outstanding. BREAKING CHANGE: a VRC issued by a peer running an older build carries their persona DID and is now refused, and one issued by this build is refused by older peers. Nothing is published yet, so no compatibility window is provided. Refs #241, OpenVTC/verifiable-trust-infrastructure#1054 Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Client-side half of #241 (RAHP finding
OVTC-RAHP-04). Makes pairwise thedefault and puts the trade-off in front of the operator at the moment they
choose.
What changed
Request form —
generate_r_didnow defaults totrue. The toggle readsContact you as: Pairwise R-DID (recommended) / Your persona DIDand rendersthe consequence of whichever is selected, rather than a bare Yes/No.
Inbox accept — the convenient key is now the private one:
aApAdeliberately keeps its old meaning, so anyone with existing muscle memorygets the private outcome they always got. No keystroke that used to produce an
R-DID now produces a persona DID.
Docs —
docs/relationships-vrcs.mdgains a Choosing your identifiercomparison table and drops the
--generate-didexample. That flag, and thewhole
openvtc relationshipssubcommand, have not existed since the v0.2.0 TUIrewrite (
1f31455); the file also contradicted itself, with a diagram showingpairwise as the normal flow and prose calling it optional. Added a note that
the remaining command examples are stale — rewriting the guide for the TUI is a
separate job.
Regression guard —
established_pairwise_relationship_never_pings_from_the_persona_didpins criterion 3: an established relationship's ping takes its
from, itsrecipient and its listener from the relationship record. The property held
already; nothing tested it. Verified the test fails when
prepare_pingis madeto read
persona_did_arc()instead.What this does not do
It does not satisfy acceptance criterion 4. Two counterparties can still
correlate you, for two reasons that are not client-side:
persona-to-persona by design — the mediator has to route them before a
pairwise channel exists.
issuermust be the persona DID, because the VTC'srelationships.regorequires issuer and subject to be current ACL-listedmembers. A VRC issued under a pairwise R-DID is rejected today.
Raised upstream as OpenVTC/verifiable-trust-infrastructure#1054. The commit
message and the docs both say so, so a flipped boolean does not later read as
"correlation solved".
Also corrected on the issue: proposal 2 (CLI opt-out flag) has nothing to
change, since the CLI it refers to is gone.
Checks
cargo fmt --check,cargo clippy --workspace --all-targets -D warnings,cargo test --workspace(all green), andRUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps.Refs #241