@govplane/runtime-sdk 0.2.4
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 +365 -0
- package/dist/index.cjs +1080 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +413 -0
- package/dist/index.d.ts +413 -0
- package/dist/index.js +1054 -0
- package/dist/index.js.map +1 -0
- package/docs/operations/Govplane_Incident_Playbook.md +318 -0
- package/docs/operations/Govplane_Runtime_Incident_Controls.md +101 -0
- package/docs/security/Govplane_Threat_Model.md +137 -0
- package/package.json +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client/RuntimeClient.ts","../src/engine/context.ts","../src/engine/when.ts","../src/engine/traceDispatcher.ts","../src/engine/toStructuredTrace.ts","../src/engine/emitTrace.ts","../src/engine/createPolicyEngine.ts","../src/errors/Errors.ts","../src/engine/formatTrace.ts"],"sourcesContent":["export { RuntimeClient } from \"./client/RuntimeClient\";\nexport type { RuntimeClientConfig, RefreshResult, RuntimeCache, BundleMeta, RuntimeStatus } from \"./client/RuntimeClient\";\nexport * from \"./engine/types\";\nexport * from \"./errors/Errors.js\";\nexport * from \"./engine/context.js\";\nexport { createPolicyEngine } from \"./engine/createPolicyEngine.js\";\nexport { formatTrace } from \"./engine/formatTrace.js\";\n","import { request } from \"undici\";\nimport { createPolicyEngine } from \"../engine/createPolicyEngine\";\nimport { promises as fsp } from \"node:fs\";\nimport type {\n RuntimeBundleV1,\n Decision,\n DecisionWithOptionalTrace,\n Target,\n TraceOptions,\n StructuredTraceEvent\n} from \"../engine/types\";\nimport type { ContextPolicy } from \"../engine/context\";\nimport type { PolicyEngine } from \"../engine/types\";\n\nexport type RuntimeClientConfig = {\n baseUrl: string;\n runtimeKey: string;\n orgId: string;\n projectId: string;\n env: string;\n\n // polling\n pollMs?: number; // default 5000\n burstPollMs?: number; // default 500\n burstDurationMs?: number; // default 30000\n\n timeoutMs?: number; // default 5000\n userAgent?: string;\n\n // backoff (Phase 0+)\n backoffBaseMs?: number; // default 500\n backoffMaxMs?: number; // default 30000\n backoffJitter?: number; // default 0.2 (±20%)\n degradeAfterFailures?: number; // default 3\n\n /**\n * Engine config\n */\n engine?: {\n validateContext?: boolean; // default true\n contextPolicy?: ContextPolicy;\n };\n\n /**\n * Decision trace (SDK-only, zero PII)\n */\n trace?: {\n defaults?: TraceOptions; // level/sampling/budget/force\n onDecisionTrace?: (evt: StructuredTraceEvent) => void; // sync\n onDecisionTraceAsync?: (evt: StructuredTraceEvent) => Promise<void>; // async\n queueMax?: number; // default 1000\n dropPolicy?: \"drop_new\" | \"drop_old\"; // default drop_new\n onTraceError?: (err: unknown) => void;\n };\n\n // Incident controls (no endpoints)\n incidentEnvFlag?: string; // default \"GP_RUNTIME_INCIDENT\"\n incidentFilePath?: string; // e.g. \"/etc/govplane/incident.json\"\n incidentFilePollMs?: number; // default 1000\n incidentSignal?: \"SIGUSR1\" | false; // default \"SIGUSR1\"\n};\n\nexport type BundleMeta = {\n etag: string;\n bundleVersion?: number;\n updatedAt?: string;\n};\n\nexport type RuntimeCache<TBundle = unknown> = {\n meta?: BundleMeta;\n bundle?: TBundle;\n};\n\nexport type RefreshResult<TBundle = unknown> =\n | { changed: false; meta?: BundleMeta }\n | { changed: true; meta: BundleMeta; bundle: TBundle };\n\nexport type RuntimeStatus =\n | { state: \"warming_up\" }\n | { state: \"ok\" }\n | {\n state: \"degraded\";\n consecutiveFailures: number;\n lastError: { message: string; at: string };\n nextRetryAt?: string;\n };\n\ntype RequiredCfg =\n Required<\n Pick<\n RuntimeClientConfig,\n | \"pollMs\"\n | \"burstPollMs\"\n | \"burstDurationMs\"\n | \"timeoutMs\"\n | \"backoffBaseMs\"\n | \"backoffMaxMs\"\n | \"backoffJitter\"\n | \"degradeAfterFailures\"\n >\n > &\n Omit<\n RuntimeClientConfig,\n | \"pollMs\"\n | \"burstPollMs\"\n | \"burstDurationMs\"\n | \"timeoutMs\"\n | \"backoffBaseMs\"\n | \"backoffMaxMs\"\n | \"backoffJitter\"\n | \"degradeAfterFailures\"\n >;\n\n type IncidentFilePayload = {\n burst?: boolean;\n burstDurationMs?: number;\n burstPollMs?: number;\n refreshNow?: boolean;\n };\n\n/**\n * RuntimeClient = polling/backoff/degraded + cached runtime bundle + policy evaluation.\n *\n * - No endpoints expuestos por el cliente\n * - No PII en trace: el engine emite StructuredTraceEvent sin context ni reglas completas\n */\nexport class RuntimeClient<TBundle = RuntimeBundleV1> {\n private readonly cfg: RequiredCfg;\n\n private cache: RuntimeCache<TBundle> = {};\n private timer: NodeJS.Timeout | null = null;\n private isRunning = false;\n private hasValidBundle = false;\n\n private inFlightRefresh: Promise<RefreshResult<TBundle>> | null = null;\n private burstUntil = 0;\n\n // health / degraded state\n private consecutiveFailures = 0;\n private lastError: { message: string; at: string } | null = null;\n private nextRetryAtMs: number | null = null;\n\n private updateListeners: Array<(res: RefreshResult<TBundle>) => void> = [];\n private statusListeners: Array<(s: RuntimeStatus) => void> = [];\n\n // Policy engine\n private readonly engine: PolicyEngine;\n\n // Incident controls\n private incidentPollTimer: NodeJS.Timeout | null = null;\n private incidentFileLastMtimeMs: number | null = null;\n private installedSignalHandler = false;\n private sigHandler?: () => void;\n\n constructor(config: RuntimeClientConfig) {\n this.cfg = {\n ...config,\n pollMs: config.pollMs ?? 5000,\n burstPollMs: config.burstPollMs ?? 500,\n burstDurationMs: config.burstDurationMs ?? 30_000,\n timeoutMs: config.timeoutMs ?? 5000,\n\n backoffBaseMs: config.backoffBaseMs ?? 500,\n backoffMaxMs: config.backoffMaxMs ?? 30_000,\n backoffJitter: config.backoffJitter ?? 0.2,\n degradeAfterFailures: config.degradeAfterFailures ?? 3,\n\n incidentEnvFlag: config.incidentEnvFlag ?? \"GP_RUNTIME_INCIDENT\",\n incidentFilePollMs: config.incidentFilePollMs ?? 1000,\n incidentSignal: config.incidentSignal ?? \"SIGUSR1\"\n \n };\n\n // Wiring: el client conecta bundle cacheado + trace sinks + context policy en el engine\n this.engine = createPolicyEngine({\n getBundle: () => this.cache.bundle as any,\n\n validateContext: config.engine?.validateContext !== false,\n contextPolicy: config.engine?.contextPolicy,\n\n traceDefaults: config.trace?.defaults,\n traceSink: config.trace?.onDecisionTrace,\n traceSinkAsync: config.trace?.onDecisionTraceAsync,\n traceQueueMax: config.trace?.queueMax,\n traceQueueDropPolicy: config.trace?.dropPolicy,\n onTraceSinkError: config.trace?.onTraceError\n });\n }\n\n /** Subscribe to bundle updates (only when changed). */\n onUpdate(fn: (res: Extract<RefreshResult<TBundle>, { changed: true }>) => void) {\n const wrapped = (res: RefreshResult<TBundle>) => {\n if (res.changed) fn(res as any);\n };\n this.updateListeners.push(wrapped);\n return () => {\n this.updateListeners = this.updateListeners.filter((x) => x !== wrapped);\n };\n }\n\n /** Subscribe to status changes (ok/degraded). */\n onStatus(fn: (s: RuntimeStatus) => void) {\n this.statusListeners.push(fn);\n fn(this.getStatus());\n return () => {\n this.statusListeners = this.statusListeners.filter((x) => x !== fn);\n };\n }\n\n /** Evaluate a decision using the cached bundle (deny-by-default if bundle missing/invalid). */\n evaluate(input: { target: Target; context?: Record<string, unknown> }): Decision {\n return this.engine.evaluate(input);\n }\n\n /** Evaluate and (optionally) attach trace based on trace defaults/overrides. */\n evaluateWithTrace(\n input: { target: Target; context?: Record<string, unknown> },\n options?: TraceOptions\n ): DecisionWithOptionalTrace {\n return this.engine.evaluateWithTrace(input, options);\n }\n\n /** Flush async trace queue (only does something if traceSinkAsync is configured). */\n flushTraces(): Promise<void> {\n return this.engine.flushTraces();\n }\n\n getCached(): RuntimeCache<TBundle> {\n return { ...this.cache };\n }\n\n getStatus(): RuntimeStatus {\n // si aún no hemos cacheado un bundle válido, es warming_up\n const b: any = this.cache.bundle;\n const valid = !!(b && typeof b === \"object\" && b.schemaVersion === 1 && Array.isArray(b.policies));\n if (!this.hasValidBundle && !valid) return { state: \"warming_up\" };\n\n if (this.consecutiveFailures >= this.cfg.degradeAfterFailures) {\n return {\n state: \"degraded\",\n consecutiveFailures: this.consecutiveFailures,\n lastError: this.lastError ?? { message: \"unknown\", at: new Date().toISOString() },\n nextRetryAt: this.nextRetryAtMs ? new Date(this.nextRetryAtMs).toISOString() : undefined\n };\n }\n return { state: \"ok\" };\n }\n\n start() {\n if (this.isRunning) return;\n this.isRunning = true;\n\n // Incident controls (primero)\n this.applyIncidentFromEnv();\n this.startIncidentFilePoller();\n this.installIncidentSignal();\n\n // Luego el loop\n this.scheduleNext(0);\n }\n\n async warmStart(opts?: { timeoutMs?: number; burst?: boolean }): Promise<void> {\n // Incident controls (por si warmStart se usa sin start)\n this.applyIncidentFromEnv();\n this.startIncidentFilePoller();\n this.installIncidentSignal();\n\n const timeoutMs = opts?.timeoutMs ?? 10_000;\n const until = Date.now() + timeoutMs;\n\n if (opts?.burst) {\n await this.refreshNow({ burst: true }).catch(() => void 0);\n } else {\n await this.refreshNow().catch(() => void 0);\n }\n\n while (Date.now() < until) {\n const b: any = this.cache.bundle;\n const valid = !!(b && typeof b === \"object\" && b.schemaVersion === 1 && Array.isArray(b.policies));\n if (valid) {\n this.hasValidBundle = true;\n return;\n }\n await new Promise((r) => setTimeout(r, 100));\n }\n\n throw new Error(\"warmStart timeout: no valid runtime bundle received\");\n }\n\n stop() {\n this.isRunning = false;\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n\n if (this.incidentPollTimer) clearInterval(this.incidentPollTimer);\n this.incidentPollTimer = null;\n this.uninstallIncidentSignal();\n }\n\n async refreshNow(opts?: { burst?: boolean }): Promise<RefreshResult<TBundle>> {\n if (opts?.burst) {\n this.burstUntil = Date.now() + this.cfg.burstDurationMs;\n if (this.isRunning) this.scheduleNext(0);\n }\n return this.refresh();\n }\n\n private emitStatusIfNeeded(prev: RuntimeStatus) {\n const next = this.getStatus();\n\n const key = (s: RuntimeStatus) => {\n if (s.state === \"warming_up\") return \"warming_up\";\n if (s.state === \"ok\") return \"ok\";\n return `degraded:${s.consecutiveFailures}:${s.lastError.message}`;\n };\n\n if (key(prev) !== key(next)) {\n for (const l of this.statusListeners) l(next);\n }\n }\n \n\n private async refresh(): Promise<RefreshResult<TBundle>> {\n if (this.inFlightRefresh) return this.inFlightRefresh;\n\n const prevStatus = this.getStatus();\n\n this.inFlightRefresh = (async () => {\n try {\n const head = await this.headBundle();\n if (!head) {\n this.markSuccess();\n this.emitStatusIfNeeded(prevStatus);\n return { changed: false, meta: this.cache.meta };\n }\n\n const prevEtag = this.cache.meta?.etag;\n if (prevEtag && head.etag === prevEtag) {\n this.cache.meta = head;\n this.markSuccess();\n this.emitStatusIfNeeded(prevStatus);\n return { changed: false, meta: head };\n }\n\n const got = await this.getBundle();\n this.markSuccess();\n this.emitStatusIfNeeded(prevStatus);\n return got.changed ? got : { changed: false, meta: got.meta };\n } catch (err: any) {\n this.markFailure(err);\n this.emitStatusIfNeeded(prevStatus);\n throw err;\n } finally {\n this.inFlightRefresh = null;\n }\n })();\n\n return this.inFlightRefresh;\n }\n\n private scheduleNext(delayMs: number) {\n if (!this.isRunning) return;\n if (this.timer) clearTimeout(this.timer);\n\n this.timer = setTimeout(async () => {\n const prevStatus = this.getStatus();\n\n try {\n // incident env flag\n this.applyIncidentFromEnv();\n\n // backoff guard (si tienes nextRetryAtMs)\n if (this.nextRetryAtMs && Date.now() < this.nextRetryAtMs) {\n this.scheduleNext(Math.max(0, this.nextRetryAtMs - Date.now()));\n return;\n }\n\n const res = await this.refresh();\n if (res.changed) {\n for (const l of this.updateListeners) l(res);\n }\n } catch {\n // swallow\n } finally {\n this.emitStatusIfNeeded(prevStatus);\n\n const next =\n this.nextRetryAtMs && Date.now() < this.nextRetryAtMs\n ? Math.max(0, this.nextRetryAtMs - Date.now())\n : this.effectivePollMs();\n\n this.scheduleNext(next);\n }\n }, delayMs);\n }\n\n private effectivePollMs() {\n const now = Date.now();\n if (now < this.burstUntil) return this.cfg.burstPollMs;\n return this.cfg.pollMs;\n }\n\n private markSuccess() {\n this.consecutiveFailures = 0;\n this.lastError = null;\n this.nextRetryAtMs = null;\n }\n\n private markFailure(err: any) {\n this.consecutiveFailures += 1;\n this.lastError = { message: String(err?.message ?? err ?? \"unknown\"), at: new Date().toISOString() };\n\n const delay = this.computeBackoffDelayMs(this.consecutiveFailures);\n this.nextRetryAtMs = Date.now() + delay;\n }\n\n private computeBackoffDelayMs(failures: number) {\n const base = this.cfg.backoffBaseMs;\n const max = this.cfg.backoffMaxMs;\n const exp = base * Math.pow(2, Math.max(0, failures - 1));\n const capped = Math.min(max, exp);\n\n const jitter = Math.max(0, Math.min(1, this.cfg.backoffJitter));\n const delta = capped * jitter;\n const min = Math.max(0, capped - delta);\n const maxJ = capped + delta;\n\n const r = Math.random();\n return Math.floor(min + r * (maxJ - min));\n }\n\n private bundleUrl(): string {\n const u = new URL(this.cfg.baseUrl);\n u.pathname = \"/v1/runtime/bundle\";\n u.searchParams.set(\"projectId\", this.cfg.projectId);\n u.searchParams.set(\"env\", this.cfg.env);\n return u.toString();\n }\n\n private commonHeaders(extra?: Record<string, string>) {\n return {\n Authorization: `Bearer ${this.cfg.runtimeKey}`,\n \"User-Agent\": this.cfg.userAgent ?? \"govplane-runtime-sdk/0.x\",\n ...extra\n };\n }\n\n private async headBundle(): Promise<BundleMeta | undefined> {\n const url = this.bundleUrl();\n\n const { statusCode, headers, body } = await request(url, {\n method: \"HEAD\",\n headers: this.commonHeaders(),\n bodyTimeout: this.cfg.timeoutMs,\n headersTimeout: this.cfg.timeoutMs\n });\n\n await body.text().catch(() => void 0);\n\n if (statusCode === 401 || statusCode === 403) throw new Error(`Unauthorized (${statusCode})`);\n if (statusCode >= 500) throw new Error(`Runtime server error (${statusCode})`);\n if (statusCode !== 200 && statusCode !== 304) return this.cache.meta;\n\n const etag = (headers[\"etag\"] as string | undefined) ?? \"\";\n if (!etag) return this.cache.meta;\n\n const bundleVersionRaw = headers[\"x-gp-bundle-version\"] as string | undefined;\n const updatedAt = headers[\"x-gp-updated-at\"] as string | undefined;\n\n return {\n etag,\n bundleVersion: bundleVersionRaw ? Number(bundleVersionRaw) : undefined,\n updatedAt\n };\n }\n\n private async getBundle(): Promise<RefreshResult<TBundle>> {\n const url = this.bundleUrl();\n const ifNoneMatch = this.cache.meta?.etag;\n\n const { statusCode, headers, body } = await request(url, {\n method: \"GET\",\n headers: this.commonHeaders(ifNoneMatch ? { \"If-None-Match\": ifNoneMatch } : undefined),\n bodyTimeout: this.cfg.timeoutMs,\n headersTimeout: this.cfg.timeoutMs\n });\n\n const txt = await body.text();\n\n if (statusCode === 304) {\n const etag = (headers[\"etag\"] as string | undefined) ?? ifNoneMatch ?? \"\";\n const bundleVersionRaw = headers[\"x-gp-bundle-version\"] as string | undefined;\n const updatedAt = headers[\"x-gp-updated-at\"] as string | undefined;\n\n const meta: BundleMeta | undefined = etag\n ? { etag, bundleVersion: bundleVersionRaw ? Number(bundleVersionRaw) : undefined, updatedAt }\n : this.cache.meta;\n\n if (meta) this.cache.meta = meta;\n return { changed: false, meta };\n }\n\n if (statusCode === 401 || statusCode === 403) throw new Error(`Unauthorized (${statusCode})`);\n if (statusCode >= 400) throw new Error(`Runtime HTTP error (${statusCode}): ${txt.slice(0, 200)}`);\n\n const etag = (headers[\"etag\"] as string | undefined) ?? \"\";\n const bundleVersionRaw = headers[\"x-gp-bundle-version\"] as string | undefined;\n const updatedAt = headers[\"x-gp-updated-at\"] as string | undefined;\n\n const meta: BundleMeta = {\n etag: etag || (ifNoneMatch ?? \"\"),\n bundleVersion: bundleVersionRaw ? Number(bundleVersionRaw) : undefined,\n updatedAt\n };\n\n const parsed = JSON.parse(txt) as any;\n\n // Normaliza: si viene { success, data }, usa data (y si data.body existe, usa data.body)\n const normalized =\n parsed?.schemaVersion === 1\n ? parsed\n : parsed?.data?.schemaVersion === 1\n ? parsed.data\n : parsed?.data?.body?.schemaVersion === 1\n ? parsed.data.body\n : parsed?.body?.schemaVersion === 1\n ? parsed.body\n : parsed;\n\n this.cache = { meta, bundle: normalized as TBundle };\n\n const nb: any = normalized;\n if (nb && typeof nb === \"object\" && nb.schemaVersion === 1 && Array.isArray(nb.policies)) {\n this.hasValidBundle = true;\n }\n\n return { changed: true, meta, bundle: normalized as TBundle };\n }\n\n // Incident controls\n private enableBurst(input: { durationMs: number; pollMs: number }) {\n const now = Date.now();\n const until = now + Math.max(0, input.durationMs);\n if (until > this.burstUntil) this.burstUntil = until;\n\n // allow runtime tuning for incident\n if (Number.isFinite(input.pollMs) && input.pollMs > 0) {\n (this.cfg as any).burstPollMs = input.pollMs;\n }\n\n console.log(`[govplane][incident] burst enabled until ${new Date(this.burstUntil).toISOString()} (pollMs=${this.cfg.burstPollMs})`);\n }\n\n private disableBurst() {\n this.burstUntil = 0;\n console.log(`[govplane][incident] burst disabled`);\n }\n\n private applyIncidentFromEnv() {\n const flag = this.cfg.incidentEnvFlag;\n if (!flag) return;\n\n const v = String(process.env[flag] ?? \"\").trim().toLowerCase();\n const on = v === \"1\" || v === \"true\" || v === \"yes\" || v === \"on\";\n\n if (on) {\n this.enableBurst({ durationMs: this.cfg.burstDurationMs, pollMs: this.cfg.burstPollMs });\n }\n\n }\n\n private startIncidentFilePoller() {\n const filePath = this.cfg.incidentFilePath;\n if (!filePath) return;\n\n if (this.incidentPollTimer) clearInterval(this.incidentPollTimer);\n\n this.incidentPollTimer = setInterval(() => {\n void this.checkIncidentFileOnce(filePath).catch(() => void 0);\n }, this.cfg.incidentFilePollMs);\n\n // run once immediately\n void this.checkIncidentFileOnce(filePath).catch(() => void 0);\n }\n\n private async checkIncidentFileOnce(filePath: string) {\n // stat: if missing, ignore\n let mtimeMs: number;\n try {\n const st = await fsp.stat(filePath);\n mtimeMs = st.mtimeMs;\n } catch {\n // file missing\n return;\n }\n\n if (this.incidentFileLastMtimeMs !== null && mtimeMs === this.incidentFileLastMtimeMs) return;\n this.incidentFileLastMtimeMs = mtimeMs;\n\n let txt: string;\n try {\n txt = await fsp.readFile(filePath, \"utf8\");\n } catch {\n return;\n }\n\n let payload: IncidentFilePayload;\n try {\n payload = JSON.parse(txt);\n } catch {\n return;\n }\n if (!payload || typeof payload !== \"object\") return;\n\n if (payload.burst === true) {\n this.enableBurst({\n durationMs: payload.burstDurationMs ?? this.cfg.burstDurationMs,\n pollMs: payload.burstPollMs ?? this.cfg.burstPollMs\n });\n\n if (this.isRunning) this.scheduleNext(0);\n } else if (payload.burst === false) {\n this.disableBurst();\n }\n\n if (payload.refreshNow === true) {\n void this.refreshNow({ burst: payload.burst === true }).catch(() => void 0);\n }\n }\n\n private installIncidentSignal() {\n if (this.installedSignalHandler) return;\n if (this.cfg.incidentSignal === false) return;\n\n const sig = this.cfg.incidentSignal;\n\n if(!sig) return;\n\n try {\n this.sigHandler = () => {\n this.enableBurst({ durationMs: this.cfg.burstDurationMs, pollMs: this.cfg.burstPollMs });\n if (this.isRunning) this.scheduleNext(0);\n void this.refreshNow({ burst: true }).catch(() => void 0);\n };\n\n process.on(sig, this.sigHandler);\n this.installedSignalHandler = true;\n } catch {\n // ignore unsupported environments\n }\n }\n\n private uninstallIncidentSignal() {\n if (!this.installedSignalHandler) return;\n if (this.cfg.incidentSignal === false) return;\n\n const sig = this.cfg.incidentSignal;\n\n if(!sig) return;\n\n try {\n if (this.sigHandler) process.off(sig, this.sigHandler);\n } catch {\n // ignore\n } finally {\n this.installedSignalHandler = false;\n this.sigHandler = undefined;\n }\n }\n}","export type ContextPolicy = {\n allowedKeys: string[];\n maxStringLen: number;\n maxArrayLen: number;\n blockLikelyPiiKeys: boolean;\n};\n\nexport const DEFAULT_CONTEXT_POLICY: ContextPolicy = {\n allowedKeys: [\n \"ctx.plan\",\n \"ctx.country\",\n \"ctx.requestTier\",\n \"ctx.feature\",\n \"ctx.amount\",\n \"ctx.isAuthenticated\",\n \"ctx.role\"\n ],\n maxStringLen: 64,\n maxArrayLen: 10,\n blockLikelyPiiKeys: true\n};\n\n// Heurística simple (no perfecta): bloquea nombres de claves típicas de PII\nconst PII_KEY_PATTERNS: RegExp[] = [\n /email/i,\n /phone/i,\n /mobile/i,\n /name/i,\n /firstname/i,\n /lastname/i,\n /address/i,\n /street/i,\n /postcode|postal/i,\n /city/i,\n /ip/i,\n /ssn/i,\n /dni|nie/i,\n /passport/i\n];\n\nconst DEFAULT_POLICY: Required<Omit<ContextPolicy, \"allowedKeys\">> = {\n maxStringLen: 80,\n maxArrayLen: 25,\n blockLikelyPiiKeys: true\n};\n\nexport function validateContext(\n ctx: Record<string, unknown>,\n policy: ContextPolicy\n): void {\n const allowed = new Set(policy.allowedKeys);\n const maxStringLen = policy.maxStringLen ?? DEFAULT_POLICY.maxStringLen;\n const maxArrayLen = policy.maxArrayLen ?? DEFAULT_POLICY.maxArrayLen;\n const blockLikelyPiiKeys = policy.blockLikelyPiiKeys ?? DEFAULT_POLICY.blockLikelyPiiKeys;\n\n for (const [k, v] of Object.entries(ctx)) {\n const path = `ctx.${k}`;\n\n if (!allowed.has(path)) {\n throw new Error(`Context key not allowed: ${path}`);\n }\n\n if (blockLikelyPiiKeys) {\n for (const re of PII_KEY_PATTERNS) {\n if (re.test(k)) {\n throw new Error(`Context key looks like PII and is blocked: ${path}`);\n }\n }\n }\n\n if (v === null || v === undefined) continue;\n\n const t = typeof v;\n if (t === \"boolean\" || t === \"number\") continue;\n\n if (t === \"string\") {\n if ((v as string).length > maxStringLen) throw new Error(`Context value too long: ${path}`);\n continue;\n }\n\n if (Array.isArray(v)) {\n if (v.length > maxArrayLen) throw new Error(`Context array too long: ${path}`);\n for (const it of v) {\n if (typeof it !== \"string\") throw new Error(`Invalid array value type: ${path}`);\n if (it.length > maxStringLen) throw new Error(`Invalid array value length: ${path}`);\n }\n continue;\n }\n\n throw new Error(`Invalid context type for ${path}`);\n }\n}","import type { WhenAstV1 } from \"./types.js\";\n\nfunction getPath(obj: any, path: string): any {\n // path esperado: \"ctx.xxx\"\n const parts = path.split(\".\");\n let cur = obj;\n for (const p of parts) {\n if (!cur || typeof cur !== \"object\") return undefined;\n cur = cur[p];\n }\n return cur;\n}\n\nexport function evalWhen(node: WhenAstV1, ctx: Record<string, unknown>): boolean {\n switch (node.op) {\n case \"and\": return node.args.every(n => evalWhen(n, ctx));\n case \"or\": return node.args.some(n => evalWhen(n, ctx));\n case \"not\": return !evalWhen(node.arg, ctx);\n\n case \"exists\": return getPath({ ctx }, node.path) !== undefined;\n\n case \"in\": {\n const v = getPath({ ctx }, node.path);\n return node.values.some(x => x === v);\n }\n\n case \"eq\": return getPath({ ctx }, node.path) === node.value;\n case \"ne\": return getPath({ ctx }, node.path) !== node.value;\n\n case \"gt\": return Number(getPath({ ctx }, node.path)) > Number(node.value);\n case \"gte\": return Number(getPath({ ctx }, node.path)) >= Number(node.value);\n case \"lt\": return Number(getPath({ ctx }, node.path)) < Number(node.value);\n case \"lte\": return Number(getPath({ ctx }, node.path)) <= Number(node.value);\n\n default:\n return false;\n }\n}","import type { StructuredTraceEvent, TraceSinkAsync, TraceQueueDropPolicy } from \"./types\";\n\ntype Opts = {\n sinkAsync: TraceSinkAsync;\n max: number;\n dropPolicy: TraceQueueDropPolicy;\n onError?: (err: unknown) => void;\n};\n\nexport class TraceDispatcher {\n private q: StructuredTraceEvent[] = [];\n private draining = false;\n\n private flushWaiters: Array<() => void> = [];\n\n constructor(private readonly opts: Opts) {}\n\n enqueue(evt: StructuredTraceEvent): void {\n if (this.q.length >= this.opts.max) {\n if (this.opts.dropPolicy === \"drop_old\") {\n this.q.shift();\n } else {\n return;\n }\n }\n\n this.q.push(evt);\n this.kick();\n }\n\n async flush(): Promise<void> {\n if (!this.draining && this.q.length === 0) return;\n\n return new Promise<void>((resolve) => {\n this.flushWaiters.push(resolve);\n this.kick();\n });\n }\n\n private kick(): void {\n if (this.draining) return;\n if (this.q.length === 0) {\n this.resolveFlushWaitersIfIdle();\n return;\n }\n\n this.draining = true;\n\n // Non-blocking drain\n queueMicrotask(() => void this.drain());\n }\n\n private resolveFlushWaitersIfIdle(): void {\n if (this.draining) return;\n if (this.q.length !== 0) return;\n\n const waiters = this.flushWaiters;\n this.flushWaiters = [];\n for (const w of waiters) w();\n }\n\n private async drain(): Promise<void> {\n try {\n while (this.q.length) {\n const evt = this.q.shift()!;\n try {\n await this.opts.sinkAsync(evt);\n } catch (err) {\n if (this.opts.onError) this.opts.onError(err);\n }\n }\n } finally {\n this.draining = false;\n // resolve flush waiters if idle now\n this.resolveFlushWaitersIfIdle();\n // if items arrived during finishing, restart\n if (this.q.length) this.kick();\n }\n }\n}","import type { Decision } from \"./types\";\nimport type { DecisionTraceCompact, DecisionTraceFull, StructuredTraceEvent, TraceLevel } from \"./types\";\n\nexport function toStructuredTraceEvent(input: {\n level: TraceLevel;\n decision: Decision;\n trace: DecisionTraceCompact | DecisionTraceFull;\n}): StructuredTraceEvent {\n const { decision, trace, level } = input;\n\n const evt: StructuredTraceEvent = {\n v: 1,\n ts: trace.evaluatedAt,\n traceId: trace.traceId,\n sampled: trace.sampled,\n level,\n target: trace.target,\n decision: decision.decision,\n reason: decision.reason,\n winner: trace.winner,\n summary: trace.summary\n };\n\n if (level === \"full\" && \"rules\" in trace) {\n evt.rules = trace.rules.map(r => ({\n policyKey: r.policyKey,\n ruleId: r.ruleId,\n priority: r.priority,\n effectType: r.effectType,\n matched: r.matched,\n discardedReason: r.discardedReason\n }));\n }\n\n return evt;\n}","import type { Decision } from \"./types\";\nimport type {\n DecisionTraceCompact,\n DecisionTraceFull,\n StructuredTraceEvent,\n TraceLevel,\n TraceSink\n} from \"./types\";\nimport { toStructuredTraceEvent } from \"./toStructuredTrace\";\nimport type { TraceDispatcher } from \"./traceDispatcher\";\n\nexport function emitTraceIfAny(input: {\n level: TraceLevel;\n decision: Decision;\n trace?: DecisionTraceCompact | DecisionTraceFull;\n\n sink?: TraceSink;\n dispatcher?: TraceDispatcher;\n\n onSinkError?: (err: unknown) => void;\n}): void {\n const { trace, decision, level } = input;\n if (!trace) return;\n\n let evt: StructuredTraceEvent;\n try {\n evt = toStructuredTraceEvent({ level, decision, trace });\n } catch (err) {\n input.onSinkError?.(err);\n return;\n }\n\n // Sync sink (best-effort)\n if (input.sink) {\n try {\n input.sink(evt);\n } catch (err) {\n input.onSinkError?.(err);\n }\n }\n\n // Async sink via dispatcher (non-blocking)\n if (input.dispatcher) {\n input.dispatcher.enqueue(evt);\n }\n}","import type { Decision, RuntimeBundleV1, Target, PolicyEngine } from \"./types\";\nimport type { ContextPolicy } from \"./context\";\nimport { validateContext, DEFAULT_CONTEXT_POLICY } from \"./context\";\nimport { evalWhen } from \"./when\";\nimport type { TraceOptions, TraceMode, DecisionWithOptionalTrace, TraceSink, TraceSinkAsync, TraceQueueDropPolicy } from \"./types\";\nimport { TraceDispatcher } from \"./traceDispatcher\";\nimport { emitTraceIfAny } from \"./emitTrace\";\n\nfunction clamp01(n: number) {\n if (!Number.isFinite(n)) return 0;\n if (n < 0) return 0;\n if (n > 1) return 1;\n return n;\n}\n\nfunction safeEffectType(effect: any): string | undefined {\n const t = effect?.type;\n return typeof t === \"string\" ? t : undefined;\n}\n\n// UUID v4 (no deps). Node 16+ usually has crypto.randomUUID.\n// Fallback uses randomBytes.\nfunction makeTraceId(): string {\n const g: any = globalThis as any;\n const cryptoAny: any = g.crypto;\n\n if (cryptoAny?.randomUUID) {\n return cryptoAny.randomUUID();\n }\n\n // Node's crypto module fallback (CJS/ESM safe: dynamic require)\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const nodeCrypto = require(\"node:crypto\");\n if (nodeCrypto?.randomUUID) return nodeCrypto.randomUUID();\n const b: Buffer | undefined = nodeCrypto.randomBytes?.(16);\n if (!b || b.length < 16) {\n throw new Error(\"Failed to generate random bytes for UUID\");\n }\n // RFC4122 v4 bits\n if (b) {\n //@ts-ignore\n b[6] = (b[6] & 0x0f) | 0x40;\n //@ts-ignore\n b[8] = (b[8] & 0x3f) | 0x80;\n }\n const hex = b.toString(\"hex\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n } catch {\n // Last resort (not cryptographically strong, but acceptable for trace correlation)\n return `gp_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`;\n }\n}\n\ntype EngineOpts = {\n getBundle: () => RuntimeBundleV1 | undefined;\n\n // default: true\n validateContext?: boolean;\n\n // policy configurable (PII-safe)\n contextPolicy?: ContextPolicy;\n\n // optional: default trace options for evaluateWithTrace()\n traceDefaults?: TraceOptions;\n\n // Event emitter for trace sink\n traceSink?: TraceSink;\n traceSinkAsync?: TraceSinkAsync;\n traceQueueMax?: number; // default 1000\n traceQueueDropPolicy?: TraceQueueDropPolicy; // \"drop_new\" | \"drop_old\"\n onTraceSinkError?: (err: unknown) => void;\n};\n\ntype EvaluateInput = {\n target: Target;\n context?: Record<string, unknown>;\n};\n\ntype Match = {\n policyKey: string;\n ruleId: string;\n priority: number;\n effect: any;\n};\n\nfunction targetMatch(a: Target, b: Target) {\n return a.service === b.service && a.resource === b.resource && a.action === b.action;\n}\n\nfunction byRuleOrder(a: Match, b: Match) {\n // priority desc, policyKey asc, ruleId asc\n const pr = (Number(b.priority) || 0) - (Number(a.priority) || 0);\n if (pr !== 0) return pr;\n const pk = String(a.policyKey).localeCompare(String(b.policyKey));\n if (pk !== 0) return pk;\n return String(a.ruleId).localeCompare(String(b.ruleId));\n}\n\nfunction throttleStrictness(th: { limit: number; windowSeconds: number }) {\n const limit = Number(th?.limit);\n const windowSeconds = Number(th?.windowSeconds);\n const rate = windowSeconds > 0 ? limit / windowSeconds : Number.POSITIVE_INFINITY; // lower => stricter\n return { rate, limit, windowSeconds };\n}\n\n// Simple in-memory budget: N traces per windowMs (default 60/min)\nfunction makeTraceBudget(maxTraces: number, windowMs: number) {\n let windowStart = Date.now();\n let used = 0;\n\n return {\n allow(): boolean {\n const now = Date.now();\n if (now - windowStart >= windowMs) {\n windowStart = now;\n used = 0;\n }\n if (used >= maxTraces) return false;\n used += 1;\n return true;\n }\n };\n}\n\nexport function createPolicyEngine(opts: EngineOpts): PolicyEngine {\n const budget = makeTraceBudget(\n Number.isFinite(opts.traceDefaults?.budget?.maxTraces) ? (opts.traceDefaults!.budget!.maxTraces as number) : 60,\n Number.isFinite(opts.traceDefaults?.budget?.windowMs) ? (opts.traceDefaults!.budget!.windowMs as number) : 60_000\n );\n\n // Initialize trace dispatcher if async sink provided\n const dispatcher =\n opts.traceSinkAsync\n ? new TraceDispatcher({\n sinkAsync: opts.traceSinkAsync,\n max: Number.isFinite(opts.traceQueueMax) ? (opts.traceQueueMax as number) : 1000,\n dropPolicy: opts.traceQueueDropPolicy ?? \"drop_new\",\n onError: opts.onTraceSinkError\n })\n : undefined;\n\n function coreEvaluate(input: EvaluateInput, wantTrace: boolean) {\n const bundle = opts.getBundle();\n const ctx = input.context ?? {};\n\n if (opts.validateContext !== false) {\n validateContext(ctx, opts.contextPolicy ?? DEFAULT_CONTEXT_POLICY);\n }\n\n const traceBase = wantTrace\n ? {\n traceId: makeTraceId(),\n sampled: \"random\" as const, // overwritten if forced\n evaluatedAt: new Date().toISOString(),\n target: input.target,\n summary: {\n policiesSeen: 0,\n rulesSeen: 0,\n matched: 0,\n considered: { kill_switch: 0, deny: 0, throttle: 0, allow: 0 }\n },\n rules: [] as any[]\n }\n : null;\n\n // deny-by-default if bundle missing/invalid\n if (!bundle || bundle.schemaVersion !== 1) {\n const decision: Decision = { decision: \"deny\", reason: \"default\" };\n if (!wantTrace) return decision;\n\n return {\n ...decision,\n trace: {\n ...traceBase!,\n winner: undefined\n }\n };\n }\n\n const kills: Match[] = [];\n const denies: Match[] = [];\n const throttles: Match[] = [];\n const allows: Match[] = [];\n\n const policies = bundle.policies ?? [];\n if (wantTrace) traceBase!.summary.policiesSeen = policies.length;\n\n for (const p of policies) {\n const policyKey = String((p as any).policyKey ?? \"\");\n const rules = (p as any).rules ?? [];\n\n for (const r of rules) {\n if (wantTrace) traceBase!.summary.rulesSeen += 1;\n\n const ruleId = String(r?.id ?? \"\");\n const priority = Number(r?.priority ?? 0);\n const effectType = safeEffectType(r?.effect);\n\n // disabled\n if (r?.status !== \"active\") {\n if (wantTrace) {\n traceBase!.rules.push({\n policyKey,\n ruleId,\n priority,\n effectType,\n matched: false,\n discardedReason: \"disabled\"\n });\n }\n continue;\n }\n\n // target mismatch\n if (!r?.target || !targetMatch(r.target, input.target)) {\n if (wantTrace) {\n traceBase!.rules.push({\n policyKey,\n ruleId,\n priority,\n effectType,\n matched: false,\n discardedReason: \"target_mismatch\"\n });\n }\n continue;\n }\n\n // when false\n if (r.when && !evalWhen(r.when, ctx)) {\n if (wantTrace) {\n traceBase!.rules.push({\n policyKey,\n ruleId,\n priority,\n effectType,\n matched: false,\n discardedReason: \"when_false\"\n });\n }\n continue;\n }\n\n // invalid effect\n if (!effectType) {\n if (wantTrace) {\n traceBase!.rules.push({\n policyKey,\n ruleId,\n priority,\n effectType: undefined,\n matched: false,\n discardedReason: \"invalid_effect\"\n });\n }\n continue;\n }\n\n // matched\n if (wantTrace) {\n traceBase!.summary.matched += 1;\n traceBase!.rules.push({\n policyKey,\n ruleId,\n priority,\n effectType,\n matched: true\n });\n }\n\n const m: Match = { policyKey, ruleId, priority, effect: r.effect };\n\n if (effectType === \"kill_switch\") {\n kills.push(m);\n if (wantTrace) traceBase!.summary.considered.kill_switch += 1;\n } else if (effectType === \"deny\") {\n denies.push(m);\n if (wantTrace) traceBase!.summary.considered.deny += 1;\n } else if (effectType === \"throttle\") {\n throttles.push(m);\n if (wantTrace) traceBase!.summary.considered.throttle += 1;\n } else if (effectType === \"allow\") {\n allows.push(m);\n if (wantTrace) traceBase!.summary.considered.allow += 1;\n }\n }\n }\n\n // Precedence: kill_switch > deny > throttle(strictest) > allow > deny-by-default\n if (kills.length) {\n const w = kills.sort(byRuleOrder)[0]!;\n const decision: Decision = {\n decision: \"kill_switch\",\n reason: \"rule\",\n policyKey: w.policyKey,\n ruleId: w.ruleId,\n killSwitch: w.effect.killSwitch\n };\n\n if (!wantTrace) return decision;\n return {\n ...decision,\n trace: {\n ...traceBase!,\n winner: { policyKey: w.policyKey, ruleId: w.ruleId, effectType: \"kill_switch\", priority: w.priority }\n }\n };\n }\n\n if (denies.length) {\n const w = denies.sort(byRuleOrder)[0]!;\n const decision: Decision = {\n decision: \"deny\",\n reason: \"rule\",\n policyKey: w.policyKey,\n ruleId: w.ruleId\n };\n\n if (!wantTrace) return decision;\n return {\n ...decision,\n trace: {\n ...traceBase!,\n winner: { policyKey: w.policyKey, ruleId: w.ruleId, effectType: \"deny\", priority: w.priority }\n }\n };\n }\n\n if (throttles.length) {\n const w = throttles\n .sort((a, b) => {\n const A = throttleStrictness(a.effect.throttle);\n const B = throttleStrictness(b.effect.throttle);\n\n // lower rate => stricter\n if (A.rate !== B.rate) return A.rate - B.rate;\n if (A.limit !== B.limit) return A.limit - B.limit;\n if (A.windowSeconds !== B.windowSeconds) return A.windowSeconds - B.windowSeconds;\n return byRuleOrder(a, b);\n })[0]!;\n\n const decision: Decision = {\n decision: \"throttle\",\n reason: \"rule\",\n policyKey: w.policyKey,\n ruleId: w.ruleId,\n throttle: w.effect.throttle\n };\n\n if (!wantTrace) return decision;\n return {\n ...decision,\n trace: {\n ...traceBase!,\n winner: { policyKey: w.policyKey, ruleId: w.ruleId, effectType: \"throttle\", priority: w.priority }\n }\n };\n }\n\n if (allows.length) {\n const w = allows.sort(byRuleOrder)[0]!;\n const decision: Decision = {\n decision: \"allow\",\n reason: \"rule\",\n policyKey: w.policyKey,\n ruleId: w.ruleId\n };\n\n if (!wantTrace) return decision;\n return {\n ...decision,\n trace: {\n ...traceBase!,\n winner: { policyKey: w.policyKey, ruleId: w.ruleId, effectType: \"allow\", priority: w.priority }\n }\n };\n }\n\n const decision: Decision = { decision: \"deny\", reason: \"default\" };\n if (!wantTrace) return decision;\n\n return {\n ...decision,\n trace: {\n ...traceBase!,\n winner: undefined\n }\n };\n }\n\n return {\n evaluate(input: EvaluateInput) {\n return coreEvaluate(input, false) as Decision;\n },\n\n evaluateWithTrace(input: EvaluateInput, options?: TraceOptions): DecisionWithOptionalTrace {\n const merged: TraceOptions = {\n ...(opts.traceDefaults ?? {}),\n ...(options ?? {})\n };\n\n const level = (merged.level ?? \"sampled\") as any;\n const sampling = clamp01(merged.sampling ?? 0.01);\n const force = merged.force === true;\n\n const isOff = level === \"off\";\n const isErrorLevel = level === \"errors\";\n const isFull = level === \"full\";\n const isSampled = level === \"sampled\";\n\n if (isOff) {\n return coreEvaluate(input, false) as any;\n }\n\n // Always compute decision first (no trace)\n const baseDecision: any = coreEvaluate(input, false);\n\n // errors: only trace on deny/kill_switch unless force\n if (isErrorLevel) {\n const isErrDecision = baseDecision.decision === \"deny\" || baseDecision.decision === \"kill_switch\";\n if (!isErrDecision && !force) {\n return baseDecision;\n }\n\n if (!force) {\n const ok = budget.allow();\n if (!ok) return baseDecision;\n }\n\n const out: any = coreEvaluate(input, true);\n if (out?.trace) out.trace.sampled = force ? \"forced\" : \"errors\";\n\n // errors => compact by default\n const { rules: _rules, ...compact } = out.trace ?? {};\n const finalOut = { ...out, trace: compact };\n\n emitTraceIfAny({ level: \"errors\", decision: out, trace: out.trace, sink: opts.traceSink, dispatcher, onSinkError: opts.onTraceSinkError });\n\n return finalOut;\n }\n\n // full: always trace (budget unless forced)\n if (isFull) {\n if (!force) {\n const ok = budget.allow();\n if (!ok) return baseDecision;\n }\n\n const out: any = coreEvaluate(input, true);\n if (out?.trace) out.trace.sampled = force ? \"forced\" : \"random\";\n\n emitTraceIfAny({ level: \"full\", decision: out, trace: out.trace, sink: opts.traceSink, dispatcher, onSinkError: opts.onTraceSinkError });\n\n return out;\n }\n\n // sampled: sampling + budget (compact)\n if (isSampled) {\n const include = force ? true : Math.random() < sampling;\n if (!include) return baseDecision;\n\n if (!force) {\n const ok = budget.allow();\n if (!ok) return baseDecision;\n }\n\n const out: any = coreEvaluate(input, true);\n if (out?.trace) out.trace.sampled = force ? \"forced\" : \"random\";\n\n const { rules: _rules, ...compact } = out.trace ?? {};\n const finalOut = { ...out, trace: compact };\n\n emitTraceIfAny({ level: \"sampled\", decision: out, trace: out.trace, sink: opts.traceSink, dispatcher, onSinkError: opts.onTraceSinkError });\n\n return finalOut;\n }\n\n // fallback: no trace\n return baseDecision;\n },\n flushTraces: async () => {\n if (!dispatcher) return;\n await dispatcher.flush();\n }\n };\n}","export class GovplaneError extends Error {\n constructor(message: string, public readonly code = \"GP_ERROR\", public readonly details?: any) {\n super(message);\n this.name = \"GovplaneError\";\n }\n}\n\nexport class HttpError extends GovplaneError {\n constructor(\n message: string,\n public readonly status: number,\n public readonly headers?: Record<string, string>,\n details?: any\n ) {\n super(message, \"HTTP_ERROR\", details);\n this.name = \"HttpError\";\n }\n}","import type {\n DecisionTraceCompact,\n DecisionTraceFull\n} from \"./types\";\n\ntype FormatOpts = {\n multiline?: boolean; // default: false\n includeDiscarded?: boolean; // only for full traces\n};\n\nexport function formatTrace(\n trace: DecisionTraceCompact | DecisionTraceFull,\n opts: FormatOpts = {}\n): string {\n const lines: string[] = [];\n\n const hdr =\n `[govplane] traceId=${trace.traceId} ` +\n `sampled=${trace.sampled} ` +\n `policies=${trace.summary.policiesSeen} ` +\n `rules=${trace.summary.rulesSeen} ` +\n `matched=${trace.summary.matched}`;\n\n lines.push(hdr);\n\n if (trace.winner) {\n lines.push(\n `winner → policy=${trace.winner.policyKey} ` +\n `rule=${trace.winner.ruleId} ` +\n `effect=${trace.winner.effectType} ` +\n `priority=${trace.winner.priority}`\n );\n } else {\n lines.push(`winner → none (default decision)`);\n }\n\n if (\"rules\" in trace && opts.includeDiscarded) {\n const discarded = trace.rules.filter(r => !r.matched);\n\n if (discarded.length) {\n lines.push(`discarded rules:`);\n\n for (const r of discarded) {\n lines.push(\n `- policy=${r.policyKey} ` +\n `rule=${r.ruleId} ` +\n `effect=${r.effectType ?? \"?\"} ` +\n `reason=${r.discardedReason}`\n );\n }\n }\n }\n\n if (opts.multiline) {\n return lines.join(\"\\n\");\n }\n\n return lines.join(\" | \");\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAAwB;;;ACOjB,IAAM,yBAAwC;AAAA,EACnD,aAAa;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,cAAc;AAAA,EACd,aAAa;AAAA,EACb,oBAAoB;AACtB;AAGA,IAAM,mBAA6B;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAA+D;AAAA,EACnE,cAAc;AAAA,EACd,aAAa;AAAA,EACb,oBAAoB;AACtB;AAEO,SAAS,gBACd,KACA,QACM;AACN,QAAM,UAAU,IAAI,IAAI,OAAO,WAAW;AAC1C,QAAM,eAAe,OAAO,gBAAgB,eAAe;AAC3D,QAAM,cAAc,OAAO,eAAe,eAAe;AACzD,QAAM,qBAAqB,OAAO,sBAAsB,eAAe;AAEvE,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,UAAM,OAAO,OAAO,CAAC;AAErB,QAAI,CAAC,QAAQ,IAAI,IAAI,GAAG;AACtB,YAAM,IAAI,MAAM,4BAA4B,IAAI,EAAE;AAAA,IACpD;AAEA,QAAI,oBAAoB;AACtB,iBAAW,MAAM,kBAAkB;AACjC,YAAI,GAAG,KAAK,CAAC,GAAG;AACd,gBAAM,IAAI,MAAM,8CAA8C,IAAI,EAAE;AAAA,QACtE;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,MAAM,OAAW;AAEnC,UAAM,IAAI,OAAO;AACjB,QAAI,MAAM,aAAa,MAAM,SAAU;AAEvC,QAAI,MAAM,UAAU;AAClB,UAAK,EAAa,SAAS,aAAc,OAAM,IAAI,MAAM,2BAA2B,IAAI,EAAE;AAC1F;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,CAAC,GAAG;AACpB,UAAI,EAAE,SAAS,YAAa,OAAM,IAAI,MAAM,2BAA2B,IAAI,EAAE;AAC7E,iBAAW,MAAM,GAAG;AAClB,YAAI,OAAO,OAAO,SAAU,OAAM,IAAI,MAAM,6BAA6B,IAAI,EAAE;AAC/E,YAAI,GAAG,SAAS,aAAc,OAAM,IAAI,MAAM,+BAA+B,IAAI,EAAE;AAAA,MACrF;AACA;AAAA,IACF;AAEA,UAAM,IAAI,MAAM,4BAA4B,IAAI,EAAE;AAAA,EACpD;AACF;;;ACzFA,SAAS,QAAQ,KAAU,MAAmB;AAE5C,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,MAAI,MAAM;AACV,aAAW,KAAK,OAAO;AACrB,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,UAAM,IAAI,CAAC;AAAA,EACb;AACA,SAAO;AACT;AAEO,SAAS,SAAS,MAAiB,KAAuC;AAC/E,UAAQ,KAAK,IAAI;AAAA,IACf,KAAK;AAAO,aAAO,KAAK,KAAK,MAAM,OAAK,SAAS,GAAG,GAAG,CAAC;AAAA,IACxD,KAAK;AAAM,aAAO,KAAK,KAAK,KAAK,OAAK,SAAS,GAAG,GAAG,CAAC;AAAA,IACtD,KAAK;AAAO,aAAO,CAAC,SAAS,KAAK,KAAK,GAAG;AAAA,IAE1C,KAAK;AAAU,aAAO,QAAQ,EAAE,IAAI,GAAG,KAAK,IAAI,MAAM;AAAA,IAEtD,KAAK,MAAM;AACT,YAAM,IAAI,QAAQ,EAAE,IAAI,GAAG,KAAK,IAAI;AACpC,aAAO,KAAK,OAAO,KAAK,OAAK,MAAM,CAAC;AAAA,IACtC;AAAA,IAEA,KAAK;AAAM,aAAO,QAAQ,EAAE,IAAI,GAAG,KAAK,IAAI,MAAM,KAAK;AAAA,IACvD,KAAK;AAAM,aAAO,QAAQ,EAAE,IAAI,GAAG,KAAK,IAAI,MAAM,KAAK;AAAA,IAEvD,KAAK;AAAM,aAAO,OAAO,QAAQ,EAAE,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,OAAO,KAAK,KAAK;AAAA,IACzE,KAAK;AAAO,aAAO,OAAO,QAAQ,EAAE,IAAI,GAAG,KAAK,IAAI,CAAC,KAAK,OAAO,KAAK,KAAK;AAAA,IAC3E,KAAK;AAAM,aAAO,OAAO,QAAQ,EAAE,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,OAAO,KAAK,KAAK;AAAA,IACzE,KAAK;AAAO,aAAO,OAAO,QAAQ,EAAE,IAAI,GAAG,KAAK,IAAI,CAAC,KAAK,OAAO,KAAK,KAAK;AAAA,IAE3E;AACE,aAAO;AAAA,EACX;AACF;;;AC5BO,IAAM,kBAAN,MAAsB;AAAA,EAM3B,YAA6B,MAAY;AAAZ;AAAA,EAAa;AAAA,EALlC,IAA4B,CAAC;AAAA,EAC7B,WAAW;AAAA,EAEX,eAAkC,CAAC;AAAA,EAI3C,QAAQ,KAAiC;AACvC,QAAI,KAAK,EAAE,UAAU,KAAK,KAAK,KAAK;AAClC,UAAI,KAAK,KAAK,eAAe,YAAY;AACvC,aAAK,EAAE,MAAM;AAAA,MACf,OAAO;AACL;AAAA,MACF;AAAA,IACF;AAEA,SAAK,EAAE,KAAK,GAAG;AACf,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,CAAC,KAAK,YAAY,KAAK,EAAE,WAAW,EAAG;AAE3C,WAAO,IAAI,QAAc,CAAC,YAAY;AACpC,WAAK,aAAa,KAAK,OAAO;AAC9B,WAAK,KAAK;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEQ,OAAa;AACnB,QAAI,KAAK,SAAU;AACnB,QAAI,KAAK,EAAE,WAAW,GAAG;AACvB,WAAK,0BAA0B;AAC/B;AAAA,IACF;AAEA,SAAK,WAAW;AAGhB,mBAAe,MAAM,KAAK,KAAK,MAAM,CAAC;AAAA,EACxC;AAAA,EAEQ,4BAAkC;AACxC,QAAI,KAAK,SAAU;AACnB,QAAI,KAAK,EAAE,WAAW,EAAG;AAEzB,UAAM,UAAU,KAAK;AACrB,SAAK,eAAe,CAAC;AACrB,eAAW,KAAK,QAAS,GAAE;AAAA,EAC7B;AAAA,EAEA,MAAc,QAAuB;AACnC,QAAI;AACF,aAAO,KAAK,EAAE,QAAQ;AACpB,cAAM,MAAM,KAAK,EAAE,MAAM;AACzB,YAAI;AACF,gBAAM,KAAK,KAAK,UAAU,GAAG;AAAA,QAC/B,SAAS,KAAK;AACZ,cAAI,KAAK,KAAK,QAAS,MAAK,KAAK,QAAQ,GAAG;AAAA,QAC9C;AAAA,MACF;AAAA,IACF,UAAE;AACA,WAAK,WAAW;AAEhB,WAAK,0BAA0B;AAE/B,UAAI,KAAK,EAAE,OAAQ,MAAK,KAAK;AAAA,IAC/B;AAAA,EACF;AACF;;;AC5EO,SAAS,uBAAuB,OAId;AACvB,QAAM,EAAE,UAAU,OAAO,MAAM,IAAI;AAEnC,QAAM,MAA4B;AAAA,IAChC,GAAG;AAAA,IACH,IAAI,MAAM;AAAA,IACV,SAAS,MAAM;AAAA,IACf,SAAS,MAAM;AAAA,IACf;AAAA,IACA,QAAQ,MAAM;AAAA,IACd,UAAU,SAAS;AAAA,IACnB,QAAQ,SAAS;AAAA,IACjB,QAAQ,MAAM;AAAA,IACd,SAAS,MAAM;AAAA,EACjB;AAEA,MAAI,UAAU,UAAU,WAAW,OAAO;AACxC,QAAI,QAAQ,MAAM,MAAM,IAAI,QAAM;AAAA,MAChC,WAAW,EAAE;AAAA,MACb,QAAQ,EAAE;AAAA,MACV,UAAU,EAAE;AAAA,MACZ,YAAY,EAAE;AAAA,MACd,SAAS,EAAE;AAAA,MACX,iBAAiB,EAAE;AAAA,IACrB,EAAE;AAAA,EACJ;AAEA,SAAO;AACT;;;ACxBO,SAAS,eAAe,OAStB;AACP,QAAM,EAAE,OAAO,UAAU,MAAM,IAAI;AACnC,MAAI,CAAC,MAAO;AAEZ,MAAI;AACJ,MAAI;AACF,UAAM,uBAAuB,EAAE,OAAO,UAAU,MAAM,CAAC;AAAA,EACzD,SAAS,KAAK;AACZ,UAAM,cAAc,GAAG;AACvB;AAAA,EACF;AAGA,MAAI,MAAM,MAAM;AACd,QAAI;AACF,YAAM,KAAK,GAAG;AAAA,IAChB,SAAS,KAAK;AACZ,YAAM,cAAc,GAAG;AAAA,IACzB;AAAA,EACF;AAGA,MAAI,MAAM,YAAY;AACpB,UAAM,WAAW,QAAQ,GAAG;AAAA,EAC9B;AACF;;;ACrCA,SAAS,QAAQ,GAAW;AAC1B,MAAI,CAAC,OAAO,SAAS,CAAC,EAAG,QAAO;AAChC,MAAI,IAAI,EAAG,QAAO;AAClB,MAAI,IAAI,EAAG,QAAO;AAClB,SAAO;AACT;AAEA,SAAS,eAAe,QAAiC;AACvD,QAAM,IAAI,QAAQ;AAClB,SAAO,OAAO,MAAM,WAAW,IAAI;AACrC;AAIA,SAAS,cAAsB;AAC7B,QAAM,IAAS;AACf,QAAM,YAAiB,EAAE;AAEzB,MAAI,WAAW,YAAY;AACzB,WAAO,UAAU,WAAW;AAAA,EAC9B;AAGA,MAAI;AAEF,UAAM,aAAa,QAAQ,QAAa;AACxC,QAAI,YAAY,WAAY,QAAO,WAAW,WAAW;AACzD,UAAM,IAAwB,WAAW,cAAc,EAAE;AACzD,QAAI,CAAC,KAAK,EAAE,SAAS,IAAI;AACvB,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAEA,QAAI,GAAG;AAEL,QAAE,CAAC,IAAK,EAAE,CAAC,IAAI,KAAQ;AAEvB,QAAE,CAAC,IAAK,EAAE,CAAC,IAAI,KAAQ;AAAA,IACzB;AACA,UAAM,MAAM,EAAE,SAAS,KAAK;AAC5B,WAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC;AAAA,EAC1G,QAAQ;AAEN,WAAO,MAAM,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAAA,EAC7E;AACF;AAkCA,SAAS,YAAY,GAAW,GAAW;AACzC,SAAO,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE;AAChF;AAEA,SAAS,YAAY,GAAU,GAAU;AAEvC,QAAM,MAAM,OAAO,EAAE,QAAQ,KAAK,MAAM,OAAO,EAAE,QAAQ,KAAK;AAC9D,MAAI,OAAO,EAAG,QAAO;AACrB,QAAM,KAAK,OAAO,EAAE,SAAS,EAAE,cAAc,OAAO,EAAE,SAAS,CAAC;AAChE,MAAI,OAAO,EAAG,QAAO;AACrB,SAAO,OAAO,EAAE,MAAM,EAAE,cAAc,OAAO,EAAE,MAAM,CAAC;AACxD;AAEA,SAAS,mBAAmB,IAA8C;AACxE,QAAM,QAAQ,OAAO,IAAI,KAAK;AAC9B,QAAM,gBAAgB,OAAO,IAAI,aAAa;AAC9C,QAAM,OAAO,gBAAgB,IAAI,QAAQ,gBAAgB,OAAO;AAChE,SAAO,EAAE,MAAM,OAAO,cAAc;AACtC;AAGA,SAAS,gBAAgB,WAAmB,UAAkB;AAC5D,MAAI,cAAc,KAAK,IAAI;AAC3B,MAAI,OAAO;AAEX,SAAO;AAAA,IACL,QAAiB;AACf,YAAM,MAAM,KAAK,IAAI;AACrB,UAAI,MAAM,eAAe,UAAU;AACjC,sBAAc;AACd,eAAO;AAAA,MACT;AACA,UAAI,QAAQ,UAAW,QAAO;AAC9B,cAAQ;AACR,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,MAAgC;AACjE,QAAM,SAAS;AAAA,IACb,OAAO,SAAS,KAAK,eAAe,QAAQ,SAAS,IAAK,KAAK,cAAe,OAAQ,YAAuB;AAAA,IAC7G,OAAO,SAAS,KAAK,eAAe,QAAQ,QAAQ,IAAK,KAAK,cAAe,OAAQ,WAAsB;AAAA,EAC7G;AAGA,QAAM,aACN,KAAK,iBACD,IAAI,gBAAgB;AAAA,IAClB,WAAW,KAAK;AAAA,IAChB,KAAK,OAAO,SAAS,KAAK,aAAa,IAAK,KAAK,gBAA2B;AAAA,IAC5E,YAAY,KAAK,wBAAwB;AAAA,IACzC,SAAS,KAAK;AAAA,EAChB,CAAC,IACD;AAEJ,WAAS,aAAa,OAAsB,WAAoB;AAC9D,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM,MAAM,MAAM,WAAW,CAAC;AAE9B,QAAI,KAAK,oBAAoB,OAAO;AAClC,sBAAgB,KAAK,KAAK,iBAAiB,sBAAsB;AAAA,IACnE;AAEA,UAAM,YAAY,YACd;AAAA,MACE,SAAS,YAAY;AAAA,MACrB,SAAS;AAAA;AAAA,MACT,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC,QAAQ,MAAM;AAAA,MACd,SAAS;AAAA,QACP,cAAc;AAAA,QACd,WAAW;AAAA,QACX,SAAS;AAAA,QACT,YAAY,EAAE,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,EAAE;AAAA,MAC/D;AAAA,MACA,OAAO,CAAC;AAAA,IACV,IACA;AAGJ,QAAI,CAAC,UAAU,OAAO,kBAAkB,GAAG;AACzC,YAAMA,YAAqB,EAAE,UAAU,QAAQ,QAAQ,UAAU;AACjE,UAAI,CAAC,UAAW,QAAOA;AAEvB,aAAO;AAAA,QACL,GAAGA;AAAA,QACH,OAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,UAAM,QAAiB,CAAC;AACxB,UAAM,SAAkB,CAAC;AACzB,UAAM,YAAqB,CAAC;AAC5B,UAAM,SAAkB,CAAC;AAEzB,UAAM,WAAW,OAAO,YAAY,CAAC;AACrC,QAAI,UAAW,WAAW,QAAQ,eAAe,SAAS;AAE1D,eAAW,KAAK,UAAU;AACxB,YAAM,YAAY,OAAQ,EAAU,aAAa,EAAE;AACnD,YAAM,QAAS,EAAU,SAAS,CAAC;AAEnC,iBAAW,KAAK,OAAO;AACrB,YAAI,UAAW,WAAW,QAAQ,aAAa;AAE/C,cAAM,SAAS,OAAO,GAAG,MAAM,EAAE;AACjC,cAAM,WAAW,OAAO,GAAG,YAAY,CAAC;AACxC,cAAM,aAAa,eAAe,GAAG,MAAM;AAG3C,YAAI,GAAG,WAAW,UAAU;AAC1B,cAAI,WAAW;AACb,sBAAW,MAAM,KAAK;AAAA,cACpB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,SAAS;AAAA,cACT,iBAAiB;AAAA,YACnB,CAAC;AAAA,UACH;AACA;AAAA,QACF;AAGA,YAAI,CAAC,GAAG,UAAU,CAAC,YAAY,EAAE,QAAQ,MAAM,MAAM,GAAG;AACtD,cAAI,WAAW;AACb,sBAAW,MAAM,KAAK;AAAA,cACpB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,SAAS;AAAA,cACT,iBAAiB;AAAA,YACnB,CAAC;AAAA,UACH;AACA;AAAA,QACF;AAGA,YAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG;AACpC,cAAI,WAAW;AACb,sBAAW,MAAM,KAAK;AAAA,cACpB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,SAAS;AAAA,cACT,iBAAiB;AAAA,YACnB,CAAC;AAAA,UACH;AACA;AAAA,QACF;AAGA,YAAI,CAAC,YAAY;AACf,cAAI,WAAW;AACb,sBAAW,MAAM,KAAK;AAAA,cACpB;AAAA,cACA;AAAA,cACA;AAAA,cACA,YAAY;AAAA,cACZ,SAAS;AAAA,cACT,iBAAiB;AAAA,YACnB,CAAC;AAAA,UACH;AACA;AAAA,QACF;AAGA,YAAI,WAAW;AACb,oBAAW,QAAQ,WAAW;AAC9B,oBAAW,MAAM,KAAK;AAAA,YACpB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAEA,cAAM,IAAW,EAAE,WAAW,QAAQ,UAAU,QAAQ,EAAE,OAAO;AAEjE,YAAI,eAAe,eAAe;AAChC,gBAAM,KAAK,CAAC;AACZ,cAAI,UAAW,WAAW,QAAQ,WAAW,eAAe;AAAA,QAC9D,WAAW,eAAe,QAAQ;AAChC,iBAAO,KAAK,CAAC;AACb,cAAI,UAAW,WAAW,QAAQ,WAAW,QAAQ;AAAA,QACvD,WAAW,eAAe,YAAY;AACpC,oBAAU,KAAK,CAAC;AAChB,cAAI,UAAW,WAAW,QAAQ,WAAW,YAAY;AAAA,QAC3D,WAAW,eAAe,SAAS;AACjC,iBAAO,KAAK,CAAC;AACb,cAAI,UAAW,WAAW,QAAQ,WAAW,SAAS;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AAGA,QAAI,MAAM,QAAQ;AAChB,YAAM,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;AACnC,YAAMA,YAAqB;AAAA,QACzB,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,WAAW,EAAE;AAAA,QACb,QAAQ,EAAE;AAAA,QACV,YAAY,EAAE,OAAO;AAAA,MACvB;AAEA,UAAI,CAAC,UAAW,QAAOA;AACvB,aAAO;AAAA,QACL,GAAGA;AAAA,QACH,OAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ,EAAE,WAAW,EAAE,WAAW,QAAQ,EAAE,QAAQ,YAAY,eAAe,UAAU,EAAE,SAAS;AAAA,QACtG;AAAA,MACF;AAAA,IACF;AAEA,QAAI,OAAO,QAAQ;AACjB,YAAM,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;AACpC,YAAMA,YAAqB;AAAA,QACzB,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,WAAW,EAAE;AAAA,QACb,QAAQ,EAAE;AAAA,MACZ;AAEA,UAAI,CAAC,UAAW,QAAOA;AACvB,aAAO;AAAA,QACL,GAAGA;AAAA,QACH,OAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ,EAAE,WAAW,EAAE,WAAW,QAAQ,EAAE,QAAQ,YAAY,QAAQ,UAAU,EAAE,SAAS;AAAA,QAC/F;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU,QAAQ;AACpB,YAAM,IAAI,UACP,KAAK,CAAC,GAAG,MAAM;AACd,cAAM,IAAI,mBAAmB,EAAE,OAAO,QAAQ;AAC9C,cAAM,IAAI,mBAAmB,EAAE,OAAO,QAAQ;AAG9C,YAAI,EAAE,SAAS,EAAE,KAAM,QAAO,EAAE,OAAO,EAAE;AACzC,YAAI,EAAE,UAAU,EAAE,MAAO,QAAO,EAAE,QAAQ,EAAE;AAC5C,YAAI,EAAE,kBAAkB,EAAE,cAAe,QAAO,EAAE,gBAAgB,EAAE;AACpE,eAAO,YAAY,GAAG,CAAC;AAAA,MACzB,CAAC,EAAE,CAAC;AAEN,YAAMA,YAAqB;AAAA,QACzB,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,WAAW,EAAE;AAAA,QACb,QAAQ,EAAE;AAAA,QACV,UAAU,EAAE,OAAO;AAAA,MACrB;AAEA,UAAI,CAAC,UAAW,QAAOA;AACvB,aAAO;AAAA,QACL,GAAGA;AAAA,QACH,OAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ,EAAE,WAAW,EAAE,WAAW,QAAQ,EAAE,QAAQ,YAAY,YAAY,UAAU,EAAE,SAAS;AAAA,QACnG;AAAA,MACF;AAAA,IACF;AAEA,QAAI,OAAO,QAAQ;AACjB,YAAM,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;AACpC,YAAMA,YAAqB;AAAA,QACzB,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,WAAW,EAAE;AAAA,QACb,QAAQ,EAAE;AAAA,MACZ;AAEA,UAAI,CAAC,UAAW,QAAOA;AACvB,aAAO;AAAA,QACL,GAAGA;AAAA,QACH,OAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ,EAAE,WAAW,EAAE,WAAW,QAAQ,EAAE,QAAQ,YAAY,SAAS,UAAU,EAAE,SAAS;AAAA,QAChG;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAqB,EAAE,UAAU,QAAQ,QAAQ,UAAU;AACjE,QAAI,CAAC,UAAW,QAAO;AAEvB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,OAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAsB;AAC7B,aAAO,aAAa,OAAO,KAAK;AAAA,IAClC;AAAA,IAEA,kBAAkB,OAAsB,SAAmD;AACvF,YAAM,SAAuB;AAAA,QAC3B,GAAI,KAAK,iBAAiB,CAAC;AAAA,QAC3B,GAAI,WAAW,CAAC;AAAA,MAClB;AAEA,YAAM,QAAS,OAAO,SAAS;AAC/B,YAAM,WAAW,QAAQ,OAAO,YAAY,IAAI;AAChD,YAAM,QAAQ,OAAO,UAAU;AAE/B,YAAM,QAAQ,UAAU;AACxB,YAAM,eAAe,UAAU;AAC/B,YAAM,SAAS,UAAU;AACzB,YAAM,YAAY,UAAU;AAE5B,UAAI,OAAO;AACT,eAAO,aAAa,OAAO,KAAK;AAAA,MAClC;AAGA,YAAM,eAAoB,aAAa,OAAO,KAAK;AAGnD,UAAI,cAAc;AAChB,cAAM,gBAAgB,aAAa,aAAa,UAAU,aAAa,aAAa;AACpF,YAAI,CAAC,iBAAiB,CAAC,OAAO;AAC5B,iBAAO;AAAA,QACT;AAEA,YAAI,CAAC,OAAO;AACV,gBAAM,KAAK,OAAO,MAAM;AACxB,cAAI,CAAC,GAAI,QAAO;AAAA,QAClB;AAEA,cAAM,MAAW,aAAa,OAAO,IAAI;AACzC,YAAI,KAAK,MAAO,KAAI,MAAM,UAAU,QAAQ,WAAW;AAGvD,cAAM,EAAE,OAAO,QAAQ,GAAG,QAAQ,IAAI,IAAI,SAAS,CAAC;AACpD,cAAM,WAAW,EAAE,GAAG,KAAK,OAAO,QAAQ;AAE1C,uBAAe,EAAE,OAAO,UAAU,UAAU,KAAK,OAAO,IAAI,OAAO,MAAM,KAAK,WAAW,YAAY,aAAa,KAAK,iBAAiB,CAAC;AAEzI,eAAO;AAAA,MACT;AAGA,UAAI,QAAQ;AACV,YAAI,CAAC,OAAO;AACV,gBAAM,KAAK,OAAO,MAAM;AACxB,cAAI,CAAC,GAAI,QAAO;AAAA,QAClB;AAEA,cAAM,MAAW,aAAa,OAAO,IAAI;AACzC,YAAI,KAAK,MAAO,KAAI,MAAM,UAAU,QAAQ,WAAW;AAEvD,uBAAe,EAAE,OAAO,QAAQ,UAAU,KAAK,OAAO,IAAI,OAAO,MAAM,KAAK,WAAW,YAAY,aAAa,KAAK,iBAAiB,CAAC;AAEvI,eAAO;AAAA,MACT;AAGA,UAAI,WAAW;AACb,cAAM,UAAU,QAAQ,OAAO,KAAK,OAAO,IAAI;AAC/C,YAAI,CAAC,QAAS,QAAO;AAErB,YAAI,CAAC,OAAO;AACV,gBAAM,KAAK,OAAO,MAAM;AACxB,cAAI,CAAC,GAAI,QAAO;AAAA,QAClB;AAEA,cAAM,MAAW,aAAa,OAAO,IAAI;AACzC,YAAI,KAAK,MAAO,KAAI,MAAM,UAAU,QAAQ,WAAW;AAEvD,cAAM,EAAE,OAAO,QAAQ,GAAG,QAAQ,IAAI,IAAI,SAAS,CAAC;AACpD,cAAM,WAAW,EAAE,GAAG,KAAK,OAAO,QAAQ;AAE1C,uBAAe,EAAE,OAAO,WAAW,UAAU,KAAK,OAAO,IAAI,OAAO,MAAM,KAAK,WAAW,YAAY,aAAa,KAAK,iBAAiB,CAAC;AAE1I,eAAO;AAAA,MACT;AAGA,aAAO;AAAA,IACT;AAAA,IACA,aAAa,YAAY;AACvB,UAAI,CAAC,WAAY;AACjB,YAAM,WAAW,MAAM;AAAA,IACzB;AAAA,EACJ;AACF;;;ANpeA,qBAAgC;AA4HzB,IAAM,gBAAN,MAA+C;AAAA,EACnC;AAAA,EAET,QAA+B,CAAC;AAAA,EAChC,QAA+B;AAAA,EAC/B,YAAY;AAAA,EACZ,iBAAiB;AAAA,EAEjB,kBAA0D;AAAA,EAC1D,aAAa;AAAA;AAAA,EAGb,sBAAsB;AAAA,EACtB,YAAoD;AAAA,EACpD,gBAA+B;AAAA,EAE/B,kBAAgE,CAAC;AAAA,EACjE,kBAAqD,CAAC;AAAA;AAAA,EAG7C;AAAA;AAAA,EAGT,oBAA2C;AAAA,EAC3C,0BAAyC;AAAA,EACzC,yBAAyB;AAAA,EACzB;AAAA,EAER,YAAY,QAA6B;AACvC,SAAK,MAAM;AAAA,MACT,GAAG;AAAA,MACH,QAAQ,OAAO,UAAU;AAAA,MACzB,aAAa,OAAO,eAAe;AAAA,MACnC,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,WAAW,OAAO,aAAa;AAAA,MAE/B,eAAe,OAAO,iBAAiB;AAAA,MACvC,cAAc,OAAO,gBAAgB;AAAA,MACrC,eAAe,OAAO,iBAAiB;AAAA,MACvC,sBAAsB,OAAO,wBAAwB;AAAA,MAErD,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,oBAAoB,OAAO,sBAAsB;AAAA,MACjD,gBAAgB,OAAO,kBAAkB;AAAA,IAE3C;AAGA,SAAK,SAAS,mBAAmB;AAAA,MAC/B,WAAW,MAAM,KAAK,MAAM;AAAA,MAE5B,iBAAiB,OAAO,QAAQ,oBAAoB;AAAA,MACpD,eAAe,OAAO,QAAQ;AAAA,MAE9B,eAAe,OAAO,OAAO;AAAA,MAC7B,WAAW,OAAO,OAAO;AAAA,MACzB,gBAAgB,OAAO,OAAO;AAAA,MAC9B,eAAe,OAAO,OAAO;AAAA,MAC7B,sBAAsB,OAAO,OAAO;AAAA,MACpC,kBAAkB,OAAO,OAAO;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAS,IAAuE;AAC9E,UAAM,UAAU,CAAC,QAAgC;AAC/C,UAAI,IAAI,QAAS,IAAG,GAAU;AAAA,IAChC;AACA,SAAK,gBAAgB,KAAK,OAAO;AACjC,WAAO,MAAM;AACX,WAAK,kBAAkB,KAAK,gBAAgB,OAAO,CAAC,MAAM,MAAM,OAAO;AAAA,IACzE;AAAA,EACF;AAAA;AAAA,EAGA,SAAS,IAAgC;AACvC,SAAK,gBAAgB,KAAK,EAAE;AAC5B,OAAG,KAAK,UAAU,CAAC;AACnB,WAAO,MAAM;AACX,WAAK,kBAAkB,KAAK,gBAAgB,OAAO,CAAC,MAAM,MAAM,EAAE;AAAA,IACpE;AAAA,EACF;AAAA;AAAA,EAGA,SAAS,OAAwE;AAC/E,WAAO,KAAK,OAAO,SAAS,KAAK;AAAA,EACnC;AAAA;AAAA,EAGA,kBACE,OACA,SAC2B;AAC3B,WAAO,KAAK,OAAO,kBAAkB,OAAO,OAAO;AAAA,EACrD;AAAA;AAAA,EAGA,cAA6B;AAC3B,WAAO,KAAK,OAAO,YAAY;AAAA,EACjC;AAAA,EAEA,YAAmC;AACjC,WAAO,EAAE,GAAG,KAAK,MAAM;AAAA,EACzB;AAAA,EAEA,YAA2B;AAEzB,UAAM,IAAS,KAAK,MAAM;AAC1B,UAAM,QAAQ,CAAC,EAAE,KAAK,OAAO,MAAM,YAAY,EAAE,kBAAkB,KAAK,MAAM,QAAQ,EAAE,QAAQ;AAChG,QAAI,CAAC,KAAK,kBAAkB,CAAC,MAAO,QAAO,EAAE,OAAO,aAAa;AAEjE,QAAI,KAAK,uBAAuB,KAAK,IAAI,sBAAsB;AAC7D,aAAO;AAAA,QACL,OAAO;AAAA,QACP,qBAAqB,KAAK;AAAA,QAC1B,WAAW,KAAK,aAAa,EAAE,SAAS,WAAW,KAAI,oBAAI,KAAK,GAAE,YAAY,EAAE;AAAA,QAChF,aAAa,KAAK,gBAAgB,IAAI,KAAK,KAAK,aAAa,EAAE,YAAY,IAAI;AAAA,MACjF;AAAA,IACF;AACA,WAAO,EAAE,OAAO,KAAK;AAAA,EACvB;AAAA,EAEA,QAAQ;AACN,QAAI,KAAK,UAAW;AACpB,SAAK,YAAY;AAGjB,SAAK,qBAAqB;AAC1B,SAAK,wBAAwB;AAC7B,SAAK,sBAAsB;AAG3B,SAAK,aAAa,CAAC;AAAA,EACrB;AAAA,EAEA,MAAM,UAAU,MAA+D;AAE7E,SAAK,qBAAqB;AAC1B,SAAK,wBAAwB;AAC7B,SAAK,sBAAsB;AAE3B,UAAM,YAAY,MAAM,aAAa;AACrC,UAAM,QAAQ,KAAK,IAAI,IAAI;AAE3B,QAAI,MAAM,OAAO;AACf,YAAM,KAAK,WAAW,EAAE,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM,MAAM;AAAA,IAC3D,OAAO;AACL,YAAM,KAAK,WAAW,EAAE,MAAM,MAAM,MAAM;AAAA,IAC5C;AAEA,WAAO,KAAK,IAAI,IAAI,OAAO;AACzB,YAAM,IAAS,KAAK,MAAM;AAC1B,YAAM,QAAQ,CAAC,EAAE,KAAK,OAAO,MAAM,YAAY,EAAE,kBAAkB,KAAK,MAAM,QAAQ,EAAE,QAAQ;AAChG,UAAI,OAAO;AACT,aAAK,iBAAiB;AACtB;AAAA,MACF;AACA,YAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAAA,IAC7C;AAEA,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AAAA,EAEA,OAAO;AACL,SAAK,YAAY;AACjB,QAAI,KAAK,MAAO,cAAa,KAAK,KAAK;AACvC,SAAK,QAAQ;AAEb,QAAI,KAAK,kBAAmB,eAAc,KAAK,iBAAiB;AAChE,SAAK,oBAAoB;AACzB,SAAK,wBAAwB;AAAA,EAC/B;AAAA,EAEA,MAAM,WAAW,MAA6D;AAC5E,QAAI,MAAM,OAAO;AACf,WAAK,aAAa,KAAK,IAAI,IAAI,KAAK,IAAI;AACxC,UAAI,KAAK,UAAW,MAAK,aAAa,CAAC;AAAA,IACzC;AACA,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEQ,mBAAmB,MAAqB;AAC9C,UAAM,OAAO,KAAK,UAAU;AAE5B,UAAM,MAAM,CAAC,MAAqB;AAChC,UAAI,EAAE,UAAU,aAAc,QAAO;AACrC,UAAI,EAAE,UAAU,KAAM,QAAO;AAC7B,aAAO,YAAY,EAAE,mBAAmB,IAAI,EAAE,UAAU,OAAO;AAAA,IACjE;AAEA,QAAI,IAAI,IAAI,MAAM,IAAI,IAAI,GAAG;AAC3B,iBAAW,KAAK,KAAK,gBAAiB,GAAE,IAAI;AAAA,IAC9C;AAAA,EACF;AAAA,EAGA,MAAc,UAA2C;AACvD,QAAI,KAAK,gBAAiB,QAAO,KAAK;AAEtC,UAAM,aAAa,KAAK,UAAU;AAElC,SAAK,mBAAmB,YAAY;AAClC,UAAI;AACF,cAAM,OAAO,MAAM,KAAK,WAAW;AACnC,YAAI,CAAC,MAAM;AACT,eAAK,YAAY;AACjB,eAAK,mBAAmB,UAAU;AAClC,iBAAO,EAAE,SAAS,OAAO,MAAM,KAAK,MAAM,KAAK;AAAA,QACjD;AAEA,cAAM,WAAW,KAAK,MAAM,MAAM;AAClC,YAAI,YAAY,KAAK,SAAS,UAAU;AACtC,eAAK,MAAM,OAAO;AAClB,eAAK,YAAY;AACjB,eAAK,mBAAmB,UAAU;AAClC,iBAAO,EAAE,SAAS,OAAO,MAAM,KAAK;AAAA,QACtC;AAEA,cAAM,MAAM,MAAM,KAAK,UAAU;AACjC,aAAK,YAAY;AACjB,aAAK,mBAAmB,UAAU;AAClC,eAAO,IAAI,UAAU,MAAM,EAAE,SAAS,OAAO,MAAM,IAAI,KAAK;AAAA,MAC9D,SAAS,KAAU;AACjB,aAAK,YAAY,GAAG;AACpB,aAAK,mBAAmB,UAAU;AAClC,cAAM;AAAA,MACR,UAAE;AACA,aAAK,kBAAkB;AAAA,MACzB;AAAA,IACF,GAAG;AAEH,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,aAAa,SAAiB;AACpC,QAAI,CAAC,KAAK,UAAW;AACrB,QAAI,KAAK,MAAO,cAAa,KAAK,KAAK;AAEvC,SAAK,QAAQ,WAAW,YAAY;AAClC,YAAM,aAAa,KAAK,UAAU;AAElC,UAAI;AAEF,aAAK,qBAAqB;AAG1B,YAAI,KAAK,iBAAiB,KAAK,IAAI,IAAI,KAAK,eAAe;AACzD,eAAK,aAAa,KAAK,IAAI,GAAG,KAAK,gBAAgB,KAAK,IAAI,CAAC,CAAC;AAC9D;AAAA,QACF;AAEA,cAAM,MAAM,MAAM,KAAK,QAAQ;AAC/B,YAAI,IAAI,SAAS;AACf,qBAAW,KAAK,KAAK,gBAAiB,GAAE,GAAG;AAAA,QAC7C;AAAA,MACF,QAAQ;AAAA,MAER,UAAE;AACA,aAAK,mBAAmB,UAAU;AAElC,cAAM,OACJ,KAAK,iBAAiB,KAAK,IAAI,IAAI,KAAK,gBACpC,KAAK,IAAI,GAAG,KAAK,gBAAgB,KAAK,IAAI,CAAC,IAC3C,KAAK,gBAAgB;AAE3B,aAAK,aAAa,IAAI;AAAA,MACxB;AAAA,IACF,GAAG,OAAO;AAAA,EACZ;AAAA,EAEQ,kBAAkB;AACxB,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,MAAM,KAAK,WAAY,QAAO,KAAK,IAAI;AAC3C,WAAO,KAAK,IAAI;AAAA,EAClB;AAAA,EAEQ,cAAc;AACpB,SAAK,sBAAsB;AAC3B,SAAK,YAAY;AACjB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEQ,YAAY,KAAU;AAC5B,SAAK,uBAAuB;AAC5B,SAAK,YAAY,EAAE,SAAS,OAAO,KAAK,WAAW,OAAO,SAAS,GAAG,KAAI,oBAAI,KAAK,GAAE,YAAY,EAAE;AAEnG,UAAM,QAAQ,KAAK,sBAAsB,KAAK,mBAAmB;AACjE,SAAK,gBAAgB,KAAK,IAAI,IAAI;AAAA,EACpC;AAAA,EAEQ,sBAAsB,UAAkB;AAC9C,UAAM,OAAO,KAAK,IAAI;AACtB,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,MAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,WAAW,CAAC,CAAC;AACxD,UAAM,SAAS,KAAK,IAAI,KAAK,GAAG;AAEhC,UAAM,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,aAAa,CAAC;AAC9D,UAAM,QAAQ,SAAS;AACvB,UAAM,MAAM,KAAK,IAAI,GAAG,SAAS,KAAK;AACtC,UAAM,OAAO,SAAS;AAEtB,UAAM,IAAI,KAAK,OAAO;AACtB,WAAO,KAAK,MAAM,MAAM,KAAK,OAAO,IAAI;AAAA,EAC1C;AAAA,EAEQ,YAAoB;AAC1B,UAAM,IAAI,IAAI,IAAI,KAAK,IAAI,OAAO;AAClC,MAAE,WAAW;AACb,MAAE,aAAa,IAAI,aAAa,KAAK,IAAI,SAAS;AAClD,MAAE,aAAa,IAAI,OAAO,KAAK,IAAI,GAAG;AACtC,WAAO,EAAE,SAAS;AAAA,EACpB;AAAA,EAEQ,cAAc,OAAgC;AACpD,WAAO;AAAA,MACL,eAAe,UAAU,KAAK,IAAI,UAAU;AAAA,MAC5C,cAAc,KAAK,IAAI,aAAa;AAAA,MACpC,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAEA,MAAc,aAA8C;AAC1D,UAAM,MAAM,KAAK,UAAU;AAE3B,UAAM,EAAE,YAAY,SAAS,KAAK,IAAI,UAAM,uBAAQ,KAAK;AAAA,MACvD,QAAQ;AAAA,MACR,SAAS,KAAK,cAAc;AAAA,MAC5B,aAAa,KAAK,IAAI;AAAA,MACtB,gBAAgB,KAAK,IAAI;AAAA,IAC3B,CAAC;AAED,UAAM,KAAK,KAAK,EAAE,MAAM,MAAM,MAAM;AAEpC,QAAI,eAAe,OAAO,eAAe,IAAK,OAAM,IAAI,MAAM,iBAAiB,UAAU,GAAG;AAC5F,QAAI,cAAc,IAAK,OAAM,IAAI,MAAM,yBAAyB,UAAU,GAAG;AAC7E,QAAI,eAAe,OAAO,eAAe,IAAK,QAAO,KAAK,MAAM;AAEhE,UAAM,OAAQ,QAAQ,MAAM,KAA4B;AACxD,QAAI,CAAC,KAAM,QAAO,KAAK,MAAM;AAE7B,UAAM,mBAAmB,QAAQ,qBAAqB;AACtD,UAAM,YAAY,QAAQ,iBAAiB;AAE3C,WAAO;AAAA,MACL;AAAA,MACA,eAAe,mBAAmB,OAAO,gBAAgB,IAAI;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,YAA6C;AACzD,UAAM,MAAM,KAAK,UAAU;AAC3B,UAAM,cAAc,KAAK,MAAM,MAAM;AAErC,UAAM,EAAE,YAAY,SAAS,KAAK,IAAI,UAAM,uBAAQ,KAAK;AAAA,MACvD,QAAQ;AAAA,MACR,SAAS,KAAK,cAAc,cAAc,EAAE,iBAAiB,YAAY,IAAI,MAAS;AAAA,MACtF,aAAa,KAAK,IAAI;AAAA,MACtB,gBAAgB,KAAK,IAAI;AAAA,IAC3B,CAAC;AAED,UAAM,MAAM,MAAM,KAAK,KAAK;AAE5B,QAAI,eAAe,KAAK;AACtB,YAAMC,QAAQ,QAAQ,MAAM,KAA4B,eAAe;AACvE,YAAMC,oBAAmB,QAAQ,qBAAqB;AACtD,YAAMC,aAAY,QAAQ,iBAAiB;AAE3C,YAAMC,QAA+BH,QACjC,EAAE,MAAAA,OAAM,eAAeC,oBAAmB,OAAOA,iBAAgB,IAAI,QAAW,WAAAC,WAAU,IAC1F,KAAK,MAAM;AAEf,UAAIC,MAAM,MAAK,MAAM,OAAOA;AAC5B,aAAO,EAAE,SAAS,OAAO,MAAAA,MAAK;AAAA,IAChC;AAEA,QAAI,eAAe,OAAO,eAAe,IAAK,OAAM,IAAI,MAAM,iBAAiB,UAAU,GAAG;AAC5F,QAAI,cAAc,IAAK,OAAM,IAAI,MAAM,uBAAuB,UAAU,MAAM,IAAI,MAAM,GAAG,GAAG,CAAC,EAAE;AAEjG,UAAM,OAAQ,QAAQ,MAAM,KAA4B;AACxD,UAAM,mBAAmB,QAAQ,qBAAqB;AACtD,UAAM,YAAY,QAAQ,iBAAiB;AAE3C,UAAM,OAAmB;AAAA,MACvB,MAAM,SAAS,eAAe;AAAA,MAC9B,eAAe,mBAAmB,OAAO,gBAAgB,IAAI;AAAA,MAC7D;AAAA,IACF;AAEA,UAAM,SAAS,KAAK,MAAM,GAAG;AAG7B,UAAM,aACJ,QAAQ,kBAAkB,IACtB,SACA,QAAQ,MAAM,kBAAkB,IAChC,OAAO,OACP,QAAQ,MAAM,MAAM,kBAAkB,IACtC,OAAO,KAAK,OACZ,QAAQ,MAAM,kBAAkB,IAChC,OAAO,OACP;AAEN,SAAK,QAAQ,EAAE,MAAM,QAAQ,WAAsB;AAEnD,UAAM,KAAU;AAChB,QAAI,MAAM,OAAO,OAAO,YAAY,GAAG,kBAAkB,KAAK,MAAM,QAAQ,GAAG,QAAQ,GAAG;AACxF,WAAK,iBAAiB;AAAA,IACxB;AAEA,WAAO,EAAE,SAAS,MAAM,MAAM,QAAQ,WAAsB;AAAA,EAC9D;AAAA;AAAA,EAGQ,YAAY,OAA+C;AACjE,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,QAAQ,MAAM,KAAK,IAAI,GAAG,MAAM,UAAU;AAChD,QAAI,QAAQ,KAAK,WAAY,MAAK,aAAa;AAG/C,QAAI,OAAO,SAAS,MAAM,MAAM,KAAK,MAAM,SAAS,GAAG;AACrD,MAAC,KAAK,IAAY,cAAc,MAAM;AAAA,IACxC;AAEA,YAAQ,IAAI,4CAA4C,IAAI,KAAK,KAAK,UAAU,EAAE,YAAY,CAAC,YAAY,KAAK,IAAI,WAAW,GAAG;AAAA,EACpI;AAAA,EAEQ,eAAe;AACrB,SAAK,aAAa;AAClB,YAAQ,IAAI,qCAAqC;AAAA,EACnD;AAAA,EAEQ,uBAAuB;AAC7B,UAAM,OAAO,KAAK,IAAI;AACtB,QAAI,CAAC,KAAM;AAEX,UAAM,IAAI,OAAO,QAAQ,IAAI,IAAI,KAAK,EAAE,EAAE,KAAK,EAAE,YAAY;AAC7D,UAAM,KAAK,MAAM,OAAO,MAAM,UAAU,MAAM,SAAS,MAAM;AAE7D,QAAI,IAAI;AACN,WAAK,YAAY,EAAE,YAAY,KAAK,IAAI,iBAAiB,QAAQ,KAAK,IAAI,YAAY,CAAC;AAAA,IACzF;AAAA,EAEF;AAAA,EAEQ,0BAA0B;AAChC,UAAM,WAAW,KAAK,IAAI;AAC1B,QAAI,CAAC,SAAU;AAEf,QAAI,KAAK,kBAAmB,eAAc,KAAK,iBAAiB;AAEhE,SAAK,oBAAoB,YAAY,MAAM;AACzC,WAAK,KAAK,sBAAsB,QAAQ,EAAE,MAAM,MAAM,MAAM;AAAA,IAC9D,GAAG,KAAK,IAAI,kBAAkB;AAG9B,SAAK,KAAK,sBAAsB,QAAQ,EAAE,MAAM,MAAM,MAAM;AAAA,EAC9D;AAAA,EAEA,MAAc,sBAAsB,UAAkB;AAEpD,QAAI;AACJ,QAAI;AACF,YAAM,KAAK,MAAM,eAAAC,SAAI,KAAK,QAAQ;AAClC,gBAAU,GAAG;AAAA,IACf,QAAQ;AAEN;AAAA,IACF;AAEA,QAAI,KAAK,4BAA4B,QAAQ,YAAY,KAAK,wBAAyB;AACvF,SAAK,0BAA0B;AAE/B,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,eAAAA,SAAI,SAAS,UAAU,MAAM;AAAA,IAC3C,QAAQ;AACN;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,gBAAU,KAAK,MAAM,GAAG;AAAA,IAC1B,QAAQ;AACN;AAAA,IACF;AACA,QAAI,CAAC,WAAW,OAAO,YAAY,SAAU;AAE7C,QAAI,QAAQ,UAAU,MAAM;AAC1B,WAAK,YAAY;AAAA,QACf,YAAY,QAAQ,mBAAmB,KAAK,IAAI;AAAA,QAChD,QAAQ,QAAQ,eAAe,KAAK,IAAI;AAAA,MAC1C,CAAC;AAED,UAAI,KAAK,UAAW,MAAK,aAAa,CAAC;AAAA,IACzC,WAAW,QAAQ,UAAU,OAAO;AAClC,WAAK,aAAa;AAAA,IACpB;AAEA,QAAI,QAAQ,eAAe,MAAM;AAC/B,WAAK,KAAK,WAAW,EAAE,OAAO,QAAQ,UAAU,KAAK,CAAC,EAAE,MAAM,MAAM,MAAM;AAAA,IAC5E;AAAA,EACF;AAAA,EAEQ,wBAAwB;AAC9B,QAAI,KAAK,uBAAwB;AACjC,QAAI,KAAK,IAAI,mBAAmB,MAAO;AAEvC,UAAM,MAAM,KAAK,IAAI;AAErB,QAAG,CAAC,IAAK;AAET,QAAI;AACF,WAAK,aAAa,MAAM;AACtB,aAAK,YAAY,EAAE,YAAY,KAAK,IAAI,iBAAiB,QAAQ,KAAK,IAAI,YAAY,CAAC;AACvF,YAAI,KAAK,UAAW,MAAK,aAAa,CAAC;AACvC,aAAK,KAAK,WAAW,EAAE,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM,MAAM;AAAA,MAC1D;AAEA,cAAQ,GAAG,KAAK,KAAK,UAAU;AAC/B,WAAK,yBAAyB;AAAA,IAChC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,0BAA0B;AAChC,QAAI,CAAC,KAAK,uBAAwB;AAClC,QAAI,KAAK,IAAI,mBAAmB,MAAO;AAEvC,UAAM,MAAM,KAAK,IAAI;AAErB,QAAG,CAAC,IAAK;AAET,QAAI;AACF,UAAI,KAAK,WAAY,SAAQ,IAAI,KAAK,KAAK,UAAU;AAAA,IACvD,QAAQ;AAAA,IAER,UAAE;AACA,WAAK,yBAAyB;AAC9B,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AACF;;;AO7pBO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YAAY,SAAiC,OAAO,YAA4B,SAAe;AAC7F,UAAM,OAAO;AAD8B;AAAmC;AAE9E,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,YAAN,cAAwB,cAAc;AAAA,EAC3C,YACE,SACgB,QACA,SAChB,SACA;AACA,UAAM,SAAS,cAAc,OAAO;AAJpB;AACA;AAIhB,SAAK,OAAO;AAAA,EACd;AACF;;;ACPO,SAAS,YACd,OACA,OAAmB,CAAC,GACZ;AACR,QAAM,QAAkB,CAAC;AAEzB,QAAM,MACJ,sBAAsB,MAAM,OAAO,YACxB,MAAM,OAAO,aACZ,MAAM,QAAQ,YAAY,UAC7B,MAAM,QAAQ,SAAS,YACrB,MAAM,QAAQ,OAAO;AAElC,QAAM,KAAK,GAAG;AAEd,MAAI,MAAM,QAAQ;AAChB,UAAM;AAAA,MACJ,wBAAmB,MAAM,OAAO,SAAS,SACjC,MAAM,OAAO,MAAM,WACjB,MAAM,OAAO,UAAU,aACrB,MAAM,OAAO,QAAQ;AAAA,IACnC;AAAA,EACF,OAAO;AACL,UAAM,KAAK,uCAAkC;AAAA,EAC/C;AAEA,MAAI,WAAW,SAAS,KAAK,kBAAkB;AAC7C,UAAM,YAAY,MAAM,MAAM,OAAO,OAAK,CAAC,EAAE,OAAO;AAEpD,QAAI,UAAU,QAAQ;AACpB,YAAM,KAAK,kBAAkB;AAE7B,iBAAW,KAAK,WAAW;AACzB,cAAM;AAAA,UACJ,YAAY,EAAE,SAAS,SACf,EAAE,MAAM,WACN,EAAE,cAAc,GAAG,WACnB,EAAE,eAAe;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,KAAK,WAAW;AAClB,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAEA,SAAO,MAAM,KAAK,KAAK;AACzB;","names":["decision","etag","bundleVersionRaw","updatedAt","meta","fsp"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
type Target = {
|
|
2
|
+
service: string;
|
|
3
|
+
resource: string;
|
|
4
|
+
action: string;
|
|
5
|
+
};
|
|
6
|
+
type Effect = {
|
|
7
|
+
type: "allow";
|
|
8
|
+
} | {
|
|
9
|
+
type: "deny";
|
|
10
|
+
} | {
|
|
11
|
+
type: "kill_switch";
|
|
12
|
+
killSwitch: {
|
|
13
|
+
service: string;
|
|
14
|
+
reason?: string;
|
|
15
|
+
};
|
|
16
|
+
} | {
|
|
17
|
+
type: "throttle";
|
|
18
|
+
throttle: {
|
|
19
|
+
limit: number;
|
|
20
|
+
windowSeconds: number;
|
|
21
|
+
key: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
type WhenAstV1 = {
|
|
25
|
+
op: "and" | "or";
|
|
26
|
+
args: WhenAstV1[];
|
|
27
|
+
} | {
|
|
28
|
+
op: "not";
|
|
29
|
+
arg: WhenAstV1;
|
|
30
|
+
} | {
|
|
31
|
+
op: "eq" | "ne" | "gt" | "gte" | "lt" | "lte";
|
|
32
|
+
path: string;
|
|
33
|
+
value: any;
|
|
34
|
+
} | {
|
|
35
|
+
op: "in";
|
|
36
|
+
path: string;
|
|
37
|
+
values: any[];
|
|
38
|
+
} | {
|
|
39
|
+
op: "exists";
|
|
40
|
+
path: string;
|
|
41
|
+
};
|
|
42
|
+
type RuntimeRule = {
|
|
43
|
+
id: string;
|
|
44
|
+
status: "active" | "disabled";
|
|
45
|
+
priority: number;
|
|
46
|
+
target: Target;
|
|
47
|
+
when?: WhenAstV1;
|
|
48
|
+
effect: Effect;
|
|
49
|
+
description?: string;
|
|
50
|
+
};
|
|
51
|
+
type RuntimePolicy = {
|
|
52
|
+
policyKey: string;
|
|
53
|
+
activeVersion: number;
|
|
54
|
+
defaults: {
|
|
55
|
+
effect: "allow" | "deny";
|
|
56
|
+
};
|
|
57
|
+
rules: RuntimeRule[];
|
|
58
|
+
};
|
|
59
|
+
type RuntimeBundleV1 = {
|
|
60
|
+
schemaVersion: 1;
|
|
61
|
+
orgId: string;
|
|
62
|
+
projectId: string;
|
|
63
|
+
env: string;
|
|
64
|
+
generatedAt: string;
|
|
65
|
+
policies: RuntimePolicy[];
|
|
66
|
+
};
|
|
67
|
+
type Decision = {
|
|
68
|
+
decision: "allow";
|
|
69
|
+
reason: "default" | "rule";
|
|
70
|
+
policyKey?: string;
|
|
71
|
+
ruleId?: string;
|
|
72
|
+
} | {
|
|
73
|
+
decision: "deny";
|
|
74
|
+
reason: "default" | "rule";
|
|
75
|
+
policyKey?: string;
|
|
76
|
+
ruleId?: string;
|
|
77
|
+
} | {
|
|
78
|
+
decision: "kill_switch";
|
|
79
|
+
reason: "rule";
|
|
80
|
+
policyKey: string;
|
|
81
|
+
ruleId: string;
|
|
82
|
+
killSwitch: {
|
|
83
|
+
service: string;
|
|
84
|
+
reason?: string;
|
|
85
|
+
};
|
|
86
|
+
} | {
|
|
87
|
+
decision: "throttle";
|
|
88
|
+
reason: "rule";
|
|
89
|
+
policyKey: string;
|
|
90
|
+
ruleId: string;
|
|
91
|
+
throttle: {
|
|
92
|
+
limit: number;
|
|
93
|
+
windowSeconds: number;
|
|
94
|
+
key: string;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
type TraceDiscardReason = "disabled" | "target_mismatch" | "when_false" | "invalid_effect";
|
|
98
|
+
type TraceRule = {
|
|
99
|
+
policyKey: string;
|
|
100
|
+
ruleId: string;
|
|
101
|
+
priority: number;
|
|
102
|
+
effectType?: string;
|
|
103
|
+
matched: boolean;
|
|
104
|
+
discardedReason?: TraceDiscardReason;
|
|
105
|
+
};
|
|
106
|
+
type DecisionTrace = {
|
|
107
|
+
evaluatedAt: string;
|
|
108
|
+
target: Target;
|
|
109
|
+
summary: {
|
|
110
|
+
policiesSeen: number;
|
|
111
|
+
rulesSeen: number;
|
|
112
|
+
matched: number;
|
|
113
|
+
considered: {
|
|
114
|
+
kill_switch: number;
|
|
115
|
+
deny: number;
|
|
116
|
+
throttle: number;
|
|
117
|
+
allow: number;
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
winner?: {
|
|
121
|
+
policyKey: string;
|
|
122
|
+
ruleId: string;
|
|
123
|
+
effectType: string;
|
|
124
|
+
priority: number;
|
|
125
|
+
};
|
|
126
|
+
rules: TraceRule[];
|
|
127
|
+
};
|
|
128
|
+
type DecisionWithTrace = Decision & {
|
|
129
|
+
trace: DecisionTrace;
|
|
130
|
+
};
|
|
131
|
+
type TraceLevel = "off" | "errors" | "sampled" | "full";
|
|
132
|
+
type TraceMode = "compact" | "full";
|
|
133
|
+
type TraceOptions = {
|
|
134
|
+
level?: TraceLevel;
|
|
135
|
+
mode?: TraceMode;
|
|
136
|
+
sampling?: number;
|
|
137
|
+
force?: boolean;
|
|
138
|
+
budget?: {
|
|
139
|
+
maxTraces: number;
|
|
140
|
+
windowMs: number;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
type PolicyEngineEvaluateInput = {
|
|
144
|
+
target: Target;
|
|
145
|
+
context?: Record<string, unknown>;
|
|
146
|
+
};
|
|
147
|
+
type PolicyEngine = {
|
|
148
|
+
evaluate(input: PolicyEngineEvaluateInput): Decision;
|
|
149
|
+
evaluateWithTrace(input: PolicyEngineEvaluateInput, options?: TraceOptions): DecisionWithOptionalTrace;
|
|
150
|
+
flushTraces(): Promise<void>;
|
|
151
|
+
};
|
|
152
|
+
type DecisionTraceCompact = {
|
|
153
|
+
traceId: string;
|
|
154
|
+
sampled: "forced" | "random";
|
|
155
|
+
evaluatedAt: string;
|
|
156
|
+
target: Target;
|
|
157
|
+
summary: {
|
|
158
|
+
policiesSeen: number;
|
|
159
|
+
rulesSeen: number;
|
|
160
|
+
matched: number;
|
|
161
|
+
considered: {
|
|
162
|
+
kill_switch: number;
|
|
163
|
+
deny: number;
|
|
164
|
+
throttle: number;
|
|
165
|
+
allow: number;
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
winner?: {
|
|
169
|
+
policyKey: string;
|
|
170
|
+
ruleId: string;
|
|
171
|
+
effectType: string;
|
|
172
|
+
priority: number;
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
type DecisionTraceFull = DecisionTraceCompact & {
|
|
176
|
+
rules: TraceRule[];
|
|
177
|
+
};
|
|
178
|
+
type DecisionWithOptionalTrace = Decision & {
|
|
179
|
+
trace?: DecisionTraceCompact | DecisionTraceFull;
|
|
180
|
+
};
|
|
181
|
+
type StructuredTraceEvent = {
|
|
182
|
+
v: 1;
|
|
183
|
+
ts: string;
|
|
184
|
+
traceId: string;
|
|
185
|
+
sampled: "forced" | "random" | "errors";
|
|
186
|
+
level: TraceLevel;
|
|
187
|
+
target: Target;
|
|
188
|
+
decision: Decision["decision"];
|
|
189
|
+
reason: Decision["reason"];
|
|
190
|
+
winner?: {
|
|
191
|
+
policyKey: string;
|
|
192
|
+
ruleId: string;
|
|
193
|
+
effectType: string;
|
|
194
|
+
priority: number;
|
|
195
|
+
};
|
|
196
|
+
summary: {
|
|
197
|
+
policiesSeen: number;
|
|
198
|
+
rulesSeen: number;
|
|
199
|
+
matched: number;
|
|
200
|
+
considered: {
|
|
201
|
+
kill_switch: number;
|
|
202
|
+
deny: number;
|
|
203
|
+
throttle: number;
|
|
204
|
+
allow: number;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
rules?: Array<{
|
|
208
|
+
policyKey: string;
|
|
209
|
+
ruleId: string;
|
|
210
|
+
priority: number;
|
|
211
|
+
effectType?: string;
|
|
212
|
+
matched: boolean;
|
|
213
|
+
discardedReason?: string;
|
|
214
|
+
}>;
|
|
215
|
+
};
|
|
216
|
+
type TraceSink = (evt: StructuredTraceEvent) => void;
|
|
217
|
+
type TraceSinkAsync = (evt: StructuredTraceEvent) => Promise<void>;
|
|
218
|
+
type TraceQueueDropPolicy = "drop_new" | "drop_old";
|
|
219
|
+
type DecisionTraceHook = (evt: StructuredTraceEvent) => void;
|
|
220
|
+
type RuntimeClientOptions = {
|
|
221
|
+
trace?: {
|
|
222
|
+
level?: TraceLevel;
|
|
223
|
+
sampling?: number;
|
|
224
|
+
budget?: {
|
|
225
|
+
maxTraces: number;
|
|
226
|
+
windowMs: number;
|
|
227
|
+
};
|
|
228
|
+
onDecisionTrace?: DecisionTraceHook;
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
type ContextPolicy = {
|
|
233
|
+
allowedKeys: string[];
|
|
234
|
+
maxStringLen: number;
|
|
235
|
+
maxArrayLen: number;
|
|
236
|
+
blockLikelyPiiKeys: boolean;
|
|
237
|
+
};
|
|
238
|
+
declare const DEFAULT_CONTEXT_POLICY: ContextPolicy;
|
|
239
|
+
declare function validateContext(ctx: Record<string, unknown>, policy: ContextPolicy): void;
|
|
240
|
+
|
|
241
|
+
type RuntimeClientConfig = {
|
|
242
|
+
baseUrl: string;
|
|
243
|
+
runtimeKey: string;
|
|
244
|
+
orgId: string;
|
|
245
|
+
projectId: string;
|
|
246
|
+
env: string;
|
|
247
|
+
pollMs?: number;
|
|
248
|
+
burstPollMs?: number;
|
|
249
|
+
burstDurationMs?: number;
|
|
250
|
+
timeoutMs?: number;
|
|
251
|
+
userAgent?: string;
|
|
252
|
+
backoffBaseMs?: number;
|
|
253
|
+
backoffMaxMs?: number;
|
|
254
|
+
backoffJitter?: number;
|
|
255
|
+
degradeAfterFailures?: number;
|
|
256
|
+
/**
|
|
257
|
+
* Engine config
|
|
258
|
+
*/
|
|
259
|
+
engine?: {
|
|
260
|
+
validateContext?: boolean;
|
|
261
|
+
contextPolicy?: ContextPolicy;
|
|
262
|
+
};
|
|
263
|
+
/**
|
|
264
|
+
* Decision trace (SDK-only, zero PII)
|
|
265
|
+
*/
|
|
266
|
+
trace?: {
|
|
267
|
+
defaults?: TraceOptions;
|
|
268
|
+
onDecisionTrace?: (evt: StructuredTraceEvent) => void;
|
|
269
|
+
onDecisionTraceAsync?: (evt: StructuredTraceEvent) => Promise<void>;
|
|
270
|
+
queueMax?: number;
|
|
271
|
+
dropPolicy?: "drop_new" | "drop_old";
|
|
272
|
+
onTraceError?: (err: unknown) => void;
|
|
273
|
+
};
|
|
274
|
+
incidentEnvFlag?: string;
|
|
275
|
+
incidentFilePath?: string;
|
|
276
|
+
incidentFilePollMs?: number;
|
|
277
|
+
incidentSignal?: "SIGUSR1" | false;
|
|
278
|
+
};
|
|
279
|
+
type BundleMeta = {
|
|
280
|
+
etag: string;
|
|
281
|
+
bundleVersion?: number;
|
|
282
|
+
updatedAt?: string;
|
|
283
|
+
};
|
|
284
|
+
type RuntimeCache<TBundle = unknown> = {
|
|
285
|
+
meta?: BundleMeta;
|
|
286
|
+
bundle?: TBundle;
|
|
287
|
+
};
|
|
288
|
+
type RefreshResult<TBundle = unknown> = {
|
|
289
|
+
changed: false;
|
|
290
|
+
meta?: BundleMeta;
|
|
291
|
+
} | {
|
|
292
|
+
changed: true;
|
|
293
|
+
meta: BundleMeta;
|
|
294
|
+
bundle: TBundle;
|
|
295
|
+
};
|
|
296
|
+
type RuntimeStatus = {
|
|
297
|
+
state: "warming_up";
|
|
298
|
+
} | {
|
|
299
|
+
state: "ok";
|
|
300
|
+
} | {
|
|
301
|
+
state: "degraded";
|
|
302
|
+
consecutiveFailures: number;
|
|
303
|
+
lastError: {
|
|
304
|
+
message: string;
|
|
305
|
+
at: string;
|
|
306
|
+
};
|
|
307
|
+
nextRetryAt?: string;
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* RuntimeClient = polling/backoff/degraded + cached runtime bundle + policy evaluation.
|
|
311
|
+
*
|
|
312
|
+
* - No endpoints expuestos por el cliente
|
|
313
|
+
* - No PII en trace: el engine emite StructuredTraceEvent sin context ni reglas completas
|
|
314
|
+
*/
|
|
315
|
+
declare class RuntimeClient<TBundle = RuntimeBundleV1> {
|
|
316
|
+
private readonly cfg;
|
|
317
|
+
private cache;
|
|
318
|
+
private timer;
|
|
319
|
+
private isRunning;
|
|
320
|
+
private hasValidBundle;
|
|
321
|
+
private inFlightRefresh;
|
|
322
|
+
private burstUntil;
|
|
323
|
+
private consecutiveFailures;
|
|
324
|
+
private lastError;
|
|
325
|
+
private nextRetryAtMs;
|
|
326
|
+
private updateListeners;
|
|
327
|
+
private statusListeners;
|
|
328
|
+
private readonly engine;
|
|
329
|
+
private incidentPollTimer;
|
|
330
|
+
private incidentFileLastMtimeMs;
|
|
331
|
+
private installedSignalHandler;
|
|
332
|
+
private sigHandler?;
|
|
333
|
+
constructor(config: RuntimeClientConfig);
|
|
334
|
+
/** Subscribe to bundle updates (only when changed). */
|
|
335
|
+
onUpdate(fn: (res: Extract<RefreshResult<TBundle>, {
|
|
336
|
+
changed: true;
|
|
337
|
+
}>) => void): () => void;
|
|
338
|
+
/** Subscribe to status changes (ok/degraded). */
|
|
339
|
+
onStatus(fn: (s: RuntimeStatus) => void): () => void;
|
|
340
|
+
/** Evaluate a decision using the cached bundle (deny-by-default if bundle missing/invalid). */
|
|
341
|
+
evaluate(input: {
|
|
342
|
+
target: Target;
|
|
343
|
+
context?: Record<string, unknown>;
|
|
344
|
+
}): Decision;
|
|
345
|
+
/** Evaluate and (optionally) attach trace based on trace defaults/overrides. */
|
|
346
|
+
evaluateWithTrace(input: {
|
|
347
|
+
target: Target;
|
|
348
|
+
context?: Record<string, unknown>;
|
|
349
|
+
}, options?: TraceOptions): DecisionWithOptionalTrace;
|
|
350
|
+
/** Flush async trace queue (only does something if traceSinkAsync is configured). */
|
|
351
|
+
flushTraces(): Promise<void>;
|
|
352
|
+
getCached(): RuntimeCache<TBundle>;
|
|
353
|
+
getStatus(): RuntimeStatus;
|
|
354
|
+
start(): void;
|
|
355
|
+
warmStart(opts?: {
|
|
356
|
+
timeoutMs?: number;
|
|
357
|
+
burst?: boolean;
|
|
358
|
+
}): Promise<void>;
|
|
359
|
+
stop(): void;
|
|
360
|
+
refreshNow(opts?: {
|
|
361
|
+
burst?: boolean;
|
|
362
|
+
}): Promise<RefreshResult<TBundle>>;
|
|
363
|
+
private emitStatusIfNeeded;
|
|
364
|
+
private refresh;
|
|
365
|
+
private scheduleNext;
|
|
366
|
+
private effectivePollMs;
|
|
367
|
+
private markSuccess;
|
|
368
|
+
private markFailure;
|
|
369
|
+
private computeBackoffDelayMs;
|
|
370
|
+
private bundleUrl;
|
|
371
|
+
private commonHeaders;
|
|
372
|
+
private headBundle;
|
|
373
|
+
private getBundle;
|
|
374
|
+
private enableBurst;
|
|
375
|
+
private disableBurst;
|
|
376
|
+
private applyIncidentFromEnv;
|
|
377
|
+
private startIncidentFilePoller;
|
|
378
|
+
private checkIncidentFileOnce;
|
|
379
|
+
private installIncidentSignal;
|
|
380
|
+
private uninstallIncidentSignal;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
declare class GovplaneError extends Error {
|
|
384
|
+
readonly code: string;
|
|
385
|
+
readonly details?: any | undefined;
|
|
386
|
+
constructor(message: string, code?: string, details?: any | undefined);
|
|
387
|
+
}
|
|
388
|
+
declare class HttpError extends GovplaneError {
|
|
389
|
+
readonly status: number;
|
|
390
|
+
readonly headers?: Record<string, string> | undefined;
|
|
391
|
+
constructor(message: string, status: number, headers?: Record<string, string> | undefined, details?: any);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
type EngineOpts = {
|
|
395
|
+
getBundle: () => RuntimeBundleV1 | undefined;
|
|
396
|
+
validateContext?: boolean;
|
|
397
|
+
contextPolicy?: ContextPolicy;
|
|
398
|
+
traceDefaults?: TraceOptions;
|
|
399
|
+
traceSink?: TraceSink;
|
|
400
|
+
traceSinkAsync?: TraceSinkAsync;
|
|
401
|
+
traceQueueMax?: number;
|
|
402
|
+
traceQueueDropPolicy?: TraceQueueDropPolicy;
|
|
403
|
+
onTraceSinkError?: (err: unknown) => void;
|
|
404
|
+
};
|
|
405
|
+
declare function createPolicyEngine(opts: EngineOpts): PolicyEngine;
|
|
406
|
+
|
|
407
|
+
type FormatOpts = {
|
|
408
|
+
multiline?: boolean;
|
|
409
|
+
includeDiscarded?: boolean;
|
|
410
|
+
};
|
|
411
|
+
declare function formatTrace(trace: DecisionTraceCompact | DecisionTraceFull, opts?: FormatOpts): string;
|
|
412
|
+
|
|
413
|
+
export { type BundleMeta, type ContextPolicy, DEFAULT_CONTEXT_POLICY, type Decision, type DecisionTrace, type DecisionTraceCompact, type DecisionTraceFull, type DecisionTraceHook, type DecisionWithOptionalTrace, type DecisionWithTrace, type Effect, GovplaneError, HttpError, type PolicyEngine, type PolicyEngineEvaluateInput, type RefreshResult, type RuntimeBundleV1, type RuntimeCache, RuntimeClient, type RuntimeClientConfig, type RuntimeClientOptions, type RuntimePolicy, type RuntimeRule, type RuntimeStatus, type StructuredTraceEvent, type Target, type TraceDiscardReason, type TraceLevel, type TraceMode, type TraceOptions, type TraceQueueDropPolicy, type TraceRule, type TraceSink, type TraceSinkAsync, type WhenAstV1, createPolicyEngine, formatTrace, validateContext };
|