@peers-app/peers-sdk 0.27.5 → 0.28.1

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 (91) hide show
  1. package/dist/context/user-context.d.ts +7 -1
  2. package/dist/context/user-context.js +4 -9
  3. package/dist/contracts/contract-proxy.d.ts +5 -0
  4. package/dist/contracts/contract-proxy.js +2 -2
  5. package/dist/contracts/contract-resolvers.d.ts +2 -2
  6. package/dist/contracts/contract-resolvers.js +14 -15
  7. package/dist/contracts/system/network-contracts.d.ts +1 -1
  8. package/dist/contracts/tool-catalog-service.js +1 -1
  9. package/dist/data/assistants.d.ts +3 -3
  10. package/dist/data/authority-write-checks.d.ts +42 -0
  11. package/dist/data/authority-write-checks.js +324 -0
  12. package/dist/data/change-tracking.d.ts +4 -4
  13. package/dist/data/create-group.js +1 -0
  14. package/dist/data/devices.d.ts +27 -4
  15. package/dist/data/devices.js +31 -0
  16. package/dist/data/group-authority.d.ts +111 -0
  17. package/dist/data/group-authority.js +281 -0
  18. package/dist/data/group-members.d.ts +8 -2
  19. package/dist/data/group-members.js +41 -18
  20. package/dist/data/group-permissions.d.ts +15 -31
  21. package/dist/data/group-permissions.js +25 -95
  22. package/dist/data/group-resign.d.ts +38 -0
  23. package/dist/data/group-resign.js +71 -0
  24. package/dist/data/groups.d.ts +11 -0
  25. package/dist/data/groups.js +31 -13
  26. package/dist/data/index.d.ts +3 -0
  27. package/dist/data/index.js +3 -0
  28. package/dist/data/invites.d.ts +14 -0
  29. package/dist/data/orm/index.d.ts +1 -0
  30. package/dist/data/orm/index.js +1 -0
  31. package/dist/data/orm/sql.data-source.d.ts +2 -2
  32. package/dist/data/orm/sql.data-source.js +24 -22
  33. package/dist/data/orm/table-container.js +20 -11
  34. package/dist/data/orm/write-checks.d.ts +89 -0
  35. package/dist/data/orm/write-checks.js +115 -0
  36. package/dist/data/package-table-identity.d.ts +21 -0
  37. package/dist/data/package-table-identity.js +87 -0
  38. package/dist/data/package-version-resolver.d.ts +15 -0
  39. package/dist/data/package-version-resolver.js +70 -3
  40. package/dist/data/package-versions.d.ts +20 -14
  41. package/dist/data/package-versions.js +15 -9
  42. package/dist/data/packages.d.ts +6 -1
  43. package/dist/data/packages.js +15 -20
  44. package/dist/data/persistent-vars.js +2 -39
  45. package/dist/data/sync-recovery-queue.d.ts +4 -4
  46. package/dist/data/sync-recovery-queue.js +7 -1
  47. package/dist/data/tool-access-approvals.d.ts +3 -3
  48. package/dist/data/user-permissions.d.ts +33 -2
  49. package/dist/data/user-permissions.js +87 -10
  50. package/dist/data/users.d.ts +49 -12
  51. package/dist/data/users.js +21 -1
  52. package/dist/data/workflows.d.ts +1 -1
  53. package/dist/define/index.d.ts +1 -1
  54. package/dist/define/index.js +2 -1
  55. package/dist/define/manifest.js +9 -1
  56. package/dist/define/table.d.ts +15 -0
  57. package/dist/device/binary-peer-connection-v2.d.ts +1 -1
  58. package/dist/device/binary-peer-connection-v2.js +1 -1
  59. package/dist/device/connection.d.ts +1 -1
  60. package/dist/device/frame-cipher.d.ts +1 -1
  61. package/dist/device/frame-cipher.js +1 -1
  62. package/dist/device/get-trust-level-fn.js +3 -6
  63. package/dist/device-pairing/types.d.ts +26 -26
  64. package/dist/identity/user-row-change.d.ts +3 -1
  65. package/dist/identity/user-row-change.js +33 -18
  66. package/dist/invites/group-approval.js +23 -24
  67. package/dist/invites/invite-messages.d.ts +250 -28
  68. package/dist/invites/invite-token.d.ts +18 -0
  69. package/dist/invites/invite-token.js +2 -0
  70. package/dist/keys.d.ts +7 -0
  71. package/dist/keys.js +27 -0
  72. package/dist/package-installer/package-installer.d.ts +1 -1
  73. package/dist/package-installer/package-installer.js +8 -3
  74. package/dist/package-installer/package-propagation.d.ts +2 -0
  75. package/dist/package-installer/package-propagation.js +20 -38
  76. package/dist/package-installer/package-remote-checker.js +15 -3
  77. package/dist/package-loader/isolated-artifact.d.ts +14 -0
  78. package/dist/package-loader/isolated-artifact.js +3 -3
  79. package/dist/package-loader/isolated-runtime.d.ts +3 -1
  80. package/dist/package-loader/isolated-table-gateway.js +4 -1
  81. package/dist/package-loader/package-loader.js +6 -0
  82. package/dist/peer-id.d.ts +19 -0
  83. package/dist/peer-id.js +41 -0
  84. package/dist/types/peer-device.d.ts +2 -0
  85. package/dist/types/workflow.d.ts +2 -2
  86. package/dist/utils.js +13 -32
  87. package/package.json +1 -1
  88. package/dist/data/package-permissions.d.ts +0 -14
  89. package/dist/data/package-permissions.js +0 -26
  90. package/dist/data/package-version-permissions.d.ts +0 -14
  91. package/dist/data/package-version-permissions.js +0 -30
@@ -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 part of a `Users` row the owner signs: everything but `anchors`.
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 object with the provided secret key. The `anchors` list is kept on the row
21
- * but is not covered by the signature; see {@link verifyUserSignature}.
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 ? { ...signed, anchors: user.anchors } : signed;
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
- (0, keys_1.verifyObjectSignature)(signedPart(user));
73
- const signerPublicKey = (0, keys_1.getPublicKeyFromObjectSignature)(user) ?? "";
74
- if (signerPublicKey !== user.publicKey) {
75
- throw new Error("User signature must be signed with their own public key");
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
  }
@@ -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<UserRowChangeVerdict>;
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. */
@@ -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()
@@ -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
  }>;
@@ -11,7 +11,7 @@ export { AccessLevel } from "../data/access-level";
11
11
  export type { DataFilter, IDataQueryParams } from "../data/orm/data-query";
12
12
  export type { IDataChangedEvent } from "../data/orm/subscribable.data-source";
13
13
  export { type Observable, observable, type Subscription } from "../observable";
14
- export { isid, newid } from "../peer-id";
14
+ export { idFromKey, isid, newid } from "../peer-id";
15
15
  export { FieldType, type IField } from "../types/field-type";
16
16
  export { zodPeerId } from "../types/zod-types";
17
17
  export * from "./context";
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.writePackageVar = exports.userVar = exports.readPackageVar = exports.groupVar = exports.groupUserVar = exports.groupDeviceVar = exports.deviceVar = exports.isImplementedObservable = exports.defineObservable = exports.declareObservable = exports.generatedField = exports.defineEvent = exports.zodPeerId = exports.FieldType = exports.newid = exports.isid = exports.observable = exports.AccessLevel = exports.z = void 0;
17
+ exports.writePackageVar = exports.userVar = exports.readPackageVar = exports.groupVar = exports.groupUserVar = exports.groupDeviceVar = exports.deviceVar = exports.isImplementedObservable = exports.defineObservable = exports.declareObservable = exports.generatedField = exports.defineEvent = exports.zodPeerId = exports.FieldType = exports.newid = exports.isid = exports.idFromKey = exports.observable = exports.AccessLevel = exports.z = void 0;
18
18
  /**
19
19
  * `@peers-app/peers-sdk/define`: declare an isolated package.
20
20
  *
@@ -30,6 +30,7 @@ Object.defineProperty(exports, "AccessLevel", { enumerable: true, get: function
30
30
  var observable_1 = require("../observable");
31
31
  Object.defineProperty(exports, "observable", { enumerable: true, get: function () { return observable_1.observable; } });
32
32
  var peer_id_1 = require("../peer-id");
33
+ Object.defineProperty(exports, "idFromKey", { enumerable: true, get: function () { return peer_id_1.idFromKey; } });
33
34
  Object.defineProperty(exports, "isid", { enumerable: true, get: function () { return peer_id_1.isid; } });
34
35
  Object.defineProperty(exports, "newid", { enumerable: true, get: function () { return peer_id_1.newid; } });
35
36
  var field_type_1 = require("../types/field-type");
@@ -501,7 +501,7 @@ function observableValueShape(name, schema) {
501
501
  return empty ? { ...shape, optional: true } : shape;
502
502
  }
503
503
  function tableManifest(table) {
504
- const { name, description, primaryKeyName, schema, versionNumber, localOnly } = table.definition;
504
+ const { name, description, primaryKeyName, schema, versionNumber, localOnly, indexes } = table.definition;
505
505
  return {
506
506
  name,
507
507
  description,
@@ -509,6 +509,14 @@ function tableManifest(table) {
509
509
  fields: describing(`Table ${name}`, () => irFields(schema)),
510
510
  ...(versionNumber === undefined ? {} : { versionNumber }),
511
511
  ...(localOnly ? { localOnly: true } : {}),
512
+ ...(indexes?.length
513
+ ? {
514
+ indexes: indexes.map((index) => ({
515
+ fields: index.fields.map((f) => typeof f === "string" ? f : { name: f.name, order: f.order }),
516
+ ...(index.unique ? { unique: true } : {}),
517
+ })),
518
+ }
519
+ : {}),
512
520
  };
513
521
  }
514
522
  /** One contract's manifest entry, with name-only references to its tables. */
@@ -16,6 +16,12 @@ export interface IPackageTableDefinition<S extends z.AnyZodObject = z.AnyZodObje
16
16
  versionNumber?: number;
17
17
  /** Keep rows on this device only. They never sync. */
18
18
  localOnly?: boolean;
19
+ /**
20
+ * Indexes for the fields queries filter or sort by, each in order (a field name, or a name with
21
+ * `"ASC"` or `"DESC"`). A local-only table can also make one `unique`. Changing them is a
22
+ * schema change, so raise `versionNumber`.
23
+ */
24
+ indexes?: IPackageTableIndex<S>[];
19
25
  /**
20
26
  * The table's class, to override its methods: `Feeds(ctx)` returns one, and so does every
21
27
  * consumer call through a contract, so an override is always the logic in use. Defaults to
@@ -23,6 +29,15 @@ export interface IPackageTableDefinition<S extends z.AnyZodObject = z.AnyZodObje
23
29
  */
24
30
  tableClass?: PackageTableClass<S>;
25
31
  }
32
+ /** One index of a {@link defineTable} table: its fields in order, each ascending unless set. */
33
+ export interface IPackageTableIndex<S extends z.AnyZodObject = z.AnyZodObject> {
34
+ fields: (Extract<keyof z.infer<S>, string> | {
35
+ name: Extract<keyof z.infer<S>, string>;
36
+ order: "ASC" | "DESC";
37
+ })[];
38
+ /** No two rows share these values. Only on a `localOnly` table: synced rows can collide. */
39
+ unique?: true;
40
+ }
26
41
  /** A class extending {@link PackageTable} for a table's schema. */
27
42
  export type PackageTableClass<S extends z.AnyZodObject = z.AnyZodObject> = new (ctx: IPackageContext, definition: Readonly<IPackageTableDefinition<S>>) => PackageTable<S>;
28
43
  /** One table's methods, bound to one handler call. */
@@ -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";
@@ -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;
@@ -48,8 +48,8 @@ export declare class Connection {
48
48
  get remoteDeviceInfo(): {
49
49
  publicKey: string;
50
50
  userId: string;
51
- deviceId: string;
52
51
  publicBoxKey: string;
52
+ deviceId: string;
53
53
  userName?: string | undefined;
54
54
  deviceName?: string | undefined;
55
55
  };
@@ -23,7 +23,7 @@
23
23
  * mismatch. AAD is the UTF-8 `connectionId`, binding every frame to the
24
24
  * connection it was sealed for.
25
25
  *
26
- * Design: `working/transport-security.md`.
26
+ * Design: `working/done/transport-security.md`.
27
27
  */
28
28
  /** Frame type byte for a sealed frame. The only cleartext byte on the wire once armed. */
29
29
  export declare const FRAME_ENC = 32;
@@ -24,7 +24,7 @@
24
24
  * mismatch. AAD is the UTF-8 `connectionId`, binding every frame to the
25
25
  * connection it was sealed for.
26
26
  *
27
- * Design: `working/transport-security.md`.
27
+ * Design: `working/done/transport-security.md`.
28
28
  */
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
30
  exports.FrameOpener = exports.FrameSealer = exports.FRAME_CIPHER_KEY_BYTES = exports.FRAME_CIPHER_OVERHEAD = exports.FRAME_CIPHER_TAG_BYTES = exports.FRAME_ENC = void 0;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getTrustLevelFn = getTrustLevelFn;
4
4
  const context_1 = require("../context");
5
5
  const data_1 = require("../data");
6
+ const user_permissions_1 = require("../data/user-permissions");
6
7
  const key_change_1 = require("../identity/key-change");
7
8
  const socket_type_1 = require("./socket.type");
8
9
  function applyReportedDeviceName(device, deviceInfo) {
@@ -32,9 +33,7 @@ function getTrustLevelFn(me, serverUrl) {
32
33
  return socket_type_1.TrustLevel.Untrusted;
33
34
  }
34
35
  // if this is my own device it is trusted
35
- if (deviceInfo.userId === me.userId &&
36
- deviceInfo.publicKey === me.publicKey &&
37
- deviceInfo.publicBoxKey === me.publicBoxKey) {
36
+ if ((0, user_permissions_1.sameUserIdentity)(deviceInfo, me)) {
38
37
  // if (deviceInfo.deviceId === thisDeviceId()) {
39
38
  // return TrustLevel.Untrusted;
40
39
  // }
@@ -96,9 +95,7 @@ function getTrustLevelFn(me, serverUrl) {
96
95
  (device ? deviceInfo.userId !== device.userId : false))) {
97
96
  return socket_type_1.TrustLevel.Untrusted;
98
97
  }
99
- if (effectiveUser &&
100
- (deviceInfo.publicKey !== effectiveUser.publicKey ||
101
- deviceInfo.publicBoxKey !== effectiveUser.publicBoxKey)) {
98
+ if (effectiveUser && !(0, user_permissions_1.sameUserIdentity)(deviceInfo, effectiveUser)) {
102
99
  // A different box key for the key on record is a mismatch. A different signing key is
103
100
  // accepted only when the anchors on record confirm a rotation.
104
101
  if (deviceInfo.publicKey === effectiveUser.publicKey) {