@peers-app/peers-sdk 0.27.4 → 0.28.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.
- package/dist/context/user-context.d.ts +7 -1
- package/dist/context/user-context.js +4 -9
- package/dist/contracts/contract-proxy.d.ts +5 -0
- package/dist/contracts/contract-proxy.js +2 -2
- package/dist/contracts/contract-resolvers.d.ts +2 -2
- package/dist/contracts/contract-resolvers.js +14 -15
- package/dist/contracts/contract-transport.d.ts +2 -1
- package/dist/contracts/contract-transport.js +24 -2
- package/dist/contracts/system/network-contracts.d.ts +1 -1
- package/dist/contracts/tool-catalog-service.js +1 -1
- package/dist/contracts/tool-catalog.js +6 -2
- package/dist/data/assistants.d.ts +3 -3
- package/dist/data/authority-write-checks.d.ts +42 -0
- package/dist/data/authority-write-checks.js +324 -0
- package/dist/data/change-tracking.d.ts +4 -4
- package/dist/data/create-group.js +1 -0
- package/dist/data/devices.d.ts +27 -4
- package/dist/data/devices.js +31 -0
- package/dist/data/group-authority.d.ts +111 -0
- package/dist/data/group-authority.js +281 -0
- package/dist/data/group-members.d.ts +8 -2
- package/dist/data/group-members.js +41 -18
- package/dist/data/group-permissions.d.ts +15 -31
- package/dist/data/group-permissions.js +25 -95
- package/dist/data/group-resign.d.ts +38 -0
- package/dist/data/group-resign.js +71 -0
- package/dist/data/groups.d.ts +11 -0
- package/dist/data/groups.js +31 -13
- package/dist/data/index.d.ts +3 -0
- package/dist/data/index.js +3 -0
- package/dist/data/invites.d.ts +14 -0
- package/dist/data/orm/index.d.ts +1 -0
- package/dist/data/orm/index.js +1 -0
- package/dist/data/orm/sql.data-source.d.ts +2 -2
- package/dist/data/orm/sql.data-source.js +8 -9
- package/dist/data/orm/table-container.js +14 -8
- package/dist/data/orm/write-checks.d.ts +89 -0
- package/dist/data/orm/write-checks.js +115 -0
- package/dist/data/package-table-identity.d.ts +6 -0
- package/dist/data/package-table-identity.js +51 -0
- package/dist/data/package-version-resolver.d.ts +15 -0
- package/dist/data/package-version-resolver.js +58 -3
- package/dist/data/package-versions.d.ts +20 -14
- package/dist/data/package-versions.js +15 -9
- package/dist/data/packages.d.ts +6 -1
- package/dist/data/packages.js +15 -20
- package/dist/data/persistent-vars.js +2 -39
- package/dist/data/sync-recovery-queue.d.ts +4 -4
- package/dist/data/sync-recovery-queue.js +7 -1
- package/dist/data/tool-access-approvals.d.ts +3 -3
- package/dist/data/user-permissions.d.ts +33 -2
- package/dist/data/user-permissions.js +87 -10
- package/dist/data/users.d.ts +49 -12
- package/dist/data/users.js +21 -1
- package/dist/data/workflows.d.ts +1 -1
- package/dist/device/binary-peer-connection-v2.d.ts +8 -16
- package/dist/device/binary-peer-connection-v2.js +15 -31
- package/dist/device/connection.d.ts +35 -44
- package/dist/device/connection.js +188 -186
- package/dist/device/device.d.ts +1 -8
- package/dist/device/device.js +1 -30
- package/dist/device/frame-cipher.d.ts +1 -1
- package/dist/device/frame-cipher.js +1 -1
- package/dist/device/get-trust-level-fn.js +3 -6
- package/dist/device/socket.type.d.ts +6 -12
- package/dist/device-pairing/types.d.ts +26 -26
- package/dist/identity/user-row-change.d.ts +3 -1
- package/dist/identity/user-row-change.js +33 -18
- package/dist/invites/group-approval.js +23 -24
- package/dist/invites/invite-messages.d.ts +250 -28
- package/dist/invites/invite-token.d.ts +18 -0
- package/dist/invites/invite-token.js +2 -0
- package/dist/keys.d.ts +7 -0
- package/dist/keys.js +27 -0
- package/dist/package-installer/package-installer.d.ts +1 -1
- package/dist/package-installer/package-installer.js +8 -3
- package/dist/package-installer/package-propagation.d.ts +2 -0
- package/dist/package-installer/package-propagation.js +20 -38
- package/dist/package-installer/package-remote-checker.js +15 -3
- package/dist/package-loader/isolated-artifact.js +0 -2
- package/dist/package-loader/package-loader.js +6 -0
- package/dist/types/peer-device.d.ts +2 -0
- package/dist/types/workflow.d.ts +2 -2
- package/package.json +1 -1
- package/dist/data/package-permissions.d.ts +0 -14
- package/dist/data/package-permissions.js +0 -26
- package/dist/data/package-version-permissions.d.ts +0 -14
- package/dist/data/package-version-permissions.js +0 -30
- package/dist/device/binary-peer-connection.d.ts +0 -58
- package/dist/device/binary-peer-connection.js +0 -516
- package/dist/device/streamed-socket.d.ts +0 -23
- package/dist/device/streamed-socket.js +0 -255
|
@@ -10,7 +10,7 @@ export declare const SYNC_RECOVERY_STUCK_ATTEMPTS = 5;
|
|
|
10
10
|
/** How long a still-retrying entry must have been failing before it is stuck. */
|
|
11
11
|
export declare const SYNC_RECOVERY_STUCK_AGE_MS: number;
|
|
12
12
|
/** Why automatic recovery stopped asking peers for an entry. */
|
|
13
|
-
export declare const syncRecoveryParkedReasons: readonly ["schema", "unique-conflict", "unresolvable"];
|
|
13
|
+
export declare const syncRecoveryParkedReasons: readonly ["schema", "unique-conflict", "unresolvable", "authorization"];
|
|
14
14
|
/** Why automatic recovery stopped asking peers for an entry. */
|
|
15
15
|
export type SyncRecoveryParkedReason = (typeof syncRecoveryParkedReasons)[number];
|
|
16
16
|
/** One recorded materialization failure for a synchronized record. */
|
|
@@ -50,7 +50,7 @@ export declare const syncRecoveryEntrySchema: z.ZodObject<{
|
|
|
50
50
|
}>, "many">;
|
|
51
51
|
/** Set when peer retry has stopped. Absent while the entry is still retrying. */
|
|
52
52
|
parkedAt: z.ZodOptional<z.ZodNumber>;
|
|
53
|
-
parkedReason: z.ZodOptional<z.ZodEnum<["schema", "unique-conflict", "unresolvable"]>>;
|
|
53
|
+
parkedReason: z.ZodOptional<z.ZodEnum<["schema", "unique-conflict", "unresolvable", "authorization"]>>;
|
|
54
54
|
/** Earliest time a retrying entry should ask peers again. */
|
|
55
55
|
nextAttemptAt: z.ZodOptional<z.ZodNumber>;
|
|
56
56
|
/**
|
|
@@ -71,7 +71,7 @@ export declare const syncRecoveryEntrySchema: z.ZodObject<{
|
|
|
71
71
|
sourceDeviceId?: string | undefined;
|
|
72
72
|
}[];
|
|
73
73
|
parkedAt?: number | undefined;
|
|
74
|
-
parkedReason?: "schema" | "unique-conflict" | "unresolvable" | undefined;
|
|
74
|
+
parkedReason?: "schema" | "unique-conflict" | "unresolvable" | "authorization" | undefined;
|
|
75
75
|
nextAttemptAt?: number | undefined;
|
|
76
76
|
sweepCount?: number | undefined;
|
|
77
77
|
}, {
|
|
@@ -87,7 +87,7 @@ export declare const syncRecoveryEntrySchema: z.ZodObject<{
|
|
|
87
87
|
sourceDeviceId?: string | undefined;
|
|
88
88
|
}[];
|
|
89
89
|
parkedAt?: number | undefined;
|
|
90
|
-
parkedReason?: "schema" | "unique-conflict" | "unresolvable" | undefined;
|
|
90
|
+
parkedReason?: "schema" | "unique-conflict" | "unresolvable" | "authorization" | undefined;
|
|
91
91
|
nextAttemptAt?: number | undefined;
|
|
92
92
|
sweepCount?: number | undefined;
|
|
93
93
|
}>;
|
|
@@ -20,7 +20,13 @@ exports.SYNC_RECOVERY_STUCK_ATTEMPTS = 5;
|
|
|
20
20
|
/** How long a still-retrying entry must have been failing before it is stuck. */
|
|
21
21
|
exports.SYNC_RECOVERY_STUCK_AGE_MS = 10 * 60 * 1000;
|
|
22
22
|
/** Why automatic recovery stopped asking peers for an entry. */
|
|
23
|
-
exports.syncRecoveryParkedReasons = [
|
|
23
|
+
exports.syncRecoveryParkedReasons = [
|
|
24
|
+
"schema",
|
|
25
|
+
"unique-conflict",
|
|
26
|
+
"unresolvable",
|
|
27
|
+
/** A write check refused the row; rechecked from local history when the group's authority changes. */
|
|
28
|
+
"authorization",
|
|
29
|
+
];
|
|
24
30
|
/** One recorded materialization failure for a synchronized record. */
|
|
25
31
|
exports.syncRecoveryFailureSchema = zod_1.z.object({
|
|
26
32
|
error: zod_1.z.string(),
|
|
@@ -50,8 +50,8 @@ export declare const toolAccessApprovalSchema: z.ZodObject<{
|
|
|
50
50
|
toolName: string;
|
|
51
51
|
toolId: string;
|
|
52
52
|
scope: ToolAccessApprovalScope;
|
|
53
|
-
dataContextId: string;
|
|
54
53
|
createdAt: Date;
|
|
54
|
+
dataContextId: string;
|
|
55
55
|
expiresAt: Date;
|
|
56
56
|
toolAccessApprovalId: string;
|
|
57
57
|
argsHash: string;
|
|
@@ -81,8 +81,8 @@ export declare const toolAccessApprovalSchema: z.ZodObject<{
|
|
|
81
81
|
};
|
|
82
82
|
status?: ToolAccessApprovalStatus | undefined;
|
|
83
83
|
scope?: ToolAccessApprovalScope | undefined;
|
|
84
|
-
assistantId?: string | undefined;
|
|
85
84
|
createdAt?: Date | undefined;
|
|
85
|
+
assistantId?: string | undefined;
|
|
86
86
|
workflowRunId?: string | undefined;
|
|
87
87
|
workflowLogId?: string | undefined;
|
|
88
88
|
threadMessageId?: string | undefined;
|
|
@@ -106,8 +106,8 @@ export declare function ToolAccessApprovals(dataContext?: DataContext): import("
|
|
|
106
106
|
toolName: string;
|
|
107
107
|
toolId: string;
|
|
108
108
|
scope: ToolAccessApprovalScope;
|
|
109
|
-
dataContextId: string;
|
|
110
109
|
createdAt: Date;
|
|
110
|
+
dataContextId: string;
|
|
111
111
|
expiresAt: Date;
|
|
112
112
|
toolAccessApprovalId: string;
|
|
113
113
|
argsHash: string;
|
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
import type { IUser } from "./users";
|
|
2
2
|
/**
|
|
3
|
-
* Signs a user
|
|
4
|
-
*
|
|
3
|
+
* Signs a user's profile and separately signs its initial anchor list. Later anchor changes
|
|
4
|
+
* are still authorized by the anchors on record; see {@link verifyUserSignature}.
|
|
5
5
|
* @param user The user object to sign
|
|
6
6
|
* @param secretKey The secret key to sign with
|
|
7
7
|
* @returns IUser The signed user object
|
|
8
8
|
*/
|
|
9
9
|
export declare function signUserObject(user: IUser, secretKey: string): IUser;
|
|
10
|
+
/** Whether the profile owner authorized this exact initial anchor list, before any anchors exist. */
|
|
11
|
+
export declare function hasSignedUserAnchors(user: IUser): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Whether a Users row is signed by its own `publicKey` (its anchor list is not signed): the
|
|
14
|
+
* only rows a group's authority takes a member's key from.
|
|
15
|
+
*
|
|
16
|
+
* @param user - A Users row.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isSelfSignedUser(user: IUser): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Whether two profiles or authenticated devices name the same user and both of their keys.
|
|
21
|
+
* This compares identity only; callers still verify signatures or the transport separately.
|
|
22
|
+
*/
|
|
23
|
+
export declare function sameUserIdentity(a: Pick<IUser, "userId" | "publicKey" | "publicBoxKey">, b: Pick<IUser, "userId" | "publicKey" | "publicBoxKey">): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* `source`'s anchor list with the owner's signature over it, to spread onto a profile or an
|
|
26
|
+
* invite identity; nothing when `source` has no list.
|
|
27
|
+
*
|
|
28
|
+
* @param source - The row or identity the list is taken from.
|
|
29
|
+
*/
|
|
30
|
+
export declare function anchorFields(source: Pick<IUser, "anchors" | "anchorsSignature">): Pick<IUser, "anchors" | "anchorsSignature">;
|
|
10
31
|
/**
|
|
11
32
|
* Verifies that a user update signature is valid, throws on invalid signature.
|
|
12
33
|
* The `anchors` list is not part of what is verified.
|
|
@@ -21,3 +42,13 @@ export declare function verifyUserSignature(user: IUser, oldUser?: IUser): void;
|
|
|
21
42
|
* @throws Error if the signature is missing, invalid, or by another key
|
|
22
43
|
*/
|
|
23
44
|
export declare function verifyUserSignedBySelf(user: IUser): void;
|
|
45
|
+
/**
|
|
46
|
+
* Whether `user`'s current key is `earlierKey`, or was handed over from it: `earlierKey` is in
|
|
47
|
+
* `keySuccession` and each link from there on is signed by its key and names the next (the
|
|
48
|
+
* last names `publicKey`). A forged profile can't produce this, since only the holder of
|
|
49
|
+
* `earlierKey` can sign its handover. The list itself sits under the profile's own signature.
|
|
50
|
+
*
|
|
51
|
+
* @param user - A profile row whose own signature has been checked.
|
|
52
|
+
* @param earlierKey - The key a grant or record names.
|
|
53
|
+
*/
|
|
54
|
+
export declare function keySucceeds(user: IUser, earlierKey: string): boolean;
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.signUserObject = signUserObject;
|
|
4
|
+
exports.hasSignedUserAnchors = hasSignedUserAnchors;
|
|
5
|
+
exports.isSelfSignedUser = isSelfSignedUser;
|
|
6
|
+
exports.sameUserIdentity = sameUserIdentity;
|
|
7
|
+
exports.anchorFields = anchorFields;
|
|
4
8
|
exports.verifyUserSignature = verifyUserSignature;
|
|
5
9
|
exports.verifyUserSignedBySelf = verifyUserSignedBySelf;
|
|
10
|
+
exports.keySucceeds = keySucceeds;
|
|
11
|
+
const anchor_document_1 = require("../identity/anchor-document");
|
|
6
12
|
const keys_1 = require("../keys");
|
|
7
13
|
/**
|
|
8
|
-
* The
|
|
14
|
+
* The profile the owner signs: everything but the separately authorized anchor list.
|
|
9
15
|
*
|
|
10
16
|
* The anchor list on record is decided by the anchors themselves (the on-record rule), not
|
|
11
17
|
* by whoever wrote the row. A peer that confirms a key change stores the row with the list
|
|
@@ -13,19 +19,68 @@ const keys_1 = require("../keys");
|
|
|
13
19
|
* must still verify, so the list is carried beside the signature rather than under it.
|
|
14
20
|
*/
|
|
15
21
|
function signedPart(user) {
|
|
16
|
-
const { anchors: _anchors, ...rest } = user;
|
|
22
|
+
const { anchors: _anchors, anchorsSignature: _anchorsSignature, ...rest } = user;
|
|
17
23
|
return rest;
|
|
18
24
|
}
|
|
19
25
|
/**
|
|
20
|
-
* Signs a user
|
|
21
|
-
*
|
|
26
|
+
* Signs a user's profile and separately signs its initial anchor list. Later anchor changes
|
|
27
|
+
* are still authorized by the anchors on record; see {@link verifyUserSignature}.
|
|
22
28
|
* @param user The user object to sign
|
|
23
29
|
* @param secretKey The secret key to sign with
|
|
24
30
|
* @returns IUser The signed user object
|
|
25
31
|
*/
|
|
26
32
|
function signUserObject(user, secretKey) {
|
|
27
33
|
const signed = (0, keys_1.addSignatureToObject)(signedPart(user), secretKey);
|
|
28
|
-
return user.anchors
|
|
34
|
+
return user.anchors
|
|
35
|
+
? {
|
|
36
|
+
...signed,
|
|
37
|
+
anchors: user.anchors,
|
|
38
|
+
anchorsSignature: (0, keys_1.addSignatureToObject)(anchorStatement(user), secretKey).signature,
|
|
39
|
+
}
|
|
40
|
+
: signed;
|
|
41
|
+
}
|
|
42
|
+
function anchorStatement(user) {
|
|
43
|
+
return {
|
|
44
|
+
purpose: "peers-user-anchors",
|
|
45
|
+
userId: user.userId,
|
|
46
|
+
publicKey: user.publicKey,
|
|
47
|
+
anchors: user.anchors ?? [],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Whether the profile owner authorized this exact initial anchor list, before any anchors exist. */
|
|
51
|
+
function hasSignedUserAnchors(user) {
|
|
52
|
+
const statement = { ...anchorStatement(user), signature: user.anchorsSignature };
|
|
53
|
+
return !!user.publicKey && (0, keys_1.signedByKey)(statement) === user.publicKey;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Whether a Users row is signed by its own `publicKey` (its anchor list is not signed): the
|
|
57
|
+
* only rows a group's authority takes a member's key from.
|
|
58
|
+
*
|
|
59
|
+
* @param user - A Users row.
|
|
60
|
+
*/
|
|
61
|
+
function isSelfSignedUser(user) {
|
|
62
|
+
return !!user.publicKey && (0, keys_1.signedByKey)(signedPart(user)) === user.publicKey;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Whether two profiles or authenticated devices name the same user and both of their keys.
|
|
66
|
+
* This compares identity only; callers still verify signatures or the transport separately.
|
|
67
|
+
*/
|
|
68
|
+
function sameUserIdentity(a, b) {
|
|
69
|
+
return a.userId === b.userId && a.publicKey === b.publicKey && a.publicBoxKey === b.publicBoxKey;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* `source`'s anchor list with the owner's signature over it, to spread onto a profile or an
|
|
73
|
+
* invite identity; nothing when `source` has no list.
|
|
74
|
+
*
|
|
75
|
+
* @param source - The row or identity the list is taken from.
|
|
76
|
+
*/
|
|
77
|
+
function anchorFields(source) {
|
|
78
|
+
if (!source.anchors?.length)
|
|
79
|
+
return {};
|
|
80
|
+
return {
|
|
81
|
+
anchors: source.anchors,
|
|
82
|
+
...(source.anchorsSignature ? { anchorsSignature: source.anchorsSignature } : {}),
|
|
83
|
+
};
|
|
29
84
|
}
|
|
30
85
|
/**
|
|
31
86
|
* Verifies that a user update signature is valid, throws on invalid signature.
|
|
@@ -69,9 +124,31 @@ function verifyUserSignedBySelf(user) {
|
|
|
69
124
|
if (!user.signature) {
|
|
70
125
|
throw new Error("A confirmed key change still has to be signed by the new key");
|
|
71
126
|
}
|
|
72
|
-
(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
127
|
+
verifyUserSignature(user);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Whether `user`'s current key is `earlierKey`, or was handed over from it: `earlierKey` is in
|
|
131
|
+
* `keySuccession` and each link from there on is signed by its key and names the next (the
|
|
132
|
+
* last names `publicKey`). A forged profile can't produce this, since only the holder of
|
|
133
|
+
* `earlierKey` can sign its handover. The list itself sits under the profile's own signature.
|
|
134
|
+
*
|
|
135
|
+
* @param user - A profile row whose own signature has been checked.
|
|
136
|
+
* @param earlierKey - The key a grant or record names.
|
|
137
|
+
*/
|
|
138
|
+
function keySucceeds(user, earlierKey) {
|
|
139
|
+
if (user.publicKey === earlierKey)
|
|
140
|
+
return true;
|
|
141
|
+
const links = user.keySuccession ?? [];
|
|
142
|
+
const start = links.findIndex((link) => link.publicKey === earlierKey);
|
|
143
|
+
if (start < 0)
|
|
144
|
+
return false;
|
|
145
|
+
return links.slice(start).every((link, i, rest) => (0, anchor_document_1.verifySuccession)({
|
|
146
|
+
userId: user.userId,
|
|
147
|
+
recordPublicKey: link.publicKey,
|
|
148
|
+
entry: {
|
|
149
|
+
publicKey: rest[i + 1]?.publicKey ?? user.publicKey,
|
|
150
|
+
issuedAt: link.issuedAt,
|
|
151
|
+
authorizedBy: { publicKey: link.publicKey, signature: link.signature },
|
|
152
|
+
},
|
|
153
|
+
}));
|
|
77
154
|
}
|
package/dist/data/users.d.ts
CHANGED
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { DataContext } from "../context/data-context";
|
|
3
|
+
import type { UserRowChangeDecision } from "../identity/user-row-change";
|
|
3
4
|
import type { ISaveOptions } from "./orm/data-query";
|
|
4
5
|
import { Table } from "./orm/table";
|
|
6
|
+
/** Most earlier keys a profile carries; a rotation past this drops the oldest. */
|
|
7
|
+
export declare const MAX_KEY_SUCCESSION = 8;
|
|
8
|
+
/**
|
|
9
|
+
* One earlier key and its handover: `signature` is that key's signature over the
|
|
10
|
+
* `peers-key-succession` statement naming the next key (see `signSuccession`).
|
|
11
|
+
*/
|
|
12
|
+
export declare const keySuccessionLinkSchema: z.ZodObject<{
|
|
13
|
+
publicKey: z.ZodString;
|
|
14
|
+
issuedAt: z.ZodString;
|
|
15
|
+
signature: z.ZodString;
|
|
16
|
+
}, "strip", z.ZodTypeAny, {
|
|
17
|
+
publicKey: string;
|
|
18
|
+
signature: string;
|
|
19
|
+
issuedAt: string;
|
|
20
|
+
}, {
|
|
21
|
+
publicKey: string;
|
|
22
|
+
signature: string;
|
|
23
|
+
issuedAt: string;
|
|
24
|
+
}>;
|
|
25
|
+
/** One earlier key and its signed handover to the next. */
|
|
26
|
+
export type IKeySuccessionLink = z.infer<typeof keySuccessionLinkSchema>;
|
|
5
27
|
/** Schema for a signed user profile. */
|
|
6
28
|
export declare const userSchema: z.ZodObject<{
|
|
7
29
|
userId: z.ZodEffects<z.ZodString, string, string>;
|
|
@@ -18,6 +40,20 @@ export declare const userSchema: z.ZodObject<{
|
|
|
18
40
|
type: "peers-services" | "https";
|
|
19
41
|
url: string;
|
|
20
42
|
}>, "many">>;
|
|
43
|
+
anchorsSignature: z.ZodOptional<z.ZodString>;
|
|
44
|
+
keySuccession: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
45
|
+
publicKey: z.ZodString;
|
|
46
|
+
issuedAt: z.ZodString;
|
|
47
|
+
signature: z.ZodString;
|
|
48
|
+
}, "strip", z.ZodTypeAny, {
|
|
49
|
+
publicKey: string;
|
|
50
|
+
signature: string;
|
|
51
|
+
issuedAt: string;
|
|
52
|
+
}, {
|
|
53
|
+
publicKey: string;
|
|
54
|
+
signature: string;
|
|
55
|
+
issuedAt: string;
|
|
56
|
+
}>, "many">>;
|
|
21
57
|
signature: z.ZodOptional<z.ZodString>;
|
|
22
58
|
}, "strip", z.ZodTypeAny, {
|
|
23
59
|
name: string;
|
|
@@ -29,6 +65,12 @@ export declare const userSchema: z.ZodObject<{
|
|
|
29
65
|
type: "peers-services" | "https";
|
|
30
66
|
url: string;
|
|
31
67
|
}[] | undefined;
|
|
68
|
+
anchorsSignature?: string | undefined;
|
|
69
|
+
keySuccession?: {
|
|
70
|
+
publicKey: string;
|
|
71
|
+
signature: string;
|
|
72
|
+
issuedAt: string;
|
|
73
|
+
}[] | undefined;
|
|
32
74
|
}, {
|
|
33
75
|
name: string;
|
|
34
76
|
publicKey: string;
|
|
@@ -39,6 +81,12 @@ export declare const userSchema: z.ZodObject<{
|
|
|
39
81
|
type: "peers-services" | "https";
|
|
40
82
|
url: string;
|
|
41
83
|
}[] | undefined;
|
|
84
|
+
anchorsSignature?: string | undefined;
|
|
85
|
+
keySuccession?: {
|
|
86
|
+
publicKey: string;
|
|
87
|
+
signature: string;
|
|
88
|
+
issuedAt: string;
|
|
89
|
+
}[] | undefined;
|
|
42
90
|
}>;
|
|
43
91
|
/** A signed user profile shared across personal and group contexts. */
|
|
44
92
|
export type IUser = z.infer<typeof userSchema>;
|
|
@@ -47,24 +95,13 @@ export type IUser = z.infer<typeof userSchema>;
|
|
|
47
95
|
* which would otherwise call the resolver again.
|
|
48
96
|
*/
|
|
49
97
|
export declare function writeResolvedUserKey(dataContext: DataContext, user: IUser): Promise<IUser>;
|
|
50
|
-
/** Outcome of a {@link UserRowChangeGuard}. See `resolveUserRowChange` in the identity module. */
|
|
51
|
-
export type UserRowChangeVerdict = {
|
|
52
|
-
action: "apply";
|
|
53
|
-
row: IUser;
|
|
54
|
-
} | {
|
|
55
|
-
action: "defer";
|
|
56
|
-
reason: string;
|
|
57
|
-
} | {
|
|
58
|
-
action: "refuse";
|
|
59
|
-
reason: string;
|
|
60
|
-
};
|
|
61
98
|
/**
|
|
62
99
|
* Consulted by {@link UsersTable.save} when another user's row already exists in the table.
|
|
63
100
|
* Decides whether a different key or anchor list may be stored, against the anchors on
|
|
64
101
|
* record. `apply` carries the row to store, whose `anchors` may have been replaced by the
|
|
65
102
|
* list on record.
|
|
66
103
|
*/
|
|
67
|
-
export type UserRowChangeGuard = (personalContext: DataContext, incoming: IUser, existing: IUser) => Promise<
|
|
104
|
+
export type UserRowChangeGuard = (personalContext: DataContext, incoming: IUser, existing: IUser) => Promise<UserRowChangeDecision>;
|
|
68
105
|
/** Installs the identity check used by {@link UsersTable.save}. The identity module sets this. */
|
|
69
106
|
export declare function setUserRowChangeGuard(guard: UserRowChangeGuard | undefined): void;
|
|
70
107
|
/** User table with owner-signature enforcement outside the personal context. */
|
package/dist/data/users.js
CHANGED
|
@@ -34,7 +34,7 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
34
34
|
done = true;
|
|
35
35
|
};
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
exports.UsersTable = exports.userSchema = void 0;
|
|
37
|
+
exports.UsersTable = exports.userSchema = exports.keySuccessionLinkSchema = exports.MAX_KEY_SUCCESSION = void 0;
|
|
38
38
|
exports.writeResolvedUserKey = writeResolvedUserKey;
|
|
39
39
|
exports.setUserRowChangeGuard = setUserRowChangeGuard;
|
|
40
40
|
exports.Users = Users;
|
|
@@ -50,6 +50,17 @@ const table_1 = require("./orm/table");
|
|
|
50
50
|
const table_definitions_system_1 = require("./orm/table-definitions.system");
|
|
51
51
|
const types_1 = require("./orm/types");
|
|
52
52
|
const user_permissions_1 = require("./user-permissions");
|
|
53
|
+
/** Most earlier keys a profile carries; a rotation past this drops the oldest. */
|
|
54
|
+
exports.MAX_KEY_SUCCESSION = 8;
|
|
55
|
+
/**
|
|
56
|
+
* One earlier key and its handover: `signature` is that key's signature over the
|
|
57
|
+
* `peers-key-succession` statement naming the next key (see `signSuccession`).
|
|
58
|
+
*/
|
|
59
|
+
exports.keySuccessionLinkSchema = zod_1.z.object({
|
|
60
|
+
publicKey: zod_1.z.string(),
|
|
61
|
+
issuedAt: zod_1.z.string(),
|
|
62
|
+
signature: zod_1.z.string(),
|
|
63
|
+
});
|
|
53
64
|
/** Schema for a signed user profile. */
|
|
54
65
|
exports.userSchema = zod_1.z.object({
|
|
55
66
|
userId: zod_types_1.zodPeerId,
|
|
@@ -62,6 +73,15 @@ exports.userSchema = zod_1.z.object({
|
|
|
62
73
|
.array(anchor_document_1.anchorRefSchema)
|
|
63
74
|
.optional()
|
|
64
75
|
.describe("Anchors on record for this user. A peer that already has a list updates it from those anchors, not from a row that arrives with a new key. Not covered by the row's signature"),
|
|
76
|
+
anchorsSignature: zod_1.z
|
|
77
|
+
.string()
|
|
78
|
+
.optional()
|
|
79
|
+
.describe("Owner's signature authorizing the first anchor list"),
|
|
80
|
+
keySuccession: zod_1.z
|
|
81
|
+
.array(exports.keySuccessionLinkSchema)
|
|
82
|
+
.max(exports.MAX_KEY_SUCCESSION)
|
|
83
|
+
.optional()
|
|
84
|
+
.describe("This user's earlier signing keys, oldest first, each with its signature handing over to the next key (the last to publicKey). A group membership granted to an earlier key still counts for the current one"),
|
|
65
85
|
signature: zod_1.z
|
|
66
86
|
.string()
|
|
67
87
|
.optional()
|
package/dist/data/workflows.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export declare function Workflows(dataContext?: DataContext): import("..").Table
|
|
|
3
3
|
name: string;
|
|
4
4
|
description: string;
|
|
5
5
|
updatedAt: Date;
|
|
6
|
+
createdBy: string;
|
|
6
7
|
createdAt: Date;
|
|
7
8
|
workflowId: string;
|
|
8
9
|
defaultAssistantId: string;
|
|
@@ -12,6 +13,5 @@ export declare function Workflows(dataContext?: DataContext): import("..").Table
|
|
|
12
13
|
directCallToolId?: string | undefined;
|
|
13
14
|
subWorkflowId?: string | undefined;
|
|
14
15
|
}[];
|
|
15
|
-
createdBy: string;
|
|
16
16
|
packageId?: string | undefined;
|
|
17
17
|
}>;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* binary-peer-connection-v2.ts
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Binary transport layer under every device connection. Provides two cleanly
|
|
5
|
+
* separated modes:
|
|
6
6
|
*
|
|
7
7
|
* 1. **RPC mode** (emit/on): request/response interactions with automatic
|
|
8
8
|
* encoding (txEncode for objects, passthrough for Uint8Array) and transparent
|
|
9
9
|
* chunking for large payloads.
|
|
10
10
|
*
|
|
11
11
|
* 2. **Stream mode** (sendRawBytes/onRawBytes): continuous byte transfer for
|
|
12
|
-
* file syncing,
|
|
12
|
+
* file syncing, log streaming, etc. Each sendRawBytes
|
|
13
13
|
* call = exactly one onRawBytes callback (atomic delivery after reassembly).
|
|
14
14
|
*
|
|
15
15
|
* Both modes share a single sendFrame() function that handles backpressure
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* 3. **Frame cipher**: once `armFrameCipher` is called (by `Connection` after
|
|
19
19
|
* the handshake), every outbound frame is sealed as `FRAME_ENC` and every
|
|
20
20
|
* inbound frame must be sealed. See `frame-cipher.ts` and
|
|
21
|
-
* `working/transport-security.md`.
|
|
21
|
+
* `working/done/transport-security.md`.
|
|
22
22
|
*/
|
|
23
23
|
import { Connection } from "./connection";
|
|
24
24
|
import type { Device } from "./device";
|
|
@@ -61,19 +61,12 @@ export declare const DEFAULT_BINARY_PEER_RECEIVE_LIMITS: Readonly<BinaryPeerRece
|
|
|
61
61
|
export interface WrapBinaryPeerOptions {
|
|
62
62
|
/** Protocol identifier used for server address (e.g., 'wrtc' or 'ws') */
|
|
63
63
|
protocol: "wrtc" | "ws";
|
|
64
|
-
/**
|
|
65
|
-
* Mark the transport as already secure (encrypted at transport layer).
|
|
66
|
-
* When true, sets secureLocal and secureRemote to skip the legacy per-message
|
|
67
|
-
* envelope against a legacy peer. Irrelevant once the frame cipher is armed.
|
|
68
|
-
* @deprecated Removed with the legacy path.
|
|
69
|
-
*/
|
|
70
|
-
markTransportSecure?: boolean;
|
|
71
64
|
/** Optional hard limits for untrusted inbound messages. */
|
|
72
65
|
receiveLimits?: Partial<BinaryPeerReceiveLimits>;
|
|
73
66
|
}
|
|
74
67
|
/**
|
|
75
68
|
* Creates an ISocket from a binary peer. This is the core v2 factory function.
|
|
76
|
-
*
|
|
69
|
+
* Used for every device connection.
|
|
77
70
|
*/
|
|
78
71
|
export declare function createBinaryPeerSocket(connectionId: string, peer: IBinaryPeer, protocol?: string, receiveLimitOverrides?: Partial<BinaryPeerReceiveLimits>): ISocket;
|
|
79
72
|
/**
|
|
@@ -82,10 +75,9 @@ export declare function createBinaryPeerSocket(connectionId: string, peer: IBina
|
|
|
82
75
|
*/
|
|
83
76
|
export declare function wrapBinaryPeer(connectionId: string, peer: IBinaryPeer, localDevice: Device, initiator: boolean, options: WrapBinaryPeerOptions, getTrustLevel?: ITrustLevelFn): Connection;
|
|
84
77
|
/**
|
|
85
|
-
* Wraps a WebRTC peer into a Connection.
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* classification.
|
|
78
|
+
* Wraps a WebRTC peer into a Connection. WebRTC is encrypted at the transport
|
|
79
|
+
* layer (DTLS-SRTP); the handshake arms the frame cipher on top of it, as on
|
|
80
|
+
* every transport.
|
|
89
81
|
*/
|
|
90
82
|
export declare function wrapWrtc(connectionId: string, peer: IWebRTCPeer, localDevice: Device, initiator: boolean, getTrustLevel?: ITrustLevelFn, receiveLimits?: Partial<BinaryPeerReceiveLimits>): Connection;
|
|
91
83
|
export {};
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* binary-peer-connection-v2.ts
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Binary transport layer under every device connection. Provides two cleanly
|
|
6
|
+
* separated modes:
|
|
7
7
|
*
|
|
8
8
|
* 1. **RPC mode** (emit/on): request/response interactions with automatic
|
|
9
9
|
* encoding (txEncode for objects, passthrough for Uint8Array) and transparent
|
|
10
10
|
* chunking for large payloads.
|
|
11
11
|
*
|
|
12
12
|
* 2. **Stream mode** (sendRawBytes/onRawBytes): continuous byte transfer for
|
|
13
|
-
* file syncing,
|
|
13
|
+
* file syncing, log streaming, etc. Each sendRawBytes
|
|
14
14
|
* call = exactly one onRawBytes callback (atomic delivery after reassembly).
|
|
15
15
|
*
|
|
16
16
|
* Both modes share a single sendFrame() function that handles backpressure
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* 3. **Frame cipher**: once `armFrameCipher` is called (by `Connection` after
|
|
20
20
|
* the handshake), every outbound frame is sealed as `FRAME_ENC` and every
|
|
21
21
|
* inbound frame must be sealed. See `frame-cipher.ts` and
|
|
22
|
-
* `working/transport-security.md`.
|
|
22
|
+
* `working/done/transport-security.md`.
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
25
|
exports.DEFAULT_BINARY_PEER_RECEIVE_LIMITS = void 0;
|
|
@@ -240,7 +240,7 @@ function buildStreamCont(sidBytes, chunkData) {
|
|
|
240
240
|
}
|
|
241
241
|
/**
|
|
242
242
|
* Creates an ISocket from a binary peer. This is the core v2 factory function.
|
|
243
|
-
*
|
|
243
|
+
* Used for every device connection.
|
|
244
244
|
*/
|
|
245
245
|
function createBinaryPeerSocket(connectionId, peer, protocol = "binary", receiveLimitOverrides = {}) {
|
|
246
246
|
const handlers = {};
|
|
@@ -265,7 +265,7 @@ function createBinaryPeerSocket(connectionId, peer, protocol = "binary", receive
|
|
|
265
265
|
let sendSealer = null;
|
|
266
266
|
let receiveOpener = null;
|
|
267
267
|
// Bare sockets (no Connection) deliver plaintext streams; Connection turns
|
|
268
|
-
// this off
|
|
268
|
+
// this off, so it receives only sealed stream frames.
|
|
269
269
|
let plaintextStreamsAllowed = true;
|
|
270
270
|
// Every inner frame must leave room for the cipher's 17 bytes so a sealed
|
|
271
271
|
// frame never exceeds the transport limit (64 KB SCTP on WebRTC). Reserved
|
|
@@ -503,7 +503,7 @@ function createBinaryPeerSocket(connectionId, peer, protocol = "binary", receive
|
|
|
503
503
|
else
|
|
504
504
|
responseMessage.result = result;
|
|
505
505
|
const encoded = encodeMessage(responseMessage);
|
|
506
|
-
sendRPC(encoded, sendOptions);
|
|
506
|
+
return sendRPC(encoded, sendOptions);
|
|
507
507
|
};
|
|
508
508
|
handler(message.args, callback);
|
|
509
509
|
}
|
|
@@ -730,17 +730,8 @@ function createBinaryPeerSocket(connectionId, peer, protocol = "binary", receive
|
|
|
730
730
|
break;
|
|
731
731
|
}
|
|
732
732
|
default: {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
// legacy format (no discriminator), try to decode as RPC.
|
|
736
|
-
// This handles the transition period where v1 peers send raw RPC without
|
|
737
|
-
// a frame type byte.
|
|
738
|
-
if (bytes.length > receiveLimits.maxRpcMessageBytes) {
|
|
739
|
-
closeForProtocolViolation("legacy RPC exceeds the message-size limit");
|
|
740
|
-
return;
|
|
741
|
-
}
|
|
742
|
-
handleIncomingRPC(bytes);
|
|
743
|
-
break;
|
|
733
|
+
closeForProtocolViolation(`unknown frame type ${frameType}`);
|
|
734
|
+
return;
|
|
744
735
|
}
|
|
745
736
|
}
|
|
746
737
|
}
|
|
@@ -762,7 +753,6 @@ function createBinaryPeerSocket(connectionId, peer, protocol = "binary", receive
|
|
|
762
753
|
const socket = {
|
|
763
754
|
id: connectionId,
|
|
764
755
|
connected: true,
|
|
765
|
-
handlesOwnEncoding: true,
|
|
766
756
|
transportType,
|
|
767
757
|
stats,
|
|
768
758
|
armFrameCipher,
|
|
@@ -811,26 +801,20 @@ function createBinaryPeerSocket(connectionId, peer, protocol = "binary", receive
|
|
|
811
801
|
* This is the main implementation that handles all binary protocols.
|
|
812
802
|
*/
|
|
813
803
|
function wrapBinaryPeer(connectionId, peer, localDevice, initiator, options, getTrustLevel) {
|
|
814
|
-
const { protocol,
|
|
804
|
+
const { protocol, receiveLimits } = options;
|
|
815
805
|
const socket = createBinaryPeerSocket(connectionId, peer, protocol, receiveLimits);
|
|
816
806
|
const serverAddress = `${protocol}://${connectionId}`;
|
|
817
807
|
const localServerAddresses = initiator ? undefined : [serverAddress];
|
|
818
808
|
if (process.env.NODE_ENV !== "test") {
|
|
819
809
|
getTrustLevel ??= (0, get_trust_level_fn_1.getTrustLevelFn)(localDevice, serverAddress);
|
|
820
810
|
}
|
|
821
|
-
|
|
822
|
-
if (markTransportSecure) {
|
|
823
|
-
connection.secureLocal = true;
|
|
824
|
-
connection.secureRemote = true;
|
|
825
|
-
}
|
|
826
|
-
return connection;
|
|
811
|
+
return new connection_1.Connection(socket, localDevice, localServerAddresses, getTrustLevel);
|
|
827
812
|
}
|
|
828
813
|
/**
|
|
829
|
-
* Wraps a WebRTC peer into a Connection.
|
|
830
|
-
*
|
|
831
|
-
*
|
|
832
|
-
* classification.
|
|
814
|
+
* Wraps a WebRTC peer into a Connection. WebRTC is encrypted at the transport
|
|
815
|
+
* layer (DTLS-SRTP); the handshake arms the frame cipher on top of it, as on
|
|
816
|
+
* every transport.
|
|
833
817
|
*/
|
|
834
818
|
function wrapWrtc(connectionId, peer, localDevice, initiator, getTrustLevel, receiveLimits) {
|
|
835
|
-
return wrapBinaryPeer(connectionId, peer, localDevice, initiator, { protocol: "wrtc",
|
|
819
|
+
return wrapBinaryPeer(connectionId, peer, localDevice, initiator, { protocol: "wrtc", receiveLimits }, getTrustLevel);
|
|
836
820
|
}
|