@volidator/node 1.0.0 → 1.0.2

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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +72 -2
  3. package/dist/{chunk-KEXIKZGN.js → chunk-AJL3OYF2.js} +7 -3
  4. package/dist/chunk-AJL3OYF2.js.map +1 -0
  5. package/dist/{chunk-YI4DCCHT.js → chunk-UDBMJC25.js} +207 -26
  6. package/dist/chunk-UDBMJC25.js.map +1 -0
  7. package/dist/index.cjs +206 -25
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +91 -3
  10. package/dist/index.d.ts +91 -3
  11. package/dist/index.js +1 -1
  12. package/dist/middleware/next.cjs +211 -26
  13. package/dist/middleware/next.cjs.map +1 -1
  14. package/dist/middleware/next.d.cts +2 -0
  15. package/dist/middleware/next.d.ts +2 -0
  16. package/dist/middleware/next.js +2 -2
  17. package/dist/plugins/agent-langchain.cjs +93 -0
  18. package/dist/plugins/agent-langchain.cjs.map +1 -0
  19. package/dist/plugins/agent-langchain.d.cts +43 -0
  20. package/dist/plugins/agent-langchain.d.ts +43 -0
  21. package/dist/plugins/agent-langchain.js +68 -0
  22. package/dist/plugins/agent-langchain.js.map +1 -0
  23. package/dist/plugins/agent-vercel.cjs +64 -0
  24. package/dist/plugins/agent-vercel.cjs.map +1 -0
  25. package/dist/plugins/agent-vercel.d.cts +21 -0
  26. package/dist/plugins/agent-vercel.d.ts +21 -0
  27. package/dist/plugins/agent-vercel.js +39 -0
  28. package/dist/plugins/agent-vercel.js.map +1 -0
  29. package/dist/plugins/clerk.cjs +215 -27
  30. package/dist/plugins/clerk.cjs.map +1 -1
  31. package/dist/plugins/clerk.d.cts +3 -1
  32. package/dist/plugins/clerk.d.ts +3 -1
  33. package/dist/plugins/clerk.js +6 -3
  34. package/dist/plugins/clerk.js.map +1 -1
  35. package/dist/plugins/universal.cjs +217 -27
  36. package/dist/plugins/universal.cjs.map +1 -1
  37. package/dist/plugins/universal.d.cts +3 -1
  38. package/dist/plugins/universal.d.ts +3 -1
  39. package/dist/plugins/universal.js +8 -3
  40. package/dist/plugins/universal.js.map +1 -1
  41. package/package.json +13 -3
  42. package/dist/chunk-KEXIKZGN.js.map +0 -1
  43. package/dist/chunk-YI4DCCHT.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Reference-Based Redaction Types\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * A structured payload for fields listed in `referenceKeys`.\r\n * - `id` — the non-sensitive internal identifier stored in Volidator as [REF:id].\r\n * - `pii` — the real value used ONLY to compute the blind index, then discarded.\r\n *\r\n * @example\r\n * actor: { id: \"usr_890\", pii: \"john@company.com\" }\r\n * // stored: \"[REF:usr_890]\"\r\n * // blind index: HMAC(\"john@company.com\")\r\n * // telemetry: extracted automatically or passed in context\r\n */\r\nexport type ReferencePayload = { id: string; pii: string };\r\n\r\n/**\r\n * Utility type that enforces { id, pii } shape on any LogPayload fields\r\n * whose key appears in the `referenceKeys` constructor option.\r\n * Gives a compile-time error if a developer passes a raw string instead.\r\n */\r\nexport type EnforceReference<TData, TRefKeys extends keyof TData> =\r\n Omit<TData, TRefKeys> & { [K in TRefKeys]: ReferencePayload };\r\n\r\nexport interface TelemetryConfig {\r\n preset?: \"strict\" | \"standard\" | \"full\";\r\n ip?: \"track\" | \"anonymize\" | \"skip\";\r\n userAgent?: \"track\" | \"parse\" | \"skip\";\r\n location?: boolean;\r\n}\r\n\r\nexport interface BatcherOptions {\r\n /**\r\n * Automatically flush and send logs when the buffer reaches this count.\r\n * Maximum count is capped at 100.\r\n */\r\n autoFlushCount?: number;\r\n /**\r\n * Automatically flush and send logs every N milliseconds.\r\n * \r\n * ⚠️ SERVERLESS/EDGE CAVEAT:\r\n * Do not use in serverless/edge environments (e.g. Cloudflare Workers, Vercel Edge)\r\n * as background timers are not guaranteed to execute after response completion.\r\n */\r\n autoFlushInterval?: number;\r\n}\r\n\r\nexport interface VolidatorBatcher {\r\n /**\r\n * Push a log payload to the buffer. Auto-flushes if autoFlushCount limit is reached.\r\n */\r\n push(payload: LogPayload): void;\r\n /**\r\n * Manually flush the buffer and send all logs.\r\n */\r\n flush(): Promise<{ accepted: number; rejected: number }>;\r\n /**\r\n * Returns the current size of the buffer.\r\n */\r\n size(): number;\r\n}\r\n\r\nexport interface TelemetryContext {\r\n ip?: string;\r\n userAgent?: string;\r\n location?: {\r\n country?: string;\r\n region?: string;\r\n city?: string;\r\n };\r\n device?: {\r\n browser?: string;\r\n os?: string;\r\n type?: string;\r\n };\r\n [key: string]: any;\r\n}\r\n\r\nexport interface LogPayload {\r\n /**\r\n * The actor performing the action. Pass a plain string for normal logs.\r\n * Pass a `ReferencePayload` when this field is listed in `referenceKeys`:\r\n * actor: { id: \"usr_890\", pii: \"john@company.com\" }\r\n */\r\n actor?: string | ReferencePayload;\r\n actorId?: string; // support actorId as alias (plain string only)\r\n action: string;\r\n /**\r\n * The target of the action. Pass a plain string for normal logs.\r\n * Pass a `ReferencePayload` when this field is listed in `referenceKeys`.\r\n */\r\n target?: string | ReferencePayload;\r\n targetId?: string; // support targetId as alias (plain string only)\r\n /**\r\n * The tenant or client identifier (e.g. B2B company name/ID).\r\n * Pass a plain string for normal logs, or a `ReferencePayload`.\r\n */\r\n tenant?: string | ReferencePayload;\r\n tenantId?: string; // support tenantId as alias (plain string only)\r\n /**\r\n * Groups all events belonging to a single agent run, workflow execution,\r\n * or request trace. Passed through as a blind index so the server can\r\n * filter by run without decrypting payloads.\r\n */\r\n traceId?: string;\r\n /**\r\n * Identifies this specific event within the trace (analogous to OTel spanId).\r\n */\r\n spanId?: string;\r\n /**\r\n * The spanId of the event that caused this one (parentSpanId).\r\n */\r\n parentSpanId?: string;\r\n /**\r\n * Arbitrary metadata. Values for keys listed in `referenceKeys` must be\r\n * `ReferencePayload` objects: { id: \"ref_id\", pii: \"sensitive_value\" }.\r\n */\r\n metadata?: Record<string, any>;\r\n context?: TelemetryContext;\r\n telemetry?: TelemetryConfig;\r\n req?: Request | import(\"node:http\").IncomingMessage; // support passing the HTTP request object directly\r\n /**\r\n * Sequence number/counter to mathematically trace causal event chains\r\n */\r\n logicalClock?: number;\r\n /**\r\n * If true, indicates the log payload is stored externally in R2\r\n */\r\n isClaimCheck?: boolean;\r\n}\r\n\r\ninterface EmbedTokenViewConfig {\r\n /** The columns to show in the table, e.g. [\"actor\", \"action\", \"metadata.region\", \"createdAt\"] */\r\n columns?: string[];\r\n /** Default search filters loaded on mount */\r\n defaultFilter?: {\r\n search?: string;\r\n action?: string;\r\n };\r\n}\r\n\r\ninterface EmbedTokenConfig {\r\n /** The plaintext actor identifier (e.g. \"usr_123\") */\r\n actorId?: string;\r\n /** The plaintext target identifier (e.g. \"usr_123\") */\r\n targetId?: string;\r\n /** The plaintext tenant identifier (e.g. \"johnsbakery\") */\r\n tenantId?: string;\r\n /** Scopes the logs to query. If not provided, defaults to 'actor' if actorId is provided, or 'tenant' if tenantId is provided. */\r\n scope?: \"actor\" | \"target\" | \"tenant\" | \"all\" | \"auditor\";\r\n /** Duration string: \"30m\", \"2h\", \"7d\". Defaults to \"2h\". */\r\n expiresIn?: string;\r\n /** Custom dashboard origin URL override */\r\n dashboardUrl?: string;\r\n /** Optional origin of host app for iframe postMessage domain validation */\r\n hostOrigin?: string;\r\n /** Custom column presentation and default filters */\r\n view?: EmbedTokenViewConfig;\r\n}\r\n\r\ninterface EmbedTokenResult {\r\n token: string;\r\n embedUrl: string;\r\n}\r\n\r\nexport class VolidatorClient {\r\n private apiKey: string;\r\n private endpoint: string;\r\n private telemetryConfig: Required<Omit<TelemetryConfig, \"preset\">>;\r\n\r\n // Optional fields required only for generateEmbedToken()\r\n private projectId?: string;\r\n private clientSecret?: string;\r\n\r\n private redactKeys: string[];\r\n private referenceKeys: string[];\r\n\r\n // Keyring properties\r\n private activeKeyId: string;\r\n private keyring: Record<string, string>;\r\n private hashedKeyring: Record<string, Uint8Array>;\r\n \r\n // Custom limit for metadata object serialization size\r\n private maxMetadataSize: number;\r\n\r\n private maxRetries: number;\r\n private onDeliveryFailure?: (payload: LogPayload, error: Error) => void;\r\n\r\n /**\r\n * Thread-local asynchronous context storage used to maintain\r\n * and increment Lamport logical clock sequences across execution boundaries\r\n * (e.g. within API requests or serverless handler contexts).\r\n */\r\n public static readonly logicalClockStore = new AsyncLocalStorage<{ clock: number }>();\r\n private fallbackLogicalClock = 0;\r\n\r\n /**\r\n * Increments and returns the current Lamport Logical Clock counter.\r\n * If a logicalClockStore context is active, it reads, syncs, and updates\r\n * the thread-scoped clock; otherwise, it falls back to a global instance-scoped counter.\r\n *\r\n * @param incomingClock Optional logical clock sequence from incoming trace parent header\r\n */\r\n public getAndIncrementClock(incomingClock?: number): number {\r\n const store = VolidatorClient.logicalClockStore.getStore();\r\n if (store) {\r\n store.clock = Math.max(store.clock, incomingClock || 0) + 1;\r\n return store.clock;\r\n }\r\n this.fallbackLogicalClock = Math.max(this.fallbackLogicalClock, incomingClock || 0) + 1;\r\n return this.fallbackLogicalClock;\r\n }\r\n\r\n public compliance: VolidatorCompliance;\r\n public agent: VolidatorAgent;\r\n\r\n constructor(config: {\r\n apiKey: string;\r\n encryptionKey?: string;\r\n activeEncryptionKeyId?: string;\r\n keyring?: Record<string, string>;\r\n endpoint?: string;\r\n // Provide these when you need to generate embed tokens server-side\r\n projectId?: string;\r\n clientSecret?: string;\r\n telemetry?: TelemetryConfig;\r\n /**\r\n * Fields to replace with [REDACTED:key] before encryption.\r\n */\r\n redactKeys?: string[];\r\n /**\r\n * Fields to replace with [REF:id] before encryption (JIT Hydration).\r\n */\r\n referenceKeys?: string[];\r\n /**\r\n * Custom maximum size for serialized metadata in bytes. Defaults to 10240 (10KB).\r\n * Serialized metadata is subject to a depth limit of 5 levels and values are\r\n * truncated to 1000 characters.\r\n */\r\n maxMetadataSize?: number;\r\n /**\r\n * Maximum number of delivery retry attempts for transient errors. Defaults to 3.\r\n */\r\n maxRetries?: number;\r\n /**\r\n * Callback fired when an event terminals fails to deliver after all retries.\r\n */\r\n onDeliveryFailure?: (payload: LogPayload, error: Error) => void;\r\n }) {\r\n this.apiKey = config.apiKey;\r\n this.endpoint = config.endpoint || \"https://ingestion.volidator.com\";\r\n this.projectId = config.projectId;\r\n this.clientSecret = config.clientSecret;\r\n this.redactKeys = config.redactKeys || [];\r\n this.referenceKeys = config.referenceKeys || [];\r\n this.maxMetadataSize = config.maxMetadataSize || 10240;\r\n this.maxRetries = config.maxRetries !== undefined ? config.maxRetries : 3;\r\n this.onDeliveryFailure = config.onDeliveryFailure;\r\n\r\n // Parse encryption keys & keyring\r\n if (config.keyring && config.activeEncryptionKeyId) {\r\n this.keyring = config.keyring;\r\n this.activeKeyId = config.activeEncryptionKeyId;\r\n } else if (config.encryptionKey) {\r\n this.activeKeyId = \"v1\";\r\n this.keyring = { \"v1\": config.encryptionKey };\r\n } else {\r\n throw new Error(\"Either encryptionKey OR (keyring AND activeEncryptionKeyId) must be provided in VolidatorClient constructor.\");\r\n }\r\n\r\n // Limit keyring size to 5 for performance & security\r\n if (Object.keys(this.keyring).length > 5) {\r\n throw new Error(\"Keyring size cannot exceed 5 keys.\");\r\n }\r\n\r\n if (!this.keyring[this.activeKeyId]) {\r\n throw new Error(`Active key ID '${this.activeKeyId}' must exist in the keyring.`);\r\n }\r\n\r\n // Keys will be hashed lazily via WebCrypto in _getHashedKey\r\n this.hashedKeyring = {};\r\n\r\n // Default to 'standard' preset if nothing is provided\r\n this.telemetryConfig = VolidatorClient.resolveTelemetryConfig(config.telemetry || { preset: \"standard\" });\r\n this.compliance = new VolidatorCompliance(this);\r\n this.agent = new VolidatorAgent(this);\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Telemetry Context Parser (Zero-latency header parsing)\r\n // ---------------------------------------------------------------------------\r\n static extractContext(req: any): TelemetryContext {\r\n const getHeader = (name: string): string => {\r\n if (!req) return \"\";\r\n // Handle standard Web API Request/Headers\r\n if (typeof req.headers?.get === \"function\") {\r\n return req.headers.get(name) || \"\";\r\n }\r\n // Handle Node.js IncomingMessage request headers\r\n if (req.headers && typeof req.headers === \"object\") {\r\n return req.headers[name] || req.headers[name.toLowerCase()] || \"\";\r\n }\r\n return \"\";\r\n };\r\n\r\n const rawIp = getHeader(\"cf-connecting-ip\") ||\r\n getHeader(\"x-real-ip\") ||\r\n getHeader(\"x-forwarded-for\");\r\n\r\n const ip = rawIp ? rawIp.split(\",\")[0].trim() : (req?.socket?.remoteAddress || \"\");\r\n const userAgent = getHeader(\"user-agent\");\r\n\r\n return {\r\n ip,\r\n userAgent,\r\n location: {\r\n country: getHeader(\"cf-ipcountry\") || getHeader(\"x-vercel-ip-country\") || \"\",\r\n region: getHeader(\"cf-region-code\") || getHeader(\"x-vercel-ip-country-region\") || \"\",\r\n city: getHeader(\"cf-ipcity\") || getHeader(\"x-vercel-ip-city\") || \"\",\r\n }\r\n };\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // OpenTelemetry W3C traceparent context parser\r\n // ---------------------------------------------------------------------------\r\n static extractTraceContext(req: any): { traceId?: string; spanId?: string; logicalClock?: number } {\r\n if (!req) return {};\r\n const getHeader = (name: string): string => {\r\n if (typeof req.headers?.get === \"function\") {\r\n return req.headers.get(name) || \"\";\r\n }\r\n if (req.headers && typeof req.headers === \"object\") {\r\n return req.headers[name] || req.headers[name.toLowerCase()] || \"\";\r\n }\r\n return \"\";\r\n };\r\n\r\n const result: { traceId?: string; spanId?: string; logicalClock?: number } = {};\r\n\r\n const clockVal = getHeader(\"x-volidator-clock\");\r\n if (clockVal) {\r\n const parsed = parseInt(clockVal, 10);\r\n if (!isNaN(parsed)) {\r\n result.logicalClock = parsed;\r\n }\r\n }\r\n\r\n const traceparent = getHeader(\"traceparent\");\r\n if (traceparent) {\r\n const parts = traceparent.split(\"-\");\r\n if (parts.length === 4) {\r\n result.traceId = parts[1];\r\n result.spanId = parts[2];\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n private static resolveTelemetryConfig(config: TelemetryConfig): Required<Omit<TelemetryConfig, \"preset\">> {\r\n const preset = config.preset || \"standard\";\r\n\r\n let ip: \"track\" | \"anonymize\" | \"skip\" = \"anonymize\";\r\n let userAgent: \"track\" | \"parse\" | \"skip\" = \"parse\";\r\n let location = true;\r\n\r\n if (preset === \"strict\") {\r\n ip = \"skip\";\r\n userAgent = \"skip\";\r\n location = false;\r\n } else if (preset === \"full\") {\r\n ip = \"track\";\r\n userAgent = \"track\";\r\n location = true;\r\n }\r\n\r\n if (config.ip !== undefined) ip = config.ip;\r\n if (config.userAgent !== undefined) userAgent = config.userAgent;\r\n if (config.location !== undefined) location = config.location;\r\n\r\n return { ip, userAgent, location };\r\n }\r\n\r\n private parseUserAgent(ua: string) {\r\n let browser = \"Unknown Browser\";\r\n let os = \"Unknown OS\";\r\n let type = \"Desktop\";\r\n\r\n if (/Volidator-Ingest-Worker/i.test(ua)) {\r\n return {\r\n browser: \"Volidator Ingest Worker\",\r\n os: \"Linux Server\",\r\n type: \"Server\"\r\n };\r\n }\r\n\r\n // Simple Device Type detection\r\n if (/mobile/i.test(ua)) {\r\n type = \"Mobile\";\r\n } else if (/tablet|ipad/i.test(ua)) {\r\n type = \"Tablet\";\r\n } else if (/server|bot/i.test(ua)) {\r\n type = \"Server\";\r\n }\r\n\r\n // Simple Browser detection\r\n if (/chrome|crios/i.test(ua) && !/edge|edg/i.test(ua) && !/opr/i.test(ua)) {\r\n const match = ua.match(/(?:chrome|crios)\\/([0-9\\.]+)/i);\r\n browser = `Chrome ${match ? match[1].split('.')[0] : \"\"}`.trim();\r\n } else if (/safari/i.test(ua) && !/chrome|crios/i.test(ua) && !/android/i.test(ua)) {\r\n browser = /mobile/i.test(ua) ? \"Safari Mobile\" : \"Safari\";\r\n } else if (/firefox|fxios/i.test(ua)) {\r\n browser = \"Firefox\";\r\n } else if (/edge|edg/i.test(ua)) {\r\n browser = \"Edge\";\r\n }\r\n\r\n // Simple OS detection\r\n if (/windows/i.test(ua)) {\r\n os = \"Windows\";\r\n } else if (/macintosh|mac os x/i.test(ua)) {\r\n os = \"macOS\";\r\n } else if (/iphone|ipad|ipod/i.test(ua)) {\r\n os = \"iOS\";\r\n } else if (/android/i.test(ua)) {\r\n os = \"Android\";\r\n } else if (/linux/i.test(ua)) {\r\n os = \"Linux\";\r\n }\r\n\r\n return { browser, os, type };\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Blind Index & Key Hashing (WebCrypto)\r\n // ---------------------------------------------------------------------------\r\n private async _getHashedKey(id: string): Promise<Uint8Array> {\r\n if (this.hashedKeyring[id]) return this.hashedKeyring[id];\r\n const rawKey = this.keyring[id];\r\n const buf = new TextEncoder().encode(rawKey);\r\n const hash = await globalThis.crypto.subtle.digest(\"SHA-256\", buf);\r\n this.hashedKeyring[id] = new Uint8Array(hash);\r\n return this.hashedKeyring[id];\r\n }\r\n\r\n private async generateBlindIndex(value: string, keyBuffer: Uint8Array): Promise<string> {\r\n const key = await globalThis.crypto.subtle.importKey(\r\n \"raw\", keyBuffer as unknown as BufferSource, { name: \"HMAC\", hash: \"SHA-256\" }, false, [\"sign\"]\r\n );\r\n const signature = await globalThis.crypto.subtle.sign(\r\n \"HMAC\", key, new TextEncoder().encode(value)\r\n );\r\n return Array.from(new Uint8Array(signature))\r\n .map(b => b.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // Payload Encryption — AES-256-GCM with prepended 12-byte IV\r\n // Layout: [IV (12B)] [Ciphertext] [Auth Tag (16B)]\r\n // ---------------------------------------------------------------------------\r\n private async encryptPayload(payload: object): Promise<string> {\r\n const text = JSON.stringify(payload);\r\n const iv = globalThis.crypto.getRandomValues(new Uint8Array(12));\r\n const activeHashedKey = await this._getHashedKey(this.activeKeyId);\r\n\r\n const cryptoKey = await globalThis.crypto.subtle.importKey(\r\n \"raw\", activeHashedKey as unknown as BufferSource, { name: \"AES-GCM\" }, false, [\"encrypt\"]\r\n );\r\n\r\n const encryptedBuffer = await globalThis.crypto.subtle.encrypt(\r\n { name: \"AES-GCM\", iv }, cryptoKey, new TextEncoder().encode(text)\r\n );\r\n\r\n const finalBuffer = new Uint8Array(iv.length + encryptedBuffer.byteLength);\r\n finalBuffer.set(iv, 0);\r\n finalBuffer.set(new Uint8Array(encryptedBuffer), iv.length);\r\n\r\n // Convert to base64 safely for edges\r\n let binary = '';\r\n const len = finalBuffer.byteLength;\r\n for (let i = 0; i < len; i++) {\r\n binary += String.fromCharCode(finalBuffer[i]);\r\n }\r\n const base64 = btoa(binary);\r\n return `${this.activeKeyId}:${base64}`;\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // prepareLogEntry() — Prepares, redacts, and encrypts a single log entry payload\r\n // ---------------------------------------------------------------------------\r\n private async prepareLogEntry(payload: LogPayload, maxMetaOverride?: number) {\r\n // Hard ceiling guardrail: reject immediately if raw metadata exceeds 5MB limit\r\n const PAYLOAD_5MB_LIMIT = 5 * 1024 * 1024;\r\n const metadata = payload.metadata || {};\r\n const payloadSize = new TextEncoder().encode(JSON.stringify(metadata)).length;\r\n\r\n if (payloadSize > PAYLOAD_5MB_LIMIT) {\r\n throw new Error(`Volidator SDK Error: Audit log payload exceeds the 5MB hard limit (${payloadSize} bytes).`);\r\n }\r\n\r\n const actorRaw = payload.actor || payload.actorId || \"unknown\";\r\n const targetRaw = payload.target || payload.targetId || \"unknown\";\r\n const tenantRaw = payload.tenant || payload.tenantId || \"\";\r\n\r\n const truncate = (str: string, maxLen: number): string => {\r\n if (str.length > maxLen) {\r\n return str.slice(0, maxLen) + \"...\";\r\n }\r\n return str;\r\n };\r\n\r\n const extractPii = (v: string | ReferencePayload): string =>\r\n typeof v === \"object\" ? v.pii : v;\r\n const extractId = (v: string | ReferencePayload): string =>\r\n typeof v === \"object\" ? v.id : v;\r\n\r\n const actor = truncate(extractPii(actorRaw), 255);\r\n const target = truncate(extractPii(targetRaw), 255);\r\n const tenant = tenantRaw ? truncate(extractPii(tenantRaw), 255) : \"\";\r\n const action = truncate(payload.action, 255);\r\n\r\n const logTelemetry = payload.telemetry\r\n ? VolidatorClient.resolveTelemetryConfig({ ...this.telemetryConfig, ...payload.telemetry })\r\n : this.telemetryConfig;\r\n\r\n let payloadCtx = payload.context || {};\r\n if (payload.req) {\r\n const extracted = VolidatorClient.extractContext(payload.req);\r\n payloadCtx = {\r\n ...extracted,\r\n ...payloadCtx,\r\n location: {\r\n ...extracted.location,\r\n ...payloadCtx.location,\r\n },\r\n device: {\r\n ...extracted.device,\r\n ...payloadCtx.device,\r\n },\r\n };\r\n }\r\n\r\n const context: TelemetryContext = {};\r\n const rawIp = payloadCtx.ip || \"\";\r\n const rawUa = payloadCtx.userAgent || \"\";\r\n\r\n if (logTelemetry.location) {\r\n context.location = {};\r\n if (payloadCtx.location) {\r\n context.location.country = payloadCtx.location.country || \"\";\r\n context.location.region = payloadCtx.location.region || \"\";\r\n const isFull = payload.telemetry?.preset === \"full\" || (!payload.telemetry && this.telemetryConfig.ip === \"track\");\r\n if (logTelemetry.ip === \"track\" || isFull) {\r\n context.location.city = payloadCtx.location.city || \"\";\r\n }\r\n }\r\n }\r\n\r\n if (logTelemetry.ip === \"anonymize\" && rawIp) {\r\n context.ip = await this.generateBlindIndex(rawIp, await this._getHashedKey(this.activeKeyId));\r\n } else if (logTelemetry.ip === \"track\" && rawIp) {\r\n context.ip = rawIp;\r\n }\r\n\r\n if (logTelemetry.userAgent !== \"skip\") {\r\n if (rawUa) {\r\n context.device = this.parseUserAgent(rawUa);\r\n if (logTelemetry.userAgent === \"track\") {\r\n context.userAgent = truncate(rawUa, 1000);\r\n }\r\n } else if (payloadCtx.device) {\r\n context.device = payloadCtx.device;\r\n }\r\n }\r\n\r\n const scrub = (value: string, key: string): string =>\r\n this.redactKeys.includes(key) ? `[REDACTED:${key}]` : value;\r\n\r\n const applyRef = (rawValue: string | ReferencePayload, key: string): string => {\r\n if (this.referenceKeys.includes(key)) {\r\n const id = extractId(rawValue);\r\n return `[REF:${id}]`;\r\n }\r\n return scrub(extractPii(rawValue), key);\r\n };\r\n\r\n const rawMetadata = payload.metadata || {};\r\n const safeMetadata: Record<string, any> = {};\r\n for (const [k, v] of Object.entries(rawMetadata)) {\r\n const metaKey = `metadata.${k}`;\r\n if (this.referenceKeys.includes(metaKey) && typeof v === \"object\" && v !== null && \"id\" in v) {\r\n safeMetadata[k] = `[REF:${(v as ReferencePayload).id}]`;\r\n } else if (this.redactKeys.includes(metaKey) && typeof v === \"string\") {\r\n safeMetadata[k] = `[REDACTED:${k}]`;\r\n } else {\r\n safeMetadata[k] = v;\r\n }\r\n }\r\n\r\n let didTruncateDepth = false;\r\n let didTruncateString = false;\r\n\r\n const limitDepth = (obj: any, currentDepth = 1): any => {\r\n if (currentDepth > 5) {\r\n didTruncateDepth = true;\r\n return \"[Truncated - Depth Exceeded]\";\r\n }\r\n if (typeof obj !== \"object\" || obj === null) {\r\n if (typeof obj === \"string\") {\r\n const truncatedVal = truncate(obj, 1000);\r\n if (truncatedVal.length !== obj.length) {\r\n didTruncateString = true;\r\n }\r\n return truncatedVal;\r\n }\r\n return obj;\r\n }\r\n if (Array.isArray(obj)) {\r\n return obj.map(item => limitDepth(item, currentDepth + 1));\r\n }\r\n const result: Record<string, any> = {};\r\n for (const [key, val] of Object.entries(obj)) {\r\n result[key] = limitDepth(val, currentDepth + 1);\r\n }\r\n return result;\r\n };\r\n\r\n const processedMetadata = limitDepth(safeMetadata);\r\n\r\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\") {\r\n if (didTruncateDepth) {\r\n console.warn(\"[Volidator] Warning: Log metadata exceeded maximum depth limit (5) and was truncated.\");\r\n }\r\n if (didTruncateString) {\r\n console.warn(\"[Volidator] Warning: One or more log metadata string values exceeded the 1000-character limit and were truncated.\");\r\n }\r\n }\r\n\r\n const serializedMeta = JSON.stringify(processedMetadata);\r\n const maxMetaLimit = maxMetaOverride || this.maxMetadataSize;\r\n if (serializedMeta.length > maxMetaLimit) {\r\n throw new Error(`Metadata size exceeds maximum allowed limit of ${maxMetaLimit / 1024}KB.`);\r\n }\r\n\r\n const safeActor = applyRef(actorRaw, \"actor\");\r\n const safeTarget = applyRef(targetRaw, \"target\");\r\n const safeTenant = tenantRaw ? applyRef(tenantRaw, \"tenant\") : undefined;\r\n\r\n const enrichedPayload: any = {\r\n actor: safeActor,\r\n action,\r\n target: safeTarget,\r\n metadata: processedMetadata,\r\n };\r\n\r\n if (safeTenant) {\r\n enrichedPayload.tenant = safeTenant;\r\n }\r\n\r\n if (Object.keys(context).length > 0) {\r\n enrichedPayload.context = context;\r\n }\r\n\r\n // Auto-extract trace contexts and logical clock from incoming request if present\r\n let traceId = payload.traceId;\r\n let spanId = payload.spanId;\r\n let parentSpanId = payload.parentSpanId;\r\n let logicalClock = payload.logicalClock;\r\n\r\n if (payload.req) {\r\n const extractedTrace = VolidatorClient.extractTraceContext(payload.req);\r\n if (!traceId && extractedTrace.traceId) {\r\n traceId = extractedTrace.traceId;\r\n }\r\n if (!spanId && extractedTrace.spanId) {\r\n spanId = extractedTrace.spanId;\r\n }\r\n if (logicalClock === undefined && extractedTrace.logicalClock !== undefined) {\r\n logicalClock = extractedTrace.logicalClock;\r\n }\r\n }\r\n\r\n const resolvedClock = this.getAndIncrementClock(logicalClock);\r\n\r\n if (spanId) {\r\n enrichedPayload.spanId = spanId;\r\n }\r\n if (parentSpanId) {\r\n enrichedPayload.parentSpanId = parentSpanId;\r\n }\r\n\r\n const activeKeyBuffer = await this._getHashedKey(this.activeKeyId);\r\n const actorBlindIndex = await this.generateBlindIndex(actor, activeKeyBuffer);\r\n const actionBlindIndex = await this.generateBlindIndex(action, activeKeyBuffer);\r\n const targetBlindIndex = await this.generateBlindIndex(target, activeKeyBuffer);\r\n const tenantBlindIndex = tenant ? await this.generateBlindIndex(tenant, activeKeyBuffer) : undefined;\r\n const traceBlindIndex = traceId ? await this.generateBlindIndex(traceId, activeKeyBuffer) : undefined;\r\n\r\n let encryptedPayload = await this.encryptPayload(enrichedPayload);\r\n let isClaimCheck = false;\r\n\r\n if (encryptedPayload.length > 30720) {\r\n // Calculate content hash of the encrypted payload\r\n const binaryBuffer = new TextEncoder().encode(encryptedPayload);\r\n const hashBuffer = await globalThis.crypto.subtle.digest(\"SHA-256\", binaryBuffer);\r\n const hashHex = Array.from(new Uint8Array(hashBuffer))\r\n .map(b => b.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n\r\n // Upload encrypted payload to edge worker storage endpoint\r\n try {\r\n const uploadRes = await fetch(`${this.endpoint}/v1/log/upload/${hashHex}`, {\r\n method: \"PUT\",\r\n headers: {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n \"Content-Type\": \"application/octet-stream\",\r\n },\r\n body: encryptedPayload,\r\n });\r\n if (!uploadRes.ok) {\r\n throw new Error(`Upload failed with status: ${uploadRes.status}`);\r\n }\r\n // Change payload to contain only the hash\r\n encryptedPayload = hashHex;\r\n isClaimCheck = true;\r\n } catch (err: any) {\r\n console.error(`[Volidator] Claim check upload failed: ${err.message}`);\r\n // Fall back to original payload and let the worker enforce limits if upload fails\r\n }\r\n }\r\n\r\n return {\r\n actorBlindIndex,\r\n actionBlindIndex,\r\n targetBlindIndex,\r\n tenantBlindIndex,\r\n traceBlindIndex,\r\n encryptedPayload,\r\n logicalClock: resolvedClock,\r\n isClaimCheck,\r\n };\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // log() — Encrypt and ingest a single audit event\r\n // ---------------------------------------------------------------------------\r\n async log(payload: LogPayload, maxMetaOverride?: number): Promise<boolean> {\r\n const entry = await this.prepareLogEntry(payload, maxMetaOverride);\r\n let attempt = 0;\r\n let delay = 500;\r\n let lastError: Error = new Error(\"Unknown error\");\r\n\r\n while (attempt <= this.maxRetries) {\r\n try {\r\n const res = await fetch(`${this.endpoint}/v1/log`, {\r\n method: \"POST\",\r\n headers: {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n \"Content-Type\": \"application/json\",\r\n },\r\n body: JSON.stringify(entry),\r\n });\r\n\r\n if (res.ok) {\r\n return true;\r\n }\r\n\r\n lastError = new Error(`Server returned status ${res.status}`);\r\n\r\n // Do not retry 4xx client errors\r\n if (res.status >= 400 && res.status < 500) {\r\n break;\r\n }\r\n } catch (err: any) {\r\n lastError = err instanceof Error ? err : new Error(String(err));\r\n }\r\n\r\n attempt++;\r\n if (attempt <= this.maxRetries) {\r\n await new Promise((resolve) => setTimeout(resolve, delay));\r\n delay *= 3;\r\n }\r\n }\r\n\r\n console.error(`[Volidator] Failed to send log after ${attempt} attempts: ${lastError.message}`);\r\n if (this.onDeliveryFailure) {\r\n try {\r\n this.onDeliveryFailure(payload, lastError);\r\n } catch (cbErr: any) {\r\n console.error(`[Volidator] Error in onDeliveryFailure callback: ${cbErr.message}`);\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // logBatch() — Bulk encrypt and ingest a batch of up to 100 audit events\r\n // ---------------------------------------------------------------------------\r\n async logBatch(payloads: LogPayload[], maxMetaOverride?: number): Promise<{ accepted: number; rejected: number }> {\r\n if (!Array.isArray(payloads) || payloads.length === 0) {\r\n return { accepted: 0, rejected: 0 };\r\n }\r\n\r\n // Cap batch size at 100\r\n const batch = payloads.slice(0, 100);\r\n const preparedEntries: any[] = [];\r\n let rejected = payloads.length - batch.length;\r\n\r\n const results = await Promise.allSettled(\r\n batch.map(p => this.prepareLogEntry(p, maxMetaOverride))\r\n );\r\n\r\n for (const res of results) {\r\n if (res.status === \"fulfilled\") {\r\n preparedEntries.push(res.value);\r\n } else {\r\n rejected++;\r\n console.error(`[Volidator] Failed to prepare batch entry: ${res.reason?.message}`);\r\n }\r\n }\r\n\r\n if (preparedEntries.length === 0) {\r\n return { accepted: 0, rejected };\r\n }\r\n\r\n try {\r\n const res = await fetch(`${this.endpoint}/v1/logs/batch`, {\r\n method: \"POST\",\r\n headers: {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n \"Content-Type\": \"application/json\",\r\n },\r\n body: JSON.stringify({ logs: preparedEntries }),\r\n });\r\n\r\n if (res.ok) {\r\n return { accepted: preparedEntries.length, rejected };\r\n } else {\r\n console.error(`[Volidator] Batch ingestion endpoint returned status: ${res.status}`);\r\n return { accepted: 0, rejected: rejected + preparedEntries.length };\r\n }\r\n } catch (err: any) {\r\n console.error(`[Volidator] Failed to send log batch: ${err.message}`);\r\n return { accepted: 0, rejected: rejected + preparedEntries.length };\r\n }\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // batcher() — Convenience batcher for buffered log ingestion\r\n // ---------------------------------------------------------------------------\r\n /**\r\n * Creates a convenience batcher instance for buffering and ingestion.\r\n * \r\n * ⚠️ SERVERLESS/EDGE CAVEAT:\r\n * autoFlushInterval uses setInterval internally. In serverless/edge environments\r\n * (e.g. Cloudflare Workers, Vercel Edge), the V8 isolate is frozen or destroyed\r\n * once the response is sent. Background timers will silently fail to fire, leading\r\n * to dropped logs. Only use autoFlushInterval in long-lived Node.js processes.\r\n * In serverless/edge environments, always call await batcher.flush() explicitly\r\n * before returning the response, or wrap it in ctx.waitUntil().\r\n */\r\n public batcher(options?: BatcherOptions): VolidatorBatcher {\r\n const client = this;\r\n let buffer: LogPayload[] = [];\r\n let intervalId: any = null;\r\n\r\n const flush = async (): Promise<{ accepted: number; rejected: number }> => {\r\n if (intervalId) {\r\n clearInterval(intervalId);\r\n intervalId = null;\r\n }\r\n if (buffer.length === 0) {\r\n if (options?.autoFlushInterval) {\r\n startTimer();\r\n }\r\n return { accepted: 0, rejected: 0 };\r\n }\r\n\r\n const payloadsToFlush = [...buffer];\r\n buffer = [];\r\n\r\n if (options?.autoFlushInterval) {\r\n startTimer();\r\n }\r\n\r\n return client.logBatch(payloadsToFlush);\r\n };\r\n\r\n const startTimer = () => {\r\n if (options?.autoFlushInterval && !intervalId) {\r\n intervalId = setInterval(() => {\r\n flush().catch((err) => {\r\n console.error(`[Volidator] Batcher auto-flush failed: ${err.message}`);\r\n });\r\n }, options.autoFlushInterval);\r\n if (intervalId && typeof intervalId.unref === \"function\") {\r\n intervalId.unref();\r\n }\r\n }\r\n };\r\n\r\n const push = (payload: LogPayload): void => {\r\n buffer.push(payload);\r\n const maxCount = options?.autoFlushCount || 100;\r\n if (buffer.length >= Math.min(maxCount, 100)) {\r\n flush().catch((err) => {\r\n console.error(`[Volidator] Batcher auto-flush on count failed: ${err.message}`);\r\n });\r\n }\r\n };\r\n\r\n const size = (): number => buffer.length;\r\n\r\n startTimer();\r\n\r\n return {\r\n push,\r\n flush,\r\n size,\r\n };\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // generateEmbedToken() — Sign a HS256 JWT for the embeddable dashboard widget\r\n // ---------------------------------------------------------------------------\r\n async generateEmbedToken(config: EmbedTokenConfig & {\r\n projectId?: string;\r\n clientSecret?: string;\r\n }): Promise<EmbedTokenResult> {\r\n const projectId = config.projectId || this.projectId;\r\n const clientSecret = config.clientSecret || this.clientSecret;\r\n\r\n if (!projectId || !clientSecret) {\r\n throw new Error(\r\n \"generateEmbedToken() requires projectId and clientSecret to be provided in either the configuration or the VolidatorClient constructor.\"\r\n );\r\n }\r\n\r\n const {\r\n actorId,\r\n targetId,\r\n tenantId,\r\n scope,\r\n expiresIn = \"2h\",\r\n dashboardUrl = \"https://dash.volidator.com\",\r\n hostOrigin,\r\n view,\r\n } = config;\r\n\r\n // Determine default query scope based on parameters\r\n const defaultScope = scope || (tenantId ? \"tenant\" : \"actor\");\r\n\r\n // Check if at least one identity parameter is provided (bypassed for auditor scope)\r\n if (defaultScope !== \"auditor\" && !actorId && !targetId && !tenantId) {\r\n throw new Error(\r\n \"At least one of actorId, targetId, or tenantId must be provided to generateEmbedToken().\"\r\n );\r\n }\r\n\r\n // 1. Compute blind indexes for all keys in the keyring\r\n const actorBlindIndexes = actorId\r\n ? await Promise.all(Object.keys(this.keyring).map(async id => this.generateBlindIndex(actorId, await this._getHashedKey(id))))\r\n : undefined;\r\n const targetBlindIndexes = targetId\r\n ? await Promise.all(Object.keys(this.keyring).map(async id => this.generateBlindIndex(targetId, await this._getHashedKey(id))))\r\n : undefined;\r\n const tenantBlindIndexes = tenantId\r\n ? await Promise.all(Object.keys(this.keyring).map(async id => this.generateBlindIndex(tenantId, await this._getHashedKey(id))))\r\n : undefined;\r\n\r\n // 2. Resolve expiry to seconds, capping it at 1 hour (3600s) for security.\r\n const parsedExpiry = this.parseExpiry(expiresIn);\r\n const maxExpiry = defaultScope === \"auditor\" ? 604800 : 3600;\r\n const expiresInSeconds = Math.min(parsedExpiry, maxExpiry);\r\n const now = Math.floor(Date.now() / 1000);\r\n\r\n // 3. Build the JWT payload\r\n const payload: Record<string, any> = {\r\n pid: projectId,\r\n scope: defaultScope,\r\n iat: now,\r\n exp: now + expiresInSeconds,\r\n };\r\n\r\n if (actorBlindIndexes) payload.abi = actorBlindIndexes;\r\n if (targetBlindIndexes) payload.tgb = targetBlindIndexes;\r\n if (tenantBlindIndexes) payload.tbi = tenantBlindIndexes;\r\n\r\n // Compresses presentation config to minimize cookie/header footprint\r\n if (view) {\r\n const compressed: Record<string, any> = {};\r\n if (Array.isArray(view.columns)) {\r\n compressed.cols = view.columns.map((col) => {\r\n if (col === \"createdAt\") return \"cat\";\r\n if (col === \"actor\") return \"act\";\r\n if (col === \"action\") return \"acn\";\r\n if (col === \"target\") return \"tgt\";\r\n if (col.startsWith(\"metadata.\")) {\r\n return `m.${col.slice(9)}`;\r\n }\r\n return col;\r\n });\r\n }\r\n if (view.defaultFilter) {\r\n compressed.flt = {};\r\n if (view.defaultFilter.search !== undefined) {\r\n compressed.flt.q = view.defaultFilter.search;\r\n }\r\n if (view.defaultFilter.action !== undefined) {\r\n compressed.flt.act = view.defaultFilter.action;\r\n }\r\n }\r\n payload.view = compressed;\r\n }\r\n\r\n // 4. Sign as HS256 JWT using the project's clientSecret\r\n const token = await this.signHS256JWT(payload, clientSecret);\r\n\r\n // 5. Append the keyring as the URL hash fragment\r\n const keyringString = Object.entries(this.keyring)\r\n .map(([id, key]) => `${id}:${key}`)\r\n .join(\",\");\r\n const hostParam = hostOrigin\r\n ? `?host=${encodeURIComponent(hostOrigin)}`\r\n : \"\";\r\n const embedUrl = `${dashboardUrl}/embed/${token}${hostParam}#${keyringString}`;\r\n\r\n return { token, embedUrl };\r\n }\r\n\r\n private async signHS256JWT(payload: object, secret: string): Promise<string> {\r\n const header = { alg: \"HS256\", typ: \"JWT\" };\r\n\r\n const encode = (obj: object) =>\r\n btoa(JSON.stringify(obj))\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\")\r\n .replace(/=/g, \"\");\r\n\r\n const unsigned = `${encode(header)}.${encode(payload)}`;\r\n\r\n const key = await globalThis.crypto.subtle.importKey(\r\n \"raw\", new TextEncoder().encode(secret) as unknown as BufferSource, { name: \"HMAC\", hash: \"SHA-256\" }, false, [\"sign\"]\r\n );\r\n const signatureBuffer = await globalThis.crypto.subtle.sign(\r\n \"HMAC\", key, new TextEncoder().encode(unsigned)\r\n );\r\n\r\n let binary = '';\r\n const arr = new Uint8Array(signatureBuffer);\r\n for (let i = 0; i < arr.byteLength; i++) {\r\n binary += String.fromCharCode(arr[i]);\r\n }\r\n const signature = btoa(binary)\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\")\r\n .replace(/=/g, \"\");\r\n\r\n return `${unsigned}.${signature}`;\r\n }\r\n\r\n private parseExpiry(expiry: string): number {\r\n const match = expiry.match(/^(\\d+)(s|m|h|d)$/);\r\n if (!match) return 7200;\r\n const [, num, unit] = match;\r\n const n = parseInt(num, 10);\r\n switch (unit) {\r\n case \"s\": return n;\r\n case \"m\": return n * 60;\r\n case \"h\": return n * 3600;\r\n case \"d\": return n * 86400;\r\n default: return 7200;\r\n }\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Standard Compliance Logging Helper Class\r\n// ---------------------------------------------------------------------------\r\nexport class VolidatorCompliance {\r\n private client: VolidatorClient;\r\n\r\n constructor(client: VolidatorClient) {\r\n this.client = client;\r\n }\r\n\r\n private async logWithControl(\r\n action: string,\r\n soc2Control: string,\r\n isoControl: string,\r\n payload: Omit<LogPayload, \"action\">\r\n ): Promise<boolean> {\r\n const metadata = {\r\n ...payload.metadata,\r\n soc2_control: soc2Control,\r\n iso27001: isoControl,\r\n };\r\n return this.client.log({\r\n ...payload,\r\n action,\r\n metadata,\r\n });\r\n }\r\n\r\n async accessRevoked(payload: Omit<LogPayload, \"action\">): Promise<boolean> {\r\n return this.logWithControl(\"access.revoked\", \"CC6.1\", \"A.9.2.6\", payload);\r\n }\r\n\r\n async accessGranted(payload: Omit<LogPayload, \"action\">): Promise<boolean> {\r\n return this.logWithControl(\"access.granted\", \"CC6.1\", \"A.9.2.1\", payload);\r\n }\r\n\r\n async dataExported(payload: Omit<LogPayload, \"action\">): Promise<boolean> {\r\n return this.logWithControl(\"data.exported\", \"CC6.6\", \"A.12.4.1\", payload);\r\n }\r\n\r\n async systemConfigChanged(payload: Omit<LogPayload, \"action\">): Promise<boolean> {\r\n return this.logWithControl(\"system.config_changed\", \"CC6.2\", \"A.12.1.2\", payload);\r\n }\r\n\r\n async mfaEnabled(payload: Omit<LogPayload, \"action\">): Promise<boolean> {\r\n return this.logWithControl(\"mfa.enabled\", \"CC6.3\", \"A.9.4.2\", payload);\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// AI & Autonomous Agent Compliance Audit Taxonomy Class\r\n// ---------------------------------------------------------------------------\r\nexport class VolidatorAgent {\r\n private client: VolidatorClient;\r\n\r\n constructor(client: VolidatorClient) {\r\n this.client = client;\r\n }\r\n\r\n private async logAgent(\r\n action: string,\r\n euAiAct: string,\r\n nistAiRmf: string,\r\n soc2Control: string,\r\n isoControl: string,\r\n payload: Omit<LogPayload, \"action\"> & Record<string, any>\r\n ): Promise<boolean> {\r\n const {\r\n actor,\r\n actorId,\r\n target,\r\n targetId,\r\n tenant,\r\n tenantId,\r\n metadata,\r\n context,\r\n telemetry,\r\n req,\r\n traceId,\r\n spanId,\r\n parentSpanId,\r\n ...agentData\r\n } = payload;\r\n\r\n const enrichedMetadata = {\r\n ...metadata,\r\n ...agentData,\r\n eu_ai_act: euAiAct,\r\n nist_ai_rmf: nistAiRmf,\r\n soc2_control: soc2Control,\r\n iso27001: isoControl,\r\n };\r\n\r\n // Use 64KB metadata limit for AI events\r\n return this.client.log(\r\n {\r\n actor,\r\n actorId,\r\n target,\r\n targetId,\r\n tenant,\r\n tenantId,\r\n action,\r\n metadata: enrichedMetadata,\r\n context,\r\n telemetry,\r\n req,\r\n traceId,\r\n spanId,\r\n parentSpanId,\r\n },\r\n 65536\r\n );\r\n }\r\n\r\n /**\r\n * Logs a tool call or external API invocation by an agent.\r\n * Maps to EU AI Act Article 12, NIST AI RMF MANAGE 2.2, SOC2 CC6.6, ISO 27001 A.12.4.1.\r\n */\r\n async toolCall(payload: Omit<LogPayload, \"action\"> & {\r\n toolName: string;\r\n toolInput?: Record<string, any>;\r\n toolOutput?: Record<string, any>;\r\n latencyMs?: number;\r\n success: boolean;\r\n }): Promise<boolean> {\r\n return this.logAgent(\"agent.tool_call\", \"Article 12\", \"MANAGE 2.2\", \"CC6.6\", \"A.12.4.1\", payload);\r\n }\r\n\r\n /**\r\n * Logs a key decision made autonomously by an AI agent model.\r\n * Maps to EU AI Act Article 12 & 13, NIST AI RMF GOVERN 1.7, SOC2 CC6.2, ISO 27001 A.18.1.3.\r\n */\r\n async decision(payload: Omit<LogPayload, \"action\"> & {\r\n decision: string;\r\n alternatives?: string[];\r\n rationale?: string;\r\n confidenceScore?: number;\r\n modelId?: string;\r\n }): Promise<boolean> {\r\n return this.logAgent(\"agent.decision\", \"Article 12 & 13\", \"GOVERN 1.7\", \"CC6.2\", \"A.18.1.3\", payload);\r\n }\r\n\r\n /**\r\n * Logs a request for human review or permission escalation.\r\n * Maps to EU AI Act Article 14, NIST AI RMF GOVERN 5.1, SOC2 CC6.3, ISO 27001 A.6.1.2.\r\n */\r\n async escalation(payload: Omit<LogPayload, \"action\"> & {\r\n reason: string;\r\n urgency?: \"low\" | \"medium\" | \"high\";\r\n blockedAction?: string;\r\n }): Promise<boolean> {\r\n return this.logAgent(\"agent.escalation\", \"Article 14\", \"GOVERN 5.1\", \"CC6.3\", \"A.6.1.2\", payload);\r\n }\r\n\r\n /**\r\n * Logs anomalous environment inputs, potential prompt injections, or policy violations.\r\n * Maps to EU AI Act Article 9, NIST AI RMF MANAGE 2.4, SOC2 CC7.2, ISO 27001 A.16.1.2.\r\n */\r\n async anomaly(payload: Omit<LogPayload, \"action\"> & {\r\n description: string;\r\n severity?: \"low\" | \"medium\" | \"high\" | \"critical\";\r\n anomalyType?: \"prompt_injection\" | \"unexpected_input\" | \"policy_violation\" | \"other\";\r\n }): Promise<boolean> {\r\n return this.logAgent(\"agent.anomaly\", \"Article 9\", \"MANAGE 2.4\", \"CC7.2\", \"A.16.1.2\", payload);\r\n }\r\n\r\n /**\r\n * Logs a model refusal to execute a user prompt or command due to alignment safety.\r\n * Maps to EU AI Act Article 5, NIST AI RMF GOVERN 1.1, SOC2 CC6.8, ISO 27001 A.18.1.3.\r\n */\r\n async refusal(payload: Omit<LogPayload, \"action\"> & {\r\n refusedInstruction: string;\r\n reason: string;\r\n policyViolated?: string;\r\n }): Promise<boolean> {\r\n return this.logAgent(\"agent.refusal\", \"Article 5\", \"GOVERN 1.1\", \"CC6.8\", \"A.18.1.3\", payload);\r\n }\r\n\r\n /**\r\n * Logs an execution context handoff from one agent to another.\r\n * Maps to EU AI Act Article 12, NIST AI RMF MAP 1.6, SOC2 CC6.6, ISO 27001 A.12.4.1.\r\n */\r\n async handoff(payload: Omit<LogPayload, \"action\"> & {\r\n toAgentId: string;\r\n instruction: string;\r\n agentContext?: Record<string, any>;\r\n }): Promise<boolean> {\r\n return this.logAgent(\"agent.handoff\", \"Article 12\", \"MAP 1.6\", \"CC6.6\", \"A.12.4.1\", payload);\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/dist/index.cjs CHANGED
@@ -25,8 +25,10 @@ __export(src_exports, {
25
25
  VolidatorCompliance: () => VolidatorCompliance
26
26
  });
27
27
  module.exports = __toCommonJS(src_exports);
28
- var VolidatorClient = class _VolidatorClient {
28
+ var import_node_async_hooks = require("async_hooks");
29
+ var _VolidatorClient = class _VolidatorClient {
29
30
  constructor(config) {
31
+ this.fallbackLogicalClock = 0;
30
32
  this.apiKey = config.apiKey;
31
33
  this.endpoint = config.endpoint || "https://ingestion.volidator.com";
32
34
  this.projectId = config.projectId;
@@ -34,6 +36,8 @@ var VolidatorClient = class _VolidatorClient {
34
36
  this.redactKeys = config.redactKeys || [];
35
37
  this.referenceKeys = config.referenceKeys || [];
36
38
  this.maxMetadataSize = config.maxMetadataSize || 10240;
39
+ this.maxRetries = config.maxRetries !== void 0 ? config.maxRetries : 3;
40
+ this.onDeliveryFailure = config.onDeliveryFailure;
37
41
  if (config.keyring && config.activeEncryptionKeyId) {
38
42
  this.keyring = config.keyring;
39
43
  this.activeKeyId = config.activeEncryptionKeyId;
@@ -54,6 +58,22 @@ var VolidatorClient = class _VolidatorClient {
54
58
  this.compliance = new VolidatorCompliance(this);
55
59
  this.agent = new VolidatorAgent(this);
56
60
  }
61
+ /**
62
+ * Increments and returns the current Lamport Logical Clock counter.
63
+ * If a logicalClockStore context is active, it reads, syncs, and updates
64
+ * the thread-scoped clock; otherwise, it falls back to a global instance-scoped counter.
65
+ *
66
+ * @param incomingClock Optional logical clock sequence from incoming trace parent header
67
+ */
68
+ getAndIncrementClock(incomingClock) {
69
+ const store = _VolidatorClient.logicalClockStore.getStore();
70
+ if (store) {
71
+ store.clock = Math.max(store.clock, incomingClock || 0) + 1;
72
+ return store.clock;
73
+ }
74
+ this.fallbackLogicalClock = Math.max(this.fallbackLogicalClock, incomingClock || 0) + 1;
75
+ return this.fallbackLogicalClock;
76
+ }
57
77
  // ---------------------------------------------------------------------------
58
78
  // Telemetry Context Parser (Zero-latency header parsing)
59
79
  // ---------------------------------------------------------------------------
@@ -95,11 +115,23 @@ var VolidatorClient = class _VolidatorClient {
95
115
  }
96
116
  return "";
97
117
  };
118
+ const result = {};
119
+ const clockVal = getHeader("x-volidator-clock");
120
+ if (clockVal) {
121
+ const parsed = parseInt(clockVal, 10);
122
+ if (!isNaN(parsed)) {
123
+ result.logicalClock = parsed;
124
+ }
125
+ }
98
126
  const traceparent = getHeader("traceparent");
99
- if (!traceparent) return {};
100
- const parts = traceparent.split("-");
101
- if (parts.length !== 4) return {};
102
- return { traceId: parts[1], spanId: parts[2] };
127
+ if (traceparent) {
128
+ const parts = traceparent.split("-");
129
+ if (parts.length === 4) {
130
+ result.traceId = parts[1];
131
+ result.spanId = parts[2];
132
+ }
133
+ }
134
+ return result;
103
135
  }
104
136
  static resolveTelemetryConfig(config) {
105
137
  const preset = config.preset || "standard";
@@ -222,6 +254,12 @@ var VolidatorClient = class _VolidatorClient {
222
254
  // prepareLogEntry() — Prepares, redacts, and encrypts a single log entry payload
223
255
  // ---------------------------------------------------------------------------
224
256
  async prepareLogEntry(payload, maxMetaOverride) {
257
+ const PAYLOAD_5MB_LIMIT = 5 * 1024 * 1024;
258
+ const metadata = payload.metadata || {};
259
+ const payloadSize = new TextEncoder().encode(JSON.stringify(metadata)).length;
260
+ if (payloadSize > PAYLOAD_5MB_LIMIT) {
261
+ throw new Error(`Volidator SDK Error: Audit log payload exceeds the 5MB hard limit (${payloadSize} bytes).`);
262
+ }
225
263
  const actorRaw = payload.actor || payload.actorId || "unknown";
226
264
  const targetRaw = payload.target || payload.targetId || "unknown";
227
265
  const tenantRaw = payload.tenant || payload.tenantId || "";
@@ -303,13 +341,20 @@ var VolidatorClient = class _VolidatorClient {
303
341
  safeMetadata[k] = v;
304
342
  }
305
343
  }
344
+ let didTruncateDepth = false;
345
+ let didTruncateString = false;
306
346
  const limitDepth = (obj, currentDepth = 1) => {
307
347
  if (currentDepth > 5) {
348
+ didTruncateDepth = true;
308
349
  return "[Truncated - Depth Exceeded]";
309
350
  }
310
351
  if (typeof obj !== "object" || obj === null) {
311
352
  if (typeof obj === "string") {
312
- return truncate(obj, 1e3);
353
+ const truncatedVal = truncate(obj, 1e3);
354
+ if (truncatedVal.length !== obj.length) {
355
+ didTruncateString = true;
356
+ }
357
+ return truncatedVal;
313
358
  }
314
359
  return obj;
315
360
  }
@@ -323,6 +368,14 @@ var VolidatorClient = class _VolidatorClient {
323
368
  return result;
324
369
  };
325
370
  const processedMetadata = limitDepth(safeMetadata);
371
+ if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
372
+ if (didTruncateDepth) {
373
+ console.warn("[Volidator] Warning: Log metadata exceeded maximum depth limit (5) and was truncated.");
374
+ }
375
+ if (didTruncateString) {
376
+ console.warn("[Volidator] Warning: One or more log metadata string values exceeded the 1000-character limit and were truncated.");
377
+ }
378
+ }
326
379
  const serializedMeta = JSON.stringify(processedMetadata);
327
380
  const maxMetaLimit = maxMetaOverride || this.maxMetadataSize;
328
381
  if (serializedMeta.length > maxMetaLimit) {
@@ -346,6 +399,7 @@ var VolidatorClient = class _VolidatorClient {
346
399
  let traceId = payload.traceId;
347
400
  let spanId = payload.spanId;
348
401
  let parentSpanId = payload.parentSpanId;
402
+ let logicalClock = payload.logicalClock;
349
403
  if (payload.req) {
350
404
  const extractedTrace = _VolidatorClient.extractTraceContext(payload.req);
351
405
  if (!traceId && extractedTrace.traceId) {
@@ -354,7 +408,11 @@ var VolidatorClient = class _VolidatorClient {
354
408
  if (!spanId && extractedTrace.spanId) {
355
409
  spanId = extractedTrace.spanId;
356
410
  }
411
+ if (logicalClock === void 0 && extractedTrace.logicalClock !== void 0) {
412
+ logicalClock = extractedTrace.logicalClock;
413
+ }
357
414
  }
415
+ const resolvedClock = this.getAndIncrementClock(logicalClock);
358
416
  if (spanId) {
359
417
  enrichedPayload.spanId = spanId;
360
418
  }
@@ -367,14 +425,39 @@ var VolidatorClient = class _VolidatorClient {
367
425
  const targetBlindIndex = await this.generateBlindIndex(target, activeKeyBuffer);
368
426
  const tenantBlindIndex = tenant ? await this.generateBlindIndex(tenant, activeKeyBuffer) : void 0;
369
427
  const traceBlindIndex = traceId ? await this.generateBlindIndex(traceId, activeKeyBuffer) : void 0;
370
- const encryptedPayload = await this.encryptPayload(enrichedPayload);
428
+ let encryptedPayload = await this.encryptPayload(enrichedPayload);
429
+ let isClaimCheck = false;
430
+ if (encryptedPayload.length > 30720) {
431
+ const binaryBuffer = new TextEncoder().encode(encryptedPayload);
432
+ const hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", binaryBuffer);
433
+ const hashHex = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
434
+ try {
435
+ const uploadRes = await fetch(`${this.endpoint}/v1/log/upload/${hashHex}`, {
436
+ method: "PUT",
437
+ headers: {
438
+ Authorization: `Bearer ${this.apiKey}`,
439
+ "Content-Type": "application/octet-stream"
440
+ },
441
+ body: encryptedPayload
442
+ });
443
+ if (!uploadRes.ok) {
444
+ throw new Error(`Upload failed with status: ${uploadRes.status}`);
445
+ }
446
+ encryptedPayload = hashHex;
447
+ isClaimCheck = true;
448
+ } catch (err) {
449
+ console.error(`[Volidator] Claim check upload failed: ${err.message}`);
450
+ }
451
+ }
371
452
  return {
372
453
  actorBlindIndex,
373
454
  actionBlindIndex,
374
455
  targetBlindIndex,
375
456
  tenantBlindIndex,
376
457
  traceBlindIndex,
377
- encryptedPayload
458
+ encryptedPayload,
459
+ logicalClock: resolvedClock,
460
+ isClaimCheck
378
461
  };
379
462
  }
380
463
  // ---------------------------------------------------------------------------
@@ -382,20 +465,44 @@ var VolidatorClient = class _VolidatorClient {
382
465
  // ---------------------------------------------------------------------------
383
466
  async log(payload, maxMetaOverride) {
384
467
  const entry = await this.prepareLogEntry(payload, maxMetaOverride);
385
- try {
386
- const res = await fetch(`${this.endpoint}/v1/log`, {
387
- method: "POST",
388
- headers: {
389
- Authorization: `Bearer ${this.apiKey}`,
390
- "Content-Type": "application/json"
391
- },
392
- body: JSON.stringify(entry)
393
- });
394
- return res.ok;
395
- } catch (err) {
396
- console.error(`[Volidator] Failed to send log: ${err.message}`);
397
- return false;
468
+ let attempt = 0;
469
+ let delay = 500;
470
+ let lastError = new Error("Unknown error");
471
+ while (attempt <= this.maxRetries) {
472
+ try {
473
+ const res = await fetch(`${this.endpoint}/v1/log`, {
474
+ method: "POST",
475
+ headers: {
476
+ Authorization: `Bearer ${this.apiKey}`,
477
+ "Content-Type": "application/json"
478
+ },
479
+ body: JSON.stringify(entry)
480
+ });
481
+ if (res.ok) {
482
+ return true;
483
+ }
484
+ lastError = new Error(`Server returned status ${res.status}`);
485
+ if (res.status >= 400 && res.status < 500) {
486
+ break;
487
+ }
488
+ } catch (err) {
489
+ lastError = err instanceof Error ? err : new Error(String(err));
490
+ }
491
+ attempt++;
492
+ if (attempt <= this.maxRetries) {
493
+ await new Promise((resolve) => setTimeout(resolve, delay));
494
+ delay *= 3;
495
+ }
496
+ }
497
+ console.error(`[Volidator] Failed to send log after ${attempt} attempts: ${lastError.message}`);
498
+ if (this.onDeliveryFailure) {
499
+ try {
500
+ this.onDeliveryFailure(payload, lastError);
501
+ } catch (cbErr) {
502
+ console.error(`[Volidator] Error in onDeliveryFailure callback: ${cbErr.message}`);
503
+ }
398
504
  }
505
+ return false;
399
506
  }
400
507
  // ---------------------------------------------------------------------------
401
508
  // logBatch() — Bulk encrypt and ingest a batch of up to 100 audit events
@@ -442,12 +549,79 @@ var VolidatorClient = class _VolidatorClient {
442
549
  }
443
550
  }
444
551
  // ---------------------------------------------------------------------------
552
+ // batcher() — Convenience batcher for buffered log ingestion
553
+ // ---------------------------------------------------------------------------
554
+ /**
555
+ * Creates a convenience batcher instance for buffering and ingestion.
556
+ *
557
+ * ⚠️ SERVERLESS/EDGE CAVEAT:
558
+ * autoFlushInterval uses setInterval internally. In serverless/edge environments
559
+ * (e.g. Cloudflare Workers, Vercel Edge), the V8 isolate is frozen or destroyed
560
+ * once the response is sent. Background timers will silently fail to fire, leading
561
+ * to dropped logs. Only use autoFlushInterval in long-lived Node.js processes.
562
+ * In serverless/edge environments, always call await batcher.flush() explicitly
563
+ * before returning the response, or wrap it in ctx.waitUntil().
564
+ */
565
+ batcher(options) {
566
+ const client = this;
567
+ let buffer = [];
568
+ let intervalId = null;
569
+ const flush = async () => {
570
+ if (intervalId) {
571
+ clearInterval(intervalId);
572
+ intervalId = null;
573
+ }
574
+ if (buffer.length === 0) {
575
+ if (options?.autoFlushInterval) {
576
+ startTimer();
577
+ }
578
+ return { accepted: 0, rejected: 0 };
579
+ }
580
+ const payloadsToFlush = [...buffer];
581
+ buffer = [];
582
+ if (options?.autoFlushInterval) {
583
+ startTimer();
584
+ }
585
+ return client.logBatch(payloadsToFlush);
586
+ };
587
+ const startTimer = () => {
588
+ if (options?.autoFlushInterval && !intervalId) {
589
+ intervalId = setInterval(() => {
590
+ flush().catch((err) => {
591
+ console.error(`[Volidator] Batcher auto-flush failed: ${err.message}`);
592
+ });
593
+ }, options.autoFlushInterval);
594
+ if (intervalId && typeof intervalId.unref === "function") {
595
+ intervalId.unref();
596
+ }
597
+ }
598
+ };
599
+ const push = (payload) => {
600
+ buffer.push(payload);
601
+ const maxCount = options?.autoFlushCount || 100;
602
+ if (buffer.length >= Math.min(maxCount, 100)) {
603
+ flush().catch((err) => {
604
+ console.error(`[Volidator] Batcher auto-flush on count failed: ${err.message}`);
605
+ });
606
+ }
607
+ };
608
+ const size = () => buffer.length;
609
+ startTimer();
610
+ return {
611
+ push,
612
+ flush,
613
+ size
614
+ };
615
+ }
616
+ // ---------------------------------------------------------------------------
445
617
  // generateEmbedToken() — Sign a HS256 JWT for the embeddable dashboard widget
446
618
  // ---------------------------------------------------------------------------
447
619
  async generateEmbedToken(config) {
448
- if (!this.projectId || !this.clientSecret) {
620
+ const projectId = config.projectId || this.projectId;
621
+ const clientSecret = config.clientSecret || this.clientSecret;
622
+ if (!projectId || !clientSecret) {
449
623
  throw new Error(
450
- "generateEmbedToken() requires projectId and clientSecret in the VolidatorClient constructor."
624
+ "generateEmbedToken() requires projectId and clientSecret to be provided in either the configuration or the VolidatorClient constructor."
451
625
  );
452
626
  }
453
627
  const {
@@ -474,7 +648,7 @@ var VolidatorClient = class _VolidatorClient {
474
648
  const expiresInSeconds = Math.min(parsedExpiry, maxExpiry);
475
649
  const now = Math.floor(Date.now() / 1e3);
476
650
  const payload = {
477
- pid: this.projectId,
651
+ pid: projectId,
478
652
  scope: defaultScope,
479
653
  iat: now,
480
654
  exp: now + expiresInSeconds
@@ -507,7 +681,7 @@ var VolidatorClient = class _VolidatorClient {
507
681
  }
508
682
  payload.view = compressed;
509
683
  }
510
- const token = await this.signHS256JWT(payload, this.clientSecret);
684
+ const token = await this.signHS256JWT(payload, clientSecret);
511
685
  const keyringString = Object.entries(this.keyring).map(([id, key]) => `${id}:${key}`).join(",");
512
686
  const hostParam = hostOrigin ? `?host=${encodeURIComponent(hostOrigin)}` : "";
513
687
  const embedUrl = `${dashboardUrl}/embed/${token}${hostParam}#${keyringString}`;
@@ -556,6 +730,13 @@ var VolidatorClient = class _VolidatorClient {
556
730
  }
557
731
  }
558
732
  };
733
+ /**
734
+ * Thread-local asynchronous context storage used to maintain
735
+ * and increment Lamport logical clock sequences across execution boundaries
736
+ * (e.g. within API requests or serverless handler contexts).
737
+ */
738
+ _VolidatorClient.logicalClockStore = new import_node_async_hooks.AsyncLocalStorage();
739
+ var VolidatorClient = _VolidatorClient;
559
740
  var VolidatorCompliance = class {
560
741
  constructor(client) {
561
742
  this.client = client;