cojson 0.0.11 → 0.0.13

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 (75) hide show
  1. package/README.md +2 -2
  2. package/dist/account.d.ts +57 -0
  3. package/dist/account.js +76 -0
  4. package/dist/account.js.map +1 -0
  5. package/dist/account.test.d.ts +1 -0
  6. package/dist/account.test.js +40 -0
  7. package/dist/account.test.js.map +1 -0
  8. package/dist/coValue.d.ts +17 -36
  9. package/dist/coValue.js +53 -117
  10. package/dist/coValue.js.map +1 -1
  11. package/dist/coValue.test.js +16 -16
  12. package/dist/coValue.test.js.map +1 -1
  13. package/dist/contentType.d.ts +9 -9
  14. package/dist/contentType.js.map +1 -1
  15. package/dist/contentType.test.js +13 -17
  16. package/dist/contentType.test.js.map +1 -1
  17. package/dist/contentTypes/coList.d.ts +3 -3
  18. package/dist/contentTypes/coList.js.map +1 -1
  19. package/dist/contentTypes/coMap.d.ts +31 -21
  20. package/dist/contentTypes/coMap.js +28 -0
  21. package/dist/contentTypes/coMap.js.map +1 -1
  22. package/dist/contentTypes/coStream.d.ts +3 -3
  23. package/dist/contentTypes/coStream.js.map +1 -1
  24. package/dist/contentTypes/static.d.ts +4 -4
  25. package/dist/contentTypes/static.js.map +1 -1
  26. package/dist/crypto.d.ts +45 -39
  27. package/dist/crypto.js +68 -49
  28. package/dist/crypto.js.map +1 -1
  29. package/dist/crypto.test.js +45 -49
  30. package/dist/crypto.test.js.map +1 -1
  31. package/dist/ids.d.ts +5 -3
  32. package/dist/ids.js +3 -1
  33. package/dist/ids.js.map +1 -1
  34. package/dist/index.d.ts +12 -14
  35. package/dist/index.js +6 -8
  36. package/dist/index.js.map +1 -1
  37. package/dist/jsonValue.d.ts +2 -2
  38. package/dist/node.d.ts +25 -15
  39. package/dist/node.js +88 -33
  40. package/dist/node.js.map +1 -1
  41. package/dist/permissions.d.ts +27 -33
  42. package/dist/permissions.js +55 -47
  43. package/dist/permissions.js.map +1 -1
  44. package/dist/permissions.test.js +231 -314
  45. package/dist/permissions.test.js.map +1 -1
  46. package/dist/sync.d.ts +27 -30
  47. package/dist/sync.js +68 -64
  48. package/dist/sync.js.map +1 -1
  49. package/dist/sync.test.js +181 -305
  50. package/dist/sync.test.js.map +1 -1
  51. package/dist/testUtils.d.ts +37 -0
  52. package/dist/testUtils.js +157 -0
  53. package/dist/testUtils.js.map +1 -0
  54. package/package.json +1 -1
  55. package/src/account.test.ts +67 -0
  56. package/src/account.ts +152 -0
  57. package/src/coValue.test.ts +17 -31
  58. package/src/coValue.ts +98 -185
  59. package/src/contentType.test.ts +18 -45
  60. package/src/contentType.ts +15 -13
  61. package/src/contentTypes/coList.ts +4 -4
  62. package/src/contentTypes/coMap.ts +55 -29
  63. package/src/contentTypes/coStream.ts +4 -4
  64. package/src/contentTypes/static.ts +5 -5
  65. package/src/crypto.test.ts +53 -59
  66. package/src/crypto.ts +123 -95
  67. package/src/ids.ts +9 -3
  68. package/src/index.ts +14 -25
  69. package/src/jsonValue.ts +2 -2
  70. package/src/node.ts +189 -61
  71. package/src/permissions.test.ts +370 -404
  72. package/src/permissions.ts +126 -109
  73. package/src/sync.test.ts +262 -440
  74. package/src/sync.ts +96 -101
  75. package/src/testUtils.ts +229 -0
@@ -1,25 +1,17 @@
1
- import {
2
- Transaction,
3
- getAgent,
4
- getAgentID,
5
- newRandomAgentCredential,
6
- newRandomSessionID,
7
- } from './coValue.js';
8
- import { LocalNode } from './node.js';
9
- import { createdNowUnique, sign } from './crypto.js';
1
+ import { Transaction } from "./coValue.js";
2
+ import { LocalNode } from "./node.js";
3
+ import { createdNowUnique, getAgentSignerSecret, newRandomAgentSecret, sign } from "./crypto.js";
4
+ import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
10
5
 
11
6
  test("Can create coValue with new agent credentials and add transaction to it", () => {
12
- const agentCredential = newRandomAgentCredential("agent1");
13
- const node = new LocalNode(
14
- agentCredential,
15
- newRandomSessionID(getAgentID(getAgent(agentCredential)))
16
- );
7
+ const [account, sessionID] = randomAnonymousAccountAndSessionID();
8
+ const node = new LocalNode(account, sessionID);
17
9
 
18
10
  const coValue = node.createCoValue({
19
11
  type: "costream",
20
12
  ruleset: { type: "unsafeAllowAll" },
21
13
  meta: null,
22
- ...createdNowUnique()
14
+ ...createdNowUnique(),
23
15
  });
24
16
 
25
17
  const transaction: Transaction = {
@@ -42,24 +34,21 @@ test("Can create coValue with new agent credentials and add transaction to it",
42
34
  node.ownSessionID,
43
35
  [transaction],
44
36
  expectedNewHash,
45
- sign(agentCredential.signatorySecret, expectedNewHash)
37
+ sign(account.currentSignerSecret(), expectedNewHash)
46
38
  )
47
39
  ).toBe(true);
48
40
  });
49
41
 
50
42
  test("transactions with wrong signature are rejected", () => {
51
- const wrongAgent = newRandomAgentCredential("wrongAgent");
52
- const agentCredential = newRandomAgentCredential("agent1");
53
- const node = new LocalNode(
54
- agentCredential,
55
- newRandomSessionID(getAgentID(getAgent(agentCredential)))
56
- );
43
+ const wrongAgent = newRandomAgentSecret();
44
+ const [agentSecret, sessionID] = randomAnonymousAccountAndSessionID();
45
+ const node = new LocalNode(agentSecret, sessionID);
57
46
 
58
47
  const coValue = node.createCoValue({
59
48
  type: "costream",
60
49
  ruleset: { type: "unsafeAllowAll" },
61
50
  meta: null,
62
- ...createdNowUnique()
51
+ ...createdNowUnique(),
63
52
  });
64
53
 
65
54
  const transaction: Transaction = {
@@ -82,23 +71,20 @@ test("transactions with wrong signature are rejected", () => {
82
71
  node.ownSessionID,
83
72
  [transaction],
84
73
  expectedNewHash,
85
- sign(wrongAgent.signatorySecret, expectedNewHash)
74
+ sign(getAgentSignerSecret(wrongAgent), expectedNewHash)
86
75
  )
87
76
  ).toBe(false);
88
77
  });
89
78
 
90
79
  test("transactions with correctly signed, but wrong hash are rejected", () => {
91
- const agentCredential = newRandomAgentCredential("agent1");
92
- const node = new LocalNode(
93
- agentCredential,
94
- newRandomSessionID(getAgentID(getAgent(agentCredential)))
95
- );
80
+ const [account, sessionID] = randomAnonymousAccountAndSessionID();
81
+ const node = new LocalNode(account, sessionID);
96
82
 
97
83
  const coValue = node.createCoValue({
98
84
  type: "costream",
99
85
  ruleset: { type: "unsafeAllowAll" },
100
86
  meta: null,
101
- ...createdNowUnique()
87
+ ...createdNowUnique(),
102
88
  });
103
89
 
104
90
  const transaction: Transaction = {
@@ -131,7 +117,7 @@ test("transactions with correctly signed, but wrong hash are rejected", () => {
131
117
  node.ownSessionID,
132
118
  [transaction],
133
119
  expectedNewHash,
134
- sign(agentCredential.signatorySecret, expectedNewHash)
120
+ sign(account.currentSignerSecret(), expectedNewHash)
135
121
  )
136
122
  ).toBe(false);
137
123
  });
package/src/coValue.ts CHANGED
@@ -1,74 +1,65 @@
1
1
  import { randomBytes } from "@noble/hashes/utils";
2
- import { ContentType } from './contentType.js';
3
- import { Static } from './contentTypes/static.js';
4
- import { CoStream } from './contentTypes/coStream.js';
5
- import { CoMap } from './contentTypes/coMap.js';
2
+ import { ContentType } from "./contentType.js";
3
+ import { Static } from "./contentTypes/static.js";
4
+ import { CoStream } from "./contentTypes/coStream.js";
5
+ import { CoMap } from "./contentTypes/coMap.js";
6
6
  import {
7
7
  Encrypted,
8
8
  Hash,
9
9
  KeySecret,
10
- RecipientID,
11
- RecipientSecret,
12
- SignatoryID,
13
- SignatorySecret,
14
10
  Signature,
15
11
  StreamingHash,
16
- getRecipientID,
17
- getSignatoryID,
18
- newRandomRecipient,
19
- newRandomSignatory,
20
- openAs,
12
+ unseal,
21
13
  shortHash,
22
14
  sign,
23
15
  verify,
24
16
  encryptForTransaction,
25
17
  decryptForTransaction,
26
18
  KeyID,
27
- unsealKeySecret,
28
- signatorySecretToBytes,
29
- recipientSecretToBytes,
30
- signatorySecretFromBytes,
31
- recipientSecretFromBytes,
32
- } from './crypto.js';
33
- import { JsonValue } from './jsonValue.js';
19
+ decryptKeySecret,
20
+ getAgentSignerID,
21
+ getAgentSealerID,
22
+ } from "./crypto.js";
23
+ import { JsonObject, JsonValue } from "./jsonValue.js";
34
24
  import { base58 } from "@scure/base";
35
25
  import {
36
26
  PermissionsDef as RulesetDef,
37
27
  Team,
38
28
  determineValidTransactions,
39
29
  expectTeamContent,
40
- } from './permissions.js';
41
- import { LocalNode } from './node.js';
42
- import { CoValueKnownState, NewContentMessage } from './sync.js';
43
- import { AgentID, RawCoValueID, SessionID, TransactionID } from './ids.js';
44
- import { CoList } from './contentTypes/coList.js';
30
+ isKeyForKeyField,
31
+ } from "./permissions.js";
32
+ import { LocalNode } from "./node.js";
33
+ import { CoValueKnownState, NewContentMessage } from "./sync.js";
34
+ import { RawCoID, SessionID, TransactionID } from "./ids.js";
35
+ import { CoList } from "./contentTypes/coList.js";
36
+ import {
37
+ AccountID,
38
+ AccountIDOrAgentID,
39
+ GeneralizedControlledAccount,
40
+ } from "./account.js";
45
41
 
46
42
  export type CoValueHeader = {
47
43
  type: ContentType["type"];
48
44
  ruleset: RulesetDef;
49
- meta: JsonValue;
45
+ meta: JsonObject | null;
50
46
  createdAt: `2${string}` | null;
51
47
  uniqueness: `z${string}` | null;
52
- publicNickname?: string;
53
48
  };
54
49
 
55
- function coValueIDforHeader(header: CoValueHeader): RawCoValueID {
50
+ export function idforHeader(header: CoValueHeader): RawCoID {
56
51
  const hash = shortHash(header);
57
- if (header.publicNickname) {
58
- return `co_${header.publicNickname}_z${hash.slice(
59
- "shortHash_z".length
60
- )}`;
61
- } else {
62
- return `co_z${hash.slice("shortHash_z".length)}`;
63
- }
52
+ return `co_z${hash.slice("shortHash_z".length)}`;
64
53
  }
65
54
 
66
- export function agentIDfromSessionID(sessionID: SessionID): AgentID {
67
- return sessionID.split("_session")[0] as AgentID;
55
+ export function accountOrAgentIDfromSessionID(
56
+ sessionID: SessionID
57
+ ): AccountIDOrAgentID {
58
+ return sessionID.split("_session")[0] as AccountIDOrAgentID;
68
59
  }
69
60
 
70
- export function newRandomSessionID(agentID: AgentID): SessionID {
71
- return `${agentID}_session_z${base58.encode(randomBytes(8))}`;
61
+ export function newRandomSessionID(accountID: AccountIDOrAgentID): SessionID {
62
+ return `${accountID}_session_z${base58.encode(randomBytes(8))}`;
72
63
  }
73
64
 
74
65
  type SessionLog = {
@@ -84,7 +75,7 @@ export type PrivateTransaction = {
84
75
  keyUsed: KeyID;
85
76
  encryptedChanges: Encrypted<
86
77
  JsonValue[],
87
- { in: RawCoValueID; tx: TransactionID }
78
+ { in: RawCoID; tx: TransactionID }
88
79
  >;
89
80
  };
90
81
 
@@ -103,7 +94,7 @@ export type DecryptedTransaction = {
103
94
  };
104
95
 
105
96
  export class CoValue {
106
- id: RawCoValueID;
97
+ id: RawCoID;
107
98
  node: LocalNode;
108
99
  header: CoValueHeader;
109
100
  sessions: { [key: SessionID]: SessionLog };
@@ -111,18 +102,18 @@ export class CoValue {
111
102
  listeners: Set<(content?: ContentType) => void> = new Set();
112
103
 
113
104
  constructor(header: CoValueHeader, node: LocalNode) {
114
- this.id = coValueIDforHeader(header);
105
+ this.id = idforHeader(header);
115
106
  this.header = header;
116
107
  this.sessions = {};
117
108
  this.node = node;
118
109
  }
119
110
 
120
- testWithDifferentCredentials(
121
- agentCredential: AgentCredential,
111
+ testWithDifferentAccount(
112
+ account: GeneralizedControlledAccount,
122
113
  ownSessionID: SessionID
123
114
  ): CoValue {
124
- const newNode = this.node.testWithDifferentCredentials(
125
- agentCredential,
115
+ const newNode = this.node.testWithDifferentAccount(
116
+ account,
126
117
  ownSessionID
127
118
  );
128
119
 
@@ -131,7 +122,7 @@ export class CoValue {
131
122
 
132
123
  knownState(): CoValueKnownState {
133
124
  return {
134
- coValueID: this.id,
125
+ id: this.id,
135
126
  header: true,
136
127
  sessions: Object.fromEntries(
137
128
  Object.entries(this.sessions).map(([k, v]) => [
@@ -157,16 +148,21 @@ export class CoValue {
157
148
  tryAddTransactions(
158
149
  sessionID: SessionID,
159
150
  newTransactions: Transaction[],
160
- newHash: Hash,
151
+ givenExpectedNewHash: Hash | undefined,
161
152
  newSignature: Signature
162
153
  ): boolean {
163
- const signatoryID = this.node.expectAgentLoaded(
164
- agentIDfromSessionID(sessionID),
165
- "Expected to know signatory of transaction"
166
- ).signatoryID;
154
+ const signerID = getAgentSignerID(
155
+ this.node.resolveAccountAgent(
156
+ accountOrAgentIDfromSessionID(sessionID),
157
+ "Expected to know signer of transaction"
158
+ )
159
+ );
167
160
 
168
- if (!signatoryID) {
169
- console.warn("Unknown agent", agentIDfromSessionID(sessionID));
161
+ if (!signerID) {
162
+ console.warn(
163
+ "Unknown agent",
164
+ accountOrAgentIDfromSessionID(sessionID)
165
+ );
170
166
  return false;
171
167
  }
172
168
 
@@ -175,17 +171,17 @@ export class CoValue {
175
171
  newTransactions
176
172
  );
177
173
 
178
- if (newHash !== expectedNewHash) {
179
- console.warn("Invalid hash", { newHash, expectedNewHash });
174
+ if (givenExpectedNewHash && givenExpectedNewHash !== expectedNewHash) {
175
+ console.warn("Invalid hash", { expectedNewHash, givenExpectedNewHash });
180
176
  return false;
181
177
  }
182
178
 
183
- if (!verify(newSignature, newHash, signatoryID)) {
179
+ if (!verify(newSignature, expectedNewHash, signerID)) {
184
180
  console.warn(
185
181
  "Invalid signature",
186
182
  newSignature,
187
- newHash,
188
- signatoryID
183
+ expectedNewHash,
184
+ signerID
189
185
  );
190
186
  return false;
191
187
  }
@@ -196,7 +192,7 @@ export class CoValue {
196
192
 
197
193
  this.sessions[sessionID] = {
198
194
  transactions,
199
- lastHash: newHash,
195
+ lastHash: expectedNewHash,
200
196
  streamingHash: newStreamingHash,
201
197
  lastSignature: newSignature,
202
198
  };
@@ -281,7 +277,7 @@ export class CoValue {
281
277
  ]);
282
278
 
283
279
  const signature = sign(
284
- this.node.agentCredential.signatorySecret,
280
+ this.node.account.currentSignerSecret(),
285
281
  expectedNewHash
286
282
  );
287
283
 
@@ -374,7 +370,7 @@ export class CoValue {
374
370
  if (this.header.ruleset.type === "team") {
375
371
  const content = expectTeamContent(this.getCurrentContent());
376
372
 
377
- const currentKeyId = content.get("readKey")?.keyID;
373
+ const currentKeyId = content.get("readKey");
378
374
 
379
375
  if (!currentKeyId) {
380
376
  throw new Error("No readKey set");
@@ -401,61 +397,63 @@ export class CoValue {
401
397
  if (this.header.ruleset.type === "team") {
402
398
  const content = expectTeamContent(this.getCurrentContent());
403
399
 
404
- const readKeyHistory = content.getHistory("readKey");
400
+ // Try to find key revelation for us
405
401
 
406
- // Try to find direct relevation of key for us
402
+ const readKeyEntry = content.getLastEntry(`${keyID}_for_${this.node.account.id}`);
407
403
 
408
- for (const entry of readKeyHistory) {
409
- if (entry.value?.keyID === keyID) {
410
- const revealer = agentIDfromSessionID(entry.txID.sessionID);
411
- const revealerAgent = this.node.expectAgentLoaded(
412
- revealer,
413
- "Expected to know revealer"
414
- );
404
+ if (readKeyEntry) {
405
+ const revealer = accountOrAgentIDfromSessionID(
406
+ readKeyEntry.txID.sessionID
407
+ );
408
+ const revealerAgent = this.node.resolveAccountAgent(
409
+ revealer,
410
+ "Expected to know revealer"
411
+ );
415
412
 
416
- const secret = openAs(
417
- entry.value.revelation,
418
- this.node.agentCredential.recipientSecret,
419
- revealerAgent.recipientID,
420
- {
421
- in: this.id,
422
- tx: entry.txID,
423
- }
424
- );
413
+ const secret = unseal(
414
+ readKeyEntry.value,
415
+ this.node.account.currentSealerSecret(),
416
+ getAgentSealerID(revealerAgent),
417
+ {
418
+ in: this.id,
419
+ tx: readKeyEntry.txID,
420
+ }
421
+ );
425
422
 
426
- if (secret) return secret as KeySecret;
427
- }
423
+ if (secret) return secret as KeySecret;
428
424
  }
429
425
 
430
426
  // Try to find indirect revelation through previousKeys
431
427
 
432
- for (const entry of readKeyHistory) {
433
- const encryptedPreviousKey = entry.value?.previousKeys?.[keyID];
434
- if (entry.value && encryptedPreviousKey) {
435
- const sealingKeyID = entry.value.keyID;
436
- const sealingKeySecret = this.getReadKey(sealingKeyID);
428
+ for (const field of content.keys()) {
429
+ if (isKeyForKeyField(field) && field.startsWith(keyID)) {
430
+ const encryptingKeyID = field.split("_for_")[1] as KeyID;
431
+ const encryptingKeySecret = this.getReadKey(encryptingKeyID);
437
432
 
438
- if (!sealingKeySecret) {
433
+ if (!encryptingKeySecret) {
439
434
  continue;
440
435
  }
441
436
 
442
- const secret = unsealKeySecret(
437
+ const encryptedPreviousKey = content.get(field)!;
438
+
439
+ const secret = decryptKeySecret(
443
440
  {
444
- sealed: keyID,
445
- sealing: sealingKeyID,
441
+ encryptedID: keyID,
442
+ encryptingID: encryptingKeyID,
446
443
  encrypted: encryptedPreviousKey,
447
444
  },
448
- sealingKeySecret
445
+ encryptingKeySecret
449
446
  );
450
447
 
451
448
  if (secret) {
452
449
  return secret;
453
450
  } else {
454
451
  console.error(
455
- `Sealing ${sealingKeyID} key didn't unseal ${keyID}`
452
+ `Encrypting ${encryptingKeyID} key didn't decrypt ${keyID}`
456
453
  );
457
454
  }
458
455
  }
456
+
459
457
  }
460
458
 
461
459
  return undefined;
@@ -493,10 +491,10 @@ export class CoValue {
493
491
  knownState: CoValueKnownState | undefined
494
492
  ): NewContentMessage | undefined {
495
493
  const newContent: NewContentMessage = {
496
- action: "newContent",
497
- coValueID: this.id,
494
+ action: "content",
495
+ id: this.id,
498
496
  header: knownState?.header ? undefined : this.header,
499
- newContent: Object.fromEntries(
497
+ new: Object.fromEntries(
500
498
  Object.entries(this.sessions)
501
499
  .map(([sessionID, log]) => {
502
500
  const newTransactions = log.transactions.slice(
@@ -519,7 +517,6 @@ export class CoValue {
519
517
  sessionID as SessionID
520
518
  ] || 0,
521
519
  newTransactions,
522
- lastHash: log.lastHash,
523
520
  lastSignature: log.lastSignature,
524
521
  },
525
522
  ];
@@ -530,7 +527,7 @@ export class CoValue {
530
527
 
531
528
  if (
532
529
  !newContent.header &&
533
- Object.keys(newContent.newContent).length === 0
530
+ Object.keys(newContent.new).length === 0
534
531
  ) {
535
532
  return undefined;
536
533
  }
@@ -538,97 +535,13 @@ export class CoValue {
538
535
  return newContent;
539
536
  }
540
537
 
541
- getDependedOnCoValues(): RawCoValueID[] {
538
+ getDependedOnCoValues(): RawCoID[] {
542
539
  return this.header.ruleset.type === "team"
543
540
  ? expectTeamContent(this.getCurrentContent())
544
541
  .keys()
545
- .filter((k): k is AgentID => k.startsWith("co_agent"))
542
+ .filter((k): k is AccountID => k.startsWith("co_"))
546
543
  : this.header.ruleset.type === "ownedByTeam"
547
544
  ? [this.header.ruleset.team]
548
545
  : [];
549
546
  }
550
- }
551
-
552
- export type Agent = {
553
- signatoryID: SignatoryID;
554
- recipientID: RecipientID;
555
- publicNickname?: string;
556
- };
557
-
558
- export function getAgent(agentCredential: AgentCredential) {
559
- return {
560
- signatoryID: getSignatoryID(agentCredential.signatorySecret),
561
- recipientID: getRecipientID(agentCredential.recipientSecret),
562
- publicNickname: agentCredential.publicNickname,
563
- };
564
- }
565
-
566
- export function getAgentCoValueHeader(agent: Agent): CoValueHeader {
567
- return {
568
- type: "comap",
569
- ruleset: {
570
- type: "agent",
571
- initialSignatoryID: agent.signatoryID,
572
- initialRecipientID: agent.recipientID,
573
- },
574
- meta: null,
575
- createdAt: null,
576
- uniqueness: null,
577
- publicNickname:
578
- "agent" + (agent.publicNickname ? `-${agent.publicNickname}` : ""),
579
- };
580
- }
581
-
582
- export function getAgentID(agent: Agent): AgentID {
583
- return coValueIDforHeader(getAgentCoValueHeader(agent)) as AgentID;
584
- }
585
-
586
- export type AgentCredential = {
587
- signatorySecret: SignatorySecret;
588
- recipientSecret: RecipientSecret;
589
- publicNickname?: string;
590
- };
591
-
592
- export function newRandomAgentCredential(
593
- publicNickname?: string
594
- ): AgentCredential {
595
- const signatorySecret = newRandomSignatory();
596
- const recipientSecret = newRandomRecipient();
597
- return { signatorySecret, recipientSecret, publicNickname };
598
- }
599
-
600
- export function agentCredentialToBytes(cred: AgentCredential): Uint8Array {
601
- if (cred.publicNickname) {
602
- throw new Error("Can't convert agent credential with publicNickname");
603
- }
604
- const bytes = new Uint8Array(64);
605
- const signatorySecretBytes = signatorySecretToBytes(cred.signatorySecret);
606
- if (signatorySecretBytes.length !== 32) {
607
- throw new Error("Invalid signatorySecret length");
608
- }
609
- bytes.set(signatorySecretBytes);
610
- const recipientSecretBytes = recipientSecretToBytes(cred.recipientSecret);
611
- if (recipientSecretBytes.length !== 32) {
612
- throw new Error("Invalid recipientSecret length");
613
- }
614
- bytes.set(recipientSecretBytes, 32);
615
-
616
- return bytes;
617
- }
618
-
619
- export function agentCredentialFromBytes(
620
- bytes: Uint8Array
621
- ): AgentCredential | undefined {
622
- if (bytes.length !== 64) {
623
- return undefined;
624
- }
625
-
626
- const signatorySecret = signatorySecretFromBytes(bytes.slice(0, 32));
627
- const recipientSecret = recipientSecretFromBytes(bytes.slice(32));
628
-
629
- return { signatorySecret, recipientSecret };
630
- }
631
-
632
- // type Role = "admin" | "writer" | "reader";
633
-
634
- // type PermissionsDef = CJMap<AgentID, Role, {[agent: AgentID]: Role}>;
547
+ }