@peers-app/peers-sdk 0.27.5 → 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.
Files changed (81) 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 +8 -9
  33. package/dist/data/orm/table-container.js +14 -8
  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 +6 -0
  37. package/dist/data/package-table-identity.js +51 -0
  38. package/dist/data/package-version-resolver.d.ts +15 -0
  39. package/dist/data/package-version-resolver.js +58 -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/device/binary-peer-connection-v2.d.ts +1 -1
  54. package/dist/device/binary-peer-connection-v2.js +1 -1
  55. package/dist/device/connection.d.ts +1 -1
  56. package/dist/device/frame-cipher.d.ts +1 -1
  57. package/dist/device/frame-cipher.js +1 -1
  58. package/dist/device/get-trust-level-fn.js +3 -6
  59. package/dist/device-pairing/types.d.ts +26 -26
  60. package/dist/identity/user-row-change.d.ts +3 -1
  61. package/dist/identity/user-row-change.js +33 -18
  62. package/dist/invites/group-approval.js +23 -24
  63. package/dist/invites/invite-messages.d.ts +250 -28
  64. package/dist/invites/invite-token.d.ts +18 -0
  65. package/dist/invites/invite-token.js +2 -0
  66. package/dist/keys.d.ts +7 -0
  67. package/dist/keys.js +27 -0
  68. package/dist/package-installer/package-installer.d.ts +1 -1
  69. package/dist/package-installer/package-installer.js +8 -3
  70. package/dist/package-installer/package-propagation.d.ts +2 -0
  71. package/dist/package-installer/package-propagation.js +20 -38
  72. package/dist/package-installer/package-remote-checker.js +15 -3
  73. package/dist/package-loader/isolated-artifact.js +0 -2
  74. package/dist/package-loader/package-loader.js +6 -0
  75. package/dist/types/peer-device.d.ts +2 -0
  76. package/dist/types/workflow.d.ts +2 -2
  77. package/package.json +1 -1
  78. package/dist/data/package-permissions.d.ts +0 -14
  79. package/dist/data/package-permissions.js +0 -26
  80. package/dist/data/package-version-permissions.d.ts +0 -14
  81. 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
  }>;
@@ -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) {
@@ -1142,15 +1142,15 @@ export declare const devicePairingTranscriptSchema: z.ZodObject<{
1142
1142
  }, "strip", z.ZodTypeAny, {
1143
1143
  publicKey: string;
1144
1144
  userId: string;
1145
- deviceId: string;
1146
1145
  publicBoxKey: string;
1146
+ deviceId: string;
1147
1147
  userName?: string | undefined;
1148
1148
  deviceName?: string | undefined;
1149
1149
  }, {
1150
1150
  publicKey: string;
1151
1151
  userId: string;
1152
- deviceId: string;
1153
1152
  publicBoxKey: string;
1153
+ deviceId: string;
1154
1154
  userName?: string | undefined;
1155
1155
  deviceName?: string | undefined;
1156
1156
  }>;
@@ -1164,15 +1164,15 @@ export declare const devicePairingTranscriptSchema: z.ZodObject<{
1164
1164
  }, "strip", z.ZodTypeAny, {
1165
1165
  publicKey: string;
1166
1166
  userId: string;
1167
- deviceId: string;
1168
1167
  publicBoxKey: string;
1168
+ deviceId: string;
1169
1169
  userName?: string | undefined;
1170
1170
  deviceName?: string | undefined;
1171
1171
  }, {
1172
1172
  publicKey: string;
1173
1173
  userId: string;
1174
- deviceId: string;
1175
1174
  publicBoxKey: string;
1175
+ deviceId: string;
1176
1176
  userName?: string | undefined;
1177
1177
  deviceName?: string | undefined;
1178
1178
  }>;
@@ -1188,16 +1188,16 @@ export declare const devicePairingTranscriptSchema: z.ZodObject<{
1188
1188
  sourceIdentity: {
1189
1189
  publicKey: string;
1190
1190
  userId: string;
1191
- deviceId: string;
1192
1191
  publicBoxKey: string;
1192
+ deviceId: string;
1193
1193
  userName?: string | undefined;
1194
1194
  deviceName?: string | undefined;
1195
1195
  };
1196
1196
  destinationIdentity: {
1197
1197
  publicKey: string;
1198
1198
  userId: string;
1199
- deviceId: string;
1200
1199
  publicBoxKey: string;
1200
+ deviceId: string;
1201
1201
  userName?: string | undefined;
1202
1202
  deviceName?: string | undefined;
1203
1203
  };
@@ -1212,16 +1212,16 @@ export declare const devicePairingTranscriptSchema: z.ZodObject<{
1212
1212
  sourceIdentity: {
1213
1213
  publicKey: string;
1214
1214
  userId: string;
1215
- deviceId: string;
1216
1215
  publicBoxKey: string;
1216
+ deviceId: string;
1217
1217
  userName?: string | undefined;
1218
1218
  deviceName?: string | undefined;
1219
1219
  };
1220
1220
  destinationIdentity: {
1221
1221
  publicKey: string;
1222
1222
  userId: string;
1223
- deviceId: string;
1224
1223
  publicBoxKey: string;
1224
+ deviceId: string;
1225
1225
  userName?: string | undefined;
1226
1226
  deviceName?: string | undefined;
1227
1227
  };
@@ -1262,15 +1262,15 @@ export declare const pairingConfirmationContentsSchema: z.ZodObject<{
1262
1262
  }, "strip", z.ZodTypeAny, {
1263
1263
  publicKey: string;
1264
1264
  userId: string;
1265
- deviceId: string;
1266
1265
  publicBoxKey: string;
1266
+ deviceId: string;
1267
1267
  userName?: string | undefined;
1268
1268
  deviceName?: string | undefined;
1269
1269
  }, {
1270
1270
  publicKey: string;
1271
1271
  userId: string;
1272
- deviceId: string;
1273
1272
  publicBoxKey: string;
1273
+ deviceId: string;
1274
1274
  userName?: string | undefined;
1275
1275
  deviceName?: string | undefined;
1276
1276
  }>;
@@ -1293,8 +1293,8 @@ export declare const pairingConfirmationContentsSchema: z.ZodObject<{
1293
1293
  device: {
1294
1294
  publicKey: string;
1295
1295
  userId: string;
1296
- deviceId: string;
1297
1296
  publicBoxKey: string;
1297
+ deviceId: string;
1298
1298
  userName?: string | undefined;
1299
1299
  deviceName?: string | undefined;
1300
1300
  };
@@ -1310,8 +1310,8 @@ export declare const pairingConfirmationContentsSchema: z.ZodObject<{
1310
1310
  device: {
1311
1311
  publicKey: string;
1312
1312
  userId: string;
1313
- deviceId: string;
1314
1313
  publicBoxKey: string;
1314
+ deviceId: string;
1315
1315
  userName?: string | undefined;
1316
1316
  deviceName?: string | undefined;
1317
1317
  };
@@ -1342,15 +1342,15 @@ export declare const pairingConfirmationSchema: z.ZodObject<{
1342
1342
  }, "strip", z.ZodTypeAny, {
1343
1343
  publicKey: string;
1344
1344
  userId: string;
1345
- deviceId: string;
1346
1345
  publicBoxKey: string;
1346
+ deviceId: string;
1347
1347
  userName?: string | undefined;
1348
1348
  deviceName?: string | undefined;
1349
1349
  }, {
1350
1350
  publicKey: string;
1351
1351
  userId: string;
1352
- deviceId: string;
1353
1352
  publicBoxKey: string;
1353
+ deviceId: string;
1354
1354
  userName?: string | undefined;
1355
1355
  deviceName?: string | undefined;
1356
1356
  }>;
@@ -1375,8 +1375,8 @@ export declare const pairingConfirmationSchema: z.ZodObject<{
1375
1375
  device: {
1376
1376
  publicKey: string;
1377
1377
  userId: string;
1378
- deviceId: string;
1379
1378
  publicBoxKey: string;
1379
+ deviceId: string;
1380
1380
  userName?: string | undefined;
1381
1381
  deviceName?: string | undefined;
1382
1382
  };
@@ -1393,8 +1393,8 @@ export declare const pairingConfirmationSchema: z.ZodObject<{
1393
1393
  device: {
1394
1394
  publicKey: string;
1395
1395
  userId: string;
1396
- deviceId: string;
1397
1396
  publicBoxKey: string;
1397
+ deviceId: string;
1398
1398
  userName?: string | undefined;
1399
1399
  deviceName?: string | undefined;
1400
1400
  };
@@ -1460,15 +1460,15 @@ export declare const pairingInstallationReceiptContentsSchema: z.ZodObject<{
1460
1460
  }, "strip", z.ZodTypeAny, {
1461
1461
  publicKey: string;
1462
1462
  userId: string;
1463
- deviceId: string;
1464
1463
  publicBoxKey: string;
1464
+ deviceId: string;
1465
1465
  userName?: string | undefined;
1466
1466
  deviceName?: string | undefined;
1467
1467
  }, {
1468
1468
  publicKey: string;
1469
1469
  userId: string;
1470
- deviceId: string;
1471
1470
  publicBoxKey: string;
1471
+ deviceId: string;
1472
1472
  userName?: string | undefined;
1473
1473
  deviceName?: string | undefined;
1474
1474
  }>;
@@ -1479,8 +1479,8 @@ export declare const pairingInstallationReceiptContentsSchema: z.ZodObject<{
1479
1479
  initializedDevice: {
1480
1480
  publicKey: string;
1481
1481
  userId: string;
1482
- deviceId: string;
1483
1482
  publicBoxKey: string;
1483
+ deviceId: string;
1484
1484
  userName?: string | undefined;
1485
1485
  deviceName?: string | undefined;
1486
1486
  };
@@ -1491,8 +1491,8 @@ export declare const pairingInstallationReceiptContentsSchema: z.ZodObject<{
1491
1491
  initializedDevice: {
1492
1492
  publicKey: string;
1493
1493
  userId: string;
1494
- deviceId: string;
1495
1494
  publicBoxKey: string;
1495
+ deviceId: string;
1496
1496
  userName?: string | undefined;
1497
1497
  deviceName?: string | undefined;
1498
1498
  };
@@ -1515,15 +1515,15 @@ export declare const signedPairingInstallationReceiptSchema: z.ZodObject<{
1515
1515
  }, "strip", z.ZodTypeAny, {
1516
1516
  publicKey: string;
1517
1517
  userId: string;
1518
- deviceId: string;
1519
1518
  publicBoxKey: string;
1519
+ deviceId: string;
1520
1520
  userName?: string | undefined;
1521
1521
  deviceName?: string | undefined;
1522
1522
  }, {
1523
1523
  publicKey: string;
1524
1524
  userId: string;
1525
- deviceId: string;
1526
1525
  publicBoxKey: string;
1526
+ deviceId: string;
1527
1527
  userName?: string | undefined;
1528
1528
  deviceName?: string | undefined;
1529
1529
  }>;
@@ -1534,8 +1534,8 @@ export declare const signedPairingInstallationReceiptSchema: z.ZodObject<{
1534
1534
  initializedDevice: {
1535
1535
  publicKey: string;
1536
1536
  userId: string;
1537
- deviceId: string;
1538
1537
  publicBoxKey: string;
1538
+ deviceId: string;
1539
1539
  userName?: string | undefined;
1540
1540
  deviceName?: string | undefined;
1541
1541
  };
@@ -1546,8 +1546,8 @@ export declare const signedPairingInstallationReceiptSchema: z.ZodObject<{
1546
1546
  initializedDevice: {
1547
1547
  publicKey: string;
1548
1548
  userId: string;
1549
- deviceId: string;
1550
1549
  publicBoxKey: string;
1550
+ deviceId: string;
1551
1551
  userName?: string | undefined;
1552
1552
  deviceName?: string | undefined;
1553
1553
  };
@@ -1564,8 +1564,8 @@ export declare const signedPairingInstallationReceiptSchema: z.ZodObject<{
1564
1564
  initializedDevice: {
1565
1565
  publicKey: string;
1566
1566
  userId: string;
1567
- deviceId: string;
1568
1567
  publicBoxKey: string;
1568
+ deviceId: string;
1569
1569
  userName?: string | undefined;
1570
1570
  deviceName?: string | undefined;
1571
1571
  };
@@ -1580,8 +1580,8 @@ export declare const signedPairingInstallationReceiptSchema: z.ZodObject<{
1580
1580
  initializedDevice: {
1581
1581
  publicKey: string;
1582
1582
  userId: string;
1583
- deviceId: string;
1584
1583
  publicBoxKey: string;
1584
+ deviceId: string;
1585
1585
  userName?: string | undefined;
1586
1586
  deviceName?: string | undefined;
1587
1587
  };
@@ -33,9 +33,11 @@ export interface ResolveUserRowChangeParams {
33
33
  * The record is the personal `Users` row when it exists, else the row already stored in the
34
34
  * table being written. The rule:
35
35
  *
36
- * - Nothing stored yet: the row is the bootstrap and is applied as it is.
36
+ * - Nothing stored yet: bootstrap the identity; its initial anchors need an owner signature.
37
37
  * - A different key: the anchors on record decide ({@link evaluatePresentedKey}). The
38
38
  * presented anchor list is ignored; the applied row keeps the list on record.
39
+ * - The user's own row with their current keys: takes the anchor list from their personal row.
40
+ * - A row with no list keeps the list on record.
39
41
  * - The same key and a different list: when nothing is on record the list is accepted as the
40
42
  * bootstrap (an upgraded contact announcing its first anchors); when the personal record
41
43
  * already holds the list it is accepted; otherwise the anchors on record must publish it