@peers-app/peers-sdk 0.21.7 → 0.23.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-singleton.d.ts +42 -0
- package/dist/context/user-context-singleton.js +45 -0
- package/dist/contracts/__tests__/contract-proxy.test.js +51 -1
- package/dist/contracts/__tests__/contract-resolvers.test.js +65 -0
- package/dist/contracts/__tests__/playground.test.js +5 -2
- package/dist/contracts/__tests__/system-contracts.test.js +3 -0
- package/dist/contracts/contract-proxy.d.ts +27 -0
- package/dist/contracts/contract-proxy.js +37 -1
- package/dist/contracts/contract-resolvers.d.ts +10 -0
- package/dist/contracts/contract-resolvers.js +21 -3
- package/dist/contracts/index.d.ts +3 -2
- package/dist/contracts/index.js +5 -2
- package/dist/contracts/system/index.d.ts +2 -0
- package/dist/contracts/system/index.js +5 -1
- package/dist/contracts/system/tool-access-control-contract.d.ts +35 -0
- package/dist/contracts/system/tool-access-control-contract.js +70 -0
- package/dist/data/access-level.d.ts +72 -0
- package/dist/data/access-level.js +109 -0
- package/dist/data/access-level.test.d.ts +1 -0
- package/dist/data/access-level.test.js +53 -0
- package/dist/data/assistants.d.ts +24 -0
- package/dist/data/assistants.js +21 -0
- package/dist/data/group-member-roles.d.ts +9 -0
- package/dist/data/group-member-roles.js +9 -0
- package/dist/data/group-permissions.d.ts +55 -1
- package/dist/data/group-permissions.js +76 -6
- package/dist/data/index.d.ts +3 -1
- package/dist/data/index.js +3 -1
- package/dist/data/orm/sql.data-source.d.ts +10 -0
- package/dist/data/orm/sql.data-source.js +48 -30
- package/dist/data/orm/sql.data-source.test.js +13 -0
- package/dist/data/package-version-resolver.test.js +2 -0
- package/dist/data/tool-access-approvals.d.ts +126 -0
- package/dist/data/tool-access-approvals.js +86 -0
- package/dist/data/tool-access.d.ts +162 -0
- package/dist/data/tool-access.js +235 -0
- package/dist/data/tool-access.test.d.ts +1 -0
- package/dist/data/tool-access.test.js +159 -0
- package/dist/data/tools.d.ts +15 -0
- package/dist/data/tools.js +11 -0
- package/dist/data/workflow-logs.d.ts +5 -5
- package/dist/data/workflow-runs.d.ts +2 -2
- package/dist/device-pairing/types.d.ts +6 -6
- package/dist/package-installer/package-creator.d.ts +31 -0
- package/dist/package-installer/package-creator.js +140 -40
- package/dist/package-installer/package-creator.test.js +113 -11
- package/dist/rpc-types.d.ts +0 -17
- package/dist/rpc-types.js +0 -15
- package/dist/system-ids.d.ts +13 -0
- package/dist/system-ids.js +14 -1
- package/package.json +1 -1
- package/dist/data/voice-messages.d.ts +0 -33
- package/dist/data/voice-messages.js +0 -33
|
@@ -3,19 +3,41 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.GroupMemberRole = void 0;
|
|
4
4
|
exports.getUserRole = getUserRole;
|
|
5
5
|
exports.getUserRoleFromPublicKey = getUserRoleFromPublicKey;
|
|
6
|
+
exports.getCurrentUserAccessLevel = getCurrentUserAccessLevel;
|
|
7
|
+
exports.getUserAccessLevel = getUserAccessLevel;
|
|
6
8
|
exports.verifyGroupSignature = verifyGroupSignature;
|
|
7
9
|
exports.isGroupMemberSignatureValid = isGroupMemberSignatureValid;
|
|
8
10
|
const context_1 = require("../context");
|
|
9
11
|
const keys_1 = require("../keys");
|
|
12
|
+
const access_level_1 = require("./access-level");
|
|
10
13
|
const group_member_roles_1 = require("./group-member-roles");
|
|
11
14
|
Object.defineProperty(exports, "GroupMemberRole", { enumerable: true, get: function () { return group_member_roles_1.GroupMemberRole; } });
|
|
12
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Return a user's {@link GroupMemberRole} in `groupId`.
|
|
17
|
+
*
|
|
18
|
+
* Missing groups and the group's founder resolve to {@link GroupMemberRole.Founder},
|
|
19
|
+
* which is how a personal context (no Groups row) becomes access 100.
|
|
20
|
+
*
|
|
21
|
+
* Prefer passing `userContext` from the provider that owns the data. The
|
|
22
|
+
* process singleton is only a fallback and is not awaited — multi-device
|
|
23
|
+
* tests never set it, and hanging here would stall contract calls.
|
|
24
|
+
*
|
|
25
|
+
* @param groupId - Group id, or the user's id for their personal context.
|
|
26
|
+
* @param userId - User whose role is requested.
|
|
27
|
+
* @param userContext - Provider-owned context. Falls back to {@link peekUserContext}.
|
|
28
|
+
* @throws If neither an explicit context nor the process singleton is available.
|
|
29
|
+
*/
|
|
30
|
+
async function getUserRole(groupId, userId, userContext) {
|
|
13
31
|
const { Groups } = await Promise.resolve().then(() => require("./groups"));
|
|
14
32
|
const { GroupMembers } = await Promise.resolve().then(() => require("./group-members"));
|
|
15
|
-
const
|
|
16
|
-
|
|
33
|
+
const ctx = userContext ?? (0, context_1.peekUserContext)();
|
|
34
|
+
if (!ctx) {
|
|
35
|
+
throw new Error("User context is not available");
|
|
36
|
+
}
|
|
37
|
+
await ctx.loadingPromise;
|
|
38
|
+
const groupDataContext = ctx.getDataContext(groupId);
|
|
17
39
|
const group = (await Groups(groupDataContext).get(groupId)) ||
|
|
18
|
-
(await Groups(
|
|
40
|
+
(await Groups(ctx.userDataContext).get(groupId));
|
|
19
41
|
// If the group doesn't exist or the current user is explicitly the founder, return Founder role
|
|
20
42
|
if (!group || group.founderUserId === userId) {
|
|
21
43
|
return group_member_roles_1.GroupMemberRole.Founder;
|
|
@@ -26,17 +48,57 @@ async function getUserRole(groupId, userId) {
|
|
|
26
48
|
}
|
|
27
49
|
return group.publicRole || group_member_roles_1.GroupMemberRole.None;
|
|
28
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolve a group role from the signing public key of a Users record.
|
|
53
|
+
*
|
|
54
|
+
* Uses {@link peekUserContext}; throws if the process singleton is unset.
|
|
55
|
+
*
|
|
56
|
+
* @param groupId - Group or personal context id.
|
|
57
|
+
* @param publicKey - User public key that signed a record.
|
|
58
|
+
*/
|
|
29
59
|
async function getUserRoleFromPublicKey(groupId, publicKey) {
|
|
30
60
|
const { Users } = await Promise.resolve().then(() => require("./users"));
|
|
31
|
-
const userContext =
|
|
61
|
+
const userContext = (0, context_1.peekUserContext)();
|
|
62
|
+
if (!userContext) {
|
|
63
|
+
throw new Error("User context is not available");
|
|
64
|
+
}
|
|
65
|
+
await userContext.loadingPromise;
|
|
32
66
|
const groupDataContext = userContext.getDataContext(groupId);
|
|
33
67
|
const user = (await Users(groupDataContext).findOne({ publicKey })) ||
|
|
34
68
|
(await Users(userContext.userDataContext).findOne({ publicKey }));
|
|
35
69
|
if (user) {
|
|
36
|
-
return getUserRole(groupId, user?.userId);
|
|
70
|
+
return getUserRole(groupId, user?.userId, userContext);
|
|
37
71
|
}
|
|
38
72
|
return group_member_roles_1.GroupMemberRole.None;
|
|
39
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Return the current user's access level in `dataContext`.
|
|
76
|
+
*
|
|
77
|
+
* Personal contexts (no `groupId`) use the user's id and resolve to 100.
|
|
78
|
+
*
|
|
79
|
+
* @param dataContext - Context whose group/personal role is evaluated.
|
|
80
|
+
*/
|
|
81
|
+
async function getCurrentUserAccessLevel(dataContext) {
|
|
82
|
+
const userId = dataContext.userContext.userId;
|
|
83
|
+
return getUserAccessLevel(dataContext, userId);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Return `userId`'s access level in `dataContext`.
|
|
87
|
+
*
|
|
88
|
+
* @param dataContext - Context whose group/personal role is evaluated.
|
|
89
|
+
* @param userId - User to resolve.
|
|
90
|
+
*/
|
|
91
|
+
async function getUserAccessLevel(dataContext, userId) {
|
|
92
|
+
const contextKey = dataContext.groupId ?? dataContext.userContext.userId;
|
|
93
|
+
const role = await getUserRole(contextKey, userId, dataContext.userContext);
|
|
94
|
+
return (0, access_level_1.accessLevelFromGroupRole)(role);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Verify that a group record was signed by an Admin+ member (Founder to change founder).
|
|
98
|
+
*
|
|
99
|
+
* @param group - Proposed group record.
|
|
100
|
+
* @param oldGroup - Previous record when this is an update.
|
|
101
|
+
*/
|
|
40
102
|
async function verifyGroupSignature(group, oldGroup) {
|
|
41
103
|
(0, keys_1.verifyObjectSignature)(group);
|
|
42
104
|
const publicKey = (0, keys_1.getPublicKeyFromObjectSignature)(group) ?? "";
|
|
@@ -50,6 +112,14 @@ async function verifyGroupSignature(group, oldGroup) {
|
|
|
50
112
|
throw new Error("Only group admins can modify group settings");
|
|
51
113
|
}
|
|
52
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Return whether a group-member write is signed by someone allowed to make it.
|
|
117
|
+
*
|
|
118
|
+
* @param groupId - Group the membership belongs to.
|
|
119
|
+
* @param newGroupMember - Proposed membership row.
|
|
120
|
+
* @param oldGroupMember - Previous row when this is an update.
|
|
121
|
+
* @param signerRole - Optional precomputed signer role.
|
|
122
|
+
*/
|
|
53
123
|
async function isGroupMemberSignatureValid(groupId, newGroupMember, oldGroupMember, signerRole) {
|
|
54
124
|
oldGroupMember ??= newGroupMember;
|
|
55
125
|
// Basic signature verification
|
package/dist/data/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from "./access-level";
|
|
1
2
|
export * from "./assistants";
|
|
2
3
|
export * from "./change-tracking";
|
|
3
4
|
export * from "./channels";
|
|
@@ -20,12 +21,13 @@ export * from "./peer-types";
|
|
|
20
21
|
export * from "./persistent-vars";
|
|
21
22
|
export * from "./sync-recovery-queue";
|
|
22
23
|
export * from "./table-definitions-table";
|
|
24
|
+
export * from "./tool-access";
|
|
25
|
+
export * from "./tool-access-approvals";
|
|
23
26
|
export * from "./tool-tests";
|
|
24
27
|
export * from "./tools";
|
|
25
28
|
export * from "./user-permissions";
|
|
26
29
|
export * from "./user-trust-levels";
|
|
27
30
|
export * from "./users";
|
|
28
|
-
export * from "./voice-messages";
|
|
29
31
|
export * from "./welcome-modal.pvar";
|
|
30
32
|
export * from "./workflow-logs";
|
|
31
33
|
export * from "./workflow-runs";
|
package/dist/data/index.js
CHANGED
|
@@ -14,6 +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
|
+
__exportStar(require("./access-level"), exports);
|
|
17
18
|
__exportStar(require("./assistants"), exports);
|
|
18
19
|
__exportStar(require("./change-tracking"), exports);
|
|
19
20
|
__exportStar(require("./channels"), exports);
|
|
@@ -36,12 +37,13 @@ __exportStar(require("./peer-types"), exports);
|
|
|
36
37
|
__exportStar(require("./persistent-vars"), exports);
|
|
37
38
|
__exportStar(require("./sync-recovery-queue"), exports);
|
|
38
39
|
__exportStar(require("./table-definitions-table"), exports);
|
|
40
|
+
__exportStar(require("./tool-access"), exports);
|
|
41
|
+
__exportStar(require("./tool-access-approvals"), exports);
|
|
39
42
|
__exportStar(require("./tool-tests"), exports);
|
|
40
43
|
__exportStar(require("./tools"), exports);
|
|
41
44
|
__exportStar(require("./user-permissions"), exports);
|
|
42
45
|
__exportStar(require("./user-trust-levels"), exports);
|
|
43
46
|
__exportStar(require("./users"), exports);
|
|
44
|
-
__exportStar(require("./voice-messages"), exports);
|
|
45
47
|
__exportStar(require("./welcome-modal.pvar"), exports);
|
|
46
48
|
__exportStar(require("./workflow-logs"), exports);
|
|
47
49
|
__exportStar(require("./workflow-runs"), exports);
|
|
@@ -34,6 +34,16 @@ export declare class SQLDataSource<T extends {
|
|
|
34
34
|
delete(idOrRecord: string | T): Promise<void>;
|
|
35
35
|
dropTableIfExists(): Promise<void>;
|
|
36
36
|
clearTable(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Validate `record` and copy Zod defaults onto missing keys so NOT NULL
|
|
39
|
+
* columns (for example `accessLevel`) are written on insert.
|
|
40
|
+
*/
|
|
41
|
+
private applySchemaDefaults;
|
|
42
|
+
/**
|
|
43
|
+
* Columns to SET on update. Required fields that are missing are omitted so
|
|
44
|
+
* older peers without a new column do not overwrite a local value with NULL.
|
|
45
|
+
*/
|
|
46
|
+
private fieldsForUpdate;
|
|
37
47
|
initRecord(data?: Partial<T>): T;
|
|
38
48
|
/**
|
|
39
49
|
* Synchronous insert for use within transactions.
|
|
@@ -245,13 +245,7 @@ class SQLDataSource {
|
|
|
245
245
|
// @ts-expect-error - need to figure out how to get typescript to understand what's going on here
|
|
246
246
|
record[this.metaData.primaryKeyName] = (0, utils_1.newid)();
|
|
247
247
|
}
|
|
248
|
-
|
|
249
|
-
try {
|
|
250
|
-
this.schema.parse(record);
|
|
251
|
-
}
|
|
252
|
-
catch (e) {
|
|
253
|
-
throw new Error(`Validation on insert failed for ${this.tableName}: ${e}`);
|
|
254
|
-
}
|
|
248
|
+
this.applySchemaDefaults(record);
|
|
255
249
|
const fields = this.metaData.fields.map((field) => `"${field.name}"`).join(", ");
|
|
256
250
|
const values = this.metaData.fields.map((field) => jsValueToSqlValue(record[field.name]));
|
|
257
251
|
const placeholders = values.map((_v) => "?").join(", ");
|
|
@@ -265,16 +259,14 @@ class SQLDataSource {
|
|
|
265
259
|
// @ts-expect-error - need to figure out how to get typescript to understand what's going on here
|
|
266
260
|
record[this.metaData.primaryKeyName] = (0, utils_1.newid)();
|
|
267
261
|
}
|
|
268
|
-
// validate data
|
|
269
262
|
this.schema.parse(record);
|
|
270
263
|
const primaryKey = record[this.metaData.primaryKeyName];
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
.map((field) => jsValueToSqlValue(record[field.name]));
|
|
264
|
+
const updateFields = this.fieldsForUpdate(record);
|
|
265
|
+
if (updateFields.length === 0) {
|
|
266
|
+
return record;
|
|
267
|
+
}
|
|
268
|
+
const fields = updateFields.map((field) => `"${field.name}" = ?`).join(",\n");
|
|
269
|
+
const values = updateFields.map((field) => jsValueToSqlValue(record[field.name]));
|
|
278
270
|
const sql = [
|
|
279
271
|
`UPDATE "${this.tableName}"`,
|
|
280
272
|
`SET ${fields}`,
|
|
@@ -299,6 +291,40 @@ class SQLDataSource {
|
|
|
299
291
|
const sql = `DELETE FROM "${this.tableName}"`;
|
|
300
292
|
await this.db.exec(sql, []);
|
|
301
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* Validate `record` and copy Zod defaults onto missing keys so NOT NULL
|
|
296
|
+
* columns (for example `accessLevel`) are written on insert.
|
|
297
|
+
*/
|
|
298
|
+
applySchemaDefaults(record) {
|
|
299
|
+
let parsed;
|
|
300
|
+
try {
|
|
301
|
+
parsed = this.schema.parse(record);
|
|
302
|
+
}
|
|
303
|
+
catch (e) {
|
|
304
|
+
throw new Error(`Validation on insert failed for ${this.tableName}: ${e}`);
|
|
305
|
+
}
|
|
306
|
+
const writable = record;
|
|
307
|
+
for (const field of this.metaData.fields) {
|
|
308
|
+
if (writable[field.name] === undefined && parsed[field.name] !== undefined) {
|
|
309
|
+
writable[field.name] = parsed[field.name];
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Columns to SET on update. Required fields that are missing are omitted so
|
|
315
|
+
* older peers without a new column do not overwrite a local value with NULL.
|
|
316
|
+
*/
|
|
317
|
+
fieldsForUpdate(record) {
|
|
318
|
+
return this.metaData.fields.filter((field) => {
|
|
319
|
+
if (field.name === this.metaData.primaryKeyName) {
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
if (record[field.name] === undefined && !field.optional) {
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
return true;
|
|
326
|
+
});
|
|
327
|
+
}
|
|
302
328
|
initRecord(data = {}) {
|
|
303
329
|
const defaults = {};
|
|
304
330
|
for (const field of this.metaData.fields) {
|
|
@@ -323,13 +349,7 @@ class SQLDataSource {
|
|
|
323
349
|
// @ts-expect-error - need to figure out how to get typescript to understand what's going on here
|
|
324
350
|
record[this.metaData.primaryKeyName] = (0, utils_1.newid)();
|
|
325
351
|
}
|
|
326
|
-
|
|
327
|
-
try {
|
|
328
|
-
this.schema.parse(record);
|
|
329
|
-
}
|
|
330
|
-
catch (e) {
|
|
331
|
-
throw new Error(`Validation on insert failed for ${this.tableName}: ${e}`);
|
|
332
|
-
}
|
|
352
|
+
this.applySchemaDefaults(record);
|
|
333
353
|
const fields = this.metaData.fields.map((field) => `"${field.name}"`).join(", ");
|
|
334
354
|
const values = this.metaData.fields.map((field) => jsValueToSqlValue(record[field.name]));
|
|
335
355
|
const placeholders = values.map((_v) => "?").join(", ");
|
|
@@ -346,16 +366,14 @@ class SQLDataSource {
|
|
|
346
366
|
// @ts-expect-error - need to figure out how to get typescript to understand what's going on here
|
|
347
367
|
record[this.metaData.primaryKeyName] = (0, utils_1.newid)();
|
|
348
368
|
}
|
|
349
|
-
// validate data
|
|
350
369
|
this.schema.parse(record);
|
|
351
370
|
const primaryKey = record[this.metaData.primaryKeyName];
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
.map((field) => jsValueToSqlValue(record[field.name]));
|
|
371
|
+
const updateFields = this.fieldsForUpdate(record);
|
|
372
|
+
if (updateFields.length === 0) {
|
|
373
|
+
return record;
|
|
374
|
+
}
|
|
375
|
+
const fields = updateFields.map((field) => `"${field.name}" = ?`).join(",\n");
|
|
376
|
+
const values = updateFields.map((field) => jsValueToSqlValue(record[field.name]));
|
|
359
377
|
const sql = [
|
|
360
378
|
`UPDATE "${this.tableName}"`,
|
|
361
379
|
`SET ${fields}`,
|
|
@@ -205,6 +205,19 @@ describe("table", () => {
|
|
|
205
205
|
newTask.title = "Test Task";
|
|
206
206
|
expect(() => TasksTable.schema.parse(newTask)).not.toThrow();
|
|
207
207
|
});
|
|
208
|
+
it("applies schema defaults on insert and preserves required fields on partial update", async () => {
|
|
209
|
+
const inserted = await TasksTable.insert({ title: "Defaulted body" });
|
|
210
|
+
expect(inserted.body).toBe("");
|
|
211
|
+
const stored = await TasksTable.get(inserted.taskId);
|
|
212
|
+
expect(stored?.body).toBe("");
|
|
213
|
+
await TasksTable.update({
|
|
214
|
+
taskId: inserted.taskId,
|
|
215
|
+
title: "Renamed",
|
|
216
|
+
});
|
|
217
|
+
const afterUpdate = await TasksTable.get(inserted.taskId);
|
|
218
|
+
expect(afterUpdate?.title).toBe("Renamed");
|
|
219
|
+
expect(afterUpdate?.body).toBe("");
|
|
220
|
+
});
|
|
208
221
|
afterAll(async () => {
|
|
209
222
|
await TasksTable.dropTableIfExists();
|
|
210
223
|
await TasksTable.db.close();
|
|
@@ -7,6 +7,7 @@ const SQLiteDB = require("better-sqlite3");
|
|
|
7
7
|
const user_context_1 = require("../context/user-context");
|
|
8
8
|
const user_context_singleton_1 = require("../context/user-context-singleton");
|
|
9
9
|
const utils_1 = require("../utils");
|
|
10
|
+
const access_level_1 = require("./access-level");
|
|
10
11
|
const assistants_1 = require("./assistants");
|
|
11
12
|
const group_member_roles_1 = require("./group-member-roles");
|
|
12
13
|
const groups_1 = require("./groups");
|
|
@@ -375,6 +376,7 @@ describe("resolveDevicePackageVersion — expected behavior (control)", () => {
|
|
|
375
376
|
const savedAssistant = await (0, assistants_1.Assistants)(dc).get(testAssistantId);
|
|
376
377
|
expect(savedAssistant).toBeDefined();
|
|
377
378
|
expect(savedAssistant?.name).toBe("Upgrade Test Assistant");
|
|
379
|
+
expect(savedAssistant?.accessLevel).toBe(access_level_1.DEFAULT_ACCESS_LEVEL);
|
|
378
380
|
const savedWorkflow = await (0, workflows_1.Workflows)(dc).get(testWorkflowId);
|
|
379
381
|
expect(savedWorkflow).toBeDefined();
|
|
380
382
|
expect(savedWorkflow?.name).toBe("Upgrade Test Workflow");
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { DataContext } from "../context/data-context";
|
|
3
|
+
/** Lifecycle of a tool-access approval request or reusable grant. */
|
|
4
|
+
export declare enum ToolAccessApprovalStatus {
|
|
5
|
+
pending = "pending",
|
|
6
|
+
approved = "approved",
|
|
7
|
+
executed = "executed",
|
|
8
|
+
rejected = "rejected",
|
|
9
|
+
expired = "expired",
|
|
10
|
+
failed = "failed"
|
|
11
|
+
}
|
|
12
|
+
/** How far a granted approval applies after the first execution. */
|
|
13
|
+
export declare enum ToolAccessApprovalScope {
|
|
14
|
+
once = "once",
|
|
15
|
+
thread = "thread",
|
|
16
|
+
context = "context"
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Local-only record of a step-up tool approval.
|
|
20
|
+
*
|
|
21
|
+
* Stores identifiers, a frozen argument hash, and sanitized preview text.
|
|
22
|
+
* Do not put secrets, tokens, or raw log bodies in this table.
|
|
23
|
+
*/
|
|
24
|
+
export declare const toolAccessApprovalSchema: z.ZodObject<{
|
|
25
|
+
toolAccessApprovalId: z.ZodEffects<z.ZodString, string, string>;
|
|
26
|
+
userId: z.ZodEffects<z.ZodString, string, string>;
|
|
27
|
+
assistantId: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
28
|
+
toolId: z.ZodEffects<z.ZodString, string, string>;
|
|
29
|
+
toolName: z.ZodString;
|
|
30
|
+
dataContextId: z.ZodString;
|
|
31
|
+
workflowRunId: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
32
|
+
threadMessageId: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
33
|
+
workflowLogId: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
34
|
+
argsHash: z.ZodString;
|
|
35
|
+
argsPreview: z.ZodDefault<z.ZodString>;
|
|
36
|
+
frozenArgs: z.ZodObject<{}, "strip", z.ZodAny, z.objectOutputType<{}, z.ZodAny, "strip">, z.objectInputType<{}, z.ZodAny, "strip">>;
|
|
37
|
+
requiredAccessLevel: z.ZodDefault<z.ZodNumber>;
|
|
38
|
+
scope: z.ZodDefault<z.ZodNativeEnum<typeof ToolAccessApprovalScope>>;
|
|
39
|
+
status: z.ZodDefault<z.ZodNativeEnum<typeof ToolAccessApprovalStatus>>;
|
|
40
|
+
nonce: z.ZodString;
|
|
41
|
+
expiresAt: z.ZodDate;
|
|
42
|
+
createdAt: z.ZodDefault<z.ZodDate>;
|
|
43
|
+
decidedAt: z.ZodOptional<z.ZodDate>;
|
|
44
|
+
executedAt: z.ZodOptional<z.ZodDate>;
|
|
45
|
+
resultSummary: z.ZodOptional<z.ZodString>;
|
|
46
|
+
}, "strip", z.ZodTypeAny, {
|
|
47
|
+
nonce: string;
|
|
48
|
+
status: ToolAccessApprovalStatus;
|
|
49
|
+
scope: ToolAccessApprovalScope;
|
|
50
|
+
userId: string;
|
|
51
|
+
expiresAt: Date;
|
|
52
|
+
toolId: string;
|
|
53
|
+
createdAt: Date;
|
|
54
|
+
dataContextId: string;
|
|
55
|
+
toolAccessApprovalId: string;
|
|
56
|
+
toolName: string;
|
|
57
|
+
argsHash: string;
|
|
58
|
+
argsPreview: string;
|
|
59
|
+
frozenArgs: {} & {
|
|
60
|
+
[k: string]: any;
|
|
61
|
+
};
|
|
62
|
+
requiredAccessLevel: number;
|
|
63
|
+
assistantId?: string | undefined;
|
|
64
|
+
threadMessageId?: string | undefined;
|
|
65
|
+
workflowRunId?: string | undefined;
|
|
66
|
+
workflowLogId?: string | undefined;
|
|
67
|
+
decidedAt?: Date | undefined;
|
|
68
|
+
executedAt?: Date | undefined;
|
|
69
|
+
resultSummary?: string | undefined;
|
|
70
|
+
}, {
|
|
71
|
+
nonce: string;
|
|
72
|
+
userId: string;
|
|
73
|
+
expiresAt: Date;
|
|
74
|
+
toolId: string;
|
|
75
|
+
dataContextId: string;
|
|
76
|
+
toolAccessApprovalId: string;
|
|
77
|
+
toolName: string;
|
|
78
|
+
argsHash: string;
|
|
79
|
+
frozenArgs: {} & {
|
|
80
|
+
[k: string]: any;
|
|
81
|
+
};
|
|
82
|
+
status?: ToolAccessApprovalStatus | undefined;
|
|
83
|
+
scope?: ToolAccessApprovalScope | undefined;
|
|
84
|
+
assistantId?: string | undefined;
|
|
85
|
+
createdAt?: Date | undefined;
|
|
86
|
+
threadMessageId?: string | undefined;
|
|
87
|
+
workflowRunId?: string | undefined;
|
|
88
|
+
workflowLogId?: string | undefined;
|
|
89
|
+
argsPreview?: string | undefined;
|
|
90
|
+
requiredAccessLevel?: number | undefined;
|
|
91
|
+
decidedAt?: Date | undefined;
|
|
92
|
+
executedAt?: Date | undefined;
|
|
93
|
+
resultSummary?: string | undefined;
|
|
94
|
+
}>;
|
|
95
|
+
/** A local-only tool-access approval or grant. */
|
|
96
|
+
export type IToolAccessApproval = z.infer<typeof toolAccessApprovalSchema>;
|
|
97
|
+
/**
|
|
98
|
+
* Accessor for the local-only {@link ToolAccessApprovals} table.
|
|
99
|
+
*
|
|
100
|
+
* @param dataContext - Optional data context; defaults to the current singleton.
|
|
101
|
+
*/
|
|
102
|
+
export declare function ToolAccessApprovals(dataContext?: DataContext): import("..").Table<{
|
|
103
|
+
nonce: string;
|
|
104
|
+
status: ToolAccessApprovalStatus;
|
|
105
|
+
scope: ToolAccessApprovalScope;
|
|
106
|
+
userId: string;
|
|
107
|
+
expiresAt: Date;
|
|
108
|
+
toolId: string;
|
|
109
|
+
createdAt: Date;
|
|
110
|
+
dataContextId: string;
|
|
111
|
+
toolAccessApprovalId: string;
|
|
112
|
+
toolName: string;
|
|
113
|
+
argsHash: string;
|
|
114
|
+
argsPreview: string;
|
|
115
|
+
frozenArgs: {} & {
|
|
116
|
+
[k: string]: any;
|
|
117
|
+
};
|
|
118
|
+
requiredAccessLevel: number;
|
|
119
|
+
assistantId?: string | undefined;
|
|
120
|
+
threadMessageId?: string | undefined;
|
|
121
|
+
workflowRunId?: string | undefined;
|
|
122
|
+
workflowLogId?: string | undefined;
|
|
123
|
+
decidedAt?: Date | undefined;
|
|
124
|
+
executedAt?: Date | undefined;
|
|
125
|
+
resultSummary?: string | undefined;
|
|
126
|
+
}>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toolAccessApprovalSchema = exports.ToolAccessApprovalScope = exports.ToolAccessApprovalStatus = void 0;
|
|
4
|
+
exports.ToolAccessApprovals = ToolAccessApprovals;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const user_context_singleton_1 = require("../context/user-context-singleton");
|
|
7
|
+
const zod_types_1 = require("../types/zod-types");
|
|
8
|
+
const access_level_1 = require("./access-level");
|
|
9
|
+
const table_definitions_system_1 = require("./orm/table-definitions.system");
|
|
10
|
+
const types_1 = require("./orm/types");
|
|
11
|
+
/** Lifecycle of a tool-access approval request or reusable grant. */
|
|
12
|
+
var ToolAccessApprovalStatus;
|
|
13
|
+
(function (ToolAccessApprovalStatus) {
|
|
14
|
+
ToolAccessApprovalStatus["pending"] = "pending";
|
|
15
|
+
ToolAccessApprovalStatus["approved"] = "approved";
|
|
16
|
+
ToolAccessApprovalStatus["executed"] = "executed";
|
|
17
|
+
ToolAccessApprovalStatus["rejected"] = "rejected";
|
|
18
|
+
ToolAccessApprovalStatus["expired"] = "expired";
|
|
19
|
+
ToolAccessApprovalStatus["failed"] = "failed";
|
|
20
|
+
})(ToolAccessApprovalStatus || (exports.ToolAccessApprovalStatus = ToolAccessApprovalStatus = {}));
|
|
21
|
+
/** How far a granted approval applies after the first execution. */
|
|
22
|
+
var ToolAccessApprovalScope;
|
|
23
|
+
(function (ToolAccessApprovalScope) {
|
|
24
|
+
ToolAccessApprovalScope["once"] = "once";
|
|
25
|
+
ToolAccessApprovalScope["thread"] = "thread";
|
|
26
|
+
ToolAccessApprovalScope["context"] = "context";
|
|
27
|
+
})(ToolAccessApprovalScope || (exports.ToolAccessApprovalScope = ToolAccessApprovalScope = {}));
|
|
28
|
+
/**
|
|
29
|
+
* Local-only record of a step-up tool approval.
|
|
30
|
+
*
|
|
31
|
+
* Stores identifiers, a frozen argument hash, and sanitized preview text.
|
|
32
|
+
* Do not put secrets, tokens, or raw log bodies in this table.
|
|
33
|
+
*/
|
|
34
|
+
exports.toolAccessApprovalSchema = zod_1.z.object({
|
|
35
|
+
toolAccessApprovalId: zod_types_1.zodPeerId,
|
|
36
|
+
userId: zod_types_1.zodPeerId.describe("User who must approve and who requested the elevation"),
|
|
37
|
+
assistantId: zod_types_1.zodPeerId
|
|
38
|
+
.optional()
|
|
39
|
+
.describe("Assistant that requested the tool; omitted for direct user calls"),
|
|
40
|
+
toolId: zod_types_1.zodPeerId,
|
|
41
|
+
toolName: zod_1.z.string().describe("Display name of the tool at request time"),
|
|
42
|
+
dataContextId: zod_1.z.string().describe("Data context the tool would run in"),
|
|
43
|
+
workflowRunId: zod_types_1.zodPeerId.optional(),
|
|
44
|
+
threadMessageId: zod_types_1.zodPeerId
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("User message / thread root that owns the workflow"),
|
|
47
|
+
workflowLogId: zod_types_1.zodPeerId.optional(),
|
|
48
|
+
argsHash: zod_1.z.string().describe("Canonical hash of the frozen tool arguments"),
|
|
49
|
+
argsPreview: zod_1.z
|
|
50
|
+
.string()
|
|
51
|
+
.default("")
|
|
52
|
+
.describe("Sanitized, truncated argument summary for the approval card"),
|
|
53
|
+
frozenArgs: zod_types_1.zodAnyObject.describe("Frozen arguments executed on approve; no secrets"),
|
|
54
|
+
requiredAccessLevel: access_level_1.accessLevelSchema,
|
|
55
|
+
scope: zod_1.z.nativeEnum(ToolAccessApprovalScope).default(ToolAccessApprovalScope.once),
|
|
56
|
+
status: zod_1.z.nativeEnum(ToolAccessApprovalStatus).default(ToolAccessApprovalStatus.pending),
|
|
57
|
+
nonce: zod_1.z.string().describe("Single-use token; empty after consume"),
|
|
58
|
+
expiresAt: zod_1.z.date(),
|
|
59
|
+
createdAt: zod_1.z.date().default(() => new Date()),
|
|
60
|
+
decidedAt: zod_1.z.date().optional(),
|
|
61
|
+
executedAt: zod_1.z.date().optional(),
|
|
62
|
+
resultSummary: zod_1.z.string().optional().describe("Sanitized outcome after execute or deny"),
|
|
63
|
+
});
|
|
64
|
+
const metaData = {
|
|
65
|
+
name: "ToolAccessApprovals",
|
|
66
|
+
description: "Local-only pending and granted step-up approvals for privileged tools.",
|
|
67
|
+
primaryKeyName: "toolAccessApprovalId",
|
|
68
|
+
fields: (0, types_1.schemaToFields)(exports.toolAccessApprovalSchema),
|
|
69
|
+
iconClassName: "bi bi-shield-lock",
|
|
70
|
+
localOnly: true,
|
|
71
|
+
indexes: [
|
|
72
|
+
{ fields: ["threadMessageId"] },
|
|
73
|
+
{ fields: ["workflowRunId"] },
|
|
74
|
+
{ fields: ["status"] },
|
|
75
|
+
{ fields: ["toolId"] },
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
(0, table_definitions_system_1.registerSystemTableDefinition)(metaData, exports.toolAccessApprovalSchema);
|
|
79
|
+
/**
|
|
80
|
+
* Accessor for the local-only {@link ToolAccessApprovals} table.
|
|
81
|
+
*
|
|
82
|
+
* @param dataContext - Optional data context; defaults to the current singleton.
|
|
83
|
+
*/
|
|
84
|
+
function ToolAccessApprovals(dataContext) {
|
|
85
|
+
return (0, user_context_singleton_1.getTableContainer)(dataContext).getTable(metaData, exports.toolAccessApprovalSchema);
|
|
86
|
+
}
|