cojson 0.10.15 → 0.11.0

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 (138) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +14 -0
  3. package/dist/CoValuesStore.d.ts +12 -0
  4. package/dist/CoValuesStore.d.ts.map +1 -0
  5. package/dist/PeerKnownStates.d.ts +38 -0
  6. package/dist/PeerKnownStates.d.ts.map +1 -0
  7. package/dist/PeerState.d.ts +46 -0
  8. package/dist/PeerState.d.ts.map +1 -0
  9. package/dist/PriorityBasedMessageQueue.d.ts +18 -0
  10. package/dist/PriorityBasedMessageQueue.d.ts.map +1 -0
  11. package/dist/SyncStateManager.d.ts +20 -0
  12. package/dist/SyncStateManager.d.ts.map +1 -0
  13. package/dist/base64url.d.ts +3 -0
  14. package/dist/base64url.d.ts.map +1 -0
  15. package/dist/base64url.test.d.ts +2 -0
  16. package/dist/base64url.test.d.ts.map +1 -0
  17. package/dist/coValue.d.ts +52 -0
  18. package/dist/coValue.d.ts.map +1 -0
  19. package/dist/coValueCore.d.ts +143 -0
  20. package/dist/coValueCore.d.ts.map +1 -0
  21. package/dist/coValueState.d.ts +58 -0
  22. package/dist/coValueState.d.ts.map +1 -0
  23. package/dist/coValues/account.d.ts +69 -0
  24. package/dist/coValues/account.d.ts.map +1 -0
  25. package/dist/coValues/coList.d.ts +163 -0
  26. package/dist/coValues/coList.d.ts.map +1 -0
  27. package/dist/coValues/coMap.d.ts +142 -0
  28. package/dist/coValues/coMap.d.ts.map +1 -0
  29. package/dist/coValues/coPlainText.d.ts +33 -0
  30. package/dist/coValues/coPlainText.d.ts.map +1 -0
  31. package/dist/coValues/coStream.d.ts +109 -0
  32. package/dist/coValues/coStream.d.ts.map +1 -0
  33. package/dist/coValues/group.d.ts +143 -0
  34. package/dist/coValues/group.d.ts.map +1 -0
  35. package/dist/coValues/group.js +51 -3
  36. package/dist/coValues/group.js.map +1 -1
  37. package/dist/coreToCoValue.d.ts +15 -0
  38. package/dist/coreToCoValue.d.ts.map +1 -0
  39. package/dist/crypto/PureJSCrypto.d.ts +50 -0
  40. package/dist/crypto/PureJSCrypto.d.ts.map +1 -0
  41. package/dist/crypto/WasmCrypto.d.ts +49 -0
  42. package/dist/crypto/WasmCrypto.d.ts.map +1 -0
  43. package/dist/crypto/crypto.d.ts +142 -0
  44. package/dist/crypto/crypto.d.ts.map +1 -0
  45. package/dist/exports.d.ts +84 -0
  46. package/dist/exports.d.ts.map +1 -0
  47. package/dist/ids.d.ts +23 -0
  48. package/dist/ids.d.ts.map +1 -0
  49. package/dist/index.d.ts +2 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/jsonStringify.d.ts +7 -0
  52. package/dist/jsonStringify.d.ts.map +1 -0
  53. package/dist/jsonValue.d.ts +45 -0
  54. package/dist/jsonValue.d.ts.map +1 -0
  55. package/dist/localNode.d.ts +111 -0
  56. package/dist/localNode.d.ts.map +1 -0
  57. package/dist/logger.d.ts +33 -0
  58. package/dist/logger.d.ts.map +1 -0
  59. package/dist/media.d.ts +8 -0
  60. package/dist/media.d.ts.map +1 -0
  61. package/dist/permissions.d.ts +24 -0
  62. package/dist/permissions.d.ts.map +1 -0
  63. package/dist/permissions.js +3 -4
  64. package/dist/permissions.js.map +1 -1
  65. package/dist/priority.d.ts +19 -0
  66. package/dist/priority.d.ts.map +1 -0
  67. package/dist/storage/FileSystem.d.ts +37 -0
  68. package/dist/storage/FileSystem.d.ts.map +1 -0
  69. package/dist/storage/chunksAndKnownStates.d.ts +7 -0
  70. package/dist/storage/chunksAndKnownStates.d.ts.map +1 -0
  71. package/dist/storage/index.d.ts +52 -0
  72. package/dist/storage/index.d.ts.map +1 -0
  73. package/dist/streamUtils.d.ts +13 -0
  74. package/dist/streamUtils.d.ts.map +1 -0
  75. package/dist/sync.d.ts +97 -0
  76. package/dist/sync.d.ts.map +1 -0
  77. package/dist/tests/PeerKnownStates.test.d.ts +2 -0
  78. package/dist/tests/PeerKnownStates.test.d.ts.map +1 -0
  79. package/dist/tests/PeerState.test.d.ts +2 -0
  80. package/dist/tests/PeerState.test.d.ts.map +1 -0
  81. package/dist/tests/PriorityBasedMessageQueue.test.d.ts +2 -0
  82. package/dist/tests/PriorityBasedMessageQueue.test.d.ts.map +1 -0
  83. package/dist/tests/SyncStateManager.test.d.ts +2 -0
  84. package/dist/tests/SyncStateManager.test.d.ts.map +1 -0
  85. package/dist/tests/account.test.d.ts +2 -0
  86. package/dist/tests/account.test.d.ts.map +1 -0
  87. package/dist/tests/coList.test.d.ts +2 -0
  88. package/dist/tests/coList.test.d.ts.map +1 -0
  89. package/dist/tests/coMap.test.d.ts +2 -0
  90. package/dist/tests/coMap.test.d.ts.map +1 -0
  91. package/dist/tests/coPlainText.test.d.ts +2 -0
  92. package/dist/tests/coPlainText.test.d.ts.map +1 -0
  93. package/dist/tests/coStream.test.d.ts +2 -0
  94. package/dist/tests/coStream.test.d.ts.map +1 -0
  95. package/dist/tests/coValueCore.test.d.ts +2 -0
  96. package/dist/tests/coValueCore.test.d.ts.map +1 -0
  97. package/dist/tests/coValueState.test.d.ts +2 -0
  98. package/dist/tests/coValueState.test.d.ts.map +1 -0
  99. package/dist/tests/crypto.test.d.ts +2 -0
  100. package/dist/tests/crypto.test.d.ts.map +1 -0
  101. package/dist/tests/cryptoImpl.test.d.ts +2 -0
  102. package/dist/tests/cryptoImpl.test.d.ts.map +1 -0
  103. package/dist/tests/group.test.d.ts +2 -0
  104. package/dist/tests/group.test.d.ts.map +1 -0
  105. package/dist/tests/group.test.js +130 -0
  106. package/dist/tests/group.test.js.map +1 -1
  107. package/dist/tests/logger.test.d.ts +2 -0
  108. package/dist/tests/logger.test.d.ts.map +1 -0
  109. package/dist/tests/permissions.test.d.ts +2 -0
  110. package/dist/tests/permissions.test.d.ts.map +1 -0
  111. package/dist/tests/permissions.test.js +194 -1
  112. package/dist/tests/permissions.test.js.map +1 -1
  113. package/dist/tests/priority.test.d.ts +2 -0
  114. package/dist/tests/priority.test.d.ts.map +1 -0
  115. package/dist/tests/sync.test.d.ts +2 -0
  116. package/dist/tests/sync.test.d.ts.map +1 -0
  117. package/dist/tests/testUtils.d.ts +142 -0
  118. package/dist/tests/testUtils.d.ts.map +1 -0
  119. package/dist/tests/testUtils.js +4 -1
  120. package/dist/tests/testUtils.js.map +1 -1
  121. package/dist/typeUtils/accountOrAgentIDfromSessionID.d.ts +4 -0
  122. package/dist/typeUtils/accountOrAgentIDfromSessionID.d.ts.map +1 -0
  123. package/dist/typeUtils/expectGroup.d.ts +4 -0
  124. package/dist/typeUtils/expectGroup.d.ts.map +1 -0
  125. package/dist/typeUtils/isAccountID.d.ts +4 -0
  126. package/dist/typeUtils/isAccountID.d.ts.map +1 -0
  127. package/dist/typeUtils/isCoValue.d.ts +4 -0
  128. package/dist/typeUtils/isCoValue.d.ts.map +1 -0
  129. package/dist/utils.d.ts +5 -0
  130. package/dist/utils.d.ts.map +1 -0
  131. package/package.json +6 -6
  132. package/src/coValues/group.ts +84 -9
  133. package/src/jsonValue.ts +9 -5
  134. package/src/permissions.ts +3 -4
  135. package/src/tests/group.test.ts +187 -0
  136. package/src/tests/permissions.test.ts +285 -0
  137. package/src/tests/testUtils.ts +4 -1
  138. package/tsconfig.json +3 -1
@@ -5,6 +5,7 @@ import { WasmCrypto } from "../crypto/WasmCrypto.js";
5
5
  import { expectGroup } from "../typeUtils/expectGroup.js";
6
6
  import {
7
7
  connectTwoPeers,
8
+ createThreeConnectedNodes,
8
9
  createTwoConnectedNodes,
9
10
  groupWithTwoAdmins,
10
11
  groupWithTwoAdminsHighLevel,
@@ -893,6 +894,26 @@ test("Admins can set group read key, make a private transaction in an owned obje
893
894
  expect(childContentAsReader.get("foo2")).toEqual("bar2");
894
895
  });
895
896
 
897
+ test("only admins can add agent ids", () => {
898
+ const { groupCore } = newGroup();
899
+
900
+ const inviteSecret = Crypto.newRandomAgentSecret();
901
+ const inviteID = Crypto.getAgentID(inviteSecret);
902
+
903
+ const groupAsInvite = expectGroup(
904
+ groupCore
905
+ .testWithDifferentAccount(
906
+ new ControlledAgent(inviteSecret, Crypto),
907
+ Crypto.newRandomSessionID(inviteID),
908
+ )
909
+ .getCurrentContent(),
910
+ );
911
+
912
+ groupAsInvite.set(inviteID, "adminInvite", "trusting");
913
+
914
+ expect(groupAsInvite.get(inviteID)).toEqual(undefined);
915
+ });
916
+
896
917
  test("Admins can set group read rey, make a private transaction in an owned object, rotate the read key, add two readers, rotate the read key again to kick out one reader, make another private transaction in the owned object, and only the remaining reader can read both transactions", () => {
897
918
  const { node, groupCore, admin } = newGroup();
898
919
 
@@ -2802,6 +2823,270 @@ test("Calling extend to create grand-child groups parent and child references an
2802
2823
  expect(childContentAsReader.get("foo")).toEqual("bar");
2803
2824
  });
2804
2825
 
2826
+ test("revoking access on a child group doesn't block access to that group if a more permissive role is inheritable", async () => {
2827
+ const { node1, node2 } = await createTwoConnectedNodes("server", "server");
2828
+
2829
+ const group = node1.node.createGroup();
2830
+ const parentGroup = node1.node.createGroup();
2831
+
2832
+ group.extend(parentGroup);
2833
+
2834
+ const randomUser = await loadCoValueOrFail(node1.node, node2.accountID);
2835
+
2836
+ parentGroup.addMember(randomUser, "writer");
2837
+ group.addMember(randomUser, "writer");
2838
+ await group.removeMember(randomUser);
2839
+
2840
+ const childMap = group.createMap();
2841
+
2842
+ childMap.set("foo", "bar", "private");
2843
+
2844
+ const mapOnNode2 = await loadCoValueOrFail(node2.node, childMap.id);
2845
+
2846
+ mapOnNode2.set("foo", "baz", "private");
2847
+
2848
+ expect(mapOnNode2.get("foo")).toEqual("baz");
2849
+ });
2850
+
2851
+ test("revoking access on a parent group doesn't block access to the child group if the same role is inheritable from a grand-parent group", async () => {
2852
+ const { node1, node2 } = await createTwoConnectedNodes("server", "server");
2853
+
2854
+ const group = node1.node.createGroup();
2855
+ const parentGroup = node1.node.createGroup();
2856
+ const grandParentGroup = node1.node.createGroup();
2857
+
2858
+ group.extend(parentGroup);
2859
+ parentGroup.extend(grandParentGroup);
2860
+
2861
+ const randomUser = await loadCoValueOrFail(node1.node, node2.accountID);
2862
+
2863
+ grandParentGroup.addMember(randomUser, "writer");
2864
+ parentGroup.addMember(randomUser, "writer");
2865
+ await parentGroup.removeMember(randomUser);
2866
+
2867
+ const childMap = group.createMap();
2868
+
2869
+ childMap.set("foo", "bar", "private");
2870
+
2871
+ const mapOnNode2 = await loadCoValueOrFail(node2.node, childMap.id);
2872
+
2873
+ mapOnNode2.set("foo", "baz", "private");
2874
+
2875
+ expect(mapOnNode2.get("foo")).toEqual("baz");
2876
+ });
2877
+
2878
+ test("revoking access on a parent group doesn't block access to the child group if the same role is inheritable from another parent group", async () => {
2879
+ const { node1, node2 } = await createTwoConnectedNodes("server", "server");
2880
+
2881
+ const group = node1.node.createGroup();
2882
+ const parentGroup1 = node1.node.createGroup();
2883
+ const parentGroup2 = node1.node.createGroup();
2884
+
2885
+ group.extend(parentGroup1);
2886
+ group.extend(parentGroup2);
2887
+
2888
+ const randomUser = await loadCoValueOrFail(node1.node, node2.accountID);
2889
+
2890
+ parentGroup1.addMember(randomUser, "writer");
2891
+ parentGroup2.addMember(randomUser, "writer");
2892
+ await parentGroup1.removeMember(randomUser);
2893
+
2894
+ const childMap = group.createMap();
2895
+
2896
+ childMap.set("foo", "bar", "private");
2897
+
2898
+ const mapOnNode2 = await loadCoValueOrFail(node2.node, childMap.id);
2899
+
2900
+ mapOnNode2.set("foo", "baz", "private");
2901
+
2902
+ expect(mapOnNode2.get("foo")).toEqual("baz");
2903
+ });
2904
+
2905
+ test("revoking write access to parent group", async () => {
2906
+ // Start with a node and a group
2907
+ const { group, node } = newGroupHighLevel();
2908
+
2909
+ // Create a parent group and relate it to the existing group
2910
+ const parentGroup = node.createGroup();
2911
+ group.extend(parentGroup);
2912
+
2913
+ // Create an account (`alice`) that can write to the parent group
2914
+ // Create an account (`bob`) that can write to the child group
2915
+ const alice = node.createAccount();
2916
+ const bob = node.createAccount();
2917
+ parentGroup.addMember(alice, "writer");
2918
+ group.addMember(bob, "writer");
2919
+
2920
+ // The child group has a map that can be written to by `bob`
2921
+ const mapCore = node.createCoValue({
2922
+ type: "comap",
2923
+ ruleset: { type: "ownedByGroup", group: group.id },
2924
+ meta: null,
2925
+ ...Crypto.createdNowUnique(),
2926
+ });
2927
+ const bobMap = expectMap(
2928
+ mapCore
2929
+ .testWithDifferentAccount(bob, Crypto.newRandomSessionID(bob.id))
2930
+ .getCurrentContent(),
2931
+ );
2932
+
2933
+ // `bob` sets `foo` to `bar`
2934
+ bobMap.set("foo", "bar", "private");
2935
+ // `bob`'s change is made successfully
2936
+ expect(bobMap.get("foo")).toEqual("bar");
2937
+
2938
+ const aliceMap = expectMap(
2939
+ mapCore
2940
+ .testWithDifferentAccount(alice, Crypto.newRandomSessionID(alice.id))
2941
+ .getCurrentContent(),
2942
+ );
2943
+ // `alice` sets `foo` to `baz`
2944
+ aliceMap.set("foo", "baz", "private");
2945
+ // `alice`'s change is made successfully
2946
+ expect(aliceMap.get("foo")).toEqual("baz");
2947
+
2948
+ // The two groups are no longer related
2949
+ await group.revokeExtend(parentGroup);
2950
+
2951
+ // `bob` sets `foo` to `abc`
2952
+ bobMap.set("foo", "abc", "private");
2953
+ // `bob`'s change is made successfully
2954
+ expect(bobMap.get("foo")).toEqual("abc");
2955
+
2956
+ const aliceMapAfterUnextend = expectMap(
2957
+ mapCore
2958
+ .testWithDifferentAccount(alice, Crypto.newRandomSessionID(alice.id))
2959
+ .getCurrentContent(),
2960
+ );
2961
+ // `alice` attempts to set `foo` to `def`, but fails
2962
+ expect(() => aliceMapAfterUnextend.set("foo", "def", "private")).toThrow(
2963
+ "Can't make transaction without read key secret",
2964
+ );
2965
+ // `alice`'s change is not made successfully
2966
+ expect(aliceMapAfterUnextend.get("foo")).not.toEqual("def");
2967
+ });
2968
+
2969
+ test("revoking read access to parent group", async () => {
2970
+ // Start with two nodes
2971
+ const { node1, node2 } = await createTwoConnectedNodes("server", "server");
2972
+ const group = node1.node.createGroup();
2973
+
2974
+ // Create a parent group and relate it to the existing group
2975
+ const parentGroup = node1.node.createGroup();
2976
+ group.extend(parentGroup);
2977
+
2978
+ // Create an account (`alice`) that can read from the parent group
2979
+ // Create an account (`bob`) that can write to the child group
2980
+ const alice = await loadCoValueOrFail(node1.node, node2.accountID);
2981
+ const bob = await loadCoValueOrFail(node1.node, node1.accountID);
2982
+ parentGroup.addMember(alice, "reader");
2983
+ group.addMember(bob, "writer");
2984
+
2985
+ // The child group has a map that can be written to by `bob`
2986
+ const bobMap = group.createMap();
2987
+
2988
+ // `bob` sets `foo` to `bar`
2989
+ bobMap.set("foo", "bar", "private");
2990
+ // `bob`'s change is made successfully
2991
+ expect(bobMap.get("foo")).toEqual("bar");
2992
+
2993
+ const aliceMap = await loadCoValueOrFail(node2.node, bobMap.id);
2994
+ // `alice` reads `foo` as `bar`
2995
+ expect(aliceMap.get("foo")).toEqual("bar");
2996
+
2997
+ // The two groups are no longer related
2998
+ await group.revokeExtend(parentGroup);
2999
+
3000
+ // `bob` sets `foo` to `abc`
3001
+ bobMap.set("foo", "abc", "private");
3002
+ // `bob`'s change is made successfully
3003
+ expect(bobMap.get("foo")).toEqual("abc");
3004
+
3005
+ // `alice` reads `foo` as `bar`
3006
+ expect(aliceMap.get("foo")).toEqual("bar");
3007
+ });
3008
+
3009
+ test("revoking read access to grandparent group", async () => {
3010
+ // Start with two nodes
3011
+ const { node1, node2, node3 } = await createThreeConnectedNodes(
3012
+ "server",
3013
+ "server",
3014
+ "server",
3015
+ );
3016
+ const group = node1.node.createGroup();
3017
+
3018
+ // Create group hierarchy
3019
+ const parentGroup = node1.node.createGroup();
3020
+ const grandParentGroup = node1.node.createGroup();
3021
+ group.extend(parentGroup);
3022
+ parentGroup.extend(grandParentGroup);
3023
+
3024
+ // Create an account (`alice`) that can read from the parent group
3025
+ // Create an account (`bob`) that can write to the child group
3026
+ // Create an account (`charlie`) that can read from the grandparent group
3027
+ const alice = await loadCoValueOrFail(node1.node, node2.accountID);
3028
+ const bob = await loadCoValueOrFail(node1.node, node1.accountID);
3029
+ const charlie = await loadCoValueOrFail(node1.node, node3.accountID);
3030
+ parentGroup.addMember(alice, "reader");
3031
+ group.addMember(bob, "writer");
3032
+ grandParentGroup.addMember(charlie, "reader");
3033
+
3034
+ // The child group has a map that can be written to by `bob`
3035
+ const bobMap = group.createMap();
3036
+
3037
+ // `bob` sets `foo` to `bar`
3038
+ bobMap.set("foo", "bar", "private");
3039
+ // `bob`'s change is made successfully
3040
+ expect(bobMap.get("foo")).toEqual("bar");
3041
+
3042
+ const aliceMap = await loadCoValueOrFail(node2.node, bobMap.id);
3043
+ // `alice` reads `foo` as `bar`
3044
+ expect(aliceMap.get("foo")).toEqual("bar");
3045
+
3046
+ const charlieMap = await loadCoValueOrFail(node3.node, bobMap.id);
3047
+ // `charlie` reads `foo` as `bar`
3048
+ expect(charlieMap.get("foo")).toEqual("bar");
3049
+
3050
+ // The groups are no longer related
3051
+ await parentGroup.revokeExtend(grandParentGroup);
3052
+ await group.revokeExtend(parentGroup);
3053
+
3054
+ // `bob` sets `foo` to `abc`
3055
+ bobMap.set("foo", "abc", "private");
3056
+ // `bob`'s change is made successfully
3057
+ expect(bobMap.get("foo")).toEqual("abc");
3058
+
3059
+ // `alice` reads `foo` as `bar`
3060
+ expect(aliceMap.get("foo")).toEqual("bar");
3061
+ // `charlie` reads `foo` as `bar`
3062
+ expect(charlieMap.get("foo")).toEqual("bar");
3063
+ });
3064
+
3065
+ test("a user should have write access if the parent group has everyone as a writer", async () => {
3066
+ const { node1, node2 } = await createTwoConnectedNodes("server", "server");
3067
+
3068
+ const group = node1.node.createGroup();
3069
+ const parentGroup = node1.node.createGroup();
3070
+
3071
+ group.extend(parentGroup);
3072
+
3073
+ parentGroup.addMember("everyone", "writer");
3074
+
3075
+ const randomUser = await loadCoValueOrFail(node1.node, node2.accountID);
3076
+
3077
+ group.addMember(randomUser, "reader");
3078
+
3079
+ const childMap = group.createMap();
3080
+
3081
+ childMap.set("foo", "bar", "private");
3082
+
3083
+ const mapOnNode2 = await loadCoValueOrFail(node2.node, childMap.id);
3084
+
3085
+ mapOnNode2.set("foo", "baz", "private");
3086
+
3087
+ expect(mapOnNode2.get("foo")).toEqual("baz");
3088
+ });
3089
+
2805
3090
  test("High-level permissions work correctly when a group is extended", async () => {
2806
3091
  const { group, node } = newGroupHighLevel();
2807
3092
  const parentGroup = node.createGroup();
@@ -5,7 +5,7 @@ import {
5
5
  MeterProvider,
6
6
  MetricReader,
7
7
  } from "@opentelemetry/sdk-metrics";
8
- import { expect, vi } from "vitest";
8
+ import { expect, onTestFinished, vi } from "vitest";
9
9
  import { ControlledAgent } from "../coValues/account.js";
10
10
  import { WasmCrypto } from "../crypto/WasmCrypto.js";
11
11
  import type { CoID, RawCoValue } from "../exports.js";
@@ -200,6 +200,9 @@ export function newGroupHighLevel() {
200
200
 
201
201
  const group = node.createGroup();
202
202
 
203
+ onTestFinished(() => {
204
+ node.gracefulShutdown();
205
+ });
203
206
  return { admin, node, group };
204
207
  }
205
208
 
package/tsconfig.json CHANGED
@@ -9,7 +9,9 @@
9
9
  "skipLibCheck": true,
10
10
  "forceConsistentCasingInFileNames": true,
11
11
  "noUncheckedIndexedAccess": true,
12
- "esModuleInterop": true
12
+ "esModuleInterop": true,
13
+ "declaration": true,
14
+ "declarationMap": true
13
15
  },
14
16
  "include": ["./src/**/*.ts"],
15
17
  "exclude": ["./node_modules"]