diff --git a/docs/pages/deployment/migration.rst b/docs/pages/deployment/migration.rst index a5f164886..6734b695d 100644 --- a/docs/pages/deployment/migration.rst +++ b/docs/pages/deployment/migration.rst @@ -7,7 +7,7 @@ Nuts node v6 runs several migrations on startup for DID documents that are manag 1. Remove controllers and add self-control to ``did:nuts`` documents, 2. Import ``did:nuts`` documents into the new SQL database under a ``subject`` with the same name, and -3. Add a ``did:web`` document with the same services to the same ``subject``. +3. Add a ``did:web`` document to the same ``subject``. **Migration: convert did:nuts to self-control** Requires ``didmethods`` to contain ``nuts``. @@ -34,6 +34,5 @@ See ``/status/diagnostics`` if you own any DIDs with a document conflict. If so, Requires ``didmethods`` to contain ``web`` and ``nuts`` (default). This migration adds a new ``did:web`` DID Document to owned subjects that do not already have one. -All services from the ``did:nuts`` DID Document are copied to the new document. A new verification method is created for the document and added to all verification relationships except KeyAgreement. This means did:web cannot be used for encryption (yet). diff --git a/docs/pages/integrating/version-incompatibilities.rst b/docs/pages/integrating/version-incompatibilities.rst index 6ab7371be..23e167f96 100644 --- a/docs/pages/integrating/version-incompatibilities.rst +++ b/docs/pages/integrating/version-incompatibilities.rst @@ -16,3 +16,18 @@ There are basically two options. Do not use the VDR V1 and VDR V2 API at the same time. This will lead to unexpected behavior. Once you use the VDR V2 API, you cannot go back to the VDR V1 API. The VDR V1 API has also been marked as deprecated. + +Publishing Services for use-cases +********************************* + +V5 use-cases define service endpoints or a collection of endpoints that should be registered in the Services on DID Documents. +The concrete endpoints are usually on the DID Document of the vendor, and then referenced by all DID Documents managed by that vendor. +And ``did:nuts`` for example, requires the registration of a ``NutsComm`` endpoint to authenticate the connection. +Use-cases built on V5 should keep using the DIDMan API to manage and resolve Services on DID Documents. +Any Service change made using the DIDMan API will only update ``did:nuts`` DID Documents. + +For use-cases built on V6, any endpoint needed for the use-case should be listed in the registration on the Discovery Service for that use-case, see :ref:`discovery` Registration. +This means that ``did:web`` DID Documents (or non-did:nuts if we look further ahead) will contain very few Services, if any. +If there is a need to add a Service for V6 use-cases, they should be added using the VDR v2 API, which will then add the Service to _all_ DIDs that are part of the Subject. +Note that resolving Services using the VDR v2 API will return the Service from the document as is. +So, it resolves Services without following any references in the Service to a concrete endpoint as is done by DIDMan. \ No newline at end of file diff --git a/docs/pages/release_notes.rst b/docs/pages/release_notes.rst index 240e6d677..3d6eb939e 100644 --- a/docs/pages/release_notes.rst +++ b/docs/pages/release_notes.rst @@ -19,6 +19,7 @@ Breaking changes - The VDR v1 ``createDID`` (``POST /internal/vdr/v1/did``) no longer supports the ``controller`` and ``selfControl`` fields. All did:nuts documents are now self controlled. All existing documents will be migrated to self controlled at startup. - Managed ``did:nuts`` DIDs are migrated to the new SQL storage. Unresolved DID document conflicts may contain an incorrect state after migrating to v6. See ``/status/diagnostics`` if you own any DIDs with a document conflict; use ``/internal/vdr/v1/did/conflicted`` to find the specific DIDs. - Removed legacy API authentication tokens. +- See caveats in :ref:`version-incompatibilities`. ============ New Features @@ -52,7 +53,7 @@ Changes - Removed support for the UZI authentication means. - Documentation of ``did:nuts``-related features have been removed (refer to v5 documentation). - Documentation of specific use cases (e.g. health care in general or eOverdracht) has been moved to the `Nuts wiki `_. -- Node can now be run without configuring TLS when the gRPC network isn't used (no bootstrap node configured and no network state), to cater use cases that don't use ``did:nuts``. +- Node can now be run without configuring TLS when the gRPC network isn't used (``didmethods`` does not contain ``nuts``), to cater use cases that don't use ``did:nuts``. - Crypto backends store keys under a key name and are linked to the kid via the ``key_reference`` SQL table. The following features have also been changed: @@ -63,7 +64,7 @@ DID management You no longer manage changes to DIDs but to Subjects. Each subject has multiple DIDs, one for each enabled DID method. You're free to choose an ID for a Subject. This feature enables forwards compatibility with new DID methods. DID methods can be enabled and disabled via the ``didmethods`` config parameter. (Default: ``['web','nuts']``). -Existing ``did:nuts`` documents will be migrated to self-controlled at startup and the DID will be added as SubjectID. +Existing ``did:nuts`` documents will be migrated to self-controlled at startup and the DID will be added as SubjectID together with a new ``did:web`` DID. See :ref:`nuts-node-migrations` for more information. HTTP interface diff --git a/e2e-tests/migration/main_test.go b/e2e-tests/migration/main_test.go index 7532897ec..2875d63dd 100644 --- a/e2e-tests/migration/main_test.go +++ b/e2e-tests/migration/main_test.go @@ -47,7 +47,7 @@ func Test_Migrations(t *testing.T) { DIDs, err := man.DID.All() require.NoError(t, err) - require.Len(t, DIDs, 4) // 4 did:nuts, 3 did:web + require.Len(t, DIDs, 7) // 4 did:nuts, 3 did:web t.Run("vendor", func(t *testing.T) { // versions for did:nuts: @@ -67,7 +67,7 @@ func Test_Migrations(t *testing.T) { assert.Len(t, doc.VerificationMethods, 2) // migration: add did:web - EqualServices(t, man, doc) + hasDIDWeb(t, man, doc) }) t.Run("org1", func(t *testing.T) { // versions for did:nuts: @@ -89,7 +89,7 @@ func Test_Migrations(t *testing.T) { assert.Empty(t, didDoc.Controller) // migration: add did:web - EqualServices(t, man, doc) + hasDIDWeb(t, man, doc) }) t.Run("org2", func(t *testing.T) { // versions for did:nuts: @@ -133,14 +133,11 @@ func Test_Migrations(t *testing.T) { assert.Empty(t, didDoc.Controller) // migration: add did:web - EqualServices(t, man, doc) + hasDIDWeb(t, man, doc) }) } -func EqualServices(t *testing.T, man *manager, nutsDoc *orm.DidDocument) { - return // disable until there is a fix for https://github.com/nuts-foundation/nuts-node/issues/3444 - didWebPrefix := "did:web:nodeA%3A8080" - +func hasDIDWeb(t *testing.T, man *manager, nutsDoc *orm.DidDocument) { dids, err := man.DID.FindBySubject(nutsDoc.DID.Subject) // migrated documents have subject == did:nuts:... require.NoError(t, err) assert.Len(t, dids, 2) @@ -152,8 +149,4 @@ func EqualServices(t *testing.T, man *manager, nutsDoc *orm.DidDocument) { } } assert.Equal(t, 0, webDoc.Version) - assert.Equal(t, len(nutsDoc.Services), len(webDoc.Services)) - for _, service := range webDoc.Services { - assert.True(t, strings.HasPrefix(service.ID, didWebPrefix)) - } } diff --git a/vdr/didsubject/manager.go b/vdr/didsubject/manager.go index a74825a00..2ece1f276 100644 --- a/vdr/didsubject/manager.go +++ b/vdr/didsubject/manager.go @@ -769,26 +769,8 @@ func (r *SqlManager) MigrateAddWebToNuts(ctx context.Context, id did.DID) error ID: webDoc.DID.ID, Subject: subject, } - // rename services. only the DID part of the service.ID needs to be updates - webDoc.Services = make([]orm.Service, len(nutsDoc.Services)) - for i, ormService := range nutsDoc.Services { - service := new(did.Service) - err = json.Unmarshal(ormService.Data, service) - if err != nil { - return err - } - service.ID = ssi.MustParseURI(webDID.ID + "#" + service.ID.Fragment) - rawService, err := json.Marshal(service) - if err != nil { - return err - } - webDoc.Services[i] = orm.Service{ - ID: service.ID.String(), - Data: rawService, - } - } - // store did:web - _, err = sqlDIDDocumentManager.CreateOrUpdate(webDID, webDoc.VerificationMethods, webDoc.Services) + // store did:web; don't migrate services + _, err = sqlDIDDocumentManager.CreateOrUpdate(webDID, webDoc.VerificationMethods, nil) if err != nil { return err } diff --git a/vdr/didsubject/manager_test.go b/vdr/didsubject/manager_test.go index 4e85f92c4..526980bce 100644 --- a/vdr/didsubject/manager_test.go +++ b/vdr/didsubject/manager_test.go @@ -627,12 +627,10 @@ func TestSqlManager_MigrateAddWebToNuts(t *testing.T) { assert.Equal(t, didNuts.String(), dids[0].ID) assert.Equal(t, didWeb.String(), dids[1].ID) - docNuts, err := NewDIDDocumentManager(db).Latest(didNuts, nil) require.NoError(t, err) docWeb, err := NewDIDDocumentManager(db).Latest(didWeb, nil) require.NoError(t, err) - assert.Equal(t, len(docNuts.Services), len(docWeb.Services)) - assert.Equal(t, didWeb.String()+"#service-1", docWeb.Services[0].ID) + assert.Len(t, docWeb.Services, 0) }) t.Run("ok - already has did:web", func(t *testing.T) { db := testDB(t) diff --git a/vdr/vdr.go b/vdr/vdr.go index cff3e50f6..0672bf339 100644 --- a/vdr/vdr.go +++ b/vdr/vdr.go @@ -392,8 +392,7 @@ func (r *Module) allMigrations() []migration { return []migration{ // key will be printed as description of the migration {r.migrateRemoveControllerFromDIDNuts, "remove controller"}, // must come before migrateHistoryOwnedDIDNuts so controller removal is also migrated. {r.migrateHistoryOwnedDIDNuts, "document history"}, - // Disable migration until we have a fix for: https://github.com/nuts-foundation/nuts-node/issues/3444 - //{r.migrateAddDIDWebToOwnedDIDNuts, "add did:web to subject"}, // must come after migrateHistoryOwnedDIDNuts since it acts on the SQL store. + {r.migrateAddDIDWebToOwnedDIDNuts, "add did:web to subject"}, // must come after migrateHistoryOwnedDIDNuts since it acts on the SQL store. } } diff --git a/vdr/vdr_test.go b/vdr/vdr_test.go index 2eebeb9b5..1c57bdc8f 100644 --- a/vdr/vdr_test.go +++ b/vdr/vdr_test.go @@ -348,7 +348,7 @@ func TestVDR_Migrate(t *testing.T) { ctx.mockDocumentOwner.EXPECT().ListOwned(gomock.Any()).Return([]did.DID{testDIDWeb}, nil) err := ctx.vdr.Migrate() assert.NoError(t, err) - assert.Len(t, ctx.vdr.migrations, 2) // confirm its running allMigrations() that currently is only did:nuts + assert.Len(t, ctx.vdr.migrations, 3) // confirm its running allMigrations() that currently is only did:nuts }) t.Run("controller migration", func(t *testing.T) { controllerMigrationSetup := func(t *testing.T) vdrTestCtx {