#4090: Wire credential_selection through API to presenter - #4122
Conversation
0 new issues
|
|
Coverage Impact Unable to calculate total coverage change because base branch coverage was not found. Modified Files with Diff Coverage (6)
🤖 Increase coverage with AI coding...🚦 See full report on Qlty Cloud » 🛟 Help
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a credential_selection parameter on the service access token request API and wires it through the RFC021/OpenID4VP flow into the holder’s presentation building so callers can deterministically disambiguate which wallet credential to present when multiple match.
Changes:
- Added
credential_selectionto the OpenAPI spec and regenerated API/client types. - Threaded
credential_selectionthrough API handler → IAM client → wallet → presenter and applied it viape.NewSelectionSelector. - Extended e2e test PD + script to validate selecting the intended organization credential end-to-end.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
docs/_static/auth/v2.yaml |
Adds credential_selection schema + documentation to the API spec. |
auth/api/iam/generated.go |
Regenerated request type to include CredentialSelection. |
auth/api/iam/api.go |
Extracts credential_selection from request body and forwards it to IAM client. |
auth/api/iam/api_test.go |
Updates mocks/calls for new IAM client method signature. |
auth/client/iam/interface.go |
Extends RequestRFC021AccessToken signature with credentialSelection. |
auth/client/iam/openid4vp.go |
Forwards credentialSelection into wallet.BuildSubmission. |
auth/client/iam/openid4vp_test.go |
Updates expectations for the updated wallet call signature. |
auth/client/iam/mock.go |
Regenerated mock for updated client interface. |
vcr/holder/interface.go |
Extends wallet BuildSubmission signature with credentialSelection. |
vcr/holder/sql_wallet.go |
Passes credentialSelection through to presenter. |
vcr/holder/memory_wallet.go |
Passes credentialSelection through to presenter (in-memory wallet). |
vcr/holder/presenter.go |
Constructs and installs a selection-based credential selector when provided. |
vcr/holder/presenter_test.go |
Adds a unit test asserting selection narrows to the intended credential. |
vcr/holder/mock.go |
Regenerated mock for updated wallet interface. |
e2e-tests/oauth-flow/rfc021/node-A/presentationexchangemapping.json |
Adds id: organization_name to PD field so it can be targeted by selection. |
e2e-tests/oauth-flow/rfc021/do-test.sh |
Adds e2e flow that issues two org creds and selects one via credential_selection. |
e2e-tests/browser/client/iam/generated.go |
Updates generated browser test client with CredentialSelection. |
auth/api/iam/openid4vp.go |
Updates wallet BuildSubmission call with new signature (selection unused here). |
auth/api/iam/openid4vp_test.go |
Updates wallet mock expectations for new signature. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Addressing review feedbackChanges made
Not changed
Also addressed on PR #4121 (base branch)
|
- Capitalize "field id" → "field ID" in OpenAPI spec - Add godoc for credentials and credentialSelection parameters - Document default behavior when credential_selection is omitted - Add comment explaining FirstMatchSelector fallback - Add comment explaining nil credential_selection is safe (read-only) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
b9c0019 to
c2a4951
Compare
Adds a credential_query test to the RFC021 e2e flow: - Issues two NutsOrganizationCredentials with different org names - Uses credential_query to select "Second Org B.V." by name - Verifies extended introspection contains the selected organization Test correctly fails: credential_query is currently ignored, so the default PD matcher picks "Caresoft B.V." instead of "Second Org B.V." Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- OpenAPI spec: add credential_query to ServiceAccessTokenRequest - Regenerate types and mocks - API handler: extract credential_query, convert to dcql.CredentialQuery - Client.RequestRFC021AccessToken: accept credentialQueries parameter - Wallet.BuildSubmission: accept credentialQueries parameter - Presenter: create DCQL selector when credentialQueries is non-empty - All existing tests pass with nil for new parameter Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace credential_query (DCQL) with credential_selection (named parameters) throughout the callstack. The API accepts a simple map[string]string mapping PD field IDs to expected values, which is propagated through the IAM client, wallet, and presenter to NewSelectionSelector. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Double-quote shell variables in e2e test to prevent globbing/splitting - Use single-quoted heredoc for JSON literal - Fix empty-response check to use proper test syntax - Add unit test for buildSubmission with credential_selection Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Capitalize "field id" → "field ID" in OpenAPI spec - Add godoc for credentials and credentialSelection parameters - Document default behavior when credential_selection is omitted - Add comment explaining FirstMatchSelector fallback - Add comment explaining nil credential_selection is safe (read-only) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The builder now handles the fallback to FirstMatchSelector when a selector returns (nil, nil), so the explicit fallback argument is no longer needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c2a4951 to
8032590
Compare
…D values (#4121) * #4120: Selection CredentialSelector — filter candidates by PD field ID values NewSelectionSelector creates a CredentialSelector that filters candidates using named field ID values from the credential_selection API parameter. Selection keys are validated against PD field IDs at construction time. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4120: Simplify key validation with matchedKeys set Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * - Rename NewSelectionSelector → NewFieldSelector for clarity - Return matchConstraint errors instead of swallowing them - Simplify matchesSelections to assert string type directly - Add comment explaining constant-only matching design Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4121: Remove fallback parameter from NewFieldSelector Selectors are not composable — default behavior belongs in the builder. NewFieldSelector now returns (nil, nil) for unmatched descriptors, and the builder falls back to FirstMatchSelector when a selector returns (nil, nil) with candidates available. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4090: Wire credential_selection through API to presenter (#4122) * #4090: RED — e2e test for credential_query selection Adds a credential_query test to the RFC021 e2e flow: - Issues two NutsOrganizationCredentials with different org names - Uses credential_query to select "Second Org B.V." by name - Verifies extended introspection contains the selected organization Test correctly fails: credential_query is currently ignored, so the default PD matcher picks "Caresoft B.V." instead of "Second Org B.V." Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4090: Wire credential_query through API to presenter - OpenAPI spec: add credential_query to ServiceAccessTokenRequest - Regenerate types and mocks - API handler: extract credential_query, convert to dcql.CredentialQuery - Client.RequestRFC021AccessToken: accept credentialQueries parameter - Wallet.BuildSubmission: accept credentialQueries parameter - Presenter: create DCQL selector when credentialQueries is non-empty - All existing tests pass with nil for new parameter Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4090: Wire credential_selection through API to presenter Replace credential_query (DCQL) with credential_selection (named parameters) throughout the callstack. The API accepts a simple map[string]string mapping PD field IDs to expected values, which is propagated through the IAM client, wallet, and presenter to NewSelectionSelector. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4090: Fix shellcheck issues, add presenter credential_selection test - Double-quote shell variables in e2e test to prevent globbing/splitting - Use single-quoted heredoc for JSON literal - Fix empty-response check to use proper test syntax - Add unit test for buildSubmission with credential_selection Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fixup: Use renamed NewFieldSelector in presenter Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4122: Address review feedback - Capitalize "field id" → "field ID" in OpenAPI spec - Add godoc for credentials and credentialSelection parameters - Document default behavior when credential_selection is omitted - Add comment explaining FirstMatchSelector fallback - Add comment explaining nil credential_selection is safe (read-only) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4122: Remove fallback parameter from NewFieldSelector call The builder now handles the fallback to FirstMatchSelector when a selector returns (nil, nil), so the explicit fallback argument is no longer needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* #4088: Extract CredentialSelector and refactor matchConstraints Introduces CredentialSelector function type and FirstMatchSelector. Refactors matchConstraints to collect all matching VCs per input descriptor, then call the selector to pick one. Match delegates to MatchWithSelector with FirstMatchSelector. No behavior change — all existing tests pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4088: Add SetCredentialSelector to PresentationSubmissionBuilder Adds SetCredentialSelector method to configure a custom CredentialSelector on the builder. Build passes it through to MatchWithSelector. Falls back to FirstMatchSelector when not set. Tests verify: custom selector picks non-first credential, default behavior preserved, selector receives all matching candidates. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4088: Document CredentialSelector contract, add ErrMultipleCredentials CredentialSelector doc now describes return value semantics: when to return nil (unfulfilled), ErrNoCredentials (no match), or ErrMultipleCredentials (ambiguous). Adds error propagation test. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4088: Soft-fail ErrNoCredentials for submission requirements compatibility When a CredentialSelector returns ErrNoCredentials, treat it as a nil selection (unfulfilled descriptor) instead of a hard failure. This allows submission requirements with pick rules (e.g., min: 0) to evaluate whether zero fulfilled descriptors is acceptable. ErrMultipleCredentials and other errors remain hard failures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4120: Selection CredentialSelector — filter candidates by PD field ID values (#4121) * #4120: Selection CredentialSelector — filter candidates by PD field ID values NewSelectionSelector creates a CredentialSelector that filters candidates using named field ID values from the credential_selection API parameter. Selection keys are validated against PD field IDs at construction time. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4120: Simplify key validation with matchedKeys set Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * - Rename NewSelectionSelector → NewFieldSelector for clarity - Return matchConstraint errors instead of swallowing them - Simplify matchesSelections to assert string type directly - Add comment explaining constant-only matching design Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4121: Remove fallback parameter from NewFieldSelector Selectors are not composable — default behavior belongs in the builder. NewFieldSelector now returns (nil, nil) for unmatched descriptors, and the builder falls back to FirstMatchSelector when a selector returns (nil, nil) with candidates available. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4090: Wire credential_selection through API to presenter (#4122) * #4090: RED — e2e test for credential_query selection Adds a credential_query test to the RFC021 e2e flow: - Issues two NutsOrganizationCredentials with different org names - Uses credential_query to select "Second Org B.V." by name - Verifies extended introspection contains the selected organization Test correctly fails: credential_query is currently ignored, so the default PD matcher picks "Caresoft B.V." instead of "Second Org B.V." Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4090: Wire credential_query through API to presenter - OpenAPI spec: add credential_query to ServiceAccessTokenRequest - Regenerate types and mocks - API handler: extract credential_query, convert to dcql.CredentialQuery - Client.RequestRFC021AccessToken: accept credentialQueries parameter - Wallet.BuildSubmission: accept credentialQueries parameter - Presenter: create DCQL selector when credentialQueries is non-empty - All existing tests pass with nil for new parameter Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4090: Wire credential_selection through API to presenter Replace credential_query (DCQL) with credential_selection (named parameters) throughout the callstack. The API accepts a simple map[string]string mapping PD field IDs to expected values, which is propagated through the IAM client, wallet, and presenter to NewSelectionSelector. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4090: Fix shellcheck issues, add presenter credential_selection test - Double-quote shell variables in e2e test to prevent globbing/splitting - Use single-quoted heredoc for JSON literal - Fix empty-response check to use proper test syntax - Add unit test for buildSubmission with credential_selection Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fixup: Use renamed NewFieldSelector in presenter Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4122: Address review feedback - Capitalize "field id" → "field ID" in OpenAPI spec - Add godoc for credentials and credentialSelection parameters - Document default behavior when credential_selection is omitted - Add comment explaining FirstMatchSelector fallback - Add comment explaining nil credential_selection is safe (read-only) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * #4122: Remove fallback parameter from NewFieldSelector call The builder now handles the fallback to FirstMatchSelector when a selector returns (nil, nil), so the explicit fallback argument is no longer needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Summary
credential_selectionparameter toServiceAccessTokenRequestOpenAPI spec — a simplemap[string]stringmapping PD field IDs to expected valuesNewSelectionSelectorcredential_query(DCQL) approach with named parametersid: "organization_name"to e2e test PD so credential selection can target itcredential_selection, verifies introspection returns correct orgCloses #4090
Part of #4067
Callstack
Test plan
vcr/pe/,vcr/holder/,auth/api/iam/,auth/client/iam/🤖 Generated with Claude Code