Skip to content

feat!: DTG Credentials v1 — role VACs, vetted/1 and witnessed/1 statements, issuerScope - #397

Merged
stormer78 merged 9 commits into
mainfrom
feat/dtg-vsc-conformance
Oct 1, 2026
Merged

stormer78 merged 9 commits into
mainfrom
feat/dtg-vsc-conformance

Conversation

@stormer78

@stormer78 stormer78 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

This moves every DTG credential OpenVTC issues, receives, verifies, stores, displays or documents onto the DTG Credentials Core Specification (WD 0.6.0) and the DTG VSC predicate registry. The DTGWG reviewed and agreed the migration plan.

This is a draft because it builds against unreleased crates. The last commit, chore: DO NOT MERGE — patch …, points dtg-credentials, vta-sdk and trust-tasks-* at local worktrees, so CI cannot build it yet. Once these release, the commit is replaced with version bumps:

What changes on the wire

Flow Before After
All DTG credentials firstperson.network/credentials/dtg/v1 context, no issuerScope registry.trustoverip.org/dtg/context/v1, with a required issuerScope
Role grants / vetter eligibility EndorsementCredential + CommunityRole A community AuthorityCredential: actions: ["role:<name>"], vetter = role:vetter
Vetting Statement EndorsementCredential, identity-vetting/0.1 A StatementCredential with predicate …/dtg/vsc/vetted/1, the body in object.value, and taskContext + taskDigestMultibase
Witness WitnessCredential A witnessed/1 statement, classified by predicate
Member VMC acknowledgement new_member_vmc new_member_vmc_for, issuerScope: directed
VRC no scope pairwise for a relationship DID, directed for the persona DID

The scope rules live in one module, openvtc-core/src/dtg.rs.

Stored state

Credentials already stored in pre-v1 shapes are non-conformant. They are dropped on load with a warn!; they are never kept and never allowed to fail the load. The member sees a notice:

  • A membership's VMC, role credential or acknowledgement is listed as retired, with "ask the community to re-issue it".
  • The Credentials panel shows the count of retired VRCs.
  • The Vetting page lists the retired vetter grants and statements.

A conformant replacement clears the notice.

Other changes

  • Vetting session: the vetter now signs and keeps the vetting/session document it sends. The applicant refuses a statement that doesn't match its copy.
  • Hidden-vetting PCS fixture: regenerated because statementType changed, which moved requirementsDigest. VTI carries the matching fixture.
  • Object-form issuer: VICs and VMCs with an object-form issuer are now refused, because the spec's Base Structure makes issuer a string.
  • Docs: vetting-process.md, vetting-hidden-vetters-pcs.md and relationships-vrcs.md describe the v1 shapes. §9.4 of vetting-process.md could use a careful read.

Follow-ups (not in this PR)

  • There is no "renew membership" action in the TUI yet. The notice asks the community to re-issue.
  • did-git-sign 0.5.2 still pulls vta-sdk 0.56 into the graph. That goes away with a VGI release on 0.57.
  • On release, dtg-credentials is raised from "0.11" to "0.12". It says 0.11 now only so the local patch matches.

Checks

  • cargo fmt is clean.
  • cargo clippy --workspace --all-targets -- -D warnings is clean.
  • cargo test --workspace: 1722 passed, 0 failed, built against the VTI branch at 32b2187b. vta-sdk is unchanged since 0c3c8c75.

@stormer78

Copy link
Copy Markdown
Contributor Author

Re-verified against VTI's final branch tip (c477700c, which includes the stricter community_roles in 11b5c32b). cargo clippy --workspace --all-targets -D warnings is clean, and cargo test --workspace passes 1722 of 1722. No code changes were needed.

@stormer78

Copy link
Copy Markdown
Contributor Author

The local-path patch is gone. The branch now requires released crates: dtg-credentials 0.12, trust-tasks-* 0.25, affinidi-* 0.31 / 0.21 (affinidi/affinidi-tdk-rs#908), and vta-sdk 0.57 / vta-service 0.46 from OpenVTC/verifiable-trust-infrastructure#1859. Cargo.lock follows once VTI publishes; after that it comes out of draft.

@stormer78
stormer78 marked this pull request as ready for review October 1, 2026 00:40
@stormer78
stormer78 requested a review from a team as a code owner October 1, 2026 00:40
Every DTG credential the client issues, receives, verifies or stores now
carries the v1 context (https://registry.trustoverip.org/dtg/context/v1,
the pre-v1 context refused with no alias), a top-level issuerScope and
exactly one concrete type, on dtg-credentials 0.12, vta-sdk 0.57,
vta-service 0.46 and trust-tasks 0.24.8.

- openvtc_core::dtg: the scope each issued credential declares
  (MEMBER_IDENTIFIER_SCOPE = directed for the persona DID a membership
  names; relationship_issuer_scope: pairwise for a relationship DID,
  directed for the persona DID; PERSONA_ANNOTATION_SCOPE = directed),
  parse_conformant, community_roles, and predicate-based statement
  display with a fail-closed core accept list.
- Member acknowledgement: new_member_vmc_for with the signing persona,
  declaring directed; build_member_vmc takes the member DID.
- VIC validation parses through dtg-credentials: v1 context second,
  issuerScope public, one concrete type. join::DTG_CONTEXT re-exports
  DTG_CONTEXT_V1.
- CredentialKind::Role is a community role VAC (AuthorityCredential,
  authority.scope the community, role:<name> actions); from_credential
  classifies conformant credentials only.
- VRCs declare the scope of the identifier the relationship uses.
- personhood AssertReply::role_vec -> role_vac (wire roleVac).
- Stored credentials in a pre-v1 shape are set aside on load with a
  logged reason: CommunityRecord::retired_credentials (persisted, cleared
  by a conformant replacement), Vrcs::retired, dropped VRCIssued tasks,
  and RejectionReason::Nonconformant on a vault rebuild.

The patch block this builds against is its own commit.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
…es are VACs

Follows vta-sdk 0.57 (vetting statements are vetted/1 VSCs; role
credentials are VACs).

- The vetter's Vetting Statement is a StatementCredential under
  https://registry.trustoverip.org/dtg/vsc/vetted/1, the body at
  object.value, issued directed, citing the vetting/session document by
  taskContext and taskDigestMultibase. The desk keeps the signed session
  document (VettingBook::record_session_document, DeskSession::document)
  and a session without one cannot be attested; the applicant keeps the
  one it received (OpenSession::document) and refuses a statement that
  does not cite it (check_against_session).
- Statements are claimed by predicate, never by type; manifests name the
  predicate IRI as statementType.
- A vetter grant is a community role VAC (community_roles, role:vetter).
- Stored vetter grants and held statements in a pre-v1 shape are set
  aside on load (VettingBook::retire_nonconformant, run by
  ProtectedConfig::parse) with a notice in VettingBook::retired, cleared
  when a replacement arrives.
- openvtc-vetting-pcs: only the statementType changes; the wire fixture
  is regenerated, which moves its requirementsDigest.
- zkp_reference_flow and its output are regenerated in the v1 shapes.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
- VRCs are issued declaring the scope of the identifier the relationship
  uses (pairwise relationship DID, directed persona DID).
- The vetter signs the vetting/session document before sending it, and
  the desk keeps that copy for the statement to cite.
- Communities: the role credential shows the roles it confers, and a
  credential set aside on load as pre-v1 is shown as a warning asking for
  it to be re-issued.
- Credentials: held credentials are described from their content ("Role:
  vetter", a statement by predicate), and set-aside VRCs are counted.
- Vetting: set-aside grants and statements are listed on the page.
- Test fixtures are v1 credentials; an object-form VIC issuer is refused.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
- vetting-process, vetting-hidden-vetters-pcs, hidden-vetting-live-run:
  the Vetting Statement is a vetted/1 VSC citing its session by id and
  digest, the vetter role a community VAC, the manifest statementType the
  predicate IRI, and pre-v1 grants and statements are set aside on load.
- relationships-vrcs: the scope a VRC declares, derived from the
  identifier the relationship uses, and the v1 sample VRC.
- openvtc-config-data-structure: Vrcs::retired and per-VRC loading.
- Retired R-DID / P-DID / M-DID / C-DID terms replaced where touched.
- CHANGELOG: the v1 migration by flow, and the stored-state behaviour.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
…ffinidi-messaging 0.31

Replaces the local-path patch with the released crates:
- dtg-credentials 0.12
- vta-sdk / vta-service 0.57 / 0.46 (OpenVTC/verifiable-trust-infrastructure#1859)
- the trust-tasks-* family at 0.25
- affinidi-tdk 0.21, affinidi-messaging-sdk 0.31 and -test-mediator 0.15
  (affinidi/affinidi-tdk-rs#908)

Cargo.lock follows once VTI publishes.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
vta-sdk 0.57.0 shipped before the DTG v1 migration, so the release that
carries it (OpenVTC/verifiable-trust-infrastructure#1859) is 0.58.0.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
dtg-credentials 0.12, vta-sdk 0.58, vta-service 0.47, trust-tasks 0.25,
affinidi-tdk 0.21 and affinidi-messaging-sdk 0.31, all from crates.io.
The only second copies come through did-git-sign 0.5.2 (vta-sdk 0.56),
which clears with the did-git-sign release on vta-sdk 0.58.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
… 0.8.4

- The outer doc comment on `pub mod dtg` made rustdoc resolve the module's
  inner docs from the crate root, where its own items are not in scope.
  dtg.rs carries its own //! docs, so the outer comment goes.
- book.rs linked Self::clear_retired; the method is clear_retired_for.
- yoke-derive 0.8.3 is yanked (cargo-deny).

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
@stormer78
stormer78 force-pushed the feat/dtg-vsc-conformance branch from 9421d40 to 2aa1ed6 Compare October 1, 2026 01:08
VGI 0.6.0 is on vta-sdk 0.58, affinidi-tdk 0.21 and trust-tasks 0.25, so
the second registry copies of vta-sdk, trust-tasks-rs, affinidi-tdk and
affinidi-messaging-sdk under did-git-sign 0.5.2 are gone.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
@stormer78
stormer78 merged commit e165bd5 into main Oct 1, 2026
15 checks passed
@stormer78
stormer78 deleted the feat/dtg-vsc-conformance branch October 1, 2026 02:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant