@verii/endpoints-organizations-registrar 1.0.0-pre.1752076816

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +1 -0
  3. package/README.md +3 -0
  4. package/package.json +86 -0
  5. package/src/config/abi.json +1 -0
  6. package/src/config/config.js +261 -0
  7. package/src/controllers/consents/autohooks.js +6 -0
  8. package/src/controllers/consents/controller.js +106 -0
  9. package/src/controllers/consents/schemas/consent-response.schema.js +45 -0
  10. package/src/controllers/did-web-host/controller.js +64 -0
  11. package/src/controllers/groups/autohooks.js +10 -0
  12. package/src/controllers/groups/controller.js +172 -0
  13. package/src/controllers/groups/schemas/group.schema.json +22 -0
  14. package/src/controllers/groups/schemas/index.js +7 -0
  15. package/src/controllers/groups/schemas/modify-group.schema.json +25 -0
  16. package/src/controllers/image_upload/controller.js +48 -0
  17. package/src/controllers/invitations/controller.js +79 -0
  18. package/src/controllers/organizations/_did/autohooks.js +16 -0
  19. package/src/controllers/organizations/_did/controller.js +617 -0
  20. package/src/controllers/organizations/_did/invitations/_invitationId/autohooks.js +16 -0
  21. package/src/controllers/organizations/_did/invitations/_invitationId/controller.js +217 -0
  22. package/src/controllers/organizations/_did/invitations/controller.js +197 -0
  23. package/src/controllers/organizations/_did/keys/controller.js +141 -0
  24. package/src/controllers/organizations/_did/services/controller.js +195 -0
  25. package/src/controllers/organizations/_did/signatories/controller.js +63 -0
  26. package/src/controllers/organizations/autohooks.js +65 -0
  27. package/src/controllers/organizations/controller.js +322 -0
  28. package/src/controllers/organizations/full/controller.js +285 -0
  29. package/src/controllers/organizations/plugins.js +21 -0
  30. package/src/controllers/organizations/schemas/add-key-body.schema.json +35 -0
  31. package/src/controllers/organizations/schemas/create-did-service.schema.json +70 -0
  32. package/src/controllers/organizations/schemas/did-key.schema.json +178 -0
  33. package/src/controllers/organizations/schemas/full-organization.schema.json +35 -0
  34. package/src/controllers/organizations/schemas/index.js +33 -0
  35. package/src/controllers/organizations/schemas/invitationCodeProperty.schema.json +3 -0
  36. package/src/controllers/organizations/schemas/organization-ids.schema.json +34 -0
  37. package/src/controllers/organizations/schemas/organization-kyb-profile-creation.schema.json +26 -0
  38. package/src/controllers/organizations/schemas/organization-profile-creation.schema.json +20 -0
  39. package/src/controllers/organizations/schemas/organization-profile-update.schema.json +19 -0
  40. package/src/controllers/organizations/schemas/organization-profile-verifiable-credential.schema.json +25 -0
  41. package/src/controllers/organizations/schemas/organization-registry-service-response.schema.json +26 -0
  42. package/src/controllers/organizations/schemas/organization-service.schema.json +34 -0
  43. package/src/controllers/organizations/schemas/organization-verified-profile.schema.json +123 -0
  44. package/src/controllers/organizations/schemas/organization.search-profile.query-params.schema.json +50 -0
  45. package/src/controllers/organizations/schemas/organization.search.query-params.schema.json +42 -0
  46. package/src/controllers/reference/controller.js +103 -0
  47. package/src/controllers/resolve-did/controller.js +45 -0
  48. package/src/controllers/resolve-did/resolve-did.js +30 -0
  49. package/src/controllers/resolve-did/schemas/did-doc.schema.json +155 -0
  50. package/src/controllers/resolve-did/schemas/did-proof.schema.json +44 -0
  51. package/src/controllers/resolve-did/schemas/index.js +26 -0
  52. package/src/controllers/resolve-did/schemas/public-key.schema.json +173 -0
  53. package/src/controllers/resolve-kid/controller.js +76 -0
  54. package/src/controllers/resolve-kid/public-key-formats.js +8 -0
  55. package/src/controllers/service-types/controller.js +81 -0
  56. package/src/controllers/setup_image_upload/controller.js +99 -0
  57. package/src/controllers/signatories/controller.js +43 -0
  58. package/src/controllers/users/autohooks.js +10 -0
  59. package/src/controllers/users/controller.js +221 -0
  60. package/src/controllers/users/schemas/base-user.schema.json +55 -0
  61. package/src/controllers/users/schemas/index.js +4 -0
  62. package/src/controllers/users/schemas/modify-user.schema.js +17 -0
  63. package/src/controllers/users/schemas/user.schema.js +20 -0
  64. package/src/entities/groups/domain/constants.js +21 -0
  65. package/src/entities/groups/domain/index.js +19 -0
  66. package/src/entities/groups/factories/groups-factory.js +48 -0
  67. package/src/entities/groups/factories/index.js +17 -0
  68. package/src/entities/groups/index.js +19 -0
  69. package/src/entities/groups/repo.js +122 -0
  70. package/src/entities/images/domain/constant.js +11 -0
  71. package/src/entities/images/domain/index.js +3 -0
  72. package/src/entities/images/extension/activate.extension.js +35 -0
  73. package/src/entities/images/extension/deactivate.extension.js +27 -0
  74. package/src/entities/images/extension/find-by-url.extension.js +24 -0
  75. package/src/entities/images/extension/index.js +5 -0
  76. package/src/entities/images/factories/images-factory.js +43 -0
  77. package/src/entities/images/factories/index.js +17 -0
  78. package/src/entities/images/index.js +5 -0
  79. package/src/entities/images/repo.js +43 -0
  80. package/src/entities/images/schema/image-metadata.schema.js +58 -0
  81. package/src/entities/images/schema/index.js +3 -0
  82. package/src/entities/index.js +31 -0
  83. package/src/entities/invitations/domains/build-invitation-url.js +14 -0
  84. package/src/entities/invitations/domains/get-given-family-name-from-name.js +20 -0
  85. package/src/entities/invitations/domains/index.js +7 -0
  86. package/src/entities/invitations/domains/init-invitation-emails.js +17 -0
  87. package/src/entities/invitations/domains/is-invitation-expired.js +5 -0
  88. package/src/entities/invitations/domains/validate-invitee-email.js +18 -0
  89. package/src/entities/invitations/factories/index.js +17 -0
  90. package/src/entities/invitations/factories/invitations-factory.js +51 -0
  91. package/src/entities/invitations/index.js +6 -0
  92. package/src/entities/invitations/orchestrators/accept-invitation.js +24 -0
  93. package/src/entities/invitations/orchestrators/index.js +4 -0
  94. package/src/entities/invitations/orchestrators/send-email-invitee.js +36 -0
  95. package/src/entities/invitations/repo.js +37 -0
  96. package/src/entities/invitations/schemas/add-invitation-body.js +122 -0
  97. package/src/entities/invitations/schemas/get-invitation-response-body.js +20 -0
  98. package/src/entities/invitations/schemas/index.js +5 -0
  99. package/src/entities/invitations/schemas/invitation-response-item-body.js +61 -0
  100. package/src/entities/kms/factories/index.js +17 -0
  101. package/src/entities/kms/factories/kms-factory.js +31 -0
  102. package/src/entities/monitors/index.js +17 -0
  103. package/src/entities/monitors/orchestrators/index.js +17 -0
  104. package/src/entities/monitors/orchestrators/monitors.js +230 -0
  105. package/src/entities/oauth/domain/constants.js +23 -0
  106. package/src/entities/oauth/domain/index.js +5 -0
  107. package/src/entities/oauth/domain/roles.js +92 -0
  108. package/src/entities/oauth/domain/scopes.js +35 -0
  109. package/src/entities/oauth/index.js +4 -0
  110. package/src/entities/oauth/orchestrators/auth0-provisioner.js +293 -0
  111. package/src/entities/oauth/orchestrators/index.js +3 -0
  112. package/src/entities/organization-keys/domains/build-organization-key.js +50 -0
  113. package/src/entities/organization-keys/domains/constants.js +30 -0
  114. package/src/entities/organization-keys/domains/extract-verification-method-from-byo-did-document.js +38 -0
  115. package/src/entities/organization-keys/domains/find-key-by-purpose.js +6 -0
  116. package/src/entities/organization-keys/domains/index.js +10 -0
  117. package/src/entities/organization-keys/domains/jwk-to-hex-key-transformer.js +13 -0
  118. package/src/entities/organization-keys/domains/map-key-response.js +29 -0
  119. package/src/entities/organization-keys/domains/validate-non-custodial-key.js +11 -0
  120. package/src/entities/organization-keys/domains/validate-organization-key.js +42 -0
  121. package/src/entities/organization-keys/factories/index.js +17 -0
  122. package/src/entities/organization-keys/factories/organization-keys-factory.js +55 -0
  123. package/src/entities/organization-keys/index.js +5 -0
  124. package/src/entities/organization-keys/orchestrators/add-key-to-did-doc.js +19 -0
  125. package/src/entities/organization-keys/orchestrators/add-key.js +155 -0
  126. package/src/entities/organization-keys/orchestrators/add-operator-keys.js +46 -0
  127. package/src/entities/organization-keys/orchestrators/delete-key.js +93 -0
  128. package/src/entities/organization-keys/orchestrators/get-key.js +39 -0
  129. package/src/entities/organization-keys/orchestrators/index.js +24 -0
  130. package/src/entities/organization-keys/orchestrators/resolve-verification-method-byo-did.js +28 -0
  131. package/src/entities/organization-keys/repos/repo.js +48 -0
  132. package/src/entities/organization-services/adapters/index.js +21 -0
  133. package/src/entities/organization-services/adapters/init-provision-auth0-client-grants.js +44 -0
  134. package/src/entities/organization-services/adapters/init-provision-auth0-clients.js +56 -0
  135. package/src/entities/organization-services/adapters/update-blockchain-permissions-from-permitted-services.js +118 -0
  136. package/src/entities/organization-services/domains/activate-services.js +12 -0
  137. package/src/entities/organization-services/domains/build-organizations-services.js +38 -0
  138. package/src/entities/organization-services/domains/build-public-services.js +19 -0
  139. package/src/entities/organization-services/domains/constants.js +32 -0
  140. package/src/entities/organization-services/domains/extract-cao-service-refs.js +10 -0
  141. package/src/entities/organization-services/domains/extract-service-endpoint-did.js +10 -0
  142. package/src/entities/organization-services/domains/get-service-consent-type.js +16 -0
  143. package/src/entities/organization-services/domains/get-service-types-from-categories.js +18 -0
  144. package/src/entities/organization-services/domains/index.js +17 -0
  145. package/src/entities/organization-services/domains/is-new-node-operator-service.js +25 -0
  146. package/src/entities/organization-services/domains/is-service-category.js +31 -0
  147. package/src/entities/organization-services/domains/normalize-service-endpoint.js +6 -0
  148. package/src/entities/organization-services/domains/select-activated-services.js +8 -0
  149. package/src/entities/organization-services/domains/transform-profile-service.js +88 -0
  150. package/src/entities/organization-services/domains/validate-cao-service-refs.js +25 -0
  151. package/src/entities/organization-services/domains/validate-service-credential-type.js +47 -0
  152. package/src/entities/organization-services/domains/validate-service-endpoint.js +35 -0
  153. package/src/entities/organization-services/domains/validate-service-fields-by-service-type.js +37 -0
  154. package/src/entities/organization-services/domains/validate-service-id-uniqueness.js +19 -0
  155. package/src/entities/organization-services/domains/validate-service-key-purposes.js +56 -0
  156. package/src/entities/organization-services/domains/validate-service-type.js +12 -0
  157. package/src/entities/organization-services/domains/validate-service.js +80 -0
  158. package/src/entities/organization-services/domains/validate-services-for-delete.js +32 -0
  159. package/src/entities/organization-services/index.js +5 -0
  160. package/src/entities/organization-services/orchestrators/add-service.js +106 -0
  161. package/src/entities/organization-services/orchestrators/delete-service.js +142 -0
  162. package/src/entities/organization-services/orchestrators/get-service.js +36 -0
  163. package/src/entities/organization-services/orchestrators/index.js +8 -0
  164. package/src/entities/organization-services/orchestrators/init-add-service-to-organization.js +141 -0
  165. package/src/entities/organization-services/orchestrators/load-cao-service-refs.js +56 -0
  166. package/src/entities/organization-services/orchestrators/update-service.js +103 -0
  167. package/src/entities/organizations/adapters/index.js +6 -0
  168. package/src/entities/organizations/adapters/init-organization-registrar-emails.js +215 -0
  169. package/src/entities/organizations/adapters/init-send-activation-emails-to-caos.js +89 -0
  170. package/src/entities/organizations/adapters/send-email-invitation-accepted-to-inviter.js +70 -0
  171. package/src/entities/organizations/adapters/send-email-notifications.js +212 -0
  172. package/src/entities/organizations/domains/build-custodied-did-web.js +12 -0
  173. package/src/entities/organizations/domains/build-full-organization-response.js +40 -0
  174. package/src/entities/organizations/domains/build-organization-modifications-on-service-change.js +82 -0
  175. package/src/entities/organizations/domains/build-profile-vc-url.js +8 -0
  176. package/src/entities/organizations/domains/build-profile-verifiable-credential.js +36 -0
  177. package/src/entities/organizations/domains/build-public-profile.js +9 -0
  178. package/src/entities/organizations/domains/constants.js +54 -0
  179. package/src/entities/organizations/domains/index.js +17 -0
  180. package/src/entities/organizations/domains/organization-vc-checks.js +49 -0
  181. package/src/entities/organizations/domains/parse-profile-to-csv.js +41 -0
  182. package/src/entities/organizations/domains/prepare-profile-vc.js +28 -0
  183. package/src/entities/organizations/domains/profile-name-normalization.js +5 -0
  184. package/src/entities/organizations/domains/validate-byo-did-keys.js +28 -0
  185. package/src/entities/organizations/domains/validate-profile-name.js +48 -0
  186. package/src/entities/organizations/domains/validate-profile-website.js +17 -0
  187. package/src/entities/organizations/domains/validate-update-profile.js +11 -0
  188. package/src/entities/organizations/factories/index.js +17 -0
  189. package/src/entities/organizations/factories/organizations-factory.js +180 -0
  190. package/src/entities/organizations/index.js +6 -0
  191. package/src/entities/organizations/orchestrators/add-primary-permissions.js +28 -0
  192. package/src/entities/organizations/orchestrators/build-custodied-organization.js +92 -0
  193. package/src/entities/organizations/orchestrators/build-non-custodied-organization.js +83 -0
  194. package/src/entities/organizations/orchestrators/index.js +6 -0
  195. package/src/entities/organizations/orchestrators/init-create-organization.js +221 -0
  196. package/src/entities/organizations/orchestrators/init-provision-group.js +48 -0
  197. package/src/entities/organizations/orchestrators/verify-profile-website-unique.js +15 -0
  198. package/src/entities/organizations/repos/find-caos-extension.js +49 -0
  199. package/src/entities/organizations/repos/index.js +17 -0
  200. package/src/entities/organizations/repos/repo.js +156 -0
  201. package/src/entities/organizations/repos/search-by-aggregation-extension.js +128 -0
  202. package/src/entities/organizations/repos/transform-did-filter.js +13 -0
  203. package/src/entities/organizations/repos/transform-organization-filter.js +106 -0
  204. package/src/entities/registrar-consents/constants.js +10 -0
  205. package/src/entities/registrar-consents/factories/index.js +17 -0
  206. package/src/entities/registrar-consents/factories/registrar-consents-factory.js +38 -0
  207. package/src/entities/registrar-consents/index.js +3 -0
  208. package/src/entities/registrar-consents/repos/registrar-consent-repo-extension.js +55 -0
  209. package/src/entities/registrar-consents/repos/repo.js +31 -0
  210. package/src/entities/signatories/domain/constants.js +12 -0
  211. package/src/entities/signatories/domain/index.js +4 -0
  212. package/src/entities/signatories/domain/organization-emails.js +29 -0
  213. package/src/entities/signatories/factories/index.js +17 -0
  214. package/src/entities/signatories/factories/signatory-status-factory.js +53 -0
  215. package/src/entities/signatories/index.js +5 -0
  216. package/src/entities/signatories/orchestrators/approve-reminder.js +24 -0
  217. package/src/entities/signatories/orchestrators/index.js +6 -0
  218. package/src/entities/signatories/orchestrators/reject-reminder.js +17 -0
  219. package/src/entities/signatories/orchestrators/send-reminders.js +102 -0
  220. package/src/entities/signatories/orchestrators/validate-auth-code.js +56 -0
  221. package/src/entities/signatories/repos/index.js +3 -0
  222. package/src/entities/signatories/repos/repo.js +35 -0
  223. package/src/entities/signatories/repos/signatory-status-state-repo-extension.js +124 -0
  224. package/src/entities/users/domains/constants.js +40 -0
  225. package/src/entities/users/domains/index.js +4 -0
  226. package/src/entities/users/domains/user-registrar-emails.js +52 -0
  227. package/src/entities/users/index.js +4 -0
  228. package/src/entities/users/orchestrators/create-auth0-user.js +60 -0
  229. package/src/entities/users/orchestrators/get-or-create-auth0-user.js +63 -0
  230. package/src/entities/users/orchestrators/index.js +22 -0
  231. package/src/entities/users/orchestrators/user-management.js +157 -0
  232. package/src/fetchers/index.js +19 -0
  233. package/src/fetchers/monitoring/index.js +9 -0
  234. package/src/fetchers/monitoring/monitor-add-to-page-fetcher.js +18 -0
  235. package/src/fetchers/monitoring/monitor-create-fetcher.js +23 -0
  236. package/src/fetchers/monitoring/monitor-delete-fetcher.js +6 -0
  237. package/src/fetchers/monitoring/monitor-get-all-fetcher.js +6 -0
  238. package/src/fetchers/monitoring/section-create-fetcher.js +16 -0
  239. package/src/fetchers/monitoring/section-get-all-fetcher.js +6 -0
  240. package/src/fetchers/monitoring/service-version-fetcher.js +6 -0
  241. package/src/helpers/init-permissions-contract.js +48 -0
  242. package/src/index.js +23 -0
  243. package/src/init-server.js +91 -0
  244. package/src/organizations-registrar-endpoints.js +68 -0
  245. package/src/plugins/authorization.js +233 -0
  246. package/src/plugins/index.js +4 -0
  247. package/src/plugins/pubsub-plugin.js +82 -0
  248. package/src/subscribers/notify-caos.js +63 -0
  249. package/src/subscribers/notify-inviters.js +42 -0
  250. package/src/subscribers/notify-monitoring.js +40 -0
  251. package/src/subscribers/notify-signatory.js +51 -0
  252. package/src/subscribers/notify-support-and-groups.js +95 -0
  253. package/src/templates/invitee-invitation-email-body.hbs +13 -0
  254. package/src/templates/invitee-invitation-email-subject.hbs +1 -0
  255. package/src/templates/signatory-approval-email-body.hbs +92 -0
  256. package/src/templates/support-organization-created-body.hbs +17 -0
  257. package/src/templates/support-organization-created-subject.hbs +1 -0
  258. package/src/templates/support-signatory-max-reminders-reached-email-body.hbs +6 -0
  259. package/src/templates/support-signatory-max-reminders-reached-email-subject.hbs +1 -0
@@ -0,0 +1,155 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const { hexToJwkKeyTransformer } = require('@verii/jwt');
18
+ const {
19
+ generateKeyPair,
20
+ KeyAlgorithms,
21
+ KeyPurposes,
22
+ } = require('@verii/crypto');
23
+ const newError = require('http-errors');
24
+ const { kebabCase, includes } = require('lodash/fp');
25
+ const {
26
+ mapKeyResponse,
27
+ validateNonCustodialKey,
28
+ validateOrganizationKey,
29
+ buildOrganizationKey,
30
+ KeyErrorMessages,
31
+ } = require('../domains');
32
+ const { addKeyToDidDoc } = require('./add-key-to-did-doc');
33
+ const { addOperatorKeys } = require('./add-operator-keys');
34
+ const {
35
+ resolveVerificationMethodFromByoDID,
36
+ } = require('./resolve-verification-method-byo-did');
37
+
38
+ const addKey = async (did, newKey, context) => {
39
+ const { repos } = context;
40
+ const organization = await repos.organizations.findOneByDid(did);
41
+
42
+ validateNonCustodialKey(newKey);
43
+ validateOrganizationKey(newKey);
44
+ const body = hexToJwkKeyTransformer(newKey);
45
+ await checkForKeyDuplication(body, organization, context);
46
+
47
+ let kmsEntry;
48
+ let keyPair;
49
+ let algorithm;
50
+ if (shouldGenerateNewKey(organization, newKey)) {
51
+ keyPair = generateKeyPair({ format: 'jwk' });
52
+ kmsEntry = await context.kms.importKey({
53
+ ...keyPair,
54
+ algorithm: 'ec',
55
+ curve: 'secp256k1',
56
+ });
57
+ algorithm = KeyAlgorithms.SECP256K1;
58
+ }
59
+
60
+ const kidFragment = defaultKidFragment(newKey);
61
+ const verificationMethod = isDIDDocumentCustodied(organization)
62
+ ? await addKeyToDidDoc(
63
+ {
64
+ organization,
65
+ kidFragment,
66
+ publicKey: shouldGenerateNewKey(organization, newKey)
67
+ ? keyPair.publicKey
68
+ : body.publicKey,
69
+ },
70
+ context
71
+ )
72
+ : await resolveVerificationMethodFromByoDID(
73
+ organization.didDoc.id,
74
+ kidFragment
75
+ );
76
+
77
+ const newOrganizationKey = buildOrganizationKey(
78
+ organization._id,
79
+ organization.didDoc.id,
80
+ {
81
+ purposes: body.purposes,
82
+ algorithm: algorithm ?? body.algorithm,
83
+ custodied: newKey.custodied,
84
+ kmsKeyId: kmsEntry?.id,
85
+ verificationMethod,
86
+ }
87
+ );
88
+
89
+ await repos.organizationKeys.insert(newOrganizationKey);
90
+
91
+ if (includes(KeyPurposes.DLT_TRANSACTIONS, newOrganizationKey.purposes)) {
92
+ await addOperatorKeys(
93
+ {
94
+ organization,
95
+ primaryAccount: organization.ids.ethereumAccount,
96
+ dltKeys: [newOrganizationKey],
97
+ },
98
+ context
99
+ );
100
+ }
101
+ return {
102
+ key: mapKeyResponse(newOrganizationKey, keyPair),
103
+ };
104
+ };
105
+
106
+ const checkForKeyDuplication = async (key, organization, { repos }) => {
107
+ const ors = [
108
+ {
109
+ id: key.kidFragment,
110
+ },
111
+ ];
112
+ if (key.publicKey) {
113
+ ors.push({
114
+ 'publicKey.kty': key.publicKey.kty,
115
+ 'publicKey.crv': key.publicKey.crv,
116
+ 'publicKey.x': key.publicKey.x,
117
+ 'publicKey.y': key.publicKey.y,
118
+ });
119
+ }
120
+ const existingOrganizationKey = await repos.organizationKeys.findOne({
121
+ filter: {
122
+ organizationId: organization._id,
123
+ $or: ors,
124
+ },
125
+ });
126
+
127
+ if (existingOrganizationKey != null) {
128
+ throw newError(
129
+ 409,
130
+ buildDuplicateKeyErrorString(key, existingOrganizationKey)
131
+ );
132
+ }
133
+ };
134
+
135
+ const defaultKidFragment = (body) => {
136
+ if (!body.kidFragment) {
137
+ return `#${kebabCase(body.purposes[0])}-${Date.now()}`;
138
+ }
139
+
140
+ return body.kidFragment;
141
+ };
142
+
143
+ const buildDuplicateKeyErrorString = (key, existingKey) => {
144
+ if (key.kidFragment === existingKey.id) {
145
+ return KeyErrorMessages.KEY_WITH_ID_FRAGMENT_ALREADY_EXISTS_TEMPLATE(key);
146
+ }
147
+ return KeyErrorMessages.PUBLIC_KEY_ALREADY_EXISTS_TEMPLATE(key);
148
+ };
149
+
150
+ const shouldGenerateNewKey = (organization, newKey) =>
151
+ isDIDDocumentCustodied(organization) && newKey.publicKey == null;
152
+
153
+ const isDIDDocumentCustodied = (organization) => !organization.didNotCustodied;
154
+
155
+ module.exports = { addKey };
@@ -0,0 +1,46 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const { toEthereumAddress } = require('@verii/blockchain-functions');
19
+ const { map } = require('lodash/fp');
20
+ const {
21
+ initPermissionsContractByKeyId,
22
+ initPermissionsContract,
23
+ } = require('../../../helpers/init-permissions-contract');
24
+
25
+ const addOperatorKeys = async (
26
+ { primaryAccount, organization, permissioningKeyId, dltKeys },
27
+ context
28
+ ) => {
29
+ const permissionContract =
30
+ permissioningKeyId != null
31
+ ? await initPermissionsContractByKeyId(permissioningKeyId, context)
32
+ : await initPermissionsContract(organization, context);
33
+
34
+ await Promise.all(
35
+ map(
36
+ ({ publicKey: dltPublicKey }) =>
37
+ permissionContract.addOperatorKey({
38
+ primary: primaryAccount,
39
+ operator: toEthereumAddress(dltPublicKey),
40
+ }),
41
+ dltKeys
42
+ )
43
+ );
44
+ };
45
+
46
+ module.exports = { addOperatorKeys };
@@ -0,0 +1,93 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const { toRelativeServiceId, removeKeyFromDidDoc } = require('@verii/did-doc');
18
+ const { ObjectId } = require('mongodb');
19
+ const newError = require('http-errors');
20
+ const { includes } = require('lodash/fp');
21
+ const { KeyPurposes } = require('@verii/crypto');
22
+ const { hexFromJwk } = require('@verii/jwt');
23
+ const { toEthereumAddress } = require('@verii/blockchain-functions');
24
+ const {
25
+ initPermissionsContract,
26
+ } = require('../../../helpers/init-permissions-contract');
27
+
28
+ const deleteKey = async (did, keyId, context) => {
29
+ const { repos, log } = context;
30
+
31
+ const organization = await repos.organizations.findOneByDid(did, {
32
+ didDoc: 1,
33
+ ids: 1,
34
+ didNotCustodied: 1,
35
+ });
36
+
37
+ const relativeKeyId = toRelativeServiceId(keyId);
38
+ const organizationKey = await repos.organizationKeys.findOne({
39
+ filter: {
40
+ id: relativeKeyId,
41
+ organizationId: new ObjectId(organization._id),
42
+ },
43
+ });
44
+
45
+ if (!organizationKey) {
46
+ throw new newError.NotFound(
47
+ `Key ${relativeKeyId} was not found in organization ${did}`
48
+ );
49
+ }
50
+ if (includes(organizationKey.purposes, KeyPurposes.ISSUING_METADATA)) {
51
+ throw new newError.BadRequest('ISSUING_METADATA Key may not be removed');
52
+ }
53
+
54
+ // Update DID Document
55
+ await removeOperatorKeyFromBlockchain(organizationKey, organization, context);
56
+
57
+ await repos.organizationKeys.delUsingFilter({
58
+ filter: {
59
+ id: relativeKeyId,
60
+ organizationId: new ObjectId(organization._id),
61
+ },
62
+ });
63
+
64
+ if (!organization.didNotCustodied) {
65
+ const { didDoc } = removeKeyFromDidDoc({
66
+ didDoc: organization.didDoc,
67
+ keyId: relativeKeyId,
68
+ });
69
+
70
+ await repos.organizations.update(organization._id, {
71
+ didDoc,
72
+ });
73
+ }
74
+
75
+ log.info({ keyId }, 'Remove key');
76
+ };
77
+
78
+ const removeOperatorKeyFromBlockchain = async (key, organization, context) => {
79
+ if (!key.purposes.includes(KeyPurposes.DLT_TRANSACTIONS)) {
80
+ return;
81
+ }
82
+ const permissionContract = await initPermissionsContract(
83
+ organization,
84
+ context
85
+ );
86
+
87
+ await permissionContract.removeOperatorKey({
88
+ primary: organization.ids.ethereumAccount,
89
+ operator: toEthereumAddress(hexFromJwk(key.publicKey, false)),
90
+ });
91
+ };
92
+
93
+ module.exports = { deleteKey };
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const { toRelativeServiceId } = require('@verii/did-doc');
18
+ const newError = require('http-errors');
19
+ const { mapKeyResponse } = require('../domains');
20
+
21
+ const getKey = async (did, kid, { repos }) => {
22
+ const organization = await repos.organizations.findOneByDid(did);
23
+
24
+ const keyId = toRelativeServiceId(kid);
25
+ const key = await repos.organizationKeys.findOne({
26
+ filter: {
27
+ id: keyId,
28
+ organizationId: organization._id,
29
+ },
30
+ });
31
+
32
+ if (key == null) {
33
+ throw newError.NotFound('Key not found');
34
+ }
35
+
36
+ return { key: mapKeyResponse(key), custodied: key.custodied };
37
+ };
38
+
39
+ module.exports = { getKey };
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ module.exports = {
18
+ ...require('./add-key-to-did-doc'),
19
+ ...require('./add-operator-keys'),
20
+ ...require('./add-key'),
21
+ ...require('./delete-key'),
22
+ ...require('./get-key'),
23
+ ...require('./resolve-verification-method-byo-did'),
24
+ };
@@ -0,0 +1,28 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const { resolveDidWeb } = require('@verii/did-web');
18
+ const { extractVerificationMethodFromByoDID } = require('../domains');
19
+
20
+ const resolveVerificationMethodFromByoDID = async (did, kidFragment) => {
21
+ const didDocument = await resolveDidWeb(did);
22
+
23
+ return extractVerificationMethodFromByoDID({ didDocument, kidFragment });
24
+ };
25
+
26
+ module.exports = {
27
+ resolveVerificationMethodFromByoDID,
28
+ };
@@ -0,0 +1,48 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const {
19
+ repoFactory,
20
+ autoboxIdsExtension,
21
+ } = require('@spencejs/spence-mongo-repos');
22
+
23
+ module.exports = (app, options, next = () => {}) => {
24
+ next();
25
+ return repoFactory(
26
+ {
27
+ name: 'organizationKeys',
28
+ entityName: 'organizationKey',
29
+ defaultProjection: {
30
+ _id: 1,
31
+ id: 1,
32
+ purposes: 1,
33
+ algorithm: 1,
34
+ encoding: 1,
35
+ publicKey: 1,
36
+ kmsKeyId: 1,
37
+ controller: 1,
38
+ organizationId: 1,
39
+ custodied: 1,
40
+ type: 1,
41
+ createdAt: 1,
42
+ updatedAt: 1,
43
+ },
44
+ extensions: [autoboxIdsExtension],
45
+ },
46
+ app
47
+ );
48
+ };
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ module.exports = {
18
+ ...require('./init-provision-auth0-clients'),
19
+ ...require('./init-provision-auth0-client-grants'),
20
+ ...require('./update-blockchain-permissions-from-permitted-services'),
21
+ };
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const { find, map, isEmpty } = require('lodash/fp');
19
+
20
+ const initProvisionAuth0ClientGrants =
21
+ ({ provisionAuth0SystemClientGrants }) =>
22
+ async (organization, activatedServiceIds = []) => {
23
+ const { authClients, services } = organization;
24
+ return Promise.all(
25
+ map(async (authClient) => {
26
+ if (
27
+ !activatedServiceIds.includes(authClient.serviceId) ||
28
+ !isEmpty(authClient.clientGrantIds)
29
+ ) {
30
+ return authClient;
31
+ }
32
+
33
+ const service = find({ id: authClient.serviceId }, services);
34
+ const clientGrant = await provisionAuth0SystemClientGrants(
35
+ authClient.clientId,
36
+ service?.type
37
+ );
38
+
39
+ return { ...authClient, clientGrantIds: [clientGrant.id] };
40
+ }, authClients)
41
+ );
42
+ };
43
+
44
+ module.exports = { initProvisionAuth0ClientGrants };
@@ -0,0 +1,56 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const { filter, flow, includes, map } = require('lodash/fp');
19
+ const { NodeServiceCategories } = require('../domains');
20
+
21
+ const initProvisionAuth0Clients =
22
+ ({ provisionAuth0SystemClient }) =>
23
+ async (organization, services, activatedServiceIds, context) => {
24
+ const {
25
+ log,
26
+ server: { sendError },
27
+ } = context;
28
+ try {
29
+ return await Promise.all(
30
+ flow(
31
+ filter((service) => includes(service.type, NodeServiceCategories)),
32
+ map((nodeService) =>
33
+ provisionAuth0SystemClient(
34
+ organization.didDoc.id,
35
+ organization.profile,
36
+ nodeService,
37
+ activatedServiceIds.includes(nodeService.id)
38
+ )
39
+ )
40
+ )(services)
41
+ );
42
+ } catch (error) {
43
+ const message = 'Error Provisioning Auth0 Apps';
44
+ const messageContext = {
45
+ did: organization.didDoc.id,
46
+ newServices: services,
47
+ };
48
+ log.error({ err: error, ...messageContext }, message);
49
+ sendError(error, { ...messageContext, message });
50
+ return [];
51
+ }
52
+ };
53
+
54
+ module.exports = {
55
+ initProvisionAuth0Clients,
56
+ };
@@ -0,0 +1,118 @@
1
+ const {
2
+ isEmpty,
3
+ values,
4
+ pullAll,
5
+ flatten,
6
+ map,
7
+ uniq,
8
+ flow,
9
+ compact,
10
+ } = require('lodash/fp');
11
+ const {
12
+ initPermissions,
13
+ AddressScopePermissions,
14
+ } = require('@verii/contract-permissions');
15
+ const { ServiceCategories } = require('@verii/organizations-registry');
16
+
17
+ const ServiceCategoryToPermissions = {
18
+ [ServiceCategories.CredentialAgentOperator]: [],
19
+ [ServiceCategories.HolderAppProvider]: [],
20
+ [ServiceCategories.NodeOperator]: [],
21
+ [ServiceCategories.IdDocumentIssuer]: [
22
+ AddressScopePermissions.TransactionsWrite,
23
+ AddressScopePermissions.CredentialRevoke,
24
+ AddressScopePermissions.CredentialIdentityIssue,
25
+ ],
26
+ [ServiceCategories.NotaryIdDocumentIssuer]: [
27
+ AddressScopePermissions.TransactionsWrite,
28
+ AddressScopePermissions.CredentialRevoke,
29
+ AddressScopePermissions.CredentialIdentityIssue,
30
+ ],
31
+ [ServiceCategories.ContactIssuer]: [
32
+ AddressScopePermissions.TransactionsWrite,
33
+ AddressScopePermissions.CredentialRevoke,
34
+ AddressScopePermissions.CredentialContactIssue,
35
+ ],
36
+ [ServiceCategories.NotaryContactIssuer]: [
37
+ AddressScopePermissions.TransactionsWrite,
38
+ AddressScopePermissions.CredentialRevoke,
39
+ AddressScopePermissions.CredentialContactIssue,
40
+ ],
41
+ [ServiceCategories.IdentityIssuer]: [],
42
+ [ServiceCategories.Inspector]: [
43
+ AddressScopePermissions.TransactionsWrite,
44
+ AddressScopePermissions.CredentialInspect,
45
+ ],
46
+ [ServiceCategories.Issuer]: [
47
+ AddressScopePermissions.TransactionsWrite,
48
+ AddressScopePermissions.CredentialRevoke,
49
+ AddressScopePermissions.CredentialIssue,
50
+ ],
51
+ [ServiceCategories.NotaryIssuer]: [
52
+ AddressScopePermissions.TransactionsWrite,
53
+ AddressScopePermissions.CredentialRevoke,
54
+ AddressScopePermissions.CredentialIssue,
55
+ ],
56
+ };
57
+
58
+ const mapPermissionsToServiceTypes = (permittedVelocityServiceCategories) => {
59
+ if (isEmpty(permittedVelocityServiceCategories)) {
60
+ return {
61
+ permissionsToAdd: [],
62
+ permissionsToRemove: values(AddressScopePermissions),
63
+ };
64
+ }
65
+
66
+ const permissionsOfCategories = flow(
67
+ map((serviceCategory) => {
68
+ return ServiceCategoryToPermissions[serviceCategory];
69
+ }),
70
+ flatten,
71
+ uniq,
72
+ compact
73
+ )(permittedVelocityServiceCategories);
74
+ const permissionsToAdd = permissionsOfCategories;
75
+ const permissionsToRemove = pullAll(
76
+ permissionsOfCategories,
77
+ values(AddressScopePermissions)
78
+ );
79
+
80
+ return {
81
+ permissionsToAdd,
82
+ permissionsToRemove,
83
+ };
84
+ };
85
+
86
+ const updateBlockchainPermissionsFromPermittedServices = async (
87
+ { organization },
88
+ ctx
89
+ ) => {
90
+ const { config, rpcProvider } = ctx;
91
+ const { rootPrivateKey, permissionsContractAddress } = config;
92
+ const {
93
+ profile: { permittedVelocityServiceCategory },
94
+ ids: { ethereumAccount: primary },
95
+ } = organization;
96
+
97
+ const permissionContractClient = await initPermissions(
98
+ {
99
+ privateKey: rootPrivateKey,
100
+ contractAddress: permissionsContractAddress,
101
+ rpcProvider,
102
+ },
103
+ ctx
104
+ );
105
+
106
+ const { permissionsToAdd, permissionsToRemove } =
107
+ mapPermissionsToServiceTypes(permittedVelocityServiceCategory);
108
+
109
+ await permissionContractClient.updateAddressScopes({
110
+ address: primary,
111
+ scopesToAdd: permissionsToAdd,
112
+ scopesToRemove: permissionsToRemove,
113
+ });
114
+ };
115
+
116
+ module.exports = {
117
+ updateBlockchainPermissionsFromPermittedServices,
118
+ };
@@ -0,0 +1,12 @@
1
+ const { map } = require('lodash/fp');
2
+
3
+ const activateServices = (did, services, { headers, config: { isProd } }) => {
4
+ if (!isProd && headers['x-auto-activate'] !== '0') {
5
+ return map('id', services);
6
+ }
7
+
8
+ return [];
9
+ };
10
+ module.exports = {
11
+ activateServices,
12
+ };