@enbox/dwn-sdk-js 0.4.3 → 0.4.5
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.
- package/dist/browser.mjs +15 -15
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/generated/precompiled-validators.js +5406 -2200
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/json-schemas/definitions.json +18 -0
- package/dist/esm/src/core/constants.js +3 -3
- package/dist/esm/src/core/constants.js.map +1 -1
- package/dist/esm/src/core/dwn-error.js +29 -1
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/messages-grant-authorization.js +20 -0
- package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-validation.js +80 -3
- package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
- package/dist/esm/src/core/recording-validation-state-reader.js +5 -0
- package/dist/esm/src/core/recording-validation-state-reader.js.map +1 -1
- package/dist/esm/src/core/replication-apply.js +163 -7
- package/dist/esm/src/core/replication-apply.js.map +1 -1
- package/dist/esm/src/core/validation-state-reader.js +20 -0
- package/dist/esm/src/core/validation-state-reader.js.map +1 -1
- package/dist/esm/src/dwn.js +19 -2
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/handlers/messages-query.js +3 -5
- package/dist/esm/src/handlers/messages-query.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js +10 -4
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +1 -1
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +2 -1
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-configure.js +23 -10
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/records-write-signing.js +2 -8
- package/dist/esm/src/interfaces/records-write-signing.js.map +1 -1
- package/dist/esm/src/interfaces/records-write.js +43 -65
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/protocols/encryption.js +411 -0
- package/dist/esm/src/protocols/encryption.js.map +1 -0
- package/dist/esm/src/protocols/permission-grant.js +3 -3
- package/dist/esm/src/protocols/permission-grant.js.map +1 -1
- package/dist/esm/src/protocols/permissions.js +1 -0
- package/dist/esm/src/protocols/permissions.js.map +1 -1
- package/dist/esm/src/types/message-types.js.map +1 -1
- package/dist/esm/src/types/permission-types.js.map +1 -1
- package/dist/esm/src/types/protocols-types.js.map +1 -1
- package/dist/esm/src/utils/encryption.js +135 -187
- package/dist/esm/src/utils/encryption.js.map +1 -1
- package/dist/esm/src/utils/hd-key.js +0 -1
- package/dist/esm/src/utils/hd-key.js.map +1 -1
- package/dist/esm/src/utils/permission-scope.js +9 -6
- package/dist/esm/src/utils/permission-scope.js.map +1 -1
- package/dist/esm/src/utils/protocols.js +12 -9
- package/dist/esm/src/utils/protocols.js.map +1 -1
- package/dist/esm/src/utils/records.js +54 -56
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/src/utils/replication.js +27 -4
- package/dist/esm/src/utils/replication.js.map +1 -1
- package/dist/esm/tests/core/replication-apply.spec.js +141 -1
- package/dist/esm/tests/core/replication-apply.spec.js.map +1 -1
- package/dist/esm/tests/core/replication-replay-property.spec.js +1 -0
- package/dist/esm/tests/core/replication-replay-property.spec.js.map +1 -1
- package/dist/esm/tests/core/validation-read-closure.spec.js +111 -0
- package/dist/esm/tests/core/validation-read-closure.spec.js.map +1 -1
- package/dist/esm/tests/core/validation-state-reader.spec.js +89 -0
- package/dist/esm/tests/core/validation-state-reader.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-composition.spec.js +30 -31
- package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/encryption.fuzz.spec.js +29 -121
- package/dist/esm/tests/fuzz/encryption.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-query.spec.js +71 -3
- package/dist/esm/tests/handlers/messages-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-read.spec.js +2 -2
- package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +9 -135
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +279 -19
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/protocols-configure.spec.js +17 -22
- package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +170 -150
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/protocols/encryption.spec.js +914 -0
- package/dist/esm/tests/protocols/encryption.spec.js.map +1 -0
- package/dist/esm/tests/protocols/permission-grant.spec.js +55 -0
- package/dist/esm/tests/protocols/permission-grant.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +100 -100
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store-level.spec.js +20 -2
- package/dist/esm/tests/store/message-store-level.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption-callbacks.spec.js +88 -125
- package/dist/esm/tests/utils/encryption-callbacks.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption.spec.js +125 -255
- package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
- package/dist/esm/tests/utils/permission-scope.spec.js +5 -1
- package/dist/esm/tests/utils/permission-scope.spec.js.map +1 -1
- package/dist/esm/tests/utils/records.spec.js +15 -5
- package/dist/esm/tests/utils/records.spec.js.map +1 -1
- package/dist/esm/tests/utils/test-data-generator.js +7 -44
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/encryption/grant-key.spec.js +63 -0
- package/dist/esm/tests/validation/json-schemas/encryption/grant-key.spec.js.map +1 -0
- package/dist/types/generated/precompiled-validators.d.ts +140 -92
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/constants.d.ts +2 -2
- package/dist/types/src/core/constants.d.ts.map +1 -1
- package/dist/types/src/core/core-protocol.d.ts +1 -1
- package/dist/types/src/core/core-protocol.d.ts.map +1 -1
- package/dist/types/src/core/dwn-error.d.ts +29 -1
- package/dist/types/src/core/dwn-error.d.ts.map +1 -1
- package/dist/types/src/core/messages-grant-authorization.d.ts +2 -0
- package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization-validation.d.ts +2 -2
- package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -1
- package/dist/types/src/core/recording-validation-state-reader.d.ts +9 -0
- package/dist/types/src/core/recording-validation-state-reader.d.ts.map +1 -1
- package/dist/types/src/core/replication-apply.d.ts +4 -3
- package/dist/types/src/core/replication-apply.d.ts.map +1 -1
- package/dist/types/src/core/validation-state-reader.d.ts +9 -0
- package/dist/types/src/core/validation-state-reader.d.ts.map +1 -1
- package/dist/types/src/dwn.d.ts +1 -0
- package/dist/types/src/dwn.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-query.d.ts.map +1 -1
- package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +6 -5
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/protocols-configure.d.ts +1 -1
- package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write-signing.d.ts +4 -8
- package/dist/types/src/interfaces/records-write-signing.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write.d.ts +10 -26
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/protocols/encryption.d.ts +43 -0
- package/dist/types/src/protocols/encryption.d.ts.map +1 -0
- package/dist/types/src/protocols/permission-grant.d.ts +3 -6
- package/dist/types/src/protocols/permission-grant.d.ts.map +1 -1
- package/dist/types/src/protocols/permissions.d.ts +2 -1
- package/dist/types/src/protocols/permissions.d.ts.map +1 -1
- package/dist/types/src/types/encryption-types.d.ts +5 -38
- package/dist/types/src/types/encryption-types.d.ts.map +1 -1
- package/dist/types/src/types/message-types.d.ts +0 -13
- package/dist/types/src/types/message-types.d.ts.map +1 -1
- package/dist/types/src/types/permission-types.d.ts +44 -9
- package/dist/types/src/types/permission-types.d.ts.map +1 -1
- package/dist/types/src/types/protocols-types.d.ts +9 -14
- package/dist/types/src/types/protocols-types.d.ts.map +1 -1
- package/dist/types/src/types/records-types.d.ts +3 -3
- package/dist/types/src/types/records-types.d.ts.map +1 -1
- package/dist/types/src/types/validation-state-reader.d.ts +12 -0
- package/dist/types/src/types/validation-state-reader.d.ts.map +1 -1
- package/dist/types/src/utils/encryption.d.ts +54 -145
- package/dist/types/src/utils/encryption.d.ts.map +1 -1
- package/dist/types/src/utils/hd-key.d.ts +1 -1
- package/dist/types/src/utils/hd-key.d.ts.map +1 -1
- package/dist/types/src/utils/permission-scope.d.ts +4 -3
- package/dist/types/src/utils/permission-scope.d.ts.map +1 -1
- package/dist/types/src/utils/protocols.d.ts +3 -5
- package/dist/types/src/utils/protocols.d.ts.map +1 -1
- package/dist/types/src/utils/records.d.ts +5 -13
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/src/utils/replication.d.ts +3 -0
- package/dist/types/src/utils/replication.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/messages-query.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
- package/dist/types/tests/protocols/encryption.spec.d.ts +2 -0
- package/dist/types/tests/protocols/encryption.spec.d.ts.map +1 -0
- package/dist/types/tests/scenarios/end-to-end-tests.spec.d.ts.map +1 -1
- package/dist/types/tests/utils/test-data-generator.d.ts +0 -5
- package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
- package/dist/types/tests/validation/json-schemas/encryption/grant-key.spec.d.ts +2 -0
- package/dist/types/tests/validation/json-schemas/encryption/grant-key.spec.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/core/constants.ts +3 -3
- package/src/core/core-protocol.ts +1 -1
- package/src/core/dwn-error.ts +29 -1
- package/src/core/messages-grant-authorization.ts +27 -0
- package/src/core/protocol-authorization-validation.ts +145 -6
- package/src/core/recording-validation-state-reader.ts +13 -0
- package/src/core/replication-apply.ts +222 -8
- package/src/core/validation-state-reader.ts +30 -0
- package/src/dwn.ts +24 -2
- package/src/handlers/messages-query.ts +6 -5
- package/src/handlers/protocols-configure.ts +19 -3
- package/src/handlers/records-write.ts +1 -1
- package/src/index.ts +15 -5
- package/src/interfaces/protocols-configure.ts +39 -12
- package/src/interfaces/records-write-signing.ts +5 -12
- package/src/interfaces/records-write.ts +75 -92
- package/src/protocols/encryption.ts +649 -0
- package/src/protocols/permission-grant.ts +4 -5
- package/src/protocols/permissions.ts +8 -6
- package/src/types/encryption-types.ts +9 -38
- package/src/types/message-types.ts +0 -13
- package/src/types/permission-types.ts +57 -9
- package/src/types/protocols-types.ts +9 -16
- package/src/types/records-types.ts +3 -3
- package/src/types/validation-state-reader.ts +13 -0
- package/src/utils/encryption.ts +213 -283
- package/src/utils/hd-key.ts +1 -1
- package/src/utils/permission-scope.ts +10 -6
- package/src/utils/protocols.ts +16 -15
- package/src/utils/records.ts +86 -71
- package/src/utils/replication.ts +30 -4
- package/dist/esm/tests/vectors/protocol-definitions/chat.json +0 -70
package/src/core/dwn-error.ts
CHANGED
|
@@ -20,6 +20,22 @@ export enum DwnErrorCode {
|
|
|
20
20
|
ComputeCidCodecNotSupported = 'ComputeCidCodecNotSupported',
|
|
21
21
|
ComputeCidMultihashNotSupported = 'ComputeCidMultihashNotSupported',
|
|
22
22
|
Ed25519InvalidJwk = 'Ed25519InvalidJwk',
|
|
23
|
+
EncryptionProtocolValidateAudienceEpochEncrypted = 'EncryptionProtocolValidateAudienceEpochEncrypted',
|
|
24
|
+
EncryptionProtocolValidateAudienceEpochKeyIdMismatch = 'EncryptionProtocolValidateAudienceEpochKeyIdMismatch',
|
|
25
|
+
EncryptionProtocolValidateAudienceEpochMissing = 'EncryptionProtocolValidateAudienceEpochMissing',
|
|
26
|
+
EncryptionProtocolValidateAudienceKeyRecipientMissing = 'EncryptionProtocolValidateAudienceKeyRecipientMissing',
|
|
27
|
+
EncryptionProtocolValidateAudienceKeyRoleRecordMissing = 'EncryptionProtocolValidateAudienceKeyRoleRecordMissing',
|
|
28
|
+
EncryptionProtocolValidateAudienceMissingRequiredTag = 'EncryptionProtocolValidateAudienceMissingRequiredTag',
|
|
29
|
+
EncryptionProtocolValidateAudienceTagsMismatch = 'EncryptionProtocolValidateAudienceTagsMismatch',
|
|
30
|
+
EncryptionProtocolValidateAudienceWriterUnauthorized = 'EncryptionProtocolValidateAudienceWriterUnauthorized',
|
|
31
|
+
EncryptionProtocolValidateEncryptedDeliveryMissingEncryption = 'EncryptionProtocolValidateEncryptedDeliveryMissingEncryption',
|
|
32
|
+
EncryptionProtocolValidateGrantKeyAuthorMismatch = 'EncryptionProtocolValidateGrantKeyAuthorMismatch',
|
|
33
|
+
EncryptionProtocolValidateGrantKeyGrantScopeMismatch = 'EncryptionProtocolValidateGrantKeyGrantScopeMismatch',
|
|
34
|
+
EncryptionProtocolValidateGrantKeyMissingRequiredTag = 'EncryptionProtocolValidateGrantKeyMissingRequiredTag',
|
|
35
|
+
EncryptionProtocolValidateGrantKeyRecipientMismatch = 'EncryptionProtocolValidateGrantKeyRecipientMismatch',
|
|
36
|
+
EncryptionProtocolValidateRoleAudienceContextInvalid = 'EncryptionProtocolValidateRoleAudienceContextInvalid',
|
|
37
|
+
EncryptionProtocolValidateRoleAudienceInvalid = 'EncryptionProtocolValidateRoleAudienceInvalid',
|
|
38
|
+
EncryptionProtocolValidateSchemaUnexpectedRecord = 'EncryptionProtocolValidateSchemaUnexpectedRecord',
|
|
23
39
|
EventLogNotOpenError = 'EventLogNotOpenError',
|
|
24
40
|
EventLogProgressGap = 'EventLogProgressGap',
|
|
25
41
|
MessagesGrantAuthorizationMismatchedProtocol = 'MessagesGrantAuthorizationMismatchedProtocol',
|
|
@@ -101,6 +117,10 @@ export enum DwnErrorCode {
|
|
|
101
117
|
ProtocolAuthorizationInitialWriteRevalidationNotInitial = 'ProtocolAuthorizationInitialWriteRevalidationNotInitial',
|
|
102
118
|
ProtocolAuthorizationDuplicateRoleRecipient = 'ProtocolAuthorizationDuplicateRoleRecipient',
|
|
103
119
|
ProtocolAuthorizationEncryptionRequired = 'ProtocolAuthorizationEncryptionRequired',
|
|
120
|
+
ProtocolAuthorizationEncryptionKeyAgreementMissing = 'ProtocolAuthorizationEncryptionKeyAgreementMissing',
|
|
121
|
+
ProtocolAuthorizationEncryptionProtocolPathEntryMissing = 'ProtocolAuthorizationEncryptionProtocolPathEntryMissing',
|
|
122
|
+
ProtocolAuthorizationEncryptionRoleAudienceEntryMissing = 'ProtocolAuthorizationEncryptionRoleAudienceEntryMissing',
|
|
123
|
+
ProtocolAuthorizationEncryptionRoleAudienceEpochMissing = 'ProtocolAuthorizationEncryptionRoleAudienceEpochMissing',
|
|
104
124
|
ProtocolAuthorizationImmutableRecord = 'ProtocolAuthorizationImmutableRecord',
|
|
105
125
|
ProtocolAuthorizationInvalidSchema = 'ProtocolAuthorizationInvalidSchema',
|
|
106
126
|
ProtocolAuthorizationInvalidType = 'ProtocolAuthorizationInvalidType',
|
|
@@ -142,6 +162,10 @@ export enum DwnErrorCode {
|
|
|
142
162
|
ProtocolsConfigureInvalidActionUpdateWithoutCreate = 'ProtocolsConfigureInvalidActionUpdateWithoutCreate',
|
|
143
163
|
ProtocolsConfigureInvalidCrossProtocolOf = 'ProtocolsConfigureInvalidCrossProtocolOf',
|
|
144
164
|
ProtocolsConfigureInvalidCrossProtocolRole = 'ProtocolsConfigureInvalidCrossProtocolRole',
|
|
165
|
+
ProtocolsConfigureInvalidEncryptedAnyoneRead = 'ProtocolsConfigureInvalidEncryptedAnyoneRead',
|
|
166
|
+
ProtocolsConfigureInvalidEncryptedRoleMissingKeyAgreement = 'ProtocolsConfigureInvalidEncryptedRoleMissingKeyAgreement',
|
|
167
|
+
ProtocolsConfigureMissingEncryptedPathKeyAgreement = 'ProtocolsConfigureMissingEncryptedPathKeyAgreement',
|
|
168
|
+
ProtocolsConfigureMissingTopLevelKeyAgreement = 'ProtocolsConfigureMissingTopLevelKeyAgreement',
|
|
145
169
|
ProtocolsConfigureInvalidRecipientOfAction = 'ProtocolsConfigureInvalidRecipientOfAction',
|
|
146
170
|
ProtocolsConfigureInvalidRuleSetRecordType = 'ProtocolsConfigureInvalidRuleSetRecordType',
|
|
147
171
|
ProtocolsConfigureInvalidTagSchema = 'ProtocolsConfigureInvalidTagSchema',
|
|
@@ -158,6 +182,7 @@ export enum DwnErrorCode {
|
|
|
158
182
|
RecordsAuthorDelegatedGrantGrantedToAndOwnerSignatureMismatch = 'RecordsAuthorDelegatedGrantGrantedToAndOwnerSignatureMismatch',
|
|
159
183
|
RecordsAuthorDelegatedGrantNotADelegatedGrant = 'RecordsAuthorDelegatedGrantNotADelegatedGrant',
|
|
160
184
|
RecordsDecryptNoMatchingKeyEncryptedFound = 'RecordsDecryptNoMatchingKeyEncryptedFound',
|
|
185
|
+
RecordsDecryptUnsupportedKeyDerivationScheme = 'RecordsDecryptUnsupportedKeyDerivationScheme',
|
|
161
186
|
RecordsCountFilterMissingRequiredProperties = 'RecordsCountFilterMissingRequiredProperties',
|
|
162
187
|
RecordsCountNestedProtocolPathContextIdInvalid = 'RecordsCountNestedProtocolPathContextIdInvalid',
|
|
163
188
|
|
|
@@ -194,6 +219,7 @@ export enum DwnErrorCode {
|
|
|
194
219
|
RecordsWriteCreateMissingSigner = 'RecordsWriteCreateMissingSigner',
|
|
195
220
|
RecordsWriteCreateDataAndDataCidMutuallyExclusive = 'RecordsWriteCreateDataAndDataCidMutuallyExclusive',
|
|
196
221
|
RecordsWriteCreateDataCidAndDataSizeMutuallyInclusive = 'RecordsWriteCreateDataCidAndDataSizeMutuallyInclusive',
|
|
222
|
+
RecordsWriteCreateEncryptionAndEncryptionInputMutuallyExclusive = 'RecordsWriteCreateEncryptionAndEncryptionInputMutuallyExclusive',
|
|
197
223
|
RecordsWriteCreateMissingProtocol = 'RecordsWriteCreateMissingProtocol',
|
|
198
224
|
RecordsWriteDataCidMismatch = 'RecordsWriteDataCidMismatch',
|
|
199
225
|
RecordsWriteDataSizeMismatch = 'RecordsWriteDataSizeMismatch',
|
|
@@ -204,7 +230,6 @@ export enum DwnErrorCode {
|
|
|
204
230
|
RecordsWriteMissingSigner = 'RecordsWriteMissingSigner',
|
|
205
231
|
RecordsWriteMissingDataInPrevious = 'RecordsWriteMissingDataInPrevious',
|
|
206
232
|
RecordsWriteMissingEncodedDataInPrevious = 'RecordsWriteMissingEncodedDataInPrevious',
|
|
207
|
-
RecordsWriteMissingEncryption = 'RecordsWriteMissingEncryption',
|
|
208
233
|
|
|
209
234
|
RecordsWriteNotAllowedAfterDelete = 'RecordsWriteNotAllowedAfterDelete',
|
|
210
235
|
RecordsWriteOwnerAndTenantMismatch = 'RecordsWriteOwnerAndTenantMismatch',
|
|
@@ -214,7 +239,10 @@ export enum DwnErrorCode {
|
|
|
214
239
|
RecordsWriteValidateIntegrityContextIdMismatch = 'RecordsWriteValidateIntegrityContextIdMismatch',
|
|
215
240
|
RecordsWriteValidateIntegrityContextIdNotInSignerSignaturePayload = 'RecordsWriteValidateIntegrityContextIdNotInSignerSignaturePayload',
|
|
216
241
|
RecordsWriteValidateIntegrityDateCreatedMismatch = 'RecordsWriteValidateIntegrityDateCreatedMismatch',
|
|
242
|
+
RecordsWriteValidateIntegrityEncryptionCidMissing = 'RecordsWriteValidateIntegrityEncryptionCidMissing',
|
|
217
243
|
RecordsWriteValidateIntegrityEncryptionCidMismatch = 'RecordsWriteValidateIntegrityEncryptionCidMismatch',
|
|
244
|
+
RecordsWriteValidateIntegrityEncryptionEphemeralPublicKeyInvalid = 'RecordsWriteValidateIntegrityEncryptionEphemeralPublicKeyInvalid',
|
|
245
|
+
RecordsWriteValidateIntegrityEncryptionInitializationVectorInvalid = 'RecordsWriteValidateIntegrityEncryptionInitializationVectorInvalid',
|
|
218
246
|
RecordsWriteValidateIntegrityRecordIdUnauthorized = 'RecordsWriteValidateIntegrityRecordIdUnauthorized',
|
|
219
247
|
SchemaValidatorAdditionalPropertyNotAllowed = 'SchemaValidatorAdditionalPropertyNotAllowed',
|
|
220
248
|
SchemaValidatorFailure = 'SchemaValidatorFailure',
|
|
@@ -8,6 +8,7 @@ import type { DataEncodedRecordsWriteMessage, RecordsDeleteMessage, RecordsWrite
|
|
|
8
8
|
import type { MessagesQueryMessage, MessagesReadMessage, MessagesSubscribeMessage } from '../types/messages-types.js';
|
|
9
9
|
|
|
10
10
|
import { DwnInterfaceName } from '../enums/dwn-interface-method.js';
|
|
11
|
+
import { EncryptionProtocol } from '../protocols/encryption.js';
|
|
11
12
|
import { GrantAuthorization } from './grant-authorization.js';
|
|
12
13
|
import { PermissionScopeMatcher } from '../utils/permission-scope.js';
|
|
13
14
|
import { PermissionsProtocol } from '../protocols/permissions.js';
|
|
@@ -240,6 +241,10 @@ export class MessagesGrantAuthorization {
|
|
|
240
241
|
);
|
|
241
242
|
}
|
|
242
243
|
|
|
244
|
+
if (recordsWriteMessage.descriptor.protocol === EncryptionProtocol.uri) {
|
|
245
|
+
return MessagesGrantAuthorization.isEncryptionRecordScopeAuthorized(recordsWriteMessage, incomingScope);
|
|
246
|
+
}
|
|
247
|
+
|
|
243
248
|
return PermissionScopeMatcher.matches(incomingScope, MessagesGrantAuthorization.getRecordsScopeTarget(recordsWriteMessage));
|
|
244
249
|
}
|
|
245
250
|
|
|
@@ -263,6 +268,23 @@ export class MessagesGrantAuthorization {
|
|
|
263
268
|
&& PermissionScopeMatcher.matches(incomingScope, permissionScope);
|
|
264
269
|
}
|
|
265
270
|
|
|
271
|
+
private static isEncryptionRecordScopeAuthorized(
|
|
272
|
+
recordsWriteMessage: RecordsWriteMessage,
|
|
273
|
+
incomingScope: MessagesPermissionScope,
|
|
274
|
+
): boolean {
|
|
275
|
+
const tags = recordsWriteMessage.descriptor.tags;
|
|
276
|
+
const protocol = tags?.protocol;
|
|
277
|
+
if (typeof protocol !== 'string') {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return PermissionScopeMatcher.matches(incomingScope, {
|
|
282
|
+
protocol,
|
|
283
|
+
protocolPath : MessagesGrantAuthorization.getStringTag(recordsWriteMessage, 'protocolPath'),
|
|
284
|
+
contextId : MessagesGrantAuthorization.getStringTag(recordsWriteMessage, 'contextId'),
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
266
288
|
private static isProtocolsConfigureScopeAuthorized(
|
|
267
289
|
protocolsConfigureMessage: ProtocolsConfigureMessage,
|
|
268
290
|
incomingScope: MessagesPermissionScope
|
|
@@ -291,6 +313,11 @@ export class MessagesGrantAuthorization {
|
|
|
291
313
|
return { protocol, protocolPath, contextId };
|
|
292
314
|
}
|
|
293
315
|
|
|
316
|
+
private static getStringTag(recordsWriteMessage: RecordsWriteMessage, tag: string): string | undefined {
|
|
317
|
+
const value = recordsWriteMessage.descriptor.tags?.[tag];
|
|
318
|
+
return typeof value === 'string' ? value : undefined;
|
|
319
|
+
}
|
|
320
|
+
|
|
294
321
|
private static isSubtreeScope(scope: MessagesPermissionScope): boolean {
|
|
295
322
|
return scope.protocolPath !== undefined || scope.contextId !== undefined;
|
|
296
323
|
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { RecordsWrite } from '../interfaces/records-write.js';
|
|
2
2
|
import type { RecordsWriteMessage } from '../types/records-types.js';
|
|
3
|
+
import type { RoleAudienceKeyEncryption } from '../utils/encryption.js';
|
|
3
4
|
import type { ValidationStateReader } from '../types/validation-state-reader.js';
|
|
4
|
-
import type { ProtocolDefinition, ProtocolRuleSet, ProtocolType, ProtocolTypes } from '../types/protocols-types.js';
|
|
5
|
-
|
|
6
|
-
import { ProtocolRecordLimitStrategy } from '../types/protocols-types.js';
|
|
5
|
+
import type { ProtocolActionRule, ProtocolDefinition, ProtocolRuleSet, ProtocolType, ProtocolTypes } from '../types/protocols-types.js';
|
|
7
6
|
|
|
7
|
+
import { KeyDerivationScheme } from '../utils/hd-key.js';
|
|
8
8
|
import { Records } from '../utils/records.js';
|
|
9
9
|
import { validateProtocolTags } from '../utils/protocol-tags.js';
|
|
10
10
|
import { DwnError, DwnErrorCode } from './dwn-error.js';
|
|
11
|
-
import {
|
|
11
|
+
import { Encryption, ROLE_AUDIENCE_DERIVATION_SCHEME } from '../utils/encryption.js';
|
|
12
|
+
import { getRuleSetAtPath, getTypeName, parseCrossProtocolRef } from '../utils/protocols.js';
|
|
13
|
+
import { ProtocolAction, ProtocolRecordLimitStrategy } from '../types/protocols-types.js';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Verifies the `protocolPath` declared in the given message matches the path of actual record chain.
|
|
@@ -170,7 +172,14 @@ export async function verifyTypeWithComposition(
|
|
|
170
172
|
tenant, declaredProtocolPath, protocolDefinition, validationStateReader, protocolDefinitionTimestamp
|
|
171
173
|
);
|
|
172
174
|
|
|
173
|
-
verifyType(inboundMessage, protocolTypes, declaredTypeName);
|
|
175
|
+
const protocolType = verifyType(inboundMessage, protocolTypes, declaredTypeName);
|
|
176
|
+
await verifyProtocolPathEncryptionIfNeeded(
|
|
177
|
+
tenant,
|
|
178
|
+
inboundMessage,
|
|
179
|
+
protocolDefinition,
|
|
180
|
+
protocolType,
|
|
181
|
+
validationStateReader,
|
|
182
|
+
);
|
|
174
183
|
}
|
|
175
184
|
|
|
176
185
|
/**
|
|
@@ -216,7 +225,7 @@ export function verifyType(
|
|
|
216
225
|
inboundMessage: RecordsWriteMessage,
|
|
217
226
|
protocolTypes: ProtocolTypes,
|
|
218
227
|
typeName?: string,
|
|
219
|
-
):
|
|
228
|
+
): ProtocolType {
|
|
220
229
|
const declaredTypeName = typeName ?? getTypeName(inboundMessage.descriptor.protocolPath);
|
|
221
230
|
const typeNames = Object.keys(protocolTypes);
|
|
222
231
|
|
|
@@ -254,6 +263,136 @@ export function verifyType(
|
|
|
254
263
|
`type '${declaredTypeName}' requires encryption but message has no encryption metadata`
|
|
255
264
|
);
|
|
256
265
|
}
|
|
266
|
+
|
|
267
|
+
return protocolType;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async function verifyProtocolPathEncryptionIfNeeded(
|
|
271
|
+
tenant: string,
|
|
272
|
+
inboundMessage: RecordsWriteMessage,
|
|
273
|
+
protocolDefinition: ProtocolDefinition,
|
|
274
|
+
protocolType: ProtocolType,
|
|
275
|
+
validationStateReader: ValidationStateReader,
|
|
276
|
+
): Promise<void> {
|
|
277
|
+
if (protocolType.encryptionRequired !== true) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const ruleSet = getRuleSetAtPath(inboundMessage.descriptor.protocolPath, protocolDefinition.structure);
|
|
282
|
+
if (ruleSet?.$keyAgreement?.publicKeyJwk === undefined) {
|
|
283
|
+
throw new DwnError(
|
|
284
|
+
DwnErrorCode.ProtocolAuthorizationEncryptionKeyAgreementMissing,
|
|
285
|
+
`encrypted protocol path '${inboundMessage.descriptor.protocolPath}' has no $keyAgreement`
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const publicKeyJwk = ruleSet.$keyAgreement.publicKeyJwk;
|
|
290
|
+
const keyId = await Encryption.getKeyId(publicKeyJwk);
|
|
291
|
+
const hasProtocolPathEntry = inboundMessage.encryption!.keyEncryption.some((entry): boolean =>
|
|
292
|
+
entry.derivationScheme === KeyDerivationScheme.ProtocolPath && entry.keyId === keyId
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
if (!hasProtocolPathEntry) {
|
|
296
|
+
throw new DwnError(
|
|
297
|
+
DwnErrorCode.ProtocolAuthorizationEncryptionProtocolPathEntryMissing,
|
|
298
|
+
`encrypted record is missing a protocolPath keyEncryption entry for '${inboundMessage.descriptor.protocolPath}'`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
await verifyRoleAudienceEncryptionIfNeeded(tenant, inboundMessage, protocolDefinition, ruleSet, validationStateReader);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
async function verifyRoleAudienceEncryptionIfNeeded(
|
|
306
|
+
tenant: string,
|
|
307
|
+
inboundMessage: RecordsWriteMessage,
|
|
308
|
+
protocolDefinition: ProtocolDefinition,
|
|
309
|
+
ruleSet: ProtocolRuleSet,
|
|
310
|
+
validationStateReader: ValidationStateReader,
|
|
311
|
+
): Promise<void> {
|
|
312
|
+
const readRoleRules = (ruleSet.$actions ?? []).filter((actionRule): boolean =>
|
|
313
|
+
actionRule.role !== undefined && actionRule.can.includes(ProtocolAction.Read)
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
for (const actionRule of readRoleRules) {
|
|
317
|
+
const roleAudience = resolveRoleAudience(actionRule, inboundMessage, protocolDefinition);
|
|
318
|
+
if (roleAudience === undefined) {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const matchingEntry = inboundMessage.encryption!.keyEncryption.find((entry): entry is RoleAudienceKeyEncryption =>
|
|
323
|
+
entry.derivationScheme === ROLE_AUDIENCE_DERIVATION_SCHEME &&
|
|
324
|
+
entry.protocol === roleAudience.protocol &&
|
|
325
|
+
entry.role === roleAudience.role
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
if (matchingEntry === undefined) {
|
|
329
|
+
throw new DwnError(
|
|
330
|
+
DwnErrorCode.ProtocolAuthorizationEncryptionRoleAudienceEntryMissing,
|
|
331
|
+
`encrypted record is missing a roleAudience keyEncryption entry for role '${roleAudience.role}'`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const matchingEpochs = await validationStateReader.queryAudienceEpochs({
|
|
336
|
+
tenant,
|
|
337
|
+
protocol : roleAudience.protocol,
|
|
338
|
+
contextId : roleAudience.contextId,
|
|
339
|
+
role : roleAudience.role,
|
|
340
|
+
epoch : matchingEntry.epoch,
|
|
341
|
+
keyId : matchingEntry.keyId,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
if (matchingEpochs.length === 0) {
|
|
345
|
+
throw new DwnError(
|
|
346
|
+
DwnErrorCode.ProtocolAuthorizationEncryptionRoleAudienceEpochMissing,
|
|
347
|
+
`encrypted record references a missing audienceEpoch for role '${roleAudience.role}'`
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function resolveRoleAudience(
|
|
354
|
+
actionRule: ProtocolActionRule,
|
|
355
|
+
inboundMessage: RecordsWriteMessage,
|
|
356
|
+
protocolDefinition: ProtocolDefinition,
|
|
357
|
+
): { protocol: string; role: string; contextId: string } | undefined {
|
|
358
|
+
const roleRef = actionRule.role;
|
|
359
|
+
if (roleRef === undefined) {
|
|
360
|
+
return undefined;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const parsed = parseCrossProtocolRef(roleRef);
|
|
364
|
+
const protocol = parsed === undefined
|
|
365
|
+
? inboundMessage.descriptor.protocol
|
|
366
|
+
: protocolDefinition.uses?.[parsed.alias];
|
|
367
|
+
const role = parsed === undefined ? roleRef : parsed.protocolPath;
|
|
368
|
+
if (protocol === undefined) {
|
|
369
|
+
return undefined;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const contextId = getRoleAudienceContextId(inboundMessage, role);
|
|
373
|
+
return contextId === undefined ? undefined : { protocol, role, contextId };
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function getRoleAudienceContextId(
|
|
377
|
+
inboundMessage: RecordsWriteMessage,
|
|
378
|
+
rolePath: string,
|
|
379
|
+
): string | undefined {
|
|
380
|
+
const parentDepth = rolePath.split('/').length - 1;
|
|
381
|
+
if (parentDepth === 0) {
|
|
382
|
+
return '';
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const contextId = inboundMessage.contextId;
|
|
386
|
+
if (typeof contextId !== 'string') {
|
|
387
|
+
return undefined;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const contextSegments = contextId.split('/');
|
|
391
|
+
if (contextSegments.length < parentDepth) {
|
|
392
|
+
return undefined;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return contextSegments.slice(0, parentDepth).join('/');
|
|
257
396
|
}
|
|
258
397
|
|
|
259
398
|
/**
|
|
@@ -87,6 +87,19 @@ export class RecordingValidationStateReader implements ValidationStateReader {
|
|
|
87
87
|
return this.inner.queryLatestRoleRecords(input);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
/** @inheritdoc */
|
|
91
|
+
public async queryAudienceEpochs(input: {
|
|
92
|
+
tenant: string;
|
|
93
|
+
protocol: string;
|
|
94
|
+
contextId: string;
|
|
95
|
+
role: string;
|
|
96
|
+
epoch: number;
|
|
97
|
+
keyId?: string;
|
|
98
|
+
}): Promise<RecordsWriteMessage[]> {
|
|
99
|
+
this.recordedReads.push({ method: 'queryAudienceEpochs' });
|
|
100
|
+
return this.inner.queryAudienceEpochs(input);
|
|
101
|
+
}
|
|
102
|
+
|
|
90
103
|
/** @inheritdoc */
|
|
91
104
|
public async fetchGrant(tenant: string, permissionGrantId: string): Promise<PermissionGrant> {
|
|
92
105
|
this.recordedReads.push({ method: 'fetchGrant' });
|
|
@@ -5,7 +5,9 @@ import type { ValidationStateReader } from '../types/validation-state-reader.js'
|
|
|
5
5
|
|
|
6
6
|
import { DwnErrorCode } from './dwn-error.js';
|
|
7
7
|
import { Encoder } from '../utils/encoder.js';
|
|
8
|
+
import { EncryptionProtocol } from '../protocols/encryption.js';
|
|
8
9
|
import { Message } from './message.js';
|
|
10
|
+
import { ROLE_AUDIENCE_DERIVATION_SCHEME } from '../utils/encryption.js';
|
|
9
11
|
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
10
12
|
import { isCrossProtocolRef, parseCrossProtocolRef } from '../utils/protocols.js';
|
|
11
13
|
|
|
@@ -40,6 +42,14 @@ export type ReplicationApplyResultContext = {
|
|
|
40
42
|
missingAncestorRecordIds?: string[];
|
|
41
43
|
};
|
|
42
44
|
|
|
45
|
+
type AudienceDependencyTags = {
|
|
46
|
+
protocol: string;
|
|
47
|
+
contextId: string;
|
|
48
|
+
role: string;
|
|
49
|
+
epoch: number;
|
|
50
|
+
keyId: string;
|
|
51
|
+
};
|
|
52
|
+
|
|
43
53
|
export type DependencyRef =
|
|
44
54
|
| { type: 'Protocol'; protocol: string; messageCid?: string; terminal?: boolean }
|
|
45
55
|
| { type: 'InitialWrite'; recordId: string; protocol?: string; messageCid?: string; terminal?: boolean }
|
|
@@ -47,7 +57,14 @@ export type DependencyRef =
|
|
|
47
57
|
| { type: 'Ancestor'; recordId: string; protocol?: string; messageCid?: string; terminal?: boolean }
|
|
48
58
|
| { type: 'Role'; protocol: string; protocolPath: string; recipient: string; contextPrefix?: string; messageCid?: string; terminal?: boolean }
|
|
49
59
|
| { type: 'Grant'; permissionGrantId: string; messageCid?: string; terminal?: boolean }
|
|
50
|
-
| {
|
|
60
|
+
| {
|
|
61
|
+
type: 'EncryptionProtocol';
|
|
62
|
+
protocolPath: 'audienceEpoch' | 'audienceKey' | 'grantKey';
|
|
63
|
+
tags?: Record<string, string | number>;
|
|
64
|
+
recipient?: string;
|
|
65
|
+
messageCid?: string;
|
|
66
|
+
terminal?: boolean;
|
|
67
|
+
}
|
|
51
68
|
| { type: 'CrossProtocolRef'; protocol: string; recordId: string; messageCid?: string; terminal?: boolean }
|
|
52
69
|
| { type: 'RecordData'; recordId: string; dataCid: string; protocol?: string; messageCid?: string; terminal?: boolean };
|
|
53
70
|
|
|
@@ -180,7 +197,14 @@ function dependencyRefsFromStatus(
|
|
|
180
197
|
case DwnErrorCode.GrantAuthorizationGrantMissing:
|
|
181
198
|
return toRefList(grantDependencyFromMessage(message));
|
|
182
199
|
case DwnErrorCode.ProtocolAuthorizationMatchingRoleRecordNotFound:
|
|
200
|
+
case DwnErrorCode.EncryptionProtocolValidateAudienceWriterUnauthorized:
|
|
183
201
|
return toRefList(roleDependencyFromMessage(message, context));
|
|
202
|
+
case DwnErrorCode.EncryptionProtocolValidateAudienceEpochMissing:
|
|
203
|
+
return toRefList(encryptionProtocolDependencyFromMessage(message, EncryptionProtocol.audienceEpochPath));
|
|
204
|
+
case DwnErrorCode.ProtocolAuthorizationEncryptionRoleAudienceEpochMissing:
|
|
205
|
+
return toRefList(encryptionProtocolDependencyFromRoleAudienceEntry(message, detail));
|
|
206
|
+
case DwnErrorCode.EncryptionProtocolValidateAudienceKeyRoleRecordMissing:
|
|
207
|
+
return toRefList(roleDependencyFromEncryptionAudienceRecipient(message));
|
|
184
208
|
case DwnErrorCode.RecordsWriteMissingDataInPrevious:
|
|
185
209
|
case DwnErrorCode.RecordsWriteMissingEncodedDataInPrevious:
|
|
186
210
|
return toRefList(recordDataDependencyFromMessage(message));
|
|
@@ -214,7 +238,7 @@ function protocolDependencyFromMessage(message: GenericMessage, detail: string):
|
|
|
214
238
|
return { type: 'Protocol', protocol: composedProtocol };
|
|
215
239
|
}
|
|
216
240
|
|
|
217
|
-
const protocol = (message
|
|
241
|
+
const protocol = dependencyProtocolFromMessage(message);
|
|
218
242
|
return typeof protocol === 'string' ? { type: 'Protocol', protocol } : undefined;
|
|
219
243
|
}
|
|
220
244
|
|
|
@@ -235,7 +259,7 @@ function parentDependenciesFromMessage(
|
|
|
235
259
|
return [];
|
|
236
260
|
}
|
|
237
261
|
|
|
238
|
-
const protocol = (message
|
|
262
|
+
const protocol = dependencyProtocolFromMessage(message);
|
|
239
263
|
const protocolProperty = typeof protocol === 'string' ? { protocol } : {};
|
|
240
264
|
const ancestorRefs = (context.missingAncestorRecordIds ?? [])
|
|
241
265
|
.filter((recordId): boolean => recordId !== parentRef.recordId)
|
|
@@ -248,9 +272,8 @@ function parentDependencyFromMessage(
|
|
|
248
272
|
message: GenericMessage,
|
|
249
273
|
detail: string,
|
|
250
274
|
): Extract<DependencyRef, { type: 'Parent' }> | undefined {
|
|
251
|
-
const descriptor = message.descriptor as Record<string, unknown>;
|
|
252
275
|
const parentId = parentRecordIdFromMessage(message, detail);
|
|
253
|
-
const protocol = /in protocol '([^']+)'/.exec(detail)?.[1] ??
|
|
276
|
+
const protocol = /in protocol '([^']+)'/.exec(detail)?.[1] ?? dependencyProtocolFromMessage(message);
|
|
254
277
|
|
|
255
278
|
if (parentId === undefined || typeof protocol !== 'string') {
|
|
256
279
|
return undefined;
|
|
@@ -278,7 +301,7 @@ function ancestorDependenciesFromMessage(
|
|
|
278
301
|
detail: string,
|
|
279
302
|
context: ReplicationApplyResultContext,
|
|
280
303
|
): DependencyRef[] {
|
|
281
|
-
const protocol = (message
|
|
304
|
+
const protocol = dependencyProtocolFromMessage(message);
|
|
282
305
|
const protocolProperty = typeof protocol === 'string' ? { protocol } : {};
|
|
283
306
|
|
|
284
307
|
const batchedRecordIds = context.missingAncestorRecordIds;
|
|
@@ -303,7 +326,7 @@ function initialWriteDependencyFromMessage(message: GenericMessage): DependencyR
|
|
|
303
326
|
return undefined;
|
|
304
327
|
}
|
|
305
328
|
|
|
306
|
-
const protocol = (message
|
|
329
|
+
const protocol = dependencyProtocolFromMessage(message);
|
|
307
330
|
return {
|
|
308
331
|
type : 'InitialWrite',
|
|
309
332
|
recordId : message.recordId,
|
|
@@ -312,6 +335,14 @@ function initialWriteDependencyFromMessage(message: GenericMessage): DependencyR
|
|
|
312
335
|
}
|
|
313
336
|
|
|
314
337
|
function grantDependencyFromMessage(message: GenericMessage): DependencyRef | undefined {
|
|
338
|
+
if (isEncryptionProtocolMessage(message)) {
|
|
339
|
+
const tags = (message.descriptor as Record<string, unknown>).tags;
|
|
340
|
+
const grantId = isRecordObject(tags) ? tags.grantId : undefined;
|
|
341
|
+
if (typeof grantId === 'string') {
|
|
342
|
+
return { type: 'Grant', permissionGrantId: grantId };
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
315
346
|
const descriptorGrantId = (message.descriptor as Record<string, unknown>).permissionGrantId;
|
|
316
347
|
if (typeof descriptorGrantId === 'string') {
|
|
317
348
|
return { type: 'Grant', permissionGrantId: descriptorGrantId };
|
|
@@ -330,7 +361,7 @@ function recordDataDependencyFromMessage(message: GenericMessage): DependencyRef
|
|
|
330
361
|
|
|
331
362
|
const descriptor = message.descriptor as Record<string, unknown>;
|
|
332
363
|
const dataCid = descriptor.dataCid;
|
|
333
|
-
const protocol =
|
|
364
|
+
const protocol = dependencyProtocolFromMessage(message);
|
|
334
365
|
return typeof dataCid === 'string'
|
|
335
366
|
? {
|
|
336
367
|
type : 'RecordData',
|
|
@@ -342,6 +373,11 @@ function recordDataDependencyFromMessage(message: GenericMessage): DependencyRef
|
|
|
342
373
|
}
|
|
343
374
|
|
|
344
375
|
function roleDependencyFromMessage(message: GenericMessage, context: ReplicationApplyResultContext): DependencyRef | undefined {
|
|
376
|
+
const encryptionRoleDependency = roleDependencyFromEncryptionAudienceWriter(message, context);
|
|
377
|
+
if (encryptionRoleDependency !== undefined) {
|
|
378
|
+
return encryptionRoleDependency;
|
|
379
|
+
}
|
|
380
|
+
|
|
345
381
|
const descriptor = message.descriptor as Record<string, unknown>;
|
|
346
382
|
const filter = descriptor.filter as Record<string, unknown> | undefined;
|
|
347
383
|
const protocol = descriptor.protocol ?? filter?.protocol;
|
|
@@ -383,6 +419,184 @@ function roleDependencyFromMessage(message: GenericMessage, context: Replication
|
|
|
383
419
|
};
|
|
384
420
|
}
|
|
385
421
|
|
|
422
|
+
function encryptionProtocolDependencyFromMessage(
|
|
423
|
+
message: GenericMessage,
|
|
424
|
+
protocolPath: Extract<DependencyRef, { type: 'EncryptionProtocol' }>['protocolPath'],
|
|
425
|
+
): DependencyRef | undefined {
|
|
426
|
+
const tags = encryptionAudienceTagsFromMessage(message);
|
|
427
|
+
return tags === undefined
|
|
428
|
+
? undefined
|
|
429
|
+
: { type: 'EncryptionProtocol', protocolPath, tags };
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function encryptionProtocolDependencyFromRoleAudienceEntry(
|
|
433
|
+
message: GenericMessage,
|
|
434
|
+
detail: string,
|
|
435
|
+
): DependencyRef | undefined {
|
|
436
|
+
const descriptor = message.descriptor as Record<string, unknown>;
|
|
437
|
+
const messageContextId = (message as { contextId?: unknown }).contextId;
|
|
438
|
+
const contextId = typeof messageContextId === 'string' ? messageContextId : descriptor.contextId;
|
|
439
|
+
const keyEncryption = (message as {
|
|
440
|
+
encryption?: {
|
|
441
|
+
keyEncryption?: Record<string, unknown>[];
|
|
442
|
+
};
|
|
443
|
+
}).encryption?.keyEncryption;
|
|
444
|
+
if (typeof contextId !== 'string' || !Array.isArray(keyEncryption)) {
|
|
445
|
+
return undefined;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const missingRole = /role '([^']+)'/.exec(detail)?.[1];
|
|
449
|
+
const entry = keyEncryption.find((candidate): boolean =>
|
|
450
|
+
candidate.derivationScheme === ROLE_AUDIENCE_DERIVATION_SCHEME &&
|
|
451
|
+
typeof candidate.protocol === 'string' &&
|
|
452
|
+
typeof candidate.role === 'string' &&
|
|
453
|
+
(missingRole === undefined || candidate.role === missingRole) &&
|
|
454
|
+
typeof candidate.epoch === 'number' &&
|
|
455
|
+
typeof candidate.keyId === 'string'
|
|
456
|
+
);
|
|
457
|
+
if (entry === undefined) {
|
|
458
|
+
return undefined;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const role = entry.role as string;
|
|
462
|
+
const audienceContextId = roleAudienceContextId(role, contextId);
|
|
463
|
+
if (audienceContextId === undefined) {
|
|
464
|
+
return undefined;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return {
|
|
468
|
+
type : 'EncryptionProtocol',
|
|
469
|
+
protocolPath : EncryptionProtocol.audienceEpochPath,
|
|
470
|
+
tags : {
|
|
471
|
+
protocol : entry.protocol as string,
|
|
472
|
+
contextId : audienceContextId,
|
|
473
|
+
role,
|
|
474
|
+
epoch : entry.epoch as number,
|
|
475
|
+
keyId : entry.keyId as string,
|
|
476
|
+
},
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function roleDependencyFromEncryptionAudienceRecipient(message: GenericMessage): DependencyRef | undefined {
|
|
481
|
+
const tags = encryptionAudienceTagsFromMessage(message);
|
|
482
|
+
const recipient = (message.descriptor as Record<string, unknown>).recipient;
|
|
483
|
+
if (tags === undefined || typeof recipient !== 'string') {
|
|
484
|
+
return undefined;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return {
|
|
488
|
+
type : 'Role',
|
|
489
|
+
protocol : tags.protocol,
|
|
490
|
+
protocolPath : tags.role,
|
|
491
|
+
recipient,
|
|
492
|
+
...(tags.contextId === '' ? {} : { contextPrefix: tags.contextId }),
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function roleDependencyFromEncryptionAudienceWriter(
|
|
497
|
+
message: GenericMessage,
|
|
498
|
+
context: ReplicationApplyResultContext,
|
|
499
|
+
): DependencyRef | undefined {
|
|
500
|
+
const tags = encryptionAudienceTagsFromMessage(message);
|
|
501
|
+
const protocolRole = getSignaturePayload(message)?.protocolRole;
|
|
502
|
+
const recipient = Message.getAuthor(message);
|
|
503
|
+
if (tags === undefined || typeof protocolRole !== 'string' || recipient === undefined) {
|
|
504
|
+
return undefined;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
let roleProtocol = tags.protocol;
|
|
508
|
+
let roleProtocolPath = protocolRole;
|
|
509
|
+
if (isCrossProtocolRef(protocolRole)) {
|
|
510
|
+
const parsed = parseCrossProtocolRef(protocolRole);
|
|
511
|
+
const referencedProtocol = parsed === undefined ? undefined : context.protocolDefinition?.uses?.[parsed.alias];
|
|
512
|
+
if (parsed === undefined || referencedProtocol === undefined) {
|
|
513
|
+
return undefined;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
roleProtocol = referencedProtocol;
|
|
517
|
+
roleProtocolPath = parsed.protocolPath;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
const contextPrefix = roleContextPrefix(roleProtocolPath, tags.contextId);
|
|
521
|
+
return {
|
|
522
|
+
type : 'Role',
|
|
523
|
+
protocol : roleProtocol,
|
|
524
|
+
protocolPath : roleProtocolPath,
|
|
525
|
+
recipient,
|
|
526
|
+
...(contextPrefix === undefined ? {} : { contextPrefix }),
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function encryptionAudienceTagsFromMessage(message: GenericMessage): AudienceDependencyTags | undefined {
|
|
531
|
+
if (!isEncryptionProtocolMessage(message)) {
|
|
532
|
+
return undefined;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const tags = (message.descriptor as Record<string, unknown>).tags;
|
|
536
|
+
if (!isRecordObject(tags)) {
|
|
537
|
+
return undefined;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const { protocol, contextId, role, epoch, keyId } = tags;
|
|
541
|
+
if (
|
|
542
|
+
typeof protocol !== 'string' ||
|
|
543
|
+
typeof contextId !== 'string' ||
|
|
544
|
+
typeof role !== 'string' ||
|
|
545
|
+
typeof epoch !== 'number' ||
|
|
546
|
+
typeof keyId !== 'string'
|
|
547
|
+
) {
|
|
548
|
+
return undefined;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
return { protocol, contextId, role, epoch, keyId };
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
function dependencyProtocolFromMessage(message: GenericMessage): string | undefined {
|
|
555
|
+
if (isEncryptionProtocolMessage(message)) {
|
|
556
|
+
const tags = (message.descriptor as Record<string, unknown>).tags;
|
|
557
|
+
const protocol = isRecordObject(tags) ? tags.protocol : undefined;
|
|
558
|
+
return typeof protocol === 'string' ? protocol : undefined;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const descriptor = message.descriptor as Record<string, unknown>;
|
|
562
|
+
const filter = descriptor.filter as Record<string, unknown> | undefined;
|
|
563
|
+
const protocol = descriptor.protocol ?? filter?.protocol;
|
|
564
|
+
return typeof protocol === 'string' ? protocol : undefined;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
function isEncryptionProtocolMessage(message: GenericMessage): boolean {
|
|
568
|
+
const descriptor = message.descriptor as Record<string, unknown>;
|
|
569
|
+
return descriptor.interface === DwnInterfaceName.Records &&
|
|
570
|
+
descriptor.protocol === EncryptionProtocol.uri;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
function roleContextPrefix(rolePath: string, contextId: string): string | undefined {
|
|
574
|
+
const roleSegments = rolePath.split('/').length - 1;
|
|
575
|
+
if (roleSegments === 0 || contextId === '') {
|
|
576
|
+
return undefined;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return contextId.split('/').slice(0, roleSegments).join('/');
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
function roleAudienceContextId(rolePath: string, contextId: string): string | undefined {
|
|
583
|
+
const roleSegments = rolePath.split('/').length - 1;
|
|
584
|
+
if (roleSegments === 0) {
|
|
585
|
+
return '';
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const contextSegments = contextId.split('/');
|
|
589
|
+
if (contextSegments.length < roleSegments) {
|
|
590
|
+
return undefined;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
return contextSegments.slice(0, roleSegments).join('/');
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
function isRecordObject(value: unknown): value is Record<string, unknown> {
|
|
597
|
+
return typeof value === 'object' && value !== null;
|
|
598
|
+
}
|
|
599
|
+
|
|
386
600
|
function isRecordsWrite(message: GenericMessage): message is GenericMessage & { recordId: string } {
|
|
387
601
|
return message.descriptor.interface === DwnInterfaceName.Records &&
|
|
388
602
|
message.descriptor.method === DwnMethodName.Write &&
|