Skip to content

Conversation

@rmlearney-digicatapult
Copy link
Contributor

@rmlearney-digicatapult rmlearney-digicatapult commented Jan 14, 2026

Pull Request

Checklist

  • Have you read Digital Catapult's Code of Conduct?
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have made corresponding changes to the documentation.
  • My changes generate no new warnings.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.

PR Type

Please delete options that are irrelevant.

  • Feature

Linked tickets

High level description

Enabling W3C credential handling and proof exchange

Detailed description

1. API Endpoint Updates

Typed Controllers: CredentialController and ProofController updated to accept W3C types. API now processes requests containing standard credential subjects and proof options, validating them against the new standard before passing them to the agent. Implemented Proof Exchange Version 2 (PEX Version 2)

2. TSOA Typing

types.ts expanded to extract all nested types required for TSOA happiness

3. VDRPC Module

Now supports both AnonCreds and PEX

4. E2E Testing

New Test Suite: e2e.didWeb_w3c.test.ts added to validate a complete lifecycle: issuing a W3C credential from Alice to Bob over an implicit connection (did document resolution against a did:web), and Charlie successfully requesting and validating a proof using PEX

Renamed Test Suite: e2e.didKey_w3c.test.ts same as above with explicit invitation (OOB) and W3C credential issuance

Describe alternatives you've considered

Operational impact

Additional context

Needs other PRs merged first to fix test flakiness, rename methods and reorganise types.ts to simplify review

Copilot AI review requested due to automatic review settings January 14, 2026 19:46
@rmlearney-digicatapult rmlearney-digicatapult requested a review from a team as a code owner January 14, 2026 19:46
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds W3C credential and Presentation Exchange (PEX v2) support to the Credo TS-based REST API, enabling issuance and verification of W3C Verifiable Credentials alongside the existing AnonCreds functionality. This hybrid architecture allows the agent to support both privacy-preserving AnonCreds and interoperable W3C credentials.

Changes:

  • Added JsonLdCredentialFormatService and DifPresentationExchangeProofFormatService to agent modules for W3C credential/proof handling
  • Extended API type definitions with W3C-specific types (W3cCredential, PresentationDefinitionV2, JsonLdCredentialFormat) to satisfy TSOA OpenAPI generation
  • Created comprehensive E2E test suite and documentation for W3C credential issuance and PEX-based proof verification flows

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
src/agent.ts Registers JsonLdCredentialFormatService and DifPresentationExchangeProofFormatService in credential/proof protocols, adds W3cCredentialsModule
src/controllers/v1/credentials/CredentialController.ts Updates credential operations to support both AnonCreds and JSON-LD formats via type assertions to internal Credo types
src/controllers/v1/proofs/ProofController.ts Extends proof request/response handlers to support both AnonCreds and PEX formats with conditional spreading
src/controllers/types.ts Adds extensive W3C and PEX type definitions (ApiJsonObject, W3cCredential, PresentationDefinitionV2, etc.) for TSOA compatibility
src/controllers/examples.ts Updates OpenAPI examples with JSON-LD credential format examples and corrects field naming (mime-type to mimeType)
tests/unit/agent.test.ts Adds test verifying W3cCredentialsModule is registered on agent instance
tests/unit/credential.test.ts Adds unit tests for JSON-LD credential proposal and offer operations
tests/unit/proof.test.ts Adds unit test verifying PEX presentationDefinition passes through correctly
tests/integration/e2e.w3c.test.ts New comprehensive E2E test covering W3C credential issuance from Alice to Bob and PEX-based proof verification by Charlie
docs/credentials-and-proofs.md New comprehensive guide documenting AnonCreds vs W3C credentials, DID methods, and API usage patterns
docs/explicit-credential-selection.md Adds reference to new credentials-and-proofs guide
README.md Adds link to new credentials and proofs documentation
package.json Version bump to 0.17.4, fixes lint:fix script syntax
Comments suppressed due to low confidence (1)

src/controllers/v1/credentials/CredentialController.ts:258

  • The error message assumes the credential format is always AnonCreds, but the endpoint now supports W3C credentials via JSON-LD format as well. When a W3C credential issuance fails, accessing options.credentialFormats.anoncreds?.credentialDefinitionId could be undefined, resulting in a confusing error message like 'credential definition "undefined" not found'. The error message should be updated to handle both credential formats appropriately.
      if (error instanceof RecordNotFoundError) {
        throw new NotFoundError(
          `credential definition "${options.credentialFormats.anoncreds?.credentialDefinitionId}" not found`
        )

@rmlearney-digicatapult rmlearney-digicatapult marked this pull request as draft January 14, 2026 20:44
@rmlearney-digicatapult rmlearney-digicatapult changed the base branch from main to chore/types-reorg January 16, 2026 16:27
@github-actions
Copy link

github-actions bot commented Jan 16, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 89.77%
⬆️ +0.34%
8323 / 9271
🔵 Statements 89.77%
⬆️ +0.34%
8323 / 9271
🔵 Functions 82.52%
⬆️ +0.17%
255 / 309
🔵 Branches 66.71%
⬆️ +0.22%
509 / 763
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/agent.ts 92.74%
⬆️ +0.50%
75%
🟰 ±0%
100%
🟰 ±0%
92.74%
⬆️ +0.50%
162-179
src/controllers/examples.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
src/controllers/v1/credentials/CredentialController.ts 91.49%
⬆️ +0.25%
50%
🟰 ±0%
100%
🟰 ±0%
91.49%
⬆️ +0.25%
106-107, 133-134, 154-155, 175-179, 210-211, 248-249, 255-261, 293-294, 326-327, 351-352, 382-386
src/controllers/v1/proofs/ProofController.ts 95.53%
⬆️ +0.04%
70%
🟰 ±0%
100%
🟰 ±0%
95.53%
⬆️ +0.04%
113-114, 146-147, 175-176, 196-197, 221-222, 256-257, 313-314, 355-358, 373-375, 435-436
src/controllers/v1/verified-drpc/VerifiedDrpcController.ts 42.26%
⬆️ +0.85%
0%
🟰 ±0%
0%
🟰 ±0%
42.26%
⬆️ +0.85%
24-26, 36-77, 86-96
src/utils/credentials.ts 100% 66.66% 100% 100%
src/utils/proofs.ts 92.4%
⬆️ +0.28%
78.66%
⬆️ +1.52%
100%
🟰 ±0%
92.4%
⬆️ +0.28%
24-25, 38-39, 64-65, 80-82, 141-142, 145-146, 169-172, 180-183, 209-210
Affected Files
src/controllers/v1/did/DidController.ts 94.89%
⬆️ +0.24%
70.83%
🟰 ±0%
100%
🟰 ±0%
94.89%
⬆️ +0.24%
62-63, 104-106, 114-115
src/routes/routes.ts 95.33%
⬆️ +0.20%
38.5%
🟰 ±0%
96.72%
🟰 ±0%
95.33%
⬆️ +0.20%
1393-1394, 1429-1430, 1445-1470, 1483-1508, 1542-1543, 1579-1580, 1616-1617, 1652-1653, 1688-1689, 1724-1725, 1761-1762, 1797-1798, 1833-1834, 1906-1907, 1941-1942, 1977-1978, 2013-2014, 2049-2050, 2085-2086, 2121-2122, 2157-2158, 2193-2194, 2230-2231, 2266-2267, 2302-2303, 2340-2341, 2377-2378, 2414-2415, 2450-2451, 2486-2487, 2522-2523, 2549-2550, 2561-2562, 2585-2586, 2597-2598, 2621-2622, 2671-2672, 2707-2708, 2780-2781, 2816-2817, 2852-2853, 2888-2889, 2924-2925, 2961-2962, 2997-2998, 3033-3034, 3070-3071, 3107-3108, 3143-3144, 3180-3181, 3218-3219, 3259-3260, 3295-3296, 3332-3333, 3368-3369, 3404-3405, 3475-3476, 3512-3513, 3547-3548
Unchanged Files
src/error.ts 88.6% 86.66% 87.5% 88.6% 44-45, 67-70, 77-79
src/ioc.ts 100% 100% 100% 100%
src/server.ts 95.18% 66.66% 100% 95.18% 69-70, 75-76
src/anoncreds/index.ts 94.6% 100% 60% 94.6% 160-163, 166-167, 171-175, 178-179
src/controllers/HealthController.ts 100% 66.66% 100% 100%
src/controllers/v1/agent/AgentController.ts 100% 75% 100% 100%
src/controllers/v1/basic-messages/BasicMessageController.ts 96.61% 75% 100% 96.61% 56-57
src/controllers/v1/connections/ConnectionController.ts 93.6% 69.23% 100% 93.6% 85-86, 100-108, 196-197, 223-224, 263-264
src/controllers/v1/credentials/CredentialDefinitionController.ts 93.5% 63.15% 100% 93.5% 87-88, 123-124, 126-127, 142-145
src/controllers/v1/credentials/SchemaController.ts 95.65% 66.66% 100% 95.65% 82-83, 124-125, 128-129
src/controllers/v1/drpc/DrpcController.ts 100% 81.81% 100% 100%
src/controllers/v1/media/MediaController.ts 100% 80% 100% 100%
src/controllers/v1/outofband/OutOfBandController.ts 96.59% 60% 100% 96.59% 192-196, 328-329, 346-350
src/controllers/v1/wallet/WalletController.ts 96.29% 66.66% 100% 96.29% 43-44
src/didweb/error.ts 38.23% 0% 0% 38.23% 5, 8-12, 17-18, 22-34
src/didweb/server.ts 61.4% 100% 62.5% 61.4% 45-46, 65-69, 77-113
src/drpc-handler/index.ts 79.31% 81.25% 66.66% 79.31% 13-14, 45-52, 70-71, 75-77, 80-82
src/events/BasicMessageEvents.ts 100% 100% 100% 100%
src/events/ConnectionEvents.ts 100% 100% 100% 100%
src/events/CredentialEvents.ts 100% 100% 100% 100%
src/events/DrpcEvents.ts 43.58% 100% 50% 43.58% 15-36
src/events/MediaSharingEvents.ts 32.35% 50% 100% 32.35% 10-30, 32-33
src/events/ProofEvents.ts 100% 100% 100% 100%
src/events/TrustPingEvents.ts 43.24% 100% 50% 43.24% 14-34
src/events/VerifiedDrpcEvents.ts 43.58% 100% 50% 43.58% 15-36
src/events/WebSocketEvents.ts 100% 66.66% 100% 100%
src/events/WebhookEvent.ts 73.33% 50% 100% 73.33% 11-14
src/ipfs/index.ts 100% 100% 100% 100%
src/ipfs/responseParser.ts 100% 100% 100% 100%
src/modules/verified-drpc/VerifiedDrpcApi.ts 44.93% 100% 40% 44.93% 62-82, 91-115, 132-145, 156-200, 209-228, 231-241
src/modules/verified-drpc/VerifiedDrpcModule.ts 100% 100% 100% 100%
src/modules/verified-drpc/VerifiedDrpcModuleConfig.ts 100% 100% 100% 100%
src/modules/verified-drpc/VerifiedDrpcRequestEvents.ts 100% 100% 100% 100%
src/modules/verified-drpc/VerifiedDrpcResponseEvents.ts 100% 100% 100% 100%
src/modules/verified-drpc/index.ts 100% 100% 100% 100%
src/modules/verified-drpc/handlers/VerifiedDrpcRequestHandler.ts 88.23% 100% 66.66% 88.23% 15-16
src/modules/verified-drpc/handlers/VerifiedDrpcResponseHandler.ts 88.23% 100% 66.66% 88.23% 15-16
src/modules/verified-drpc/handlers/index.ts 100% 100% 100% 100%
src/modules/verified-drpc/messages/VerifiedDrpcRequestMessage.ts 100% 100% 100% 100%
src/modules/verified-drpc/messages/VerifiedDrpcResponseMessage.ts 75.55% 50% 33.33% 75.55% 29-35, 41-44
src/modules/verified-drpc/messages/index.ts 100% 100% 100% 100%
src/modules/verified-drpc/models/ValidRequest.ts 62.79% 75% 66.66% 62.79% 12-25, 40-41
src/modules/verified-drpc/models/ValidResponse.ts 38.8% 100% 25% 38.8% 12-25, 39-62, 65-67
src/modules/verified-drpc/models/VerifiedDrpcErrorCodes.ts 100% 100% 100% 100%
src/modules/verified-drpc/models/VerifiedDrpcRole.ts 100% 100% 100% 100%
src/modules/verified-drpc/models/VerifiedDrpcState.ts 100% 100% 100% 100%
src/modules/verified-drpc/models/index.ts 100% 100% 100% 100%
src/modules/verified-drpc/repository/VerifiedDrpcRecord.ts 72.5% 100% 50% 72.5% 54-59, 62-65, 68-79
src/modules/verified-drpc/repository/VerifiedDrpcRepository.ts 100% 100% 100% 100%
src/modules/verified-drpc/repository/index.ts 100% 100% 100% 100%
src/modules/verified-drpc/services/VerifiedDrpcService.ts 73.7% 85.18% 65% 73.7% 138-152, 161-167, 171-172, 176-193, 196-214, 225-226, 252-253, 262-265, 267-271, 297-298, 301-302, 305-307
src/modules/verified-drpc/services/index.ts 100% 100% 100% 100%
src/utils/didWebGenerator.ts 64.06% 75% 60% 64.06% 65-66, 79-117, 123-127
src/utils/helpers.ts 85% 100% 50% 85% 18-20
src/utils/logger.ts 91.59% 100% 75% 91.59% 57-59, 68-69, 92-93, 105-107
src/utils/version.ts 100% 100% 100% 100%
src/utils/webhook.ts 95.74% 88.88% 100% 95.74% 21-22
Generated in workflow #2630 for commit 581397b by the Vitest Coverage Report Action

@rmlearney-digicatapult rmlearney-digicatapult added the v:minor Change requires a semver minor version change label Jan 16, 2026
Base automatically changed from chore/types-reorg to main January 19, 2026 12:17
@rmlearney-digicatapult rmlearney-digicatapult marked this pull request as ready for review January 21, 2026 19:07
@rmlearney-digicatapult rmlearney-digicatapult marked this pull request as draft January 21, 2026 19:08
@rmlearney-digicatapult rmlearney-digicatapult force-pushed the feature/w3c-credential-endpoints branch 2 times, most recently from e9ec57a to 0ce208f Compare January 22, 2026 09:57
@rmlearney-digicatapult rmlearney-digicatapult marked this pull request as ready for review January 22, 2026 09:57
Comment on lines 32 to 54

/**
* Recursive JSON types for TSOA compatibility.
* Defined locally to avoid TSOA errors with imported specific types.
*
* NOTE: The extensive type and interface definitions in this file (specifically explicitly
* recursive types like ApiJsonObject) are required to satisfy TSOA's schema generation.
* TSOA struggles with generic 'Record<string, any>' or complex union types imported
* from @credo-ts/core, often throwing 'Index Type' or 'Reference' errors during spec generation.
* By defining strict, self-contained recursive structures here, we ensure Swagger/OpenAPI
* specs are generated correctly.
*
* TODO: TSOA v7.0.0-alpha.0 added OpenAPI 3.1 support (PR #1768), effectively supporting
* variadic tuples and usage of 'prefixItems' for array validation.
* Once upgraded, we should revisit these recursive types to see if the workaround is still needed.
*/
export type ApiJsonValue = string | number | boolean | null | ApiJsonObject | ApiJsonArray | undefined
export type ApiJsonArray = Array<ApiJsonValue>
export interface ApiJsonObject {
[key: string]: ApiJsonValue
}

export type GenericRecord = ApiJsonObject
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty nasty. Essentially we're typing a bunch of objects as "any valid value for JSON". We should have a look at how bad a representation that is compared to the credo types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am reworking some of the types but sadly I think there are some non-ideal things we will have to do to make TSOA happy because of type collisions with sphereon-pex within credo-ts

@rmlearney-digicatapult rmlearney-digicatapult force-pushed the feature/w3c-credential-endpoints branch from 4a1a24d to 85ac247 Compare January 26, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v:minor Change requires a semver minor version change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants