oydid 0.8.2 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/oydid.rb +70 -13
- data/spec/output/main/sample0_read.doc +1 -1
- data/spec/oydid_spec.rb +135 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d3e561caa744ec1b341317d142b27f5b9d7d9dddf92b2d18aaf2117fff05cb9a
|
|
4
|
+
data.tar.gz: 6aa242687b1765148f79e9b6911d22e81339159f2f0c45445c0be1ce804fe0ad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35d735d7f16edf812645b91034b5c8824437144fb86b2dba19e2b165a1912279fc3e6b09916cde37004402bb309f5faad7248105b41de07f293892f7e6963d09
|
|
7
|
+
data.tar.gz: 0e333ede2a2b46e9c6264264f638cf3b54823cab9663a11af3bf776f796965210abb39b3c37555d0824f67d9b55506d3065803b1a94182097acdf0b11b9c670e
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.9.0
|
data/lib/oydid.rb
CHANGED
|
@@ -68,8 +68,15 @@ class Oydid
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
# setup
|
|
71
|
+
#
|
|
72
|
+
# did_requested is the identifier the caller asked for. dag_update
|
|
73
|
+
# overwrites "did" with every version it walks through, so by the time a
|
|
74
|
+
# DID document is rendered the requested identifier would be lost - and
|
|
75
|
+
# after an update that is exactly the one a relying party holds, e.g.
|
|
76
|
+
# printed on a product's data carrier.
|
|
71
77
|
currentDID = {
|
|
72
78
|
"did": did,
|
|
79
|
+
"did_requested": did,
|
|
73
80
|
"doc": "",
|
|
74
81
|
"log": [],
|
|
75
82
|
"doc_log_id": nil,
|
|
@@ -1426,6 +1433,61 @@ class Oydid
|
|
|
1426
1433
|
wd
|
|
1427
1434
|
end
|
|
1428
1435
|
|
|
1436
|
+
# Identifiers of every published version of a DID, oldest first.
|
|
1437
|
+
#
|
|
1438
|
+
# A did:oyd is the hash over its own DID document, so every update mints a
|
|
1439
|
+
# new identifier while the earlier ones stay resolvable through the log.
|
|
1440
|
+
# The version reached by traversing the log is the canonical identifier,
|
|
1441
|
+
# every other version identifier is logically equivalent to it - which is
|
|
1442
|
+
# what DID Core expresses as didDocumentMetadata canonicalId/equivalentId.
|
|
1443
|
+
#
|
|
1444
|
+
# This lives in the gem rather than in the resolving controllers because
|
|
1445
|
+
# there are three of them (repository resolve and resolve_full, plus the
|
|
1446
|
+
# uniresolver plugin) and they had drifted into computing this list with
|
|
1447
|
+
# different rules.
|
|
1448
|
+
#
|
|
1449
|
+
# Returns [canonicalId, equivalentIds]; equivalentIds never contains the
|
|
1450
|
+
# identifier the DID document itself carries as `id` (see document_id).
|
|
1451
|
+
def self.version_ids(did_info)
|
|
1452
|
+
canonical = percent_encode(did_info["did"].to_s)
|
|
1453
|
+
if !canonical.start_with?("did:oyd:")
|
|
1454
|
+
canonical = "did:oyd:" + canonical
|
|
1455
|
+
end
|
|
1456
|
+
own = document_id(did_info)
|
|
1457
|
+
equivalentIds = []
|
|
1458
|
+
did_info["log"].each do |log|
|
|
1459
|
+
if log["op"] == 2 || log["op"] == 3
|
|
1460
|
+
eid = percent_encode("did:oyd:" + log["doc"].to_s)
|
|
1461
|
+
if eid != own
|
|
1462
|
+
equivalentIds << eid
|
|
1463
|
+
end
|
|
1464
|
+
end
|
|
1465
|
+
end unless did_info["log"].nil?
|
|
1466
|
+
[canonical, equivalentIds]
|
|
1467
|
+
end
|
|
1468
|
+
|
|
1469
|
+
# The identifier a resolved DID document carries as `id`.
|
|
1470
|
+
#
|
|
1471
|
+
# A did:oyd is the hash over its own document, so an update mints a new one
|
|
1472
|
+
# and the resolution walks the log to the newest version. Answering with that
|
|
1473
|
+
# newest identifier means a relying party never sees the DID it asked for -
|
|
1474
|
+
# the one on the data carrier, in the credential, in the database. So the
|
|
1475
|
+
# requested identifier is what goes into the document; which version it is
|
|
1476
|
+
# remains readable from didDocumentMetadata canonicalId.
|
|
1477
|
+
#
|
|
1478
|
+
# Callers that build a did_info by hand - the registrar endpoints do, for a
|
|
1479
|
+
# DID that was just created or updated - carry no did_requested and keep
|
|
1480
|
+
# getting the identifier they passed in.
|
|
1481
|
+
def self.document_id(did_info)
|
|
1482
|
+
did = did_info["did_requested"].to_s
|
|
1483
|
+
did = did_info["did"].to_s if did == ""
|
|
1484
|
+
did = percent_encode(did)
|
|
1485
|
+
if !did.start_with?("did:oyd:")
|
|
1486
|
+
did = "did:oyd:" + did
|
|
1487
|
+
end
|
|
1488
|
+
did
|
|
1489
|
+
end
|
|
1490
|
+
|
|
1429
1491
|
def self.w3c(did_info, options)
|
|
1430
1492
|
# check if doc is already W3C DID
|
|
1431
1493
|
is_already_w3c_did = (did_info.transform_keys(&:to_s)["doc"]["doc"].has_key?("@context") &&
|
|
@@ -1434,10 +1496,7 @@ class Oydid
|
|
|
1434
1496
|
if is_already_w3c_did
|
|
1435
1497
|
return did_info.transform_keys(&:to_s)["doc"]["doc"]
|
|
1436
1498
|
end
|
|
1437
|
-
did =
|
|
1438
|
-
if !did.start_with?("did:oyd:")
|
|
1439
|
-
did = "did:oyd:" + did
|
|
1440
|
-
end
|
|
1499
|
+
did = document_id(did_info)
|
|
1441
1500
|
|
|
1442
1501
|
didDoc = did_info.dup.transform_keys(&:to_s)["doc"]
|
|
1443
1502
|
pubDocKey = didDoc["key"].split(":")[0] rescue ""
|
|
@@ -1568,15 +1627,13 @@ class Oydid
|
|
|
1568
1627
|
end
|
|
1569
1628
|
end
|
|
1570
1629
|
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
end
|
|
1579
|
-
end unless did_info["log"].nil?
|
|
1630
|
+
# alsoKnownAs is a statement about the DID *subject*, and DID Core calls
|
|
1631
|
+
# it best practice not to read it as equivalence unless the relationship
|
|
1632
|
+
# is reciprocated - which it cannot be here, because all versions resolve
|
|
1633
|
+
# to the same document. It stays for backwards compatibility; the
|
|
1634
|
+
# authoritative statement is didDocumentMetadata canonicalId/equivalentId,
|
|
1635
|
+
# built from the same list.
|
|
1636
|
+
equivalentIds = version_ids(did_info).last
|
|
1580
1637
|
if equivalentIds.length > 0
|
|
1581
1638
|
wd["alsoKnownAs"] = equivalentIds
|
|
1582
1639
|
end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"did":"zQmaBZTghndXTgxNwfbdpVLWdFf6faYE4oeuN2zzXdQt1kh","doc":{"doc":{"simple":"example"},"key":"z6MusYB5iT5krCHYsZ76EzBaTdRwGKsaBhMcSbrXaPJgkuRQ:z6Mv7EYihbAat6Wq7GsjNsjcxt58dZT8fmsRjQGTkYamYrjB","log":"zQmVwMvovLy5KNYHHVHQ1wv8J7y9L6UPE8eyU4tzypFWtYe"},"log":[{"ts":1641224736,"op":2,"doc":"zQmaBZTghndXTgxNwfbdpVLWdFf6faYE4oeuN2zzXdQt1kh","sig":"z3Kb5qeReCqr3ftxpf2i5UypUwrzrVkyspMtaDcb6e9YdHVSptcAFgvwbgk3qWqspTcGiKDYKXZZh8g6XyM2WPmNp","previous":[]},{"ts":1641224736,"op":0,"doc":"zQmT8SG7a238bF7wdV7LdrEAQpimqhKGor7CQsjtCYdZdTS","sig":"z63hu8LseptBrvB2kEDwhPP35sBj7JDDJsEDW85cjRkrjjac9ZV3HxPW9NVKewHcQYwrVLVsnDCcm1RjbEARE5rJU","previous":[]}],"doc_log_id":0,"termination_log_id":1,"error":0,"message":"","verification":"identifier: zQmaBZTghndXTgxNwfbdpVLWdFf6faYE4oeuN2zzXdQt1kh\n✅ is hash of DID Document:\n{\n \"doc\": {\n \"simple\": \"example\"\n },\n \"key\": \"z6MusYB5iT5krCHYsZ76EzBaTdRwGKsaBhMcSbrXaPJgkuRQ:z6Mv7EYihbAat6Wq7GsjNsjcxt58dZT8fmsRjQGTkYamYrjB\",\n \"log\": \"zQmVwMvovLy5KNYHHVHQ1wv8J7y9L6UPE8eyU4tzypFWtYe\"\n}\n(Details: https://ownyourdata.github.io/oydid/#calculate_hash)\n\n'log' reference in DID Document: zQmVwMvovLy5KNYHHVHQ1wv8J7y9L6UPE8eyU4tzypFWtYe\n✅ is hash of TERMINATE log record:\n{\n \"ts\": 1641224736,\n \"op\": 0,\n \"doc\": \"zQmT8SG7a238bF7wdV7LdrEAQpimqhKGor7CQsjtCYdZdTS\",\n \"sig\": \"z63hu8LseptBrvB2kEDwhPP35sBj7JDDJsEDW85cjRkrjjac9ZV3HxPW9NVKewHcQYwrVLVsnDCcm1RjbEARE5rJU\",\n \"previous\": []\n}\n(Details: https://ownyourdata.github.io/oydid/#calculate_hash)\n\nRevocation reference in log record: zQmT8SG7a238bF7wdV7LdrEAQpimqhKGor7CQsjtCYdZdTS\n✅ cannot find revocation record searching at\n- https://oydid.ownyourdata.eu\n(Details: https://ownyourdata.github.io/oydid/#retrieve_log)\n\n","full_log":[{"ts":1641224736,"op":2,"doc":"zQmaBZTghndXTgxNwfbdpVLWdFf6faYE4oeuN2zzXdQt1kh","sig":"z3Kb5qeReCqr3ftxpf2i5UypUwrzrVkyspMtaDcb6e9YdHVSptcAFgvwbgk3qWqspTcGiKDYKXZZh8g6XyM2WPmNp","previous":[]},{"ts":1641224736,"op":0,"doc":"zQmT8SG7a238bF7wdV7LdrEAQpimqhKGor7CQsjtCYdZdTS","sig":"z63hu8LseptBrvB2kEDwhPP35sBj7JDDJsEDW85cjRkrjjac9ZV3HxPW9NVKewHcQYwrVLVsnDCcm1RjbEARE5rJU","previous":[]}]},""]
|
|
1
|
+
[{"did":"zQmaBZTghndXTgxNwfbdpVLWdFf6faYE4oeuN2zzXdQt1kh","did_requested":"did:oyd:zQmaBZTghndXTgxNwfbdpVLWdFf6faYE4oeuN2zzXdQt1kh","doc":{"doc":{"simple":"example"},"key":"z6MusYB5iT5krCHYsZ76EzBaTdRwGKsaBhMcSbrXaPJgkuRQ:z6Mv7EYihbAat6Wq7GsjNsjcxt58dZT8fmsRjQGTkYamYrjB","log":"zQmVwMvovLy5KNYHHVHQ1wv8J7y9L6UPE8eyU4tzypFWtYe"},"log":[{"ts":1641224736,"op":2,"doc":"zQmaBZTghndXTgxNwfbdpVLWdFf6faYE4oeuN2zzXdQt1kh","sig":"z3Kb5qeReCqr3ftxpf2i5UypUwrzrVkyspMtaDcb6e9YdHVSptcAFgvwbgk3qWqspTcGiKDYKXZZh8g6XyM2WPmNp","previous":[]},{"ts":1641224736,"op":0,"doc":"zQmT8SG7a238bF7wdV7LdrEAQpimqhKGor7CQsjtCYdZdTS","sig":"z63hu8LseptBrvB2kEDwhPP35sBj7JDDJsEDW85cjRkrjjac9ZV3HxPW9NVKewHcQYwrVLVsnDCcm1RjbEARE5rJU","previous":[]}],"doc_log_id":0,"termination_log_id":1,"error":0,"message":"","verification":"identifier: zQmaBZTghndXTgxNwfbdpVLWdFf6faYE4oeuN2zzXdQt1kh\n✅ is hash of DID Document:\n{\n \"doc\": {\n \"simple\": \"example\"\n },\n \"key\": \"z6MusYB5iT5krCHYsZ76EzBaTdRwGKsaBhMcSbrXaPJgkuRQ:z6Mv7EYihbAat6Wq7GsjNsjcxt58dZT8fmsRjQGTkYamYrjB\",\n \"log\": \"zQmVwMvovLy5KNYHHVHQ1wv8J7y9L6UPE8eyU4tzypFWtYe\"\n}\n(Details: https://ownyourdata.github.io/oydid/#calculate_hash)\n\n'log' reference in DID Document: zQmVwMvovLy5KNYHHVHQ1wv8J7y9L6UPE8eyU4tzypFWtYe\n✅ is hash of TERMINATE log record:\n{\n \"ts\": 1641224736,\n \"op\": 0,\n \"doc\": \"zQmT8SG7a238bF7wdV7LdrEAQpimqhKGor7CQsjtCYdZdTS\",\n \"sig\": \"z63hu8LseptBrvB2kEDwhPP35sBj7JDDJsEDW85cjRkrjjac9ZV3HxPW9NVKewHcQYwrVLVsnDCcm1RjbEARE5rJU\",\n \"previous\": []\n}\n(Details: https://ownyourdata.github.io/oydid/#calculate_hash)\n\nRevocation reference in log record: zQmT8SG7a238bF7wdV7LdrEAQpimqhKGor7CQsjtCYdZdTS\n✅ cannot find revocation record searching at\n- https://oydid.ownyourdata.eu\n(Details: https://ownyourdata.github.io/oydid/#retrieve_log)\n\n","full_log":[{"ts":1641224736,"op":2,"doc":"zQmaBZTghndXTgxNwfbdpVLWdFf6faYE4oeuN2zzXdQt1kh","sig":"z3Kb5qeReCqr3ftxpf2i5UypUwrzrVkyspMtaDcb6e9YdHVSptcAFgvwbgk3qWqspTcGiKDYKXZZh8g6XyM2WPmNp","previous":[]},{"ts":1641224736,"op":0,"doc":"zQmT8SG7a238bF7wdV7LdrEAQpimqhKGor7CQsjtCYdZdTS","sig":"z63hu8LseptBrvB2kEDwhPP35sBj7JDDJsEDW85cjRkrjjac9ZV3HxPW9NVKewHcQYwrVLVsnDCcm1RjbEARE5rJU","previous":[]}]},""]
|
data/spec/oydid_spec.rb
CHANGED
|
@@ -584,4 +584,139 @@ describe "OYDID handling" do
|
|
|
584
584
|
end
|
|
585
585
|
end
|
|
586
586
|
|
|
587
|
+
# Identifiers of the published versions of a DID. Every update mints a new
|
|
588
|
+
# one, so a resolver has to be able to say which is current and which are
|
|
589
|
+
# earlier - didDocumentMetadata canonicalId and equivalentId.
|
|
590
|
+
describe "version_ids" do
|
|
591
|
+
let(:first_did) { "zQmSE1hzumtZ7AoK1qhHf4t5kiKsujMsJSHqoXtWrdd7K7W" }
|
|
592
|
+
let(:second_did) { "zQmfEb3KgYZjZUPLTHPmFPdcV6peF5itB5NmJ9N6gaxxE8K" }
|
|
593
|
+
|
|
594
|
+
it "reports a freshly created DID as canonical without equivalents" do
|
|
595
|
+
canonical, equivalent = Oydid.version_ids(
|
|
596
|
+
"did" => "did:oyd:" + first_did,
|
|
597
|
+
"log" => [{ "op" => 2, "doc" => first_did },
|
|
598
|
+
{ "op" => 0, "doc" => "terminate" }])
|
|
599
|
+
expect(canonical).to eq "did:oyd:" + first_did
|
|
600
|
+
expect(equivalent).to eq []
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
it "names the current version canonical and the previous one equivalent" do
|
|
604
|
+
canonical, equivalent = Oydid.version_ids(
|
|
605
|
+
"did" => "did:oyd:" + second_did,
|
|
606
|
+
"log" => [{ "op" => 1, "doc" => "revoke" },
|
|
607
|
+
{ "op" => 2, "doc" => first_did },
|
|
608
|
+
{ "op" => 3, "doc" => second_did },
|
|
609
|
+
{ "op" => 0, "doc" => "terminate" }])
|
|
610
|
+
expect(canonical).to eq "did:oyd:" + second_did
|
|
611
|
+
expect(equivalent).to eq ["did:oyd:" + first_did]
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
it "keeps every earlier version, oldest first" do
|
|
615
|
+
canonical, equivalent = Oydid.version_ids(
|
|
616
|
+
"did" => "did:oyd:zC",
|
|
617
|
+
"log" => [{ "op" => 2, "doc" => "zA" },
|
|
618
|
+
{ "op" => 3, "doc" => "zB" },
|
|
619
|
+
{ "op" => 3, "doc" => "zC" }])
|
|
620
|
+
expect(canonical).to eq "did:oyd:zC"
|
|
621
|
+
expect(equivalent).to eq ["did:oyd:zA", "did:oyd:zB"]
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
it "adds the method prefix when the resolved DID carries none" do
|
|
625
|
+
canonical, = Oydid.version_ids("did" => second_did, "log" => [])
|
|
626
|
+
expect(canonical).to eq "did:oyd:" + second_did
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
it "percent-encodes a location suffix" do
|
|
630
|
+
canonical, equivalent = Oydid.version_ids(
|
|
631
|
+
"did" => "did:oyd:" + second_did + "@https://example.org",
|
|
632
|
+
"log" => [{ "op" => 2, "doc" => first_did + "@https://example.org" },
|
|
633
|
+
{ "op" => 3, "doc" => second_did + "@https://example.org" }])
|
|
634
|
+
expect(canonical).to eq "did:oyd:" + second_did + "%40example.org"
|
|
635
|
+
expect(equivalent).to eq ["did:oyd:" + first_did + "%40example.org"]
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
it "tolerates a missing log" do
|
|
639
|
+
canonical, equivalent = Oydid.version_ids("did" => "did:oyd:" + second_did)
|
|
640
|
+
expect(canonical).to eq "did:oyd:" + second_did
|
|
641
|
+
expect(equivalent).to eq []
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
# w3c builds alsoKnownAs from the same list. The two used to be computed
|
|
645
|
+
# separately in three places and drifted apart; this guards the merge.
|
|
646
|
+
#
|
|
647
|
+
# The canonical DID has to be one this suite stubs: w3c looks up delegation
|
|
648
|
+
# keys for it, and WebMock::NetConnectNotAllowedError descends from Exception
|
|
649
|
+
# rather than StandardError, so the inline `rescue []` around
|
|
650
|
+
# getDelegatedPubKeysFromDID does not catch it. Only the canonical DID is
|
|
651
|
+
# fetched - log entries are read, not resolved.
|
|
652
|
+
it "agrees with the alsoKnownAs the DID document carries" do
|
|
653
|
+
stubbed_did = "zQmaBZTghndXTgxNwfbdpVLWdFf6faYE4oeuN2zzXdQt1kh"
|
|
654
|
+
did_info = {
|
|
655
|
+
"did" => "did:oyd:" + stubbed_did,
|
|
656
|
+
"doc" => { "doc" => { "hello" => "world" },
|
|
657
|
+
"key" => "z6MktULudTtAsAhRegYPiZ6631RV3viv12qd4GQF8z1xB22S:" \
|
|
658
|
+
"z6MkqGC3nWZhYieEVTVDKW5v588CiGfsDSmRVG9ZwwWTvLSK" },
|
|
659
|
+
"log" => [{ "op" => 2, "doc" => first_did },
|
|
660
|
+
{ "op" => 3, "doc" => stubbed_did }]
|
|
661
|
+
}
|
|
662
|
+
wd = Oydid.w3c(Marshal.load(Marshal.dump(did_info)), {})
|
|
663
|
+
expect(wd["alsoKnownAs"]).to eq ["did:oyd:" + first_did]
|
|
664
|
+
expect(wd["alsoKnownAs"]).to eq Oydid.version_ids(did_info).last
|
|
665
|
+
end
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
# Which identifier a resolved DID document announces as its own. An update
|
|
669
|
+
# mints a new did:oyd, but the identifier a relying party holds is the one it
|
|
670
|
+
# asked for - that is the one the document has to carry.
|
|
671
|
+
describe "document_id" do
|
|
672
|
+
let(:first_did) { "zQmSE1hzumtZ7AoK1qhHf4t5kiKsujMsJSHqoXtWrdd7K7W" }
|
|
673
|
+
let(:second_did) { "zQmfEb3KgYZjZUPLTHPmFPdcV6peF5itB5NmJ9N6gaxxE8K" }
|
|
674
|
+
# a DID this suite stubs - w3c looks up delegation keys for whatever it
|
|
675
|
+
# emits as id, see the note on the alsoKnownAs example above
|
|
676
|
+
let(:stubbed_did) { "zQmaBZTghndXTgxNwfbdpVLWdFf6faYE4oeuN2zzXdQt1kh" }
|
|
677
|
+
|
|
678
|
+
it "answers with the requested DID when the resolver kept it" do
|
|
679
|
+
expect(Oydid.document_id("did" => "did:oyd:" + second_did,
|
|
680
|
+
"did_requested" => "did:oyd:" + first_did))
|
|
681
|
+
.to eq "did:oyd:" + first_did
|
|
682
|
+
end
|
|
683
|
+
|
|
684
|
+
it "falls back to the resolved DID for a did_info built by hand" do
|
|
685
|
+
expect(Oydid.document_id("did" => "did:oyd:" + second_did))
|
|
686
|
+
.to eq "did:oyd:" + second_did
|
|
687
|
+
end
|
|
688
|
+
|
|
689
|
+
it "adds the method prefix and percent-encodes a location suffix" do
|
|
690
|
+
expect(Oydid.document_id("did" => "", "did_requested" => first_did + "@https://example.org"))
|
|
691
|
+
.to eq "did:oyd:" + first_did + "%40example.org"
|
|
692
|
+
end
|
|
693
|
+
|
|
694
|
+
# the point of the exercise: a DID printed on a data carrier keeps naming
|
|
695
|
+
# itself after an update, while the current version stays readable
|
|
696
|
+
it "keeps the requested DID as id and moves the current one to alsoKnownAs" do
|
|
697
|
+
did_info = {
|
|
698
|
+
"did" => "did:oyd:" + second_did,
|
|
699
|
+
"did_requested" => "did:oyd:" + stubbed_did,
|
|
700
|
+
"doc" => { "doc" => { "hello" => "world" },
|
|
701
|
+
"key" => "z6MktULudTtAsAhRegYPiZ6631RV3viv12qd4GQF8z1xB22S:" \
|
|
702
|
+
"z6MkqGC3nWZhYieEVTVDKW5v588CiGfsDSmRVG9ZwwWTvLSK" },
|
|
703
|
+
"log" => [{ "op" => 2, "doc" => stubbed_did },
|
|
704
|
+
{ "op" => 3, "doc" => second_did }]
|
|
705
|
+
}
|
|
706
|
+
wd = Oydid.w3c(Marshal.load(Marshal.dump(did_info)), {})
|
|
707
|
+
expect(wd["id"]).to eq "did:oyd:" + stubbed_did
|
|
708
|
+
expect(wd["alsoKnownAs"]).to eq ["did:oyd:" + second_did]
|
|
709
|
+
# the entries of verificationMethod are built as hash literals with
|
|
710
|
+
# "id": - Ruby makes that a symbol key, the surrounding keys are strings
|
|
711
|
+
expect(wd["verificationMethod"].first[:id]).to start_with("did:oyd:" + stubbed_did + "#")
|
|
712
|
+
expect(wd["verificationMethod"].first[:controller]).to eq "did:oyd:" + stubbed_did
|
|
713
|
+
|
|
714
|
+
# canonicalId still names the version the log resolves to, and the
|
|
715
|
+
# equivalent list is everything the document does not call itself
|
|
716
|
+
canonical, equivalent = Oydid.version_ids(did_info)
|
|
717
|
+
expect(canonical).to eq "did:oyd:" + second_did
|
|
718
|
+
expect(equivalent).to eq ["did:oyd:" + second_did]
|
|
719
|
+
end
|
|
720
|
+
end
|
|
721
|
+
|
|
587
722
|
end
|