@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.
Files changed (204) hide show
  1. package/dist/browser.mjs +15 -15
  2. package/dist/browser.mjs.map +4 -4
  3. package/dist/esm/generated/precompiled-validators.js +5406 -2200
  4. package/dist/esm/generated/precompiled-validators.js.map +1 -1
  5. package/dist/esm/json-schemas/definitions.json +18 -0
  6. package/dist/esm/src/core/constants.js +3 -3
  7. package/dist/esm/src/core/constants.js.map +1 -1
  8. package/dist/esm/src/core/dwn-error.js +29 -1
  9. package/dist/esm/src/core/dwn-error.js.map +1 -1
  10. package/dist/esm/src/core/messages-grant-authorization.js +20 -0
  11. package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
  12. package/dist/esm/src/core/protocol-authorization-validation.js +80 -3
  13. package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
  14. package/dist/esm/src/core/recording-validation-state-reader.js +5 -0
  15. package/dist/esm/src/core/recording-validation-state-reader.js.map +1 -1
  16. package/dist/esm/src/core/replication-apply.js +163 -7
  17. package/dist/esm/src/core/replication-apply.js.map +1 -1
  18. package/dist/esm/src/core/validation-state-reader.js +20 -0
  19. package/dist/esm/src/core/validation-state-reader.js.map +1 -1
  20. package/dist/esm/src/dwn.js +19 -2
  21. package/dist/esm/src/dwn.js.map +1 -1
  22. package/dist/esm/src/handlers/messages-query.js +3 -5
  23. package/dist/esm/src/handlers/messages-query.js.map +1 -1
  24. package/dist/esm/src/handlers/protocols-configure.js +10 -4
  25. package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
  26. package/dist/esm/src/handlers/records-write.js +1 -1
  27. package/dist/esm/src/handlers/records-write.js.map +1 -1
  28. package/dist/esm/src/index.js +2 -1
  29. package/dist/esm/src/index.js.map +1 -1
  30. package/dist/esm/src/interfaces/protocols-configure.js +23 -10
  31. package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
  32. package/dist/esm/src/interfaces/records-write-signing.js +2 -8
  33. package/dist/esm/src/interfaces/records-write-signing.js.map +1 -1
  34. package/dist/esm/src/interfaces/records-write.js +43 -65
  35. package/dist/esm/src/interfaces/records-write.js.map +1 -1
  36. package/dist/esm/src/protocols/encryption.js +411 -0
  37. package/dist/esm/src/protocols/encryption.js.map +1 -0
  38. package/dist/esm/src/protocols/permission-grant.js +3 -3
  39. package/dist/esm/src/protocols/permission-grant.js.map +1 -1
  40. package/dist/esm/src/protocols/permissions.js +1 -0
  41. package/dist/esm/src/protocols/permissions.js.map +1 -1
  42. package/dist/esm/src/types/message-types.js.map +1 -1
  43. package/dist/esm/src/types/permission-types.js.map +1 -1
  44. package/dist/esm/src/types/protocols-types.js.map +1 -1
  45. package/dist/esm/src/utils/encryption.js +135 -187
  46. package/dist/esm/src/utils/encryption.js.map +1 -1
  47. package/dist/esm/src/utils/hd-key.js +0 -1
  48. package/dist/esm/src/utils/hd-key.js.map +1 -1
  49. package/dist/esm/src/utils/permission-scope.js +9 -6
  50. package/dist/esm/src/utils/permission-scope.js.map +1 -1
  51. package/dist/esm/src/utils/protocols.js +12 -9
  52. package/dist/esm/src/utils/protocols.js.map +1 -1
  53. package/dist/esm/src/utils/records.js +54 -56
  54. package/dist/esm/src/utils/records.js.map +1 -1
  55. package/dist/esm/src/utils/replication.js +27 -4
  56. package/dist/esm/src/utils/replication.js.map +1 -1
  57. package/dist/esm/tests/core/replication-apply.spec.js +141 -1
  58. package/dist/esm/tests/core/replication-apply.spec.js.map +1 -1
  59. package/dist/esm/tests/core/replication-replay-property.spec.js +1 -0
  60. package/dist/esm/tests/core/replication-replay-property.spec.js.map +1 -1
  61. package/dist/esm/tests/core/validation-read-closure.spec.js +111 -0
  62. package/dist/esm/tests/core/validation-read-closure.spec.js.map +1 -1
  63. package/dist/esm/tests/core/validation-state-reader.spec.js +89 -0
  64. package/dist/esm/tests/core/validation-state-reader.spec.js.map +1 -1
  65. package/dist/esm/tests/features/protocol-composition.spec.js +30 -31
  66. package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
  67. package/dist/esm/tests/fuzz/encryption.fuzz.spec.js +29 -121
  68. package/dist/esm/tests/fuzz/encryption.fuzz.spec.js.map +1 -1
  69. package/dist/esm/tests/handlers/messages-query.spec.js +71 -3
  70. package/dist/esm/tests/handlers/messages-query.spec.js.map +1 -1
  71. package/dist/esm/tests/handlers/messages-read.spec.js +2 -2
  72. package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
  73. package/dist/esm/tests/handlers/records-read.spec.js +9 -135
  74. package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
  75. package/dist/esm/tests/handlers/records-write.spec.js +279 -19
  76. package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
  77. package/dist/esm/tests/interfaces/protocols-configure.spec.js +17 -22
  78. package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -1
  79. package/dist/esm/tests/interfaces/records-write.spec.js +170 -150
  80. package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
  81. package/dist/esm/tests/protocols/encryption.spec.js +914 -0
  82. package/dist/esm/tests/protocols/encryption.spec.js.map +1 -0
  83. package/dist/esm/tests/protocols/permission-grant.spec.js +55 -0
  84. package/dist/esm/tests/protocols/permission-grant.spec.js.map +1 -1
  85. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +100 -100
  86. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
  87. package/dist/esm/tests/store/message-store-level.spec.js +20 -2
  88. package/dist/esm/tests/store/message-store-level.spec.js.map +1 -1
  89. package/dist/esm/tests/utils/encryption-callbacks.spec.js +88 -125
  90. package/dist/esm/tests/utils/encryption-callbacks.spec.js.map +1 -1
  91. package/dist/esm/tests/utils/encryption.spec.js +125 -255
  92. package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
  93. package/dist/esm/tests/utils/permission-scope.spec.js +5 -1
  94. package/dist/esm/tests/utils/permission-scope.spec.js.map +1 -1
  95. package/dist/esm/tests/utils/records.spec.js +15 -5
  96. package/dist/esm/tests/utils/records.spec.js.map +1 -1
  97. package/dist/esm/tests/utils/test-data-generator.js +7 -44
  98. package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
  99. package/dist/esm/tests/validation/json-schemas/encryption/grant-key.spec.js +63 -0
  100. package/dist/esm/tests/validation/json-schemas/encryption/grant-key.spec.js.map +1 -0
  101. package/dist/types/generated/precompiled-validators.d.ts +140 -92
  102. package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
  103. package/dist/types/src/core/constants.d.ts +2 -2
  104. package/dist/types/src/core/constants.d.ts.map +1 -1
  105. package/dist/types/src/core/core-protocol.d.ts +1 -1
  106. package/dist/types/src/core/core-protocol.d.ts.map +1 -1
  107. package/dist/types/src/core/dwn-error.d.ts +29 -1
  108. package/dist/types/src/core/dwn-error.d.ts.map +1 -1
  109. package/dist/types/src/core/messages-grant-authorization.d.ts +2 -0
  110. package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
  111. package/dist/types/src/core/protocol-authorization-validation.d.ts +2 -2
  112. package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -1
  113. package/dist/types/src/core/recording-validation-state-reader.d.ts +9 -0
  114. package/dist/types/src/core/recording-validation-state-reader.d.ts.map +1 -1
  115. package/dist/types/src/core/replication-apply.d.ts +4 -3
  116. package/dist/types/src/core/replication-apply.d.ts.map +1 -1
  117. package/dist/types/src/core/validation-state-reader.d.ts +9 -0
  118. package/dist/types/src/core/validation-state-reader.d.ts.map +1 -1
  119. package/dist/types/src/dwn.d.ts +1 -0
  120. package/dist/types/src/dwn.d.ts.map +1 -1
  121. package/dist/types/src/handlers/messages-query.d.ts.map +1 -1
  122. package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
  123. package/dist/types/src/index.d.ts +6 -5
  124. package/dist/types/src/index.d.ts.map +1 -1
  125. package/dist/types/src/interfaces/protocols-configure.d.ts +1 -1
  126. package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
  127. package/dist/types/src/interfaces/records-write-signing.d.ts +4 -8
  128. package/dist/types/src/interfaces/records-write-signing.d.ts.map +1 -1
  129. package/dist/types/src/interfaces/records-write.d.ts +10 -26
  130. package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
  131. package/dist/types/src/protocols/encryption.d.ts +43 -0
  132. package/dist/types/src/protocols/encryption.d.ts.map +1 -0
  133. package/dist/types/src/protocols/permission-grant.d.ts +3 -6
  134. package/dist/types/src/protocols/permission-grant.d.ts.map +1 -1
  135. package/dist/types/src/protocols/permissions.d.ts +2 -1
  136. package/dist/types/src/protocols/permissions.d.ts.map +1 -1
  137. package/dist/types/src/types/encryption-types.d.ts +5 -38
  138. package/dist/types/src/types/encryption-types.d.ts.map +1 -1
  139. package/dist/types/src/types/message-types.d.ts +0 -13
  140. package/dist/types/src/types/message-types.d.ts.map +1 -1
  141. package/dist/types/src/types/permission-types.d.ts +44 -9
  142. package/dist/types/src/types/permission-types.d.ts.map +1 -1
  143. package/dist/types/src/types/protocols-types.d.ts +9 -14
  144. package/dist/types/src/types/protocols-types.d.ts.map +1 -1
  145. package/dist/types/src/types/records-types.d.ts +3 -3
  146. package/dist/types/src/types/records-types.d.ts.map +1 -1
  147. package/dist/types/src/types/validation-state-reader.d.ts +12 -0
  148. package/dist/types/src/types/validation-state-reader.d.ts.map +1 -1
  149. package/dist/types/src/utils/encryption.d.ts +54 -145
  150. package/dist/types/src/utils/encryption.d.ts.map +1 -1
  151. package/dist/types/src/utils/hd-key.d.ts +1 -1
  152. package/dist/types/src/utils/hd-key.d.ts.map +1 -1
  153. package/dist/types/src/utils/permission-scope.d.ts +4 -3
  154. package/dist/types/src/utils/permission-scope.d.ts.map +1 -1
  155. package/dist/types/src/utils/protocols.d.ts +3 -5
  156. package/dist/types/src/utils/protocols.d.ts.map +1 -1
  157. package/dist/types/src/utils/records.d.ts +5 -13
  158. package/dist/types/src/utils/records.d.ts.map +1 -1
  159. package/dist/types/src/utils/replication.d.ts +3 -0
  160. package/dist/types/src/utils/replication.d.ts.map +1 -1
  161. package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -1
  162. package/dist/types/tests/handlers/messages-query.spec.d.ts.map +1 -1
  163. package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
  164. package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
  165. package/dist/types/tests/protocols/encryption.spec.d.ts +2 -0
  166. package/dist/types/tests/protocols/encryption.spec.d.ts.map +1 -0
  167. package/dist/types/tests/scenarios/end-to-end-tests.spec.d.ts.map +1 -1
  168. package/dist/types/tests/utils/test-data-generator.d.ts +0 -5
  169. package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
  170. package/dist/types/tests/validation/json-schemas/encryption/grant-key.spec.d.ts +2 -0
  171. package/dist/types/tests/validation/json-schemas/encryption/grant-key.spec.d.ts.map +1 -0
  172. package/package.json +3 -3
  173. package/src/core/constants.ts +3 -3
  174. package/src/core/core-protocol.ts +1 -1
  175. package/src/core/dwn-error.ts +29 -1
  176. package/src/core/messages-grant-authorization.ts +27 -0
  177. package/src/core/protocol-authorization-validation.ts +145 -6
  178. package/src/core/recording-validation-state-reader.ts +13 -0
  179. package/src/core/replication-apply.ts +222 -8
  180. package/src/core/validation-state-reader.ts +30 -0
  181. package/src/dwn.ts +24 -2
  182. package/src/handlers/messages-query.ts +6 -5
  183. package/src/handlers/protocols-configure.ts +19 -3
  184. package/src/handlers/records-write.ts +1 -1
  185. package/src/index.ts +15 -5
  186. package/src/interfaces/protocols-configure.ts +39 -12
  187. package/src/interfaces/records-write-signing.ts +5 -12
  188. package/src/interfaces/records-write.ts +75 -92
  189. package/src/protocols/encryption.ts +649 -0
  190. package/src/protocols/permission-grant.ts +4 -5
  191. package/src/protocols/permissions.ts +8 -6
  192. package/src/types/encryption-types.ts +9 -38
  193. package/src/types/message-types.ts +0 -13
  194. package/src/types/permission-types.ts +57 -9
  195. package/src/types/protocols-types.ts +9 -16
  196. package/src/types/records-types.ts +3 -3
  197. package/src/types/validation-state-reader.ts +13 -0
  198. package/src/utils/encryption.ts +213 -283
  199. package/src/utils/hd-key.ts +1 -1
  200. package/src/utils/permission-scope.ts +10 -6
  201. package/src/utils/protocols.ts +16 -15
  202. package/src/utils/records.ts +86 -71
  203. package/src/utils/replication.ts +30 -4
  204. package/dist/esm/tests/vectors/protocol-definitions/chat.json +0 -70
@@ -3,7 +3,6 @@ import type { KeyValues } from '../types/query-types.js';
3
3
  import type { MessageInterface } from '../types/message-interface.js';
4
4
  import type { MessageSigner } from '../types/signer.js';
5
5
  import type { MessageStore } from '../types/message-store.js';
6
- import type { PublicKeyJwk } from '../types/jose-types.js';
7
6
  import type { ValidationStateReader } from '../types/validation-state-reader.js';
8
7
  import type {
9
8
  DataEncodedRecordsWriteMessage,
@@ -13,10 +12,11 @@ import type {
13
12
  RecordsWriteSignaturePayload,
14
13
  RecordsWriteTags
15
14
  } from '../types/records-types.js';
16
- import type { EncryptionInput, JweEncryption } from '../utils/encryption.js';
15
+ import type { DwnEncryption, EncryptionInput } from '../utils/encryption.js';
17
16
  import type { GenericMessage, GenericSignaturePayload } from '../types/message-types.js';
18
17
 
19
18
  import { Cid } from '../utils/cid.js';
19
+ import { Encryption } from '../utils/encryption.js';
20
20
  import { Jws } from '../utils/jws.js';
21
21
  import { Message } from '../core/message.js';
22
22
  import { PermissionGrant } from '../protocols/permission-grant.js';
@@ -77,6 +77,11 @@ export type RecordsWriteOptions = {
77
77
  delegatedGrant?: DataEncodedRecordsWriteMessage;
78
78
 
79
79
  attestationSigners?: MessageSigner[];
80
+
81
+ /**
82
+ * Pre-built encryption envelope. Use `encryptionInput` when wrapping a CEK from plaintext/ciphertext inputs.
83
+ */
84
+ encryption?: DwnEncryption;
80
85
  encryptionInput?: EncryptionInput;
81
86
  permissionGrantId?: string;
82
87
 
@@ -87,19 +92,14 @@ export type RecordsWriteOptions = {
87
92
  */
88
93
  squash?: true;
89
94
 
90
- /**
91
- * The author's ProtocolPath-derived public key for key delivery.
92
- * When set, this is attached to the authorization model so the DWN owner
93
- * can encrypt context keys back to the author without querying the
94
- * author's DWN.
95
- */
96
- authorKeyDeliveryPublicKey?: {
97
- rootKeyId: string;
98
- publicKeyJwk: PublicKeyJwk;
99
- };
100
95
  };
101
96
 
102
- export type { EncryptionInput, KeyEncryptionInput } from '../utils/encryption.js';
97
+ export type {
98
+ EncryptionInput,
99
+ KeyEncryptionInput,
100
+ ProtocolPathKeyEncryptionInput,
101
+ RoleAudienceKeyEncryptionInput,
102
+ } from '../utils/encryption.js';
103
103
 
104
104
  export type CreateFromOptions = {
105
105
  recordsWriteMessage: RecordsWriteMessage,
@@ -262,6 +262,9 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
262
262
  // - `initialWrite`: the initial RecordsWrite when this message is an update
263
263
  const { encodedData: _, initialWrite: __, ...messageToValidate } = message as RecordsWriteMessage & Record<string, unknown>;
264
264
  Message.validateJsonSchema(messageToValidate);
265
+ if (message.encryption !== undefined) {
266
+ Encryption.validateEncryptionProperty(message.encryption);
267
+ }
265
268
 
266
269
  // asynchronous checks that are required by the constructor to initialize members properly
267
270
 
@@ -298,23 +301,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
298
301
  * If not given, it means this write is for a root protocol record.
299
302
  */
300
303
  public static async create(options: RecordsWriteOptions): Promise<RecordsWrite> {
301
- if (options.protocol === undefined || options.protocolPath === undefined) {
302
- throw new DwnError(DwnErrorCode.RecordsWriteCreateMissingProtocol, '`protocol` and `protocolPath` are required');
303
- }
304
-
305
- if ((options.data === undefined && options.dataCid === undefined) ||
306
- (options.data !== undefined && options.dataCid !== undefined)) {
307
- throw new DwnError(DwnErrorCode.RecordsWriteCreateDataAndDataCidMutuallyExclusive, 'one and only one parameter between `data` and `dataCid` is required');
308
- }
309
-
310
- if ((options.dataCid === undefined && options.dataSize !== undefined) ||
311
- (options.dataCid !== undefined && options.dataSize === undefined)) {
312
- throw new DwnError(DwnErrorCode.RecordsWriteCreateDataCidAndDataSizeMutuallyInclusive, '`dataCid` and `dataSize` must both be defined or undefined at the same time');
313
- }
314
-
315
- if (options.signer === undefined && options.delegatedGrant !== undefined) {
316
- throw new DwnError(DwnErrorCode.RecordsWriteCreateMissingSigner, '`signer` must be given when `delegatedGrant` is given');
317
- }
304
+ RecordsWrite.validateCreateOptions(options);
318
305
 
319
306
  const dataCid = options.dataCid ?? await Cid.computeDagPbCidFromBytes(options.data!);
320
307
  const dataSize = options.dataSize ?? options.data!.length;
@@ -362,7 +349,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
362
349
  const attestation = await createAttestation(descriptorCid, options.attestationSigners);
363
350
 
364
351
  // `encryption` generation
365
- const encryption = await createEncryptionProperty(options.encryptionInput);
352
+ const encryption = options.encryption ?? await createEncryptionProperty(options.encryptionInput);
366
353
 
367
354
  const message: InternalRecordsWriteMessage = {
368
355
  recordId,
@@ -377,17 +364,43 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
377
364
 
378
365
  if (options.signer !== undefined) {
379
366
  await recordsWrite.sign({
380
- signer : options.signer,
381
- delegatedGrant : options.delegatedGrant,
367
+ signer : options.signer,
368
+ delegatedGrant : options.delegatedGrant,
382
369
  ...permissionGrantInvocation,
383
- protocolRole : options.protocolRole,
384
- authorKeyDeliveryPublicKey : options.authorKeyDeliveryPublicKey,
370
+ protocolRole : options.protocolRole,
385
371
  });
386
372
  }
387
373
 
388
374
  return recordsWrite;
389
375
  }
390
376
 
377
+ private static validateCreateOptions(options: RecordsWriteOptions): void {
378
+ if (options.protocol === undefined || options.protocolPath === undefined) {
379
+ throw new DwnError(DwnErrorCode.RecordsWriteCreateMissingProtocol, '`protocol` and `protocolPath` are required');
380
+ }
381
+
382
+ if ((options.data === undefined && options.dataCid === undefined) ||
383
+ (options.data !== undefined && options.dataCid !== undefined)) {
384
+ throw new DwnError(DwnErrorCode.RecordsWriteCreateDataAndDataCidMutuallyExclusive, 'one and only one parameter between `data` and `dataCid` is required');
385
+ }
386
+
387
+ if ((options.dataCid === undefined && options.dataSize !== undefined) ||
388
+ (options.dataCid !== undefined && options.dataSize === undefined)) {
389
+ throw new DwnError(DwnErrorCode.RecordsWriteCreateDataCidAndDataSizeMutuallyInclusive, '`dataCid` and `dataSize` must both be defined or undefined at the same time');
390
+ }
391
+
392
+ if (options.signer === undefined && options.delegatedGrant !== undefined) {
393
+ throw new DwnError(DwnErrorCode.RecordsWriteCreateMissingSigner, '`signer` must be given when `delegatedGrant` is given');
394
+ }
395
+
396
+ if (options.encryption !== undefined && options.encryptionInput !== undefined) {
397
+ throw new DwnError(
398
+ DwnErrorCode.RecordsWriteCreateEncryptionAndEncryptionInputMutuallyExclusive,
399
+ '`encryption` and `encryptionInput` cannot both be defined'
400
+ );
401
+ }
402
+ }
403
+
391
404
  private static getRecordIdFromContextId(contextId: string | undefined): string | undefined {
392
405
  return contextId?.split('/').filter(segment => segment !== '').pop();
393
406
  }
@@ -454,7 +467,9 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
454
467
  delegatedGrant : options.delegatedGrant,
455
468
  // finally still need signers
456
469
  signer : options.signer,
457
- attestationSigners : options.attestationSigners
470
+ attestationSigners : options.attestationSigners,
471
+ encryption : options.encryptionInput === undefined && options.data === undefined ? sourceMessage.encryption : undefined,
472
+ encryptionInput : options.encryptionInput,
458
473
  };
459
474
 
460
475
  const recordsWrite = await RecordsWrite.create(createOptions);
@@ -498,51 +513,16 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
498
513
  }
499
514
 
500
515
  /**
501
- * Encrypts the symmetric encryption key using the public keys given and attach the resulting `encryption` property to the RecordsWrite.
502
- *
503
- * @param options.append - When `true`, appends new `recipients` entries to the existing
504
- * `encryption` property instead of replacing it. Requires `this._message.encryption` to
505
- * already exist (i.e., the record must already be encrypted).
516
+ * Encrypts the symmetric encryption key using the public keys given and attaches the resulting `encryption` property.
506
517
  */
507
518
  public async encryptSymmetricEncryptionKey(
508
519
  encryptionInput: EncryptionInput,
509
- options?: { append?: boolean },
510
520
  ): Promise<void> {
511
- if (options?.append) {
512
- if (!this._message.encryption) {
513
- throw new DwnError(
514
- DwnErrorCode.RecordsWriteMissingEncryption,
515
- 'Cannot append recipients: record does not have an existing `encryption` property.'
516
- );
517
- }
518
-
519
- // Build only the new recipients (reuses createEncryptionProperty for ECDH-ES+A256KW logic)
520
- const newEncryption = await createEncryptionProperty(encryptionInput);
521
- if (newEncryption) {
522
- this._message.encryption.recipients.push(...newEncryption.recipients);
523
- }
524
-
525
- // In append mode, preserve the author's identity and authorization so
526
- // that signAsOwner() can be called afterwards. The author's signature
527
- // payload will have a stale encryptionCid (since we just appended new
528
- // recipients), but the owner's signature vouches for the
529
- // updated state. validateIntegrity() skips the encryptionCid check on
530
- // the author's signature when an ownerSignature is present.
531
- //
532
- // NOTE: An alternative design would deliver the DEK out-of-band via the
533
- // key-delivery protocol (as a field on the contextKey record) instead of
534
- // mutating the record's encryption property. That avoids the stale
535
- // encryptionCid issue entirely but adds complexity to the read path and
536
- // the contextKey schema. We chose the in-record approach because it keeps
537
- // records self-contained and the read/decrypt path unchanged.
538
- } else {
539
- this._message.encryption = await createEncryptionProperty(encryptionInput);
521
+ this._message.encryption = await createEncryptionProperty(encryptionInput);
540
522
 
541
- // Full replacement invalidates the authorization — caller must re-sign.
542
- delete this._message.authorization;
543
- this._signaturePayload = undefined;
544
- this._author = undefined;
545
- }
523
+ delete this._message.authorization;
524
+ this._signaturePayload = undefined;
525
+ this._author = undefined;
546
526
  }
547
527
 
548
528
  /**
@@ -553,9 +533,8 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
553
533
  delegatedGrant?: DataEncodedRecordsWriteMessage,
554
534
  permissionGrantId?: string,
555
535
  protocolRole?: string,
556
- authorKeyDeliveryPublicKey?: { rootKeyId: string; publicKeyJwk: PublicKeyJwk },
557
536
  }): Promise<void> {
558
- const { signer, delegatedGrant, permissionGrantId, protocolRole, authorKeyDeliveryPublicKey } = options;
537
+ const { signer, delegatedGrant, permissionGrantId, protocolRole } = options;
559
538
 
560
539
  // compute delegated grant ID and author if delegated grant is given
561
540
  let delegatedGrantId;
@@ -601,10 +580,6 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
601
580
  this._message.authorization.authorDelegatedGrant = delegatedGrant;
602
581
  }
603
582
 
604
- if (authorKeyDeliveryPublicKey !== undefined) {
605
- this._message.authorization.authorKeyDeliveryPublicKey = authorKeyDeliveryPublicKey;
606
- }
607
-
608
583
  // there is opportunity to optimize here as the payload is constructed within `createAuthorization(...)`
609
584
  this._signaturePayload = Jws.decodePlainObjectPayload(signature);
610
585
  this._author = authorDid;
@@ -719,16 +694,24 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
719
694
  }
720
695
  }
721
696
 
722
- // If `encryption` is given in message, make sure the correct `encryptionCid`
723
- // is in the payload of the message signature UNLESS the message has an
724
- // ownerSignature. When the DWN owner appends recipients to an externally-authored
725
- // record before normal admission, the author's encryptionCid becomes stale. The
726
- // owner's signature vouches for the updated encryption property, so the mismatch
727
- // is expected and safe.
728
- const hasOwnerSignature = this.message.authorization?.ownerSignature !== undefined;
729
- if (signaturePayload.encryptionCid !== undefined && !hasOwnerSignature) {
697
+ // if `encryption` is given in message, make sure the correct `encryptionCid` is in the payload of the message signature
698
+ if (this.message.encryption !== undefined && signaturePayload.encryptionCid === undefined) {
699
+ throw new DwnError(
700
+ DwnErrorCode.RecordsWriteValidateIntegrityEncryptionCidMissing,
701
+ 'encryptionCid must be present in the authorization payload when encryption is present in the message'
702
+ );
703
+ }
704
+
705
+ if (this.message.encryption === undefined && signaturePayload.encryptionCid !== undefined) {
706
+ throw new DwnError(
707
+ DwnErrorCode.RecordsWriteValidateIntegrityEncryptionCidMissing,
708
+ 'encryption must be present in the message when encryptionCid is present in the authorization payload'
709
+ );
710
+ }
711
+
712
+ if (this.message.encryption !== undefined) {
730
713
  const expectedEncryptionCid = await Cid.computeCid(this.message.encryption);
731
- const actualEncryptionCid = signaturePayload.encryptionCid;
714
+ const actualEncryptionCid = signaturePayload.encryptionCid!;
732
715
  if (actualEncryptionCid !== expectedEncryptionCid) {
733
716
  throw new DwnError(
734
717
  DwnErrorCode.RecordsWriteValidateIntegrityEncryptionCidMismatch,
@@ -871,7 +854,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
871
854
  contextId: string,
872
855
  descriptorCid: string,
873
856
  attestation: GeneralJws | undefined,
874
- encryption: JweEncryption | undefined,
857
+ encryption: DwnEncryption | undefined,
875
858
  signer: MessageSigner,
876
859
  delegatedGrantId?: string,
877
860
  permissionGrantId?: string,