evlog 2.13.0 → 2.14.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.
- package/README.md +118 -15
- package/dist/{_http-CHSsrWDJ.mjs → _http-BY1e9pwC.mjs} +9 -2
- package/dist/_http-BY1e9pwC.mjs.map +1 -0
- package/dist/adapters/axiom.d.mts +1 -1
- package/dist/adapters/axiom.mjs +1 -1
- package/dist/adapters/axiom.mjs.map +1 -1
- package/dist/adapters/better-stack.d.mts +1 -1
- package/dist/adapters/better-stack.mjs +1 -1
- package/dist/adapters/better-stack.mjs.map +1 -1
- package/dist/adapters/datadog.d.mts +1 -1
- package/dist/adapters/datadog.mjs +1 -1
- package/dist/adapters/datadog.mjs.map +1 -1
- package/dist/adapters/fs.d.mts +1 -1
- package/dist/adapters/fs.mjs.map +1 -1
- package/dist/adapters/hyperdx.d.mts +1 -1
- package/dist/adapters/hyperdx.mjs +1 -1
- package/dist/adapters/otlp.d.mts +1 -1
- package/dist/adapters/otlp.mjs +1 -1
- package/dist/adapters/otlp.mjs.map +1 -1
- package/dist/adapters/posthog.d.mts +1 -1
- package/dist/adapters/posthog.mjs +1 -1
- package/dist/adapters/posthog.mjs.map +1 -1
- package/dist/adapters/sentry.d.mts +1 -1
- package/dist/adapters/sentry.mjs +1 -1
- package/dist/adapters/sentry.mjs.map +1 -1
- package/dist/ai/index.d.mts +106 -5
- package/dist/ai/index.d.mts.map +1 -1
- package/dist/ai/index.mjs +28 -5
- package/dist/ai/index.mjs.map +1 -1
- package/dist/{types-DbzDln7O.d.mts → audit-CTIviX3P.d.mts} +509 -3
- package/dist/audit-CTIviX3P.d.mts.map +1 -0
- package/dist/{logger-DnobymUQ.mjs → audit-DQoBo7Dl.mjs} +758 -16
- package/dist/audit-DQoBo7Dl.mjs.map +1 -0
- package/dist/better-auth/index.d.mts +1 -1
- package/dist/better-auth/index.mjs.map +1 -1
- package/dist/browser.d.mts +1 -1
- package/dist/elysia/index.d.mts +2 -2
- package/dist/elysia/index.mjs +2 -2
- package/dist/enrichers.d.mts +1 -1
- package/dist/enrichers.mjs.map +1 -1
- package/dist/{error-B9CiGK_i.d.mts → error-C7gSQVqk.d.mts} +2 -2
- package/dist/{error-B9CiGK_i.d.mts.map → error-C7gSQVqk.d.mts.map} +1 -1
- package/dist/error.d.mts +1 -1
- package/dist/{errors-Dr0r4OpR.d.mts → errors-4MPmTzjY.d.mts} +2 -2
- package/dist/{errors-Dr0r4OpR.d.mts.map → errors-4MPmTzjY.d.mts.map} +1 -1
- package/dist/express/index.d.mts +2 -2
- package/dist/express/index.mjs +2 -2
- package/dist/fastify/index.d.mts +2 -2
- package/dist/fastify/index.mjs +2 -2
- package/dist/{fork-Y4z8iHti.mjs → fork-D1j1Fuzy.mjs} +3 -3
- package/dist/{fork-Y4z8iHti.mjs.map → fork-D1j1Fuzy.mjs.map} +1 -1
- package/dist/hono/index.d.mts +2 -2
- package/dist/hono/index.mjs +1 -1
- package/dist/http.d.mts +1 -1
- package/dist/http.d.mts.map +1 -1
- package/dist/http.mjs +3 -2
- package/dist/http.mjs.map +1 -1
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +2 -2
- package/dist/{logger-Dp6nYWjH.d.mts → logger-DttRJRGa.d.mts} +23 -4
- package/dist/logger-DttRJRGa.d.mts.map +1 -0
- package/dist/logger.d.mts +1 -1
- package/dist/logger.mjs +1 -1
- package/dist/{middleware-FgC1OdOD.d.mts → middleware-CTnDsST-.d.mts} +2 -2
- package/dist/{middleware-FgC1OdOD.d.mts.map → middleware-CTnDsST-.d.mts.map} +1 -1
- package/dist/{middleware-BtBuosFV.mjs → middleware-oAccqyPp.mjs} +2 -2
- package/dist/{middleware-BtBuosFV.mjs.map → middleware-oAccqyPp.mjs.map} +1 -1
- package/dist/nestjs/index.d.mts +2 -2
- package/dist/nestjs/index.mjs +2 -2
- package/dist/next/client.d.mts +1 -1
- package/dist/next/index.d.mts +4 -4
- package/dist/next/index.mjs +2 -2
- package/dist/next/index.mjs.map +1 -1
- package/dist/next/instrumentation.d.mts +1 -1
- package/dist/next/instrumentation.mjs +1 -1
- package/dist/next/instrumentation.mjs.map +1 -1
- package/dist/nitro/errorHandler.mjs.map +1 -1
- package/dist/nitro/module.d.mts +2 -2
- package/dist/nitro/plugin.mjs +1 -1
- package/dist/nitro/plugin.mjs.map +1 -1
- package/dist/nitro/v3/index.d.mts +2 -2
- package/dist/nitro/v3/middleware.mjs.map +1 -1
- package/dist/nitro/v3/module.d.mts +1 -1
- package/dist/nitro/v3/plugin.mjs +1 -1
- package/dist/nitro/v3/plugin.mjs.map +1 -1
- package/dist/nitro/v3/useLogger.d.mts +1 -1
- package/dist/nitro/v3/useLogger.mjs.map +1 -1
- package/dist/{nitro-CDHLfRdw.d.mts → nitro-CPPRCPbG.d.mts} +2 -2
- package/dist/{nitro-CDHLfRdw.d.mts.map → nitro-CPPRCPbG.d.mts.map} +1 -1
- package/dist/nuxt/module.d.mts +1 -1
- package/dist/nuxt/module.mjs +1 -1
- package/dist/{parseError-DM-lyezZ.d.mts → parseError-o1GpZEOR.d.mts} +2 -2
- package/dist/parseError-o1GpZEOR.d.mts.map +1 -0
- package/dist/pipeline.mjs.map +1 -1
- package/dist/react-router/index.d.mts +2 -2
- package/dist/react-router/index.mjs +2 -2
- package/dist/runtime/client/log.d.mts +1 -1
- package/dist/runtime/client/log.mjs +2 -2
- package/dist/runtime/client/log.mjs.map +1 -1
- package/dist/runtime/client/plugin.mjs.map +1 -1
- package/dist/runtime/server/routes/_evlog/ingest.post.mjs +1 -1
- package/dist/runtime/server/routes/_evlog/ingest.post.mjs.map +1 -1
- package/dist/runtime/server/useLogger.d.mts +1 -1
- package/dist/runtime/server/useLogger.mjs.map +1 -1
- package/dist/runtime/utils/parseError.d.mts +2 -2
- package/dist/source-location-DRvDDqfq.mjs.map +1 -1
- package/dist/sveltekit/index.d.mts +2 -2
- package/dist/sveltekit/index.mjs +2 -2
- package/dist/sveltekit/index.mjs.map +1 -1
- package/dist/toolkit.d.mts +3 -3
- package/dist/toolkit.mjs +2 -2
- package/dist/types.d.mts +2 -2
- package/dist/{useLogger-N5A-d5l9.d.mts → useLogger-CyPP1sVB.d.mts} +2 -2
- package/dist/{useLogger-N5A-d5l9.d.mts.map → useLogger-CyPP1sVB.d.mts.map} +1 -1
- package/dist/{utils-DnX6VMNi.d.mts → utils-Dmin7wVL.d.mts} +4 -3
- package/dist/utils-Dmin7wVL.d.mts.map +1 -0
- package/dist/utils.d.mts +2 -2
- package/dist/utils.mjs +7 -1
- package/dist/utils.mjs.map +1 -1
- package/dist/vite/index.d.mts +1 -1
- package/dist/vite/index.mjs.map +1 -1
- package/dist/workers.d.mts +48 -4
- package/dist/workers.d.mts.map +1 -1
- package/dist/workers.mjs +32 -5
- package/dist/workers.mjs.map +1 -1
- package/package.json +17 -21
- package/dist/_http-CHSsrWDJ.mjs.map +0 -1
- package/dist/logger-DnobymUQ.mjs.map +0 -1
- package/dist/logger-Dp6nYWjH.d.mts.map +0 -1
- package/dist/parseError-DM-lyezZ.d.mts.map +0 -1
- package/dist/types-DbzDln7O.d.mts.map +0 -1
- package/dist/utils-DnX6VMNi.d.mts.map +0 -1
|
@@ -363,7 +363,97 @@ interface LoggerConfig {
|
|
|
363
363
|
_suppressDrainWarning?: boolean;
|
|
364
364
|
}
|
|
365
365
|
/**
|
|
366
|
-
*
|
|
366
|
+
* Audit actor — who initiated the action.
|
|
367
|
+
*
|
|
368
|
+
* `type` covers the most common actor families. `id` is required and should be
|
|
369
|
+
* a stable identifier (user id, service name, API key id, agent id). `model`,
|
|
370
|
+
* `tools`, `reason`, and `promptId` are filled when `type === 'agent'` and
|
|
371
|
+
* mirror the AI SDK fields already used by `evlog/ai`.
|
|
372
|
+
*/
|
|
373
|
+
interface AuditActor {
|
|
374
|
+
type: 'user' | 'system' | 'api' | 'agent';
|
|
375
|
+
id: string;
|
|
376
|
+
displayName?: string;
|
|
377
|
+
email?: string;
|
|
378
|
+
model?: string;
|
|
379
|
+
tools?: string[];
|
|
380
|
+
reason?: string;
|
|
381
|
+
promptId?: string;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Audit target — the resource the action was performed on.
|
|
385
|
+
*
|
|
386
|
+
* `type` is a free-form string (e.g. `'invoice'`, `'user'`, `'subscription'`)
|
|
387
|
+
* narrowed by {@link defineAuditAction}. Additional fields are allowed for
|
|
388
|
+
* resource-specific metadata (e.g. `tenantId`, `path`, `previousOwnerId`).
|
|
389
|
+
*/
|
|
390
|
+
interface AuditTarget {
|
|
391
|
+
type: string;
|
|
392
|
+
id: string;
|
|
393
|
+
[key: string]: unknown;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Reserved audit fields on the wide event.
|
|
397
|
+
*
|
|
398
|
+
* Set via `log.audit({ ... })`, `log.set({ audit: { ... } })`, or the
|
|
399
|
+
* standalone `audit({ ... })` helper. Downstream filters on `audit IS NOT NULL`.
|
|
400
|
+
*
|
|
401
|
+
* - `outcome` — `'success' | 'failure' | 'denied'`. `'denied'` records an
|
|
402
|
+
* AuthZ-denied action (often forgotten but exactly what auditors want).
|
|
403
|
+
* - `changes.before/after` — the diff for mutating actions. Use
|
|
404
|
+
* {@link auditDiff} to produce a redact-aware compact JSON Patch.
|
|
405
|
+
* - `causationId` / `correlationId` — chain related actions (admin action →
|
|
406
|
+
* system reactions). Set by callers, propagated by `auditEnricher` when
|
|
407
|
+
* available on the request.
|
|
408
|
+
* - `signature` / `prevHash` — populated by the {@link signed} drain wrapper.
|
|
409
|
+
* Never set by application code.
|
|
410
|
+
* - `idempotencyKey` — derived deterministically by `log.audit()` so retries
|
|
411
|
+
* across drains are safe.
|
|
412
|
+
* - `context` — request/runtime context auto-populated by {@link auditEnricher}
|
|
413
|
+
* (`requestId`, `traceId`, `ip`, `userAgent`, `tenantId`).
|
|
414
|
+
*/
|
|
415
|
+
interface AuditFields {
|
|
416
|
+
/** Action name. Convention: `'<resource>.<verb>'`, e.g. `'invoice.refund'`. */
|
|
417
|
+
action: string;
|
|
418
|
+
actor: AuditActor;
|
|
419
|
+
target?: AuditTarget;
|
|
420
|
+
outcome: 'success' | 'failure' | 'denied';
|
|
421
|
+
/** Human-readable explanation, especially required for `outcome: 'denied'`. */
|
|
422
|
+
reason?: string;
|
|
423
|
+
/** Before/after snapshots for mutating actions. */
|
|
424
|
+
changes?: {
|
|
425
|
+
before?: unknown;
|
|
426
|
+
after?: unknown;
|
|
427
|
+
};
|
|
428
|
+
/** ID of the action that caused this one. */
|
|
429
|
+
causationId?: string;
|
|
430
|
+
/** ID shared by every action in the same logical operation. */
|
|
431
|
+
correlationId?: string;
|
|
432
|
+
/** Schema version of the audit envelope. Defaults to `1` when omitted by the caller. */
|
|
433
|
+
version?: number;
|
|
434
|
+
/** Set by `log.audit()` as a stable hash for safe retries across drains. */
|
|
435
|
+
idempotencyKey?: string;
|
|
436
|
+
/** Request/runtime context — populated by `auditEnricher`. */
|
|
437
|
+
context?: {
|
|
438
|
+
requestId?: string;
|
|
439
|
+
traceId?: string;
|
|
440
|
+
ip?: string;
|
|
441
|
+
userAgent?: string;
|
|
442
|
+
tenantId?: string;
|
|
443
|
+
[key: string]: unknown;
|
|
444
|
+
};
|
|
445
|
+
/** HMAC signature of the event when wrapped with `signed({ strategy: 'hmac' })`. */
|
|
446
|
+
signature?: string;
|
|
447
|
+
/** Previous event hash when wrapped with `signed({ strategy: 'hash-chain' })`. */
|
|
448
|
+
prevHash?: string;
|
|
449
|
+
/** Hash of the current event when wrapped with `signed({ strategy: 'hash-chain' })`. */
|
|
450
|
+
hash?: string;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Base structure for all wide events.
|
|
454
|
+
*
|
|
455
|
+
* Augment via `declare module 'evlog'` to add app-specific top-level fields.
|
|
456
|
+
* `audit` is reserved for {@link AuditFields}.
|
|
367
457
|
*/
|
|
368
458
|
interface BaseWideEvent {
|
|
369
459
|
timestamp: string;
|
|
@@ -373,6 +463,7 @@ interface BaseWideEvent {
|
|
|
373
463
|
version?: string;
|
|
374
464
|
commitHash?: string;
|
|
375
465
|
region?: string;
|
|
466
|
+
audit?: AuditFields;
|
|
376
467
|
}
|
|
377
468
|
/**
|
|
378
469
|
* Wide event with arbitrary additional fields
|
|
@@ -508,6 +599,34 @@ interface RequestLogger<T extends object = Record<string, unknown>> {
|
|
|
508
599
|
* ```
|
|
509
600
|
*/
|
|
510
601
|
fork?: (label: string, fn: () => void | Promise<void>) => void;
|
|
602
|
+
/**
|
|
603
|
+
* Record an audit event on this wide event. Strictly equivalent to
|
|
604
|
+
* `log.set({ audit: { ... } })` plus tail-sample force-keep.
|
|
605
|
+
*
|
|
606
|
+
* Use `log.audit.deny(reason, fields)` for AuthZ-denied actions — most teams
|
|
607
|
+
* forget to log denials but they are exactly what auditors and security teams
|
|
608
|
+
* ask for.
|
|
609
|
+
*
|
|
610
|
+
* Available on every logger returned by `createLogger()` / `createRequestLogger()`
|
|
611
|
+
* and on framework loggers exposed via `useLogger()` / `c.get('log')` etc.
|
|
612
|
+
*
|
|
613
|
+
* @example
|
|
614
|
+
* ```ts
|
|
615
|
+
* log.audit({
|
|
616
|
+
* action: 'invoice.refund',
|
|
617
|
+
* actor: { type: 'user', id: user.id, email: user.email },
|
|
618
|
+
* target: { type: 'invoice', id: 'inv_889' },
|
|
619
|
+
* outcome: 'success',
|
|
620
|
+
* reason: 'Customer requested refund',
|
|
621
|
+
* })
|
|
622
|
+
* ```
|
|
623
|
+
*/
|
|
624
|
+
audit?: AuditLoggerMethod;
|
|
625
|
+
}
|
|
626
|
+
/** @internal Forward-declaration to avoid a circular import with `audit.ts`. */
|
|
627
|
+
interface AuditLoggerMethod {
|
|
628
|
+
(input: AuditInput): void;
|
|
629
|
+
deny: (reason: string, input: Omit<AuditInput, 'outcome' | 'reason'>) => void;
|
|
511
630
|
}
|
|
512
631
|
/**
|
|
513
632
|
* Log level type
|
|
@@ -581,6 +700,16 @@ interface RequestLoggerOptions {
|
|
|
581
700
|
method?: string;
|
|
582
701
|
path?: string;
|
|
583
702
|
requestId?: string;
|
|
703
|
+
/**
|
|
704
|
+
* Registers async drain work with the host runtime so it can finish after the
|
|
705
|
+
* HTTP response is returned. Required on **Cloudflare Workers** (and similar
|
|
706
|
+
* edge runtimes): without this, `initLogger({ drain })` + `log.emit()` may
|
|
707
|
+
* never complete outbound HTTP to observability backends.
|
|
708
|
+
*
|
|
709
|
+
* Pass the same function you would pass to `ExecutionContext#waitUntil`, e.g.
|
|
710
|
+
* `context.waitUntil.bind(context)` from a Workers `fetch` handler.
|
|
711
|
+
*/
|
|
712
|
+
waitUntil?: (promise: Promise<unknown>) => void;
|
|
584
713
|
}
|
|
585
714
|
/**
|
|
586
715
|
* H3 event context with evlog logger attached
|
|
@@ -630,5 +759,382 @@ interface ParsedError {
|
|
|
630
759
|
raw: unknown;
|
|
631
760
|
}
|
|
632
761
|
//#endregion
|
|
633
|
-
|
|
634
|
-
|
|
762
|
+
//#region src/audit.d.ts
|
|
763
|
+
/**
|
|
764
|
+
* Current version of the audit envelope. Bumped when `AuditFields` evolves
|
|
765
|
+
* in a backward-incompatible way so downstream pipelines can branch on it.
|
|
766
|
+
*/
|
|
767
|
+
declare const AUDIT_SCHEMA_VERSION = 1;
|
|
768
|
+
/**
|
|
769
|
+
* Input accepted by `log.audit()`, `audit()`, and `withAudit()`.
|
|
770
|
+
*
|
|
771
|
+
* `outcome` defaults to `'success'`. Internal fields populated by the audit
|
|
772
|
+
* pipeline (`idempotencyKey`, `context`, `signature`, `prevHash`, `hash`) are
|
|
773
|
+
* stripped — pass them through `log.set({ audit })` if you really need to.
|
|
774
|
+
*/
|
|
775
|
+
interface AuditInput {
|
|
776
|
+
action: string;
|
|
777
|
+
actor: AuditActor;
|
|
778
|
+
target?: AuditTarget;
|
|
779
|
+
outcome?: AuditFields['outcome'];
|
|
780
|
+
reason?: string;
|
|
781
|
+
changes?: AuditFields['changes'];
|
|
782
|
+
causationId?: string;
|
|
783
|
+
correlationId?: string;
|
|
784
|
+
version?: number;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Build a normalised {@link AuditFields} from caller input. Defaults:
|
|
788
|
+
* - `outcome` → `'success'`
|
|
789
|
+
* - `version` → {@link AUDIT_SCHEMA_VERSION}
|
|
790
|
+
*
|
|
791
|
+
* `idempotencyKey` is filled at emit time with the event timestamp so retries
|
|
792
|
+
* stay deterministic.
|
|
793
|
+
*/
|
|
794
|
+
declare function buildAuditFields(input: AuditInput): AuditFields;
|
|
795
|
+
/**
|
|
796
|
+
* Add audit semantics to an existing {@link RequestLogger}.
|
|
797
|
+
*
|
|
798
|
+
* Mutates the logger in place by adding an `audit` method (with a `.deny()`
|
|
799
|
+
* sub-method). Strictly equivalent to calling `log.set({ audit: ... })` plus
|
|
800
|
+
* `_forceKeep` on emit. Idempotent: calling twice on the same logger only
|
|
801
|
+
* attaches the methods once.
|
|
802
|
+
*
|
|
803
|
+
* @example
|
|
804
|
+
* ```ts
|
|
805
|
+
* const log = withAuditMethods(createLogger())
|
|
806
|
+
* log.audit({
|
|
807
|
+
* action: 'invoice.refund',
|
|
808
|
+
* actor: { type: 'user', id: user.id },
|
|
809
|
+
* target: { type: 'invoice', id: 'inv_889' },
|
|
810
|
+
* })
|
|
811
|
+
* ```
|
|
812
|
+
*/
|
|
813
|
+
declare function withAuditMethods<T extends object = Record<string, unknown>>(logger: RequestLogger<T>): AuditableLogger<T>;
|
|
814
|
+
/**
|
|
815
|
+
* Logger augmented with `.audit()` / `.audit.deny()` helpers.
|
|
816
|
+
*/
|
|
817
|
+
type AuditableLogger<T extends object = Record<string, unknown>> = RequestLogger<T> & {
|
|
818
|
+
audit: AuditMethod<T>;
|
|
819
|
+
};
|
|
820
|
+
/** Method shape attached to {@link AuditableLogger}. */
|
|
821
|
+
interface AuditMethod<T extends object = Record<string, unknown>> {
|
|
822
|
+
(input: AuditInput): void;
|
|
823
|
+
/**
|
|
824
|
+
* Record an AuthZ-denied action. Forces `outcome: 'denied'` and requires
|
|
825
|
+
* a human-readable `reason`. Most teams forget to log denials — they are
|
|
826
|
+
* exactly what auditors and security teams ask for.
|
|
827
|
+
*/
|
|
828
|
+
deny: (reason: string, input: Omit<AuditInput, 'outcome' | 'reason'>) => void;
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Standalone audit emitter for non-request contexts (jobs, scripts, CLIs).
|
|
832
|
+
*
|
|
833
|
+
* Creates a one-shot logger, sets the audit fields, and emits immediately.
|
|
834
|
+
* The event is force-kept past tail sampling. Returns the emitted wide event,
|
|
835
|
+
* or `null` if logging is globally disabled.
|
|
836
|
+
*
|
|
837
|
+
* @example
|
|
838
|
+
* ```ts
|
|
839
|
+
* import { audit } from 'evlog'
|
|
840
|
+
*
|
|
841
|
+
* audit({
|
|
842
|
+
* action: 'cron.cleanup',
|
|
843
|
+
* actor: { type: 'system', id: 'cron' },
|
|
844
|
+
* target: { type: 'job', id: 'cleanup-stale-sessions' },
|
|
845
|
+
* outcome: 'success',
|
|
846
|
+
* })
|
|
847
|
+
* ```
|
|
848
|
+
*/
|
|
849
|
+
declare function audit(input: AuditInput): WideEvent | null;
|
|
850
|
+
/**
|
|
851
|
+
* Wrap a function so its outcome (success / failure / denied) is automatically
|
|
852
|
+
* audited.
|
|
853
|
+
*
|
|
854
|
+
* Behaviour:
|
|
855
|
+
* - If `fn` resolves, an audit event with `outcome: 'success'` is emitted.
|
|
856
|
+
* - If `fn` throws an `EvlogError` (or any error) with `status === 403`, the
|
|
857
|
+
* audit event is recorded as `'denied'` with the error message as `reason`.
|
|
858
|
+
* - Any other thrown error produces `outcome: 'failure'` and re-throws.
|
|
859
|
+
*
|
|
860
|
+
* Use {@link AuditDeniedError} to signal denial without an HTTP status.
|
|
861
|
+
*
|
|
862
|
+
* @example
|
|
863
|
+
* ```ts
|
|
864
|
+
* const refundInvoice = withAudit(
|
|
865
|
+
* { action: 'invoice.refund', target: (input) => ({ type: 'invoice', id: input.id }) },
|
|
866
|
+
* async (input: { id: string }, ctx: { actor: AuditActor }) => {
|
|
867
|
+
* await db.invoices.refund(input.id)
|
|
868
|
+
* }
|
|
869
|
+
* )
|
|
870
|
+
*
|
|
871
|
+
* await refundInvoice({ id: 'inv_889' }, { actor: { type: 'user', id: user.id } })
|
|
872
|
+
* ```
|
|
873
|
+
*/
|
|
874
|
+
declare function withAudit<TInput, TOutput>(options: WithAuditOptions<TInput>, fn: (input: TInput, ctx: WithAuditContext) => Promise<TOutput> | TOutput): (input: TInput, ctx: WithAuditContext) => Promise<TOutput>;
|
|
875
|
+
/**
|
|
876
|
+
* Throw inside a {@link withAudit} body to mark the action as `outcome: 'denied'`
|
|
877
|
+
* regardless of the underlying HTTP status. The constructor message becomes the
|
|
878
|
+
* audit `reason`.
|
|
879
|
+
*/
|
|
880
|
+
declare class AuditDeniedError extends Error {
|
|
881
|
+
constructor(reason: string);
|
|
882
|
+
}
|
|
883
|
+
/** Options for {@link withAudit}. `target` may be derived from the input. */
|
|
884
|
+
interface WithAuditOptions<TInput> {
|
|
885
|
+
action: string;
|
|
886
|
+
target?: AuditTarget | ((input: TInput) => AuditTarget | undefined);
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Runtime context required by a {@link withAudit}-wrapped function.
|
|
890
|
+
* The actor is always required; correlation IDs are optional.
|
|
891
|
+
*/
|
|
892
|
+
interface WithAuditContext {
|
|
893
|
+
actor: AuditActor;
|
|
894
|
+
causationId?: string;
|
|
895
|
+
correlationId?: string;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Compute a compact, redact-aware diff between two objects for the
|
|
899
|
+
* `changes` field. Output is a JSON Patch-style array (RFC 6902 subset:
|
|
900
|
+
* `add`, `remove`, `replace`) — small enough to ship over the wire.
|
|
901
|
+
*
|
|
902
|
+
* Object keys whose name matches one of the `redactPaths` (dot-notation, e.g.
|
|
903
|
+
* `'user.password'`, `'card.cvv'`) are replaced with `'[REDACTED]'` so PII
|
|
904
|
+
* never leaks through the diff.
|
|
905
|
+
*
|
|
906
|
+
* @example
|
|
907
|
+
* ```ts
|
|
908
|
+
* log.audit({
|
|
909
|
+
* action: 'user.update',
|
|
910
|
+
* actor: { type: 'user', id: user.id },
|
|
911
|
+
* target: { type: 'user', id: 'usr_42' },
|
|
912
|
+
* changes: auditDiff(before, after, { redactPaths: ['password'] }),
|
|
913
|
+
* })
|
|
914
|
+
* ```
|
|
915
|
+
*/
|
|
916
|
+
declare function auditDiff(before: unknown, after: unknown, options?: AuditDiffOptions): {
|
|
917
|
+
before?: unknown;
|
|
918
|
+
after?: unknown;
|
|
919
|
+
patch: AuditPatchOp[];
|
|
920
|
+
};
|
|
921
|
+
/** Single JSON Patch operation produced by {@link auditDiff}. */
|
|
922
|
+
interface AuditPatchOp {
|
|
923
|
+
op: 'add' | 'remove' | 'replace';
|
|
924
|
+
path: string;
|
|
925
|
+
value?: unknown;
|
|
926
|
+
}
|
|
927
|
+
/** Options for {@link auditDiff}. */
|
|
928
|
+
interface AuditDiffOptions {
|
|
929
|
+
/** Object keys (dot-notation) whose values should be replaced with `[REDACTED]`. */
|
|
930
|
+
redactPaths?: string[];
|
|
931
|
+
/** Custom replacement string. @default '[REDACTED]' */
|
|
932
|
+
replacement?: string;
|
|
933
|
+
/** Include the full redacted `before` snapshot alongside the patch. */
|
|
934
|
+
includeBefore?: boolean;
|
|
935
|
+
/** Include the full redacted `after` snapshot alongside the patch. */
|
|
936
|
+
includeAfter?: boolean;
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Define a typed audit action with an optional fixed target type.
|
|
940
|
+
*
|
|
941
|
+
* Returns a curried helper that fills in the action name (and target shape
|
|
942
|
+
* if provided) so call sites stay terse and the action set is discoverable
|
|
943
|
+
* in one place.
|
|
944
|
+
*
|
|
945
|
+
* @example
|
|
946
|
+
* ```ts
|
|
947
|
+
* const refund = defineAuditAction('invoice.refund', { target: 'invoice' })
|
|
948
|
+
*
|
|
949
|
+
* log.audit(refund({
|
|
950
|
+
* actor: { type: 'user', id: user.id },
|
|
951
|
+
* target: { id: 'inv_889' }, // type inferred as 'invoice'
|
|
952
|
+
* outcome: 'success',
|
|
953
|
+
* }))
|
|
954
|
+
* ```
|
|
955
|
+
*/
|
|
956
|
+
declare function defineAuditAction<TTargetType extends string | undefined = undefined>(action: string, options?: {
|
|
957
|
+
target?: TTargetType;
|
|
958
|
+
}): DefinedAuditAction<TTargetType>;
|
|
959
|
+
/**
|
|
960
|
+
* Return type of {@link defineAuditAction}. Accepts a partial input (no
|
|
961
|
+
* `action`, target type pre-filled when provided).
|
|
962
|
+
*/
|
|
963
|
+
type DefinedAuditAction<TTargetType extends string | undefined> = (input: TTargetType extends string ? Omit<AuditInput, 'action' | 'target'> & {
|
|
964
|
+
target?: Omit<AuditTarget, 'type'> & {
|
|
965
|
+
type?: TTargetType;
|
|
966
|
+
};
|
|
967
|
+
} : Omit<AuditInput, 'action'>) => AuditInput;
|
|
968
|
+
/**
|
|
969
|
+
* Test helper that captures every audit event emitted while it is active.
|
|
970
|
+
*
|
|
971
|
+
* Returns `{ events, restore, expect }`:
|
|
972
|
+
* - `events` — live array of captured `AuditFields`, populated as audits fire.
|
|
973
|
+
* - `restore()` — uninstall the collector. Call from `afterEach()`.
|
|
974
|
+
* - `expect.toIncludeAuditOf(matcher)` — assertion helper used inside `expect`
|
|
975
|
+
* blocks, returns `true` if at least one captured event matches.
|
|
976
|
+
*
|
|
977
|
+
* Only captures audits going through `log.audit()` and the standalone
|
|
978
|
+
* `audit()` function. Events emitted via raw `log.set({ audit })` skip the
|
|
979
|
+
* collector by design — wrap them with `log.audit()` to make them visible to
|
|
980
|
+
* tests.
|
|
981
|
+
*
|
|
982
|
+
* @example
|
|
983
|
+
* ```ts
|
|
984
|
+
* const captured = mockAudit()
|
|
985
|
+
* await refundInvoice('inv_889')
|
|
986
|
+
* expect(captured.events).toHaveLength(1)
|
|
987
|
+
* expect(captured.toIncludeAuditOf({ action: 'invoice.refund' })).toBe(true)
|
|
988
|
+
* captured.restore()
|
|
989
|
+
* ```
|
|
990
|
+
*/
|
|
991
|
+
declare function mockAudit(): MockAudit;
|
|
992
|
+
/** Result of {@link mockAudit}. */
|
|
993
|
+
interface MockAudit {
|
|
994
|
+
events: AuditFields[];
|
|
995
|
+
restore: () => void;
|
|
996
|
+
toIncludeAuditOf: (matcher: AuditMatcher) => boolean;
|
|
997
|
+
}
|
|
998
|
+
/** Partial structural matcher for {@link MockAudit.toIncludeAuditOf}. */
|
|
999
|
+
interface AuditMatcher {
|
|
1000
|
+
action?: string | RegExp;
|
|
1001
|
+
outcome?: AuditFields['outcome'];
|
|
1002
|
+
actor?: Partial<AuditActor>;
|
|
1003
|
+
target?: Partial<AuditTarget>;
|
|
1004
|
+
}
|
|
1005
|
+
/** Shape of the optional better-auth bridge for the audit enricher. */
|
|
1006
|
+
interface AuditEnricherBetterAuthBridge {
|
|
1007
|
+
/** Read the current authenticated session for this request, if any. */
|
|
1008
|
+
getSession: (ctx: EnrichContext) => Promise<AuditActor | null | undefined> | AuditActor | null | undefined;
|
|
1009
|
+
}
|
|
1010
|
+
/** Options for {@link auditEnricher}. */
|
|
1011
|
+
interface AuditEnricherOptions {
|
|
1012
|
+
/**
|
|
1013
|
+
* Resolve the tenant id for the current request. The result is stored at
|
|
1014
|
+
* `event.audit.context.tenantId`. Multi-tenant SaaS gets isolation by default.
|
|
1015
|
+
*/
|
|
1016
|
+
tenantId?: (ctx: EnrichContext) => string | undefined;
|
|
1017
|
+
/**
|
|
1018
|
+
* Bridge to populate `event.audit.actor` from the authenticated session.
|
|
1019
|
+
* Only used when the application has not already filled `actor`.
|
|
1020
|
+
*/
|
|
1021
|
+
bridge?: AuditEnricherBetterAuthBridge;
|
|
1022
|
+
/** When true, overwrite existing context fields. @default false */
|
|
1023
|
+
overwrite?: boolean;
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* Enrich audit-bearing wide events with request, runtime, and tenant context.
|
|
1027
|
+
*
|
|
1028
|
+
* Runs only when `event.audit` is present — every other event passes through
|
|
1029
|
+
* untouched. Populates:
|
|
1030
|
+
* - `event.audit.context.requestId` from `ctx.request.requestId`
|
|
1031
|
+
* - `event.audit.context.traceId` from `event.traceId`
|
|
1032
|
+
* - `event.audit.context.ip` from `x-forwarded-for` / `x-real-ip`
|
|
1033
|
+
* - `event.audit.context.userAgent` from `user-agent`
|
|
1034
|
+
* - `event.audit.context.tenantId` from `options.tenantId(ctx)`
|
|
1035
|
+
*
|
|
1036
|
+
* Optionally fills `event.audit.actor` from the better-auth bridge when the
|
|
1037
|
+
* caller did not provide one. Anything else (custom actor strategies,
|
|
1038
|
+
* extra context) belongs in a custom enricher — replace this one entirely.
|
|
1039
|
+
*/
|
|
1040
|
+
declare function auditEnricher(options?: AuditEnricherOptions): (ctx: EnrichContext) => void | Promise<void>;
|
|
1041
|
+
/** Options accepted by {@link auditOnly}. */
|
|
1042
|
+
interface AuditOnlyOptions {
|
|
1043
|
+
/**
|
|
1044
|
+
* When true, the wrapper awaits the wrapped drain so the event is flushed
|
|
1045
|
+
* before the request resolves. Use for crash-safe audit storage.
|
|
1046
|
+
* @default false
|
|
1047
|
+
*/
|
|
1048
|
+
await?: boolean;
|
|
1049
|
+
}
|
|
1050
|
+
/** Drain function signature accepted by all wrappers. Matches `LoggerConfig['drain']`. */
|
|
1051
|
+
type DrainFn = (ctx: DrainContext) => void | Promise<void>;
|
|
1052
|
+
/**
|
|
1053
|
+
* Wrap any drain so it only receives events that carry an `audit` field.
|
|
1054
|
+
*
|
|
1055
|
+
* Use to route audit events to dedicated storage (separate Axiom dataset,
|
|
1056
|
+
* append-only Postgres table, FS journal) without affecting your main drain.
|
|
1057
|
+
*
|
|
1058
|
+
* Per-sink failure isolation comes from `initLogger({ drain: [...] })`: each
|
|
1059
|
+
* drain in the array is invoked independently, so a crashed Axiom call never
|
|
1060
|
+
* blocks the FS audit drain.
|
|
1061
|
+
*
|
|
1062
|
+
* @example
|
|
1063
|
+
* ```ts
|
|
1064
|
+
* import { initLogger, auditOnly } from 'evlog'
|
|
1065
|
+
* import { createAxiomDrain } from 'evlog/axiom'
|
|
1066
|
+
* import { createFsDrain } from 'evlog/fs'
|
|
1067
|
+
*
|
|
1068
|
+
* initLogger({
|
|
1069
|
+
* drain: [
|
|
1070
|
+
* createAxiomDrain({ dataset: 'logs' }),
|
|
1071
|
+
* auditOnly(createFsDrain({ dir: '.audit' }), { await: true }),
|
|
1072
|
+
* ],
|
|
1073
|
+
* })
|
|
1074
|
+
* ```
|
|
1075
|
+
*/
|
|
1076
|
+
declare function auditOnly(drain: DrainFn, options?: AuditOnlyOptions): DrainFn;
|
|
1077
|
+
/** Pluggable persistence for the hash-chain state. */
|
|
1078
|
+
interface SignedChainState {
|
|
1079
|
+
/** Load the previous hash from durable storage, or `null` on first run. */
|
|
1080
|
+
load: () => Promise<string | null> | string | null;
|
|
1081
|
+
/** Persist the latest hash so the chain survives process restarts. */
|
|
1082
|
+
save: (hash: string) => Promise<void> | void;
|
|
1083
|
+
}
|
|
1084
|
+
/** Options for {@link signed}. Pick a strategy at construction time. */
|
|
1085
|
+
type SignedOptions = {
|
|
1086
|
+
strategy: 'hmac';
|
|
1087
|
+
secret: string;
|
|
1088
|
+
algorithm?: 'sha256' | 'sha512';
|
|
1089
|
+
} | {
|
|
1090
|
+
strategy: 'hash-chain';
|
|
1091
|
+
state?: SignedChainState;
|
|
1092
|
+
algorithm?: 'sha256' | 'sha512';
|
|
1093
|
+
};
|
|
1094
|
+
/**
|
|
1095
|
+
* Wrap a drain so every event passing through gains tamper-evident integrity.
|
|
1096
|
+
*
|
|
1097
|
+
* - `'hmac'` — adds `event.audit.signature` (HMAC of the canonical event).
|
|
1098
|
+
* - `'hash-chain'` — adds `event.audit.prevHash` and `event.audit.hash` so the
|
|
1099
|
+
* sequence of events forms a verifiable chain. State persists in memory
|
|
1100
|
+
* by default; pass a `state: { load, save }` for cross-process / durable
|
|
1101
|
+
* chains (Redis, file, Postgres).
|
|
1102
|
+
*
|
|
1103
|
+
* The signature is computed before the event is forwarded to the wrapped
|
|
1104
|
+
* drain — combine with {@link auditOnly} when you only want integrity for
|
|
1105
|
+
* audit events.
|
|
1106
|
+
*
|
|
1107
|
+
* @example
|
|
1108
|
+
* ```ts
|
|
1109
|
+
* import { initLogger, auditOnly, signed } from 'evlog'
|
|
1110
|
+
* import { createFsDrain } from 'evlog/fs'
|
|
1111
|
+
*
|
|
1112
|
+
* initLogger({
|
|
1113
|
+
* drain: auditOnly(
|
|
1114
|
+
* signed(createFsDrain({ dir: '.audit' }), { strategy: 'hash-chain' }),
|
|
1115
|
+
* { await: true },
|
|
1116
|
+
* ),
|
|
1117
|
+
* })
|
|
1118
|
+
* ```
|
|
1119
|
+
*/
|
|
1120
|
+
declare function signed(drain: DrainFn, options: SignedOptions): DrainFn;
|
|
1121
|
+
/**
|
|
1122
|
+
* Strict redact preset for audit events.
|
|
1123
|
+
*
|
|
1124
|
+
* Combine with the user's existing redact configuration via spread:
|
|
1125
|
+
* `initLogger({ redact: { paths: [...auditRedactPreset.paths!, ...mine] } })`.
|
|
1126
|
+
*
|
|
1127
|
+
* Hardens PII handling:
|
|
1128
|
+
* - Drops `Authorization` and `Cookie` headers anywhere they appear.
|
|
1129
|
+
* - Drops common credential field names (`password`, `passwordHash`, `token`,
|
|
1130
|
+
* `apiKey`, `secret`, `accessToken`, `refreshToken`, `cardNumber`, `cvv`,
|
|
1131
|
+
* `ssn`).
|
|
1132
|
+
*
|
|
1133
|
+
* Built-in pattern maskers (email, credit card, …) keep their default
|
|
1134
|
+
* behaviour — partial masking, not full redaction — so audit trails retain
|
|
1135
|
+
* enough signal to be useful.
|
|
1136
|
+
*/
|
|
1137
|
+
declare const auditRedactPreset: RedactConfig;
|
|
1138
|
+
//#endregion
|
|
1139
|
+
export { SamplingRates as $, AuditFields as A, H3EventContext as B, buildAuditFields as C, withAudit as D, signed as E, DrainContext as F, LoggerConfig as G, InternalFields as H, EnrichContext as I, RequestLogEntry as J, ParsedError as K, EnvironmentContext as L, AuditTarget as M, BaseWideEvent as N, withAuditMethods as O, DeepPartial as P, SamplingConfig as Q, ErrorOptions as R, auditRedactPreset as S, mockAudit as T, Log as U, IngestPayload as V, LogLevel as W, RequestLoggerOptions as X, RequestLogger as Y, RouteConfig as Z, WithAuditOptions as _, AuditInput as a, auditEnricher as b, AuditOnlyOptions as c, DefinedAuditAction as d, ServerEvent as et, DrainFn as f, WithAuditContext as g, SignedOptions as h, AuditEnricherOptions as i, WideEvent as it, AuditLoggerMethod as j, AuditActor as k, AuditPatchOp as l, SignedChainState as m, AuditDeniedError as n, TailSamplingContext as nt, AuditMatcher as o, MockAudit as p, RedactConfig as q, AuditDiffOptions as r, TransportConfig as rt, AuditMethod as s, AUDIT_SCHEMA_VERSION as t, TailSamplingCondition as tt, AuditableLogger as u, audit as v, defineAuditAction as w, auditOnly as x, auditDiff as y, FieldContext as z };
|
|
1140
|
+
//# sourceMappingURL=audit-CTIviX3P.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-CTIviX3P.d.mts","names":[],"sources":["../src/types.ts","../src/audit.ts"],"mappings":";;YAGY,iBAAA;IAqpBc;;;;;;;;;;;;;IAvoBtB,iBAAA,GAAoB,GAAA,EAAK,mBAAA,YAA+B,OAAA;IAAA;;;;;;;;;;;IAaxD,cAAA,GAAiB,GAAA,EAAK,aAAA,YAAyB,OAAA;IAkBK;;;;;;;;;;;;;;;;IAApD,aAAA,GAAgB,GAAA,EAAK,YAAA,YAAwB,OAAA;EAAA;AAAA;AAAA;EAAA,UAKrC,iBAAA;IACR,iBAAA,GAAoB,GAAA,EAAK,mBAAA,YAA+B,OAAA;IACxD,cAAA,GAAiB,GAAA,EAAK,aAAA,YAAyB,OAAA;IAC/C,aAAA,GAAgB,GAAA,EAAK,YAAA,YAAwB,OAAA;EAAA;AAAA;;AAOjD;;UAAiB,eAAA;EAiBiB;;;;EAZhC,OAAA;EAYgC;;AAMlC;;EAZE,QAAA;EAY4B;;;;EAN5B,WAAA,GAAc,kBAAA;AAAA;AAmBhB;;;AAAA,UAbiB,aAAA;EACf,SAAA;EACA,KAAA;EAAA,CACC,GAAA;AAAA;;;;;;;;UAUc,YAAA;EAqBJ;EAnBX,KAAA;EAmB2B;EAjB3B,QAAA,GAAW,MAAA;EAiB6B;AAM1C;;;;;;;EAdE,QAAA,WAAmB,KAAA;EAsBd;;AAOP;;;EAvBE,WAAA;EAyBA;EAvBA,QAAA,GAAW,KAAA,EAAO,MAAA,GAAS,KAAA;AAAA;;;AAkC7B;UA5BiB,aAAA;;EAEf,IAAA;EA4BA;EA1BA,IAAA;EA8BA;EA5BA,KAAA;EAgCA;EA9BA,KAAA;AAAA;;;AA0CF;;UAnCiB,qBAAA;EAqCR;EAnCP,MAAA;EA+CY;EA7CZ,QAAA;EA6CkB;EA3ClB,IAAA;AAAA;;;;;UAOe,mBAAA;EAgCL;EA9BV,MAAA;EAiCE;EA/BF,QAAA;EAgCY;EA9BZ,IAAA;EA8BkB;EA5BlB,MAAA;EAoC2B;EAlC3B,OAAA,EAAS,MAAA;EA4CO;;;;EAvChB,UAAA;AAAA;;;;;UAOe,aAAA;EAsCA;EApCf,KAAA,EAAO,SAAA;;EAEP,OAAA;IACE,MAAA;IACA,IAAA;IACA,SAAA;EAAA;EAqE0B;EAlE5B,OAAA,GAAU,MAAA;EAwEK;EAtEf,QAAA;IACE,MAAA;IACA,OAAA,GAAU,MAAA;EAAA;AAAA;;;;;UAQG,YAAA;EA0Ef;EAxEA,KAAA,EAAO,SAAA;EA4EP;EA1EA,OAAA;IACE,MAAA;IACA,IAAA;IACA,SAAA;EAAA;EAqFY;EAlFd,OAAA,GAAU,MAAA;AAAA;;;;UAMK,cAAA;EAqK8B;;;;;;;;;;;;;;;;;;EAlJ7C,KAAA,GAAQ,aAAA;EAoJR;;;AAWF;;;;;;;;;;;;;;EA5IE,IAAA,GAAO,qBAAA;AAAA;;;;UAMQ,WAAA;EA2Jd;EAzJD,OAAA;AAAA;AAgLF;;;AAAA,UA1KiB,kBAAA;EA4Kf;EA1KA,OAAA;EA2KO;EAzKP,WAAA;EA0KS;EAxKT,OAAA;EA2KA;EAzKA,UAAA;EA2KY;EAzKZ,MAAA;AAAA;;;;UAMe,YAAA;EA8Kb;;;;;EAxKF,OAAA;EAgLA;EA9KA,GAAA,GAAM,OAAA,CAAQ,kBAAA;EAkLd;EAhLA,MAAA;EAgLI;EA9KJ,QAAA,GAAW,cAAA;EAuLiB;;;;;;EAhL5B,QAAA,GAAW,QAAA;EAqLX;;;;;EA/KA,SAAA;EAkLmB;AAMrB;;;;;AAMA;EAtLE,MAAA;EAsLqB;;;;;;;;;;;;;;;;;;;;;;;;;AAUvB;;;;;;EAhKE,MAAA,aAAmB,YAAA;EAmKL;;;;;AAUhB;;;;;;;;;AAYA;;;;;;;;;;;;;;;;;EAzJE,KAAA,IAAS,GAAA,EAAK,YAAA,YAAwB,OAAA;EA0JqB;EAxJ3D,qBAAA;AAAA;;;;;;;;;UAWe,UAAA;EACf,IAAA;EACA,EAAA;EACA,WAAA;EACA,KAAA;EACA,KAAA;EACA,KAAA;EACA,MAAA;EACA,QAAA;AAAA;;;;;;;;UAUe,WAAA;EACf,IAAA;EACA,EAAA;EAAA,CACC,GAAA;AAAA;;;;;;;;;;;;;;;;;;;;;UAuBc,WAAA;EAkLG;EAhLlB,MAAA;EACA,KAAA,EAAO,UAAA;EACP,MAAA,GAAS,WAAA;EACT,OAAA;EAkMwC;EAhMxC,MAAA;EAwNA;EAtNA,OAAA;IAAY,MAAA;IAAkB,KAAA;EAAA;EA0NE;EAxNhC,WAAA;EAwNgC;EAtNhC,aAAA;EAwN8B;EAtN9B,OAAA;EAsNkC;EApNlC,cAAA;EAmNC;EAjND,OAAA;IACE,SAAA;IACA,OAAA;IACA,EAAA;IACA,SAAA;IACA,QAAA;IAAA,CACC,GAAA;EAAA;EAkNe;EA/MlB,SAAA;EA+MkB;EA7MlB,QAAA;EAwNe;EAtNf,IAAA;AAAA;;;;;;;UASe,aAAA;EACf,SAAA;EACA,KAAA;EACA,OAAA;EACA,WAAA;EACA,OAAA;EACA,UAAA;EACA,MAAA;EACA,KAAA,GAAQ,WAAA;AAAA;;;;KAME,SAAA,GAAY,aAAA,GAAgB,MAAA;;;;;KAM5B,WAAA,MAAiB,CAAA,SAAU,KAAA,YACnC,CAAA,GACA,CAAA,gCACgB,CAAA,IAAK,WAAA,CAAY,CAAA,CAAE,CAAA,OACjC,CAAA;;;;;UAMW,cAAA;EACf,MAAA;EACA,OAAA;EACA,WAAA,GAAc,eAAA;EAkOG;EAhOjB,SAAA;EAmNA;EAjNA,gBAAA;AAAA;;;;UAMe,eAAA;EACf,KAAA;EACA,OAAA;EACA,SAAA;AAAA;;;;;;;KASU,YAAA,oBAAgC,MAAA,qBAC1C,WAAA,CAAY,IAAA,CAAK,CAAA,QAAS,cAAA,KAAmB,cAAA;;;;;AAoO/C;;;;;;;;;;;;;;AAgBA;;;;;;;;;;;;;;;;;UA/MiB,aAAA,oBAAiC,MAAA;EA0N9C;;;;;;;;EAjNF,GAAA,GAAM,OAAA,EAAS,YAAA,CAAa,CAAA;EAoNT;AAMrB;;;;EAnNE,KAAA,GAAQ,KAAA,EAAO,KAAA,WAAgB,OAAA,GAAU,YAAA,CAAa,CAAA;EAqNtD;;;;;EA9MA,IAAA,GAAO,OAAA,UAAiB,OAAA,GAAU,YAAA,CAAa,CAAA;EAkN5C;;;;AC5xBL;EDilBE,IAAA,GAAO,OAAA,UAAiB,OAAA,GAAU,YAAA,CAAa,CAAA;;;;ACxkBjD;;;;EDilBE,IAAA,GAAO,SAAA,GAAY,YAAA,CAAa,CAAA;IAAO,UAAA;EAAA,MAA2B,SAAA;EC3kB7C;;;EDglBrB,UAAA,QAAkB,YAAA,CAAa,CAAA,IAAK,MAAA;ECplB7B;;;;;;;;;;;;;AAuET;;;;;;EDkiBE,IAAA,IAAQ,KAAA,UAAe,EAAA,eAAiB,OAAA;ECliBsB;;AA4ChE;;;;;;;;;;;;;;;;;;;AA+BA;ED+eE,KAAA,GAAQ,iBAAA;AAAA;;UAIO,iBAAA;EAAA,CACd,KAAA,EAD+B,UAAA;EAEhC,IAAA,GAAO,MAAA,UAAgB,KAAA,EAAO,IAAA,CADM,UAAA;AAAA;;;;KAO1B,QAAA;;;;;;;;ACxfZ;;UDmgBiB,GAAA;ECngB+B;;;;;EDygB9C,IAAA,CAAK,GAAA,UAAa,OAAA;EAClB,IAAA,CAAK,KAAA,EAAO,MAAA;EC1gBkC;;;;;EDihB9C,KAAA,CAAM,GAAA,UAAa,OAAA;EACnB,KAAA,CAAM,KAAA,EAAO,MAAA;EC3gBU;;;AAsBzB;;ED4fE,IAAA,CAAK,GAAA,UAAa,OAAA;EAClB,IAAA,CAAK,KAAA,EAAO,MAAA;EC7fe;;;;;EDogB3B,KAAA,CAAM,GAAA,UAAa,OAAA;EACnB,KAAA,CAAM,KAAA,EAAO,MAAA;AAAA;;;;UAME,YAAA;ECzeuC;ED2etD,OAAA;EC3eiE;ED6ejE,MAAA;EC5esB;ED8etB,GAAA;EC9e2C;EDgf3C,GAAA;EChfkD;EDkflD,IAAA;ECrfgC;EDufhC,KAAA,GAAQ,KAAA;ECtfkB;;;;ED2f1B,QAAA,GAAW,MAAA;AAAA;;;;UAMI,oBAAA;EACf,MAAA;EACA,IAAA;EACA,SAAA;EClgBiB;;;;;AAqCnB;;;;EDueE,SAAA,IAAa,OAAA,EAAS,OAAA;AAAA;;;;UAMP,cAAA;EACf,GAAA,GAAM,aAAA;EACN,SAAA;EACA,MAAA;ECpegC;EDsehC,eAAA;ECtesD;EDwetD,aAAA;EC1egC;ED4ehC,gBAAA;EAAA,CACC,GAAA;AAAA;;;;UAMc,WAAA;EACf,MAAA;EACA,IAAA;EACA,OAAA,EAAS,cAAA;IC5eF,yED8eL,UAAA;MACE,OAAA;QACE,SAAA,GAAY,OAAA,EAAS,OAAA;MAAA;IAAA,GC9ed;IDkfX,SAAA,IAAa,OAAA,EAAS,OAAA;EAAA;EAExB,IAAA;IAAS,GAAA;MAAQ,UAAA;IAAA;EAAA;EACjB,QAAA,GAAW,QAAA;AAAA;;;;UAMI,WAAA;EACf,OAAA;EACA,MAAA;EACA,GAAA;EACA,GAAA;EACA,IAAA;EACA,GAAA;AAAA;;;AA3IwB;;;;AAAA,cCjpBb,oBAAA;;;;;;;;UASI,UAAA;EACf,MAAA;EACA,KAAA,EAAO,UAAA;EACP,MAAA,GAAS,WAAA;EACT,OAAA,GAAU,WAAA;EACV,MAAA;EACA,OAAA,GAAU,WAAA;EACV,WAAA;EACA,aAAA;EACA,OAAA;AAAA;;;;;ADuBsD;;;;iBCyCxC,gBAAA,CAAiB,KAAA,EAAO,UAAA,GAAa,WAAA;;;;;;;;;;;;;;;;;;;iBA4CrC,gBAAA,oBAAoC,MAAA,kBAAA,CAAyB,MAAA,EAAQ,aAAA,CAAc,CAAA,IAAK,eAAA,CAAgB,CAAA;;;;KA+B5G,eAAA,oBAAmC,MAAA,qBAA2B,aAAA,CAAc,CAAA;EAAO,KAAA,EAAO,WAAA,CAAY,CAAA;AAAA;;UAGjG,WAAA,oBAA+B,MAAA;EAAA,CAC7C,KAAA,EAAO,UAAA;EDxFR;;;;AAMF;ECwFE,IAAA,GAAO,MAAA,UAAgB,KAAA,EAAO,IAAA,CAAK,UAAA;AAAA;;;;;;;AD3ErC;;;;;;;;;;;;;iBCiGgB,KAAA,CAAM,KAAA,EAAO,UAAA,GAAa,SAAA;;;;;;;;ADtE1C;;;;;;;;;;AAeA;;;;;;;iBCuFgB,SAAA,iBAAA,CACd,OAAA,EAAS,gBAAA,CAAiB,MAAA,GAC1B,EAAA,GAAK,KAAA,EAAO,MAAA,EAAQ,GAAA,EAAK,gBAAA,KAAqB,OAAA,CAAQ,OAAA,IAAW,OAAA,IAC/D,KAAA,EAAO,MAAA,EAAQ,GAAA,EAAK,gBAAA,KAAqB,OAAA,CAAQ,OAAA;;AD7ErD;;;;cCkHa,gBAAA,SAAyB,KAAA;cAExB,MAAA;AAAA;;UAQG,gBAAA;EACf,MAAA;EACA,MAAA,GAAS,WAAA,KAAgB,KAAA,EAAO,MAAA,KAAW,WAAA;AAAA;;ADxG7C;;;UC+GiB,gBAAA;EACf,KAAA,EAAO,UAAA;EACP,WAAA;EACA,aAAA;AAAA;;;;;;;;;;;;;;;AD5FF;;;;;iBCkHgB,SAAA,CACd,MAAA,WACA,KAAA,WACA,OAAA,GAAS,gBAAA;EACN,MAAA;EAAkB,KAAA;EAAiB,KAAA,EAAO,YAAA;AAAA;;UAkE9B,YAAA;EACf,EAAA;EACA,IAAA;EACA,KAAA;AAAA;;UAIe,gBAAA;ED5Jf;EC8JA,WAAA;ED3IA;EC6IA,WAAA;ED7I4B;EC+I5B,aAAA;EDzIe;EC2If,YAAA;AAAA;;;ADnIF;;;;;;;;;;;AAgBA;;;;;iBCwIgB,iBAAA,oDAAA,CACd,MAAA,UACA,OAAA;EAAY,MAAA,GAAS,WAAA;AAAA,IACpB,kBAAA,CAAmB,WAAA;;;;;KAkBV,kBAAA,4CACV,KAAA,EAAO,WAAA,kBACH,IAAA,CAAK,UAAA;EAAqC,MAAA,GAAS,IAAA,CAAK,WAAA;IAAyB,IAAA,GAAO,WAAA;EAAA;AAAA,IACxF,IAAA,CAAK,UAAA,gBACN,UAAA;;;;;;;;;;;;;;;;ADnDL;;;;;;;;iBC4EgB,SAAA,CAAA,GAAa,SAAA;;UAmBZ,SAAA;EACf,MAAA,EAAQ,WAAA;EACR,OAAA;EACA,gBAAA,GAAmB,OAAA,EAAS,YAAA;AAAA;;UAIb,YAAA;EACf,MAAA,YAAkB,MAAA;EAClB,OAAA,GAAU,WAAA;EACV,KAAA,GAAQ,OAAA,CAAQ,UAAA;EAChB,MAAA,GAAS,OAAA,CAAQ,WAAA;AAAA;;UAqDF,6BAAA;ED1Ge;EC4G9B,UAAA,GAAa,GAAA,EAAK,aAAA,KAAkB,OAAA,CAAQ,UAAA,uBAAiC,UAAA;AAAA;;UAI9D,oBAAA;EDtGf;;;;EC2GA,QAAA,IAAY,GAAA,EAAK,aAAA;EDtGf;;;;EC2GF,MAAA,GAAS,6BAAA;EDnGL;ECqGJ,SAAA;AAAA;;;;;;;;;;;;;;;AD9EF;iBCgGgB,aAAA,CAAc,OAAA,GAAS,oBAAA,IAA6B,GAAA,EAAK,aAAA,YAAyB,OAAA;;UA6CjF,gBAAA;ED7I6B;AAM9C;;;;EC6IE,KAAA;AAAA;;KAIU,OAAA,IAAW,GAAA,EAAK,YAAA,YAAwB,OAAA;;;;;;;;;;;;;;;;;;;;ADvIpD;;;;;iBCiKgB,SAAA,CAAU,KAAA,EAAO,OAAA,EAAS,OAAA,GAAS,gBAAA,GAAwB,OAAA;;UAY1D,gBAAA;EDxKf;EC0KA,IAAA,QAAY,OAAA;EDxKI;EC0KhB,IAAA,GAAO,IAAA,aAAiB,OAAA;AAAA;;KAId,aAAA;EACN,QAAA;EAAkB,MAAA;EAAgB,SAAA;AAAA;EAClC,QAAA;EAAwB,KAAA,GAAQ,gBAAA;EAAkB,SAAA;AAAA;;;;;;;;;;;;;;;;;;;ADxHxD;;;;;;;;iBCoJgB,MAAA,CAAO,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,aAAA,GAAgB,OAAA;;;;;;;;;;;;;;;;;cAwHnD,iBAAA,EAAmB,YAAA"}
|