@agenticmail/enterprise 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/ARCHITECTURE.md +183 -0
  2. package/agenticmail-enterprise.db +0 -0
  3. package/dashboards/README.md +120 -0
  4. package/dashboards/dotnet/Program.cs +261 -0
  5. package/dashboards/express/app.js +146 -0
  6. package/dashboards/go/main.go +513 -0
  7. package/dashboards/html/index.html +535 -0
  8. package/dashboards/java/AgenticMailDashboard.java +376 -0
  9. package/dashboards/php/index.php +414 -0
  10. package/dashboards/python/app.py +273 -0
  11. package/dashboards/ruby/app.rb +195 -0
  12. package/dist/chunk-77IDQJL3.js +7 -0
  13. package/dist/chunk-7RGCCHIT.js +115 -0
  14. package/dist/chunk-DXNKR3TG.js +1355 -0
  15. package/dist/chunk-IQWA44WT.js +970 -0
  16. package/dist/chunk-LCUZGIDH.js +965 -0
  17. package/dist/chunk-N2JVTNNJ.js +2553 -0
  18. package/dist/chunk-O462UJBH.js +363 -0
  19. package/dist/chunk-PNKVD2UK.js +26 -0
  20. package/dist/cli.js +218 -0
  21. package/dist/dashboard/index.html +558 -0
  22. package/dist/db-adapter-DEWEFNIV.js +7 -0
  23. package/dist/dynamodb-CCGL2E77.js +426 -0
  24. package/dist/engine/index.js +1261 -0
  25. package/dist/index.js +522 -0
  26. package/dist/mongodb-ODTXIVPV.js +319 -0
  27. package/dist/mysql-RM3S2FV5.js +521 -0
  28. package/dist/postgres-LN7A6MGQ.js +518 -0
  29. package/dist/routes-2JEPIIKC.js +441 -0
  30. package/dist/routes-74ZLKJKP.js +399 -0
  31. package/dist/server.js +7 -0
  32. package/dist/sqlite-3K5YOZ4K.js +439 -0
  33. package/dist/turso-LDWODSDI.js +442 -0
  34. package/package.json +49 -0
  35. package/src/admin/routes.ts +331 -0
  36. package/src/auth/routes.ts +130 -0
  37. package/src/cli.ts +260 -0
  38. package/src/dashboard/index.html +558 -0
  39. package/src/db/adapter.ts +230 -0
  40. package/src/db/dynamodb.ts +456 -0
  41. package/src/db/factory.ts +51 -0
  42. package/src/db/mongodb.ts +360 -0
  43. package/src/db/mysql.ts +472 -0
  44. package/src/db/postgres.ts +479 -0
  45. package/src/db/sql-schema.ts +123 -0
  46. package/src/db/sqlite.ts +391 -0
  47. package/src/db/turso.ts +411 -0
  48. package/src/deploy/fly.ts +368 -0
  49. package/src/deploy/managed.ts +213 -0
  50. package/src/engine/activity.ts +474 -0
  51. package/src/engine/agent-config.ts +429 -0
  52. package/src/engine/agenticmail-bridge.ts +296 -0
  53. package/src/engine/approvals.ts +278 -0
  54. package/src/engine/db-adapter.ts +682 -0
  55. package/src/engine/db-schema.ts +335 -0
  56. package/src/engine/deployer.ts +595 -0
  57. package/src/engine/index.ts +134 -0
  58. package/src/engine/knowledge.ts +486 -0
  59. package/src/engine/lifecycle.ts +635 -0
  60. package/src/engine/openclaw-hook.ts +371 -0
  61. package/src/engine/routes.ts +528 -0
  62. package/src/engine/skills.ts +473 -0
  63. package/src/engine/tenant.ts +345 -0
  64. package/src/engine/tool-catalog.ts +189 -0
  65. package/src/index.ts +64 -0
  66. package/src/lib/resilience.ts +326 -0
  67. package/src/middleware/index.ts +286 -0
  68. package/src/server.ts +310 -0
  69. package/tsconfig.json +14 -0
@@ -0,0 +1,426 @@
1
+ import {
2
+ DatabaseAdapter
3
+ } from "./chunk-77IDQJL3.js";
4
+ import "./chunk-PNKVD2UK.js";
5
+
6
+ // src/db/dynamodb.ts
7
+ import { randomUUID, createHash } from "crypto";
8
+ var ddbLib;
9
+ var ddbDocLib;
10
+ async function getDdb() {
11
+ if (!ddbLib) {
12
+ try {
13
+ ddbLib = await import("@aws-sdk/client-dynamodb");
14
+ ddbDocLib = await import("@aws-sdk/lib-dynamodb");
15
+ } catch {
16
+ throw new Error("DynamoDB drivers not found. Install: npm install @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb");
17
+ }
18
+ }
19
+ return { ddbLib, ddbDocLib };
20
+ }
21
+ var TABLE = "agenticmail_enterprise";
22
+ function pk(type) {
23
+ return `${type}`;
24
+ }
25
+ var DynamoAdapter = class extends DatabaseAdapter {
26
+ type = "dynamodb";
27
+ client = null;
28
+ docClient = null;
29
+ tableName = TABLE;
30
+ async connect(config) {
31
+ const { ddbLib: ddbLib2, ddbDocLib: ddbDocLib2 } = await getDdb();
32
+ const opts = {};
33
+ if (config.region) opts.region = config.region;
34
+ if (config.accessKeyId && config.secretAccessKey) {
35
+ opts.credentials = { accessKeyId: config.accessKeyId, secretAccessKey: config.secretAccessKey };
36
+ }
37
+ if (config.connectionString) {
38
+ opts.endpoint = config.connectionString;
39
+ }
40
+ if (config.options?.tableName) this.tableName = config.options.tableName;
41
+ this.client = new ddbLib2.DynamoDBClient(opts);
42
+ this.docClient = ddbDocLib2.DynamoDBDocumentClient.from(this.client);
43
+ }
44
+ async disconnect() {
45
+ if (this.client) this.client.destroy();
46
+ }
47
+ isConnected() {
48
+ return this.client !== null;
49
+ }
50
+ async put(item) {
51
+ const { ddbDocLib: ddbDocLib2 } = await getDdb();
52
+ await this.docClient.send(new ddbDocLib2.PutCommand({ TableName: this.tableName, Item: item }));
53
+ }
54
+ async getItem(pkVal, skVal) {
55
+ const { ddbDocLib: ddbDocLib2 } = await getDdb();
56
+ const result = await this.docClient.send(new ddbDocLib2.GetCommand({
57
+ TableName: this.tableName,
58
+ Key: { PK: pkVal, SK: skVal }
59
+ }));
60
+ return result.Item || null;
61
+ }
62
+ async query(pkVal, opts) {
63
+ const { ddbDocLib: ddbDocLib2 } = await getDdb();
64
+ const params = {
65
+ TableName: this.tableName,
66
+ KeyConditionExpression: "#pk = :pk",
67
+ ExpressionAttributeNames: { "#pk": opts?.pkField || "PK" },
68
+ ExpressionAttributeValues: { ":pk": pkVal }
69
+ };
70
+ if (opts?.sk?.begins) {
71
+ params.KeyConditionExpression += " AND begins_with(#sk, :skPrefix)";
72
+ params.ExpressionAttributeNames["#sk"] = "SK";
73
+ params.ExpressionAttributeValues[":skPrefix"] = opts.sk.begins;
74
+ }
75
+ if (opts?.index) params.IndexName = opts.index;
76
+ if (opts?.limit) params.Limit = opts.limit;
77
+ params.ScanIndexForward = false;
78
+ const result = await this.docClient.send(new ddbDocLib2.QueryCommand(params));
79
+ return result.Items || [];
80
+ }
81
+ async deleteItem(pkVal, skVal) {
82
+ const { ddbDocLib: ddbDocLib2 } = await getDdb();
83
+ await this.docClient.send(new ddbDocLib2.DeleteCommand({
84
+ TableName: this.tableName,
85
+ Key: { PK: pkVal, SK: skVal }
86
+ }));
87
+ }
88
+ async migrate() {
89
+ const { ddbLib: ddbLib2 } = await getDdb();
90
+ try {
91
+ await this.client.send(new ddbLib2.CreateTableCommand({
92
+ TableName: this.tableName,
93
+ KeySchema: [
94
+ { AttributeName: "PK", KeyType: "HASH" },
95
+ { AttributeName: "SK", KeyType: "RANGE" }
96
+ ],
97
+ AttributeDefinitions: [
98
+ { AttributeName: "PK", AttributeType: "S" },
99
+ { AttributeName: "SK", AttributeType: "S" },
100
+ { AttributeName: "GSI1PK", AttributeType: "S" },
101
+ { AttributeName: "GSI1SK", AttributeType: "S" }
102
+ ],
103
+ GlobalSecondaryIndexes: [
104
+ {
105
+ IndexName: "GSI1",
106
+ KeySchema: [
107
+ { AttributeName: "GSI1PK", KeyType: "HASH" },
108
+ { AttributeName: "GSI1SK", KeyType: "RANGE" }
109
+ ],
110
+ Projection: { ProjectionType: "ALL" },
111
+ ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 }
112
+ }
113
+ ],
114
+ BillingMode: "PAY_PER_REQUEST"
115
+ }));
116
+ const waiter = new ddbLib2.DescribeTableCommand({ TableName: this.tableName });
117
+ for (let i = 0; i < 30; i++) {
118
+ const desc = await this.client.send(waiter);
119
+ if (desc.Table?.TableStatus === "ACTIVE") break;
120
+ await new Promise((r) => setTimeout(r, 1e3));
121
+ }
122
+ } catch (err) {
123
+ if (!err.name?.includes("ResourceInUse") && !err.message?.includes("already exists")) throw err;
124
+ }
125
+ const existing = await this.getItem(pk("SETTINGS"), "default");
126
+ if (!existing) {
127
+ await this.put({ PK: pk("SETTINGS"), SK: "default", name: "", subdomain: "", plan: "free", primaryColor: "#6366f1", createdAt: (/* @__PURE__ */ new Date()).toISOString(), updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
128
+ }
129
+ const retPol = await this.getItem(pk("RETENTION"), "default");
130
+ if (!retPol) {
131
+ await this.put({ PK: pk("RETENTION"), SK: "default", enabled: false, retainDays: 365, excludeTags: [], archiveFirst: true });
132
+ }
133
+ }
134
+ // ─── Company ─────────────────────────────────────────────
135
+ async getSettings() {
136
+ const r = await this.getItem(pk("SETTINGS"), "default");
137
+ if (!r) return null;
138
+ return { id: "default", name: r.name, domain: r.domain, subdomain: r.subdomain, smtpHost: r.smtpHost, smtpPort: r.smtpPort, smtpUser: r.smtpUser, smtpPass: r.smtpPass, dkimPrivateKey: r.dkimPrivateKey, logoUrl: r.logoUrl, primaryColor: r.primaryColor, plan: r.plan, createdAt: new Date(r.createdAt), updatedAt: new Date(r.updatedAt) };
139
+ }
140
+ async updateSettings(updates) {
141
+ const current = await this.getItem(pk("SETTINGS"), "default") || {};
142
+ const { id, ...rest } = updates;
143
+ await this.put({ ...current, ...rest, PK: pk("SETTINGS"), SK: "default", updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
144
+ return this.getSettings();
145
+ }
146
+ // ─── Agents ──────────────────────────────────────────────
147
+ async createAgent(input) {
148
+ const id = randomUUID();
149
+ const now = (/* @__PURE__ */ new Date()).toISOString();
150
+ const email = input.email || `${input.name.toLowerCase().replace(/\s+/g, "-")}@localhost`;
151
+ const item = {
152
+ PK: pk("AGENT"),
153
+ SK: id,
154
+ GSI1PK: "AGENT_NAME",
155
+ GSI1SK: input.name,
156
+ name: input.name,
157
+ email,
158
+ role: input.role || "assistant",
159
+ status: "active",
160
+ metadata: input.metadata || {},
161
+ createdBy: input.createdBy,
162
+ createdAt: now,
163
+ updatedAt: now
164
+ };
165
+ await this.put(item);
166
+ return this.itemToAgent(item);
167
+ }
168
+ async getAgent(id) {
169
+ const r = await this.getItem(pk("AGENT"), id);
170
+ return r ? this.itemToAgent(r) : null;
171
+ }
172
+ async getAgentByName(name) {
173
+ const items = await this.query("AGENT_NAME", { index: "GSI1", pkField: "GSI1PK", sk: { begins: name }, limit: 1 });
174
+ return items.length > 0 ? this.itemToAgent(items[0]) : null;
175
+ }
176
+ async listAgents(opts) {
177
+ const items = await this.query(pk("AGENT"), { limit: (opts?.limit || 50) + (opts?.offset || 0) });
178
+ let result = items.map((r) => this.itemToAgent(r));
179
+ if (opts?.status) result = result.filter((a) => a.status === opts.status);
180
+ if (opts?.offset) result = result.slice(opts.offset);
181
+ if (opts?.limit) result = result.slice(0, opts.limit);
182
+ return result;
183
+ }
184
+ async updateAgent(id, updates) {
185
+ const current = await this.getItem(pk("AGENT"), id);
186
+ if (!current) throw new Error("Agent not found");
187
+ const merged = { ...current, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
188
+ for (const key of ["name", "email", "role", "status", "metadata"]) {
189
+ if (updates[key] !== void 0) merged[key] = updates[key];
190
+ }
191
+ if (updates.name) {
192
+ merged.GSI1SK = updates.name;
193
+ }
194
+ await this.put(merged);
195
+ return this.itemToAgent(merged);
196
+ }
197
+ async archiveAgent(id) {
198
+ await this.updateAgent(id, { status: "archived" });
199
+ }
200
+ async deleteAgent(id) {
201
+ await this.deleteItem(pk("AGENT"), id);
202
+ }
203
+ async countAgents(status) {
204
+ const items = await this.query(pk("AGENT"));
205
+ if (status) return items.filter((i) => i.status === status).length;
206
+ return items.length;
207
+ }
208
+ // ─── Users ───────────────────────────────────────────────
209
+ async createUser(input) {
210
+ const id = randomUUID();
211
+ const now = (/* @__PURE__ */ new Date()).toISOString();
212
+ let passwordHash = null;
213
+ if (input.password) {
214
+ const { default: bcrypt } = await import("bcryptjs");
215
+ passwordHash = await bcrypt.hash(input.password, 12);
216
+ }
217
+ const item = {
218
+ PK: pk("USER"),
219
+ SK: id,
220
+ GSI1PK: "USER_EMAIL",
221
+ GSI1SK: input.email,
222
+ email: input.email,
223
+ name: input.name,
224
+ role: input.role,
225
+ passwordHash,
226
+ ssoProvider: input.ssoProvider || null,
227
+ ssoSubject: input.ssoSubject || null,
228
+ createdAt: now,
229
+ updatedAt: now,
230
+ lastLoginAt: null
231
+ };
232
+ await this.put(item);
233
+ return this.itemToUser(item);
234
+ }
235
+ async getUser(id) {
236
+ const r = await this.getItem(pk("USER"), id);
237
+ return r ? this.itemToUser(r) : null;
238
+ }
239
+ async getUserByEmail(email) {
240
+ const items = await this.query("USER_EMAIL", { index: "GSI1", pkField: "GSI1PK", sk: { begins: email }, limit: 1 });
241
+ return items.length > 0 ? this.itemToUser(items[0]) : null;
242
+ }
243
+ async getUserBySso(provider, subject) {
244
+ const items = await this.query(pk("USER"));
245
+ const found = items.find((i) => i.ssoProvider === provider && i.ssoSubject === subject);
246
+ return found ? this.itemToUser(found) : null;
247
+ }
248
+ async listUsers(opts) {
249
+ const items = await this.query(pk("USER"), { limit: (opts?.limit || 50) + (opts?.offset || 0) });
250
+ let result = items.map((r) => this.itemToUser(r));
251
+ if (opts?.offset) result = result.slice(opts.offset);
252
+ if (opts?.limit) result = result.slice(0, opts.limit);
253
+ return result;
254
+ }
255
+ async updateUser(id, updates) {
256
+ const current = await this.getItem(pk("USER"), id);
257
+ if (!current) throw new Error("User not found");
258
+ const merged = { ...current, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
259
+ for (const key of ["email", "name", "role", "lastLoginAt"]) {
260
+ if (updates[key] !== void 0) merged[key] = updates[key];
261
+ }
262
+ if (updates.email) {
263
+ merged.GSI1SK = updates.email;
264
+ }
265
+ await this.put(merged);
266
+ return this.itemToUser(merged);
267
+ }
268
+ async deleteUser(id) {
269
+ await this.deleteItem(pk("USER"), id);
270
+ }
271
+ // ─── Audit ───────────────────────────────────────────────
272
+ async logEvent(event) {
273
+ const id = randomUUID();
274
+ const now = (/* @__PURE__ */ new Date()).toISOString();
275
+ await this.put({
276
+ PK: pk("AUDIT"),
277
+ SK: `${now}#${id}`,
278
+ GSI1PK: `AUDIT_ACTOR#${event.actor}`,
279
+ GSI1SK: now,
280
+ id,
281
+ timestamp: now,
282
+ actor: event.actor,
283
+ actorType: event.actorType,
284
+ action: event.action,
285
+ resource: event.resource,
286
+ details: event.details || {},
287
+ ip: event.ip || null
288
+ });
289
+ }
290
+ async queryAudit(filters) {
291
+ let items;
292
+ if (filters.actor) {
293
+ items = await this.query(`AUDIT_ACTOR#${filters.actor}`, { index: "GSI1", pkField: "GSI1PK" });
294
+ } else {
295
+ items = await this.query(pk("AUDIT"));
296
+ }
297
+ if (filters.action) items = items.filter((i) => i.action === filters.action);
298
+ if (filters.resource) items = items.filter((i) => i.resource?.includes(filters.resource));
299
+ if (filters.from) items = items.filter((i) => new Date(i.timestamp) >= filters.from);
300
+ if (filters.to) items = items.filter((i) => new Date(i.timestamp) <= filters.to);
301
+ const total = items.length;
302
+ if (filters.offset) items = items.slice(filters.offset);
303
+ if (filters.limit) items = items.slice(0, filters.limit);
304
+ return {
305
+ events: items.map((r) => ({ id: r.id || r.SK, timestamp: new Date(r.timestamp), actor: r.actor, actorType: r.actorType, action: r.action, resource: r.resource, details: r.details, ip: r.ip })),
306
+ total
307
+ };
308
+ }
309
+ // ─── API Keys ────────────────────────────────────────────
310
+ async createApiKey(input) {
311
+ const id = randomUUID();
312
+ const plaintext = `ek_${randomUUID().replace(/-/g, "")}`;
313
+ const keyHash = createHash("sha256").update(plaintext).digest("hex");
314
+ const keyPrefix = plaintext.substring(0, 11);
315
+ const now = (/* @__PURE__ */ new Date()).toISOString();
316
+ const item = {
317
+ PK: pk("APIKEY"),
318
+ SK: id,
319
+ GSI1PK: "APIKEY_HASH",
320
+ GSI1SK: keyHash,
321
+ name: input.name,
322
+ keyHash,
323
+ keyPrefix,
324
+ scopes: input.scopes,
325
+ createdBy: input.createdBy,
326
+ createdAt: now,
327
+ lastUsedAt: null,
328
+ expiresAt: input.expiresAt?.toISOString() || null,
329
+ revoked: false
330
+ };
331
+ await this.put(item);
332
+ return { key: this.itemToApiKey(item), plaintext };
333
+ }
334
+ async getApiKey(id) {
335
+ const r = await this.getItem(pk("APIKEY"), id);
336
+ return r ? this.itemToApiKey(r) : null;
337
+ }
338
+ async validateApiKey(plaintext) {
339
+ const keyHash = createHash("sha256").update(plaintext).digest("hex");
340
+ const items = await this.query("APIKEY_HASH", { index: "GSI1", pkField: "GSI1PK", sk: { begins: keyHash }, limit: 1 });
341
+ if (items.length === 0 || items[0].revoked) return null;
342
+ const key = this.itemToApiKey(items[0]);
343
+ if (key.expiresAt && /* @__PURE__ */ new Date() > key.expiresAt) return null;
344
+ items[0].lastUsedAt = (/* @__PURE__ */ new Date()).toISOString();
345
+ await this.put(items[0]);
346
+ return key;
347
+ }
348
+ async listApiKeys(opts) {
349
+ const items = await this.query(pk("APIKEY"));
350
+ let result = items;
351
+ if (opts?.createdBy) result = result.filter((i) => i.createdBy === opts.createdBy);
352
+ return result.map((r) => this.itemToApiKey(r));
353
+ }
354
+ async revokeApiKey(id) {
355
+ const current = await this.getItem(pk("APIKEY"), id);
356
+ if (current) {
357
+ current.revoked = true;
358
+ await this.put(current);
359
+ }
360
+ }
361
+ // ─── Rules ───────────────────────────────────────────────
362
+ async createRule(rule) {
363
+ const id = randomUUID();
364
+ const now = (/* @__PURE__ */ new Date()).toISOString();
365
+ const item = { PK: pk("RULE"), SK: id, ...rule, createdAt: now, updatedAt: now };
366
+ await this.put(item);
367
+ return this.itemToRule(item);
368
+ }
369
+ async getRules(agentId) {
370
+ const items = await this.query(pk("RULE"));
371
+ let result = items;
372
+ if (agentId) result = result.filter((i) => !i.agentId || i.agentId === agentId);
373
+ return result.map((r) => this.itemToRule(r)).sort((a, b) => b.priority - a.priority);
374
+ }
375
+ async updateRule(id, updates) {
376
+ const current = await this.getItem(pk("RULE"), id);
377
+ if (!current) throw new Error("Rule not found");
378
+ const { id: _id, createdAt, ...rest } = updates;
379
+ const merged = { ...current, ...rest, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
380
+ await this.put(merged);
381
+ return this.itemToRule(merged);
382
+ }
383
+ async deleteRule(id) {
384
+ await this.deleteItem(pk("RULE"), id);
385
+ }
386
+ // ─── Retention ───────────────────────────────────────────
387
+ async getRetentionPolicy() {
388
+ const r = await this.getItem(pk("RETENTION"), "default");
389
+ if (!r) return { enabled: false, retainDays: 365, archiveFirst: true };
390
+ return { enabled: r.enabled, retainDays: r.retainDays, excludeTags: r.excludeTags || [], archiveFirst: r.archiveFirst };
391
+ }
392
+ async setRetentionPolicy(policy) {
393
+ await this.put({ PK: pk("RETENTION"), SK: "default", ...policy });
394
+ }
395
+ // ─── Stats ───────────────────────────────────────────────
396
+ async getStats() {
397
+ const [agents, users, audit] = await Promise.all([
398
+ this.query(pk("AGENT")),
399
+ this.query(pk("USER")),
400
+ this.query(pk("AUDIT"))
401
+ ]);
402
+ return {
403
+ totalAgents: agents.length,
404
+ activeAgents: agents.filter((a) => a.status === "active").length,
405
+ totalUsers: users.length,
406
+ totalEmails: 0,
407
+ totalAuditEvents: audit.length
408
+ };
409
+ }
410
+ // ─── Mappers ─────────────────────────────────────────────
411
+ itemToAgent(r) {
412
+ return { id: r.SK || r.id, name: r.name, email: r.email, role: r.role, status: r.status, metadata: r.metadata || {}, createdBy: r.createdBy, createdAt: new Date(r.createdAt), updatedAt: new Date(r.updatedAt) };
413
+ }
414
+ itemToUser(r) {
415
+ return { id: r.SK || r.id, email: r.email, name: r.name, role: r.role, passwordHash: r.passwordHash, ssoProvider: r.ssoProvider, ssoSubject: r.ssoSubject, createdAt: new Date(r.createdAt), updatedAt: new Date(r.updatedAt), lastLoginAt: r.lastLoginAt ? new Date(r.lastLoginAt) : void 0 };
416
+ }
417
+ itemToApiKey(r) {
418
+ return { id: r.SK || r.id, name: r.name, keyHash: r.keyHash, keyPrefix: r.keyPrefix, scopes: r.scopes || [], createdBy: r.createdBy, createdAt: new Date(r.createdAt), lastUsedAt: r.lastUsedAt ? new Date(r.lastUsedAt) : void 0, expiresAt: r.expiresAt ? new Date(r.expiresAt) : void 0, revoked: r.revoked };
419
+ }
420
+ itemToRule(r) {
421
+ return { id: r.SK || r.id, name: r.name, agentId: r.agentId, conditions: r.conditions || {}, actions: r.actions || {}, priority: r.priority || 0, enabled: r.enabled ?? true, createdAt: new Date(r.createdAt), updatedAt: new Date(r.updatedAt) };
422
+ }
423
+ };
424
+ export {
425
+ DynamoAdapter
426
+ };