diff --git a/auth/auth.go b/auth/auth.go
index f135335c0..e869f35f8 100644
--- a/auth/auth.go
+++ b/auth/auth.go
@@ -22,6 +22,7 @@ import (
"crypto/tls"
"errors"
"github.com/nuts-foundation/nuts-node/auth/client/iam"
+ "github.com/nuts-foundation/nuts-node/policy"
"github.com/nuts-foundation/nuts-node/vdr"
"github.com/nuts-foundation/nuts-node/vdr/didjwk"
"github.com/nuts-foundation/nuts-node/vdr/didkey"
@@ -68,6 +69,7 @@ type Auth struct {
httpClientTimeout time.Duration
tlsConfig *tls.Config
subjectManager didsubject.Manager
+ policyBackend policy.PDPBackend
// configuredDIDMethods contains the DID methods that are configured in the Nuts node,
// of which VDR will create DIDs.
configuredDIDMethods []string
@@ -100,7 +102,7 @@ func (auth *Auth) ContractNotary() services.ContractNotary {
// NewAuthInstance accepts a Config with several Nuts Engines and returns an instance of Auth
func NewAuthInstance(config Config, vdrInstance vdr.VDR, subjectManager didsubject.Manager, vcr vcr.VCR, keyStore crypto.KeyStore,
- serviceResolver didman.CompoundServiceResolver, jsonldManager jsonld.JSONLD, pkiProvider pki.Provider) *Auth {
+ serviceResolver didman.CompoundServiceResolver, jsonldManager jsonld.JSONLD, pkiProvider pki.Provider, policyBackend policy.PDPBackend) *Auth {
return &Auth{
config: config,
jsonldManager: jsonldManager,
@@ -110,6 +112,7 @@ func NewAuthInstance(config Config, vdrInstance vdr.VDR, subjectManager didsubje
vcr: vcr,
pkiProvider: pkiProvider,
serviceResolver: serviceResolver,
+ policyBackend: policyBackend,
shutdownFunc: func() {},
}
}
@@ -126,7 +129,7 @@ func (auth *Auth) RelyingParty() oauth.RelyingParty {
func (auth *Auth) IAMClient() iam.Client {
keyResolver := resolver.DIDKeyResolver{Resolver: auth.vdrInstance.Resolver()}
- return iam.NewClient(auth.vcr.Wallet(), keyResolver, auth.subjectManager, auth.keyStore, auth.jsonldManager.DocumentLoader(), auth.strictMode, auth.httpClientTimeout)
+ return iam.NewClient(auth.vcr.Wallet(), keyResolver, auth.subjectManager, auth.keyStore, auth.jsonldManager.DocumentLoader(), auth.policyBackend, auth.strictMode, auth.httpClientTimeout)
}
// Configure the Auth struct by creating a validator and create an Irma server
diff --git a/auth/auth_test.go b/auth/auth_test.go
index 968ea61ef..8ae69fbd8 100644
--- a/auth/auth_test.go
+++ b/auth/auth_test.go
@@ -47,7 +47,7 @@ func TestAuth_Configure(t *testing.T) {
vdrInstance := vdr.NewMockVDR(ctrl)
vdrInstance.EXPECT().Resolver().AnyTimes()
- i := NewAuthInstance(config, vdrInstance, nil, vcr.NewTestVCRInstance(t), crypto.NewMemoryCryptoInstance(t), nil, nil, pkiMock)
+ i := NewAuthInstance(config, vdrInstance, nil, vcr.NewTestVCRInstance(t), crypto.NewMemoryCryptoInstance(t), nil, nil, pkiMock, nil)
require.NoError(t, i.Configure(tlsServerConfig))
})
@@ -61,7 +61,7 @@ func TestAuth_Configure(t *testing.T) {
vdrInstance := vdr.NewMockVDR(ctrl)
vdrInstance.EXPECT().Resolver().AnyTimes()
- i := NewAuthInstance(config, vdrInstance, nil, vcr.NewTestVCRInstance(t), crypto.NewMemoryCryptoInstance(t), nil, nil, pkiMock)
+ i := NewAuthInstance(config, vdrInstance, nil, vcr.NewTestVCRInstance(t), crypto.NewMemoryCryptoInstance(t), nil, nil, pkiMock, nil)
require.NoError(t, i.Configure(tlsServerConfig))
})
@@ -119,7 +119,7 @@ func TestAuth_IAMClient(t *testing.T) {
vdrInstance := vdr.NewMockVDR(ctrl)
vdrInstance.EXPECT().Resolver().AnyTimes()
- i := NewAuthInstance(config, vdrInstance, nil, vcr.NewTestVCRInstance(t), crypto.NewMemoryCryptoInstance(t), nil, jsonld.NewTestJSONLDManager(t), pkiMock)
+ i := NewAuthInstance(config, vdrInstance, nil, vcr.NewTestVCRInstance(t), crypto.NewMemoryCryptoInstance(t), nil, jsonld.NewTestJSONLDManager(t), pkiMock, nil)
assert.NotNil(t, i.IAMClient())
})
diff --git a/auth/client/iam/openid4vp.go b/auth/client/iam/openid4vp.go
index bf7f8fef6..a5a2728d1 100644
--- a/auth/client/iam/openid4vp.go
+++ b/auth/client/iam/openid4vp.go
@@ -25,6 +25,7 @@ import (
"errors"
"fmt"
"github.com/nuts-foundation/nuts-node/http/client"
+ "github.com/nuts-foundation/nuts-node/policy"
"github.com/nuts-foundation/nuts-node/vcr/credential"
"github.com/nuts-foundation/nuts-node/vdr/didsubject"
"github.com/piprate/json-gold/ld"
@@ -60,23 +61,30 @@ type OpenID4VPClient struct {
wallet holder.Wallet
ldDocumentLoader ld.DocumentLoader
subjectManager didsubject.Manager
+ pdResolver PresentationDefinitionResolver
}
// NewClient returns an implementation of Holder
func NewClient(wallet holder.Wallet, keyResolver resolver.KeyResolver, subjectManager didsubject.Manager, jwtSigner nutsCrypto.JWTSigner,
- ldDocumentLoader ld.DocumentLoader, strictMode bool, httpClientTimeout time.Duration) *OpenID4VPClient {
+ ldDocumentLoader ld.DocumentLoader, policyBackend policy.PDPBackend, strictMode bool, httpClientTimeout time.Duration) *OpenID4VPClient {
+ httpClient := HTTPClient{
+ strictMode: strictMode,
+ httpClient: client.NewWithCache(httpClientTimeout),
+ keyResolver: keyResolver,
+ }
return &OpenID4VPClient{
- httpClient: HTTPClient{
- strictMode: strictMode,
- httpClient: client.NewWithCache(httpClientTimeout),
- keyResolver: keyResolver,
- },
+ httpClient: httpClient,
keyResolver: keyResolver,
jwtSigner: jwtSigner,
ldDocumentLoader: ldDocumentLoader,
subjectManager: subjectManager,
strictMode: strictMode,
wallet: wallet,
+ pdResolver: PresentationDefinitionResolver{
+ httpClient: httpClient,
+ policyBackend: policyBackend,
+ strictMode: strictMode,
+ },
}
}
@@ -242,18 +250,12 @@ func (c *OpenID4VPClient) RequestRFC021AccessToken(ctx context.Context, clientID
return nil, err
}
- // get the presentation definition from the verifier
- parsedURL, err := core.ParsePublicURL(metadata.PresentationDefinitionEndpoint, c.strictMode)
- if err != nil {
- return nil, err
- }
- presentationDefinitionURL := nutsHttp.AddQueryParams(*parsedURL, map[string]string{
- "scope": scopes,
- })
- presentationDefinition, err := c.PresentationDefinition(ctx, presentationDefinitionURL.String())
+ // Resolve the presentation definition: from remote AS when available, local policy otherwise
+ resolved, err := c.pdResolver.Resolve(ctx, scopes, *metadata)
if err != nil {
return nil, err
}
+ presentationDefinition := &resolved.PresentationDefinition
params := holder.BuildParams{
Audience: authServerURL,
@@ -312,7 +314,7 @@ func (c *OpenID4VPClient) RequestRFC021AccessToken(ctx context.Context, clientID
data.Set(oauth.GrantTypeParam, oauth.VpTokenGrantType)
data.Set(oauth.AssertionParam, assertion)
data.Set(oauth.PresentationSubmissionParam, string(presentationSubmission))
- data.Set(oauth.ScopeParam, scopes)
+ data.Set(oauth.ScopeParam, resolved.Scope)
// create DPoP header
var dpopHeader string
diff --git a/auth/client/iam/openid4vp_test.go b/auth/client/iam/openid4vp_test.go
index f4a725a09..118b2aea0 100644
--- a/auth/client/iam/openid4vp_test.go
+++ b/auth/client/iam/openid4vp_test.go
@@ -491,6 +491,12 @@ func createClientTestContext(t *testing.T, tlsConfig *tls.Config) *clientTestCon
},
jwtSigner: jwtSigner,
keyResolver: keyResolver,
+ pdResolver: PresentationDefinitionResolver{
+ httpClient: HTTPClient{
+ strictMode: false,
+ httpClient: client.NewWithTLSConfig(10*time.Second, tlsConfig),
+ },
+ },
},
jwtSigner: jwtSigner,
keyResolver: keyResolver,
diff --git a/auth/client/iam/pd_resolver.go b/auth/client/iam/pd_resolver.go
new file mode 100644
index 000000000..4cdce7c92
--- /dev/null
+++ b/auth/client/iam/pd_resolver.go
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2026 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package iam
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/nuts-foundation/nuts-node/auth/oauth"
+ "github.com/nuts-foundation/nuts-node/core"
+ nutsHttp "github.com/nuts-foundation/nuts-node/http"
+ "github.com/nuts-foundation/nuts-node/policy"
+ "github.com/nuts-foundation/nuts-node/vcr/pe"
+)
+
+// ResolvedPresentationDefinition contains a resolved PD and the scope to use in the token request.
+type ResolvedPresentationDefinition struct {
+ PresentationDefinition pe.PresentationDefinition
+ // Scope is the scope string to include in the token request.
+ // When resolved remotely, this is the original scope string (remote AS handles scope policy).
+ // When resolved locally, this depends on the configured scope policy.
+ Scope string
+}
+
+// PresentationDefinitionResolver resolves a PresentationDefinition for a given scope string.
+// It uses the remote AS's PD endpoint when available, falling back to local policy resolution.
+type PresentationDefinitionResolver struct {
+ httpClient HTTPClient
+ policyBackend policy.PDPBackend
+ strictMode bool
+}
+
+// Resolve resolves a PresentationDefinition for the given scope string.
+// If the remote AS metadata advertises a PD endpoint, the PD is fetched remotely
+// and the full scope string is returned (remote AS handles scope policy).
+// If no PD endpoint is available, the local policy backend is used and scope policy is enforced.
+func (r *PresentationDefinitionResolver) Resolve(ctx context.Context, scope string, metadata oauth.AuthorizationServerMetadata) (*ResolvedPresentationDefinition, error) {
+ if metadata.PresentationDefinitionEndpoint != "" {
+ return r.resolveRemote(ctx, scope, metadata)
+ }
+ return r.resolveLocal(ctx, scope)
+}
+
+func (r *PresentationDefinitionResolver) resolveRemote(ctx context.Context, scope string, metadata oauth.AuthorizationServerMetadata) (*ResolvedPresentationDefinition, error) {
+ parsedURL, err := core.ParsePublicURL(metadata.PresentationDefinitionEndpoint, r.strictMode)
+ if err != nil {
+ return nil, err
+ }
+ pdURL := nutsHttp.AddQueryParams(*parsedURL, map[string]string{
+ "scope": scope,
+ })
+ pd, err := r.httpClient.PresentationDefinition(ctx, pdURL)
+ if err != nil {
+ return nil, err
+ }
+ return &ResolvedPresentationDefinition{
+ PresentationDefinition: *pd,
+ Scope: scope,
+ }, nil
+}
+
+func (r *PresentationDefinitionResolver) resolveLocal(ctx context.Context, scope string) (*ResolvedPresentationDefinition, error) {
+ if r.policyBackend == nil {
+ return nil, fmt.Errorf("local PD resolution requires a policy backend, but none is configured")
+ }
+ match, err := r.policyBackend.FindCredentialProfile(ctx, scope)
+ if err != nil {
+ return nil, fmt.Errorf("local PD resolution failed: %w", err)
+ }
+ if match.ScopePolicy == policy.ScopePolicyProfileOnly && len(match.OtherScopes) > 0 {
+ return nil, oauth.OAuth2Error{
+ Code: oauth.InvalidScope,
+ Description: "scope policy 'profile-only' does not allow additional scopes",
+ }
+ }
+ // Select the organization PD (default for current single-VP flow).
+ // TODO: When #4080 adds two-VP support, this resolver will need to return multiple PDs.
+ pd, ok := match.WalletOwnerMapping[pe.WalletOwnerOrganization]
+ if !ok {
+ return nil, fmt.Errorf("no organization presentation definition for scope %q", match.CredentialProfileScope)
+ }
+ // For passthrough and dynamic, forward all scopes to the remote AS.
+ // The client does not evaluate dynamic scopes — the server handles PDP evaluation at token-grant time (PR #4179).
+ resolvedScope := scope
+ if match.ScopePolicy == policy.ScopePolicyProfileOnly {
+ resolvedScope = match.CredentialProfileScope
+ }
+ return &ResolvedPresentationDefinition{
+ PresentationDefinition: pd,
+ Scope: resolvedScope,
+ }, nil
+}
diff --git a/auth/client/iam/pd_resolver_test.go b/auth/client/iam/pd_resolver_test.go
new file mode 100644
index 000000000..5f7c6255e
--- /dev/null
+++ b/auth/client/iam/pd_resolver_test.go
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2026 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package iam
+
+import (
+ "context"
+ "encoding/json"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+ "time"
+
+ "github.com/nuts-foundation/nuts-node/auth/oauth"
+ "github.com/nuts-foundation/nuts-node/http/client"
+ "github.com/nuts-foundation/nuts-node/policy"
+ "github.com/nuts-foundation/nuts-node/vcr/pe"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
+)
+
+var testPD = pe.PresentationDefinition{
+ Id: "test-pd",
+ InputDescriptors: []*pe.InputDescriptor{
+ {Id: "id1"},
+ },
+}
+
+func TestPresentationDefinitionResolver_Resolve(t *testing.T) {
+ t.Run("remote PD endpoint exists - fetches from remote and returns full scope", func(t *testing.T) {
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, "/presentation_definition", r.URL.Path)
+ assert.Equal(t, "profile-scope extra-scope", r.URL.Query().Get("scope"))
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(testPD)
+ }))
+ defer server.Close()
+
+ resolver := &PresentationDefinitionResolver{
+ httpClient: HTTPClient{
+ strictMode: false,
+ httpClient: client.New(10 * time.Second),
+ },
+ }
+ metadata := oauth.AuthorizationServerMetadata{
+ PresentationDefinitionEndpoint: server.URL + "/presentation_definition",
+ }
+
+ result, err := resolver.Resolve(context.Background(), "profile-scope extra-scope", metadata)
+
+ require.NoError(t, err)
+ assert.Equal(t, "test-pd", result.PresentationDefinition.Id)
+ assert.Equal(t, "profile-scope extra-scope", result.Scope)
+ })
+ t.Run("no remote PD endpoint", func(t *testing.T) {
+ metadata := oauth.AuthorizationServerMetadata{} // no PD endpoint
+
+ t.Run("single scope, profile-only", func(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockPolicy := policy.NewMockPDPBackend(ctrl)
+ mockPolicy.EXPECT().FindCredentialProfile(gomock.Any(), "profile-scope").Return(&policy.CredentialProfileMatch{
+ CredentialProfileScope: "profile-scope",
+ WalletOwnerMapping: pe.WalletOwnerMapping{pe.WalletOwnerOrganization: testPD},
+ ScopePolicy: policy.ScopePolicyProfileOnly,
+ }, nil)
+
+ resolver := &PresentationDefinitionResolver{policyBackend: mockPolicy}
+ result, err := resolver.Resolve(context.Background(), "profile-scope", metadata)
+
+ require.NoError(t, err)
+ assert.Equal(t, "test-pd", result.PresentationDefinition.Id)
+ assert.Equal(t, "profile-scope", result.Scope)
+ })
+ t.Run("multi-scope, profile-only rejects", func(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockPolicy := policy.NewMockPDPBackend(ctrl)
+ mockPolicy.EXPECT().FindCredentialProfile(gomock.Any(), "profile-scope extra-scope").Return(&policy.CredentialProfileMatch{
+ CredentialProfileScope: "profile-scope",
+ OtherScopes: []string{"extra-scope"},
+ WalletOwnerMapping: pe.WalletOwnerMapping{pe.WalletOwnerOrganization: testPD},
+ ScopePolicy: policy.ScopePolicyProfileOnly,
+ }, nil)
+
+ resolver := &PresentationDefinitionResolver{policyBackend: mockPolicy}
+ _, err := resolver.Resolve(context.Background(), "profile-scope extra-scope", metadata)
+
+ assert.ErrorContains(t, err, "does not allow additional scopes")
+ })
+ t.Run("multi-scope, passthrough forwards all scopes", func(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockPolicy := policy.NewMockPDPBackend(ctrl)
+ mockPolicy.EXPECT().FindCredentialProfile(gomock.Any(), "profile-scope extra-scope").Return(&policy.CredentialProfileMatch{
+ CredentialProfileScope: "profile-scope",
+ OtherScopes: []string{"extra-scope"},
+ WalletOwnerMapping: pe.WalletOwnerMapping{pe.WalletOwnerOrganization: testPD},
+ ScopePolicy: policy.ScopePolicyPassthrough,
+ }, nil)
+
+ resolver := &PresentationDefinitionResolver{policyBackend: mockPolicy}
+ result, err := resolver.Resolve(context.Background(), "profile-scope extra-scope", metadata)
+
+ require.NoError(t, err)
+ assert.Equal(t, "test-pd", result.PresentationDefinition.Id)
+ assert.Equal(t, "profile-scope extra-scope", result.Scope)
+ })
+ t.Run("multi-scope, dynamic forwards all scopes", func(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockPolicy := policy.NewMockPDPBackend(ctrl)
+ mockPolicy.EXPECT().FindCredentialProfile(gomock.Any(), "profile-scope extra-scope").Return(&policy.CredentialProfileMatch{
+ CredentialProfileScope: "profile-scope",
+ OtherScopes: []string{"extra-scope"},
+ WalletOwnerMapping: pe.WalletOwnerMapping{pe.WalletOwnerOrganization: testPD},
+ ScopePolicy: policy.ScopePolicyDynamic,
+ }, nil)
+
+ resolver := &PresentationDefinitionResolver{policyBackend: mockPolicy}
+ result, err := resolver.Resolve(context.Background(), "profile-scope extra-scope", metadata)
+
+ require.NoError(t, err)
+ assert.Equal(t, "profile-scope extra-scope", result.Scope)
+ })
+ t.Run("unknown scope returns error", func(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockPolicy := policy.NewMockPDPBackend(ctrl)
+ mockPolicy.EXPECT().FindCredentialProfile(gomock.Any(), "unknown").Return(nil, policy.ErrNotFound)
+
+ resolver := &PresentationDefinitionResolver{policyBackend: mockPolicy}
+ _, err := resolver.Resolve(context.Background(), "unknown", metadata)
+
+ assert.ErrorIs(t, err, policy.ErrNotFound)
+ })
+ t.Run("no organization PD in wallet owner mapping returns error", func(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockPolicy := policy.NewMockPDPBackend(ctrl)
+ mockPolicy.EXPECT().FindCredentialProfile(gomock.Any(), "user-only-scope").Return(&policy.CredentialProfileMatch{
+ CredentialProfileScope: "user-only-scope",
+ WalletOwnerMapping: pe.WalletOwnerMapping{pe.WalletOwnerUser: testPD},
+ ScopePolicy: policy.ScopePolicyProfileOnly,
+ }, nil)
+
+ resolver := &PresentationDefinitionResolver{policyBackend: mockPolicy}
+ _, err := resolver.Resolve(context.Background(), "user-only-scope", metadata)
+
+ assert.ErrorContains(t, err, "no organization presentation definition")
+ })
+ t.Run("nil policy backend returns error", func(t *testing.T) {
+ resolver := &PresentationDefinitionResolver{policyBackend: nil}
+ _, err := resolver.Resolve(context.Background(), "any-scope", metadata)
+
+ assert.ErrorContains(t, err, "policy backend")
+ })
+ })
+ t.Run("remote PD endpoint returns error", func(t *testing.T) {
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusInternalServerError)
+ }))
+ defer server.Close()
+
+ resolver := &PresentationDefinitionResolver{
+ httpClient: HTTPClient{
+ strictMode: false,
+ httpClient: client.New(10 * time.Second),
+ },
+ }
+ metadata := oauth.AuthorizationServerMetadata{
+ PresentationDefinitionEndpoint: server.URL + "/presentation_definition",
+ }
+
+ _, err := resolver.Resolve(context.Background(), "scope", metadata)
+
+ assert.Error(t, err)
+ })
+}
diff --git a/auth/test.go b/auth/test.go
index 4142046cd..cd1940af3 100644
--- a/auth/test.go
+++ b/auth/test.go
@@ -44,5 +44,5 @@ func testInstance(t *testing.T, cfg Config) *Auth {
vdrInstance := vdr.NewMockVDR(ctrl)
vdrInstance.EXPECT().Resolver().AnyTimes()
subjectManager := didsubject.NewMockManager(ctrl)
- return NewAuthInstance(cfg, vdrInstance, subjectManager, vcrInstance, cryptoInstance, nil, nil, pkiMock)
+ return NewAuthInstance(cfg, vdrInstance, subjectManager, vcrInstance, cryptoInstance, nil, nil, pkiMock, nil)
}
diff --git a/cmd/root.go b/cmd/root.go
index b2737c9b3..4cce7e287 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -201,11 +201,11 @@ func CreateSystem(shutdownCallback context.CancelFunc) *core.System {
credentialInstance := vcr.NewVCRInstance(cryptoInstance, vdrInstance, networkInstance, jsonld, eventManager, storageInstance, pkiInstance)
didmanInstance := didman.NewDidmanInstance(vdrInstance, credentialInstance, jsonld)
discoveryInstance := discovery.New(storageInstance, credentialInstance, vdrInstance, vdrInstance)
- authInstance := auth.NewAuthInstance(auth.DefaultConfig(), vdrInstance, vdrInstance, credentialInstance, cryptoInstance, didmanInstance, jsonld, pkiInstance)
+ policyInstance := policy.New()
+ authInstance := auth.NewAuthInstance(auth.DefaultConfig(), vdrInstance, vdrInstance, credentialInstance, cryptoInstance, didmanInstance, jsonld, pkiInstance, policyInstance)
statusEngine := status.NewStatusEngine(system)
metricsEngine := core.NewMetricsEngine()
goldenHammer := golden_hammer.New(vdrInstance, didmanInstance)
- policyInstance := policy.New()
// Register HTTP routes
didKeyResolver := resolver.DIDKeyResolver{Resolver: vdrInstance.Resolver()}