@lenso/audit 0.0.0-stage → 0.2.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.
@@ -0,0 +1,398 @@
1
+ import type { BunSQLiteDatabase } from "drizzle-orm/bun-sqlite";
2
+ import type { DrizzleD1Database } from "drizzle-orm/d1";
3
+ import type { AuditRepository } from "./contracts";
4
+ export declare const auditEvents: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
5
+ name: "lenso_audit_events";
6
+ schema: undefined;
7
+ columns: {
8
+ tenantKey: import("drizzle-orm/sqlite-core").SQLiteColumn<{
9
+ name: "tenant_key";
10
+ tableName: "lenso_audit_events";
11
+ dataType: "string";
12
+ columnType: "SQLiteText";
13
+ data: string;
14
+ driverParam: string;
15
+ notNull: true;
16
+ hasDefault: false;
17
+ isPrimaryKey: false;
18
+ isAutoincrement: false;
19
+ hasRuntimeDefault: false;
20
+ enumValues: [string, ...string[]];
21
+ baseColumn: never;
22
+ identity: undefined;
23
+ generated: undefined;
24
+ }, {}, {
25
+ length: number | undefined;
26
+ }>;
27
+ scopeId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
28
+ name: "scope_id";
29
+ tableName: "lenso_audit_events";
30
+ dataType: "string";
31
+ columnType: "SQLiteText";
32
+ data: string;
33
+ driverParam: string;
34
+ notNull: true;
35
+ hasDefault: false;
36
+ isPrimaryKey: false;
37
+ isAutoincrement: false;
38
+ hasRuntimeDefault: false;
39
+ enumValues: [string, ...string[]];
40
+ baseColumn: never;
41
+ identity: undefined;
42
+ generated: undefined;
43
+ }, {}, {
44
+ length: number | undefined;
45
+ }>;
46
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
47
+ name: "id";
48
+ tableName: "lenso_audit_events";
49
+ dataType: "string";
50
+ columnType: "SQLiteText";
51
+ data: string;
52
+ driverParam: string;
53
+ notNull: true;
54
+ hasDefault: false;
55
+ isPrimaryKey: false;
56
+ isAutoincrement: false;
57
+ hasRuntimeDefault: false;
58
+ enumValues: [string, ...string[]];
59
+ baseColumn: never;
60
+ identity: undefined;
61
+ generated: undefined;
62
+ }, {}, {
63
+ length: number | undefined;
64
+ }>;
65
+ recordedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
66
+ name: "recorded_at";
67
+ tableName: "lenso_audit_events";
68
+ dataType: "number";
69
+ columnType: "SQLiteInteger";
70
+ data: number;
71
+ driverParam: number;
72
+ notNull: true;
73
+ hasDefault: false;
74
+ isPrimaryKey: false;
75
+ isAutoincrement: false;
76
+ hasRuntimeDefault: false;
77
+ enumValues: undefined;
78
+ baseColumn: never;
79
+ identity: undefined;
80
+ generated: undefined;
81
+ }, {}, {}>;
82
+ action: import("drizzle-orm/sqlite-core").SQLiteColumn<{
83
+ name: "action";
84
+ tableName: "lenso_audit_events";
85
+ dataType: "string";
86
+ columnType: "SQLiteText";
87
+ data: string;
88
+ driverParam: string;
89
+ notNull: true;
90
+ hasDefault: false;
91
+ isPrimaryKey: false;
92
+ isAutoincrement: false;
93
+ hasRuntimeDefault: false;
94
+ enumValues: [string, ...string[]];
95
+ baseColumn: never;
96
+ identity: undefined;
97
+ generated: undefined;
98
+ }, {}, {
99
+ length: number | undefined;
100
+ }>;
101
+ targetType: import("drizzle-orm/sqlite-core").SQLiteColumn<{
102
+ name: "target_type";
103
+ tableName: "lenso_audit_events";
104
+ dataType: "string";
105
+ columnType: "SQLiteText";
106
+ data: string;
107
+ driverParam: string;
108
+ notNull: true;
109
+ hasDefault: false;
110
+ isPrimaryKey: false;
111
+ isAutoincrement: false;
112
+ hasRuntimeDefault: false;
113
+ enumValues: [string, ...string[]];
114
+ baseColumn: never;
115
+ identity: undefined;
116
+ generated: undefined;
117
+ }, {}, {
118
+ length: number | undefined;
119
+ }>;
120
+ targetId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
121
+ name: "target_id";
122
+ tableName: "lenso_audit_events";
123
+ dataType: "string";
124
+ columnType: "SQLiteText";
125
+ data: string;
126
+ driverParam: string;
127
+ notNull: true;
128
+ hasDefault: false;
129
+ isPrimaryKey: false;
130
+ isAutoincrement: false;
131
+ hasRuntimeDefault: false;
132
+ enumValues: [string, ...string[]];
133
+ baseColumn: never;
134
+ identity: undefined;
135
+ generated: undefined;
136
+ }, {}, {
137
+ length: number | undefined;
138
+ }>;
139
+ result: import("drizzle-orm/sqlite-core").SQLiteColumn<{
140
+ name: "result";
141
+ tableName: "lenso_audit_events";
142
+ dataType: "string";
143
+ columnType: "SQLiteText";
144
+ data: string;
145
+ driverParam: string;
146
+ notNull: true;
147
+ hasDefault: false;
148
+ isPrimaryKey: false;
149
+ isAutoincrement: false;
150
+ hasRuntimeDefault: false;
151
+ enumValues: [string, ...string[]];
152
+ baseColumn: never;
153
+ identity: undefined;
154
+ generated: undefined;
155
+ }, {}, {
156
+ length: number | undefined;
157
+ }>;
158
+ correlationId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
159
+ name: "correlation_id";
160
+ tableName: "lenso_audit_events";
161
+ dataType: "string";
162
+ columnType: "SQLiteText";
163
+ data: string;
164
+ driverParam: string;
165
+ notNull: false;
166
+ hasDefault: false;
167
+ isPrimaryKey: false;
168
+ isAutoincrement: false;
169
+ hasRuntimeDefault: false;
170
+ enumValues: [string, ...string[]];
171
+ baseColumn: never;
172
+ identity: undefined;
173
+ generated: undefined;
174
+ }, {}, {
175
+ length: number | undefined;
176
+ }>;
177
+ eventJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
178
+ name: "event_json";
179
+ tableName: "lenso_audit_events";
180
+ dataType: "string";
181
+ columnType: "SQLiteText";
182
+ data: string;
183
+ driverParam: string;
184
+ notNull: true;
185
+ hasDefault: false;
186
+ isPrimaryKey: false;
187
+ isAutoincrement: false;
188
+ hasRuntimeDefault: false;
189
+ enumValues: [string, ...string[]];
190
+ baseColumn: never;
191
+ identity: undefined;
192
+ generated: undefined;
193
+ }, {}, {
194
+ length: number | undefined;
195
+ }>;
196
+ };
197
+ dialect: 'sqlite';
198
+ }>;
199
+ export declare const auditSqliteSchema: {
200
+ auditEvents: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
201
+ name: "lenso_audit_events";
202
+ schema: undefined;
203
+ columns: {
204
+ tenantKey: import("drizzle-orm/sqlite-core").SQLiteColumn<{
205
+ name: "tenant_key";
206
+ tableName: "lenso_audit_events";
207
+ dataType: "string";
208
+ columnType: "SQLiteText";
209
+ data: string;
210
+ driverParam: string;
211
+ notNull: true;
212
+ hasDefault: false;
213
+ isPrimaryKey: false;
214
+ isAutoincrement: false;
215
+ hasRuntimeDefault: false;
216
+ enumValues: [string, ...string[]];
217
+ baseColumn: never;
218
+ identity: undefined;
219
+ generated: undefined;
220
+ }, {}, {
221
+ length: number | undefined;
222
+ }>;
223
+ scopeId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
224
+ name: "scope_id";
225
+ tableName: "lenso_audit_events";
226
+ dataType: "string";
227
+ columnType: "SQLiteText";
228
+ data: string;
229
+ driverParam: string;
230
+ notNull: true;
231
+ hasDefault: false;
232
+ isPrimaryKey: false;
233
+ isAutoincrement: false;
234
+ hasRuntimeDefault: false;
235
+ enumValues: [string, ...string[]];
236
+ baseColumn: never;
237
+ identity: undefined;
238
+ generated: undefined;
239
+ }, {}, {
240
+ length: number | undefined;
241
+ }>;
242
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
243
+ name: "id";
244
+ tableName: "lenso_audit_events";
245
+ dataType: "string";
246
+ columnType: "SQLiteText";
247
+ data: string;
248
+ driverParam: string;
249
+ notNull: true;
250
+ hasDefault: false;
251
+ isPrimaryKey: false;
252
+ isAutoincrement: false;
253
+ hasRuntimeDefault: false;
254
+ enumValues: [string, ...string[]];
255
+ baseColumn: never;
256
+ identity: undefined;
257
+ generated: undefined;
258
+ }, {}, {
259
+ length: number | undefined;
260
+ }>;
261
+ recordedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
262
+ name: "recorded_at";
263
+ tableName: "lenso_audit_events";
264
+ dataType: "number";
265
+ columnType: "SQLiteInteger";
266
+ data: number;
267
+ driverParam: number;
268
+ notNull: true;
269
+ hasDefault: false;
270
+ isPrimaryKey: false;
271
+ isAutoincrement: false;
272
+ hasRuntimeDefault: false;
273
+ enumValues: undefined;
274
+ baseColumn: never;
275
+ identity: undefined;
276
+ generated: undefined;
277
+ }, {}, {}>;
278
+ action: import("drizzle-orm/sqlite-core").SQLiteColumn<{
279
+ name: "action";
280
+ tableName: "lenso_audit_events";
281
+ dataType: "string";
282
+ columnType: "SQLiteText";
283
+ data: string;
284
+ driverParam: string;
285
+ notNull: true;
286
+ hasDefault: false;
287
+ isPrimaryKey: false;
288
+ isAutoincrement: false;
289
+ hasRuntimeDefault: false;
290
+ enumValues: [string, ...string[]];
291
+ baseColumn: never;
292
+ identity: undefined;
293
+ generated: undefined;
294
+ }, {}, {
295
+ length: number | undefined;
296
+ }>;
297
+ targetType: import("drizzle-orm/sqlite-core").SQLiteColumn<{
298
+ name: "target_type";
299
+ tableName: "lenso_audit_events";
300
+ dataType: "string";
301
+ columnType: "SQLiteText";
302
+ data: string;
303
+ driverParam: string;
304
+ notNull: true;
305
+ hasDefault: false;
306
+ isPrimaryKey: false;
307
+ isAutoincrement: false;
308
+ hasRuntimeDefault: false;
309
+ enumValues: [string, ...string[]];
310
+ baseColumn: never;
311
+ identity: undefined;
312
+ generated: undefined;
313
+ }, {}, {
314
+ length: number | undefined;
315
+ }>;
316
+ targetId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
317
+ name: "target_id";
318
+ tableName: "lenso_audit_events";
319
+ dataType: "string";
320
+ columnType: "SQLiteText";
321
+ data: string;
322
+ driverParam: string;
323
+ notNull: true;
324
+ hasDefault: false;
325
+ isPrimaryKey: false;
326
+ isAutoincrement: false;
327
+ hasRuntimeDefault: false;
328
+ enumValues: [string, ...string[]];
329
+ baseColumn: never;
330
+ identity: undefined;
331
+ generated: undefined;
332
+ }, {}, {
333
+ length: number | undefined;
334
+ }>;
335
+ result: import("drizzle-orm/sqlite-core").SQLiteColumn<{
336
+ name: "result";
337
+ tableName: "lenso_audit_events";
338
+ dataType: "string";
339
+ columnType: "SQLiteText";
340
+ data: string;
341
+ driverParam: string;
342
+ notNull: true;
343
+ hasDefault: false;
344
+ isPrimaryKey: false;
345
+ isAutoincrement: false;
346
+ hasRuntimeDefault: false;
347
+ enumValues: [string, ...string[]];
348
+ baseColumn: never;
349
+ identity: undefined;
350
+ generated: undefined;
351
+ }, {}, {
352
+ length: number | undefined;
353
+ }>;
354
+ correlationId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
355
+ name: "correlation_id";
356
+ tableName: "lenso_audit_events";
357
+ dataType: "string";
358
+ columnType: "SQLiteText";
359
+ data: string;
360
+ driverParam: string;
361
+ notNull: false;
362
+ hasDefault: false;
363
+ isPrimaryKey: false;
364
+ isAutoincrement: false;
365
+ hasRuntimeDefault: false;
366
+ enumValues: [string, ...string[]];
367
+ baseColumn: never;
368
+ identity: undefined;
369
+ generated: undefined;
370
+ }, {}, {
371
+ length: number | undefined;
372
+ }>;
373
+ eventJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
374
+ name: "event_json";
375
+ tableName: "lenso_audit_events";
376
+ dataType: "string";
377
+ columnType: "SQLiteText";
378
+ data: string;
379
+ driverParam: string;
380
+ notNull: true;
381
+ hasDefault: false;
382
+ isPrimaryKey: false;
383
+ isAutoincrement: false;
384
+ hasRuntimeDefault: false;
385
+ enumValues: [string, ...string[]];
386
+ baseColumn: never;
387
+ identity: undefined;
388
+ generated: undefined;
389
+ }, {}, {
390
+ length: number | undefined;
391
+ }>;
392
+ };
393
+ dialect: 'sqlite';
394
+ }>;
395
+ };
396
+ export declare function createSqliteAuditRepository<TSchema extends Record<string, unknown>>(db: BunSQLiteDatabase<TSchema> | DrizzleD1Database<TSchema>, options?: {
397
+ durableIntents?: boolean;
398
+ }): AuditRepository;
package/dist/sqlite.js ADDED
@@ -0,0 +1,80 @@
1
+ import {
2
+ tenantKey,
3
+ decodeEvent,
4
+ insertionResult
5
+ } from "./index-9cajwcjn.js";
6
+
7
+ // src/sqlite.ts
8
+ import { and, desc, eq, lt, or, gte, lte } from "drizzle-orm";
9
+ import { index, integer, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core";
10
+ var auditEvents = sqliteTable("lenso_audit_events", {
11
+ tenantKey: text("tenant_key").notNull(),
12
+ scopeId: text("scope_id").notNull(),
13
+ id: text("id").notNull(),
14
+ recordedAt: integer("recorded_at").notNull(),
15
+ action: text("action").notNull(),
16
+ targetType: text("target_type").notNull(),
17
+ targetId: text("target_id").notNull(),
18
+ result: text("result").notNull(),
19
+ correlationId: text("correlation_id"),
20
+ eventJson: text("event_json").notNull()
21
+ }, (table) => [
22
+ primaryKey({ columns: [table.tenantKey, table.scopeId, table.id] }),
23
+ index("lenso_audit_events_scope_order").on(table.tenantKey, table.scopeId, desc(table.recordedAt), desc(table.id))
24
+ ]);
25
+ var auditSqliteSchema = { auditEvents };
26
+ function createSqliteAuditRepository(db, options = {}) {
27
+ return {
28
+ durableIntents: options.durableIntents ?? false,
29
+ async insert(event) {
30
+ const rows = await db.insert(auditEvents).values({
31
+ tenantKey: tenantKey(event.scope),
32
+ scopeId: event.scope.scopeId,
33
+ id: event.id,
34
+ recordedAt: event.recordedAt,
35
+ action: event.action,
36
+ targetType: event.target.type,
37
+ targetId: event.target.id,
38
+ result: event.result,
39
+ correlationId: event.correlationId ?? null,
40
+ eventJson: JSON.stringify(event)
41
+ }).onConflictDoNothing({
42
+ target: [auditEvents.tenantKey, auditEvents.scopeId, auditEvents.id]
43
+ }).returning();
44
+ if (rows.length)
45
+ return "inserted";
46
+ return insertionResult(event, await this.get(event.scope, event.id) ?? undefined);
47
+ },
48
+ async get(scope, id) {
49
+ const rows = await db.select().from(auditEvents).where(and(eq(auditEvents.tenantKey, tenantKey(scope)), eq(auditEvents.scopeId, scope.scopeId), eq(auditEvents.id, id))).limit(1);
50
+ return rows[0] ? decodeEvent(rows[0].eventJson) : null;
51
+ },
52
+ async list(query) {
53
+ const terms = [
54
+ eq(auditEvents.tenantKey, tenantKey(query.scope)),
55
+ eq(auditEvents.scopeId, query.scope.scopeId)
56
+ ];
57
+ if (query.action !== undefined)
58
+ terms.push(eq(auditEvents.action, query.action));
59
+ if (query.target)
60
+ terms.push(eq(auditEvents.targetType, query.target.type), eq(auditEvents.targetId, query.target.id));
61
+ if (query.result !== undefined)
62
+ terms.push(eq(auditEvents.result, query.result));
63
+ if (query.correlationId !== undefined)
64
+ terms.push(eq(auditEvents.correlationId, query.correlationId));
65
+ if (query.recordedFrom !== undefined)
66
+ terms.push(gte(auditEvents.recordedAt, query.recordedFrom));
67
+ if (query.recordedTo !== undefined)
68
+ terms.push(lte(auditEvents.recordedAt, query.recordedTo));
69
+ if (query.cursor)
70
+ terms.push(or(lt(auditEvents.recordedAt, query.cursor.recordedAt), and(eq(auditEvents.recordedAt, query.cursor.recordedAt), lt(auditEvents.id, query.cursor.id))));
71
+ const rows = await db.select().from(auditEvents).where(and(...terms)).orderBy(desc(auditEvents.recordedAt), desc(auditEvents.id)).limit(query.limit);
72
+ return rows.map((row) => decodeEvent(row.eventJson));
73
+ }
74
+ };
75
+ }
76
+ export {
77
+ auditEvents,
78
+ auditSqliteSchema,
79
+ createSqliteAuditRepository
80
+ };
@@ -0,0 +1,26 @@
1
+ import { z } from "zod";
2
+ import type { AuditScope } from "./contracts";
3
+ import type { AuditService } from "./service";
4
+ /**
5
+ * The job carries only a locator. An application-owned resolver must check the
6
+ * real effect and supply a stable new event ID; queue payloads grant no authority.
7
+ */
8
+ export declare function createAuditReconciliationTask<P>(options: {
9
+ name: string;
10
+ audit: AuditService<P>;
11
+ principal(): Promise<P>;
12
+ reconcile(intentId: string, scope: AuditScope): Promise<{
13
+ id: string;
14
+ occurredAt: number;
15
+ result: "success" | "failure" | "unknown";
16
+ reasonCode: string;
17
+ }>;
18
+ }): import("@lenso/tasks").Task<z.ZodObject<{
19
+ scope: z.ZodObject<{
20
+ tenantId: z.ZodNullable<z.ZodString>;
21
+ scopeId: z.ZodString;
22
+ }, z.core.$strict>;
23
+ intentId: z.ZodString;
24
+ }, z.core.$strict>, {
25
+ eventId: string;
26
+ }>;
package/dist/tasks.js ADDED
@@ -0,0 +1,40 @@
1
+ import {
2
+ eventIdPattern
3
+ } from "./index-xk4zknet.js";
4
+
5
+ // src/tasks.ts
6
+ import { defineTask } from "@lenso/tasks";
7
+ import { z } from "zod";
8
+ var reconciliationInput = z.strictObject({
9
+ scope: z.strictObject({
10
+ tenantId: z.string().min(1).max(128).nullable(),
11
+ scopeId: z.string().min(1).max(128)
12
+ }),
13
+ intentId: z.string().regex(eventIdPattern)
14
+ });
15
+ function createAuditReconciliationTask(options) {
16
+ return defineTask({
17
+ name: options.name,
18
+ input: reconciliationInput,
19
+ async handler(input) {
20
+ const principal = await options.principal();
21
+ const intent = await options.audit.get({ scope: input.scope, id: input.intentId }, principal);
22
+ if (!intent || intent.result !== "intent")
23
+ throw new Error("Audit reconciliation intent missing");
24
+ const outcome = await options.reconcile(intent.id, intent.scope);
25
+ const result = await options.audit.append({
26
+ ...outcome,
27
+ scope: intent.scope,
28
+ action: intent.action,
29
+ target: intent.target,
30
+ ...intent.correlationId ? { correlationId: intent.correlationId } : {},
31
+ relation: { kind: "outcome", eventId: intent.id }
32
+ }, principal);
33
+ return { eventId: result.event.id };
34
+ },
35
+ result: (value) => value
36
+ });
37
+ }
38
+ export {
39
+ createAuditReconciliationTask
40
+ };
@@ -0,0 +1,16 @@
1
+ import { type AuditActor, type AuditInput, type AuditQuery, type AuditScope, type SummaryPolicy, type SummaryValue } from "./contracts";
2
+ export declare const eventIdPattern: RegExp;
3
+ export declare function invalid(): never;
4
+ export declare function object(value: unknown, keys?: readonly string[]): Record<string, unknown>;
5
+ export declare function identifier(value: unknown, max?: number): string;
6
+ export declare function uuid(value: unknown): string;
7
+ export declare function time(value: unknown): number;
8
+ export declare function scope(value: unknown): AuditScope;
9
+ export declare function actor(value: unknown): AuditActor;
10
+ export declare function summaryPolicy(data: SummaryPolicy): SummaryPolicy;
11
+ export declare function eventInput(data: AuditInput, policy: SummaryPolicy): AuditInput & {
12
+ summary: Readonly<Record<string, SummaryValue>>;
13
+ };
14
+ export declare function query(value: AuditQuery, maxPageSize: number): AuditQuery & {
15
+ limit: number;
16
+ };
@@ -0,0 +1,15 @@
1
+ CREATE TABLE lenso_audit_events (
2
+ tenant_key TEXT NOT NULL,
3
+ scope_id TEXT NOT NULL,
4
+ id TEXT NOT NULL,
5
+ recorded_at BIGINT NOT NULL,
6
+ action TEXT NOT NULL,
7
+ target_type TEXT NOT NULL,
8
+ target_id TEXT NOT NULL,
9
+ result TEXT NOT NULL,
10
+ correlation_id TEXT,
11
+ event_json TEXT NOT NULL,
12
+ PRIMARY KEY (tenant_key, scope_id, id)
13
+ );
14
+ CREATE INDEX lenso_audit_events_scope_order
15
+ ON lenso_audit_events (tenant_key, scope_id, recorded_at DESC, id DESC);
@@ -0,0 +1,15 @@
1
+ CREATE TABLE lenso_audit_events (
2
+ tenant_key TEXT NOT NULL,
3
+ scope_id TEXT NOT NULL,
4
+ id TEXT NOT NULL,
5
+ recorded_at INTEGER NOT NULL,
6
+ action TEXT NOT NULL,
7
+ target_type TEXT NOT NULL,
8
+ target_id TEXT NOT NULL,
9
+ result TEXT NOT NULL,
10
+ correlation_id TEXT,
11
+ event_json TEXT NOT NULL,
12
+ PRIMARY KEY (tenant_key, scope_id, id)
13
+ );
14
+ CREATE INDEX lenso_audit_events_scope_order
15
+ ON lenso_audit_events (tenant_key, scope_id, recorded_at DESC, id DESC);