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.
- package/README.md +2 -2
- package/dist/account.d.ts +57 -0
- package/dist/account.js +76 -0
- package/dist/account.js.map +1 -0
- package/dist/account.test.d.ts +1 -0
- package/dist/account.test.js +40 -0
- package/dist/account.test.js.map +1 -0
- package/dist/coValue.d.ts +17 -36
- package/dist/coValue.js +53 -117
- package/dist/coValue.js.map +1 -1
- package/dist/coValue.test.js +16 -16
- package/dist/coValue.test.js.map +1 -1
- package/dist/contentType.d.ts +9 -9
- package/dist/contentType.js.map +1 -1
- package/dist/contentType.test.js +13 -17
- package/dist/contentType.test.js.map +1 -1
- package/dist/contentTypes/coList.d.ts +3 -3
- package/dist/contentTypes/coList.js.map +1 -1
- package/dist/contentTypes/coMap.d.ts +31 -21
- package/dist/contentTypes/coMap.js +28 -0
- package/dist/contentTypes/coMap.js.map +1 -1
- package/dist/contentTypes/coStream.d.ts +3 -3
- package/dist/contentTypes/coStream.js.map +1 -1
- package/dist/contentTypes/static.d.ts +4 -4
- package/dist/contentTypes/static.js.map +1 -1
- package/dist/crypto.d.ts +45 -39
- package/dist/crypto.js +68 -49
- package/dist/crypto.js.map +1 -1
- package/dist/crypto.test.js +45 -49
- package/dist/crypto.test.js.map +1 -1
- package/dist/ids.d.ts +5 -3
- package/dist/ids.js +3 -1
- package/dist/ids.js.map +1 -1
- package/dist/index.d.ts +12 -14
- package/dist/index.js +6 -8
- package/dist/index.js.map +1 -1
- package/dist/jsonValue.d.ts +2 -2
- package/dist/node.d.ts +25 -15
- package/dist/node.js +88 -33
- package/dist/node.js.map +1 -1
- package/dist/permissions.d.ts +27 -33
- package/dist/permissions.js +55 -47
- package/dist/permissions.js.map +1 -1
- package/dist/permissions.test.js +231 -314
- package/dist/permissions.test.js.map +1 -1
- package/dist/sync.d.ts +27 -30
- package/dist/sync.js +68 -64
- package/dist/sync.js.map +1 -1
- package/dist/sync.test.js +181 -305
- package/dist/sync.test.js.map +1 -1
- package/dist/testUtils.d.ts +37 -0
- package/dist/testUtils.js +157 -0
- package/dist/testUtils.js.map +1 -0
- package/package.json +1 -1
- package/src/account.test.ts +67 -0
- package/src/account.ts +152 -0
- package/src/coValue.test.ts +17 -31
- package/src/coValue.ts +98 -185
- package/src/contentType.test.ts +18 -45
- package/src/contentType.ts +15 -13
- package/src/contentTypes/coList.ts +4 -4
- package/src/contentTypes/coMap.ts +55 -29
- package/src/contentTypes/coStream.ts +4 -4
- package/src/contentTypes/static.ts +5 -5
- package/src/crypto.test.ts +53 -59
- package/src/crypto.ts +123 -95
- package/src/ids.ts +9 -3
- package/src/index.ts +14 -25
- package/src/jsonValue.ts +2 -2
- package/src/node.ts +189 -61
- package/src/permissions.test.ts +370 -404
- package/src/permissions.ts +126 -109
- package/src/sync.test.ts +262 -440
- package/src/sync.ts +96 -101
- package/src/testUtils.ts +229 -0
package/src/coValue.test.ts
CHANGED
|
@@ -1,25 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
|
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(
|
|
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 =
|
|
52
|
-
const
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
3
|
-
import { Static } from
|
|
4
|
-
import { CoStream } from
|
|
5
|
-
import { CoMap } from
|
|
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
|
-
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
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:
|
|
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
|
|
50
|
+
export function idforHeader(header: CoValueHeader): RawCoID {
|
|
56
51
|
const hash = shortHash(header);
|
|
57
|
-
|
|
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
|
|
67
|
-
|
|
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(
|
|
71
|
-
return `${
|
|
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:
|
|
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:
|
|
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 =
|
|
105
|
+
this.id = idforHeader(header);
|
|
115
106
|
this.header = header;
|
|
116
107
|
this.sessions = {};
|
|
117
108
|
this.node = node;
|
|
118
109
|
}
|
|
119
110
|
|
|
120
|
-
|
|
121
|
-
|
|
111
|
+
testWithDifferentAccount(
|
|
112
|
+
account: GeneralizedControlledAccount,
|
|
122
113
|
ownSessionID: SessionID
|
|
123
114
|
): CoValue {
|
|
124
|
-
const newNode = this.node.
|
|
125
|
-
|
|
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
|
-
|
|
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
|
-
|
|
151
|
+
givenExpectedNewHash: Hash | undefined,
|
|
161
152
|
newSignature: Signature
|
|
162
153
|
): boolean {
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
154
|
+
const signerID = getAgentSignerID(
|
|
155
|
+
this.node.resolveAccountAgent(
|
|
156
|
+
accountOrAgentIDfromSessionID(sessionID),
|
|
157
|
+
"Expected to know signer of transaction"
|
|
158
|
+
)
|
|
159
|
+
);
|
|
167
160
|
|
|
168
|
-
if (!
|
|
169
|
-
console.warn(
|
|
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 (
|
|
179
|
-
console.warn("Invalid hash", {
|
|
174
|
+
if (givenExpectedNewHash && givenExpectedNewHash !== expectedNewHash) {
|
|
175
|
+
console.warn("Invalid hash", { expectedNewHash, givenExpectedNewHash });
|
|
180
176
|
return false;
|
|
181
177
|
}
|
|
182
178
|
|
|
183
|
-
if (!verify(newSignature,
|
|
179
|
+
if (!verify(newSignature, expectedNewHash, signerID)) {
|
|
184
180
|
console.warn(
|
|
185
181
|
"Invalid signature",
|
|
186
182
|
newSignature,
|
|
187
|
-
|
|
188
|
-
|
|
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:
|
|
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.
|
|
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")
|
|
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
|
-
|
|
400
|
+
// Try to find key revelation for us
|
|
405
401
|
|
|
406
|
-
|
|
402
|
+
const readKeyEntry = content.getLastEntry(`${keyID}_for_${this.node.account.id}`);
|
|
407
403
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
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
|
-
|
|
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
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
const
|
|
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 (!
|
|
433
|
+
if (!encryptingKeySecret) {
|
|
439
434
|
continue;
|
|
440
435
|
}
|
|
441
436
|
|
|
442
|
-
const
|
|
437
|
+
const encryptedPreviousKey = content.get(field)!;
|
|
438
|
+
|
|
439
|
+
const secret = decryptKeySecret(
|
|
443
440
|
{
|
|
444
|
-
|
|
445
|
-
|
|
441
|
+
encryptedID: keyID,
|
|
442
|
+
encryptingID: encryptingKeyID,
|
|
446
443
|
encrypted: encryptedPreviousKey,
|
|
447
444
|
},
|
|
448
|
-
|
|
445
|
+
encryptingKeySecret
|
|
449
446
|
);
|
|
450
447
|
|
|
451
448
|
if (secret) {
|
|
452
449
|
return secret;
|
|
453
450
|
} else {
|
|
454
451
|
console.error(
|
|
455
|
-
`
|
|
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: "
|
|
497
|
-
|
|
494
|
+
action: "content",
|
|
495
|
+
id: this.id,
|
|
498
496
|
header: knownState?.header ? undefined : this.header,
|
|
499
|
-
|
|
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.
|
|
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():
|
|
538
|
+
getDependedOnCoValues(): RawCoID[] {
|
|
542
539
|
return this.header.ruleset.type === "team"
|
|
543
540
|
? expectTeamContent(this.getCurrentContent())
|
|
544
541
|
.keys()
|
|
545
|
-
.filter((k): k is
|
|
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
|
+
}
|