@enbox/dwn-sdk-js 0.4.9 → 0.4.11
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 +1 -1
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/generated/precompiled-validators.js +1262 -3888
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/constants.js +0 -26
- package/dist/esm/src/core/constants.js.map +1 -1
- package/dist/esm/src/core/encryption-control.js +0 -10
- package/dist/esm/src/core/encryption-control.js.map +1 -1
- package/dist/esm/src/core/replication-apply.js.map +1 -1
- package/dist/esm/src/handlers/records-query.js +9 -11
- package/dist/esm/src/handlers/records-query.js.map +1 -1
- package/dist/esm/src/handlers/records-read.js +15 -6
- package/dist/esm/src/handlers/records-read.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +8 -11
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +6 -12
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +1 -1
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/records-write-query.js +3 -0
- package/dist/esm/src/interfaces/records-write-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-write.js +0 -9
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/store/message-store-level.js +104 -3
- package/dist/esm/src/store/message-store-level.js.map +1 -1
- package/dist/esm/src/store/storage-controller.js +44 -33
- package/dist/esm/src/store/storage-controller.js.map +1 -1
- package/dist/esm/src/utils/encryption.js +2 -7
- package/dist/esm/src/utils/encryption.js.map +1 -1
- package/dist/esm/src/utils/hd-key.js +0 -27
- package/dist/esm/src/utils/hd-key.js.map +1 -1
- package/dist/esm/src/utils/initial-write-attachment.js +48 -0
- package/dist/esm/src/utils/initial-write-attachment.js.map +1 -0
- package/dist/esm/src/utils/protocols.js +23 -51
- package/dist/esm/src/utils/protocols.js.map +1 -1
- package/dist/esm/src/utils/records.js +17 -31
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/tests/core/constants.spec.js +1 -11
- package/dist/esm/tests/core/constants.spec.js.map +1 -1
- package/dist/esm/tests/core/validation-read-closure.spec.js +1 -1
- package/dist/esm/tests/core/validation-read-closure.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-composition.spec.js +15 -60
- package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-delete.spec.js +1 -1
- package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-query.spec.js +82 -0
- package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +40 -13
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +60 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +10 -10
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/protocols-configure.spec.js +5 -5
- package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +5 -51
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +2 -2
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store.spec.js +105 -0
- package/dist/esm/tests/store/message-store.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption-callbacks.spec.js +18 -30
- package/dist/esm/tests/utils/encryption-callbacks.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption-control-test-utils.js +1 -1
- package/dist/esm/tests/utils/encryption-control-test-utils.js.map +1 -1
- package/dist/esm/tests/utils/encryption.spec.js +30 -33
- package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
- package/dist/esm/tests/utils/test-data-generator.js +76 -24
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js +1 -1
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js.map +1 -1
- package/dist/types/generated/precompiled-validators.d.ts +88 -120
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/constants.d.ts +0 -13
- package/dist/types/src/core/constants.d.ts.map +1 -1
- package/dist/types/src/core/encryption-control.d.ts +0 -1
- package/dist/types/src/core/encryption-control.d.ts.map +1 -1
- package/dist/types/src/core/replication-apply.d.ts +0 -7
- package/dist/types/src/core/replication-apply.d.ts.map +1 -1
- package/dist/types/src/handlers/records-query.d.ts.map +1 -1
- package/dist/types/src/handlers/records-read.d.ts.map +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write-query.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write.d.ts +0 -4
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/store/message-store-level.d.ts +9 -1
- package/dist/types/src/store/message-store-level.d.ts.map +1 -1
- package/dist/types/src/store/storage-controller.d.ts +18 -8
- package/dist/types/src/store/storage-controller.d.ts.map +1 -1
- package/dist/types/src/types/message-store.d.ts +36 -0
- package/dist/types/src/types/message-store.d.ts.map +1 -1
- package/dist/types/src/utils/encryption.d.ts +0 -3
- package/dist/types/src/utils/encryption.d.ts.map +1 -1
- package/dist/types/src/utils/hd-key.d.ts +1 -11
- package/dist/types/src/utils/hd-key.d.ts.map +1 -1
- package/dist/types/src/utils/initial-write-attachment.d.ts +17 -0
- package/dist/types/src/utils/initial-write-attachment.d.ts.map +1 -0
- package/dist/types/src/utils/protocols.d.ts +2 -7
- package/dist/types/src/utils/protocols.d.ts.map +1 -1
- package/dist/types/src/utils/records.d.ts +1 -8
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-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-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/scenarios/end-to-end-tests.spec.d.ts.map +1 -1
- package/dist/types/tests/store/message-store.spec.d.ts.map +1 -1
- package/dist/types/tests/utils/test-data-generator.d.ts +17 -1
- package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/core/constants.ts +0 -30
- package/src/core/encryption-control.ts +1 -17
- package/src/core/replication-apply.ts +0 -8
- package/src/handlers/records-query.ts +21 -22
- package/src/handlers/records-read.ts +22 -9
- package/src/handlers/records-subscribe.ts +9 -15
- package/src/handlers/records-write.ts +15 -15
- package/src/index.ts +1 -2
- package/src/interfaces/records-write-query.ts +3 -0
- package/src/interfaces/records-write.ts +0 -13
- package/src/store/message-store-level.ts +160 -5
- package/src/store/storage-controller.ts +57 -43
- package/src/types/message-store.ts +37 -0
- package/src/utils/encryption.ts +2 -15
- package/src/utils/hd-key.ts +1 -32
- package/src/utils/initial-write-attachment.ts +64 -0
- package/src/utils/protocols.ts +15 -78
- package/src/utils/records.ts +15 -57
- package/dist/esm/tests/validation/json-schemas/encryption/delivery.spec.js +0 -47
- package/dist/esm/tests/validation/json-schemas/encryption/delivery.spec.js.map +0 -1
- package/dist/esm/tests/validation/json-schemas/encryption/grant-key.spec.js +0 -72
- package/dist/esm/tests/validation/json-schemas/encryption/grant-key.spec.js.map +0 -1
- package/dist/types/tests/validation/json-schemas/encryption/delivery.spec.d.ts +0 -2
- package/dist/types/tests/validation/json-schemas/encryption/delivery.spec.d.ts.map +0 -1
- package/dist/types/tests/validation/json-schemas/encryption/grant-key.spec.d.ts +0 -2
- package/dist/types/tests/validation/json-schemas/encryption/grant-key.spec.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-data-generator.d.ts","sourceRoot":"","sources":["../../../../tests/utils/test-data-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAK/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"test-data-generator.d.ts","sourceRoot":"","sources":["../../../../tests/utils/test-data-generator.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enbox/dwn-sdk-js",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.11",
|
|
4
4
|
"description": "A reference implementation of https://identity.foundation/decentralized-web-node/spec/",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -73,8 +73,8 @@
|
|
|
73
73
|
"react-native": "./dist/esm/src/index.js",
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"@enbox/common": "0.1.3",
|
|
76
|
-
"@enbox/crypto": "0.1.
|
|
77
|
-
"@enbox/dids": "0.1.
|
|
76
|
+
"@enbox/crypto": "0.1.5",
|
|
77
|
+
"@enbox/dids": "0.1.5",
|
|
78
78
|
"@ipld/dag-cbor": "10.0.1",
|
|
79
79
|
"@noble/curves": "2.2.0",
|
|
80
80
|
"ajv": "8.18.0",
|
package/src/core/constants.ts
CHANGED
|
@@ -56,11 +56,6 @@ export const ENCRYPTION_CONTROL_PATHS = [
|
|
|
56
56
|
|
|
57
57
|
export type EncryptionControlPath = typeof ENCRYPTION_CONTROL_PATHS[number];
|
|
58
58
|
|
|
59
|
-
export enum EncryptionControlRecordType {
|
|
60
|
-
Audience = 'audience',
|
|
61
|
-
Delivery = 'delivery',
|
|
62
|
-
}
|
|
63
|
-
|
|
64
59
|
/**
|
|
65
60
|
* Returns true when the protocol path is one of the exact reserved encryption
|
|
66
61
|
* control paths.
|
|
@@ -69,28 +64,3 @@ export function isEncryptionControlPath(protocolPath: string | undefined): proto
|
|
|
69
64
|
return protocolPath !== undefined &&
|
|
70
65
|
(ENCRYPTION_CONTROL_PATHS as readonly string[]).includes(protocolPath);
|
|
71
66
|
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Returns the encryption control record type for exact reserved paths.
|
|
75
|
-
*/
|
|
76
|
-
export function getEncryptionControlRecordType(protocolPath: EncryptionControlPath): EncryptionControlRecordType {
|
|
77
|
-
if (protocolPath === ENCRYPTION_CONTROL_AUDIENCE_PATH) {
|
|
78
|
-
return EncryptionControlRecordType.Audience;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return EncryptionControlRecordType.Delivery;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const RECORDS_PRIMARY_PROJECTION_EXCLUDED_PROTOCOLS = new Set<string>([
|
|
85
|
-
ENCRYPTION_PROTOCOL_URI,
|
|
86
|
-
PERMISSIONS_PROTOCOL_URI,
|
|
87
|
-
]);
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Returns true for infrastructure protocols whose records are dependencies or
|
|
91
|
-
* authorization metadata, not primary application records for projection roots.
|
|
92
|
-
*/
|
|
93
|
-
export function isRecordsPrimaryProjectionExcludedProtocol(protocol: string | undefined): boolean {
|
|
94
|
-
return protocol !== undefined &&
|
|
95
|
-
RECORDS_PRIMARY_PROJECTION_EXCLUDED_PROTOCOLS.has(protocol);
|
|
96
|
-
}
|
|
@@ -5,7 +5,7 @@ import type { ValidationStateReader } from '../types/validation-state-reader.js'
|
|
|
5
5
|
import type { EncryptionControlAudiencePayload, EncryptionControlDeliveryTags, RoleAudienceKeyId } from '../types/encryption-types.js';
|
|
6
6
|
import type { Filter, PaginationCursor } from '../types/query-types.js';
|
|
7
7
|
import type { ProtocolActionRule, ProtocolDefinition, ProtocolRuleSet } from '../types/protocols-types.js';
|
|
8
|
-
import type { RecordsCountMessage, RecordsFilter, RecordsQueryMessage, RecordsReadMessage, RecordsSubscribeMessage, RecordsWriteMessage
|
|
8
|
+
import type { RecordsCountMessage, RecordsFilter, RecordsQueryMessage, RecordsReadMessage, RecordsSubscribeMessage, RecordsWriteMessage } from '../types/records-types.js';
|
|
9
9
|
|
|
10
10
|
import { checkActor } from './protocol-authorization-action.js';
|
|
11
11
|
import { DwnConstant } from './dwn-constant.js';
|
|
@@ -1230,20 +1230,4 @@ export class EncryptionControl {
|
|
|
1230
1230
|
|
|
1231
1231
|
return value;
|
|
1232
1232
|
}
|
|
1233
|
-
|
|
1234
|
-
private static getOptionalStringTag(tags: RecordsWriteTags | undefined, tag: string): string | undefined {
|
|
1235
|
-
const value = tags?.[tag];
|
|
1236
|
-
if (value === undefined) {
|
|
1237
|
-
return undefined;
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
if (typeof value !== 'string') {
|
|
1241
|
-
throw new DwnError(
|
|
1242
|
-
DwnErrorCode.EncryptionControlValidateDeliveryMissingRequiredTag,
|
|
1243
|
-
`delivery control tag '${tag}' must be a string.`
|
|
1244
|
-
);
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
return value;
|
|
1248
|
-
}
|
|
1249
1233
|
}
|
|
@@ -51,14 +51,6 @@ export type DependencyRef =
|
|
|
51
51
|
| { type: 'Ancestor'; recordId: string; protocol?: string; messageCid?: string; terminal?: boolean }
|
|
52
52
|
| { type: 'Role'; protocol: string; protocolPath: string; recipient: string; contextPrefix?: string; messageCid?: string; terminal?: boolean }
|
|
53
53
|
| { type: 'Grant'; permissionGrantId: string; messageCid?: string; terminal?: boolean }
|
|
54
|
-
| {
|
|
55
|
-
type: 'EncryptionProtocol';
|
|
56
|
-
protocolPath: 'grantKey';
|
|
57
|
-
tags?: Record<string, string | number>;
|
|
58
|
-
recipient?: string;
|
|
59
|
-
messageCid?: string;
|
|
60
|
-
terminal?: boolean;
|
|
61
|
-
}
|
|
62
54
|
| {
|
|
63
55
|
type: 'EncryptionControl';
|
|
64
56
|
protocol: string;
|
|
@@ -3,6 +3,7 @@ import type { GenericMessage, MessageSort } from '../types/message-types.js';
|
|
|
3
3
|
import type { HandlerDependencies, MethodHandler } from '../types/method-handler.js';
|
|
4
4
|
import type { RecordsQueryMessage, RecordsQueryReply, RecordsQueryReplyEntry } from '../types/records-types.js';
|
|
5
5
|
|
|
6
|
+
import { attachInitialWrites } from '../utils/initial-write-attachment.js';
|
|
6
7
|
import { authenticate } from '../core/auth.js';
|
|
7
8
|
import { DateSort } from '../types/records-types.js';
|
|
8
9
|
import { EncryptionControl } from '../core/encryption-control.js';
|
|
@@ -13,10 +14,18 @@ import { queryRecordsWithRecordLimitOccupancy } from '../utils/record-limit-occu
|
|
|
13
14
|
import { Records } from '../utils/records.js';
|
|
14
15
|
import { RecordsGrantAuthorization } from '../core/records-grant-authorization.js';
|
|
15
16
|
import { RecordsQuery } from '../interfaces/records-query.js';
|
|
16
|
-
import { RecordsWrite } from '../interfaces/records-write.js';
|
|
17
17
|
import { SortDirection } from '../types/query-types.js';
|
|
18
18
|
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
19
19
|
|
|
20
|
+
type RecordsQueryProjectionInput = {
|
|
21
|
+
tenant: string;
|
|
22
|
+
recordsQuery: RecordsQuery;
|
|
23
|
+
requester: string | undefined;
|
|
24
|
+
filters: Filter[];
|
|
25
|
+
messageSort: MessageSort;
|
|
26
|
+
pagination?: { cursor?: PaginationCursor; limit?: number };
|
|
27
|
+
};
|
|
28
|
+
|
|
20
29
|
export class RecordsQueryHandler implements MethodHandler {
|
|
21
30
|
|
|
22
31
|
constructor(private readonly deps: HandlerDependencies) { }
|
|
@@ -63,22 +72,17 @@ export class RecordsQueryHandler implements MethodHandler {
|
|
|
63
72
|
}
|
|
64
73
|
}
|
|
65
74
|
|
|
66
|
-
// attach initial write
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const initialWrite = initialWriteQueryResult.messages[0] as RecordsQueryReplyEntry;
|
|
74
|
-
delete initialWrite.encodedData; // defensive measure but technically optional because we do this when an update RecordsWrite takes place
|
|
75
|
-
recordsWrite.initialWrite = initialWrite;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
75
|
+
// attach the retained initial write to every entry that is not itself an initial write
|
|
76
|
+
const completeRecordsWrites = await attachInitialWrites({
|
|
77
|
+
messageStore : this.deps.messageStore,
|
|
78
|
+
tenant,
|
|
79
|
+
recordsWrites,
|
|
80
|
+
operationName : 'RecordsQuery',
|
|
81
|
+
});
|
|
78
82
|
|
|
79
83
|
return {
|
|
80
84
|
status : { code: 200, detail: 'OK' },
|
|
81
|
-
entries :
|
|
85
|
+
entries : completeRecordsWrites,
|
|
82
86
|
cursor
|
|
83
87
|
};
|
|
84
88
|
}
|
|
@@ -244,14 +248,9 @@ export class RecordsQueryHandler implements MethodHandler {
|
|
|
244
248
|
});
|
|
245
249
|
}
|
|
246
250
|
|
|
247
|
-
private async queryRecordsWithVisibleControlFiltering(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
requester: string | undefined;
|
|
251
|
-
filters: Filter[];
|
|
252
|
-
messageSort: MessageSort;
|
|
253
|
-
pagination?: { cursor?: PaginationCursor; limit?: number };
|
|
254
|
-
}): Promise<{ messages: RecordsQueryReplyEntry[], cursor?: PaginationCursor }> {
|
|
251
|
+
private async queryRecordsWithVisibleControlFiltering(
|
|
252
|
+
input: RecordsQueryProjectionInput
|
|
253
|
+
): Promise<{ messages: RecordsQueryReplyEntry[], cursor?: PaginationCursor }> {
|
|
255
254
|
const {
|
|
256
255
|
tenant, recordsQuery, requester, filters, messageSort, pagination
|
|
257
256
|
} = input;
|
|
@@ -9,6 +9,7 @@ import { EncryptionControl } from '../core/encryption-control.js';
|
|
|
9
9
|
import { isRecordLimitOccupant } from '../utils/record-limit-occupancy.js';
|
|
10
10
|
import { Message } from '../core/message.js';
|
|
11
11
|
import { messageReplyFromError } from '../core/message-reply.js';
|
|
12
|
+
import { Messages } from '../utils/messages.js';
|
|
12
13
|
import { ProtocolAuthorization } from '../core/protocol-authorization.js';
|
|
13
14
|
import { Records } from '../utils/records.js';
|
|
14
15
|
import { RecordsGrantAuthorization } from '../core/records-grant-authorization.js';
|
|
@@ -114,15 +115,27 @@ export class RecordsReadHandler implements MethodHandler {
|
|
|
114
115
|
}
|
|
115
116
|
};
|
|
116
117
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
118
|
+
try {
|
|
119
|
+
// Attach the initial write by its stable entry ID. Looking it up through
|
|
120
|
+
// `isLatestBaseState:false` races with the update that demotes it.
|
|
121
|
+
if (!await RecordsWrite.isInitialWrite(matchedRecordsWrite)) {
|
|
122
|
+
const storedInitialWrite = await RecordsWrite.fetchInitialRecordsWriteMessage(
|
|
123
|
+
this.deps.messageStore,
|
|
124
|
+
tenant,
|
|
125
|
+
matchedRecordsWrite.recordId,
|
|
126
|
+
);
|
|
127
|
+
if (storedInitialWrite === undefined) {
|
|
128
|
+
throw new DwnError(
|
|
129
|
+
DwnErrorCode.RecordsWriteGetInitialWriteNotFound,
|
|
130
|
+
`initial write not found for record ${matchedRecordsWrite.recordId}`,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const { message: initialWrite } = Messages.detachEncodedData(storedInitialWrite);
|
|
135
|
+
recordsReadReply.entry!.initialWrite = initialWrite as RecordsQueryReplyEntry;
|
|
136
|
+
}
|
|
137
|
+
} catch (error) {
|
|
138
|
+
return messageReplyFromError(error, 500);
|
|
126
139
|
}
|
|
127
140
|
|
|
128
141
|
return recordsReadReply;
|
|
@@ -4,6 +4,7 @@ import type { Filter, PaginationCursor } from '../types/query-types.js';
|
|
|
4
4
|
import type { HandlerDependencies, MethodHandler } from '../types/method-handler.js';
|
|
5
5
|
import type { RecordsQueryReplyEntry, RecordsSubscribeMessage, RecordsSubscribeReply } from '../types/records-types.js';
|
|
6
6
|
|
|
7
|
+
import { attachInitialWrites } from '../utils/initial-write-attachment.js';
|
|
7
8
|
import { authenticate } from '../core/auth.js';
|
|
8
9
|
import { DateSort } from '../types/records-types.js';
|
|
9
10
|
import { EncryptionControl } from '../core/encryption-control.js';
|
|
@@ -13,7 +14,6 @@ import { ProtocolAuthorization } from '../core/protocol-authorization.js';
|
|
|
13
14
|
import { Records } from '../utils/records.js';
|
|
14
15
|
import { RecordsGrantAuthorization } from '../core/records-grant-authorization.js';
|
|
15
16
|
import { RecordsSubscribe } from '../interfaces/records-subscribe.js';
|
|
16
|
-
import { RecordsWrite } from '../interfaces/records-write.js';
|
|
17
17
|
import { SortDirection } from '../types/query-types.js';
|
|
18
18
|
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
19
19
|
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
@@ -141,21 +141,15 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
141
141
|
messageSort,
|
|
142
142
|
pagination,
|
|
143
143
|
);
|
|
144
|
-
entries = queryResult.messages;
|
|
145
|
-
paginationCursor = queryResult.cursor;
|
|
146
144
|
|
|
147
|
-
// attach
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
delete initialWrite.encodedData;
|
|
156
|
-
entry.initialWrite = initialWrite;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
145
|
+
// attach the retained initial write to every entry that is not itself an initial write
|
|
146
|
+
entries = await attachInitialWrites({
|
|
147
|
+
messageStore : this.deps.messageStore,
|
|
148
|
+
tenant,
|
|
149
|
+
recordsWrites : queryResult.messages,
|
|
150
|
+
operationName : 'RecordsSubscribe',
|
|
151
|
+
});
|
|
152
|
+
paginationCursor = queryResult.cursor;
|
|
159
153
|
} catch (error) {
|
|
160
154
|
// if the query fails, close the subscription and return the error
|
|
161
155
|
await subscription.close();
|
|
@@ -100,16 +100,10 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
100
100
|
|
|
101
101
|
const newestExistingMessage = await Message.getNewestMessage(existingMessages);
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (newestExistingMessage === undefined || await Message.isNewer(message, newestExistingMessage)) {
|
|
106
|
-
incomingMessageIsNewest = true;
|
|
107
|
-
newestMessage = message;
|
|
108
|
-
} else { // existing message is the same age or newer than the incoming message
|
|
109
|
-
newestMessage = newestExistingMessage;
|
|
110
|
-
}
|
|
111
|
-
|
|
103
|
+
const incomingMessageIsNewest =
|
|
104
|
+
newestExistingMessage === undefined || await Message.isNewer(message, newestExistingMessage);
|
|
112
105
|
if (!incomingMessageIsNewest) {
|
|
106
|
+
// existing message is the same age or newer than the incoming message
|
|
113
107
|
return {
|
|
114
108
|
status: { code: 409, detail: 'Conflict' }
|
|
115
109
|
};
|
|
@@ -170,7 +164,18 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
170
164
|
}
|
|
171
165
|
|
|
172
166
|
const indexes = await recordsWrite.constructIndexes(isLatestBaseState);
|
|
173
|
-
|
|
167
|
+
|
|
168
|
+
// store the new message and displace every other message for this record in one atomic
|
|
169
|
+
// commit, retaining only the initial write as non-latest state — readers can never observe
|
|
170
|
+
// two latest-state rows for the record
|
|
171
|
+
const putResult = await StorageController.commitLatestStateTransition(
|
|
172
|
+
tenant,
|
|
173
|
+
existingMessages,
|
|
174
|
+
{ message: messageWithOptionalEncodedData, indexes },
|
|
175
|
+
[],
|
|
176
|
+
this.deps.messageStore,
|
|
177
|
+
this.deps.dataStore!,
|
|
178
|
+
);
|
|
174
179
|
position = putResult.position;
|
|
175
180
|
} catch (error) {
|
|
176
181
|
if (error instanceof DwnError) {
|
|
@@ -200,11 +205,6 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
200
205
|
position,
|
|
201
206
|
};
|
|
202
207
|
|
|
203
|
-
// displace every other message for this record, retaining only the initial write as non-latest state
|
|
204
|
-
await StorageController.deleteDisplacedMessagesAndRetainWrites(
|
|
205
|
-
tenant, existingMessages, newestMessage, this.deps.messageStore, this.deps.dataStore!, []
|
|
206
|
-
);
|
|
207
|
-
|
|
208
208
|
// Squash processing: if the incoming write is a squash, delete all older sibling records
|
|
209
209
|
// at the same protocol path and parent context. Uses the resumable task system for crash safety.
|
|
210
210
|
if (message.descriptor.squash === true) {
|
package/src/index.ts
CHANGED
|
@@ -25,7 +25,6 @@ export {
|
|
|
25
25
|
ENCRYPTION_CONTROL_PATHS,
|
|
26
26
|
ENCRYPTION_CONTROL_ROOT_PATH,
|
|
27
27
|
ENCRYPTION_PROTOCOL_URI,
|
|
28
|
-
EncryptionControlRecordType,
|
|
29
28
|
PERMISSIONS_REVOCATION_PATH,
|
|
30
29
|
isEncryptionControlPath,
|
|
31
30
|
} from './core/constants.js';
|
|
@@ -80,7 +79,7 @@ export type { MessagesReadOptions } from './interfaces/messages-read.js';
|
|
|
80
79
|
export { MessagesQuery } from './interfaces/messages-query.js';
|
|
81
80
|
export type { MessagesQueryOptions } from './interfaces/messages-query.js';
|
|
82
81
|
export type { UnionMessageReply } from './core/message-reply.js';
|
|
83
|
-
export type { MessageStore, MessageStoreOptions, MessageStorePutResult } from './types/message-store.js';
|
|
82
|
+
export type { MessageStore, MessageStoreLatestStateTransition, MessageStoreOptions, MessageStorePutResult } from './types/message-store.js';
|
|
84
83
|
export { Replication } from './utils/replication.js';
|
|
85
84
|
export type { MessageInterface } from './types/message-interface.js';
|
|
86
85
|
export { PermissionGrant } from './protocols/permission-grant.js';
|
|
@@ -128,6 +128,9 @@ export async function fetchInitialRecordsWriteMessage(
|
|
|
128
128
|
tenant: string,
|
|
129
129
|
recordId: string
|
|
130
130
|
): Promise<RecordsWriteMessage | undefined> {
|
|
131
|
+
// `entryId === recordId` identifies the initial write. Do not also filter on
|
|
132
|
+
// `isLatestBaseState:false`: that mutable index is updated after a newer
|
|
133
|
+
// write is inserted, so it can still be `true` during the update transition.
|
|
131
134
|
const query = { entryId: recordId };
|
|
132
135
|
const { messages } = await messageStore.query(tenant, [query]);
|
|
133
136
|
|
|
@@ -518,19 +518,6 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
|
|
|
518
518
|
return this.message;
|
|
519
519
|
}
|
|
520
520
|
|
|
521
|
-
/**
|
|
522
|
-
* Encrypts the symmetric encryption key using the public keys given and attaches the resulting `encryption` property.
|
|
523
|
-
*/
|
|
524
|
-
public async encryptSymmetricEncryptionKey(
|
|
525
|
-
encryptionInput: EncryptionInput,
|
|
526
|
-
): Promise<void> {
|
|
527
|
-
this._message.encryption = await createEncryptionProperty(encryptionInput);
|
|
528
|
-
|
|
529
|
-
delete this._message.authorization;
|
|
530
|
-
this._signaturePayload = undefined;
|
|
531
|
-
this._author = undefined;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
521
|
/**
|
|
535
522
|
* Signs the RecordsWrite, the signer is commonly the author, but can also be a delegate.
|
|
536
523
|
*/
|
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
import type { Filter, KeyValues, PaginationCursor, QueryOptions } from '../types/query-types.js';
|
|
14
14
|
import type { GenericMessage, MessageSort, Pagination } from '../types/message-types.js';
|
|
15
15
|
import type { LevelDatabase, LevelWrapperBatchOperation } from './level-wrapper.js';
|
|
16
|
-
import type { MessageStore, MessageStoreOptions, MessageStorePutResult } from '../types/message-store.js';
|
|
16
|
+
import type { MessageStore, MessageStoreLatestStateTransition, MessageStoreOptions, MessageStorePutResult } from '../types/message-store.js';
|
|
17
17
|
|
|
18
18
|
import * as block from 'multiformats/block';
|
|
19
19
|
import * as cbor from '@ipld/dag-cbor';
|
|
@@ -441,6 +441,140 @@ export class MessageStoreLevel implements MessageStore, ReplicationFeedReader {
|
|
|
441
441
|
});
|
|
442
442
|
}
|
|
443
443
|
|
|
444
|
+
async commitLatestState(
|
|
445
|
+
tenant: string,
|
|
446
|
+
transition: MessageStoreLatestStateTransition,
|
|
447
|
+
options?: MessageStoreOptions
|
|
448
|
+
): Promise<MessageStorePutResult> {
|
|
449
|
+
options?.signal?.throwIfAborted();
|
|
450
|
+
|
|
451
|
+
const partitions = await executeUnlessAborted(this.partitions(), options?.signal);
|
|
452
|
+
const index = await executeUnlessAborted(this.index(), options?.signal);
|
|
453
|
+
|
|
454
|
+
const { message, indexes } = transition.put;
|
|
455
|
+
const encodedMessageBlock = await executeUnlessAborted(block.encode({ value: message, codec: cbor, hasher: sha256 }), options?.signal);
|
|
456
|
+
const messageCid = Cid.parseCid(await Message.getCid(message)).toString();
|
|
457
|
+
|
|
458
|
+
// Validate and encode the retained replacements before entering the write lock.
|
|
459
|
+
const retains: { messageCid: string, message: GenericMessage, indexes: KeyValues, blockBytes: Uint8Array }[] = [];
|
|
460
|
+
for (const retain of transition.retains ?? []) {
|
|
461
|
+
const computedMessageCid = Cid.parseCid(await Message.getCid(retain.message)).toString();
|
|
462
|
+
const normalizedMessageCid = Cid.parseCid(retain.messageCid).toString();
|
|
463
|
+
if (computedMessageCid !== normalizedMessageCid) {
|
|
464
|
+
throw new DwnError(
|
|
465
|
+
DwnErrorCode.MessageStoreUpdateMessageAndIndexesCidMismatch,
|
|
466
|
+
`replacement message CID ${computedMessageCid} does not match target CID ${normalizedMessageCid}`
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const encodedRetainBlock = await executeUnlessAborted(block.encode({ value: retain.message, codec: cbor, hasher: sha256 }), options?.signal);
|
|
471
|
+
retains.push({
|
|
472
|
+
messageCid : normalizedMessageCid,
|
|
473
|
+
message : retain.message,
|
|
474
|
+
indexes : retain.indexes,
|
|
475
|
+
blockBytes : encodedRetainBlock.bytes,
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
const deleteCids = (transition.deletes ?? []).map((cidString): string => CID.parse(cidString).toString());
|
|
479
|
+
|
|
480
|
+
return this.withTenantWriteLock(tenant, async () => {
|
|
481
|
+
options?.signal?.throwIfAborted();
|
|
482
|
+
|
|
483
|
+
const tenantBlocks = await partitions.blocks.partition(tenant);
|
|
484
|
+
const tenantLog = await partitions.log.partition(tenant);
|
|
485
|
+
const tenantCidToSeq = await partitions.cidToSeq.partition(tenant);
|
|
486
|
+
|
|
487
|
+
const operations: LevelWrapperBatchOperation<string>[] = [];
|
|
488
|
+
const fingerprintFolds: { messageCid: string, scopes: string[] }[] = [];
|
|
489
|
+
|
|
490
|
+
// The new message insert. A duplicate inserts nothing but still applies the retains and
|
|
491
|
+
// deletes below, so replaying a transition heals one that previously stopped mid-plan.
|
|
492
|
+
const existingSeq = await tenantCidToSeq.get(messageCid, options);
|
|
493
|
+
const inserted = existingSeq === undefined;
|
|
494
|
+
let seq = 0n;
|
|
495
|
+
if (inserted) {
|
|
496
|
+
const head = await this.getHead(partitions, tenant);
|
|
497
|
+
seq = head + 1n;
|
|
498
|
+
const fingerprintScopes = Replication.computeFingerprintScopes(message, indexes);
|
|
499
|
+
|
|
500
|
+
const logEntry: LogEntryValue = {
|
|
501
|
+
seq: seq.toString(),
|
|
502
|
+
messageCid,
|
|
503
|
+
indexes,
|
|
504
|
+
fingerprintScopes,
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
operations.push(
|
|
508
|
+
tenantBlocks.createOperation({ type: 'put', key: messageCid, value: encodedMessageBlock.bytes }) as unknown as LevelWrapperBatchOperation<string>,
|
|
509
|
+
...await index.createPutOperations(tenant, messageCid, indexes),
|
|
510
|
+
tenantLog.createOperation({ type: 'put', key: Replication.encodePositionKey(seq), value: JSON.stringify(logEntry) }),
|
|
511
|
+
tenantCidToSeq.createOperation({ type: 'put', key: messageCid, value: seq.toString() }),
|
|
512
|
+
partitions.heads.createOperation({ type: 'put', key: tenant, value: seq.toString() }),
|
|
513
|
+
);
|
|
514
|
+
fingerprintFolds.push({ messageCid, scopes: fingerprintScopes });
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Retained displaced writes: same-CID in-place replacement, exactly as `updateMessageAndIndexes`.
|
|
518
|
+
for (const retain of retains) {
|
|
519
|
+
const { entry, positionKey } = await this.getLogEntryForMutation(
|
|
520
|
+
partitions, tenant, retain.messageCid, DwnErrorCode.MessageStoreUpdateMessageAndIndexesMessageNotFound
|
|
521
|
+
);
|
|
522
|
+
Replication.assertFingerprintScopesUntouched(entry.fingerprintScopes, retain.message, retain.messageCid, retain.indexes);
|
|
523
|
+
|
|
524
|
+
const updatedEntry: LogEntryValue = { ...entry, indexes: retain.indexes };
|
|
525
|
+
operations.push(
|
|
526
|
+
tenantBlocks.createOperation({ type: 'put', key: retain.messageCid, value: retain.blockBytes }) as unknown as LevelWrapperBatchOperation<string>,
|
|
527
|
+
...await index.createDeleteOperations(tenant, retain.messageCid),
|
|
528
|
+
...await index.createPutOperations(tenant, retain.messageCid, retain.indexes),
|
|
529
|
+
tenantLog.createOperation({ type: 'put', key: positionKey, value: JSON.stringify(updatedEntry) }),
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Non-retained displaced rows: full removal, exactly as `delete`. Absent rows are no-ops.
|
|
534
|
+
for (const deleteCid of deleteCids) {
|
|
535
|
+
const seqString = await tenantCidToSeq.get(deleteCid, options);
|
|
536
|
+
if (seqString === undefined) {
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const positionKey = Replication.encodePositionKey(BigInt(seqString));
|
|
541
|
+
const serializedEntry = await tenantLog.get(positionKey);
|
|
542
|
+
if (serializedEntry === undefined) {
|
|
543
|
+
throw new DwnError(
|
|
544
|
+
DwnErrorCode.MessageStoreDeleteLogEntryMissing,
|
|
545
|
+
`cid index for tenant ${tenant} points to missing log entry at seq ${seqString} (CID ${deleteCid})`
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
const entry = JSON.parse(serializedEntry) as LogEntryValue;
|
|
550
|
+
operations.push(
|
|
551
|
+
tenantBlocks.createOperation({ type: 'del', key: deleteCid }) as unknown as LevelWrapperBatchOperation<string>,
|
|
552
|
+
...await index.createDeleteOperations(tenant, deleteCid),
|
|
553
|
+
tenantLog.createOperation({ type: 'del', key: positionKey }),
|
|
554
|
+
tenantCidToSeq.createOperation({ type: 'del', key: deleteCid }),
|
|
555
|
+
);
|
|
556
|
+
fingerprintFolds.push({ messageCid: deleteCid, scopes: entry.fingerprintScopes });
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
operations.push(...await this.createFingerprintFoldOperationsForMessages(partitions, tenant, fingerprintFolds));
|
|
560
|
+
|
|
561
|
+
if (operations.length > 0) {
|
|
562
|
+
await partitions.root.batch(operations);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
if (!inserted) {
|
|
566
|
+
return { status: 'duplicate' as const };
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
this.publishWake(tenant, seq);
|
|
570
|
+
|
|
571
|
+
return {
|
|
572
|
+
status : 'inserted' as const,
|
|
573
|
+
position : await this.buildToken(tenant, seq, messageCid),
|
|
574
|
+
};
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
|
|
444
578
|
async updateIndexes(
|
|
445
579
|
tenant: string,
|
|
446
580
|
messageCid: string,
|
|
@@ -907,12 +1041,33 @@ export class MessageStoreLevel implements MessageStore, ReplicationFeedReader {
|
|
|
907
1041
|
messageCid: string,
|
|
908
1042
|
scopes: string[],
|
|
909
1043
|
): Promise<LevelWrapperBatchOperation<string>[]> {
|
|
910
|
-
|
|
911
|
-
|
|
1044
|
+
return this.createFingerprintFoldOperationsForMessages(partitions, tenant, [{ messageCid, scopes }]);
|
|
1045
|
+
}
|
|
912
1046
|
|
|
1047
|
+
/**
|
|
1048
|
+
* Creates the batch operations that fold multiple messages' contributions into their fingerprint
|
|
1049
|
+
* domains. Contributions targeting the same domain are XOR-combined before the single
|
|
1050
|
+
* read-fold-write per domain — concatenating per-message fold operations into one batch would
|
|
1051
|
+
* let the last write to a shared domain silently discard the earlier folds.
|
|
1052
|
+
*/
|
|
1053
|
+
private async createFingerprintFoldOperationsForMessages(
|
|
1054
|
+
partitions: StorePartitions,
|
|
1055
|
+
tenant: string,
|
|
1056
|
+
folds: { messageCid: string, scopes: string[] }[],
|
|
1057
|
+
): Promise<LevelWrapperBatchOperation<string>[]> {
|
|
1058
|
+
const combinedContributionByKey = new Map<string, Uint8Array>();
|
|
1059
|
+
for (const { messageCid, scopes } of folds) {
|
|
1060
|
+
const contribution = await Replication.hashMessageCid(messageCid);
|
|
1061
|
+
for (const scope of scopes) {
|
|
1062
|
+
const key = MessageStoreLevel.fingerprintKey(scope);
|
|
1063
|
+
const combined = combinedContributionByKey.get(key);
|
|
1064
|
+
combinedContributionByKey.set(key, combined === undefined ? contribution : Replication.xorFingerprint(combined, contribution));
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
const tenantFingerprints = await partitions.fingerprints.partition(tenant);
|
|
913
1069
|
const operations: LevelWrapperBatchOperation<string>[] = [];
|
|
914
|
-
for (const
|
|
915
|
-
const key = MessageStoreLevel.fingerprintKey(scope);
|
|
1070
|
+
for (const [key, contribution] of combinedContributionByKey) {
|
|
916
1071
|
const storedHex = await tenantFingerprints.get(key);
|
|
917
1072
|
const current = storedHex === undefined ? Replication.emptyFingerprint() : Replication.hexToFingerprint(storedHex);
|
|
918
1073
|
const folded = Replication.xorFingerprint(current, contribution);
|