diff --git a/README.md b/README.md index 8b4324e..98b18cd 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Verifiable Legal Entity Identifier Schema Generator and Server | main | dev | |--------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------| | [![main](https://github.com/webOfTrust/vLEI/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/WebOfTrust/vLEI/actions) | [![dev](https://github.com/webOfTrust/vLEI/actions/workflows/test.yml/badge.svg?branch=dev)](https://github.com/WebOfTrust/vLEI/actions) | -| [![codecov](https://codecov.io/gh/WebOfTrust/vLEI/branch/main/graph/badge.svg?token=C30E9WBW4D)](https://codecov.io/gh/WebOfTrust/vLEI) | [![codecov](https://codecov.io/gh/WebOfTrust/vLEI/branch/dev/graph/badge.svg?token=C30E9WBW4D)](https://codecov.io/gh/WebOfTrust/vLEI) | +| [![codecov](https://codecov.io/gh/WebOfTrust/vLEI/branch/main/graph/badge.svg?token=C30E9WBW4D)](https://codecov.io/gh/WebOfTrust/vLEI) | [![codecov](https://codecov.io/gh/WebOfTrust/vLEI/branch/dev/graph/badge.svg?token=C30E9WBW4D)](https://codecov.io/gh/WebOfTrust/vLEI) | ## Public Open Specifications for GLEIF vLEI (verifiable Legal Entity Identifiers) diff --git a/samples/oobis/gleif-external b/samples/oobis.old/gleif-external similarity index 100% rename from samples/oobis/gleif-external rename to samples/oobis.old/gleif-external diff --git a/samples/oobis/gleif-internal b/samples/oobis.old/gleif-internal similarity index 100% rename from samples/oobis/gleif-internal rename to samples/oobis.old/gleif-internal diff --git a/samples/oobis/gleif-root b/samples/oobis.old/gleif-root similarity index 100% rename from samples/oobis/gleif-root rename to samples/oobis.old/gleif-root diff --git a/samples/oobis/.well-known/index.json b/samples/oobis/.well-known/index.json new file mode 100644 index 0000000..f2e92cd --- /dev/null +++ b/samples/oobis/.well-known/index.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://gleif-it.github.io/.well-known/schema.json", + "$id": "EAyAqJjqLHZqkF7gHoFEagEJNoqNa5TEZlDPdJaVC3GD", + "name": "GLEIF Well-Known Resources", + "description": "GLEIF well-known resources for KERI OOBIs, Schemas, and Witnesses", + "version": "1.0.0", + "updated": "2025-11-14", + "oobi": "/keri/oobi/index.json", + "aids": { + "GLEIF RoOT": "EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2", + "GLEIF External": "EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS", + "GLEIF Internal": "EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL" + }, + "schemas": { + "LegalEntityvLEICredential": "ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY", + "QualifiedvLEIIssuervLEICredential": "EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao", + "OORAuthorizationvLEICredential": "EKA57bKBKxr_kN7iN5i7lMUxpMG-s19dRcmov1iDxz-E", + "ECRAuthorizationvLEICredential": "EH6ekLjSr8V32WyFbGe1zXjTzFs9PkTYmupJ9H65O14g", + "LegalEntityOfficialOrganizationalRolevLEICredential": "EBNaNu-M9P5cgrnfl2Fvymy4E_jvxxyjb70PRtiANlJy", + "LegalEntityEngagementContextRolevLEICredential": "EEy9PkikFcANV1l7EHukCeXqrzT1hNZjGlUk7wuMO5jw", + "iXBRLDataAttestation": "EMhvwOlyEJ9kN4PrwCpr9Jsv7TxPhiYveZ0oP3lJzdEi", + "iXBRLDataAttestationSchema": "EOxm1erpuJtjy9bBWO6Wgp9iggefDTNsM6DpO8-jUKbU" + }, + "witnesses": { + "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS": "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS", + "BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt": "BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt", + "BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo": "BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo", + "BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG": "BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG", + "BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X": "BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X", + "BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-": "BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-", + "BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw": "BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw", + "BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC": "BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC", + "BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj": "BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj", + "BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB": "BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB" + }, + "metadata": { + "organization": "Global Legal Entity Identifier Foundation (GLEIF)", + "contact": "https://www.gleif.org", + "documentation": "https://gleif-it.github.io/.well-known/" + } +} diff --git a/samples/oobis/.well-known/keri/oobi/BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS/index.json b/samples/oobis/.well-known/keri/oobi/BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS/index.json new file mode 100644 index 0000000..4a01242 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON0000fd_","t":"icp","d":"ENe1_PfyyL8xsDPkFWLjgmEu9howWWIz2UYboVfA9W-w","i":"BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS","s":"0","kt":"1","k":["BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS"],"nt":"0","n":[],"bt":"0","b":[],"c":[],"a":[]}-VAn-AABAADl3kO6WSb3ebsAnmmP0eze8FQ--UoiWM4QYfLSl4PxnQcHYzCILcAS1_Hhe8TAH1e_aQztJmfMnTo4sojhmq8M-EAB0AAAAAAAAAAAAAAAAAAAAAAA1AAG2022-11-18T19c23c42d243318p00c00{"v":"KERI10JSON0000fe_","t":"rpy","d":"EDi9RAOZ0inUJDze4mI3WfyfX9JQCfrVnRVwbHJYSNjc","dt":"2022-01-20T12:57:59.823350+00:00","r":"/loc/scheme","a":{"eid":"BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS","scheme":"http","url":"http://65.21.253.212:5623/"}}-VAi-CABBDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS0BAAMuhzJlPc5BJV-LJW3-BDQdfWWy_0CQy0uJlRmXf52pGBXmZia0zQ_NgumF95AQ16dUfZZDDpOqruyv0eAhQO{"v":"KERI10JSON000116_","t":"rpy","d":"ENHkUmb81EqzV6F3703OZesYmb2npf7FF7tcB_i4euUW","dt":"2022-01-20T12:57:59.823350+00:00","r":"/end/role/add","a":{"cid":"BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS","role":"controller","eid":"BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS"}}-VAi-CABBDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS0BBJ5YdTH-RFuujwqNk0a4F4JBedu1z8YXr5SbCTzWkgXPk8ZyPTwnI3RwAraAwOQgafXSqAQY8oaObtwO8x_MIB diff --git a/samples/oobis/.well-known/keri/oobi/BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt/index.json b/samples/oobis/.well-known/keri/oobi/BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt/index.json new file mode 100644 index 0000000..118e9ec --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON0000fd_","t":"icp","d":"EOzpJDw0eeuMi8XJDcuu93jMirOqZ8jRZiQMU17CJawy","i":"BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt","s":"0","kt":"1","k":["BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt"],"nt":"0","n":[],"bt":"0","b":[],"c":[],"a":[]}-VAn-AABAAAs3-gxJGlhAU5Oab5ofI94jWopI6lN175FtI1p-dkNi_ukpiLrtd5yzX2QK43oBwSY5wrDnbSOFmxKJWxUa2wG-EAB0AAAAAAAAAAAAAAAAAAAAAAA1AAG2022-11-18T19c18c07d892358p00c00{"v":"KERI10JSON0000fe_","t":"rpy","d":"ENspzHRaG6BD4jZZUkFkd6pzV59Hb4vE_EIU9jhE2SE9","dt":"2022-01-20T12:57:59.823350+00:00","r":"/loc/scheme","a":{"eid":"BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt","scheme":"http","url":"http://51.161.130.60:5623/"}}-VAi-CABBDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt0BDiNFwryWogJgvkV2NTlUCU8Bv8qqu3K1dUnkE_MtvJOZe8OSLKHhTpcTVCQSwps-Sk7zfiU0UsoW5xXFPKDDMO{"v":"KERI10JSON000116_","t":"rpy","d":"EEpqnwYC0kmLNrfOUoJtVxEDkL9tB487ukAjwjxSL98M","dt":"2022-01-20T12:57:59.823350+00:00","r":"/end/role/add","a":{"cid":"BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt","role":"controller","eid":"BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt"}}-VAi-CABBDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt0BAQOT7BP1h_c336YAENd5G8VNIzE7SZumMaZxQ-o8e7LeHBzlEc81POxSIkGZy-0lYRI2tCq86lkO4qRfWAZXQB diff --git a/samples/oobis/.well-known/keri/oobi/BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo/index.json b/samples/oobis/.well-known/keri/oobi/BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo/index.json new file mode 100644 index 0000000..4010dc0 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON0000fd_","t":"icp","d":"EKLf4ZuCDfkcb8XL7olyxKLEc4vHvD05nu3srnTGFJTI","i":"BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo","s":"0","kt":"1","k":["BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo"],"nt":"0","n":[],"bt":"0","b":[],"c":[],"a":[]}-VAn-AABAAAImoIfkajFR8E4y4I5keAqj2kVvPqs-22sPT_os1bO4SesTxyPaM7_d07P4De-TTqHcLf479qgYHVa1lamDWoA-EAB0AAAAAAAAAAAAAAAAAAAAAAA1AAG2022-11-18T19c38c00d064227p00c00{"v":"KERI10JSON0000ff_","t":"rpy","d":"EInvpPtc6EOv4pbqGOlDF6SXv903VcM4fmehC1lyvu2K","dt":"2022-01-20T12:57:59.823350+00:00","r":"/loc/scheme","a":{"eid":"BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo","scheme":"http","url":"http://54.233.109.129:5623/"}}-VAi-CABBFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo0BBuMBwuFmQtHGHh_n9wUAbfX8zDNNh8XTT8Yh5EziWOFw-9EMDXmo8-bMaxQWbu7xWZAXygrktlxO-m_11c1DUA{"v":"KERI10JSON000116_","t":"rpy","d":"EPNh2ju8JWgRe6DTaw_nlo3aR4KHan775Fr7SiV6Nso2","dt":"2022-01-20T12:57:59.823350+00:00","r":"/end/role/add","a":{"cid":"BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo","role":"controller","eid":"BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo"}}-VAi-CABBFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo0BCt_vEX-BCXqvOl6OyjaXR-aepsKqREQA6YG-HK2CeQs5ipCdWXUjjdLrNlmM-BEYhtkJYzVIVDCK5xge6Ip_sB diff --git a/samples/oobis/.well-known/keri/oobi/BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG/index.json b/samples/oobis/.well-known/keri/oobi/BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG/index.json new file mode 100644 index 0000000..8b7e699 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON0000fd_","t":"icp","d":"EC7gmwWKhDX-iiubxdOG67NLbrnycPOGNsPMEVQKBtlA","i":"BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG","s":"0","kt":"1","k":["BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG"],"nt":"0","n":[],"bt":"0","b":[],"c":[],"a":[]}-VAn-AABAAAQcYQkrS9QX13HTovrnkYlIrprX09cEyr97juEjmp97kEsgIgGExs_lLU6Pah2TrZugIHwUCflBvgYZHjZsKgP-EAB0AAAAAAAAAAAAAAAAAAAAAAA1AAG2022-11-18T19c32c38d489439p00c00{"v":"KERI10JSON0000fe_","t":"rpy","d":"EATNZiiLKhpq2erQTzdKae63kUB61GqN1oSqHy97In9u","dt":"2022-01-20T12:57:59.823350+00:00","r":"/loc/scheme","a":{"eid":"BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG","scheme":"http","url":"http://102.37.159.99:5623/"}}-VAi-CABBGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG0BAlJWRjKtTODqVXmunSNojBuJcyRgkA7IEXl6ELfcCeDZccA7lteFyq1hlrfgw9ggbUrIp62KNXZeLpusZBG5UM{"v":"KERI10JSON000116_","t":"rpy","d":"ELRe_dTrQK2MEL2psyqzd4lwowvSIFp6PTY3qhRgTKBC","dt":"2022-01-20T12:57:59.823350+00:00","r":"/end/role/add","a":{"cid":"BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG","role":"controller","eid":"BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG"}}-VAi-CABBGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG0BAOr8JDEeWTVGqGDOnT-UNU4USCuBWkdjyJl5iyMxKLyketMz3gzwUb29Uz6BA_sLuK18i86eJS70tet-3F654G diff --git a/samples/oobis/.well-known/keri/oobi/BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X/index.json b/samples/oobis/.well-known/keri/oobi/BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X/index.json new file mode 100644 index 0000000..6ec36f1 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON0000fd_","t":"icp","d":"EG_u-Wv7iDT8EBSGxl75DQNWOBihT3qWrUTAX10h4DzM","i":"BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X","s":"0","kt":"1","k":["BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X"],"nt":"0","n":[],"bt":"0","b":[],"c":[],"a":[]}-VAn-AABAAC2SfT-NPhdCD5VNpyldgXzOYJn5HzWi8H7rXlfl9RVT6bc4Pp_Fp9T1QjFK7hyDMwOS0PC8U0eWQtTEGhwOBoH-EAB0AAAAAAAAAAAAAAAAAAAAAAA1AAG2022-11-18T19c18c07d200623p00c00{"v":"KERI10JSON0000fd_","t":"rpy","d":"EHXyl8ekBure0fRN0zaP0kL408f7NSZL9a8ZY0HbC9Ok","dt":"2022-01-20T12:57:59.823350+00:00","r":"/loc/scheme","a":{"eid":"BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X","scheme":"http","url":"http://51.79.54.121:5623/"}}-VAi-CABBHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X0BBKucnYILQ1k7y3nUyrGshjfqcD1n9SOAXpB39Td04Y2NtmcBeenT_q97mqyCODGUm1kMvI_nDW8gecM5cGJDcL{"v":"KERI10JSON000116_","t":"rpy","d":"ECLknVA3qjdCId_gtoqpDzfvdernSeKS4gM4_iFZCbf7","dt":"2022-01-20T12:57:59.823350+00:00","r":"/end/role/add","a":{"cid":"BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X","role":"controller","eid":"BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X"}}-VAi-CABBHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X0BAbs2keCljImP7f0cIkH5_Lpmmhc8EKOvWb2nuJgI82zI0z8GnROcJN4gpXMCMXHD9_NFh3EzvCkqQDgGVPiO0A diff --git a/samples/oobis/.well-known/keri/oobi/BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-/index.json b/samples/oobis/.well-known/keri/oobi/BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-/index.json new file mode 100644 index 0000000..062a8f2 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON0000fd_","t":"icp","d":"EKVPUCHW2GdDJSYsOKd9fk5i9hH5O-MvxLVFKf5Gciwq","i":"BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-","s":"0","kt":"1","k":["BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-"],"nt":"0","n":[],"bt":"0","b":[],"c":[],"a":[]}-VAn-AABAADDBNEyAEFGjYUvAQSYAzWX9IUd5NISTOxRVAbshhVW-TqNAuRzkpFAwQMtc8CGNkVbeafgd61b2VmGZn2szTwI-EAB0AAAAAAAAAAAAAAAAAAAAAAA1AAG2022-11-18T19c32c39d511732p00c00{"v":"KERI10JSON0000fd_","t":"rpy","d":"EOYLs0w-CgBm5f97NbW5vNRLTgYb12uY6-xfawnY_KhL","dt":"2022-01-20T12:57:59.823350+00:00","r":"/loc/scheme","a":{"eid":"BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-","scheme":"http","url":"http://20.78.61.227:5623/"}}-VAi-CABBICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-0BBCpyKU-syhrWDZ3NFTCQcqNkeLUkdD5yjgdq8B42LBP0rb4LEZ9Gsda2P4i_ZRTZuPB66gMjnqRkpL3Pd_KbAM{"v":"KERI10JSON000116_","t":"rpy","d":"EM8EPMkWKwU6t1SNSvfn2hgfCbw8cZte23ENpxF1emWw","dt":"2022-01-20T12:57:59.823350+00:00","r":"/end/role/add","a":{"cid":"BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-","role":"controller","eid":"BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-"}}-VAi-CABBICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-0BB8Ock74xoNgF_GXzTIz3_iv9lgWJRKGOPB9qYvCGU5CgMYAm-Dpe1A-Vet2qOJjNeI4VUnDbJeNlZhosu7YKkG diff --git a/samples/oobis/.well-known/keri/oobi/BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw/index.json b/samples/oobis/.well-known/keri/oobi/BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw/index.json new file mode 100644 index 0000000..100715c --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON0000fd_","t":"icp","d":"EHWArtD-ZHs-2jgGIgGRaITOCE7Gbj3j4fwwLQiuAAi9","i":"BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw","s":"0","kt":"1","k":["BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw"],"nt":"0","n":[],"bt":"0","b":[],"c":[],"a":[]}-VAn-AABAACnZmEiv6BKe5S74u3NMizh_hfuMmtFgpkDTo-h2s88sJizA96m0Pzj7dPrcuRgb2u3z-DbdNiXMK7UV86sk0gJ-EAB0AAAAAAAAAAAAAAAAAAAAAAA1AAG2022-11-18T19c44c24d910095p00c00{"v":"KERI10JSON0000fe_","t":"rpy","d":"EGDsrAeQh0gk_vFcb5rFrXyb8kFvnZ7opDPr4HpXiF-t","dt":"2022-01-20T12:57:59.823350+00:00","r":"/loc/scheme","a":{"eid":"BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw","scheme":"http","url":"http://8.210.213.186:5623/"}}-VAi-CABBLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw0BBUKtX4G9_YB7fBcKPrZCv7KzWlIX-GK6bnDOnyMZfI6TI0ls8mFipI981u8cn2stw2chvy5VD0ajietcWW6fsK{"v":"KERI10JSON000116_","t":"rpy","d":"EFWC2u7BiJgbOqA5IzWGK8G_fMGlDWtNGpGBaYwH-P29","dt":"2022-01-20T12:57:59.823350+00:00","r":"/end/role/add","a":{"cid":"BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw","role":"controller","eid":"BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw"}}-VAi-CABBLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw0BAkI7ixBMIzHjdHlobEukSBqypBs5vNR3-WNhQmVi1hnlxvJNMQaZoFjDM55vrMucsKoZty6NLa2ltR7v0KNcoM diff --git a/samples/oobis/.well-known/keri/oobi/BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC/index.json b/samples/oobis/.well-known/keri/oobi/BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC/index.json new file mode 100644 index 0000000..c19980a --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON0000fd_","t":"icp","d":"EGx3FkWEtNUfQXafaxyS9EplP-GWeQJCY4gujYJyAelA","i":"BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC","s":"0","kt":"1","k":["BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC"],"nt":"0","n":[],"bt":"0","b":[],"c":[],"a":[]}-VAn-AABAAC6Qb_BEX86k3m9Aq301jcxEAYtO0mzAwNFjRCiQHjrpFecIlV42zHy2LnPPN1e4ZB2wmvLH-nvKml7toqbjNkH-EAB0AAAAAAAAAAAAAAAAAAAAAAA1AAG2022-11-18T19c44c15d693126p00c00{"v":"KERI10JSON0000fd_","t":"rpy","d":"ENNIQDbQitjOinMGab9keI8qBUrXYLGYN8x2QhGW4KsA","dt":"2022-01-20T12:57:59.823350+00:00","r":"/loc/scheme","a":{"eid":"BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC","scheme":"http","url":"http://8.208.27.153:5623/"}}-VAi-CABBLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC0BAFfyo5mHdQoLwvEAtK8af8lN3oiKu4gZvUXyQqiSRfaUaSIrcpRzAeAcnnL50Q9Gl88mvFLcKJpDcEf0hyPaAB{"v":"KERI10JSON000116_","t":"rpy","d":"EFzkVDiKmW3Kluty0Kjn4KoOYmvUSn0QqceecyjKlv2l","dt":"2022-01-20T12:57:59.823350+00:00","r":"/end/role/add","a":{"cid":"BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC","role":"controller","eid":"BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC"}}-VAi-CABBLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC0BCtdXrUBmMtYjgM5MwtG8su7xKVCIXGT6-7Lllwk5tAHWlig7jAYovIGc--O5J8JUXMmnBGa-VwqJGjLEf8gZgG diff --git a/samples/oobis/.well-known/keri/oobi/BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj/index.json b/samples/oobis/.well-known/keri/oobi/BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj/index.json new file mode 100644 index 0000000..0053ce5 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON0000fd_","t":"icp","d":"EJzQ9k7wLv1gmGn3_KuJ0E6VXB-xOj60L10HBi_p07Dl","i":"BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj","s":"0","kt":"1","k":["BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj"],"nt":"0","n":[],"bt":"0","b":[],"c":[],"a":[]}-VAn-AABAACkK6iBtN3KXqpQYVHA5JUeRFZR9sTs87B0lZqAwJhzdZNV15xjregiIURwYXzcGAwX1pNQuoyQdTU81FBZptwG-EAB0AAAAAAAAAAAAAAAAAAAAAAA1AAG2022-11-18T19c37c59d836770p00c00{"v":"KERI10JSON0000ff_","t":"rpy","d":"EKG0T9CYS_U8wy7yYjSzuGwvLzVcxASbuJAZaCxgxht8","dt":"2022-01-20T12:57:59.823350+00:00","r":"/loc/scheme","a":{"eid":"BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj","scheme":"http","url":"http://13.244.119.106:5623/"}}-VAi-CABBM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj0BCe5L24PhSVATgpcB5iMOXbahPshTKo6G6YbDWeDS-NUD-oIHHBgeQ4PBdxveUGZRWIE_tKaic8AJSLIb1DLLgH{"v":"KERI10JSON000116_","t":"rpy","d":"EMkaE0wETvpqM6Iz-A4mukFE0sG1fI0SZSrjTAeHBM7g","dt":"2022-01-20T12:57:59.823350+00:00","r":"/end/role/add","a":{"cid":"BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj","role":"controller","eid":"BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj"}}-VAi-CABBM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj0BAM7iOFhq6_tqDePlCtfXefu8loM-gBjNlKNwmxeHtODl1Gotoh-2j9wOGt6Q2YqWk2t7EdZwAhvgGg0LM4ae4D diff --git a/samples/oobis/.well-known/keri/oobi/BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB/index.json b/samples/oobis/.well-known/keri/oobi/BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB/index.json new file mode 100644 index 0000000..204540d --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON0000fd_","t":"icp","d":"EAa1iuG4PSqADOP1BgT1AZjPHjoOWF2HdtDX9LJwToVM","i":"BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB","s":"0","kt":"1","k":["BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB"],"nt":"0","n":[],"bt":"0","b":[],"c":[],"a":[]}-VAn-AABAADmNNzhHlc59paCkBz_SkP1RLAj3wF8yukPjHLw0BrzaSqXDqPqq9ve2WZUm54M7L3CT8FlUCVsVJe1ZK3Yk34I-EAB0AAAAAAAAAAAAAAAAAAAAAAA1AAG2022-11-18T19c23c42d340198p00c00{"v":"KERI10JSON0000fc_","t":"rpy","d":"EDF_MGXhz2xAvssCHXJNcV7KkBV1FakBgIkDHkMaVFxc","dt":"2022-01-20T12:57:59.823350+00:00","r":"/loc/scheme","a":{"eid":"BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB","scheme":"http","url":"http://5.161.69.25:5623/"}}-VAi-CABBNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB0BCnuP2gg4XOby7MeX1jOGkdhybrgWVdOaHqQ4la19WstRKm7avepYbLm0Vph2f_T1lXmA5SYwDhfOtC0mCvNSYJ{"v":"KERI10JSON000116_","t":"rpy","d":"EIAZU6xpPSQCXAOUDp7sqH8ARR3hPbYdK9UQy7E0EDfa","dt":"2022-01-20T12:57:59.823350+00:00","r":"/end/role/add","a":{"cid":"BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB","role":"controller","eid":"BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB"}}-VAi-CABBNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB0BAKzOuCeWUusv-0daoPXU5kY4zdrSF4QAd8yu-HDUmn_9DSy4iJowQMuXpjoTMZzBXYj02XTQ0-mDjGjdvqvbUE diff --git a/samples/oobis/.well-known/keri/oobi/EBNaNu-M9P5cgrnfl2Fvymy4E_jvxxyjb70PRtiANlJy/index.json b/samples/oobis/.well-known/keri/oobi/EBNaNu-M9P5cgrnfl2Fvymy4E_jvxxyjb70PRtiANlJy/index.json new file mode 100644 index 0000000..f8970bf --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/EBNaNu-M9P5cgrnfl2Fvymy4E_jvxxyjb70PRtiANlJy/index.json @@ -0,0 +1 @@ +{"$id":"EBNaNu-M9P5cgrnfl2Fvymy4E_jvxxyjb70PRtiANlJy","$schema":"http://json-schema.org/draft-07/schema#","title":"Legal Entity Official Organizational Role vLEI Credential","description":"A vLEI Role Credential issued by a Qualified vLEI issuer to official representatives of a Legal Entity","type":"object","credentialType":"LegalEntityOfficialOrganizationalRolevLEICredential","version":"1.0.0","properties":{"v":{"description":"Version","type":"string"},"d":{"description":"Credential SAID","type":"string"},"u":{"description":"One time use nonce","type":"string"},"i":{"description":"QVI Issuer AID","type":"string"},"ri":{"description":"Credential status registry","type":"string"},"s":{"description":"Schema SAID","type":"string"},"a":{"oneOf":[{"description":"Attributes block SAID","type":"string"},{"$id":"ELDXjQ-FnKApK1DJhzmtKDcnfoJ9qusQr1Qz5g9MFt0o","description":"Attributes block","type":"object","properties":{"d":{"description":"Attributes block SAID","type":"string"},"i":{"description":"Person Issuee AID","type":"string"},"dt":{"description":"Issuance date time","type":"string","format":"date-time"},"LEI":{"description":"LEI of the Legal Entity","type":"string","format":"ISO 17442"},"personLegalName":{"description":"Recipient name as provided during identity assurance","type":"string"},"officialRole":{"description":"Official role title","type":"string"}},"additionalProperties":false,"required":["i","dt","LEI","personLegalName","officialRole"]}]},"e":{"oneOf":[{"description":"Edges block SAID","type":"string"},{"$id":"EMsSqaJsthSBA4OINZ1_fxfNVkgEPF-Sg5fq-vXM7Z6b","description":"Edges block","type":"object","properties":{"d":{"description":"Edges block SAID","type":"string"},"auth":{"description":"Chain to Auth vLEI credential from legal entity","type":"object","properties":{"n":{"description":"SAID of the ACDC to which the edge connects","type":"string"},"s":{"description":"SAID of required schema of the credential pointed to by this node","type":"string","const":"EKA57bKBKxr_kN7iN5i7lMUxpMG-s19dRcmov1iDxz-E"},"o":{"description":"Operator indicating this node is the issuer","type":"string","const":"I2I"}},"additionalProperties":false,"required":["n","s","o"]}},"additionalProperties":false,"required":["d","auth"]}]},"r":{"oneOf":[{"description":"Rules block SAID","type":"string"},{"$id":"ECllqarpkZrSIWCb97XlMpEZZH3q4kc--FQ9mbkFMb_5","description":"Rules block","type":"object","properties":{"d":{"description":"Rules block SAID","type":"string"},"usageDisclaimer":{"description":"Usage Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"Usage of a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, does not assert that the Legal Entity is trustworthy, honest, reputable in its business dealings, safe to do business with, or compliant with any laws or that an implied or expressly intended purpose will be fulfilled."}}},"issuanceDisclaimer":{"description":"Issuance Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"All information in a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, is accurate as of the date the validation process was complete. The vLEI Credential has been issued to the legal entity or person named in the vLEI Credential as the subject; and the qualified vLEI Issuer exercised reasonable care to perform the validation process set forth in the vLEI Ecosystem Governance Framework."}}}},"additionalProperties":false,"required":["d","usageDisclaimer","issuanceDisclaimer"]}]}},"additionalProperties":false,"required":["i","ri","s","d","e","r"]} diff --git a/samples/oobis/.well-known/keri/oobi/EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao/index.json b/samples/oobis/.well-known/keri/oobi/EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao/index.json new file mode 100644 index 0000000..2b7ebbd --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao/index.json @@ -0,0 +1 @@ +{"$id":"EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao","$schema":"http://json-schema.org/draft-07/schema#","title":"Qualified vLEI Issuer Credential","description":"A vLEI Credential issued by GLEIF to Qualified vLEI Issuers which allows the Qualified vLEI Issuers to issue, verify and revoke Legal Entity vLEI Credentials and Legal Entity Official Organizational Role vLEI Credentials","type":"object","credentialType":"QualifiedvLEIIssuervLEICredential","version":"1.0.0","properties":{"v":{"description":"Version","type":"string"},"d":{"description":"Credential SAID","type":"string"},"u":{"description":"One time use nonce","type":"string"},"i":{"description":"GLEIF Issuee AID","type":"string"},"ri":{"description":"Credential status registry","type":"string"},"s":{"description":"Schema SAID","type":"string"},"a":{"oneOf":[{"description":"Attributes block SAID","type":"string"},{"$id":"ELGgI0fkloqKWREXgqUfgS0bJybP1LChxCO3sqPSFHCj","description":"Attributes block","type":"object","properties":{"d":{"description":"Attributes block SAID","type":"string"},"i":{"description":"QVI Issuee AID","type":"string"},"dt":{"description":"Issuance date time","type":"string","format":"date-time"},"LEI":{"description":"LEI of the requesting Legal Entity","type":"string","format":"ISO 17442"},"gracePeriod":{"description":"Allocated grace period","type":"integer","default":90}},"additionalProperties":false,"required":["i","dt","LEI"]}]},"r":{"oneOf":[{"description":"Rules block SAID","type":"string"},{"$id":"ECllqarpkZrSIWCb97XlMpEZZH3q4kc--FQ9mbkFMb_5","description":"Rules block","type":"object","properties":{"d":{"description":"Rules block SAID","type":"string"},"usageDisclaimer":{"description":"Usage Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"Usage of a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, does not assert that the Legal Entity is trustworthy, honest, reputable in its business dealings, safe to do business with, or compliant with any laws or that an implied or expressly intended purpose will be fulfilled."}}},"issuanceDisclaimer":{"description":"Issuance Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"All information in a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, is accurate as of the date the validation process was complete. The vLEI Credential has been issued to the legal entity or person named in the vLEI Credential as the subject; and the qualified vLEI Issuer exercised reasonable care to perform the validation process set forth in the vLEI Ecosystem Governance Framework."}}}},"additionalProperties":false,"required":["d","usageDisclaimer","issuanceDisclaimer"]}]}},"additionalProperties":false,"required":["i","ri","s","d"]} diff --git a/samples/oobis/.well-known/keri/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/index.json b/samples/oobis/.well-known/keri/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/index.json new file mode 100644 index 0000000..ebcdf9b --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON000282_","t":"rpy","d":"EPflJSbTCs2WKoGx4zIJ5OpOXHXuY0JE9et9ile2gMpv","dt":"2022-11-21T21:20:24.003241+00:00","r":"/oobi/witness","a":{"urls":["http://5.161.69.25:5623/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/witness","http://51.161.130.60:5623/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/witness","http://102.37.159.99:5623/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/witness","http://13.244.119.106:5623/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/witness","http://8.208.27.153:5623/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/witness"],"aid":"EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2"}} diff --git a/samples/oobis/.well-known/keri/oobi/EEy9PkikFcANV1l7EHukCeXqrzT1hNZjGlUk7wuMO5jw/index.json b/samples/oobis/.well-known/keri/oobi/EEy9PkikFcANV1l7EHukCeXqrzT1hNZjGlUk7wuMO5jw/index.json new file mode 100644 index 0000000..26d7128 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/EEy9PkikFcANV1l7EHukCeXqrzT1hNZjGlUk7wuMO5jw/index.json @@ -0,0 +1 @@ +{"$id":"EEy9PkikFcANV1l7EHukCeXqrzT1hNZjGlUk7wuMO5jw","$schema":"http://json-schema.org/draft-07/schema#","title":"Legal Entity Engagement Context Role vLEI Credential","description":"A vLEI Role Credential issued to representatives of a Legal Entity in other than official roles but in functional or other context of engagement","type":"object","credentialType":"LegalEntityEngagementContextRolevLEICredential","version":"1.0.0","properties":{"v":{"description":"Version","type":"string"},"d":{"description":"Credential SAID","type":"string"},"u":{"description":"A salty nonce","type":"string"},"i":{"description":"QVI or LE Issuer AID","type":"string"},"ri":{"description":"Credential status registry","type":"string"},"s":{"description":"Schema SAID","type":"string"},"a":{"oneOf":[{"description":"Attributes block SAID","type":"string"},{"$id":"EDv4wiOMHE125CXu-EuOd0YRXz-AgpLilJfjoODFqtHD","description":"Attributes block","type":"object","properties":{"d":{"description":"Attributes block SAID","type":"string"},"u":{"description":"A salty nonce","type":"string"},"i":{"description":"Person Issuee AID","type":"string"},"dt":{"description":"Issuance date time","type":"string","format":"date-time"},"LEI":{"description":"LEI of the Legal Entity","type":"string","format":"ISO 17442"},"personLegalName":{"description":"Recipient name as provided during identity assurance","type":"string"},"engagementContextRole":{"description":"Role description i.e. 'Head of Standards'","type":"string"}},"additionalProperties":false,"required":["i","dt","LEI","personLegalName","engagementContextRole"]}]},"e":{"oneOf":[{"description":"Edges block SAID","type":"string"},{"$id":"EEM9OvWMEmAfAY0BV2kXatSc8WM13QW1B5y33E8z4f33","description":"Edges block","type":"object","properties":{"d":{"description":"Edges block SAID","type":"string"},"auth":{"description":"Chain to Auth vLEI credential from legal entity","type":"object","properties":{"n":{"description":"SAID of the ACDC to which the edge connects","type":"string"},"s":{"description":"SAID of required schema of the credential pointed to by this node","type":"string","const":"EH6ekLjSr8V32WyFbGe1zXjTzFs9PkTYmupJ9H65O14g"},"o":{"description":"Operator indicating this node is the issuer","type":"string","const":"I2I"}},"additionalProperties":false,"required":["n","s","o"]}},"additionalProperties":false,"required":["d","auth"]},{"$id":"EHeZGaLBhCc_-sAcyAEgFFeCkxgnqCubPOBuEvoh9jHX","description":"Edges block for issuance from Legal Entity","type":"object","properties":{"d":{"description":"SAID of edges block","type":"string"},"le":{"description":"Chain to legal entity vLEI credential","type":"object","properties":{"n":{"description":"SAID of the ACDC to which the edge connects","type":"string"},"s":{"description":"SAID of required schema of the credential pointed to by this node","type":"string","const":"ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY"}},"additionalProperties":false,"required":["n","s"]}},"additionalProperties":false,"required":["d","le"]}]},"r":{"oneOf":[{"description":"Rules block SAID","type":"string"},{"$id":"EEBm6OIpem19B8BzxWXOAuzKTtYeutGpXMLW9o3pAuRe","description":"Rules block","type":"object","properties":{"d":{"description":"Rules block SAID","type":"string"},"usageDisclaimer":{"description":"Usage Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"Usage of a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, does not assert that the Legal Entity is trustworthy, honest, reputable in its business dealings, safe to do business with, or compliant with any laws or that an implied or expressly intended purpose will be fulfilled."}}},"issuanceDisclaimer":{"description":"Issuance Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"All information in a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, is accurate as of the date the validation process was complete. The vLEI Credential has been issued to the legal entity or person named in the vLEI Credential as the subject; and the qualified vLEI Issuer exercised reasonable care to perform the validation process set forth in the vLEI Ecosystem Governance Framework."}}},"privacyDisclaimer":{"description":"Privacy Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"It is the sole responsibility of Holders as Issuees of an ECR vLEI Credential to present that Credential in a privacy-preserving manner using the mechanisms provided in the Issuance and Presentation Exchange (IPEX) protocol specification and the Authentic Chained Data Container (ACDC) specification. https://github.com/WebOfTrust/IETF-IPEX and https://github.com/trustoverip/tswg-acdc-specification."}}}},"additionalProperties":false,"required":["d","usageDisclaimer","issuanceDisclaimer","privacyDisclaimer"]}]}},"additionalProperties":false,"required":["v","u","i","ri","s","d","r","a","e"]} diff --git a/samples/oobis/.well-known/keri/oobi/EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL/index.json b/samples/oobis/.well-known/keri/oobi/EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL/index.json new file mode 100644 index 0000000..150b4e5 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON000281_","t":"rpy","d":"EIMyFlQKLca4zBs7Y2LqW3tYEeI78fezJ9F_C4SkDI96","dt":"2022-12-01T21:42:57.711329+00:00","r":"/oobi/witness","a":{"urls":["http://13.244.119.106:5623/oobi/EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL/witness","http://51.161.130.60:5623/oobi/EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL/witness","http://20.78.61.227:5623/oobi/EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL/witness","http://8.208.27.153:5623/oobi/EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL/witness","http://5.161.69.25:5623/oobi/EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL/witness"],"aid":"EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL"}} diff --git a/samples/oobis/.well-known/keri/oobi/EH6ekLjSr8V32WyFbGe1zXjTzFs9PkTYmupJ9H65O14g/index.json b/samples/oobis/.well-known/keri/oobi/EH6ekLjSr8V32WyFbGe1zXjTzFs9PkTYmupJ9H65O14g/index.json new file mode 100644 index 0000000..9696a66 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/EH6ekLjSr8V32WyFbGe1zXjTzFs9PkTYmupJ9H65O14g/index.json @@ -0,0 +1 @@ +{"$id":"EH6ekLjSr8V32WyFbGe1zXjTzFs9PkTYmupJ9H65O14g","$schema":"http://json-schema.org/draft-07/schema#","title":"ECR Authorization vLEI Credential","description":"A vLEI Authorization Credential issued by a Legal Entity to a QVI for the authorization of ECR credentials","type":"object","credentialType":"ECRAuthorizationvLEICredential","version":"1.0.0","properties":{"v":{"description":"Version","type":"string"},"d":{"description":"Credential SAID","type":"string"},"u":{"description":"One time use nonce","type":"string"},"i":{"description":"LE Issuer AID","type":"string"},"ri":{"description":"Credential status registry","type":"string"},"s":{"description":"Schema SAID","type":"string"},"a":{"oneOf":[{"description":"Attributes block SAID","type":"string"},{"$id":"EBMwtCJt7LUfA9u0jmZ1cAoCavZFIBmZBmlufYeX4gdy","description":"Attributes block","type":"object","properties":{"d":{"description":"Attributes block SAID","type":"string"},"i":{"description":"QVI Issuee AID","type":"string"},"dt":{"description":"Issuance date time","type":"string","format":"date-time"},"AID":{"description":"AID of the intended recipient of the ECR credential","type":"string"},"LEI":{"description":"LEI of the requesting Legal Entity","type":"string","format":"ISO 17442"},"personLegalName":{"description":"Requested recipient name as provided during identity assurance","type":"string"},"engagementContextRole":{"description":"Requested role description i.e. 'Head of Standards'","type":"string"}},"additionalProperties":false,"required":["i","dt","AID","LEI","personLegalName","engagementContextRole"]}]},"e":{"oneOf":[{"description":"Edges block SAID","type":"string"},{"$id":"EB6E1GJvVen5NqkKb2TG5jqX66vYOL3md-xkXQqQBySX","description":"Edges block","type":"object","properties":{"d":{"description":"Edges block SAID","type":"string"},"le":{"description":"Chain to legal entity vLEI credential","type":"object","properties":{"n":{"description":"QVI Issuer credential SAID","type":"string"},"s":{"description":"SAID of required schema of the credential pointed to by this node","type":"string","const":"ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY"}},"additionalProperties":false,"required":["n","s"]}},"additionalProperties":false,"required":["d","le"]}]},"r":{"oneOf":[{"description":"Rules block SAID","type":"string"},{"$id":"ELLuSgEW2h8n5fHKLvZc9uTtxzqXQqlWR7MiwEt7AcmM","description":"Rules block","type":"object","properties":{"d":{"description":"Rules block SAID","type":"string"},"usageDisclaimer":{"description":"Usage Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"Usage of a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, does not assert that the Legal Entity is trustworthy, honest, reputable in its business dealings, safe to do business with, or compliant with any laws or that an implied or expressly intended purpose will be fulfilled."}}},"issuanceDisclaimer":{"description":"Issuance Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"All information in a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, is accurate as of the date the validation process was complete. The vLEI Credential has been issued to the legal entity or person named in the vLEI Credential as the subject; and the qualified vLEI Issuer exercised reasonable care to perform the validation process set forth in the vLEI Ecosystem Governance Framework."}}},"privacyDisclaimer":{"description":"Privacy Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"Privacy Considerations are applicable to QVI ECR AUTH vLEI Credentials. It is the sole responsibility of QVIs as Issuees of QVI ECR AUTH vLEI Credentials to present these Credentials in a privacy-preserving manner using the mechanisms provided in the Issuance and Presentation Exchange (IPEX) protocol specification and the Authentic Chained Data Container (ACDC) specification. https://github.com/WebOfTrust/IETF-IPEX and https://github.com/trustoverip/tswg-acdc-specification."}}}},"additionalProperties":false,"required":["d","usageDisclaimer","issuanceDisclaimer","privacyDisclaimer"]}]}},"additionalProperties":false,"required":["i","ri","s","d","e","r"]} diff --git a/samples/oobis/.well-known/keri/oobi/EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS/index.json b/samples/oobis/.well-known/keri/oobi/EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS/index.json new file mode 100644 index 0000000..6a7fe69 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS/index.json @@ -0,0 +1 @@ +{"v":"KERI10JSON000284_","t":"rpy","d":"EIRLkv5pe2QMTahfsDYlPxgcj64BD4XKABxBYNFZIdNH","dt":"2022-12-01T01:01:01.489126+00:00","r":"/oobi/witness","a":{"urls":["http://65.21.253.212:5623/oobi/EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS/witness","http://8.210.213.186:5623/oobi/EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS/witness","http://51.79.54.121:5623/oobi/EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS/witness","http://102.37.159.99:5623/oobi/EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS/witness","http://54.233.109.129:5623/oobi/EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS/witness"],"aid":"EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS"}} diff --git a/samples/oobis/.well-known/keri/oobi/EKA57bKBKxr_kN7iN5i7lMUxpMG-s19dRcmov1iDxz-E/index.json b/samples/oobis/.well-known/keri/oobi/EKA57bKBKxr_kN7iN5i7lMUxpMG-s19dRcmov1iDxz-E/index.json new file mode 100644 index 0000000..3ee66d1 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/EKA57bKBKxr_kN7iN5i7lMUxpMG-s19dRcmov1iDxz-E/index.json @@ -0,0 +1 @@ +{"$id":"EKA57bKBKxr_kN7iN5i7lMUxpMG-s19dRcmov1iDxz-E","$schema":"http://json-schema.org/draft-07/schema#","title":"OOR Authorization vLEI Credential","description":"A vLEI Authorization Credential issued by a Legal Entity to a QVI for the authorization of OOR credentials","type":"object","credentialType":"OORAuthorizationvLEICredential","version":"1.0.0","properties":{"v":{"description":"Version","type":"string"},"d":{"description":"Credential SAID","type":"string"},"u":{"description":"One time use nonce","type":"string"},"i":{"description":"LE Issuer AID","type":"string"},"ri":{"description":"Credential status registry","type":"string"},"s":{"description":"Schema SAID","type":"string"},"a":{"oneOf":[{"description":"Attributes block SAID","type":"string"},{"$id":"EPli-kppZ4gj8g4i3-FUx3ZG1H_UrMhXwzyP1E6uAot6","description":"Attributes block","type":"object","properties":{"d":{"description":"Attributes block SAID","type":"string"},"i":{"description":"QVI Issuee AID","type":"string"},"dt":{"description":"Issuance date time","format":"date-time","type":"string"},"AID":{"description":"AID of the intended recipient of the ECR credential","type":"string"},"LEI":{"description":"LEI of the requesting Legal Entity","type":"string","format":"ISO 17442"},"personLegalName":{"description":"Requested recipient name as provided during identity assurance","type":"string"},"officialRole":{"description":"Requested role description i.e. 'Head of Standards'","type":"string"}},"additionalProperties":false,"required":["i","dt","AID","LEI","personLegalName","officialRole"]}]},"e":{"oneOf":[{"description":"Edges block SAID","type":"string"},{"$id":"EB6E1GJvVen5NqkKb2TG5jqX66vYOL3md-xkXQqQBySX","description":"Edges block","type":"object","properties":{"d":{"description":"Edges block SAID","type":"string"},"le":{"description":"Chain to legal entity vLEI credential","type":"object","properties":{"n":{"description":"QVI Issuer credential SAID","type":"string"},"s":{"description":"SAID of required schema of the credential pointed to by this node","type":"string","const":"ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY"}},"additionalProperties":false,"required":["n","s"]}},"additionalProperties":false,"required":["d","le"]}]},"r":{"oneOf":[{"description":"Rules block SAID","type":"string"},{"$id":"ECllqarpkZrSIWCb97XlMpEZZH3q4kc--FQ9mbkFMb_5","description":"Rules block","type":"object","properties":{"d":{"description":"Rules block SAID","type":"string"},"usageDisclaimer":{"description":"Usage Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"Usage of a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, does not assert that the Legal Entity is trustworthy, honest, reputable in its business dealings, safe to do business with, or compliant with any laws or that an implied or expressly intended purpose will be fulfilled."}}},"issuanceDisclaimer":{"description":"Issuance Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"All information in a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, is accurate as of the date the validation process was complete. The vLEI Credential has been issued to the legal entity or person named in the vLEI Credential as the subject; and the qualified vLEI Issuer exercised reasonable care to perform the validation process set forth in the vLEI Ecosystem Governance Framework."}}}},"additionalProperties":false,"required":["d","usageDisclaimer","issuanceDisclaimer"]}]}},"additionalProperties":false,"required":["i","ri","s","d","e","r"]} diff --git a/samples/oobis/.well-known/keri/oobi/EMhvwOlyEJ9kN4PrwCpr9Jsv7TxPhiYveZ0oP3lJzdEi/index.json b/samples/oobis/.well-known/keri/oobi/EMhvwOlyEJ9kN4PrwCpr9Jsv7TxPhiYveZ0oP3lJzdEi/index.json new file mode 100644 index 0000000..89741c9 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/EMhvwOlyEJ9kN4PrwCpr9Jsv7TxPhiYveZ0oP3lJzdEi/index.json @@ -0,0 +1 @@ +{"$id":"EMhvwOlyEJ9kN4PrwCpr9Jsv7TxPhiYveZ0oP3lJzdEi","$schema":"http://json-schema.org/draft-07/schema#","title":"iXBRL Data Value Attestation","description":"A data attestation against an iXBRL report, linked to either a vLEI OOR or vLEI ECR credential","credentialType":"iXBRLDataAttestation","properties":{"v":{"type":"string"},"d":{"type":"string"},"i":{"type":"string"},"ri":{"description":"credential status registry","type":"string"},"s":{"description":"schema SAID","type":"string"},"a":{"$id":"EDj-Pm8CNw80aA5djaobjhM__eFeAZIIkgo1-nfkB7M1","description":"data block","properties":{"d":{"type":"string"},"dt":{"description":"signed date time","format":"date-time","type":"string"},"rd":{"type":"string","description":"Digest of entire signed iXBRL report"},"f":{"description":"Signed facts of report","items":{"type":"object","properties":{"i":{"type":"string","description":"XBRL data element ID"},"t":{"type":"string","description":"XBRL element type (qname)"},"d":{"type":"string","description":"Digest of canonicalized XBRL attribute"},"v":{"type":"string","description":"Data value"},"f":{"type":"string","description":"Data type"},"c":{"type":"string","description":"XBRL Element Context"},"e":{"type":"string","description":"Unknown"},"p":{"type":"string","description":"Date range"}},"additionalProperties":false,"required":["i","t","d","v","c","e","p"]},"type":"array"}},"additionalProperties":false,"required":["d","dt","rd","f"],"type":"object"},"e":{"oneOf":[{"$id":"EGdpNTt_v5NAIhzWZjisHE5oaYnoJVOC7iVFySw9eFKX","description":"Chained vLEI OOR Credential","properties":{"d":{"description":"SAID of edge block containing OOR Credential node","type":"string"},"oor":{"description":"node SAID of signer OOR credential","properties":{"n":{"type":"string"},"s":{"type":"string","description":"SAID of required schema of the credential pointed to by this node","const":"EBNaNu-M9P5cgrnfl2Fvymy4E_jvxxyjb70PRtiANlJy"}},"additionalProperties":false,"required":["n","s"],"type":"object"}},"additionalProperties":false,"required":["d","oor"],"type":"object"},{"$id":"EO2AOkCvsjm5RyQYAPpUZP96pbXlPGym57VemjxlOlMe","description":"Chained vLEI ECR Credential","properties":{"d":{"description":"SAID of edge block contai0ning ECR Credential node","type":"string"},"ecr":{"description":"node SAID of signer ECR credential","properties":{"n":{"type":"string"},"s":{"type":"string","description":"SAID of required schema of the credential pointed to by this node","const":"EEy9PkikFcANV1l7EHukCeXqrzT1hNZjGlUk7wuMO5jw"}},"additionalProperties":false,"required":["n","s"],"type":"object"}},"additionalProperties":false,"required":["d","ecr"],"type":"object"}]}},"additionalProperties":false,"required":["i","ri","s","d","e"],"type":"object"} diff --git a/samples/oobis/.well-known/keri/oobi/ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY/index.json b/samples/oobis/.well-known/keri/oobi/ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY/index.json new file mode 100644 index 0000000..18f7b94 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY/index.json @@ -0,0 +1 @@ +{"$id":"ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY","$schema":"http://json-schema.org/draft-07/schema#","title":"Legal Entity vLEI Credential","description":"A vLEI Credential issued by a Qualified vLEI issuer to a Legal Entity","type":"object","credentialType":"LegalEntityvLEICredential","version":"1.0.0","properties":{"v":{"description":"Version","type":"string"},"d":{"description":"Credential SAID","type":"string"},"u":{"description":"One time use nonce","type":"string"},"i":{"description":"QVI Issuer AID","type":"string"},"ri":{"description":"Credential status registry","type":"string"},"s":{"description":"Schema SAID","type":"string"},"a":{"oneOf":[{"description":"Attributes block SAID","type":"string"},{"$id":"EJ6bFDLrv50bHmIDg-MSummpvYWsPa9CFygPUZyHoESj","description":"Attributes block","type":"object","properties":{"d":{"description":"Attributes block SAID","type":"string"},"i":{"description":"LE Issuer AID","type":"string"},"dt":{"description":"issuance date time","type":"string","format":"date-time"},"LEI":{"description":"LE Issuer AID","type":"string","format":"ISO 17442"}},"additionalProperties":false,"required":["i","dt","LEI"]}]},"e":{"oneOf":[{"description":"Edges block SAID","type":"string"},{"$id":"EDh9sp5cPk0-yo5sFMo6WJS1HMBYIOYCwJrnPvNaH1vI","description":"Edges block","type":"object","properties":{"d":{"description":"Edges block SAID","type":"string"},"qvi":{"description":"QVI node","type":"object","properties":{"n":{"description":"Issuer credential SAID","type":"string"},"s":{"description":"SAID of required schema of the credential pointed to by this node","type":"string","const":"EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao"}},"additionalProperties":false,"required":["n","s"]}},"additionalProperties":false,"required":["d","qvi"]}]},"r":{"oneOf":[{"description":"Rules block SAID","type":"string"},{"$id":"ECllqarpkZrSIWCb97XlMpEZZH3q4kc--FQ9mbkFMb_5","description":"Rules block","type":"object","properties":{"d":{"description":"Rules block SAID","type":"string"},"usageDisclaimer":{"description":"Usage Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"Usage of a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, does not assert that the Legal Entity is trustworthy, honest, reputable in its business dealings, safe to do business with, or compliant with any laws or that an implied or expressly intended purpose will be fulfilled."}}},"issuanceDisclaimer":{"description":"Issuance Disclaimer","type":"object","properties":{"l":{"description":"Associated legal language","type":"string","const":"All information in a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, is accurate as of the date the validation process was complete. The vLEI Credential has been issued to the legal entity or person named in the vLEI Credential as the subject; and the qualified vLEI Issuer exercised reasonable care to perform the validation process set forth in the vLEI Ecosystem Governance Framework."}}}},"additionalProperties":false,"required":["d","usageDisclaimer","issuanceDisclaimer"]}]}},"additionalProperties":false,"required":["i","ri","s","d","e","r"]} diff --git a/samples/oobis/.well-known/keri/oobi/EOxm1erpuJtjy9bBWO6Wgp9iggefDTNsM6DpO8-jUKbU/index.json b/samples/oobis/.well-known/keri/oobi/EOxm1erpuJtjy9bBWO6Wgp9iggefDTNsM6DpO8-jUKbU/index.json new file mode 100644 index 0000000..89a4dcf --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/EOxm1erpuJtjy9bBWO6Wgp9iggefDTNsM6DpO8-jUKbU/index.json @@ -0,0 +1 @@ +{"$schema":"http://json-schema.org/draft-07/schema#","$id":"EOxm1erpuJtjy9bBWO6Wgp9iggefDTNsM6DpO8-jUKbU","title":"Well-Known Resources Discovery","description":"JSON Schema for well-known resource discovery","type":"object","required":["name","description","version","updated","resources"],"properties":{"$id":{"type":"string","description":"Schema SAID"},"name":{"type":"string","description":"Display name for the well-known resources"},"description":{"type":"string","description":"Description of the well-known resources"},"version":{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$","description":"Semantic version of the discovery format"},"updated":{"type":"string","format":"date","description":"Last update date in YYYY-MM-DD format"},"resources":{"type":"object","description":"Available resource types","properties":{"aid":{"type":"object","description":"KERI identifiers and related resources","properties":{"name":{"type":"string","description":"Resource type name"},"description":{"type":"string","description":"Resource type description"},"aids":{"type":"object","description":"KERI identifiers","patternProperties":{"^[A-Za-z0-9_-]+$":{"type":"object","description":"KERI identifier entry","properties":{"name":{"type":"string","description":"Human-readable name for the identifier"},"oobi":{"type":"string","description":"Path to the OOBI for this identifier"}},"required":["name","oobi"],"additionalProperties":false}},"additionalProperties":false}},"required":["name","description","aids"],"additionalProperties":false},"schema":{"type":"object","description":"vLEI credential schema definitions","properties":{"name":{"type":"string","description":"Resource type name"},"description":{"type":"string","description":"Resource type description"},"$id":{"type":"string","description":"Schema resource identifier"},"schemas":{"type":"object","description":"Available schemas","patternProperties":{"^[A-Za-z0-9_-]+$":{"type":"object","description":"Schema definition entry","properties":{"title":{"type":"string","description":"Human-readable schema title"},"type":{"type":"string","description":"Schema credential type"},"version":{"type":"string","description":"Schema version"},"oobi":{"type":"string","description":"Path to the schema OOBI"}},"required":["title","type","version","oobi"],"additionalProperties":false}},"additionalProperties":false}},"required":["name","description","schemas"],"additionalProperties":false},"witness":{"type":"object","description":"KERI witness identifiers and their OOBIs","properties":{"name":{"type":"string","description":"Resource type name"},"description":{"type":"string","description":"Resource type description"},"$id":{"type":"string","description":"Witness resource identifier"},"witnesses":{"type":"object","description":"Available witnesses","patternProperties":{"^[A-Za-z0-9_-]+$":{"type":"object","description":"Witness OOBI entry","properties":{"oobi":{"type":"string","description":"Path to the witness OOBI"}},"required":["oobi"],"additionalProperties":false}},"additionalProperties":false}},"required":["name","description","witnesses"],"additionalProperties":false}},"additionalProperties":false},"metadata":{"type":"object","description":"Additional metadata about the resources","properties":{"$id":{"type":"string","description":"Metadata identifier"},"organization":{"type":"string","description":"Organization providing these resources"},"contact":{"type":"string","format":"uri","description":"Contact URL for the organization"},"documentation":{"type":"string","format":"uri","description":"Documentation URL"}},"required":["organization","contact","documentation"],"additionalProperties":false}},"additionalProperties":false} diff --git a/samples/oobis/.well-known/keri/oobi/index.json b/samples/oobis/.well-known/keri/oobi/index.json new file mode 100644 index 0000000..4508884 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/index.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://gleif-it.github.io/.well-known/keri/oobi/schema.json", + "aids": { + "GLEIF RoOT": "EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2", + "GLEIF External": "EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS", + "GLEIF Internal": "EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL" + }, + "witnesses": { + "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS": "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS", + "BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt": "BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt", + "BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo": "BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo", + "BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG": "BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG", + "BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X": "BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X", + "BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-": "BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-", + "BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw": "BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw", + "BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC": "BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC", + "BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj": "BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj", + "BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB": "BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB" + }, + "schemas": { + "LegalEntityvLEICredential": "ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY", + "QualifiedvLEIIssuervLEICredential": "EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao", + "OORAuthorizationvLEICredential": "EKA57bKBKxr_kN7iN5i7lMUxpMG-s19dRcmov1iDxz-E", + "ECRAuthorizationvLEICredential": "EH6ekLjSr8V32WyFbGe1zXjTzFs9PkTYmupJ9H65O14g", + "LegalEntityOfficialOrganizationalRolevLEICredential": "EBNaNu-M9P5cgrnfl2Fvymy4E_jvxxyjb70PRtiANlJy", + "LegalEntityEngagementContextRolevLEICredential": "EEy9PkikFcANV1l7EHukCeXqrzT1hNZjGlUk7wuMO5jw", + "iXBRLDataAttestation": "EMhvwOlyEJ9kN4PrwCpr9Jsv7TxPhiYveZ0oP3lJzdEi", + "iXBRLDataAttestationSchema": "EOxm1erpuJtjy9bBWO6Wgp9iggefDTNsM6DpO8-jUKbU" + } +} diff --git a/samples/oobis/.well-known/keri/oobi/schema.json b/samples/oobis/.well-known/keri/oobi/schema.json new file mode 100644 index 0000000..9fdcfa9 --- /dev/null +++ b/samples/oobis/.well-known/keri/oobi/schema.json @@ -0,0 +1,50 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://gleif-it.github.io/.well-known/keri/oobi/schema.json", + "title": "GLEIF KERI OOBI Index Schema", + "description": "JSON Schema for GLEIF KERI OOBI directory index structure", + "type": "object", + "required": ["aids", "witnesses", "schemas"], + "properties": { + "aids": { + "type": "object", + "description": "GLEIF Autonomic Identifiers (AIDs)", + "patternProperties": { + "^GLEIF .+$": { + "type": "string", + "description": "AID in CESR format (prefix E for Ed25519)", + "pattern": "^E[A-Za-z0-9_-]{43}$" + } + }, + "minProperties": 1, + "additionalProperties": false + }, + "witnesses": { + "type": "object", + "description": "KERI witness identifiers (self-referential key-value pairs)", + "patternProperties": { + "^B[A-Za-z0-9_-]{43}$": { + "type": "string", + "description": "Witness AID in CESR format (prefix B for Ed25519 non-transferable)", + "pattern": "^B[A-Za-z0-9_-]{43}$" + } + }, + "minProperties": 1, + "additionalProperties": false + }, + "schemas": { + "type": "object", + "description": "vLEI credential schema SAIDs mapped by credential type", + "patternProperties": { + "^.+vLEICredential$|^.+Attestation(Schema)?$": { + "type": "string", + "description": "Schema SAID in CESR format (prefix E for Blake3-256)", + "pattern": "^E[A-Za-z0-9_-]{43}$" + } + }, + "minProperties": 1, + "additionalProperties": false + } + }, + "additionalProperties": false +} diff --git a/samples/oobis/.well-known/schema.json b/samples/oobis/.well-known/schema.json new file mode 100644 index 0000000..9abdc6a --- /dev/null +++ b/samples/oobis/.well-known/schema.json @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://gleif-it.github.io/.well-known/schema.json", + "title": "GLEIF Well-Known Resources Schema", + "description": "JSON Schema for GLEIF .well-known directory structure", + "type": "object", + "required": ["$id", "name", "description", "version", "updated", "oobi", "aids", "schemas", "witnesses", "metadata"], + "properties": { + "$id": { + "type": "string", + "description": "Self-addressing identifier for this index", + "pattern": "^E[A-Za-z0-9_-]{43}$" + }, + "name": { + "type": "string", + "description": "Human-readable name for this resource collection" + }, + "description": { + "type": "string", + "description": "Description of the resources provided" + }, + "version": { + "type": "string", + "description": "Version of this index format", + "pattern": "^\\d+\\.\\d+\\.\\d+$" + }, + "updated": { + "type": "string", + "description": "Last update date in YYYY-MM-DD format", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$" + }, + "oobi": { + "type": "string", + "description": "Path to the KERI OOBI index", + "pattern": "^/keri/oobi/index\\.json$" + }, + "aids": { + "type": "object", + "description": "GLEIF Autonomic Identifiers", + "patternProperties": { + "^.+$": { + "type": "string", + "description": "AID in CESR format", + "pattern": "^E[A-Za-z0-9_-]{43}$" + } + }, + "minProperties": 1 + }, + "schemas": { + "type": "object", + "description": "vLEI credential schema identifiers", + "patternProperties": { + "^.+vLEICredential$|^.+Attestation(Schema)?$": { + "type": "string", + "description": "Schema SAID in CESR format", + "pattern": "^E[A-Za-z0-9_-]{43}$" + } + }, + "minProperties": 1 + }, + "witnesses": { + "type": "object", + "description": "KERI witness identifiers", + "patternProperties": { + "^B[A-Za-z0-9_-]{43}$": { + "type": "string", + "description": "Witness AID in CESR format (self-referential)", + "pattern": "^B[A-Za-z0-9_-]{43}$" + } + }, + "minProperties": 1 + }, + "metadata": { + "type": "object", + "description": "Additional metadata about this resource", + "required": ["organization", "contact", "documentation"], + "properties": { + "organization": { + "type": "string", + "description": "Organization name" + }, + "contact": { + "type": "string", + "format": "uri", + "description": "Contact URL" + }, + "documentation": { + "type": "string", + "format": "uri", + "description": "Documentation URL" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false +} diff --git a/samples/oobis/MIGRATION.md b/samples/oobis/MIGRATION.md new file mode 100644 index 0000000..48b5e1e --- /dev/null +++ b/samples/oobis/MIGRATION.md @@ -0,0 +1,122 @@ +# Migration to RFC 8615 Compliant Well-Known Structure + +## Summary + +The `samples/oobis/` directory has been restructured to follow the [GLEIF Well-Known URI Structure Specification](https://github.com/GLEIF-IT/GLEIF-IT.github.io/blob/main/.well-known/STRUCTURE.md) and [RFC 8615](https://www.rfc-editor.org/rfc/rfc8615.html). + +## Changes Made + +### Old Structure (Deprecated) +``` +samples/oobis/ +├── gleif-root # Plain text file with single OOBI URL +├── gleif-external # Plain text file with single OOBI URL +└── gleif-internal # Plain text file with single OOBI URL +``` + +**Backed up to**: `samples/oobis.old/` + +### New Structure (RFC 8615 Compliant) +``` +samples/oobis/.well-known/ +├── index.json # Main discovery index +├── schema.json # JSON Schema for validation +└── keri/ + └── oobi/ + ├── index.json # OOBI catalog + ├── schema.json # OOBI index schema + ├── EDP1vHcw_.../ # GLEIF Root AID + │ └── index.json # rpy message with witness URLs + ├── EINmHd5g_.../ # GLEIF External AID + │ └── index.json # rpy message with witness URLs + ├── EFcrtYzHx_.../ # GLEIF Internal AID + │ └── index.json # rpy message with witness URLs + ├── BDkq35LUU_.../ # Sample witness + │ └── index.json # Witness KEL (icp + rpy) + ├── ENPXp1vQz_.../ # LegalEntityvLEICredential schema + │ └── index.json # JSON Schema + └── EBfdlu8R2_.../ # QualifiedvLEIIssuervLEICredential schema + └── index.json # JSON Schema +``` + +## Benefits + +1. **RFC 8615 Compliance**: Uses standard `/.well-known/` path prefix +2. **Structured Discovery**: JSON indexes enable programmatic resource discovery +3. **Type Safety**: JSON Schema validation for all indexes +4. **Complete Resource Serving**: + - AIDs return full witness set in rpy messages + - Witnesses return complete KEL + - Schemas return full JSON Schema definitions +5. **Extensible**: Easy to add new AIDs, witnesses, or schemas + +## Implementation + +### New Python Module +- **`src/vlei/app/well_known.py`**: RFC 8615 compliant endpoint handler + - `WellKnownIndex`: Loads and queries index.json + - `WellKnownEnd`: Falcon endpoint handler + - `loadWellKnownEnds()`: Helper to register endpoints + +### Test Coverage +- **`tests/app/test_well_known.py`**: 15 unit tests with mocked data +- **`tests/app/test_well_known_samples.py`**: 12 integration tests with real GLEIF data + +All 27 tests pass. + +## Usage + +### Serving Well-Known Resources + +```python +from vlei.app.well_known import loadWellKnownEnds +import falcon + +app = falcon.App() +oobi_dir = "./samples/oobis/.well-known/keri/oobi" +loadWellKnownEnds(app, oobi_dir) +``` + +### Discovery Examples + +```bash +# Discover all resources +curl http://localhost:7723/.well-known/index.json + +# Discover KERI OOBIs +curl http://localhost:7723/.well-known/keri/oobi/index.json + +# Get GLEIF Root witness URLs +curl http://localhost:7723/.well-known/keri/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/index.json + +# Get witness KEL +curl http://localhost:7723/.well-known/keri/oobi/BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS/index.json + +# Get Legal Entity schema +curl http://localhost:7723/.well-known/keri/oobi/ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY/index.json +``` + +## Content Types + +The handler returns appropriate content types based on identifier type: + +| Type | Content-Type | Description | +|------|-------------|-------------| +| AID | `application/cesr` | KERI rpy message with witness URLs | +| Witness | `application/cesr` | Witness KEL (icp + rpy messages) | +| Schema | `application/cesr` | ACDC JSON Schema | + +Note: When content is valid JSON, `application/json+cesr` may be used. + +## Source Data + +All content copied from the live GLEIF implementation: +- Repository: https://github.com/GLEIF-IT/GLEIF-IT.github.io/tree/main/.well-known +- Live site: https://gleif-it.github.io/.well-known/ + +## References + +- [GLEIF Well-Known Structure Spec](https://github.com/GLEIF-IT/GLEIF-IT.github.io/blob/main/.well-known/STRUCTURE.md) +- [GLEIF Well-Known Schema Spec](https://github.com/GLEIF-IT/GLEIF-IT.github.io/blob/main/.well-known/SCHEMA.md) +- [RFC 8615: Well-Known URIs](https://www.rfc-editor.org/rfc/rfc8615.html) +- [KERI Specification](https://trustoverip.github.io/kswg-keri-specification/) diff --git a/samples/oobis/README.md b/samples/oobis/README.md new file mode 100644 index 0000000..b8c24cb --- /dev/null +++ b/samples/oobis/README.md @@ -0,0 +1,132 @@ +# vLEI Well-Known OOBI Samples + +This directory contains sample KERI well-known OOBI resources following the [GLEIF Well-Known URI Structure Specification](https://github.com/GLEIF-IT/GLEIF-IT.github.io/blob/main/.well-known/STRUCTURE.md) and [RFC 8615](https://www.rfc-editor.org/rfc/rfc8615.html). + +## Directory Structure + +``` +.well-known/ +├── index.json # Main discovery index +├── schema.json # JSON Schema for index.json validation +└── keri/ + └── oobi/ + ├── index.json # OOBI catalog (AIDs, witnesses, schemas) + ├── schema.json # JSON Schema for OOBI index validation + ├── {aid}/ # AID directories (E prefix) + │ └── index.json # KERI rpy message with witness URLs + ├── {witness}/ # Witness directories (B prefix) + │ └── index.json # Witness KEL (icp + rpy messages) + └── {schema}/ # Schema directories (E prefix) + └── index.json # ACDC JSON Schema +``` + +## Resource Types + +### AIDs (Autonomic Identifiers) +- **Prefix**: `E` (transferable) +- **Example**: `EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2` +- **Content**: KERI `rpy` message containing witness OOBI URLs +- **Content-Type**: `application/json+cesr` or `application/cesr` + +### Witnesses +- **Prefix**: `B` (non-transferable) +- **Example**: `BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS` +- **Content**: Witness KEL (inception event + location scheme + endpoint role) +- **Content-Type**: `application/cesr` + +### Schemas +- **Prefix**: `E` (SAID) +- **Example**: `ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY` +- **Content**: ACDC JSON Schema +- **Content-Type**: `application/cesr` or `application/schema+json` + +## Discovery Protocol + +### 1. Discover Main Index +```bash +curl https://example.org/.well-known/index.json +``` + +Returns metadata and references to AIDs, witnesses, and schemas. + +### 2. Discover OOBI Catalog +```bash +curl https://example.org/.well-known/keri/oobi/index.json +``` + +Returns flat map of all identifiers by type. + +### 3. Resolve Specific Resource +```bash +# Get GLEIF Root AID witness URLs +curl https://example.org/.well-known/keri/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/index.json + +# Get witness KEL +curl https://example.org/.well-known/keri/oobi/BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS/index.json + +# Get schema +curl https://example.org/.well-known/keri/oobi/ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY/index.json +``` + +## Sample Resources Included + +### AIDs (3 total) +- **GLEIF RoOT**: `EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2` +- **GLEIF External**: `EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS` +- **GLEIF Internal**: `EFcrtYzHx11TElxDmEDx355zm7nJhbmdcIluw7UMbUIL` + +### Witnesses (10 total - complete GLEIF production witness set) +- `BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS` +- `BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt` +- `BFl6k3UznzmEVuMpBOtUUiR2RO2NZkR3mKrZkNRaZedo` +- `BGYJwPAzjyJgsipO7GY9ZsBTeoUJrdzjI2w_5N-Nl6gG` +- `BHxz8CDS_mNxAhAxQe1qxdEIzS625HoYgEMgqjZH_g2X` +- `BICY3-X3S3iEsKH73Q1fF_w1JrXJ41V0c4Dn9aQjOSQ-` +- `BLmvLSt1mDShWS67aJNP4gBVBhtOc3YEu8SytqVSsyfw` +- `BLo6wQR73-eH5v90at_Wt8Ep_0xfz05qBjM3_B1UtKbC` +- `BM4Ef3zlUzIAIx-VC8mXziIbtj-ZltM8Aor6TZzmTldj` +- `BNfDO63ZpGc3xiFb0-jIOUnbr_bA-ixMva5cZb3s4BHB` + +### Schemas (8 total - complete vLEI schema set) +- **LegalEntityvLEICredential**: `ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY` +- **QualifiedvLEIIssuervLEICredential**: `EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao` +- **OORAuthorizationvLEICredential**: `EKA57bKBKxr_kN7iN5i7lMUxpMG-s19dRcmov1iDxz-E` +- **ECRAuthorizationvLEICredential**: `EH6ekLjSr8V32WyFbGe1zXjTzFs9PkTYmupJ9H65O14g` +- **LegalEntityOfficialOrganizationalRolevLEICredential**: `EBNaNu-M9P5cgrnfl2Fvymy4E_jvxxyjb70PRtiANlJy` +- **LegalEntityEngagementContextRolevLEICredential**: `EEy9PkikFcANV1l7EHukCeXqrzT1hNZjGlUk7wuMO5jw` +- **iXBRLDataAttestation**: `EMhvwOlyEJ9kN4PrwCpr9Jsv7TxPhiYveZ0oP3lJzdEi` +- **iXBRLDataAttestationSchema**: `EOxm1erpuJtjy9bBWO6Wgp9iggefDTNsM6DpO8-jUKbU` + +## Testing with the vLEI Server + +The vLEI server includes a `WellKnownEnd` handler that serves these resources: + +```python +from vlei.app.well_known import loadWellKnownEnds + +# In your server setup +oobi_dir = "./samples/oobis/.well-known/keri/oobi" +loadWellKnownEnds(app, oobi_dir) +``` + +## References + +- [GLEIF Well-Known Implementation](https://github.com/GLEIF-IT/GLEIF-IT.github.io/tree/main/.well-known) +- [GLEIF Live Site](https://gleif-it.github.io/.well-known/) +- [RFC 8615: Well-Known URIs](https://www.rfc-editor.org/rfc/rfc8615.html) +- [KERI Specification](https://trustoverip.github.io/kswg-keri-specification/) +- [CESR Specification](https://trustoverip.github.io/kswg-cesr-specification/) + +## Migration from Old Format + +The old `samples/oobis/` directory contained simple text files with OOBI URLs: +- `gleif-root` → URL string +- `gleif-external` → URL string +- `gleif-internal` → URL string + +The new structure provides: +- Full RFC 8615 compliance with `/.well-known/` path prefix +- Structured JSON indexes for discovery +- Per-identifier directories with KERI message content +- JSON Schema validation +- Support for AIDs, witnesses, and schemas diff --git a/src/vlei/app/serving.py b/src/vlei/app/serving.py index 9322205..9758830 100644 --- a/src/vlei/app/serving.py +++ b/src/vlei/app/serving.py @@ -11,7 +11,7 @@ from keri import help from keri.help import nowIso8601 -from vlei.app import caching +from vlei.app import caching, well_known logger = help.ogler.getLogger() @@ -48,38 +48,6 @@ def on_get(self, _, rep, said): rep.data = data.encode("utf-8") return - -class WellKnownEnd: - """ - Returns well known OOBI URLs on HTTP GET in the Location header as a HTTP 301 redirect. - The well known OOBI URLs are text files stored in the directory specified by the oobiDir argument. - The file name is the alias of the well known OOBI and the content of the file is the URL. - """ - def __init__(self, oobiDir): - self.oobiDir = oobiDir - for root, dirs, files in os.walk(oobiDir): - for file in files: - p = Path(oobiDir, file) - url = p.open().read() - logger.info(f"serving well known {file}") - logger.debug(url) - - def on_get(self, req, rep, alias): - """ - Returns the URL of the well known OOBI in the Location header as a HTTP 301 redirect - - Parameters: - req (Request): HTTP Request Object - rep (Response): HTTP Response Object - alias (str): Alias of Well-Known OOBI - """ - p = Path(self.oobiDir, alias) - if not p.exists(): - raise falcon.HTTPBadRequest(title="Unknown well known") - - url = p.open().read() - raise falcon.HTTPMovedPermanently(location=url) - class HealthEnd: """Health resource for determining that a container is live""" @@ -94,8 +62,7 @@ def loadEnds(app, schemaDir, credDir, oobiDir): schemaEnd = ACDCMaterialEnd(schemaDir=schemaDir, credDir=credDir) app.add_route("/oobi/{said}", schemaEnd) - wellknownEnd = WellKnownEnd(oobiDir) - app.add_route("/.well-known/keri/oobi/{alias}", wellknownEnd) + well_known.loadWellKnownEnds(app, oobiDir) healthEnd = HealthEnd() app.add_route("/health", healthEnd) diff --git a/src/vlei/app/well_known.py b/src/vlei/app/well_known.py new file mode 100644 index 0000000..10cb3a4 --- /dev/null +++ b/src/vlei/app/well_known.py @@ -0,0 +1,321 @@ +# -*- encoding: utf-8 -*- +""" +vLEI.app.well_known module + +Well-Known KERI OOBI endpoint handler compliant with RFC 8615. + +This module implements a well-known endpoint handler that serves KERI resources +based on the identifier type: +- Witnesses (B prefix): HTTP 301 redirect to witness OOBI URL +- Schemas (E prefix in schemas): Schema CESR stream in body +- AIDs (E prefix in aids): KEL CESR stream in body + +The handler uses an index.json file to determine the identifier type and +locate the appropriate resource files. + +Reference: https://github.com/GLEIF-IT/GLEIF-IT.github.io/tree/main/.well-known +""" +import json +import os +from pathlib import Path +from typing import Optional + +import falcon +from keri import help + +logger = help.ogler.getLogger() + + +class WellKnownIndex: + """ + Manages the well-known index.json and provides lookup functionality. + + The index.json structure follows the GLEIF specification: + { + "$schema": "...", + "aids": { "Human Name": "AID_PREFIX", ... }, + "witnesses": { "WIT_PREFIX": "WIT_PREFIX", ... }, + "schemas": { "Schema Name": "SCHEMA_SAID", ... } + } + """ + + def __init__(self, index_path: str): + """ + Initialize the well-known index from an index.json file. + + Parameters: + index_path (str): Path to the index.json file + """ + self.index_path = index_path + self.aids: dict[str, str] = {} + self.witnesses: dict[str, str] = {} + self.schemas: dict[str, str] = {} + self._aid_lookup: set[str] = set() + self._witness_lookup: set[str] = set() + self._schema_lookup: set[str] = set() + + self._load_index() + + def _load_index(self): + """Load and parse the index.json file.""" + if not os.path.exists(self.index_path): + logger.warning(f"Well-known index not found at {self.index_path}") + return + + try: + with open(self.index_path, 'r') as f: + data = json.load(f) + + self.aids = data.get("aids", {}) + self.witnesses = data.get("witnesses", {}) + self.schemas = data.get("schemas", {}) + + # Build reverse lookup sets for efficient identifier matching + self._aid_lookup = set(self.aids.values()) + self._witness_lookup = set(self.witnesses.values()) + self._schema_lookup = set(self.schemas.values()) + + logger.info(f"Loaded well-known index: {len(self.aids)} AIDs, " + f"{len(self.witnesses)} witnesses, {len(self.schemas)} schemas") + + except json.JSONDecodeError as e: + logger.error(f"Failed to parse well-known index: {e}") + except Exception as e: + logger.error(f"Failed to load well-known index: {e}") + + def is_witness(self, identifier: str) -> bool: + """Check if identifier is a witness (typically B prefix).""" + return identifier in self._witness_lookup + + def is_schema(self, identifier: str) -> bool: + """Check if identifier is a schema SAID.""" + return identifier in self._schema_lookup + + def is_aid(self, identifier: str) -> bool: + """Check if identifier is an AID.""" + return identifier in self._aid_lookup + + def get_type(self, identifier: str) -> Optional[str]: + """ + Determine the type of identifier. + + Returns: + 'witness', 'schema', 'aid', or None if not found + """ + if self.is_witness(identifier): + return 'witness' + if self.is_schema(identifier): + return 'schema' + if self.is_aid(identifier): + return 'aid' + return None + + +class WellKnownEnd: + """ + RFC 8615 compliant well-known KERI OOBI endpoint handler. + + Serves KERI resources from /.well-known/keri/oobi/{identifier} based on + the identifier type: + + - Witnesses: KERI rpy message with complete witness set (application/json+cesr) + - Schemas: Schema CESR stream in response body (application/cesr) + - AIDs: KEL CESR stream in response body (application/cesr) + + Directory structure expected: + {oobi_dir}/ + ├── index.json # Index of all identifiers + └── {identifier}/ # Per-identifier directories + └── index.json # KERI rpy message or CESR content + """ + + CONTENT_TYPE_CESR = "application/cesr" + CONTENT_TYPE_JSON_CESR = "application/json+cesr" + + def __init__(self, oobi_dir: str): + """ + Initialize the well-known endpoint handler. + + Parameters: + oobi_dir (str): Path to the well-known/keri/oobi directory + """ + if "keri/oobi" not in oobi_dir: + oobi_dir = os.path.join(oobi_dir, "keri", "oobi") + self.oobi_dir = oobi_dir + self.index = WellKnownIndex(os.path.join(oobi_dir, "index.json")) + + logger.info(f"WellKnownEnd initialized with directory: {oobi_dir}") + + def on_get(self, req, rep, identifier: str): + """ + Handle GET requests for well-known KERI resources. + Assumes the "keri/oobi" path segment is already included in the self.oobi_dir. + + Parameters: + req (Request): Falcon HTTP Request object + rep (Response): Falcon HTTP Response object + identifier (str): KERI identifier (AID, witness ID, or schema SAID) + """ + # Determine identifier type from index + id_type = self.index.get_type(identifier) + + if id_type is None: + # Identifier not found in index - check if directory exists anyway + id_dir = Path(self.oobi_dir, identifier) + if not id_dir.exists(): + raise falcon.HTTPNotFound( + title="Unknown Identifier", + description=f"Identifier {identifier} not found in well-known index" + ) + # If directory exists but not in index, try to serve as generic CESR + id_type = self._infer_type_from_prefix(identifier) + + # Get the resource file path + resource_path = Path(self.oobi_dir, identifier, "index.json") + if not resource_path.exists(): + raise falcon.HTTPNotFound( + title="Resource Not Found", + description=f"Resource file not found for identifier {identifier}" + ) + + # Handle based on type + if id_type == 'witness': + self._handle_witness(req, rep, identifier, resource_path) + elif id_type == 'schema': + self._handle_schema(req, rep, identifier, resource_path) + elif id_type == 'aid': + self._handle_aid(req, rep, identifier, resource_path) + else: + # Unknown type - serve raw content + self._handle_generic(req, rep, identifier, resource_path) + + def _infer_type_from_prefix(self, identifier: str) -> str: + """ + Infer identifier type from CESR prefix when not in index. + + CESR prefixes: + - B: Non-transferable identifier (typically witnesses) + - E: Transferable identifier or SAID (AIDs, schemas) + """ + if identifier.startswith('B'): + return 'witness' + elif identifier.startswith('E'): + # Could be AID or schema - default to AID + return 'aid' + return 'unknown' + + def _handle_witness(self, req, rep, identifier: str, resource_path: Path): + """ + Handle witness identifier - return rpy message with witness URLs. + + The witness resource file contains a KERI rpy message with the complete + witness set for an AID. We return the entire rpy message so the caller + can discover all witnesses, not just the first one. + + Returns HTTP 200 with the rpy message in the body. + """ + try: + with open(resource_path, 'r') as f: + content = f.read().strip() + + # Try to parse as JSON to validate it's a proper rpy message + try: + rpy_data = json.loads(content) + # Return the rpy message as JSON+CESR + rep.status = falcon.HTTP_200 + rep.content_type = self.CONTENT_TYPE_JSON_CESR + rep.text = content + except json.JSONDecodeError: + # Not JSON - might be raw CESR, serve as-is + with open(resource_path, 'rb') as f: + rep.status = falcon.HTTP_200 + rep.content_type = self.CONTENT_TYPE_CESR + rep.data = f.read() + + except Exception as e: + logger.error(f"Error handling witness {identifier}: {e}") + raise falcon.HTTPInternalServerError( + title="Error", + description=f"Failed to process witness resource: {e}" + ) + + def _handle_schema(self, req, rep, identifier: str, resource_path: Path): + """ + Handle schema identifier - return schema CESR stream in body. + + Content-Type: application/cesr + """ + try: + with open(resource_path, 'rb') as f: + content = f.read() + + rep.status = falcon.HTTP_200 + rep.content_type = self.CONTENT_TYPE_CESR + rep.data = content + + except Exception as e: + logger.error(f"Error handling schema {identifier}: {e}") + raise falcon.HTTPInternalServerError( + title="Error", + description=f"Failed to process schema resource: {e}" + ) + + def _handle_aid(self, req, rep, identifier: str, resource_path: Path): + """ + Handle AID identifier - return KEL CESR stream in body. + + Content-Type: application/cesr + """ + try: + with open(resource_path, 'rb') as f: + content = f.read() + + rep.status = falcon.HTTP_200 + rep.content_type = self.CONTENT_TYPE_CESR + rep.data = content + + except Exception as e: + logger.error(f"Error handling AID {identifier}: {e}") + raise falcon.HTTPInternalServerError( + title="Error", + description=f"Failed to process AID resource: {e}" + ) + + def _handle_generic(self, req, rep, identifier: str, resource_path: Path): + """ + Handle unknown identifier type - serve raw content as CESR. + """ + try: + with open(resource_path, 'rb') as f: + content = f.read() + + rep.status = falcon.HTTP_200 + rep.content_type = self.CONTENT_TYPE_CESR + rep.data = content + + except Exception as e: + logger.error(f"Error handling generic identifier {identifier}: {e}") + raise falcon.HTTPInternalServerError( + title="Error", + description=f"Failed to process resource: {e}" + ) + + +def loadWellKnownEnds(app, oobi_dir: str, prefix: str = ""): + """ + Load well-known KERI OOBI endpoints into a Falcon app. + + Parameters: + app: Falcon application instance + oobi_dir (str): Path to the well-known/keri/oobi directory + prefix (str): Optional URL prefix + + Returns: + WellKnownEnd: The endpoint instance for testing/inspection + """ + well_known_end = WellKnownEnd(oobi_dir) + app.add_route(prefix + "/.well-known/keri/oobi/{identifier}", well_known_end) + + logger.info(f"Loaded well-known endpoint at {prefix}/.well-known/keri/oobi/{{identifier}}") + + return well_known_end diff --git a/tests/app/__init__.py b/tests/app/__init__.py new file mode 100644 index 0000000..fff0b30 --- /dev/null +++ b/tests/app/__init__.py @@ -0,0 +1,4 @@ +# -*- encoding: utf-8 -*- +""" +vLEI tests.app package +""" diff --git a/tests/app/test_well_known.py b/tests/app/test_well_known.py new file mode 100644 index 0000000..231d9c5 --- /dev/null +++ b/tests/app/test_well_known.py @@ -0,0 +1,310 @@ +# -*- encoding: utf-8 -*- +""" +Tests for the well_known module. + +Tests the WellKnownEnd handler and WellKnownIndex lookup functionality. +""" +import json +import os +import tempfile +import shutil +from pathlib import Path + +import falcon +import falcon.testing +import pytest + +from vlei.app.well_known import WellKnownEnd, WellKnownIndex, loadWellKnownEnds + + +# Test data - simulating GLEIF-style well-known structure +SAMPLE_INDEX = { + "$schema": "https://example.org/.well-known/keri/oobi/schema.json", + "aids": { + "Test Root": "EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2", + "Test External": "EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS", + }, + "witnesses": { + "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS": "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS", + "BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt": "BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt", + }, + "schemas": { + "LegalEntityvLEICredential": "ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY", + "QualifiedvLEIIssuervLEICredential": "EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao", + } +} + +# Sample witness rpy message with URLs +SAMPLE_WITNESS_RPY = { + "v": "KERI10JSON000282_", + "t": "rpy", + "d": "EPflJSbTCs2WKoGx4zIJ5OpOXHXuY0JE9et9ile2gMpv", + "dt": "2022-11-21T21:20:24.003241+00:00", + "r": "/oobi/witness", + "a": { + "urls": [ + "http://witness1.example.com:5623/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/witness", + "http://witness2.example.com:5623/oobi/EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2/witness", + ], + "aid": "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS" + } +} + +# Sample KEL content (simplified for testing) +SAMPLE_KEL_CESR = b'{"v":"KERI10JSON000159_","t":"icp","d":"EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2"}' + +# Sample schema CESR content +SAMPLE_SCHEMA_CESR = b'{"$id":"ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY","$schema":"http://json-schema.org/draft-07/schema#"}' + + +@pytest.fixture +def well_known_dir(): + """Create a temporary well-known directory structure for testing.""" + tmpdir = tempfile.mkdtemp() + oobi_dir = os.path.join(tmpdir, ".well-known", "keri", "oobi") + os.makedirs(oobi_dir) + + # Write index.json + with open(os.path.join(oobi_dir, "index.json"), 'w') as f: + json.dump(SAMPLE_INDEX, f) + + # Create witness directory with rpy message + witness_id = "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS" + witness_dir = os.path.join(oobi_dir, witness_id) + os.makedirs(witness_dir) + with open(os.path.join(witness_dir, "index.json"), 'w') as f: + json.dump(SAMPLE_WITNESS_RPY, f) + + # Create AID directory with KEL + aid_id = "EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2" + aid_dir = os.path.join(oobi_dir, aid_id) + os.makedirs(aid_dir) + with open(os.path.join(aid_dir, "index.json"), 'wb') as f: + f.write(SAMPLE_KEL_CESR) + + # Create schema directory with schema CESR + schema_id = "ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY" + schema_dir = os.path.join(oobi_dir, schema_id) + os.makedirs(schema_dir) + with open(os.path.join(schema_dir, "index.json"), 'wb') as f: + f.write(SAMPLE_SCHEMA_CESR) + + yield oobi_dir + + # Cleanup + shutil.rmtree(tmpdir) + + +@pytest.fixture +def client(well_known_dir): + """Create a Falcon test client with the well-known endpoint.""" + app = falcon.App() + loadWellKnownEnds(app, well_known_dir) + return falcon.testing.TestClient(app) + + +class TestWellKnownIndex: + """Tests for WellKnownIndex class.""" + + def test_load_index(self, well_known_dir): + """Test loading index.json file.""" + index_path = os.path.join(well_known_dir, "index.json") + index = WellKnownIndex(index_path) + + assert len(index.aids) == 2 + assert len(index.witnesses) == 2 + assert len(index.schemas) == 2 + + def test_is_witness(self, well_known_dir): + """Test witness identification.""" + index_path = os.path.join(well_known_dir, "index.json") + index = WellKnownIndex(index_path) + + assert index.is_witness("BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS") is True + assert index.is_witness("BDwydI_FJJ-tvAtCl1tIu_VQqYTI3Q0JyHDhO1v2hZBt") is True + assert index.is_witness("EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2") is False + + def test_is_schema(self, well_known_dir): + """Test schema identification.""" + index_path = os.path.join(well_known_dir, "index.json") + index = WellKnownIndex(index_path) + + assert index.is_schema("ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY") is True + assert index.is_schema("EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao") is True + assert index.is_schema("BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS") is False + + def test_is_aid(self, well_known_dir): + """Test AID identification.""" + index_path = os.path.join(well_known_dir, "index.json") + index = WellKnownIndex(index_path) + + assert index.is_aid("EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2") is True + assert index.is_aid("EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS") is True + assert index.is_aid("BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS") is False + + def test_get_type(self, well_known_dir): + """Test identifier type resolution.""" + index_path = os.path.join(well_known_dir, "index.json") + index = WellKnownIndex(index_path) + + assert index.get_type("BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS") == "witness" + assert index.get_type("ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY") == "schema" + assert index.get_type("EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2") == "aid" + assert index.get_type("unknown_identifier") is None + + def test_missing_index_file(self): + """Test handling of missing index.json.""" + index = WellKnownIndex("/nonexistent/path/index.json") + + assert len(index.aids) == 0 + assert len(index.witnesses) == 0 + assert len(index.schemas) == 0 + + +class TestWellKnownEnd: + """Tests for WellKnownEnd HTTP handler.""" + + def test_witness_rpy_response(self, client): + """Test that witness requests return rpy message with witness URLs.""" + witness_id = "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS" + response = client.simulate_get(f"/.well-known/keri/oobi/{witness_id}") + + assert response.status == falcon.HTTP_200 + assert response.content_type == "application/json+cesr" + + # Parse the rpy message + rpy_data = json.loads(response.text) + assert rpy_data["t"] == "rpy" + assert "urls" in rpy_data["a"] + assert len(rpy_data["a"]["urls"]) == 2 # Both witness URLs present + assert "witness1.example.com" in rpy_data["a"]["urls"][0] + assert "witness2.example.com" in rpy_data["a"]["urls"][1] + + def test_schema_cesr_response(self, client): + """Test that schema requests return CESR in body.""" + schema_id = "ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY" + response = client.simulate_get(f"/.well-known/keri/oobi/{schema_id}") + + assert response.status == falcon.HTTP_200 + assert response.content_type == "application/cesr" + assert b"$schema" in response.content + + def test_aid_cesr_response(self, client): + """Test that AID requests return KEL CESR in body.""" + aid_id = "EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2" + response = client.simulate_get(f"/.well-known/keri/oobi/{aid_id}") + + assert response.status == falcon.HTTP_200 + assert response.content_type == "application/cesr" + assert b"icp" in response.content # Inception event marker + + def test_unknown_identifier_404(self, client): + """Test that unknown identifiers return 404.""" + response = client.simulate_get("/.well-known/keri/oobi/unknown_identifier") + + assert response.status == falcon.HTTP_404 + + def test_identifier_not_in_index_but_dir_exists(self, well_known_dir): + """Test handling of identifier with directory but not in index.""" + # Create a directory for an identifier not in the index + unknown_id = "EUnknownIdentifier_NotInIndex_ButHasDirectory" + unknown_dir = os.path.join(well_known_dir, unknown_id) + os.makedirs(unknown_dir) + with open(os.path.join(unknown_dir, "index.json"), 'wb') as f: + f.write(b'{"test": "data"}') + + # Create client with updated directory + app = falcon.App() + loadWellKnownEnds(app, well_known_dir) + client = falcon.testing.TestClient(app) + + # Should serve the content even if not in index (infers type from prefix) + response = client.simulate_get(f"/.well-known/keri/oobi/{unknown_id}") + + # E prefix infers as AID, returns CESR + assert response.status == falcon.HTTP_200 + assert response.content_type == "application/cesr" + + +class TestWellKnownEndEdgeCases: + """Edge case tests for WellKnownEnd.""" + + def test_witness_no_urls_in_rpy(self, well_known_dir): + """Test witness with empty URLs in rpy message still returns rpy message.""" + # Create witness with no URLs + witness_id = "BNoUrlsWitness_TestIdentifier_ForEmptyUrls" + witness_dir = os.path.join(well_known_dir, witness_id) + os.makedirs(witness_dir) + + empty_rpy = {"v": "KERI10JSON", "t": "rpy", "a": {"urls": [], "aid": witness_id}} + with open(os.path.join(witness_dir, "index.json"), 'w') as f: + json.dump(empty_rpy, f) + + # Add to index + index_path = os.path.join(well_known_dir, "index.json") + with open(index_path, 'r') as f: + index_data = json.load(f) + index_data["witnesses"][witness_id] = witness_id + with open(index_path, 'w') as f: + json.dump(index_data, f) + + # Create fresh client + app = falcon.App() + loadWellKnownEnds(app, well_known_dir) + client = falcon.testing.TestClient(app) + + response = client.simulate_get(f"/.well-known/keri/oobi/{witness_id}") + + # Should return the rpy message as JSON+CESR with empty URLs array + assert response.status == falcon.HTTP_200 + assert response.content_type == "application/json+cesr" + + rpy_data = json.loads(response.text) + assert rpy_data["a"]["urls"] == [] + + def test_resource_file_missing(self, well_known_dir): + """Test handling when identifier directory exists but index.json is missing.""" + # Create directory without index.json + orphan_id = "EOrphanDirectory_NoIndexJson_ShouldFail" + orphan_dir = os.path.join(well_known_dir, orphan_id) + os.makedirs(orphan_dir) + + # Add to index but don't create the file + index_path = os.path.join(well_known_dir, "index.json") + with open(index_path, 'r') as f: + index_data = json.load(f) + index_data["aids"]["Orphan"] = orphan_id + with open(index_path, 'w') as f: + json.dump(index_data, f) + + app = falcon.App() + loadWellKnownEnds(app, well_known_dir) + client = falcon.testing.TestClient(app) + + response = client.simulate_get(f"/.well-known/keri/oobi/{orphan_id}") + + assert response.status == falcon.HTTP_404 + + +class TestLoadWellKnownEnds: + """Tests for the loadWellKnownEnds helper function.""" + + def test_load_returns_endpoint(self, well_known_dir): + """Test that loadWellKnownEnds returns the endpoint instance.""" + app = falcon.App() + endpoint = loadWellKnownEnds(app, well_known_dir) + + assert isinstance(endpoint, WellKnownEnd) + assert endpoint.oobi_dir == well_known_dir + + def test_load_with_prefix(self, well_known_dir): + """Test loading with URL prefix.""" + app = falcon.App() + endpoint = loadWellKnownEnds(app, well_known_dir, prefix="/api/v1") + client = falcon.testing.TestClient(app) + + # Should work with prefix + aid_id = "EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2" + response = client.simulate_get(f"/api/v1/.well-known/keri/oobi/{aid_id}") + + assert response.status == falcon.HTTP_200 diff --git a/tests/app/test_well_known_samples.py b/tests/app/test_well_known_samples.py new file mode 100644 index 0000000..b849e13 --- /dev/null +++ b/tests/app/test_well_known_samples.py @@ -0,0 +1,216 @@ +# -*- encoding: utf-8 -*- +""" +Integration tests for well_known module using the samples/oobis directory. + +Tests that the WellKnownEnd handler correctly serves the GLEIF-style +well-known structure from samples/oobis/.well-known/ +""" +import json +import os +from pathlib import Path + +import falcon +import falcon.testing +import pytest + +from vlei.app.well_known import WellKnownEnd, WellKnownIndex, loadWellKnownEnds + + +@pytest.fixture +def samples_oobi_dir(): + """Get the path to the samples/oobis/.well-known/keri/oobi directory.""" + # Get the vLEI project root (3 levels up from tests/app/) + test_dir = Path(__file__).parent + project_root = test_dir.parent.parent + oobi_dir = project_root / "samples" / "oobis" / ".well-known" / "keri" / "oobi" + + if not oobi_dir.exists(): + pytest.skip(f"Samples directory not found at {oobi_dir}") + + return str(oobi_dir) + + +@pytest.fixture +def samples_client(samples_oobi_dir): + """Create a Falcon test client with the samples well-known endpoint.""" + app = falcon.App() + loadWellKnownEnds(app, samples_oobi_dir) + return falcon.testing.TestClient(app) + + +class TestSamplesWellKnownIndex: + """Test WellKnownIndex with the samples directory.""" + + def test_load_gleif_index(self, samples_oobi_dir): + """Test loading the GLEIF-style index.json.""" + index_path = os.path.join(samples_oobi_dir, "index.json") + index = WellKnownIndex(index_path) + + # Verify GLEIF AIDs are loaded + assert "GLEIF RoOT" in index.aids + assert "GLEIF External" in index.aids + assert "GLEIF Internal" in index.aids + + # Verify witness identifiers + assert "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS" in index.witnesses + + # Verify schema SAIDs + assert "LegalEntityvLEICredential" in index.schemas + assert "QualifiedvLEIIssuervLEICredential" in index.schemas + + def test_gleif_root_is_aid(self, samples_oobi_dir): + """Test that GLEIF Root is identified as an AID.""" + index_path = os.path.join(samples_oobi_dir, "index.json") + index = WellKnownIndex(index_path) + + gleif_root = "EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2" + assert index.is_aid(gleif_root) is True + assert index.get_type(gleif_root) == "aid" + + def test_witness_identification(self, samples_oobi_dir): + """Test witness identifier detection.""" + index_path = os.path.join(samples_oobi_dir, "index.json") + index = WellKnownIndex(index_path) + + witness_id = "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS" + assert index.is_witness(witness_id) is True + assert index.get_type(witness_id) == "witness" + + def test_schema_identification(self, samples_oobi_dir): + """Test schema SAID detection.""" + index_path = os.path.join(samples_oobi_dir, "index.json") + index = WellKnownIndex(index_path) + + schema_said = "ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY" + assert index.is_schema(schema_said) is True + assert index.get_type(schema_said) == "schema" + + +class TestSamplesWellKnownEnd: + """Test WellKnownEnd HTTP handler with samples directory.""" + + def test_gleif_root_aid_response(self, samples_client): + """Test fetching GLEIF Root AID returns rpy message with witness URLs.""" + aid_id = "EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2" + response = samples_client.simulate_get(f"/.well-known/keri/oobi/{aid_id}") + + assert response.status == falcon.HTTP_200 + assert response.content_type == "application/cesr" + + # Verify it contains KERI rpy message + content = response.text + assert "rpy" in content + assert "witness" in content + assert aid_id in content + + def test_gleif_external_aid_response(self, samples_client): + """Test fetching GLEIF External AID.""" + aid_id = "EINmHd5g7iV-UldkkkKyBIH052bIyxZNBn9pq-zNrYoS" + response = samples_client.simulate_get(f"/.well-known/keri/oobi/{aid_id}") + + assert response.status == falcon.HTTP_200 + assert response.content_type == "application/cesr" + assert aid_id in response.text + + def test_witness_response(self, samples_client): + """Test fetching witness returns KEL with icp and rpy messages.""" + witness_id = "BDkq35LUU63xnFmfhljYYRY0ymkCg7goyeCxN30tsvmS" + response = samples_client.simulate_get(f"/.well-known/keri/oobi/{witness_id}") + + assert response.status == falcon.HTTP_200 + assert response.content_type == "application/cesr" + + # Verify witness KEL content + content = response.text + assert "icp" in content # Inception event + assert witness_id in content + + def test_legal_entity_schema_response(self, samples_client): + """Test fetching Legal Entity vLEI Credential schema.""" + schema_said = "ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY" + response = samples_client.simulate_get(f"/.well-known/keri/oobi/{schema_said}") + + assert response.status == falcon.HTTP_200 + assert response.content_type == "application/cesr" + + # Parse as JSON schema + schema = json.loads(response.text) + assert schema["$id"] == schema_said + assert schema["credentialType"] == "LegalEntityvLEICredential" + assert schema["title"] == "Legal Entity vLEI Credential" + + def test_qvi_schema_response(self, samples_client): + """Test fetching QVI vLEI Credential schema.""" + schema_said = "EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao" + response = samples_client.simulate_get(f"/.well-known/keri/oobi/{schema_said}") + + assert response.status == falcon.HTTP_200 + assert response.content_type == "application/cesr" + + # Parse as JSON schema + schema = json.loads(response.text) + assert schema["$id"] == schema_said + assert schema["credentialType"] == "QualifiedvLEIIssuervLEICredential" + + +class TestSamplesStructureCompliance: + """Test that samples directory complies with GLEIF specification.""" + + def test_index_has_required_fields(self, samples_oobi_dir): + """Test that index.json has all required fields per spec.""" + index_path = os.path.join(samples_oobi_dir, "index.json") + + with open(index_path, 'r') as f: + index = json.load(f) + + # Required fields per GLEIF OOBI schema + assert "aids" in index + assert "witnesses" in index + assert "schemas" in index + + # Verify structure + assert isinstance(index["aids"], dict) + assert isinstance(index["witnesses"], dict) + assert isinstance(index["schemas"], dict) + + def test_identifier_directories_exist(self, samples_oobi_dir): + """Test that all identifiers in index have corresponding directories.""" + index_path = os.path.join(samples_oobi_dir, "index.json") + + with open(index_path, 'r') as f: + index = json.load(f) + + # Check AIDs + for name, aid in index["aids"].items(): + aid_dir = Path(samples_oobi_dir, aid) + assert aid_dir.exists(), f"AID directory missing for {name}: {aid}" + assert (aid_dir / "index.json").exists(), f"index.json missing for {name}" + + # Check at least one witness (we don't need all 10) + witness_ids = list(index["witnesses"].keys()) + if witness_ids: + witness_id = witness_ids[0] + witness_dir = Path(samples_oobi_dir, witness_id) + assert witness_dir.exists(), f"Witness directory missing: {witness_id}" + + def test_cesr_identifier_format(self, samples_oobi_dir): + """Test that identifiers follow CESR format (44 chars, proper prefix).""" + index_path = os.path.join(samples_oobi_dir, "index.json") + + with open(index_path, 'r') as f: + index = json.load(f) + + # Check AIDs (E prefix, 44 chars) + for name, aid in index["aids"].items(): + assert len(aid) == 44, f"AID {name} wrong length: {len(aid)}" + assert aid[0] == 'E', f"AID {name} wrong prefix: {aid[0]}" + + # Check witnesses (B prefix, 44 chars) + for witness_id in index["witnesses"].keys(): + assert len(witness_id) == 44, f"Witness wrong length: {len(witness_id)}" + assert witness_id[0] == 'B', f"Witness wrong prefix: {witness_id[0]}" + + # Check schemas (E prefix, 44 chars) + for schema_name, schema_said in index["schemas"].items(): + assert len(schema_said) == 44, f"Schema {schema_name} wrong length: {len(schema_said)}" + assert schema_said[0] == 'E', f"Schema {schema_name} wrong prefix: {schema_said[0]}"