cojson 0.17.9 → 0.17.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +18 -0
- package/dist/coValueCore/SessionMap.d.ts +45 -0
- package/dist/coValueCore/SessionMap.d.ts.map +1 -0
- package/dist/coValueCore/SessionMap.js +118 -0
- package/dist/coValueCore/SessionMap.js.map +1 -0
- package/dist/coValueCore/coValueCore.d.ts +10 -4
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +55 -68
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValueCore/verifiedState.d.ts +15 -19
- package/dist/coValueCore/verifiedState.d.ts.map +1 -1
- package/dist/coValueCore/verifiedState.js +24 -87
- package/dist/coValueCore/verifiedState.js.map +1 -1
- package/dist/coValues/account.d.ts +4 -0
- package/dist/coValues/account.d.ts.map +1 -1
- package/dist/coValues/account.js +24 -4
- package/dist/coValues/account.js.map +1 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +6 -2
- package/dist/coValues/group.js.map +1 -1
- package/dist/crypto/PureJSCrypto.d.ts +31 -3
- package/dist/crypto/PureJSCrypto.d.ts.map +1 -1
- package/dist/crypto/PureJSCrypto.js +115 -0
- package/dist/crypto/PureJSCrypto.js.map +1 -1
- package/dist/crypto/WasmCrypto.d.ts +23 -4
- package/dist/crypto/WasmCrypto.d.ts.map +1 -1
- package/dist/crypto/WasmCrypto.js +44 -2
- package/dist/crypto/WasmCrypto.js.map +1 -1
- package/dist/crypto/crypto.d.ts +17 -1
- package/dist/crypto/crypto.d.ts.map +1 -1
- package/dist/crypto/crypto.js.map +1 -1
- package/dist/localNode.d.ts +1 -0
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +10 -5
- package/dist/localNode.js.map +1 -1
- package/dist/permissions.d.ts +17 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js.map +1 -1
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +55 -49
- package/dist/sync.js.map +1 -1
- package/dist/tests/PureJSCrypto.test.d.ts +2 -0
- package/dist/tests/PureJSCrypto.test.d.ts.map +1 -0
- package/dist/tests/PureJSCrypto.test.js +102 -0
- package/dist/tests/PureJSCrypto.test.js.map +1 -0
- package/dist/tests/WasmCrypto.test.d.ts +2 -0
- package/dist/tests/WasmCrypto.test.d.ts.map +1 -0
- package/dist/tests/WasmCrypto.test.js +88 -0
- package/dist/tests/WasmCrypto.test.js.map +1 -0
- package/dist/tests/coValueCore.test.js +62 -187
- package/dist/tests/coValueCore.test.js.map +1 -1
- package/dist/tests/coreWasm.test.d.ts +2 -0
- package/dist/tests/coreWasm.test.d.ts.map +1 -0
- package/dist/tests/coreWasm.test.js +80 -0
- package/dist/tests/coreWasm.test.js.map +1 -0
- package/dist/tests/group.addMember.test.js +6 -11
- package/dist/tests/group.addMember.test.js.map +1 -1
- package/dist/tests/sync.load.test.js +40 -1
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.test.js +1 -1
- package/dist/tests/sync.test.js.map +1 -1
- package/dist/tests/testUtils.d.ts +3 -0
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +4 -1
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +3 -3
- package/src/coValueCore/SessionMap.ts +229 -0
- package/src/coValueCore/coValueCore.ts +106 -121
- package/src/coValueCore/verifiedState.ts +61 -132
- package/src/coValues/account.ts +28 -4
- package/src/coValues/group.ts +10 -2
- package/src/crypto/PureJSCrypto.ts +206 -2
- package/src/crypto/WasmCrypto.ts +95 -4
- package/src/crypto/crypto.ts +38 -1
- package/src/localNode.ts +18 -10
- package/src/permissions.ts +17 -1
- package/src/sync.ts +63 -59
- package/src/tests/PureJSCrypto.test.ts +153 -0
- package/src/tests/WasmCrypto.test.ts +128 -0
- package/src/tests/coValueCore.test.ts +81 -293
- package/src/tests/coreWasm.test.ts +142 -0
- package/src/tests/group.addMember.test.ts +69 -63
- package/src/tests/sync.load.test.ts +52 -0
- package/src/tests/sync.test.ts +0 -2
- package/src/tests/testUtils.ts +9 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { assert, describe, expect, it } from "vitest";
|
|
2
|
+
import { WasmCrypto } from "../crypto/WasmCrypto";
|
|
3
|
+
import { JsonValue, LocalNode, SessionID } from "../exports";
|
|
4
|
+
import {
|
|
5
|
+
agentAndSessionIDFromSecret,
|
|
6
|
+
randomAgentAndSessionID,
|
|
7
|
+
} from "./testUtils";
|
|
8
|
+
import { PureJSCrypto } from "../crypto/PureJSCrypto";
|
|
9
|
+
import { Encrypted } from "../crypto/crypto";
|
|
10
|
+
import { PrivateTransaction } from "../coValueCore/verifiedState";
|
|
11
|
+
|
|
12
|
+
const wasmCrypto = await WasmCrypto.create();
|
|
13
|
+
const jsCrypto = await PureJSCrypto.create();
|
|
14
|
+
|
|
15
|
+
const agentSecret =
|
|
16
|
+
"sealerSecret_zE3Nr7YFr1KkVbJSx4JDCzYn4ApYdm8kJ5ghNBxREHQya/signerSecret_z9fEu4eNG1eXHMak3YSzY7uLdoG8HESSJ8YW4xWdNNDSP";
|
|
17
|
+
|
|
18
|
+
function createTestNode() {
|
|
19
|
+
const [agent, session] = agentAndSessionIDFromSecret(agentSecret);
|
|
20
|
+
return {
|
|
21
|
+
agent,
|
|
22
|
+
session,
|
|
23
|
+
node: new LocalNode(agent.agentSecret, session, jsCrypto),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe("SessionLog WASM", () => {
|
|
28
|
+
it("it works", () => {
|
|
29
|
+
const [agent, sessionId] = agentAndSessionIDFromSecret(agentSecret);
|
|
30
|
+
|
|
31
|
+
const session = wasmCrypto.createSessionLog(
|
|
32
|
+
"co_test1" as any,
|
|
33
|
+
sessionId,
|
|
34
|
+
agent.currentSignerID(),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
expect(session).toBeDefined();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("test_add_from_example_json", () => {
|
|
41
|
+
const { agent, session, node } = createTestNode();
|
|
42
|
+
|
|
43
|
+
const group = node.createGroup();
|
|
44
|
+
const sessionContent =
|
|
45
|
+
group.core.verified.newContentSince(undefined)?.[0]?.new[session];
|
|
46
|
+
assert(sessionContent);
|
|
47
|
+
|
|
48
|
+
let log = wasmCrypto.createSessionLog(
|
|
49
|
+
group.id,
|
|
50
|
+
session,
|
|
51
|
+
agent.currentSignerID(),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
log.tryAdd(
|
|
55
|
+
sessionContent.newTransactions,
|
|
56
|
+
sessionContent.lastSignature,
|
|
57
|
+
false,
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("test_add_new_transaction", () => {
|
|
62
|
+
const { agent, session, node } = createTestNode();
|
|
63
|
+
|
|
64
|
+
const group = node.createGroup();
|
|
65
|
+
const sessionContent =
|
|
66
|
+
group.core.verified.newContentSince(undefined)?.[0]?.new[session];
|
|
67
|
+
assert(sessionContent);
|
|
68
|
+
|
|
69
|
+
let log = wasmCrypto.createSessionLog(
|
|
70
|
+
group.id,
|
|
71
|
+
session,
|
|
72
|
+
agent.currentSignerID(),
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const changesJson = [
|
|
76
|
+
{ after: "start", op: "app", value: "co_zMphsnYN6GU8nn2HDY5suvyGufY" },
|
|
77
|
+
];
|
|
78
|
+
const key = group.getCurrentReadKey();
|
|
79
|
+
assert(key);
|
|
80
|
+
assert(key.secret);
|
|
81
|
+
|
|
82
|
+
const { signature, transaction } = log.addNewPrivateTransaction(
|
|
83
|
+
agent,
|
|
84
|
+
changesJson,
|
|
85
|
+
key.id,
|
|
86
|
+
key.secret,
|
|
87
|
+
0,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
expect(signature).toMatch(/^signature_z[a-zA-Z0-9]+$/);
|
|
91
|
+
expect(transaction).toEqual({
|
|
92
|
+
encryptedChanges: expect.stringMatching(/^encrypted_U/),
|
|
93
|
+
keyUsed: expect.stringMatching(/^key_z/),
|
|
94
|
+
madeAt: 0,
|
|
95
|
+
privacy: "private",
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const decrypted = log.decryptNextTransactionChangesJson(0, key.secret);
|
|
99
|
+
|
|
100
|
+
expect(decrypted).toEqual(
|
|
101
|
+
'[{"after":"start","op":"app","value":"co_zMphsnYN6GU8nn2HDY5suvyGufY"}]',
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("test_decrypt + clone", () => {
|
|
106
|
+
const [agent] = agentAndSessionIDFromSecret(agentSecret);
|
|
107
|
+
const fixtures = {
|
|
108
|
+
id: "co_zWwrEiushQLvbkWd6Z3L8WxTU1r",
|
|
109
|
+
signature:
|
|
110
|
+
"signature_z3ktW7wxMnW7VYExCGZv4Ug2UJSW3ag6zLDiP8GpZThzif6veJt7JipYpUgshhuGbgHtLcWywWSWysV7hChxFypDt",
|
|
111
|
+
decrypted:
|
|
112
|
+
'[{"after":"start","op":"app","value":"co_zMphsnYN6GU8nn2HDY5suvyGufY"}]',
|
|
113
|
+
key: {
|
|
114
|
+
secret: "keySecret_z3dU66SsyQkkGKpNCJW6NX74MnfVGHUyY7r85b4M8X88L",
|
|
115
|
+
id: "key_z5XUAHyoqUV9zXWvMK",
|
|
116
|
+
},
|
|
117
|
+
transaction: {
|
|
118
|
+
privacy: "private",
|
|
119
|
+
madeAt: 0,
|
|
120
|
+
encryptedChanges:
|
|
121
|
+
"encrypted_UNAxqdUSGRZ2rzuLU99AFPKCe2C0HwsTzMWQreXZqLr6RpWrSMa-5lwgwIev7xPHTgZFq5UyUgMFrO9zlHJHJGgjJcDzFihY=" as any,
|
|
122
|
+
keyUsed: "key_z5XUAHyoqUV9zXWvMK",
|
|
123
|
+
},
|
|
124
|
+
session:
|
|
125
|
+
"sealer_z5yhsCCe2XwLTZC4254mUoMASshm3Diq49JrefPpjTktp/signer_z7gVGDpNz9qUtsRxAkHMuu4DYdtVVCG4XELTKPYdoYLPr_session_z9mDP8FoonSA",
|
|
126
|
+
} as const;
|
|
127
|
+
|
|
128
|
+
let log = wasmCrypto.createSessionLog(
|
|
129
|
+
fixtures.id,
|
|
130
|
+
fixtures.session,
|
|
131
|
+
agent.currentSignerID(),
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
log.tryAdd([fixtures.transaction], fixtures.signature, true);
|
|
135
|
+
|
|
136
|
+
const decrypted = log
|
|
137
|
+
.clone()
|
|
138
|
+
.decryptNextTransactionChangesJson(0, fixtures.key.secret);
|
|
139
|
+
|
|
140
|
+
expect(decrypted).toEqual(fixtures.decrypted);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
@@ -2,7 +2,6 @@ import { beforeEach, describe, expect, test } from "vitest";
|
|
|
2
2
|
import { expectMap } from "../coValue.js";
|
|
3
3
|
import {
|
|
4
4
|
SyncMessagesLog,
|
|
5
|
-
TEST_NODE_CONFIG,
|
|
6
5
|
loadCoValueOrFail,
|
|
7
6
|
setupTestAccount,
|
|
8
7
|
setupTestNode,
|
|
@@ -220,68 +219,75 @@ describe("Group.addMember", () => {
|
|
|
220
219
|
expect(personOnReaderNode.get("name")).toEqual(undefined);
|
|
221
220
|
});
|
|
222
221
|
|
|
223
|
-
test("
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
)
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
222
|
+
test.each(["writer", "reader", "writeOnly"] as const)(
|
|
223
|
+
"an admin should not be able to downgrade an admin to %s",
|
|
224
|
+
async (targetRole) => {
|
|
225
|
+
const admin = await setupTestAccount({
|
|
226
|
+
connected: true,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const otherAdmin = await setupTestAccount({
|
|
230
|
+
connected: true,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const group = admin.node.createGroup();
|
|
234
|
+
const person = group.createMap({
|
|
235
|
+
name: "John Doe",
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
const otherAdminOnAdminNode = await loadCoValueOrFail(
|
|
239
|
+
admin.node,
|
|
240
|
+
otherAdmin.accountID,
|
|
241
|
+
);
|
|
242
|
+
group.addMember(otherAdminOnAdminNode, "admin");
|
|
243
|
+
|
|
244
|
+
// Try to downgrade other admin
|
|
245
|
+
expect(() => group.addMember(otherAdminOnAdminNode, targetRole)).toThrow(
|
|
246
|
+
"Administrators cannot demote other administrators in a group",
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
expect(group.roleOf(otherAdmin.accountID)).toEqual("admin");
|
|
250
|
+
|
|
251
|
+
// Verify other admin still has admin access by adding a new member
|
|
252
|
+
const reader = await setupTestAccount({
|
|
253
|
+
connected: true,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
const readerOnOtherAdminNode = await loadCoValueOrFail(
|
|
257
|
+
otherAdmin.node,
|
|
258
|
+
reader.accountID,
|
|
259
|
+
);
|
|
260
|
+
group.addMember(readerOnOtherAdminNode, "reader");
|
|
261
|
+
|
|
262
|
+
const personOnReaderNode = await loadCoValueOrFail(
|
|
263
|
+
reader.node,
|
|
264
|
+
person.id,
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
await waitFor(() => {
|
|
268
|
+
expect(
|
|
269
|
+
expectMap(personOnReaderNode.core.getCurrentContent()).get("name"),
|
|
270
|
+
).toEqual("John Doe");
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
test.each(["writer", "reader", "writeOnly"] as const)(
|
|
276
|
+
"an admin should be able downgrade themselves to %s",
|
|
277
|
+
async (targetRole) => {
|
|
278
|
+
const admin = await setupTestAccount({
|
|
279
|
+
connected: true,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
const group = admin.node.createGroup();
|
|
283
|
+
|
|
284
|
+
const account = await loadCoValueOrFail(admin.node, admin.accountID);
|
|
285
|
+
|
|
286
|
+
// Downgrade self to target role
|
|
287
|
+
group.addMember(account, targetRole);
|
|
288
|
+
expect(group.roleOf(admin.accountID)).toEqual(targetRole);
|
|
289
|
+
},
|
|
290
|
+
);
|
|
285
291
|
|
|
286
292
|
test("an admin should be able downgrade a writeOnly to reader", async () => {
|
|
287
293
|
const admin = await setupTestAccount({
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
SyncMessagesLog,
|
|
10
10
|
TEST_NODE_CONFIG,
|
|
11
11
|
blockMessageTypeOnOutgoingPeer,
|
|
12
|
+
getSyncServerConnectedPeer,
|
|
12
13
|
loadCoValueOrFail,
|
|
13
14
|
setupTestAccount,
|
|
14
15
|
setupTestNode,
|
|
@@ -1034,4 +1035,55 @@ describe("loading coValues from server", () => {
|
|
|
1034
1035
|
|
|
1035
1036
|
vi.useRealTimers();
|
|
1036
1037
|
});
|
|
1038
|
+
|
|
1039
|
+
test("should not request dependencies if transaction verification is disabled", async () => {
|
|
1040
|
+
// Create a disconnected client
|
|
1041
|
+
const { node: client, accountID } = await setupTestAccount({
|
|
1042
|
+
connected: false,
|
|
1043
|
+
});
|
|
1044
|
+
const account = client.expectCurrentAccount(accountID);
|
|
1045
|
+
|
|
1046
|
+
// Prepare a group -- this will be a non-account dependency of a forthcoming map.
|
|
1047
|
+
const group = client.createGroup();
|
|
1048
|
+
group.addMember("everyone", "writer");
|
|
1049
|
+
|
|
1050
|
+
// Create a sync server and disable transaction verification
|
|
1051
|
+
const syncServer = await setupTestAccount({ isSyncServer: true });
|
|
1052
|
+
syncServer.node.syncManager.disableTransactionVerification();
|
|
1053
|
+
|
|
1054
|
+
// Connect the client, but don't setup syncing just yet...
|
|
1055
|
+
const { peer } = getSyncServerConnectedPeer({
|
|
1056
|
+
peerId: client.getCurrentAgent().id,
|
|
1057
|
+
syncServer: syncServer.node,
|
|
1058
|
+
});
|
|
1059
|
+
|
|
1060
|
+
// Disable reconciliation while we setup syncing because we don't want the
|
|
1061
|
+
// server to know about our forthcoming map's dependencies (group + account).
|
|
1062
|
+
const blocker = blockMessageTypeOnOutgoingPeer(peer, "load", {});
|
|
1063
|
+
client.syncManager.addPeer(peer);
|
|
1064
|
+
blocker.unblock();
|
|
1065
|
+
|
|
1066
|
+
// Create a map and set a value on it.
|
|
1067
|
+
// If transaction verification were enabled, this would trigger LOAD messages
|
|
1068
|
+
// from the server to the client asking for the group and account. However, we
|
|
1069
|
+
// don't expect to see those messages since we disabled transaction verification.
|
|
1070
|
+
const map = group.createMap();
|
|
1071
|
+
map.set("hello", "world");
|
|
1072
|
+
await map.core.waitForSync();
|
|
1073
|
+
|
|
1074
|
+
const syncMessages = SyncMessagesLog.getMessages({
|
|
1075
|
+
Account: account.core,
|
|
1076
|
+
Group: group.core,
|
|
1077
|
+
Map: map.core,
|
|
1078
|
+
});
|
|
1079
|
+
expect(
|
|
1080
|
+
syncMessages.some(
|
|
1081
|
+
(msg) => msg.includes("LOAD Account") || msg.includes("LOAD Group"),
|
|
1082
|
+
),
|
|
1083
|
+
).toBe(false);
|
|
1084
|
+
|
|
1085
|
+
// Verify the map is available on the server (transaction was accepted)
|
|
1086
|
+
const mapOnServerCore = await syncServer.node.loadCoValueCore(map.core.id);
|
|
1087
|
+
expect(mapOnServerCore.isAvailable()).toBe(true);
|
|
1088
|
+
});
|
|
1037
1089
|
});
|
package/src/tests/sync.test.ts
CHANGED
package/src/tests/testUtils.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
type AgentSecret,
|
|
13
13
|
type CoID,
|
|
14
14
|
type CoValueCore,
|
|
15
|
+
CryptoProvider,
|
|
15
16
|
type RawAccount,
|
|
16
17
|
type RawCoValue,
|
|
17
18
|
StorageAPI,
|
|
@@ -23,8 +24,15 @@ import type { Peer, SyncMessage } from "../sync.js";
|
|
|
23
24
|
import { expectGroup } from "../typeUtils/expectGroup.js";
|
|
24
25
|
import { toSimplifiedMessages } from "./messagesTestUtils.js";
|
|
25
26
|
import { createAsyncStorage, createSyncStorage } from "./testStorage.js";
|
|
27
|
+
import { PureJSCrypto } from "../crypto/PureJSCrypto.js";
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
let Crypto = await WasmCrypto.create();
|
|
30
|
+
|
|
31
|
+
export function setCurrentTestCryptoProvider(
|
|
32
|
+
crypto: WasmCrypto | PureJSCrypto,
|
|
33
|
+
) {
|
|
34
|
+
Crypto = crypto;
|
|
35
|
+
}
|
|
28
36
|
|
|
29
37
|
const syncServer: {
|
|
30
38
|
current: undefined | LocalNode;
|