@enbox/dwn-sdk-js 0.4.14 → 0.4.16

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 (85) hide show
  1. package/dist/browser.mjs +1 -1
  2. package/dist/browser.mjs.map +4 -4
  3. package/dist/esm/src/core/constants.js +2 -0
  4. package/dist/esm/src/core/constants.js.map +1 -1
  5. package/dist/esm/src/core/dwn-error.js +2 -0
  6. package/dist/esm/src/core/dwn-error.js.map +1 -1
  7. package/dist/esm/src/core/protocol-authorization-validation.js +9 -0
  8. package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
  9. package/dist/esm/src/handlers/messages-query.js +2 -29
  10. package/dist/esm/src/handlers/messages-query.js.map +1 -1
  11. package/dist/esm/src/handlers/messages-subscribe.js +52 -1
  12. package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
  13. package/dist/esm/src/handlers/protocols-configure.js +157 -7
  14. package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
  15. package/dist/esm/src/index.js +2 -2
  16. package/dist/esm/src/index.js.map +1 -1
  17. package/dist/esm/src/protocols/encryption.js +41 -10
  18. package/dist/esm/src/protocols/encryption.js.map +1 -1
  19. package/dist/esm/src/store/message-store-level.js +4 -2
  20. package/dist/esm/src/store/message-store-level.js.map +1 -1
  21. package/dist/esm/src/types/protocols-types.js.map +1 -1
  22. package/dist/esm/src/utils/messages.js +36 -0
  23. package/dist/esm/src/utils/messages.js.map +1 -1
  24. package/dist/esm/src/utils/replication.js +14 -0
  25. package/dist/esm/src/utils/replication.js.map +1 -1
  26. package/dist/esm/tests/features/protocol-composition.spec.js +5 -1
  27. package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
  28. package/dist/esm/tests/handlers/messages-query.spec.js +7 -15
  29. package/dist/esm/tests/handlers/messages-query.spec.js.map +1 -1
  30. package/dist/esm/tests/handlers/messages-subscribe.spec.js +129 -1
  31. package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
  32. package/dist/esm/tests/handlers/protocols-configure.spec.js +244 -1
  33. package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
  34. package/dist/esm/tests/handlers/records-read.spec.js +2 -1
  35. package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
  36. package/dist/esm/tests/handlers/records-write.spec.js +24 -1
  37. package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
  38. package/dist/esm/tests/protocols/encryption.spec.js +3 -1
  39. package/dist/esm/tests/protocols/encryption.spec.js.map +1 -1
  40. package/dist/esm/tests/store/message-store-level.spec.js +21 -0
  41. package/dist/esm/tests/store/message-store-level.spec.js.map +1 -1
  42. package/dist/types/src/core/constants.d.ts +2 -0
  43. package/dist/types/src/core/constants.d.ts.map +1 -1
  44. package/dist/types/src/core/dwn-error.d.ts +2 -0
  45. package/dist/types/src/core/dwn-error.d.ts.map +1 -1
  46. package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -1
  47. package/dist/types/src/handlers/messages-query.d.ts +0 -2
  48. package/dist/types/src/handlers/messages-query.d.ts.map +1 -1
  49. package/dist/types/src/handlers/messages-subscribe.d.ts +16 -0
  50. package/dist/types/src/handlers/messages-subscribe.d.ts.map +1 -1
  51. package/dist/types/src/handlers/protocols-configure.d.ts +17 -0
  52. package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
  53. package/dist/types/src/index.d.ts +2 -2
  54. package/dist/types/src/index.d.ts.map +1 -1
  55. package/dist/types/src/protocols/encryption.d.ts +3 -1
  56. package/dist/types/src/protocols/encryption.d.ts.map +1 -1
  57. package/dist/types/src/store/message-store-level.d.ts.map +1 -1
  58. package/dist/types/src/types/messages-types.d.ts +14 -0
  59. package/dist/types/src/types/messages-types.d.ts.map +1 -1
  60. package/dist/types/src/types/protocols-types.d.ts +2 -1
  61. package/dist/types/src/types/protocols-types.d.ts.map +1 -1
  62. package/dist/types/src/utils/messages.d.ts +8 -0
  63. package/dist/types/src/utils/messages.d.ts.map +1 -1
  64. package/dist/types/src/utils/replication.d.ts +8 -1
  65. package/dist/types/src/utils/replication.d.ts.map +1 -1
  66. package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -1
  67. package/dist/types/tests/handlers/messages-query.spec.d.ts.map +1 -1
  68. package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -1
  69. package/dist/types/tests/handlers/protocols-configure.spec.d.ts.map +1 -1
  70. package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
  71. package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
  72. package/package.json +1 -1
  73. package/src/core/constants.ts +2 -0
  74. package/src/core/dwn-error.ts +2 -0
  75. package/src/core/protocol-authorization-validation.ts +14 -0
  76. package/src/handlers/messages-query.ts +3 -41
  77. package/src/handlers/messages-subscribe.ts +67 -3
  78. package/src/handlers/protocols-configure.ts +236 -7
  79. package/src/index.ts +3 -0
  80. package/src/protocols/encryption.ts +54 -11
  81. package/src/store/message-store-level.ts +4 -2
  82. package/src/types/messages-types.ts +14 -0
  83. package/src/types/protocols-types.ts +2 -1
  84. package/src/utils/messages.ts +45 -0
  85. package/src/utils/replication.ts +19 -1
@@ -46,7 +46,8 @@ export type ProtocolType = {
46
46
  * DID must have an X25519 keyAgreement key; protocol installation will
47
47
  * fail if it does not.
48
48
  *
49
- * When `false` or omitted, encryption is not required for this type.
49
+ * When `false` or omitted, records of this type **must** be plaintext at the
50
+ * DWN record level. Applications cannot override this protocol policy per write.
50
51
  */
51
52
  encryptionRequired?: boolean;
52
53
  };
@@ -1 +1 @@
1
- {"version":3,"file":"protocols-types.d.ts","sourceRoot":"","sources":["../../../../src/types/protocols-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"protocols-types.d.ts","sourceRoot":"","sources":["../../../../src/types/protocols-types.ts"],"names":[],"mappings":"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"}
@@ -36,6 +36,14 @@ export declare class Messages {
36
36
  * (including cursor-based subscriptions) also apply to the shadow filter.
37
37
  */
38
38
  private static constructProtocolConfigureShadowFilter;
39
+ /**
40
+ * Maps a filter set onto the replication fingerprint domains it covers, or
41
+ * `undefined` when the filters do not correspond to fingerprint domains.
42
+ * An empty filter set covers the global domain; a set of protocol-only
43
+ * filters covers each protocol's domain plus its tagged core-protocol
44
+ * domains. Any other filter shape has no domain mapping.
45
+ */
46
+ static computeFingerprintScopes(filters: MessagesFilter[]): string[] | undefined;
39
47
  /**
40
48
  * Returns a copy of a RecordsWrite message without inline encodedData, and the
41
49
  * detached encodedData value for wire surfaces that carry data beside the message.
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../../src/utils/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAUjE;;GAEG;AACH,qBAAa,QAAQ;IACnB;;OAEG;WACW,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE;IAwB3E;;;;;;;;;;OAUG;WACW,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,aAAa,CAAC,EAAE,oBAAoB,GAAG,MAAM,EAAE;IAoBvG;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;IAgB3C;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,sCAAsC;IAqBrD;;;OAGG;WACW,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG;QAAE,OAAO,EAAE,cAAc,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE;IAY3G;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAmC5B,OAAO,CAAC,MAAM,CAAC,cAAc;CAG9B"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../../src/utils/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAWjE;;GAEG;AACH,qBAAa,QAAQ;IACnB;;OAEG;WACW,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE;IAwB3E;;;;;;;;;;OAUG;WACW,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,aAAa,CAAC,EAAE,oBAAoB,GAAG,MAAM,EAAE;IAoBvG;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;IAgB3C;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,sCAAsC;IAqBrD;;;;;;OAMG;WACW,wBAAwB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,EAAE,GAAG,SAAS;IAqCvF;;;OAGG;WACW,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG;QAAE,OAAO,EAAE,cAAc,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE;IAY3G;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAmC5B,OAAO,CAAC,MAAM,CAAC,cAAc;CAG9B"}
@@ -1,5 +1,6 @@
1
1
  import type { GenericMessage } from '../types/message-types.js';
2
2
  import type { KeyValues } from '../types/query-types.js';
3
+ import type { ReplicationFeedReader } from '../types/subscriptions.js';
3
4
  /**
4
5
  * Shared helpers for the replication log substrate.
5
6
  */
@@ -9,12 +10,18 @@ export declare class Replication {
9
10
  static permissionDomain(protocolUri: string): string;
10
11
  static encryptionDomain(protocolUri: string): string;
11
12
  static taggedCoreProtocolDomains(protocolUri: string, protocolsInScope?: ReadonlySet<string>): string[];
13
+ /**
14
+ * Narrows a message store to its replication feed surface when it implements
15
+ * one. Returns `undefined` for stores without replication feed support.
16
+ */
17
+ static asFeedReader(candidate: unknown): ReplicationFeedReader | undefined;
12
18
  static deriveStreamId(tenant: string): Promise<string>;
13
19
  static computeFingerprintScopes(message: GenericMessage, indexes: KeyValues): string[];
14
20
  static assertFingerprintScopesUntouched(persistedScopes: string[], message: GenericMessage, messageCid: string, newIndexes: KeyValues): void;
15
21
  private static scopeSetsMatch;
16
22
  private static throwFingerprintScopeMutation;
17
- private static isCoreProtocolUri;
23
+ /** Whether a protocol URI is one of the core protocols (permissions, encryption). */
24
+ static isCoreProtocolUri(protocolUri: string): boolean;
18
25
  static hashMessageCid(messageCid: string): Promise<Uint8Array>;
19
26
  static emptyFingerprint(): Uint8Array;
20
27
  static xorFingerprint(fingerprint: Uint8Array, contribution: Uint8Array): Uint8Array;
@@ -1 +1 @@
1
- {"version":3,"file":"replication.d.ts","sourceRoot":"","sources":["../../../../src/utils/replication.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAYzD;;GAEG;AACH,qBAAa,WAAW;IACtB,gBAAuB,YAAY,MAAM;WAE3B,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;WAI3C,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;WAI7C,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;WAI7C,yBAAyB,CAAC,WAAW,EAAE,MAAM,EAAE,gBAAgB,GAAE,WAAW,CAAC,MAAM,CAAa,GAAG,MAAM,EAAE;WAerG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;WAOrD,wBAAwB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,EAAE;WAsB/E,gCAAgC,CAC5C,eAAe,EAAE,MAAM,EAAE,EACzB,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,SAAS,GACpB,IAAI;IAOP,OAAO,CAAC,MAAM,CAAC,cAAc;IAQ7B,OAAO,CAAC,MAAM,CAAC,6BAA6B;IAO5C,OAAO,CAAC,MAAM,CAAC,iBAAiB;WAIZ,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;WAM7D,gBAAgB,IAAI,UAAU;WAI9B,cAAc,CAAC,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,GAAG,UAAU;WAQ7E,gBAAgB,CAAC,WAAW,EAAE,UAAU,GAAG,MAAM;WAIjD,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;WAQzC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAW1D"}
1
+ {"version":3,"file":"replication.d.ts","sourceRoot":"","sources":["../../../../src/utils/replication.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAYvE;;GAEG;AACH,qBAAa,WAAW;IACtB,gBAAuB,YAAY,MAAM;WAE3B,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;WAI3C,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;WAI7C,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;WAI7C,yBAAyB,CAAC,WAAW,EAAE,MAAM,EAAE,gBAAgB,GAAE,WAAW,CAAC,MAAM,CAAa,GAAG,MAAM,EAAE;IAezH;;;OAGG;WACW,YAAY,CAAC,SAAS,EAAE,OAAO,GAAG,qBAAqB,GAAG,SAAS;WAY7D,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;WAOrD,wBAAwB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,EAAE;WAsB/E,gCAAgC,CAC5C,eAAe,EAAE,MAAM,EAAE,EACzB,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,SAAS,GACpB,IAAI;IAOP,OAAO,CAAC,MAAM,CAAC,cAAc;IAQ7B,OAAO,CAAC,MAAM,CAAC,6BAA6B;IAO5C,qFAAqF;WACvE,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;WAIzC,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;WAM7D,gBAAgB,IAAI,UAAU;WAI9B,cAAc,CAAC,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,GAAG,UAAU;WAQ7E,gBAAgB,CAAC,WAAW,EAAE,UAAU,GAAG,MAAM;WAIjD,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;WAQzC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAW1D"}
@@ -1 +1 @@
1
- {"version":3,"file":"protocol-composition.spec.d.ts","sourceRoot":"","sources":["../../../../tests/features/protocol-composition.spec.ts"],"names":[],"mappings":"AAyBA;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAm+E9C"}
1
+ {"version":3,"file":"protocol-composition.spec.d.ts","sourceRoot":"","sources":["../../../../tests/features/protocol-composition.spec.ts"],"names":[],"mappings":"AAyBA;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CA0+E9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"messages-query.spec.d.ts","sourceRoot":"","sources":["../../../../tests/handlers/messages-query.spec.ts"],"names":[],"mappings":"AAoCA,wBAAgB,wBAAwB,IAAI,IAAI,CAsb/C"}
1
+ {"version":3,"file":"messages-query.spec.d.ts","sourceRoot":"","sources":["../../../../tests/handlers/messages-query.spec.ts"],"names":[],"mappings":"AAoCA,wBAAgB,wBAAwB,IAAI,IAAI,CA8a/C"}
@@ -1 +1 @@
1
- {"version":3,"file":"messages-subscribe.spec.d.ts","sourceRoot":"","sources":["../../../../tests/handlers/messages-subscribe.spec.ts"],"names":[],"mappings":"AA6BA,wBAAgB,4BAA4B,IAAI,IAAI,CA23CnD"}
1
+ {"version":3,"file":"messages-subscribe.spec.d.ts","sourceRoot":"","sources":["../../../../tests/handlers/messages-subscribe.spec.ts"],"names":[],"mappings":"AA6BA,wBAAgB,4BAA4B,IAAI,IAAI,CAohDnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"protocols-configure.spec.d.ts","sourceRoot":"","sources":["../../../../tests/handlers/protocols-configure.spec.ts"],"names":[],"mappings":"AAgCA,wBAAgB,6BAA6B,IAAI,IAAI,CAkkEpD"}
1
+ {"version":3,"file":"protocols-configure.spec.d.ts","sourceRoot":"","sources":["../../../../tests/handlers/protocols-configure.spec.ts"],"names":[],"mappings":"AAwEA,wBAAgB,6BAA6B,IAAI,IAAI,CA+zEpD"}
@@ -1 +1 @@
1
- {"version":3,"file":"records-read.spec.d.ts","sourceRoot":"","sources":["../../../../tests/handlers/records-read.spec.ts"],"names":[],"mappings":"AAqCA,wBAAgB,sBAAsB,IAAI,IAAI,CAkpE7C"}
1
+ {"version":3,"file":"records-read.spec.d.ts","sourceRoot":"","sources":["../../../../tests/handlers/records-read.spec.ts"],"names":[],"mappings":"AAqCA,wBAAgB,sBAAsB,IAAI,IAAI,CAmpE7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"records-write.spec.d.ts","sourceRoot":"","sources":["../../../../tests/handlers/records-write.spec.ts"],"names":[],"mappings":"AA+DA,wBAAgB,uBAAuB,IAAI,IAAI,CA6yM9C"}
1
+ {"version":3,"file":"records-write.spec.d.ts","sourceRoot":"","sources":["../../../../tests/handlers/records-write.spec.ts"],"names":[],"mappings":"AA+DA,wBAAgB,uBAAuB,IAAI,IAAI,CAg1M9C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enbox/dwn-sdk-js",
3
- "version": "0.4.14",
3
+ "version": "0.4.16",
4
4
  "description": "A reference implementation of https://identity.foundation/decentralized-web-node/spec/",
5
5
  "repository": {
6
6
  "type": "git",
@@ -19,6 +19,8 @@ export const PERMISSIONS_PROTOCOL_URI = 'https://identity.foundation/dwn/permiss
19
19
  * The DWN Encryption protocol URI.
20
20
  */
21
21
  export const ENCRYPTION_PROTOCOL_URI = 'https://identity.foundation/dwn/protocols/encryption';
22
+ export const ENCRYPTION_PROTOCOL_GRANT_KEY_PATH = 'grantKey';
23
+ export const ENCRYPTION_PROTOCOL_WRAPPED_GRANT_KEY_PATH = 'wrappedGrantKey';
22
24
 
23
25
  /**
24
26
  * Reserved virtual protocol path root for source-protocol-native encryption
@@ -145,6 +145,7 @@ export enum DwnErrorCode {
145
145
  ProtocolAuthorizationIncorrectProtocolPath = 'ProtocolAuthorizationIncorrectProtocolPath',
146
146
  ProtocolAuthorizationInitialWriteRevalidationNotInitial = 'ProtocolAuthorizationInitialWriteRevalidationNotInitial',
147
147
  ProtocolAuthorizationDuplicateRoleRecipient = 'ProtocolAuthorizationDuplicateRoleRecipient',
148
+ ProtocolAuthorizationEncryptionNotAllowed = 'ProtocolAuthorizationEncryptionNotAllowed',
148
149
  ProtocolAuthorizationEncryptionRequired = 'ProtocolAuthorizationEncryptionRequired',
149
150
  ProtocolAuthorizationEncryptionKeyAgreementMissing = 'ProtocolAuthorizationEncryptionKeyAgreementMissing',
150
151
  ProtocolAuthorizationEncryptionProtocolPathEntryMissing = 'ProtocolAuthorizationEncryptionProtocolPathEntryMissing',
@@ -196,6 +197,7 @@ export enum DwnErrorCode {
196
197
  ProtocolsConfigureInvalidEncryptedRoleMissingKeyAgreement = 'ProtocolsConfigureInvalidEncryptedRoleMissingKeyAgreement',
197
198
  ProtocolsConfigureMissingEncryptedPathKeyAgreement = 'ProtocolsConfigureMissingEncryptedPathKeyAgreement',
198
199
  ProtocolsConfigureMissingTopLevelKeyAgreement = 'ProtocolsConfigureMissingTopLevelKeyAgreement',
200
+ ProtocolsConfigureEncryptionPolicyImmutable = 'ProtocolsConfigureEncryptionPolicyImmutable',
199
201
  ProtocolsConfigureInvalidRecipientOfAction = 'ProtocolsConfigureInvalidRecipientOfAction',
200
202
  ProtocolsConfigureInvalidRuleSetRecordType = 'ProtocolsConfigureInvalidRuleSetRecordType',
201
203
  ProtocolsConfigureInvalidTagSchema = 'ProtocolsConfigureInvalidTagSchema',
@@ -9,6 +9,7 @@ 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
11
  import { Encryption, ROLE_AUDIENCE_DERIVATION_SCHEME } from '../utils/encryption.js';
12
+ import { ENCRYPTION_PROTOCOL_GRANT_KEY_PATH, ENCRYPTION_PROTOCOL_URI } from './constants.js';
12
13
  import { getRoleAudienceContextId, getRuleSetAtPath, getTypeName, parseCrossProtocolRef } from '../utils/protocols.js';
13
14
  import { ProtocolAction, ProtocolRecordLimitStrategy } from '../types/protocols-types.js';
14
15
 
@@ -275,6 +276,13 @@ export function verifyType(
275
276
  );
276
277
  }
277
278
 
279
+ if (protocolType.encryptionRequired !== true && inboundMessage.encryption !== undefined) {
280
+ throw new DwnError(
281
+ DwnErrorCode.ProtocolAuthorizationEncryptionNotAllowed,
282
+ `type '${declaredTypeName}' requires plaintext but message has encryption metadata`
283
+ );
284
+ }
285
+
278
286
  return protocolType;
279
287
  }
280
288
 
@@ -291,6 +299,12 @@ async function verifyProtocolPathEncryptionIfNeeded(
291
299
 
292
300
  const ruleSet = getRuleSetAtPath(inboundMessage.descriptor.protocolPath, protocolDefinition.structure);
293
301
  if (ruleSet?.$keyAgreement?.publicKeyJwk === undefined) {
302
+ const usesDynamicCoreRecipientKey = protocolDefinition.protocol === ENCRYPTION_PROTOCOL_URI &&
303
+ inboundMessage.descriptor.protocolPath === ENCRYPTION_PROTOCOL_GRANT_KEY_PATH;
304
+ if (usesDynamicCoreRecipientKey) {
305
+ return;
306
+ }
307
+
294
308
  throw new DwnError(
295
309
  DwnErrorCode.ProtocolAuthorizationEncryptionKeyAgreementMissing,
296
310
  `encrypted protocol path '${inboundMessage.descriptor.protocolPath}' has no $keyAgreement`
@@ -1,4 +1,4 @@
1
- import type { EventLogEntry, ProgressGapInfo, ReplicationFeedReader } from '../types/subscriptions.js';
1
+ import type { EventLogEntry, ProgressGapInfo } from '../types/subscriptions.js';
2
2
  import type { Filter, KeyValues } from '../types/query-types.js';
3
3
  import type { HandlerDependencies, MethodHandler } from '../types/method-handler.js';
4
4
  import type { MessagesFilter, MessagesQueryMessage, MessagesQueryReply, MessagesQueryReplyEntry } from '../types/messages-types.js';
@@ -31,7 +31,7 @@ export class MessagesQueryHandler implements MethodHandler {
31
31
  return messageReplyFromError(e, 401);
32
32
  }
33
33
 
34
- const replicationFeedReader = MessagesQueryHandler.asReplicationFeedReader(this.deps.messageStore);
34
+ const replicationFeedReader = Replication.asFeedReader(this.deps.messageStore);
35
35
  if (replicationFeedReader === undefined) {
36
36
  return {
37
37
  status: {
@@ -56,7 +56,7 @@ export class MessagesQueryHandler implements MethodHandler {
56
56
  drained : result.drained,
57
57
  };
58
58
 
59
- const fingerprintScopes = MessagesQueryHandler.computeFingerprintScopes(message.descriptor.filters);
59
+ const fingerprintScopes = Messages.computeFingerprintScopes(message.descriptor.filters);
60
60
  if (fingerprintScopes !== undefined) {
61
61
  reply.fingerprint = await replicationFeedReader.fingerprint(tenant, fingerprintScopes);
62
62
  }
@@ -87,18 +87,6 @@ export class MessagesQueryHandler implements MethodHandler {
87
87
  });
88
88
  }
89
89
 
90
- private static asReplicationFeedReader(candidate: unknown): ReplicationFeedReader | undefined {
91
- const partial = candidate as Partial<ReplicationFeedReader>;
92
- if (
93
- typeof partial.logRead === 'function' &&
94
- typeof partial.logBounds === 'function' &&
95
- typeof partial.fingerprint === 'function' &&
96
- typeof partial.epoch === 'function'
97
- ) {
98
- return partial as ReplicationFeedReader;
99
- }
100
- }
101
-
102
90
  private static convertFilters(filters: MessagesFilter[], deps: HandlerDependencies): Filter[] | undefined {
103
91
  if (filters.length === 0) {
104
92
  return undefined;
@@ -155,32 +143,6 @@ export class MessagesQueryHandler implements MethodHandler {
155
143
  return indexes.isLatestBaseState === true || indexes.isLatestBaseState === 'true';
156
144
  }
157
145
 
158
- private static computeFingerprintScopes(filters: MessagesFilter[]): string[] | undefined {
159
- if (filters.length === 0) {
160
- return [Replication.globalDomain];
161
- }
162
-
163
- const protocols = new Set<string>();
164
- for (const filter of filters) {
165
- const keys = Object.keys(filter);
166
- if (keys.length !== 1 || typeof filter.protocol !== 'string') {
167
- return undefined;
168
- }
169
-
170
- protocols.add(filter.protocol);
171
- }
172
-
173
- const scopes: string[] = [];
174
- for (const protocol of protocols) {
175
- scopes.push(
176
- Replication.protocolDomain(protocol),
177
- ...Replication.taggedCoreProtocolDomains(protocol, protocols),
178
- );
179
- }
180
-
181
- return scopes;
182
- }
183
-
184
146
  private static getProgressGapInfo(error: DwnError): ProgressGapInfo | undefined {
185
147
  const gapInfo = (error as DwnError & { gapInfo?: ProgressGapInfo }).gapInfo;
186
148
  return gapInfo;
@@ -1,7 +1,7 @@
1
1
  import type { PermissionGrant } from '../protocols/permission-grant.js';
2
- import type { EventSubscription, ProgressGapInfo, SubscriptionEvent, SubscriptionListener, SubscriptionMessage } from '../types/subscriptions.js';
2
+ import type { EventSubscription, ProgressGapInfo, ProgressToken, ReplicationFeedReader, SubscriptionEvent, SubscriptionListener, SubscriptionMessage } from '../types/subscriptions.js';
3
3
  import type { HandlerDependencies, MethodHandler } from '../types/method-handler.js';
4
- import type { MessagesSubscribeMessage, MessagesSubscribeReply } from '../types/messages-types.js';
4
+ import type { MessagesFilter, MessagesSubscribeMessage, MessagesSubscribeReply } from '../types/messages-types.js';
5
5
 
6
6
  import { authenticate } from '../core/auth.js';
7
7
  import { Message } from '../core/message.js';
@@ -9,6 +9,7 @@ import { messageReplyFromError } from '../core/message-reply.js';
9
9
  import { Messages } from '../utils/messages.js';
10
10
  import { MessagesGrantAuthorization } from '../core/messages-grant-authorization.js';
11
11
  import { MessagesSubscribe } from '../interfaces/messages-subscribe.js';
12
+ import { Replication } from '../utils/replication.js';
12
13
  import { Time } from '../utils/time.js';
13
14
  import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
14
15
 
@@ -79,10 +80,20 @@ export class MessagesSubscribeHandler implements MethodHandler {
79
80
  });
80
81
  await guardedHandler.setSubscription(subscription);
81
82
 
82
- return {
83
+ const reply: MessagesSubscribeReply = {
83
84
  status: { code: 200, detail: 'OK' },
84
85
  subscription,
85
86
  };
87
+ try {
88
+ await MessagesSubscribeHandler.attachFeedSnapshot(reply, tenant, filters, this.deps);
89
+ } catch {
90
+ // Best-effort enrichment: the subscription is live and correct
91
+ // without the snapshot — consumers feature-detect the fields. A
92
+ // failure reply here would orphan the just-installed listener, since
93
+ // close handles are registered only from successful replies.
94
+ }
95
+
96
+ return reply;
86
97
  } catch (error) {
87
98
  if (error instanceof DwnError && error.code === DwnErrorCode.EventLogProgressGap) {
88
99
  const gapInfo = (error as any).gapInfo as ProgressGapInfo | undefined;
@@ -95,6 +106,59 @@ export class MessagesSubscribeHandler implements MethodHandler {
95
106
  }
96
107
  }
97
108
 
109
+ /**
110
+ * Attaches the replication feed's `head` token and scope `fingerprint` to a
111
+ * successful subscribe reply, when the message store exposes the feed.
112
+ *
113
+ * Ordering is load-bearing: both values are observed AFTER the subscription
114
+ * became active, so every event past `head` is either replayable from it or
115
+ * already flowing on the live stream — a caller that verifies `fingerprint`
116
+ * against its local feed may adopt `head` as a checkpoint without a delivery
117
+ * gap. The head is captured before the fingerprint, mirroring MessagesQuery's
118
+ * cursor-then-fingerprint order: an event landing between the two captures
119
+ * makes the fingerprint read ahead of the head, which a consumer observes as
120
+ * a mismatch (one redundant reconcile), never as a silently skipped event.
121
+ */
122
+ private static async attachFeedSnapshot(
123
+ reply: MessagesSubscribeReply,
124
+ tenant: string,
125
+ filters: MessagesFilter[],
126
+ deps: HandlerDependencies,
127
+ ): Promise<void> {
128
+ const feedReader = Replication.asFeedReader(deps.messageStore);
129
+ if (feedReader === undefined) {
130
+ return;
131
+ }
132
+
133
+ // Build the complete snapshot before attaching anything: a partial
134
+ // snapshot (a head without its fingerprint) would read to consumers as
135
+ // a fingerprint-less server rather than as a failed capture.
136
+ const bounds = await feedReader.logBounds(tenant);
137
+ const head = bounds?.latest ?? await MessagesSubscribeHandler.buildAnchorToken(tenant, feedReader);
138
+
139
+ const fingerprintScopes = Messages.computeFingerprintScopes(filters);
140
+ const fingerprint = fingerprintScopes === undefined
141
+ ? undefined
142
+ : await feedReader.fingerprint(tenant, fingerprintScopes);
143
+
144
+ reply.head = head;
145
+ if (fingerprint !== undefined) {
146
+ reply.fingerprint = fingerprint;
147
+ }
148
+ }
149
+
150
+ /** Builds the position-zero anchor token for a tenant log with no events. */
151
+ private static async buildAnchorToken(
152
+ tenant: string,
153
+ feedReader: ReplicationFeedReader,
154
+ ): Promise<ProgressToken> {
155
+ return {
156
+ streamId : await Replication.deriveStreamId(tenant),
157
+ epoch : await feedReader.epoch(),
158
+ position : '0',
159
+ };
160
+ }
161
+
98
162
  private static async authorizeMessagesSubscribe(
99
163
  tenant: string,
100
164
  messagesSubscribe: MessagesSubscribe,