@peers-app/peers-sdk 0.25.1 → 0.25.3

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 (35) hide show
  1. package/dist/contracts/__tests__/contract-resolvers.test.js +35 -2
  2. package/dist/contracts/__tests__/host-contract-consumer.test.d.ts +1 -0
  3. package/dist/contracts/__tests__/host-contract-consumer.test.js +163 -0
  4. package/dist/contracts/__tests__/system-contracts.test.js +14 -0
  5. package/dist/contracts/contract-resolvers.d.ts +14 -2
  6. package/dist/contracts/contract-resolvers.js +69 -6
  7. package/dist/contracts/host-contract-consumer.d.ts +40 -0
  8. package/dist/contracts/host-contract-consumer.js +105 -0
  9. package/dist/contracts/index.d.ts +2 -0
  10. package/dist/contracts/index.js +7 -2
  11. package/dist/contracts/system/identity-contract.d.ts +43 -0
  12. package/dist/contracts/system/identity-contract.js +133 -0
  13. package/dist/contracts/system/index.d.ts +2 -0
  14. package/dist/contracts/system/index.js +5 -1
  15. package/dist/contracts/types.d.ts +6 -0
  16. package/dist/data/devices.d.ts +4 -4
  17. package/dist/data/group-share.js +0 -38
  18. package/dist/data/index.d.ts +1 -0
  19. package/dist/data/index.js +1 -0
  20. package/dist/data/invites.d.ts +40 -40
  21. package/dist/data/invites.js +4 -2
  22. package/dist/data/peers-services-registration.pvar.d.ts +37 -0
  23. package/dist/data/peers-services-registration.pvar.js +57 -0
  24. package/dist/data/tool-access-approvals.d.ts +3 -3
  25. package/dist/device/connection.d.ts +1 -1
  26. package/dist/device/device.d.ts +1 -1
  27. package/dist/device-pairing/constants.d.ts +0 -2
  28. package/dist/device-pairing/constants.js +1 -3
  29. package/dist/device-pairing/types.d.ts +80 -80
  30. package/dist/invites/invite-messages.d.ts +12 -12
  31. package/dist/rpc-types.d.ts +0 -14
  32. package/dist/rpc-types.js +0 -13
  33. package/dist/system-ids.d.ts +17 -0
  34. package/dist/system-ids.js +18 -1
  35. package/package.json +1 -1
@@ -0,0 +1,43 @@
1
+ import type { DevicePairingCeremonyAction, DevicePairingStartDestinationInput, DevicePairingStartSourceInput, DevicePairingState } from "../../device-pairing";
2
+ import type { Observable } from "../../observable";
3
+ import type { IContractConsumerBase } from "../contract-proxy";
4
+ import type { IContractDefinition } from "../types";
5
+ /** Version of the built-in System Identity contract. */
6
+ export declare const IDENTITY_CONTRACT_VERSION = 1;
7
+ /** Who is signed in on this host, and whether they registered with peers-services. */
8
+ export interface IIdentitySessionInfo {
9
+ /** Signed-in user, absent on the setup screen. */
10
+ userId?: string;
11
+ /** True when this user has completed peers-services registration on this device. */
12
+ registered: boolean;
13
+ }
14
+ /**
15
+ * Local-only host contract for device pairing and the signed-in session.
16
+ *
17
+ * It resolves before sign-in (`requiresUserContext: false`) so the setup screen can
18
+ * show a pairing code. Remote device connections must not resolve it. Pairing progress
19
+ * is the `state` observable; there is no separate get-state tool.
20
+ */
21
+ export declare function getIdentityContractDefinition(): IContractDefinition;
22
+ /** Consumer-side TypeScript shape for System Identity. */
23
+ export interface IIdentityConsumer extends IContractConsumerBase {
24
+ tools: {
25
+ startSource(input: DevicePairingStartSourceInput): Promise<DevicePairingState>;
26
+ startDestination(input?: DevicePairingStartDestinationInput): Promise<DevicePairingState>;
27
+ approve(input: DevicePairingCeremonyAction): Promise<DevicePairingState>;
28
+ reject(input: DevicePairingCeremonyAction): Promise<DevicePairingState>;
29
+ cancel(input: DevicePairingCeremonyAction): Promise<DevicePairingState>;
30
+ getSession(): Promise<IIdentitySessionInfo>;
31
+ signIn(input: {
32
+ userId: string;
33
+ secretKey: string;
34
+ }): Promise<void>;
35
+ signOut(): Promise<void>;
36
+ registerWithPeersServices(): Promise<{
37
+ token: string;
38
+ }>;
39
+ };
40
+ observables: {
41
+ state: Observable<DevicePairingState>;
42
+ };
43
+ }
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IDENTITY_CONTRACT_VERSION = void 0;
4
+ exports.getIdentityContractDefinition = getIdentityContractDefinition;
5
+ const system_ids_1 = require("../../system-ids");
6
+ const field_type_1 = require("../../types/field-type");
7
+ const system_contracts_1 = require("../system-contracts");
8
+ /** Version of the built-in System Identity contract. */
9
+ exports.IDENTITY_CONTRACT_VERSION = 1;
10
+ const field = (name, type, description, opts = {}) => ({ name, type, description, ...opts });
11
+ let definition;
12
+ /**
13
+ * Fields of {@link DevicePairingState}. Ceremony tools return this object directly.
14
+ */
15
+ const pairingStateFields = [
16
+ field("sessionId", field_type_1.FieldType.id, "Active ceremony id.", { optional: true }),
17
+ field("role", field_type_1.FieldType.string, "source or destination.", { optional: true }),
18
+ field("phase", field_type_1.FieldType.string, "idle, showing-code, connecting, authenticating, waiting-for-approval, transferring, complete, rejected, or error."),
19
+ field("expiresAt", field_type_1.FieldType.number, "Unix milliseconds when the ceremony expires.", {
20
+ optional: true,
21
+ }),
22
+ field("remoteDevice", field_type_1.FieldType.object, "Name, user, and type presented by the other device.", {
23
+ optional: true,
24
+ }),
25
+ field("code", field_type_1.FieldType.string, "Pairing code the destination is showing.", { optional: true }),
26
+ field("notice", field_type_1.FieldType.string, "Non-fatal message alongside the current phase.", {
27
+ optional: true,
28
+ }),
29
+ field("error", field_type_1.FieldType.string, "Failure message when the phase is error.", { optional: true }),
30
+ ];
31
+ /**
32
+ * Local-only host contract for device pairing and the signed-in session.
33
+ *
34
+ * It resolves before sign-in (`requiresUserContext: false`) so the setup screen can
35
+ * show a pairing code. Remote device connections must not resolve it. Pairing progress
36
+ * is the `state` observable; there is no separate get-state tool.
37
+ */
38
+ function getIdentityContractDefinition() {
39
+ definition ??= {
40
+ contractId: system_ids_1.identityContractId,
41
+ version: exports.IDENTITY_CONTRACT_VERSION,
42
+ devTag: "dev",
43
+ name: "System Identity",
44
+ description: "Device pairing ceremony and the local signed-in session.",
45
+ requiresUserContext: false,
46
+ tables: [],
47
+ tools: [
48
+ {
49
+ name: "startSource",
50
+ usageDescription: "Join a pairing room from a code shown on a new device.",
51
+ inputFields: [field("code", field_type_1.FieldType.string, "Pairing code from the new device.")],
52
+ outputFields: pairingStateFields,
53
+ },
54
+ {
55
+ name: "startDestination",
56
+ usageDescription: "Show a pairing code on this signed-out device.",
57
+ inputFields: [
58
+ field("deviceName", field_type_1.FieldType.string, "Name to present for this device.", {
59
+ optional: true,
60
+ }),
61
+ field("deviceType", field_type_1.FieldType.string, "Kind of device, such as browser or desktop.", {
62
+ optional: true,
63
+ }),
64
+ ],
65
+ outputFields: pairingStateFields,
66
+ },
67
+ {
68
+ name: "approve",
69
+ usageDescription: "Approve the active pairing ceremony and send credentials.",
70
+ inputFields: [field("sessionId", field_type_1.FieldType.id, "Active ceremony id.")],
71
+ outputFields: pairingStateFields,
72
+ },
73
+ {
74
+ name: "reject",
75
+ usageDescription: "Reject the active pairing ceremony.",
76
+ inputFields: [field("sessionId", field_type_1.FieldType.id, "Active ceremony id.")],
77
+ outputFields: pairingStateFields,
78
+ },
79
+ {
80
+ name: "cancel",
81
+ usageDescription: "Cancel the active pairing ceremony.",
82
+ inputFields: [field("sessionId", field_type_1.FieldType.id, "Active ceremony id.")],
83
+ outputFields: pairingStateFields,
84
+ },
85
+ {
86
+ name: "getSession",
87
+ usageDescription: "Return the signed-in user, if any, and peers-services registration.",
88
+ inputFields: [],
89
+ outputFields: [
90
+ field("userId", field_type_1.FieldType.id, "Signed-in user id.", { optional: true }),
91
+ field("registered", field_type_1.FieldType.boolean, "Whether peers-services registration completed."),
92
+ ],
93
+ },
94
+ {
95
+ name: "signIn",
96
+ usageDescription: "Store a user id and secret key and start the local runtime.",
97
+ inputFields: [
98
+ field("userId", field_type_1.FieldType.id, "User id to sign in as."),
99
+ field("secretKey", field_type_1.FieldType.string, "Secret key for that user."),
100
+ ],
101
+ outputFields: [],
102
+ },
103
+ {
104
+ name: "signOut",
105
+ usageDescription: "Clear the local credentials and leave the signed-in session.",
106
+ inputFields: [],
107
+ outputFields: [],
108
+ },
109
+ {
110
+ name: "registerWithPeersServices",
111
+ usageDescription: "Register or authenticate this user with peers-services and return a JWT.",
112
+ inputFields: [],
113
+ outputFields: [field("token", field_type_1.FieldType.string, "peers-services JWT.")],
114
+ },
115
+ ],
116
+ observables: [
117
+ {
118
+ name: "state",
119
+ description: "Live device-pairing ceremony state.",
120
+ valueType: field_type_1.FieldType.object,
121
+ writable: false,
122
+ },
123
+ ],
124
+ events: [],
125
+ };
126
+ return definition;
127
+ }
128
+ (0, system_contracts_1.registerSystemContract)({
129
+ providerPackageId: system_ids_1.peersSystemPackageId,
130
+ contractId: system_ids_1.identityContractId,
131
+ version: exports.IDENTITY_CONTRACT_VERSION,
132
+ getDefinition: getIdentityContractDefinition,
133
+ });
@@ -3,11 +3,13 @@
3
3
  * {@link registerSystemContract} side effect so the catalog is populated.
4
4
  */
5
5
  import "./device-operations-contract";
6
+ import "./identity-contract";
6
7
  import "./invites-contract";
7
8
  import "./logs-contract";
8
9
  import "./network-contracts";
9
10
  import "./tool-access-control-contract";
10
11
  export { DEVICE_OPERATIONS_CONTRACT_VERSION, DEVICE_OPERATIONS_MAX_QUERY_LENGTH, DEVICE_OPERATIONS_MAX_RESULT_BYTES, DEVICE_OPERATIONS_MAX_ROWS, DEVICE_OPERATIONS_MAX_TOOLS, type DeviceOperationCapability, deviceOperationsProviderPackageId, deviceOperationsToolIds, getDeviceOperationsContractDefinition, type IDeviceDatabaseQueryInput, type IDeviceDatabaseQueryResult, type IDeviceOperationStatus, type IDeviceToolListInput, type IDeviceToolLookupInput, type IDeviceToolLookupResult, type IDeviceToolRunInput, } from "./device-operations-contract";
12
+ export { getIdentityContractDefinition, IDENTITY_CONTRACT_VERSION, type IIdentityConsumer, type IIdentitySessionInfo, } from "./identity-contract";
11
13
  export { getInvitesContractDefinition, type IAcceptInviteResult, type ICreatedInvite, type IInvitePreview, type IInvitesConsumer, INVITES_CONTRACT_VERSION, } from "./invites-contract";
12
14
  export { getLogsContractDefinition, type ILogsConsumer, LOGS_CONTRACT_VERSION, resolveLogsContract, } from "./logs-contract";
13
15
  export * from "./network-contracts";
@@ -14,12 +14,13 @@ 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.TOOL_ACCESS_CONTROL_CONTRACT_VERSION = exports.getToolAccessControlContractDefinition = exports.resolveLogsContract = exports.LOGS_CONTRACT_VERSION = exports.getLogsContractDefinition = exports.INVITES_CONTRACT_VERSION = exports.getInvitesContractDefinition = exports.getDeviceOperationsContractDefinition = exports.deviceOperationsToolIds = exports.deviceOperationsProviderPackageId = exports.DEVICE_OPERATIONS_MAX_TOOLS = exports.DEVICE_OPERATIONS_MAX_ROWS = exports.DEVICE_OPERATIONS_MAX_RESULT_BYTES = exports.DEVICE_OPERATIONS_MAX_QUERY_LENGTH = exports.DEVICE_OPERATIONS_CONTRACT_VERSION = void 0;
17
+ exports.TOOL_ACCESS_CONTROL_CONTRACT_VERSION = exports.getToolAccessControlContractDefinition = exports.resolveLogsContract = exports.LOGS_CONTRACT_VERSION = exports.getLogsContractDefinition = exports.INVITES_CONTRACT_VERSION = exports.getInvitesContractDefinition = exports.IDENTITY_CONTRACT_VERSION = exports.getIdentityContractDefinition = exports.getDeviceOperationsContractDefinition = exports.deviceOperationsToolIds = exports.deviceOperationsProviderPackageId = exports.DEVICE_OPERATIONS_MAX_TOOLS = exports.DEVICE_OPERATIONS_MAX_ROWS = exports.DEVICE_OPERATIONS_MAX_RESULT_BYTES = exports.DEVICE_OPERATIONS_MAX_QUERY_LENGTH = exports.DEVICE_OPERATIONS_CONTRACT_VERSION = void 0;
18
18
  /**
19
19
  * Built-in system contracts. Importing this barrel runs each module's
20
20
  * {@link registerSystemContract} side effect so the catalog is populated.
21
21
  */
22
22
  require("./device-operations-contract");
23
+ require("./identity-contract");
23
24
  require("./invites-contract");
24
25
  require("./logs-contract");
25
26
  require("./network-contracts");
@@ -33,6 +34,9 @@ Object.defineProperty(exports, "DEVICE_OPERATIONS_MAX_TOOLS", { enumerable: true
33
34
  Object.defineProperty(exports, "deviceOperationsProviderPackageId", { enumerable: true, get: function () { return device_operations_contract_1.deviceOperationsProviderPackageId; } });
34
35
  Object.defineProperty(exports, "deviceOperationsToolIds", { enumerable: true, get: function () { return device_operations_contract_1.deviceOperationsToolIds; } });
35
36
  Object.defineProperty(exports, "getDeviceOperationsContractDefinition", { enumerable: true, get: function () { return device_operations_contract_1.getDeviceOperationsContractDefinition; } });
37
+ var identity_contract_1 = require("./identity-contract");
38
+ Object.defineProperty(exports, "getIdentityContractDefinition", { enumerable: true, get: function () { return identity_contract_1.getIdentityContractDefinition; } });
39
+ Object.defineProperty(exports, "IDENTITY_CONTRACT_VERSION", { enumerable: true, get: function () { return identity_contract_1.IDENTITY_CONTRACT_VERSION; } });
36
40
  var invites_contract_1 = require("./invites-contract");
37
41
  Object.defineProperty(exports, "getInvitesContractDefinition", { enumerable: true, get: function () { return invites_contract_1.getInvitesContractDefinition; } });
38
42
  Object.defineProperty(exports, "INVITES_CONTRACT_VERSION", { enumerable: true, get: function () { return invites_contract_1.INVITES_CONTRACT_VERSION; } });
@@ -25,6 +25,12 @@ export interface IContractDefinition {
25
25
  * emits an array (possibly empty) and consumers read `contract.events ?? []`.
26
26
  */
27
27
  events?: IContractEvent[];
28
+ /**
29
+ * When `false`, the local host may resolve this contract before anyone is
30
+ * signed in. Defaults to requiring a user context. The host router honors this
31
+ * only when the provider registers with `requiresUserContext: false`.
32
+ */
33
+ requiresUserContext?: boolean;
28
34
  }
29
35
  /** Table shape within a contract — derived from ITableMetaData + IField[]. */
30
36
  export interface IContractTable {
@@ -49,15 +49,15 @@ export declare const deviceInfoSchema: z.ZodObject<{
49
49
  publicBoxKey: string;
50
50
  userId: string;
51
51
  deviceId: string;
52
- deviceName?: string | undefined;
53
52
  userName?: string | undefined;
53
+ deviceName?: string | undefined;
54
54
  }, {
55
55
  publicKey: string;
56
56
  publicBoxKey: string;
57
57
  userId: string;
58
58
  deviceId: string;
59
- deviceName?: string | undefined;
60
59
  userName?: string | undefined;
60
+ deviceName?: string | undefined;
61
61
  }>;
62
62
  /** Signed identity and optional presentation hints advertised by a device. */
63
63
  export type IDeviceInfo = z.infer<typeof deviceInfoSchema>;
@@ -81,8 +81,8 @@ export declare const deviceHandshakeSchema: z.ZodObject<{
81
81
  deviceId: string;
82
82
  connectionId: string;
83
83
  serverAddress: string;
84
- deviceName?: string | undefined;
85
84
  userName?: string | undefined;
85
+ deviceName?: string | undefined;
86
86
  }, {
87
87
  timestamp: number;
88
88
  publicKey: string;
@@ -91,8 +91,8 @@ export declare const deviceHandshakeSchema: z.ZodObject<{
91
91
  deviceId: string;
92
92
  connectionId: string;
93
93
  serverAddress: string;
94
- deviceName?: string | undefined;
95
94
  userName?: string | undefined;
95
+ deviceName?: string | undefined;
96
96
  }>;
97
97
  /** Signed device information bound to one connection handshake. */
98
98
  export type IDeviceHandshake = z.infer<typeof deviceHandshakeSchema>;
@@ -4,7 +4,6 @@ exports.generateGroupShare = generateGroupShare;
4
4
  exports.seedGroupContextFromShare = seedGroupContextFromShare;
5
5
  exports.validateGroupShare = validateGroupShare;
6
6
  exports.copyToClipboard = copyToClipboard;
7
- const __1 = require("..");
8
7
  const user_context_singleton_1 = require("../context/user-context-singleton");
9
8
  const group_member_roles_1 = require("./group-member-roles");
10
9
  const group_members_1 = require("./group-members");
@@ -36,37 +35,6 @@ async function generateGroupShare(groupId) {
36
35
  };
37
36
  return groupShare;
38
37
  }
39
- /**
40
- * Imports a GroupShare object, creating the group and seeding admin members
41
- * @param groupShareJson JSON string containing the GroupShare data
42
- * @returns Promise<string> The imported group ID
43
- * @throws Error if JSON invalid or import fails
44
- */
45
- async function importGroupShare(groupShareJson) {
46
- // Parse and validate JSON
47
- let groupShare;
48
- try {
49
- groupShare = JSON.parse(groupShareJson);
50
- }
51
- catch (_error) {
52
- throw new Error("Invalid JSON format");
53
- }
54
- // Validate structure - maybe redo this with a zod schema
55
- if (!validateGroupShare(groupShare)) {
56
- throw new Error("Invalid GroupShare structure");
57
- }
58
- const userContext = await (0, user_context_singleton_1.getUserContext)();
59
- const { group } = groupShare;
60
- // Check if group already exists
61
- const existingGroup = await (0, groups_1.Groups)(userContext.userDataContext).get(group.groupId);
62
- if (existingGroup) {
63
- throw new Error(`Group "${group.name}" already exists`);
64
- }
65
- // Save group to user's groups table
66
- await (0, groups_1.Groups)(userContext.userDataContext).save(group, { restoreIfDeleted: true });
67
- await seedGroupContextFromShare(userContext, groupShare);
68
- return group.groupId;
69
- }
70
38
  /**
71
39
  * Write a group record and missing membership rows into the group's data context.
72
40
  *
@@ -172,12 +140,6 @@ async function copyToClipboard(text) {
172
140
  return false;
173
141
  }
174
142
  }
175
- // get around circular dependency issue
176
- setTimeout(() => {
177
- if (__1.rpcServerCalls) {
178
- __1.rpcServerCalls.importGroupShare = (groupShareJson) => importGroupShare(groupShareJson);
179
- }
180
- }, 10);
181
143
  function getLowestDataSource(table) {
182
144
  let ds = table.dataSource;
183
145
  for (let i = 0; i < 100; i++) {
@@ -21,6 +21,7 @@ export * from "./package-versions";
21
21
  export * from "./packages";
22
22
  export * from "./packages.utils";
23
23
  export * from "./peer-types";
24
+ export * from "./peers-services-registration.pvar";
24
25
  export * from "./persistent-vars";
25
26
  export * from "./sync-recovery-queue";
26
27
  export * from "./table-definitions-table";
@@ -37,6 +37,7 @@ __exportStar(require("./package-versions"), exports);
37
37
  __exportStar(require("./packages"), exports);
38
38
  __exportStar(require("./packages.utils"), exports);
39
39
  __exportStar(require("./peer-types"), exports);
40
+ __exportStar(require("./peers-services-registration.pvar"), exports);
40
41
  __exportStar(require("./persistent-vars"), exports);
41
42
  __exportStar(require("./sync-recovery-queue"), exports);
42
43
  __exportStar(require("./table-definitions-table"), exports);
@@ -10,7 +10,7 @@ export type InviteStatus = z.infer<typeof inviteStatusSchema>;
10
10
  * - `direct`: a known contact was invited to a group (3a); the payload is the approval.
11
11
  * - `approve`: group link whose join requests the inviter approves (3b).
12
12
  * - `open`: group link any Admin+ member auto-approves (3c).
13
- * - `profile`: the reusable contact QR on the Account screen.
13
+ * - `profile`: the reusable contact QR on Identity → People.
14
14
  * - `contact`: a one-off contact token.
15
15
  */
16
16
  export declare const inviteModeSchema: z.ZodEnum<["direct", "approve", "open", "profile", "contact"]>;
@@ -28,7 +28,7 @@ export declare const inviteDeliveryStateSchema: z.ZodEnum<["queued", "sent"]>;
28
28
  export declare const inviteSchema: z.ZodObject<{
29
29
  inviteId: z.ZodEffects<z.ZodString, string, string>;
30
30
  direction: z.ZodEnum<["in", "out"]>;
31
- type: z.ZodEnum<["contact", "group"]>;
31
+ type: z.ZodEnum<["contact", "group", "device"]>;
32
32
  status: z.ZodDefault<z.ZodEnum<["pending", "accepted", "declined", "expired", "revoked"]>>;
33
33
  mode: z.ZodEnum<["direct", "approve", "open", "profile", "contact"]>;
34
34
  /** The other party, once known (unknown for outstanding link invites). */
@@ -179,25 +179,22 @@ export declare const inviteSchema: z.ZodObject<{
179
179
  resolvedAt: z.ZodOptional<z.ZodDate>;
180
180
  note: z.ZodOptional<z.ZodString>;
181
181
  }, "strip", z.ZodTypeAny, {
182
- type: "group" | "contact";
182
+ type: "group" | "device" | "contact";
183
183
  direction: "in" | "out";
184
184
  status: "pending" | "expired" | "accepted" | "declined" | "revoked";
185
- expiresAt: Date;
186
185
  createdAt: Date;
186
+ expiresAt: Date;
187
187
  mode: "direct" | "open" | "approve" | "contact" | "profile";
188
188
  epoch: number;
189
189
  inviteId: string;
190
190
  role?: GroupMemberRole | undefined;
191
191
  nonce?: string | undefined;
192
192
  groupId?: string | undefined;
193
- counterpart?: {
194
- publicKey: string;
195
- publicBoxKey: string;
196
- userId: string;
197
- displayName?: string | undefined;
193
+ payload?: {
194
+ nonce: string;
195
+ contents: string;
196
+ fromPublicKey: string;
198
197
  } | undefined;
199
- counterpartDeviceId?: string | undefined;
200
- groupName?: string | undefined;
201
198
  token?: {
202
199
  type: "group" | "contact";
203
200
  nonce: string;
@@ -221,18 +218,21 @@ export declare const inviteSchema: z.ZodObject<{
221
218
  mode: "open" | "approve";
222
219
  } | undefined;
223
220
  } | undefined;
224
- payload?: {
225
- nonce: string;
226
- contents: string;
227
- fromPublicKey: string;
221
+ counterpart?: {
222
+ publicKey: string;
223
+ publicBoxKey: string;
224
+ userId: string;
225
+ displayName?: string | undefined;
228
226
  } | undefined;
227
+ counterpartDeviceId?: string | undefined;
228
+ groupName?: string | undefined;
229
229
  parentInviteId?: string | undefined;
230
230
  deliveryState?: "queued" | "sent" | undefined;
231
231
  recipientUserId?: string | undefined;
232
232
  resolvedAt?: Date | undefined;
233
233
  note?: string | undefined;
234
234
  }, {
235
- type: "group" | "contact";
235
+ type: "group" | "device" | "contact";
236
236
  direction: "in" | "out";
237
237
  expiresAt: Date;
238
238
  mode: "direct" | "open" | "approve" | "contact" | "profile";
@@ -243,14 +243,11 @@ export declare const inviteSchema: z.ZodObject<{
243
243
  status?: "pending" | "expired" | "accepted" | "declined" | "revoked" | undefined;
244
244
  groupId?: string | undefined;
245
245
  createdAt?: Date | undefined;
246
- counterpart?: {
247
- publicKey: string;
248
- publicBoxKey: string;
249
- userId: string;
250
- displayName?: string | undefined;
246
+ payload?: {
247
+ nonce: string;
248
+ contents: string;
249
+ fromPublicKey: string;
251
250
  } | undefined;
252
- counterpartDeviceId?: string | undefined;
253
- groupName?: string | undefined;
254
251
  token?: {
255
252
  type: "group" | "contact";
256
253
  nonce: string;
@@ -274,11 +271,14 @@ export declare const inviteSchema: z.ZodObject<{
274
271
  mode: "open" | "approve";
275
272
  } | undefined;
276
273
  } | undefined;
277
- payload?: {
278
- nonce: string;
279
- contents: string;
280
- fromPublicKey: string;
274
+ counterpart?: {
275
+ publicKey: string;
276
+ publicBoxKey: string;
277
+ userId: string;
278
+ displayName?: string | undefined;
281
279
  } | undefined;
280
+ counterpartDeviceId?: string | undefined;
281
+ groupName?: string | undefined;
282
282
  parentInviteId?: string | undefined;
283
283
  deliveryState?: "queued" | "sent" | undefined;
284
284
  recipientUserId?: string | undefined;
@@ -293,25 +293,22 @@ export type IInvite = z.infer<typeof inviteSchema>;
293
293
  * @param dataContext - Optional data context; defaults to the current singleton.
294
294
  */
295
295
  export declare function Invites(dataContext?: DataContext): import("..").Table<{
296
- type: "group" | "contact";
296
+ type: "group" | "device" | "contact";
297
297
  direction: "in" | "out";
298
298
  status: "pending" | "expired" | "accepted" | "declined" | "revoked";
299
- expiresAt: Date;
300
299
  createdAt: Date;
300
+ expiresAt: Date;
301
301
  mode: "direct" | "open" | "approve" | "contact" | "profile";
302
302
  epoch: number;
303
303
  inviteId: string;
304
304
  role?: GroupMemberRole | undefined;
305
305
  nonce?: string | undefined;
306
306
  groupId?: string | undefined;
307
- counterpart?: {
308
- publicKey: string;
309
- publicBoxKey: string;
310
- userId: string;
311
- displayName?: string | undefined;
307
+ payload?: {
308
+ nonce: string;
309
+ contents: string;
310
+ fromPublicKey: string;
312
311
  } | undefined;
313
- counterpartDeviceId?: string | undefined;
314
- groupName?: string | undefined;
315
312
  token?: {
316
313
  type: "group" | "contact";
317
314
  nonce: string;
@@ -335,11 +332,14 @@ export declare function Invites(dataContext?: DataContext): import("..").Table<{
335
332
  mode: "open" | "approve";
336
333
  } | undefined;
337
334
  } | undefined;
338
- payload?: {
339
- nonce: string;
340
- contents: string;
341
- fromPublicKey: string;
335
+ counterpart?: {
336
+ publicKey: string;
337
+ publicBoxKey: string;
338
+ userId: string;
339
+ displayName?: string | undefined;
342
340
  } | undefined;
341
+ counterpartDeviceId?: string | undefined;
342
+ groupName?: string | undefined;
343
343
  parentInviteId?: string | undefined;
344
344
  deliveryState?: "queued" | "sent" | undefined;
345
345
  recipientUserId?: string | undefined;
@@ -17,7 +17,7 @@ exports.inviteStatusSchema = zod_1.z.enum(["pending", "accepted", "declined", "e
17
17
  * - `direct`: a known contact was invited to a group (3a); the payload is the approval.
18
18
  * - `approve`: group link whose join requests the inviter approves (3b).
19
19
  * - `open`: group link any Admin+ member auto-approves (3c).
20
- * - `profile`: the reusable contact QR on the Account screen.
20
+ * - `profile`: the reusable contact QR on Identity → People.
21
21
  * - `contact`: a one-off contact token.
22
22
  */
23
23
  exports.inviteModeSchema = zod_1.z.enum(["direct", "approve", "open", "profile", "contact"]);
@@ -33,7 +33,9 @@ exports.inviteDeliveryStateSchema = zod_1.z.enum(["queued", "sent"]);
33
33
  exports.inviteSchema = zod_1.z.object({
34
34
  inviteId: zod_types_1.zodPeerId,
35
35
  direction: zod_1.z.enum(["in", "out"]).describe("Whether I issued (out) or received (in) this item"),
36
- type: zod_1.z.enum(["contact", "group"]),
36
+ type: zod_1.z
37
+ .enum(["contact", "group", "device"])
38
+ .describe("contact, group, or a device admission slot (nothing produces device rows yet)"),
37
39
  status: exports.inviteStatusSchema.default("pending"),
38
40
  mode: exports.inviteModeSchema,
39
41
  /** The other party, once known (unknown for outstanding link invites). */
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Persistent variables that record a user's registration with `peers-services`.
3
+ *
4
+ * These are the single definition of the variable names. The device runtime reads
5
+ * {@link PEERS_SERVICES_TOKEN_VAR} to authenticate mailbox calls; UIs and headless hosts write
6
+ * both variables through {@link persistPeersServicesRegistration} after a successful
7
+ * `registerWithPeersServices` RPC.
8
+ */
9
+ /** Name of the secret user variable that holds the `peers-services` JWT. */
10
+ export declare const PEERS_SERVICES_TOKEN_VAR = "PEERS_SERVICES_TOKEN";
11
+ /** Name of the user variable that records when registration completed (ISO timestamp). */
12
+ export declare const PEERS_SERVICES_REGISTERED_VAR = "PEERS_SERVICES_REGISTERED";
13
+ /** Set when the user has completed challenge-response registration (ISO timestamp). */
14
+ export declare const registrationStatusPvar: import("./persistent-vars").PersistentVar<string>;
15
+ /**
16
+ * The `peers-services` JWT, encrypted at rest with the user's secret key and synced to all of
17
+ * the user's devices.
18
+ */
19
+ export declare const servicesTokenPvar: import("./persistent-vars").PersistentVar<string>;
20
+ /**
21
+ * Store the JWT and the local "registered" flag after a successful `registerWithPeersServices`
22
+ * call.
23
+ *
24
+ * Waits for both variables to finish loading first: a value written before the initial load
25
+ * completes is overwritten by the stored (empty) value when the load lands. Resolves once the
26
+ * new values have been saved, so a host can register, persist, and only then report ready.
27
+ * UIs may call this without awaiting.
28
+ */
29
+ export declare function persistPeersServicesRegistration(token: string): Promise<void>;
30
+ /**
31
+ * Replace the stored JWT after a routine re-authentication.
32
+ *
33
+ * Unlike {@link persistPeersServicesRegistration} this leaves the "registered" timestamp
34
+ * alone: the user registered once, and the Account screen shows that date, not the date of
35
+ * the latest token renewal. Same loading-promise discipline as the registration write.
36
+ */
37
+ export declare function persistPeersServicesToken(token: string): Promise<void>;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /**
3
+ * Persistent variables that record a user's registration with `peers-services`.
4
+ *
5
+ * These are the single definition of the variable names. The device runtime reads
6
+ * {@link PEERS_SERVICES_TOKEN_VAR} to authenticate mailbox calls; UIs and headless hosts write
7
+ * both variables through {@link persistPeersServicesRegistration} after a successful
8
+ * `registerWithPeersServices` RPC.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.servicesTokenPvar = exports.registrationStatusPvar = exports.PEERS_SERVICES_REGISTERED_VAR = exports.PEERS_SERVICES_TOKEN_VAR = void 0;
12
+ exports.persistPeersServicesRegistration = persistPeersServicesRegistration;
13
+ exports.persistPeersServicesToken = persistPeersServicesToken;
14
+ const persistent_vars_1 = require("./persistent-vars");
15
+ /** Name of the secret user variable that holds the `peers-services` JWT. */
16
+ exports.PEERS_SERVICES_TOKEN_VAR = "PEERS_SERVICES_TOKEN";
17
+ /** Name of the user variable that records when registration completed (ISO timestamp). */
18
+ exports.PEERS_SERVICES_REGISTERED_VAR = "PEERS_SERVICES_REGISTERED";
19
+ /** Set when the user has completed challenge-response registration (ISO timestamp). */
20
+ exports.registrationStatusPvar = (0, persistent_vars_1.userVar)(exports.PEERS_SERVICES_REGISTERED_VAR, {
21
+ defaultValue: "",
22
+ });
23
+ /**
24
+ * The `peers-services` JWT, encrypted at rest with the user's secret key and synced to all of
25
+ * the user's devices.
26
+ */
27
+ exports.servicesTokenPvar = (0, persistent_vars_1.userVar)(exports.PEERS_SERVICES_TOKEN_VAR, {
28
+ isSecret: true,
29
+ defaultValue: "",
30
+ });
31
+ /**
32
+ * Store the JWT and the local "registered" flag after a successful `registerWithPeersServices`
33
+ * call.
34
+ *
35
+ * Waits for both variables to finish loading first: a value written before the initial load
36
+ * completes is overwritten by the stored (empty) value when the load lands. Resolves once the
37
+ * new values have been saved, so a host can register, persist, and only then report ready.
38
+ * UIs may call this without awaiting.
39
+ */
40
+ async function persistPeersServicesRegistration(token) {
41
+ await Promise.all([exports.servicesTokenPvar.loadingPromise, exports.registrationStatusPvar.loadingPromise]);
42
+ (0, exports.servicesTokenPvar)(token);
43
+ (0, exports.registrationStatusPvar)(new Date().toISOString());
44
+ await Promise.all([exports.servicesTokenPvar.loadingPromise, exports.registrationStatusPvar.loadingPromise]);
45
+ }
46
+ /**
47
+ * Replace the stored JWT after a routine re-authentication.
48
+ *
49
+ * Unlike {@link persistPeersServicesRegistration} this leaves the "registered" timestamp
50
+ * alone: the user registered once, and the Account screen shows that date, not the date of
51
+ * the latest token renewal. Same loading-promise discipline as the registration write.
52
+ */
53
+ async function persistPeersServicesToken(token) {
54
+ await exports.servicesTokenPvar.loadingPromise;
55
+ (0, exports.servicesTokenPvar)(token);
56
+ await exports.servicesTokenPvar.loadingPromise;
57
+ }