@astrasyncai/verification-gateway 5.10.0 → 5.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/express.js +1 -1
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +1 -1
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.js +1 -1
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +1 -1
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.js +1 -1
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +1 -1
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.js +1 -1
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +1 -1
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.js +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +1 -1
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +522 -10
- package/dist/bin/astrasync-codex-hook.js +522 -10
- package/dist/bin/astrasync-guard.js +611 -65
- package/dist/bin/astrasync.js +655 -66
- package/dist/browser/background.js +1 -1
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +1 -1
- package/dist/browser/background.mjs.map +1 -1
- package/dist/cli/index.d.mts +8 -8
- package/dist/cli/index.d.ts +8 -8
- package/dist/cli/index.js +22 -64
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +22 -64
- package/dist/cli/index.mjs.map +1 -1
- package/dist/codex/index.d.mts +5 -0
- package/dist/codex/index.d.ts +5 -0
- package/dist/codex/index.js +538 -18
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +540 -20
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/extension.d.mts +9 -2
- package/dist/cursor/extension.d.ts +9 -2
- package/dist/cursor/extension.js +504 -5
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +506 -5
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.js +1 -1
- package/dist/edge-config.js.map +1 -1
- package/dist/edge-config.mjs +1 -1
- package/dist/edge-config.mjs.map +1 -1
- package/dist/edge-core/index.js +1 -1
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +1 -1
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/enrolment-store-8DyaIOLe.d.mts +26 -0
- package/dist/enrolment-store-8DyaIOLe.d.ts +26 -0
- package/dist/gateway/gateway.js +1 -1
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +1 -1
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/index.d.mts +100 -3
- package/dist/index.d.ts +100 -3
- package/dist/index.js +3271 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3269 -18
- package/dist/index.mjs.map +1 -1
- package/dist/registration/index.js +1 -1
- package/dist/registration/index.js.map +1 -1
- package/dist/registration/index.mjs +1 -1
- package/dist/registration/index.mjs.map +1 -1
- package/dist/transport/index.js +1 -1
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs +1 -1
- package/dist/transport/index.mjs.map +1 -1
- package/dist/verify.js +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +1 -1
- package/dist/verify.mjs.map +1 -1
- package/package.json +1 -1
package/dist/codex/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapter-interface/interface.ts","../../src/adapter-interface/purpose-mapping.ts","../../src/claude-code/tool-mapping.ts","../../src/codex/tool-mapping.ts","../../src/codex/codex-adapter.ts","../../src/codex/hook.ts","../../src/gateway/types.ts","../../src/local-evaluator/command-matcher.ts","../../src/local-evaluator/evaluator.ts","../../../../node_modules/js-yaml/lib/common.js","../../../../node_modules/js-yaml/lib/exception.js","../../../../node_modules/js-yaml/lib/snippet.js","../../../../node_modules/js-yaml/lib/type.js","../../../../node_modules/js-yaml/lib/schema.js","../../../../node_modules/js-yaml/lib/type/str.js","../../../../node_modules/js-yaml/lib/type/seq.js","../../../../node_modules/js-yaml/lib/type/map.js","../../../../node_modules/js-yaml/lib/schema/failsafe.js","../../../../node_modules/js-yaml/lib/type/null.js","../../../../node_modules/js-yaml/lib/type/bool.js","../../../../node_modules/js-yaml/lib/type/int.js","../../../../node_modules/js-yaml/lib/type/float.js","../../../../node_modules/js-yaml/lib/schema/json.js","../../../../node_modules/js-yaml/lib/schema/core.js","../../../../node_modules/js-yaml/lib/type/timestamp.js","../../../../node_modules/js-yaml/lib/type/merge.js","../../../../node_modules/js-yaml/lib/type/binary.js","../../../../node_modules/js-yaml/lib/type/omap.js","../../../../node_modules/js-yaml/lib/type/pairs.js","../../../../node_modules/js-yaml/lib/type/set.js","../../../../node_modules/js-yaml/lib/schema/default.js","../../../../node_modules/js-yaml/lib/loader.js","../../../../node_modules/js-yaml/lib/dumper.js","../../../../node_modules/js-yaml/index.js","../../../../node_modules/js-yaml/lib/index_vite_proxy.tmp.mjs","../../src/local-evaluator/pdlss-parser.ts","../../src/local-evaluator/schema.ts","../../src/gateway/modes/local.ts","../../src/trust-levels.ts","../../src/version.ts","../../src/http.ts","../../src/well-known.ts","../../src/verify.ts","../../src/adapters/stepup-poll.ts","../../src/metadata-capture.ts","../../src/edge-config.ts","../../src/adapters/express.ts","../../src/adapters/nextjs.ts","../../src/transport/rfc9421.ts","../../src/transport/rfc9421-verify.ts","../../src/transport/nonce-store.ts","../../src/transport/vi.ts","../../src/transport/stripe-webhook.ts","../../src/transport/ap2.ts","../../src/transport/mpp.ts","../../src/transport/mpp-verify.ts","../../src/transport/x402.ts","../../src/transport/vi-verify.ts","../../src/transport/registry/visa.ts","../../src/gateway/modes/online.ts","../../src/gateway/modes/hybrid.ts","../../src/gateway/redact.ts","../../src/gateway/trace-logger.ts","../../src/gateway/gateway.ts","../../src/claude-code/guard-config.ts","../../src/claude-code/settings-installer.ts","../../src/codex/settings-installer.ts"],"sourcesContent":["/**\n * PlatformAdapter Interface\n *\n * The contract that Layer 4 platform adapters implement.\n * Agent-side interception: governs what agents are allowed to do before they do it.\n *\n * Each adapter is 200-500 lines of platform-specific code.\n * All verification logic lives in the gateway — adapters just translate\n * between the platform's world and AstraSync's world.\n */\n\nimport type { AstraSyncGateway } from '../gateway/gateway';\nimport type { PDLSSContext, VerificationDecision, AgentAction, InterceptResult } from '../gateway/types';\n\nexport interface AdapterConfig {\n /** The AstraSyncGateway instance (handles mode routing) */\n gateway: AstraSyncGateway;\n /** Platform-specific configuration */\n adapterOptions: Record<string, unknown>;\n}\n\nexport interface PlatformAdapter {\n /**\n * Interface version for compatibility checking.\n * Current version: 1.\n */\n readonly interfaceVersion: number;\n\n /**\n * Platform-specific initialization.\n * Load config, register hooks, establish connections.\n */\n initialize(config: AdapterConfig): Promise<void>;\n\n /**\n * Graceful shutdown.\n * Drain in-flight verifications, deregister hooks, close connections.\n */\n shutdown(): Promise<void>;\n\n /**\n * Intercept an agent action before execution.\n *\n * How this works depends on the platform:\n * - CLI adapter: proxy server captures outbound request\n * - Browser adapter: content script intercepts DOM interaction\n * - Express: middleware captures inbound request\n */\n interceptAction(action: AgentAction): Promise<InterceptResult>;\n\n /**\n * Extract PDLSS-compatible context from a platform-specific action.\n * Maps platform-native action format to the universal PDLSSContext.\n */\n extractContext(action: AgentAction): PDLSSContext;\n\n /**\n * Enforce the verification decision in a platform-specific way.\n *\n * How this works depends on the platform:\n * - CLI: block command / allow command / prompt for approval\n * - Browser: block navigation / show confirmation dialog\n * - Express: return 403 / pass through / inject headers\n */\n enforceDecision(decision: VerificationDecision): Promise<void>;\n}\n\n/**\n * Current adapter interface version.\n */\nexport const ADAPTER_INTERFACE_VERSION = 1;\n\n/**\n * Check if an adapter is compatible with the current interface version.\n */\nexport function isCompatibleAdapter(adapter: PlatformAdapter): boolean {\n return adapter.interfaceVersion === ADAPTER_INTERFACE_VERSION;\n}\n","/**\n * Shared purpose mapping utilities for Layer 4 platform adapters.\n *\n * Maps platform-native action names to PDLSS purpose categories.\n * Used by OpenClaw CLI, Cursor, browser, and future adapters.\n */\n\n// -----------------------------------------------------------------------\n// Tool → Purpose mapping\n// -----------------------------------------------------------------------\n\n/** Standard tool name → PDLSS purpose mapping used by all adapters */\nconst TOOL_PURPOSE_MAP: Record<string, string> = {\n // Shell\n shell_exec: 'shell.exec',\n run_command: 'shell.exec',\n execute: 'shell.exec',\n terminal_exec: 'shell.exec',\n run_terminal_command: 'shell.exec',\n\n // File read\n file_read: 'file.read',\n read_file: 'file.read',\n\n // File write\n file_write: 'file.write',\n write_file: 'file.write',\n create_file: 'file.write',\n edit_file: 'file.write',\n\n // File delete\n file_delete: 'file.delete',\n delete_file: 'file.delete',\n\n // Network\n http_request: 'network.request',\n fetch: 'network.request',\n web_request: 'network.request',\n\n // Email\n send_email: 'email.send',\n read_email: 'email.read',\n\n // Calendar\n create_event: 'calendar.create',\n\n // Database\n query_database: 'database.query',\n write_database: 'database.write',\n\n // Payment\n payment_execute: 'payment.execute',\n};\n\n/**\n * Map a tool/action name to a PDLSS purpose category.\n * Returns `tool.<name>` for unmapped tools (denied by default).\n */\nexport function mapToolToPurpose(toolName: string): string {\n return TOOL_PURPOSE_MAP[toolName] || `tool.${toolName}`;\n}\n\n/**\n * Register additional tool → purpose mappings (e.g. from a platform adapter).\n * Does not overwrite existing mappings.\n */\nexport function registerToolMappings(mappings: Record<string, string>): void {\n for (const [tool, purpose] of Object.entries(mappings)) {\n if (!(tool in TOOL_PURPOSE_MAP)) {\n TOOL_PURPOSE_MAP[tool] = purpose;\n }\n }\n}\n\n// -----------------------------------------------------------------------\n// Target extraction\n// -----------------------------------------------------------------------\n\n/**\n * Extract the meaningful target string from tool arguments.\n * Uses the purpose category to determine which argument field is relevant.\n */\nexport function extractTarget(toolName: string, args: Record<string, unknown>): string {\n const purpose = mapToolToPurpose(toolName);\n\n if (purpose.startsWith('shell.')) {\n return String(args.command || args.cmd || args.script || '');\n }\n\n if (purpose.startsWith('file.')) {\n return String(args.path || args.file || args.filename || args.file_path || '');\n }\n\n if (purpose.startsWith('network.')) {\n return String(args.url || args.endpoint || args.uri || '');\n }\n\n if (purpose.startsWith('email.')) {\n return String(args.to || args.recipient || args.address || '');\n }\n\n if (purpose.startsWith('database.')) {\n return String(args.query || args.table || '');\n }\n\n if (purpose.startsWith('payment.')) {\n return String(args.description || args.merchant || args.amount || '');\n }\n\n // Fallback: try common field names\n if (args.command) return String(args.command);\n if (args.path) return String(args.path);\n if (args.url) return String(args.url);\n\n // Default: use first non-empty string argument or tool name\n for (const val of Object.values(args)) {\n if (typeof val === 'string' && val.length > 0) return val;\n }\n return toolName;\n}\n\n// -----------------------------------------------------------------------\n// Network domain extraction\n// -----------------------------------------------------------------------\n\n/**\n * Extract network domains from a URL target.\n * Returns undefined if the target is not a URL.\n */\nexport function extractNetworkDomains(target: string): string[] | undefined {\n try {\n if (target.startsWith('http://') || target.startsWith('https://')) {\n const url = new URL(target);\n return [url.hostname];\n }\n } catch {\n // Not a URL\n }\n return undefined;\n}\n","/**\n * @astrasyncai/adapter-claude-code — tool → purpose mapping\n *\n * Maps Claude Code's built-in tool names (as delivered in PreToolUse hook\n * payloads) to PDLSS purpose categories, and parses MCP tool names\n * (mcp__{server}__{tool}) into app-connector style purposes.\n */\n\nimport { registerToolMappings } from '../adapter-interface/purpose-mapping';\n\n/** Claude Code built-in tool name → PDLSS purpose */\nexport const CLAUDE_CODE_TOOL_MAP: Record<string, string> = {\n Bash: 'shell.exec',\n // Native Windows ships shell execution as a distinct PowerShell tool\n // (hooks docs: \"Tool Names in PreToolUse\"). Found live on 10 Jul 2026 —\n // the desktop-app runtime verification showed shell commands bypassing\n // the guard entirely on Windows because only Bash was mapped/matched.\n PowerShell: 'shell.exec',\n Write: 'file.write',\n Edit: 'file.write',\n MultiEdit: 'file.write',\n NotebookEdit: 'file.write',\n Read: 'file.read',\n Glob: 'file.read',\n Grep: 'file.read',\n WebFetch: 'network.request',\n WebSearch: 'network.request',\n Task: 'sub_agent.spawn',\n Agent: 'sub_agent.spawn',\n};\n\nlet registered = false;\n\n/**\n * Register the Claude Code mappings into the shared adapter purpose map.\n * Idempotent; safe to call from both the adapter and the hook entry.\n */\nexport function registerClaudeCodeMappings(): void {\n if (registered) return;\n registerToolMappings(CLAUDE_CODE_TOOL_MAP);\n registered = true;\n}\n\n/**\n * Parse an MCP tool name (mcp__{server}__{tool}) into an app-connector\n * style purpose `{server}.{tool}`. Returns null for non-MCP tool names.\n */\nexport function mapMcpTool(toolName: string): string | null {\n const match = /^mcp__(.+?)__(.+)$/.exec(toolName);\n if (!match) return null;\n return `${match[1]}.${match[2]}`;\n}\n","/**\n * @astrasyncai/adapter-codex — tool → purpose mapping\n *\n * Maps OpenAI Codex CLI's built-in tool names (as delivered in PreToolUse\n * hook payloads) to PDLSS purpose categories. MCP tool names use the same\n * mcp__{server}__{tool} convention as Claude Code, so the parser is shared.\n */\n\nimport { registerToolMappings } from '../adapter-interface/purpose-mapping';\nexport { mapMcpTool } from '../claude-code/tool-mapping';\n\n/**\n * Codex CLI built-in tool name → PDLSS purpose.\n * Documented canonical names: `Bash`, `apply_patch` (aliases `Edit`/`Write`\n * appear in matcher examples), `web_search`. Undocumented tools stay\n * unmapped and are skipped unless strictUnmapped is on.\n */\nexport const CODEX_TOOL_MAP: Record<string, string> = {\n Bash: 'shell.exec',\n apply_patch: 'file.write',\n Edit: 'file.write',\n Write: 'file.write',\n web_search: 'network.request',\n};\n\nlet registered = false;\n\n/**\n * Register the Codex mappings into the shared adapter purpose map.\n * Idempotent; safe to call from both the adapter and the hook entry.\n */\nexport function registerCodexMappings(): void {\n if (registered) return;\n registerToolMappings(CODEX_TOOL_MAP);\n registered = true;\n}\n\n/**\n * Extract the file paths an apply_patch envelope touches. Codex's patch\n * format marks each file with `*** Add File:` / `*** Update File:` /\n * `*** Delete File:` headers. Returns [] when nothing parseable is found —\n * callers should then fall back to a raw-text target.\n */\nexport function extractApplyPatchPaths(patchText: string): string[] {\n const paths: string[] = [];\n const re = /^\\*\\*\\*\\s+(?:Add|Update|Delete)\\s+File:\\s+(.+)$/gim;\n let match: RegExpExecArray | null;\n while ((match = re.exec(patchText)) !== null) {\n const p = match[1].trim();\n if (p) paths.push(p);\n }\n return paths;\n}\n","/**\n * @astrasyncai/adapter-codex\n *\n * Layer 4 adapter for OpenAI Codex CLI. Intercepts tool calls via Codex's\n * native PreToolUse hooks (stable since Codex v0.124.0): the hook binary\n * receives {tool_name, tool_input, permission_mode, ...} on stdin and may\n * answer with a permissionDecision on stdout.\n *\n * Decision mapping is strictly tightening, with two Codex-specific twists\n * versus the Claude Code adapter:\n *\n * - Codex has NO \"ask\" decision. MANUAL_REVIEW therefore emits nothing —\n * \"no matching hook decides\" makes Codex fall through to its own native\n * approval prompt, which is the HITL. EXCEPT when the session runs in\n * `dontAsk` / `bypassPermissions` permission mode: no native prompt will\n * catch the fall-through there, so MANUAL_REVIEW escalates to deny.\n * - Codex FAILS OPEN on hook errors/timeouts (it \"reports the error and\n * continues the tool call\"). The hook binary therefore fails closed\n * internally — every internal failure becomes an explicit deny (unless\n * failOpen is configured). A hard kill/timeout still fails open on\n * Codex's side; that residual gap is documented, and the mitigation is\n * the hook's ~200ms cost against a 10s timeout.\n *\n * ALLOW never emits \"allow\" (and never `updatedInput`) — a hook allow would\n * suppress Codex's own approval prompt rather than defer to it.\n */\n\nimport type { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface';\nimport type {\n PDLSSContext,\n VerificationDecision,\n AgentAction,\n InterceptResult,\n} from '../gateway/types';\nimport type { AstraSyncGateway } from '../gateway/gateway';\nimport { ADAPTER_INTERFACE_VERSION } from '../adapter-interface/interface';\nimport {\n mapToolToPurpose,\n extractTarget,\n extractNetworkDomains,\n} from '../adapter-interface/purpose-mapping';\nimport {\n registerCodexMappings,\n mapMcpTool,\n CODEX_TOOL_MAP,\n extractApplyPatchPaths,\n} from './tool-mapping';\n\n// -----------------------------------------------------------------------\n// Codex hook payload / output shapes\n// (contract: https://developers.openai.com/codex/hooks)\n// -----------------------------------------------------------------------\n\n/** The PreToolUse payload Codex CLI writes to the hook's stdin. */\nexport interface CodexPreToolUsePayload {\n hook_event_name?: string;\n tool_name: string;\n tool_input: Record<string, unknown>;\n session_id?: string;\n turn_id?: string;\n tool_use_id?: string;\n cwd?: string;\n model?: string;\n transcript_path?: string | null;\n /** default | acceptEdits | plan | dontAsk | bypassPermissions */\n permission_mode?: string;\n}\n\n/**\n * The JSON the hook prints to stdout when it wants to tighten a decision.\n * Deny-only by design: Codex has no \"ask\", and the guard never emits\n * \"allow\". Any unsupported field would make Codex mark the hook run failed\n * and continue the call — keep this shape strictly to documented fields.\n */\nexport interface CodexHookOutput {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse';\n permissionDecision: 'deny';\n permissionDecisionReason: string;\n };\n}\n\n/** Permission modes with no native approval prompt to catch a fall-through. */\nexport const UNPROMPTED_PERMISSION_MODES = new Set(['dontAsk', 'bypassPermissions']);\n\n// -----------------------------------------------------------------------\n// Configuration\n// -----------------------------------------------------------------------\n\n/** Session bookkeeping tools that are never governed. */\nexport const DEFAULT_SKIP_TOOLS = ['update_plan'];\n\nexport interface CodexAdapterOptions {\n /** Tool names to never intercept (replaces DEFAULT_SKIP_TOOLS if given) */\n skipTools?: string[];\n /**\n * When true, unmapped non-MCP tools are still intercepted (purpose\n * `tool.<name>`, denied by default policy). When false (default),\n * unmapped tools are skipped — Codex's own approval flow remains their\n * only gate.\n */\n strictUnmapped?: boolean;\n /**\n * Govern MCP tools (mcp__{server}__{tool} → purpose {server}.{tool}).\n * Defaults to true; installers default it off until the policy lists\n * {server}.{tool} rules (the evaluator denies unknown purposes).\n */\n governMcp?: boolean;\n}\n\n// -----------------------------------------------------------------------\n// Adapter implementation\n// -----------------------------------------------------------------------\n\nexport class CodexAdapter implements PlatformAdapter {\n readonly interfaceVersion = ADAPTER_INTERFACE_VERSION;\n\n private gateway!: AstraSyncGateway;\n private skipTools: Set<string>;\n private strictUnmapped: boolean;\n private governMcp: boolean;\n private _isRunning = false;\n\n constructor(options?: CodexAdapterOptions) {\n this.skipTools = new Set(options?.skipTools ?? DEFAULT_SKIP_TOOLS);\n this.strictUnmapped = options?.strictUnmapped ?? false;\n this.governMcp = options?.governMcp ?? true;\n registerCodexMappings();\n }\n\n get isRunning(): boolean {\n return this._isRunning;\n }\n\n async initialize(config: AdapterConfig): Promise<void> {\n this.gateway = config.gateway as AstraSyncGateway;\n\n if (Array.isArray(config.adapterOptions.skipTools)) {\n this.skipTools = new Set(config.adapterOptions.skipTools as string[]);\n }\n if (typeof config.adapterOptions.strictUnmapped === 'boolean') {\n this.strictUnmapped = config.adapterOptions.strictUnmapped;\n }\n\n this._isRunning = true;\n }\n\n async shutdown(): Promise<void> {\n this._isRunning = false;\n }\n\n async interceptAction(action: AgentAction): Promise<InterceptResult> {\n const raw = action.raw as Partial<CodexPreToolUsePayload> | null;\n\n if (!raw || typeof raw.tool_name !== 'string' || raw.tool_name.length === 0) {\n return { intercepted: false, skipReason: 'No tool_name in payload' };\n }\n\n if (this.skipTools.has(raw.tool_name)) {\n return { intercepted: false, skipReason: `Tool ${raw.tool_name} is not governed` };\n }\n\n const isMcp = mapMcpTool(raw.tool_name) !== null;\n if (isMcp && !this.governMcp) {\n return { intercepted: false, skipReason: 'MCP tools not governed (governMcp off)' };\n }\n\n const isMapped = raw.tool_name in CODEX_TOOL_MAP || isMcp;\n if (!isMapped && !this.strictUnmapped) {\n return {\n intercepted: false,\n skipReason: `Unmapped tool ${raw.tool_name} (strictUnmapped off)`,\n };\n }\n\n const context = this.extractContext(action);\n return { intercepted: true, context };\n }\n\n extractContext(action: AgentAction): PDLSSContext {\n const raw = action.raw as CodexPreToolUsePayload;\n return this.buildContext(raw, extractTarget(raw.tool_name, raw.tool_input ?? {}));\n }\n\n private buildContext(raw: CodexPreToolUsePayload, target: string): PDLSSContext {\n const toolName = raw.tool_name;\n const mcpPurpose = mapMcpTool(toolName);\n const purpose = mcpPurpose ?? mapToolToPurpose(toolName);\n const networkAccess = extractNetworkDomains(target);\n\n return {\n purpose,\n action: toolName,\n target,\n ...(networkAccess && { networkAccess }),\n metadata: {\n ...(raw.session_id && { sessionId: raw.session_id }),\n ...(raw.cwd && { cwd: raw.cwd }),\n ...(raw.permission_mode && { permissionMode: raw.permission_mode }),\n ...(raw.model && { model: raw.model }),\n platform: 'codex',\n },\n };\n }\n\n /**\n * Translate a gateway decision into hook stdout JSON.\n *\n * Returns null on ALLOW (silent — Codex's own approval flow stays in\n * charge) and on MANUAL_REVIEW in prompted permission modes (the\n * fall-through IS Codex's native prompt). MANUAL_REVIEW in dontAsk /\n * bypassPermissions escalates to deny — no prompt exists to catch it.\n */\n decisionToHookOutput(\n decision: VerificationDecision,\n permissionMode?: string\n ): CodexHookOutput | null {\n switch (decision.recommendation) {\n case 'DENY':\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'deny',\n permissionDecisionReason: `AstraSync Local Guard: ${decision.reason}`,\n },\n };\n case 'MANUAL_REVIEW':\n if (permissionMode && UNPROMPTED_PERMISSION_MODES.has(permissionMode)) {\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'deny',\n permissionDecisionReason:\n `AstraSync Local Guard requires approval: ${decision.reason} — ` +\n `denied because permission mode '${permissionMode}' would skip the approval prompt. ` +\n 'Re-run in a prompted mode to approve interactively.',\n },\n };\n }\n // Silent fall-through: Codex's native approval prompt is the HITL.\n return null;\n case 'ALLOW':\n return null;\n }\n }\n\n /**\n * Convenience for the hook entry: full payload → hook output (or null).\n *\n * apply_patch envelopes are evaluated per touched file (one context per\n * `*** Add/Update/Delete File:` header) and tightened to the worst\n * decision, so file.write blockedPatterns (including guard\n * self-protection) apply to every path in the patch.\n */\n async evaluatePayload(payload: CodexPreToolUsePayload): Promise<CodexHookOutput | null> {\n const action: AgentAction = {\n raw: payload,\n platform: 'codex',\n timestamp: new Date(),\n };\n\n const interception = await this.interceptAction(action);\n if (!interception.intercepted || !interception.context) {\n // Visible skip — ungoverned tools must show up in traces (see the\n // Claude Code adapter's PowerShell gap, found 10 Jul 2026).\n this.gateway.logSkippedTool(payload.tool_name, interception.skipReason ?? 'not intercepted');\n return null;\n }\n\n const decision = await this.evaluateInterceptedPayload(payload, interception.context);\n return this.decisionToHookOutput(decision, payload.permission_mode);\n }\n\n private async evaluateInterceptedPayload(\n payload: CodexPreToolUsePayload,\n context: PDLSSContext\n ): Promise<VerificationDecision> {\n const patchText =\n payload.tool_name === 'apply_patch'\n ? String(\n (payload.tool_input as Record<string, unknown>)?.command ??\n (payload.tool_input as Record<string, unknown>)?.patch ??\n ''\n )\n : '';\n const patchPaths = patchText ? extractApplyPatchPaths(patchText) : [];\n\n if (patchPaths.length === 0) {\n return this.gateway.evaluate(context);\n }\n\n // Worst decision across all touched paths wins.\n let worst: VerificationDecision | null = null;\n const rank = { ALLOW: 0, MANUAL_REVIEW: 1, DENY: 2 } as const;\n for (const path of patchPaths) {\n const decision = await this.gateway.evaluate(this.buildContext(payload, path));\n if (!worst || rank[decision.recommendation] > rank[worst.recommendation]) {\n worst = decision;\n }\n if (worst.recommendation === 'DENY') break;\n }\n return worst!;\n }\n\n /**\n * Enforcement happens via the stdout JSON the hook prints; there is no\n * in-process side to enforce on.\n */\n async enforceDecision(_decision: VerificationDecision): Promise<void> {\n // Contract no-op: Codex enforces based on the hook's stdout.\n }\n}\n","/**\n * AstraSync Local Guard for OpenAI Codex CLI — PreToolUse hook entry.\n *\n * Codex invokes this binary for each governed tool call, writing the\n * PreToolUse payload to stdin. The hook evaluates the call against the\n * local PDLSS policy (shared with the Claude Code adapter: same\n * ~/.astrasync/policy.yaml + guard.json) and prints a permissionDecision\n * JSON to stdout only when it wants to tighten the outcome (deny). On\n * ALLOW — and on MANUAL_REVIEW in prompted permission modes — it prints\n * nothing, so Codex's own approval flow stays in charge.\n *\n * Fail posture: Codex itself FAILS OPEN on hook errors (\"reports the error\n * and continues the tool call\"), so unlike the Claude Code hook we cannot\n * lean on exit codes alone — every internal failure is converted into an\n * explicit deny decision (opt-outs: ASTRASYNC_GUARD_FAIL_OPEN=1 or\n * guard.json {\"failOpen\": true}). A missing policy file everywhere means\n * the guard simply isn't configured — silent no-op, never a block.\n */\n\nimport { join } from 'path';\nimport { AstraSyncGateway } from '../gateway/gateway';\nimport { resolveGuardConfig } from '../claude-code/guard-config';\nimport { CodexAdapter } from './codex-adapter';\nimport type { CodexHookOutput, CodexPreToolUsePayload } from './codex-adapter';\n\nconst MAX_STDIN_BYTES = 1024 * 1024;\nconst STDIN_TIMEOUT_MS = 5000;\n\n/** Bounded sync-flush budget per hook invocation (mirrors the Claude Code hook). */\nconst HYBRID_FLUSH_LIMIT = 3;\nconst HYBRID_FLUSH_TIMEOUT_MS = 1500;\n\nexport interface ProcessCodexHookOptions {\n env?: NodeJS.ProcessEnv;\n home?: string;\n /** Injectable for tests */\n gatewayFactory?: (config: ConstructorParameters<typeof AstraSyncGateway>[0]) => AstraSyncGateway;\n}\n\nexport interface ProcessCodexHookResult {\n output: CodexHookOutput | null;\n exitCode: number;\n}\n\nfunction denyOutput(reason: string): CodexHookOutput {\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'deny',\n permissionDecisionReason: reason,\n },\n };\n}\n\nexport async function processCodexHookPayload(\n payloadJson: string,\n options: ProcessCodexHookOptions = {}\n): Promise<ProcessCodexHookResult> {\n const env = options.env ?? process.env;\n\n if (env.ASTRASYNC_GUARD_DISABLE === '1') {\n return { output: null, exitCode: 0 };\n }\n\n const envFailOpen = env.ASTRASYNC_GUARD_FAIL_OPEN === '1';\n\n let payload: CodexPreToolUsePayload;\n try {\n payload = JSON.parse(payloadJson) as CodexPreToolUsePayload;\n } catch {\n if (envFailOpen) return { output: null, exitCode: 0 };\n return {\n output: denyOutput('AstraSync Local Guard: could not parse hook payload'),\n exitCode: 0,\n };\n }\n\n const resolved = resolveGuardConfig(env, payload.cwd, options.home);\n if (!resolved) {\n // Guard not configured — never block an unconfigured machine.\n return { output: null, exitCode: 0 };\n }\n\n const failOpen = envFailOpen || resolved.settings.failOpen === true;\n\n try {\n let mode: 'local' | 'hybrid' = resolved.settings.mode === 'hybrid' ? 'hybrid' : 'local';\n if (mode === 'hybrid' && !(resolved.settings.apiBaseUrl && resolved.settings.apiKey)) {\n console.error(\n 'AstraSync Local Guard: guard.json requests hybrid mode but apiBaseUrl/apiKey are missing — running local-only'\n );\n mode = 'local';\n }\n\n const gatewayConfig = {\n mode,\n policyFile: resolved.policyFile,\n posture: resolved.settings.posture ?? 'active',\n traceEnabled: true,\n tracePath: join(resolved.guardDir, 'traces'),\n debug: false,\n ...(mode === 'hybrid' && {\n apiBaseUrl: resolved.settings.apiBaseUrl,\n apiKey: resolved.settings.apiKey,\n agentId: resolved.settings.agentId,\n }),\n };\n const gateway = options.gatewayFactory\n ? options.gatewayFactory(gatewayConfig)\n : new AstraSyncGateway(gatewayConfig);\n await gateway.initialize();\n\n const adapter = new CodexAdapter({\n ...(resolved.settings.skipTools && { skipTools: resolved.settings.skipTools }),\n ...(typeof resolved.settings.governMcp === 'boolean' && {\n governMcp: resolved.settings.governMcp,\n }),\n });\n await adapter.initialize({ gateway, adapterOptions: {} });\n\n const output = await adapter.evaluatePayload(payload);\n\n await adapter.shutdown();\n await gateway.shutdown({\n syncFlush: { limit: HYBRID_FLUSH_LIMIT, perEntryTimeoutMs: HYBRID_FLUSH_TIMEOUT_MS },\n });\n\n return { output, exitCode: 0 };\n } catch (err) {\n if (failOpen) return { output: null, exitCode: 0 };\n const detail = err instanceof Error ? err.message : String(err);\n // Explicit deny JSON, not just an exit code — Codex continues the tool\n // call on hook \"failures\", so the deny must be a valid decision.\n return {\n output: denyOutput(`AstraSync Local Guard: policy evaluation failed (${detail})`),\n exitCode: 0,\n };\n }\n}\n\n// -----------------------------------------------------------------------\n// Process entry\n// -----------------------------------------------------------------------\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve) => {\n const chunks: Buffer[] = [];\n let total = 0;\n let done = false;\n\n const finish = () => {\n if (done) return;\n done = true;\n clearTimeout(timer);\n resolve(Buffer.concat(chunks).toString('utf-8'));\n };\n\n const timer = setTimeout(finish, STDIN_TIMEOUT_MS);\n\n process.stdin.on('data', (chunk: Buffer) => {\n total += chunk.length;\n if (total > MAX_STDIN_BYTES) {\n // Oversized payload: replace with a non-JSON sentinel so the\n // parse step fails and the guard's fail posture decides.\n chunks.length = 0;\n chunks.push(Buffer.from('OVERSIZED_PAYLOAD'));\n finish();\n return;\n }\n chunks.push(chunk);\n });\n process.stdin.on('end', finish);\n process.stdin.on('error', finish);\n });\n}\n\nasync function main(): Promise<void> {\n // stdout is reserved for the hook decision JSON — route everything a\n // library might log to stderr instead.\n // eslint-disable-next-line no-console\n console.log = (...args: unknown[]) => console.error(...args);\n\n const payloadJson = await readStdin();\n const result = await processCodexHookPayload(payloadJson);\n\n if (result.output) {\n process.stdout.write(JSON.stringify(result.output));\n }\n process.exit(result.exitCode);\n}\n\n/* c8 ignore start */\nif (typeof require !== 'undefined' && require.main === module) {\n main().catch((err) => {\n // Last-resort: exit 2 is Codex's documented deny-with-stderr path, so\n // even a crash surfaces as a denial rather than Codex's fail-open.\n console.error(`AstraSync Local Guard hook crashed: ${err}`);\n process.exit(process.env.ASTRASYNC_GUARD_FAIL_OPEN === '1' ? 0 : 2);\n });\n}\n/* c8 ignore stop */\n","/**\n * AstraSync Gateway - Types for gateway modes, local evaluation, and adapter interface.\n */\n\n// ========================================================================\n// Gateway Configuration\n// ========================================================================\n\nexport type GatewayMode = 'online' | 'local' | 'hybrid';\n\n/**\n * Posture controls whether the gateway actively blocks or just monitors.\n * - active: Evaluate and enforce decisions (block/allow/review)\n * - passive: Evaluate and log but never block (telemetry-only mode)\n */\nexport type GatewayPosture = 'active' | 'passive';\n\nexport interface AstraSyncGatewayConfig {\n mode: GatewayMode;\n /** Enforcement posture: 'active' blocks actions, 'passive' logs only (default: 'active') */\n posture?: GatewayPosture;\n /** AstraSync API base URL (required for online/hybrid modes) */\n apiBaseUrl?: string;\n /** API key for authenticating with AstraSync (required for online/hybrid modes) */\n apiKey?: string;\n /**\n * ASTRA- agent id this gateway acts as. Attached to hybrid sync entries and\n * used as the default identity for online verification when the caller\n * passes no per-call astraId.\n */\n agentId?: string;\n /** Path to local PDLSS policy YAML file (required for local/hybrid modes) */\n policyFile?: string;\n /** Inline policy object (alternative to policyFile) */\n policy?: LocalPolicy;\n /** Sync interval in seconds for hybrid mode (default: 3600) */\n syncInterval?: number;\n /** Cache verification results TTL in seconds (default: 300) */\n cacheTtl?: number;\n /** Enable debug logging */\n debug?: boolean;\n /** Enable trace logging to .astrasync/traces/ (default: false) */\n traceEnabled?: boolean;\n /** Trace log directory (default: .astrasync/traces/) */\n tracePath?: string;\n /** Minimum trust score for standard access (online/hybrid) */\n minTrustScore?: number;\n /** Minimum trust score for full access (online/hybrid) */\n minTrustScoreForFull?: number;\n /** Custom headers to send with API requests */\n customHeaders?: Record<string, string>;\n /** Counterparty URL for analytics */\n counterpartyUrl?: string;\n /** Counterparty type for analytics */\n counterpartyType?: import('../types').CounterpartyType;\n}\n\n// ========================================================================\n// PDLSS Context (Agent-side action context)\n// ========================================================================\n\nexport interface PDLSSContext {\n /** Purpose category (e.g. email.send, shell.exec, file.read) */\n purpose: string;\n /** Specific action within purpose */\n action: string;\n /** Target resource, recipient, or counterparty */\n target: string;\n /** Types of data access (read, write, delete) */\n dataAccess?: string[];\n /** Network domains/IPs being accessed */\n networkAccess?: string[];\n /** Resource type (customer, order, file, directory, process) */\n resourceType?: string;\n /** Risk factors for this action */\n riskFactors?: RiskFactor[];\n /** Transaction value (if financial) */\n transactionValue?: number;\n /** Currency for transaction */\n currency?: string;\n /** Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\nexport interface RiskFactor {\n type: 'financial' | 'data_sensitivity' | 'privilege_escalation' | 'network_scope' | 'destructive';\n severity: 'low' | 'medium' | 'high' | 'critical';\n detail: string;\n}\n\n// ========================================================================\n// Verification Decision\n// ========================================================================\n\nexport interface VerificationDecision {\n recommendation: 'ALLOW' | 'DENY' | 'MANUAL_REVIEW';\n reason: string;\n trustScore?: number;\n tokenGuidance?: import('../types').TokenGuidance;\n sessionId?: string;\n /**\n * PDLSS dimensions that were evaluated. `true` = the dimension was\n * configured in the policy and therefore ran; `false` = the dimension is\n * absent from the policy and was skipped — NOT \"failed\" (a failed\n * dimension never produces an ALLOW; this field is only set on ALLOW).\n */\n evaluatedDimensions?: {\n purpose: boolean;\n scope: boolean;\n limits: boolean;\n riskThresholds: boolean;\n };\n}\n\n// ========================================================================\n// Local Policy Types (YAML format)\n// ========================================================================\n\nexport interface LocalPolicy {\n version: string;\n name: string;\n description?: string;\n purposes: LocalPurposeRule[];\n scope?: LocalScope;\n limits?: LocalLimits;\n riskThresholds?: LocalRiskThresholds;\n selfInstantiation?: LocalSelfInstantiation;\n}\n\nexport interface LocalPurposeRule {\n id: string;\n allowed: boolean;\n targets?: string[];\n blockedPatterns?: string[];\n requiresApproval?: boolean;\n}\n\nexport interface LocalScope {\n allowedDomains?: string[];\n blockedDomains?: string[];\n blockedResources?: string[];\n}\n\nexport interface LocalLimits {\n /**\n * Autonomous Limit — a transaction value at or below this is granted without\n * escalation. A value in the band `[autonomousThreshold, maxTransactionAmount)`\n * requires human approval (step-up → MANUAL_REVIEW), mirroring the backend\n * `checkWithinLimits` ladder. When omitted there is no autonomous band: every\n * positive value below the Hard Limit is granted (legacy flat-cap behaviour).\n */\n autonomousThreshold?: number;\n /**\n * Hard Limit — a transaction value at or above this is denied outright. (Named\n * `maxTransactionAmount` for backward compatibility with existing local policy\n * files; it is the SDK equivalent of the backend `approvalThreshold`.)\n */\n maxTransactionAmount?: number;\n maxRequestsPerHour?: number;\n currency?: string;\n}\n\nexport interface LocalRiskThresholds {\n autoAllow: { min: number; max: number };\n requireApproval: { min: number; max: number };\n autoBlock: { min: number; max: number };\n}\n\nexport interface LocalSelfInstantiation {\n /** Whether sub-agent spawning is allowed */\n allowed: boolean;\n /** Maximum depth of sub-agent chain */\n maxDepth?: number;\n}\n\n// ========================================================================\n// Risk Scoring Defaults (cherry-picked from trust-harness-core)\n// ========================================================================\n\n/** Base risk scores per action category */\nexport const BASE_RISK_SCORES: Record<string, number> = {\n 'file.read': 10,\n 'file.write': 40,\n 'file.delete': 70,\n 'shell.exec': 50,\n 'network.fetch': 60,\n 'network.request': 60,\n 'email.send': 45,\n 'email.read': 15,\n 'calendar.create': 20,\n 'calendar.modify': 30,\n 'database.query': 25,\n 'database.write': 55,\n 'payment.execute': 80,\n 'sub_agent.spawn': 65,\n 'code.execute': 45,\n};\n\n/** Shell commands that significantly increase risk score */\nexport const HIGH_RISK_COMMANDS = [\n 'rm',\n 'rmdir',\n 'dd',\n 'mkfs',\n 'chmod',\n 'chown',\n 'sudo',\n 'su',\n 'curl',\n 'wget',\n 'nc',\n 'netcat',\n 'ssh',\n 'scp',\n 'rsync',\n 'git push',\n 'npm publish',\n 'docker',\n 'kubectl',\n 'gh pr create',\n 'gh pr merge',\n];\n\n/** File paths that indicate sensitive data access */\nexport const SENSITIVE_PATHS = [\n '.ssh',\n '.aws',\n '.gnupg',\n '.env',\n 'credentials',\n 'secrets',\n 'password',\n '.git/config',\n '/etc',\n '/var',\n '/root',\n 'id_rsa',\n '.npmrc',\n '.pypirc',\n];\n\n// ========================================================================\n// Trace Event Types\n// ========================================================================\n\nexport interface TraceEvent {\n id: string;\n timestamp: Date;\n /**\n * 'skipped' records a tool call the guard saw but did NOT govern\n * (unmapped tool, MCP with governMcp off, skipTools). Added 10 Jul 2026\n * after an ungoverned-PowerShell gap hid behind silent skips — coverage\n * holes must be visible in passive observation.\n */\n type: 'evaluation' | 'decision' | 'error' | 'mode_switch' | 'skipped';\n context?: PDLSSContext;\n decision?: VerificationDecision;\n metadata?: Record<string, unknown>;\n}\n\n// ========================================================================\n// Adapter Interface Types\n// ========================================================================\n\nexport interface AdapterConfig {\n /** The gateway instance (handles mode routing) */\n gateway: unknown; // Typed as AstraSyncGateway at usage site to avoid circular deps\n /** Platform-specific configuration */\n adapterOptions: Record<string, unknown>;\n}\n\nexport interface AgentAction {\n /** Raw action data from the platform */\n raw: unknown;\n /** Platform identifier (e.g. 'openclaw-cli', 'cursor', 'browser') */\n platform: string;\n /** Timestamp of the action */\n timestamp: Date;\n}\n\nexport interface InterceptResult {\n /** Whether the action was intercepted */\n intercepted: boolean;\n /** Extracted PDLSS context (if intercepted) */\n context?: PDLSSContext;\n /** Reason for not intercepting (if not intercepted) */\n skipReason?: string;\n}\n\n// ========================================================================\n// Sync Queue Types (Hybrid mode)\n// ========================================================================\n\nexport interface SyncQueueEntry {\n id: string;\n context: PDLSSContext;\n decision: VerificationDecision;\n timestamp: Date;\n retryCount: number;\n status: 'pending' | 'synced' | 'failed';\n}\n","/**\n * Command-position matching for high-risk shell commands.\n *\n * Replaces the substring-based HIGH_RISK_COMMANDS check that flagged any\n * command merely *containing* a high-risk name (` su` matched \"superadmin\",\n * quoted text and heredoc bodies triggered). A high-risk entry now matches\n * only when it is the invoked command of some pipeline/list segment.\n *\n * Deliberately NOT a shell parser — pure regex/token splitting inside the\n * hook's latency budget. Known accepted misses: option arguments that survive\n * flag filtering (`git -C /tmp push`), exotic quoting/escapes.\n */\n\nimport { HIGH_RISK_COMMANDS } from '../gateway/types';\n\n/** Wrapper commands that prefix the real command; hop over them and re-check. */\nconst WRAPPERS = new Set([\n 'sudo',\n 'doas',\n 'env',\n 'nohup',\n 'time',\n 'timeout',\n 'nice',\n 'ionice',\n 'stdbuf',\n 'xargs',\n 'command',\n 'exec',\n 'builtin',\n]);\n\n/** Leading environment assignment, e.g. `FOO=bar cmd` (input is lowercased). */\nconst ASSIGN_RE = /^[a-z_][a-z0-9_]*=/;\n\nconst MAX_WRAPPER_HOPS = 4;\nconst MAX_RECURSION_DEPTH = 3;\nconst MAX_COMMAND_LENGTH = 100_000;\n\n/** Hosts considered local for the curl/wget risk downgrade (brackets pre-stripped). */\nconst LOCAL_HOST_RE = /^(localhost|127\\.0\\.0\\.1|::1|[a-z0-9.-]*\\.localhost)$/;\n\ninterface RiskList {\n singleWord: Set<string>;\n /** Sorted longest-first so `gh pr create` wins over a shorter prefix entry. */\n multiWord: string[][];\n}\n\nfunction buildRiskList(entries: readonly string[]): RiskList {\n const singleWord = new Set<string>();\n const multiWord: string[][] = [];\n for (const entry of entries) {\n const words = entry.toLowerCase().trim().split(/\\s+/);\n if (words.length === 1) singleWord.add(words[0]);\n else multiWord.push(words);\n }\n multiWord.sort((a, b) => b.length - a.length);\n return { singleWord, multiWord };\n}\n\n/** Drop heredoc bodies (`<<TAG` … `TAG`) — stdin text, not executed commands. */\nfunction stripHeredocBodies(text: string): string {\n const lines = text.split('\\n');\n const kept: string[] = [];\n let terminator: string | null = null;\n for (const line of lines) {\n if (terminator !== null) {\n if (line.trim() === terminator) terminator = null;\n continue;\n }\n kept.push(line);\n const heredoc = line.match(/<<-?\\s*['\"]?(\\w+)['\"]?/);\n if (heredoc) terminator = heredoc[1];\n }\n return kept.join('\\n');\n}\n\n/**\n * Pull out `$(…)` command substitutions (recursing into their contents via\n * `collect`) and blank their spans. No quote awareness inside the parens —\n * pragmatic depth counting only.\n */\nfunction extractDollarSubstitutions(text: string, collect: (inner: string) => void): string {\n let result = text;\n let start = result.indexOf('$(');\n let iterations = 0;\n while (start !== -1 && iterations < 50) {\n iterations++;\n let depth = 0;\n let end = result.length;\n for (let i = start + 1; i < result.length; i++) {\n if (result[i] === '(') depth++;\n else if (result[i] === ')') {\n depth--;\n if (depth === 0) {\n end = i;\n break;\n }\n }\n }\n collect(result.slice(start + 2, end));\n result = `${result.slice(0, start)} ${result.slice(Math.min(end + 1, result.length))}`;\n start = result.indexOf('$(');\n }\n return result;\n}\n\n/** Pull out backtick substitutions (odd chunks when split on `) and blank them. */\nfunction extractBacktickSubstitutions(text: string, collect: (inner: string) => void): string {\n if (!text.includes('`')) return text;\n const chunks = text.split('`');\n const kept: string[] = [];\n for (let i = 0; i < chunks.length; i++) {\n if (i % 2 === 1) collect(chunks[i]);\n else kept.push(chunks[i]);\n }\n return kept.join(' ');\n}\n\n/**\n * Reduce a command token to its matchable name: strip any leading path\n * (both separator styles — PowerShell targets arrive with backslashes) and\n * a trailing Windows executable extension, so `C:\\Tools\\curl.exe` and\n * `curl.exe` both match the `curl` high-risk entry.\n */\nfunction basename(token: string): string {\n const slash = Math.max(token.lastIndexOf('/'), token.lastIndexOf('\\\\'));\n const name = slash === -1 ? token : token.slice(slash + 1);\n return name.replace(/\\.(exe|cmd|bat|ps1)$/i, '');\n}\n\nfunction matchSegment(segment: string, list: RiskList): string | null {\n const tokens = segment.split(/\\s+/).filter((t) => /[a-z0-9]/.test(t));\n let i = 0;\n let hops = 0;\n while (i < tokens.length) {\n // Skip `export` and leading env assignments to reach the command position.\n while (i < tokens.length && (tokens[i] === 'export' || ASSIGN_RE.test(tokens[i]))) i++;\n if (i >= tokens.length) return null;\n\n const cmd = basename(tokens[i]);\n\n // Multi-word entries match against the leading non-flag tokens.\n const significant = [cmd, ...tokens.slice(i + 1).filter((t) => !t.startsWith('-'))];\n for (const entry of list.multiWord) {\n if (entry.length <= significant.length && entry.every((w, j) => significant[j] === w)) {\n return entry.join(' ');\n }\n }\n if (list.singleWord.has(cmd)) return cmd;\n\n // High-risk check ran first, so `sudo …` matches `sudo` before hopping.\n if (WRAPPERS.has(cmd) && hops < MAX_WRAPPER_HOPS) {\n hops++;\n i++;\n while (i < tokens.length && (tokens[i].startsWith('-') || ASSIGN_RE.test(tokens[i]))) i++;\n continue;\n }\n return null;\n }\n return null;\n}\n\nfunction collectMatches(\n command: string,\n list: RiskList,\n matches: Set<string>,\n depth: number\n): void {\n if (depth > MAX_RECURSION_DEPTH || command.length > MAX_COMMAND_LENGTH) return;\n\n let text = command.toLowerCase();\n text = stripHeredocBodies(text);\n\n // Substitutions are extracted (and their contents checked) BEFORE quote\n // stripping so `\"$(curl x)\"` is still evaluated in command position.\n const recurse = (inner: string) => collectMatches(inner, list, matches, depth + 1);\n text = extractDollarSubstitutions(text, recurse);\n text = extractBacktickSubstitutions(text, recurse);\n\n // Quoted spans are data, not commands; `#` comments are noise.\n text = text.replace(/'[^']*'/g, ' ').replace(/\"[^\"]*\"/g, ' ');\n text = text.replace(/(^|\\s)#[^\\n]*/g, ' ');\n\n const segments = text.split(/\\|\\||&&|[;|&\\n]|[({]/);\n for (const segment of segments) {\n const matched = matchSegment(segment, list);\n if (matched) matches.add(matched);\n }\n}\n\n/**\n * Returns every high-risk entry invoked in command position anywhere in\n * `command` (deduplicated), or an empty array.\n */\nexport function matchHighRiskCommands(\n command: string,\n highRiskCommands: readonly string[] = HIGH_RISK_COMMANDS\n): string[] {\n if (!command) return [];\n const matches = new Set<string>();\n collectMatches(command, buildRiskList(highRiskCommands), matches, 0);\n return [...matches];\n}\n\n/**\n * Returns the first high-risk entry invoked in command position, or null.\n * Convenience wrapper over {@link matchHighRiskCommands}.\n */\nexport function matchHighRiskCommand(\n command: string,\n highRiskCommands: readonly string[] = HIGH_RISK_COMMANDS\n): string | null {\n return matchHighRiskCommands(command, highRiskCommands)[0] ?? null;\n}\n\n/**\n * True when the command's network destinations are exclusively local\n * (localhost / 127.0.0.1 / ::1 / *.localhost) AND at least one destination is\n * present. Used to skip the risk-80 bump for curl/wget dev-loop probes.\n * Unparseable or absent destinations keep the bump (fail toward review).\n */\nexport function isLocalhostOnlyNetworkCommand(command: string): boolean {\n const text = command.toLowerCase();\n // Candidate destinations: explicit URLs, host:port tokens, or bare local hosts.\n const tokens = text.split(/\\s+/).map((t) => t.replace(/^[\"'`]+|[\"'`,;)]+$/g, ''));\n let localCount = 0;\n for (const token of tokens) {\n let host: string | null = null;\n if (token.includes('://')) {\n let rest = token.slice(token.indexOf('://') + 3);\n const at = rest.indexOf('@');\n if (at !== -1) rest = rest.slice(at + 1);\n host = rest.split(/[/?#]/)[0];\n } else if (/^[a-z0-9.[\\]:-]+:\\d+(\\/.*)?$/.test(token)) {\n host = token.split('/')[0];\n } else if (/^(localhost|127\\.0\\.0\\.1|\\[?::1\\]?)(\\/.*)?$/.test(token)) {\n host = token.split('/')[0];\n }\n if (host === null) continue;\n // Strip a trailing numeric port, then IPv6 brackets ([::1]:3000 → ::1).\n const bare = host.replace(/:\\d+$/, '').replace(/^\\[|\\]$/g, '');\n if (LOCAL_HOST_RE.test(bare)) {\n localCount++;\n } else {\n return false;\n }\n }\n return localCount > 0;\n}\n","/**\n * Local PDLSS Evaluator\n *\n * Evaluates agent actions against a local PDLSS policy.\n * Same logic as the cloud evaluator but runs in-process with no I/O.\n *\n * Evaluation order:\n * 1. Purpose: find matching rule, check if allowed\n * 2. Purpose: check allowed targets (if specified)\n * 3. Purpose: check blocked patterns (if specified)\n * 4. Scope: check global blocked resources/domains\n * 5. Limits: check transaction/rate limits\n * 6. Risk thresholds + approval requirements\n */\n\nimport type {\n LocalPolicy,\n PDLSSContext,\n VerificationDecision,\n LocalPurposeRule,\n} from '../gateway/types';\nimport { SENSITIVE_PATHS } from '../gateway/types';\nimport { matchHighRiskCommands, isLocalhostOnlyNetworkCommand } from './command-matcher';\n\nexport class LocalEvaluator {\n private policy: LocalPolicy;\n private requestCounts: Map<string, { count: number; windowStart: number }> = new Map();\n\n constructor(policy: LocalPolicy) {\n this.policy = policy;\n }\n\n /**\n * Update the policy (e.g. after hot-reload or sync).\n */\n updatePolicy(policy: LocalPolicy): void {\n this.policy = policy;\n }\n\n /**\n * Evaluate an action context against the loaded policy.\n */\n evaluate(context: PDLSSContext): VerificationDecision {\n // 1. Purpose: find matching rule\n const purposeRule = this.policy.purposes.find((p) => p.id === context.purpose);\n if (!purposeRule) {\n return { recommendation: 'DENY', reason: 'Purpose not in policy' };\n }\n if (!purposeRule.allowed) {\n return { recommendation: 'DENY', reason: 'Purpose explicitly blocked' };\n }\n\n // 2. Purpose: check allowed targets\n if (purposeRule.targets && !this.matchesAnyPattern(context.target, purposeRule.targets)) {\n return { recommendation: 'DENY', reason: 'Target not in allowed list' };\n }\n\n // 3. Purpose: check blocked patterns\n if (\n purposeRule.blockedPatterns &&\n this.matchesAnyPattern(context.target, purposeRule.blockedPatterns)\n ) {\n return { recommendation: 'DENY', reason: 'Target matches blocked pattern' };\n }\n\n // 4. Scope: check global blocked resources/domains\n const scopeBlock = this.checkScopeBlock(context);\n if (scopeBlock) {\n return { recommendation: 'DENY', reason: scopeBlock };\n }\n\n // 5. Limits: check transaction (autonomous/hard band) and rate limits\n const limitDecision = this.checkLimits(context);\n if (limitDecision) {\n return limitDecision;\n }\n\n // 6. Self-instantiation: check sub-agent spawning rules\n if (context.purpose === 'sub_agent.spawn' && this.policy.selfInstantiation) {\n if (!this.policy.selfInstantiation.allowed) {\n return { recommendation: 'DENY', reason: 'Sub-agent spawning is not allowed' };\n }\n const depth = (context.metadata?.subAgentDepth as number) || 0;\n if (\n this.policy.selfInstantiation.maxDepth !== undefined &&\n depth >= this.policy.selfInstantiation.maxDepth\n ) {\n return {\n recommendation: 'DENY',\n reason: `Sub-agent depth ${depth} exceeds max depth ${this.policy.selfInstantiation.maxDepth}`,\n };\n }\n }\n\n // 7. Risk thresholds + approval requirements\n if (purposeRule.requiresApproval) {\n return { recommendation: 'MANUAL_REVIEW', reason: 'Purpose requires approval' };\n }\n\n const riskDecision = this.checkRiskThresholds(context);\n if (riskDecision) {\n return riskDecision;\n }\n\n return {\n recommendation: 'ALLOW',\n // \"evaluated\": dimensions absent from the policy are skipped, not\n // failed — evaluatedDimensions below records which ones ran.\n reason: 'All evaluated PDLSS checks passed',\n evaluatedDimensions: {\n purpose: true,\n scope: !!this.policy.scope,\n limits: !!this.policy.limits,\n riskThresholds: !!this.policy.riskThresholds,\n },\n };\n }\n\n private checkScopeBlock(context: PDLSSContext): string | null {\n const scope = this.policy.scope;\n if (!scope) return null;\n\n // Check blocked domains against target and network access\n if (scope.blockedDomains) {\n const targetDomain = this.extractDomain(context.target);\n if (this.matchesAnyPattern(targetDomain, scope.blockedDomains)) {\n return `Target blocked by scope: ${context.target}`;\n }\n if (context.networkAccess) {\n for (const domain of context.networkAccess) {\n if (this.matchesAnyPattern(this.extractDomain(domain), scope.blockedDomains)) {\n return `Domain blocked by scope: ${domain}`;\n }\n }\n }\n }\n\n // Check blocked resources against target\n if (scope.blockedResources && this.matchesAnyPattern(context.target, scope.blockedResources)) {\n return `Resource blocked by scope: ${context.target}`;\n }\n\n // Check allowed domains (if specified, target must match)\n if (scope.allowedDomains && context.networkAccess) {\n for (const domain of context.networkAccess) {\n if (!this.matchesAnyPattern(this.extractDomain(domain), scope.allowedDomains)) {\n return `Domain not in allowed list: ${domain}`;\n }\n }\n }\n\n return null;\n }\n\n private checkLimits(context: PDLSSContext): VerificationDecision | null {\n const limits = this.policy.limits;\n if (!limits) return null;\n\n // Transaction-value ladder — parity with the backend `checkWithinLimits`:\n // A = Autonomous Limit (autonomousThreshold, default 0)\n // H = Hard Limit (maxTransactionAmount; falls back to A when only the\n // Autonomous Limit is declared)\n // value <= A -> autonomous (falls through — rate check still applies)\n // A < value < H -> MANUAL_REVIEW (step-up / human approval)\n // value >= H -> DENY\n // The ladder only runs when the policy declares at least one threshold; a\n // limits block with only a currency/rate cap imposes no transaction ceiling.\n const value = context.transactionValue;\n if (\n value !== undefined &&\n value > 0 &&\n (limits.autonomousThreshold !== undefined || limits.maxTransactionAmount !== undefined)\n ) {\n const autonomousThreshold = limits.autonomousThreshold ?? 0;\n const hardLimit = limits.maxTransactionAmount ?? limits.autonomousThreshold ?? 0;\n if (value > autonomousThreshold) {\n if (value >= hardLimit) {\n return {\n recommendation: 'DENY',\n reason: `Transaction value ${value} at or above Hard Limit ${hardLimit}`,\n };\n }\n return {\n recommendation: 'MANUAL_REVIEW',\n reason: `Transaction value ${value} is in the human-approval band (${autonomousThreshold}, ${hardLimit})`,\n };\n }\n }\n\n // Rate limit check\n if (limits.maxRequestsPerHour !== undefined) {\n const key = context.purpose;\n const now = Date.now();\n const entry = this.requestCounts.get(key);\n const hourMs = 3600000;\n\n if (!entry || now - entry.windowStart > hourMs) {\n this.requestCounts.set(key, { count: 1, windowStart: now });\n } else {\n entry.count++;\n if (entry.count > limits.maxRequestsPerHour) {\n return {\n recommendation: 'DENY',\n reason: `Rate limit exceeded: ${entry.count}/${limits.maxRequestsPerHour} requests per hour`,\n };\n }\n }\n }\n\n return null;\n }\n\n private checkRiskThresholds(context: PDLSSContext): VerificationDecision | null {\n if (!this.policy.riskThresholds) return null;\n\n const riskScore = this.calculateRiskScore(context);\n const thresholds = this.policy.riskThresholds;\n\n if (riskScore >= thresholds.autoBlock.min) {\n return { recommendation: 'DENY', reason: `Risk score ${riskScore} exceeds block threshold` };\n }\n\n if (riskScore >= thresholds.requireApproval.min) {\n return {\n recommendation: 'MANUAL_REVIEW',\n reason: `Risk score ${riskScore} requires approval`,\n };\n }\n\n return null;\n }\n\n private calculateRiskScore(context: PDLSSContext): number {\n let score = 0;\n\n // Explicit risk factors take priority (highest severity wins)\n if (context.riskFactors?.length) {\n const severityScores: Record<string, number> = {\n low: 10,\n medium: 40,\n high: 70,\n critical: 90,\n };\n\n for (const factor of context.riskFactors) {\n const factorScore = severityScores[factor.severity] || 0;\n if (factorScore > score) score = factorScore;\n }\n return score;\n }\n\n // Auto-detect risk from high-risk shell commands (command-position match,\n // not substring). curl/wget aimed exclusively at localhost stay below the\n // review threshold — dev-loop probes, not exfiltration surface.\n if (context.purpose === 'shell.exec' && context.target) {\n const matched = matchHighRiskCommands(context.target);\n const localProbeOnly =\n matched.length > 0 &&\n matched.every((cmd) => cmd === 'curl' || cmd === 'wget') &&\n isLocalhostOnlyNetworkCommand(context.target);\n if (matched.length > 0 && !localProbeOnly) {\n score = Math.max(score, 80);\n }\n }\n\n // Auto-detect risk from sensitive file paths (score 50 = review range).\n // Separators normalized so entries containing '/' (e.g. '.git/config')\n // match Windows backslash targets — same class as the matchGlob fix.\n if (\n (context.purpose === 'file.read' ||\n context.purpose === 'file.write' ||\n context.purpose === 'file.delete') &&\n context.target\n ) {\n const targetLower = context.target.toLowerCase().replace(/\\\\/g, '/');\n for (const sensitivePath of SENSITIVE_PATHS) {\n if (targetLower.includes(sensitivePath.toLowerCase())) {\n score = Math.max(score, 50);\n break;\n }\n }\n }\n\n return score;\n }\n\n /**\n * Extract domain from a URL-like string (strips protocol and path).\n */\n private extractDomain(value: string): string {\n let domain = value;\n // Strip protocol\n const protoIndex = domain.indexOf('://');\n if (protoIndex !== -1) domain = domain.slice(protoIndex + 3);\n // Strip path\n const slashIndex = domain.indexOf('/');\n if (slashIndex !== -1) domain = domain.slice(0, slashIndex);\n // Strip port\n const colonIndex = domain.indexOf(':');\n if (colonIndex !== -1) domain = domain.slice(0, colonIndex);\n return domain;\n }\n\n /**\n * Check if a value matches any of the given glob patterns.\n */\n private matchesAnyPattern(value: string, patterns: string[]): boolean {\n return patterns.some((pattern) => this.matchGlob(value, pattern));\n }\n\n /**\n * Simple glob pattern matching.\n * Supports * (matches any characters including / and spaces) and ? (single char).\n * Uses the same approach as the backend's matchGlobPattern.\n */\n /**\n * Home directory as a forward-slash prefix for `~` pattern expansion,\n * resolved from the environment WITHOUT importing `os` (this evaluator\n * also runs bundled inside the browser extension, where node builtins\n * don't exist — there `~` patterns stay literal, which is correct since\n * browser targets are URLs). Cached per instance.\n */\n private cachedHomePrefix: string | null | undefined;\n\n private homePrefix(): string | null {\n if (this.cachedHomePrefix !== undefined) return this.cachedHomePrefix;\n const env = typeof process !== 'undefined' ? process.env : undefined;\n const home = env?.HOME || env?.USERPROFILE;\n this.cachedHomePrefix = home ? home.replace(/\\\\/g, '/') : null;\n return this.cachedHomePrefix;\n }\n\n private matchGlob(value: string, pattern: string): boolean {\n // Two live bypasses found 11 Jul 2026 (Windows desktop verification):\n // 1. Windows targets arrive with backslashes (C:\\Users\\...\\settings.json)\n // and never matched forward-slash glob patterns — EVERY file-path\n // protection was dead on native Windows. Normalize separators on\n // both sides so Windows-authored patterns keep working too.\n // 2. `~/...` patterns were never expanded, so the default policy's\n // credential-path protections (~/.ssh/*, ~/.aws/*) matched nothing\n // on ANY platform. Expand a leading `~` to the home directory.\n value = value.replace(/\\\\/g, '/');\n pattern = pattern.replace(/\\\\/g, '/');\n if (pattern === '~' || pattern.startsWith('~/')) {\n const home = this.homePrefix();\n if (home) pattern = home + pattern.slice(1);\n }\n\n // Exact match\n if (pattern === value) return true;\n\n // Audit F-A1-13: ReDoS guard. Patterns with too many `*` segments\n // produce catastrophic-backtracking regexes (e.g. `a*a*a*a*a*a*a*a*b`\n // against `aaaaaaaa` runs in exponential time). Local policies are\n // operator-controlled so attacker access requires operator-side\n // compromise, but a copy-pasted-from-internet example pattern could\n // still DoS the gateway when matched against request input.\n const starCount = (pattern.match(/\\*/g) ?? []).length;\n if (starCount > 8) {\n return false;\n }\n\n // Convert glob to regex\n const regexStr = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&') // Escape special regex chars (except * and ?)\n .replace(/\\*/g, '.*') // * matches anything\n .replace(/\\?/g, '.'); // ? matches single char\n\n try {\n return new RegExp(`^${regexStr}$`, 'i').test(value);\n } catch {\n return false;\n }\n }\n}\n\n/**\n * Convenience: find a matching purpose rule.\n */\nexport function findPurposeRule(\n policy: LocalPolicy,\n purposeId: string\n): LocalPurposeRule | undefined {\n return policy.purposes.find((p) => p.id === purposeId);\n}\n","'use strict'\n\nfunction isNothing (subject) {\n return (typeof subject === 'undefined') || (subject === null)\n}\n\nfunction isObject (subject) {\n return (typeof subject === 'object') && (subject !== null)\n}\n\nfunction toArray (sequence) {\n if (Array.isArray(sequence)) return sequence\n else if (isNothing(sequence)) return []\n\n return [sequence]\n}\n\nfunction extend (target, source) {\n if (source) {\n const sourceKeys = Object.keys(source)\n\n for (let index = 0, length = sourceKeys.length; index < length; index += 1) {\n const key = sourceKeys[index]\n target[key] = source[key]\n }\n }\n\n return target\n}\n\nfunction repeat (string, count) {\n let result = ''\n\n for (let cycle = 0; cycle < count; cycle += 1) {\n result += string\n }\n\n return result\n}\n\nfunction isNegativeZero (number) {\n return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number)\n}\n\nmodule.exports.isNothing = isNothing\nmodule.exports.isObject = isObject\nmodule.exports.toArray = toArray\nmodule.exports.repeat = repeat\nmodule.exports.isNegativeZero = isNegativeZero\nmodule.exports.extend = extend\n","// YAML error class. http://stackoverflow.com/questions/8458984\n//\n'use strict'\n\nfunction formatError (exception, compact) {\n let where = ''\n const message = exception.reason || '(unknown reason)'\n\n if (!exception.mark) return message\n\n if (exception.mark.name) {\n where += 'in \"' + exception.mark.name + '\" '\n }\n\n where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')'\n\n if (!compact && exception.mark.snippet) {\n where += '\\n\\n' + exception.mark.snippet\n }\n\n return message + ' ' + where\n}\n\nfunction YAMLException (reason, mark) {\n // Super constructor\n Error.call(this)\n\n this.name = 'YAMLException'\n this.reason = reason\n this.mark = mark\n this.message = formatError(this, false)\n\n // Include stack trace in error object\n if (Error.captureStackTrace) {\n // Chrome and NodeJS\n Error.captureStackTrace(this, this.constructor)\n } else {\n // FF, IE 10+ and Safari 6+. Fallback for others\n this.stack = (new Error()).stack || ''\n }\n}\n\n// Inherit from Error\nYAMLException.prototype = Object.create(Error.prototype)\nYAMLException.prototype.constructor = YAMLException\n\nYAMLException.prototype.toString = function toString (compact) {\n return this.name + ': ' + formatError(this, compact)\n}\n\nmodule.exports = YAMLException\n","'use strict'\n\nconst common = require('./common')\n\n// get snippet for a single line, respecting maxLength\nfunction getLine (buffer, lineStart, lineEnd, position, maxLineLength) {\n let head = ''\n let tail = ''\n const maxHalfLength = Math.floor(maxLineLength / 2) - 1\n\n if (position - lineStart > maxHalfLength) {\n head = ' ... '\n lineStart = position - maxHalfLength + head.length\n }\n\n if (lineEnd - position > maxHalfLength) {\n tail = ' ...'\n lineEnd = position + maxHalfLength - tail.length\n }\n\n return {\n str: head + buffer.slice(lineStart, lineEnd).replace(/\\t/g, '→') + tail,\n pos: position - lineStart + head.length // relative position\n }\n}\n\nfunction padStart (string, max) {\n return common.repeat(' ', max - string.length) + string\n}\n\nfunction makeSnippet (mark, options) {\n options = Object.create(options || null)\n\n if (!mark.buffer) return null\n\n if (!options.maxLength) options.maxLength = 79\n if (typeof options.indent !== 'number') options.indent = 1\n if (typeof options.linesBefore !== 'number') options.linesBefore = 3\n if (typeof options.linesAfter !== 'number') options.linesAfter = 2\n\n const re = /\\r?\\n|\\r|\\0/g\n const lineStarts = [0]\n const lineEnds = []\n let match\n let foundLineNo = -1\n\n while ((match = re.exec(mark.buffer))) {\n lineEnds.push(match.index)\n lineStarts.push(match.index + match[0].length)\n\n if (mark.position <= match.index && foundLineNo < 0) {\n foundLineNo = lineStarts.length - 2\n }\n }\n\n if (foundLineNo < 0) foundLineNo = lineStarts.length - 1\n\n let result = ''\n const lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length\n const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3)\n\n for (let i = 1; i <= options.linesBefore; i++) {\n if (foundLineNo - i < 0) break\n const line = getLine(\n mark.buffer,\n lineStarts[foundLineNo - i],\n lineEnds[foundLineNo - i],\n mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),\n maxLineLength\n )\n result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) +\n ' | ' + line.str + '\\n' + result\n }\n\n const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength)\n result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) +\n ' | ' + line.str + '\\n'\n result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\\n'\n\n for (let i = 1; i <= options.linesAfter; i++) {\n if (foundLineNo + i >= lineEnds.length) break\n const line = getLine(\n mark.buffer,\n lineStarts[foundLineNo + i],\n lineEnds[foundLineNo + i],\n mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),\n maxLineLength\n )\n result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) +\n ' | ' + line.str + '\\n'\n }\n\n return result.replace(/\\n$/, '')\n}\n\nmodule.exports = makeSnippet\n","'use strict'\n\nconst YAMLException = require('./exception')\n\nconst TYPE_CONSTRUCTOR_OPTIONS = [\n 'kind',\n 'multi',\n 'resolve',\n 'construct',\n 'instanceOf',\n 'predicate',\n 'represent',\n 'representName',\n 'defaultStyle',\n 'styleAliases'\n]\n\nconst YAML_NODE_KINDS = [\n 'scalar',\n 'sequence',\n 'mapping'\n]\n\nfunction compileStyleAliases (map) {\n const result = {}\n\n if (map !== null) {\n Object.keys(map).forEach(function (style) {\n map[style].forEach(function (alias) {\n result[String(alias)] = style\n })\n })\n }\n\n return result\n}\n\nfunction Type (tag, options) {\n options = options || {}\n\n Object.keys(options).forEach(function (name) {\n if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {\n throw new YAMLException('Unknown option \"' + name + '\" is met in definition of \"' + tag + '\" YAML type.')\n }\n })\n\n // TODO: Add tag format check.\n this.options = options // keep original options in case user wants to extend this type later\n this.tag = tag\n this.kind = options['kind'] || null\n this.resolve = options['resolve'] || function () { return true }\n this.construct = options['construct'] || function (data) { return data }\n this.instanceOf = options['instanceOf'] || null\n this.predicate = options['predicate'] || null\n this.represent = options['represent'] || null\n this.representName = options['representName'] || null\n this.defaultStyle = options['defaultStyle'] || null\n this.multi = options['multi'] || false\n this.styleAliases = compileStyleAliases(options['styleAliases'] || null)\n\n if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {\n throw new YAMLException('Unknown kind \"' + this.kind + '\" is specified for \"' + tag + '\" YAML type.')\n }\n}\n\nmodule.exports = Type\n","'use strict'\n\nconst YAMLException = require('./exception')\nconst Type = require('./type')\n\nfunction compileList (schema, name) {\n const result = []\n\n schema[name].forEach(function (currentType) {\n let newIndex = result.length\n\n result.forEach(function (previousType, previousIndex) {\n if (previousType.tag === currentType.tag &&\n previousType.kind === currentType.kind &&\n previousType.multi === currentType.multi) {\n newIndex = previousIndex\n }\n })\n\n result[newIndex] = currentType\n })\n\n return result\n}\n\nfunction compileMap (/* lists... */) {\n const result = {\n scalar: {},\n sequence: {},\n mapping: {},\n fallback: {},\n multi: {\n scalar: [],\n sequence: [],\n mapping: [],\n fallback: []\n }\n }\n function collectType (type) {\n if (type.multi) {\n result.multi[type.kind].push(type)\n result.multi['fallback'].push(type)\n } else {\n result[type.kind][type.tag] = result['fallback'][type.tag] = type\n }\n }\n\n for (let index = 0, length = arguments.length; index < length; index += 1) {\n arguments[index].forEach(collectType)\n }\n return result\n}\n\nfunction Schema (definition) {\n return this.extend(definition)\n}\n\nSchema.prototype.extend = function extend (definition) {\n let implicit = []\n let explicit = []\n\n if (definition instanceof Type) {\n // Schema.extend(type)\n explicit.push(definition)\n } else if (Array.isArray(definition)) {\n // Schema.extend([ type1, type2, ... ])\n explicit = explicit.concat(definition)\n } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {\n // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] })\n if (definition.implicit) implicit = implicit.concat(definition.implicit)\n if (definition.explicit) explicit = explicit.concat(definition.explicit)\n } else {\n throw new YAMLException('Schema.extend argument should be a Type, [ Type ], ' +\n 'or a schema definition ({ implicit: [...], explicit: [...] })')\n }\n\n implicit.forEach(function (type) {\n if (!(type instanceof Type)) {\n throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')\n }\n\n if (type.loadKind && type.loadKind !== 'scalar') {\n throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.')\n }\n\n if (type.multi) {\n throw new YAMLException('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.')\n }\n })\n\n explicit.forEach(function (type) {\n if (!(type instanceof Type)) {\n throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')\n }\n })\n\n const result = Object.create(Schema.prototype)\n\n result.implicit = (this.implicit || []).concat(implicit)\n result.explicit = (this.explicit || []).concat(explicit)\n\n result.compiledImplicit = compileList(result, 'implicit')\n result.compiledExplicit = compileList(result, 'explicit')\n result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit)\n\n return result\n}\n\nmodule.exports = Schema\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:str', {\n kind: 'scalar',\n construct: function (data) { return data !== null ? data : '' }\n})\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:seq', {\n kind: 'sequence',\n construct: function (data) { return data !== null ? data : [] }\n})\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:map', {\n kind: 'mapping',\n construct: function (data) { return data !== null ? data : {} }\n})\n","// Standard YAML's Failsafe schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2802346\n\n'use strict'\n\nconst Schema = require('../schema')\n\nmodule.exports = new Schema({\n explicit: [\n require('../type/str'),\n require('../type/seq'),\n require('../type/map')\n ]\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlNull (data) {\n if (data === null) return true\n\n const max = data.length\n\n return (max === 1 && data === '~') ||\n (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'))\n}\n\nfunction constructYamlNull () {\n return null\n}\n\nfunction isNull (object) {\n return object === null\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:null', {\n kind: 'scalar',\n resolve: resolveYamlNull,\n construct: constructYamlNull,\n predicate: isNull,\n represent: {\n canonical: function () { return '~' },\n lowercase: function () { return 'null' },\n uppercase: function () { return 'NULL' },\n camelcase: function () { return 'Null' },\n empty: function () { return '' }\n },\n defaultStyle: 'lowercase'\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlBoolean (data) {\n if (data === null) return false\n\n const max = data.length\n\n return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||\n (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'))\n}\n\nfunction constructYamlBoolean (data) {\n return data === 'true' ||\n data === 'True' ||\n data === 'TRUE'\n}\n\nfunction isBoolean (object) {\n return Object.prototype.toString.call(object) === '[object Boolean]'\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:bool', {\n kind: 'scalar',\n resolve: resolveYamlBoolean,\n construct: constructYamlBoolean,\n predicate: isBoolean,\n represent: {\n lowercase: function (object) { return object ? 'true' : 'false' },\n uppercase: function (object) { return object ? 'TRUE' : 'FALSE' },\n camelcase: function (object) { return object ? 'True' : 'False' }\n },\n defaultStyle: 'lowercase'\n})\n","'use strict'\n\nconst common = require('../common')\nconst Type = require('../type')\n\nfunction isHexCode (c) {\n return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) ||\n ((c >= 0x41/* A */) && (c <= 0x46/* F */)) ||\n ((c >= 0x61/* a */) && (c <= 0x66/* f */))\n}\n\nfunction isOctCode (c) {\n return ((c >= 0x30/* 0 */) && (c <= 0x37/* 7 */))\n}\n\nfunction isDecCode (c) {\n return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */))\n}\n\nfunction resolveYamlInteger (data) {\n if (data === null) return false\n\n const max = data.length\n let index = 0\n let hasDigits = false\n\n if (!max) return false\n\n let ch = data[index]\n\n // sign\n if (ch === '-' || ch === '+') {\n ch = data[++index]\n }\n\n if (ch === '0') {\n // 0\n if (index + 1 === max) return true\n ch = data[++index]\n\n // base 2, base 8, base 16\n\n if (ch === 'b') {\n // base 2\n index++\n\n for (; index < max; index++) {\n ch = data[index]\n if (ch !== '0' && ch !== '1') return false\n hasDigits = true\n }\n return hasDigits && isFinite(parseYamlInteger(data))\n }\n\n if (ch === 'x') {\n // base 16\n index++\n\n for (; index < max; index++) {\n if (!isHexCode(data.charCodeAt(index))) return false\n hasDigits = true\n }\n return hasDigits && isFinite(parseYamlInteger(data))\n }\n\n if (ch === 'o') {\n // base 8\n index++\n\n for (; index < max; index++) {\n if (!isOctCode(data.charCodeAt(index))) return false\n hasDigits = true\n }\n return hasDigits && isFinite(parseYamlInteger(data))\n }\n }\n\n // base 10 (except 0)\n\n for (; index < max; index++) {\n if (!isDecCode(data.charCodeAt(index))) {\n return false\n }\n hasDigits = true\n }\n\n if (!hasDigits) return false\n\n return isFinite(parseYamlInteger(data))\n}\n\nfunction parseYamlInteger (data) {\n let value = data\n let sign = 1\n\n let ch = value[0]\n\n if (ch === '-' || ch === '+') {\n if (ch === '-') sign = -1\n value = value.slice(1)\n ch = value[0]\n }\n\n if (value === '0') return 0\n\n if (ch === '0') {\n if (value[1] === 'b') return sign * parseInt(value.slice(2), 2)\n if (value[1] === 'x') return sign * parseInt(value.slice(2), 16)\n if (value[1] === 'o') return sign * parseInt(value.slice(2), 8)\n }\n\n return sign * parseInt(value, 10)\n}\n\nfunction constructYamlInteger (data) {\n return parseYamlInteger(data)\n}\n\nfunction isInteger (object) {\n return (Object.prototype.toString.call(object)) === '[object Number]' &&\n (object % 1 === 0 && !common.isNegativeZero(object))\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:int', {\n kind: 'scalar',\n resolve: resolveYamlInteger,\n construct: constructYamlInteger,\n predicate: isInteger,\n represent: {\n binary: function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1) },\n octal: function (obj) { return obj >= 0 ? '0o' + obj.toString(8) : '-0o' + obj.toString(8).slice(1) },\n decimal: function (obj) { return obj.toString(10) },\n hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() : '-0x' + obj.toString(16).toUpperCase().slice(1) }\n },\n defaultStyle: 'decimal',\n styleAliases: {\n binary: [2, 'bin'],\n octal: [8, 'oct'],\n decimal: [10, 'dec'],\n hexadecimal: [16, 'hex']\n }\n})\n","'use strict'\n\nconst common = require('../common')\nconst Type = require('../type')\n\nconst YAML_FLOAT_PATTERN = new RegExp(\n // 2.5e4, 2.5 and integers\n '^(?:[-+]?(?:[0-9]+)(?:\\\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?' +\n // .2e4, .2\n // special case, seems not from spec\n '|\\\\.[0-9]+(?:[eE][-+]?[0-9]+)?' +\n // .inf\n '|[-+]?\\\\.(?:inf|Inf|INF)' +\n // .nan\n '|\\\\.(?:nan|NaN|NAN))$')\n\nconst YAML_FLOAT_SPECIAL_PATTERN = new RegExp(\n '^(?:' +\n // .inf\n '[-+]?\\\\.(?:inf|Inf|INF)' +\n // .nan\n '|\\\\.(?:nan|NaN|NAN))$')\n\nfunction resolveYamlFloat (data) {\n if (data === null) return false\n\n if (!YAML_FLOAT_PATTERN.test(data)) {\n return false\n }\n\n if (isFinite(parseFloat(data, 10))) {\n return true\n }\n\n return YAML_FLOAT_SPECIAL_PATTERN.test(data)\n}\n\nfunction constructYamlFloat (data) {\n let value = data.toLowerCase()\n const sign = value[0] === '-' ? -1 : 1\n\n if ('+-'.indexOf(value[0]) >= 0) {\n value = value.slice(1)\n }\n\n if (value === '.inf') {\n return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY\n } else if (value === '.nan') {\n return NaN\n }\n return sign * parseFloat(value, 10)\n}\n\nconst SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/\n\nfunction representYamlFloat (object, style) {\n if (isNaN(object)) {\n switch (style) {\n case 'lowercase': return '.nan'\n case 'uppercase': return '.NAN'\n case 'camelcase': return '.NaN'\n }\n } else if (Number.POSITIVE_INFINITY === object) {\n switch (style) {\n case 'lowercase': return '.inf'\n case 'uppercase': return '.INF'\n case 'camelcase': return '.Inf'\n }\n } else if (Number.NEGATIVE_INFINITY === object) {\n switch (style) {\n case 'lowercase': return '-.inf'\n case 'uppercase': return '-.INF'\n case 'camelcase': return '-.Inf'\n }\n } else if (common.isNegativeZero(object)) {\n return '-0.0'\n }\n\n const res = object.toString(10)\n\n // JS stringifier can build scientific format without dots: 5e-100,\n // while YAML requres dot: 5.e-100. Fix it with simple hack\n\n return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res\n}\n\nfunction isFloat (object) {\n return (Object.prototype.toString.call(object) === '[object Number]') &&\n (object % 1 !== 0 || common.isNegativeZero(object))\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:float', {\n kind: 'scalar',\n resolve: resolveYamlFloat,\n construct: constructYamlFloat,\n predicate: isFloat,\n represent: representYamlFloat,\n defaultStyle: 'lowercase'\n})\n","// Standard YAML's JSON schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2803231\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, this schema is not such strict as defined in the YAML specification.\n// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.\n\n'use strict'\n\nmodule.exports = require('./failsafe').extend({\n implicit: [\n require('../type/null'),\n require('../type/bool'),\n require('../type/int'),\n require('../type/float')\n ]\n})\n","// Standard YAML's Core schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2804923\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, Core schema has no distinctions from JSON schema is JS-YAML.\n\n'use strict'\n\nmodule.exports = require('./json')\n","'use strict'\n\nconst Type = require('../type')\n\nconst YAML_DATE_REGEXP = new RegExp(\n '^([0-9][0-9][0-9][0-9])' + // [1] year\n '-([0-9][0-9])' + // [2] month\n '-([0-9][0-9])$') // [3] day\n\nconst YAML_TIMESTAMP_REGEXP = new RegExp(\n '^([0-9][0-9][0-9][0-9])' + // [1] year\n '-([0-9][0-9]?)' + // [2] month\n '-([0-9][0-9]?)' + // [3] day\n '(?:[Tt]|[ \\\\t]+)' + // ...\n '([0-9][0-9]?)' + // [4] hour\n ':([0-9][0-9])' + // [5] minute\n ':([0-9][0-9])' + // [6] second\n '(?:\\\\.([0-9]*))?' + // [7] fraction\n '(?:[ \\\\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tzHour\n '(?::([0-9][0-9]))?))?$') // [11] tzMinute\n\nfunction resolveYamlTimestamp (data) {\n if (data === null) return false\n if (YAML_DATE_REGEXP.exec(data) !== null) return true\n if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true\n return false\n}\n\nfunction constructYamlTimestamp (data) {\n let fraction = 0\n let delta = null\n\n let match = YAML_DATE_REGEXP.exec(data)\n if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data)\n\n if (match === null) throw new Error('Date resolve error')\n\n // match: [1] year [2] month [3] day\n\n const year = +(match[1])\n const month = +(match[2]) - 1 // JS month starts with 0\n const day = +(match[3])\n\n if (!match[4]) { // no hour\n return new Date(Date.UTC(year, month, day))\n }\n\n // match: [4] hour [5] minute [6] second [7] fraction\n\n const hour = +(match[4])\n const minute = +(match[5])\n const second = +(match[6])\n\n if (match[7]) {\n fraction = match[7].slice(0, 3)\n while (fraction.length < 3) { // milli-seconds\n fraction += '0'\n }\n fraction = +fraction\n }\n\n // match: [8] tz [9] tz_sign [10] tzHour [11] tzMinute\n\n if (match[9]) {\n const tzHour = +(match[10])\n const tzMinute = +(match[11] || 0)\n delta = (tzHour * 60 + tzMinute) * 60000 // delta in mili-seconds\n if (match[9] === '-') delta = -delta\n }\n\n const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction))\n\n if (delta) date.setTime(date.getTime() - delta)\n\n return date\n}\n\nfunction representYamlTimestamp (object /*, style */) {\n return object.toISOString()\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:timestamp', {\n kind: 'scalar',\n resolve: resolveYamlTimestamp,\n construct: constructYamlTimestamp,\n instanceOf: Date,\n represent: representYamlTimestamp\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlMerge (data) {\n return data === '<<' || data === null\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:merge', {\n kind: 'scalar',\n resolve: resolveYamlMerge\n})\n","'use strict'\n\nconst Type = require('../type')\n\n// [ 64, 65, 66 ] -> [ padding, CR, LF ]\nconst BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\\n\\r'\n\nfunction resolveYamlBinary (data) {\n if (data === null) return false\n\n let bitlen = 0\n const max = data.length\n const map = BASE64_MAP\n\n // Convert one by one.\n for (let idx = 0; idx < max; idx++) {\n const code = map.indexOf(data.charAt(idx))\n\n // Skip CR/LF\n if (code > 64) continue\n\n // Fail on illegal characters\n if (code < 0) return false\n\n bitlen += 6\n }\n\n // If there are any bits left, source was corrupted\n return (bitlen % 8) === 0\n}\n\nfunction constructYamlBinary (data) {\n const input = data.replace(/[\\r\\n=]/g, '') // remove CR/LF & padding to simplify scan\n const max = input.length\n const map = BASE64_MAP\n let bits = 0\n const result = []\n\n // Collect by 6*4 bits (3 bytes)\n\n for (let idx = 0; idx < max; idx++) {\n if ((idx % 4 === 0) && idx) {\n result.push((bits >> 16) & 0xFF)\n result.push((bits >> 8) & 0xFF)\n result.push(bits & 0xFF)\n }\n\n bits = (bits << 6) | map.indexOf(input.charAt(idx))\n }\n\n // Dump tail\n\n const tailbits = (max % 4) * 6\n\n if (tailbits === 0) {\n result.push((bits >> 16) & 0xFF)\n result.push((bits >> 8) & 0xFF)\n result.push(bits & 0xFF)\n } else if (tailbits === 18) {\n result.push((bits >> 10) & 0xFF)\n result.push((bits >> 2) & 0xFF)\n } else if (tailbits === 12) {\n result.push((bits >> 4) & 0xFF)\n }\n\n return new Uint8Array(result)\n}\n\nfunction representYamlBinary (object /*, style */) {\n let result = ''\n let bits = 0\n const max = object.length\n const map = BASE64_MAP\n\n // Convert every three bytes to 4 ASCII characters.\n\n for (let idx = 0; idx < max; idx++) {\n if ((idx % 3 === 0) && idx) {\n result += map[(bits >> 18) & 0x3F]\n result += map[(bits >> 12) & 0x3F]\n result += map[(bits >> 6) & 0x3F]\n result += map[bits & 0x3F]\n }\n\n bits = (bits << 8) + object[idx]\n }\n\n // Dump tail\n\n const tail = max % 3\n\n if (tail === 0) {\n result += map[(bits >> 18) & 0x3F]\n result += map[(bits >> 12) & 0x3F]\n result += map[(bits >> 6) & 0x3F]\n result += map[bits & 0x3F]\n } else if (tail === 2) {\n result += map[(bits >> 10) & 0x3F]\n result += map[(bits >> 4) & 0x3F]\n result += map[(bits << 2) & 0x3F]\n result += map[64]\n } else if (tail === 1) {\n result += map[(bits >> 2) & 0x3F]\n result += map[(bits << 4) & 0x3F]\n result += map[64]\n result += map[64]\n }\n\n return result\n}\n\nfunction isBinary (obj) {\n return Object.prototype.toString.call(obj) === '[object Uint8Array]'\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:binary', {\n kind: 'scalar',\n resolve: resolveYamlBinary,\n construct: constructYamlBinary,\n predicate: isBinary,\n represent: representYamlBinary\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\nconst _toString = Object.prototype.toString\n\nfunction resolveYamlOmap (data) {\n if (data === null) return true\n\n const objectKeys = {}\n const object = data\n\n for (let index = 0, length = object.length; index < length; index += 1) {\n const pair = object[index]\n let pairHasKey = false\n\n if (_toString.call(pair) !== '[object Object]') return false\n\n let pairKey\n for (pairKey in pair) {\n if (_hasOwnProperty.call(pair, pairKey)) {\n if (!pairHasKey) pairHasKey = true\n else return false\n }\n }\n\n if (!pairHasKey) return false\n\n if (_hasOwnProperty.call(objectKeys, pairKey)) return false\n Object.defineProperty(objectKeys, pairKey, { value: true })\n }\n\n return true\n}\n\nfunction constructYamlOmap (data) {\n return data !== null ? data : []\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:omap', {\n kind: 'sequence',\n resolve: resolveYamlOmap,\n construct: constructYamlOmap\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _toString = Object.prototype.toString\n\nfunction resolveYamlPairs (data) {\n if (data === null) return true\n\n const object = data\n\n const result = new Array(object.length)\n\n for (let index = 0, length = object.length; index < length; index += 1) {\n const pair = object[index]\n\n if (_toString.call(pair) !== '[object Object]') return false\n\n const keys = Object.keys(pair)\n\n if (keys.length !== 1) return false\n\n result[index] = [keys[0], pair[keys[0]]]\n }\n\n return true\n}\n\nfunction constructYamlPairs (data) {\n if (data === null) return []\n\n const object = data\n const result = new Array(object.length)\n\n for (let index = 0, length = object.length; index < length; index += 1) {\n const pair = object[index]\n\n const keys = Object.keys(pair)\n\n result[index] = [keys[0], pair[keys[0]]]\n }\n\n return result\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:pairs', {\n kind: 'sequence',\n resolve: resolveYamlPairs,\n construct: constructYamlPairs\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nfunction resolveYamlSet (data) {\n if (data === null) return true\n\n const object = data\n\n for (const key in object) {\n if (_hasOwnProperty.call(object, key)) {\n if (object[key] !== null) return false\n }\n }\n\n return true\n}\n\nfunction constructYamlSet (data) {\n return data !== null ? data : {}\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:set', {\n kind: 'mapping',\n resolve: resolveYamlSet,\n construct: constructYamlSet\n})\n","// JS-YAML's default schema for `safeLoad` function.\n// It is not described in the YAML specification.\n//\n// This schema is based on standard YAML's Core schema and includes most of\n// extra types described at YAML tag repository. (http://yaml.org/type/)\n\n'use strict'\n\nmodule.exports = require('./core').extend({\n implicit: [\n require('../type/timestamp'),\n require('../type/merge')\n ],\n explicit: [\n require('../type/binary'),\n require('../type/omap'),\n require('../type/pairs'),\n require('../type/set')\n ]\n})\n","'use strict'\n\nconst common = require('./common')\nconst YAMLException = require('./exception')\nconst makeSnippet = require('./snippet')\nconst DEFAULT_SCHEMA = require('./schema/default')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nconst CONTEXT_FLOW_IN = 1\nconst CONTEXT_FLOW_OUT = 2\nconst CONTEXT_BLOCK_IN = 3\nconst CONTEXT_BLOCK_OUT = 4\n\nconst CHOMPING_CLIP = 1\nconst CHOMPING_STRIP = 2\nconst CHOMPING_KEEP = 3\n\n// eslint-disable-next-line no-control-regex\nconst PATTERN_NON_PRINTABLE = /[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x84\\x86-\\x9F\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/\nconst PATTERN_NON_ASCII_LINE_BREAKS = /[\\x85\\u2028\\u2029]/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_FLOW_INDICATORS = /[,\\[\\]{}]/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_TAG_URI = /^(?:!|[^,\\[\\]{}])(?:%[0-9a-f]{2}|[0-9a-z\\-#;/?:@&=+$,_.!~*'()\\[\\]])*$/i\n\nfunction _class (obj) { return Object.prototype.toString.call(obj) }\n\nfunction isEol (c) {\n return (c === 0x0A/* LF */) || (c === 0x0D/* CR */)\n}\n\nfunction isWhiteSpace (c) {\n return (c === 0x09/* Tab */) || (c === 0x20/* Space */)\n}\n\nfunction isWsOrEol (c) {\n return (c === 0x09/* Tab */) ||\n (c === 0x20/* Space */) ||\n (c === 0x0A/* LF */) ||\n (c === 0x0D/* CR */)\n}\n\nfunction isFlowIndicator (c) {\n return c === 0x2C/* , */ ||\n c === 0x5B/* [ */ ||\n c === 0x5D/* ] */ ||\n c === 0x7B/* { */ ||\n c === 0x7D/* } */\n}\n\nfunction fromHexCode (c) {\n if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {\n return c - 0x30\n }\n\n const lc = c | 0x20\n\n if ((lc >= 0x61/* a */) && (lc <= 0x66/* f */)) {\n return lc - 0x61 + 10\n }\n\n return -1\n}\n\nfunction escapedHexLen (c) {\n if (c === 0x78/* x */) { return 2 }\n if (c === 0x75/* u */) { return 4 }\n if (c === 0x55/* U */) { return 8 }\n return 0\n}\n\nfunction fromDecimalCode (c) {\n if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {\n return c - 0x30\n }\n\n return -1\n}\n\nfunction simpleEscapeSequence (c) {\n switch (c) {\n case 0x30/* 0 */: return '\\x00'\n case 0x61/* a */: return '\\x07'\n case 0x62/* b */: return '\\x08'\n case 0x74/* t */: return '\\x09'\n case 0x09/* Tab */: return '\\x09'\n case 0x6E/* n */: return '\\x0A'\n case 0x76/* v */: return '\\x0B'\n case 0x66/* f */: return '\\x0C'\n case 0x72/* r */: return '\\x0D'\n case 0x65/* e */: return '\\x1B'\n case 0x20/* Space */: return ' '\n case 0x22/* \" */: return '\\x22'\n case 0x2F/* / */: return '/'\n case 0x5C/* \\ */: return '\\x5C'\n case 0x4E/* N */: return '\\x85'\n case 0x5F/* _ */: return '\\xA0'\n case 0x4C/* L */: return '\\u2028'\n case 0x50/* P */: return '\\u2029'\n default: return ''\n }\n}\n\nfunction charFromCodepoint (c) {\n if (c <= 0xFFFF) {\n return String.fromCharCode(c)\n }\n // Encode UTF-16 surrogate pair\n // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF\n return String.fromCharCode(\n ((c - 0x010000) >> 10) + 0xD800,\n ((c - 0x010000) & 0x03FF) + 0xDC00\n )\n}\n\n// set a property of a literal object, while protecting against prototype pollution,\n// see https://github.com/nodeca/js-yaml/issues/164 for more details\nfunction setProperty (object, key, value) {\n // used for this specific key only because Object.defineProperty is slow\n if (key === '__proto__') {\n Object.defineProperty(object, key, {\n configurable: true,\n enumerable: true,\n writable: true,\n value: value\n })\n } else {\n object[key] = value\n }\n}\n\nconst simpleEscapeCheck = new Array(256) // integer, for fast access\nconst simpleEscapeMap = new Array(256)\nfor (let i = 0; i < 256; i++) {\n simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0\n simpleEscapeMap[i] = simpleEscapeSequence(i)\n}\n\nfunction State (input, options) {\n this.input = input\n\n this.filename = options['filename'] || null\n this.schema = options['schema'] || DEFAULT_SCHEMA\n this.onWarning = options['onWarning'] || null\n // (Hidden) Remove? makes the loader to expect YAML 1.1 documents\n // if such documents have no explicit %YAML directive\n this.legacy = options['legacy'] || false\n\n this.json = options['json'] || false\n this.listener = options['listener'] || null\n this.maxDepth = typeof options['maxDepth'] === 'number' ? options['maxDepth'] : 100\n this.maxTotalMergeKeys = typeof options['maxTotalMergeKeys'] === 'number' ? options['maxTotalMergeKeys'] : 10000\n\n this.implicitTypes = this.schema.compiledImplicit\n this.typeMap = this.schema.compiledTypeMap\n\n this.length = input.length\n this.position = 0\n this.line = 0\n this.lineStart = 0\n this.lineIndent = 0\n this.depth = 0\n this.totalMergeKeys = 0\n\n // position of first leading tab in the current line,\n // used to make sure there are no tabs in the indentation\n this.firstTabInLine = -1\n\n this.documents = []\n this.anchorMapTransactions = []\n\n /*\n this.version;\n this.checkLineBreaks;\n this.tagMap;\n this.anchorMap;\n this.tag;\n this.anchor;\n this.kind;\n this.result; */\n}\n\nfunction generateError (state, message) {\n const mark = {\n name: state.filename,\n buffer: state.input.slice(0, -1), // omit trailing \\0\n position: state.position,\n line: state.line,\n column: state.position - state.lineStart\n }\n\n mark.snippet = makeSnippet(mark)\n\n return new YAMLException(message, mark)\n}\n\nfunction throwError (state, message) {\n throw generateError(state, message)\n}\n\nfunction throwWarning (state, message) {\n if (state.onWarning) {\n state.onWarning.call(null, generateError(state, message))\n }\n}\n\nfunction storeAnchor (state, name, value) {\n const transactions = state.anchorMapTransactions\n\n if (transactions.length !== 0) {\n const transaction = transactions[transactions.length - 1]\n\n if (!_hasOwnProperty.call(transaction, name)) {\n transaction[name] = {\n existed: _hasOwnProperty.call(state.anchorMap, name),\n value: state.anchorMap[name]\n }\n }\n }\n\n state.anchorMap[name] = value\n}\n\nfunction beginAnchorTransaction (state) {\n state.anchorMapTransactions.push(Object.create(null))\n}\n\nfunction commitAnchorTransaction (state) {\n const transaction = state.anchorMapTransactions.pop()\n const transactions = state.anchorMapTransactions\n\n if (transactions.length === 0) return\n\n const parent = transactions[transactions.length - 1]\n const names = Object.keys(transaction)\n\n for (let index = 0, length = names.length; index < length; index += 1) {\n const name = names[index]\n\n if (!_hasOwnProperty.call(parent, name)) {\n parent[name] = transaction[name]\n }\n }\n}\n\nfunction rollbackAnchorTransaction (state) {\n const transaction = state.anchorMapTransactions.pop()\n const names = Object.keys(transaction)\n\n for (let index = names.length - 1; index >= 0; index -= 1) {\n const entry = transaction[names[index]]\n\n if (entry.existed) {\n state.anchorMap[names[index]] = entry.value\n } else {\n delete state.anchorMap[names[index]]\n }\n }\n}\n\nfunction snapshotState (state) {\n return {\n position: state.position,\n line: state.line,\n lineStart: state.lineStart,\n lineIndent: state.lineIndent,\n firstTabInLine: state.firstTabInLine,\n tag: state.tag,\n anchor: state.anchor,\n kind: state.kind,\n result: state.result\n }\n}\n\nfunction restoreState (state, snapshot) {\n state.position = snapshot.position\n state.line = snapshot.line\n state.lineStart = snapshot.lineStart\n state.lineIndent = snapshot.lineIndent\n state.firstTabInLine = snapshot.firstTabInLine\n state.tag = snapshot.tag\n state.anchor = snapshot.anchor\n state.kind = snapshot.kind\n state.result = snapshot.result\n}\n\nconst directiveHandlers = {\n\n YAML: function handleYamlDirective (state, name, args) {\n if (state.version !== null) {\n throwError(state, 'duplication of %YAML directive')\n }\n\n if (args.length !== 1) {\n throwError(state, 'YAML directive accepts exactly one argument')\n }\n\n const match = /^([0-9]+)\\.([0-9]+)$/.exec(args[0])\n\n if (match === null) {\n throwError(state, 'ill-formed argument of the YAML directive')\n }\n\n const major = parseInt(match[1], 10)\n const minor = parseInt(match[2], 10)\n\n if (major !== 1) {\n throwError(state, 'unacceptable YAML version of the document')\n }\n\n state.version = args[0]\n state.checkLineBreaks = (minor < 2)\n\n if (minor !== 1 && minor !== 2) {\n throwWarning(state, 'unsupported YAML version of the document')\n }\n },\n\n TAG: function handleTagDirective (state, name, args) {\n let prefix\n\n if (args.length !== 2) {\n throwError(state, 'TAG directive accepts exactly two arguments')\n }\n\n const handle = args[0]\n prefix = args[1]\n\n if (!PATTERN_TAG_HANDLE.test(handle)) {\n throwError(state, 'ill-formed tag handle (first argument) of the TAG directive')\n }\n\n if (_hasOwnProperty.call(state.tagMap, handle)) {\n throwError(state, 'there is a previously declared suffix for \"' + handle + '\" tag handle')\n }\n\n if (!PATTERN_TAG_URI.test(prefix)) {\n throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive')\n }\n\n try {\n prefix = decodeURIComponent(prefix)\n } catch (err) {\n throwError(state, 'tag prefix is malformed: ' + prefix)\n }\n\n state.tagMap[handle] = prefix\n }\n}\n\nfunction captureSegment (state, start, end, checkJson) {\n if (start < end) {\n const _result = state.input.slice(start, end)\n\n if (checkJson) {\n for (let _position = 0, _length = _result.length; _position < _length; _position += 1) {\n const _character = _result.charCodeAt(_position)\n if (!(_character === 0x09 ||\n (_character >= 0x20 && _character <= 0x10FFFF))) {\n throwError(state, 'expected valid JSON character')\n }\n }\n } else if (PATTERN_NON_PRINTABLE.test(_result)) {\n throwError(state, 'the stream contains non-printable characters')\n }\n\n state.result += _result\n }\n}\n\nfunction chargeMergeWork (state) {\n state.totalMergeKeys++\n\n if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) {\n throwError(state, 'merge keys exceeded maxTotalMergeKeys (' + state.maxTotalMergeKeys + ')')\n }\n}\n\nfunction mergeMappings (state, destination, source, overridableKeys) {\n if (!common.isObject(source)) {\n throwError(state, 'cannot merge mappings; the provided source object is unacceptable')\n }\n\n // Count the source mapping itself to bound sequences of empty mappings.\n chargeMergeWork(state)\n\n const sourceKeys = Object.keys(source)\n\n for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {\n const key = sourceKeys[index]\n\n chargeMergeWork(state)\n\n if (!_hasOwnProperty.call(destination, key)) {\n setProperty(destination, key, source[key])\n overridableKeys[key] = true\n }\n }\n}\n\nfunction storeMappingPair (state, _result, overridableKeys, keyTag, keyNode, valueNode,\n startLine, startLineStart, startPos) {\n // The output is a plain object here, so keys can only be strings.\n // We need to convert keyNode to a string, but doing so can hang the process\n // (deeply nested arrays that explode exponentially using aliases).\n if (Array.isArray(keyNode)) {\n keyNode = Array.prototype.slice.call(keyNode)\n\n for (let index = 0, quantity = keyNode.length; index < quantity; index += 1) {\n if (Array.isArray(keyNode[index])) {\n throwError(state, 'nested arrays are not supported inside keys')\n }\n\n if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') {\n keyNode[index] = '[object Object]'\n }\n }\n }\n\n // Avoid code execution in load() via toString property\n // (still use its own toString for arrays, timestamps,\n // and whatever user schema extensions happen to have @@toStringTag)\n if (typeof keyNode === 'object' && _class(keyNode) === '[object Object]') {\n keyNode = '[object Object]'\n }\n\n keyNode = String(keyNode)\n\n if (_result === null) {\n _result = {}\n }\n\n if (keyTag === 'tag:yaml.org,2002:merge') {\n if (Array.isArray(valueNode)) {\n if (valueNode.length > 100) {\n throwError(state, 'abnormal merge sequence size')\n }\n\n for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) {\n mergeMappings(state, _result, valueNode[index], overridableKeys)\n }\n } else {\n mergeMappings(state, _result, valueNode, overridableKeys)\n }\n } else {\n if (!state.json &&\n !_hasOwnProperty.call(overridableKeys, keyNode) &&\n _hasOwnProperty.call(_result, keyNode)) {\n state.line = startLine || state.line\n state.lineStart = startLineStart || state.lineStart\n state.position = startPos || state.position\n throwError(state, 'duplicated mapping key')\n }\n\n setProperty(_result, keyNode, valueNode)\n delete overridableKeys[keyNode]\n }\n\n return _result\n}\n\nfunction readLineBreak (state) {\n const ch = state.input.charCodeAt(state.position)\n\n if (ch === 0x0A/* LF */) {\n state.position++\n } else if (ch === 0x0D/* CR */) {\n state.position++\n if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {\n state.position++\n }\n } else {\n throwError(state, 'a line break is expected')\n }\n\n state.line += 1\n state.lineStart = state.position\n state.firstTabInLine = -1\n}\n\nfunction skipSeparationSpace (state, allowComments, checkIndent) {\n let lineBreaks = 0\n let ch = state.input.charCodeAt(state.position)\n\n while (ch !== 0) {\n while (isWhiteSpace(ch)) {\n if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) {\n state.firstTabInLine = state.position\n }\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (allowComments && ch === 0x23/* # */) {\n do {\n ch = state.input.charCodeAt(++state.position)\n } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0)\n }\n\n if (isEol(ch)) {\n readLineBreak(state)\n\n ch = state.input.charCodeAt(state.position)\n lineBreaks++\n state.lineIndent = 0\n\n while (ch === 0x20/* Space */) {\n state.lineIndent++\n ch = state.input.charCodeAt(++state.position)\n }\n } else {\n break\n }\n }\n\n if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {\n throwWarning(state, 'deficient indentation')\n }\n\n return lineBreaks\n}\n\nfunction testDocumentSeparator (state) {\n let _position = state.position\n let ch = state.input.charCodeAt(_position)\n\n // Condition state.position === state.lineStart is tested\n // in parent on each call, for efficiency. No needs to test here again.\n if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&\n ch === state.input.charCodeAt(_position + 1) &&\n ch === state.input.charCodeAt(_position + 2)) {\n _position += 3\n\n ch = state.input.charCodeAt(_position)\n\n if (ch === 0 || isWsOrEol(ch)) {\n return true\n }\n }\n\n return false\n}\n\nfunction writeFoldedLines (state, count) {\n if (count === 1) {\n state.result += ' '\n } else if (count > 1) {\n state.result += common.repeat('\\n', count - 1)\n }\n}\n\nfunction readPlainScalar (state, nodeIndent, withinFlowCollection) {\n let captureStart\n let captureEnd\n let hasPendingContent\n let _line\n let _lineStart\n let _lineIndent\n const _kind = state.kind\n const _result = state.result\n\n let ch = state.input.charCodeAt(state.position)\n\n if (isWsOrEol(ch) ||\n isFlowIndicator(ch) ||\n ch === 0x23/* # */ ||\n ch === 0x26/* & */ ||\n ch === 0x2A/* * */ ||\n ch === 0x21/* ! */ ||\n ch === 0x7C/* | */ ||\n ch === 0x3E/* > */ ||\n ch === 0x27/* ' */ ||\n ch === 0x22/* \" */ ||\n ch === 0x25/* % */ ||\n ch === 0x40/* @ */ ||\n ch === 0x60/* ` */) {\n return false\n }\n\n if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {\n const following = state.input.charCodeAt(state.position + 1)\n\n if (isWsOrEol(following) ||\n (withinFlowCollection && isFlowIndicator(following))) {\n return false\n }\n }\n\n state.kind = 'scalar'\n state.result = ''\n captureStart = captureEnd = state.position\n hasPendingContent = false\n\n while (ch !== 0) {\n if (ch === 0x3A/* : */) {\n const following = state.input.charCodeAt(state.position + 1)\n\n if (isWsOrEol(following) ||\n (withinFlowCollection && isFlowIndicator(following))) {\n break\n }\n } else if (ch === 0x23/* # */) {\n const preceding = state.input.charCodeAt(state.position - 1)\n\n if (isWsOrEol(preceding)) {\n break\n }\n } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||\n (withinFlowCollection && isFlowIndicator(ch))) {\n break\n } else if (isEol(ch)) {\n _line = state.line\n _lineStart = state.lineStart\n _lineIndent = state.lineIndent\n skipSeparationSpace(state, false, -1)\n\n if (state.lineIndent >= nodeIndent) {\n hasPendingContent = true\n ch = state.input.charCodeAt(state.position)\n continue\n } else {\n state.position = captureEnd\n state.line = _line\n state.lineStart = _lineStart\n state.lineIndent = _lineIndent\n break\n }\n }\n\n if (hasPendingContent) {\n captureSegment(state, captureStart, captureEnd, false)\n writeFoldedLines(state, state.line - _line)\n captureStart = captureEnd = state.position\n hasPendingContent = false\n }\n\n if (!isWhiteSpace(ch)) {\n captureEnd = state.position + 1\n }\n\n ch = state.input.charCodeAt(++state.position)\n }\n\n captureSegment(state, captureStart, captureEnd, false)\n\n if (state.result) {\n return true\n }\n\n state.kind = _kind\n state.result = _result\n return false\n}\n\nfunction readSingleQuotedScalar (state, nodeIndent) {\n let captureStart\n let captureEnd\n\n let ch = state.input.charCodeAt(state.position)\n\n if (ch !== 0x27/* ' */) {\n return false\n }\n\n state.kind = 'scalar'\n state.result = ''\n state.position++\n captureStart = captureEnd = state.position\n\n while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n if (ch === 0x27/* ' */) {\n captureSegment(state, captureStart, state.position, true)\n ch = state.input.charCodeAt(++state.position)\n\n if (ch === 0x27/* ' */) {\n captureStart = state.position\n state.position++\n captureEnd = state.position\n } else {\n return true\n }\n } else if (isEol(ch)) {\n captureSegment(state, captureStart, captureEnd, true)\n writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))\n captureStart = captureEnd = state.position\n } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n throwError(state, 'unexpected end of the document within a single quoted scalar')\n } else {\n state.position++\n if (!isWhiteSpace(ch)) {\n captureEnd = state.position\n }\n }\n }\n\n throwError(state, 'unexpected end of the stream within a single quoted scalar')\n}\n\nfunction readDoubleQuotedScalar (state, nodeIndent) {\n let captureStart\n let captureEnd\n let tmp\n\n let ch = state.input.charCodeAt(state.position)\n\n if (ch !== 0x22/* \" */) {\n return false\n }\n\n state.kind = 'scalar'\n state.result = ''\n state.position++\n captureStart = captureEnd = state.position\n\n while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n if (ch === 0x22/* \" */) {\n captureSegment(state, captureStart, state.position, true)\n state.position++\n return true\n } else if (ch === 0x5C/* \\ */) {\n captureSegment(state, captureStart, state.position, true)\n ch = state.input.charCodeAt(++state.position)\n\n if (isEol(ch)) {\n skipSeparationSpace(state, false, nodeIndent)\n\n // TODO: rework to inline fn with no type cast?\n } else if (ch < 256 && simpleEscapeCheck[ch]) {\n state.result += simpleEscapeMap[ch]\n state.position++\n } else if ((tmp = escapedHexLen(ch)) > 0) {\n let hexLength = tmp\n let hexResult = 0\n\n for (; hexLength > 0; hexLength--) {\n ch = state.input.charCodeAt(++state.position)\n\n if ((tmp = fromHexCode(ch)) >= 0) {\n hexResult = (hexResult << 4) + tmp\n } else {\n throwError(state, 'expected hexadecimal character')\n }\n }\n\n state.result += charFromCodepoint(hexResult)\n\n state.position++\n } else {\n throwError(state, 'unknown escape sequence')\n }\n\n captureStart = captureEnd = state.position\n } else if (isEol(ch)) {\n captureSegment(state, captureStart, captureEnd, true)\n writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))\n captureStart = captureEnd = state.position\n } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n throwError(state, 'unexpected end of the document within a double quoted scalar')\n } else {\n state.position++\n if (!isWhiteSpace(ch)) {\n captureEnd = state.position\n }\n }\n }\n\n throwError(state, 'unexpected end of the stream within a double quoted scalar')\n}\n\nfunction readFlowCollection (state, nodeIndent) {\n let readNext = true\n let _line\n let _lineStart\n let _pos\n const _tag = state.tag\n let _result\n const _anchor = state.anchor\n let terminator\n let isPair\n let isExplicitPair\n let isMapping\n const overridableKeys = Object.create(null)\n let keyNode\n let keyTag\n let valueNode\n\n let ch = state.input.charCodeAt(state.position)\n\n if (ch === 0x5B/* [ */) {\n terminator = 0x5D/* ] */\n isMapping = false\n _result = []\n } else if (ch === 0x7B/* { */) {\n terminator = 0x7D/* } */\n isMapping = true\n _result = {}\n } else {\n return false\n }\n\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, _result)\n }\n\n ch = state.input.charCodeAt(++state.position)\n\n while (ch !== 0) {\n skipSeparationSpace(state, true, nodeIndent)\n\n ch = state.input.charCodeAt(state.position)\n\n if (ch === terminator) {\n state.position++\n state.tag = _tag\n state.anchor = _anchor\n state.kind = isMapping ? 'mapping' : 'sequence'\n state.result = _result\n return true\n } else if (!readNext) {\n throwError(state, 'missed comma between flow collection entries')\n } else if (ch === 0x2C/* , */) {\n // \"flow collection entries can never be completely empty\", as per YAML 1.2, section 7.4\n throwError(state, \"expected the node content, but found ','\")\n }\n\n keyTag = keyNode = valueNode = null\n isPair = isExplicitPair = false\n\n if (ch === 0x3F/* ? */) {\n const following = state.input.charCodeAt(state.position + 1)\n\n if (isWsOrEol(following)) {\n isPair = isExplicitPair = true\n state.position++\n skipSeparationSpace(state, true, nodeIndent)\n }\n }\n\n _line = state.line // Save the current line.\n _lineStart = state.lineStart\n _pos = state.position\n composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)\n keyTag = state.tag\n keyNode = state.result\n skipSeparationSpace(state, true, nodeIndent)\n\n ch = state.input.charCodeAt(state.position)\n\n if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {\n isPair = true\n ch = state.input.charCodeAt(++state.position)\n skipSeparationSpace(state, true, nodeIndent)\n composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)\n valueNode = state.result\n }\n\n if (isMapping) {\n storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos)\n } else if (isPair) {\n _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos))\n } else {\n _result.push(keyNode)\n }\n\n skipSeparationSpace(state, true, nodeIndent)\n\n ch = state.input.charCodeAt(state.position)\n\n if (ch === 0x2C/* , */) {\n readNext = true\n ch = state.input.charCodeAt(++state.position)\n } else {\n readNext = false\n }\n }\n\n throwError(state, 'unexpected end of the stream within a flow collection')\n}\n\nfunction readBlockScalar (state, nodeIndent) {\n let folding\n let chomping = CHOMPING_CLIP\n let didReadContent = false\n let detectedIndent = false\n let textIndent = nodeIndent\n let emptyLines = 0\n let atMoreIndented = false\n let tmp\n\n let ch = state.input.charCodeAt(state.position)\n\n if (ch === 0x7C/* | */) {\n folding = false\n } else if (ch === 0x3E/* > */) {\n folding = true\n } else {\n return false\n }\n\n state.kind = 'scalar'\n state.result = ''\n\n while (ch !== 0) {\n ch = state.input.charCodeAt(++state.position)\n\n if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {\n if (CHOMPING_CLIP === chomping) {\n chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP\n } else {\n throwError(state, 'repeat of a chomping mode identifier')\n }\n } else if ((tmp = fromDecimalCode(ch)) >= 0) {\n if (tmp === 0) {\n throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one')\n } else if (!detectedIndent) {\n textIndent = nodeIndent + tmp - 1\n detectedIndent = true\n } else {\n throwError(state, 'repeat of an indentation width identifier')\n }\n } else {\n break\n }\n }\n\n if (isWhiteSpace(ch)) {\n do { ch = state.input.charCodeAt(++state.position) }\n while (isWhiteSpace(ch))\n\n if (ch === 0x23/* # */) {\n do { ch = state.input.charCodeAt(++state.position) }\n while (!isEol(ch) && (ch !== 0))\n }\n }\n\n while (ch !== 0) {\n readLineBreak(state)\n state.lineIndent = 0\n\n ch = state.input.charCodeAt(state.position)\n\n // eslint-disable-next-line no-unmodified-loop-condition\n while ((!detectedIndent || state.lineIndent < textIndent) &&\n (ch === 0x20/* Space */)) {\n state.lineIndent++\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (!detectedIndent && state.lineIndent > textIndent) {\n textIndent = state.lineIndent\n }\n\n if (isEol(ch)) {\n emptyLines++\n continue\n }\n\n if (!detectedIndent && textIndent === 0) {\n throwError(state, 'missing indentation for block scalar')\n }\n\n // End of the scalar.\n if (state.lineIndent < textIndent) {\n // Perform the chomping.\n if (chomping === CHOMPING_KEEP) {\n state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n } else if (chomping === CHOMPING_CLIP) {\n if (didReadContent) { // i.e. only if the scalar is not empty.\n state.result += '\\n'\n }\n }\n\n // Break this `while` cycle and go to the funciton's epilogue.\n break\n }\n\n // Folded style: use fancy rules to handle line breaks.\n if (folding) {\n // Lines starting with white space characters (more-indented lines) are not folded.\n if (isWhiteSpace(ch)) {\n atMoreIndented = true\n // except for the first content line (cf. Example 8.1)\n state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n\n // End of more-indented block.\n } else if (atMoreIndented) {\n atMoreIndented = false\n state.result += common.repeat('\\n', emptyLines + 1)\n\n // Just one line break - perceive as the same line.\n } else if (emptyLines === 0) {\n if (didReadContent) { // i.e. only if we have already read some scalar content.\n state.result += ' '\n }\n\n // Several line breaks - perceive as different lines.\n } else {\n state.result += common.repeat('\\n', emptyLines)\n }\n\n // Literal style: just add exact number of line breaks between content lines.\n } else {\n // Keep all line breaks except the header line break.\n state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n }\n\n didReadContent = true\n detectedIndent = true\n emptyLines = 0\n const captureStart = state.position\n\n while (!isEol(ch) && (ch !== 0)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n captureSegment(state, captureStart, state.position, false)\n }\n\n return true\n}\n\nfunction readBlockSequence (state, nodeIndent) {\n const _tag = state.tag\n const _anchor = state.anchor\n const _result = []\n let detected = false\n\n // there is a leading tab before this token, so it can't be a block sequence/mapping;\n // it can still be flow sequence/mapping or a scalar\n if (state.firstTabInLine !== -1) return false\n\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, _result)\n }\n\n let ch = state.input.charCodeAt(state.position)\n\n while (ch !== 0) {\n if (state.firstTabInLine !== -1) {\n state.position = state.firstTabInLine\n throwError(state, 'tab characters must not be used in indentation')\n }\n\n if (ch !== 0x2D/* - */) {\n break\n }\n\n const following = state.input.charCodeAt(state.position + 1)\n\n if (!isWsOrEol(following)) {\n break\n }\n\n detected = true\n state.position++\n\n if (skipSeparationSpace(state, true, -1)) {\n if (state.lineIndent <= nodeIndent) {\n _result.push(null)\n ch = state.input.charCodeAt(state.position)\n continue\n }\n }\n\n const _line = state.line\n composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true)\n _result.push(state.result)\n skipSeparationSpace(state, true, -1)\n\n ch = state.input.charCodeAt(state.position)\n\n if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {\n throwError(state, 'bad indentation of a sequence entry')\n } else if (state.lineIndent < nodeIndent) {\n break\n }\n }\n\n if (detected) {\n state.tag = _tag\n state.anchor = _anchor\n state.kind = 'sequence'\n state.result = _result\n return true\n }\n return false\n}\n\nfunction readBlockMapping (state, nodeIndent, flowIndent) {\n let allowCompact\n let _keyLine\n let _keyLineStart\n let _keyPos\n const _tag = state.tag\n const _anchor = state.anchor\n const _result = {}\n const overridableKeys = Object.create(null)\n let keyTag = null\n let keyNode = null\n let valueNode = null\n let atExplicitKey = false\n let detected = false\n\n // there is a leading tab before this token, so it can't be a block sequence/mapping;\n // it can still be flow sequence/mapping or a scalar\n if (state.firstTabInLine !== -1) return false\n\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, _result)\n }\n\n let ch = state.input.charCodeAt(state.position)\n\n while (ch !== 0) {\n if (!atExplicitKey && state.firstTabInLine !== -1) {\n state.position = state.firstTabInLine\n throwError(state, 'tab characters must not be used in indentation')\n }\n\n const following = state.input.charCodeAt(state.position + 1)\n const _line = state.line // Save the current line.\n\n //\n // Explicit notation case. There are two separate blocks:\n // first for the key (denoted by \"?\") and second for the value (denoted by \":\")\n //\n if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && isWsOrEol(following)) {\n if (ch === 0x3F/* ? */) {\n if (atExplicitKey) {\n storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n keyTag = keyNode = valueNode = null\n }\n\n detected = true\n atExplicitKey = true\n allowCompact = true\n } else if (atExplicitKey) {\n // i.e. 0x3A/* : */ === character after the explicit key.\n atExplicitKey = false\n allowCompact = true\n } else {\n throwError(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line')\n }\n\n state.position += 1\n ch = following\n\n //\n // Implicit notation case. Flow-style node as the key first, then \":\", and the value.\n //\n } else {\n _keyLine = state.line\n _keyLineStart = state.lineStart\n _keyPos = state.position\n\n if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {\n // Neither implicit nor explicit notation.\n // Reading is done. Go to the epilogue.\n break\n }\n\n if (state.line === _line) {\n ch = state.input.charCodeAt(state.position)\n\n while (isWhiteSpace(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (ch === 0x3A/* : */) {\n ch = state.input.charCodeAt(++state.position)\n\n if (!isWsOrEol(ch)) {\n throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping')\n }\n\n if (atExplicitKey) {\n storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n keyTag = keyNode = valueNode = null\n }\n\n detected = true\n atExplicitKey = false\n allowCompact = false\n keyTag = state.tag\n keyNode = state.result\n } else if (detected) {\n throwError(state, 'can not read an implicit mapping pair; a colon is missed')\n } else {\n state.tag = _tag\n state.anchor = _anchor\n return true // Keep the result of `composeNode`.\n }\n } else if (detected) {\n throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key')\n } else {\n state.tag = _tag\n state.anchor = _anchor\n return true // Keep the result of `composeNode`.\n }\n }\n\n //\n // Common reading code for both explicit and implicit notations.\n //\n if (state.line === _line || state.lineIndent > nodeIndent) {\n if (atExplicitKey) {\n _keyLine = state.line\n _keyLineStart = state.lineStart\n _keyPos = state.position\n }\n\n if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {\n if (atExplicitKey) {\n keyNode = state.result\n } else {\n valueNode = state.result\n }\n }\n\n if (!atExplicitKey) {\n storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos)\n keyTag = keyNode = valueNode = null\n }\n\n skipSeparationSpace(state, true, -1)\n ch = state.input.charCodeAt(state.position)\n }\n\n if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {\n throwError(state, 'bad indentation of a mapping entry')\n } else if (state.lineIndent < nodeIndent) {\n break\n }\n }\n\n //\n // Epilogue.\n //\n\n // Special case: last mapping's node contains only the key in explicit notation.\n if (atExplicitKey) {\n storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n }\n\n // Expose the resulting mapping.\n if (detected) {\n state.tag = _tag\n state.anchor = _anchor\n state.kind = 'mapping'\n state.result = _result\n }\n\n return detected\n}\n\nfunction readTagProperty (state) {\n let isVerbatim = false\n let isNamed = false\n let tagHandle\n let tagName\n\n let ch = state.input.charCodeAt(state.position)\n\n if (ch !== 0x21/* ! */) return false\n\n if (state.tag !== null) {\n throwError(state, 'duplication of a tag property')\n }\n\n ch = state.input.charCodeAt(++state.position)\n\n if (ch === 0x3C/* < */) {\n isVerbatim = true\n ch = state.input.charCodeAt(++state.position)\n } else if (ch === 0x21/* ! */) {\n isNamed = true\n tagHandle = '!!'\n ch = state.input.charCodeAt(++state.position)\n } else {\n tagHandle = '!'\n }\n\n let _position = state.position\n\n if (isVerbatim) {\n do { ch = state.input.charCodeAt(++state.position) }\n while (ch !== 0 && ch !== 0x3E/* > */)\n\n if (state.position < state.length) {\n tagName = state.input.slice(_position, state.position)\n ch = state.input.charCodeAt(++state.position)\n } else {\n throwError(state, 'unexpected end of the stream within a verbatim tag')\n }\n } else {\n while (ch !== 0 && !isWsOrEol(ch)) {\n if (ch === 0x21/* ! */) {\n if (!isNamed) {\n tagHandle = state.input.slice(_position - 1, state.position + 1)\n\n if (!PATTERN_TAG_HANDLE.test(tagHandle)) {\n throwError(state, 'named tag handle cannot contain such characters')\n }\n\n isNamed = true\n _position = state.position + 1\n } else {\n throwError(state, 'tag suffix cannot contain exclamation marks')\n }\n }\n\n ch = state.input.charCodeAt(++state.position)\n }\n\n tagName = state.input.slice(_position, state.position)\n\n if (PATTERN_FLOW_INDICATORS.test(tagName)) {\n throwError(state, 'tag suffix cannot contain flow indicator characters')\n }\n }\n\n if (tagName && !PATTERN_TAG_URI.test(tagName)) {\n throwError(state, 'tag name cannot contain such characters: ' + tagName)\n }\n\n try {\n tagName = decodeURIComponent(tagName)\n } catch (err) {\n throwError(state, 'tag name is malformed: ' + tagName)\n }\n\n if (isVerbatim) {\n state.tag = tagName\n } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {\n state.tag = state.tagMap[tagHandle] + tagName\n } else if (tagHandle === '!') {\n state.tag = '!' + tagName\n } else if (tagHandle === '!!') {\n state.tag = 'tag:yaml.org,2002:' + tagName\n } else {\n throwError(state, 'undeclared tag handle \"' + tagHandle + '\"')\n }\n\n return true\n}\n\nfunction readAnchorProperty (state) {\n let ch = state.input.charCodeAt(state.position)\n\n if (ch !== 0x26/* & */) return false\n\n if (state.anchor !== null) {\n throwError(state, 'duplication of an anchor property')\n }\n\n ch = state.input.charCodeAt(++state.position)\n const _position = state.position\n\n while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (state.position === _position) {\n throwError(state, 'name of an anchor node must contain at least one character')\n }\n\n state.anchor = state.input.slice(_position, state.position)\n return true\n}\n\nfunction readAlias (state) {\n let ch = state.input.charCodeAt(state.position)\n\n if (ch !== 0x2A/* * */) return false\n\n ch = state.input.charCodeAt(++state.position)\n const _position = state.position\n\n while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (state.position === _position) {\n throwError(state, 'name of an alias node must contain at least one character')\n }\n\n const alias = state.input.slice(_position, state.position)\n\n if (!_hasOwnProperty.call(state.anchorMap, alias)) {\n throwError(state, 'unidentified alias \"' + alias + '\"')\n }\n\n state.result = state.anchorMap[alias]\n skipSeparationSpace(state, true, -1)\n return true\n}\n\nfunction tryReadBlockMappingFromProperty (state, propertyStart, nodeIndent, flowIndent) {\n const fallbackState = snapshotState(state)\n\n beginAnchorTransaction(state)\n restoreState(state, propertyStart)\n\n // Re-read the leading properties as part of the first implicit key, not as\n // properties of the current node.\n state.tag = null\n state.anchor = null\n state.kind = null\n state.result = null\n\n if (readBlockMapping(state, nodeIndent, flowIndent) && state.kind === 'mapping') {\n commitAnchorTransaction(state)\n return true\n }\n\n rollbackAnchorTransaction(state)\n restoreState(state, fallbackState)\n return false\n}\n\nfunction composeNode (state, parentIndent, nodeContext, allowToSeek, allowCompact) {\n let allowBlockScalars\n let allowBlockCollections\n let indentStatus = 1 // 1: this>parent, 0: this=parent, -1: this<parent\n let atNewLine = false\n let hasContent = false\n let propertyStart = null\n let type\n let flowIndent\n let blockIndent\n\n if (state.depth >= state.maxDepth) {\n throwError(state, 'nesting exceeded maxDepth (' + state.maxDepth + ')')\n }\n\n state.depth += 1\n\n if (state.listener !== null) {\n state.listener('open', state)\n }\n\n state.tag = null\n state.anchor = null\n state.kind = null\n state.result = null\n\n const allowBlockStyles = allowBlockScalars = allowBlockCollections =\n CONTEXT_BLOCK_OUT === nodeContext ||\n CONTEXT_BLOCK_IN === nodeContext\n\n if (allowToSeek) {\n if (skipSeparationSpace(state, true, -1)) {\n atNewLine = true\n\n if (state.lineIndent > parentIndent) {\n indentStatus = 1\n } else if (state.lineIndent === parentIndent) {\n indentStatus = 0\n } else if (state.lineIndent < parentIndent) {\n indentStatus = -1\n }\n }\n }\n\n if (indentStatus === 1) {\n while (true) {\n const ch = state.input.charCodeAt(state.position)\n const propertyState = snapshotState(state)\n\n // A duplicate property token after a line break can be the first key of\n // a nested block mapping, e.g. `!!map\\n !!str key: value`.\n if (atNewLine &&\n ((ch === 0x21/* ! */ && state.tag !== null) ||\n (ch === 0x26/* & */ && state.anchor !== null))) {\n break\n }\n\n if (!readTagProperty(state) && !readAnchorProperty(state)) {\n break\n }\n\n if (propertyStart === null) {\n propertyStart = propertyState\n }\n\n if (skipSeparationSpace(state, true, -1)) {\n atNewLine = true\n allowBlockCollections = allowBlockStyles\n\n if (state.lineIndent > parentIndent) {\n indentStatus = 1\n } else if (state.lineIndent === parentIndent) {\n indentStatus = 0\n } else if (state.lineIndent < parentIndent) {\n indentStatus = -1\n }\n } else {\n allowBlockCollections = false\n }\n }\n }\n\n if (allowBlockCollections) {\n allowBlockCollections = atNewLine || allowCompact\n }\n\n if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {\n if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {\n flowIndent = parentIndent\n } else {\n flowIndent = parentIndent + 1\n }\n\n blockIndent = state.position - state.lineStart\n\n if (indentStatus === 1) {\n if ((allowBlockCollections &&\n (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent))) ||\n readFlowCollection(state, flowIndent)) {\n hasContent = true\n } else {\n const ch = state.input.charCodeAt(state.position)\n\n if (propertyStart !== null && allowBlockStyles && !allowBlockCollections &&\n ch !== 0x7C/* | */ && ch !== 0x3E/* > */ &&\n tryReadBlockMappingFromProperty(\n state,\n propertyStart,\n propertyStart.position - propertyStart.lineStart,\n flowIndent\n )) {\n hasContent = true\n } else if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||\n readSingleQuotedScalar(state, flowIndent) ||\n readDoubleQuotedScalar(state, flowIndent)) {\n hasContent = true\n } else if (readAlias(state)) {\n hasContent = true\n\n if (state.tag !== null || state.anchor !== null) {\n throwError(state, 'alias node should not have any properties')\n }\n } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {\n hasContent = true\n\n if (state.tag === null) {\n state.tag = '?'\n }\n }\n\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, state.result)\n }\n }\n } else if (indentStatus === 0) {\n // Special case: block sequences are allowed to have same indentation level as the parent.\n // http://www.yaml.org/spec/1.2/spec.html#id2799784\n hasContent = allowBlockCollections && readBlockSequence(state, blockIndent)\n }\n }\n\n if (state.tag === null) {\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, state.result)\n }\n } else if (state.tag === '?') {\n // Implicit resolving is not allowed for non-scalar types, and '?'\n // non-specific tag is only automatically assigned to plain scalars.\n //\n // We only need to check kind conformity in case user explicitly assigns '?'\n // tag, for example like this: \"!<?> [0]\"\n //\n if (state.result !== null && state.kind !== 'scalar') {\n throwError(state, 'unacceptable node kind for !<?> tag; it should be \"scalar\", not \"' + state.kind + '\"')\n }\n\n for (let typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {\n type = state.implicitTypes[typeIndex]\n\n if (type.resolve(state.result)) { // `state.result` updated in resolver if matched\n state.result = type.construct(state.result)\n state.tag = type.tag\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, state.result)\n }\n break\n }\n }\n } else if (state.tag !== '!') {\n if (_hasOwnProperty.call(state.typeMap[state.kind || 'fallback'], state.tag)) {\n type = state.typeMap[state.kind || 'fallback'][state.tag]\n } else {\n // looking for multi type\n type = null\n const typeList = state.typeMap.multi[state.kind || 'fallback']\n\n for (let typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) {\n if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) {\n type = typeList[typeIndex]\n break\n }\n }\n }\n\n if (!type) {\n throwError(state, 'unknown tag !<' + state.tag + '>')\n }\n\n if (state.result !== null && type.kind !== state.kind) {\n throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be \"' + type.kind + '\", not \"' + state.kind + '\"')\n }\n\n if (!type.resolve(state.result, state.tag)) { // `state.result` updated in resolver if matched\n throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag')\n } else {\n state.result = type.construct(state.result, state.tag)\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, state.result)\n }\n }\n }\n\n if (state.listener !== null) {\n state.listener('close', state)\n }\n\n state.depth -= 1\n return state.tag !== null || state.anchor !== null || hasContent\n}\n\nfunction readDocument (state) {\n const documentStart = state.position\n let hasDirectives = false\n let ch\n\n state.version = null\n state.checkLineBreaks = state.legacy\n state.tagMap = Object.create(null)\n state.anchorMap = Object.create(null)\n\n while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n skipSeparationSpace(state, true, -1)\n\n ch = state.input.charCodeAt(state.position)\n\n if (state.lineIndent > 0 || ch !== 0x25/* % */) {\n break\n }\n\n hasDirectives = true\n ch = state.input.charCodeAt(++state.position)\n let _position = state.position\n\n while (ch !== 0 && !isWsOrEol(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n const directiveName = state.input.slice(_position, state.position)\n const directiveArgs = []\n\n if (directiveName.length < 1) {\n throwError(state, 'directive name must not be less than one character in length')\n }\n\n while (ch !== 0) {\n while (isWhiteSpace(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (ch === 0x23/* # */) {\n do { ch = state.input.charCodeAt(++state.position) }\n while (ch !== 0 && !isEol(ch))\n break\n }\n\n if (isEol(ch)) break\n\n _position = state.position\n\n while (ch !== 0 && !isWsOrEol(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n directiveArgs.push(state.input.slice(_position, state.position))\n }\n\n if (ch !== 0) readLineBreak(state)\n\n if (_hasOwnProperty.call(directiveHandlers, directiveName)) {\n directiveHandlers[directiveName](state, directiveName, directiveArgs)\n } else {\n throwWarning(state, 'unknown document directive \"' + directiveName + '\"')\n }\n }\n\n skipSeparationSpace(state, true, -1)\n\n if (state.lineIndent === 0 &&\n state.input.charCodeAt(state.position) === 0x2D/* - */ &&\n state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&\n state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {\n state.position += 3\n skipSeparationSpace(state, true, -1)\n } else if (hasDirectives) {\n throwError(state, 'directives end mark is expected')\n }\n\n composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true)\n skipSeparationSpace(state, true, -1)\n\n if (state.checkLineBreaks &&\n PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {\n throwWarning(state, 'non-ASCII line breaks are interpreted as content')\n }\n\n state.documents.push(state.result)\n\n if (state.position === state.lineStart && testDocumentSeparator(state)) {\n if (state.input.charCodeAt(state.position) === 0x2E/* . */) {\n state.position += 3\n skipSeparationSpace(state, true, -1)\n }\n return\n }\n\n if (state.position < (state.length - 1)) {\n throwError(state, 'end of the stream or a document separator is expected')\n }\n}\n\nfunction loadDocuments (input, options) {\n input = String(input)\n options = options || {}\n\n if (input.length !== 0) {\n // Add tailing `\\n` if not exists\n if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&\n input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {\n input += '\\n'\n }\n\n // Strip BOM\n if (input.charCodeAt(0) === 0xFEFF) {\n input = input.slice(1)\n }\n }\n\n const state = new State(input, options)\n\n const nullpos = input.indexOf('\\0')\n\n if (nullpos !== -1) {\n state.position = nullpos\n throwError(state, 'null byte is not allowed in input')\n }\n\n // Use 0 as string terminator. That significantly simplifies bounds check.\n state.input += '\\0'\n\n while (state.input.charCodeAt(state.position) === 0x20/* Space */) {\n state.lineIndent += 1\n state.position += 1\n }\n\n while (state.position < (state.length - 1)) {\n readDocument(state)\n }\n\n return state.documents\n}\n\nfunction loadAll (input, iterator, options) {\n if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') {\n options = iterator\n iterator = null\n }\n\n const documents = loadDocuments(input, options)\n\n if (typeof iterator !== 'function') {\n return documents\n }\n\n for (let index = 0, length = documents.length; index < length; index += 1) {\n iterator(documents[index])\n }\n}\n\nfunction load (input, options) {\n const documents = loadDocuments(input, options)\n\n if (documents.length === 0) {\n return undefined\n } else if (documents.length === 1) {\n return documents[0]\n }\n throw new YAMLException('expected a single document in the stream, but found more')\n}\n\nmodule.exports.loadAll = loadAll\nmodule.exports.load = load\n","'use strict'\n\nconst common = require('./common')\nconst YAMLException = require('./exception')\nconst DEFAULT_SCHEMA = require('./schema/default')\n\nconst _toString = Object.prototype.toString\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nconst CHAR_BOM = 0xFEFF\nconst CHAR_TAB = 0x09 /* Tab */\nconst CHAR_LINE_FEED = 0x0A /* LF */\nconst CHAR_CARRIAGE_RETURN = 0x0D /* CR */\nconst CHAR_SPACE = 0x20 /* Space */\nconst CHAR_EXCLAMATION = 0x21 /* ! */\nconst CHAR_DOUBLE_QUOTE = 0x22 /* \" */\nconst CHAR_SHARP = 0x23 /* # */\nconst CHAR_PERCENT = 0x25 /* % */\nconst CHAR_AMPERSAND = 0x26 /* & */\nconst CHAR_SINGLE_QUOTE = 0x27 /* ' */\nconst CHAR_ASTERISK = 0x2A /* * */\nconst CHAR_COMMA = 0x2C /* , */\nconst CHAR_MINUS = 0x2D /* - */\nconst CHAR_COLON = 0x3A /* : */\nconst CHAR_EQUALS = 0x3D /* = */\nconst CHAR_GREATER_THAN = 0x3E /* > */\nconst CHAR_QUESTION = 0x3F /* ? */\nconst CHAR_COMMERCIAL_AT = 0x40 /* @ */\nconst CHAR_LEFT_SQUARE_BRACKET = 0x5B /* [ */\nconst CHAR_RIGHT_SQUARE_BRACKET = 0x5D /* ] */\nconst CHAR_GRAVE_ACCENT = 0x60 /* ` */\nconst CHAR_LEFT_CURLY_BRACKET = 0x7B /* { */\nconst CHAR_VERTICAL_LINE = 0x7C /* | */\nconst CHAR_RIGHT_CURLY_BRACKET = 0x7D /* } */\n\nconst ESCAPE_SEQUENCES = {}\n\nESCAPE_SEQUENCES[0x00] = '\\\\0'\nESCAPE_SEQUENCES[0x07] = '\\\\a'\nESCAPE_SEQUENCES[0x08] = '\\\\b'\nESCAPE_SEQUENCES[0x09] = '\\\\t'\nESCAPE_SEQUENCES[0x0A] = '\\\\n'\nESCAPE_SEQUENCES[0x0B] = '\\\\v'\nESCAPE_SEQUENCES[0x0C] = '\\\\f'\nESCAPE_SEQUENCES[0x0D] = '\\\\r'\nESCAPE_SEQUENCES[0x1B] = '\\\\e'\nESCAPE_SEQUENCES[0x22] = '\\\\\"'\nESCAPE_SEQUENCES[0x5C] = '\\\\\\\\'\nESCAPE_SEQUENCES[0x85] = '\\\\N'\nESCAPE_SEQUENCES[0xA0] = '\\\\_'\nESCAPE_SEQUENCES[0x2028] = '\\\\L'\nESCAPE_SEQUENCES[0x2029] = '\\\\P'\n\nconst DEPRECATED_BOOLEANS_SYNTAX = [\n 'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',\n 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'\n]\n\nconst DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\\.[0-9_]*)?$/\n\nfunction compileStyleMap (schema, map) {\n if (map === null) return {}\n\n const result = {}\n const keys = Object.keys(map)\n\n for (let index = 0, length = keys.length; index < length; index += 1) {\n let tag = keys[index]\n let style = String(map[tag])\n\n if (tag.slice(0, 2) === '!!') {\n tag = 'tag:yaml.org,2002:' + tag.slice(2)\n }\n const type = schema.compiledTypeMap['fallback'][tag]\n\n if (type && _hasOwnProperty.call(type.styleAliases, style)) {\n style = type.styleAliases[style]\n }\n\n result[tag] = style\n }\n\n return result\n}\n\nfunction encodeHex (character) {\n let handle\n let length\n\n const string = character.toString(16).toUpperCase()\n\n if (character <= 0xFF) {\n handle = 'x'\n length = 2\n } else if (character <= 0xFFFF) {\n handle = 'u'\n length = 4\n } else if (character <= 0xFFFFFFFF) {\n handle = 'U'\n length = 8\n } else {\n throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF')\n }\n\n return '\\\\' + handle + common.repeat('0', length - string.length) + string\n}\n\nconst QUOTING_TYPE_SINGLE = 1\nconst QUOTING_TYPE_DOUBLE = 2\n\nfunction State (options) {\n this.schema = options['schema'] || DEFAULT_SCHEMA\n this.indent = Math.max(1, (options['indent'] || 2))\n this.noArrayIndent = options['noArrayIndent'] || false\n this.skipInvalid = options['skipInvalid'] || false\n this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel'])\n this.styleMap = compileStyleMap(this.schema, options['styles'] || null)\n this.sortKeys = options['sortKeys'] || false\n this.lineWidth = options['lineWidth'] || 80\n this.noRefs = options['noRefs'] || false\n this.noCompatMode = options['noCompatMode'] || false\n this.condenseFlow = options['condenseFlow'] || false\n this.quotingType = options['quotingType'] === '\"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE\n this.forceQuotes = options['forceQuotes'] || false\n this.replacer = typeof options['replacer'] === 'function' ? options['replacer'] : null\n\n this.implicitTypes = this.schema.compiledImplicit\n this.explicitTypes = this.schema.compiledExplicit\n\n this.tag = null\n this.result = ''\n\n this.duplicates = []\n this.usedDuplicates = null\n}\n\n// Indents every line in a string. Empty lines (\\n only) are not indented.\nfunction indentString (string, spaces) {\n const ind = common.repeat(' ', spaces)\n let position = 0\n let result = ''\n const length = string.length\n\n while (position < length) {\n let line\n const next = string.indexOf('\\n', position)\n if (next === -1) {\n line = string.slice(position)\n position = length\n } else {\n line = string.slice(position, next + 1)\n position = next + 1\n }\n\n if (line.length && line !== '\\n') result += ind\n\n result += line\n }\n\n return result\n}\n\nfunction generateNextLine (state, level) {\n return '\\n' + common.repeat(' ', state.indent * level)\n}\n\nfunction testImplicitResolving (state, str) {\n for (let index = 0, length = state.implicitTypes.length; index < length; index += 1) {\n const type = state.implicitTypes[index]\n\n if (type.resolve(str)) {\n return true\n }\n }\n\n return false\n}\n\n// [33] s-white ::= s-space | s-tab\nfunction isWhitespace (c) {\n return c === CHAR_SPACE || c === CHAR_TAB\n}\n\n// Returns true if the character can be printed without escaping.\n// From YAML 1.2: \"any allowed characters known to be non-printable\n// should also be escaped. [However,] This isn’t mandatory\"\n// Derived from nb-char - \\t - #x85 - #xA0 - #x2028 - #x2029.\nfunction isPrintable (c) {\n return (c >= 0x00020 && c <= 0x00007E) ||\n ((c >= 0x000A1 && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029) ||\n ((c >= 0x0E000 && c <= 0x00FFFD) && c !== CHAR_BOM) ||\n (c >= 0x10000 && c <= 0x10FFFF)\n}\n\n// [34] ns-char ::= nb-char - s-white\n// [27] nb-char ::= c-printable - b-char - c-byte-order-mark\n// [26] b-char ::= b-line-feed | b-carriage-return\n// Including s-white (for some reason, examples doesn't match specs in this aspect)\n// ns-char ::= c-printable - b-line-feed - b-carriage-return - c-byte-order-mark\nfunction isNsCharOrWhitespace (c) {\n return isPrintable(c) &&\n c !== CHAR_BOM &&\n // - b-char\n c !== CHAR_CARRIAGE_RETURN &&\n c !== CHAR_LINE_FEED\n}\n\n// [127] ns-plain-safe(c) ::= c = flow-out ⇒ ns-plain-safe-out\n// c = flow-in ⇒ ns-plain-safe-in\n// c = block-key ⇒ ns-plain-safe-out\n// c = flow-key ⇒ ns-plain-safe-in\n// [128] ns-plain-safe-out ::= ns-char\n// [129] ns-plain-safe-in ::= ns-char - c-flow-indicator\n// [130] ns-plain-char(c) ::= ( ns-plain-safe(c) - “:” - “#” )\n// | ( /* An ns-char preceding */ “#” )\n// | ( “:” /* Followed by an ns-plain-safe(c) */ )\nfunction isPlainSafe (c, prev, inblock) {\n const cIsNsCharOrWhitespace = isNsCharOrWhitespace(c)\n const cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c)\n return (\n (\n // ns-plain-safe\n inblock // c = flow-in\n ? cIsNsCharOrWhitespace\n : cIsNsCharOrWhitespace &&\n // - c-flow-indicator\n c !== CHAR_COMMA &&\n c !== CHAR_LEFT_SQUARE_BRACKET &&\n c !== CHAR_RIGHT_SQUARE_BRACKET &&\n c !== CHAR_LEFT_CURLY_BRACKET &&\n c !== CHAR_RIGHT_CURLY_BRACKET\n ) &&\n // ns-plain-char\n c !== CHAR_SHARP && // false on '#'\n !(prev === CHAR_COLON && !cIsNsChar)\n ) || // false on ': '\n (isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP) || // change to true on '[^ ]#'\n (prev === CHAR_COLON && cIsNsChar) // change to true on ':[^ ]'\n}\n\n// Simplified test for values allowed as the first character in plain style.\nfunction isPlainSafeFirst (c) {\n // Uses a subset of ns-char - c-indicator\n // where ns-char = nb-char - s-white.\n // No support of ( ( “?” | “:” | “-” ) /* Followed by an ns-plain-safe(c)) */ ) part\n return isPrintable(c) &&\n c !== CHAR_BOM &&\n !isWhitespace(c) && // - s-white\n // - (c-indicator ::=\n // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”\n c !== CHAR_MINUS &&\n c !== CHAR_QUESTION &&\n c !== CHAR_COLON &&\n c !== CHAR_COMMA &&\n c !== CHAR_LEFT_SQUARE_BRACKET &&\n c !== CHAR_RIGHT_SQUARE_BRACKET &&\n c !== CHAR_LEFT_CURLY_BRACKET &&\n c !== CHAR_RIGHT_CURLY_BRACKET &&\n // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “\"”\n c !== CHAR_SHARP &&\n c !== CHAR_AMPERSAND &&\n c !== CHAR_ASTERISK &&\n c !== CHAR_EXCLAMATION &&\n c !== CHAR_VERTICAL_LINE &&\n c !== CHAR_EQUALS &&\n c !== CHAR_GREATER_THAN &&\n c !== CHAR_SINGLE_QUOTE &&\n c !== CHAR_DOUBLE_QUOTE &&\n // | “%” | “@” | “`”)\n c !== CHAR_PERCENT &&\n c !== CHAR_COMMERCIAL_AT &&\n c !== CHAR_GRAVE_ACCENT\n}\n\n// Simplified test for values allowed as the last character in plain style.\nfunction isPlainSafeLast (c) {\n // just not whitespace or colon, it will be checked to be plain character later\n return !isWhitespace(c) && c !== CHAR_COLON\n}\n\n// Same as 'string'.codePointAt(pos), but works in older browsers.\nfunction codePointAt (string, pos) {\n const first = string.charCodeAt(pos)\n let second\n\n if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) {\n second = string.charCodeAt(pos + 1)\n if (second >= 0xDC00 && second <= 0xDFFF) {\n // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae\n return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000\n }\n }\n return first\n}\n\n// Determines whether block indentation indicator is required.\nfunction needIndentIndicator (string) {\n const leadingSpaceRe = /^\\n* /\n return leadingSpaceRe.test(string)\n}\n\nconst STYLE_PLAIN = 1\nconst STYLE_SINGLE = 2\nconst STYLE_LITERAL = 3\nconst STYLE_FOLDED = 4\nconst STYLE_DOUBLE = 5\n\n// Determines which scalar styles are possible and returns the preferred style.\n// lineWidth = -1 => no limit.\n// Pre-conditions: str.length > 0.\n// Post-conditions:\n// STYLE_PLAIN or STYLE_SINGLE => no \\n are in the string.\n// STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).\n// STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).\nfunction chooseScalarStyle (string, singleLineOnly, indentPerLevel, lineWidth,\n testAmbiguousType, quotingType, forceQuotes, inblock) {\n let i\n let char = 0\n let prevChar = null\n let hasLineBreak = false\n let hasFoldableLine = false // only checked if shouldTrackWidth\n const shouldTrackWidth = lineWidth !== -1\n let previousLineBreak = -1 // count the first line correctly\n let plain = isPlainSafeFirst(codePointAt(string, 0)) &&\n isPlainSafeLast(codePointAt(string, string.length - 1))\n\n if (singleLineOnly || forceQuotes) {\n // Case: no block styles.\n // Check for disallowed characters to rule out plain and single.\n for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n char = codePointAt(string, i)\n if (!isPrintable(char)) {\n return STYLE_DOUBLE\n }\n plain = plain && isPlainSafe(char, prevChar, inblock)\n prevChar = char\n }\n } else {\n // Case: block styles permitted.\n for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n char = codePointAt(string, i)\n if (char === CHAR_LINE_FEED) {\n hasLineBreak = true\n // Check if any line can be folded.\n if (shouldTrackWidth) {\n hasFoldableLine = hasFoldableLine ||\n // Foldable line = too long, and not more-indented.\n (i - previousLineBreak - 1 > lineWidth &&\n string[previousLineBreak + 1] !== ' ')\n previousLineBreak = i\n }\n } else if (!isPrintable(char)) {\n return STYLE_DOUBLE\n }\n plain = plain && isPlainSafe(char, prevChar, inblock)\n prevChar = char\n }\n // in case the end is missing a \\n\n hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&\n (i - previousLineBreak - 1 > lineWidth &&\n string[previousLineBreak + 1] !== ' '))\n }\n // Although every style can represent \\n without escaping, prefer block styles\n // for multiline, since they're more readable and they don't add empty lines.\n // Also prefer folding a super-long line.\n if (!hasLineBreak && !hasFoldableLine) {\n // Strings interpretable as another type have to be quoted;\n // e.g. the string 'true' vs. the boolean true.\n if (plain && !forceQuotes && !testAmbiguousType(string)) {\n return STYLE_PLAIN\n }\n return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE\n }\n // Edge case: block indentation indicator can only have one digit.\n if (indentPerLevel > 9 && needIndentIndicator(string)) {\n return STYLE_DOUBLE\n }\n // At this point we know block styles are valid.\n // Prefer literal style unless we want to fold.\n if (!forceQuotes) {\n return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL\n }\n return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE\n}\n\n// Note: line breaking/folding is implemented for only the folded style.\n// NB. We drop the last trailing newline (if any) of a returned block scalar\n// since the dumper adds its own newline. This always works:\n// • No ending newline => unaffected; already using strip \"-\" chomping.\n// • Ending newline => removed then restored.\n// Importantly, this keeps the \"+\" chomp indicator from gaining an extra line.\nfunction writeScalar (state, string, level, iskey, inblock) {\n state.dump = (function () {\n if (string.length === 0) {\n return state.quotingType === QUOTING_TYPE_DOUBLE ? '\"\"' : \"''\"\n }\n if (!state.noCompatMode) {\n if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {\n return state.quotingType === QUOTING_TYPE_DOUBLE ? ('\"' + string + '\"') : (\"'\" + string + \"'\")\n }\n }\n\n const indent = state.indent * Math.max(1, level) // no 0-indent scalars\n // As indentation gets deeper, let the width decrease monotonically\n // to the lower bound min(state.lineWidth, 40).\n // Note that this implies\n // state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.\n // state.lineWidth > 40 + state.indent: width decreases until the lower bound.\n // This behaves better than a constant minimum width which disallows narrower options,\n // or an indent threshold which causes the width to suddenly increase.\n const lineWidth = (state.lineWidth === -1)\n ? -1\n : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent)\n\n // Without knowing if keys are implicit/explicit, assume implicit for safety.\n const singleLineOnly = iskey ||\n // No block styles in flow mode.\n (state.flowLevel > -1 && level >= state.flowLevel)\n function testAmbiguity (string) {\n return testImplicitResolving(state, string)\n }\n\n switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth,\n testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {\n case STYLE_PLAIN:\n return string\n case STYLE_SINGLE:\n return \"'\" + string.replace(/'/g, \"''\") + \"'\"\n case STYLE_LITERAL:\n return '|' + blockHeader(string, state.indent) +\n dropEndingNewline(indentString(string, indent))\n case STYLE_FOLDED:\n return '>' + blockHeader(string, state.indent) +\n dropEndingNewline(indentString(foldString(string, lineWidth), indent))\n case STYLE_DOUBLE:\n return '\"' + escapeString(string, lineWidth) + '\"'\n default:\n throw new YAMLException('impossible error: invalid scalar style')\n }\n }())\n}\n\n// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.\nfunction blockHeader (string, indentPerLevel) {\n const indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : ''\n\n // note the special case: the string '\\n' counts as a \"trailing\" empty line.\n const clip = string[string.length - 1] === '\\n'\n const keep = clip && (string[string.length - 2] === '\\n' || string === '\\n')\n const chomp = keep ? '+' : (clip ? '' : '-')\n\n return indentIndicator + chomp + '\\n'\n}\n\n// (See the note for writeScalar.)\nfunction dropEndingNewline (string) {\n return string[string.length - 1] === '\\n' ? string.slice(0, -1) : string\n}\n\n// Note: a long line without a suitable break point will exceed the width limit.\n// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.\nfunction foldString (string, width) {\n // In folded style, $k$ consecutive newlines output as $k+1$ newlines—\n // unless they're before or after a more-indented line, or at the very\n // beginning or end, in which case $k$ maps to $k$.\n // Therefore, parse each chunk as newline(s) followed by a content line.\n const lineRe = /(\\n+)([^\\n]*)/g\n\n // first line (possibly an empty line)\n let result = (function () {\n let nextLF = string.indexOf('\\n')\n nextLF = nextLF !== -1 ? nextLF : string.length\n lineRe.lastIndex = nextLF\n return foldLine(string.slice(0, nextLF), width)\n }())\n // If we haven't reached the first content line yet, don't add an extra \\n.\n let prevMoreIndented = string[0] === '\\n' || string[0] === ' '\n let moreIndented\n\n // rest of the lines\n let match\n while ((match = lineRe.exec(string))) {\n const prefix = match[1]\n const line = match[2]\n\n moreIndented = (line[0] === ' ')\n result += prefix +\n ((!prevMoreIndented && !moreIndented && line !== '') ? '\\n' : '') +\n foldLine(line, width)\n prevMoreIndented = moreIndented\n }\n\n return result\n}\n\n// Greedy line breaking.\n// Picks the longest line under the limit each time,\n// otherwise settles for the shortest line over the limit.\n// NB. More-indented lines *cannot* be folded, as that would add an extra \\n.\nfunction foldLine (line, width) {\n if (line === '' || line[0] === ' ') return line\n\n // Since a more-indented line adds a \\n, breaks can't be followed by a space.\n const breakRe = / [^ ]/g // note: the match index will always be <= length-2.\n let match\n // start is an inclusive index. end, curr, and next are exclusive.\n let start = 0\n let end\n let curr = 0\n let next = 0\n let result = ''\n\n // Invariants: 0 <= start <= length-1.\n // 0 <= curr <= next <= max(0, length-2). curr - start <= width.\n // Inside the loop:\n // A match implies length >= 2, so curr and next are <= length-2.\n while ((match = breakRe.exec(line))) {\n next = match.index\n // maintain invariant: curr - start <= width\n if (next - start > width) {\n end = (curr > start) ? curr : next // derive end <= length-2\n result += '\\n' + line.slice(start, end)\n // skip the space that was output as \\n\n start = end + 1 // derive start <= length-1\n }\n curr = next\n }\n\n // By the invariants, start <= length-1, so there is something left over.\n // It is either the whole string or a part starting from non-whitespace.\n result += '\\n'\n // Insert a break if the remainder is too long and there is a break available.\n if (line.length - start > width && curr > start) {\n result += line.slice(start, curr) + '\\n' + line.slice(curr + 1)\n } else {\n result += line.slice(start)\n }\n\n return result.slice(1) // drop extra \\n joiner\n}\n\n// Escapes a double-quoted string.\nfunction escapeString (string) {\n let result = ''\n let char = 0\n\n for (let i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n char = codePointAt(string, i)\n const escapeSeq = ESCAPE_SEQUENCES[char]\n\n if (!escapeSeq && isPrintable(char)) {\n result += string[i]\n if (char >= 0x10000) result += string[i + 1]\n } else {\n result += escapeSeq || encodeHex(char)\n }\n }\n\n return result\n}\n\nfunction writeFlowSequence (state, level, object) {\n let _result = ''\n const _tag = state.tag\n\n for (let index = 0, length = object.length; index < length; index += 1) {\n let value = object[index]\n\n if (state.replacer) {\n value = state.replacer.call(object, String(index), value)\n }\n\n // Write only valid elements, put null instead of invalid elements.\n if (writeNode(state, level, value, false, false) ||\n (typeof value === 'undefined' &&\n writeNode(state, level, null, false, false))) {\n if (_result !== '') _result += ',' + (!state.condenseFlow ? ' ' : '')\n _result += state.dump\n }\n }\n\n state.tag = _tag\n state.dump = '[' + _result + ']'\n}\n\nfunction writeBlockSequence (state, level, object, compact) {\n let _result = ''\n const _tag = state.tag\n\n for (let index = 0, length = object.length; index < length; index += 1) {\n let value = object[index]\n\n if (state.replacer) {\n value = state.replacer.call(object, String(index), value)\n }\n\n // Write only valid elements, put null instead of invalid elements.\n if (writeNode(state, level + 1, value, true, true, false, true) ||\n (typeof value === 'undefined' &&\n writeNode(state, level + 1, null, true, true, false, true))) {\n if (!compact || _result !== '') {\n _result += generateNextLine(state, level)\n }\n\n if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n _result += '-'\n } else {\n _result += '- '\n }\n\n _result += state.dump\n }\n }\n\n state.tag = _tag\n state.dump = _result || '[]' // Empty sequence if no valid values.\n}\n\nfunction writeFlowMapping (state, level, object) {\n let _result = ''\n const _tag = state.tag\n const objectKeyList = Object.keys(object)\n\n for (let index = 0, length = objectKeyList.length; index < length; index += 1) {\n let pairBuffer = ''\n if (_result !== '') pairBuffer += ', '\n\n if (state.condenseFlow) pairBuffer += '\"'\n\n const objectKey = objectKeyList[index]\n let objectValue = object[objectKey]\n\n if (state.replacer) {\n objectValue = state.replacer.call(object, objectKey, objectValue)\n }\n\n if (!writeNode(state, level, objectKey, false, false)) {\n continue // Skip this pair because of invalid key;\n }\n\n if (state.dump.length > 1024) pairBuffer += '? '\n\n pairBuffer += state.dump + (state.condenseFlow ? '\"' : '') + ':' + (state.condenseFlow ? '' : ' ')\n\n if (!writeNode(state, level, objectValue, false, false)) {\n continue // Skip this pair because of invalid value.\n }\n\n pairBuffer += state.dump\n\n // Both key and value are valid.\n _result += pairBuffer\n }\n\n state.tag = _tag\n state.dump = '{' + _result + '}'\n}\n\nfunction writeBlockMapping (state, level, object, compact) {\n let _result = ''\n const _tag = state.tag\n const objectKeyList = Object.keys(object)\n\n // Allow sorting keys so that the output file is deterministic\n if (state.sortKeys === true) {\n // Default sorting\n objectKeyList.sort()\n } else if (typeof state.sortKeys === 'function') {\n // Custom sort function\n objectKeyList.sort(state.sortKeys)\n } else if (state.sortKeys) {\n // Something is wrong\n throw new YAMLException('sortKeys must be a boolean or a function')\n }\n\n for (let index = 0, length = objectKeyList.length; index < length; index += 1) {\n let pairBuffer = ''\n\n if (!compact || _result !== '') {\n pairBuffer += generateNextLine(state, level)\n }\n\n const objectKey = objectKeyList[index]\n let objectValue = object[objectKey]\n\n if (state.replacer) {\n objectValue = state.replacer.call(object, objectKey, objectValue)\n }\n\n if (!writeNode(state, level + 1, objectKey, true, true, true)) {\n continue // Skip this pair because of invalid key.\n }\n\n const explicitPair = (state.tag !== null && state.tag !== '?') ||\n (state.dump && state.dump.length > 1024)\n\n if (explicitPair) {\n if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n pairBuffer += '?'\n } else {\n pairBuffer += '? '\n }\n }\n\n pairBuffer += state.dump\n\n if (explicitPair) {\n pairBuffer += generateNextLine(state, level)\n }\n\n if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {\n continue // Skip this pair because of invalid value.\n }\n\n if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n pairBuffer += ':'\n } else {\n pairBuffer += ': '\n }\n\n pairBuffer += state.dump\n\n // Both key and value are valid.\n _result += pairBuffer\n }\n\n state.tag = _tag\n state.dump = _result || '{}' // Empty mapping if no valid pairs.\n}\n\nfunction detectType (state, object, explicit) {\n const typeList = explicit ? state.explicitTypes : state.implicitTypes\n\n for (let index = 0, length = typeList.length; index < length; index += 1) {\n const type = typeList[index]\n\n if ((type.instanceOf || type.predicate) &&\n (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&\n (!type.predicate || type.predicate(object))) {\n if (explicit) {\n if (type.multi && type.representName) {\n state.tag = type.representName(object)\n } else {\n state.tag = type.tag\n }\n } else {\n state.tag = '?'\n }\n\n if (type.represent) {\n const style = state.styleMap[type.tag] || type.defaultStyle\n\n let _result\n if (_toString.call(type.represent) === '[object Function]') {\n _result = type.represent(object, style)\n } else if (_hasOwnProperty.call(type.represent, style)) {\n _result = type.represent[style](object, style)\n } else {\n throw new YAMLException('!<' + type.tag + '> tag resolver accepts not \"' + style + '\" style')\n }\n\n state.dump = _result\n }\n\n return true\n }\n }\n\n return false\n}\n\n// Serializes `object` and writes it to global `result`.\n// Returns true on success, or false on invalid object.\n//\nfunction writeNode (state, level, object, block, compact, iskey, isblockseq) {\n state.tag = null\n state.dump = object\n\n if (!detectType(state, object, false)) {\n detectType(state, object, true)\n }\n\n const type = _toString.call(state.dump)\n const inblock = block\n\n if (block) {\n block = (state.flowLevel < 0 || state.flowLevel > level)\n }\n\n const objectOrArray = type === '[object Object]' || type === '[object Array]'\n let duplicateIndex\n let duplicate\n\n if (objectOrArray) {\n duplicateIndex = state.duplicates.indexOf(object)\n duplicate = duplicateIndex !== -1\n }\n\n if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {\n compact = false\n }\n\n if (duplicate && state.usedDuplicates[duplicateIndex]) {\n state.dump = '*ref_' + duplicateIndex\n } else {\n if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {\n state.usedDuplicates[duplicateIndex] = true\n }\n if (type === '[object Object]') {\n if (block && (Object.keys(state.dump).length !== 0)) {\n writeBlockMapping(state, level, state.dump, compact)\n if (duplicate) {\n state.dump = '&ref_' + duplicateIndex + state.dump\n }\n } else {\n writeFlowMapping(state, level, state.dump)\n if (duplicate) {\n state.dump = '&ref_' + duplicateIndex + ' ' + state.dump\n }\n }\n } else if (type === '[object Array]') {\n if (block && (state.dump.length !== 0)) {\n if (state.noArrayIndent && !isblockseq && level > 0) {\n writeBlockSequence(state, level - 1, state.dump, compact)\n } else {\n writeBlockSequence(state, level, state.dump, compact)\n }\n if (duplicate) {\n state.dump = '&ref_' + duplicateIndex + state.dump\n }\n } else {\n writeFlowSequence(state, level, state.dump)\n if (duplicate) {\n state.dump = '&ref_' + duplicateIndex + ' ' + state.dump\n }\n }\n } else if (type === '[object String]') {\n if (state.tag !== '?') {\n writeScalar(state, state.dump, level, iskey, inblock)\n }\n } else if (type === '[object Undefined]') {\n return false\n } else {\n if (state.skipInvalid) return false\n throw new YAMLException('unacceptable kind of an object to dump ' + type)\n }\n\n if (state.tag !== null && state.tag !== '?') {\n // Need to encode all characters except those allowed by the spec:\n //\n // [35] ns-dec-digit ::= [#x30-#x39] /* 0-9 */\n // [36] ns-hex-digit ::= ns-dec-digit\n // | [#x41-#x46] /* A-F */ | [#x61-#x66] /* a-f */\n // [37] ns-ascii-letter ::= [#x41-#x5A] /* A-Z */ | [#x61-#x7A] /* a-z */\n // [38] ns-word-char ::= ns-dec-digit | ns-ascii-letter | “-”\n // [39] ns-uri-char ::= “%” ns-hex-digit ns-hex-digit | ns-word-char | “#”\n // | “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,”\n // | “_” | “.” | “!” | “~” | “*” | “'” | “(” | “)” | “[” | “]”\n //\n // Also need to encode '!' because it has special meaning (end of tag prefix).\n //\n let tagStr = encodeURI(\n state.tag[0] === '!' ? state.tag.slice(1) : state.tag\n ).replace(/!/g, '%21')\n\n if (state.tag[0] === '!') {\n tagStr = '!' + tagStr\n } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') {\n tagStr = '!!' + tagStr.slice(18)\n } else {\n tagStr = '!<' + tagStr + '>'\n }\n\n state.dump = tagStr + ' ' + state.dump\n }\n }\n\n return true\n}\n\nfunction getDuplicateReferences (object, state) {\n const objects = []\n const duplicatesIndexes = []\n\n inspectNode(object, objects, duplicatesIndexes)\n\n const length = duplicatesIndexes.length\n for (let index = 0; index < length; index += 1) {\n state.duplicates.push(objects[duplicatesIndexes[index]])\n }\n state.usedDuplicates = new Array(length)\n}\n\nfunction inspectNode (object, objects, duplicatesIndexes) {\n if (object !== null && typeof object === 'object') {\n const index = objects.indexOf(object)\n if (index !== -1) {\n if (duplicatesIndexes.indexOf(index) === -1) {\n duplicatesIndexes.push(index)\n }\n } else {\n objects.push(object)\n\n if (Array.isArray(object)) {\n for (let i = 0, length = object.length; i < length; i += 1) {\n inspectNode(object[i], objects, duplicatesIndexes)\n }\n } else {\n const objectKeyList = Object.keys(object)\n\n for (let i = 0, length = objectKeyList.length; i < length; i += 1) {\n inspectNode(object[objectKeyList[i]], objects, duplicatesIndexes)\n }\n }\n }\n }\n}\n\nfunction dump (input, options) {\n options = options || {}\n\n const state = new State(options)\n\n if (!state.noRefs) getDuplicateReferences(input, state)\n\n let value = input\n\n if (state.replacer) {\n value = state.replacer.call({ '': value }, '', value)\n }\n\n if (writeNode(state, 0, value, true, true)) return state.dump + '\\n'\n\n return ''\n}\n\nmodule.exports.dump = dump\n","'use strict'\n\nconst loader = require('./lib/loader')\nconst dumper = require('./lib/dumper')\n\nfunction renamed (from, to) {\n return function () {\n throw new Error('Function yaml.' + from + ' is removed in js-yaml 4. ' +\n 'Use yaml.' + to + ' instead, which is now safe by default.')\n }\n}\n\nmodule.exports.Type = require('./lib/type')\nmodule.exports.Schema = require('./lib/schema')\nmodule.exports.FAILSAFE_SCHEMA = require('./lib/schema/failsafe')\nmodule.exports.JSON_SCHEMA = require('./lib/schema/json')\nmodule.exports.CORE_SCHEMA = require('./lib/schema/core')\nmodule.exports.DEFAULT_SCHEMA = require('./lib/schema/default')\nmodule.exports.load = loader.load\nmodule.exports.loadAll = loader.loadAll\nmodule.exports.dump = dumper.dump\nmodule.exports.YAMLException = require('./lib/exception')\n\n// Re-export all types in case user wants to create custom schema\nmodule.exports.types = {\n binary: require('./lib/type/binary'),\n float: require('./lib/type/float'),\n map: require('./lib/type/map'),\n null: require('./lib/type/null'),\n pairs: require('./lib/type/pairs'),\n set: require('./lib/type/set'),\n timestamp: require('./lib/type/timestamp'),\n bool: require('./lib/type/bool'),\n int: require('./lib/type/int'),\n merge: require('./lib/type/merge'),\n omap: require('./lib/type/omap'),\n seq: require('./lib/type/seq'),\n str: require('./lib/type/str')\n}\n\n// Removed functions from JS-YAML 3.0.x\nmodule.exports.safeLoad = renamed('safeLoad', 'load')\nmodule.exports.safeLoadAll = renamed('safeLoadAll', 'loadAll')\nmodule.exports.safeDump = renamed('safeDump', 'dump')\n","import yaml from '../index.js'\n\nconst {\n Type,\n Schema,\n FAILSAFE_SCHEMA,\n JSON_SCHEMA,\n CORE_SCHEMA,\n DEFAULT_SCHEMA,\n load,\n loadAll,\n dump,\n YAMLException,\n types,\n safeLoad,\n safeLoadAll,\n safeDump\n} = yaml\n\nexport {\n Type,\n Schema,\n FAILSAFE_SCHEMA,\n JSON_SCHEMA,\n CORE_SCHEMA,\n DEFAULT_SCHEMA,\n load,\n loadAll,\n dump,\n YAMLException,\n types,\n safeLoad,\n safeLoadAll,\n safeDump\n}\n\nexport default yaml\n","/**\n * PDLSS Policy Parser\n *\n * Parses local YAML policy files into typed LocalPolicy objects.\n * Validates against the PDLSS schema to ensure cloud compatibility.\n */\n\nimport * as yaml from 'js-yaml';\nimport { readFileSync } from 'fs';\nimport type { LocalPolicy } from '../gateway/types';\nimport { validatePolicy, type ValidationResult } from './schema';\n\nexport interface ParseResult {\n policy: LocalPolicy | null;\n validation: ValidationResult;\n rawYaml?: string;\n}\n\n/**\n * Parse a YAML string into a LocalPolicy.\n */\nexport function parseYaml(yamlContent: string): ParseResult {\n let parsed: unknown;\n\n try {\n parsed = yaml.load(yamlContent);\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Invalid YAML';\n return {\n policy: null,\n validation: { valid: false, errors: [{ path: '', message: `YAML parse error: ${message}` }] },\n rawYaml: yamlContent,\n };\n }\n\n const validation = validatePolicy(parsed);\n\n if (!validation.valid) {\n return { policy: null, validation, rawYaml: yamlContent };\n }\n\n return {\n policy: parsed as LocalPolicy,\n validation,\n rawYaml: yamlContent,\n };\n}\n\n/**\n * Parse a YAML file from disk into a LocalPolicy.\n */\nexport function parseFile(filePath: string): ParseResult {\n let content: string;\n\n try {\n content = readFileSync(filePath, 'utf-8');\n } catch (err) {\n const message = err instanceof Error ? err.message : 'File read error';\n return {\n policy: null,\n validation: { valid: false, errors: [{ path: '', message: `Failed to read policy file: ${message}` }] },\n };\n }\n\n return parseYaml(content);\n}\n\n/**\n * Convert a LocalPolicy back to YAML string (for upload to cloud).\n */\nexport function toYaml(policy: LocalPolicy): string {\n return yaml.dump(policy, { lineWidth: 120, noRefs: true });\n}\n","/**\n * PDLSS Policy Schema Validation\n *\n * Validates local YAML policy files against the PDLSS schema.\n * Ensures local policies can be uploaded to cloud without lossy transformation.\n */\n\nimport type { LocalRiskThresholds } from '../gateway/types';\n\nexport interface ValidationError {\n path: string;\n message: string;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationError[];\n}\n\n/**\n * Validate a parsed local policy object against the PDLSS schema.\n */\nexport function validatePolicy(policy: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n\n if (!policy || typeof policy !== 'object') {\n return { valid: false, errors: [{ path: '', message: 'Policy must be an object' }] };\n }\n\n const p = policy as Record<string, unknown>;\n\n // Required fields\n if (typeof p.version !== 'string') {\n errors.push({ path: 'version', message: 'version is required and must be a string' });\n }\n if (typeof p.name !== 'string') {\n errors.push({ path: 'name', message: 'name is required and must be a string' });\n }\n\n // Purposes\n if (!Array.isArray(p.purposes)) {\n errors.push({ path: 'purposes', message: 'purposes is required and must be an array' });\n } else {\n p.purposes.forEach((purpose: unknown, i: number) => {\n errors.push(...validatePurpose(purpose, `purposes[${i}]`));\n });\n }\n\n // Scope (optional)\n if (p.scope !== undefined) {\n errors.push(...validateScope(p.scope, 'scope'));\n }\n\n // Limits (optional)\n if (p.limits !== undefined) {\n errors.push(...validateLimits(p.limits, 'limits'));\n }\n\n // Risk thresholds (optional)\n if (p.riskThresholds !== undefined) {\n errors.push(...validateRiskThresholds(p.riskThresholds, 'riskThresholds'));\n }\n\n return { valid: errors.length === 0, errors };\n}\n\nfunction validatePurpose(purpose: unknown, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (!purpose || typeof purpose !== 'object') {\n return [{ path, message: 'purpose must be an object' }];\n }\n\n const p = purpose as Record<string, unknown>;\n\n if (typeof p.id !== 'string' || !p.id) {\n errors.push({ path: `${path}.id`, message: 'id is required and must be a non-empty string' });\n }\n\n if (typeof p.allowed !== 'boolean') {\n errors.push({ path: `${path}.allowed`, message: 'allowed is required and must be a boolean' });\n }\n\n if (p.targets !== undefined && !isStringArray(p.targets)) {\n errors.push({ path: `${path}.targets`, message: 'targets must be an array of strings' });\n }\n\n if (p.blockedPatterns !== undefined && !isStringArray(p.blockedPatterns)) {\n errors.push({\n path: `${path}.blockedPatterns`,\n message: 'blockedPatterns must be an array of strings',\n });\n }\n\n if (p.requiresApproval !== undefined && typeof p.requiresApproval !== 'boolean') {\n errors.push({\n path: `${path}.requiresApproval`,\n message: 'requiresApproval must be a boolean',\n });\n }\n\n return errors;\n}\n\nfunction validateScope(scope: unknown, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (typeof scope !== 'object' || scope === null) {\n return [{ path, message: 'scope must be an object' }];\n }\n\n const s = scope as Record<string, unknown>;\n\n for (const field of ['allowedDomains', 'blockedDomains', 'blockedResources']) {\n if (s[field] !== undefined && !isStringArray(s[field])) {\n errors.push({ path: `${path}.${field}`, message: `${field} must be an array of strings` });\n }\n }\n\n return errors;\n}\n\nfunction validateLimits(limits: unknown, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (typeof limits !== 'object' || limits === null) {\n return [{ path, message: 'limits must be an object' }];\n }\n\n const l = limits as Record<string, unknown>;\n\n if (l.autonomousThreshold !== undefined && typeof l.autonomousThreshold !== 'number') {\n errors.push({\n path: `${path}.autonomousThreshold`,\n message: 'autonomousThreshold must be a number',\n });\n }\n\n if (l.maxTransactionAmount !== undefined && typeof l.maxTransactionAmount !== 'number') {\n errors.push({\n path: `${path}.maxTransactionAmount`,\n message: 'maxTransactionAmount must be a number',\n });\n }\n\n // Relationship: the Autonomous Limit must not exceed the Hard Limit, else the\n // step-up band [autonomousThreshold, maxTransactionAmount) is empty/inverted.\n if (\n typeof l.autonomousThreshold === 'number' &&\n typeof l.maxTransactionAmount === 'number' &&\n l.autonomousThreshold > l.maxTransactionAmount\n ) {\n errors.push({\n path: `${path}.autonomousThreshold`,\n message:\n 'autonomousThreshold (Autonomous Limit) must be <= maxTransactionAmount (Hard Limit)',\n });\n }\n\n if (l.maxRequestsPerHour !== undefined && typeof l.maxRequestsPerHour !== 'number') {\n errors.push({\n path: `${path}.maxRequestsPerHour`,\n message: 'maxRequestsPerHour must be a number',\n });\n }\n\n if (l.currency !== undefined && typeof l.currency !== 'string') {\n errors.push({ path: `${path}.currency`, message: 'currency must be a string' });\n }\n\n return errors;\n}\n\nfunction validateRiskThresholds(thresholds: unknown, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (typeof thresholds !== 'object' || thresholds === null) {\n return [{ path, message: 'riskThresholds must be an object' }];\n }\n\n const t = thresholds as Record<string, unknown>;\n\n for (const range of ['autoAllow', 'requireApproval', 'autoBlock'] as const) {\n if (!t[range] || typeof t[range] !== 'object') {\n errors.push({\n path: `${path}.${range}`,\n message: `${range} is required and must be an object with min and max`,\n });\n continue;\n }\n\n const r = t[range] as Record<string, unknown>;\n if (typeof r.min !== 'number' || typeof r.max !== 'number') {\n errors.push({ path: `${path}.${range}`, message: `${range} must have numeric min and max` });\n } else if (r.min > r.max) {\n errors.push({ path: `${path}.${range}`, message: `${range}.min must be <= ${range}.max` });\n }\n }\n\n // Validate contiguous ranges (no gaps)\n if (isValidThresholdShape(t)) {\n const thresholdObj = t as unknown as LocalRiskThresholds;\n if (thresholdObj.autoAllow.max + 1 !== thresholdObj.requireApproval.min) {\n errors.push({\n path: `${path}`,\n message: `Gap between autoAllow.max (${thresholdObj.autoAllow.max}) and requireApproval.min (${thresholdObj.requireApproval.min}). Ranges must be contiguous.`,\n });\n }\n if (thresholdObj.requireApproval.max + 1 !== thresholdObj.autoBlock.min) {\n errors.push({\n path: `${path}`,\n message: `Gap between requireApproval.max (${thresholdObj.requireApproval.max}) and autoBlock.min (${thresholdObj.autoBlock.min}). Ranges must be contiguous.`,\n });\n }\n }\n\n return errors;\n}\n\nfunction isStringArray(val: unknown): val is string[] {\n return Array.isArray(val) && val.every((v) => typeof v === 'string');\n}\n\nfunction isValidThresholdShape(t: Record<string, unknown>): boolean {\n for (const key of ['autoAllow', 'requireApproval', 'autoBlock']) {\n const r = t[key];\n if (!r || typeof r !== 'object') return false;\n const range = r as Record<string, unknown>;\n if (typeof range.min !== 'number' || typeof range.max !== 'number') return false;\n }\n return true;\n}\n","/**\n * Local Mode — Evaluates actions against a local PDLSS policy file.\n * No network calls, no account required, runs entirely in-process.\n */\n\nimport type { AstraSyncGatewayConfig, PDLSSContext, VerificationDecision } from '../types';\nimport { LocalEvaluator } from '../../local-evaluator/evaluator';\nimport { parseFile } from '../../local-evaluator/pdlss-parser';\n\n/**\n * Load a local evaluator from config.\n */\nexport function loadEvaluator(config: AstraSyncGatewayConfig): LocalEvaluator {\n if (config.policy) {\n return new LocalEvaluator(config.policy);\n }\n\n if (config.policyFile) {\n const result = parseFile(config.policyFile);\n if (!result.policy) {\n const errors = result.validation.errors.map((e) => `${e.path}: ${e.message}`).join('; ');\n throw new Error(`Invalid policy file ${config.policyFile}: ${errors}`);\n }\n return new LocalEvaluator(result.policy);\n }\n\n throw new Error('Local mode requires either policyFile or policy in config');\n}\n\n/**\n * Verify locally against the loaded PDLSS policy.\n */\nexport function verifyLocal(evaluator: LocalEvaluator, context: PDLSSContext): VerificationDecision {\n return evaluator.evaluate(context);\n}\n","/**\n * AstraSync Universal Verification Gateway — Trust Level helpers.\n *\n * SDK 5.0.0: the `accessLevel` band (`none`/`restricted`/`read-only`/`standard`/\n * `full`/`internal`) was removed entirely — it never gated the access decision\n * (the server does, from a verified ID + runtime challenge + PDLSS match + trust\n * score). What remains here is the coarse trust-level badge derived from the\n * numeric trust score, used only for display.\n */\n\nimport type { TrustLevel } from './types';\n\n/**\n * Trust level score ranges\n */\nexport const TRUST_LEVEL_RANGES: Record<TrustLevel, { min: number; max: number }> = {\n BRONZE: { min: 0, max: 39 },\n SILVER: { min: 40, max: 59 },\n GOLD: { min: 60, max: 79 },\n PLATINUM: { min: 80, max: 100 },\n};\n\n/**\n * Determine trust level from score\n */\nexport function getTrustLevel(score: number): TrustLevel {\n if (score >= 80) return 'PLATINUM';\n if (score >= 60) return 'GOLD';\n if (score >= 40) return 'SILVER';\n return 'BRONZE';\n}\n","/**\n * Single source-of-truth for the SDK's\n * package version emitted on verify-access bodies (and any future\n * telemetry). Bumped alongside `package.json#version` on every release.\n *\n * Why a constant rather than `import pkg from '../package.json'`:\n * - `tsconfig.json` sets `rootDir: ./src`; importing the sibling\n * package.json fails the build with \"outside rootDir\".\n * - Build-time string replacement (tsup `define`, esbuild banner, etc.)\n * adds toolchain coupling for a trivial gain.\n * - Embedded readonly constant works in every environment (Node, browser,\n * bundlers, Deno) without runtime fs / network access.\n *\n * Release discipline: a CI lint can grep `package.json#version` against\n * this constant if the two ever diverge in the wild. A manual bump\n * is fine — bumping both in the release-ceremony commit keeps them\n * lockstep.\n */\nexport const SDK_VERSION = '5.10.0';\n","/**\n * Shared outbound-HTTP wrapper — every request the SDK makes to the\n * AstraSync backend (or anywhere else) goes through `sdkFetch` so it\n * carries an identifying User-Agent.\n *\n * Why: Node's global fetch defaults to `user-agent: node`, which is\n * indistinguishable from every other Node client on the wire. Visit\n * Intelligence observed our own SDK/beacon traffic as anonymous \"node\"\n * visits. Self-identification is the platform's own medicine.\n *\n * Browser note: some browsers filter the User-Agent request header\n * silently (never throwing), so this is a no-op there — which is correct:\n * in a browser the page's real UA is the honest identity.\n */\n\nimport { SDK_VERSION } from './version';\n\nexport const SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;\n\n/**\n * Add the SDK User-Agent without changing the SHAPE of the caller's headers\n * (plain records stay plain records) — interceptors, adapters, and tests\n * read `init.headers` as a record, and `Headers` would also lowercase names.\n */\nfunction withUserAgent(initHeaders: HeadersInit | undefined): HeadersInit {\n if (!initHeaders) return { 'user-agent': SDK_USER_AGENT };\n if (initHeaders instanceof Headers) {\n const copy = new Headers(initHeaders);\n if (!copy.has('user-agent')) copy.set('user-agent', SDK_USER_AGENT);\n return copy;\n }\n if (Array.isArray(initHeaders)) {\n const has = initHeaders.some(([name]) => name.toLowerCase() === 'user-agent');\n return has ? initHeaders : [...initHeaders, ['user-agent', SDK_USER_AGENT]];\n }\n const has = Object.keys(initHeaders).some((name) => name.toLowerCase() === 'user-agent');\n return has ? initHeaders : { 'user-agent': SDK_USER_AGENT, ...initHeaders };\n}\n\nexport const sdkFetch: typeof fetch = (input, init) =>\n fetch(input, { ...init, headers: withUserAgent(init?.headers) });\n","import { sdkFetch } from './http';\n/**\n * SDK-side discovery of canonical platform URLs via `/.well-known/agentic-commerce`.\n *\n * Fire-and-forget pre-fetch at middleware creation; first verify() awaits\n * the in-flight promise if it hasn't resolved. 60-minute TTL with\n * stale-while-revalidate background refresh.\n */\n\nexport interface WellKnownAgenticCommerce {\n registrationUrl: string;\n documentationUrl: string;\n verifyAccessUrl: string;\n /** 5.1.0: hosted AstraSync MCP bridge endpoint (absent on self-hosted backends). */\n mcpEndpoint?: string;\n /** 5.1.0: bridge connector-discovery doc (absent on self-hosted backends). */\n mcpDiscoveryUrl?: string;\n}\n\ninterface CacheEntry {\n data: WellKnownAgenticCommerce;\n fetchedAt: number;\n}\n\nconst CACHE_TTL_MS = 60 * 60 * 1000; // 60 minutes\n\nconst cache = new Map<string, CacheEntry>();\nconst inflight = new Map<string, Promise<WellKnownAgenticCommerce>>();\n\nfunction wellKnownUrl(apiBaseUrl: string): string {\n // apiBaseUrl is typically 'https://astrasync.ai/api' — strip the /api suffix\n // to get the platform root, then append /.well-known/agentic-commerce.\n const base = apiBaseUrl.replace(/\\/api\\/?$/, '');\n return `${base}/.well-known/agentic-commerce`;\n}\n\nasync function fetchWellKnown(apiBaseUrl: string): Promise<WellKnownAgenticCommerce> {\n const url = wellKnownUrl(apiBaseUrl);\n const response = await sdkFetch(url, {\n method: 'GET',\n headers: { Accept: 'application/json' },\n signal: AbortSignal.timeout(5000),\n });\n if (!response.ok) {\n throw new Error(\n `AstraSync platform must expose /.well-known/agentic-commerce; ` +\n `got ${response.status} from ${url}. SDK cannot initialise without it.`\n );\n }\n const data = (await response.json()) as Record<string, unknown>;\n if (!data.registrationUrl || !data.documentationUrl || !data.verifyAccessUrl) {\n throw new Error(\n `/.well-known/agentic-commerce response missing required fields ` +\n `(registrationUrl, documentationUrl, verifyAccessUrl).`\n );\n }\n return data as unknown as WellKnownAgenticCommerce;\n}\n\n/**\n * Start a background fetch. Returns the promise for callers that need\n * to await it (first verify() call).\n */\nexport function prefetchWellKnown(apiBaseUrl: string): Promise<WellKnownAgenticCommerce> {\n const existing = inflight.get(apiBaseUrl);\n if (existing) return existing;\n\n const promise = fetchWellKnown(apiBaseUrl)\n .then((data) => {\n cache.set(apiBaseUrl, { data, fetchedAt: Date.now() });\n inflight.delete(apiBaseUrl);\n return data;\n })\n .catch((err) => {\n inflight.delete(apiBaseUrl);\n throw err;\n });\n\n inflight.set(apiBaseUrl, promise);\n return promise;\n}\n\n/**\n * Get cached well-known URLs. If stale, triggers a background refresh\n * and returns stale data (stale-while-revalidate). If no cache exists,\n * awaits the in-flight fetch or starts a new one.\n */\nexport async function getWellKnownUrls(apiBaseUrl: string): Promise<WellKnownAgenticCommerce> {\n const entry = cache.get(apiBaseUrl);\n\n if (entry) {\n if (Date.now() - entry.fetchedAt > CACHE_TTL_MS) {\n // Stale — trigger background refresh, return stale data\n prefetchWellKnown(apiBaseUrl).catch(() => {\n // Background refresh failed — stale data remains until next request\n });\n }\n return entry.data;\n }\n\n // No cache — must await\n const pending = inflight.get(apiBaseUrl);\n if (pending) return pending;\n\n return prefetchWellKnown(apiBaseUrl);\n}\n\n/**\n * Synchronous cache read — returns cached URLs or undefined.\n * Never triggers a fetch. Used by verify() to avoid extra HTTP calls\n * in the hot path; adapters are responsible for prefetching.\n */\nexport function getCachedWellKnownUrls(apiBaseUrl: string): WellKnownAgenticCommerce | undefined {\n return cache.get(apiBaseUrl)?.data;\n}\n\n/** Reset cache — for testing only. */\nexport function _resetWellKnownCache(): void {\n cache.clear();\n inflight.clear();\n}\n","/**\n * AstraSync Universal Verification Gateway - Core Verification Logic\n *\n * This module handles the core verification logic, calling the AstraSync API\n * and processing the response into a standardized VerificationResult.\n */\n\nimport { sdkFetch } from './http';\nimport type {\n GatewayConfig,\n AgentCredentials,\n VerificationRequest,\n VerificationResult,\n VerifiedAgent,\n VerifiedDeveloper,\n VerifiedOrganization,\n GuidanceInfo,\n EnhancedVerificationResult,\n TokenGuidance,\n RuntimeChallengeResult,\n StepUpApprovalInfo,\n SettlementOutcomeInfo,\n MerchantSettlementToken,\n FulfilmentInfo,\n SettlementArtifact,\n AttemptReport,\n} from './types';\nimport { getTrustLevel } from './trust-levels';\nimport type { ObservedMetadata } from './metadata-capture';\nimport { SDK_VERSION } from './version';\nimport { getCachedWellKnownUrls, type WellKnownAgenticCommerce } from './well-known';\n\n/**\n * Default configuration values\n *\n * apiBaseUrl matches the OpenAPI authoritative server (https://astrasync.ai/api\n * for prod, https://staging.astrasync.ai/api for staging). Always include the\n * /api path prefix when overriding — registration / docs URLs are derived by\n * stripping it.\n */\nconst DEFAULT_CONFIG: Partial<GatewayConfig> = {\n apiBaseUrl: 'https://astrasync.ai/api',\n // minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.\n // cacheTtl deliberately unset. When undefined, cacheResult applies the 60s\n // default; the caller's explicit value is honoured for cacheable results.\n // Denials and step-up escalations are NEVER cached (3.6.0) regardless of\n // cacheTtl. Set cacheTtl: 0 to disable caching entirely.\n debug: false,\n};\n\n/**\n * Init self-test state. Fires once per process on first verify() call to warn\n * if apiBaseUrl is pointing at the wrong host (e.g. a marketing site that\n * 200s with text/html instead of the API).\n */\nlet initCheckPerformed = false;\n\n/** Test-only: re-arm the one-time init self-check. */\nexport function _resetInitCheck(): void {\n initCheckPerformed = false;\n}\n\n/** One-shot guard for v2.3.0 deprecation warning. */\nlet deprecationWarningShown = false;\n\nasync function performInitCheck(\n apiBaseUrl: string,\n debug?: boolean,\n strictInit?: boolean,\n apiKey?: string\n): Promise<void> {\n initCheckPerformed = true;\n try {\n const probeUrl = `${apiBaseUrl}/agents/verify-access`;\n // HEAD mirrors GET semantics (running the full request pipeline without a\n // body) so the response carries the same content-type the marketing 404\n // would return. OPTIONS often gets short-circuited by CORS-preflight\n // handlers and returns no content-type, defeating the check.\n const response = await sdkFetch(probeUrl, { method: 'HEAD' });\n const contentType = response.headers.get('content-type') ?? '';\n if (contentType.startsWith('text/html')) {\n const message =\n `[VerificationGateway] apiBaseUrl '${apiBaseUrl}' returned HTML (content-type: ${contentType}). ` +\n `This usually means apiBaseUrl is pointing at a marketing site instead of the API. ` +\n `Expected: 'https://astrasync.ai/api' (prod) or 'https://staging.astrasync.ai/api' (staging).`;\n // Audit F-A6-33: when strictInit is set, throw on misconfig instead\n // of warning + continuing. Recurring footgun per\n // `[[feedback_astrasync_api_url_canonical]]` — silent warn lets\n // misconfigured prod deploys ship with all verify-access calls\n // silently failing.\n if (strictInit) {\n throw new Error(`${message} (strictInit=true)`);\n }\n console.warn(`${message} Set disableInitChecks: true on GatewayConfig to silence.`);\n } else if (debug) {\n console.log(\n `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`\n );\n }\n\n // 4.0.0: key liveness probe. A dead API key otherwise surfaces only\n // per-request as inbound agents get turned away — the operator should\n // learn at deploy time. 404 = older backend without self-check: silent.\n if (apiKey) {\n const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check`, {\n headers: { Authorization: `Bearer ${apiKey}` },\n });\n if (selfCheck.status === 401) {\n const body = (await selfCheck.json().catch(() => ({}))) as {\n code?: string;\n message?: string;\n remediation?: { manageUrl?: string };\n };\n const message =\n `[VerificationGateway] the configured AstraSync API key was REJECTED at startup ` +\n `(${body.code ?? 'api_key_invalid'}: ${body.message ?? 'invalid key'}). Every inbound agent ` +\n `will be turned away until the key is rotated` +\n (body.remediation?.manageUrl ? ` at ${body.remediation.manageUrl}` : '') +\n `.`;\n if (strictInit) {\n throw new Error(`${message} (strictInit=true)`);\n }\n console.error(message);\n } else if (selfCheck.ok) {\n const body = (await selfCheck.json().catch(() => ({}))) as {\n daysToExpiry?: number | null;\n };\n if (typeof body.daysToExpiry === 'number' && body.daysToExpiry <= 7) {\n console.warn(\n `[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) — ` +\n `rotate it at Settings → Developer Tools before integrations start failing.`\n );\n } else if (debug) {\n console.log('[VerificationGateway] API key self-check passed');\n }\n }\n }\n } catch (err) {\n if (strictInit) {\n // strict mode propagates init failures so callers get a clear,\n // synchronous \"your config is broken\" signal at startup.\n throw err;\n }\n if (debug) {\n console.log(`[VerificationGateway] init check failed (non-blocking): ${String(err)}`);\n }\n }\n}\n\n/**\n * Simple in-memory cache for verification results\n */\nconst verificationCache = new Map<string, { result: VerificationResult; expiresAt: number }>();\n\n/**\n * Generate cache key from the full request shape.\n *\n * Historically the key was credentials-only (`astraId-apiKey-jwt`),\n * which silently returned the cached result of a prior call even when the\n * subsequent call's purpose/action/counterparty/etc. differed. That was a\n * security gap — a warm cache could serve an allow verdict for a purpose the\n * agent hadn't actually been authorised for. Key now includes every field\n * that affects the backend verdict.\n *\n * MAINTAIN: when adding a field to VerificationRequest that affects the\n * backend verdict, add it to this key. Fields that don't affect verdict\n * (e.g. requestId, timestamps, sdkVersion) don't belong here — including\n * them would needlessly thrash the cache for repeated identical requests.\n *\n * 3.12.0 (Trust Record): `attemptId` and `considerationSet` are\n * deliberately EXCLUDED — like `callerMetadata.observedMetadata` they are\n * observational pass-through that never affects the verdict, and keying on\n * a per-attempt id would defeat verdict caching entirely. Cache hits get\n * their attemptId rewritten in verify() instead (never leak a prior\n * attempt's id from a cached result).\n */\nfunction getCacheKey(request: VerificationRequest, counterpartyId?: string): string {\n const c = request.credentials;\n return [\n c.astraId || '',\n c.apiKey || '',\n c.jwt || '',\n request.purpose || '',\n request.action || '',\n request.resourceType || '',\n request.resource || '',\n request.jurisdiction || '',\n request.transactionValue ?? '',\n request.currency || '',\n // SECURITY (cross-merchant cache leak): the merchant identity is sent via\n // `config.counterpartyId`, NOT on the request, so it was previously absent\n // from the key — two verifies for the SAME agent/purpose/action/value but\n // DIFFERENT merchants collided, and a grant at a permissive merchant (low\n // trust floor) was served for a stricter one. Same bug class as the\n // duration omission (F-A1-07). counterpartyId affects the backend verdict\n // (trust floor / per-route policy), so it MUST key the cache.\n counterpartyId || '',\n request.counterpartyUrl || '',\n request.counterpartyType || '',\n request.isSubAgentRequest ? '1' : '0',\n request.parentAgentId || '',\n request.subAgentDepth ?? '',\n // Audit F-A1-07: previously-missing dimensions that DO affect the\n // backend verdict. Without these, two requests with different\n // durations (e.g. 60s vs 86400s) collided on the same cache key and\n // the shorter-duration allow served the longer-duration request.\n request.durationRequired ?? '',\n request.invocationProtocol || '',\n request.enableRuntimeChallenge ? '1' : '0',\n // callerMetadata fields contribute to risk model; include the ones\n // backend reads. sourceIp/userAgent/forwardedFor change per-request\n // so their inclusion effectively forces a re-check for any varying\n // client (the right behavior — IP-driven anomaly scoring shouldn't\n // be cached across IPs).\n request.callerMetadata?.sourceIp || '',\n request.callerMetadata?.userAgent || '',\n request.callerMetadata?.forwardedFor || '',\n request.callerMetadata?.agentCardUrl || '',\n // UAT2 Bug B (5.4.1): the commerce phase and cart identity DO affect the\n // backend verdict — the confirm leg is the ONLY leg that may execute\n // first-party settlement. Without these, a confirm within the cache TTL of\n // its start_checkout quote was served the cached quote-leg grant (no\n // settlementOutcome) and never reached the backend. Same F-A1-07 bug class.\n request.commercePhase || '',\n request.checkoutSessionId || '',\n ].join('|');\n}\n\n/**\n * Check if cached result is still valid\n */\nfunction getCachedResult(\n request: VerificationRequest,\n counterpartyId?: string\n): VerificationResult | null {\n const key = getCacheKey(request, counterpartyId);\n const cached = verificationCache.get(key);\n\n if (cached && cached.expiresAt > Date.now()) {\n return cached.result;\n }\n\n if (cached) {\n verificationCache.delete(key);\n }\n\n return null;\n}\n\n/**\n * Cache a verification result.\n *\n * 3.6.0: uniform 60s default. The earlier step-up TTL split (300s for\n * step-up verdicts) is gone — step-up verdicts are no longer cached AT ALL\n * (see the write predicate in verify()): a cached step_up_required result\n * carries a pollUrl that goes stale (consumed/expired) and, worse, keeps\n * denying retries that the owner has already approved. When `configuredTtl`\n * is set (truthy positive number), it's honoured for cacheable results.\n */\nconst DEFAULT_CACHE_TTL_SECONDS = 60;\n\nfunction cacheResult(\n request: VerificationRequest,\n result: VerificationResult,\n configuredTtl: number | undefined,\n counterpartyId?: string\n): void {\n const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : DEFAULT_CACHE_TTL_SECONDS;\n const key = getCacheKey(request, counterpartyId);\n verificationCache.set(key, {\n result,\n expiresAt: Date.now() + ttlSeconds * 1000,\n });\n}\n\n/**\n * Clear the verification cache\n */\nexport function clearCache(): void {\n verificationCache.clear();\n}\n\n/**\n * Extract agent credentials from various sources\n */\nexport function extractCredentials(\n headers: Record<string, string | string[] | undefined>,\n query?: Record<string, string | undefined>\n): AgentCredentials {\n const credentials: AgentCredentials = {};\n\n // Audit F-A1-12: ASTRA-ID shape validation. Accept only the canonical\n // pattern (ASTRA-/ASTRAE- prefix + 1-64 url-safe chars) to prevent CRLF\n // header injection or downstream interpolation surprises. Reject otherwise.\n const ASTRA_ID_PATTERN = /^ASTRAE?-[A-Za-z0-9_-]{1,64}$/;\n\n // Check for ASTRA-ID in headers (case-insensitive). Accepts the historical\n // X-Astra-Id name plus the X-Astra-AgentId / x-astra-agent-id alias the\n // partner asked for in #9a — both surface the same field.\n const astraIdHeader =\n headers['x-astra-id'] ||\n headers['X-Astra-Id'] ||\n headers['X-ASTRA-ID'] ||\n headers['x-astra-agentid'] ||\n headers['X-Astra-AgentId'] ||\n headers['x-astra-agent-id'] ||\n headers['X-Astra-Agent-Id'] ||\n headers['X-ASTRA-AGENT-ID'];\n if (astraIdHeader) {\n // Audit F-A1-11: guard array-confusion. If multiple X-Astra-Id headers\n // were sent (Express collapses to comma-joined string on most paths),\n // take only the first canonical-shaped one.\n const raw = Array.isArray(astraIdHeader)\n ? astraIdHeader[0]\n : typeof astraIdHeader === 'string'\n ? astraIdHeader\n : undefined;\n if (typeof raw === 'string' && ASTRA_ID_PATTERN.test(raw)) {\n credentials.astraId = raw;\n }\n }\n\n // Check for API key in headers\n const apiKeyHeader = headers['x-api-key'] || headers['X-Api-Key'] || headers['X-API-KEY'];\n if (apiKeyHeader) {\n credentials.apiKey = Array.isArray(apiKeyHeader) ? apiKeyHeader[0] : apiKeyHeader;\n }\n\n // Check Authorization header for Bearer token.\n // Audit F-A1-11: defensive type guard — Array.isArray gives a non-string,\n // and Express path quirks can produce undefined despite the truthy check.\n const authHeader = headers['authorization'] || headers['Authorization'];\n if (authHeader) {\n const authValue = Array.isArray(authHeader) ? authHeader[0] : authHeader;\n if (typeof authValue === 'string') {\n credentials.authorizationHeader = authValue;\n if (authValue.startsWith('Bearer ')) {\n credentials.jwt = authValue.slice(7);\n }\n }\n }\n\n // Check query parameters as fallback\n if (query) {\n if (query.astraId && !credentials.astraId) {\n credentials.astraId = query.astraId;\n }\n if (query.apiKey && !credentials.apiKey) {\n credentials.apiKey = query.apiKey;\n }\n }\n\n return credentials;\n}\n\n/**\n * Check if credentials are present\n */\nexport function hasCredentials(credentials: AgentCredentials): boolean {\n return !!(credentials.astraId || credentials.apiKey || credentials.jwt);\n}\n\n/**\n * Source of a synthesised guidance response. The sources are split — the\n * `'no_credentials'` shape is the original (caller has no AstraSync\n * credentials, suggest registration). The `'api_error'` shape is for when\n * the verify-access HTTP call itself failed (5xx, network, etc.) — DON'T\n * tell a verified-but-currently-blocked partner to \"register your agent\".\n *\n * 4.0.0 adds `'merchant_misconfig'`: the backend rejected THIS INTEGRATION'S\n * own API key (401 api_key_revoked/expired/invalid). Neither the agent's\n * fault nor a platform outage — retrying won't help, and the inbound agent\n * deserves to know the site operator's integration is broken (the\n * gadget-emporium failure mode: a rotated key silently 401ing every\n * credentialed agent for days).\n */\ntype GuidanceSource = 'no_credentials' | 'api_error' | 'merchant_misconfig';\n\n/**\n * MCP-connector steering (5.1.0). Present only when the backend's well-known\n * doc advertises a hosted bridge. The copy must directly counter the observed\n * model refusal (\"go register manually on the dashboard\"): registration via\n * the connector is the agent's own next action, with the human approval built\n * into the flow.\n */\nfunction mcpGuidance(urls?: WellKnownAgenticCommerce): GuidanceInfo['mcp'] {\n if (!urls?.mcpEndpoint) return undefined;\n return {\n endpoint: urls.mcpEndpoint,\n discoveryUrl: urls.mcpDiscoveryUrl,\n message:\n 'If you are operating inside an MCP-capable host (Claude, ChatGPT, Cursor, or any MCP client), ' +\n 'add the AstraSync MCP connector instead of integrating these URLs by hand: registration through ' +\n 'the connector is KEYLESS and HUMAN-APPROVED — your human approves in an in-chat card, and you ' +\n 'never see, hold, or transmit an API key, password, or private key.',\n };\n}\n\n/**\n * Create guidance response for unverified agents or for API-error fallback.\n *\n * The source is split so the `register your agent` template\n * doesn't fire on transient backend failures. Also threads `correlationId`\n * through so adapter `onDenied` handlers can surface it on the merchant's\n * response body for log correlation.\n */\nfunction createGuidanceResponse(\n _config: GatewayConfig,\n reason?: string,\n options: {\n source?: GuidanceSource;\n correlationId?: string;\n /** 3.12.0 (Trust Record): server-echoed attempt handle, threaded like correlationId. */\n attemptId?: string;\n urls?: WellKnownAgenticCommerce;\n /** 4.0.0: backend-provided remediation URLs for the merchant (misconfig source). */\n remediation?: { docsUrl?: string; manageUrl?: string };\n } = {}\n): VerificationResult {\n const source = options.source ?? 'no_credentials';\n const isApiError = source === 'api_error';\n const isMisconfig = source === 'merchant_misconfig';\n const urls = options.urls;\n\n const guidance: GuidanceInfo = isMisconfig\n ? {\n message:\n \"This site's AstraSync integration is misconfigured (its API key was revoked, expired, or rotated). \" +\n 'Your identity and the AstraSync platform are fine — contact the site operator. Retrying will not help.',\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? '',\n steps: [\n 'Report the failure to the site operator — their AstraSync API key needs rotating',\n 'Do not retry: the failure is deterministic until the operator updates their key',\n ],\n }\n : isApiError\n ? {\n message:\n 'Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.',\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: urls?.documentationUrl ?? '',\n steps: [\n 'Retry the request with exponential backoff',\n 'If failures persist, share the correlationId with support',\n ],\n }\n : {\n message:\n 'This service verifies AI agents before granting access. Please register your agent with AstraSync.',\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: urls?.documentationUrl ?? '',\n steps: [\n // MCP steering leads when the hosted bridge is advertised — the\n // connector is the agent-actionable path (keyless, human-approved).\n ...(urls?.mcpEndpoint\n ? [\n `Fastest path (inside an MCP host): add the AstraSync MCP connector at ${urls.mcpEndpoint} — keyless, human-approved registration`,\n ]\n : []),\n 'Register for an AstraSync account',\n 'Create and register your agent',\n 'Add your ASTRA-ID to request headers',\n 'Retry your request',\n ],\n ...(mcpGuidance(urls) && { mcp: mcpGuidance(urls) }),\n };\n\n return {\n // Round-18 G4: createGuidanceResponse fires for unverified-agent path or\n // API-error fallback. Identity is not verified (no agent resolved);\n // policy is not evaluated (we never reached the gate).\n identityVerified: false,\n policyAllowed: false,\n guidance,\n denialReasons: reason ? [reason] : ['No valid agent credentials provided'],\n // Round-10 (#47, O5): on API-error fallback, surface a typed failure so\n // partners (and their custom onDenied handlers) can branch on\n // dimension. Without this, the synthesised stub was indistinguishable\n // from a real policy deny.\n failures: isMisconfig\n ? [\n {\n dimension: 'verify_access.merchant_misconfigured',\n message: reason ?? 'The integration API key was rejected by AstraSync',\n guidance: guidance.message,\n },\n ]\n : isApiError\n ? [\n {\n dimension: 'verify_access.api_error',\n message: reason ?? 'Verification temporarily unavailable',\n guidance: guidance.message,\n },\n ]\n : undefined,\n // 4.0.0: typed marker so adapters render the misconfig envelope (503 +\n // MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.\n ...(isMisconfig && { misconfigured: true }),\n // 4.6.0: a transient api_error is retryable — mark it so consumers surface\n // \"temporarily unavailable, retry\" (recommendation 'error') instead of\n // coercing the absent recommendation to a policy 'deny'. Misconfig is\n // deterministic and intentionally NOT marked retryable.\n ...(isApiError && { retryable: true }),\n correlationId: options.correlationId,\n attemptId: options.attemptId,\n verifiedAt: new Date(),\n };\n}\n\n/**\n * Call the AstraSync verify-access API\n */\nasync function callVerifyAccessAPI(\n config: GatewayConfig,\n request: VerificationRequest\n): Promise<{\n success: boolean;\n access?: {\n allowed: boolean;\n reason?: string;\n /**\n * Aggregated denial failures (v2.9.8+). Empty / absent when allowed.\n * Each entry is `{ dimension, message, guidance? }` — see\n * `AccessFailure` for the contract.\n */\n failures?: Array<{ dimension: string; message: string; guidance?: string }>;\n requiresStepUp?: boolean;\n requiresApproval?: boolean;\n appliedPolicy?: {\n boundaryName: string;\n policyVersion: string;\n };\n counterparty?: {\n id: string;\n name: string;\n trustScoreRequirement: number;\n };\n };\n agent?: {\n kyaAgentId: string;\n astraId: string;\n name: string;\n trustScore: number;\n trustLevel: string;\n agentStatus: string;\n blockchainStatus: string;\n };\n developer?: {\n kyaOwnerId: string;\n fullName: string;\n email: string;\n identityVerified: boolean;\n trustScore: number;\n };\n organization?: {\n name: string;\n verified: boolean;\n trustScore: number;\n };\n /**\n * Structured explanation of the verification decision. Tells the merchant\n * WHY (id verified? challenge passed? request within PDLSS? trust score?)\n * without exposing thresholds, scope lists, or other-tenant counterparty\n * membership. Empty `attestations` unless the endpoint's access policy\n * declared `required_attestations`.\n */\n verificationContext?: {\n idVerified: boolean;\n runtimeChallenge: {\n status: 'passed' | 'skipped' | 'failed' | 'timeout' | 'not_configured';\n checkedAt: string | null;\n };\n pdlssCheck: {\n result: 'within' | 'exceeded' | 'denied' | 'not_evaluated';\n purpose: 'approved' | 'denied';\n scope: 'approved' | 'denied';\n };\n dynamicTrustScore: number;\n attestations: Array<{\n type: string;\n status: 'passed' | 'failed';\n /** LMAX-POC C1: underlying check timestamp for merchant freshness gates. */\n checkedAt: string;\n validUntil?: string;\n proofType: 'reference' | 'zkp';\n proof: string;\n }>;\n };\n error?: string;\n /**\n * 4.0.0: the backend 401'd this integration's OWN API key (revoked /\n * expired / invalid) — deterministic merchant-side misconfig, not a\n * transient failure. `misconfigCode` carries the backend's api_key_* code\n * and `remediation` its operator-facing URLs when present.\n */\n misconfig?: boolean;\n misconfigCode?: string;\n remediation?: { docsUrl?: string; manageUrl?: string };\n /**\n * When the verify-access server response carries a\n * correlationId on an error envelope, propagate it so the SDK can thread\n * it through createGuidanceResponse → adapter onDenied → merchant body.\n */\n correlationId?: string;\n /**\n * 3.12.0 (Trust Record): the server echoes the attempt-chain\n * handle top-level on every response branch (error envelopes included).\n */\n attemptId?: string;\n}> {\n const { credentials, ...requestData } = request;\n\n // Build the request body. agentId is omitted when not provided so the\n // server treats it as an anonymous canonical-flow call (Branch A/B/C).\n const body: Record<string, unknown> = {\n ...(credentials.astraId && { agentId: credentials.astraId }),\n ...(requestData.purpose && { purpose: requestData.purpose }),\n };\n\n // Add optional fields\n if (requestData.action) body.action = requestData.action;\n if (requestData.resourceType) body.resourceType = requestData.resourceType;\n if (requestData.resource) body.resource = requestData.resource;\n if (requestData.jurisdiction) body.jurisdiction = requestData.jurisdiction;\n if (requestData.transactionValue) body.transactionValue = requestData.transactionValue;\n if (requestData.currency) body.currency = requestData.currency;\n if (requestData.isSubAgentRequest) body.isSubAgentRequest = requestData.isSubAgentRequest;\n if (requestData.parentAgentId) body.parentAgentId = requestData.parentAgentId;\n if (requestData.subAgentDepth !== undefined) body.subAgentDepth = requestData.subAgentDepth;\n // Handshake Protocol v10 additions\n if (requestData.enableRuntimeChallenge)\n body.enableRuntimeChallenge = requestData.enableRuntimeChallenge;\n if (requestData.createSession) body.createSession = requestData.createSession;\n if (requestData.durationRequired) body.durationRequired = requestData.durationRequired;\n if (requestData.counterpartyType) body.counterpartyType = requestData.counterpartyType;\n if (requestData.counterpartyUrl) body.counterpartyUrl = requestData.counterpartyUrl;\n if (config.counterpartyId) body.counterpartyId = config.counterpartyId;\n if (requestData.runtimeChallengeOptions)\n body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;\n // Round-12 (F19): transport-vs-intent separation. MCP middleware sets\n // this to 'mcp'; non-MCP callers leave it unset.\n if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;\n // 5.3.0 (astra-pay): checkout-leg discriminator — first-party settlement\n // fires only on 'confirm'; absent keeps pre-phase server behavior.\n if (requestData.commercePhase) body.commercePhase = requestData.commercePhase;\n // Per-cart idempotency key (checkout session id) forwarded on the confirm\n // leg so concurrent confirms for one cart charge at most once.\n if (requestData.checkoutSessionId) body.checkoutSessionId = requestData.checkoutSessionId;\n // Order-plane cart lines (receipts + fulfillment email) — informational.\n if (requestData.checkoutItems) body.checkoutItems = requestData.checkoutItems;\n // 5.6.0 (astra-pay): transit-only fulfilment contact — echoed back in\n // result.fulfilment for first-party confirms, never persisted server-side.\n if (requestData.buyerEmail) body.buyerEmail = requestData.buyerEmail;\n // 3.9.0 (§33.5 #1): raw commerce artifacts forwarded verbatim — the\n // backend's Step 0.5 pipeline does the cryptographic verification\n // server-side (adapters forward, never verify locally).\n if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;\n // 3.12.0 (Trust Record, §33.5 #3): attempt-chain handle + consideration set,\n // forwarded skip-when-undefined (observedMetadata precedent) — pure\n // observational pass-through; the server echoes attemptId on every branch.\n if (requestData.attemptId) body.attemptId = requestData.attemptId;\n if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;\n\n // Round-13 (F14 closure / R13-7): emit the SDK package version on every\n // verify-access body so the backend can auto-populate `kya_counterparty.\n // sdk_version` for the calling endpoint. Body field (not User-Agent\n // header) is the canonical channel — works in Node, browser, behind\n // Cloudflare, and across SDK bundlers without environment-specific\n // header gymnastics. Backend's `validation.ts:verifyAccessSchema`\n // accepts the semver regex; the auto-pop logic is forward-only.\n body.sdkVersion = SDK_VERSION;\n\n // Forward caller metadata when present. Merges the legacy top-level\n // clientIp/userAgent into the nested block for backward compatibility.\n if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {\n const meta = {\n ...(requestData.clientIp && { sourceIp: requestData.clientIp }),\n ...(requestData.userAgent && { userAgent: requestData.userAgent }),\n ...requestData.callerMetadata,\n };\n if (Object.keys(meta).length > 0) body.callerMetadata = meta;\n }\n\n // Build headers\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...config.customHeaders,\n };\n\n // verify-access requires authentication. Use ONLY the merchant's\n // configured apiKey for outbound auth. Previously the caller's inbound\n // Authorization header took priority, which pivoted the verify-access\n // call to the caller's identity — letting an attacker who supplied\n // their own Authorization header trigger verify-access calls under\n // THEIR account and observe the resulting verdicts for arbitrary\n // lookups they triggered via the merchant. Audit F-A1-10.\n //\n // The caller-supplied JWT (if any) is already extracted to\n // credentials.jwt and travels in the verify-access request body so\n // backend can evaluate it as the agent's identity claim — separate from\n // the merchant-attribution auth on the outbound HTTPS call.\n if (config.apiKey) {\n headers['Authorization'] = `Bearer ${config.apiKey}`;\n // Legacy header kept for compatibility with any middleware that reads it directly.\n headers['X-API-Key'] = config.apiKey;\n }\n\n try {\n // 4.0.0: hard timeout — without one, a backend that accepts the\n // connection but never answers hangs the merchant's middleware and every\n // inbound agent request behind it (observed live on a partner property).\n // Timeouts land on the catch path below → api_error (fail-closed),\n // NOT misconfig. The edge adapter races its own tighter withBudget.\n const response = await sdkFetch(`${config.apiBaseUrl}/agents/verify-access`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 10_000),\n });\n\n const data = await response.json();\n\n // v2.3.8 (defect #29): treat 410 Gone as a deterministic deactivated-endpoint\n // signal. Older SDKs may treat any non-2xx as transient and retry; v2.3.8+\n // surfaces it as a structured denial with `reason: 'endpoint_deactivated'`\n // so callers can distinguish \"endpoint gone\" from \"endpoint denied this\".\n if (response.status === 410) {\n return {\n success: true,\n // 3.12.0 (Trust Record): keep the server-echoed attempt handle even on\n // the synthesised 410 deny shape (echoed on every branch).\n attemptId: typeof data?.attemptId === 'string' ? data.attemptId : undefined,\n access: {\n allowed: false,\n reason: 'endpoint_deactivated',\n failures: [\n {\n dimension: 'endpoint.deactivated',\n message:\n typeof data?.message === 'string' ? data.message : 'Endpoint has been deactivated',\n guidance:\n typeof data?.guidance === 'string'\n ? data.guidance\n : 'Reactivate via POST /api/endpoints/{id}/reactivate, or update the URL on the calling agent.',\n },\n ],\n },\n };\n }\n\n // 5.10.0: a caller-supplied agent id that isn't a canonical ASTRA-id\n // (e.g. `ASTRA-bogus123`) is a deterministic failed identity claim, not\n // an outage. Previously it fell through to the transient api_error path,\n // so the edge answered 503 \"verification unavailable — retry\" under\n // enforce; it is now an identity deny (403 + registration guidance).\n if (response.status === 400 && data?.error === 'INVALID_AGENT_ID') {\n const message =\n typeof data?.message === 'string'\n ? data.message\n : 'Agent identifier must be a canonical ASTRA-* id.';\n return {\n success: true,\n attemptId: typeof data?.attemptId === 'string' ? data.attemptId : undefined,\n access: {\n allowed: false,\n reason: 'invalid_agent_id',\n failures: [\n {\n dimension: 'identity.invalid_agent_id',\n message,\n guidance:\n typeof data?.guidance === 'string'\n ? data.guidance\n : 'Present your canonical ASTRA-* id (discover it via GET /api/agents/request-registration/{requestId} after owner approval).',\n },\n ],\n },\n };\n }\n\n if (!response.ok) {\n // 4.0.0: a 401 from verify-access can ONLY mean the backend rejected\n // THIS INTEGRATION'S own API key — agent denials come back as 200 with\n // access.allowed=false. Surface it as merchant-misconfig, not a\n // transient api_error: it is deterministic until the operator rotates\n // the key, and the \"retry with backoff\" template actively misleads.\n // Backends ≥ this round also send code: api_key_* + remediation URLs.\n if (response.status === 401) {\n return {\n success: false,\n error: data.message || data.error || 'Integration API key rejected',\n misconfig: true,\n misconfigCode: typeof data?.code === 'string' ? data.code : undefined,\n remediation:\n data?.remediation && typeof data.remediation === 'object'\n ? (data.remediation as { docsUrl?: string; manageUrl?: string })\n : undefined,\n correlationId: typeof data?.correlationId === 'string' ? data.correlationId : undefined,\n attemptId: typeof data?.attemptId === 'string' ? data.attemptId : undefined,\n };\n }\n // Round-10 (#47, O5): propagate correlationId on the error path too if\n // the server happened to include one (some 5xx error envelopes carry\n // it). Lets the SDK pass it through to the adapter onDenied handler.\n return {\n success: false,\n error: data.message || data.error || `API returned ${response.status}`,\n correlationId: typeof data?.correlationId === 'string' ? data.correlationId : undefined,\n attemptId: typeof data?.attemptId === 'string' ? data.attemptId : undefined,\n };\n }\n\n return data;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n error: `Failed to call verify-access API: ${message}`,\n };\n }\n}\n\n/**\n * Options for a single verify() call (as opposed to GatewayConfig, which is\n * per-gateway). Mirrors the Java SDK's `verify(request, bypassCache)`.\n */\nexport interface VerifyOptions {\n /**\n * Skip the cache READ for this call so the request is guaranteed to reach\n * the backend (the result is still written to the cache if cacheable).\n * Used by the step-up hold-and-poll retry: the re-verify after an approval\n * must hit the server to redeem the single-use approval.\n */\n bypassCache?: boolean;\n}\n\n/**\n * Main verification function\n */\nexport async function verify(\n config: GatewayConfig,\n request: VerificationRequest,\n options?: VerifyOptions\n): Promise<VerificationResult> {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n\n // v2.5.0: read well-known URLs from cache (prefetched by adapter at middleware creation).\n // Synchronous — never triggers a fetch. If cache is empty, guidance URLs are empty strings.\n const urls = mergedConfig.apiBaseUrl\n ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl)\n : undefined;\n\n // One-time init self-test — fire-and-forget by default, never blocks verify().\n // Audit F-A6-33: when GatewayConfig.strictInit is set, the init promise is\n // awaited and any failure throws synchronously so callers learn about\n // misconfigured apiBaseUrl on the first verify() call rather than silently\n // running with broken auth.\n if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {\n if (mergedConfig.strictInit) {\n await performInitCheck(\n mergedConfig.apiBaseUrl,\n mergedConfig.debug,\n true,\n mergedConfig.apiKey\n );\n } else {\n void performInitCheck(\n mergedConfig.apiBaseUrl,\n mergedConfig.debug,\n false,\n mergedConfig.apiKey\n );\n }\n }\n\n // Deprecation warning for v2.3.0 removed config fields. Fires once per process.\n if (\n !deprecationWarningShown &&\n (config.minTrustScore !== undefined || config.minTrustScoreForFull !== undefined)\n ) {\n deprecationWarningShown = true;\n console.warn(\n '[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 ' +\n 'and have no effect. Server is now the single source of truth for access decisions ' +\n '(verified ID + runtime challenge + PDLSS + trust score). To gate access ' +\n \"to an endpoint, configure the endpoint's trust_score_requirement server-side.\"\n );\n }\n\n // v2.3.0: anonymous traffic no longer short-circuits here. We forward the\n // request to the server with no agentId; the server applies the endpoint's\n // unverifiedAgentPolicy and returns advisory. createGuidanceResponse remains\n // as the offline fallback if the API itself fails (handled below).\n\n // Check cache first. Caching on unless caller explicitly sets cacheTtl: 0\n // to disable. Undefined falls through to the 60s default at cacheResult\n // write time. options.bypassCache skips the read only (hold-and-poll retry\n // must reach the backend to redeem its approval).\n if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {\n const cached = getCachedResult(request, mergedConfig.counterpartyId);\n if (cached) {\n if (mergedConfig.debug) {\n console.log('[VerificationGateway] Returning cached result');\n }\n // 3.12.0 (Trust Record, §33.5 #3): attemptId is excluded from the cache\n // key, so the stored result may carry a PRIOR attempt's id. Overwrite it\n // with this request's own attemptId — or drop it when this request has\n // none — a cached verdict must never leak another attempt's handle.\n // Shallow clone: never mutate the stored entry (a concurrent holder of\n // the same cached object may still be reading it).\n const hit: VerificationResult = { ...cached };\n if (request.attemptId) {\n hit.attemptId = request.attemptId;\n } else {\n delete hit.attemptId;\n }\n return hit;\n }\n }\n\n // Inject counterparty info from config if not already set in request\n const enrichedRequest = { ...request };\n if (!enrichedRequest.counterpartyUrl && mergedConfig.counterpartyUrl) {\n enrichedRequest.counterpartyUrl = mergedConfig.counterpartyUrl;\n }\n if (!enrichedRequest.counterpartyType && mergedConfig.counterpartyType) {\n enrichedRequest.counterpartyType = mergedConfig.counterpartyType;\n }\n\n // Call the API\n if (mergedConfig.debug) {\n console.log('[VerificationGateway] Calling verify-access API');\n }\n\n const apiResponse = await callVerifyAccessAPI(mergedConfig, enrichedRequest);\n\n // 3.6.0: the server emits a top-level denialReasons array on every deny\n // path (same strings as the failure messages). Non-empty → authoritative;\n // absent/empty → fall back to the client-side reconstructions below.\n const rawServerDenialReasons = (apiResponse as Record<string, unknown>).denialReasons;\n const serverDenialReasons =\n Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0\n ? (rawServerDenialReasons as string[])\n : undefined;\n\n // Handle API errors\n if (!apiResponse.success) {\n // Round-10 (#47, O5): distinguish API errors from missing-credentials.\n // The previous default tagged any failure with the \"register your\n // agent\" template, which is misleading to a verified partner whose\n // verify-access call hit a 500. The `api_error` source surfaces a\n // typed `verify_access.api_error` failure entry instead.\n // 4.0.0: a rejected merchant key gets its own source — deterministic\n // misconfig must not wear the \"temporarily unavailable, retry\" template.\n return createGuidanceResponse(mergedConfig, apiResponse.error, {\n source: apiResponse.misconfig ? 'merchant_misconfig' : 'api_error',\n correlationId: (apiResponse as { correlationId?: string }).correlationId,\n attemptId: (apiResponse as { attemptId?: string }).attemptId,\n remediation: apiResponse.remediation,\n urls,\n });\n }\n\n // Check access result\n if (!apiResponse.access?.allowed) {\n // v2.9.8 (defect M1): aggregated failures across every gate that\n // denied. Surface them on the result so the integrator can see every\n // blocker in one go instead of the previous fail-fast cascade.\n const aggregatedFailures = (apiResponse.access as Record<string, unknown> | undefined)\n ?.failures as Array<{ dimension: string; message: string; guidance?: string }> | undefined;\n // Round-18 G4: backend denied access (PDLSS or other gate); identity status\n // depends on whether the backend resolved the caller. Read from\n // verificationContext.idVerified; default false if absent (anonymous or\n // identity-fail paths land here too). policyAllowed is false by definition\n // in this branch (apiResponse.access.allowed === false).\n const idVerifiedFromBackend =\n (apiResponse.verificationContext as { idVerified?: boolean } | undefined)?.idVerified ===\n true;\n const result: EnhancedVerificationResult = {\n identityVerified: idVerifiedFromBackend,\n policyAllowed: false,\n // 3.6.0: the server now emits top-level denialReasons on every deny\n // path — prefer it verbatim; the failure-message reconstruction remains\n // as the fallback for older backends.\n denialReasons:\n serverDenialReasons ??\n (aggregatedFailures && aggregatedFailures.length > 0\n ? aggregatedFailures.map((f) => f.message)\n : apiResponse.access?.reason\n ? [apiResponse.access.reason]\n : ['Access denied']),\n failures: aggregatedFailures,\n requiresStepUp: apiResponse.access?.requiresStepUp,\n requiresApproval: apiResponse.access?.requiresApproval,\n guidance: {\n message: apiResponse.access?.reason || 'Access denied by PDLSS policy',\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: urls?.documentationUrl ?? '',\n // 5.1.0: anonymous callers land on this branch — steer MCP-hosted\n // agents to the connector (this is what the edge deny body surfaces).\n ...(mcpGuidance(urls) && { mcp: mcpGuidance(urls) }),\n },\n verifiedAt: new Date(),\n // Extract sessionId so decisions can be recorded for denials too\n sessionId: (apiResponse as Record<string, unknown>).sessionId as string | undefined,\n // Anonymous traffic has no session → correlationId is the per-attempt\n // linking key (the sessionId-equivalent for anonymous callers).\n correlationId: (apiResponse as Record<string, unknown>).correlationId as string | undefined,\n // 3.12.0 (Trust Record): server echoes the attempt-chain handle on\n // every branch — denials included (the funnel outlives one deny).\n attemptId: (apiResponse as Record<string, unknown>).attemptId as string | undefined,\n recommendation: (apiResponse as Record<string, unknown>)\n .recommendation as EnhancedVerificationResult['recommendation'],\n recommendationReasons: (apiResponse as Record<string, unknown>).recommendationReasons as\n | string[]\n | undefined,\n stepUpApproval: (apiResponse as Record<string, unknown>).stepUpApproval as\n | StepUpApprovalInfo\n | undefined,\n settlement: (apiResponse as Record<string, unknown>).settlement as\n | SettlementArtifact\n | undefined,\n settlementOutcome: (apiResponse as Record<string, unknown>).settlementOutcome as\n | SettlementOutcomeInfo\n | undefined,\n // 5.5.0 self-settlement: merchant-only material — passes through to the\n // MERCHANT caller only (bridge callers strip it before the agent plane).\n settlementToken: (apiResponse as Record<string, unknown>).settlementToken as\n | MerchantSettlementToken\n | undefined,\n // 5.6.0: fulfilment contact — merchant-only lane, same strip rule.\n fulfilment: (apiResponse as Record<string, unknown>).fulfilment as FulfilmentInfo | undefined,\n };\n\n return result;\n }\n\n // Build successful result\n const agent: VerifiedAgent | undefined = apiResponse.agent\n ? {\n astraId: apiResponse.agent.astraId,\n name: apiResponse.agent.name,\n trustScore: apiResponse.agent.trustScore,\n trustLevel: getTrustLevel(apiResponse.agent.trustScore),\n blockchainAnchored: apiResponse.agent.blockchainStatus === 'anchored',\n status: apiResponse.agent.agentStatus as VerifiedAgent['status'],\n }\n : undefined;\n\n const developer: VerifiedDeveloper | undefined = apiResponse.developer\n ? {\n astradId: apiResponse.developer.kyaOwnerId,\n name: apiResponse.developer.fullName,\n trustScore: apiResponse.developer.trustScore || 0,\n verified: apiResponse.developer.identityVerified,\n }\n : undefined;\n\n const organization: VerifiedOrganization | undefined = apiResponse.organization\n ? {\n name: apiResponse.organization.name,\n verified: apiResponse.organization.verified,\n trustScore: apiResponse.organization.trustScore,\n }\n : undefined;\n\n // Verification context — structured \"why\" the merchant gets in v2.2.4+.\n // Carries appliedPolicy (no UUIDs), pdlssCheck summary, dynamic trust score,\n // and policy-driven attestations. Replaces the old over-sharing `pdlss` block.\n const verificationContext = apiResponse.verificationContext;\n\n const result: EnhancedVerificationResult = {\n // 4.5.0 (probe F1): read idVerified from verificationContext with the\n // SAME absent⇒false default as the deny branch. The previous `!== false`\n // default manufactured `identityVerified: true` for anonymous\n // allow_full/allow_partial/audit responses (which allow access but omit\n // verificationContext entirely) — the \"anonymous caller labelled\n // verified\" defect. Every authenticated success response has carried\n // `verificationContext.idVerified: true` since v2.2.4, so a truth claim\n // this load-bearing must never be defaulted on.\n identityVerified:\n (apiResponse.verificationContext as { idVerified?: boolean } | undefined)?.idVerified ===\n true,\n policyAllowed: true,\n agent,\n developer,\n organization,\n appliedPolicy: apiResponse.access?.appliedPolicy,\n verificationContext,\n requiresStepUp: apiResponse.access?.requiresStepUp,\n requiresApproval: apiResponse.access?.requiresApproval,\n verifiedAt: new Date(),\n cacheTtl: mergedConfig.cacheTtl,\n // Handshake Protocol v10 enhanced fields (present when backend returns them)\n sessionId: (apiResponse as Record<string, unknown>).sessionId as string | undefined,\n // v2.3.10 (defect #34, round-4): anonymous responses surface correlationId\n // (no session row exists for unverified callers).\n correlationId: (apiResponse as Record<string, unknown>).correlationId as string | undefined,\n // 3.12.0 (Trust Record): server-echoed attempt-chain handle.\n attemptId: (apiResponse as Record<string, unknown>).attemptId as string | undefined,\n runtimeChallenge: (apiResponse as Record<string, unknown>).runtimeChallenge as\n | RuntimeChallengeResult\n | undefined,\n tokenGuidance: (apiResponse as Record<string, unknown>).tokenGuidance as\n | TokenGuidance\n | undefined,\n recommendation: (apiResponse as Record<string, unknown>)\n .recommendation as EnhancedVerificationResult['recommendation'],\n recommendationReasons: (apiResponse as Record<string, unknown>).recommendationReasons as\n | string[]\n | undefined,\n warningHeader: (apiResponse as Record<string, unknown>).warningHeader as\n | { name: string; value: string }\n | undefined,\n stepUpApproval: (apiResponse as Record<string, unknown>).stepUpApproval as\n | StepUpApprovalInfo\n | undefined,\n settlement: (apiResponse as Record<string, unknown>).settlement as\n | SettlementArtifact\n | undefined,\n settlementOutcome: (apiResponse as Record<string, unknown>).settlementOutcome as\n | SettlementOutcomeInfo\n | undefined,\n settlementToken: (apiResponse as Record<string, unknown>).settlementToken as\n | MerchantSettlementToken\n | undefined,\n // 5.6.0: fulfilment contact — merchant-only lane, same strip rule.\n fulfilment: (apiResponse as Record<string, unknown>).fulfilment as FulfilmentInfo | undefined,\n };\n\n // Enforce AstraSync recommendation\n if (result.recommendation === 'deny') {\n // Round-18 G4: recommendation-driven deny lands on the success-path\n // construction (identity was resolved). Flip policy only — identity stays\n // verified — so adapters return 403 (re-auth won't help; the policy\n // decision is the blocker).\n result.policyAllowed = false;\n // 3.6.0: server-sent top-level denialReasons wins; recommendationReasons\n // reconstruction is the fallback for older backends.\n result.denialReasons = serverDenialReasons ??\n result.recommendationReasons ?? ['Access denied by AstraSync recommendation'];\n result.guidance = result.runtimeChallenge\n ? {\n message: `Verification failed: ${result.runtimeChallenge.reason || 'runtime challenge failed'}`,\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: urls?.documentationUrl ?? '',\n }\n : {\n message: result.recommendationReasons?.[0] || 'Access denied by AstraSync recommendation',\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: urls?.documentationUrl ?? '',\n };\n } else if (result.recommendation === 'step_up_required') {\n // The escalation signal rides on `requiresStepUp` / `stepUpApproval`, not\n // on any masquerade of the (now-removed) access band.\n result.requiresStepUp = true;\n result.denialReasons = serverDenialReasons ??\n result.recommendationReasons ?? ['Step-up verification required'];\n }\n\n // Cache the result. Never cache denials (agent may fix challenge endpoint\n // and retry) NOR step-up escalations (3.6.0 — the same bug the Java SDK\n // had: a cached step_up_required verdict keeps denying retries the owner\n // has already approved, and its pollUrl goes stale once consumed/expired).\n // Escalations stay uncached even when the caller pins an explicit cacheTtl.\n const escalates =\n result.requiresStepUp === true ||\n result.requiresApproval === true ||\n result.recommendation === 'step_up_required';\n if (mergedConfig.cacheTtl !== 0 && result.recommendation !== 'deny' && !escalates) {\n cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);\n }\n\n return result;\n}\n\n/**\n * Record a counterparty's grant/deny decision for a verification session.\n * Fire-and-forget — errors are silently swallowed.\n */\nexport async function recordDecision(\n config: GatewayConfig,\n sessionId: string,\n decision: 'granted' | 'denied',\n reason?: string\n): Promise<void> {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (config.apiKey) {\n headers['Authorization'] = `Bearer ${config.apiKey}`;\n headers['X-API-Key'] = config.apiKey;\n }\n\n await sdkFetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ decision, reason }),\n }).catch(() => {\n /* fire-and-forget */\n });\n}\n\n/**\n * Report post-hoc consideration/outcome data for an attempt chain (Trust\n * Record). Use when the signal never reached verify-access: a\n * catalog served from a local cache, a transport-side deny (sku not found,\n * over budget), or a terminal outcome (settled / blocked on step-up).\n * Authenticated with the same credentials as verify(); the backend responds\n * 202 and folds the data into the attempt chain keyed by `attemptId`.\n *\n * Fire-and-forget — errors are silently swallowed, never throws.\n */\nexport async function reportAttempt(config: GatewayConfig, report: AttemptReport): Promise<void> {\n const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl!;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (config.apiKey) {\n headers['Authorization'] = `Bearer ${config.apiKey}`;\n headers['X-API-Key'] = config.apiKey;\n }\n\n // counterpartyId resolution mirrors reportUnregisteredAttempt: an explicit\n // report value wins; otherwise attribute to the configured endpoint.\n const body = {\n ...report,\n ...(!report.counterpartyId &&\n config.counterpartyId && { counterpartyId: config.counterpartyId }),\n };\n\n await sdkFetch(`${apiBaseUrl}/agents/verify-access/attempt-report`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n }).catch(() => {\n /* fire-and-forget */\n });\n}\n\n/**\n * Fetch the per-route policy for an endpoint from the AstraSync backend.\n * v2.9.7 moved policy authority into the dashboard — the SDK no longer\n * accepts `routes` from merchant-side source code, it fetches them from\n * here on init (and refreshes periodically).\n *\n * Returns `null` when the request fails for any reason — the caller decides\n * how to fall back (the middleware allows-all when no policy is loaded so\n * a misconfigured init doesn't take down the merchant's API).\n */\nexport async function fetchRoutes(\n config: GatewayConfig,\n counterpartyId: string\n): Promise<RouteAccessConfigShape[] | null> {\n if (!counterpartyId) return null;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (config.apiKey) {\n headers['Authorization'] = `Bearer ${config.apiKey}`;\n headers['X-API-Key'] = config.apiKey;\n }\n try {\n const response = await sdkFetch(\n `${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,\n { method: 'GET', headers }\n );\n if (!response.ok) return null;\n const body = (await response.json()) as { data?: { routes?: RouteAccessConfigShape[] } };\n return body.data?.routes ?? [];\n } catch {\n return null;\n }\n}\n\n/**\n * Minimal shape of an EndpointRoute as the SDK consumes it. Mirrors the\n * server's `EndpointRoute` type and the SDK's `RouteAccessConfig` — same\n * JSON moves between server and SDK unchanged.\n */\nexport interface RouteAccessConfigShape {\n pattern: string;\n method: string;\n /** Pass through unenforced (observe). Replaces `minAccessLevel: 'none'`. */\n observe?: boolean;\n minTrustScore?: number;\n requiredPurposes?: string[];\n allowedPurposes?: string[];\n allowedJurisdictions?: string[];\n maxDuration?: number;\n maxTransactionValue?: number;\n requirePurpose?: boolean;\n /** Send-mapping — see RouteAccessConfig in types.ts. */\n purpose?: string;\n action?: string;\n}\n\n/**\n * Verify an agent AND automatically record the grant/deny decision.\n *\n * This is the recommended entry point for counterparties that call verify()\n * directly (e.g. MCP servers) rather than using createMiddleware().\n * It adds createSession: true, then fire-and-forgets the decision.\n */\nexport async function verifyAndRecord(\n config: GatewayConfig,\n request: VerificationRequest,\n options?: VerifyOptions\n): Promise<VerificationResult> {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n const result = await verify(mergedConfig, { ...request, createSession: true }, options);\n const sessionId = (result as EnhancedVerificationResult).sessionId;\n\n if (sessionId) {\n // Round-18 G4: a session is \"granted\" only if identity verified AND\n // policy allowed; either failing is a deny.\n if (result.identityVerified && result.policyAllowed) {\n recordDecision(mergedConfig, sessionId, 'granted').catch(() => {});\n } else {\n recordDecision(mergedConfig, sessionId, 'denied', result.denialReasons?.[0]).catch(() => {});\n }\n }\n\n return result;\n}\n\n/**\n * Report an unregistered agent attempt (no AstraSync credentials).\n * Called by SDK adapters when an agent is redirected to /docs/agent-access.\n * Fire-and-forget — errors are silently swallowed.\n */\nexport async function reportUnregisteredAttempt(\n config: GatewayConfig,\n data: {\n /**\n * 3.6.0: optional — the backend attributes by counterpartyId first (sent\n * from config below) and requires at least ONE of counterpartyId/URL.\n * A null/undefined URL is omitted from the body, not sent as null.\n */\n counterpartyUrl?: string;\n counterpartyType?: string;\n sourceIp?: string;\n userAgent?: string;\n requestPath?: string;\n requestMethod?: string;\n /**\n * VI uplift Part 3 — attempt-chain handle (`att_<32hex>`, from the\n * X-Astra-Attempt-Id header or an `?astra_attempt=` deep link). Joins\n * the beacon into the agent's research chain. Attribution only.\n */\n attemptId?: string;\n /** First-class referer (traffic-source reporting). */\n referer?: string;\n /** The caller's Accept header (surface-classifier input). */\n accept?: string;\n /** Self-declared platform from X-Astra-Source (attribution, never trust). */\n declaredSource?: string;\n /**\n * 3.9.0 — edge-adapter evidence fields, persisted into the\n * event's eventData by the backend: `protocol` = detected transport/\n * credential protocol; `evidence` = light crypto-free detection detail.\n */\n protocol?: string;\n evidence?: Record<string, unknown>;\n /**\n * Maximal metadata capture — the full sanitised metadata for an\n * unregistered caller (every signal legitimately visible on the wire).\n * Persisted into eventData; feeds platform attribution and (via\n * correlationId) registration auto-fill. Fire-and-forget, so free.\n */\n observedMetadata?: ObservedMetadata;\n }\n): Promise<void> {\n const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl!;\n\n const { counterpartyUrl, ...rest } = data;\n const body = {\n ...rest,\n ...(counterpartyUrl && { counterpartyUrl }),\n ...(config.counterpartyId && { counterpartyId: config.counterpartyId }),\n };\n\n await sdkFetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n }).catch(() => {\n /* fire-and-forget */\n });\n}\n\n/**\n * Report a counterparty-side PDLSS pre-check failure.\n * Called by SDK adapters when the agent's requested PDLSS exceeds\n * counterparty-defined maximums BEFORE calling verify-access.\n * Fire-and-forget — errors are silently swallowed.\n */\nexport async function reportCounterpartyPreCheckFailure(\n config: GatewayConfig,\n data: {\n agentId: string;\n counterpartyUrl: string;\n counterpartyType?: string;\n failures: Array<{\n field: string;\n requested: string | number;\n limit: string | number | string[];\n message: string;\n }>;\n requestPath?: string;\n requestMethod?: string;\n }\n): Promise<void> {\n const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl!;\n\n await sdkFetch(`${apiBaseUrl}/verification-activity/counterparty-pre-check-failure`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n }).catch(() => {\n /* fire-and-forget */\n });\n}\n\n/**\n * Quick verification — checks credentials and policy in one call.\n *\n * The return shape mirrors `VerificationResult`'s split — partners\n * writing custom handlers around `quickVerify` get the same identity/policy\n * distinction as those calling `verify()` directly. Map to HTTP status the\n * same way: `!identityVerified` → 401; `identityVerified && !policyAllowed`\n * → 403.\n */\nexport async function quickVerify(\n config: GatewayConfig,\n credentials: AgentCredentials\n): Promise<{\n identityVerified: boolean;\n policyAllowed: boolean;\n reason?: string;\n}> {\n const result = await verify(config, {\n credentials,\n purpose: 'verification',\n });\n\n return {\n identityVerified: result.identityVerified,\n policyAllowed: result.policyAllowed,\n reason: result.denialReasons?.[0],\n };\n}\n","/**\n * Step-up hold-and-poll (3.6.0) — the synchronous half of the MFA-style gate,\n * mirroring the Java SDK's `awaitStepUpApproval` / `pollStepUpStatus`.\n *\n * A verify() that comes back step_up_required carries a `stepUpApproval`\n * handle: `{ approvalId, pollUrl, expiresAt }`. The adapter HOLDS the original\n * request, polls the approval status, and on 'approved' re-verifies the same\n * request once (cache-bypassed) so the backend redeems the single-use approval\n * and returns a grant. Any other terminal outcome falls into the adapter's\n * normal fail-closed deny path.\n *\n * The poll endpoint is deliberately unauthenticated (it sits above the\n * backend router's `authenticate` middleware): the unguessable UUIDv4\n * approvalId is the capability token, and the route is rate-limited\n * (60/min/IP). No Authorization header is sent.\n */\n\nimport { sdkFetch } from '../http';\nimport { GatewayConfig, StepUpApprovalInfo, StepUpApprovalStatus, StepUpOutcome } from '../types';\n\nconst DEFAULT_POLL_INTERVAL_MS = 3000;\nconst MIN_POLL_INTERVAL_MS = 250;\nconst FALLBACK_MAX_WAIT_MS = 5 * 60 * 1000;\nconst EXPIRY_GRACE_MS = 5000;\nconst POLL_REQUEST_TIMEOUT_MS = 10_000;\n\n/** Resolve the absolute poll URL. pollUrl is server-relative\n * (`/api/step-up-approvals/poll/:id`), so join it to apiBaseUrl minus its\n * `/api` suffix (the origin) — same idiom as well-known.ts. Absolute URLs\n * pass through untouched. */\nfunction resolvePollUrl(config: GatewayConfig, pollUrl: string): string {\n if (pollUrl.startsWith('http')) return pollUrl;\n const origin = (config.apiBaseUrl ?? '').replace(/\\/api\\/?$/, '');\n return origin + pollUrl;\n}\n\n/**\n * One GET of the approval's poll endpoint. Returns the status string, or\n * null on any error / non-2xx / unparsable body — the hold loop treats null\n * as transient and just polls again.\n */\nexport async function pollStepUpStatus(\n config: GatewayConfig,\n approval: StepUpApprovalInfo\n): Promise<StepUpApprovalStatus | null> {\n if (!approval.pollUrl) return null;\n try {\n const res = await sdkFetch(resolvePollUrl(config, approval.pollUrl), {\n method: 'GET',\n signal: AbortSignal.timeout(POLL_REQUEST_TIMEOUT_MS),\n });\n if (!res.ok) return null;\n const body = (await res.json()) as Record<string, unknown>;\n // Envelope shape: { success, data: { status, resolvedAt } } — a flat\n // `status` read hangs every hold (live-UAT catch). Envelope-first with a\n // flat fallback for forward compatibility, exactly like the Java SDK.\n const data = body?.data;\n const status =\n data && typeof data === 'object' ? (data as Record<string, unknown>).status : body?.status;\n return typeof status === 'string' ? (status as StepUpApprovalStatus) : null;\n } catch {\n return null; // transient poll failure — the loop just polls again\n }\n}\n\nfunction resolveDeadline(config: GatewayConfig, approval: StepUpApprovalInfo): number {\n const now = Date.now();\n const maxWait = config.stepUpMaxWaitMs ?? 0;\n if (maxWait > 0) return now + maxWait;\n // stepUpMaxWaitMs === 0: hold until the approval itself expires (+ a small\n // grace so an approval landing at the buzzer still resolves on the next\n // poll). Missing/unparsable expiresAt → fixed 5-min fallback (Java parity).\n if (approval.expiresAt) {\n const expiry = Date.parse(approval.expiresAt);\n if (!Number.isNaN(expiry)) return Math.max(now, expiry) + EXPIRY_GRACE_MS;\n }\n return now + FALLBACK_MAX_WAIT_MS;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Block until a pending step-up approval reaches a terminal state or the wait\n * budget runs out. Returns the terminal status, or 'timeout'.\n *\n * Unknown non-pending statuses (a future backend state) still terminate the\n * hold — they are returned as-is and land in the deny path, which is the safe\n * reading of \"not approved\".\n */\nexport async function awaitStepUpApproval(\n config: GatewayConfig,\n approval: StepUpApprovalInfo\n): Promise<StepUpOutcome> {\n const deadline = resolveDeadline(config, approval);\n const pollInterval = Math.max(\n MIN_POLL_INTERVAL_MS,\n config.stepUpPollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS\n );\n\n while (Date.now() < deadline) {\n const status = await pollStepUpStatus(config, approval);\n if (status && status !== 'pending') {\n return status as StepUpOutcome;\n }\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n await sleep(Math.min(pollInterval, remaining));\n }\n return 'timeout';\n}\n","/**\n * Maximal metadata capture — the shared, edge-safe sanitiser.\n *\n * AstraSync's thesis is total metadata capture: every header and connection\n * signal an inbound agent presents is a signal we want to keep. This module is\n * the ONE place that decides what is safe to store verbatim, what is a secret\n * to drop, and what credential headers reduce to a safe *format prefix* (a\n * platform signal, never the secret itself).\n *\n * It runs in three places that must agree byte-for-byte:\n * - the edge adapter (`@astrasyncai/adapter-lambda`) — the richest capture\n * point (full CloudFront header arrays),\n * - the SDK adapters (express / nextjs) — for SDK-only merchants with no edge,\n * - (indirectly) the backend, which stores whatever the above forward.\n *\n * Pure — no Node built-ins, no I/O — so it is safe in Lambda@Edge, the browser\n * build, and Deno. Capture is cheap: at the edge and SDK it is local string\n * work, and the backend stores it on a fire-and-forget event insert, so it adds\n * ZERO verify-access decision latency. Detection (which few signals imply which\n * vendor) is a separate, curated concern — see `platform-signatures.ts`.\n */\n\n/**\n * Version of the capture semantics (what is kept, dropped, reduced, or\n * derived — and under which key names).\n *\n * Capture semantics are FROZEN within a package major version: a given\n * `schemaVersion` always means the same field vocabulary and the same\n * keep/drop/reduce rules. The number bumps only on a SEMANTIC change to\n * capture (a renamed key, a changed reduction rule) — never for additive\n * signals, and never merely because the package version moved. To tell\n * builds apart, use the `sdkVersion` already present on the verify body;\n * `schemaVersion` answers the different question \"how do I interpret this\n * stored metadata?\".\n */\nexport const CAPTURE_SCHEMA_VERSION = 1;\n\n/**\n * The captured, sanitised view of an inbound agent's request metadata. Attached\n * to verify-access / beacon payloads as `callerMetadata.observedMetadata`.\n */\nexport interface ObservedMetadata {\n /** Header name → value, secrets removed, verbatim otherwise. */\n headers: Record<string, string>;\n /**\n * Safe key-format prefix of a credential header (e.g. `sk-ant-api03`,\n * `sk-proj`, `AIza`) — a platform signal, NEVER the secret. Absent if no\n * credential header was present or none matched a known format.\n */\n apiKeyFormat?: string;\n /**\n * The subset of `headers` that are known platform-signal headers\n * (`openai-organization`, `x-goog-user-project`, `anthropic-version`, …),\n * pulled out for convenient detection + display. Values are the same\n * sanitised strings as in `headers`.\n */\n platformHeaders?: Record<string, string>;\n /**\n * Connection-layer signals (IP, ASN, country, TLS version, HTTP version,\n * device class, TLS fingerprint). Edge adapters populate this from the\n * platform's native connection surface — the authoritative source. SDK\n * adapters populate it as a fallback via {@link deriveConnectionFromHeaders}\n * when a CDN in front of the merchant injected the equivalent headers;\n * absent when neither source had anything.\n */\n connection?: Record<string, string>;\n /**\n * Number of cookie pairs the caller sent. The `cookie` header VALUE is a\n * secret and is always dropped; the COUNT is a client-shape signal\n * (browsers carry cookies, most automation carries none) that would\n * otherwise be unobservable downstream. Absent when no cookie header\n * arrived.\n */\n cookieCount?: number;\n /**\n * Query-string parameter NAMES (deduped, lowercased) — values are NEVER\n * captured (they routinely carry OAuth codes, tokens, and PII, and no\n * deny-list is complete). Names alone fingerprint client shape. Populated\n * by the edge path, which sees the raw query string.\n */\n queryKeys?: string[];\n /**\n * Query-string VALUES for parameter names the endpoint owner explicitly\n * allow-listed (`EdgeConfig.queryValueAllowlist`, seeded `utm_*` — VI\n * uplift Part 4). The default remains NO value capture; this exists so\n * campaign attribution (utm_source/medium/campaign) can be reported\n * without widening the privacy stance. Bounded 16 entries × 256 chars.\n */\n queryParams?: Record<string, string>;\n /**\n * Version of the capture semantics this object was produced under — see\n * {@link CAPTURE_SCHEMA_VERSION}. Optional for backward compatibility with\n * metadata captured before the field existed.\n */\n schemaVersion?: number;\n}\n\n/**\n * Result of sanitising a raw header map. `headers` is always present (possibly\n * empty); `apiKeyFormat` / `platformHeaders` only when a signal was found.\n */\nexport interface SanitizeHeadersResult {\n headers: Record<string, string>;\n apiKeyFormat?: string;\n platformHeaders?: Record<string, string>;\n /** Cookie-pair count; the cookie value itself is always dropped. */\n cookieCount?: number;\n}\n\n/**\n * Header names dropped entirely — genuine secrets or our own credentials that\n * describe the request's transport, not the agent. Matched case-insensitively\n * on the exact header name.\n */\nconst SECRET_HEADER_NAMES = new Set([\n 'cookie',\n 'set-cookie',\n 'x-csrf-token',\n 'proxy-authorization',\n 'x-astrasync-signature',\n 'x-astrasync-secret',\n 'x-hub-signature',\n 'x-hub-signature-256',\n // Short-lived verify dedupe token — must never persist in stored metadata.\n 'x-astra-verified-hop',\n]);\n\n/**\n * Header-name prefixes dropped entirely — our own credential / signing surface\n * (`x-astrasync-*`, `kya-*`) must never round-trip into stored metadata.\n */\nconst SECRET_HEADER_PREFIXES = ['x-astrasync-', 'kya-', 'kya_'];\n\n/**\n * Credential headers whose VALUE is a secret but whose FORMAT is a signal. We\n * keep the leading format prefix (up to the random tail) and drop the rest.\n */\nconst CREDENTIAL_HEADER_NAMES = new Set([\n 'authorization',\n 'x-api-key',\n 'x-goog-api-key',\n 'api-key',\n]);\n\n/**\n * Header names that carry a raw signature value (drop the value; the presence\n * is not worth a bloat risk). Matched as a suffix so `x-*-signature` variants\n * are covered without an exhaustive list.\n */\nfunction isSignatureHeader(name: string): boolean {\n return name === 'signature' || name.endsWith('-signature') || name.endsWith('-signature-256');\n}\n\n/**\n * Known platform-signal headers — pulled into `platformHeaders` for convenient\n * detection + display. Exact names plus a few prefixes (`x-goog-`,\n * `x-stainless-` — the OpenAI/Anthropic SDK client fingerprint headers).\n */\nconst PLATFORM_HEADER_NAMES = new Set([\n 'openai-organization',\n 'openai-project',\n 'openai-version',\n 'openai-processing-ms',\n 'anthropic-version',\n 'anthropic-beta',\n 'x-goog-user-project',\n 'x-goog-api-client',\n 'user-agent',\n 'x-agent-card-url',\n 'x-agent-provider',\n]);\n// `sec-ch-*` client hints are platform signals: Chromium forks (agentic\n// browsers included) often carry their real brand in `sec-ch-ua` even when\n// the UA string mimics stock Chrome.\nconst PLATFORM_HEADER_PREFIXES = [\n 'x-goog-',\n 'x-stainless-',\n 'x-anthropic-',\n 'x-openai-',\n 'sec-ch-',\n];\n\n/**\n * Known API-key format prefixes, longest-first so `sk-ant-api03` wins over\n * `sk-ant` and `sk-`. Each is the SAFE, non-secret leading token of a\n * credential; the random tail is never captured.\n */\nconst KEY_FORMAT_PREFIXES = [\n 'sk-ant-api03',\n 'sk-ant-api',\n 'sk-ant',\n 'sk-proj',\n 'sk-svcacct',\n 'sk-or-v1',\n 'sk-or',\n 'sk-lf',\n 'sk-',\n 'gsk_',\n 'aiza',\n 'ya29',\n 'ghp_',\n 'gho_',\n 'github_pat_',\n 'xai-',\n 'pplx-',\n 'r8_',\n 'hf_',\n 'astra-',\n 'astrae-',\n];\n\n/** Size caps — the only guard against jsonb bloat from a hostile POST. */\nexport const MAX_HEADERS = 64;\nexport const MAX_HEADER_VALUE_BYTES = 1024;\nexport const MAX_TOTAL_BYTES = 16 * 1024;\n\n/**\n * `X-Astra-Source` declared-source protocol (VI uplift Part 2). The header is\n * SELF-ASSERTED and spoofable — it buys attribution, never trust: it is never\n * read by any access decision and never conflated with fingerprint-matched\n * (`platformVendor`) or ASTRA-verified evidence. One shared validator so the\n * edge, backend, and bridge accept byte-identical values.\n */\nexport const DECLARED_SOURCE_MAX = 64;\nconst DECLARED_SOURCE_PATTERN = /^[a-z0-9][a-z0-9 ._/-]{0,63}$/;\n\nexport function normalizeDeclaredSource(value: string | undefined | null): string | undefined {\n const trimmed = value?.trim().slice(0, DECLARED_SOURCE_MAX).toLowerCase();\n return trimmed && DECLARED_SOURCE_PATTERN.test(trimmed) ? trimmed : undefined;\n}\n\nfunction byteLength(s: string): number {\n // Edge-safe (no Buffer): count UTF-8 bytes without allocating a Buffer.\n let bytes = 0;\n for (let i = 0; i < s.length; i++) {\n const code = s.charCodeAt(i);\n if (code < 0x80) bytes += 1;\n else if (code < 0x800) bytes += 2;\n else if (code >= 0xd800 && code <= 0xdbff) {\n bytes += 4;\n i++; // surrogate pair\n } else bytes += 3;\n }\n return bytes;\n}\n\n/**\n * Extract the safe key-format prefix from a credential header value. Strips a\n * leading `Bearer ` / `Basic ` scheme, then returns the longest known prefix\n * that the (lowercased) value starts with. Returns undefined for opaque values\n * (e.g. a bare UUID token) so we never guess a format we don't recognise.\n */\nexport function extractApiKeyFormat(rawValue: string): string | undefined {\n if (!rawValue) return undefined;\n let value = rawValue.trim();\n const spaceIdx = value.indexOf(' ');\n if (spaceIdx > 0) {\n const scheme = value.slice(0, spaceIdx).toLowerCase();\n if (scheme === 'bearer' || scheme === 'basic' || scheme === 'token') {\n value = value.slice(spaceIdx + 1).trim();\n }\n }\n const lower = value.toLowerCase();\n for (const prefix of KEY_FORMAT_PREFIXES) {\n if (lower.startsWith(prefix)) {\n // Return the prefix as-declared in the list (canonical casing).\n return prefix;\n }\n }\n return undefined;\n}\n\nfunction isSecretHeader(name: string): boolean {\n if (SECRET_HEADER_NAMES.has(name)) return true;\n if (SECRET_HEADER_PREFIXES.some((p) => name.startsWith(p))) return true;\n if (isSignatureHeader(name)) return true;\n return false;\n}\n\nfunction isPlatformHeader(name: string): boolean {\n if (PLATFORM_HEADER_NAMES.has(name)) return true;\n return PLATFORM_HEADER_PREFIXES.some((p) => name.startsWith(p));\n}\n\n/**\n * Sanitise a raw header map for storage. Deny-lists genuine secrets, reduces\n * credential headers to a safe format prefix, keeps everything else verbatim,\n * and enforces the size caps that bound jsonb growth.\n *\n * Accepts any string→(string|string[]|undefined) map (Node's `req.headers`,\n * CloudFront's flattened headers, a plain object). Multi-value headers are\n * joined with `, ` per RFC 7230.\n */\nexport function sanitizeHeaders(\n raw: Record<string, string | string[] | undefined> | undefined | null\n): SanitizeHeadersResult {\n const headers: Record<string, string> = {};\n const platformHeaders: Record<string, string> = {};\n let apiKeyFormat: string | undefined;\n let cookieCount: number | undefined;\n let totalBytes = 0;\n let count = 0;\n\n if (!raw) return { headers };\n\n for (const rawName of Object.keys(raw)) {\n if (count >= MAX_HEADERS) break;\n const name = rawName.toLowerCase();\n const rawValue = raw[rawName];\n if (rawValue === undefined) continue;\n const joined = Array.isArray(rawValue) ? rawValue.join(', ') : String(rawValue);\n\n // Credential headers: capture the format prefix, drop the secret.\n if (CREDENTIAL_HEADER_NAMES.has(name)) {\n const fmt = extractApiKeyFormat(joined);\n if (fmt && !apiKeyFormat) apiKeyFormat = fmt;\n continue;\n }\n\n // Cookie: the value is a secret (dropped below), but the PAIR COUNT is a\n // client-shape signal worth keeping.\n if (name === 'cookie') {\n cookieCount = joined.split(';').filter((s) => s.trim().length > 0).length;\n }\n\n // Genuine secrets: drop entirely.\n if (isSecretHeader(name)) continue;\n\n // Everything else describing the agent: keep, bounded.\n let value = joined;\n if (byteLength(value) > MAX_HEADER_VALUE_BYTES) {\n value = value.slice(0, MAX_HEADER_VALUE_BYTES);\n }\n const entryBytes = byteLength(name) + byteLength(value);\n if (totalBytes + entryBytes > MAX_TOTAL_BYTES) continue;\n totalBytes += entryBytes;\n count++;\n headers[name] = value;\n if (isPlatformHeader(name)) platformHeaders[name] = value;\n }\n\n const result: SanitizeHeadersResult = { headers };\n if (apiKeyFormat) result.apiKeyFormat = apiKeyFormat;\n if (Object.keys(platformHeaders).length > 0) result.platformHeaders = platformHeaders;\n if (cookieCount !== undefined) result.cookieCount = cookieCount;\n return result;\n}\n\n/**\n * Pull the known platform-signal headers out of an ALREADY-sanitised header\n * map. `sanitizeHeaders` already computes this as a by-product; this standalone\n * form is exported for call-sites (edge, tests) that hold a sanitised map and\n * want only the platform subset. Never re-run over raw (unsanitised) headers.\n */\nexport function extractPlatformHeaders(\n sanitized: Record<string, string> | undefined | null\n): Record<string, string> {\n const out: Record<string, string> = {};\n if (!sanitized) return out;\n for (const name of Object.keys(sanitized)) {\n if (isPlatformHeader(name.toLowerCase())) out[name.toLowerCase()] = sanitized[name];\n }\n return out;\n}\n\n/**\n * Precedence-ordered CDN header sources for each derived `connection` key.\n * First present header wins; the special `x-forwarded-for` source takes the\n * LEFTMOST (client) entry of the comma-separated chain.\n */\nconst CONNECTION_HEADER_SOURCES: ReadonlyArray<readonly [key: string, headers: readonly string[]]> =\n [\n ['ip', ['cf-connecting-ip', 'fastly-client-ip', 'true-client-ip', 'x-real-ip']],\n [\n 'country',\n ['cf-ipcountry', 'x-vercel-ip-country', 'cloudfront-viewer-country', 'fastly-geo-country'],\n ],\n ['region', ['x-vercel-ip-country-region', 'cloudfront-viewer-country-region']],\n ['countryRegionName', ['cloudfront-viewer-country-region-name']],\n ['city', ['x-vercel-ip-city', 'cloudfront-viewer-city']],\n ['latitude', ['x-vercel-ip-latitude', 'cloudfront-viewer-latitude']],\n ['longitude', ['x-vercel-ip-longitude', 'cloudfront-viewer-longitude']],\n ['postalCode', ['x-vercel-ip-postal-code', 'cloudfront-viewer-postal-code']],\n ['asn', ['cloudfront-viewer-asn']],\n ['tlsVersion', ['cloudfront-viewer-tls']],\n ['httpVersion', ['cloudfront-viewer-http-version']],\n ['timeZone', ['x-vercel-ip-timezone', 'cloudfront-viewer-time-zone']],\n ['metroCode', ['cloudfront-viewer-metro-code']],\n // TLS fingerprints can only be computed where TLS terminates. When a CDN\n // terminates TLS in front of the merchant, its fingerprint headers ARE the\n // connection-layer truth — normalising them here is the permanent design.\n // CloudFront delivers JA3/JA4 only via an origin request policy and only\n // for HTTPS viewer connections.\n ['tlsFingerprint', ['cf-ja3-hash', 'cloudfront-viewer-ja3-fingerprint']],\n ['ja4', ['cf-ja4', 'cloudfront-viewer-ja4-fingerprint']],\n // Header-structure fingerprint: browser/SDK-distinctive header ordering.\n ['headerOrder', ['cloudfront-viewer-header-order']],\n ['headerCount', ['cloudfront-viewer-header-count']],\n ];\n\n/**\n * Backend bound: observedMetadata.connection values longer than this fail\n * the platform's zod parse outright (boundedStringRecord(32, 256)), so every\n * emitter truncates — headerOrder routinely exceeds it.\n */\nexport const MAX_CONNECTION_VALUE_CHARS = 256;\n\n/**\n * Derive the connection-layer block from CDN-injected request headers.\n *\n * When a merchant's SDK-gated origin sits behind a CDN (Cloudflare, Fastly,\n * Vercel, CloudFront), the CDN has already seen the connection layer and\n * injected it as headers. This promotes those headers to the same\n * `connection` keys the edge adapters populate natively, so SDK-only\n * deployments still get IP / geo / TLS attribution. Precedence per key:\n *\n * - `ip`: `cf-connecting-ip` > `fastly-client-ip` > `true-client-ip` >\n * `x-real-ip` > `cloudfront-viewer-address` (port stripped) > leftmost\n * `x-forwarded-for`\n * - `country`: `cf-ipcountry` > `x-vercel-ip-country` >\n * `cloudfront-viewer-country` > `fastly-geo-country`\n * - `region` / `city` / `timeZone`: Vercel then CloudFront viewer headers\n * - `countryRegionName` / `asn` / `tlsVersion` / `httpVersion` /\n * `metroCode` / `headerOrder` / `headerCount`: `cloudfront-viewer-*`\n * - `tlsFingerprint`: `cf-ja3-hash` > `cloudfront-viewer-ja3-fingerprint`\n * - `ja4`: `cf-ja4` > `cloudfront-viewer-ja4-fingerprint`\n *\n * All keys are additive under `schemaVersion` 1 (the frozen-capture doctrine\n * bumps only for changed semantics, never for additive signals). Values are\n * truncated to MAX_CONNECTION_VALUE_CHARS — the platform's hard bound.\n *\n * Edge adapters keep their richer native collectors — native platform\n * signals are authoritative; this header derivation is the SDK-level\n * fallback. Header names are matched case-insensitively. Returns undefined\n * when no source header is present, so the `connection` key is simply\n * omitted (matching edge behaviour).\n */\nexport function deriveConnectionFromHeaders(\n headers: Record<string, string> | undefined | null\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n const lower: Record<string, string> = {};\n for (const name of Object.keys(headers)) {\n const value = headers[name];\n if (typeof value === 'string' && value.length > 0) lower[name.toLowerCase()] = value;\n }\n\n const connection: Record<string, string> = {};\n for (const [key, sources] of CONNECTION_HEADER_SOURCES) {\n for (const source of sources) {\n const value = lower[source]?.trim();\n if (value) {\n connection[key] = value.slice(0, MAX_CONNECTION_VALUE_CHARS);\n break;\n }\n }\n }\n // ip fallback 1: cloudfront-viewer-address arrives as ip:port — strip the\n // trailing port only (IPv6-safe), unlike the dedicated client-ip headers.\n // The port itself is kept as its own key: ephemeral-port patterns signal\n // NAT/proxy connection reuse.\n {\n const addr = lower['cloudfront-viewer-address']?.trim();\n const portMatch = addr?.match(/:(\\d+)$/);\n if (portMatch) connection.sourcePort = portMatch[1];\n if (!connection.ip && addr) connection.ip = addr.replace(/:\\d+$/, '');\n }\n // ip fallback 2: leftmost (client) hop of the x-forwarded-for chain.\n if (!connection.ip) {\n const xff = lower['x-forwarded-for'];\n const client = xff?.split(',')[0]?.trim();\n if (client) connection.ip = client;\n }\n // tlsCipher: CloudFront folds the cipher into the viewer-tls string\n // (`TLSv1.3:TLS_AES_128_GCM_SHA256:fullHandshake`). `tlsVersion` stays\n // verbatim (reducing it would be a semantic change → schema v2); the\n // cipher is pulled out additively so it is queryable on its own.\n if (!connection.tlsCipher) {\n const cipher = connection.tlsVersion?.split(':')[1];\n if (cipher) connection.tlsCipher = cipher;\n }\n\n return Object.keys(connection).length > 0 ? connection : undefined;\n}\n\n/**\n * The FULL metadata capture for one request at an SDK adapter (express /\n * nextjs / mcp): sanitised headers, the safe credential format prefix, the\n * platform-signal subset, the CDN-derived connection block, and the capture\n * schema version. This is the ONE builder all SDK adapters share, so their\n * verify-access bodies agree byte-for-byte.\n *\n * Connection derivation runs over the RAW header map (pre-cap) — the size\n * caps guard storage growth and must never hide a geo/IP header that\n * happened to arrive late in an oversized map.\n */\nexport function buildSdkObservedMetadata(\n rawHeaders: Record<string, string | string[] | undefined> | undefined | null\n): ObservedMetadata {\n const { headers, apiKeyFormat, platformHeaders, cookieCount } = sanitizeHeaders(rawHeaders);\n const flat: Record<string, string> = {};\n if (rawHeaders) {\n for (const name of Object.keys(rawHeaders)) {\n const value = rawHeaders[name];\n if (value === undefined) continue;\n flat[name.toLowerCase()] = Array.isArray(value) ? value.join(', ') : String(value);\n }\n }\n const connection = deriveConnectionFromHeaders(flat);\n return {\n headers,\n ...(apiKeyFormat && { apiKeyFormat }),\n ...(platformHeaders && { platformHeaders }),\n ...(connection && { connection }),\n ...(cookieCount !== undefined && { cookieCount }),\n schemaVersion: CAPTURE_SCHEMA_VERSION,\n };\n}\n","/**\n * Edge verification config — the per-endpoint policy the Trusted Agent\n * Gateway edge adapters (e.g. `@astrasyncai/adapter-lambda`) fetch from the\n * AstraSync dashboard to decide how much verification friction to apply\n * to inbound traffic, and where.\n *\n * Fetch pattern mirrors `well-known.ts`: TTL cache + stale-while-revalidate\n * + in-flight dedupe, with a `_reset*` hook for tests. Fail posture is\n * deliberately asymmetric: this module can NEVER put a site into enforce\n * mode on its own — enforce only ever originates from a successfully\n * fetched config, and a config that has gone stale past `maxStaleMs`\n * degrades back to observe.\n *\n * Which EdgeConfig fields each integration consumes:\n *\n * | Field | Edge adapters | SDK adapters (express/nextjs/mcp) |\n * | ------------------------------ | ------------- | --------------------------------- |\n * | `mode` (observe/enforce) | yes | — |\n * | `depth` | yes | — |\n * | `pathRules` | yes | — |\n * | `sampling.anonymousBeaconRate` | yes | yes — the SDK anonymous beacon |\n * | `failurePosture` | yes | — |\n *\n * The observe/enforce × depth posture is EDGE-ONLY by design: SDK adapters\n * enforce via the dashboard route policy (`fetchRoutes`), not via this\n * config, and consume only the `sampling` block for their anonymous\n * traffic beacon.\n */\n\nimport { sdkFetch } from './http';\nimport type { GatewayConfig } from './types';\n\n/**\n * Edge posture. Canonical Trusted Agent Gateway vocabulary:\n * `observe` ≈ the gateway's `passive` posture (verify +\n * record, enforce nothing), `enforce` ≈ `active`. New value set on a new\n * field name — do NOT reuse `GatewayPosture`'s `active`/`passive` here\n * (different field, different meaning: posture governs an agent-side\n * gateway; mode governs counterparty-side edge interception).\n */\nexport type EdgeMode = 'observe' | 'enforce';\n\n/**\n * How deep the edge checks each request — what is it → who is it → are\n * they allowed:\n * - `classify` — UA / platform-fingerprint classification only; no\n * credential handling.\n * - `authenticate` — establish who is calling: detect and parse agent\n * credentials (X-Astra-*, VI SD-JWT, RFC 9421, ACP,\n * UCP, AP2…) and verify presented AstraSync identities.\n * - `authorize` — full policy decision: credentials cryptographically\n * proven and PDLSS-evaluated via a verify-access round\n * trip. (US spelling on the wire, matching\n * `authorizeSettlement` and HTTP `Authorization`.)\n */\nexport type EdgeVerificationDepth = 'classify' | 'authenticate' | 'authorize';\n\nexport interface EdgePathRule {\n /**\n * `*`-wildcard glob matched against the request path. Matching is\n * case-INsensitive and all regex metacharacters except `*` are\n * escaped. (Deliberately diverges from the express adapter's\n * `matchRoute`, which is historically case-sensitive by default —\n * new surface ships case-insensitive matching as the default.)\n */\n pattern: string;\n /** Pass the request through untouched (static assets); mode/depth ignored. */\n skip?: boolean;\n /** Override the top-level mode for this path. */\n mode?: EdgeMode;\n /** Override the top-level depth for this path. */\n depth?: EdgeVerificationDepth;\n /**\n * Per-path beacon sampling opt-DOWN (VI uplift 1.2). The default is full\n * capture; put a fractional rate on explicitly high-volume/low-value paths\n * (static mirrors, health checks) instead of sampling commerce traffic.\n */\n sampling?: {\n /** Fraction (0..1) of anonymous-bot requests that emit a beacon. */\n anonymousBeaconRate: number;\n };\n}\n\nexport interface EdgeConfig {\n /** Shape version — bump on breaking changes. */\n version: 1;\n /** Default posture for paths no rule matches. */\n mode: EdgeMode;\n /** Default check depth for paths no rule matches. */\n depth: EdgeVerificationDepth;\n /** Ordered, first-match-wins. */\n pathRules: EdgePathRule[];\n sampling: {\n /** Fraction (0..1) of anonymous-bot requests that emit a beacon. */\n anonymousBeaconRate: number;\n };\n /**\n * Query-string parameter names whose VALUES may be captured into\n * `observedMetadata.queryParams` (VI uplift Part 4 — campaign/UTM\n * attribution). Lowercase exact names or a single trailing-`*` glob\n * (`utm_*`); ≤16 entries × ≤64 chars. ABSENT by default — the privacy\n * stance (query values dropped at capture) is unchanged unless the\n * endpoint owner explicitly configures this.\n */\n queryValueAllowlist?: string[];\n /**\n * 4.5.0: the EFFECTIVE failure posture is derived from the effective\n * mode — fail posture follows success posture. Observe fails open\n * (unreachable backend = pass-through, site never breaks); enforce fails\n * closed on verification-infrastructure failure (503\n * `VERIFICATION_UNAVAILABLE`, retry-later — see edge-core/pipeline). This\n * field is retained on the wire for adapter compatibility and as a future\n * explicit override; it is not consulted by the 4.5.x pipeline. Note the\n * distinction from CONFIG staleness: a config stale past 24h still has\n * enforce degraded to observe (`degradeToObserve`) — that is config-trust\n * hygiene, independent of runtime verification availability.\n */\n failurePosture: 'open' | 'closed';\n}\n\n/**\n * The safe default: observe-only, classification depth, nothing enforced.\n * Served by the backend when an endpoint has never been configured, and\n * used by `getEdgeConfig` whenever no config can be fetched.\n *\n * Beacon rate 1.0 (VI uplift 1.2): every anonymous hit beacons by default —\n * a sampled denominator understates anonymous traffic in every dashboard\n * tile and no toggle can reveal the dropped rows. Sampling is a deliberate\n * per-path opt-down (`EdgePathRule.sampling`) for static/high-volume paths.\n */\nexport const DEFAULT_EDGE_CONFIG: EdgeConfig = Object.freeze({\n version: 1,\n mode: 'observe',\n depth: 'classify',\n pathRules: [],\n sampling: Object.freeze({ anonymousBeaconRate: 1.0 }),\n failurePosture: 'open',\n}) as EdgeConfig;\n\nconst EDGE_MODES: readonly string[] = ['observe', 'enforce'];\nconst EDGE_DEPTHS: readonly string[] = ['classify', 'authenticate', 'authorize'];\n\nfunction isSamplingShape(value: unknown): value is { anonymousBeaconRate: number } {\n if (typeof value !== 'object' || value === null) return false;\n const rate = (value as Record<string, unknown>).anonymousBeaconRate;\n return typeof rate === 'number' && rate >= 0 && rate <= 1;\n}\n\n/** Structural guard for configs arriving over the wire. */\nexport function isEdgeConfig(value: unknown): value is EdgeConfig {\n if (typeof value !== 'object' || value === null) return false;\n const v = value as Record<string, unknown>;\n if (v.version !== 1) return false;\n if (!EDGE_MODES.includes(v.mode as string)) return false;\n if (!EDGE_DEPTHS.includes(v.depth as string)) return false;\n if (!Array.isArray(v.pathRules)) return false;\n for (const rule of v.pathRules) {\n if (typeof rule !== 'object' || rule === null) return false;\n const r = rule as Record<string, unknown>;\n if (typeof r.pattern !== 'string' || r.pattern.length === 0) return false;\n if (r.mode !== undefined && !EDGE_MODES.includes(r.mode as string)) return false;\n if (r.depth !== undefined && !EDGE_DEPTHS.includes(r.depth as string)) return false;\n if (r.sampling !== undefined && !isSamplingShape(r.sampling)) return false;\n }\n if (!isSamplingShape(v.sampling)) return false;\n if (v.queryValueAllowlist !== undefined) {\n if (\n !Array.isArray(v.queryValueAllowlist) ||\n v.queryValueAllowlist.length > 16 ||\n !v.queryValueAllowlist.every((e) => typeof e === 'string' && e.length > 0 && e.length <= 64)\n ) {\n return false;\n }\n }\n return v.failurePosture === 'open';\n}\n\nexport interface FetchEdgeConfigSuccess {\n edgeConfig: EdgeConfig;\n etag?: string;\n}\n\nexport type FetchEdgeConfigResult = FetchEdgeConfigSuccess | { notModified: true } | null;\n\n/**\n * Fetch the edge config for an endpoint from the AstraSync backend.\n * `GET {apiBaseUrl}/endpoints/:counterpartyId/edge-config` with the same\n * auth headers as `fetchRoutes`. Pass the cached `etag` to get a cheap\n * `{ notModified: true }` on 304. Returns `null` on any failure —\n * the caller decides how to fall back.\n */\nexport async function fetchEdgeConfig(\n config: Pick<GatewayConfig, 'apiBaseUrl' | 'apiKey'>,\n counterpartyId: string,\n opts?: { etag?: string; timeoutMs?: number }\n): Promise<FetchEdgeConfigResult> {\n if (!counterpartyId) return null;\n const headers: Record<string, string> = { Accept: 'application/json' };\n if (config.apiKey) {\n headers['Authorization'] = `Bearer ${config.apiKey}`;\n headers['X-API-Key'] = config.apiKey;\n }\n if (opts?.etag) headers['If-None-Match'] = opts.etag;\n try {\n const response = await sdkFetch(\n `${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/edge-config`,\n { method: 'GET', headers, signal: AbortSignal.timeout(opts?.timeoutMs ?? 5000) }\n );\n if (response.status === 304) return { notModified: true };\n if (!response.ok) return null;\n const body = (await response.json()) as { data?: { edgeConfig?: unknown } };\n const edgeConfig = body.data?.edgeConfig;\n if (!isEdgeConfig(edgeConfig)) return null;\n return { edgeConfig, etag: response.headers.get('etag') ?? undefined };\n } catch {\n return null;\n }\n}\n\ninterface CacheEntry {\n config: EdgeConfig;\n etag?: string;\n /** When the entry was last confirmed fresh (fetch or 304). */\n lastSuccessAt: number;\n}\n\nconst DEFAULT_TTL_MS = 60 * 1000;\nconst DEFAULT_MAX_STALE_MS = 24 * 60 * 60 * 1000;\n\nconst cache = new Map<string, CacheEntry>();\nconst inflight = new Map<string, Promise<void>>();\n\nfunction cacheKey(apiBaseUrl: string, counterpartyId: string): string {\n return `${apiBaseUrl}|${counterpartyId}`;\n}\n\n/** Copy of `config` with every enforce (top-level and per-rule) degraded to observe. */\nexport function degradeToObserve(config: EdgeConfig): EdgeConfig {\n if (config.mode !== 'enforce' && !config.pathRules.some((r) => r.mode === 'enforce')) {\n return config;\n }\n return {\n ...config,\n mode: 'observe',\n pathRules: config.pathRules.map((r) => (r.mode === 'enforce' ? { ...r, mode: 'observe' } : r)),\n };\n}\n\nasync function revalidate(\n config: Pick<GatewayConfig, 'apiBaseUrl' | 'apiKey'>,\n counterpartyId: string\n): Promise<void> {\n const key = cacheKey(config.apiBaseUrl, counterpartyId);\n const existing = inflight.get(key);\n if (existing) return existing;\n\n const promise = fetchEdgeConfig(config, counterpartyId, { etag: cache.get(key)?.etag })\n .then((result) => {\n if (result === null) return; // failure — cache untouched, caller falls back\n const now = Date.now();\n if ('notModified' in result) {\n const entry = cache.get(key);\n if (entry) entry.lastSuccessAt = now;\n return;\n }\n cache.set(key, { config: result.edgeConfig, etag: result.etag, lastSuccessAt: now });\n })\n .finally(() => {\n inflight.delete(key);\n });\n\n inflight.set(key, promise);\n return promise;\n}\n\n/**\n * Get the edge config for an endpoint, cached. Never throws, never blocks\n * longer than one fetch.\n *\n * - Fresh cache (within `ttlMs`) → cached config, no network.\n * - Stale cache → cached config immediately + background revalidate\n * (stale-while-revalidate). If the last successful fetch is older than\n * `maxStaleMs` (default 24h), any enforce is degraded to observe — a\n * long-dead backend can never keep a site enforcing.\n * - No cache → await one fetch; on failure return `DEFAULT_EDGE_CONFIG`\n * (observe-only). Defaults never enforce.\n */\nexport async function getEdgeConfig(\n config: Pick<GatewayConfig, 'apiBaseUrl' | 'apiKey'>,\n counterpartyId: string,\n opts?: { ttlMs?: number; maxStaleMs?: number }\n): Promise<EdgeConfig> {\n const ttlMs = opts?.ttlMs ?? DEFAULT_TTL_MS;\n const maxStaleMs = opts?.maxStaleMs ?? DEFAULT_MAX_STALE_MS;\n const key = cacheKey(config.apiBaseUrl, counterpartyId);\n\n const entry = cache.get(key);\n if (entry) {\n const age = Date.now() - entry.lastSuccessAt;\n if (age > ttlMs) {\n revalidate(config, counterpartyId).catch(() => {\n // background refresh failed — stale entry remains until next call\n });\n }\n return age > maxStaleMs ? degradeToObserve(entry.config) : entry.config;\n }\n\n await revalidate(config, counterpartyId).catch(() => {\n // fetch failed — fall through to defaults\n });\n return cache.get(key)?.config ?? DEFAULT_EDGE_CONFIG;\n}\n\n/**\n * First-match-wins path-rule lookup. Case-insensitive `*` globs with all\n * other regex metacharacters escaped (a literal `.` in a pattern matches\n * only `.`). Returns `undefined` when no rule matches — the caller applies\n * the config's top-level mode/depth.\n */\nexport function matchEdgePathRule(rules: EdgePathRule[], path: string): EdgePathRule | undefined {\n for (const rule of rules) {\n if (globToRegExp(rule.pattern).test(path)) return rule;\n }\n return undefined;\n}\n\nfunction globToRegExp(pattern: string): RegExp {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '.*');\n return new RegExp(`^${escaped}$`, 'i');\n}\n\n/** Reset cache — for testing only. */\nexport function _resetEdgeConfigCache(): void {\n cache.clear();\n inflight.clear();\n}\n","/**\n * AstraSync Universal Verification Gateway - Express Middleware\n *\n * Express.js middleware for verifying AI agents on API endpoints.\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { createMiddleware } from '@astrasyncai/verification-gateway/express';\n *\n * const app = express();\n *\n * app.use(createMiddleware({\n * apiBaseUrl: 'https://astrasync.ai/api',\n * apiKey: process.env.ASTRASYNC_API_KEY,\n * counterpartyId: 'ASTRAE-...', // your registered endpoint id\n * }));\n * ```\n *\n * Per-route policy (which paths are gated, trust floors, PDLSS purposes) is\n * configured in the AstraSync dashboard, not in code — the middleware\n * fetches it automatically on init and refreshes periodically. There is no\n * `routes` option; a `routes` key in the config object is ignored (with a\n * warning) since v2.9.7.\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport type {\n ExpressMiddlewareOptions,\n AgentCredentials,\n VerificationResult,\n EnhancedVerificationResult,\n RouteAccessConfig,\n AstraSyncCredentials,\n VerificationRequest,\n} from '../types';\nimport { awaitStepUpApproval } from './stepup-poll';\nimport {\n verify,\n extractCredentials,\n recordDecision,\n reportCounterpartyPreCheckFailure,\n fetchRoutes,\n} from '../verify';\nimport { extractHttpCredentials } from '../transport/http';\nimport { MCP_VERIFIED_HOP_HEADER, parseVerifiedHop, isVerifiedHopValidFor } from '../verified-hop';\nimport { resolveHttpPdlss, type HttpPdlssResolution } from './http-pdlss';\nimport { requiresHumanApproval, annotateApprovalRequired } from './approval-gate';\nimport { performCounterpartyPreCheck } from '../pdlss-pre-check';\nimport { prefetchWellKnown, getWellKnownUrls } from '../well-known';\nimport { buildSdkObservedMetadata } from '../metadata-capture';\nimport { createAnonymousBeacon } from './anonymous-beacon';\n\n/**\n * Extend Express Request with verification result\n */\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Express {\n interface Request {\n agentVerification?: VerificationResult;\n }\n }\n}\n\n/**\n * Default credential extractor\n */\nfunction defaultExtractCredentials(req: Request): AgentCredentials {\n return extractCredentials(\n req.headers as Record<string, string | string[] | undefined>,\n req.query as Record<string, string | undefined>\n );\n}\n\n/**\n * Extract extended AstraSync credentials (X-Astra-* headers) from Express request.\n * Returns null if no AstraSync headers are present.\n */\nexport function extractAstraSyncCredentials(req: Request): AstraSyncCredentials | null {\n return extractHttpCredentials(req.headers as Record<string, string | string[] | undefined>);\n}\n\n/** Read a possibly-array header value as a single string. */\nfunction headerValue(value: string | string[] | undefined): string | undefined {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) return value[0];\n return undefined;\n}\n\n/**\n * Resolve the canonical {purpose, action} pair for a request.\n * Replaces the gen-1 `defaultExtractPurpose` method-inference (`read_data`/\n * `write_data`) and the hardwired `action: req.method.toUpperCase()` — the\n * transport verb never travels as a PDLSS action. Full precedence chains\n * live in http-pdlss.ts.\n */\nfunction resolveRequestPdlss(\n req: Request,\n routeConfig: { purpose?: string; action?: string } | null,\n customExtractPurpose: ((req: Request) => string | undefined) | undefined,\n customExtractAction: ((req: Request) => string | undefined) | undefined\n): HttpPdlssResolution {\n return resolveHttpPdlss({\n method: req.method,\n astraPurpose: headerValue(req.headers['x-astra-purpose']),\n astraAction: headerValue(req.headers['x-astra-action']),\n legacyPurpose: headerValue(req.headers['x-purpose'] ?? req.headers['X-Purpose']),\n queryPurpose: typeof req.query.purpose === 'string' ? req.query.purpose : undefined,\n routePurpose: routeConfig?.purpose,\n routeAction: routeConfig?.action,\n hasCustomPurposeExtractor: !!customExtractPurpose,\n customPurpose: customExtractPurpose?.(req),\n hasCustomActionExtractor: !!customExtractAction,\n customAction: customExtractAction?.(req),\n });\n}\n\n/**\n * Match a route pattern against a path.\n *\n * Historically the SDK's\n * matchRoute was case-sensitive while Express's default `case sensitive\n * routing` is FALSE. A customer policy `/api/admin/*` did NOT match\n * `/api/ADMIN/users` → SDK returned `no-match` → request passed ungated →\n * Express routed it to the admin handler. The case-insensitive codepath\n * below closes the bypass.\n *\n * Ships in SHADOW MODE in SDK 2.4.13: by default the case-sensitive\n * regex is still authoritative; the case-insensitive variant is\n * computed in parallel and logged when results diverge. Follow-up\n * release flips the default to case-insensitive after 1-week\n * observation. Customers can flip early by setting\n * `caseInsensitiveRouteMatch: true` on the middleware options.\n */\nfunction matchRoute(\n pattern: string,\n path: string,\n opts?: { caseInsensitive?: boolean; correlationId?: string; logShadowDivergence?: boolean }\n): boolean {\n // Convert pattern to regex\n const regexPattern = pattern.replace(/\\*/g, '.*').replace(/\\//g, '\\\\/');\n\n const caseSensitiveRegex = new RegExp(`^${regexPattern}$`);\n const caseSensitiveResult = caseSensitiveRegex.test(path);\n\n if (!opts?.caseInsensitive && !opts?.logShadowDivergence) {\n return caseSensitiveResult;\n }\n\n const caseInsensitiveRegex = new RegExp(`^${regexPattern}$`, 'i');\n const caseInsensitiveResult = caseInsensitiveRegex.test(path);\n\n // Shadow logging: emit only when results diverge so operators can grep\n // their own logs for the bypass class without log volume spam.\n if (opts?.logShadowDivergence && caseSensitiveResult !== caseInsensitiveResult) {\n // eslint-disable-next-line no-console\n console.warn(\n `[SHADOW] matchRoute case-insensitive would change result: pattern=${pattern} path=${path} ` +\n `caseSensitive=${caseSensitiveResult} caseInsensitive=${caseInsensitiveResult} correlationId=${opts.correlationId ?? 'unknown'}`\n );\n }\n\n return opts?.caseInsensitive ? caseInsensitiveResult : caseSensitiveResult;\n}\n\n/**\n * Find the route configuration for a request\n */\nfunction findRouteConfig(\n routes: RouteAccessConfig[],\n path: string,\n method: string,\n opts?: { caseInsensitive?: boolean; correlationId?: string; logShadowDivergence?: boolean }\n): RouteAccessConfig | undefined {\n return routes.find((route) => {\n const methodMatches =\n route.method === '*' || route.method.toUpperCase() === method.toUpperCase();\n const pathMatches = matchRoute(route.pattern, path, opts);\n return methodMatches && pathMatches;\n });\n}\n\n/**\n * Default denied handler\n *\n * The response body carries the full `failures[]`\n * array and the `correlationId` so partners can render per-dimension UX\n * and tie a denial back to a server log line. Previously the merchant only\n * got the first denialReason — meaningful detail was thrown away before\n * the response left the SDK. Also stamps `X-Astra-Gateway-Mode: enforced`\n * so partners can tell a gate-evaluated denial apart from a gate-skipped\n * pass-through (the `unenforced` complement).\n */\nfunction dedupeFailures(result: VerificationResult): void {\n if (result.failures && result.failures.length > 1) {\n const seen = new Set<string>();\n result.failures = result.failures.filter((f) => {\n const key = `${f.dimension}|${f.message}|${(f as { guidance?: string }).guidance ?? ''}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n }\n if (result.denialReasons && result.denialReasons.length > 1) {\n result.denialReasons = [...new Set(result.denialReasons)];\n }\n}\n\nfunction defaultOnDenied(result: VerificationResult, _req: Request, res: Response): void {\n // 4.0.0 BREAKING: when this integration's OWN API key was rejected by the\n // backend (misconfigured marker), the inbound agent did nothing wrong and\n // re-authenticating won't help — a 401 both blames the agent and invites\n // re-auth loops. Answer 503: this site's verification layer is down, by\n // the operator's own configuration. No Retry-After — retrying is futile\n // until the operator rotates the key.\n if (result.misconfigured) {\n res.setHeader('X-Astra-Gateway-Mode', 'enforced');\n res.status(503).json({\n success: false,\n error: {\n code: 'MERCHANT_VERIFICATION_MISCONFIGURED',\n message: result.denialReasons?.[0] || \"This site's AstraSync integration is misconfigured\",\n guidance: result.guidance,\n failures: result.failures,\n correlationId: result.correlationId,\n },\n });\n return;\n }\n\n // Round-18 G4: identity-verification failures → 401 (re-authenticate);\n // identity-verified-but-policy-denied → 403 (re-auth won't help; update\n // PDLSS scope or escalate to step-up). Maps to the two distinct recovery\n // actions that HTTP middleware acts on without parsing bodies. The\n // impossible state `!identityVerified && policyAllowed` falls into the\n // `!identityVerified` branch — identity is the more-fundamental missing\n // precondition.\n const statusCode = !result.identityVerified ? 401 : 403;\n\n res.setHeader('X-Astra-Gateway-Mode', 'enforced');\n\n res.status(statusCode).json({\n success: false,\n error: {\n code: !result.identityVerified ? 'UNAUTHORIZED' : 'INSUFFICIENT_ACCESS',\n message: result.denialReasons?.[0] || 'Access denied',\n guidance: result.guidance,\n // Round-10: aggregated per-dimension detail + correlation handle.\n failures: result.failures,\n correlationId: result.correlationId,\n stepUpApproval: result.stepUpApproval,\n // 3.6.0: terminal outcome of an opt-in hold-and-poll wait (denied /\n // expired / consumed / timeout). Absent when the feature is off.\n ...(result.stepUpOutcome && { stepUpOutcome: result.stepUpOutcome }),\n },\n });\n}\n\n/**\n * Refresh interval for the remote-fetched route policy. Default: every 5\n * minutes. Override via `routesRefreshMs` on the middleware options. Each\n * middleware instance keeps its own cache; multiple instances pointing at the\n * same endpoint will each fetch independently.\n */\nconst DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1000;\n\n/**\n * Create Express middleware for agent verification.\n *\n * v2.9.7 moved per-route policy authority out of merchant-side source code\n * into the AstraSync dashboard. `createMiddleware` no longer accepts a\n * `routes` array — it fetches the endpoint's stored policy via\n * `GET /endpoints/:counterpartyId/routes` on init and refreshes\n * periodically. Policy edits in the dashboard take effect on the next\n * refresh (or sooner if the operator manually restarts the SDK).\n *\n * `counterpartyId` is required: the SDK can't know which endpoint's policy\n * to fetch without it. Local-development workflows that don't have an\n * AstraSync endpoint registered can omit it — the middleware logs a\n * one-time warning and falls through (allows all) until a policy is\n * fetchable.\n */\nexport function createMiddleware(options: ExpressMiddlewareOptions): RequestHandler {\n // Guard against configs authored for pre-2.9.7 SDKs: a `routes` array in\n // merchant source is silently dead config (the type contract rejects it at\n // literal call sites, but variable-typed configs slip through) — and dead\n // route config means the author believes paths are gated that aren't.\n if ('routes' in options) {\n // eslint-disable-next-line no-console\n console.warn(\n '[VerificationGateway] `routes` is dashboard-managed since v2.9.7; this option is ignored — ' +\n 'configure route policy in your AstraSync dashboard.'\n );\n }\n const {\n extractCredentials: customExtractCredentials,\n extractPurpose: customExtractPurpose,\n extractAction: customExtractAction,\n skipPaths = [],\n onDenied = defaultOnDenied,\n recordDecisions,\n enableRuntimeChallenge = true,\n routesRefreshMs = DEFAULT_ROUTES_REFRESH_MS,\n failOnError = 'open',\n caseInsensitiveRouteMatch = false,\n anonymousBeacon = true,\n trustVerifiedHop = false,\n verifiedHopMaxAgeMs,\n ...config\n } = options;\n\n // v2.5.0: fire-and-forget pre-fetch of well-known URLs\n if (config.apiBaseUrl) {\n prefetchWellKnown(config.apiBaseUrl).catch(() => {});\n }\n\n // Dashboard-driven anonymous-traffic beacon for the pass-through paths\n // (no matching route / route gated at `none`). Fire-and-forget: never\n // awaited, never delays next(). See ./anonymous-beacon.ts.\n const emitAnonymousBeacon = anonymousBeacon\n ? createAnonymousBeacon(config, { counterpartyType: config.counterpartyType ?? 'api' })\n : undefined;\n const beaconPassThrough = emitAnonymousBeacon\n ? (req: Request): void => {\n const xff = req.headers['x-forwarded-for'];\n const xffStr = Array.isArray(xff) ? xff.join(', ') : xff;\n emitAnonymousBeacon({\n requestPath: req.path,\n requestMethod: req.method,\n counterpartyUrl: config.counterpartyUrl || `${req.protocol}://${req.get('host')}`,\n sourceIp: req.ip ?? (xffStr ? xffStr.split(',')[0].trim() : undefined),\n rawHeaders: req.headers as Record<string, string | string[] | undefined>,\n });\n }\n : undefined;\n\n // Per-middleware-instance route cache. Populated on first fetch; refreshed\n // every `routesRefreshMs`. Until first successful fetch we hold an empty\n // array which means \"no per-route gating active\" — the middleware falls\n // through. Pre-fix the array came from merchant source, which both broke\n // the auth-boundary story (defect 24) and silently disagreed with the\n // dashboard.\n let cachedRoutes: RouteAccessConfig[] = [];\n let lastFetchAt = 0;\n let refreshing: Promise<void> | null = null;\n let warnedNoCounterparty = false;\n let warnedEmptyRoutes = false;\n\n async function refreshRoutes(): Promise<void> {\n if (!config.counterpartyId) {\n if (!warnedNoCounterparty) {\n // eslint-disable-next-line no-console\n console.warn(\n '[VerificationGateway] No counterpartyId configured — falling through (allow all). ' +\n 'Per-route policy lives in the AstraSync dashboard now; register the endpoint and ' +\n 'set counterpartyId in your middleware config to enforce policy.'\n );\n warnedNoCounterparty = true;\n }\n return;\n }\n const fetched = await fetchRoutes(config, config.counterpartyId);\n if (fetched) {\n cachedRoutes = fetched;\n lastFetchAt = Date.now();\n // v2.3.8 (defect #25): if the fetch succeeded but returned an empty\n // policy, the endpoint is registered correctly but the operator hasn't\n // configured any routes yet — every request will fall through ungated.\n // Surface this loudly once so silent pass-through can't go unnoticed.\n if (cachedRoutes.length === 0 && !warnedEmptyRoutes) {\n // Audit F-PROBE-01: app.astrasync.ai doesn't resolve in DNS today;\n // dashboard actually lives at astrasync.ai/dashboard. Use that as\n // the fallback. If DevOps provisions app.astrasync.ai later, the\n // dashboardUrl config option lets merchants override.\n const dashboard = config.dashboardUrl ?? 'https://astrasync.ai/dashboard';\n // eslint-disable-next-line no-console\n console.warn(\n `[VerificationGateway] No route policy configured for ${config.counterpartyId}. ` +\n `Gateway is in pass-through mode for ALL traffic until you add at least one route. ` +\n `Configure at ${dashboard}/dashboard/endpoints/${config.counterpartyId}/routes`\n );\n warnedEmptyRoutes = true;\n }\n }\n }\n\n // Eager first fetch so the first request after init has policy loaded.\n // Errors are swallowed (handled by fetchRoutes returning null).\n refreshing = refreshRoutes().finally(() => {\n refreshing = null;\n });\n\n return async (req: Request, res: Response, next: NextFunction): Promise<void> => {\n try {\n // Check if path should be skipped\n const shouldSkip = skipPaths.some((pattern) => matchRoute(pattern, req.path));\n if (shouldSkip) {\n return next();\n }\n\n // Wait for in-flight init fetch (only on the very first request) so we\n // don't admit traffic with no policy loaded.\n if (refreshing) {\n await refreshing.catch(() => {});\n }\n // Time-based refresh: kick off a background refresh if the cache is\n // stale. Doesn't block the current request — readers see whatever is\n // cached at this moment; the next request will see the refreshed copy.\n if (config.counterpartyId && Date.now() - lastFetchAt > routesRefreshMs) {\n refreshing = refreshRoutes().finally(() => {\n refreshing = null;\n });\n }\n\n // Find route configuration\n // Audit F-A6-31 shadow-mode wiring: pass caseInsensitive flag (default\n // false in 2.4.13) + always log divergences so merchants can grep for\n // would-have-matched results during the 1-week observation window.\n const correlationId =\n (req.headers['x-request-id'] as string | undefined) ||\n (req.headers['x-correlation-id'] as string | undefined);\n const routeConfig = findRouteConfig(cachedRoutes, req.path, req.method, {\n caseInsensitive: caseInsensitiveRouteMatch,\n logShadowDivergence: true,\n correlationId,\n });\n\n // If no route config, skip verification (allow through)\n if (!routeConfig) {\n if (config.setPassThroughHeader) {\n // Round-10 (#49, O10): `unenforced` replaces the previous\n // `pass-through` label. The previous name conflated \"gateway\n // didn't evaluate policy\" with \"request succeeded end-to-end\" —\n // the downstream handler may still return any status. The new\n // semantic describes the GATE state only.\n res.setHeader('X-Astra-Gateway-Mode', 'unenforced');\n res.setHeader(\n 'X-Astra-Gateway-Reason',\n cachedRoutes.length === 0 ? 'no-policy' : 'no-match'\n );\n }\n // Anonymous-traffic beacon: this request never reaches verify-access,\n // so bot/agent-shaped callers would otherwise be invisible to the\n // dashboard. Fire-and-forget — does not delay next().\n beaconPassThrough?.(req);\n return next();\n }\n\n // v2.5.0: resolve well-known URLs (cached; prefetched at middleware creation)\n const wellKnownUrls = config.apiBaseUrl\n ? await getWellKnownUrls(config.apiBaseUrl).catch(() => undefined)\n : undefined;\n\n // Extract credentials (hoisted from below the route-none check so the\n // round-12 F9 evaluateAlwaysIfCredentialed flag can decide whether to\n // evaluate vs short-circuit).\n const credentials = customExtractCredentials\n ? customExtractCredentials(req)\n : defaultExtractCredentials(req);\n\n // Round-12 (F9): route-none short-circuit unless the caller wants\n // evaluation-without-enforcement. With evaluateAlwaysIfCredentialed\n // set to true AND credentials present, the middleware calls\n // verify-access for audit + req.agentVerification population, then\n // proceeds without gating. Default behaviour (flag off) preserves\n // pre-F9 short-circuit semantics.\n const shouldEnforce = !routeConfig.observe;\n if (routeConfig.observe && (!config.evaluateAlwaysIfCredentialed || !credentials.astraId)) {\n if (config.setPassThroughHeader) {\n res.setHeader('X-Astra-Gateway-Mode', 'unenforced');\n res.setHeader('X-Astra-Gateway-Reason', 'route-observe');\n }\n // Anonymous-traffic beacon (see the no-route-match branch above).\n beaconPassThrough?.(req);\n return next();\n }\n\n // Inner-hop dedupe: a trusted upstream AstraSync hop (edge gateway or\n // MCP outer hop) already verified this exact ASTRA-id moments ago —\n // accept the fresh marker and skip the duplicate verify-access call.\n // Mirrors the MCP adapter contract: no req.agentVerification on a\n // hop-skip. The marker must match the request's own X-Astra-Id.\n if (trustVerifiedHop && credentials.astraId) {\n const hopRaw = req.headers[MCP_VERIFIED_HOP_HEADER.toLowerCase()];\n const hopValue =\n typeof hopRaw === 'string' ? hopRaw : Array.isArray(hopRaw) ? hopRaw[0] : undefined;\n const marker = parseVerifiedHop(hopValue);\n if (\n isVerifiedHopValidFor(marker, credentials.astraId, {\n ...(verifiedHopMaxAgeMs !== undefined ? { maxAgeMs: verifiedHopMaxAgeMs } : {}),\n })\n ) {\n return next();\n }\n }\n\n // v2.3.0: anonymous traffic no longer short-circuits client-side.\n // The server applies the endpoint's `unverifiedAgentPolicy` (deny /\n // allow_partial / allow_full) and emits the verification event +\n // blockchain record per the canonical flow. SDK forwards verbatim.\n\n // Resolve the canonical {purpose, action} pair (Bug 14, §4.6): dashboard\n // route mapping → custom extractors → agent X-Astra-* headers →\n // method-table fallback. The transport verb never travels as the action.\n const pdlssPair = resolveRequestPdlss(\n req,\n routeConfig,\n customExtractPurpose,\n customExtractAction\n );\n const purpose = pdlssPair.purpose;\n if (config.debug) {\n // Same telemetry shape as the MCP adapter — adoption tracking and\n // support triage read the *_source fields to see which integration\n // path each partner uses (route mapping vs headers vs fallback).\n // eslint-disable-next-line no-console\n console.debug('[express-middleware] pdlss resolved', {\n purpose_source: pdlssPair.purposeSource,\n resolved_purpose: pdlssPair.purpose,\n action_source: pdlssPair.actionSource,\n resolved_action: pdlssPair.action,\n });\n }\n\n // Extract full AstraSync credentials (includes PDLSS from X-Astra-* headers)\n const astraCreds = extractAstraSyncCredentials(req);\n\n // Auto-detect counterparty URL from the request if not explicitly configured.\n // Since the SDK is installed at this endpoint, we always know the origin.\n const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get('host')}`;\n\n // Step 2: Counterparty-side PDLSS pre-check — compare agent's requested PDLSS\n // against counterparty-defined maximums on the route config.\n // Rejects immediately if outside limits, BEFORE calling verify-access.\n const preCheckFailures = performCounterpartyPreCheck(routeConfig, astraCreds, purpose);\n if (preCheckFailures.length > 0) {\n // Round-18 G4: counterparty pre-check failure — request rejected\n // before reaching verify-access. Neither identity nor policy was\n // remotely verified; both axes truthfully false.\n const result: VerificationResult = {\n identityVerified: false,\n policyAllowed: false,\n denialReasons: preCheckFailures.map((f) => f.message),\n guidance: {\n message: 'Request exceeds counterparty-defined PDLSS limits.',\n registrationUrl: wellKnownUrls?.registrationUrl ?? '',\n documentationUrl: wellKnownUrls?.documentationUrl ?? '',\n },\n verifiedAt: new Date(),\n };\n\n req.agentVerification = result;\n\n // Fire-and-forget: notify AstraSync of the pre-check failure\n reportCounterpartyPreCheckFailure(config, {\n agentId: astraCreds?.agentId || credentials.astraId || 'unknown',\n counterpartyUrl,\n counterpartyType: config.counterpartyType || 'api',\n failures: preCheckFailures,\n requestPath: req.path,\n requestMethod: req.method,\n }).catch(() => {});\n\n dedupeFailures(result);\n onDenied(result, req, res);\n return;\n }\n\n // Step 3: Call AstraSync verify-access with runtime challenge enabled\n const shouldRecordDecisions = recordDecisions !== false;\n const forwardedFor = req.headers['x-forwarded-for'];\n const forwardedForStr = Array.isArray(forwardedFor) ? forwardedFor.join(', ') : forwardedFor;\n // Audit F-A6-34: previously the LEFTMOST X-Forwarded-For entry was\n // taken as the original client IP. That value is attacker-controlled\n // whenever the customer's reverse proxy doesn't strip\n // client-supplied X-Forwarded-For — an attacker prepends\n // `X-Forwarded-For: 1.1.1.1` and we audit the spoofed IP. Now we\n // prefer req.ip (which Express resolves via configured `trust proxy`\n // hop count — the customer's responsibility to set correctly per\n // their actual hop chain). XFF still provides a fallback for\n // customers without `trust proxy` configured, but emits a one-time\n // warning when used so they know to fix.\n const originalClientIp =\n req.ip ?? (forwardedForStr ? forwardedForStr.split(',')[0].trim() : undefined);\n if (!req.ip && forwardedForStr) {\n // eslint-disable-next-line no-console\n console.warn(\n '[VerificationGateway] req.ip unset — falling back to leftmost X-Forwarded-For. ' +\n 'Configure Express trust proxy correctly to avoid spoofable client IPs in audit logs.'\n );\n }\n const agentCardUrl =\n typeof req.headers['x-astrasync-agent-card'] === 'string'\n ? (req.headers['x-astrasync-agent-card'] as string)\n : undefined;\n\n // P1 (SDK 3.5.0): when extractTransactionValue is configured, include\n // the value in verify-access so PDLSS limit evaluation runs at\n // middleware time. Must return major units (dollars, not cents).\n let txValue: number | undefined;\n let txCurrency: string | undefined;\n if (config.extractTransactionValue) {\n try {\n const extracted = config.extractTransactionValue(req);\n if (extracted) {\n txValue = extracted.value;\n txCurrency = extracted.currency;\n }\n } catch (e) {\n if (config.debug) {\n // eslint-disable-next-line no-console\n console.warn('[VerificationGateway] extractTransactionValue threw:', e);\n }\n }\n }\n\n // 5.8.0 attempt-chain (X-Astra-Attempt-Id): the bridge stamps the\n // interaction-chain id on every venue call (the edge pipeline already\n // reads it). Threading it into verify-access makes this hop part of the\n // SAME chain server-side, so a step-up the human already approved for\n // the chain passes here instead of minting a second approval — the\n // two-hop approval-loop fix. Invalid values are dropped, never sent.\n const attemptHeader = req.headers['x-astra-attempt-id'];\n const inboundAttemptId =\n typeof attemptHeader === 'string' && /^att_[0-9a-f]{32}$/.test(attemptHeader)\n ? attemptHeader\n : undefined;\n\n const verificationRequest: VerificationRequest = {\n credentials,\n purpose,\n action: pdlssPair.action,\n resource: req.path,\n createSession: shouldRecordDecisions,\n counterpartyUrl,\n counterpartyType: config.counterpartyType || 'api',\n enableRuntimeChallenge,\n durationRequired: astraCreds?.pdlss?.duration?.maxSessionDuration,\n ...(txValue !== undefined && { transactionValue: txValue }),\n ...(txCurrency && { currency: txCurrency }),\n ...(inboundAttemptId && { attemptId: inboundAttemptId }),\n callerMetadata: {\n sourceIp: originalClientIp,\n userAgent: req.headers['user-agent'] as string | undefined,\n referer: req.headers.referer as string | undefined,\n host: req.headers.host as string | undefined,\n forwardedFor: forwardedForStr,\n agentCardUrl,\n // Workstream D — capture EVERY inbound header (SDK-only merchants\n // have no edge to do it upstream) plus the CDN-derived connection\n // block. Local string work, secrets stripped; out of the verify\n // cache key so it doesn't defeat caching.\n observedMetadata: buildSdkObservedMetadata(req.headers),\n },\n };\n let result = await verify(config, verificationRequest);\n\n // Attach result to request\n req.agentVerification = result;\n let sessionId = (result as EnhancedVerificationResult).sessionId;\n\n // 3.6.0 hold-and-poll (opt-in via stepUpMaxWaitMs): HOLD a step-up\n // outcome, poll the approval, and on 'approved' re-verify the same\n // request once (cache-bypassed — the retry must reach the backend to\n // redeem the single-use approval). Every non-approved outcome falls\n // through to the existing fail-closed branches below with\n // result.stepUpOutcome stamped for the deny body.\n if (\n config.stepUpMaxWaitMs !== undefined &&\n result.policyAllowed &&\n requiresHumanApproval(result) &&\n result.stepUpApproval?.pollUrl\n ) {\n const outcome = await awaitStepUpApproval(config, result.stepUpApproval);\n res.setHeader('X-Astra-Step-Up', outcome);\n if (outcome === 'approved') {\n result = await verify(config, verificationRequest, { bypassCache: true });\n req.agentVerification = result;\n sessionId = (result as EnhancedVerificationResult).sessionId;\n } else {\n result.stepUpOutcome = outcome;\n }\n }\n\n // Denied verifications short-circuit here: failing either identity OR\n // policy already means \"deny.\" We check that first.\n // 4.5.0 (probe F1 follow-through): the gate is the SERVER's decision —\n // `policyAllowed` is true exactly when the backend allowed the call\n // (every deny/guidance/api-error shape sets it false), so gating on it\n // alone preserves the endpoint policy verbatim. `identityVerified` no\n // longer gates here: anonymous callers granted by an\n // audit/allow_partial/allow_full endpoint policy are honestly\n // identity-unverified yet server-allowed, and re-deriving a deny from\n // identity would override the backend evaluator (the SDK-pre-check\n // asymmetry antipattern). Identity still picks 401-vs-403 in the deny\n // body builder.\n if (!result.policyAllowed) {\n if (shouldRecordDecisions && sessionId) {\n recordDecision(config, sessionId, 'denied', result.denialReasons?.[0]).catch(() => {});\n }\n dedupeFailures(result);\n onDenied(result, req, res);\n return;\n }\n\n // F2 direct-path fail-closed: an \"allowed-but-escalate\" outcome\n // (step-up / requires-approval, policyAllowed:true) cannot be completed\n // autonomously. The backend creates a step-up approval record and returns\n // it on `result.stepUpApproval`; deny here — symmetric with the bridge —\n // and surface the polling info in the deny response body.\n if (requiresHumanApproval(result)) {\n annotateApprovalRequired(result);\n if (shouldRecordDecisions && sessionId) {\n recordDecision(config, sessionId, 'denied', result.denialReasons?.[0]).catch(() => {});\n }\n dedupeFailures(result);\n onDenied(result, req, res);\n return;\n }\n\n // Round-12 (F9): evaluation-without-enforcement. When the route is\n // 'none' but we ran verify-access for audit, skip the gates and call\n // next() — the result is on req.agentVerification for the handler\n // to render tier-aware responses (e.g. anonymous vs verified\n // catalog view on the same path).\n if (!shouldEnforce) {\n if (config.setPassThroughHeader) {\n res.setHeader('X-Astra-Gateway-Mode', 'enforced');\n res.setHeader('X-Astra-Gateway-Reason', 'evaluated-not-enforced');\n }\n if (shouldRecordDecisions && sessionId) {\n recordDecision(config, sessionId, 'granted').catch(() => {});\n }\n return next();\n }\n\n // The access decision is the server's (identityVerified / policyAllowed,\n // above) — resting on a verified ID + runtime challenge + PDLSS match +\n // trust score. The only client-side refinement is the per-route trust\n // floor below; there is no access-level band (removed in SDK 5.0.0).\n\n // Per-route trust tightening (only refinement that still gates).\n if (routeConfig.minTrustScore && result.agent) {\n if (result.agent.trustScore < routeConfig.minTrustScore) {\n // 3.2.0: qualitative — never embed the score or the threshold in an\n // agent-visible message (trust is a system-internal signal; exposing\n // the number is a gaming vector — post-3.1.0 feedback #2).\n const trustFailure = {\n dimension: 'endpoint.trust',\n message: 'Trust below the route requirement for this endpoint.',\n guidance:\n \"Trust is below this route's floor. Trust is not overridable — the agent either meets the endpoint's trust policy or it doesn't. Raise the agent's trust via real signals (KYD, blockchain registration, agent-card), or have the operator lower the route's minTrustScore.\",\n };\n result.failures = [...(result.failures ?? []), trustFailure];\n result.denialReasons = [trustFailure.message];\n if (!result.guidance && wellKnownUrls) {\n result.guidance = {\n message: trustFailure.message,\n registrationUrl: wellKnownUrls.registrationUrl,\n documentationUrl: wellKnownUrls.documentationUrl,\n };\n }\n if (shouldRecordDecisions && sessionId) {\n recordDecision(config, sessionId, 'denied', trustFailure.message).catch(() => {});\n }\n dedupeFailures(result);\n onDenied(result, req, res);\n return;\n }\n }\n\n // All checks passed — record grant decision\n if (shouldRecordDecisions && sessionId) {\n recordDecision(config, sessionId, 'granted').catch(() => {});\n }\n // v2.3.8 (defect #26): if the endpoint's `unverifiedAgentPolicy` is\n // `'audit'` (allow + soft-launch warning), the server returns the\n // header to relay. Lift it onto the merchant's response BEFORE\n // calling next() so downstream handlers and the eventual response\n // back to the agent both carry it.\n const enhancedResult = result as EnhancedVerificationResult;\n if (enhancedResult.warningHeader) {\n res.setHeader(enhancedResult.warningHeader.name, enhancedResult.warningHeader.value);\n }\n next();\n } catch (error) {\n // Audit F-A1-06: shadow-mode logging for fail-closed default migration.\n // Always log `[SHADOW] would-have-denied` so merchants can grep their\n // own application logs for would-have-been-denied impact during the\n // observation window. Actual deny/admit behavior controlled by\n // failOnError option (default 'open' for backward compatibility).\n const errorClass = error instanceof Error ? error.constructor.name : typeof error;\n const correlationId =\n (req.headers['x-request-id'] as string | undefined) ||\n (req.headers['x-correlation-id'] as string | undefined) ||\n `gen-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n // eslint-disable-next-line no-console\n console.error('[VerificationGateway] Middleware error:', error);\n // eslint-disable-next-line no-console\n console.warn(\n `[SHADOW] would-have-denied: errorClass=${errorClass} route=${req.method}:${req.path} merchantId=${config.counterpartyId ?? 'unknown'} correlationId=${correlationId}`\n );\n\n if (failOnError === 'closed') {\n const result: VerificationResult = {\n identityVerified: false,\n policyAllowed: false,\n denialReasons: [`Verification middleware internal error: ${errorClass}`],\n failures: [\n {\n dimension: 'middleware.internal_error',\n message: `Middleware threw ${errorClass} — failing closed`,\n },\n ],\n verifiedAt: new Date(),\n correlationId,\n };\n const catchUrls = config.apiBaseUrl\n ? await getWellKnownUrls(config.apiBaseUrl).catch(() => undefined)\n : undefined;\n if (catchUrls) {\n result.guidance = {\n message: `Middleware threw ${errorClass} — failing closed`,\n registrationUrl: catchUrls.registrationUrl,\n documentationUrl: catchUrls.documentationUrl,\n };\n }\n dedupeFailures(result);\n return onDenied(result, req, res);\n }\n\n next();\n }\n };\n}\n\n// `requireAccess` and `verifyOnly` were removed in v2.9.7. Both injected a\n// local `routes` array into the merchant's source code, which is the exact\n// dual-config attack vector defect 24 closed. Per-route policy now lives in\n// the AstraSync dashboard (gated by team.role admin auth + audit + alerts).\n// To tighten a route, set its `minTrustScore` (+ purpose/jurisdiction/value\n// gates) in the dashboard. For \"verify but don't block,\" set the route to\n// `observe` (or run the endpoint in an audit `unverifiedAgentPolicy`).\n","/**\n * AstraSync Universal Verification Gateway - Next.js Middleware\n *\n * Next.js middleware for verifying AI agents on web applications.\n * Serves the verification interstitial (an HTML overlay with registration\n * guidance) to unverified web-page traffic; API routes get structured JSON.\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import { createMiddleware } from '@astrasyncai/verification-gateway/nextjs';\n *\n * export const middleware = createMiddleware({\n * apiBaseUrl: 'https://astrasync.ai/api',\n * apiKey: process.env.ASTRASYNC_API_KEY,\n * counterpartyId: 'ASTRAE-...', // per-route policy is fetched from the dashboard\n * showInterstitial: true,\n * });\n *\n * export const config = {\n * matcher: ['/api/:path*', '/dashboard/:path*'],\n * };\n * ```\n */\n\nimport type { NextRequest } from 'next/server';\nimport type {\n NextJsMiddlewareOptions,\n AgentCredentials,\n VerificationResult,\n RouteAccessConfig,\n AstraSyncCredentials,\n VerificationRequest,\n StepUpOutcome,\n} from '../types';\nimport { awaitStepUpApproval } from './stepup-poll';\nimport { verify, reportCounterpartyPreCheckFailure, fetchRoutes } from '../verify';\nimport { extractHttpCredentials } from '../transport/http';\nimport { performCounterpartyPreCheck } from '../pdlss-pre-check';\nimport { buildSdkObservedMetadata } from '../metadata-capture';\nimport { createAnonymousBeacon } from './anonymous-beacon';\nimport { resolveHttpPdlss, type HttpPdlssResolution } from './http-pdlss';\nimport { requiresHumanApproval, annotateApprovalRequired } from './approval-gate';\nimport { MCP_VERIFIED_HOP_HEADER, parseVerifiedHop, isVerifiedHopValidFor } from '../verified-hop';\n\n/**\n * HTML-escape arbitrary string for safe interpolation into HTML text or\n * attribute values. Used by the interstitial HTML generator\n * to prevent reflected XSS from attacker-influenced denial messages.\n */\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * Sanitize a URL for `href=`. Accepts only `http://` / `https://` schemes\n * (relative URLs allowed too); rejects `javascript:` / `data:` / `vbscript:`\n * and falls back to the supplied default on rejection. Then HTML-escapes\n * the result.\n */\nfunction sanitizeUrl(value: string | undefined, fallback: string): string {\n if (typeof value !== 'string' || value.length === 0) return escapeHtml(fallback);\n const trimmed = value.trim();\n if (/^javascript:|^data:|^vbscript:/i.test(trimmed)) return escapeHtml(fallback);\n if (/^https?:\\/\\//i.test(trimmed) || trimmed.startsWith('/')) {\n return escapeHtml(trimmed);\n }\n return escapeHtml(fallback);\n}\n\n/**\n * Extract credentials from Next.js request\n */\nfunction extractCredentialsFromNextRequest(request: NextRequest): AgentCredentials {\n const credentials: AgentCredentials = {};\n\n // Check for ASTRA-ID in headers\n const astraId = request.headers.get('x-astra-id') || request.headers.get('X-Astra-Id');\n if (astraId) {\n credentials.astraId = astraId;\n }\n\n // Check for API key\n const apiKey = request.headers.get('x-api-key') || request.headers.get('X-Api-Key');\n if (apiKey) {\n credentials.apiKey = apiKey;\n }\n\n // Check Authorization header\n const authHeader = request.headers.get('authorization');\n if (authHeader) {\n credentials.authorizationHeader = authHeader;\n if (authHeader.startsWith('Bearer ')) {\n credentials.jwt = authHeader.slice(7);\n }\n }\n\n // Check query parameters\n const url = new URL(request.url);\n const astraIdParam = url.searchParams.get('astraId');\n const apiKeyParam = url.searchParams.get('apiKey');\n\n if (astraIdParam && !credentials.astraId) {\n credentials.astraId = astraIdParam;\n }\n if (apiKeyParam && !credentials.apiKey) {\n credentials.apiKey = apiKeyParam;\n }\n\n return credentials;\n}\n\n/**\n * Match a route pattern against a path\n */\nfunction matchRoute(pattern: string, path: string): boolean {\n const regexPattern = pattern.replace(/\\*/g, '.*').replace(/\\//g, '\\\\/');\n\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(path);\n}\n\n/**\n * Find the route configuration for a request\n */\nfunction findRouteConfig(\n routes: RouteAccessConfig[],\n path: string,\n method: string\n): RouteAccessConfig | undefined {\n return routes.find((route) => {\n const methodMatches =\n route.method === '*' || route.method.toUpperCase() === method.toUpperCase();\n const pathMatches = matchRoute(route.pattern, path);\n return methodMatches && pathMatches;\n });\n}\n\n/**\n * Extract AstraSyncCredentials from Next.js request headers.\n * Returns null if no AstraSync headers are present.\n */\nfunction extractAstraSyncCredentialsFromNextRequest(\n request: NextRequest\n): AstraSyncCredentials | null {\n const headers: Record<string, string> = {};\n request.headers.forEach((value, key) => {\n headers[key] = value;\n });\n return extractHttpCredentials(headers);\n}\n\n/**\n * Resolve the canonical {purpose, action} pair for a request.\n * Replaces the gen-1 method-inference (`read_data`/`write_data`) and the\n * hardwired verb action — the transport verb never travels as a PDLSS\n * action. Same resolver as the express adapter (http-pdlss.ts); nextjs has\n * no custom extractors and no query-param step (never existed here).\n */\nfunction resolveNextPdlss(\n request: NextRequest,\n routeConfig: { purpose?: string; action?: string } | null\n): HttpPdlssResolution {\n return resolveHttpPdlss({\n method: request.method,\n astraPurpose: request.headers.get('x-astra-purpose') ?? undefined,\n astraAction: request.headers.get('x-astra-action') ?? undefined,\n legacyPurpose: request.headers.get('x-purpose') ?? undefined,\n routePurpose: routeConfig?.purpose,\n routeAction: routeConfig?.action,\n });\n}\n\n/**\n * Generate the verification-interstitial HTML response served to unverified\n * web-page traffic.\n */\nfunction generateInterstitialHtml(\n result: VerificationResult,\n options: NextJsMiddlewareOptions\n): string {\n // result.guidance.message may quote attacker-controlled input from the\n // backend deny path (e.g. `Purpose \"<script>...\" is not in the allowed\n // list`). HTML-escape every interpolated value; validate URLs reject\n // non-http(s) schemes to prevent `javascript:` smuggling.\n const title = escapeHtml(options.commerceShield?.title || 'AstraSync Agent Verification');\n const message = escapeHtml(\n options.commerceShield?.message ||\n result.guidance?.message ||\n \"This site verifies AI agents before granting access. We noticed you're visiting without AstraSync credentials.\"\n );\n const registrationUrl = sanitizeUrl(\n result.guidance?.registrationUrl,\n 'https://astrasync.ai/agents/register'\n );\n const docsUrl = sanitizeUrl(\n result.guidance?.documentationUrl,\n 'https://astrasync.ai/docs/agent-access'\n );\n const allowGuest = options.commerceShield?.allowGuestAccess ?? true;\n\n return `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${title}</title>\n <style>\n * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n }\n .shield-container {\n background: rgba(255, 255, 255, 0.95);\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);\n max-width: 480px;\n width: 100%;\n padding: 40px;\n text-align: center;\n }\n .shield-icon {\n font-size: 48px;\n margin-bottom: 20px;\n }\n .shield-title {\n font-size: 24px;\n font-weight: 700;\n color: #1a1a2e;\n margin-bottom: 16px;\n }\n .shield-message {\n color: #4a5568;\n line-height: 1.6;\n margin-bottom: 24px;\n }\n .shield-steps {\n text-align: left;\n background: #f7fafc;\n border-radius: 8px;\n padding: 20px;\n margin-bottom: 24px;\n }\n .shield-steps h3 {\n font-size: 14px;\n font-weight: 600;\n color: #2d3748;\n margin-bottom: 12px;\n }\n .shield-steps ol {\n padding-left: 20px;\n color: #4a5568;\n }\n .shield-steps li {\n margin-bottom: 8px;\n }\n .shield-buttons {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n .btn {\n display: inline-block;\n padding: 14px 24px;\n border-radius: 8px;\n font-weight: 600;\n text-decoration: none;\n transition: all 0.2s;\n cursor: pointer;\n border: none;\n font-size: 16px;\n }\n .btn-primary {\n background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);\n color: white;\n }\n .btn-primary:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);\n }\n .btn-secondary {\n background: #e2e8f0;\n color: #4a5568;\n }\n .btn-secondary:hover {\n background: #cbd5e0;\n }\n .shield-footer {\n margin-top: 24px;\n font-size: 14px;\n color: #718096;\n }\n .shield-footer a {\n color: #6366f1;\n text-decoration: none;\n }\n .shield-footer a:hover {\n text-decoration: underline;\n }\n </style>\n</head>\n<body>\n <div class=\"shield-container\">\n <div class=\"shield-icon\">🛡️</div>\n <h1 class=\"shield-title\">${title}</h1>\n <p class=\"shield-message\">${message}</p>\n\n <div class=\"shield-steps\">\n <h3>To get verified access:</h3>\n <ol>\n <li>Register at <a href=\"${registrationUrl}\">astrasync.ai/agents/register</a></li>\n <li>Create and register your agent</li>\n <li>Add your ASTRA-ID to request headers</li>\n <li>Refresh this page</li>\n </ol>\n </div>\n\n <div class=\"shield-buttons\">\n <a href=\"${registrationUrl}\" class=\"btn btn-primary\">Register Now</a>\n ${allowGuest ? '<button onclick=\"window.location.reload()\" class=\"btn btn-secondary\">Continue as Guest (Limited)</button>' : ''}\n </div>\n\n <p class=\"shield-footer\">\n Learn more: <a href=\"${docsUrl}\">Agent Access Documentation</a>\n </p>\n </div>\n</body>\n</html>\n `.trim();\n}\n\nconst DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1000;\n\n/**\n * Create Next.js middleware for agent verification.\n *\n * v2.9.7 moved per-route policy out of merchant-side source code into the\n * AstraSync dashboard. The middleware fetches its routes from the backend\n * via `GET /endpoints/:counterpartyId/routes` on init and refreshes\n * periodically — see `ExpressMiddlewareOptions` for the rationale (a dual\n * config source silently conflicts with dashboard policy).\n */\nexport function createMiddleware(options: NextJsMiddlewareOptions) {\n // Guard against configs authored for pre-2.9.7 SDKs: a `routes` array in\n // merchant source is silently dead config — and dead route config means\n // the author believes paths are gated that aren't.\n if ('routes' in options) {\n // eslint-disable-next-line no-console\n console.warn(\n '[VerificationGateway/Next.js] `routes` is dashboard-managed since v2.9.7; this option is ignored — ' +\n 'configure route policy in your AstraSync dashboard.'\n );\n }\n const {\n skipPaths = [],\n showInterstitial,\n showCommerceShield,\n enableRuntimeChallenge = true,\n routesRefreshMs = DEFAULT_ROUTES_REFRESH_MS,\n anonymousBeacon = true,\n trustVerifiedHop = false,\n verifiedHopMaxAgeMs,\n ...config\n } = options;\n\n // 4.1.0: `showInterstitial` supersedes the deprecated `showCommerceShield`\n // flag; the new name wins when both are set. Default remains true.\n const interstitialEnabled = showInterstitial ?? showCommerceShield ?? true;\n\n // Dashboard-driven anonymous-traffic beacon for the pass-through paths\n // (no matching route / route gated at `none`). Fire-and-forget: never\n // awaited, never delays the NextResponse. See ./anonymous-beacon.ts.\n const emitAnonymousBeacon = anonymousBeacon\n ? createAnonymousBeacon(config, { counterpartyType: config.counterpartyType ?? 'website' })\n : undefined;\n const beaconPassThrough = emitAnonymousBeacon\n ? (request: NextRequest, pathname: string): void => {\n emitAnonymousBeacon({\n requestPath: pathname,\n requestMethod: request.method,\n counterpartyUrl: config.counterpartyUrl || request.nextUrl.origin,\n sourceIp: request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || undefined,\n rawHeaders: Object.fromEntries(request.headers.entries()),\n });\n }\n : undefined;\n\n let cachedRoutes: RouteAccessConfig[] = [];\n let lastFetchAt = 0;\n let refreshing: Promise<void> | null = null;\n let warnedNoCounterparty = false;\n\n async function refreshRoutes(): Promise<void> {\n if (!config.counterpartyId) {\n if (!warnedNoCounterparty) {\n // eslint-disable-next-line no-console\n console.warn(\n '[VerificationGateway/Next.js] No counterpartyId configured — falling through (allow all). ' +\n 'Per-route policy lives in the AstraSync dashboard now; register the endpoint and ' +\n 'set counterpartyId in your middleware config to enforce policy.'\n );\n warnedNoCounterparty = true;\n }\n return;\n }\n const fetched = await fetchRoutes(config, config.counterpartyId);\n if (fetched) {\n cachedRoutes = fetched;\n lastFetchAt = Date.now();\n }\n }\n\n refreshing = refreshRoutes().finally(() => {\n refreshing = null;\n });\n\n return async function middleware(request: NextRequest) {\n // Dynamic import NextResponse to avoid build issues\n const { NextResponse } = await import('next/server');\n\n const pathname = request.nextUrl.pathname;\n\n // Check if path should be skipped\n const shouldSkip = skipPaths.some((pattern) => matchRoute(pattern, pathname));\n if (shouldSkip) {\n return NextResponse.next();\n }\n\n if (refreshing) {\n await refreshing.catch(() => {});\n }\n if (config.counterpartyId && Date.now() - lastFetchAt > routesRefreshMs) {\n refreshing = refreshRoutes().finally(() => {\n refreshing = null;\n });\n }\n\n // Find route configuration (from remote-fetched cache)\n const routeConfig = findRouteConfig(cachedRoutes, pathname, request.method);\n\n // If no route config, allow through\n if (!routeConfig) {\n // Anonymous-traffic beacon: this request never reaches verify-access,\n // so bot/agent-shaped callers would otherwise be invisible to the\n // dashboard. Fire-and-forget — does not delay the response.\n beaconPassThrough?.(request, pathname);\n return NextResponse.next();\n }\n\n // Observe-only route: pass through unenforced.\n if (routeConfig.observe) {\n // Anonymous-traffic beacon (see the no-route-match branch above).\n beaconPassThrough?.(request, pathname);\n return NextResponse.next();\n }\n\n // Extract credentials\n const credentials = extractCredentialsFromNextRequest(request);\n\n // Inner-hop dedupe: a trusted upstream AstraSync hop (edge gateway or\n // MCP outer hop) already verified this exact ASTRA-id moments ago —\n // accept the fresh marker and skip the duplicate verify-access call.\n // Mirrors the express/MCP adapter contract. The marker must match the\n // request's own X-Astra-Id.\n if (trustVerifiedHop && credentials.astraId) {\n const marker = parseVerifiedHop(request.headers.get(MCP_VERIFIED_HOP_HEADER) ?? undefined);\n if (\n isVerifiedHopValidFor(marker, credentials.astraId, {\n ...(verifiedHopMaxAgeMs !== undefined ? { maxAgeMs: verifiedHopMaxAgeMs } : {}),\n })\n ) {\n return NextResponse.next();\n }\n }\n\n // v2.3.0: anonymous traffic no longer short-circuits client-side.\n // The server applies the endpoint's `unverifiedAgentPolicy` (deny /\n // allow_partial / allow_full) and emits the verification event +\n // blockchain record per the canonical flow. SDK forwards verbatim.\n\n // Auto-detect counterparty URL from the request if not explicitly configured.\n // Since the SDK is installed at this endpoint, we always know the origin.\n const counterpartyUrl = config.counterpartyUrl || request.nextUrl.origin;\n\n // Resolve the canonical {purpose, action} pair (Bug 14, §4.6) and full\n // AstraSync credentials (includes PDLSS from X-Astra-* headers)\n const pdlssPair = resolveNextPdlss(request, routeConfig);\n const purpose = pdlssPair.purpose;\n if (config.debug) {\n // eslint-disable-next-line no-console\n console.debug('[nextjs-middleware] pdlss resolved', {\n purpose_source: pdlssPair.purposeSource,\n resolved_purpose: pdlssPair.purpose,\n action_source: pdlssPair.actionSource,\n resolved_action: pdlssPair.action,\n });\n }\n const astraCreds = extractAstraSyncCredentialsFromNextRequest(request);\n\n // Step 2: Counterparty-side PDLSS pre-check — compare agent's requested PDLSS\n // against counterparty-defined maximums on the route config.\n // Rejects immediately if outside limits, BEFORE calling verify-access.\n const preCheckFailures = performCounterpartyPreCheck(routeConfig, astraCreds, purpose);\n if (preCheckFailures.length > 0) {\n // Round-18 G4: counterparty pre-check failure — see express.ts for the\n // rationale. Neither axis verified remotely → both false.\n const preCheckResult: VerificationResult = {\n identityVerified: false,\n policyAllowed: false,\n denialReasons: preCheckFailures.map((f) => f.message),\n guidance: {\n message: 'Request exceeds counterparty-defined PDLSS limits.',\n registrationUrl: `${config.apiBaseUrl?.replace('/api', '')}/agents/register`,\n documentationUrl: `${config.apiBaseUrl?.replace('/api', '')}/docs/pdlss`,\n },\n verifiedAt: new Date(),\n };\n\n // Fire-and-forget: notify AstraSync of the pre-check failure\n reportCounterpartyPreCheckFailure(config, {\n agentId: astraCreds?.agentId || credentials.astraId || 'unknown',\n counterpartyUrl,\n counterpartyType: config.counterpartyType || 'website',\n failures: preCheckFailures,\n requestPath: pathname,\n requestMethod: request.method,\n }).catch(() => {});\n\n // For API routes, return JSON\n if (pathname.startsWith('/api/')) {\n return NextResponse.json(\n {\n success: false,\n error: {\n code: 'PDLSS_PRE_CHECK_FAILED',\n message: preCheckResult.denialReasons?.[0] || 'PDLSS pre-check failed',\n guidance: preCheckResult.guidance,\n },\n },\n { status: 403 }\n );\n }\n\n // For web pages, show the verification interstitial\n if (interstitialEnabled) {\n return new NextResponse(generateInterstitialHtml(preCheckResult, options), {\n status: 200,\n headers: {\n 'Content-Type': 'text/html',\n 'X-AstraSync-Verification': 'commerce-shield',\n },\n });\n }\n\n return NextResponse.redirect(new URL('/unauthorized', request.url));\n }\n\n // Step 3: Call AstraSync verify-access with runtime challenge enabled\n const forwardedFor = request.headers.get('x-forwarded-for') || undefined;\n const originalClientIp = forwardedFor?.split(',')[0]?.trim();\n // 5.8.0 attempt-chain (X-Astra-Attempt-Id) — see express.ts for the full\n // rationale: threading the bridge-stamped chain id lets an already-\n // approved step-up pass this hop instead of minting a second approval.\n const attemptHeader = request.headers.get('x-astra-attempt-id');\n const inboundAttemptId =\n attemptHeader && /^att_[0-9a-f]{32}$/.test(attemptHeader) ? attemptHeader : undefined;\n const verificationRequest: VerificationRequest = {\n credentials,\n purpose,\n action: pdlssPair.action,\n resource: pathname,\n counterpartyUrl,\n counterpartyType: config.counterpartyType || 'website',\n enableRuntimeChallenge,\n durationRequired: astraCreds?.pdlss?.duration?.maxSessionDuration,\n ...(inboundAttemptId && { attemptId: inboundAttemptId }),\n callerMetadata: {\n sourceIp: originalClientIp,\n userAgent: request.headers.get('user-agent') || undefined,\n referer: request.headers.get('referer') || undefined,\n host: request.headers.get('host') || undefined,\n forwardedFor,\n agentCardUrl: request.headers.get('x-astrasync-agent-card') || undefined,\n // Workstream D — full sanitised header capture + CDN-derived\n // connection block (Web Headers → plain map).\n observedMetadata: buildSdkObservedMetadata(Object.fromEntries(request.headers.entries())),\n },\n };\n let result = await verify(config, verificationRequest);\n\n // 3.6.0 hold-and-poll (opt-in via stepUpMaxWaitMs) — see express.ts for\n // the full rationale. CAUTION on edge runtimes (~25s wall-clock budget):\n // set a small stepUpMaxWaitMs or gate in a Node route handler instead.\n // On 'approved' the same request is re-verified once, cache-bypassed, so\n // the backend redeems the single-use approval.\n let stepUpHoldOutcome: StepUpOutcome | undefined;\n if (\n config.stepUpMaxWaitMs !== undefined &&\n result.policyAllowed &&\n requiresHumanApproval(result) &&\n result.stepUpApproval?.pollUrl\n ) {\n stepUpHoldOutcome = await awaitStepUpApproval(config, result.stepUpApproval);\n if (stepUpHoldOutcome === 'approved') {\n result = await verify(config, verificationRequest, { bypassCache: true });\n } else {\n result.stepUpOutcome = stepUpHoldOutcome;\n }\n }\n\n // Round-18 G4: short-circuit on either axis failing (identity-fail or\n // policy-fail) — both encode the server-side trust-floor + PDLSS decision.\n // The access decision rests on a verified ID + runtime challenge + PDLSS\n // match + trust score; there is no access-level band (removed in SDK 5.0.0).\n // Per-route tightening is `route.minTrustScore` (below).\n // F2 direct-path fail-closed: a step-up / requires-approval outcome\n // (policyAllowed:true, allowed-but-escalate) cannot be completed\n // autonomously — deny and surface stepUpApproval polling info.\n // 4.5.0: gate on the SERVER decision only (`policyAllowed`) — anonymous\n // callers allowed by an audit/allow endpoint policy are honestly\n // identity-unverified; see express.ts for the full rationale.\n const approvalRequired = result.policyAllowed && requiresHumanApproval(result);\n if (approvalRequired) annotateApprovalRequired(result);\n\n if (!result.policyAllowed || approvalRequired) {\n // 4.0.0 BREAKING (API routes): this site's OWN key was rejected —\n // answer 503 with the dedicated code so agents don't read a merchant\n // misconfig as their own auth failure (see express.defaultOnDenied).\n // Web pages keep their existing shield/redirect flow — a human page\n // view must not turn into raw JSON because the operator rotated a key.\n if (result.misconfigured && pathname.startsWith('/api/')) {\n return NextResponse.json(\n {\n success: false,\n error: {\n code: 'MERCHANT_VERIFICATION_MISCONFIGURED',\n message:\n result.denialReasons?.[0] || \"This site's AstraSync integration is misconfigured\",\n guidance: result.guidance,\n failures: result.failures,\n correlationId: result.correlationId,\n },\n },\n { status: 503 }\n );\n }\n\n // For API routes, return JSON\n if (pathname.startsWith('/api/')) {\n return NextResponse.json(\n {\n success: false,\n error: {\n // Round-18 G4: 401 → identity missing (re-auth); 403 → identity\n // OK, policy denied (update PDLSS / step up).\n code: !result.identityVerified ? 'UNAUTHORIZED' : 'POLICY_DENIED',\n message: result.denialReasons?.[0] || 'Access denied',\n guidance: result.guidance,\n failures: result.failures,\n stepUpApproval: result.stepUpApproval,\n // 3.6.0: terminal outcome of an opt-in hold-and-poll wait.\n ...(result.stepUpOutcome && { stepUpOutcome: result.stepUpOutcome }),\n },\n },\n {\n status: !result.identityVerified ? 401 : 403,\n ...(stepUpHoldOutcome && {\n headers: { 'X-Astra-Step-Up': stepUpHoldOutcome },\n }),\n }\n );\n }\n\n // For web pages, show the verification interstitial\n if (interstitialEnabled) {\n return new NextResponse(generateInterstitialHtml(result, options), {\n status: 200,\n headers: {\n 'Content-Type': 'text/html',\n 'X-AstraSync-Verification': 'commerce-shield',\n },\n });\n }\n\n // Redirect to unauthorized page\n return NextResponse.redirect(new URL('/unauthorized', request.url));\n }\n\n // All checks passed - continue with verification info in headers\n const response = NextResponse.next();\n\n // Add verification info to response headers\n // Round-18 G4: composite `verified` (identity AND policy) for legacy\n // header consumers; new headers expose each axis separately so middleware\n // chains can branch without re-running verify-access.\n response.headers.set(\n 'X-AstraSync-Verified',\n (result.identityVerified && result.policyAllowed).toString()\n );\n if (stepUpHoldOutcome) {\n response.headers.set('X-Astra-Step-Up', stepUpHoldOutcome);\n }\n response.headers.set('X-AstraSync-Identity-Verified', result.identityVerified.toString());\n response.headers.set('X-AstraSync-Policy-Allowed', result.policyAllowed.toString());\n\n if (result.agent) {\n response.headers.set('X-AstraSync-Agent-Id', result.agent.astraId);\n // 3.2.0 (post-3.1.0 feedback #2): the X-AstraSync-Trust-Score header is\n // no longer emitted — trust is a system-internal signal and this header\n // rode on the passthrough response toward the agent (gaming vector).\n }\n\n return response;\n };\n}\n\n/**\n * Helper to create matcher config\n */\nexport function createMatcherConfig(paths: string[]): { matcher: string[] } {\n return { matcher: paths };\n}\n","/**\n * RFC 9421 HTTP Message Signatures parser.\n *\n * Wraps `structured-headers` (transitive dep of http-message-signatures) to\n * parse the Signature-Input and Signature Dictionary headers per RFC 9421\n * Section 2.\n *\n * Produces structured metadata (kid, algorithm, covered components, tag,\n * created/expires/nonce, signature bytes) without verifying the signature —\n * verification lives in rfc9421-verify.ts.\n *\n * Shared by:\n * - Agent Pay (Mastercard) — kid resolves via Mastercard Agent Registry\n * - TAP (Visa) — kid resolves via Visa JWKS\n * - Web Bot Auth (generic transport substrate) — kid resolves via\n * /.well-known/http-message-signatures-directory\n */\n\nimport { parseDictionary } from 'structured-headers';\n\nexport interface RFC9421SignatureParams {\n /** The label identifying the signature in the Dictionary header (e.g. \"sig1\"). */\n label: string;\n /** Key ID used to look up the verifying key in the relevant registry. */\n kid: string;\n /** Algorithm declared in the Signature-Input params (e.g. \"ecdsa-p256-sha256\", \"ed25519\"). */\n alg?: string;\n /** Covered components, in order, per RFC 9421 Section 2.1. */\n covered: string[];\n /** Base64url-encoded signature bytes extracted from the paired Signature header. */\n signatureBase64: string;\n /** Unix seconds when the signature was created. */\n created?: number;\n /** Unix seconds when the signature expires. */\n expires?: number;\n /** Nonce (opaque string) for replay protection. */\n nonce?: string;\n /** Tag parameter. For Agent Pay/TAP this is \"browse\" or \"purchase\"; undefined otherwise. */\n tag?: 'browse' | 'purchase' | string;\n}\n\nexport interface ParsedRFC9421 {\n signatures: RFC9421SignatureParams[];\n}\n\n/**\n * Parse the RFC 9421 Signature-Input and Signature headers from a request or response.\n * Returns all signatures present (a single message may carry multiple labelled signatures).\n *\n * Returns null if either header is missing or malformed.\n */\nexport function parseRFC9421(\n headers: Record<string, string | string[] | undefined>\n): ParsedRFC9421 | null {\n const sigInput = readHeader(headers, 'signature-input');\n const sig = readHeader(headers, 'signature');\n if (!sigInput || !sig) return null;\n\n let inputDict;\n let sigDict;\n try {\n inputDict = parseDictionary(sigInput);\n sigDict = parseDictionary(sig);\n } catch {\n return null;\n }\n\n const signatures: RFC9421SignatureParams[] = [];\n\n for (const [label, entry] of inputDict) {\n // entry.value is the inner list of covered components; entry[1] is the params Map.\n const innerList = Array.isArray(entry)\n ? entry[0]\n : (entry as { value?: unknown; params?: unknown }).value;\n const params = Array.isArray(entry)\n ? entry[1]\n : (entry as { value?: unknown; params?: unknown }).params;\n if (!Array.isArray(innerList) || !params) continue;\n\n const covered: string[] = [];\n for (const item of innerList as Array<[unknown, Map<string, unknown>]>) {\n const [bare] = Array.isArray(item) ? item : [item];\n if (typeof bare === 'string') covered.push(bare);\n else if (bare && typeof bare === 'object' && 'toString' in bare) covered.push(String(bare));\n }\n\n const paramsMap = params as Map<string, unknown>;\n const kid = coerceString(paramsMap.get('keyid'));\n if (!kid) continue;\n\n const sigEntry = sigDict.get(label);\n if (!sigEntry) continue;\n\n const sigBare = Array.isArray(sigEntry) ? sigEntry[0] : (sigEntry as { value?: unknown }).value;\n const signatureBase64 = extractBase64(sigBare);\n if (!signatureBase64) continue;\n\n signatures.push({\n label,\n kid,\n alg: coerceString(paramsMap.get('alg')),\n covered,\n signatureBase64,\n created: coerceNumber(paramsMap.get('created')),\n expires: coerceNumber(paramsMap.get('expires')),\n nonce: coerceString(paramsMap.get('nonce')),\n tag: coerceString(paramsMap.get('tag')),\n });\n }\n\n if (signatures.length === 0) return null;\n return { signatures };\n}\n\nfunction readHeader(\n headers: Record<string, string | string[] | undefined>,\n name: string\n): string | null {\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === name) {\n const raw = headers[key];\n if (typeof raw === 'string') return raw;\n if (Array.isArray(raw)) return raw.join(', ');\n return null;\n }\n }\n return null;\n}\n\nfunction coerceString(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (value == null) return undefined;\n if (typeof value === 'object' && 'toString' in (value as object)) {\n const s = String(value);\n return s.length > 0 ? s : undefined;\n }\n return undefined;\n}\n\nfunction coerceNumber(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'bigint') return Number(value);\n return undefined;\n}\n\nfunction extractBase64(value: unknown): string | null {\n if (value instanceof Uint8Array) return bufferToBase64(value);\n if (value instanceof ArrayBuffer) return bufferToBase64(new Uint8Array(value));\n if (ArrayBuffer.isView(value)) {\n const v = value as ArrayBufferView;\n return bufferToBase64(new Uint8Array(v.buffer, v.byteOffset, v.byteLength));\n }\n if (typeof value === 'string') {\n if (value.startsWith(':') && value.endsWith(':')) return value.slice(1, -1);\n return value;\n }\n return null;\n}\n\nfunction bufferToBase64(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString('base64');\n}\n","/**\n * RFC 9421 HTTP Message Signatures verification.\n *\n * Wraps http-message-signatures (dhensby) verifyMessage() with a RegistryResolver\n * hook for kid → JWK lookup. Library handles canonicalization + ES256/EdDSA/\n * HMAC/RSA verification; we supply the key-finding callback and policy around\n * clock skew.\n *\n * Shared by:\n * - Agent Pay (Mastercard) — resolver = createMastercardRegistry\n * - TAP (Visa) — resolver = createVisaRegistry\n * - Web Bot Auth (generic) — resolver = createWebBotAuthRegistry\n */\n\nimport { httpbis, type VerifierFinder, type VerifyingKey } from 'http-message-signatures';\nimport type { JWK } from 'jose';\nimport type { RegistryResolver } from './registry/types';\nimport { defaultNonceStore, type NonceStore } from './nonce-store';\n\nexport interface RFC9421VerifyRequest {\n method: string;\n url: string;\n headers: Record<string, string | string[]>;\n body?: string;\n}\n\nexport interface RFC9421VerifyOptions {\n resolver: RegistryResolver;\n /** Seconds of tolerance around created/expires. Default 60 (tightened from 300). */\n clockSkewSec?: number;\n /** Injectable for deterministic tests. */\n now?: () => number;\n /** Optional replay-protection store. Defaults to in-process LRU. */\n nonceStore?: NonceStore;\n}\n\nexport interface RFC9421VerifyResult {\n ok: boolean;\n kid?: string;\n registry?: RegistryResolver['name'];\n algorithm?: string;\n error?: string;\n}\n\nexport async function verifyRFC9421(\n request: RFC9421VerifyRequest,\n options: RFC9421VerifyOptions\n): Promise<RFC9421VerifyResult> {\n const { resolver } = options;\n const tolerance = options.clockSkewSec ?? 60;\n const nowSec = options.now ? options.now() : Math.floor(Date.now() / 1000);\n const nonceStore = options.nonceStore ?? defaultNonceStore;\n\n let resolvedKid: string | undefined;\n let resolvedAlg: string | undefined;\n let replayDetected = false;\n\n const keyLookup: VerifierFinder = async (parameters) => {\n const kid = typeof parameters.keyid === 'string' ? parameters.keyid : undefined;\n if (!kid) return null;\n resolvedKid = kid;\n const alg = typeof parameters.alg === 'string' ? parameters.alg : undefined;\n if (alg) resolvedAlg = alg;\n\n const origin = safeOrigin(request.url);\n const jwk = await resolver.resolve(kid, { origin, algorithm: alg });\n if (!jwk) return null;\n\n // Check clock-skew on this specific signature's created/expires.\n // SignatureParameters may carry Date, number, or ISO string per library.\n const created = toUnixSeconds(parameters.created);\n const expires = toUnixSeconds(parameters.expires);\n if (created !== undefined && Math.abs(nowSec - created) > tolerance) return null;\n if (expires !== undefined && nowSec > expires + tolerance) return null;\n\n // Audit F-A1-05: replay protection. RFC 9421 signatures include a\n // `nonce` parameter (optional but recommended for replay-sensitive\n // contexts). When present, register kid+nonce; reject duplicates\n // within the expiry window.\n const nonce = typeof parameters.nonce === 'string' ? parameters.nonce : undefined;\n if (nonce) {\n const expiresAtMs = (expires !== undefined ? expires + tolerance : nowSec + tolerance) * 1000;\n if (nonceStore.seen(`rfc9421:${kid}:${nonce}`, expiresAtMs)) {\n replayDetected = true;\n return null;\n }\n }\n\n return jwkToVerifyingKey(kid, jwk, alg);\n };\n\n try {\n const result = await httpbis.verifyMessage(\n {\n keyLookup,\n },\n normalizeRequest(request)\n );\n if (result === true) {\n return {\n ok: true,\n kid: resolvedKid,\n registry: resolver.name,\n algorithm: resolvedAlg,\n };\n }\n return {\n ok: false,\n kid: resolvedKid,\n registry: resolver.name,\n algorithm: resolvedAlg,\n error: replayDetected\n ? 'RFC9421 signature replay — already seen within tolerance window'\n : result === false\n ? 'signature invalid'\n : 'no signature found',\n };\n } catch (err) {\n return {\n ok: false,\n kid: resolvedKid,\n registry: resolver.name,\n algorithm: resolvedAlg,\n error: err instanceof Error ? err.message : 'verification error',\n };\n }\n}\n\nfunction normalizeRequest(request: RFC9421VerifyRequest): {\n method: string;\n url: string;\n headers: Record<string, string | string[]>;\n} {\n return {\n method: request.method.toUpperCase(),\n url: request.url,\n headers: request.headers,\n };\n}\n\nfunction safeOrigin(url: string): string | undefined {\n try {\n return new URL(url).origin;\n } catch {\n return undefined;\n }\n}\n\nasync function jwkToVerifyingKey(\n id: string,\n jwk: JWK,\n alg: string | undefined\n): Promise<VerifyingKey> {\n const algorithm = alg ?? inferAlgFromJwk(jwk);\n const { subtle } = await getCrypto();\n const importAlg = webCryptoImportAlgFor(algorithm);\n const verifyAlg = webCryptoAlgFor(algorithm);\n if (!importAlg || !verifyAlg) {\n return {\n id,\n algs: alg ? [alg] : undefined,\n verify: async () => false,\n };\n }\n const key = await subtle.importKey('jwk', jwk as JsonWebKey, importAlg, false, ['verify']);\n\n return {\n id,\n algs: alg ? [alg] : undefined,\n verify: async (data: Buffer, signature: Buffer): Promise<boolean> => {\n try {\n return await subtle.verify(verifyAlg, key, toArrayBuffer(signature), toArrayBuffer(data));\n } catch {\n return false;\n }\n },\n };\n}\n\nfunction inferAlgFromJwk(jwk: JWK): string {\n if (jwk.kty === 'OKP' && jwk.crv === 'Ed25519') return 'ed25519';\n if (jwk.kty === 'EC' && jwk.crv === 'P-256') return 'ecdsa-p256-sha256';\n if (jwk.kty === 'EC' && jwk.crv === 'P-384') return 'ecdsa-p384-sha384';\n if (jwk.kty === 'RSA') return 'rsa-v1_5-sha256';\n return 'ecdsa-p256-sha256';\n}\n\nfunction webCryptoAlgFor(\n rfc9421Alg: string\n): AlgorithmIdentifier | EcdsaParams | RsaPssParams | null {\n switch (rfc9421Alg) {\n case 'ed25519':\n return { name: 'Ed25519' };\n case 'ecdsa-p256-sha256':\n return { name: 'ECDSA', hash: 'SHA-256' };\n case 'ecdsa-p384-sha384':\n return { name: 'ECDSA', hash: 'SHA-384' };\n case 'rsa-v1_5-sha256':\n return { name: 'RSASSA-PKCS1-v1_5' };\n case 'rsa-pss-sha512':\n return { name: 'RSA-PSS', saltLength: 64 };\n default:\n return null;\n }\n}\n\nfunction webCryptoImportAlgFor(\n rfc9421Alg: string\n): AlgorithmIdentifier | EcKeyImportParams | RsaHashedImportParams | null {\n switch (rfc9421Alg) {\n case 'ed25519':\n return { name: 'Ed25519' };\n case 'ecdsa-p256-sha256':\n return { name: 'ECDSA', namedCurve: 'P-256' };\n case 'ecdsa-p384-sha384':\n return { name: 'ECDSA', namedCurve: 'P-384' };\n case 'rsa-v1_5-sha256':\n return { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' };\n case 'rsa-pss-sha512':\n return { name: 'RSA-PSS', hash: 'SHA-512' };\n default:\n return null;\n }\n}\n\nfunction toArrayBuffer(buf: Buffer): ArrayBuffer {\n const out = new ArrayBuffer(buf.byteLength);\n new Uint8Array(out).set(buf);\n return out;\n}\n\nfunction toUnixSeconds(v: unknown): number | undefined {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n if (v instanceof Date) return Math.floor(v.getTime() / 1000);\n if (typeof v === 'string') {\n const parsed = Date.parse(v);\n if (Number.isFinite(parsed)) return Math.floor(parsed / 1000);\n }\n return undefined;\n}\n\nasync function getCrypto(): Promise<{ subtle: SubtleCrypto }> {\n if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.subtle) {\n return { subtle: globalThis.crypto.subtle };\n }\n // Node fallback\n const nodeCrypto = await import('node:crypto');\n return { subtle: nodeCrypto.webcrypto.subtle as SubtleCrypto };\n}\n","/**\n * Shared nonce/signature replay-protection store for transport verifiers.\n *\n * Rationale: every transport-signature verifier (RFC9421, VI, AP2, ACP,\n * MPP) validates a created/expires window, but without a seen-nonce\n * cache any captured signed request can be replayed within the (default\n * 300s, now tightened to 60s) tolerance window.\n *\n * This module ships a bounded in-memory LRU as the default. Production\n * deployments with multi-pod horizontal scaling SHOULD pass a shared store\n * (Redis-backed) via the verifier options to make replay protection global\n * rather than per-pod.\n *\n * The store interface is intentionally minimal: a single `seen(key,\n * expiresAt)` method that returns true iff the key was already recorded\n * (i.e. caller should reject as a replay). Callers compose the key from\n * whichever identifiers are unique to the signature (kid + nonce + sig\n * digest, typically).\n */\n\nexport interface NonceStore {\n /**\n * Record `key` as seen. Returns true iff the key was ALREADY present —\n * i.e. caller should reject the request as a replay. Returns false on\n * first sighting (caller should proceed).\n *\n * `expiresAtMs` is a hint for the store to evict entries that can no\n * longer cause harm (their signature window has elapsed).\n */\n seen(key: string, expiresAtMs: number): boolean;\n}\n\n/**\n * Default in-memory LRU. Per-process, lost on restart. Suitable for\n * single-pod deploys and for development; production multi-pod deploys\n * should pass a shared store.\n *\n * Capacity-bounded: once the limit is reached, the oldest entry is dropped\n * even if it hasn't yet expired. The limit (default 10k entries) is large\n * enough that meaningful replay windows shouldn't approach it; if a\n * deployment is hitting it, that's a signal to migrate to Redis.\n *\n * Also runs a lazy sweep on each `seen` call to evict entries past their\n * `expiresAtMs` — keeps memory bounded under burst load.\n */\nexport class InMemoryNonceStore implements NonceStore {\n private readonly entries = new Map<string, number>();\n private readonly capacity: number;\n private lastSweepMs = 0;\n\n constructor(capacity = 10_000) {\n this.capacity = capacity;\n }\n\n seen(key: string, expiresAtMs: number): boolean {\n const nowMs = Date.now();\n\n // Lazy sweep: at most once per second, walk expired entries.\n if (nowMs - this.lastSweepMs > 1000) {\n for (const [k, exp] of this.entries) {\n if (exp <= nowMs) this.entries.delete(k);\n }\n this.lastSweepMs = nowMs;\n }\n\n const existing = this.entries.get(key);\n if (existing !== undefined && existing > nowMs) {\n return true; // replay\n }\n\n // First sighting (or stale entry) — record + evict oldest if over capacity.\n if (this.entries.size >= this.capacity) {\n const oldest = this.entries.keys().next().value;\n if (oldest !== undefined) this.entries.delete(oldest);\n }\n this.entries.set(key, expiresAtMs);\n return false;\n }\n}\n\n/**\n * Process-wide singleton instance for convenience. Verifiers that don't\n * receive an explicit nonceStore in their options fall back to this.\n *\n * Memory-bounded at 10k entries by default; sufficient for a single pod\n * handling thousands of requests/sec where signatures only carry value\n * within their (60s default) expiry window.\n */\nexport const defaultNonceStore = new InMemoryNonceStore();\n","/**\n * VI (Verifiable Intent) SD-JWT extraction.\n *\n * Open-sourced 5 March 2026 by Mastercard + Google (v0.1-draft).\n * VI is a 3-layer SD-JWT chain:\n * L1 — issuer → wallet (credential provider)\n * L2 — user → agent (cnf.jwk binding to L3 agent key)\n * L3 — agent → merchant (payment or checkout mandate, split into L3a / L3b\n * cross-referenced via transaction_id)\n *\n * This module does EXTRACTION ONLY — it decodes SD-JWT structure and pulls\n * out the mandate type, kid, executionMode, 8 constraint types, checkoutHash\n * (constraint type 8), transactionId, and raw layers for later verification.\n *\n * Signature verification lives in vi-verify.ts; this module uses @sd-jwt's\n * sync decoder with a SHA-256 hasher for structural parsing only.\n */\n\nimport { splitSdJwt, decodeSdJwtSync } from '@sd-jwt/core';\nimport { createHash } from 'node:crypto';\nimport type { VIMandateType } from './purpose-mapping';\n\nexport type { VIMandateType };\nexport type VIExecutionMode = 'Immediate' | 'Autonomous' | 'Both';\n\nexport interface VIAllowedParty {\n id?: string;\n name?: string;\n website?: string;\n}\n\nexport interface VILineItem {\n id?: string;\n acceptableItems?: string[];\n quantity?: number;\n}\n\nexport interface VIPaymentAmount {\n currency?: string;\n min?: number;\n max?: number;\n}\n\nexport interface VIBudgetLimit {\n currency?: string;\n max?: number;\n}\n\nexport interface VIRecurrence {\n frequency?: string;\n startDate?: string;\n endDate?: string;\n maxOccurrences?: number;\n}\n\nexport interface VIConstraints {\n allowedMerchants?: VIAllowedParty[];\n allowedPayees?: VIAllowedParty[];\n lineItems?: VILineItem[];\n paymentAmount?: VIPaymentAmount;\n budgetLimit?: VIBudgetLimit;\n recurrence?: VIRecurrence;\n agentRecurrence?: VIRecurrence;\n}\n\nexport interface VIExtractedClaims {\n mandateType: VIMandateType;\n kid?: string;\n executionMode?: VIExecutionMode;\n credentialProvider?: string;\n constraints: VIConstraints;\n /** VI constraint type 8 — SHA-256 of the paired L2 checkout disclosure. */\n checkoutHash?: string;\n transactionId?: string;\n rawLayers: { l1?: string; l2?: string; l3?: string };\n}\n\n/**\n * Extract VI claims from a compact SD-JWT string.\n *\n * Input shape:\n * <jwt>~<disclosure1>~<disclosure2>~...~<kbJwt?>\n *\n * Returns null if parsing fails at any layer. Does not verify signatures.\n */\nexport function extractVIClaims(sdJwtCompact: string): VIExtractedClaims | null {\n if (!sdJwtCompact || typeof sdJwtCompact !== 'string') return null;\n\n let decoded;\n try {\n decoded = decodeSdJwtSync(sdJwtCompact, sha256Sync);\n } catch {\n return null;\n }\n\n const split = safeSplit(sdJwtCompact);\n\n const payload = (decoded.jwt?.payload ?? {}) as Record<string, unknown>;\n const disclosures = decoded.disclosures ?? [];\n\n // Apply disclosures onto payload to resolve _sd references.\n // Disclosure from @sd-jwt/core has { key, value, digest() } where digest is\n // a function — we only need key+value here, so narrow via a structural cast.\n const claims = applyDisclosures(\n payload,\n disclosures as unknown as Array<{ key?: string; value?: unknown }>\n );\n\n const mandateType = coerceMandateType(\n claims.mandate_type ?? claims.mandateType ?? payload.mandate_type ?? payload.mandateType\n );\n if (!mandateType) return null;\n\n const kid = coerceString(\n (decoded.jwt?.header as Record<string, unknown> | undefined)?.kid ?? claims.kid ?? payload.kid\n );\n\n const executionMode = coerceExecutionMode(claims.execution_mode ?? claims.executionMode);\n const credentialProvider = coerceString(claims.iss ?? payload.iss);\n\n const constraints = extractConstraints(\n (claims.constraints ?? claims.default_constraints ?? {}) as Record<string, unknown>\n );\n\n const transactionId = coerceString(claims.transaction_id ?? claims.transactionId);\n const checkoutHash = coerceString(\n claims.checkout_hash ??\n claims.conditional_transaction_id ??\n (claims.payment_reference as Record<string, unknown> | undefined)?.checkout_hash\n );\n\n return {\n mandateType,\n kid,\n executionMode,\n credentialProvider,\n constraints,\n checkoutHash,\n transactionId,\n rawLayers: split,\n };\n}\n\nfunction safeSplit(compact: string): { l1?: string; l2?: string; l3?: string } {\n try {\n const { jwt, kbJwt } = splitSdJwt(compact);\n // VI layering maps loosely: the outer JWT is L3 (agent mandate), KB-JWT\n // (if present) is the key-binding proof, and disclosures carry L2/L1 fragments.\n return { l3: jwt, l2: kbJwt };\n } catch {\n return {};\n }\n}\n\nfunction applyDisclosures(\n payload: Record<string, unknown>,\n disclosures: Array<{ key?: string; value?: unknown }>\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...payload };\n for (const d of disclosures) {\n if (d.key && d.value !== undefined && !(d.key in result)) {\n result[d.key] = d.value;\n }\n }\n return result;\n}\n\nfunction extractConstraints(raw: Record<string, unknown>): VIConstraints {\n return {\n allowedMerchants: toAllowedPartyArray(raw.allowed_merchants ?? raw.allowedMerchants),\n allowedPayees: toAllowedPartyArray(raw.allowed_payees ?? raw.allowedPayees),\n lineItems: toLineItemArray(raw.line_items ?? raw.lineItems),\n paymentAmount: toPaymentAmount(raw.payment_amount ?? raw.paymentAmount),\n budgetLimit: toBudgetLimit(raw.budget_limit ?? raw.budgetLimit ?? raw.budget),\n recurrence: toRecurrence(raw.recurrence),\n agentRecurrence: toRecurrence(raw.agent_recurrence ?? raw.agentRecurrence),\n };\n}\n\nfunction toAllowedPartyArray(v: unknown): VIAllowedParty[] | undefined {\n if (!Array.isArray(v)) return undefined;\n const out: VIAllowedParty[] = [];\n for (const item of v) {\n if (item && typeof item === 'object') {\n const r = item as Record<string, unknown>;\n out.push({\n id: coerceString(r.id),\n name: coerceString(r.name),\n website: coerceString(r.website),\n });\n }\n }\n return out.length > 0 ? out : undefined;\n}\n\nfunction toLineItemArray(v: unknown): VILineItem[] | undefined {\n if (!Array.isArray(v)) return undefined;\n const out: VILineItem[] = [];\n for (const item of v) {\n if (item && typeof item === 'object') {\n const r = item as Record<string, unknown>;\n const acc = r.acceptable_items ?? r.acceptableItems;\n out.push({\n id: coerceString(r.id),\n acceptableItems: Array.isArray(acc)\n ? (acc.filter((a) => typeof a === 'string') as string[])\n : undefined,\n quantity: coerceNumber(r.quantity),\n });\n }\n }\n return out.length > 0 ? out : undefined;\n}\n\nfunction toPaymentAmount(v: unknown): VIPaymentAmount | undefined {\n if (!v || typeof v !== 'object') return undefined;\n const r = v as Record<string, unknown>;\n return {\n currency: coerceString(r.currency),\n min: coerceNumber(r.min),\n max: coerceNumber(r.max),\n };\n}\n\nfunction toBudgetLimit(v: unknown): VIBudgetLimit | undefined {\n if (!v || typeof v !== 'object') return undefined;\n const r = v as Record<string, unknown>;\n return {\n currency: coerceString(r.currency),\n max: coerceNumber(r.max),\n };\n}\n\nfunction toRecurrence(v: unknown): VIRecurrence | undefined {\n if (!v || typeof v !== 'object') return undefined;\n const r = v as Record<string, unknown>;\n return {\n frequency: coerceString(r.frequency),\n startDate: coerceString(r.start_date ?? r.startDate),\n endDate: coerceString(r.end_date ?? r.endDate),\n maxOccurrences: coerceNumber(r.max_occurrences ?? r.maxOccurrences),\n };\n}\n\nfunction coerceMandateType(v: unknown): VIMandateType | null {\n if (v === 'checkout' || v === 'payment' || v === 'checkout.open' || v === 'payment.open') {\n return v;\n }\n return null;\n}\n\nfunction coerceExecutionMode(v: unknown): VIExecutionMode | undefined {\n return v === 'Immediate' || v === 'Autonomous' || v === 'Both' ? v : undefined;\n}\n\nfunction coerceString(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n}\n\nfunction coerceNumber(v: unknown): number | undefined {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n if (typeof v === 'string') {\n const n = Number(v);\n return Number.isFinite(n) ? n : undefined;\n }\n return undefined;\n}\n\nfunction sha256Sync(data: string | ArrayBuffer): Uint8Array {\n const buf =\n typeof data === 'string' ? Buffer.from(data, 'utf-8') : Buffer.from(new Uint8Array(data));\n const hash = createHash('sha256').update(buf).digest();\n return new Uint8Array(hash.buffer, hash.byteOffset, hash.byteLength);\n}\n","/**\n * Stripe webhook HMAC-SHA256 verifier (inline).\n *\n * Stripe-Signature header format: \"t=TIMESTAMP,v1=HEX_SIGNATURE\"\n * - t: unix seconds when Stripe signed the webhook\n * - v1: HMAC-SHA256(webhook_secret, `${t}.${payload}`) as hex\n *\n * Multiple v1 signatures can coexist during secret rotation; any match wins.\n * Default tolerance on timestamp age: 300s (matches Stripe's own default).\n *\n * Documented at docs.stripe.com — we intentionally inline ~25 LOC rather\n * than pull in the full stripe npm package (MIT but 600KB+ with deps).\n */\n\nimport { createHmac, timingSafeEqual } from 'node:crypto';\n\nexport interface VerifyStripeWebhookResult {\n ok: boolean;\n timestamp?: number;\n error?: string;\n}\n\nexport interface VerifyStripeWebhookOptions {\n toleranceSec?: number;\n /** Injectable for deterministic tests. */\n now?: () => number;\n}\n\nexport function verifyStripeWebhook(\n payload: string,\n signatureHeader: string | undefined,\n secret: string,\n options: VerifyStripeWebhookOptions = {}\n): VerifyStripeWebhookResult {\n if (!signatureHeader) return { ok: false, error: 'missing Stripe-Signature header' };\n if (!secret) return { ok: false, error: 'missing webhook secret' };\n\n const parsed = parseStripeSignature(signatureHeader);\n if (!parsed.timestamp) return { ok: false, error: 'malformed Stripe-Signature (missing t=)' };\n if (parsed.v1Signatures.length === 0) {\n return { ok: false, error: 'malformed Stripe-Signature (no v1=)' };\n }\n\n const tolerance = options.toleranceSec ?? 300;\n const now = options.now ? options.now() : Math.floor(Date.now() / 1000);\n if (Math.abs(now - parsed.timestamp) > tolerance) {\n return {\n ok: false,\n timestamp: parsed.timestamp,\n error: `timestamp outside tolerance (${tolerance}s)`,\n };\n }\n\n const signedPayload = `${parsed.timestamp}.${payload}`;\n const expected = createHmac('sha256', secret).update(signedPayload).digest();\n\n for (const candidateHex of parsed.v1Signatures) {\n const candidate = hexToBuffer(candidateHex);\n if (!candidate) continue;\n if (candidate.length !== expected.length) continue;\n if (timingSafeEqual(candidate, expected)) {\n return { ok: true, timestamp: parsed.timestamp };\n }\n }\n\n return { ok: false, timestamp: parsed.timestamp, error: 'signature mismatch' };\n}\n\ninterface ParsedStripeSignature {\n timestamp: number | null;\n v1Signatures: string[];\n}\n\nfunction parseStripeSignature(header: string): ParsedStripeSignature {\n let timestamp: number | null = null;\n const v1Signatures: string[] = [];\n for (const part of header.split(',')) {\n const [rawKey, rawValue] = part.split('=');\n if (!rawKey || !rawValue) continue;\n const key = rawKey.trim();\n const value = rawValue.trim();\n if (key === 't') {\n const n = Number(value);\n if (Number.isFinite(n)) timestamp = n;\n } else if (key === 'v1') {\n v1Signatures.push(value);\n }\n }\n return { timestamp, v1Signatures };\n}\n\nfunction hexToBuffer(hex: string): Buffer | null {\n if (!/^[0-9a-fA-F]+$/.test(hex) || hex.length % 2 !== 0) return null;\n return Buffer.from(hex, 'hex');\n}\n","/**\n * AP2 (Agent Payments Protocol) mandate extraction.\n *\n * Google-led, launched 3 April 2026 with 60+ partners (Mastercard, PayPal,\n * Coinbase, AmEx, Revolut, UnionPay, ...). AP2 ships three mandate types as\n * SD-JWTs in series:\n * - intent_mandate — user declares intent (amount, merchant category, etc.)\n * - cart_mandate — user approves a cart (specific items, totals)\n * - payment_mandate — authorizes the actual payment rail\n *\n * Mandates are cross-referenced via ids; each is an SD-JWT over ES256 (or\n * equivalent). We decode via @sd-jwt/core and extract the AP2-specific\n * shape — verification lives in ap2-verify.ts.\n */\n\nimport { decodeSdJwtSync } from '@sd-jwt/core';\nimport { createHash } from 'node:crypto';\nimport type { AP2MandateType } from './purpose-mapping';\n\nexport type { AP2MandateType };\n\nexport interface AP2PaymentDetailsTotal {\n amount?: { value?: string | number; currency?: string };\n label?: string;\n}\n\nexport interface AP2IntentMandateClaims {\n type: 'intent_mandate';\n agent_id?: string;\n user_id?: string;\n merchant_category?: string;\n allowedMerchantDomains?: string[];\n paymentMethods?: string[];\n expires?: string;\n payment_details_total?: AP2PaymentDetailsTotal;\n raw: Record<string, unknown>;\n}\n\nexport interface AP2CartMandateClaims {\n type: 'cart_mandate';\n agent_id?: string;\n intent_mandate_id?: string;\n merchant_id?: string;\n line_items?: Array<{\n id?: string;\n quantity?: number;\n price?: { value?: string | number; currency?: string };\n }>;\n payment_details_total?: AP2PaymentDetailsTotal;\n expires?: string;\n raw: Record<string, unknown>;\n}\n\nexport interface AP2PaymentMandateClaims {\n type: 'payment_mandate';\n agent_id?: string;\n cart_mandate_id?: string;\n payment_method?: string;\n payment_details_total?: AP2PaymentDetailsTotal;\n credential_provider?: string;\n raw: Record<string, unknown>;\n}\n\nexport type AP2MandateClaims =\n | AP2IntentMandateClaims\n | AP2CartMandateClaims\n | AP2PaymentMandateClaims;\n\nexport interface AP2MandateTriple {\n intent?: AP2IntentMandateClaims;\n cart?: AP2CartMandateClaims;\n payment?: AP2PaymentMandateClaims;\n rawLayers: { intentJwt?: string; cartJwt?: string; paymentJwt?: string };\n}\n\n/**\n * Extract a single AP2 mandate from a compact SD-JWT.\n * Returns null if the SD-JWT is malformed or lacks a recognized type field.\n */\nexport function extractAP2Mandate(sdJwtCompact: string): AP2MandateClaims | null {\n if (!sdJwtCompact || typeof sdJwtCompact !== 'string') return null;\n\n let decoded;\n try {\n decoded = decodeSdJwtSync(sdJwtCompact, sha256Sync);\n } catch {\n return null;\n }\n\n const payload = (decoded.jwt?.payload ?? {}) as Record<string, unknown>;\n const disclosures = decoded.disclosures ?? [];\n const claims = applyDisclosures(\n payload,\n disclosures as unknown as Array<{ key?: string; value?: unknown }>\n );\n\n const type = coerceMandateType(claims.type ?? claims.mandate_type ?? claims.mandateType);\n if (!type) return null;\n\n if (type === 'intent_mandate') return buildIntent(claims);\n if (type === 'cart_mandate') return buildCart(claims);\n return buildPayment(claims);\n}\n\nexport interface AP2MandateTripleInput {\n intent?: string;\n cart?: string;\n payment?: string;\n}\n\n/**\n * Extract an intent / cart / payment triple, returning whichever are present.\n * Does NOT enforce cross-reference consistency — that's ap2-verify.ts's job.\n */\nexport function extractAP2Mandates(input: AP2MandateTripleInput): AP2MandateTriple {\n const intent = input.intent\n ? (extractAP2Mandate(input.intent) as AP2IntentMandateClaims | null)\n : null;\n const cart = input.cart ? (extractAP2Mandate(input.cart) as AP2CartMandateClaims | null) : null;\n const payment = input.payment\n ? (extractAP2Mandate(input.payment) as AP2PaymentMandateClaims | null)\n : null;\n return {\n intent: intent ?? undefined,\n cart: cart ?? undefined,\n payment: payment ?? undefined,\n rawLayers: {\n intentJwt: input.intent,\n cartJwt: input.cart,\n paymentJwt: input.payment,\n },\n };\n}\n\nfunction buildIntent(claims: Record<string, unknown>): AP2IntentMandateClaims {\n return {\n type: 'intent_mandate',\n agent_id: coerceString(claims.agent_id ?? claims.agentId),\n user_id: coerceString(claims.user_id ?? claims.userId ?? claims.sub),\n merchant_category: coerceString(claims.merchant_category ?? claims.merchantCategory),\n allowedMerchantDomains: toStringArray(\n claims.allowed_merchant_domains ?? claims.allowedMerchantDomains\n ),\n paymentMethods: toStringArray(claims.payment_methods ?? claims.paymentMethods),\n expires: coerceString(claims.expires ?? claims.exp),\n payment_details_total: toPaymentDetails(claims.payment_details_total ?? claims.total),\n raw: claims,\n };\n}\n\nfunction buildCart(claims: Record<string, unknown>): AP2CartMandateClaims {\n return {\n type: 'cart_mandate',\n agent_id: coerceString(claims.agent_id ?? claims.agentId),\n intent_mandate_id: coerceString(claims.intent_mandate_id ?? claims.intentMandateId),\n merchant_id: coerceString(claims.merchant_id ?? claims.merchantId),\n line_items: toLineItems(claims.line_items ?? claims.lineItems),\n payment_details_total: toPaymentDetails(claims.payment_details_total ?? claims.total),\n expires: coerceString(claims.expires ?? claims.exp),\n raw: claims,\n };\n}\n\nfunction buildPayment(claims: Record<string, unknown>): AP2PaymentMandateClaims {\n return {\n type: 'payment_mandate',\n agent_id: coerceString(claims.agent_id ?? claims.agentId),\n cart_mandate_id: coerceString(claims.cart_mandate_id ?? claims.cartMandateId),\n payment_method: coerceString(claims.payment_method ?? claims.paymentMethod),\n payment_details_total: toPaymentDetails(claims.payment_details_total ?? claims.total),\n credential_provider: coerceString(claims.credential_provider ?? claims.credentialProvider),\n raw: claims,\n };\n}\n\nfunction toPaymentDetails(v: unknown): AP2PaymentDetailsTotal | undefined {\n if (!v || typeof v !== 'object') return undefined;\n const r = v as Record<string, unknown>;\n const amount = r.amount as Record<string, unknown> | undefined;\n return {\n amount: amount\n ? {\n value: coerceStringOrNumber(amount.value),\n currency: coerceString(amount.currency),\n }\n : undefined,\n label: coerceString(r.label),\n };\n}\n\nfunction toLineItems(v: unknown): AP2CartMandateClaims['line_items'] {\n if (!Array.isArray(v)) return undefined;\n const items: NonNullable<AP2CartMandateClaims['line_items']> = [];\n for (const item of v) {\n if (!item || typeof item !== 'object') continue;\n const r = item as Record<string, unknown>;\n const price = r.price as Record<string, unknown> | undefined;\n items.push({\n id: coerceString(r.id),\n quantity: coerceNumber(r.quantity),\n price: price\n ? {\n value: coerceStringOrNumber(price.value),\n currency: coerceString(price.currency),\n }\n : undefined,\n });\n }\n return items.length > 0 ? items : undefined;\n}\n\nfunction toStringArray(v: unknown): string[] | undefined {\n if (!Array.isArray(v)) return undefined;\n const out = v.filter((i): i is string => typeof i === 'string' && i.length > 0);\n return out.length > 0 ? out : undefined;\n}\n\nfunction applyDisclosures(\n payload: Record<string, unknown>,\n disclosures: Array<{ key?: string; value?: unknown }>\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...payload };\n for (const d of disclosures) {\n if (d.key && d.value !== undefined && !(d.key in result)) {\n result[d.key] = d.value;\n }\n }\n return result;\n}\n\nfunction coerceMandateType(v: unknown): AP2MandateType | null {\n if (v === 'intent_mandate' || v === 'cart_mandate' || v === 'payment_mandate') return v;\n return null;\n}\n\nfunction coerceString(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n}\n\nfunction coerceNumber(v: unknown): number | undefined {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n if (typeof v === 'string') {\n const n = Number(v);\n return Number.isFinite(n) ? n : undefined;\n }\n return undefined;\n}\n\nfunction coerceStringOrNumber(v: unknown): string | number | undefined {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n if (typeof v === 'string' && v.length > 0) return v;\n return undefined;\n}\n\nfunction sha256Sync(data: string | ArrayBuffer): Uint8Array {\n const buf =\n typeof data === 'string' ? Buffer.from(data, 'utf-8') : Buffer.from(new Uint8Array(data));\n const hash = createHash('sha256').update(buf).digest();\n return new Uint8Array(hash.buffer, hash.byteOffset, hash.byteLength);\n}\n","/**\n * MPP (Machine Payments Protocol) extractor.\n *\n * Wraps mppx (wevm) — pinned to 0.5.13, wrapped behind this adapter so\n * upgrades localise here. MPP launched March 18 2026 (Stripe + Tempo +\n * Paradigm), IETF draft-ryan-httpauth-payment-01.\n *\n * Flow:\n * Client → GET /resource\n * Server → 402 + WWW-Authenticate: Payment id=..., realm=..., method=tempo|stripe|...\n * Client → GET /resource with Authorization: Payment <base64url-json credential>\n * Server → 200 + Payment-Receipt: <base64url-json receipt>\n *\n * What we extract:\n * - Challenge: id, realm, method, intent, request{amount,currency,...}, expires, digest\n * - Credential: challenge + source (DID/chain-key) + payload (method-specific)\n * - Receipt: challengeId, method, reference (tx hash / pi_... ID), settlement\n * - Multi-method 402 offers (may be multiple WWW-Authenticate headers)\n *\n * What we do NOT verify here (pass-through):\n * - HMAC challenge binding (requires merchant's MPP_SECRET_KEY)\n * - Payment proof cryptography (Tempo tx sig, Stripe SPT, Lightning preimage)\n * — each requires upstream connectivity\n *\n * Verification (expiry + BodyDigest + source extraction) in mpp-verify.ts.\n */\n\nimport { Challenge, Credential, Receipt } from 'mppx';\n\nexport interface MPPChallengeSummary {\n id: string;\n realm: string;\n method: string;\n intent: string;\n /** Method-specific request data (amount, currency, recipient, etc.) */\n request: Record<string, unknown>;\n expires?: string;\n digest?: string;\n description?: string;\n opaque?: Record<string, string>;\n}\n\nexport interface MPPCredentialSummary {\n challenge: MPPChallengeSummary;\n /** DID or chain-native key identifying the payer. */\n source?: string;\n /** Method-specific payment proof (Tempo tx, SPT, Lightning preimage, etc.). */\n payload: unknown;\n}\n\nexport interface MPPReceiptSummary {\n method?: string;\n reference?: string;\n externalId?: string;\n status?: string;\n timestamp?: string;\n raw: Record<string, unknown>;\n}\n\nexport type MPPKind = 'challenge' | 'credential' | 'receipt' | 'error' | 'unknown';\n\nexport interface MPPRequestContext {\n kind: MPPKind;\n /** For 402 responses: one or more challenge offers. */\n challenges?: MPPChallengeSummary[];\n /** For requests with Authorization: Payment header. */\n credential?: MPPCredentialSummary;\n /** For 200 responses with Payment-Receipt header. */\n receipt?: MPPReceiptSummary;\n /** For problem+json error responses. */\n error?: { type?: string; title?: string; detail?: string };\n /** Detected payment methods offered (for multi-method 402). */\n offeredMethods?: string[];\n /** Raw body captured for BodyDigest verification in mpp-verify.ts. */\n rawBody?: string;\n}\n\nexport interface MPPRequestLike {\n method: string;\n url: string;\n headers: Record<string, string | string[] | undefined>;\n body?: unknown;\n rawBody?: string;\n}\n\nexport interface MPPResponseLike {\n status: number;\n headers: Record<string, string | string[] | undefined>;\n body?: unknown;\n rawBody?: string;\n}\n\n/**\n * Extract MPP context from an agent → merchant request.\n * Looks for `Authorization: Payment <credential>` header.\n */\nexport function extractMPPFromRequest(request: MPPRequestLike): MPPRequestContext | null {\n const auth = readHeader(request.headers, 'authorization');\n if (!auth || !/^\\s*Payment\\s+/i.test(auth)) return null;\n\n try {\n const credential = Credential.deserialize(auth);\n return {\n kind: 'credential',\n credential: {\n challenge: summarizeChallenge(credential.challenge),\n source: credential.source,\n payload: credential.payload,\n },\n rawBody: request.rawBody,\n };\n } catch {\n return { kind: 'error', error: { type: 'invalid-credential-encoding' } };\n }\n}\n\n/**\n * Extract MPP context from a merchant → agent response.\n * Handles 402 (challenge offers), 200 (receipt), 4xx (problem+json errors).\n */\nexport function extractMPPFromResponse(response: MPPResponseLike): MPPRequestContext | null {\n if (response.status === 402) {\n const challenges = collectChallenges(response);\n if (challenges.length === 0) return null;\n const methods = Array.from(new Set(challenges.map((c) => c.method)));\n return {\n kind: 'challenge',\n challenges,\n offeredMethods: methods,\n };\n }\n\n const receiptHeader = readHeader(response.headers, 'payment-receipt');\n if (receiptHeader) {\n try {\n const parsed = Receipt.deserialize(receiptHeader);\n const r = parsed as unknown as Record<string, unknown>;\n return {\n kind: 'receipt',\n receipt: {\n method: coerceString(r.method),\n reference: coerceString(r.reference),\n externalId: coerceString(r.externalId ?? r.external_id),\n status: coerceString(r.status),\n timestamp: coerceString(r.timestamp),\n raw: r,\n },\n };\n } catch {\n return { kind: 'error', error: { type: 'invalid-receipt-encoding' } };\n }\n }\n\n const contentType = readHeader(response.headers, 'content-type');\n if (contentType && /application\\/problem\\+json/i.test(contentType)) {\n const body =\n typeof response.body === 'object' && response.body !== null\n ? (response.body as Record<string, unknown>)\n : {};\n return {\n kind: 'error',\n error: {\n type: coerceString(body.type),\n title: coerceString(body.title),\n detail: coerceString(body.detail),\n },\n };\n }\n\n return null;\n}\n\n/**\n * Extract from either a request OR a response, auto-detecting which has MPP\n * artifacts. Convenience for pipeline callers.\n */\nexport function extractMPPContext(\n message:\n | { request: MPPRequestLike }\n | { response: MPPResponseLike }\n | (MPPRequestLike & Partial<MPPResponseLike>)\n): MPPRequestContext | null {\n if ('request' in message) return extractMPPFromRequest(message.request);\n if ('response' in message) return extractMPPFromResponse(message.response);\n if (typeof (message as MPPResponseLike).status === 'number') {\n return extractMPPFromResponse(message as MPPResponseLike);\n }\n return extractMPPFromRequest(message as MPPRequestLike);\n}\n\nfunction collectChallenges(response: MPPResponseLike): MPPChallengeSummary[] {\n const wwwAuth = readHeader(response.headers, 'www-authenticate');\n if (!wwwAuth) return [];\n const headers = new Headers();\n headers.set('www-authenticate', wwwAuth);\n\n const out: MPPChallengeSummary[] = [];\n try {\n const list = Challenge.fromHeadersList(headers);\n for (const ch of list) {\n out.push(summarizeChallenge(ch as unknown as Challenge.Challenge));\n }\n } catch {\n // fall through with empty list\n }\n return out;\n}\n\nfunction summarizeChallenge(\n ch: Challenge.Challenge | Record<string, unknown>\n): MPPChallengeSummary {\n const raw = ch as Record<string, unknown>;\n return {\n id: coerceString(raw.id) ?? '',\n realm: coerceString(raw.realm) ?? '',\n method: coerceString(raw.method) ?? '',\n intent: coerceString(raw.intent) ?? '',\n request: (raw.request as Record<string, unknown>) ?? {},\n expires: coerceString(raw.expires),\n digest: coerceString(raw.digest),\n description: coerceString(raw.description),\n opaque: raw.opaque as Record<string, string> | undefined,\n };\n}\n\nfunction readHeader(\n headers: Record<string, string | string[] | undefined>,\n name: string\n): string | undefined {\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === name) {\n const raw = headers[key];\n if (typeof raw === 'string') return raw;\n if (Array.isArray(raw)) return raw.join(', ');\n }\n }\n return undefined;\n}\n\nfunction coerceString(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n}\n","/**\n * MPP verification — expiry + optional BodyDigest + source extraction.\n *\n * We do NOT verify the challenge's HMAC binding (needs merchant's secret)\n * or the cryptographic payment proof (per-method, requires upstream\n * connectivity). Those are the merchant's / settlement layer's job.\n *\n * Our job: structural correctness, expiry policy, tamper detection via\n * optional BodyDigest, and identity extraction for PDLSS binding.\n */\n\nimport { BodyDigest } from 'mppx';\nimport type { MPPRequestContext } from './mpp';\nimport { defaultNonceStore, type NonceStore } from './nonce-store';\n\nexport interface MPPVerifyInput {\n context: MPPRequestContext;\n /** Raw request body to validate BodyDigest against, if the challenge declares one. */\n rawBody?: string;\n /** Seconds of clock-skew tolerance on challenge.expires. Default 60. */\n clockSkewSec?: number;\n /** Injectable for deterministic tests. */\n now?: () => number;\n /** Optional replay-protection store. Defaults to in-process LRU. */\n nonceStore?: NonceStore;\n}\n\nexport interface MPPVerifyResult {\n ok: boolean;\n expiryOk: boolean;\n bodyDigestOk: boolean | null;\n source?: string;\n method?: string;\n error?: string;\n}\n\nexport function verifyMPP(input: MPPVerifyInput): MPPVerifyResult {\n const { context } = input;\n const tolerance = input.clockSkewSec ?? 60;\n const nowSec = input.now ? input.now() : Math.floor(Date.now() / 1000);\n const nonceStore = input.nonceStore ?? defaultNonceStore;\n\n // Extract the challenge under test — for credential flow, from inside the\n // wrapped challenge; for bare challenge flow, from context.challenges[0].\n const challenge = context.credential?.challenge ?? (context.challenges && context.challenges[0]);\n const source = context.credential?.source;\n const method = challenge?.method;\n\n let expiryOk = true;\n if (challenge?.expires) {\n const parsedExpiry = Date.parse(challenge.expires);\n if (!Number.isFinite(parsedExpiry)) {\n return {\n ok: false,\n expiryOk: false,\n bodyDigestOk: null,\n source,\n method,\n error: 'unparseable challenge.expires',\n };\n }\n const expiresSec = Math.floor(parsedExpiry / 1000);\n if (nowSec > expiresSec + tolerance) {\n expiryOk = false;\n }\n }\n\n // Audit F-A1-04: previously when rawBody was present but the challenge\n // omitted `digest`, bodyDigestOk stayed `null` and was treated as OK.\n // Attacker could strip the digest field from the challenge and tamper\n // with body. Now: when rawBody is present, digest is REQUIRED.\n let bodyDigestOk: boolean | null = null;\n if (input.rawBody !== undefined) {\n if (!challenge?.digest) {\n bodyDigestOk = false;\n } else {\n try {\n if (!/^sha-256=/.test(challenge.digest)) {\n bodyDigestOk = false;\n } else {\n bodyDigestOk = BodyDigest.verify(challenge.digest as `sha-256=${string}`, input.rawBody);\n }\n } catch {\n bodyDigestOk = false;\n }\n }\n }\n\n // Audit F-A1-05: replay protection. Use challenge nonce + digest as\n // replay key when available; fall back to digest alone. Window matches\n // the expiry tolerance.\n let replayOk = true;\n if (challenge?.digest && expiryOk) {\n const replayKey = `mpp:${challenge.digest}:${(challenge as { nonce?: string }).nonce ?? ''}`;\n const expiresAt = (nowSec + tolerance) * 1000;\n if (nonceStore.seen(replayKey, expiresAt)) {\n replayOk = false;\n }\n }\n\n const ok = expiryOk && (bodyDigestOk === null || bodyDigestOk === true) && replayOk;\n const errors: string[] = [];\n if (!expiryOk) errors.push('challenge expired');\n if (bodyDigestOk === false) {\n errors.push(\n input.rawBody !== undefined && !challenge?.digest\n ? 'body digest required when rawBody present'\n : 'body digest mismatch'\n );\n }\n if (!replayOk) errors.push('MPP challenge replay — already seen within tolerance window');\n\n return {\n ok,\n expiryOk,\n bodyDigestOk,\n source,\n method,\n error: errors.length > 0 ? errors.join('; ') : undefined,\n };\n}\n","/**\n * x402 (Coinbase / Linux Foundation x402 Foundation) extractor.\n *\n * Wraps @x402/core's schema parsers. x402 Foundation launched April 2 2026\n * with v2 adding network-agnostic identifiers + multiple facilitators +\n * Bazaar discovery. MPP (Machine Payments Protocol) is the IETF-formalised\n * superset of x402; this module normalizes x402 output to MPP-shape so\n * downstream pipeline code is uniform.\n *\n * Where x402 lives on the wire:\n * - 402 response body (v2) OR `X-PAYMENT-REQUIRED` header (v1) — PaymentRequired\n * - Request body (v2) OR `X-PAYMENT` header (v1, base64) — PaymentPayload\n */\n\nimport {\n validatePaymentRequired,\n validatePaymentPayload,\n type PaymentRequired,\n type PaymentPayload,\n type PaymentRequirements,\n} from '@x402/core/schemas';\nimport { safeBase64Decode } from '@x402/core/utils';\n\nexport type X402Kind = 'required' | 'payload' | 'error' | 'unknown';\n\nexport interface X402RequirementsSummary {\n scheme: string;\n network: string;\n asset: string;\n /** Normalized to string for v1/v2 compat — v1 uses maxAmountRequired, v2 uses amount. */\n amount: string;\n payTo: string;\n maxTimeoutSeconds?: number;\n resource?: string;\n description?: string;\n}\n\nexport interface X402RequestContext {\n kind: X402Kind;\n version: 1 | 2 | null;\n /** For 402 responses: the PaymentRequired body. */\n paymentRequired?: {\n resource: string;\n accepts: X402RequirementsSummary[];\n extensions?: Record<string, unknown>;\n error?: string;\n };\n /** For request body (v2) or X-PAYMENT header (v1 base64): the PaymentPayload. */\n paymentPayload?: {\n scheme: string;\n network: string;\n /** Free-form per-scheme payload (e.g. EIP-3009 authorization, Solana tx). */\n payload: Record<string, unknown>;\n extensions?: Record<string, unknown>;\n };\n error?: { type: string; detail?: string };\n /** Whether this was parsed from a header (v1 back-compat) or body (v2). */\n source: 'header' | 'body' | null;\n}\n\nexport interface X402RequestLike {\n method?: string;\n url?: string;\n headers?: Record<string, string | string[] | undefined>;\n body?: unknown;\n}\n\nexport interface X402ResponseLike {\n status?: number;\n headers?: Record<string, string | string[] | undefined>;\n body?: unknown;\n}\n\n/**\n * Extract x402 PaymentPayload from an agent → merchant request.\n * Checks v2 body (if it parses as PaymentPayload) and v1 X-PAYMENT header.\n */\nexport function extractX402FromRequest(request: X402RequestLike): X402RequestContext | null {\n const headerValue = readHeader(request.headers, 'x-payment');\n\n // v2 body path first\n if (request.body && typeof request.body === 'object') {\n const parsed = tryParsePayload(request.body);\n if (parsed) return buildPayloadContext(parsed, 'body');\n }\n\n // v1 header path\n if (headerValue) {\n try {\n const decoded = safeBase64Decode(headerValue);\n if (decoded) {\n const json = JSON.parse(decoded);\n const parsed = tryParsePayload(json);\n if (parsed) return buildPayloadContext(parsed, 'header');\n }\n } catch {\n return {\n kind: 'error',\n version: 1,\n source: 'header',\n error: { type: 'invalid-x402-payload' },\n };\n }\n }\n\n return null;\n}\n\n/**\n * Extract x402 PaymentRequired from a merchant → agent 402 response.\n */\nexport function extractX402FromResponse(response: X402ResponseLike): X402RequestContext | null {\n if (response.status !== 402) return null;\n\n // v2 body path\n if (response.body && typeof response.body === 'object') {\n const parsed = tryParseRequired(response.body);\n if (parsed) return buildRequiredContext(parsed, 'body');\n }\n\n // v1 header path\n const headerValue = readHeader(response.headers, 'x-payment-required');\n if (headerValue) {\n try {\n const decoded = safeBase64Decode(headerValue);\n if (decoded) {\n const json = JSON.parse(decoded);\n const parsed = tryParseRequired(json);\n if (parsed) return buildRequiredContext(parsed, 'header');\n }\n } catch {\n return {\n kind: 'error',\n version: 1,\n source: 'header',\n error: { type: 'invalid-x402-required' },\n };\n }\n }\n\n return null;\n}\n\nexport function extractX402Context(\n message:\n | { request: X402RequestLike }\n | { response: X402ResponseLike }\n | (X402RequestLike & Partial<X402ResponseLike>)\n): X402RequestContext | null {\n if ('request' in message) return extractX402FromRequest(message.request);\n if ('response' in message) return extractX402FromResponse(message.response);\n if (typeof (message as X402ResponseLike).status === 'number') {\n return extractX402FromResponse(message as X402ResponseLike);\n }\n return extractX402FromRequest(message as X402RequestLike);\n}\n\nfunction tryParseRequired(data: unknown): PaymentRequired | null {\n try {\n return validatePaymentRequired(data);\n } catch {\n return null;\n }\n}\n\nfunction tryParsePayload(data: unknown): PaymentPayload | null {\n try {\n return validatePaymentPayload(data);\n } catch {\n return null;\n }\n}\n\nfunction buildRequiredContext(\n parsed: PaymentRequired,\n source: 'header' | 'body'\n): X402RequestContext {\n const asRecord = parsed as unknown as Record<string, unknown>;\n const version = coerceVersion(asRecord.x402Version);\n const accepts = (asRecord.accepts as PaymentRequirements[] | undefined) ?? [];\n return {\n kind: 'required',\n version,\n source,\n paymentRequired: {\n resource: resolveResource(asRecord.resource),\n accepts: accepts.map(summarizeRequirement),\n extensions: asRecord.extensions as Record<string, unknown> | undefined,\n error: typeof asRecord.error === 'string' ? asRecord.error : undefined,\n },\n };\n}\n\nfunction buildPayloadContext(\n parsed: PaymentPayload,\n source: 'header' | 'body'\n): X402RequestContext {\n const asRecord = parsed as unknown as Record<string, unknown>;\n const version = coerceVersion(asRecord.x402Version);\n const accepted = asRecord.accepted as PaymentRequirements | undefined;\n const payload = (asRecord.payload as Record<string, unknown>) ?? {};\n return {\n kind: 'payload',\n version,\n source,\n paymentPayload: {\n scheme: accepted?.scheme ?? (typeof asRecord.scheme === 'string' ? asRecord.scheme : ''),\n network: accepted?.network ?? (typeof asRecord.network === 'string' ? asRecord.network : ''),\n payload,\n extensions: asRecord.extensions as Record<string, unknown> | undefined,\n },\n };\n}\n\nfunction summarizeRequirement(req: PaymentRequirements): X402RequirementsSummary {\n const r = req as unknown as Record<string, unknown>;\n const amount = (r.amount ?? r.maxAmountRequired ?? '0') as string;\n return {\n scheme: (r.scheme as string) ?? '',\n network: (r.network as string) ?? '',\n asset: (r.asset as string) ?? '',\n amount: String(amount),\n payTo: (r.payTo as string) ?? '',\n maxTimeoutSeconds: typeof r.maxTimeoutSeconds === 'number' ? r.maxTimeoutSeconds : undefined,\n resource: typeof r.resource === 'string' ? r.resource : undefined,\n description: typeof r.description === 'string' ? r.description : undefined,\n };\n}\n\nfunction resolveResource(v: unknown): string {\n if (typeof v === 'string') return v;\n if (v && typeof v === 'object' && 'url' in v && typeof (v as { url: unknown }).url === 'string') {\n return (v as { url: string }).url;\n }\n return '';\n}\n\nfunction coerceVersion(v: unknown): 1 | 2 | null {\n if (v === 1 || v === 2) return v;\n return null;\n}\n\nfunction readHeader(\n headers: Record<string, string | string[] | undefined> | undefined,\n name: string\n): string | undefined {\n if (!headers) return undefined;\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === name) {\n const raw = headers[key];\n if (typeof raw === 'string') return raw;\n if (Array.isArray(raw)) return raw[0];\n }\n }\n return undefined;\n}\n","/**\n * VI (Verifiable Intent) 3-layer SD-JWT chain verification.\n *\n * VI chains: L1 (credential provider → wallet) → L2 (user → agent) → L3\n * (agent → merchant). L3 itself can split into L3a (payment mandate) + L3b\n * (checkout mandate) cross-referenced via transaction_id, with L3b carrying\n * a checkout_hash (VI constraint type 8) that must match SHA-256 of the L2\n * checkout disclosure.\n *\n * Signature primitives are delegated to @sd-jwt/core (via our extractor);\n * cnf.jwk chain-walking + cross-references + checkout_hash binding is\n * AstraSync-specific composition logic — that's the whitespace here.\n *\n * This module does NOT re-verify selective-disclosure hashes (the extractor\n * already applied them via @sd-jwt/core). It DOES verify:\n * - cnf.jwk in L1 payload points to L2's signing key (thumbprint match)\n * - cnf.jwk in L2 payload points to L3's signing key\n * - L3a.transaction_id === L3b.transaction_id (when both present)\n * - L3b.checkout_hash === SHA-256(L2 canonical checkout disclosure) — type 8\n * - mandate-level `exp` is not in the past (beyond clock skew)\n *\n * Cryptographic signature verification on each layer uses the verifier\n * callback the caller supplies (e.g. resolves via @sd-jwt/core with the\n * right JWK from the L1 issuer's JWKS).\n */\n\nimport { createHash, webcrypto } from 'node:crypto';\nimport type { JWK } from 'jose';\nimport { defaultNonceStore, type NonceStore } from './nonce-store';\n\nexport interface VILayer {\n /** Compact SD-JWT / JWS for this layer. */\n compact: string;\n /** Decoded JWT payload (already disclosure-merged). */\n payload: Record<string, unknown>;\n /** Decoded JWT header. */\n header: Record<string, unknown>;\n}\n\nexport interface VIVerifyInput {\n /**\n * Layers in chain order. L1 is REQUIRED by default —\n * without L1 there is no chain root and L2 can be verified against any\n * attacker-supplied key. Callers who have resolved L2's signing key by\n * a trusted out-of-band mechanism (wallet binding, prior protocol step)\n * MUST set `allowUnboundChain: true` AND supply `expectedL2Key`.\n */\n layers: {\n l1?: VILayer;\n l2: VILayer;\n l3a?: VILayer;\n l3b?: VILayer;\n };\n /**\n * Verifier callback invoked per layer. Should return true iff the layer's\n * JWS signature verifies against the resolved public key (for L2 this is\n * L1's cnf.jwk; for L3 this is L2's cnf.jwk; for L1 this is the issuer's\n * JWKS per `iss` claim).\n */\n verifySignature: (layer: VILayer, expectedKey: JWK | null) => Promise<boolean>;\n /**\n * Clock skew tolerance in seconds for expiry checks. Default 60s\n * (tightened from the previous 300s default).\n */\n clockSkewSec?: number;\n now?: () => number;\n /**\n * Explicit opt-in to verify a chain with L1 omitted.\n * Defaults to false. When true, `expectedL2Key` MUST also be supplied\n * (used as the expected signing key for L2 verification).\n */\n allowUnboundChain?: boolean;\n /** Required when allowUnboundChain === true. */\n expectedL2Key?: JWK;\n /** Optional replay-protection store. Defaults to in-process LRU. */\n nonceStore?: NonceStore;\n}\n\nexport interface VIVerifyResult {\n ok: boolean;\n checks: {\n l1SigOk: boolean | null;\n l2SigOk: boolean;\n l3aSigOk: boolean | null;\n l3bSigOk: boolean | null;\n l1BindsL2: boolean;\n l2BindsL3: boolean;\n l3aL3bTxnIdMatch: boolean | null;\n checkoutHashOk: boolean | null;\n expiryOk: boolean;\n };\n errors: string[];\n}\n\nexport async function verifyVIChain(input: VIVerifyInput): Promise<VIVerifyResult> {\n const errors: string[] = [];\n const tolerance = input.clockSkewSec ?? 60;\n const now = input.now ? input.now() : Math.floor(Date.now() / 1000);\n const { l1, l2, l3a, l3b } = input.layers;\n const nonceStore = input.nonceStore ?? defaultNonceStore;\n\n // Audit F-A1-02: L1 is required unless caller explicitly opts into an\n // unbound chain AND supplies the expected L2 signing key. Otherwise L2\n // would be verified against null, which most verifier callbacks\n // interpret as \"use the JWK in the JWS header\" — accepting any\n // attacker-supplied key.\n if (!l1) {\n if (!input.allowUnboundChain) {\n errors.push(\n 'L1 missing — chain root unbound (set allowUnboundChain + expectedL2Key to override)'\n );\n } else if (!input.expectedL2Key) {\n errors.push('allowUnboundChain set but expectedL2Key missing');\n }\n }\n\n // Signature verification ---------------------------------\n const l1SigOk = l1 ? await input.verifySignature(l1, null) : null;\n if (l1 && !l1SigOk) errors.push('L1 signature invalid');\n\n const l1Cnf = extractCnfJwk(l1?.payload);\n // Use L1's cnf.jwk when L1 present; otherwise (opt-in unbound chain) use\n // the caller-supplied expectedL2Key. Never null — F-A1-02.\n const l2ExpectedKey: JWK | null = l1Cnf ?? input.expectedL2Key ?? null;\n const l2SigOk = await input.verifySignature(l2, l2ExpectedKey);\n if (!l2SigOk) errors.push('L2 signature invalid');\n\n // Audit F-A1-05: replay protection on L2 signature. Use the compact JWS\n // as the nonce key; the signature is unique per request. Window matches\n // tolerance (denied replays past the window are already rejected by\n // expiry check, so we don't need to retain entries longer).\n if (l2SigOk) {\n const replayKey = `vi:l2:${l2.compact}`;\n const expiresAt = now * 1000 + tolerance * 1000;\n if (nonceStore.seen(replayKey, expiresAt)) {\n errors.push('L2 signature replay — already seen within tolerance window');\n }\n }\n\n const l2Cnf = extractCnfJwk(l2.payload);\n const l3aSigOk = l3a ? await input.verifySignature(l3a, l2Cnf ?? null) : null;\n if (l3a && !l3aSigOk) errors.push('L3a signature invalid');\n const l3bSigOk = l3b ? await input.verifySignature(l3b, l2Cnf ?? null) : null;\n if (l3b && !l3bSigOk) errors.push('L3b signature invalid');\n\n // cnf.jwk binding ----------------------------------------\n let l1BindsL2 = true;\n if (l1Cnf) {\n const l2KeyFromHeader = await jwkForLayer(l2);\n l1BindsL2 = l2KeyFromHeader ? await thumbprintsMatch(l1Cnf, l2KeyFromHeader) : false;\n if (!l1BindsL2) errors.push('L1.cnf.jwk does not bind L2 signing key');\n }\n\n let l2BindsL3 = true;\n if (l2Cnf && (l3a || l3b)) {\n const l3Layer = l3a ?? l3b!;\n const l3KeyFromHeader = await jwkForLayer(l3Layer);\n l2BindsL3 = l3KeyFromHeader ? await thumbprintsMatch(l2Cnf, l3KeyFromHeader) : false;\n if (!l2BindsL3) errors.push('L2.cnf.jwk does not bind L3 signing key');\n }\n\n // L3a/L3b cross-reference --------------------------------\n let l3aL3bTxnIdMatch: boolean | null = null;\n if (l3a && l3b) {\n const a = coerceString(l3a.payload.transaction_id ?? l3a.payload.transactionId);\n const b = coerceString(l3b.payload.transaction_id ?? l3b.payload.transactionId);\n if (a && b) {\n l3aL3bTxnIdMatch = a === b;\n if (!l3aL3bTxnIdMatch) {\n errors.push(`L3a.transaction_id (${a}) does not match L3b.transaction_id (${b})`);\n }\n }\n }\n\n // checkout_hash (VI constraint type 8) -------------------\n let checkoutHashOk: boolean | null = null;\n if (l3b) {\n const declaredHash = coerceString(\n l3b.payload.checkout_hash ??\n l3b.payload.conditional_transaction_id ??\n (l3b.payload.payment_reference as Record<string, unknown> | undefined)?.checkout_hash\n );\n if (declaredHash) {\n const computed = computeCheckoutHashFromL2(l2);\n checkoutHashOk = computed ? declaredHash === computed : false;\n if (!checkoutHashOk) {\n errors.push('L3b.checkout_hash does not match SHA-256 of L2 checkout disclosure');\n }\n }\n }\n\n // Expiry policy ------------------------------------------\n const expiryOk = checkExpiryAcross([l1, l2, l3a, l3b], tolerance, now, errors);\n\n // Audit F-A1-02 + F-A1-05: ok also requires the chain-root + replay\n // checks above to have passed (errors array captures both). Previously\n // `ok` was derived purely from individual check booleans, so the L1-\n // required errors and replay-detected errors didn't gate it.\n const noUnboundChainOrReplayErrors = !errors.some(\n (e) =>\n e.startsWith('L1 missing') ||\n e.startsWith('allowUnboundChain set') ||\n e.startsWith('L2 signature replay')\n );\n\n const ok =\n l1SigOk !== false &&\n l2SigOk &&\n l3aSigOk !== false &&\n l3bSigOk !== false &&\n l1BindsL2 &&\n l2BindsL3 &&\n l3aL3bTxnIdMatch !== false &&\n checkoutHashOk !== false &&\n expiryOk &&\n noUnboundChainOrReplayErrors;\n\n return {\n ok,\n checks: {\n l1SigOk,\n l2SigOk,\n l3aSigOk,\n l3bSigOk,\n l1BindsL2,\n l2BindsL3,\n l3aL3bTxnIdMatch,\n checkoutHashOk,\n expiryOk,\n },\n errors,\n };\n}\n\nfunction extractCnfJwk(payload: Record<string, unknown> | undefined): JWK | null {\n if (!payload) return null;\n const cnf = payload.cnf as Record<string, unknown> | undefined;\n if (!cnf) return null;\n const jwk = cnf.jwk as JWK | undefined;\n return jwk ?? null;\n}\n\nasync function jwkForLayer(layer: VILayer): Promise<JWK | null> {\n // Prefer explicit cnf.jwk in the header, then payload; fallback to null.\n const fromHeader = extractCnfJwk(layer.header);\n if (fromHeader) return fromHeader;\n const fromPayload = extractCnfJwk(layer.payload);\n return fromPayload;\n}\n\nasync function thumbprintsMatch(a: JWK, b: JWK): Promise<boolean> {\n try {\n const ta = await jwkThumbprint(a);\n const tb = await jwkThumbprint(b);\n return ta === tb;\n } catch {\n return false;\n }\n}\n\n// RFC 7638 thumbprint: SHA-256 over the canonical JSON of required JWK members.\nasync function jwkThumbprint(jwk: JWK): Promise<string> {\n const canonical = canonicalJwk(jwk);\n const bytes = new TextEncoder().encode(JSON.stringify(canonical));\n const subtle = webcrypto.subtle as SubtleCrypto;\n const buffer = await new Promise<ArrayBuffer>((resolve, reject) => {\n const source = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(source).set(bytes);\n subtle.digest('SHA-256', source).then(resolve).catch(reject);\n });\n return Buffer.from(new Uint8Array(buffer)).toString('base64url').replace(/=+$/, '');\n}\n\nfunction canonicalJwk(jwk: JWK): Record<string, string> {\n // Per RFC 7638: members must appear in lexicographic order; only required\n // fields per kty are included.\n if (jwk.kty === 'EC') {\n return { crv: jwk.crv ?? '', kty: 'EC', x: jwk.x ?? '', y: jwk.y ?? '' };\n }\n if (jwk.kty === 'OKP') {\n return { crv: jwk.crv ?? '', kty: 'OKP', x: jwk.x ?? '' };\n }\n if (jwk.kty === 'RSA') {\n return { e: jwk.e ?? '', kty: 'RSA', n: jwk.n ?? '' };\n }\n return { kty: jwk.kty ?? '' };\n}\n\nfunction computeCheckoutHashFromL2(l2: VILayer): string | null {\n const checkoutDisclosure = (l2.payload.checkout ?? l2.payload.checkout_mandate) as unknown;\n if (!checkoutDisclosure) return null;\n const canonical = canonicalStringify(checkoutDisclosure);\n const hash = createHash('sha256').update(canonical).digest('base64url').replace(/=+$/, '');\n return hash;\n}\n\nfunction canonicalStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return '[' + value.map(canonicalStringify).join(',') + ']';\n const entries = Object.entries(value as Record<string, unknown>).sort(([a], [b]) =>\n a < b ? -1 : a > b ? 1 : 0\n );\n return (\n '{' + entries.map(([k, v]) => JSON.stringify(k) + ':' + canonicalStringify(v)).join(',') + '}'\n );\n}\n\nfunction checkExpiryAcross(\n layers: Array<VILayer | undefined>,\n toleranceSec: number,\n nowSec: number,\n errors: string[]\n): boolean {\n let ok = true;\n const names = ['L1', 'L2', 'L3a', 'L3b'];\n layers.forEach((layer, idx) => {\n if (!layer) return;\n const exp = toUnixSeconds(layer.payload.exp ?? layer.payload.expires);\n if (exp === undefined) return;\n if (nowSec > exp + toleranceSec) {\n errors.push(`${names[idx]} mandate expired at ${exp}`);\n ok = false;\n }\n });\n return ok;\n}\n\nfunction toUnixSeconds(v: unknown): number | undefined {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n if (typeof v === 'string') {\n const asInt = Number(v);\n if (Number.isFinite(asInt) && asInt > 0) {\n return asInt >= 1e12 ? Math.floor(asInt / 1000) : Math.floor(asInt);\n }\n const parsed = Date.parse(v);\n if (Number.isFinite(parsed)) return Math.floor(parsed / 1000);\n }\n return undefined;\n}\n\nfunction coerceString(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n}\n","/**\n * Visa JWKS registry resolver.\n *\n * Default endpoint: https://mcp.visa.com/.well-known/jwks (per Visa TAP spec).\n * Wraps jose.createRemoteJWKSet which handles caching + rotation natively.\n */\n\nimport { createRemoteJWKSet, type JWK } from 'jose';\nimport type { RegistryResolver, ResolveContext } from './types';\n\nconst DEFAULT_VISA_JWKS_URL = 'https://mcp.visa.com/.well-known/jwks';\n\nexport interface VisaRegistryOptions {\n jwksUrl?: string;\n cacheMaxAge?: number;\n cooldownDuration?: number;\n}\n\nexport function createVisaRegistry(options: VisaRegistryOptions = {}): RegistryResolver {\n const url = new URL(options.jwksUrl ?? DEFAULT_VISA_JWKS_URL);\n const jwks = createRemoteJWKSet(url, {\n cacheMaxAge: options.cacheMaxAge,\n cooldownDuration: options.cooldownDuration,\n });\n\n return {\n name: 'visa',\n async resolve(kid: string, context?: ResolveContext): Promise<JWK | null> {\n if (!kid) return null;\n try {\n const key = await jwks({\n kid,\n alg: context?.algorithm ?? 'ES256',\n typ: 'JWT',\n });\n return exportJwkFromKeyLike(key);\n } catch {\n return null;\n }\n },\n };\n}\n\nasync function exportJwkFromKeyLike(keyLike: unknown): Promise<JWK | null> {\n if (!keyLike) return null;\n // jose returns KeyObject or CryptoKey — both export via exportJWK at caller side.\n // Runtime shape check: if it already looks like a JWK, pass through.\n if (typeof keyLike === 'object' && 'kty' in (keyLike as object)) {\n return keyLike as JWK;\n }\n const { exportJWK } = await import('jose');\n try {\n return await exportJWK(keyLike as Parameters<typeof exportJWK>[0]);\n } catch {\n return null;\n }\n}\n","/**\n * Online Mode — Delegates to the existing verify() function.\n * Full trust scoring, blockchain verification, audit trail, PDLSS evaluation via API.\n */\n\nimport type { AstraSyncGatewayConfig, PDLSSContext, VerificationDecision } from '../types';\nimport {\n verify,\n type VerificationResult,\n type VerificationRequest,\n type GatewayConfig,\n} from '../../index';\n\n/**\n * Convert gateway config to the existing GatewayConfig format.\n */\nfunction toGatewayConfig(config: AstraSyncGatewayConfig): GatewayConfig {\n return {\n apiBaseUrl: config.apiBaseUrl || 'https://api.astrasync.ai',\n apiKey: config.apiKey,\n minTrustScore: config.minTrustScore,\n minTrustScoreForFull: config.minTrustScoreForFull,\n cacheTtl: config.cacheTtl,\n debug: config.debug,\n customHeaders: config.customHeaders,\n counterpartyUrl: config.counterpartyUrl,\n counterpartyType: config.counterpartyType,\n };\n}\n\n/**\n * Convert PDLSS context to a verification request.\n *\n * Vocabulary shim (transport-layer, per the platform's canonical PDLSS\n * vocabulary): the LOCAL evaluator's purposes are dotted actions\n * (`shell.exec`, `file.write`), but the platform's wire contract is\n * purpose = bare category noun, action = dotted verb — the backend rejects\n * dotted purposes with exactly this guidance. Split dotted local purposes\n * so online verification and hybrid sync record real decisions instead of\n * vocabulary-mismatch denials. The local tool name (`context.action`, e.g.\n * `Bash`) is subsumed by the dotted action on the wire.\n */\nexport function toVerificationRequest(\n context: PDLSSContext,\n astraId?: string\n): VerificationRequest {\n const dotIndex = context.purpose.indexOf('.');\n const dotted = dotIndex > 0;\n return {\n credentials: { astraId },\n purpose: dotted ? context.purpose.slice(0, dotIndex) : context.purpose,\n action: dotted ? context.purpose : context.action,\n resourceType: context.resourceType,\n resource: context.target,\n transactionValue: context.transactionValue,\n currency: context.currency,\n createSession: true,\n };\n}\n\n/**\n * Convert verification result to a VerificationDecision.\n */\nfunction toDecision(result: VerificationResult): VerificationDecision {\n // Round-18 G4: ALLOW only when both identity AND policy pass.\n if (result.identityVerified && result.policyAllowed) {\n return {\n recommendation: 'ALLOW',\n reason: result.agent?.trustScore\n ? `Verified (trust score ${result.agent.trustScore})`\n : 'Verified',\n trustScore: result.agent?.trustScore,\n sessionId:\n 'sessionId' in result\n ? ((result as Record<string, unknown>).sessionId as string)\n : undefined,\n };\n }\n\n if (result.requiresStepUp || result.requiresApproval) {\n return {\n recommendation: 'MANUAL_REVIEW',\n reason: result.denialReasons?.[0] || 'Step-up or approval required',\n trustScore: result.agent?.trustScore,\n };\n }\n\n return {\n recommendation: 'DENY',\n reason: result.denialReasons?.[0] || 'Access denied',\n trustScore: result.agent?.trustScore,\n };\n}\n\n/**\n * Verify via the AstraSync API (online mode).\n */\nexport async function verifyOnline(\n config: AstraSyncGatewayConfig,\n context: PDLSSContext,\n astraId?: string\n): Promise<VerificationDecision> {\n const gatewayConfig = toGatewayConfig(config);\n const request = toVerificationRequest(context, astraId);\n const result = await verify(gatewayConfig, request);\n return toDecision(result);\n}\n","/**\n * Hybrid Mode — Local evaluation for speed, async API sync for trust scoring.\n *\n * Immediate: local PDLSS evaluation (< 1ms)\n * Async: queued API verification for audit trail and trust score updates\n *\n * Queue entries are persisted to disk so they survive process restarts.\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { dirname } from 'path';\nimport type {\n AstraSyncGatewayConfig,\n PDLSSContext,\n VerificationDecision,\n SyncQueueEntry,\n} from '../types';\nimport type { LocalEvaluator } from '../../local-evaluator/evaluator';\nimport { verifyOnline } from './online';\nimport { redactDeep } from '../redact';\n\nconst MAX_QUEUE_SIZE = 1000;\nconst MAX_RETRIES = 3;\n\nexport interface FlushOptions {\n /** Max entries to attempt this flush (default: all pending). */\n limit?: number;\n /**\n * Per-entry time budget in ms. A timed-out entry stays pending (no retry\n * penalty — slow network is not a failure) and ends the flush early.\n * Stateless callers (the Claude Code hook) use this to keep sync off the\n * tool-call critical path.\n */\n perEntryTimeoutMs?: number;\n}\n\nconst FLUSH_TIMEOUT = Symbol('flush-timeout');\n\nfunction delay(ms: number): Promise<typeof FLUSH_TIMEOUT> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => resolve(FLUSH_TIMEOUT), ms);\n // Don't hold the process open just for the timeout race.\n if (typeof timer.unref === 'function') timer.unref();\n });\n}\n\nexport class HybridSyncQueue {\n private queue: SyncQueueEntry[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private config: AstraSyncGatewayConfig;\n private processing = false;\n private persistPath: string | null = null;\n\n constructor(config: AstraSyncGatewayConfig, persistPath?: string) {\n this.config = config;\n this.persistPath = persistPath ?? null;\n this.loadFromDisk();\n }\n\n /**\n * Start periodic sync.\n */\n start(intervalMs: number): void {\n if (this.timer) return;\n this.timer = setInterval(() => this.flush(), intervalMs);\n }\n\n /**\n * Stop periodic sync and flush remaining entries.\n */\n async stop(flushOptions: FlushOptions = {}): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush(flushOptions);\n this.saveToDisk();\n }\n\n /**\n * Add a decision to the sync queue.\n */\n enqueue(context: PDLSSContext, decision: VerificationDecision): void {\n if (this.queue.length >= MAX_QUEUE_SIZE) {\n // Drop oldest entry\n this.queue.shift();\n }\n\n // Sync payloads leave the machine (and persist to disk while queued):\n // credential-scrub them at the boundary. Local evaluation already ran\n // on the raw text.\n this.queue.push({\n id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n context: redactDeep(context),\n decision: redactDeep(decision),\n timestamp: new Date(),\n retryCount: 0,\n status: 'pending',\n });\n\n this.saveToDisk();\n }\n\n /**\n * Flush pending entries to the API.\n */\n async flush(options: FlushOptions = {}): Promise<void> {\n if (this.processing) return;\n this.processing = true;\n\n try {\n const pending = this.queue.filter((e) => e.status === 'pending');\n const batch = typeof options.limit === 'number' ? pending.slice(0, options.limit) : pending;\n\n for (const entry of batch) {\n // Sync entries carry the guard's own identity (config.agentId) so the\n // platform attributes them instead of treating them as anonymous.\n const attempt = verifyOnline(this.config, entry.context, this.config.agentId)\n .then(() => 'synced' as const)\n .catch(() => 'error' as const);\n const result = options.perEntryTimeoutMs\n ? await Promise.race([attempt, delay(options.perEntryTimeoutMs)])\n : await attempt;\n\n if (result === FLUSH_TIMEOUT) {\n // Slow network: leave the entry pending without a retry penalty and\n // stop burning budget on the rest of the batch.\n break;\n }\n if (result === 'synced') {\n entry.status = 'synced';\n } else {\n entry.retryCount++;\n if (entry.retryCount >= MAX_RETRIES) {\n entry.status = 'failed';\n }\n }\n }\n\n // Remove synced and permanently failed entries\n this.queue = this.queue.filter((e) => e.status === 'pending');\n this.saveToDisk();\n } finally {\n this.processing = false;\n }\n }\n\n /**\n * Get queue status.\n */\n getStatus(): { pending: number; total: number } {\n return {\n pending: this.queue.filter((e) => e.status === 'pending').length,\n total: this.queue.length,\n };\n }\n\n /**\n * Load persisted queue entries from disk.\n */\n private loadFromDisk(): void {\n if (!this.persistPath) return;\n\n try {\n if (!existsSync(this.persistPath)) return;\n const data = readFileSync(this.persistPath, 'utf-8');\n const entries = JSON.parse(data) as SyncQueueEntry[];\n // Only restore pending entries\n this.queue = entries\n .filter((e) => e.status === 'pending')\n .map((e) => ({ ...e, timestamp: new Date(e.timestamp) }));\n } catch {\n // Corrupted file or read error — start with empty queue\n this.queue = [];\n }\n }\n\n /**\n * Persist queue entries to disk.\n */\n private saveToDisk(): void {\n if (!this.persistPath) return;\n\n try {\n const dir = dirname(this.persistPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(this.persistPath, JSON.stringify(this.queue, null, 2), 'utf-8');\n } catch {\n // Best-effort — don't crash if disk write fails\n }\n }\n}\n\n/**\n * Verify in hybrid mode: local eval + queued sync.\n */\nexport function verifyHybrid(\n evaluator: LocalEvaluator,\n syncQueue: HybridSyncQueue,\n context: PDLSSContext\n): VerificationDecision {\n // Local evaluation is the immediate response\n const decision = evaluator.evaluate(context);\n\n // Queue for async API sync (fire-and-forget)\n syncQueue.enqueue(context, decision);\n\n return decision;\n}\n","/**\n * Secret redaction for Local Guard trace files and hybrid sync payloads.\n *\n * Raw tool-call text (shell commands, file contents, URLs) routinely carries\n * live credentials — the passive-week traces captured a GitHub PAT and org\n * API keys verbatim. Evaluation always runs on the RAW text (policy matching\n * needs it); redaction applies only at the persistence boundaries:\n * TraceLogger writes and HybridSyncQueue enqueue.\n *\n * Deny-list philosophy mirrors metadata-capture's sanitizeHeaders: match\n * known credential shapes, replace with a typed marker, keep everything else\n * verbatim. False positives (redacting a non-secret) are acceptable; false\n * negatives are the failure mode to avoid.\n */\n\ninterface RedactionPattern {\n type: string;\n re: RegExp;\n /** Replacement; defaults to the bare marker. */\n replacement?: string;\n}\n\nconst marker = (type: string) => `[REDACTED:${type}]`;\n\nconst REDACTION_PATTERNS: RedactionPattern[] = [\n // Multi-line blocks first so later single-line patterns don't shred them.\n {\n type: 'private-key',\n re: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*?(?:-----END [A-Z ]*PRIVATE KEY-----|$)/g,\n },\n // URL userinfo credentials (https://user:pass@, x-access-token:ghp_…@).\n {\n type: 'url-credentials',\n re: /([a-z][a-z0-9+.-]*:\\/\\/)[^\\s/@]+:[^\\s/@]+@/gi,\n replacement: `$1${marker('url-credentials')}@`,\n },\n // Known token formats.\n { type: 'github-token', re: /\\bgh[pousr]_[A-Za-z0-9]{20,255}\\b/g },\n { type: 'github-token', re: /\\bgithub_pat_[A-Za-z0-9_]{20,255}\\b/g },\n { type: 'astrasync-key', re: /\\bkya_[A-Fa-f0-9]{32,128}\\b/g },\n { type: 'openai-key', re: /\\bsk-[A-Za-z0-9_-]{20,}\\b/g },\n { type: 'aws-access-key-id', re: /\\bAKIA[0-9A-Z]{16}\\b/g },\n { type: 'jwt', re: /\\beyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\b/g },\n // Bearer/token headers.\n {\n type: 'bearer-token',\n re: /\\b(bearer\\s+)[a-z0-9._~+/=-]{16,}/gi,\n replacement: `$1${marker('bearer-token')}`,\n },\n // Generic KEY=value / key: value assignments with secret-ish names.\n {\n type: 'assigned-secret',\n re: /\\b((?:password|passwd|secret|token|api[_-]?key|apikey|access[_-]?key|client[_-]?secret|private[_-]?key)\\s*[=:]\\s*)(['\"]?)[^\\s'\"&;]{8,}\\2/gi,\n replacement: `$1$2${marker('assigned-secret')}$2`,\n },\n];\n\n/**\n * Replace credential-shaped substrings in `text` with `[REDACTED:<type>]`\n * markers. Pure; safe on arbitrary text.\n */\nexport function redactSecrets(text: string): string {\n let result = text;\n for (const { type, re, replacement } of REDACTION_PATTERNS) {\n result = result.replace(re, replacement ?? marker(type));\n }\n return result;\n}\n\n/**\n * Deep-redact every string field of a JSON-ish value (objects, arrays,\n * strings). Non-string leaves (numbers, booleans, Dates, null) pass through\n * untouched. Returns a new value; the input is never mutated.\n */\nexport function redactDeep<T>(value: T): T {\n if (typeof value === 'string') {\n return redactSecrets(value) as unknown as T;\n }\n if (Array.isArray(value)) {\n return value.map((item) => redactDeep(item)) as unknown as T;\n }\n if (value !== null && typeof value === 'object' && !(value instanceof Date)) {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = redactDeep(v);\n }\n return out as unknown as T;\n }\n return value;\n}\n","/**\n * Trace Logger — append-only JSONL audit trail.\n *\n * Cherry-picked from trust-harness-core and simplified.\n * Writes evaluation events to .astrasync/traces/ as JSONL files,\n * one file per day, with rotation.\n */\n\nimport { appendFileSync, mkdirSync, existsSync, statSync, readdirSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport type { TraceEvent, PDLSSContext, VerificationDecision } from './types';\nimport { redactDeep } from './redact';\n\nconst MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB\nconst MAX_FILES = 10;\n\nexport class TraceLogger {\n private tracePath: string;\n private enabled: boolean;\n\n constructor(tracePath: string, enabled: boolean) {\n this.tracePath = tracePath;\n this.enabled = enabled;\n\n if (enabled) {\n mkdirSync(tracePath, { recursive: true });\n }\n }\n\n /**\n * Log an evaluation event.\n */\n logEvaluation(context: PDLSSContext, decision: VerificationDecision): void {\n if (!this.enabled) return;\n\n // Evaluation ran on the raw text; what hits disk is credential-scrubbed.\n // Redaction is guarded: a throw here (e.g. pathological metadata) must\n // neither lose the trace line nor fail the already-completed evaluation\n // — degrade to an error event that still records the decision outcome.\n let event: TraceEvent;\n try {\n event = {\n id: this.generateId(),\n timestamp: new Date(),\n type: 'evaluation',\n context: redactDeep(context),\n decision: redactDeep(decision),\n };\n } catch (err) {\n event = {\n id: this.generateId(),\n timestamp: new Date(),\n type: 'error',\n metadata: {\n error: `trace redaction failed: ${err instanceof Error ? err.message : String(err)}`,\n recommendation: decision.recommendation,\n purpose: context.purpose,\n action: context.action,\n },\n };\n }\n this.write(event);\n }\n\n /**\n * Log a tool call the guard saw but did not govern. One line per skip\n * keeps coverage holes (unmapped platform tools) visible in the traces\n * instead of silently indistinguishable from ALLOW.\n */\n logSkipped(toolName: string, reason: string): void {\n if (!this.enabled) return;\n\n this.write({\n id: this.generateId(),\n timestamp: new Date(),\n type: 'skipped',\n metadata: { toolName, reason },\n });\n }\n\n /**\n * Log a mode switch event.\n */\n logModeSwitch(from: string, to: string): void {\n if (!this.enabled) return;\n\n this.write({\n id: this.generateId(),\n timestamp: new Date(),\n type: 'mode_switch',\n metadata: { from, to },\n });\n }\n\n /**\n * Log an error event.\n */\n logError(error: string, context?: PDLSSContext): void {\n if (!this.enabled) return;\n\n this.write({\n id: this.generateId(),\n timestamp: new Date(),\n type: 'error',\n context,\n metadata: { error },\n });\n }\n\n private write(event: TraceEvent): void {\n let line: string;\n try {\n line = JSON.stringify(event) + '\\n';\n } catch {\n // Unserializable event — nothing sane to persist.\n return;\n }\n\n try {\n const filePath = this.getCurrentFilePath();\n\n // Rotate if needed\n if (existsSync(filePath)) {\n const stats = statSync(filePath);\n if (stats.size > MAX_FILE_SIZE) {\n this.rotate();\n }\n }\n\n // Each hook invocation is a separate process appending to the same\n // daily file; on Windows a concurrent append (or an antivirus/indexer\n // hold) throws EBUSY/EPERM. A silent drop here is how a real trace\n // line went missing during desktop verification — retry, then fall\n // back to a per-process file (same `trace-` prefix, so rotation\n // covers it), and as a last resort say so on stderr. Never silently\n // lose an audit line.\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n appendFileSync(filePath, line);\n return;\n } catch {\n // immediate retry — transient share-violations usually clear\n }\n }\n const fallbackPath = filePath.replace(/\\.jsonl$/, `-r${process.pid}.jsonl`);\n appendFileSync(fallbackPath, line);\n } catch {\n // Trace logging must never crash the gateway — but a lost audit\n // line should leave SOME evidence.\n try {\n console.error(`[AstraSync TraceLogger] failed to persist trace line: ${line.trim()}`);\n } catch {\n /* stderr unavailable — nothing left to do */\n }\n }\n }\n\n private getCurrentFilePath(): string {\n const date = new Date().toISOString().split('T')[0];\n return join(this.tracePath, `trace-${date}.jsonl`);\n }\n\n private rotate(): void {\n try {\n const files = readdirSync(this.tracePath)\n .filter((f) => f.startsWith('trace-') && f.endsWith('.jsonl'))\n .sort();\n\n while (files.length >= MAX_FILES) {\n const oldest = files.shift()!;\n unlinkSync(join(this.tracePath, oldest));\n }\n } catch {\n // Best effort rotation\n }\n }\n\n private generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n}\n","/**\n * AstraSyncGateway — Primary API surface for agent verification.\n *\n * Supports three operational modes:\n * - online: Full API-based verification with trust scoring and audit trail\n * - local: Offline PDLSS evaluation using a local policy file (no account required)\n * - hybrid: Local eval for speed + async API sync for trust scoring\n *\n * @example\n * ```typescript\n * // Local mode (free, no account)\n * const gateway = new AstraSyncGateway({ mode: 'local', policyFile: './policy.yaml' });\n * const decision = await gateway.evaluate(context);\n *\n * // Online mode (paid, full features)\n * const gateway = new AstraSyncGateway({ mode: 'online', apiKey: 'key' });\n * const decision = await gateway.evaluate(context);\n * ```\n */\n\nimport type { AstraSyncGatewayConfig, PDLSSContext, VerificationDecision } from './types';\nimport type { LocalEvaluator } from '../local-evaluator/evaluator';\nimport { loadEvaluator } from './modes/local';\nimport { verifyLocal } from './modes/local';\nimport { verifyOnline } from './modes/online';\nimport { verifyHybrid, HybridSyncQueue } from './modes/hybrid';\nimport type { FlushOptions } from './modes/hybrid';\nimport { TraceLogger } from './trace-logger';\n\nexport class AstraSyncGateway {\n private config: AstraSyncGatewayConfig;\n private evaluator: LocalEvaluator | null = null;\n private syncQueue: HybridSyncQueue | null = null;\n private traceLogger: TraceLogger | null = null;\n private initialized = false;\n\n constructor(config: AstraSyncGatewayConfig) {\n this.config = config;\n this.validateConfig();\n }\n\n private validateConfig(): void {\n const { mode } = this.config;\n\n if (mode === 'online') {\n if (!this.config.apiBaseUrl && !this.config.apiKey) {\n throw new Error('Online mode requires apiBaseUrl or apiKey');\n }\n }\n\n if (mode === 'local') {\n if (!this.config.policyFile && !this.config.policy) {\n throw new Error('Local mode requires policyFile or policy');\n }\n }\n\n if (mode === 'hybrid') {\n if (!this.config.policyFile && !this.config.policy) {\n throw new Error('Hybrid mode requires policyFile or policy');\n }\n }\n }\n\n /**\n * Initialize the gateway (loads policy files, starts sync queues).\n * Called automatically on first evaluate() if not called manually.\n */\n async initialize(): Promise<void> {\n if (this.initialized) return;\n\n const { mode } = this.config;\n\n if (mode === 'local' || mode === 'hybrid') {\n this.evaluator = loadEvaluator(this.config);\n }\n\n if (mode === 'hybrid') {\n const persistPath = this.config.tracePath\n ? `${this.config.tracePath}/../sync-queue.json`\n : '.astrasync/sync-queue.json';\n this.syncQueue = new HybridSyncQueue(this.config, persistPath);\n const intervalMs = (this.config.syncInterval || 3600) * 1000;\n this.syncQueue.start(intervalMs);\n }\n\n // Initialize trace logger\n if (this.config.traceEnabled) {\n const tracePath = this.config.tracePath || '.astrasync/traces';\n this.traceLogger = new TraceLogger(tracePath, true);\n }\n\n this.initialized = true;\n\n if (this.config.debug) {\n const posture = this.config.posture || 'active';\n console.log(`[AstraSyncGateway] Initialized in ${mode} mode (${posture})`);\n }\n }\n\n /**\n * Graceful shutdown. Flushes sync queue and cleans up resources.\n * Stateless callers (hooks) pass bounded flush options so sync never\n * sits on a tool call's critical path.\n */\n async shutdown(options?: { syncFlush?: FlushOptions }): Promise<void> {\n if (this.syncQueue) {\n await this.syncQueue.stop(options?.syncFlush ?? {});\n this.syncQueue = null;\n }\n\n this.evaluator = null;\n this.initialized = false;\n\n if (this.config.debug) {\n console.log('[AstraSyncGateway] Shut down');\n }\n }\n\n /**\n * Evaluate an action against the verification policy.\n * Routes to the appropriate mode handler.\n *\n * In passive posture, evaluation runs but always returns ALLOW\n * (the real decision is logged for telemetry).\n */\n async evaluate(context: PDLSSContext, astraId?: string): Promise<VerificationDecision> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n let decision: VerificationDecision;\n\n switch (this.config.mode) {\n case 'online':\n decision = await verifyOnline(this.config, context, astraId ?? this.config.agentId);\n break;\n\n case 'local':\n if (!this.evaluator) throw new Error('Local evaluator not initialized');\n decision = verifyLocal(this.evaluator, context);\n break;\n\n case 'hybrid':\n if (!this.evaluator || !this.syncQueue) throw new Error('Hybrid mode not initialized');\n decision = verifyHybrid(this.evaluator, this.syncQueue, context);\n break;\n\n default:\n throw new Error(`Unknown mode: ${this.config.mode}`);\n }\n\n // In passive posture, log but don't block\n if (this.config.posture === 'passive' && decision.recommendation !== 'ALLOW') {\n decision = {\n ...decision,\n recommendation: 'ALLOW',\n reason: `[PASSIVE] Would have been ${decision.recommendation}: ${decision.reason}`,\n };\n }\n\n // Trace logging — captures the final decision (including passive override)\n this.traceLogger?.logEvaluation(context, decision);\n\n return decision;\n }\n\n /**\n * Get the current mode.\n */\n get mode(): AstraSyncGatewayConfig['mode'] {\n return this.config.mode;\n }\n\n /**\n * Get the current posture (active or passive).\n */\n get posture(): 'active' | 'passive' {\n return this.config.posture || 'active';\n }\n\n /**\n * Switch modes at runtime (e.g. after upgrade from free to paid).\n */\n async switchMode(\n newMode: AstraSyncGatewayConfig['mode'],\n additionalConfig?: Partial<AstraSyncGatewayConfig>\n ): Promise<void> {\n const oldMode = this.config.mode;\n await this.shutdown();\n\n this.config = { ...this.config, ...additionalConfig, mode: newMode };\n this.validateConfig();\n await this.initialize();\n\n this.traceLogger?.logModeSwitch(oldMode, newMode);\n\n if (this.config.debug) {\n console.log(`[AstraSyncGateway] Switched to ${newMode} mode`);\n }\n }\n\n /**\n * Get sync queue status (hybrid mode only).\n */\n getSyncStatus(): { pending: number; total: number } | null {\n return this.syncQueue?.getStatus() || null;\n }\n\n /**\n * Record a tool call the calling adapter saw but did not govern\n * (unmapped tool, skipTools, MCP with governMcp off). Trace-only.\n */\n logSkippedTool(toolName: string, reason: string): void {\n this.traceLogger?.logSkipped(toolName, reason);\n }\n}\n","/**\n * Local Guard configuration resolution — shared by every hook-based\n * adapter (Claude Code, Codex CLI). Deliberately free of any process\n * entry point: hook binaries import from here, and bundling this module\n * into a bin entry must never execute anything.\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\n\nexport interface GuardSettings {\n posture?: 'active' | 'passive';\n failOpen?: boolean;\n skipTools?: string[];\n /** Govern MCP tools; default true (see adapter options) */\n governMcp?: boolean;\n /**\n * Gateway mode. 'local' (default) decides entirely on-device; 'hybrid'\n * decides locally AND queues redacted evaluation events for async upload\n * to the platform audit trail. Bare 'online' is deliberately not offered:\n * the guard must never block a tool call on network I/O.\n */\n mode?: 'local' | 'hybrid';\n /** AstraSync API base URL (required for hybrid), e.g. https://api.astrasync.ai */\n apiBaseUrl?: string;\n /** Org API key authenticating the sync upload (required for hybrid) */\n apiKey?: string;\n /** ASTRA- agent id the guard syncs as (recommended for hybrid) */\n agentId?: string;\n}\n\nexport interface ResolvedGuardConfig {\n policyFile: string;\n /** The .astrasync directory the policy came from (traces live here too) */\n guardDir: string;\n settings: GuardSettings;\n}\n\n/**\n * Locate the governing policy: project (.astrasync/policy.yaml under\n * CLAUDE_PROJECT_DIR, then the payload cwd) overrides the user-level\n * ~/.astrasync/policy.yaml. Returns null when no policy exists anywhere.\n */\nexport function resolveGuardConfig(\n env: NodeJS.ProcessEnv,\n payloadCwd?: string,\n home: string = homedir()\n): ResolvedGuardConfig | null {\n const candidateRoots = [env.CLAUDE_PROJECT_DIR, payloadCwd, home].filter(\n (root): root is string => typeof root === 'string' && root.length > 0\n );\n\n for (const root of candidateRoots) {\n const guardDir = join(root, '.astrasync');\n const policyFile = join(guardDir, 'policy.yaml');\n if (!existsSync(policyFile)) continue;\n\n let settings: GuardSettings = {};\n const settingsFile = join(guardDir, 'guard.json');\n if (existsSync(settingsFile)) {\n try {\n settings = JSON.parse(readFileSync(settingsFile, 'utf-8')) as GuardSettings;\n } catch {\n // A corrupt guard.json must not silently loosen the guard:\n // ignore it and run with defaults (active posture, fail-closed).\n settings = {};\n }\n }\n\n return { policyFile, guardDir, settings };\n }\n\n return null;\n}\n","/**\n * AstraSync Local Guard for Claude Code — settings.json installer.\n *\n * Merges the guard's PreToolUse hook entry into a Claude Code settings\n * file (~/.claude/settings.json or <project>/.claude/settings.json)\n * without clobbering anything else in it, and builds the default policy\n * for a coding agent.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { dirname } from 'path';\nimport type { LocalPolicy } from '../gateway/types';\nimport { DEFAULT_BLOCKED_COMMANDS, DEFAULT_BLOCKED_PATHS, RISK_PRESETS } from '../cli/wizard';\nimport { parseFile, toYaml } from '../local-evaluator/pdlss-parser';\n\n/** Substring that identifies the guard's hook entry inside settings.json */\nexport const ASTRASYNC_HOOK_MARKER = 'astrasync-claude-hook';\n\n/**\n * Tools worth spawning the hook for. Matcher-side filtering keeps\n * bookkeeping tools (TodoWrite etc.) from paying node startup cost.\n */\nexport const HOOK_MATCHER =\n 'Bash|PowerShell|Write|Edit|MultiEdit|NotebookEdit|Read|Glob|Grep|WebFetch|WebSearch|Task|Agent|mcp__.*';\n\nconst HOOK_TIMEOUT_SECONDS = 10;\n\n// -----------------------------------------------------------------------\n// Settings file shapes (only the parts we touch)\n// -----------------------------------------------------------------------\n\ninterface HookCommand {\n type: string;\n command: string;\n timeout?: number;\n [key: string]: unknown;\n}\n\ninterface HookMatcherEntry {\n matcher?: string;\n hooks?: HookCommand[];\n [key: string]: unknown;\n}\n\ninterface ClaudeSettings {\n hooks?: {\n PreToolUse?: HookMatcherEntry[];\n [key: string]: unknown;\n };\n permissions?: {\n deny?: unknown;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\nexport interface InstallResult {\n installed: boolean;\n alreadyPresent: boolean;\n updated: boolean;\n}\n\nfunction isGuardEntry(entry: HookMatcherEntry, marker: string): boolean {\n return (entry.hooks ?? []).some(\n (h) => typeof h.command === 'string' && h.command.includes(marker)\n );\n}\n\nfunction readSettings(settingsPath: string): ClaudeSettings {\n if (!existsSync(settingsPath)) return {};\n const content = readFileSync(settingsPath, 'utf-8').trim();\n if (!content) return {};\n return JSON.parse(content) as ClaudeSettings;\n}\n\nfunction writeSettings(settingsPath: string, settings: ClaudeSettings): void {\n mkdirSync(dirname(settingsPath), { recursive: true });\n writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\\n`, 'utf-8');\n}\n\nexport function buildHookEntry(\n hookCommand: string,\n matcher: string = HOOK_MATCHER,\n extraHookFields: Record<string, unknown> = {}\n): HookMatcherEntry {\n return {\n matcher,\n hooks: [\n { type: 'command', command: hookCommand, timeout: HOOK_TIMEOUT_SECONDS, ...extraHookFields },\n ],\n };\n}\n\n/**\n * Merge the guard's PreToolUse entry into a hooks settings file.\n * Claude Code's settings.json and Codex CLI's hooks.json share this JSON\n * shape (`hooks.PreToolUse[].hooks[]`), so the Codex installer reuses this\n * with its own marker/matcher. Never clobbers: preserves unknown keys,\n * foreign hooks, and other PreToolUse entries. Idempotent — re-running\n * updates our entry in place.\n *\n * Throws if the existing settings file is not valid JSON (never overwrite\n * a file we cannot faithfully rewrite).\n */\nexport function installClaudeHooks(\n settingsPath: string,\n hookCommand: string,\n marker: string = ASTRASYNC_HOOK_MARKER,\n matcher: string = HOOK_MATCHER,\n extraHookFields: Record<string, unknown> = {}\n): InstallResult {\n if (!hookCommand.includes(marker)) {\n throw new Error(\n `Hook command must reference ${marker} (got: ${hookCommand}) — ` +\n 'the marker is how install/uninstall identify the guard entry.'\n );\n }\n\n const settings = readSettings(settingsPath);\n settings.hooks = settings.hooks ?? {};\n const preToolUse = (settings.hooks.PreToolUse = settings.hooks.PreToolUse ?? []);\n\n const existing = preToolUse.find((entry) => isGuardEntry(entry, marker));\n if (existing) {\n const fresh = buildHookEntry(hookCommand, matcher, extraHookFields);\n const changed = JSON.stringify(existing) !== JSON.stringify(fresh);\n if (changed) {\n preToolUse[preToolUse.indexOf(existing)] = fresh;\n writeSettings(settingsPath, settings);\n }\n return { installed: false, alreadyPresent: true, updated: changed };\n }\n\n preToolUse.push(buildHookEntry(hookCommand, matcher, extraHookFields));\n writeSettings(settingsPath, settings);\n return { installed: true, alreadyPresent: false, updated: false };\n}\n\n/**\n * Remove the guard's PreToolUse entry. Leaves everything else untouched;\n * prunes hooks.PreToolUse / hooks only if the guard was their sole content.\n * Returns true if an entry was removed.\n */\nexport function uninstallClaudeHooks(\n settingsPath: string,\n marker: string = ASTRASYNC_HOOK_MARKER\n): boolean {\n if (!existsSync(settingsPath)) return false;\n\n let settings: ClaudeSettings;\n try {\n settings = readSettings(settingsPath);\n } catch {\n return false;\n }\n\n const preToolUse = settings.hooks?.PreToolUse;\n if (!preToolUse) return false;\n\n const remaining = preToolUse.filter((entry) => !isGuardEntry(entry, marker));\n if (remaining.length === preToolUse.length) return false;\n\n if (remaining.length > 0) {\n settings.hooks!.PreToolUse = remaining;\n } else {\n delete settings.hooks!.PreToolUse;\n if (Object.keys(settings.hooks!).length === 0) delete settings.hooks;\n }\n\n writeSettings(settingsPath, settings);\n return true;\n}\n\n// -----------------------------------------------------------------------\n// Claude Code native permission rules (settings self-protection)\n// -----------------------------------------------------------------------\n\n/**\n * Paths the guard denies via Claude Code's native permissions.deny, in\n * addition to the hook's blockedPatterns. Needed because Claude Code\n * evaluates permission rules BEFORE PreToolUse hooks, enforces them even\n * when the guard posture is passive, and rejects schema-invalid settings\n * edits without ever invoking the hook — so the hook alone cannot fully\n * protect the settings file it is registered in. A governed agent also\n * cannot remove these rules: the removal edit is itself denied\n * (runtime-verified on Claude Code 2.1.210, 2026-07-15).\n *\n * Both `~/` and `**` forms ship because bare globs are anchored relative\n * to cwd/settings-dir per the gitignore spec; unmatched forms are inert.\n */\nconst PERMISSION_DENY_PATHS = [\n '**/.claude/settings.json',\n '**/.claude/settings.local.json',\n '~/.claude/settings.json',\n '~/.claude/settings.local.json',\n '**/.astrasync/**',\n '~/.astrasync/**',\n];\n\n/**\n * The guard's canonical permissions.deny rule strings.\n *\n * Edit() rules only: Claude Code's file permission checks match Edit(path)\n * rules against every file-editing tool (Write/NotebookEdit included) and\n * warn at session start that Write(path) rules are never matched.\n *\n * Claude-Code-only — never install these into Codex's hooks.json, which\n * has no permissions concept. Ownership is by exact string match (deny\n * entries have no marker field), so these strings are the contract:\n * when a rule changes form, move the old string to\n * LEGACY_GUARD_PERMISSION_DENY_RULES so install/uninstall clean it up.\n */\nexport const GUARD_PERMISSION_DENY_RULES: readonly string[] = PERMISSION_DENY_PATHS.map(\n (p) => `Edit(${p})`\n);\n\n/** Rule strings shipped by previous versions, no longer canonical. */\nexport const LEGACY_GUARD_PERMISSION_DENY_RULES: readonly string[] = [];\n\nexport interface PermissionRulesResult {\n addedRules: string[];\n removedStaleRules: string[];\n changed: boolean;\n}\n\nfunction readDenyRules(settings: ClaudeSettings, settingsPath: string): string[] {\n const permissions = settings.permissions;\n if (\n permissions !== undefined &&\n (typeof permissions !== 'object' || Array.isArray(permissions) || permissions === null)\n ) {\n throw new Error(`${settingsPath}: \"permissions\" is not an object — refusing to rewrite it.`);\n }\n const deny = permissions?.deny;\n if (deny === undefined) return [];\n if (!Array.isArray(deny) || deny.some((r) => typeof r !== 'string')) {\n throw new Error(\n `${settingsPath}: \"permissions.deny\" is not an array of strings — refusing to rewrite it.`\n );\n }\n return deny as string[];\n}\n\n/**\n * Merge the guard's permissions.deny rules into a Claude Code settings\n * file. User rules keep their positions; guard rules append at the end;\n * stale (legacy-form) guard rules are dropped. Idempotent; writes only on\n * change. Throws on invalid JSON or a wrong-typed permissions block.\n *\n * These rules live in the very file they protect — mutual reinforcement\n * with the PreToolUse hook, not an independent root of trust.\n */\nexport function installClaudePermissionRules(\n settingsPath: string,\n rules: readonly string[] = GUARD_PERMISSION_DENY_RULES,\n staleRules: readonly string[] = LEGACY_GUARD_PERMISSION_DENY_RULES\n): PermissionRulesResult {\n const settings = readSettings(settingsPath);\n const deny = readDenyRules(settings, settingsPath);\n\n const stale = new Set(staleRules);\n const removedStaleRules = deny.filter((r) => stale.has(r));\n const kept = deny.filter((r) => !stale.has(r));\n\n const present = new Set(kept);\n const addedRules = rules.filter((r) => !present.has(r));\n\n const changed = addedRules.length > 0 || removedStaleRules.length > 0;\n if (changed) {\n settings.permissions = settings.permissions ?? {};\n settings.permissions.deny = [...kept, ...addedRules];\n writeSettings(settingsPath, settings);\n }\n return { addedRules, removedStaleRules, changed };\n}\n\n/**\n * Remove the guard's permissions.deny rules (canonical + legacy forms).\n * Prunes an emptied deny array / permissions object; everything else is\n * untouched. Returns the removed strings — ownership is exact-string\n * match, so a rule the user added independently is removed too; callers\n * should surface the returned list so the user can re-add their own.\n */\nexport function uninstallClaudePermissionRules(\n settingsPath: string,\n rules: readonly string[] = GUARD_PERMISSION_DENY_RULES,\n staleRules: readonly string[] = LEGACY_GUARD_PERMISSION_DENY_RULES\n): string[] {\n if (!existsSync(settingsPath)) return [];\n\n let settings: ClaudeSettings;\n let deny: string[];\n try {\n settings = readSettings(settingsPath);\n deny = readDenyRules(settings, settingsPath);\n } catch {\n return [];\n }\n if (deny.length === 0) return [];\n\n const ours = new Set([...rules, ...staleRules]);\n const removed = deny.filter((r) => ours.has(r));\n if (removed.length === 0) return [];\n\n const remaining = deny.filter((r) => !ours.has(r));\n if (remaining.length > 0) {\n settings.permissions!.deny = remaining;\n } else {\n delete settings.permissions!.deny;\n if (Object.keys(settings.permissions!).length === 0) delete settings.permissions;\n }\n\n writeSettings(settingsPath, settings);\n return removed;\n}\n\n// -----------------------------------------------------------------------\n// Default policy for a coding agent\n// -----------------------------------------------------------------------\n\n/**\n * Hook-layer patterns that keep a governed agent from disabling its own\n * guard by editing the hook config or policy. Effective only when the\n * hook fires AND posture is active — for Claude Code's own settings files\n * that is not sufficient (see GUARD_PERMISSION_DENY_RULES), so the\n * installer pairs these with native permissions.deny rules.\n */\nexport const GUARD_SELF_PROTECTION_PATTERNS = [\n '**/.claude/settings.json',\n '**/.claude/settings.local.json',\n '**/.astrasync/**',\n '**/.codex/hooks.json',\n '**/.codex/config.toml',\n];\n\n/**\n * Ensure an existing policy file's file.write rule carries the guard\n * self-protection patterns (used after the interactive wizard, whose\n * questions don't know about the guard's own files). No-op when the\n * patterns are already present or the file has no file.write rule.\n * Returns true if the file was modified.\n */\nexport function ensureGuardSelfProtection(policyPath: string): boolean {\n const parsed = parseFile(policyPath);\n if (!parsed.validation.valid || !parsed.policy) return false;\n\n const fileWrite = parsed.policy.purposes.find((p) => p.id === 'file.write');\n if (!fileWrite || !fileWrite.allowed) return false;\n\n const existing = new Set(fileWrite.blockedPatterns ?? []);\n const missing = GUARD_SELF_PROTECTION_PATTERNS.filter((p) => !existing.has(p));\n if (missing.length === 0) return false;\n\n fileWrite.blockedPatterns = [...(fileWrite.blockedPatterns ?? []), ...missing];\n writeFileSync(policyPath, toYaml(parsed.policy), 'utf-8');\n return true;\n}\n\n/**\n * Default Local Guard policy for Claude Code.\n *\n * Tuned for a coding agent that already has its own permission layer:\n * - permissive risk preset — HIGH_RISK commands (git push, curl, docker…)\n * surface as \"ask\" (Claude Code's native prompt), never auto-block;\n * - the wizard's recommended blocked commands (sudo, rm -rf, curl|bash…)\n * and credential paths (~/.ssh, ~/.aws, .env…) hard-deny;\n * - guard self-protection patterns hard-deny writes to the guard's own\n * config (backed by native permissions.deny rules for Claude Code's\n * settings files, which the hook alone cannot fully protect);\n * - MCP purposes are intentionally absent: pair with governMcp=false\n * until specific {server}.{tool} rules are added.\n */\nexport function buildDefaultClaudeCodePolicy(name = 'claude-code-local-guard'): LocalPolicy {\n const recommendedCommands = DEFAULT_BLOCKED_COMMANDS.filter((c) => c.recommended).map(\n (c) => c.pattern\n );\n const recommendedPaths = DEFAULT_BLOCKED_PATHS.filter((p) => p.recommended).map((p) => p.pattern);\n const permissive = RISK_PRESETS.find((p) => p.name === 'permissive')!;\n\n return {\n version: '1.0',\n name,\n description:\n 'AstraSync Local Guard for Claude Code — default coding-agent policy. ' +\n 'Edit freely; the hook re-reads this file on every tool call.',\n purposes: [\n {\n id: 'file.read',\n allowed: true,\n blockedPatterns: recommendedPaths,\n },\n {\n id: 'file.write',\n allowed: true,\n blockedPatterns: [...GUARD_SELF_PROTECTION_PATTERNS, ...recommendedPaths],\n },\n {\n id: 'shell.exec',\n allowed: true,\n blockedPatterns: recommendedCommands,\n },\n { id: 'network.request', allowed: true },\n { id: 'sub_agent.spawn', allowed: true },\n ],\n riskThresholds: permissive.thresholds,\n };\n}\n","/**\n * AstraSync Local Guard for Codex CLI — hooks.json installer.\n *\n * Codex reads hooks from ~/.codex/hooks.json (user scope) or\n * <repo>/.codex/hooks.json (project scope) with the SAME JSON shape as\n * Claude Code's settings.json (`hooks.PreToolUse[].hooks[]`), so the merge\n * and uninstall machinery is shared with the Claude Code installer — only\n * the marker, matcher, and file location differ.\n *\n * The policy itself is shared with every other Local Guard adapter on the\n * machine: ~/.astrasync/policy.yaml + guard.json. One policy per user.\n */\n\nimport { installClaudeHooks, uninstallClaudeHooks } from '../claude-code/settings-installer';\nimport type { InstallResult } from '../claude-code/settings-installer';\n\n/** Substring that identifies the guard's hook entry inside hooks.json */\nexport const ASTRASYNC_CODEX_HOOK_MARKER = 'astrasync-codex-hook';\n\n/**\n * Tools worth spawning the hook for. Codex matchers are regexes over\n * tool_name; bookkeeping tools (update_plan) never pay node startup cost.\n */\nexport const CODEX_HOOK_MATCHER = 'Bash|apply_patch|Edit|Write|web_search|mcp__.*';\n\n/** Shown in the Codex TUI while the hook runs. */\nconst CODEX_STATUS_MESSAGE = 'AstraSync Local Guard';\n\n/**\n * Merge the guard's PreToolUse entry into a Codex hooks.json file.\n * Same never-clobber/idempotent semantics as the Claude Code installer.\n */\nexport function installCodexHooks(hooksPath: string, hookCommand: string): InstallResult {\n return installClaudeHooks(\n hooksPath,\n hookCommand,\n ASTRASYNC_CODEX_HOOK_MARKER,\n CODEX_HOOK_MATCHER,\n {\n statusMessage: CODEX_STATUS_MESSAGE,\n }\n );\n}\n\n/** Remove the guard's PreToolUse entry from a Codex hooks.json file. */\nexport function uninstallCodexHooks(hooksPath: string): boolean {\n return uninstallClaudeHooks(hooksPath, ASTRASYNC_CODEX_HOOK_MARKER);\n}\n"],"mappings":";;;;;;;;AAsEO,IAAM,4BAA4B;;;AC1DzC,IAAM,mBAA2C;AAAA;AAAA,EAE/C,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,SAAS;AAAA,EACT,eAAe;AAAA,EACf,sBAAsB;AAAA;AAAA,EAGtB,WAAW;AAAA,EACX,WAAW;AAAA;AAAA,EAGX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,WAAW;AAAA;AAAA,EAGX,aAAa;AAAA,EACb,aAAa;AAAA;AAAA,EAGb,cAAc;AAAA,EACd,OAAO;AAAA,EACP,aAAa;AAAA;AAAA,EAGb,YAAY;AAAA,EACZ,YAAY;AAAA;AAAA,EAGZ,cAAc;AAAA;AAAA,EAGd,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAGhB,iBAAiB;AACnB;AAMO,SAAS,iBAAiB,UAA0B;AACzD,SAAO,iBAAiB,QAAQ,KAAK,QAAQ,QAAQ;AACvD;AAMO,SAAS,qBAAqB,UAAwC;AAC3E,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACtD,QAAI,EAAE,QAAQ,mBAAmB;AAC/B,uBAAiB,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AACF;AAUO,SAAS,cAAc,UAAkB,MAAuC;AACrF,QAAM,UAAU,iBAAiB,QAAQ;AAEzC,MAAI,QAAQ,WAAW,QAAQ,GAAG;AAChC,WAAO,OAAO,KAAK,WAAW,KAAK,OAAO,KAAK,UAAU,EAAE;AAAA,EAC7D;AAEA,MAAI,QAAQ,WAAW,OAAO,GAAG;AAC/B,WAAO,OAAO,KAAK,QAAQ,KAAK,QAAQ,KAAK,YAAY,KAAK,aAAa,EAAE;AAAA,EAC/E;AAEA,MAAI,QAAQ,WAAW,UAAU,GAAG;AAClC,WAAO,OAAO,KAAK,OAAO,KAAK,YAAY,KAAK,OAAO,EAAE;AAAA,EAC3D;AAEA,MAAI,QAAQ,WAAW,QAAQ,GAAG;AAChC,WAAO,OAAO,KAAK,MAAM,KAAK,aAAa,KAAK,WAAW,EAAE;AAAA,EAC/D;AAEA,MAAI,QAAQ,WAAW,WAAW,GAAG;AACnC,WAAO,OAAO,KAAK,SAAS,KAAK,SAAS,EAAE;AAAA,EAC9C;AAEA,MAAI,QAAQ,WAAW,UAAU,GAAG;AAClC,WAAO,OAAO,KAAK,eAAe,KAAK,YAAY,KAAK,UAAU,EAAE;AAAA,EACtE;AAGA,MAAI,KAAK,QAAS,QAAO,OAAO,KAAK,OAAO;AAC5C,MAAI,KAAK,KAAM,QAAO,OAAO,KAAK,IAAI;AACtC,MAAI,KAAK,IAAK,QAAO,OAAO,KAAK,GAAG;AAGpC,aAAW,OAAO,OAAO,OAAO,IAAI,GAAG;AACrC,QAAI,OAAO,QAAQ,YAAY,IAAI,SAAS,EAAG,QAAO;AAAA,EACxD;AACA,SAAO;AACT;AAUO,SAAS,sBAAsB,QAAsC;AAC1E,MAAI;AACF,QAAI,OAAO,WAAW,SAAS,KAAK,OAAO,WAAW,UAAU,GAAG;AACjE,YAAM,MAAM,IAAI,IAAI,MAAM;AAC1B,aAAO,CAAC,IAAI,QAAQ;AAAA,IACtB;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;;;AC5FO,SAAS,WAAW,UAAiC;AAC1D,QAAM,QAAQ,qBAAqB,KAAK,QAAQ;AAChD,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,GAAG,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AAChC;;;AClCO,IAAM,iBAAyC;AAAA,EACpD,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,EACN,OAAO;AAAA,EACP,YAAY;AACd;AAEA,IAAI,aAAa;AAMV,SAAS,wBAA8B;AAC5C,MAAI,WAAY;AAChB,uBAAqB,cAAc;AACnC,eAAa;AACf;AAQO,SAAS,uBAAuB,WAA6B;AAClE,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK;AACX,MAAI;AACJ,UAAQ,QAAQ,GAAG,KAAK,SAAS,OAAO,MAAM;AAC5C,UAAM,IAAI,MAAM,CAAC,EAAE,KAAK;AACxB,QAAI,EAAG,OAAM,KAAK,CAAC;AAAA,EACrB;AACA,SAAO;AACT;;;AC+BO,IAAM,8BAA8B,oBAAI,IAAI,CAAC,WAAW,mBAAmB,CAAC;AAO5E,IAAM,qBAAqB,CAAC,aAAa;AAwBzC,IAAM,eAAN,MAA8C;AAAA,EASnD,YAAY,SAA+B;AAR3C,SAAS,mBAAmB;AAM5B,SAAQ,aAAa;AAGnB,SAAK,YAAY,IAAI,IAAI,SAAS,aAAa,kBAAkB;AACjE,SAAK,iBAAiB,SAAS,kBAAkB;AACjD,SAAK,YAAY,SAAS,aAAa;AACvC,0BAAsB;AAAA,EACxB;AAAA,EAEA,IAAI,YAAqB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,WAAW,QAAsC;AACrD,SAAK,UAAU,OAAO;AAEtB,QAAI,MAAM,QAAQ,OAAO,eAAe,SAAS,GAAG;AAClD,WAAK,YAAY,IAAI,IAAI,OAAO,eAAe,SAAqB;AAAA,IACtE;AACA,QAAI,OAAO,OAAO,eAAe,mBAAmB,WAAW;AAC7D,WAAK,iBAAiB,OAAO,eAAe;AAAA,IAC9C;AAEA,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAM,WAA0B;AAC9B,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAM,gBAAgB,QAA+C;AACnE,UAAM,MAAM,OAAO;AAEnB,QAAI,CAAC,OAAO,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,WAAW,GAAG;AAC3E,aAAO,EAAE,aAAa,OAAO,YAAY,0BAA0B;AAAA,IACrE;AAEA,QAAI,KAAK,UAAU,IAAI,IAAI,SAAS,GAAG;AACrC,aAAO,EAAE,aAAa,OAAO,YAAY,QAAQ,IAAI,SAAS,mBAAmB;AAAA,IACnF;AAEA,UAAM,QAAQ,WAAW,IAAI,SAAS,MAAM;AAC5C,QAAI,SAAS,CAAC,KAAK,WAAW;AAC5B,aAAO,EAAE,aAAa,OAAO,YAAY,yCAAyC;AAAA,IACpF;AAEA,UAAM,WAAW,IAAI,aAAa,kBAAkB;AACpD,QAAI,CAAC,YAAY,CAAC,KAAK,gBAAgB;AACrC,aAAO;AAAA,QACL,aAAa;AAAA,QACb,YAAY,iBAAiB,IAAI,SAAS;AAAA,MAC5C;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,eAAe,MAAM;AAC1C,WAAO,EAAE,aAAa,MAAM,QAAQ;AAAA,EACtC;AAAA,EAEA,eAAe,QAAmC;AAChD,UAAM,MAAM,OAAO;AACnB,WAAO,KAAK,aAAa,KAAK,cAAc,IAAI,WAAW,IAAI,cAAc,CAAC,CAAC,CAAC;AAAA,EAClF;AAAA,EAEQ,aAAa,KAA6B,QAA8B;AAC9E,UAAM,WAAW,IAAI;AACrB,UAAM,aAAa,WAAW,QAAQ;AACtC,UAAM,UAAU,cAAc,iBAAiB,QAAQ;AACvD,UAAM,gBAAgB,sBAAsB,MAAM;AAElD,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA,GAAI,iBAAiB,EAAE,cAAc;AAAA,MACrC,UAAU;AAAA,QACR,GAAI,IAAI,cAAc,EAAE,WAAW,IAAI,WAAW;AAAA,QAClD,GAAI,IAAI,OAAO,EAAE,KAAK,IAAI,IAAI;AAAA,QAC9B,GAAI,IAAI,mBAAmB,EAAE,gBAAgB,IAAI,gBAAgB;AAAA,QACjE,GAAI,IAAI,SAAS,EAAE,OAAO,IAAI,MAAM;AAAA,QACpC,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,qBACE,UACA,gBACwB;AACxB,YAAQ,SAAS,gBAAgB;AAAA,MAC/B,KAAK;AACH,eAAO;AAAA,UACL,oBAAoB;AAAA,YAClB,eAAe;AAAA,YACf,oBAAoB;AAAA,YACpB,0BAA0B,0BAA0B,SAAS,MAAM;AAAA,UACrE;AAAA,QACF;AAAA,MACF,KAAK;AACH,YAAI,kBAAkB,4BAA4B,IAAI,cAAc,GAAG;AACrE,iBAAO;AAAA,YACL,oBAAoB;AAAA,cAClB,eAAe;AAAA,cACf,oBAAoB;AAAA,cACpB,0BACE,4CAA4C,SAAS,MAAM,2CACxB,cAAc;AAAA,YAErD;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBAAgB,SAAkE;AACtF,UAAM,SAAsB;AAAA,MAC1B,KAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAW,oBAAI,KAAK;AAAA,IACtB;AAEA,UAAM,eAAe,MAAM,KAAK,gBAAgB,MAAM;AACtD,QAAI,CAAC,aAAa,eAAe,CAAC,aAAa,SAAS;AAGtD,WAAK,QAAQ,eAAe,QAAQ,WAAW,aAAa,cAAc,iBAAiB;AAC3F,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,MAAM,KAAK,2BAA2B,SAAS,aAAa,OAAO;AACpF,WAAO,KAAK,qBAAqB,UAAU,QAAQ,eAAe;AAAA,EACpE;AAAA,EAEA,MAAc,2BACZ,SACA,SAC+B;AAC/B,UAAM,YACJ,QAAQ,cAAc,gBAClB;AAAA,MACG,QAAQ,YAAwC,WAC9C,QAAQ,YAAwC,SACjD;AAAA,IACJ,IACA;AACN,UAAM,aAAa,YAAY,uBAAuB,SAAS,IAAI,CAAC;AAEpE,QAAI,WAAW,WAAW,GAAG;AAC3B,aAAO,KAAK,QAAQ,SAAS,OAAO;AAAA,IACtC;AAGA,QAAI,QAAqC;AACzC,UAAM,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,MAAM,EAAE;AACnD,eAAW,QAAQ,YAAY;AAC7B,YAAM,WAAW,MAAM,KAAK,QAAQ,SAAS,KAAK,aAAa,SAAS,IAAI,CAAC;AAC7E,UAAI,CAAC,SAAS,KAAK,SAAS,cAAc,IAAI,KAAK,MAAM,cAAc,GAAG;AACxE,gBAAQ;AAAA,MACV;AACA,UAAI,MAAM,mBAAmB,OAAQ;AAAA,IACvC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBAAgB,WAAgD;AAAA,EAEtE;AACF;;;ACpSA,SAAS,QAAAA,aAAY;;;ACoLd,IAAM,qBAAqB;AAAA,EAChC;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;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,kBAAkB;AAAA,EAC7B;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;;;AC/NA,IAAM,WAAW,oBAAI,IAAI;AAAA,EACvB;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,CAAC;AAGD,IAAM,YAAY;AAElB,IAAM,mBAAmB;AACzB,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB;AAG3B,IAAM,gBAAgB;AAQtB,SAAS,cAAc,SAAsC;AAC3D,QAAM,aAAa,oBAAI,IAAY;AACnC,QAAM,YAAwB,CAAC;AAC/B,aAAW,SAAS,SAAS;AAC3B,UAAM,QAAQ,MAAM,YAAY,EAAE,KAAK,EAAE,MAAM,KAAK;AACpD,QAAI,MAAM,WAAW,EAAG,YAAW,IAAI,MAAM,CAAC,CAAC;AAAA,QAC1C,WAAU,KAAK,KAAK;AAAA,EAC3B;AACA,YAAU,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC5C,SAAO,EAAE,YAAY,UAAU;AACjC;AAGA,SAAS,mBAAmB,MAAsB;AAChD,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,OAAiB,CAAC;AACxB,MAAI,aAA4B;AAChC,aAAW,QAAQ,OAAO;AACxB,QAAI,eAAe,MAAM;AACvB,UAAI,KAAK,KAAK,MAAM,WAAY,cAAa;AAC7C;AAAA,IACF;AACA,SAAK,KAAK,IAAI;AACd,UAAM,UAAU,KAAK,MAAM,wBAAwB;AACnD,QAAI,QAAS,cAAa,QAAQ,CAAC;AAAA,EACrC;AACA,SAAO,KAAK,KAAK,IAAI;AACvB;AAOA,SAAS,2BAA2B,MAAc,SAA0C;AAC1F,MAAI,SAAS;AACb,MAAI,QAAQ,OAAO,QAAQ,IAAI;AAC/B,MAAI,aAAa;AACjB,SAAO,UAAU,MAAM,aAAa,IAAI;AACtC;AACA,QAAI,QAAQ;AACZ,QAAI,MAAM,OAAO;AACjB,aAAS,IAAI,QAAQ,GAAG,IAAI,OAAO,QAAQ,KAAK;AAC9C,UAAI,OAAO,CAAC,MAAM,IAAK;AAAA,eACd,OAAO,CAAC,MAAM,KAAK;AAC1B;AACA,YAAI,UAAU,GAAG;AACf,gBAAM;AACN;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,YAAQ,OAAO,MAAM,QAAQ,GAAG,GAAG,CAAC;AACpC,aAAS,GAAG,OAAO,MAAM,GAAG,KAAK,CAAC,IAAI,OAAO,MAAM,KAAK,IAAI,MAAM,GAAG,OAAO,MAAM,CAAC,CAAC;AACpF,YAAQ,OAAO,QAAQ,IAAI;AAAA,EAC7B;AACA,SAAO;AACT;AAGA,SAAS,6BAA6B,MAAc,SAA0C;AAC5F,MAAI,CAAC,KAAK,SAAS,GAAG,EAAG,QAAO;AAChC,QAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QAAM,OAAiB,CAAC;AACxB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,QAAI,IAAI,MAAM,EAAG,SAAQ,OAAO,CAAC,CAAC;AAAA,QAC7B,MAAK,KAAK,OAAO,CAAC,CAAC;AAAA,EAC1B;AACA,SAAO,KAAK,KAAK,GAAG;AACtB;AAQA,SAAS,SAAS,OAAuB;AACvC,QAAM,QAAQ,KAAK,IAAI,MAAM,YAAY,GAAG,GAAG,MAAM,YAAY,IAAI,CAAC;AACtE,QAAM,OAAO,UAAU,KAAK,QAAQ,MAAM,MAAM,QAAQ,CAAC;AACzD,SAAO,KAAK,QAAQ,yBAAyB,EAAE;AACjD;AAEA,SAAS,aAAa,SAAiB,MAA+B;AACpE,QAAM,SAAS,QAAQ,MAAM,KAAK,EAAE,OAAO,CAAC,MAAM,WAAW,KAAK,CAAC,CAAC;AACpE,MAAI,IAAI;AACR,MAAI,OAAO;AACX,SAAO,IAAI,OAAO,QAAQ;AAExB,WAAO,IAAI,OAAO,WAAW,OAAO,CAAC,MAAM,YAAY,UAAU,KAAK,OAAO,CAAC,CAAC,GAAI;AACnF,QAAI,KAAK,OAAO,OAAQ,QAAO;AAE/B,UAAM,MAAM,SAAS,OAAO,CAAC,CAAC;AAG9B,UAAM,cAAc,CAAC,KAAK,GAAG,OAAO,MAAM,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC;AAClF,eAAW,SAAS,KAAK,WAAW;AAClC,UAAI,MAAM,UAAU,YAAY,UAAU,MAAM,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,GAAG;AACrF,eAAO,MAAM,KAAK,GAAG;AAAA,MACvB;AAAA,IACF;AACA,QAAI,KAAK,WAAW,IAAI,GAAG,EAAG,QAAO;AAGrC,QAAI,SAAS,IAAI,GAAG,KAAK,OAAO,kBAAkB;AAChD;AACA;AACA,aAAO,IAAI,OAAO,WAAW,OAAO,CAAC,EAAE,WAAW,GAAG,KAAK,UAAU,KAAK,OAAO,CAAC,CAAC,GAAI;AACtF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,eACP,SACA,MACA,SACA,OACM;AACN,MAAI,QAAQ,uBAAuB,QAAQ,SAAS,mBAAoB;AAExE,MAAI,OAAO,QAAQ,YAAY;AAC/B,SAAO,mBAAmB,IAAI;AAI9B,QAAM,UAAU,CAAC,UAAkB,eAAe,OAAO,MAAM,SAAS,QAAQ,CAAC;AACjF,SAAO,2BAA2B,MAAM,OAAO;AAC/C,SAAO,6BAA6B,MAAM,OAAO;AAGjD,SAAO,KAAK,QAAQ,YAAY,GAAG,EAAE,QAAQ,YAAY,GAAG;AAC5D,SAAO,KAAK,QAAQ,kBAAkB,GAAG;AAEzC,QAAM,WAAW,KAAK,MAAM,sBAAsB;AAClD,aAAW,WAAW,UAAU;AAC9B,UAAM,UAAU,aAAa,SAAS,IAAI;AAC1C,QAAI,QAAS,SAAQ,IAAI,OAAO;AAAA,EAClC;AACF;AAMO,SAAS,sBACd,SACA,mBAAsC,oBAC5B;AACV,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,QAAM,UAAU,oBAAI,IAAY;AAChC,iBAAe,SAAS,cAAc,gBAAgB,GAAG,SAAS,CAAC;AACnE,SAAO,CAAC,GAAG,OAAO;AACpB;AAmBO,SAAS,8BAA8B,SAA0B;AACtE,QAAM,OAAO,QAAQ,YAAY;AAEjC,QAAM,SAAS,KAAK,MAAM,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,uBAAuB,EAAE,CAAC;AAChF,MAAI,aAAa;AACjB,aAAW,SAAS,QAAQ;AAC1B,QAAI,OAAsB;AAC1B,QAAI,MAAM,SAAS,KAAK,GAAG;AACzB,UAAI,OAAO,MAAM,MAAM,MAAM,QAAQ,KAAK,IAAI,CAAC;AAC/C,YAAM,KAAK,KAAK,QAAQ,GAAG;AAC3B,UAAI,OAAO,GAAI,QAAO,KAAK,MAAM,KAAK,CAAC;AACvC,aAAO,KAAK,MAAM,OAAO,EAAE,CAAC;AAAA,IAC9B,WAAW,+BAA+B,KAAK,KAAK,GAAG;AACrD,aAAO,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,IAC3B,WAAW,8CAA8C,KAAK,KAAK,GAAG;AACpE,aAAO,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,IAC3B;AACA,QAAI,SAAS,KAAM;AAEnB,UAAM,OAAO,KAAK,QAAQ,SAAS,EAAE,EAAE,QAAQ,YAAY,EAAE;AAC7D,QAAI,cAAc,KAAK,IAAI,GAAG;AAC5B;AAAA,IACF,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,aAAa;AACtB;;;ACjOO,IAAM,iBAAN,MAAqB;AAAA,EAI1B,YAAY,QAAqB;AAFjC,SAAQ,gBAAqE,oBAAI,IAAI;AAGnF,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,QAA2B;AACtC,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,SAA6C;AAEpD,UAAM,cAAc,KAAK,OAAO,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ,OAAO;AAC7E,QAAI,CAAC,aAAa;AAChB,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,wBAAwB;AAAA,IACnE;AACA,QAAI,CAAC,YAAY,SAAS;AACxB,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,6BAA6B;AAAA,IACxE;AAGA,QAAI,YAAY,WAAW,CAAC,KAAK,kBAAkB,QAAQ,QAAQ,YAAY,OAAO,GAAG;AACvF,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,6BAA6B;AAAA,IACxE;AAGA,QACE,YAAY,mBACZ,KAAK,kBAAkB,QAAQ,QAAQ,YAAY,eAAe,GAClE;AACA,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,iCAAiC;AAAA,IAC5E;AAGA,UAAM,aAAa,KAAK,gBAAgB,OAAO;AAC/C,QAAI,YAAY;AACd,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,WAAW;AAAA,IACtD;AAGA,UAAM,gBAAgB,KAAK,YAAY,OAAO;AAC9C,QAAI,eAAe;AACjB,aAAO;AAAA,IACT;AAGA,QAAI,QAAQ,YAAY,qBAAqB,KAAK,OAAO,mBAAmB;AAC1E,UAAI,CAAC,KAAK,OAAO,kBAAkB,SAAS;AAC1C,eAAO,EAAE,gBAAgB,QAAQ,QAAQ,oCAAoC;AAAA,MAC/E;AACA,YAAM,QAAS,QAAQ,UAAU,iBAA4B;AAC7D,UACE,KAAK,OAAO,kBAAkB,aAAa,UAC3C,SAAS,KAAK,OAAO,kBAAkB,UACvC;AACA,eAAO;AAAA,UACL,gBAAgB;AAAA,UAChB,QAAQ,mBAAmB,KAAK,sBAAsB,KAAK,OAAO,kBAAkB,QAAQ;AAAA,QAC9F;AAAA,MACF;AAAA,IACF;AAGA,QAAI,YAAY,kBAAkB;AAChC,aAAO,EAAE,gBAAgB,iBAAiB,QAAQ,4BAA4B;AAAA,IAChF;AAEA,UAAM,eAAe,KAAK,oBAAoB,OAAO;AACrD,QAAI,cAAc;AAChB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,gBAAgB;AAAA;AAAA;AAAA,MAGhB,QAAQ;AAAA,MACR,qBAAqB;AAAA,QACnB,SAAS;AAAA,QACT,OAAO,CAAC,CAAC,KAAK,OAAO;AAAA,QACrB,QAAQ,CAAC,CAAC,KAAK,OAAO;AAAA,QACtB,gBAAgB,CAAC,CAAC,KAAK,OAAO;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAAgB,SAAsC;AAC5D,UAAM,QAAQ,KAAK,OAAO;AAC1B,QAAI,CAAC,MAAO,QAAO;AAGnB,QAAI,MAAM,gBAAgB;AACxB,YAAM,eAAe,KAAK,cAAc,QAAQ,MAAM;AACtD,UAAI,KAAK,kBAAkB,cAAc,MAAM,cAAc,GAAG;AAC9D,eAAO,4BAA4B,QAAQ,MAAM;AAAA,MACnD;AACA,UAAI,QAAQ,eAAe;AACzB,mBAAW,UAAU,QAAQ,eAAe;AAC1C,cAAI,KAAK,kBAAkB,KAAK,cAAc,MAAM,GAAG,MAAM,cAAc,GAAG;AAC5E,mBAAO,4BAA4B,MAAM;AAAA,UAC3C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,MAAM,oBAAoB,KAAK,kBAAkB,QAAQ,QAAQ,MAAM,gBAAgB,GAAG;AAC5F,aAAO,8BAA8B,QAAQ,MAAM;AAAA,IACrD;AAGA,QAAI,MAAM,kBAAkB,QAAQ,eAAe;AACjD,iBAAW,UAAU,QAAQ,eAAe;AAC1C,YAAI,CAAC,KAAK,kBAAkB,KAAK,cAAc,MAAM,GAAG,MAAM,cAAc,GAAG;AAC7E,iBAAO,+BAA+B,MAAM;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,YAAY,SAAoD;AACtE,UAAM,SAAS,KAAK,OAAO;AAC3B,QAAI,CAAC,OAAQ,QAAO;AAWpB,UAAM,QAAQ,QAAQ;AACtB,QACE,UAAU,UACV,QAAQ,MACP,OAAO,wBAAwB,UAAa,OAAO,yBAAyB,SAC7E;AACA,YAAM,sBAAsB,OAAO,uBAAuB;AAC1D,YAAM,YAAY,OAAO,wBAAwB,OAAO,uBAAuB;AAC/E,UAAI,QAAQ,qBAAqB;AAC/B,YAAI,SAAS,WAAW;AACtB,iBAAO;AAAA,YACL,gBAAgB;AAAA,YAChB,QAAQ,qBAAqB,KAAK,2BAA2B,SAAS;AAAA,UACxE;AAAA,QACF;AACA,eAAO;AAAA,UACL,gBAAgB;AAAA,UAChB,QAAQ,qBAAqB,KAAK,mCAAmC,mBAAmB,KAAK,SAAS;AAAA,QACxG;AAAA,MACF;AAAA,IACF;AAGA,QAAI,OAAO,uBAAuB,QAAW;AAC3C,YAAM,MAAM,QAAQ;AACpB,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,QAAQ,KAAK,cAAc,IAAI,GAAG;AACxC,YAAM,SAAS;AAEf,UAAI,CAAC,SAAS,MAAM,MAAM,cAAc,QAAQ;AAC9C,aAAK,cAAc,IAAI,KAAK,EAAE,OAAO,GAAG,aAAa,IAAI,CAAC;AAAA,MAC5D,OAAO;AACL,cAAM;AACN,YAAI,MAAM,QAAQ,OAAO,oBAAoB;AAC3C,iBAAO;AAAA,YACL,gBAAgB;AAAA,YAChB,QAAQ,wBAAwB,MAAM,KAAK,IAAI,OAAO,kBAAkB;AAAA,UAC1E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,oBAAoB,SAAoD;AAC9E,QAAI,CAAC,KAAK,OAAO,eAAgB,QAAO;AAExC,UAAM,YAAY,KAAK,mBAAmB,OAAO;AACjD,UAAM,aAAa,KAAK,OAAO;AAE/B,QAAI,aAAa,WAAW,UAAU,KAAK;AACzC,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,cAAc,SAAS,2BAA2B;AAAA,IAC7F;AAEA,QAAI,aAAa,WAAW,gBAAgB,KAAK;AAC/C,aAAO;AAAA,QACL,gBAAgB;AAAA,QAChB,QAAQ,cAAc,SAAS;AAAA,MACjC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAmB,SAA+B;AACxD,QAAI,QAAQ;AAGZ,QAAI,QAAQ,aAAa,QAAQ;AAC/B,YAAM,iBAAyC;AAAA,QAC7C,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,UAAU;AAAA,MACZ;AAEA,iBAAW,UAAU,QAAQ,aAAa;AACxC,cAAM,cAAc,eAAe,OAAO,QAAQ,KAAK;AACvD,YAAI,cAAc,MAAO,SAAQ;AAAA,MACnC;AACA,aAAO;AAAA,IACT;AAKA,QAAI,QAAQ,YAAY,gBAAgB,QAAQ,QAAQ;AACtD,YAAM,UAAU,sBAAsB,QAAQ,MAAM;AACpD,YAAM,iBACJ,QAAQ,SAAS,KACjB,QAAQ,MAAM,CAAC,QAAQ,QAAQ,UAAU,QAAQ,MAAM,KACvD,8BAA8B,QAAQ,MAAM;AAC9C,UAAI,QAAQ,SAAS,KAAK,CAAC,gBAAgB;AACzC,gBAAQ,KAAK,IAAI,OAAO,EAAE;AAAA,MAC5B;AAAA,IACF;AAKA,SACG,QAAQ,YAAY,eACnB,QAAQ,YAAY,gBACpB,QAAQ,YAAY,kBACtB,QAAQ,QACR;AACA,YAAM,cAAc,QAAQ,OAAO,YAAY,EAAE,QAAQ,OAAO,GAAG;AACnE,iBAAW,iBAAiB,iBAAiB;AAC3C,YAAI,YAAY,SAAS,cAAc,YAAY,CAAC,GAAG;AACrD,kBAAQ,KAAK,IAAI,OAAO,EAAE;AAC1B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,OAAuB;AAC3C,QAAI,SAAS;AAEb,UAAM,aAAa,OAAO,QAAQ,KAAK;AACvC,QAAI,eAAe,GAAI,UAAS,OAAO,MAAM,aAAa,CAAC;AAE3D,UAAM,aAAa,OAAO,QAAQ,GAAG;AACrC,QAAI,eAAe,GAAI,UAAS,OAAO,MAAM,GAAG,UAAU;AAE1D,UAAM,aAAa,OAAO,QAAQ,GAAG;AACrC,QAAI,eAAe,GAAI,UAAS,OAAO,MAAM,GAAG,UAAU;AAC1D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB,OAAe,UAA6B;AACpE,WAAO,SAAS,KAAK,CAAC,YAAY,KAAK,UAAU,OAAO,OAAO,CAAC;AAAA,EAClE;AAAA,EAgBQ,aAA4B;AAClC,QAAI,KAAK,qBAAqB,OAAW,QAAO,KAAK;AACrD,UAAM,MAAM,OAAO,YAAY,cAAc,QAAQ,MAAM;AAC3D,UAAM,OAAO,KAAK,QAAQ,KAAK;AAC/B,SAAK,mBAAmB,OAAO,KAAK,QAAQ,OAAO,GAAG,IAAI;AAC1D,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,UAAU,OAAe,SAA0B;AASzD,YAAQ,MAAM,QAAQ,OAAO,GAAG;AAChC,cAAU,QAAQ,QAAQ,OAAO,GAAG;AACpC,QAAI,YAAY,OAAO,QAAQ,WAAW,IAAI,GAAG;AAC/C,YAAM,OAAO,KAAK,WAAW;AAC7B,UAAI,KAAM,WAAU,OAAO,QAAQ,MAAM,CAAC;AAAA,IAC5C;AAGA,QAAI,YAAY,MAAO,QAAO;AAQ9B,UAAM,aAAa,QAAQ,MAAM,KAAK,KAAK,CAAC,GAAG;AAC/C,QAAI,YAAY,GAAG;AACjB,aAAO;AAAA,IACT;AAGA,UAAM,WAAW,QACd,QAAQ,qBAAqB,MAAM,EACnC,QAAQ,OAAO,IAAI,EACnB,QAAQ,OAAO,GAAG;AAErB,QAAI;AACF,aAAO,IAAI,OAAO,IAAI,QAAQ,KAAK,GAAG,EAAE,KAAK,KAAK;AAAA,IACpD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;;;;;;;;;;;ACpXA,WAAS,UAAW,SAAS;AAC3B,WAAQ,OAAO,YAAY,eAAiB,YAAY;EAC1D;AAEA,WAAS,SAAU,SAAS;AAC1B,WAAQ,OAAO,YAAY,YAAc,YAAY;EACvD;AAEA,WAAS,QAAS,UAAU;AAC1B,QAAI,MAAM,QAAQ,QAAQ,EAAG,QAAO;aAC3B,UAAU,QAAQ,EAAG,QAAO,CAAA;AAErC,WAAO,CAAC,QAAQ;EAClB;AAEA,WAAS,OAAQ,QAAQ,QAAQ;AAC/B,QAAI,QAAQ;AACV,YAAM,aAAa,OAAO,KAAK,MAAM;AAErC,eAAS,QAAQ,GAAG,SAAS,WAAW,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AAC1E,cAAM,MAAM,WAAW,KAAK;AAC5B,eAAO,GAAG,IAAI,OAAO,GAAG;MAC9B;IACA;AAEE,WAAO;EACT;AAEA,WAAS,OAAQ,QAAQ,OAAO;AAC9B,QAAI,SAAS;AAEb,aAAS,QAAQ,GAAG,QAAQ,OAAO,SAAS,GAAG;AAC7C,gBAAU;IACd;AAEE,WAAO;EACT;AAEA,WAAS,eAAgB,QAAQ;AAC/B,WAAQ,WAAW,KAAO,OAAO,sBAAsB,IAAI;EAC7D;AAEA,SAAA,YAA2B;AAC3B,SAAA,WAA0B;AAC1B,SAAA,UAAyB;AACzB,SAAA,SAAwB;AACxB,SAAA,iBAAgC;AAChC,SAAA,SAAwB;;;;;;;;AC7CxB,WAAS,YAAaC,YAAW,SAAS;AACxC,QAAI,QAAQ;AACZ,UAAM,UAAUA,WAAU,UAAU;AAEpC,QAAI,CAACA,WAAU,KAAM,QAAO;AAE5B,QAAIA,WAAU,KAAK,MAAM;AACvB,eAAS,SAASA,WAAU,KAAK,OAAO;IAC5C;AAEE,aAAS,OAAOA,WAAU,KAAK,OAAO,KAAK,OAAOA,WAAU,KAAK,SAAS,KAAK;AAE/E,QAAI,CAAC,WAAWA,WAAU,KAAK,SAAS;AACtC,eAAS,SAASA,WAAU,KAAK;IACrC;AAEE,WAAO,UAAU,MAAM;EACzB;AAEA,WAASC,eAAe,QAAQ,MAAM;AAEpC,UAAM,KAAK,IAAI;AAEf,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,UAAU,YAAY,MAAM,KAAK;AAGtC,QAAI,MAAM,mBAAmB;AAE3B,YAAM,kBAAkB,MAAM,KAAK,WAAW;IAClD,OAAS;AAEL,WAAK,QAAS,IAAI,MAAK,EAAI,SAAS;IACxC;EACA;AAGAA,iBAAc,YAAY,OAAO,OAAO,MAAM,SAAS;AACvDA,iBAAc,UAAU,cAAcA;AAEtCA,iBAAc,UAAU,WAAW,SAAS,SAAU,SAAS;AAC7D,WAAO,KAAK,OAAO,OAAO,YAAY,MAAM,OAAO;EACrD;AAEA,cAAiBA;;;;;;;;AChDjB,QAAMC,UAASC,cAAA;AAGf,WAAS,QAAS,QAAQ,WAAW,SAAS,UAAU,eAAe;AACrE,QAAI,OAAO;AACX,QAAI,OAAO;AACX,UAAM,gBAAgB,KAAK,MAAM,gBAAgB,CAAC,IAAI;AAEtD,QAAI,WAAW,YAAY,eAAe;AACxC,aAAO;AACP,kBAAY,WAAW,gBAAgB,KAAK;IAChD;AAEE,QAAI,UAAU,WAAW,eAAe;AACtC,aAAO;AACP,gBAAU,WAAW,gBAAgB,KAAK;IAC9C;AAEE,WAAO;MACL,KAAK,OAAO,OAAO,MAAM,WAAW,OAAO,EAAE,QAAQ,OAAO,QAAG,IAAI;MACnE,KAAK,WAAW,YAAY,KAAK;;IACrC;EACA;AAEA,WAAS,SAAU,QAAQ,KAAK;AAC9B,WAAOD,QAAO,OAAO,KAAK,MAAM,OAAO,MAAM,IAAI;EACnD;AAEA,WAAS,YAAa,MAAM,SAAS;AACnC,cAAU,OAAO,OAAO,WAAW,IAAI;AAEvC,QAAI,CAAC,KAAK,OAAQ,QAAO;AAEzB,QAAI,CAAC,QAAQ,UAAW,SAAQ,YAAY;AAC5C,QAAI,OAAO,QAAQ,WAAW,SAAU,SAAQ,SAAS;AACzD,QAAI,OAAO,QAAQ,gBAAgB,SAAU,SAAQ,cAAc;AACnE,QAAI,OAAO,QAAQ,eAAe,SAAU,SAAQ,aAAa;AAEjE,UAAM,KAAK;AACX,UAAM,aAAa,CAAC,CAAC;AACrB,UAAM,WAAW,CAAA;AACjB,QAAI;AACJ,QAAI,cAAc;AAElB,WAAQ,QAAQ,GAAG,KAAK,KAAK,MAAM,GAAI;AACrC,eAAS,KAAK,MAAM,KAAK;AACzB,iBAAW,KAAK,MAAM,QAAQ,MAAM,CAAC,EAAE,MAAM;AAE7C,UAAI,KAAK,YAAY,MAAM,SAAS,cAAc,GAAG;AACnD,sBAAc,WAAW,SAAS;MACxC;IACA;AAEE,QAAI,cAAc,EAAG,eAAc,WAAW,SAAS;AAEvD,QAAI,SAAS;AACb,UAAM,eAAe,KAAK,IAAI,KAAK,OAAO,QAAQ,YAAY,SAAS,MAAM,EAAE,SAAQ,EAAG;AAC1F,UAAM,gBAAgB,QAAQ,aAAa,QAAQ,SAAS,eAAe;AAE3E,aAAS,IAAI,GAAG,KAAK,QAAQ,aAAa,KAAK;AAC7C,UAAI,cAAc,IAAI,EAAG;AACzB,YAAME,QAAO;QACX,KAAK;QACL,WAAW,cAAc,CAAC;QAC1B,SAAS,cAAc,CAAC;QACxB,KAAK,YAAY,WAAW,WAAW,IAAI,WAAW,cAAc,CAAC;QACrE;MACN;AACI,eAASF,QAAO,OAAO,KAAK,QAAQ,MAAM,IAAI,UAAU,KAAK,OAAO,IAAI,GAAG,SAAQ,GAAI,YAAY,IACjG,QAAQE,MAAK,MAAM,OAAO;IAChC;AAEE,UAAM,OAAO,QAAQ,KAAK,QAAQ,WAAW,WAAW,GAAG,SAAS,WAAW,GAAG,KAAK,UAAU,aAAa;AAC9G,cAAUF,QAAO,OAAO,KAAK,QAAQ,MAAM,IAAI,UAAU,KAAK,OAAO,GAAG,SAAQ,GAAI,YAAY,IAC9F,QAAQ,KAAK,MAAM;AACrB,cAAUA,QAAO,OAAO,KAAK,QAAQ,SAAS,eAAe,IAAI,KAAK,GAAG,IAAI;AAE7E,aAAS,IAAI,GAAG,KAAK,QAAQ,YAAY,KAAK;AAC5C,UAAI,cAAc,KAAK,SAAS,OAAQ;AACxC,YAAME,QAAO;QACX,KAAK;QACL,WAAW,cAAc,CAAC;QAC1B,SAAS,cAAc,CAAC;QACxB,KAAK,YAAY,WAAW,WAAW,IAAI,WAAW,cAAc,CAAC;QACrE;MACN;AACI,gBAAUF,QAAO,OAAO,KAAK,QAAQ,MAAM,IAAI,UAAU,KAAK,OAAO,IAAI,GAAG,SAAQ,GAAI,YAAY,IAClG,QAAQE,MAAK,MAAM;IACzB;AAEE,WAAO,OAAO,QAAQ,OAAO,EAAE;EACjC;AAEA,YAAiB;;;;;;;;AC7FjB,QAAMH,iBAAgBE,iBAAA;AAEtB,QAAM,2BAA2B;IAC/B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;EACF;AAEA,QAAM,kBAAkB;IACtB;IACA;IACA;EACF;AAEA,WAAS,oBAAqBE,MAAK;AACjC,UAAM,SAAS,CAAA;AAEf,QAAIA,SAAQ,MAAM;AAChB,aAAO,KAAKA,IAAG,EAAE,QAAQ,SAAU,OAAO;AACxCA,aAAI,KAAK,EAAE,QAAQ,SAAU,OAAO;AAClC,iBAAO,OAAO,KAAK,CAAC,IAAI;QAChC,CAAO;MACP,CAAK;IACL;AAEE,WAAO;EACT;AAEA,WAASC,MAAM,KAAK,SAAS;AAC3B,cAAU,WAAW,CAAA;AAErB,WAAO,KAAK,OAAO,EAAE,QAAQ,SAAU,MAAM;AAC3C,UAAI,yBAAyB,QAAQ,IAAI,MAAM,IAAI;AACjD,cAAM,IAAIL,eAAc,qBAAqB,OAAO,gCAAgC,MAAM,cAAc;MAC9G;IACA,CAAG;AAGD,SAAK,UAAU;AACf,SAAK,MAAM;AACX,SAAK,OAAO,QAAQ,MAAM,KAAK;AAC/B,SAAK,UAAU,QAAQ,SAAS,KAAK,WAAY;AAAE,aAAO;IAAI;AAC9D,SAAK,YAAY,QAAQ,WAAW,KAAK,SAAU,MAAM;AAAE,aAAO;IAAI;AACtE,SAAK,aAAa,QAAQ,YAAY,KAAK;AAC3C,SAAK,YAAY,QAAQ,WAAW,KAAK;AACzC,SAAK,YAAY,QAAQ,WAAW,KAAK;AACzC,SAAK,gBAAgB,QAAQ,eAAe,KAAK;AACjD,SAAK,eAAe,QAAQ,cAAc,KAAK;AAC/C,SAAK,QAAQ,QAAQ,OAAO,KAAK;AACjC,SAAK,eAAe,oBAAoB,QAAQ,cAAc,KAAK,IAAI;AAEvE,QAAI,gBAAgB,QAAQ,KAAK,IAAI,MAAM,IAAI;AAC7C,YAAM,IAAIA,eAAc,mBAAmB,KAAK,OAAO,yBAAyB,MAAM,cAAc;IACxG;EACA;AAEA,SAAiBK;;;;;;;;AC/DjB,QAAML,iBAAgBE,iBAAA;AACtB,QAAMG,QAAOC,YAAA;AAEb,WAAS,YAAaC,SAAQ,MAAM;AAClC,UAAM,SAAS,CAAA;AAEfA,YAAO,IAAI,EAAE,QAAQ,SAAU,aAAa;AAC1C,UAAI,WAAW,OAAO;AAEtB,aAAO,QAAQ,SAAU,cAAc,eAAe;AACpD,YAAI,aAAa,QAAQ,YAAY,OACjC,aAAa,SAAS,YAAY,QAClC,aAAa,UAAU,YAAY,OAAO;AAC5C,qBAAW;QACnB;MACA,CAAK;AAED,aAAO,QAAQ,IAAI;IACvB,CAAG;AAED,WAAO;EACT;AAEA,WAAS,aAA4B;AACnC,UAAM,SAAS;MACb,QAAQ,CAAA;MACR,UAAU,CAAA;MACV,SAAS,CAAA;MACT,UAAU,CAAA;MACV,OAAO;QACL,QAAQ,CAAA;QACR,UAAU,CAAA;QACV,SAAS,CAAA;QACT,UAAU,CAAA;MAChB;IACA;AACE,aAAS,YAAaC,OAAM;AAC1B,UAAIA,MAAK,OAAO;AACd,eAAO,MAAMA,MAAK,IAAI,EAAE,KAAKA,KAAI;AACjC,eAAO,MAAM,UAAU,EAAE,KAAKA,KAAI;MACxC,OAAW;AACL,eAAOA,MAAK,IAAI,EAAEA,MAAK,GAAG,IAAI,OAAO,UAAU,EAAEA,MAAK,GAAG,IAAIA;MACnE;IACA;AAEE,aAAS,QAAQ,GAAG,SAAS,UAAU,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACzE,gBAAU,KAAK,EAAE,QAAQ,WAAW;IACxC;AACE,WAAO;EACT;AAEA,WAASC,QAAQ,YAAY;AAC3B,WAAO,KAAK,OAAO,UAAU;EAC/B;AAEAA,UAAO,UAAU,SAAS,SAAS,OAAQ,YAAY;AACrD,QAAI,WAAW,CAAA;AACf,QAAI,WAAW,CAAA;AAEf,QAAI,sBAAsBJ,OAAM;AAE9B,eAAS,KAAK,UAAU;IAC5B,WAAa,MAAM,QAAQ,UAAU,GAAG;AAEpC,iBAAW,SAAS,OAAO,UAAU;IACzC,WAAa,eAAe,MAAM,QAAQ,WAAW,QAAQ,KAAK,MAAM,QAAQ,WAAW,QAAQ,IAAI;AAEnG,UAAI,WAAW,SAAU,YAAW,SAAS,OAAO,WAAW,QAAQ;AACvE,UAAI,WAAW,SAAU,YAAW,SAAS,OAAO,WAAW,QAAQ;IAC3E,OAAS;AACL,YAAM,IAAIL,eAAc,kHACyC;IACrE;AAEE,aAAS,QAAQ,SAAUQ,OAAM;AAC/B,UAAI,EAAEA,iBAAgBH,QAAO;AAC3B,cAAM,IAAIL,eAAc,oFAAoF;MAClH;AAEI,UAAIQ,MAAK,YAAYA,MAAK,aAAa,UAAU;AAC/C,cAAM,IAAIR,eAAc,iHAAiH;MAC/I;AAEI,UAAIQ,MAAK,OAAO;AACd,cAAM,IAAIR,eAAc,oGAAoG;MAClI;IACA,CAAG;AAED,aAAS,QAAQ,SAAUQ,OAAM;AAC/B,UAAI,EAAEA,iBAAgBH,QAAO;AAC3B,cAAM,IAAIL,eAAc,oFAAoF;MAClH;IACA,CAAG;AAED,UAAM,SAAS,OAAO,OAAOS,QAAO,SAAS;AAE7C,WAAO,YAAY,KAAK,YAAY,CAAA,GAAI,OAAO,QAAQ;AACvD,WAAO,YAAY,KAAK,YAAY,CAAA,GAAI,OAAO,QAAQ;AAEvD,WAAO,mBAAmB,YAAY,QAAQ,UAAU;AACxD,WAAO,mBAAmB,YAAY,QAAQ,UAAU;AACxD,WAAO,kBAAkB,WAAW,OAAO,kBAAkB,OAAO,gBAAgB;AAEpF,WAAO;EACT;AAEA,WAAiBA;;;;;;;;AC1GjB,QAAMJ,QAAOH,YAAA;AAEb,QAAiB,IAAIG,MAAK,yBAAyB;IACjD,MAAM;IACN,WAAW,SAAU,MAAM;AAAE,aAAO,SAAS,OAAO,OAAO;IAAE;EAAA,CAC9D;;;;;;;;ACLD,QAAMA,QAAOH,YAAA;AAEb,QAAiB,IAAIG,MAAK,yBAAyB;IACjD,MAAM;IACN,WAAW,SAAU,MAAM;AAAE,aAAO,SAAS,OAAO,OAAO,CAAA;IAAE;EAAA,CAC9D;;;;;;;;ACLD,QAAMA,QAAOH,YAAA;AAEb,QAAiB,IAAIG,MAAK,yBAAyB;IACjD,MAAM;IACN,WAAW,SAAU,MAAM;AAAE,aAAO,SAAS,OAAO,OAAO,CAAA;IAAE;EAAA,CAC9D;;;;;;;;ACFD,QAAMI,UAASP,cAAA;AAEf,aAAiB,IAAIO,QAAO;IAC1B,UAAU;MACRH,WAAA;MACAI,WAAA;MACAC,WAAA;IACJ;EAAA,CACC;;;;;;;;ACXD,QAAMN,QAAOH,YAAA;AAEb,WAAS,gBAAiB,MAAM;AAC9B,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,MAAM,KAAK;AAEjB,WAAQ,QAAQ,KAAK,SAAS,OACtB,QAAQ,MAAM,SAAS,UAAU,SAAS,UAAU,SAAS;EACvE;AAEA,WAAS,oBAAqB;AAC5B,WAAO;EACT;AAEA,WAAS,OAAQ,QAAQ;AACvB,WAAO,WAAW;EACpB;AAEA,UAAiB,IAAIG,MAAK,0BAA0B;IAClD,MAAM;IACN,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;MACT,WAAW,WAAY;AAAE,eAAO;MAAG;MACnC,WAAW,WAAY;AAAE,eAAO;MAAM;MACtC,WAAW,WAAY;AAAE,eAAO;MAAM;MACtC,WAAW,WAAY;AAAE,eAAO;MAAM;MACtC,OAAO,WAAY;AAAE,eAAO;MAAE;IAAA;IAEhC,cAAc;EAAA,CACf;;;;;;;;AChCD,QAAMA,QAAOH,YAAA;AAEb,WAAS,mBAAoB,MAAM;AACjC,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,MAAM,KAAK;AAEjB,WAAQ,QAAQ,MAAM,SAAS,UAAU,SAAS,UAAU,SAAS,WAC7D,QAAQ,MAAM,SAAS,WAAW,SAAS,WAAW,SAAS;EACzE;AAEA,WAAS,qBAAsB,MAAM;AACnC,WAAO,SAAS,UACT,SAAS,UACT,SAAS;EAClB;AAEA,WAAS,UAAW,QAAQ;AAC1B,WAAO,OAAO,UAAU,SAAS,KAAK,MAAM,MAAM;EACpD;AAEA,SAAiB,IAAIG,MAAK,0BAA0B;IAClD,MAAM;IACN,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;MACT,WAAW,SAAU,QAAQ;AAAE,eAAO,SAAS,SAAS;MAAO;MAC/D,WAAW,SAAU,QAAQ;AAAE,eAAO,SAAS,SAAS;MAAO;MAC/D,WAAW,SAAU,QAAQ;AAAE,eAAO,SAAS,SAAS;MAAO;IAAA;IAEjE,cAAc;EAAA,CACf;;;;;;;;AChCD,QAAMJ,UAASC,cAAA;AACf,QAAMG,QAAOC,YAAA;AAEb,WAAS,UAAW,GAAG;AACrB,WAAS,KAAK,MAAiB,KAAK,MAC3B,KAAK,MAAiB,KAAK,MAC3B,KAAK,MAAiB,KAAK;EACtC;AAEA,WAAS,UAAW,GAAG;AACrB,WAAS,KAAK,MAAiB,KAAK;EACtC;AAEA,WAAS,UAAW,GAAG;AACrB,WAAS,KAAK,MAAiB,KAAK;EACtC;AAEA,WAAS,mBAAoB,MAAM;AACjC,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,MAAM,KAAK;AACjB,QAAI,QAAQ;AACZ,QAAI,YAAY;AAEhB,QAAI,CAAC,IAAK,QAAO;AAEjB,QAAI,KAAK,KAAK,KAAK;AAGnB,QAAI,OAAO,OAAO,OAAO,KAAK;AAC5B,WAAK,KAAK,EAAE,KAAK;IACrB;AAEE,QAAI,OAAO,KAAK;AAEd,UAAI,QAAQ,MAAM,IAAK,QAAO;AAC9B,WAAK,KAAK,EAAE,KAAK;AAIjB,UAAI,OAAO,KAAK;AAEd;AAEA,eAAO,QAAQ,KAAK,SAAS;AAC3B,eAAK,KAAK,KAAK;AACf,cAAI,OAAO,OAAO,OAAO,IAAK,QAAO;AACrC,sBAAY;QACpB;AACM,eAAO,aAAa,SAAS,iBAAiB,IAAI,CAAC;MACzD;AAEI,UAAI,OAAO,KAAK;AAEd;AAEA,eAAO,QAAQ,KAAK,SAAS;AAC3B,cAAI,CAAC,UAAU,KAAK,WAAW,KAAK,CAAC,EAAG,QAAO;AAC/C,sBAAY;QACpB;AACM,eAAO,aAAa,SAAS,iBAAiB,IAAI,CAAC;MACzD;AAEI,UAAI,OAAO,KAAK;AAEd;AAEA,eAAO,QAAQ,KAAK,SAAS;AAC3B,cAAI,CAAC,UAAU,KAAK,WAAW,KAAK,CAAC,EAAG,QAAO;AAC/C,sBAAY;QACpB;AACM,eAAO,aAAa,SAAS,iBAAiB,IAAI,CAAC;MACzD;IACA;AAIE,WAAO,QAAQ,KAAK,SAAS;AAC3B,UAAI,CAAC,UAAU,KAAK,WAAW,KAAK,CAAC,GAAG;AACtC,eAAO;MACb;AACI,kBAAY;IAChB;AAEE,QAAI,CAAC,UAAW,QAAO;AAEvB,WAAO,SAAS,iBAAiB,IAAI,CAAC;EACxC;AAEA,WAAS,iBAAkB,MAAM;AAC/B,QAAI,QAAQ;AACZ,QAAI,OAAO;AAEX,QAAI,KAAK,MAAM,CAAC;AAEhB,QAAI,OAAO,OAAO,OAAO,KAAK;AAC5B,UAAI,OAAO,IAAK,QAAO;AACvB,cAAQ,MAAM,MAAM,CAAC;AACrB,WAAK,MAAM,CAAC;IAChB;AAEE,QAAI,UAAU,IAAK,QAAO;AAE1B,QAAI,OAAO,KAAK;AACd,UAAI,MAAM,CAAC,MAAM,IAAK,QAAO,OAAO,SAAS,MAAM,MAAM,CAAC,GAAG,CAAC;AAC9D,UAAI,MAAM,CAAC,MAAM,IAAK,QAAO,OAAO,SAAS,MAAM,MAAM,CAAC,GAAG,EAAE;AAC/D,UAAI,MAAM,CAAC,MAAM,IAAK,QAAO,OAAO,SAAS,MAAM,MAAM,CAAC,GAAG,CAAC;IAClE;AAEE,WAAO,OAAO,SAAS,OAAO,EAAE;EAClC;AAEA,WAAS,qBAAsB,MAAM;AACnC,WAAO,iBAAiB,IAAI;EAC9B;AAEA,WAAS,UAAW,QAAQ;AAC1B,WAAQ,OAAO,UAAU,SAAS,KAAK,MAAM,MAAO,sBAC5C,SAAS,MAAM,KAAK,CAACL,QAAO,eAAe,MAAM;EAC3D;AAEA,QAAiB,IAAII,MAAK,yBAAyB;IACjD,MAAM;IACN,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;MACT,QAAQ,SAAU,KAAK;AAAE,eAAO,OAAO,IAAI,OAAO,IAAI,SAAS,CAAC,IAAI,QAAQ,IAAI,SAAS,CAAC,EAAE,MAAM,CAAC;MAAC;MACpG,OAAO,SAAU,KAAK;AAAE,eAAO,OAAO,IAAI,OAAO,IAAI,SAAS,CAAC,IAAI,QAAQ,IAAI,SAAS,CAAC,EAAE,MAAM,CAAC;MAAC;MACnG,SAAS,SAAU,KAAK;AAAE,eAAO,IAAI,SAAS,EAAE;MAAC;MACjD,aAAa,SAAU,KAAK;AAAE,eAAO,OAAO,IAAI,OAAO,IAAI,SAAS,EAAE,EAAE,YAAA,IAAgB,QAAQ,IAAI,SAAS,EAAE,EAAE,YAAW,EAAG,MAAM,CAAC;MAAC;IAAA;IAEzI,cAAc;IACd,cAAc;MACZ,QAAQ,CAAC,GAAG,KAAK;MACjB,OAAO,CAAC,GAAG,KAAK;MAChB,SAAS,CAAC,IAAI,KAAK;MACnB,aAAa,CAAC,IAAI,KAAK;IAC3B;EAAA,CACC;;;;;;;;AC3ID,QAAMJ,UAASC,cAAA;AACf,QAAMG,QAAOC,YAAA;AAEb,QAAM,qBAAqB,IAAI;;IAE7B;EAOuB;AAEzB,QAAM,6BAA6B,IAAI;IACrC;EAIuB;AAEzB,WAAS,iBAAkB,MAAM;AAC/B,QAAI,SAAS,KAAM,QAAO;AAE1B,QAAI,CAAC,mBAAmB,KAAK,IAAI,GAAG;AAClC,aAAO;IACX;AAEE,QAAI,SAAS,WAAW,MAAM,EAAE,CAAC,GAAG;AAClC,aAAO;IACX;AAEE,WAAO,2BAA2B,KAAK,IAAI;EAC7C;AAEA,WAAS,mBAAoB,MAAM;AACjC,QAAI,QAAQ,KAAK,YAAW;AAC5B,UAAM,OAAO,MAAM,CAAC,MAAM,MAAM,KAAK;AAErC,QAAI,KAAK,QAAQ,MAAM,CAAC,CAAC,KAAK,GAAG;AAC/B,cAAQ,MAAM,MAAM,CAAC;IACzB;AAEE,QAAI,UAAU,QAAQ;AACpB,aAAQ,SAAS,IAAK,OAAO,oBAAoB,OAAO;IAC5D,WAAa,UAAU,QAAQ;AAC3B,aAAO;IACX;AACE,WAAO,OAAO,WAAW,OAAO,EAAE;EACpC;AAEA,QAAM,yBAAyB;AAE/B,WAAS,mBAAoB,QAAQ,OAAO;AAC1C,QAAI,MAAM,MAAM,GAAG;AACjB,cAAQ,OAAK;QACX,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;MAC/B;IACA,WAAa,OAAO,sBAAsB,QAAQ;AAC9C,cAAQ,OAAK;QACX,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;MAC/B;IACA,WAAa,OAAO,sBAAsB,QAAQ;AAC9C,cAAQ,OAAK;QACX,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;MAC/B;IACA,WAAaL,QAAO,eAAe,MAAM,GAAG;AACxC,aAAO;IACX;AAEE,UAAM,MAAM,OAAO,SAAS,EAAE;AAK9B,WAAO,uBAAuB,KAAK,GAAG,IAAI,IAAI,QAAQ,KAAK,IAAI,IAAI;EACrE;AAEA,WAAS,QAAS,QAAQ;AACxB,WAAQ,OAAO,UAAU,SAAS,KAAK,MAAM,MAAM,sBAC3C,SAAS,MAAM,KAAKA,QAAO,eAAe,MAAM;EAC1D;AAEA,UAAiB,IAAII,MAAK,2BAA2B;IACnD,MAAM;IACN,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;IACX,cAAc;EAAA,CACf;;;;;;;;ACzFD,SAAiBH,gBAAA,EAAsB,OAAO;IAC5C,UAAU;MACRI,aAAA;MACAI,YAAA;MACAC,WAAA;MACAC,aAAA;IACJ;EAAA,CACC;;;;;;;;ACRD,SAAiBV,YAAA;;;;;;;;ACNjB,QAAMG,QAAOH,YAAA;AAEb,QAAM,mBAAmB,IAAI;IAC3B;EAEgB;AAElB,QAAM,wBAAwB,IAAI;IAChC;EASwB;AAE1B,WAAS,qBAAsB,MAAM;AACnC,QAAI,SAAS,KAAM,QAAO;AAC1B,QAAI,iBAAiB,KAAK,IAAI,MAAM,KAAM,QAAO;AACjD,QAAI,sBAAsB,KAAK,IAAI,MAAM,KAAM,QAAO;AACtD,WAAO;EACT;AAEA,WAAS,uBAAwB,MAAM;AACrC,QAAI,WAAW;AACf,QAAI,QAAQ;AAEZ,QAAI,QAAQ,iBAAiB,KAAK,IAAI;AACtC,QAAI,UAAU,KAAM,SAAQ,sBAAsB,KAAK,IAAI;AAE3D,QAAI,UAAU,KAAM,OAAM,IAAI,MAAM,oBAAoB;AAIxD,UAAM,OAAO,CAAE,MAAM,CAAC;AACtB,UAAM,QAAQ,CAAE,MAAM,CAAC,IAAK;AAC5B,UAAM,MAAM,CAAE,MAAM,CAAC;AAErB,QAAI,CAAC,MAAM,CAAC,GAAG;AACb,aAAO,IAAI,KAAK,KAAK,IAAI,MAAM,OAAO,GAAG,CAAC;IAC9C;AAIE,UAAM,OAAO,CAAE,MAAM,CAAC;AACtB,UAAM,SAAS,CAAE,MAAM,CAAC;AACxB,UAAM,SAAS,CAAE,MAAM,CAAC;AAExB,QAAI,MAAM,CAAC,GAAG;AACZ,iBAAW,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC;AAC9B,aAAO,SAAS,SAAS,GAAG;AAC1B,oBAAY;MAClB;AACI,iBAAW,CAAC;IAChB;AAIE,QAAI,MAAM,CAAC,GAAG;AACZ,YAAM,SAAS,CAAE,MAAM,EAAE;AACzB,YAAM,WAAW,EAAE,MAAM,EAAE,KAAK;AAChC,eAAS,SAAS,KAAK,YAAY;AACnC,UAAI,MAAM,CAAC,MAAM,IAAK,SAAQ,CAAC;IACnC;AAEE,UAAM,OAAO,IAAI,KAAK,KAAK,IAAI,MAAM,OAAO,KAAK,MAAM,QAAQ,QAAQ,QAAQ,CAAC;AAEhF,QAAI,MAAO,MAAK,QAAQ,KAAK,QAAO,IAAK,KAAK;AAE9C,WAAO;EACT;AAEA,WAAS,uBAAwB,QAAqB;AACpD,WAAO,OAAO,YAAW;EAC3B;AAEA,cAAiB,IAAIG,MAAK,+BAA+B;IACvD,MAAM;IACN,SAAS;IACT,WAAW;IACX,YAAY;IACZ,WAAW;EAAA,CACZ;;;;;;;;ACrFD,QAAMA,QAAOH,YAAA;AAEb,WAAS,iBAAkB,MAAM;AAC/B,WAAO,SAAS,QAAQ,SAAS;EACnC;AAEA,UAAiB,IAAIG,MAAK,2BAA2B;IACnD,MAAM;IACN,SAAS;EAAA,CACV;;;;;;;;ACTD,QAAMA,QAAOH,YAAA;AAGb,QAAM,aAAa;AAEnB,WAAS,kBAAmB,MAAM;AAChC,QAAI,SAAS,KAAM,QAAO;AAE1B,QAAI,SAAS;AACb,UAAM,MAAM,KAAK;AACjB,UAAME,OAAM;AAGZ,aAAS,MAAM,GAAG,MAAM,KAAK,OAAO;AAClC,YAAM,OAAOA,KAAI,QAAQ,KAAK,OAAO,GAAG,CAAC;AAGzC,UAAI,OAAO,GAAI;AAGf,UAAI,OAAO,EAAG,QAAO;AAErB,gBAAU;IACd;AAGE,WAAQ,SAAS,MAAO;EAC1B;AAEA,WAAS,oBAAqB,MAAM;AAClC,UAAM,QAAQ,KAAK,QAAQ,YAAY,EAAE;AACzC,UAAM,MAAM,MAAM;AAClB,UAAMA,OAAM;AACZ,QAAI,OAAO;AACX,UAAM,SAAS,CAAA;AAIf,aAAS,MAAM,GAAG,MAAM,KAAK,OAAO;AAClC,UAAK,MAAM,MAAM,KAAM,KAAK;AAC1B,eAAO,KAAM,QAAQ,KAAM,GAAI;AAC/B,eAAO,KAAM,QAAQ,IAAK,GAAI;AAC9B,eAAO,KAAK,OAAO,GAAI;MAC7B;AAEI,aAAQ,QAAQ,IAAKA,KAAI,QAAQ,MAAM,OAAO,GAAG,CAAC;IACtD;AAIE,UAAM,WAAY,MAAM,IAAK;AAE7B,QAAI,aAAa,GAAG;AAClB,aAAO,KAAM,QAAQ,KAAM,GAAI;AAC/B,aAAO,KAAM,QAAQ,IAAK,GAAI;AAC9B,aAAO,KAAK,OAAO,GAAI;IAC3B,WAAa,aAAa,IAAI;AAC1B,aAAO,KAAM,QAAQ,KAAM,GAAI;AAC/B,aAAO,KAAM,QAAQ,IAAK,GAAI;IAClC,WAAa,aAAa,IAAI;AAC1B,aAAO,KAAM,QAAQ,IAAK,GAAI;IAClC;AAEE,WAAO,IAAI,WAAW,MAAM;EAC9B;AAEA,WAAS,oBAAqB,QAAqB;AACjD,QAAI,SAAS;AACb,QAAI,OAAO;AACX,UAAM,MAAM,OAAO;AACnB,UAAMA,OAAM;AAIZ,aAAS,MAAM,GAAG,MAAM,KAAK,OAAO;AAClC,UAAK,MAAM,MAAM,KAAM,KAAK;AAC1B,kBAAUA,KAAK,QAAQ,KAAM,EAAI;AACjC,kBAAUA,KAAK,QAAQ,KAAM,EAAI;AACjC,kBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,kBAAUA,KAAI,OAAO,EAAI;MAC/B;AAEI,cAAQ,QAAQ,KAAK,OAAO,GAAG;IACnC;AAIE,UAAM,OAAO,MAAM;AAEnB,QAAI,SAAS,GAAG;AACd,gBAAUA,KAAK,QAAQ,KAAM,EAAI;AACjC,gBAAUA,KAAK,QAAQ,KAAM,EAAI;AACjC,gBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,gBAAUA,KAAI,OAAO,EAAI;IAC7B,WAAa,SAAS,GAAG;AACrB,gBAAUA,KAAK,QAAQ,KAAM,EAAI;AACjC,gBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,gBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,gBAAUA,KAAI,EAAE;IACpB,WAAa,SAAS,GAAG;AACrB,gBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,gBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,gBAAUA,KAAI,EAAE;AAChB,gBAAUA,KAAI,EAAE;IACpB;AAEE,WAAO;EACT;AAEA,WAAS,SAAU,KAAK;AACtB,WAAO,OAAO,UAAU,SAAS,KAAK,GAAG,MAAM;EACjD;AAEA,WAAiB,IAAIC,MAAK,4BAA4B;IACpD,MAAM;IACN,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;EAAA,CACZ;;;;;;;;ACvHD,QAAMA,QAAOH,YAAA;AAEb,QAAM,kBAAkB,OAAO,UAAU;AACzC,QAAM,YAAY,OAAO,UAAU;AAEnC,WAAS,gBAAiB,MAAM;AAC9B,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,aAAa,CAAA;AACnB,UAAM,SAAS;AAEf,aAAS,QAAQ,GAAG,SAAS,OAAO,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtE,YAAM,OAAO,OAAO,KAAK;AACzB,UAAI,aAAa;AAEjB,UAAI,UAAU,KAAK,IAAI,MAAM,kBAAmB,QAAO;AAEvD,UAAI;AACJ,WAAK,WAAW,MAAM;AACpB,YAAI,gBAAgB,KAAK,MAAM,OAAO,GAAG;AACvC,cAAI,CAAC,WAAY,cAAa;cACzB,QAAO;QACpB;MACA;AAEI,UAAI,CAAC,WAAY,QAAO;AAExB,UAAI,gBAAgB,KAAK,YAAY,OAAO,EAAG,QAAO;AACtD,aAAO,eAAe,YAAY,SAAS,EAAE,OAAO,KAAI,CAAE;IAC9D;AAEE,WAAO;EACT;AAEA,WAAS,kBAAmB,MAAM;AAChC,WAAO,SAAS,OAAO,OAAO,CAAA;EAChC;AAEA,SAAiB,IAAIG,MAAK,0BAA0B;IAClD,MAAM;IACN,SAAS;IACT,WAAW;EAAA,CACZ;;;;;;;;AC1CD,QAAMA,QAAOH,YAAA;AAEb,QAAM,YAAY,OAAO,UAAU;AAEnC,WAAS,iBAAkB,MAAM;AAC/B,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,SAAS;AAEf,UAAM,SAAS,IAAI,MAAM,OAAO,MAAM;AAEtC,aAAS,QAAQ,GAAG,SAAS,OAAO,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtE,YAAM,OAAO,OAAO,KAAK;AAEzB,UAAI,UAAU,KAAK,IAAI,MAAM,kBAAmB,QAAO;AAEvD,YAAM,OAAO,OAAO,KAAK,IAAI;AAE7B,UAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,aAAO,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC;IAC3C;AAEE,WAAO;EACT;AAEA,WAAS,mBAAoB,MAAM;AACjC,QAAI,SAAS,KAAM,QAAO,CAAA;AAE1B,UAAM,SAAS;AACf,UAAM,SAAS,IAAI,MAAM,OAAO,MAAM;AAEtC,aAAS,QAAQ,GAAG,SAAS,OAAO,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtE,YAAM,OAAO,OAAO,KAAK;AAEzB,YAAM,OAAO,OAAO,KAAK,IAAI;AAE7B,aAAO,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC;IAC3C;AAEE,WAAO;EACT;AAEA,UAAiB,IAAIG,MAAK,2BAA2B;IACnD,MAAM;IACN,SAAS;IACT,WAAW;EAAA,CACZ;;;;;;;;AC/CD,QAAMA,QAAOH,YAAA;AAEb,QAAM,kBAAkB,OAAO,UAAU;AAEzC,WAAS,eAAgB,MAAM;AAC7B,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,SAAS;AAEf,eAAW,OAAO,QAAQ;AACxB,UAAI,gBAAgB,KAAK,QAAQ,GAAG,GAAG;AACrC,YAAI,OAAO,GAAG,MAAM,KAAM,QAAO;MACvC;IACA;AAEE,WAAO;EACT;AAEA,WAAS,iBAAkB,MAAM;AAC/B,WAAO,SAAS,OAAO,OAAO,CAAA;EAChC;AAEA,QAAiB,IAAIG,MAAK,yBAAyB;IACjD,MAAM;IACN,SAAS;IACT,WAAW;EAAA,CACZ;;;;;;;;ACpBD,aAAiBH,YAAA,EAAkB,OAAO;IACxC,UAAU;MACRI,iBAAA;MACAI,aAAA;IAAA;IAEF,UAAU;MACRC,cAAA;MACAC,YAAA;MACAC,aAAA;MACAC,WAAA;IACJ;EAAA,CACC;;;;;;;ACjBD,QAAMb,UAASC,cAAA;AACf,QAAMF,iBAAgBM,iBAAA;AACtB,QAAM,cAAcI,eAAA;AACpB,QAAMK,kBAAiBJ,gBAAA;AAEvB,QAAM,kBAAkB,OAAO,UAAU;AAEzC,QAAM,kBAAkB;AACxB,QAAM,mBAAmB;AACzB,QAAM,mBAAmB;AACzB,QAAM,oBAAoB;AAE1B,QAAM,gBAAgB;AACtB,QAAM,iBAAiB;AACvB,QAAM,gBAAgB;AAGtB,QAAM,wBAAwB;AAC9B,QAAM,gCAAgC;AAEtC,QAAM,0BAA0B;AAEhC,QAAM,qBAAqB;AAE3B,QAAM,kBAAkB;AAExB,WAAS,OAAQ,KAAK;AAAE,WAAO,OAAO,UAAU,SAAS,KAAK,GAAG;EAAC;AAElE,WAAS,MAAO,GAAG;AACjB,WAAQ,MAAM,MAAkB,MAAM;EACxC;AAEA,WAAS,aAAc,GAAG;AACxB,WAAQ,MAAM,KAAmB,MAAM;EACzC;AAEA,WAAS,UAAW,GAAG;AACrB,WAAQ,MAAM,KACN,MAAM,MACN,MAAM,MACN,MAAM;EAChB;AAEA,WAAS,gBAAiB,GAAG;AAC3B,WAAO,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,OACN,MAAM;EACf;AAEA,WAAS,YAAa,GAAG;AACvB,QAAK,KAAK,MAAiB,KAAK,IAAc;AAC5C,aAAO,IAAI;IACf;AAEE,UAAM,KAAK,IAAI;AAEf,QAAK,MAAM,MAAiB,MAAM,KAAc;AAC9C,aAAO,KAAK,KAAO;IACvB;AAEE,WAAO;EACT;AAEA,WAAS,cAAe,GAAG;AACzB,QAAI,MAAM,KAAa;AAAE,aAAO;IAAC;AACjC,QAAI,MAAM,KAAa;AAAE,aAAO;IAAC;AACjC,QAAI,MAAM,IAAa;AAAE,aAAO;IAAC;AACjC,WAAO;EACT;AAEA,WAAS,gBAAiB,GAAG;AAC3B,QAAK,KAAK,MAAiB,KAAK,IAAc;AAC5C,aAAO,IAAI;IACf;AAEE,WAAO;EACT;AAEA,WAAS,qBAAsB,GAAG;AAChC,YAAQ,GAAC;MACP,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAe,eAAO;MAC3B,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAiB,eAAO;MAC7B,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB;AAAS,eAAO;IACpB;EACA;AAEA,WAAS,kBAAmB,GAAG;AAC7B,QAAI,KAAK,OAAQ;AACf,aAAO,OAAO,aAAa,CAAC;IAChC;AAGE,WAAO,OAAO;OACV,IAAI,SAAa,MAAM;OACvB,IAAI,QAAY,QAAU;IAChC;EACA;AAIA,WAAS,YAAa,QAAQ,KAAK,OAAO;AAExC,QAAI,QAAQ,aAAa;AACvB,aAAO,eAAe,QAAQ,KAAK;QACjC,cAAc;QACd,YAAY;QACZ,UAAU;QACV;MAAA,CACD;IACL,OAAS;AACL,aAAO,GAAG,IAAI;IAClB;EACA;AAEA,QAAM,oBAAoB,IAAI,MAAM,GAAG;AACvC,QAAM,kBAAkB,IAAI,MAAM,GAAG;AACrC,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,sBAAkB,CAAC,IAAI,qBAAqB,CAAC,IAAI,IAAI;AACrD,oBAAgB,CAAC,IAAI,qBAAqB,CAAC;EAC7C;AAEA,WAAS,MAAO,OAAO,SAAS;AAC9B,SAAK,QAAQ;AAEb,SAAK,WAAW,QAAQ,UAAU,KAAK;AACvC,SAAK,SAAS,QAAQ,QAAQ,KAAKI;AACnC,SAAK,YAAY,QAAQ,WAAW,KAAK;AAGzC,SAAK,SAAS,QAAQ,QAAQ,KAAK;AAEnC,SAAK,OAAO,QAAQ,MAAM,KAAK;AAC/B,SAAK,WAAW,QAAQ,UAAU,KAAK;AACvC,SAAK,WAAW,OAAO,QAAQ,UAAU,MAAM,WAAW,QAAQ,UAAU,IAAI;AAChF,SAAK,oBAAoB,OAAO,QAAQ,mBAAmB,MAAM,WAAW,QAAQ,mBAAmB,IAAI;AAE3G,SAAK,gBAAgB,KAAK,OAAO;AACjC,SAAK,UAAU,KAAK,OAAO;AAE3B,SAAK,SAAS,MAAM;AACpB,SAAK,WAAW;AAChB,SAAK,OAAO;AACZ,SAAK,YAAY;AACjB,SAAK,aAAa;AAClB,SAAK,QAAQ;AACb,SAAK,iBAAiB;AAItB,SAAK,iBAAiB;AAEtB,SAAK,YAAY,CAAA;AACjB,SAAK,wBAAwB,CAAA;EAW/B;AAEA,WAAS,cAAe,OAAO,SAAS;AACtC,UAAM,OAAO;MACX,MAAM,MAAM;MACZ,QAAQ,MAAM,MAAM,MAAM,GAAG,EAAE;;MAC/B,UAAU,MAAM;MAChB,MAAM,MAAM;MACZ,QAAQ,MAAM,WAAW,MAAM;IACnC;AAEE,SAAK,UAAU,YAAY,IAAI;AAE/B,WAAO,IAAIf,eAAc,SAAS,IAAI;EACxC;AAEA,WAAS,WAAY,OAAO,SAAS;AACnC,UAAM,cAAc,OAAO,OAAO;EACpC;AAEA,WAAS,aAAc,OAAO,SAAS;AACrC,QAAI,MAAM,WAAW;AACnB,YAAM,UAAU,KAAK,MAAM,cAAc,OAAO,OAAO,CAAC;IAC5D;EACA;AAEA,WAAS,YAAa,OAAO,MAAM,OAAO;AACxC,UAAM,eAAe,MAAM;AAE3B,QAAI,aAAa,WAAW,GAAG;AAC7B,YAAM,cAAc,aAAa,aAAa,SAAS,CAAC;AAExD,UAAI,CAAC,gBAAgB,KAAK,aAAa,IAAI,GAAG;AAC5C,oBAAY,IAAI,IAAI;UAClB,SAAS,gBAAgB,KAAK,MAAM,WAAW,IAAI;UACnD,OAAO,MAAM,UAAU,IAAI;QACnC;MACA;IACA;AAEE,UAAM,UAAU,IAAI,IAAI;EAC1B;AAEA,WAAS,uBAAwB,OAAO;AACtC,UAAM,sBAAsB,KAAK,uBAAO,OAAO,IAAI,CAAC;EACtD;AAEA,WAAS,wBAAyB,OAAO;AACvC,UAAM,cAAc,MAAM,sBAAsB,IAAG;AACnD,UAAM,eAAe,MAAM;AAE3B,QAAI,aAAa,WAAW,EAAG;AAE/B,UAAM,SAAS,aAAa,aAAa,SAAS,CAAC;AACnD,UAAM,QAAQ,OAAO,KAAK,WAAW;AAErC,aAAS,QAAQ,GAAG,SAAS,MAAM,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACrE,YAAM,OAAO,MAAM,KAAK;AAExB,UAAI,CAAC,gBAAgB,KAAK,QAAQ,IAAI,GAAG;AACvC,eAAO,IAAI,IAAI,YAAY,IAAI;MACrC;IACA;EACA;AAEA,WAAS,0BAA2B,OAAO;AACzC,UAAM,cAAc,MAAM,sBAAsB,IAAG;AACnD,UAAM,QAAQ,OAAO,KAAK,WAAW;AAErC,aAAS,QAAQ,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AACzD,YAAM,QAAQ,YAAY,MAAM,KAAK,CAAC;AAEtC,UAAI,MAAM,SAAS;AACjB,cAAM,UAAU,MAAM,KAAK,CAAC,IAAI,MAAM;MAC5C,OAAW;AACL,eAAO,MAAM,UAAU,MAAM,KAAK,CAAC;MACzC;IACA;EACA;AAEA,WAAS,cAAe,OAAO;AAC7B,WAAO;MACL,UAAU,MAAM;MAChB,MAAM,MAAM;MACZ,WAAW,MAAM;MACjB,YAAY,MAAM;MAClB,gBAAgB,MAAM;MACtB,KAAK,MAAM;MACX,QAAQ,MAAM;MACd,MAAM,MAAM;MACZ,QAAQ,MAAM;IAClB;EACA;AAEA,WAAS,aAAc,OAAO,UAAU;AACtC,UAAM,WAAW,SAAS;AAC1B,UAAM,OAAO,SAAS;AACtB,UAAM,YAAY,SAAS;AAC3B,UAAM,aAAa,SAAS;AAC5B,UAAM,iBAAiB,SAAS;AAChC,UAAM,MAAM,SAAS;AACrB,UAAM,SAAS,SAAS;AACxB,UAAM,OAAO,SAAS;AACtB,UAAM,SAAS,SAAS;EAC1B;AAEA,QAAM,oBAAoB;IAExB,MAAM,SAAS,oBAAqB,OAAO,MAAM,MAAM;AACrD,UAAI,MAAM,YAAY,MAAM;AAC1B,mBAAW,OAAO,gCAAgC;MACxD;AAEI,UAAI,KAAK,WAAW,GAAG;AACrB,mBAAW,OAAO,6CAA6C;MACrE;AAEI,YAAM,QAAQ,uBAAuB,KAAK,KAAK,CAAC,CAAC;AAEjD,UAAI,UAAU,MAAM;AAClB,mBAAW,OAAO,2CAA2C;MACnE;AAEI,YAAM,QAAQ,SAAS,MAAM,CAAC,GAAG,EAAE;AACnC,YAAM,QAAQ,SAAS,MAAM,CAAC,GAAG,EAAE;AAEnC,UAAI,UAAU,GAAG;AACf,mBAAW,OAAO,2CAA2C;MACnE;AAEI,YAAM,UAAU,KAAK,CAAC;AACtB,YAAM,kBAAmB,QAAQ;AAEjC,UAAI,UAAU,KAAK,UAAU,GAAG;AAC9B,qBAAa,OAAO,0CAA0C;MACpE;IACA;IAEE,KAAK,SAAS,mBAAoB,OAAO,MAAM,MAAM;AACnD,UAAI;AAEJ,UAAI,KAAK,WAAW,GAAG;AACrB,mBAAW,OAAO,6CAA6C;MACrE;AAEI,YAAM,SAAS,KAAK,CAAC;AACrB,eAAS,KAAK,CAAC;AAEf,UAAI,CAAC,mBAAmB,KAAK,MAAM,GAAG;AACpC,mBAAW,OAAO,6DAA6D;MACrF;AAEI,UAAI,gBAAgB,KAAK,MAAM,QAAQ,MAAM,GAAG;AAC9C,mBAAW,OAAO,gDAAgD,SAAS,cAAc;MAC/F;AAEI,UAAI,CAAC,gBAAgB,KAAK,MAAM,GAAG;AACjC,mBAAW,OAAO,8DAA8D;MACtF;AAEI,UAAI;AACF,iBAAS,mBAAmB,MAAM;MACxC,SAAa,KAAK;AACZ,mBAAW,OAAO,8BAA8B,MAAM;MAC5D;AAEI,YAAM,OAAO,MAAM,IAAI;IAC3B;EACA;AAEA,WAAS,eAAgB,OAAO,OAAO,KAAK,WAAW;AACrD,QAAI,QAAQ,KAAK;AACf,YAAM,UAAU,MAAM,MAAM,MAAM,OAAO,GAAG;AAE5C,UAAI,WAAW;AACb,iBAAS,YAAY,GAAG,UAAU,QAAQ,QAAQ,YAAY,SAAS,aAAa,GAAG;AACrF,gBAAM,aAAa,QAAQ,WAAW,SAAS;AAC/C,cAAI,EAAE,eAAe,KACd,cAAc,MAAQ,cAAc,UAAY;AACrD,uBAAW,OAAO,+BAA+B;UAC3D;QACA;MACA,WAAe,sBAAsB,KAAK,OAAO,GAAG;AAC9C,mBAAW,OAAO,8CAA8C;MACtE;AAEI,YAAM,UAAU;IACpB;EACA;AAEA,WAAS,gBAAiB,OAAO;AAC/B,UAAM;AAEN,QAAI,MAAM,sBAAsB,MAAM,MAAM,iBAAiB,MAAM,mBAAmB;AACpF,iBAAW,OAAO,4CAA4C,MAAM,oBAAoB,GAAG;IAC/F;EACA;AAEA,WAAS,cAAe,OAAO,aAAa,QAAQ,iBAAiB;AACnE,QAAI,CAACC,QAAO,SAAS,MAAM,GAAG;AAC5B,iBAAW,OAAO,mEAAmE;IACzF;AAGE,oBAAgB,KAAK;AAErB,UAAM,aAAa,OAAO,KAAK,MAAM;AAErC,aAAS,QAAQ,GAAG,WAAW,WAAW,QAAQ,QAAQ,UAAU,SAAS,GAAG;AAC9E,YAAM,MAAM,WAAW,KAAK;AAE5B,sBAAgB,KAAK;AAErB,UAAI,CAAC,gBAAgB,KAAK,aAAa,GAAG,GAAG;AAC3C,oBAAY,aAAa,KAAK,OAAO,GAAG,CAAC;AACzC,wBAAgB,GAAG,IAAI;MAC7B;IACA;EACA;AAEA,WAAS,iBAAkB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,WAC3E,WAAW,gBAAgB,UAAU;AAIrC,QAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,gBAAU,MAAM,UAAU,MAAM,KAAK,OAAO;AAE5C,eAAS,QAAQ,GAAG,WAAW,QAAQ,QAAQ,QAAQ,UAAU,SAAS,GAAG;AAC3E,YAAI,MAAM,QAAQ,QAAQ,KAAK,CAAC,GAAG;AACjC,qBAAW,OAAO,6CAA6C;QACvE;AAEM,YAAI,OAAO,YAAY,YAAY,OAAO,QAAQ,KAAK,CAAC,MAAM,mBAAmB;AAC/E,kBAAQ,KAAK,IAAI;QACzB;MACA;IACA;AAKE,QAAI,OAAO,YAAY,YAAY,OAAO,OAAO,MAAM,mBAAmB;AACxE,gBAAU;IACd;AAEE,cAAU,OAAO,OAAO;AAExB,QAAI,YAAY,MAAM;AACpB,gBAAU,CAAA;IACd;AAEE,QAAI,WAAW,2BAA2B;AACxC,UAAI,MAAM,QAAQ,SAAS,GAAG;AAC5B,YAAI,UAAU,SAAS,KAAK;AAC1B,qBAAW,OAAO,8BAA8B;QACxD;AAEM,iBAAS,QAAQ,GAAG,WAAW,UAAU,QAAQ,QAAQ,UAAU,SAAS,GAAG;AAC7E,wBAAc,OAAO,SAAS,UAAU,KAAK,GAAG,eAAe;QACvE;MACA,OAAW;AACL,sBAAc,OAAO,SAAS,WAAW,eAAe;MAC9D;IACA,OAAS;AACL,UAAI,CAAC,MAAM,QACP,CAAC,gBAAgB,KAAK,iBAAiB,OAAO,KAC9C,gBAAgB,KAAK,SAAS,OAAO,GAAG;AAC1C,cAAM,OAAO,aAAa,MAAM;AAChC,cAAM,YAAY,kBAAkB,MAAM;AAC1C,cAAM,WAAW,YAAY,MAAM;AACnC,mBAAW,OAAO,wBAAwB;MAChD;AAEI,kBAAY,SAAS,SAAS,SAAS;AACvC,aAAO,gBAAgB,OAAO;IAClC;AAEE,WAAO;EACT;AAEA,WAAS,cAAe,OAAO;AAC7B,UAAM,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAEhD,QAAI,OAAO,IAAc;AACvB,YAAM;IACV,WAAa,OAAO,IAAc;AAC9B,YAAM;AACN,UAAI,MAAM,MAAM,WAAW,MAAM,QAAQ,MAAM,IAAc;AAC3D,cAAM;MACZ;IACA,OAAS;AACL,iBAAW,OAAO,0BAA0B;IAChD;AAEE,UAAM,QAAQ;AACd,UAAM,YAAY,MAAM;AACxB,UAAM,iBAAiB;EACzB;AAEA,WAAS,oBAAqB,OAAO,eAAe,aAAa;AAC/D,QAAI,aAAa;AACjB,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,WAAO,OAAO,GAAG;AACf,aAAO,aAAa,EAAE,GAAG;AACvB,YAAI,OAAO,KAAiB,MAAM,mBAAmB,IAAI;AACvD,gBAAM,iBAAiB,MAAM;QACrC;AACM,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD;AAEI,UAAI,iBAAiB,OAAO,IAAa;AACvC,WAAG;AACD,eAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;QACpD,SAAe,OAAO,MAAgB,OAAO,MAAgB,OAAO;MACpE;AAEI,UAAI,MAAM,EAAE,GAAG;AACb,sBAAc,KAAK;AAEnB,aAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAC1C;AACA,cAAM,aAAa;AAEnB,eAAO,OAAO,IAAiB;AAC7B,gBAAM;AACN,eAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;QACpD;MACA,OAAW;AACL;MACN;IACA;AAEE,QAAI,gBAAgB,MAAM,eAAe,KAAK,MAAM,aAAa,aAAa;AAC5E,mBAAa,OAAO,uBAAuB;IAC/C;AAEE,WAAO;EACT;AAEA,WAAS,sBAAuB,OAAO;AACrC,QAAI,YAAY,MAAM;AACtB,QAAI,KAAK,MAAM,MAAM,WAAW,SAAS;AAIzC,SAAK,OAAO,MAAe,OAAO,OAC9B,OAAO,MAAM,MAAM,WAAW,YAAY,CAAC,KAC3C,OAAO,MAAM,MAAM,WAAW,YAAY,CAAC,GAAG;AAChD,mBAAa;AAEb,WAAK,MAAM,MAAM,WAAW,SAAS;AAErC,UAAI,OAAO,KAAK,UAAU,EAAE,GAAG;AAC7B,eAAO;MACb;IACA;AAEE,WAAO;EACT;AAEA,WAAS,iBAAkB,OAAO,OAAO;AACvC,QAAI,UAAU,GAAG;AACf,YAAM,UAAU;IACpB,WAAa,QAAQ,GAAG;AACpB,YAAM,UAAUA,QAAO,OAAO,MAAM,QAAQ,CAAC;IACjD;EACA;AAEA,WAAS,gBAAiB,OAAO,YAAY,sBAAsB;AACjE,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAM,QAAQ,MAAM;AACpB,UAAM,UAAU,MAAM;AAEtB,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,UAAU,EAAE,KACZ,gBAAgB,EAAE,KAClB,OAAO,MACP,OAAO,MACP,OAAO,MACP,OAAO,MACP,OAAO,OACP,OAAO,MACP,OAAO,MACP,OAAO,MACP,OAAO,MACP,OAAO,MACP,OAAO,IAAa;AACtB,aAAO;IACX;AAEE,QAAI,OAAO,MAAe,OAAO,IAAa;AAC5C,YAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAE3D,UAAI,UAAU,SAAS,KAClB,wBAAwB,gBAAgB,SAAS,GAAI;AACxD,eAAO;MACb;IACA;AAEE,UAAM,OAAO;AACb,UAAM,SAAS;AACf,mBAAe,aAAa,MAAM;AAClC,wBAAoB;AAEpB,WAAO,OAAO,GAAG;AACf,UAAI,OAAO,IAAa;AACtB,cAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAE3D,YAAI,UAAU,SAAS,KAClB,wBAAwB,gBAAgB,SAAS,GAAI;AACxD;QACR;MACA,WAAe,OAAO,IAAa;AAC7B,cAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAE3D,YAAI,UAAU,SAAS,GAAG;AACxB;QACR;MACA,WAAgB,MAAM,aAAa,MAAM,aAAa,sBAAsB,KAAK,KACjE,wBAAwB,gBAAgB,EAAE,GAAI;AACxD;MACN,WAAe,MAAM,EAAE,GAAG;AACpB,gBAAQ,MAAM;AACd,qBAAa,MAAM;AACnB,sBAAc,MAAM;AACpB,4BAAoB,OAAO,OAAO,EAAE;AAEpC,YAAI,MAAM,cAAc,YAAY;AAClC,8BAAoB;AACpB,eAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAC1C;QACR,OAAa;AACL,gBAAM,WAAW;AACjB,gBAAM,OAAO;AACb,gBAAM,YAAY;AAClB,gBAAM,aAAa;AACnB;QACR;MACA;AAEI,UAAI,mBAAmB;AACrB,uBAAe,OAAO,cAAc,YAAY,KAAK;AACrD,yBAAiB,OAAO,MAAM,OAAO,KAAK;AAC1C,uBAAe,aAAa,MAAM;AAClC,4BAAoB;MAC1B;AAEI,UAAI,CAAC,aAAa,EAAE,GAAG;AACrB,qBAAa,MAAM,WAAW;MACpC;AAEI,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;IAChD;AAEE,mBAAe,OAAO,cAAc,YAAY,KAAK;AAErD,QAAI,MAAM,QAAQ;AAChB,aAAO;IACX;AAEE,UAAM,OAAO;AACb,UAAM,SAAS;AACf,WAAO;EACT;AAEA,WAAS,uBAAwB,OAAO,YAAY;AAClD,QAAI;AACJ,QAAI;AAEJ,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,IAAa;AACtB,aAAO;IACX;AAEE,UAAM,OAAO;AACb,UAAM,SAAS;AACf,UAAM;AACN,mBAAe,aAAa,MAAM;AAElC,YAAQ,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ,OAAO,GAAG;AAC1D,UAAI,OAAO,IAAa;AACtB,uBAAe,OAAO,cAAc,MAAM,UAAU,IAAI;AACxD,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,YAAI,OAAO,IAAa;AACtB,yBAAe,MAAM;AACrB,gBAAM;AACN,uBAAa,MAAM;QAC3B,OAAa;AACL,iBAAO;QACf;MACA,WAAe,MAAM,EAAE,GAAG;AACpB,uBAAe,OAAO,cAAc,YAAY,IAAI;AACpD,yBAAiB,OAAO,oBAAoB,OAAO,OAAO,UAAU,CAAC;AACrE,uBAAe,aAAa,MAAM;MACxC,WAAe,MAAM,aAAa,MAAM,aAAa,sBAAsB,KAAK,GAAG;AAC7E,mBAAW,OAAO,8DAA8D;MACtF,OAAW;AACL,cAAM;AACN,YAAI,CAAC,aAAa,EAAE,GAAG;AACrB,uBAAa,MAAM;QAC3B;MACA;IACA;AAEE,eAAW,OAAO,4DAA4D;EAChF;AAEA,WAAS,uBAAwB,OAAO,YAAY;AAClD,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,IAAa;AACtB,aAAO;IACX;AAEE,UAAM,OAAO;AACb,UAAM,SAAS;AACf,UAAM;AACN,mBAAe,aAAa,MAAM;AAElC,YAAQ,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ,OAAO,GAAG;AAC1D,UAAI,OAAO,IAAa;AACtB,uBAAe,OAAO,cAAc,MAAM,UAAU,IAAI;AACxD,cAAM;AACN,eAAO;MACb,WAAe,OAAO,IAAa;AAC7B,uBAAe,OAAO,cAAc,MAAM,UAAU,IAAI;AACxD,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,YAAI,MAAM,EAAE,GAAG;AACb,8BAAoB,OAAO,OAAO,UAAU;QAGpD,WAAiB,KAAK,OAAO,kBAAkB,EAAE,GAAG;AAC5C,gBAAM,UAAU,gBAAgB,EAAE;AAClC,gBAAM;QACd,YAAkB,MAAM,cAAc,EAAE,KAAK,GAAG;AACxC,cAAI,YAAY;AAChB,cAAI,YAAY;AAEhB,iBAAO,YAAY,GAAG,aAAa;AACjC,iBAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,iBAAK,MAAM,YAAY,EAAE,MAAM,GAAG;AAChC,2BAAa,aAAa,KAAK;YAC3C,OAAiB;AACL,yBAAW,OAAO,gCAAgC;YAC9D;UACA;AAEQ,gBAAM,UAAU,kBAAkB,SAAS;AAE3C,gBAAM;QACd,OAAa;AACL,qBAAW,OAAO,yBAAyB;QACnD;AAEM,uBAAe,aAAa,MAAM;MACxC,WAAe,MAAM,EAAE,GAAG;AACpB,uBAAe,OAAO,cAAc,YAAY,IAAI;AACpD,yBAAiB,OAAO,oBAAoB,OAAO,OAAO,UAAU,CAAC;AACrE,uBAAe,aAAa,MAAM;MACxC,WAAe,MAAM,aAAa,MAAM,aAAa,sBAAsB,KAAK,GAAG;AAC7E,mBAAW,OAAO,8DAA8D;MACtF,OAAW;AACL,cAAM;AACN,YAAI,CAAC,aAAa,EAAE,GAAG;AACrB,uBAAa,MAAM;QAC3B;MACA;IACA;AAEE,eAAW,OAAO,4DAA4D;EAChF;AAEA,WAAS,mBAAoB,OAAO,YAAY;AAC9C,QAAI,WAAW;AACf,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAM,OAAO,MAAM;AACnB,QAAI;AACJ,UAAM,UAAU,MAAM;AACtB,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAM,kBAAkB,uBAAO,OAAO,IAAI;AAC1C,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,IAAa;AACtB,mBAAa;AACb,kBAAY;AACZ,gBAAU,CAAA;IACd,WAAa,OAAO,KAAa;AAC7B,mBAAa;AACb,kBAAY;AACZ,gBAAU,CAAA;IACd,OAAS;AACL,aAAO;IACX;AAEE,QAAI,MAAM,WAAW,MAAM;AACzB,kBAAY,OAAO,MAAM,QAAQ,OAAO;IAC5C;AAEE,SAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,WAAO,OAAO,GAAG;AACf,0BAAoB,OAAO,MAAM,UAAU;AAE3C,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,UAAI,OAAO,YAAY;AACrB,cAAM;AACN,cAAM,MAAM;AACZ,cAAM,SAAS;AACf,cAAM,OAAO,YAAY,YAAY;AACrC,cAAM,SAAS;AACf,eAAO;MACb,WAAe,CAAC,UAAU;AACpB,mBAAW,OAAO,8CAA8C;MACtE,WAAe,OAAO,IAAa;AAE7B,mBAAW,OAAO,0CAA0C;MAClE;AAEI,eAAS,UAAU,YAAY;AAC/B,eAAS,iBAAiB;AAE1B,UAAI,OAAO,IAAa;AACtB,cAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAE3D,YAAI,UAAU,SAAS,GAAG;AACxB,mBAAS,iBAAiB;AAC1B,gBAAM;AACN,8BAAoB,OAAO,MAAM,UAAU;QACnD;MACA;AAEI,cAAQ,MAAM;AACd,mBAAa,MAAM;AACnB,aAAO,MAAM;AACb,kBAAY,OAAO,YAAY,iBAAiB,OAAO,IAAI;AAC3D,eAAS,MAAM;AACf,gBAAU,MAAM;AAChB,0BAAoB,OAAO,MAAM,UAAU;AAE3C,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,WAAK,kBAAkB,MAAM,SAAS,UAAU,OAAO,IAAa;AAClE,iBAAS;AACT,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAC5C,4BAAoB,OAAO,MAAM,UAAU;AAC3C,oBAAY,OAAO,YAAY,iBAAiB,OAAO,IAAI;AAC3D,oBAAY,MAAM;MACxB;AAEI,UAAI,WAAW;AACb,yBAAiB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,WAAW,OAAO,YAAY,IAAI;MAC3G,WAAe,QAAQ;AACjB,gBAAQ,KAAK,iBAAiB,OAAO,MAAM,iBAAiB,QAAQ,SAAS,WAAW,OAAO,YAAY,IAAI,CAAC;MACtH,OAAW;AACL,gBAAQ,KAAK,OAAO;MAC1B;AAEI,0BAAoB,OAAO,MAAM,UAAU;AAE3C,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,UAAI,OAAO,IAAa;AACtB,mBAAW;AACX,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD,OAAW;AACL,mBAAW;MACjB;IACA;AAEE,eAAW,OAAO,uDAAuD;EAC3E;AAEA,WAAS,gBAAiB,OAAO,YAAY;AAC3C,QAAI;AACJ,QAAI,WAAW;AACf,QAAI,iBAAiB;AACrB,QAAI,iBAAiB;AACrB,QAAI,aAAa;AACjB,QAAI,aAAa;AACjB,QAAI,iBAAiB;AACrB,QAAI;AAEJ,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,KAAa;AACtB,gBAAU;IACd,WAAa,OAAO,IAAa;AAC7B,gBAAU;IACd,OAAS;AACL,aAAO;IACX;AAEE,UAAM,OAAO;AACb,UAAM,SAAS;AAEf,WAAO,OAAO,GAAG;AACf,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,UAAI,OAAO,MAAe,OAAO,IAAa;AAC5C,YAAI,kBAAkB,UAAU;AAC9B,qBAAY,OAAO,KAAe,gBAAgB;QAC1D,OAAa;AACL,qBAAW,OAAO,sCAAsC;QAChE;MACA,YAAgB,MAAM,gBAAgB,EAAE,MAAM,GAAG;AAC3C,YAAI,QAAQ,GAAG;AACb,qBAAW,OAAO,8EAA8E;QACxG,WAAiB,CAAC,gBAAgB;AAC1B,uBAAa,aAAa,MAAM;AAChC,2BAAiB;QACzB,OAAa;AACL,qBAAW,OAAO,2CAA2C;QACrE;MACA,OAAW;AACL;MACN;IACA;AAEE,QAAI,aAAa,EAAE,GAAG;AACpB,SAAG;AAAE,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAAC,SAC3C,aAAa,EAAE;AAEtB,UAAI,OAAO,IAAa;AACtB,WAAG;AAAE,eAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;QAAC,SAC3C,CAAC,MAAM,EAAE,KAAM,OAAO;MACnC;IACA;AAEE,WAAO,OAAO,GAAG;AACf,oBAAc,KAAK;AACnB,YAAM,aAAa;AAEnB,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAG1C,cAAQ,CAAC,kBAAkB,MAAM,aAAa,eACtC,OAAO,IAAkB;AAC/B,cAAM;AACN,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD;AAEI,UAAI,CAAC,kBAAkB,MAAM,aAAa,YAAY;AACpD,qBAAa,MAAM;MACzB;AAEI,UAAI,MAAM,EAAE,GAAG;AACb;AACA;MACN;AAEI,UAAI,CAAC,kBAAkB,eAAe,GAAG;AACvC,mBAAW,OAAO,sCAAsC;MAC9D;AAGI,UAAI,MAAM,aAAa,YAAY;AAEjC,YAAI,aAAa,eAAe;AAC9B,gBAAM,UAAUA,QAAO,OAAO,MAAM,iBAAiB,IAAI,aAAa,UAAU;QACxF,WAAiB,aAAa,eAAe;AACrC,cAAI,gBAAgB;AAClB,kBAAM,UAAU;UAC1B;QACA;AAGM;MACN;AAGI,UAAI,SAAS;AAEX,YAAI,aAAa,EAAE,GAAG;AACpB,2BAAiB;AAEjB,gBAAM,UAAUA,QAAO,OAAO,MAAM,iBAAiB,IAAI,aAAa,UAAU;QAGxF,WAAiB,gBAAgB;AACzB,2BAAiB;AACjB,gBAAM,UAAUA,QAAO,OAAO,MAAM,aAAa,CAAC;QAG1D,WAAiB,eAAe,GAAG;AAC3B,cAAI,gBAAgB;AAClB,kBAAM,UAAU;UAC1B;QAGA,OAAa;AACL,gBAAM,UAAUA,QAAO,OAAO,MAAM,UAAU;QACtD;MAGA,OAAW;AAEL,cAAM,UAAUA,QAAO,OAAO,MAAM,iBAAiB,IAAI,aAAa,UAAU;MACtF;AAEI,uBAAiB;AACjB,uBAAiB;AACjB,mBAAa;AACb,YAAM,eAAe,MAAM;AAE3B,aAAO,CAAC,MAAM,EAAE,KAAM,OAAO,GAAI;AAC/B,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD;AAEI,qBAAe,OAAO,cAAc,MAAM,UAAU,KAAK;IAC7D;AAEE,WAAO;EACT;AAEA,WAAS,kBAAmB,OAAO,YAAY;AAC7C,UAAM,OAAO,MAAM;AACnB,UAAM,UAAU,MAAM;AACtB,UAAM,UAAU,CAAA;AAChB,QAAI,WAAW;AAIf,QAAI,MAAM,mBAAmB,GAAI,QAAO;AAExC,QAAI,MAAM,WAAW,MAAM;AACzB,kBAAY,OAAO,MAAM,QAAQ,OAAO;IAC5C;AAEE,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,WAAO,OAAO,GAAG;AACf,UAAI,MAAM,mBAAmB,IAAI;AAC/B,cAAM,WAAW,MAAM;AACvB,mBAAW,OAAO,gDAAgD;MACxE;AAEI,UAAI,OAAO,IAAa;AACtB;MACN;AAEI,YAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAE3D,UAAI,CAAC,UAAU,SAAS,GAAG;AACzB;MACN;AAEI,iBAAW;AACX,YAAM;AAEN,UAAI,oBAAoB,OAAO,MAAM,EAAE,GAAG;AACxC,YAAI,MAAM,cAAc,YAAY;AAClC,kBAAQ,KAAK,IAAI;AACjB,eAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAC1C;QACR;MACA;AAEI,YAAM,QAAQ,MAAM;AACpB,kBAAY,OAAO,YAAY,kBAAkB,OAAO,IAAI;AAC5D,cAAQ,KAAK,MAAM,MAAM;AACzB,0BAAoB,OAAO,MAAM,EAAE;AAEnC,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,WAAK,MAAM,SAAS,SAAS,MAAM,aAAa,eAAgB,OAAO,GAAI;AACzE,mBAAW,OAAO,qCAAqC;MAC7D,WAAe,MAAM,aAAa,YAAY;AACxC;MACN;IACA;AAEE,QAAI,UAAU;AACZ,YAAM,MAAM;AACZ,YAAM,SAAS;AACf,YAAM,OAAO;AACb,YAAM,SAAS;AACf,aAAO;IACX;AACE,WAAO;EACT;AAEA,WAAS,iBAAkB,OAAO,YAAY,YAAY;AACxD,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAM,OAAO,MAAM;AACnB,UAAM,UAAU,MAAM;AACtB,UAAM,UAAU,CAAA;AAChB,UAAM,kBAAkB,uBAAO,OAAO,IAAI;AAC1C,QAAI,SAAS;AACb,QAAI,UAAU;AACd,QAAI,YAAY;AAChB,QAAI,gBAAgB;AACpB,QAAI,WAAW;AAIf,QAAI,MAAM,mBAAmB,GAAI,QAAO;AAExC,QAAI,MAAM,WAAW,MAAM;AACzB,kBAAY,OAAO,MAAM,QAAQ,OAAO;IAC5C;AAEE,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,WAAO,OAAO,GAAG;AACf,UAAI,CAAC,iBAAiB,MAAM,mBAAmB,IAAI;AACjD,cAAM,WAAW,MAAM;AACvB,mBAAW,OAAO,gDAAgD;MACxE;AAEI,YAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAC3D,YAAM,QAAQ,MAAM;AAMpB,WAAK,OAAO,MAAe,OAAO,OAAgB,UAAU,SAAS,GAAG;AACtE,YAAI,OAAO,IAAa;AACtB,cAAI,eAAe;AACjB,6BAAiB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,MAAM,UAAU,eAAe,OAAO;AACzG,qBAAS,UAAU,YAAY;UACzC;AAEQ,qBAAW;AACX,0BAAgB;AAChB,yBAAe;QACvB,WAAiB,eAAe;AAExB,0BAAgB;AAChB,yBAAe;QACvB,OAAa;AACL,qBAAW,OAAO,mGAAmG;QAC7H;AAEM,cAAM,YAAY;AAClB,aAAK;MAKX,OAAW;AACL,mBAAW,MAAM;AACjB,wBAAgB,MAAM;AACtB,kBAAU,MAAM;AAEhB,YAAI,CAAC,YAAY,OAAO,YAAY,kBAAkB,OAAO,IAAI,GAAG;AAGlE;QACR;AAEM,YAAI,MAAM,SAAS,OAAO;AACxB,eAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,iBAAO,aAAa,EAAE,GAAG;AACvB,iBAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;UACtD;AAEQ,cAAI,OAAO,IAAa;AACtB,iBAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,gBAAI,CAAC,UAAU,EAAE,GAAG;AAClB,yBAAW,OAAO,yFAAyF;YACvH;AAEU,gBAAI,eAAe;AACjB,+BAAiB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,MAAM,UAAU,eAAe,OAAO;AACzG,uBAAS,UAAU,YAAY;YAC3C;AAEU,uBAAW;AACX,4BAAgB;AAChB,2BAAe;AACf,qBAAS,MAAM;AACf,sBAAU,MAAM;UAC1B,WAAmB,UAAU;AACnB,uBAAW,OAAO,0DAA0D;UACtF,OAAe;AACL,kBAAM,MAAM;AACZ,kBAAM,SAAS;AACf,mBAAO;UACjB;QACA,WAAiB,UAAU;AACnB,qBAAW,OAAO,gFAAgF;QAC1G,OAAa;AACL,gBAAM,MAAM;AACZ,gBAAM,SAAS;AACf,iBAAO;QACf;MACA;AAKI,UAAI,MAAM,SAAS,SAAS,MAAM,aAAa,YAAY;AACzD,YAAI,eAAe;AACjB,qBAAW,MAAM;AACjB,0BAAgB,MAAM;AACtB,oBAAU,MAAM;QACxB;AAEM,YAAI,YAAY,OAAO,YAAY,mBAAmB,MAAM,YAAY,GAAG;AACzE,cAAI,eAAe;AACjB,sBAAU,MAAM;UAC1B,OAAe;AACL,wBAAY,MAAM;UAC5B;QACA;AAEM,YAAI,CAAC,eAAe;AAClB,2BAAiB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,WAAW,UAAU,eAAe,OAAO;AAC9G,mBAAS,UAAU,YAAY;QACvC;AAEM,4BAAoB,OAAO,MAAM,EAAE;AACnC,aAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;MAChD;AAEI,WAAK,MAAM,SAAS,SAAS,MAAM,aAAa,eAAgB,OAAO,GAAI;AACzE,mBAAW,OAAO,oCAAoC;MAC5D,WAAe,MAAM,aAAa,YAAY;AACxC;MACN;IACA;AAOE,QAAI,eAAe;AACjB,uBAAiB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,MAAM,UAAU,eAAe,OAAO;IAC7G;AAGE,QAAI,UAAU;AACZ,YAAM,MAAM;AACZ,YAAM,SAAS;AACf,YAAM,OAAO;AACb,YAAM,SAAS;IACnB;AAEE,WAAO;EACT;AAEA,WAAS,gBAAiB,OAAO;AAC/B,QAAI,aAAa;AACjB,QAAI,UAAU;AACd,QAAI;AACJ,QAAI;AAEJ,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,GAAa,QAAO;AAE/B,QAAI,MAAM,QAAQ,MAAM;AACtB,iBAAW,OAAO,+BAA+B;IACrD;AAEE,SAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,QAAI,OAAO,IAAa;AACtB,mBAAa;AACb,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;IAChD,WAAa,OAAO,IAAa;AAC7B,gBAAU;AACV,kBAAY;AACZ,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;IAChD,OAAS;AACL,kBAAY;IAChB;AAEE,QAAI,YAAY,MAAM;AAEtB,QAAI,YAAY;AACd,SAAG;AAAE,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAAC,SAC3C,OAAO,KAAK,OAAO;AAE1B,UAAI,MAAM,WAAW,MAAM,QAAQ;AACjC,kBAAU,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ;AACrD,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD,OAAW;AACL,mBAAW,OAAO,oDAAoD;MAC5E;IACA,OAAS;AACL,aAAO,OAAO,KAAK,CAAC,UAAU,EAAE,GAAG;AACjC,YAAI,OAAO,IAAa;AACtB,cAAI,CAAC,SAAS;AACZ,wBAAY,MAAM,MAAM,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC;AAE/D,gBAAI,CAAC,mBAAmB,KAAK,SAAS,GAAG;AACvC,yBAAW,OAAO,iDAAiD;YAC/E;AAEU,sBAAU;AACV,wBAAY,MAAM,WAAW;UACvC,OAAe;AACL,uBAAW,OAAO,6CAA6C;UACzE;QACA;AAEM,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD;AAEI,gBAAU,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ;AAErD,UAAI,wBAAwB,KAAK,OAAO,GAAG;AACzC,mBAAW,OAAO,qDAAqD;MAC7E;IACA;AAEE,QAAI,WAAW,CAAC,gBAAgB,KAAK,OAAO,GAAG;AAC7C,iBAAW,OAAO,8CAA8C,OAAO;IAC3E;AAEE,QAAI;AACF,gBAAU,mBAAmB,OAAO;IACxC,SAAW,KAAK;AACZ,iBAAW,OAAO,4BAA4B,OAAO;IACzD;AAEE,QAAI,YAAY;AACd,YAAM,MAAM;IAChB,WAAa,gBAAgB,KAAK,MAAM,QAAQ,SAAS,GAAG;AACxD,YAAM,MAAM,MAAM,OAAO,SAAS,IAAI;IAC1C,WAAa,cAAc,KAAK;AAC5B,YAAM,MAAM,MAAM;IACtB,WAAa,cAAc,MAAM;AAC7B,YAAM,MAAM,uBAAuB;IACvC,OAAS;AACL,iBAAW,OAAO,4BAA4B,YAAY,GAAG;IACjE;AAEE,WAAO;EACT;AAEA,WAAS,mBAAoB,OAAO;AAClC,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,GAAa,QAAO;AAE/B,QAAI,MAAM,WAAW,MAAM;AACzB,iBAAW,OAAO,mCAAmC;IACzD;AAEE,SAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAC5C,UAAM,YAAY,MAAM;AAExB,WAAO,OAAO,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,gBAAgB,EAAE,GAAG;AACzD,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;IAChD;AAEE,QAAI,MAAM,aAAa,WAAW;AAChC,iBAAW,OAAO,4DAA4D;IAClF;AAEE,UAAM,SAAS,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ;AAC1D,WAAO;EACT;AAEA,WAAS,UAAW,OAAO;AACzB,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,GAAa,QAAO;AAE/B,SAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAC5C,UAAM,YAAY,MAAM;AAExB,WAAO,OAAO,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,gBAAgB,EAAE,GAAG;AACzD,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;IAChD;AAEE,QAAI,MAAM,aAAa,WAAW;AAChC,iBAAW,OAAO,2DAA2D;IACjF;AAEE,UAAM,QAAQ,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ;AAEzD,QAAI,CAAC,gBAAgB,KAAK,MAAM,WAAW,KAAK,GAAG;AACjD,iBAAW,OAAO,yBAAyB,QAAQ,GAAG;IAC1D;AAEE,UAAM,SAAS,MAAM,UAAU,KAAK;AACpC,wBAAoB,OAAO,MAAM,EAAE;AACnC,WAAO;EACT;AAEA,WAAS,gCAAiC,OAAO,eAAe,YAAY,YAAY;AACtF,UAAM,gBAAgB,cAAc,KAAK;AAEzC,2BAAuB,KAAK;AAC5B,iBAAa,OAAO,aAAa;AAIjC,UAAM,MAAM;AACZ,UAAM,SAAS;AACf,UAAM,OAAO;AACb,UAAM,SAAS;AAEf,QAAI,iBAAiB,OAAO,YAAY,UAAU,KAAK,MAAM,SAAS,WAAW;AAC/E,8BAAwB,KAAK;AAC7B,aAAO;IACX;AAEE,8BAA0B,KAAK;AAC/B,iBAAa,OAAO,aAAa;AACjC,WAAO;EACT;AAEA,WAAS,YAAa,OAAO,cAAc,aAAa,aAAa,cAAc;AACjF,QAAI;AACJ,QAAI;AACJ,QAAI,eAAe;AACnB,QAAI,YAAY;AAChB,QAAI,aAAa;AACjB,QAAI,gBAAgB;AACpB,QAAIO;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,MAAM,SAAS,MAAM,UAAU;AACjC,iBAAW,OAAO,gCAAgC,MAAM,WAAW,GAAG;IAC1E;AAEE,UAAM,SAAS;AAEf,QAAI,MAAM,aAAa,MAAM;AAC3B,YAAM,SAAS,QAAQ,KAAK;IAChC;AAEE,UAAM,MAAM;AACZ,UAAM,SAAS;AACf,UAAM,OAAO;AACb,UAAM,SAAS;AAEf,UAAM,mBAAmB,oBAAoB,wBAC3C,sBAAsB,eACtB,qBAAqB;AAEvB,QAAI,aAAa;AACf,UAAI,oBAAoB,OAAO,MAAM,EAAE,GAAG;AACxC,oBAAY;AAEZ,YAAI,MAAM,aAAa,cAAc;AACnC,yBAAe;QACvB,WAAiB,MAAM,eAAe,cAAc;AAC5C,yBAAe;QACvB,WAAiB,MAAM,aAAa,cAAc;AAC1C,yBAAe;QACvB;MACA;IACA;AAEE,QAAI,iBAAiB,GAAG;AACtB,aAAO,MAAM;AACX,cAAM,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAChD,cAAM,gBAAgB,cAAc,KAAK;AAIzC,YAAI,cACE,OAAO,MAAe,MAAM,QAAQ,QACpC,OAAO,MAAe,MAAM,WAAW,OAAQ;AACnD;QACR;AAEM,YAAI,CAAC,gBAAgB,KAAK,KAAK,CAAC,mBAAmB,KAAK,GAAG;AACzD;QACR;AAEM,YAAI,kBAAkB,MAAM;AAC1B,0BAAgB;QACxB;AAEM,YAAI,oBAAoB,OAAO,MAAM,EAAE,GAAG;AACxC,sBAAY;AACZ,kCAAwB;AAExB,cAAI,MAAM,aAAa,cAAc;AACnC,2BAAe;UACzB,WAAmB,MAAM,eAAe,cAAc;AAC5C,2BAAe;UACzB,WAAmB,MAAM,aAAa,cAAc;AAC1C,2BAAe;UACzB;QACA,OAAa;AACL,kCAAwB;QAChC;MACA;IACA;AAEE,QAAI,uBAAuB;AACzB,8BAAwB,aAAa;IACzC;AAEE,QAAI,iBAAiB,KAAK,sBAAsB,aAAa;AAC3D,UAAI,oBAAoB,eAAe,qBAAqB,aAAa;AACvE,qBAAa;MACnB,OAAW;AACL,qBAAa,eAAe;MAClC;AAEI,oBAAc,MAAM,WAAW,MAAM;AAErC,UAAI,iBAAiB,GAAG;AACtB,YAAK,0BACA,kBAAkB,OAAO,WAAW,KAAK,iBAAiB,OAAO,aAAa,UAAU,MACzF,mBAAmB,OAAO,UAAU,GAAG;AACzC,uBAAa;QACrB,OAAa;AACL,gBAAM,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAEhD,cAAI,kBAAkB,QAAQ,oBAAoB,CAAC,yBAC/C,OAAO,OAAe,OAAO,MAC7B;YACE;YACA;YACA,cAAc,WAAW,cAAc;YACvC;UACd,GAAe;AACL,yBAAa;UACvB,WAAoB,qBAAqB,gBAAgB,OAAO,UAAU,KAC9D,uBAAuB,OAAO,UAAU,KACxC,uBAAuB,OAAO,UAAU,GAAG;AAC7C,yBAAa;UACvB,WAAmB,UAAU,KAAK,GAAG;AAC3B,yBAAa;AAEb,gBAAI,MAAM,QAAQ,QAAQ,MAAM,WAAW,MAAM;AAC/C,yBAAW,OAAO,2CAA2C;YACzE;UACA,WAAmB,gBAAgB,OAAO,YAAY,oBAAoB,WAAW,GAAG;AAC9E,yBAAa;AAEb,gBAAI,MAAM,QAAQ,MAAM;AACtB,oBAAM,MAAM;YACxB;UACA;AAEQ,cAAI,MAAM,WAAW,MAAM;AACzB,wBAAY,OAAO,MAAM,QAAQ,MAAM,MAAM;UACvD;QACA;MACA,WAAe,iBAAiB,GAAG;AAG7B,qBAAa,yBAAyB,kBAAkB,OAAO,WAAW;MAChF;IACA;AAEE,QAAI,MAAM,QAAQ,MAAM;AACtB,UAAI,MAAM,WAAW,MAAM;AACzB,oBAAY,OAAO,MAAM,QAAQ,MAAM,MAAM;MACnD;IACA,WAAa,MAAM,QAAQ,KAAK;AAO5B,UAAI,MAAM,WAAW,QAAQ,MAAM,SAAS,UAAU;AACpD,mBAAW,OAAO,sEAAsE,MAAM,OAAO,GAAG;MAC9G;AAEI,eAAS,YAAY,GAAG,eAAe,MAAM,cAAc,QAAQ,YAAY,cAAc,aAAa,GAAG;AAC3GA,gBAAO,MAAM,cAAc,SAAS;AAEpC,YAAIA,MAAK,QAAQ,MAAM,MAAM,GAAG;AAC9B,gBAAM,SAASA,MAAK,UAAU,MAAM,MAAM;AAC1C,gBAAM,MAAMA,MAAK;AACjB,cAAI,MAAM,WAAW,MAAM;AACzB,wBAAY,OAAO,MAAM,QAAQ,MAAM,MAAM;UACvD;AACQ;QACR;MACA;IACA,WAAa,MAAM,QAAQ,KAAK;AAC5B,UAAI,gBAAgB,KAAK,MAAM,QAAQ,MAAM,QAAQ,UAAU,GAAG,MAAM,GAAG,GAAG;AAC5EA,gBAAO,MAAM,QAAQ,MAAM,QAAQ,UAAU,EAAE,MAAM,GAAG;MAC9D,OAAW;AAELA,gBAAO;AACP,cAAM,WAAW,MAAM,QAAQ,MAAM,MAAM,QAAQ,UAAU;AAE7D,iBAAS,YAAY,GAAG,eAAe,SAAS,QAAQ,YAAY,cAAc,aAAa,GAAG;AAChG,cAAI,MAAM,IAAI,MAAM,GAAG,SAAS,SAAS,EAAE,IAAI,MAAM,MAAM,SAAS,SAAS,EAAE,KAAK;AAClFA,oBAAO,SAAS,SAAS;AACzB;UACV;QACA;MACA;AAEI,UAAI,CAACA,OAAM;AACT,mBAAW,OAAO,mBAAmB,MAAM,MAAM,GAAG;MAC1D;AAEI,UAAI,MAAM,WAAW,QAAQA,MAAK,SAAS,MAAM,MAAM;AACrD,mBAAW,OAAO,kCAAkC,MAAM,MAAM,0BAA0BA,MAAK,OAAO,aAAa,MAAM,OAAO,GAAG;MACzI;AAEI,UAAI,CAACA,MAAK,QAAQ,MAAM,QAAQ,MAAM,GAAG,GAAG;AAC1C,mBAAW,OAAO,kCAAkC,MAAM,MAAM,gBAAgB;MACtF,OAAW;AACL,cAAM,SAASA,MAAK,UAAU,MAAM,QAAQ,MAAM,GAAG;AACrD,YAAI,MAAM,WAAW,MAAM;AACzB,sBAAY,OAAO,MAAM,QAAQ,MAAM,MAAM;QACrD;MACA;IACA;AAEE,QAAI,MAAM,aAAa,MAAM;AAC3B,YAAM,SAAS,SAAS,KAAK;IACjC;AAEE,UAAM,SAAS;AACf,WAAO,MAAM,QAAQ,QAAQ,MAAM,WAAW,QAAQ;EACxD;AAEA,WAAS,aAAc,OAAO;AAC5B,UAAM,gBAAgB,MAAM;AAC5B,QAAI,gBAAgB;AACpB,QAAI;AAEJ,UAAM,UAAU;AAChB,UAAM,kBAAkB,MAAM;AAC9B,UAAM,SAAS,uBAAO,OAAO,IAAI;AACjC,UAAM,YAAY,uBAAO,OAAO,IAAI;AAEpC,YAAQ,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ,OAAO,GAAG;AAC1D,0BAAoB,OAAO,MAAM,EAAE;AAEnC,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,UAAI,MAAM,aAAa,KAAK,OAAO,IAAa;AAC9C;MACN;AAEI,sBAAgB;AAChB,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAC5C,UAAI,YAAY,MAAM;AAEtB,aAAO,OAAO,KAAK,CAAC,UAAU,EAAE,GAAG;AACjC,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD;AAEI,YAAM,gBAAgB,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ;AACjE,YAAM,gBAAgB,CAAA;AAEtB,UAAI,cAAc,SAAS,GAAG;AAC5B,mBAAW,OAAO,8DAA8D;MACtF;AAEI,aAAO,OAAO,GAAG;AACf,eAAO,aAAa,EAAE,GAAG;AACvB,eAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;QACpD;AAEM,YAAI,OAAO,IAAa;AACtB,aAAG;AAAE,iBAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;UAAC,SAC3C,OAAO,KAAK,CAAC,MAAM,EAAE;AAC5B;QACR;AAEM,YAAI,MAAM,EAAE,EAAG;AAEf,oBAAY,MAAM;AAElB,eAAO,OAAO,KAAK,CAAC,UAAU,EAAE,GAAG;AACjC,eAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;QACpD;AAEM,sBAAc,KAAK,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ,CAAC;MACrE;AAEI,UAAI,OAAO,EAAG,eAAc,KAAK;AAEjC,UAAI,gBAAgB,KAAK,mBAAmB,aAAa,GAAG;AAC1D,0BAAkB,aAAa,EAAE,OAAO,eAAe,aAAa;MAC1E,OAAW;AACL,qBAAa,OAAO,iCAAiC,gBAAgB,GAAG;MAC9E;IACA;AAEE,wBAAoB,OAAO,MAAM,EAAE;AAEnC,QAAI,MAAM,eAAe,KACrB,MAAM,MAAM,WAAW,MAAM,QAAQ,MAAM,MAC3C,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC,MAAM,MAC/C,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC,MAAM,IAAa;AAC9D,YAAM,YAAY;AAClB,0BAAoB,OAAO,MAAM,EAAE;IACvC,WAAa,eAAe;AACxB,iBAAW,OAAO,iCAAiC;IACvD;AAEE,gBAAY,OAAO,MAAM,aAAa,GAAG,mBAAmB,OAAO,IAAI;AACvE,wBAAoB,OAAO,MAAM,EAAE;AAEnC,QAAI,MAAM,mBACN,8BAA8B,KAAK,MAAM,MAAM,MAAM,eAAe,MAAM,QAAQ,CAAC,GAAG;AACxF,mBAAa,OAAO,kDAAkD;IAC1E;AAEE,UAAM,UAAU,KAAK,MAAM,MAAM;AAEjC,QAAI,MAAM,aAAa,MAAM,aAAa,sBAAsB,KAAK,GAAG;AACtE,UAAI,MAAM,MAAM,WAAW,MAAM,QAAQ,MAAM,IAAa;AAC1D,cAAM,YAAY;AAClB,4BAAoB,OAAO,MAAM,EAAE;MACzC;AACI;IACJ;AAEE,QAAI,MAAM,WAAY,MAAM,SAAS,GAAI;AACvC,iBAAW,OAAO,uDAAuD;IAC7E;EACA;AAEA,WAAS,cAAe,OAAO,SAAS;AACtC,YAAQ,OAAO,KAAK;AACpB,cAAU,WAAW,CAAA;AAErB,QAAI,MAAM,WAAW,GAAG;AAEtB,UAAI,MAAM,WAAW,MAAM,SAAS,CAAC,MAAM,MACvC,MAAM,WAAW,MAAM,SAAS,CAAC,MAAM,IAAc;AACvD,iBAAS;MACf;AAGI,UAAI,MAAM,WAAW,CAAC,MAAM,OAAQ;AAClC,gBAAQ,MAAM,MAAM,CAAC;MAC3B;IACA;AAEE,UAAM,QAAQ,IAAI,MAAM,OAAO,OAAO;AAEtC,UAAM,UAAU,MAAM,QAAQ,IAAI;AAElC,QAAI,YAAY,IAAI;AAClB,YAAM,WAAW;AACjB,iBAAW,OAAO,mCAAmC;IACzD;AAGE,UAAM,SAAS;AAEf,WAAO,MAAM,MAAM,WAAW,MAAM,QAAQ,MAAM,IAAiB;AACjE,YAAM,cAAc;AACpB,YAAM,YAAY;IACtB;AAEE,WAAO,MAAM,WAAY,MAAM,SAAS,GAAI;AAC1C,mBAAa,KAAK;IACtB;AAEE,WAAO,MAAM;EACf;AAEA,WAASQ,SAAS,OAAO,UAAU,SAAS;AAC1C,QAAI,aAAa,QAAQ,OAAO,aAAa,YAAY,OAAO,YAAY,aAAa;AACvF,gBAAU;AACV,iBAAW;IACf;AAEE,UAAM,YAAY,cAAc,OAAO,OAAO;AAE9C,QAAI,OAAO,aAAa,YAAY;AAClC,aAAO;IACX;AAEE,aAAS,QAAQ,GAAG,SAAS,UAAU,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACzE,eAAS,UAAU,KAAK,CAAC;IAC7B;EACA;AAEA,WAASC,MAAM,OAAO,SAAS;AAC7B,UAAM,YAAY,cAAc,OAAO,OAAO;AAE9C,QAAI,UAAU,WAAW,GAAG;AAC1B,aAAO;IACX,WAAa,UAAU,WAAW,GAAG;AACjC,aAAO,UAAU,CAAC;IACtB;AACE,UAAM,IAAIjB,eAAc,0DAA0D;EACpF;AAEA,SAAA,UAAyBgB;AACzB,SAAA,OAAsBC;;;;;;;;ACxwDtB,QAAMhB,UAASC,cAAA;AACf,QAAMF,iBAAgBM,iBAAA;AACtB,QAAMS,kBAAiBL,gBAAA;AAEvB,QAAM,YAAY,OAAO,UAAU;AACnC,QAAM,kBAAkB,OAAO,UAAU;AAEzC,QAAM,WAAW;AACjB,QAAM,WAAW;AACjB,QAAM,iBAAiB;AACvB,QAAM,uBAAuB;AAC7B,QAAM,aAAa;AACnB,QAAM,mBAAmB;AACzB,QAAM,oBAAoB;AAC1B,QAAM,aAAa;AACnB,QAAM,eAAe;AACrB,QAAM,iBAAiB;AACvB,QAAM,oBAAoB;AAC1B,QAAM,gBAAgB;AACtB,QAAM,aAAa;AACnB,QAAM,aAAa;AACnB,QAAM,aAAa;AACnB,QAAM,cAAc;AACpB,QAAM,oBAAoB;AAC1B,QAAM,gBAAgB;AACtB,QAAM,qBAAqB;AAC3B,QAAM,2BAA2B;AACjC,QAAM,4BAA4B;AAClC,QAAM,oBAAoB;AAC1B,QAAM,0BAA0B;AAChC,QAAM,qBAAqB;AAC3B,QAAM,2BAA2B;AAEjC,QAAM,mBAAmB,CAAA;AAEzB,mBAAiB,CAAI,IAAI;AACzB,mBAAiB,CAAI,IAAI;AACzB,mBAAiB,CAAI,IAAI;AACzB,mBAAiB,CAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,GAAI,IAAI;AACzB,mBAAiB,GAAI,IAAI;AACzB,mBAAiB,IAAM,IAAI;AAC3B,mBAAiB,IAAM,IAAI;AAE3B,QAAM,6BAA6B;IACjC;IAAK;IAAK;IAAO;IAAO;IAAO;IAAM;IAAM;IAC3C;IAAK;IAAK;IAAM;IAAM;IAAM;IAAO;IAAO;EAC5C;AAEA,QAAM,2BAA2B;AAEjC,WAAS,gBAAiBH,SAAQH,MAAK;AACrC,QAAIA,SAAQ,KAAM,QAAO,CAAA;AAEzB,UAAM,SAAS,CAAA;AACf,UAAM,OAAO,OAAO,KAAKA,IAAG;AAE5B,aAAS,QAAQ,GAAG,SAAS,KAAK,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACpE,UAAI,MAAM,KAAK,KAAK;AACpB,UAAI,QAAQ,OAAOA,KAAI,GAAG,CAAC;AAE3B,UAAI,IAAI,MAAM,GAAG,CAAC,MAAM,MAAM;AAC5B,cAAM,uBAAuB,IAAI,MAAM,CAAC;MAC9C;AACI,YAAMI,QAAOD,QAAO,gBAAgB,UAAU,EAAE,GAAG;AAEnD,UAAIC,SAAQ,gBAAgB,KAAKA,MAAK,cAAc,KAAK,GAAG;AAC1D,gBAAQA,MAAK,aAAa,KAAK;MACrC;AAEI,aAAO,GAAG,IAAI;IAClB;AAEE,WAAO;EACT;AAEA,WAAS,UAAW,WAAW;AAC7B,QAAI;AACJ,QAAI;AAEJ,UAAM,SAAS,UAAU,SAAS,EAAE,EAAE,YAAW;AAEjD,QAAI,aAAa,KAAM;AACrB,eAAS;AACT,eAAS;IACb,WAAa,aAAa,OAAQ;AAC9B,eAAS;AACT,eAAS;IACb,WAAa,aAAa,YAAY;AAClC,eAAS;AACT,eAAS;IACb,OAAS;AACL,YAAM,IAAIR,eAAc,+DAA+D;IAC3F;AAEE,WAAO,OAAO,SAASC,QAAO,OAAO,KAAK,SAAS,OAAO,MAAM,IAAI;EACtE;AAEA,QAAM,sBAAsB;AAC5B,QAAM,sBAAsB;AAE5B,WAAS,MAAO,SAAS;AACvB,SAAK,SAAS,QAAQ,QAAQ,KAAKc;AACnC,SAAK,SAAS,KAAK,IAAI,GAAI,QAAQ,QAAQ,KAAK,CAAC;AACjD,SAAK,gBAAgB,QAAQ,eAAe,KAAK;AACjD,SAAK,cAAc,QAAQ,aAAa,KAAK;AAC7C,SAAK,YAAad,QAAO,UAAU,QAAQ,WAAW,CAAC,IAAI,KAAK,QAAQ,WAAW;AACnF,SAAK,WAAW,gBAAgB,KAAK,QAAQ,QAAQ,QAAQ,KAAK,IAAI;AACtE,SAAK,WAAW,QAAQ,UAAU,KAAK;AACvC,SAAK,YAAY,QAAQ,WAAW,KAAK;AACzC,SAAK,SAAS,QAAQ,QAAQ,KAAK;AACnC,SAAK,eAAe,QAAQ,cAAc,KAAK;AAC/C,SAAK,eAAe,QAAQ,cAAc,KAAK;AAC/C,SAAK,cAAc,QAAQ,aAAa,MAAM,MAAM,sBAAsB;AAC1E,SAAK,cAAc,QAAQ,aAAa,KAAK;AAC7C,SAAK,WAAW,OAAO,QAAQ,UAAU,MAAM,aAAa,QAAQ,UAAU,IAAI;AAElF,SAAK,gBAAgB,KAAK,OAAO;AACjC,SAAK,gBAAgB,KAAK,OAAO;AAEjC,SAAK,MAAM;AACX,SAAK,SAAS;AAEd,SAAK,aAAa,CAAA;AAClB,SAAK,iBAAiB;EACxB;AAGA,WAAS,aAAc,QAAQ,QAAQ;AACrC,UAAM,MAAMA,QAAO,OAAO,KAAK,MAAM;AACrC,QAAI,WAAW;AACf,QAAI,SAAS;AACb,UAAM,SAAS,OAAO;AAEtB,WAAO,WAAW,QAAQ;AACxB,UAAI;AACJ,YAAM,OAAO,OAAO,QAAQ,MAAM,QAAQ;AAC1C,UAAI,SAAS,IAAI;AACf,eAAO,OAAO,MAAM,QAAQ;AAC5B,mBAAW;MACjB,OAAW;AACL,eAAO,OAAO,MAAM,UAAU,OAAO,CAAC;AACtC,mBAAW,OAAO;MACxB;AAEI,UAAI,KAAK,UAAU,SAAS,KAAM,WAAU;AAE5C,gBAAU;IACd;AAEE,WAAO;EACT;AAEA,WAAS,iBAAkB,OAAO,OAAO;AACvC,WAAO,OAAOA,QAAO,OAAO,KAAK,MAAM,SAAS,KAAK;EACvD;AAEA,WAAS,sBAAuB,OAAOiB,MAAK;AAC1C,aAAS,QAAQ,GAAG,SAAS,MAAM,cAAc,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACnF,YAAMV,QAAO,MAAM,cAAc,KAAK;AAEtC,UAAIA,MAAK,QAAQU,IAAG,GAAG;AACrB,eAAO;MACb;IACA;AAEE,WAAO;EACT;AAGA,WAAS,aAAc,GAAG;AACxB,WAAO,MAAM,cAAc,MAAM;EACnC;AAMA,WAAS,YAAa,GAAG;AACvB,WAAQ,KAAK,MAAW,KAAK,OACzB,KAAK,OAAW,KAAK,SAAa,MAAM,QAAU,MAAM,QACxD,KAAK,SAAW,KAAK,SAAa,MAAM,YACzC,KAAK,SAAW,KAAK;EAC1B;AAOA,WAAS,qBAAsB,GAAG;AAChC,WAAO,YAAY,CAAC,KAClB,MAAM;IAEN,MAAM,wBACN,MAAM;EACV;AAWA,WAAS,YAAa,GAAG,MAAM,SAAS;AACtC,UAAM,wBAAwB,qBAAqB,CAAC;AACpD,UAAM,YAAY,yBAAyB,CAAC,aAAa,CAAC;AAC1D;;OAGI,UACI,wBACA;MAEA,MAAM,cACN,MAAM,4BACN,MAAM,6BACN,MAAM,2BACN,MAAM;MAGZ,MAAM;MACN,EAAE,SAAS,cAAc,CAAC;MAE3B,qBAAqB,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,MAAM;MAC3D,SAAS,cAAc;;EAC1B;AAGA,WAAS,iBAAkB,GAAG;AAI5B,WAAO,YAAY,CAAC,KAClB,MAAM,YACN,CAAC,aAAa,CAAC;;;IAGf,MAAM,cACN,MAAM,iBACN,MAAM,cACN,MAAM,cACN,MAAM,4BACN,MAAM,6BACN,MAAM,2BACN,MAAM;IAEN,MAAM,cACN,MAAM,kBACN,MAAM,iBACN,MAAM,oBACN,MAAM,sBACN,MAAM,eACN,MAAM,qBACN,MAAM,qBACN,MAAM;IAEN,MAAM,gBACN,MAAM,sBACN,MAAM;EACV;AAGA,WAAS,gBAAiB,GAAG;AAE3B,WAAO,CAAC,aAAa,CAAC,KAAK,MAAM;EACnC;AAGA,WAAS,YAAa,QAAQ,KAAK;AACjC,UAAM,QAAQ,OAAO,WAAW,GAAG;AACnC,QAAI;AAEJ,QAAI,SAAS,SAAU,SAAS,SAAU,MAAM,IAAI,OAAO,QAAQ;AACjE,eAAS,OAAO,WAAW,MAAM,CAAC;AAClC,UAAI,UAAU,SAAU,UAAU,OAAQ;AAExC,gBAAQ,QAAQ,SAAU,OAAQ,SAAS,QAAS;MAC1D;IACA;AACE,WAAO;EACT;AAGA,WAAS,oBAAqB,QAAQ;AACpC,UAAM,iBAAiB;AACvB,WAAO,eAAe,KAAK,MAAM;EACnC;AAEA,QAAM,cAAc;AACpB,QAAM,eAAe;AACrB,QAAM,gBAAgB;AACtB,QAAM,eAAe;AACrB,QAAM,eAAe;AASrB,WAAS,kBAAmB,QAAQ,gBAAgB,gBAAgB,WAClE,mBAAmB,aAAa,aAAa,SAAS;AACtD,QAAI;AACJ,QAAI,OAAO;AACX,QAAI,WAAW;AACf,QAAI,eAAe;AACnB,QAAI,kBAAkB;AACtB,UAAM,mBAAmB,cAAc;AACvC,QAAI,oBAAoB;AACxB,QAAI,QAAQ,iBAAiB,YAAY,QAAQ,CAAC,CAAC,KACjD,gBAAgB,YAAY,QAAQ,OAAO,SAAS,CAAC,CAAC;AAExD,QAAI,kBAAkB,aAAa;AAGjC,WAAK,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,QAAU,KAAK,IAAI,KAAK;AAC7D,eAAO,YAAY,QAAQ,CAAC;AAC5B,YAAI,CAAC,YAAY,IAAI,GAAG;AACtB,iBAAO;QACf;AACM,gBAAQ,SAAS,YAAY,MAAM,UAAU,OAAO;AACpD,mBAAW;MACjB;IACA,OAAS;AAEL,WAAK,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,QAAU,KAAK,IAAI,KAAK;AAC7D,eAAO,YAAY,QAAQ,CAAC;AAC5B,YAAI,SAAS,gBAAgB;AAC3B,yBAAe;AAEf,cAAI,kBAAkB;AACpB,8BAAkB;YAEf,IAAI,oBAAoB,IAAI,aAC5B,OAAO,oBAAoB,CAAC,MAAM;AACrC,gCAAoB;UAC9B;QACA,WAAiB,CAAC,YAAY,IAAI,GAAG;AAC7B,iBAAO;QACf;AACM,gBAAQ,SAAS,YAAY,MAAM,UAAU,OAAO;AACpD,mBAAW;MACjB;AAEI,wBAAkB,mBAAoB,qBACnC,IAAI,oBAAoB,IAAI,aAC5B,OAAO,oBAAoB,CAAC,MAAM;IACzC;AAIE,QAAI,CAAC,gBAAgB,CAAC,iBAAiB;AAGrC,UAAI,SAAS,CAAC,eAAe,CAAC,kBAAkB,MAAM,GAAG;AACvD,eAAO;MACb;AACI,aAAO,gBAAgB,sBAAsB,eAAe;IAChE;AAEE,QAAI,iBAAiB,KAAK,oBAAoB,MAAM,GAAG;AACrD,aAAO;IACX;AAGE,QAAI,CAAC,aAAa;AAChB,aAAO,kBAAkB,eAAe;IAC5C;AACE,WAAO,gBAAgB,sBAAsB,eAAe;EAC9D;AAQA,WAAS,YAAa,OAAO,QAAQ,OAAO,OAAO,SAAS;AAC1D,UAAM,QAAQ,WAAY;AACxB,UAAI,OAAO,WAAW,GAAG;AACvB,eAAO,MAAM,gBAAgB,sBAAsB,OAAO;MAChE;AACI,UAAI,CAAC,MAAM,cAAc;AACvB,YAAI,2BAA2B,QAAQ,MAAM,MAAM,MAAM,yBAAyB,KAAK,MAAM,GAAG;AAC9F,iBAAO,MAAM,gBAAgB,sBAAuB,MAAM,SAAS,MAAQ,MAAM,SAAS;QAClG;MACA;AAEI,YAAM,SAAS,MAAM,SAAS,KAAK,IAAI,GAAG,KAAK;AAQ/C,YAAM,YAAa,MAAM,cAAc,KACnC,KACA,KAAK,IAAI,KAAK,IAAI,MAAM,WAAW,EAAE,GAAG,MAAM,YAAY,MAAM;AAGpE,YAAM,iBAAiB;MAEpB,MAAM,YAAY,MAAM,SAAS,MAAM;AAC1C,eAAS,cAAeC,SAAQ;AAC9B,eAAO,sBAAsB,OAAOA,OAAM;MAChD;AAEI,cAAQ;QAAkB;QAAQ;QAAgB,MAAM;QAAQ;QAC9D;QAAe,MAAM;QAAa,MAAM,eAAe,CAAC;QAAO;MAAO,GAAC;QACvE,KAAK;AACH,iBAAO;QACT,KAAK;AACH,iBAAO,MAAM,OAAO,QAAQ,MAAM,IAAI,IAAI;QAC5C,KAAK;AACH,iBAAO,MAAM,YAAY,QAAQ,MAAM,MAAM,IAC3C,kBAAkB,aAAa,QAAQ,MAAM,CAAC;QAClD,KAAK;AACH,iBAAO,MAAM,YAAY,QAAQ,MAAM,MAAM,IAC3C,kBAAkB,aAAa,WAAW,QAAQ,SAAS,GAAG,MAAM,CAAC;QACzE,KAAK;AACH,iBAAO,MAAM,aAAa,MAAiB,IAAI;QACjD;AACE,gBAAM,IAAInB,eAAc,wCAAwC;MACxE;IACA,GAAG;EACH;AAGA,WAAS,YAAa,QAAQ,gBAAgB;AAC5C,UAAM,kBAAkB,oBAAoB,MAAM,IAAI,OAAO,cAAc,IAAI;AAG/E,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC,MAAM;AAC3C,UAAM,OAAO,SAAS,OAAO,OAAO,SAAS,CAAC,MAAM,QAAQ,WAAW;AACvE,UAAM,QAAQ,OAAO,MAAO,OAAO,KAAK;AAExC,WAAO,kBAAkB,QAAQ;EACnC;AAGA,WAAS,kBAAmB,QAAQ;AAClC,WAAO,OAAO,OAAO,SAAS,CAAC,MAAM,OAAO,OAAO,MAAM,GAAG,EAAE,IAAI;EACpE;AAIA,WAAS,WAAY,QAAQ,OAAO;AAKlC,UAAM,SAAS;AAGf,QAAI,UAAU,WAAY;AACxB,UAAI,SAAS,OAAO,QAAQ,IAAI;AAChC,eAAS,WAAW,KAAK,SAAS,OAAO;AACzC,aAAO,YAAY;AACnB,aAAO,SAAS,OAAO,MAAM,GAAG,MAAM,GAAG,KAAK;IAClD,GAAG;AAED,QAAI,mBAAmB,OAAO,CAAC,MAAM,QAAQ,OAAO,CAAC,MAAM;AAC3D,QAAI;AAGJ,QAAI;AACJ,WAAQ,QAAQ,OAAO,KAAK,MAAM,GAAI;AACpC,YAAM,SAAS,MAAM,CAAC;AACtB,YAAM,OAAO,MAAM,CAAC;AAEpB,qBAAgB,KAAK,CAAC,MAAM;AAC5B,gBAAU,UACN,CAAC,oBAAoB,CAAC,gBAAgB,SAAS,KAAM,OAAO,MAC9D,SAAS,MAAM,KAAK;AACtB,yBAAmB;IACvB;AAEE,WAAO;EACT;AAMA,WAAS,SAAU,MAAM,OAAO;AAC9B,QAAI,SAAS,MAAM,KAAK,CAAC,MAAM,IAAK,QAAO;AAG3C,UAAM,UAAU;AAChB,QAAI;AAEJ,QAAI,QAAQ;AACZ,QAAI;AACJ,QAAI,OAAO;AACX,QAAI,OAAO;AACX,QAAI,SAAS;AAMb,WAAQ,QAAQ,QAAQ,KAAK,IAAI,GAAI;AACnC,aAAO,MAAM;AAEb,UAAI,OAAO,QAAQ,OAAO;AACxB,cAAO,OAAO,QAAS,OAAO;AAC9B,kBAAU,OAAO,KAAK,MAAM,OAAO,GAAG;AAEtC,gBAAQ,MAAM;MACpB;AACI,aAAO;IACX;AAIE,cAAU;AAEV,QAAI,KAAK,SAAS,QAAQ,SAAS,OAAO,OAAO;AAC/C,gBAAU,KAAK,MAAM,OAAO,IAAI,IAAI,OAAO,KAAK,MAAM,OAAO,CAAC;IAClE,OAAS;AACL,gBAAU,KAAK,MAAM,KAAK;IAC9B;AAEE,WAAO,OAAO,MAAM,CAAC;EACvB;AAGA,WAAS,aAAc,QAAQ;AAC7B,QAAI,SAAS;AACb,QAAI,OAAO;AAEX,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,QAAU,KAAK,IAAI,KAAK;AACjE,aAAO,YAAY,QAAQ,CAAC;AAC5B,YAAM,YAAY,iBAAiB,IAAI;AAEvC,UAAI,CAAC,aAAa,YAAY,IAAI,GAAG;AACnC,kBAAU,OAAO,CAAC;AAClB,YAAI,QAAQ,MAAS,WAAU,OAAO,IAAI,CAAC;MACjD,OAAW;AACL,kBAAU,aAAa,UAAU,IAAI;MAC3C;IACA;AAEE,WAAO;EACT;AAEA,WAAS,kBAAmB,OAAO,OAAO,QAAQ;AAChD,QAAI,UAAU;AACd,UAAM,OAAO,MAAM;AAEnB,aAAS,QAAQ,GAAG,SAAS,OAAO,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtE,UAAI,QAAQ,OAAO,KAAK;AAExB,UAAI,MAAM,UAAU;AAClB,gBAAQ,MAAM,SAAS,KAAK,QAAQ,OAAO,KAAK,GAAG,KAAK;MAC9D;AAGI,UAAI,UAAU,OAAO,OAAO,OAAO,OAAO,KAAK,KAC1C,OAAO,UAAU,eACjB,UAAU,OAAO,OAAO,MAAM,OAAO,KAAK,GAAI;AACjD,YAAI,YAAY,GAAI,YAAW,OAAO,CAAC,MAAM,eAAe,MAAM;AAClE,mBAAW,MAAM;MACvB;IACA;AAEE,UAAM,MAAM;AACZ,UAAM,OAAO,MAAM,UAAU;EAC/B;AAEA,WAAS,mBAAoB,OAAO,OAAO,QAAQ,SAAS;AAC1D,QAAI,UAAU;AACd,UAAM,OAAO,MAAM;AAEnB,aAAS,QAAQ,GAAG,SAAS,OAAO,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtE,UAAI,QAAQ,OAAO,KAAK;AAExB,UAAI,MAAM,UAAU;AAClB,gBAAQ,MAAM,SAAS,KAAK,QAAQ,OAAO,KAAK,GAAG,KAAK;MAC9D;AAGI,UAAI,UAAU,OAAO,QAAQ,GAAG,OAAO,MAAM,MAAM,OAAO,IAAI,KACzD,OAAO,UAAU,eACjB,UAAU,OAAO,QAAQ,GAAG,MAAM,MAAM,MAAM,OAAO,IAAI,GAAI;AAChE,YAAI,CAAC,WAAW,YAAY,IAAI;AAC9B,qBAAW,iBAAiB,OAAO,KAAK;QAChD;AAEM,YAAI,MAAM,QAAQ,mBAAmB,MAAM,KAAK,WAAW,CAAC,GAAG;AAC7D,qBAAW;QACnB,OAAa;AACL,qBAAW;QACnB;AAEM,mBAAW,MAAM;MACvB;IACA;AAEE,UAAM,MAAM;AACZ,UAAM,OAAO,WAAW;EAC1B;AAEA,WAAS,iBAAkB,OAAO,OAAO,QAAQ;AAC/C,QAAI,UAAU;AACd,UAAM,OAAO,MAAM;AACnB,UAAM,gBAAgB,OAAO,KAAK,MAAM;AAExC,aAAS,QAAQ,GAAG,SAAS,cAAc,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AAC7E,UAAI,aAAa;AACjB,UAAI,YAAY,GAAI,eAAc;AAElC,UAAI,MAAM,aAAc,eAAc;AAEtC,YAAM,YAAY,cAAc,KAAK;AACrC,UAAI,cAAc,OAAO,SAAS;AAElC,UAAI,MAAM,UAAU;AAClB,sBAAc,MAAM,SAAS,KAAK,QAAQ,WAAW,WAAW;MACtE;AAEI,UAAI,CAAC,UAAU,OAAO,OAAO,WAAW,OAAO,KAAK,GAAG;AACrD;MACN;AAEI,UAAI,MAAM,KAAK,SAAS,KAAM,eAAc;AAE5C,oBAAc,MAAM,QAAQ,MAAM,eAAe,MAAM,MAAM,OAAO,MAAM,eAAe,KAAK;AAE9F,UAAI,CAAC,UAAU,OAAO,OAAO,aAAa,OAAO,KAAK,GAAG;AACvD;MACN;AAEI,oBAAc,MAAM;AAGpB,iBAAW;IACf;AAEE,UAAM,MAAM;AACZ,UAAM,OAAO,MAAM,UAAU;EAC/B;AAEA,WAAS,kBAAmB,OAAO,OAAO,QAAQ,SAAS;AACzD,QAAI,UAAU;AACd,UAAM,OAAO,MAAM;AACnB,UAAM,gBAAgB,OAAO,KAAK,MAAM;AAGxC,QAAI,MAAM,aAAa,MAAM;AAE3B,oBAAc,KAAI;IACtB,WAAa,OAAO,MAAM,aAAa,YAAY;AAE/C,oBAAc,KAAK,MAAM,QAAQ;IACrC,WAAa,MAAM,UAAU;AAEzB,YAAM,IAAIA,eAAc,0CAA0C;IACtE;AAEE,aAAS,QAAQ,GAAG,SAAS,cAAc,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AAC7E,UAAI,aAAa;AAEjB,UAAI,CAAC,WAAW,YAAY,IAAI;AAC9B,sBAAc,iBAAiB,OAAO,KAAK;MACjD;AAEI,YAAM,YAAY,cAAc,KAAK;AACrC,UAAI,cAAc,OAAO,SAAS;AAElC,UAAI,MAAM,UAAU;AAClB,sBAAc,MAAM,SAAS,KAAK,QAAQ,WAAW,WAAW;MACtE;AAEI,UAAI,CAAC,UAAU,OAAO,QAAQ,GAAG,WAAW,MAAM,MAAM,IAAI,GAAG;AAC7D;MACN;AAEI,YAAM,eAAgB,MAAM,QAAQ,QAAQ,MAAM,QAAQ,OAC1C,MAAM,QAAQ,MAAM,KAAK,SAAS;AAElD,UAAI,cAAc;AAChB,YAAI,MAAM,QAAQ,mBAAmB,MAAM,KAAK,WAAW,CAAC,GAAG;AAC7D,wBAAc;QACtB,OAAa;AACL,wBAAc;QACtB;MACA;AAEI,oBAAc,MAAM;AAEpB,UAAI,cAAc;AAChB,sBAAc,iBAAiB,OAAO,KAAK;MACjD;AAEI,UAAI,CAAC,UAAU,OAAO,QAAQ,GAAG,aAAa,MAAM,YAAY,GAAG;AACjE;MACN;AAEI,UAAI,MAAM,QAAQ,mBAAmB,MAAM,KAAK,WAAW,CAAC,GAAG;AAC7D,sBAAc;MACpB,OAAW;AACL,sBAAc;MACpB;AAEI,oBAAc,MAAM;AAGpB,iBAAW;IACf;AAEE,UAAM,MAAM;AACZ,UAAM,OAAO,WAAW;EAC1B;AAEA,WAAS,WAAY,OAAO,QAAQ,UAAU;AAC5C,UAAM,WAAW,WAAW,MAAM,gBAAgB,MAAM;AAExD,aAAS,QAAQ,GAAG,SAAS,SAAS,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACxE,YAAMQ,QAAO,SAAS,KAAK;AAE3B,WAAKA,MAAK,cAAcA,MAAK,eACxB,CAACA,MAAK,cAAgB,OAAO,WAAW,YAAc,kBAAkBA,MAAK,gBAC7E,CAACA,MAAK,aAAaA,MAAK,UAAU,MAAM,IAAI;AAC/C,YAAI,UAAU;AACZ,cAAIA,MAAK,SAASA,MAAK,eAAe;AACpC,kBAAM,MAAMA,MAAK,cAAc,MAAM;UAC/C,OAAe;AACL,kBAAM,MAAMA,MAAK;UAC3B;QACA,OAAa;AACL,gBAAM,MAAM;QACpB;AAEM,YAAIA,MAAK,WAAW;AAClB,gBAAM,QAAQ,MAAM,SAASA,MAAK,GAAG,KAAKA,MAAK;AAE/C,cAAI;AACJ,cAAI,UAAU,KAAKA,MAAK,SAAS,MAAM,qBAAqB;AAC1D,sBAAUA,MAAK,UAAU,QAAQ,KAAK;UAChD,WAAmB,gBAAgB,KAAKA,MAAK,WAAW,KAAK,GAAG;AACtD,sBAAUA,MAAK,UAAU,KAAK,EAAE,QAAQ,KAAK;UACvD,OAAe;AACL,kBAAM,IAAIR,eAAc,OAAOQ,MAAK,MAAM,iCAAiC,QAAQ,SAAS;UACtG;AAEQ,gBAAM,OAAO;QACrB;AAEM,eAAO;MACb;IACA;AAEE,WAAO;EACT;AAKA,WAAS,UAAW,OAAO,OAAO,QAAQ,OAAO,SAAS,OAAO,YAAY;AAC3E,UAAM,MAAM;AACZ,UAAM,OAAO;AAEb,QAAI,CAAC,WAAW,OAAO,QAAQ,KAAK,GAAG;AACrC,iBAAW,OAAO,QAAQ,IAAI;IAClC;AAEE,UAAMA,QAAO,UAAU,KAAK,MAAM,IAAI;AACtC,UAAM,UAAU;AAEhB,QAAI,OAAO;AACT,cAAS,MAAM,YAAY,KAAK,MAAM,YAAY;IACtD;AAEE,UAAM,gBAAgBA,UAAS,qBAAqBA,UAAS;AAC7D,QAAI;AACJ,QAAI;AAEJ,QAAI,eAAe;AACjB,uBAAiB,MAAM,WAAW,QAAQ,MAAM;AAChD,kBAAY,mBAAmB;IACnC;AAEE,QAAK,MAAM,QAAQ,QAAQ,MAAM,QAAQ,OAAQ,aAAc,MAAM,WAAW,KAAK,QAAQ,GAAI;AAC/F,gBAAU;IACd;AAEE,QAAI,aAAa,MAAM,eAAe,cAAc,GAAG;AACrD,YAAM,OAAO,UAAU;IAC3B,OAAS;AACL,UAAI,iBAAiB,aAAa,CAAC,MAAM,eAAe,cAAc,GAAG;AACvE,cAAM,eAAe,cAAc,IAAI;MAC7C;AACI,UAAIA,UAAS,mBAAmB;AAC9B,YAAI,SAAU,OAAO,KAAK,MAAM,IAAI,EAAE,WAAW,GAAI;AACnD,4BAAkB,OAAO,OAAO,MAAM,MAAM,OAAO;AACnD,cAAI,WAAW;AACb,kBAAM,OAAO,UAAU,iBAAiB,MAAM;UACxD;QACA,OAAa;AACL,2BAAiB,OAAO,OAAO,MAAM,IAAI;AACzC,cAAI,WAAW;AACb,kBAAM,OAAO,UAAU,iBAAiB,MAAM,MAAM;UAC9D;QACA;MACA,WAAeA,UAAS,kBAAkB;AACpC,YAAI,SAAU,MAAM,KAAK,WAAW,GAAI;AACtC,cAAI,MAAM,iBAAiB,CAAC,cAAc,QAAQ,GAAG;AACnD,+BAAmB,OAAO,QAAQ,GAAG,MAAM,MAAM,OAAO;UAClE,OAAe;AACL,+BAAmB,OAAO,OAAO,MAAM,MAAM,OAAO;UAC9D;AACQ,cAAI,WAAW;AACb,kBAAM,OAAO,UAAU,iBAAiB,MAAM;UACxD;QACA,OAAa;AACL,4BAAkB,OAAO,OAAO,MAAM,IAAI;AAC1C,cAAI,WAAW;AACb,kBAAM,OAAO,UAAU,iBAAiB,MAAM,MAAM;UAC9D;QACA;MACA,WAAeA,UAAS,mBAAmB;AACrC,YAAI,MAAM,QAAQ,KAAK;AACrB,sBAAY,OAAO,MAAM,MAAM,OAAO,OAAO,OAAO;QAC5D;MACA,WAAeA,UAAS,sBAAsB;AACxC,eAAO;MACb,OAAW;AACL,YAAI,MAAM,YAAa,QAAO;AAC9B,cAAM,IAAIR,eAAc,4CAA4CQ,KAAI;MAC9E;AAEI,UAAI,MAAM,QAAQ,QAAQ,MAAM,QAAQ,KAAK;AAc3C,YAAI,SAAS;UACX,MAAM,IAAI,CAAC,MAAM,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,MAAM;QAC1D,EAAQ,QAAQ,MAAM,KAAK;AAErB,YAAI,MAAM,IAAI,CAAC,MAAM,KAAK;AACxB,mBAAS,MAAM;QACvB,WAAiB,OAAO,MAAM,GAAG,EAAE,MAAM,sBAAsB;AACvD,mBAAS,OAAO,OAAO,MAAM,EAAE;QACvC,OAAa;AACL,mBAAS,OAAO,SAAS;QACjC;AAEM,cAAM,OAAO,SAAS,MAAM,MAAM;MACxC;IACA;AAEE,WAAO;EACT;AAEA,WAAS,uBAAwB,QAAQ,OAAO;AAC9C,UAAM,UAAU,CAAA;AAChB,UAAM,oBAAoB,CAAA;AAE1B,gBAAY,QAAQ,SAAS,iBAAiB;AAE9C,UAAM,SAAS,kBAAkB;AACjC,aAAS,QAAQ,GAAG,QAAQ,QAAQ,SAAS,GAAG;AAC9C,YAAM,WAAW,KAAK,QAAQ,kBAAkB,KAAK,CAAC,CAAC;IAC3D;AACE,UAAM,iBAAiB,IAAI,MAAM,MAAM;EACzC;AAEA,WAAS,YAAa,QAAQ,SAAS,mBAAmB;AACxD,QAAI,WAAW,QAAQ,OAAO,WAAW,UAAU;AACjD,YAAM,QAAQ,QAAQ,QAAQ,MAAM;AACpC,UAAI,UAAU,IAAI;AAChB,YAAI,kBAAkB,QAAQ,KAAK,MAAM,IAAI;AAC3C,4BAAkB,KAAK,KAAK;QACpC;MACA,OAAW;AACL,gBAAQ,KAAK,MAAM;AAEnB,YAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,mBAAS,IAAI,GAAG,SAAS,OAAO,QAAQ,IAAI,QAAQ,KAAK,GAAG;AAC1D,wBAAY,OAAO,CAAC,GAAG,SAAS,iBAAiB;UAC3D;QACA,OAAa;AACL,gBAAM,gBAAgB,OAAO,KAAK,MAAM;AAExC,mBAAS,IAAI,GAAG,SAAS,cAAc,QAAQ,IAAI,QAAQ,KAAK,GAAG;AACjE,wBAAY,OAAO,cAAc,CAAC,CAAC,GAAG,SAAS,iBAAiB;UAC1E;QACA;MACA;IACA;EACA;AAEA,WAASY,MAAM,OAAO,SAAS;AAC7B,cAAU,WAAW,CAAA;AAErB,UAAM,QAAQ,IAAI,MAAM,OAAO;AAE/B,QAAI,CAAC,MAAM,OAAQ,wBAAuB,OAAO,KAAK;AAEtD,QAAI,QAAQ;AAEZ,QAAI,MAAM,UAAU;AAClB,cAAQ,MAAM,SAAS,KAAK,EAAE,IAAI,MAAK,GAAI,IAAI,KAAK;IACxD;AAEE,QAAI,UAAU,OAAO,GAAG,OAAO,MAAM,IAAI,EAAG,QAAO,MAAM,OAAO;AAEhE,WAAO;EACT;AAEA,SAAA,OAAsBA;;;;;;;ACt6BtB,QAAMC,UAASnB,cAAA;AACf,QAAMoB,UAAShB,cAAA;AAEf,WAAS,QAAS,MAAM,IAAI;AAC1B,WAAO,WAAY;AACjB,YAAM,IAAI,MAAM,mBAAmB,OAAO,wCAC1B,KAAK,yCAAyC;IAClE;EACA;AAEA,SAAA,OAAsBI,YAAA;AACtB,SAAA,SAAwBC,cAAA;AACxB,SAAA,kBAAiCC,gBAAA;AACjC,SAAA,cAA6BC,YAAA;AAC7B,SAAA,cAA6BC,YAAA;AAC7B,SAAA,iBAAgCS,gBAAA;AAChC,SAAA,OAAsBF,QAAO;AAC7B,SAAA,UAAyBA,QAAO;AAChC,SAAA,OAAsBC,QAAO;AAC7B,SAAA,gBAA+BE,iBAAA;AAG/B,SAAA,QAAuB;IACrB,QAAQC,cAAA;IACR,OAAOC,aAAA;IACP,KAAKC,WAAA;IACL,MAAMC,aAAA;IACN,OAAOC,aAAA;IACP,KAAKC,WAAA;IACL,WAAWC,iBAAA;IACX,MAAMC,YAAA;IACN,KAAKC,WAAA;IACL,OAAOC,aAAA;IACP,MAAMC,YAAA;IACN,KAAKC,WAAA;IACL,KAAKC,WAAA;EACP;AAGA,SAAA,WAA0B,QAAQ,YAAY,MAAM;AACpD,SAAA,cAA6B,QAAQ,eAAe,SAAS;AAC7D,SAAA,WAA0B,QAAQ,YAAY,MAAM;;;;;ACzC/C,IAAC;EACJ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AACF,IAAI;;;ACTJ,SAAS,oBAAoB;;;ACctB,SAAS,eAAe,QAAmC;AAChE,QAAM,SAA4B,CAAC;AAEnC,MAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,WAAO,EAAE,OAAO,OAAO,QAAQ,CAAC,EAAE,MAAM,IAAI,SAAS,2BAA2B,CAAC,EAAE;AAAA,EACrF;AAEA,QAAM,IAAI;AAGV,MAAI,OAAO,EAAE,YAAY,UAAU;AACjC,WAAO,KAAK,EAAE,MAAM,WAAW,SAAS,2CAA2C,CAAC;AAAA,EACtF;AACA,MAAI,OAAO,EAAE,SAAS,UAAU;AAC9B,WAAO,KAAK,EAAE,MAAM,QAAQ,SAAS,wCAAwC,CAAC;AAAA,EAChF;AAGA,MAAI,CAAC,MAAM,QAAQ,EAAE,QAAQ,GAAG;AAC9B,WAAO,KAAK,EAAE,MAAM,YAAY,SAAS,4CAA4C,CAAC;AAAA,EACxF,OAAO;AACL,MAAE,SAAS,QAAQ,CAAC,SAAkB,MAAc;AAClD,aAAO,KAAK,GAAG,gBAAgB,SAAS,YAAY,CAAC,GAAG,CAAC;AAAA,IAC3D,CAAC;AAAA,EACH;AAGA,MAAI,EAAE,UAAU,QAAW;AACzB,WAAO,KAAK,GAAG,cAAc,EAAE,OAAO,OAAO,CAAC;AAAA,EAChD;AAGA,MAAI,EAAE,WAAW,QAAW;AAC1B,WAAO,KAAK,GAAG,eAAe,EAAE,QAAQ,QAAQ,CAAC;AAAA,EACnD;AAGA,MAAI,EAAE,mBAAmB,QAAW;AAClC,WAAO,KAAK,GAAG,uBAAuB,EAAE,gBAAgB,gBAAgB,CAAC;AAAA,EAC3E;AAEA,SAAO,EAAE,OAAO,OAAO,WAAW,GAAG,OAAO;AAC9C;AAEA,SAAS,gBAAgB,SAAkB,MAAiC;AAC1E,QAAM,SAA4B,CAAC;AAEnC,MAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,WAAO,CAAC,EAAE,MAAM,SAAS,4BAA4B,CAAC;AAAA,EACxD;AAEA,QAAM,IAAI;AAEV,MAAI,OAAO,EAAE,OAAO,YAAY,CAAC,EAAE,IAAI;AACrC,WAAO,KAAK,EAAE,MAAM,GAAG,IAAI,OAAO,SAAS,gDAAgD,CAAC;AAAA,EAC9F;AAEA,MAAI,OAAO,EAAE,YAAY,WAAW;AAClC,WAAO,KAAK,EAAE,MAAM,GAAG,IAAI,YAAY,SAAS,4CAA4C,CAAC;AAAA,EAC/F;AAEA,MAAI,EAAE,YAAY,UAAa,CAAC,cAAc,EAAE,OAAO,GAAG;AACxD,WAAO,KAAK,EAAE,MAAM,GAAG,IAAI,YAAY,SAAS,sCAAsC,CAAC;AAAA,EACzF;AAEA,MAAI,EAAE,oBAAoB,UAAa,CAAC,cAAc,EAAE,eAAe,GAAG;AACxE,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,MAAI,EAAE,qBAAqB,UAAa,OAAO,EAAE,qBAAqB,WAAW;AAC/E,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,cAAc,OAAgB,MAAiC;AACtE,QAAM,SAA4B,CAAC;AAEnC,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO,CAAC,EAAE,MAAM,SAAS,0BAA0B,CAAC;AAAA,EACtD;AAEA,QAAM,IAAI;AAEV,aAAW,SAAS,CAAC,kBAAkB,kBAAkB,kBAAkB,GAAG;AAC5E,QAAI,EAAE,KAAK,MAAM,UAAa,CAAC,cAAc,EAAE,KAAK,CAAC,GAAG;AACtD,aAAO,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,KAAK,IAAI,SAAS,GAAG,KAAK,+BAA+B,CAAC;AAAA,IAC3F;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,QAAiB,MAAiC;AACxE,QAAM,SAA4B,CAAC;AAEnC,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,WAAO,CAAC,EAAE,MAAM,SAAS,2BAA2B,CAAC;AAAA,EACvD;AAEA,QAAM,IAAI;AAEV,MAAI,EAAE,wBAAwB,UAAa,OAAO,EAAE,wBAAwB,UAAU;AACpF,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,MAAI,EAAE,yBAAyB,UAAa,OAAO,EAAE,yBAAyB,UAAU;AACtF,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAIA,MACE,OAAO,EAAE,wBAAwB,YACjC,OAAO,EAAE,yBAAyB,YAClC,EAAE,sBAAsB,EAAE,sBAC1B;AACA,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SACE;AAAA,IACJ,CAAC;AAAA,EACH;AAEA,MAAI,EAAE,uBAAuB,UAAa,OAAO,EAAE,uBAAuB,UAAU;AAClF,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,MAAI,EAAE,aAAa,UAAa,OAAO,EAAE,aAAa,UAAU;AAC9D,WAAO,KAAK,EAAE,MAAM,GAAG,IAAI,aAAa,SAAS,4BAA4B,CAAC;AAAA,EAChF;AAEA,SAAO;AACT;AAEA,SAAS,uBAAuB,YAAqB,MAAiC;AACpF,QAAM,SAA4B,CAAC;AAEnC,MAAI,OAAO,eAAe,YAAY,eAAe,MAAM;AACzD,WAAO,CAAC,EAAE,MAAM,SAAS,mCAAmC,CAAC;AAAA,EAC/D;AAEA,QAAM,IAAI;AAEV,aAAW,SAAS,CAAC,aAAa,mBAAmB,WAAW,GAAY;AAC1E,QAAI,CAAC,EAAE,KAAK,KAAK,OAAO,EAAE,KAAK,MAAM,UAAU;AAC7C,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,IAAI,IAAI,KAAK;AAAA,QACtB,SAAS,GAAG,KAAK;AAAA,MACnB,CAAC;AACD;AAAA,IACF;AAEA,UAAM,IAAI,EAAE,KAAK;AACjB,QAAI,OAAO,EAAE,QAAQ,YAAY,OAAO,EAAE,QAAQ,UAAU;AAC1D,aAAO,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,KAAK,IAAI,SAAS,GAAG,KAAK,iCAAiC,CAAC;AAAA,IAC7F,WAAW,EAAE,MAAM,EAAE,KAAK;AACxB,aAAO,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,KAAK,IAAI,SAAS,GAAG,KAAK,mBAAmB,KAAK,OAAO,CAAC;AAAA,IAC3F;AAAA,EACF;AAGA,MAAI,sBAAsB,CAAC,GAAG;AAC5B,UAAM,eAAe;AACrB,QAAI,aAAa,UAAU,MAAM,MAAM,aAAa,gBAAgB,KAAK;AACvE,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,IAAI;AAAA,QACb,SAAS,8BAA8B,aAAa,UAAU,GAAG,8BAA8B,aAAa,gBAAgB,GAAG;AAAA,MACjI,CAAC;AAAA,IACH;AACA,QAAI,aAAa,gBAAgB,MAAM,MAAM,aAAa,UAAU,KAAK;AACvE,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,IAAI;AAAA,QACb,SAAS,oCAAoC,aAAa,gBAAgB,GAAG,wBAAwB,aAAa,UAAU,GAAG;AAAA,MACjI,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,cAAc,KAA+B;AACpD,SAAO,MAAM,QAAQ,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ;AACrE;AAEA,SAAS,sBAAsB,GAAqC;AAClE,aAAW,OAAO,CAAC,aAAa,mBAAmB,WAAW,GAAG;AAC/D,UAAM,IAAI,EAAE,GAAG;AACf,QAAI,CAAC,KAAK,OAAO,MAAM,SAAU,QAAO;AACxC,UAAM,QAAQ;AACd,QAAI,OAAO,MAAM,QAAQ,YAAY,OAAO,MAAM,QAAQ,SAAU,QAAO;AAAA,EAC7E;AACA,SAAO;AACT;;;ADlNO,SAAS,UAAU,aAAkC;AAC1D,MAAI;AAEJ,MAAI;AACF,aAAc,KAAK,WAAW;AAAA,EAChC,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,YAAY,EAAE,OAAO,OAAO,QAAQ,CAAC,EAAE,MAAM,IAAI,SAAS,qBAAqB,OAAO,GAAG,CAAC,EAAE;AAAA,MAC5F,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,aAAa,eAAe,MAAM;AAExC,MAAI,CAAC,WAAW,OAAO;AACrB,WAAO,EAAE,QAAQ,MAAM,YAAY,SAAS,YAAY;AAAA,EAC1D;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAKO,SAAS,UAAU,UAA+B;AACvD,MAAI;AAEJ,MAAI;AACF,cAAU,aAAa,UAAU,OAAO;AAAA,EAC1C,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,YAAY,EAAE,OAAO,OAAO,QAAQ,CAAC,EAAE,MAAM,IAAI,SAAS,+BAA+B,OAAO,GAAG,CAAC,EAAE;AAAA,IACxG;AAAA,EACF;AAEA,SAAO,UAAU,OAAO;AAC1B;;;AErDO,SAAS,cAAc,QAAgD;AAC5E,MAAI,OAAO,QAAQ;AACjB,WAAO,IAAI,eAAe,OAAO,MAAM;AAAA,EACzC;AAEA,MAAI,OAAO,YAAY;AACrB,UAAM,SAAS,UAAU,OAAO,UAAU;AAC1C,QAAI,CAAC,OAAO,QAAQ;AAClB,YAAM,SAAS,OAAO,WAAW,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AACvF,YAAM,IAAI,MAAM,uBAAuB,OAAO,UAAU,KAAK,MAAM,EAAE;AAAA,IACvE;AACA,WAAO,IAAI,eAAe,OAAO,MAAM;AAAA,EACzC;AAEA,QAAM,IAAI,MAAM,2DAA2D;AAC7E;AAKO,SAAS,YAAY,WAA2B,SAA6C;AAClG,SAAO,UAAU,SAAS,OAAO;AACnC;;;ACTO,SAAS,cAAc,OAA2B;AACvD,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,SAAO;AACT;;;ACZO,IAAM,cAAc;;;ACDpB,IAAM,iBAAiB,iBAAiB,WAAW;AAO1D,SAAS,cAAc,aAAmD;AACxE,MAAI,CAAC,YAAa,QAAO,EAAE,cAAc,eAAe;AACxD,MAAI,uBAAuB,SAAS;AAClC,UAAM,OAAO,IAAI,QAAQ,WAAW;AACpC,QAAI,CAAC,KAAK,IAAI,YAAY,EAAG,MAAK,IAAI,cAAc,cAAc;AAClE,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,WAAW,GAAG;AAC9B,UAAMC,OAAM,YAAY,KAAK,CAAC,CAAC,IAAI,MAAM,KAAK,YAAY,MAAM,YAAY;AAC5E,WAAOA,OAAM,cAAc,CAAC,GAAG,aAAa,CAAC,cAAc,cAAc,CAAC;AAAA,EAC5E;AACA,QAAM,MAAM,OAAO,KAAK,WAAW,EAAE,KAAK,CAAC,SAAS,KAAK,YAAY,MAAM,YAAY;AACvF,SAAO,MAAM,cAAc,EAAE,cAAc,gBAAgB,GAAG,YAAY;AAC5E;AAEO,IAAM,WAAyB,CAAC,OAAO,SAC5C,MAAM,OAAO,EAAE,GAAG,MAAM,SAAS,cAAc,MAAM,OAAO,EAAE,CAAC;;;AChBjE,IAAM,eAAe,KAAK,KAAK;AAE/B,IAAM,QAAQ,oBAAI,IAAwB;AAsFnC,SAAS,uBAAuB,YAA0D;AAC/F,SAAO,MAAM,IAAI,UAAU,GAAG;AAChC;;;AC1EA,IAAM,iBAAyC;AAAA,EAC7C,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMZ,OAAO;AACT;AAOA,IAAI,qBAAqB;AAQzB,IAAI,0BAA0B;AAE9B,eAAe,iBACb,YACA,OACA,YACA,QACe;AACf,uBAAqB;AACrB,MAAI;AACF,UAAM,WAAW,GAAG,UAAU;AAK9B,UAAM,WAAW,MAAM,SAAS,UAAU,EAAE,QAAQ,OAAO,CAAC;AAC5D,UAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,QAAI,YAAY,WAAW,WAAW,GAAG;AACvC,YAAM,UACJ,qCAAqC,UAAU,kCAAkC,WAAW;AAQ9F,UAAI,YAAY;AACd,cAAM,IAAI,MAAM,GAAG,OAAO,oBAAoB;AAAA,MAChD;AACA,cAAQ,KAAK,GAAG,OAAO,2DAA2D;AAAA,IACpF,WAAW,OAAO;AAChB,cAAQ;AAAA,QACN,+CAA+C,UAAU,mBAAmB,WAAW;AAAA,MACzF;AAAA,IACF;AAKA,QAAI,QAAQ;AACV,YAAM,YAAY,MAAM,SAAS,GAAG,UAAU,oCAAoC;AAAA,QAChF,SAAS,EAAE,eAAe,UAAU,MAAM,GAAG;AAAA,MAC/C,CAAC;AACD,UAAI,UAAU,WAAW,KAAK;AAC5B,cAAM,OAAQ,MAAM,UAAU,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAKrD,cAAM,UACJ,mFACI,KAAK,QAAQ,iBAAiB,KAAK,KAAK,WAAW,aAAa,yEAEnE,KAAK,aAAa,YAAY,OAAO,KAAK,YAAY,SAAS,KAAK,MACrE;AACF,YAAI,YAAY;AACd,gBAAM,IAAI,MAAM,GAAG,OAAO,oBAAoB;AAAA,QAChD;AACA,gBAAQ,MAAM,OAAO;AAAA,MACvB,WAAW,UAAU,IAAI;AACvB,cAAM,OAAQ,MAAM,UAAU,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGrD,YAAI,OAAO,KAAK,iBAAiB,YAAY,KAAK,gBAAgB,GAAG;AACnE,kBAAQ;AAAA,YACN,qEAAqE,KAAK,YAAY;AAAA,UAExF;AAAA,QACF,WAAW,OAAO;AAChB,kBAAQ,IAAI,iDAAiD;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,YAAY;AAGd,YAAM;AAAA,IACR;AACA,QAAI,OAAO;AACT,cAAQ,IAAI,2DAA2D,OAAO,GAAG,CAAC,EAAE;AAAA,IACtF;AAAA,EACF;AACF;AAKA,IAAM,oBAAoB,oBAAI,IAA+D;AAwB7F,SAAS,YAAY,SAA8B,gBAAiC;AAClF,QAAM,IAAI,QAAQ;AAClB,SAAO;AAAA,IACL,EAAE,WAAW;AAAA,IACb,EAAE,UAAU;AAAA,IACZ,EAAE,OAAO;AAAA,IACT,QAAQ,WAAW;AAAA,IACnB,QAAQ,UAAU;AAAA,IAClB,QAAQ,gBAAgB;AAAA,IACxB,QAAQ,YAAY;AAAA,IACpB,QAAQ,gBAAgB;AAAA,IACxB,QAAQ,oBAAoB;AAAA,IAC5B,QAAQ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQpB,kBAAkB;AAAA,IAClB,QAAQ,mBAAmB;AAAA,IAC3B,QAAQ,oBAAoB;AAAA,IAC5B,QAAQ,oBAAoB,MAAM;AAAA,IAClC,QAAQ,iBAAiB;AAAA,IACzB,QAAQ,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,IAKzB,QAAQ,oBAAoB;AAAA,IAC5B,QAAQ,sBAAsB;AAAA,IAC9B,QAAQ,yBAAyB,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMvC,QAAQ,gBAAgB,YAAY;AAAA,IACpC,QAAQ,gBAAgB,aAAa;AAAA,IACrC,QAAQ,gBAAgB,gBAAgB;AAAA,IACxC,QAAQ,gBAAgB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMxC,QAAQ,iBAAiB;AAAA,IACzB,QAAQ,qBAAqB;AAAA,EAC/B,EAAE,KAAK,GAAG;AACZ;AAKA,SAAS,gBACP,SACA,gBAC2B;AAC3B,QAAM,MAAM,YAAY,SAAS,cAAc;AAC/C,QAAM,SAAS,kBAAkB,IAAI,GAAG;AAExC,MAAI,UAAU,OAAO,YAAY,KAAK,IAAI,GAAG;AAC3C,WAAO,OAAO;AAAA,EAChB;AAEA,MAAI,QAAQ;AACV,sBAAkB,OAAO,GAAG;AAAA,EAC9B;AAEA,SAAO;AACT;AAYA,IAAM,4BAA4B;AAElC,SAAS,YACP,SACA,QACA,eACA,gBACM;AACN,QAAM,aAAa,iBAAiB,gBAAgB,IAAI,gBAAgB;AACxE,QAAM,MAAM,YAAY,SAAS,cAAc;AAC/C,oBAAkB,IAAI,KAAK;AAAA,IACzB;AAAA,IACA,WAAW,KAAK,IAAI,IAAI,aAAa;AAAA,EACvC,CAAC;AACH;AAgHA,SAAS,YAAY,MAAsD;AACzE,MAAI,CAAC,MAAM,YAAa,QAAO;AAC/B,SAAO;AAAA,IACL,UAAU,KAAK;AAAA,IACf,cAAc,KAAK;AAAA,IACnB,SACE;AAAA,EAIJ;AACF;AAUA,SAAS,uBACP,SACA,QACA,UAQI,CAAC,GACe;AACpB,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,aAAa,WAAW;AAC9B,QAAM,cAAc,WAAW;AAC/B,QAAM,OAAO,QAAQ;AAErB,QAAM,WAAyB,cAC3B;AAAA,IACE,SACE;AAAA,IAEF,iBAAiB,MAAM,mBAAmB;AAAA,IAC1C,kBAAkB,QAAQ,aAAa,WAAW,MAAM,oBAAoB;AAAA,IAC5E,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF,IACA,aACE;AAAA,IACE,SACE;AAAA,IACF,iBAAiB,MAAM,mBAAmB;AAAA,IAC1C,kBAAkB,MAAM,oBAAoB;AAAA,IAC5C,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF,IACA;AAAA,IACE,SACE;AAAA,IACF,iBAAiB,MAAM,mBAAmB;AAAA,IAC1C,kBAAkB,MAAM,oBAAoB;AAAA,IAC5C,OAAO;AAAA;AAAA;AAAA,MAGL,GAAI,MAAM,cACN;AAAA,QACE,yEAAyE,KAAK,WAAW;AAAA,MAC3F,IACA,CAAC;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,GAAI,YAAY,IAAI,KAAK,EAAE,KAAK,YAAY,IAAI,EAAE;AAAA,EACpD;AAEN,SAAO;AAAA;AAAA;AAAA;AAAA,IAIL,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf;AAAA,IACA,eAAe,SAAS,CAAC,MAAM,IAAI,CAAC,qCAAqC;AAAA;AAAA;AAAA;AAAA;AAAA,IAKzE,UAAU,cACN;AAAA,MACE;AAAA,QACE,WAAW;AAAA,QACX,SAAS,UAAU;AAAA,QACnB,UAAU,SAAS;AAAA,MACrB;AAAA,IACF,IACA,aACE;AAAA,MACE;AAAA,QACE,WAAW;AAAA,QACX,SAAS,UAAU;AAAA,QACnB,UAAU,SAAS;AAAA,MACrB;AAAA,IACF,IACA;AAAA;AAAA;AAAA,IAGN,GAAI,eAAe,EAAE,eAAe,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,IAKzC,GAAI,cAAc,EAAE,WAAW,KAAK;AAAA,IACpC,eAAe,QAAQ;AAAA,IACvB,WAAW,QAAQ;AAAA,IACnB,YAAY,oBAAI,KAAK;AAAA,EACvB;AACF;AAKA,eAAe,oBACb,QACA,SA+FC;AACD,QAAM,EAAE,aAAa,GAAG,YAAY,IAAI;AAIxC,QAAM,OAAgC;AAAA,IACpC,GAAI,YAAY,WAAW,EAAE,SAAS,YAAY,QAAQ;AAAA,IAC1D,GAAI,YAAY,WAAW,EAAE,SAAS,YAAY,QAAQ;AAAA,EAC5D;AAGA,MAAI,YAAY,OAAQ,MAAK,SAAS,YAAY;AAClD,MAAI,YAAY,aAAc,MAAK,eAAe,YAAY;AAC9D,MAAI,YAAY,SAAU,MAAK,WAAW,YAAY;AACtD,MAAI,YAAY,aAAc,MAAK,eAAe,YAAY;AAC9D,MAAI,YAAY,iBAAkB,MAAK,mBAAmB,YAAY;AACtE,MAAI,YAAY,SAAU,MAAK,WAAW,YAAY;AACtD,MAAI,YAAY,kBAAmB,MAAK,oBAAoB,YAAY;AACxE,MAAI,YAAY,cAAe,MAAK,gBAAgB,YAAY;AAChE,MAAI,YAAY,kBAAkB,OAAW,MAAK,gBAAgB,YAAY;AAE9E,MAAI,YAAY;AACd,SAAK,yBAAyB,YAAY;AAC5C,MAAI,YAAY,cAAe,MAAK,gBAAgB,YAAY;AAChE,MAAI,YAAY,iBAAkB,MAAK,mBAAmB,YAAY;AACtE,MAAI,YAAY,iBAAkB,MAAK,mBAAmB,YAAY;AACtE,MAAI,YAAY,gBAAiB,MAAK,kBAAkB,YAAY;AACpE,MAAI,OAAO,eAAgB,MAAK,iBAAiB,OAAO;AACxD,MAAI,YAAY;AACd,SAAK,0BAA0B,YAAY;AAG7C,MAAI,YAAY,mBAAoB,MAAK,qBAAqB,YAAY;AAG1E,MAAI,YAAY,cAAe,MAAK,gBAAgB,YAAY;AAGhE,MAAI,YAAY,kBAAmB,MAAK,oBAAoB,YAAY;AAExE,MAAI,YAAY,cAAe,MAAK,gBAAgB,YAAY;AAGhE,MAAI,YAAY,WAAY,MAAK,aAAa,YAAY;AAI1D,MAAI,YAAY,kBAAmB,MAAK,oBAAoB,YAAY;AAIxE,MAAI,YAAY,UAAW,MAAK,YAAY,YAAY;AACxD,MAAI,YAAY,iBAAkB,MAAK,mBAAmB,YAAY;AAStE,OAAK,aAAa;AAIlB,MAAI,YAAY,kBAAkB,YAAY,YAAY,YAAY,WAAW;AAC/E,UAAM,OAAO;AAAA,MACX,GAAI,YAAY,YAAY,EAAE,UAAU,YAAY,SAAS;AAAA,MAC7D,GAAI,YAAY,aAAa,EAAE,WAAW,YAAY,UAAU;AAAA,MAChE,GAAG,YAAY;AAAA,IACjB;AACA,QAAI,OAAO,KAAK,IAAI,EAAE,SAAS,EAAG,MAAK,iBAAiB;AAAA,EAC1D;AAGA,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,GAAG,OAAO;AAAA,EACZ;AAcA,MAAI,OAAO,QAAQ;AACjB,YAAQ,eAAe,IAAI,UAAU,OAAO,MAAM;AAElD,YAAQ,WAAW,IAAI,OAAO;AAAA,EAChC;AAEA,MAAI;AAMF,UAAM,WAAW,MAAM,SAAS,GAAG,OAAO,UAAU,yBAAyB;AAAA,MAC3E,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ,YAAY,QAAQ,OAAO,mBAAmB,GAAM;AAAA,IAC9D,CAAC;AAED,UAAM,OAAO,MAAM,SAAS,KAAK;AAMjC,QAAI,SAAS,WAAW,KAAK;AAC3B,aAAO;AAAA,QACL,SAAS;AAAA;AAAA;AAAA,QAGT,WAAW,OAAO,MAAM,cAAc,WAAW,KAAK,YAAY;AAAA,QAClE,QAAQ;AAAA,UACN,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,UAAU;AAAA,YACR;AAAA,cACE,WAAW;AAAA,cACX,SACE,OAAO,MAAM,YAAY,WAAW,KAAK,UAAU;AAAA,cACrD,UACE,OAAO,MAAM,aAAa,WACtB,KAAK,WACL;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAOA,QAAI,SAAS,WAAW,OAAO,MAAM,UAAU,oBAAoB;AACjE,YAAM,UACJ,OAAO,MAAM,YAAY,WACrB,KAAK,UACL;AACN,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,OAAO,MAAM,cAAc,WAAW,KAAK,YAAY;AAAA,QAClE,QAAQ;AAAA,UACN,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,UAAU;AAAA,YACR;AAAA,cACE,WAAW;AAAA,cACX;AAAA,cACA,UACE,OAAO,MAAM,aAAa,WACtB,KAAK,WACL;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,IAAI;AAOhB,UAAI,SAAS,WAAW,KAAK;AAC3B,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,KAAK,WAAW,KAAK,SAAS;AAAA,UACrC,WAAW;AAAA,UACX,eAAe,OAAO,MAAM,SAAS,WAAW,KAAK,OAAO;AAAA,UAC5D,aACE,MAAM,eAAe,OAAO,KAAK,gBAAgB,WAC5C,KAAK,cACN;AAAA,UACN,eAAe,OAAO,MAAM,kBAAkB,WAAW,KAAK,gBAAgB;AAAA,UAC9E,WAAW,OAAO,MAAM,cAAc,WAAW,KAAK,YAAY;AAAA,QACpE;AAAA,MACF;AAIA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,KAAK,WAAW,KAAK,SAAS,gBAAgB,SAAS,MAAM;AAAA,QACpE,eAAe,OAAO,MAAM,kBAAkB,WAAW,KAAK,gBAAgB;AAAA,QAC9E,WAAW,OAAO,MAAM,cAAc,WAAW,KAAK,YAAY;AAAA,MACpE;AAAA,IACF;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,qCAAqC,OAAO;AAAA,IACrD;AAAA,EACF;AACF;AAmBA,eAAsB,OACpB,QACA,SACA,SAC6B;AAC7B,QAAM,eAAe,EAAE,GAAG,gBAAgB,GAAG,OAAO;AAIpD,QAAM,OAAO,aAAa,aACtB,uBAAuB,aAAa,UAAU,IAC9C;AAOJ,MAAI,CAAC,sBAAsB,CAAC,aAAa,qBAAqB,aAAa,YAAY;AACrF,QAAI,aAAa,YAAY;AAC3B,YAAM;AAAA,QACJ,aAAa;AAAA,QACb,aAAa;AAAA,QACb;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF,OAAO;AACL,WAAK;AAAA,QACH,aAAa;AAAA,QACb,aAAa;AAAA,QACb;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MACE,CAAC,4BACA,OAAO,kBAAkB,UAAa,OAAO,yBAAyB,SACvE;AACA,8BAA0B;AAC1B,YAAQ;AAAA,MACN;AAAA,IAIF;AAAA,EACF;AAWA,MAAI,aAAa,aAAa,KAAK,CAAC,SAAS,aAAa;AACxD,UAAM,SAAS,gBAAgB,SAAS,aAAa,cAAc;AACnE,QAAI,QAAQ;AACV,UAAI,aAAa,OAAO;AACtB,gBAAQ,IAAI,+CAA+C;AAAA,MAC7D;AAOA,YAAM,MAA0B,EAAE,GAAG,OAAO;AAC5C,UAAI,QAAQ,WAAW;AACrB,YAAI,YAAY,QAAQ;AAAA,MAC1B,OAAO;AACL,eAAO,IAAI;AAAA,MACb;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,kBAAkB,EAAE,GAAG,QAAQ;AACrC,MAAI,CAAC,gBAAgB,mBAAmB,aAAa,iBAAiB;AACpE,oBAAgB,kBAAkB,aAAa;AAAA,EACjD;AACA,MAAI,CAAC,gBAAgB,oBAAoB,aAAa,kBAAkB;AACtE,oBAAgB,mBAAmB,aAAa;AAAA,EAClD;AAGA,MAAI,aAAa,OAAO;AACtB,YAAQ,IAAI,iDAAiD;AAAA,EAC/D;AAEA,QAAM,cAAc,MAAM,oBAAoB,cAAc,eAAe;AAK3E,QAAM,yBAA0B,YAAwC;AACxE,QAAM,sBACJ,MAAM,QAAQ,sBAAsB,KAAK,uBAAuB,SAAS,IACpE,yBACD;AAGN,MAAI,CAAC,YAAY,SAAS;AAQxB,WAAO,uBAAuB,cAAc,YAAY,OAAO;AAAA,MAC7D,QAAQ,YAAY,YAAY,uBAAuB;AAAA,MACvD,eAAgB,YAA2C;AAAA,MAC3D,WAAY,YAAuC;AAAA,MACnD,aAAa,YAAY;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH;AAGA,MAAI,CAAC,YAAY,QAAQ,SAAS;AAIhC,UAAM,qBAAsB,YAAY,QACpC;AAMJ,UAAM,wBACH,YAAY,qBAA8D,eAC3E;AACF,UAAMC,UAAqC;AAAA,MACzC,kBAAkB;AAAA,MAClB,eAAe;AAAA;AAAA;AAAA;AAAA,MAIf,eACE,wBACC,sBAAsB,mBAAmB,SAAS,IAC/C,mBAAmB,IAAI,CAAC,MAAM,EAAE,OAAO,IACvC,YAAY,QAAQ,SAClB,CAAC,YAAY,OAAO,MAAM,IAC1B,CAAC,eAAe;AAAA,MACxB,UAAU;AAAA,MACV,gBAAgB,YAAY,QAAQ;AAAA,MACpC,kBAAkB,YAAY,QAAQ;AAAA,MACtC,UAAU;AAAA,QACR,SAAS,YAAY,QAAQ,UAAU;AAAA,QACvC,iBAAiB,MAAM,mBAAmB;AAAA,QAC1C,kBAAkB,MAAM,oBAAoB;AAAA;AAAA;AAAA,QAG5C,GAAI,YAAY,IAAI,KAAK,EAAE,KAAK,YAAY,IAAI,EAAE;AAAA,MACpD;AAAA,MACA,YAAY,oBAAI,KAAK;AAAA;AAAA,MAErB,WAAY,YAAwC;AAAA;AAAA;AAAA,MAGpD,eAAgB,YAAwC;AAAA;AAAA;AAAA,MAGxD,WAAY,YAAwC;AAAA,MACpD,gBAAiB,YACd;AAAA,MACH,uBAAwB,YAAwC;AAAA,MAGhE,gBAAiB,YAAwC;AAAA,MAGzD,YAAa,YAAwC;AAAA,MAGrD,mBAAoB,YAAwC;AAAA;AAAA;AAAA,MAK5D,iBAAkB,YAAwC;AAAA;AAAA,MAI1D,YAAa,YAAwC;AAAA,IACvD;AAEA,WAAOA;AAAA,EACT;AAGA,QAAM,QAAmC,YAAY,QACjD;AAAA,IACE,SAAS,YAAY,MAAM;AAAA,IAC3B,MAAM,YAAY,MAAM;AAAA,IACxB,YAAY,YAAY,MAAM;AAAA,IAC9B,YAAY,cAAc,YAAY,MAAM,UAAU;AAAA,IACtD,oBAAoB,YAAY,MAAM,qBAAqB;AAAA,IAC3D,QAAQ,YAAY,MAAM;AAAA,EAC5B,IACA;AAEJ,QAAM,YAA2C,YAAY,YACzD;AAAA,IACE,UAAU,YAAY,UAAU;AAAA,IAChC,MAAM,YAAY,UAAU;AAAA,IAC5B,YAAY,YAAY,UAAU,cAAc;AAAA,IAChD,UAAU,YAAY,UAAU;AAAA,EAClC,IACA;AAEJ,QAAM,eAAiD,YAAY,eAC/D;AAAA,IACE,MAAM,YAAY,aAAa;AAAA,IAC/B,UAAU,YAAY,aAAa;AAAA,IACnC,YAAY,YAAY,aAAa;AAAA,EACvC,IACA;AAKJ,QAAM,sBAAsB,YAAY;AAExC,QAAM,SAAqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASzC,kBACG,YAAY,qBAA8D,eAC3E;AAAA,IACF,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,YAAY,QAAQ;AAAA,IACnC;AAAA,IACA,gBAAgB,YAAY,QAAQ;AAAA,IACpC,kBAAkB,YAAY,QAAQ;AAAA,IACtC,YAAY,oBAAI,KAAK;AAAA,IACrB,UAAU,aAAa;AAAA;AAAA,IAEvB,WAAY,YAAwC;AAAA;AAAA;AAAA,IAGpD,eAAgB,YAAwC;AAAA;AAAA,IAExD,WAAY,YAAwC;AAAA,IACpD,kBAAmB,YAAwC;AAAA,IAG3D,eAAgB,YAAwC;AAAA,IAGxD,gBAAiB,YACd;AAAA,IACH,uBAAwB,YAAwC;AAAA,IAGhE,eAAgB,YAAwC;AAAA,IAGxD,gBAAiB,YAAwC;AAAA,IAGzD,YAAa,YAAwC;AAAA,IAGrD,mBAAoB,YAAwC;AAAA,IAG5D,iBAAkB,YAAwC;AAAA;AAAA,IAI1D,YAAa,YAAwC;AAAA,EACvD;AAGA,MAAI,OAAO,mBAAmB,QAAQ;AAKpC,WAAO,gBAAgB;AAGvB,WAAO,gBAAgB,uBACrB,OAAO,yBAAyB,CAAC,2CAA2C;AAC9E,WAAO,WAAW,OAAO,mBACrB;AAAA,MACE,SAAS,wBAAwB,OAAO,iBAAiB,UAAU,0BAA0B;AAAA,MAC7F,iBAAiB,MAAM,mBAAmB;AAAA,MAC1C,kBAAkB,MAAM,oBAAoB;AAAA,IAC9C,IACA;AAAA,MACE,SAAS,OAAO,wBAAwB,CAAC,KAAK;AAAA,MAC9C,iBAAiB,MAAM,mBAAmB;AAAA,MAC1C,kBAAkB,MAAM,oBAAoB;AAAA,IAC9C;AAAA,EACN,WAAW,OAAO,mBAAmB,oBAAoB;AAGvD,WAAO,iBAAiB;AACxB,WAAO,gBAAgB,uBACrB,OAAO,yBAAyB,CAAC,+BAA+B;AAAA,EACpE;AAOA,QAAM,YACJ,OAAO,mBAAmB,QAC1B,OAAO,qBAAqB,QAC5B,OAAO,mBAAmB;AAC5B,MAAI,aAAa,aAAa,KAAK,OAAO,mBAAmB,UAAU,CAAC,WAAW;AACjF,gBAAY,SAAS,QAAQ,aAAa,UAAU,aAAa,cAAc;AAAA,EACjF;AAEA,SAAO;AACT;;;ACloCA,IAAM,uBAAuB,IAAI,KAAK;;;ACgM/B,IAAM,kBAAkB,KAAK;;;ACpF7B,IAAM,sBAAkC,OAAO,OAAO;AAAA,EAC3D,SAAS;AAAA,EACT,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW,CAAC;AAAA,EACZ,UAAU,OAAO,OAAO,EAAE,qBAAqB,EAAI,CAAC;AAAA,EACpD,gBAAgB;AAClB,CAAC;AAyFD,IAAM,iBAAiB,KAAK;AAC5B,IAAM,uBAAuB,KAAK,KAAK,KAAK;;;ACsC5C,IAAM,4BAA4B,IAAI,KAAK;;;ACkF3C,IAAMC,6BAA4B,IAAI,KAAK;;;ACzU3C,SAAS,uBAAuB;;;ACJhC,SAAS,eAAuD;;;AC+BzD,IAAM,qBAAN,MAA+C;AAAA,EAKpD,YAAY,WAAW,KAAQ;AAJ/B,SAAiB,UAAU,oBAAI,IAAoB;AAEnD,SAAQ,cAAc;AAGpB,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,KAAK,KAAa,aAA8B;AAC9C,UAAM,QAAQ,KAAK,IAAI;AAGvB,QAAI,QAAQ,KAAK,cAAc,KAAM;AACnC,iBAAW,CAAC,GAAG,GAAG,KAAK,KAAK,SAAS;AACnC,YAAI,OAAO,MAAO,MAAK,QAAQ,OAAO,CAAC;AAAA,MACzC;AACA,WAAK,cAAc;AAAA,IACrB;AAEA,UAAM,WAAW,KAAK,QAAQ,IAAI,GAAG;AACrC,QAAI,aAAa,UAAa,WAAW,OAAO;AAC9C,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,QAAQ,QAAQ,KAAK,UAAU;AACtC,YAAM,SAAS,KAAK,QAAQ,KAAK,EAAE,KAAK,EAAE;AAC1C,UAAI,WAAW,OAAW,MAAK,QAAQ,OAAO,MAAM;AAAA,IACtD;AACA,SAAK,QAAQ,IAAI,KAAK,WAAW;AACjC,WAAO;AAAA,EACT;AACF;AAUO,IAAM,oBAAoB,IAAI,mBAAmB;;;ACtExD,SAAS,YAAY,uBAAuB;AAC5C,SAAS,kBAAkB;;;ACL3B,SAAS,YAAY,uBAAuB;;;ACC5C,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,cAAAC,mBAAkB;;;ACW3B,SAAS,WAAW,YAAY,eAAe;;;AChB/C,SAAS,kBAAkB;;;ACG3B;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AACP,SAAS,wBAAwB;;;ACKjC,SAAS,cAAAC,aAAY,iBAAiB;;;ACnBtC,SAAS,0BAAoC;;;ACS7C,SAAS,gBAAgB,QAA+C;AACtE,SAAO;AAAA,IACL,YAAY,OAAO,cAAc;AAAA,IACjC,QAAQ,OAAO;AAAA,IACf,eAAe,OAAO;AAAA,IACtB,sBAAsB,OAAO;AAAA,IAC7B,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO;AAAA,IACd,eAAe,OAAO;AAAA,IACtB,iBAAiB,OAAO;AAAA,IACxB,kBAAkB,OAAO;AAAA,EAC3B;AACF;AAcO,SAAS,sBACd,SACA,SACqB;AACrB,QAAM,WAAW,QAAQ,QAAQ,QAAQ,GAAG;AAC5C,QAAM,SAAS,WAAW;AAC1B,SAAO;AAAA,IACL,aAAa,EAAE,QAAQ;AAAA,IACvB,SAAS,SAAS,QAAQ,QAAQ,MAAM,GAAG,QAAQ,IAAI,QAAQ;AAAA,IAC/D,QAAQ,SAAS,QAAQ,UAAU,QAAQ;AAAA,IAC3C,cAAc,QAAQ;AAAA,IACtB,UAAU,QAAQ;AAAA,IAClB,kBAAkB,QAAQ;AAAA,IAC1B,UAAU,QAAQ;AAAA,IAClB,eAAe;AAAA,EACjB;AACF;AAKA,SAAS,WAAW,QAAkD;AAEpE,MAAI,OAAO,oBAAoB,OAAO,eAAe;AACnD,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,QAAQ,OAAO,OAAO,aAClB,yBAAyB,OAAO,MAAM,UAAU,MAChD;AAAA,MACJ,YAAY,OAAO,OAAO;AAAA,MAC1B,WACE,eAAe,SACT,OAAmC,YACrC;AAAA,IACR;AAAA,EACF;AAEA,MAAI,OAAO,kBAAkB,OAAO,kBAAkB;AACpD,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,QAAQ,OAAO,gBAAgB,CAAC,KAAK;AAAA,MACrC,YAAY,OAAO,OAAO;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,gBAAgB;AAAA,IAChB,QAAQ,OAAO,gBAAgB,CAAC,KAAK;AAAA,IACrC,YAAY,OAAO,OAAO;AAAA,EAC5B;AACF;AAKA,eAAsB,aACpB,QACA,SACA,SAC+B;AAC/B,QAAM,gBAAgB,gBAAgB,MAAM;AAC5C,QAAM,UAAU,sBAAsB,SAAS,OAAO;AACtD,QAAM,SAAS,MAAM,OAAO,eAAe,OAAO;AAClD,SAAO,WAAW,MAAM;AAC1B;;;ACjGA,SAAS,YAAY,gBAAAC,eAAc,eAAe,iBAAiB;AACnE,SAAS,eAAe;;;ACYxB,IAAM,SAAS,CAACC,UAAiB,aAAaA,KAAI;AAElD,IAAM,qBAAyC;AAAA;AAAA,EAE7C;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,EACN;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,aAAa,KAAK,OAAO,iBAAiB,CAAC;AAAA,EAC7C;AAAA;AAAA,EAEA,EAAE,MAAM,gBAAgB,IAAI,qCAAqC;AAAA,EACjE,EAAE,MAAM,gBAAgB,IAAI,uCAAuC;AAAA,EACnE,EAAE,MAAM,iBAAiB,IAAI,+BAA+B;AAAA,EAC5D,EAAE,MAAM,cAAc,IAAI,6BAA6B;AAAA,EACvD,EAAE,MAAM,qBAAqB,IAAI,wBAAwB;AAAA,EACzD,EAAE,MAAM,OAAO,IAAI,qEAAqE;AAAA;AAAA,EAExF;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,aAAa,KAAK,OAAO,cAAc,CAAC;AAAA,EAC1C;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,aAAa,OAAO,OAAO,iBAAiB,CAAC;AAAA,EAC/C;AACF;AAMO,SAAS,cAAc,MAAsB;AAClD,MAAI,SAAS;AACb,aAAW,EAAE,MAAAA,OAAM,IAAI,YAAY,KAAK,oBAAoB;AAC1D,aAAS,OAAO,QAAQ,IAAI,eAAe,OAAOA,KAAI,CAAC;AAAA,EACzD;AACA,SAAO;AACT;AAOO,SAAS,WAAc,OAAa;AACzC,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,cAAc,KAAK;AAAA,EAC5B;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,SAAS,WAAW,IAAI,CAAC;AAAA,EAC7C;AACA,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,EAAE,iBAAiB,OAAO;AAC3E,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACrE,UAAI,CAAC,IAAI,WAAW,CAAC;AAAA,IACvB;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;ADpEA,IAAM,iBAAiB;AACvB,IAAM,cAAc;AAcpB,IAAM,gBAAgB,uBAAO,eAAe;AAE5C,SAAS,MAAM,IAA2C;AACxD,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,QAAQ,WAAW,MAAM,QAAQ,aAAa,GAAG,EAAE;AAEzD,QAAI,OAAO,MAAM,UAAU,WAAY,OAAM,MAAM;AAAA,EACrD,CAAC;AACH;AAEO,IAAM,kBAAN,MAAsB;AAAA,EAO3B,YAAY,QAAgC,aAAsB;AANlE,SAAQ,QAA0B,CAAC;AACnC,SAAQ,QAA+C;AAEvD,SAAQ,aAAa;AACrB,SAAQ,cAA6B;AAGnC,SAAK,SAAS;AACd,SAAK,cAAc,eAAe;AAClC,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAA0B;AAC9B,QAAI,KAAK,MAAO;AAChB,SAAK,QAAQ,YAAY,MAAM,KAAK,MAAM,GAAG,UAAU;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,eAA6B,CAAC,GAAkB;AACzD,QAAI,KAAK,OAAO;AACd,oBAAc,KAAK,KAAK;AACxB,WAAK,QAAQ;AAAA,IACf;AACA,UAAM,KAAK,MAAM,YAAY;AAC7B,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,SAAuB,UAAsC;AACnE,QAAI,KAAK,MAAM,UAAU,gBAAgB;AAEvC,WAAK,MAAM,MAAM;AAAA,IACnB;AAKA,SAAK,MAAM,KAAK;AAAA,MACd,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,MAC3D,SAAS,WAAW,OAAO;AAAA,MAC3B,UAAU,WAAW,QAAQ;AAAA,MAC7B,WAAW,oBAAI,KAAK;AAAA,MACpB,YAAY;AAAA,MACZ,QAAQ;AAAA,IACV,CAAC;AAED,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAM,UAAwB,CAAC,GAAkB;AACrD,QAAI,KAAK,WAAY;AACrB,SAAK,aAAa;AAElB,QAAI;AACF,YAAM,UAAU,KAAK,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AAC/D,YAAM,QAAQ,OAAO,QAAQ,UAAU,WAAW,QAAQ,MAAM,GAAG,QAAQ,KAAK,IAAI;AAEpF,iBAAW,SAAS,OAAO;AAGzB,cAAM,UAAU,aAAa,KAAK,QAAQ,MAAM,SAAS,KAAK,OAAO,OAAO,EACzE,KAAK,MAAM,QAAiB,EAC5B,MAAM,MAAM,OAAgB;AAC/B,cAAM,SAAS,QAAQ,oBACnB,MAAM,QAAQ,KAAK,CAAC,SAAS,MAAM,QAAQ,iBAAiB,CAAC,CAAC,IAC9D,MAAM;AAEV,YAAI,WAAW,eAAe;AAG5B;AAAA,QACF;AACA,YAAI,WAAW,UAAU;AACvB,gBAAM,SAAS;AAAA,QACjB,OAAO;AACL,gBAAM;AACN,cAAI,MAAM,cAAc,aAAa;AACnC,kBAAM,SAAS;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAGA,WAAK,QAAQ,KAAK,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AAC5D,WAAK,WAAW;AAAA,IAClB,UAAE;AACA,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAgD;AAC9C,WAAO;AAAA,MACL,SAAS,KAAK,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE;AAAA,MAC1D,OAAO,KAAK,MAAM;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,QAAI,CAAC,KAAK,YAAa;AAEvB,QAAI;AACF,UAAI,CAAC,WAAW,KAAK,WAAW,EAAG;AACnC,YAAM,OAAOC,cAAa,KAAK,aAAa,OAAO;AACnD,YAAM,UAAU,KAAK,MAAM,IAAI;AAE/B,WAAK,QAAQ,QACV,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EACpC,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,WAAW,IAAI,KAAK,EAAE,SAAS,EAAE,EAAE;AAAA,IAC5D,QAAQ;AAEN,WAAK,QAAQ,CAAC;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAmB;AACzB,QAAI,CAAC,KAAK,YAAa;AAEvB,QAAI;AACF,YAAM,MAAM,QAAQ,KAAK,WAAW;AACpC,UAAI,CAAC,WAAW,GAAG,EAAG,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACxD,oBAAc,KAAK,aAAa,KAAK,UAAU,KAAK,OAAO,MAAM,CAAC,GAAG,OAAO;AAAA,IAC9E,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAKO,SAAS,aACd,WACA,WACA,SACsB;AAEtB,QAAM,WAAW,UAAU,SAAS,OAAO;AAG3C,YAAU,QAAQ,SAAS,QAAQ;AAEnC,SAAO;AACT;;;AExMA,SAAS,gBAAgB,aAAAC,YAAW,cAAAC,aAAY,UAAU,aAAa,kBAAkB;AACzF,SAAS,YAAY;AAIrB,IAAM,gBAAgB,KAAK,OAAO;AAClC,IAAM,YAAY;AAEX,IAAM,cAAN,MAAkB;AAAA,EAIvB,YAAY,WAAmB,SAAkB;AAC/C,SAAK,YAAY;AACjB,SAAK,UAAU;AAEf,QAAI,SAAS;AACX,MAAAC,WAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,SAAuB,UAAsC;AACzE,QAAI,CAAC,KAAK,QAAS;AAMnB,QAAI;AACJ,QAAI;AACF,cAAQ;AAAA,QACN,IAAI,KAAK,WAAW;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,SAAS,WAAW,OAAO;AAAA,QAC3B,UAAU,WAAW,QAAQ;AAAA,MAC/B;AAAA,IACF,SAAS,KAAK;AACZ,cAAQ;AAAA,QACN,IAAI,KAAK,WAAW;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,UAAU;AAAA,UACR,OAAO,2BAA2B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UAClF,gBAAgB,SAAS;AAAA,UACzB,SAAS,QAAQ;AAAA,UACjB,QAAQ,QAAQ;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AACA,SAAK,MAAM,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,UAAkB,QAAsB;AACjD,QAAI,CAAC,KAAK,QAAS;AAEnB,SAAK,MAAM;AAAA,MACT,IAAI,KAAK,WAAW;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,MACpB,MAAM;AAAA,MACN,UAAU,EAAE,UAAU,OAAO;AAAA,IAC/B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,MAAc,IAAkB;AAC5C,QAAI,CAAC,KAAK,QAAS;AAEnB,SAAK,MAAM;AAAA,MACT,IAAI,KAAK,WAAW;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,MACpB,MAAM;AAAA,MACN,UAAU,EAAE,MAAM,GAAG;AAAA,IACvB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,OAAe,SAA8B;AACpD,QAAI,CAAC,KAAK,QAAS;AAEnB,SAAK,MAAM;AAAA,MACT,IAAI,KAAK,WAAW;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,MACpB,MAAM;AAAA,MACN;AAAA,MACA,UAAU,EAAE,MAAM;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEQ,MAAM,OAAyB;AACrC,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,UAAU,KAAK,IAAI;AAAA,IACjC,QAAQ;AAEN;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,KAAK,mBAAmB;AAGzC,UAAIC,YAAW,QAAQ,GAAG;AACxB,cAAM,QAAQ,SAAS,QAAQ;AAC/B,YAAI,MAAM,OAAO,eAAe;AAC9B,eAAK,OAAO;AAAA,QACd;AAAA,MACF;AASA,eAAS,UAAU,GAAG,UAAU,GAAG,WAAW;AAC5C,YAAI;AACF,yBAAe,UAAU,IAAI;AAC7B;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AACA,YAAM,eAAe,SAAS,QAAQ,YAAY,KAAK,QAAQ,GAAG,QAAQ;AAC1E,qBAAe,cAAc,IAAI;AAAA,IACnC,QAAQ;AAGN,UAAI;AACF,gBAAQ,MAAM,yDAAyD,KAAK,KAAK,CAAC,EAAE;AAAA,MACtF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,qBAA6B;AACnC,UAAM,QAAO,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAClD,WAAO,KAAK,KAAK,WAAW,SAAS,IAAI,QAAQ;AAAA,EACnD;AAAA,EAEQ,SAAe;AACrB,QAAI;AACF,YAAM,QAAQ,YAAY,KAAK,SAAS,EACrC,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ,KAAK,EAAE,SAAS,QAAQ,CAAC,EAC5D,KAAK;AAER,aAAO,MAAM,UAAU,WAAW;AAChC,cAAM,SAAS,MAAM,MAAM;AAC3B,mBAAW,KAAK,KAAK,WAAW,MAAM,CAAC;AAAA,MACzC;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,aAAqB;AAC3B,WAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,EAChE;AACF;;;ACvJO,IAAM,mBAAN,MAAuB;AAAA,EAO5B,YAAY,QAAgC;AAL5C,SAAQ,YAAmC;AAC3C,SAAQ,YAAoC;AAC5C,SAAQ,cAAkC;AAC1C,SAAQ,cAAc;AAGpB,SAAK,SAAS;AACd,SAAK,eAAe;AAAA,EACtB;AAAA,EAEQ,iBAAuB;AAC7B,UAAM,EAAE,KAAK,IAAI,KAAK;AAEtB,QAAI,SAAS,UAAU;AACrB,UAAI,CAAC,KAAK,OAAO,cAAc,CAAC,KAAK,OAAO,QAAQ;AAClD,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AAAA,IACF;AAEA,QAAI,SAAS,SAAS;AACpB,UAAI,CAAC,KAAK,OAAO,cAAc,CAAC,KAAK,OAAO,QAAQ;AAClD,cAAM,IAAI,MAAM,0CAA0C;AAAA,MAC5D;AAAA,IACF;AAEA,QAAI,SAAS,UAAU;AACrB,UAAI,CAAC,KAAK,OAAO,cAAc,CAAC,KAAK,OAAO,QAAQ;AAClD,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAA4B;AAChC,QAAI,KAAK,YAAa;AAEtB,UAAM,EAAE,KAAK,IAAI,KAAK;AAEtB,QAAI,SAAS,WAAW,SAAS,UAAU;AACzC,WAAK,YAAY,cAAc,KAAK,MAAM;AAAA,IAC5C;AAEA,QAAI,SAAS,UAAU;AACrB,YAAM,cAAc,KAAK,OAAO,YAC5B,GAAG,KAAK,OAAO,SAAS,wBACxB;AACJ,WAAK,YAAY,IAAI,gBAAgB,KAAK,QAAQ,WAAW;AAC7D,YAAM,cAAc,KAAK,OAAO,gBAAgB,QAAQ;AACxD,WAAK,UAAU,MAAM,UAAU;AAAA,IACjC;AAGA,QAAI,KAAK,OAAO,cAAc;AAC5B,YAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,WAAK,cAAc,IAAI,YAAY,WAAW,IAAI;AAAA,IACpD;AAEA,SAAK,cAAc;AAEnB,QAAI,KAAK,OAAO,OAAO;AACrB,YAAM,UAAU,KAAK,OAAO,WAAW;AACvC,cAAQ,IAAI,qCAAqC,IAAI,UAAU,OAAO,GAAG;AAAA,IAC3E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAAS,SAAuD;AACpE,QAAI,KAAK,WAAW;AAClB,YAAM,KAAK,UAAU,KAAK,SAAS,aAAa,CAAC,CAAC;AAClD,WAAK,YAAY;AAAA,IACnB;AAEA,SAAK,YAAY;AACjB,SAAK,cAAc;AAEnB,QAAI,KAAK,OAAO,OAAO;AACrB,cAAQ,IAAI,8BAA8B;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAAS,SAAuB,SAAiD;AACrF,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,KAAK,WAAW;AAAA,IACxB;AAEA,QAAI;AAEJ,YAAQ,KAAK,OAAO,MAAM;AAAA,MACxB,KAAK;AACH,mBAAW,MAAM,aAAa,KAAK,QAAQ,SAAS,WAAW,KAAK,OAAO,OAAO;AAClF;AAAA,MAEF,KAAK;AACH,YAAI,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,iCAAiC;AACtE,mBAAW,YAAY,KAAK,WAAW,OAAO;AAC9C;AAAA,MAEF,KAAK;AACH,YAAI,CAAC,KAAK,aAAa,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,6BAA6B;AACrF,mBAAW,aAAa,KAAK,WAAW,KAAK,WAAW,OAAO;AAC/D;AAAA,MAEF;AACE,cAAM,IAAI,MAAM,iBAAiB,KAAK,OAAO,IAAI,EAAE;AAAA,IACvD;AAGA,QAAI,KAAK,OAAO,YAAY,aAAa,SAAS,mBAAmB,SAAS;AAC5E,iBAAW;AAAA,QACT,GAAG;AAAA,QACH,gBAAgB;AAAA,QAChB,QAAQ,6BAA6B,SAAS,cAAc,KAAK,SAAS,MAAM;AAAA,MAClF;AAAA,IACF;AAGA,SAAK,aAAa,cAAc,SAAS,QAAQ;AAEjD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAuC;AACzC,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAgC;AAClC,WAAO,KAAK,OAAO,WAAW;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WACJ,SACA,kBACe;AACf,UAAM,UAAU,KAAK,OAAO;AAC5B,UAAM,KAAK,SAAS;AAEpB,SAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAG,kBAAkB,MAAM,QAAQ;AACnE,SAAK,eAAe;AACpB,UAAM,KAAK,WAAW;AAEtB,SAAK,aAAa,cAAc,SAAS,OAAO;AAEhD,QAAI,KAAK,OAAO,OAAO;AACrB,cAAQ,IAAI,kCAAkC,OAAO,OAAO;AAAA,IAC9D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAA2D;AACzD,WAAO,KAAK,WAAW,UAAU,KAAK;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe,UAAkB,QAAsB;AACrD,SAAK,aAAa,WAAW,UAAU,MAAM;AAAA,EAC/C;AACF;;;AChNA,SAAS,cAAAC,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,eAAe;AACxB,SAAS,QAAAC,aAAY;AAmCd,SAAS,mBACd,KACA,YACA,OAAe,QAAQ,GACK;AAC5B,QAAM,iBAAiB,CAAC,IAAI,oBAAoB,YAAY,IAAI,EAAE;AAAA,IAChE,CAAC,SAAyB,OAAO,SAAS,YAAY,KAAK,SAAS;AAAA,EACtE;AAEA,aAAW,QAAQ,gBAAgB;AACjC,UAAM,WAAWA,MAAK,MAAM,YAAY;AACxC,UAAM,aAAaA,MAAK,UAAU,aAAa;AAC/C,QAAI,CAACF,YAAW,UAAU,EAAG;AAE7B,QAAI,WAA0B,CAAC;AAC/B,UAAM,eAAeE,MAAK,UAAU,YAAY;AAChD,QAAIF,YAAW,YAAY,GAAG;AAC5B,UAAI;AACF,mBAAW,KAAK,MAAMC,cAAa,cAAc,OAAO,CAAC;AAAA,MAC3D,QAAQ;AAGN,mBAAW,CAAC;AAAA,MACd;AAAA,IACF;AAEA,WAAO,EAAE,YAAY,UAAU,SAAS;AAAA,EAC1C;AAEA,SAAO;AACT;;;A3DjDA,IAAM,kBAAkB,OAAO;AAC/B,IAAM,mBAAmB;AAGzB,IAAM,qBAAqB;AAC3B,IAAM,0BAA0B;AAchC,SAAS,WAAW,QAAiC;AACnD,SAAO;AAAA,IACL,oBAAoB;AAAA,MAClB,eAAe;AAAA,MACf,oBAAoB;AAAA,MACpB,0BAA0B;AAAA,IAC5B;AAAA,EACF;AACF;AAEA,eAAsB,wBACpB,aACA,UAAmC,CAAC,GACH;AACjC,QAAM,MAAM,QAAQ,OAAO,QAAQ;AAEnC,MAAI,IAAI,4BAA4B,KAAK;AACvC,WAAO,EAAE,QAAQ,MAAM,UAAU,EAAE;AAAA,EACrC;AAEA,QAAM,cAAc,IAAI,8BAA8B;AAEtD,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,MAAM,WAAW;AAAA,EAClC,QAAQ;AACN,QAAI,YAAa,QAAO,EAAE,QAAQ,MAAM,UAAU,EAAE;AACpD,WAAO;AAAA,MACL,QAAQ,WAAW,qDAAqD;AAAA,MACxE,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,WAAW,mBAAmB,KAAK,QAAQ,KAAK,QAAQ,IAAI;AAClE,MAAI,CAAC,UAAU;AAEb,WAAO,EAAE,QAAQ,MAAM,UAAU,EAAE;AAAA,EACrC;AAEA,QAAM,WAAW,eAAe,SAAS,SAAS,aAAa;AAE/D,MAAI;AACF,QAAI,OAA2B,SAAS,SAAS,SAAS,WAAW,WAAW;AAChF,QAAI,SAAS,YAAY,EAAE,SAAS,SAAS,cAAc,SAAS,SAAS,SAAS;AACpF,cAAQ;AAAA,QACN;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA,YAAY,SAAS;AAAA,MACrB,SAAS,SAAS,SAAS,WAAW;AAAA,MACtC,cAAc;AAAA,MACd,WAAWE,MAAK,SAAS,UAAU,QAAQ;AAAA,MAC3C,OAAO;AAAA,MACP,GAAI,SAAS,YAAY;AAAA,QACvB,YAAY,SAAS,SAAS;AAAA,QAC9B,QAAQ,SAAS,SAAS;AAAA,QAC1B,SAAS,SAAS,SAAS;AAAA,MAC7B;AAAA,IACF;AACA,UAAM,UAAU,QAAQ,iBACpB,QAAQ,eAAe,aAAa,IACpC,IAAI,iBAAiB,aAAa;AACtC,UAAM,QAAQ,WAAW;AAEzB,UAAM,UAAU,IAAI,aAAa;AAAA,MAC/B,GAAI,SAAS,SAAS,aAAa,EAAE,WAAW,SAAS,SAAS,UAAU;AAAA,MAC5E,GAAI,OAAO,SAAS,SAAS,cAAc,aAAa;AAAA,QACtD,WAAW,SAAS,SAAS;AAAA,MAC/B;AAAA,IACF,CAAC;AACD,UAAM,QAAQ,WAAW,EAAE,SAAS,gBAAgB,CAAC,EAAE,CAAC;AAExD,UAAM,SAAS,MAAM,QAAQ,gBAAgB,OAAO;AAEpD,UAAM,QAAQ,SAAS;AACvB,UAAM,QAAQ,SAAS;AAAA,MACrB,WAAW,EAAE,OAAO,oBAAoB,mBAAmB,wBAAwB;AAAA,IACrF,CAAC;AAED,WAAO,EAAE,QAAQ,UAAU,EAAE;AAAA,EAC/B,SAAS,KAAK;AACZ,QAAI,SAAU,QAAO,EAAE,QAAQ,MAAM,UAAU,EAAE;AACjD,UAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAG9D,WAAO;AAAA,MACL,QAAQ,WAAW,oDAAoD,MAAM,GAAG;AAAA,MAChF,UAAU;AAAA,IACZ;AAAA,EACF;AACF;AAMA,SAAS,YAA6B;AACpC,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,SAAmB,CAAC;AAC1B,QAAI,QAAQ;AACZ,QAAI,OAAO;AAEX,UAAM,SAAS,MAAM;AACnB,UAAI,KAAM;AACV,aAAO;AACP,mBAAa,KAAK;AAClB,cAAQ,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO,CAAC;AAAA,IACjD;AAEA,UAAM,QAAQ,WAAW,QAAQ,gBAAgB;AAEjD,YAAQ,MAAM,GAAG,QAAQ,CAAC,UAAkB;AAC1C,eAAS,MAAM;AACf,UAAI,QAAQ,iBAAiB;AAG3B,eAAO,SAAS;AAChB,eAAO,KAAK,OAAO,KAAK,mBAAmB,CAAC;AAC5C,eAAO;AACP;AAAA,MACF;AACA,aAAO,KAAK,KAAK;AAAA,IACnB,CAAC;AACD,YAAQ,MAAM,GAAG,OAAO,MAAM;AAC9B,YAAQ,MAAM,GAAG,SAAS,MAAM;AAAA,EAClC,CAAC;AACH;AAEA,eAAe,OAAsB;AAInC,UAAQ,MAAM,IAAI,SAAoB,QAAQ,MAAM,GAAG,IAAI;AAE3D,QAAM,cAAc,MAAM,UAAU;AACpC,QAAM,SAAS,MAAM,wBAAwB,WAAW;AAExD,MAAI,OAAO,QAAQ;AACjB,YAAQ,OAAO,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC;AAAA,EACpD;AACA,UAAQ,KAAK,OAAO,QAAQ;AAC9B;AAGA,IAAI,OAAO,cAAY,eAAe,UAAQ,SAAS,QAAQ;AAC7D,OAAK,EAAE,MAAM,CAAC,QAAQ;AAGpB,YAAQ,MAAM,uCAAuC,GAAG,EAAE;AAC1D,YAAQ,KAAK,QAAQ,IAAI,8BAA8B,MAAM,IAAI,CAAC;AAAA,EACpE,CAAC;AACH;;;A4D9LA,SAAS,cAAAC,aAAY,aAAAC,YAAW,gBAAAC,eAAc,iBAAAC,sBAAqB;AACnE,SAAS,WAAAC,gBAAe;AAMjB,IAAM,wBAAwB;AAM9B,IAAM,eACX;AAEF,IAAM,uBAAuB;AAqC7B,SAAS,aAAa,OAAyBC,SAAyB;AACtE,UAAQ,MAAM,SAAS,CAAC,GAAG;AAAA,IACzB,CAAC,MAAM,OAAO,EAAE,YAAY,YAAY,EAAE,QAAQ,SAASA,OAAM;AAAA,EACnE;AACF;AAEA,SAAS,aAAa,cAAsC;AAC1D,MAAI,CAACC,YAAW,YAAY,EAAG,QAAO,CAAC;AACvC,QAAM,UAAUC,cAAa,cAAc,OAAO,EAAE,KAAK;AACzD,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,SAAO,KAAK,MAAM,OAAO;AAC3B;AAEA,SAAS,cAAc,cAAsB,UAAgC;AAC3E,EAAAC,WAAUC,SAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AACpD,EAAAC,eAAc,cAAc,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,GAAM,OAAO;AAC/E;AAEO,SAAS,eACd,aACA,UAAkB,cAClB,kBAA2C,CAAC,GAC1B;AAClB,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,MACL,EAAE,MAAM,WAAW,SAAS,aAAa,SAAS,sBAAsB,GAAG,gBAAgB;AAAA,IAC7F;AAAA,EACF;AACF;AAaO,SAAS,mBACd,cACA,aACAL,UAAiB,uBACjB,UAAkB,cAClB,kBAA2C,CAAC,GAC7B;AACf,MAAI,CAAC,YAAY,SAASA,OAAM,GAAG;AACjC,UAAM,IAAI;AAAA,MACR,+BAA+BA,OAAM,UAAU,WAAW;AAAA,IAE5D;AAAA,EACF;AAEA,QAAM,WAAW,aAAa,YAAY;AAC1C,WAAS,QAAQ,SAAS,SAAS,CAAC;AACpC,QAAM,aAAc,SAAS,MAAM,aAAa,SAAS,MAAM,cAAc,CAAC;AAE9E,QAAM,WAAW,WAAW,KAAK,CAAC,UAAU,aAAa,OAAOA,OAAM,CAAC;AACvE,MAAI,UAAU;AACZ,UAAM,QAAQ,eAAe,aAAa,SAAS,eAAe;AAClE,UAAM,UAAU,KAAK,UAAU,QAAQ,MAAM,KAAK,UAAU,KAAK;AACjE,QAAI,SAAS;AACX,iBAAW,WAAW,QAAQ,QAAQ,CAAC,IAAI;AAC3C,oBAAc,cAAc,QAAQ;AAAA,IACtC;AACA,WAAO,EAAE,WAAW,OAAO,gBAAgB,MAAM,SAAS,QAAQ;AAAA,EACpE;AAEA,aAAW,KAAK,eAAe,aAAa,SAAS,eAAe,CAAC;AACrE,gBAAc,cAAc,QAAQ;AACpC,SAAO,EAAE,WAAW,MAAM,gBAAgB,OAAO,SAAS,MAAM;AAClE;AAOO,SAAS,qBACd,cACAA,UAAiB,uBACR;AACT,MAAI,CAACC,YAAW,YAAY,EAAG,QAAO;AAEtC,MAAI;AACJ,MAAI;AACF,eAAW,aAAa,YAAY;AAAA,EACtC,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,SAAS,OAAO;AACnC,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,YAAY,WAAW,OAAO,CAAC,UAAU,CAAC,aAAa,OAAOD,OAAM,CAAC;AAC3E,MAAI,UAAU,WAAW,WAAW,OAAQ,QAAO;AAEnD,MAAI,UAAU,SAAS,GAAG;AACxB,aAAS,MAAO,aAAa;AAAA,EAC/B,OAAO;AACL,WAAO,SAAS,MAAO;AACvB,QAAI,OAAO,KAAK,SAAS,KAAM,EAAE,WAAW,EAAG,QAAO,SAAS;AAAA,EACjE;AAEA,gBAAc,cAAc,QAAQ;AACpC,SAAO;AACT;AAmBA,IAAM,wBAAwB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAeO,IAAM,8BAAiD,sBAAsB;AAAA,EAClF,CAAC,MAAM,QAAQ,CAAC;AAClB;;;ACrMO,IAAM,8BAA8B;AAMpC,IAAM,qBAAqB;AAGlC,IAAM,uBAAuB;AAMtB,SAAS,kBAAkB,WAAmB,aAAoC;AACvF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACE,eAAe;AAAA,IACjB;AAAA,EACF;AACF;AAGO,SAAS,oBAAoB,WAA4B;AAC9D,SAAO,qBAAqB,WAAW,2BAA2B;AACpE;","names":["join","exception","YAMLException","common","require$$0","line","map","Type","require$$1","schema","type","Schema","require$$2","require$$3","require$$4","require$$5","require$$6","DEFAULT_SCHEMA","loadAll","load","str","string","dump","loader","dumper","require$$7","require$$8","require$$9","require$$10","require$$11","require$$12","require$$13","require$$14","require$$15","require$$16","require$$17","require$$18","require$$19","require$$20","require$$21","has","result","DEFAULT_ROUTES_REFRESH_MS","decodeSdJwtSync","createHash","createHash","readFileSync","type","readFileSync","mkdirSync","existsSync","mkdirSync","existsSync","existsSync","readFileSync","join","join","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","marker","existsSync","readFileSync","mkdirSync","dirname","writeFileSync"]}
|
|
1
|
+
{"version":3,"sources":["../../src/adapter-interface/interface.ts","../../src/adapter-interface/purpose-mapping.ts","../../src/claude-code/tool-mapping.ts","../../src/codex/tool-mapping.ts","../../src/codex/codex-adapter.ts","../../src/codex/hook.ts","../../src/gateway/types.ts","../../src/local-evaluator/command-matcher.ts","../../src/local-evaluator/evaluator.ts","../../../../node_modules/js-yaml/lib/common.js","../../../../node_modules/js-yaml/lib/exception.js","../../../../node_modules/js-yaml/lib/snippet.js","../../../../node_modules/js-yaml/lib/type.js","../../../../node_modules/js-yaml/lib/schema.js","../../../../node_modules/js-yaml/lib/type/str.js","../../../../node_modules/js-yaml/lib/type/seq.js","../../../../node_modules/js-yaml/lib/type/map.js","../../../../node_modules/js-yaml/lib/schema/failsafe.js","../../../../node_modules/js-yaml/lib/type/null.js","../../../../node_modules/js-yaml/lib/type/bool.js","../../../../node_modules/js-yaml/lib/type/int.js","../../../../node_modules/js-yaml/lib/type/float.js","../../../../node_modules/js-yaml/lib/schema/json.js","../../../../node_modules/js-yaml/lib/schema/core.js","../../../../node_modules/js-yaml/lib/type/timestamp.js","../../../../node_modules/js-yaml/lib/type/merge.js","../../../../node_modules/js-yaml/lib/type/binary.js","../../../../node_modules/js-yaml/lib/type/omap.js","../../../../node_modules/js-yaml/lib/type/pairs.js","../../../../node_modules/js-yaml/lib/type/set.js","../../../../node_modules/js-yaml/lib/schema/default.js","../../../../node_modules/js-yaml/lib/loader.js","../../../../node_modules/js-yaml/lib/dumper.js","../../../../node_modules/js-yaml/index.js","../../../../node_modules/js-yaml/lib/index_vite_proxy.tmp.mjs","../../src/local-evaluator/pdlss-parser.ts","../../src/local-evaluator/schema.ts","../../src/gateway/modes/local.ts","../../src/trust-levels.ts","../../src/version.ts","../../src/http.ts","../../src/well-known.ts","../../src/verify.ts","../../src/adapters/stepup-poll.ts","../../src/metadata-capture.ts","../../src/edge-config.ts","../../src/adapters/express.ts","../../src/adapters/nextjs.ts","../../src/transport/rfc9421.ts","../../src/transport/rfc9421-verify.ts","../../src/transport/nonce-store.ts","../../src/transport/vi.ts","../../src/transport/stripe-webhook.ts","../../src/transport/ap2.ts","../../src/transport/mpp.ts","../../src/transport/mpp-verify.ts","../../src/transport/x402.ts","../../src/transport/vi-verify.ts","../../src/transport/registry/visa.ts","../../src/gateway/modes/online.ts","../../src/gateway/modes/hybrid.ts","../../src/gateway/redact.ts","../../src/gateway/trace-logger.ts","../../src/gateway/gateway.ts","../../src/claude-code/guard-config.ts","../../src/fleet/enrolment-store.ts","../../src/fleet/hook-runner.ts","../../src/fleet/client.ts","../../src/fleet/policy-verify.ts","../../src/fleet/types.ts","../../src/fleet/runtime.ts","../../src/claude-code/settings-installer.ts","../../src/codex/settings-installer.ts"],"sourcesContent":["/**\n * PlatformAdapter Interface\n *\n * The contract that Layer 4 platform adapters implement.\n * Agent-side interception: governs what agents are allowed to do before they do it.\n *\n * Each adapter is 200-500 lines of platform-specific code.\n * All verification logic lives in the gateway — adapters just translate\n * between the platform's world and AstraSync's world.\n */\n\nimport type { AstraSyncGateway } from '../gateway/gateway';\nimport type { PDLSSContext, VerificationDecision, AgentAction, InterceptResult } from '../gateway/types';\n\nexport interface AdapterConfig {\n /** The AstraSyncGateway instance (handles mode routing) */\n gateway: AstraSyncGateway;\n /** Platform-specific configuration */\n adapterOptions: Record<string, unknown>;\n}\n\nexport interface PlatformAdapter {\n /**\n * Interface version for compatibility checking.\n * Current version: 1.\n */\n readonly interfaceVersion: number;\n\n /**\n * Platform-specific initialization.\n * Load config, register hooks, establish connections.\n */\n initialize(config: AdapterConfig): Promise<void>;\n\n /**\n * Graceful shutdown.\n * Drain in-flight verifications, deregister hooks, close connections.\n */\n shutdown(): Promise<void>;\n\n /**\n * Intercept an agent action before execution.\n *\n * How this works depends on the platform:\n * - CLI adapter: proxy server captures outbound request\n * - Browser adapter: content script intercepts DOM interaction\n * - Express: middleware captures inbound request\n */\n interceptAction(action: AgentAction): Promise<InterceptResult>;\n\n /**\n * Extract PDLSS-compatible context from a platform-specific action.\n * Maps platform-native action format to the universal PDLSSContext.\n */\n extractContext(action: AgentAction): PDLSSContext;\n\n /**\n * Enforce the verification decision in a platform-specific way.\n *\n * How this works depends on the platform:\n * - CLI: block command / allow command / prompt for approval\n * - Browser: block navigation / show confirmation dialog\n * - Express: return 403 / pass through / inject headers\n */\n enforceDecision(decision: VerificationDecision): Promise<void>;\n}\n\n/**\n * Current adapter interface version.\n */\nexport const ADAPTER_INTERFACE_VERSION = 1;\n\n/**\n * Check if an adapter is compatible with the current interface version.\n */\nexport function isCompatibleAdapter(adapter: PlatformAdapter): boolean {\n return adapter.interfaceVersion === ADAPTER_INTERFACE_VERSION;\n}\n","/**\n * Shared purpose mapping utilities for Layer 4 platform adapters.\n *\n * Maps platform-native action names to PDLSS purpose categories.\n * Used by OpenClaw CLI, Cursor, browser, and future adapters.\n */\n\n// -----------------------------------------------------------------------\n// Tool → Purpose mapping\n// -----------------------------------------------------------------------\n\n/** Standard tool name → PDLSS purpose mapping used by all adapters */\nconst TOOL_PURPOSE_MAP: Record<string, string> = {\n // Shell\n shell_exec: 'shell.exec',\n run_command: 'shell.exec',\n execute: 'shell.exec',\n terminal_exec: 'shell.exec',\n run_terminal_command: 'shell.exec',\n\n // File read\n file_read: 'file.read',\n read_file: 'file.read',\n\n // File write\n file_write: 'file.write',\n write_file: 'file.write',\n create_file: 'file.write',\n edit_file: 'file.write',\n\n // File delete\n file_delete: 'file.delete',\n delete_file: 'file.delete',\n\n // Network\n http_request: 'network.request',\n fetch: 'network.request',\n web_request: 'network.request',\n\n // Email\n send_email: 'email.send',\n read_email: 'email.read',\n\n // Calendar\n create_event: 'calendar.create',\n\n // Database\n query_database: 'database.query',\n write_database: 'database.write',\n\n // Payment\n payment_execute: 'payment.execute',\n};\n\n/**\n * Map a tool/action name to a PDLSS purpose category.\n * Returns `tool.<name>` for unmapped tools (denied by default).\n */\nexport function mapToolToPurpose(toolName: string): string {\n return TOOL_PURPOSE_MAP[toolName] || `tool.${toolName}`;\n}\n\n/**\n * Register additional tool → purpose mappings (e.g. from a platform adapter).\n * Does not overwrite existing mappings.\n */\nexport function registerToolMappings(mappings: Record<string, string>): void {\n for (const [tool, purpose] of Object.entries(mappings)) {\n if (!(tool in TOOL_PURPOSE_MAP)) {\n TOOL_PURPOSE_MAP[tool] = purpose;\n }\n }\n}\n\n// -----------------------------------------------------------------------\n// Target extraction\n// -----------------------------------------------------------------------\n\n/**\n * Extract the meaningful target string from tool arguments.\n * Uses the purpose category to determine which argument field is relevant.\n */\nexport function extractTarget(toolName: string, args: Record<string, unknown>): string {\n const purpose = mapToolToPurpose(toolName);\n\n if (purpose.startsWith('shell.')) {\n return String(args.command || args.cmd || args.script || '');\n }\n\n if (purpose.startsWith('file.')) {\n return String(args.path || args.file || args.filename || args.file_path || '');\n }\n\n if (purpose.startsWith('network.')) {\n return String(args.url || args.endpoint || args.uri || '');\n }\n\n if (purpose.startsWith('email.')) {\n return String(args.to || args.recipient || args.address || '');\n }\n\n if (purpose.startsWith('database.')) {\n return String(args.query || args.table || '');\n }\n\n if (purpose.startsWith('payment.')) {\n return String(args.description || args.merchant || args.amount || '');\n }\n\n // Fallback: try common field names\n if (args.command) return String(args.command);\n if (args.path) return String(args.path);\n if (args.url) return String(args.url);\n\n // Default: use first non-empty string argument or tool name\n for (const val of Object.values(args)) {\n if (typeof val === 'string' && val.length > 0) return val;\n }\n return toolName;\n}\n\n// -----------------------------------------------------------------------\n// Network domain extraction\n// -----------------------------------------------------------------------\n\n/**\n * Extract network domains from a URL target.\n * Returns undefined if the target is not a URL.\n */\nexport function extractNetworkDomains(target: string): string[] | undefined {\n try {\n if (target.startsWith('http://') || target.startsWith('https://')) {\n const url = new URL(target);\n return [url.hostname];\n }\n } catch {\n // Not a URL\n }\n return undefined;\n}\n","/**\n * @astrasyncai/adapter-claude-code — tool → purpose mapping\n *\n * Maps Claude Code's built-in tool names (as delivered in PreToolUse hook\n * payloads) to PDLSS purpose categories, and parses MCP tool names\n * (mcp__{server}__{tool}) into app-connector style purposes.\n */\n\nimport { registerToolMappings } from '../adapter-interface/purpose-mapping';\n\n/** Claude Code built-in tool name → PDLSS purpose */\nexport const CLAUDE_CODE_TOOL_MAP: Record<string, string> = {\n Bash: 'shell.exec',\n // Native Windows ships shell execution as a distinct PowerShell tool\n // (hooks docs: \"Tool Names in PreToolUse\"). Found live on 10 Jul 2026 —\n // the desktop-app runtime verification showed shell commands bypassing\n // the guard entirely on Windows because only Bash was mapped/matched.\n PowerShell: 'shell.exec',\n Write: 'file.write',\n Edit: 'file.write',\n MultiEdit: 'file.write',\n NotebookEdit: 'file.write',\n Read: 'file.read',\n Glob: 'file.read',\n Grep: 'file.read',\n WebFetch: 'network.request',\n WebSearch: 'network.request',\n Task: 'sub_agent.spawn',\n Agent: 'sub_agent.spawn',\n};\n\nlet registered = false;\n\n/**\n * Register the Claude Code mappings into the shared adapter purpose map.\n * Idempotent; safe to call from both the adapter and the hook entry.\n */\nexport function registerClaudeCodeMappings(): void {\n if (registered) return;\n registerToolMappings(CLAUDE_CODE_TOOL_MAP);\n registered = true;\n}\n\n/**\n * Parse an MCP tool name (mcp__{server}__{tool}) into an app-connector\n * style purpose `{server}.{tool}`. Returns null for non-MCP tool names.\n */\nexport function mapMcpTool(toolName: string): string | null {\n const match = /^mcp__(.+?)__(.+)$/.exec(toolName);\n if (!match) return null;\n return `${match[1]}.${match[2]}`;\n}\n","/**\n * @astrasyncai/adapter-codex — tool → purpose mapping\n *\n * Maps OpenAI Codex CLI's built-in tool names (as delivered in PreToolUse\n * hook payloads) to PDLSS purpose categories. MCP tool names use the same\n * mcp__{server}__{tool} convention as Claude Code, so the parser is shared.\n */\n\nimport { registerToolMappings } from '../adapter-interface/purpose-mapping';\nexport { mapMcpTool } from '../claude-code/tool-mapping';\n\n/**\n * Codex CLI built-in tool name → PDLSS purpose.\n * Documented canonical names: `Bash`, `apply_patch` (aliases `Edit`/`Write`\n * appear in matcher examples), `web_search`. Undocumented tools stay\n * unmapped and are skipped unless strictUnmapped is on.\n */\nexport const CODEX_TOOL_MAP: Record<string, string> = {\n Bash: 'shell.exec',\n apply_patch: 'file.write',\n Edit: 'file.write',\n Write: 'file.write',\n web_search: 'network.request',\n};\n\nlet registered = false;\n\n/**\n * Register the Codex mappings into the shared adapter purpose map.\n * Idempotent; safe to call from both the adapter and the hook entry.\n */\nexport function registerCodexMappings(): void {\n if (registered) return;\n registerToolMappings(CODEX_TOOL_MAP);\n registered = true;\n}\n\n/**\n * Extract the file paths an apply_patch envelope touches. Codex's patch\n * format marks each file with `*** Add File:` / `*** Update File:` /\n * `*** Delete File:` headers. Returns [] when nothing parseable is found —\n * callers should then fall back to a raw-text target.\n */\nexport function extractApplyPatchPaths(patchText: string): string[] {\n const paths: string[] = [];\n const re = /^\\*\\*\\*\\s+(?:Add|Update|Delete)\\s+File:\\s+(.+)$/gim;\n let match: RegExpExecArray | null;\n while ((match = re.exec(patchText)) !== null) {\n const p = match[1].trim();\n if (p) paths.push(p);\n }\n return paths;\n}\n","/**\n * @astrasyncai/adapter-codex\n *\n * Layer 4 adapter for OpenAI Codex CLI. Intercepts tool calls via Codex's\n * native PreToolUse hooks (stable since Codex v0.124.0): the hook binary\n * receives {tool_name, tool_input, permission_mode, ...} on stdin and may\n * answer with a permissionDecision on stdout.\n *\n * Decision mapping is strictly tightening, with two Codex-specific twists\n * versus the Claude Code adapter:\n *\n * - Codex has NO \"ask\" decision. MANUAL_REVIEW therefore emits nothing —\n * \"no matching hook decides\" makes Codex fall through to its own native\n * approval prompt, which is the HITL. EXCEPT when the session runs in\n * `dontAsk` / `bypassPermissions` permission mode: no native prompt will\n * catch the fall-through there, so MANUAL_REVIEW escalates to deny.\n * - Codex FAILS OPEN on hook errors/timeouts (it \"reports the error and\n * continues the tool call\"). The hook binary therefore fails closed\n * internally — every internal failure becomes an explicit deny (unless\n * failOpen is configured). A hard kill/timeout still fails open on\n * Codex's side; that residual gap is documented, and the mitigation is\n * the hook's ~200ms cost against a 10s timeout.\n *\n * ALLOW never emits \"allow\" (and never `updatedInput`) — a hook allow would\n * suppress Codex's own approval prompt rather than defer to it.\n */\n\nimport type { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface';\nimport type {\n PDLSSContext,\n VerificationDecision,\n AgentAction,\n InterceptResult,\n} from '../gateway/types';\nimport type { AstraSyncGateway } from '../gateway/gateway';\nimport { ADAPTER_INTERFACE_VERSION } from '../adapter-interface/interface';\nimport {\n mapToolToPurpose,\n extractTarget,\n extractNetworkDomains,\n} from '../adapter-interface/purpose-mapping';\nimport {\n registerCodexMappings,\n mapMcpTool,\n CODEX_TOOL_MAP,\n extractApplyPatchPaths,\n} from './tool-mapping';\n\n// -----------------------------------------------------------------------\n// Codex hook payload / output shapes\n// (contract: https://developers.openai.com/codex/hooks)\n// -----------------------------------------------------------------------\n\n/** The PreToolUse payload Codex CLI writes to the hook's stdin. */\nexport interface CodexPreToolUsePayload {\n hook_event_name?: string;\n tool_name: string;\n tool_input: Record<string, unknown>;\n session_id?: string;\n turn_id?: string;\n tool_use_id?: string;\n cwd?: string;\n model?: string;\n transcript_path?: string | null;\n /** default | acceptEdits | plan | dontAsk | bypassPermissions */\n permission_mode?: string;\n}\n\n/**\n * The JSON the hook prints to stdout when it wants to tighten a decision.\n * Deny-only by design: Codex has no \"ask\", and the guard never emits\n * \"allow\". Any unsupported field would make Codex mark the hook run failed\n * and continue the call — keep this shape strictly to documented fields.\n */\nexport interface CodexHookOutput {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse';\n permissionDecision: 'deny';\n permissionDecisionReason: string;\n };\n}\n\n/** Permission modes with no native approval prompt to catch a fall-through. */\nexport const UNPROMPTED_PERMISSION_MODES = new Set(['dontAsk', 'bypassPermissions']);\n\n// -----------------------------------------------------------------------\n// Configuration\n// -----------------------------------------------------------------------\n\n/** Session bookkeeping tools that are never governed. */\nexport const DEFAULT_SKIP_TOOLS = ['update_plan'];\n\nexport interface CodexAdapterOptions {\n /** Tool names to never intercept (replaces DEFAULT_SKIP_TOOLS if given) */\n skipTools?: string[];\n /**\n * When true, unmapped non-MCP tools are still intercepted (purpose\n * `tool.<name>`, denied by default policy). When false (default),\n * unmapped tools are skipped — Codex's own approval flow remains their\n * only gate.\n */\n strictUnmapped?: boolean;\n /**\n * Govern MCP tools (mcp__{server}__{tool} → purpose {server}.{tool}).\n * Defaults to true; installers default it off until the policy lists\n * {server}.{tool} rules (the evaluator denies unknown purposes).\n */\n governMcp?: boolean;\n}\n\n// -----------------------------------------------------------------------\n// Adapter implementation\n// -----------------------------------------------------------------------\n\nexport class CodexAdapter implements PlatformAdapter {\n readonly interfaceVersion = ADAPTER_INTERFACE_VERSION;\n\n private gateway!: AstraSyncGateway;\n private skipTools: Set<string>;\n private strictUnmapped: boolean;\n private governMcp: boolean;\n private _isRunning = false;\n\n constructor(options?: CodexAdapterOptions) {\n this.skipTools = new Set(options?.skipTools ?? DEFAULT_SKIP_TOOLS);\n this.strictUnmapped = options?.strictUnmapped ?? false;\n this.governMcp = options?.governMcp ?? true;\n registerCodexMappings();\n }\n\n get isRunning(): boolean {\n return this._isRunning;\n }\n\n async initialize(config: AdapterConfig): Promise<void> {\n this.gateway = config.gateway as AstraSyncGateway;\n\n if (Array.isArray(config.adapterOptions.skipTools)) {\n this.skipTools = new Set(config.adapterOptions.skipTools as string[]);\n }\n if (typeof config.adapterOptions.strictUnmapped === 'boolean') {\n this.strictUnmapped = config.adapterOptions.strictUnmapped;\n }\n\n this._isRunning = true;\n }\n\n async shutdown(): Promise<void> {\n this._isRunning = false;\n }\n\n async interceptAction(action: AgentAction): Promise<InterceptResult> {\n const raw = action.raw as Partial<CodexPreToolUsePayload> | null;\n\n if (!raw || typeof raw.tool_name !== 'string' || raw.tool_name.length === 0) {\n return { intercepted: false, skipReason: 'No tool_name in payload' };\n }\n\n if (this.skipTools.has(raw.tool_name)) {\n return { intercepted: false, skipReason: `Tool ${raw.tool_name} is not governed` };\n }\n\n const isMcp = mapMcpTool(raw.tool_name) !== null;\n if (isMcp && !this.governMcp) {\n return { intercepted: false, skipReason: 'MCP tools not governed (governMcp off)' };\n }\n\n const isMapped = raw.tool_name in CODEX_TOOL_MAP || isMcp;\n if (!isMapped && !this.strictUnmapped) {\n return {\n intercepted: false,\n skipReason: `Unmapped tool ${raw.tool_name} (strictUnmapped off)`,\n };\n }\n\n const context = this.extractContext(action);\n return { intercepted: true, context };\n }\n\n extractContext(action: AgentAction): PDLSSContext {\n const raw = action.raw as CodexPreToolUsePayload;\n return this.buildContext(raw, extractTarget(raw.tool_name, raw.tool_input ?? {}));\n }\n\n private buildContext(raw: CodexPreToolUsePayload, target: string): PDLSSContext {\n const toolName = raw.tool_name;\n const mcpPurpose = mapMcpTool(toolName);\n const purpose = mcpPurpose ?? mapToolToPurpose(toolName);\n const networkAccess = extractNetworkDomains(target);\n\n return {\n purpose,\n action: toolName,\n target,\n ...(networkAccess && { networkAccess }),\n metadata: {\n ...(raw.session_id && { sessionId: raw.session_id }),\n ...(raw.cwd && { cwd: raw.cwd }),\n ...(raw.permission_mode && { permissionMode: raw.permission_mode }),\n ...(raw.model && { model: raw.model }),\n platform: 'codex',\n },\n };\n }\n\n /**\n * Translate a gateway decision into hook stdout JSON.\n *\n * Returns null on ALLOW (silent — Codex's own approval flow stays in\n * charge) and on MANUAL_REVIEW in prompted permission modes (the\n * fall-through IS Codex's native prompt). MANUAL_REVIEW in dontAsk /\n * bypassPermissions escalates to deny — no prompt exists to catch it.\n */\n decisionToHookOutput(\n decision: VerificationDecision,\n permissionMode?: string\n ): CodexHookOutput | null {\n switch (decision.recommendation) {\n case 'DENY':\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'deny',\n permissionDecisionReason: `AstraSync Local Guard: ${decision.reason}`,\n },\n };\n case 'MANUAL_REVIEW':\n if (permissionMode && UNPROMPTED_PERMISSION_MODES.has(permissionMode)) {\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'deny',\n permissionDecisionReason:\n `AstraSync Local Guard requires approval: ${decision.reason} — ` +\n `denied because permission mode '${permissionMode}' would skip the approval prompt. ` +\n 'Re-run in a prompted mode to approve interactively.',\n },\n };\n }\n // Silent fall-through: Codex's native approval prompt is the HITL.\n return null;\n case 'ALLOW':\n return null;\n }\n }\n\n /**\n * Convenience for the hook entry: full payload → hook output (or null).\n *\n * apply_patch envelopes are evaluated per touched file (one context per\n * `*** Add/Update/Delete File:` header) and tightened to the worst\n * decision, so file.write blockedPatterns (including guard\n * self-protection) apply to every path in the patch.\n */\n async evaluatePayload(payload: CodexPreToolUsePayload): Promise<CodexHookOutput | null> {\n const action: AgentAction = {\n raw: payload,\n platform: 'codex',\n timestamp: new Date(),\n };\n\n const interception = await this.interceptAction(action);\n if (!interception.intercepted || !interception.context) {\n // Visible skip — ungoverned tools must show up in traces (see the\n // Claude Code adapter's PowerShell gap, found 10 Jul 2026).\n this.gateway.logSkippedTool(payload.tool_name, interception.skipReason ?? 'not intercepted');\n return null;\n }\n\n const decision = await this.evaluateInterceptedPayload(payload, interception.context);\n return this.decisionToHookOutput(decision, payload.permission_mode);\n }\n\n private async evaluateInterceptedPayload(\n payload: CodexPreToolUsePayload,\n context: PDLSSContext\n ): Promise<VerificationDecision> {\n const patchText =\n payload.tool_name === 'apply_patch'\n ? String(\n (payload.tool_input as Record<string, unknown>)?.command ??\n (payload.tool_input as Record<string, unknown>)?.patch ??\n ''\n )\n : '';\n const patchPaths = patchText ? extractApplyPatchPaths(patchText) : [];\n\n if (patchPaths.length === 0) {\n return this.gateway.evaluate(context);\n }\n\n // Worst decision across all touched paths wins.\n let worst: VerificationDecision | null = null;\n const rank = { ALLOW: 0, MANUAL_REVIEW: 1, DENY: 2 } as const;\n for (const path of patchPaths) {\n const decision = await this.gateway.evaluate(this.buildContext(payload, path));\n if (!worst || rank[decision.recommendation] > rank[worst.recommendation]) {\n worst = decision;\n }\n if (worst.recommendation === 'DENY') break;\n }\n return worst!;\n }\n\n /**\n * Enforcement happens via the stdout JSON the hook prints; there is no\n * in-process side to enforce on.\n */\n async enforceDecision(_decision: VerificationDecision): Promise<void> {\n // Contract no-op: Codex enforces based on the hook's stdout.\n }\n}\n","/**\n * AstraSync Local Guard for OpenAI Codex CLI — PreToolUse hook entry.\n *\n * Codex invokes this binary for each governed tool call, writing the\n * PreToolUse payload to stdin. The hook evaluates the call against the\n * local PDLSS policy (shared with the Claude Code adapter: same\n * ~/.astrasync/policy.yaml + guard.json) and prints a permissionDecision\n * JSON to stdout only when it wants to tighten the outcome (deny). On\n * ALLOW — and on MANUAL_REVIEW in prompted permission modes — it prints\n * nothing, so Codex's own approval flow stays in charge.\n *\n * Fail posture: Codex itself FAILS OPEN on hook errors (\"reports the error\n * and continues the tool call\"), so unlike the Claude Code hook we cannot\n * lean on exit codes alone — every internal failure is converted into an\n * explicit deny decision (opt-outs: ASTRASYNC_GUARD_FAIL_OPEN=1 or\n * guard.json {\"failOpen\": true}). A missing policy file everywhere means\n * the guard simply isn't configured — silent no-op, never a block.\n */\n\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { AstraSyncGateway } from '../gateway/gateway';\nimport { resolveFleet, resolveGuardConfig } from '../claude-code/guard-config';\nimport { runFleetHook } from '../fleet/hook-runner';\nimport type { FleetPaths } from '../fleet/enrolment-store';\nimport { CodexAdapter } from './codex-adapter';\nimport type { CodexHookOutput, CodexPreToolUsePayload } from './codex-adapter';\n\nconst MAX_STDIN_BYTES = 1024 * 1024;\nconst STDIN_TIMEOUT_MS = 5000;\n\n/** Bounded sync-flush budget per hook invocation (mirrors the Claude Code hook). */\nconst HYBRID_FLUSH_LIMIT = 3;\nconst HYBRID_FLUSH_TIMEOUT_MS = 1500;\n\nexport interface ProcessCodexHookOptions {\n env?: NodeJS.ProcessEnv;\n home?: string;\n /** Injectable for tests */\n gatewayFactory?: (config: ConstructorParameters<typeof AstraSyncGateway>[0]) => AstraSyncGateway;\n /** Injectable for tests: fleet enrolment/cache locations. */\n fleetPaths?: FleetPaths;\n /** Injectable for tests: clock for the fleet heartbeat throttle. */\n now?: () => number;\n}\n\nexport interface ProcessCodexHookResult {\n output: CodexHookOutput | null;\n exitCode: number;\n}\n\nfunction denyOutput(reason: string): CodexHookOutput {\n return {\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'deny',\n permissionDecisionReason: reason,\n },\n };\n}\n\nexport async function processCodexHookPayload(\n payloadJson: string,\n options: ProcessCodexHookOptions = {}\n): Promise<ProcessCodexHookResult> {\n const env = options.env ?? process.env;\n\n // Fleet first (5.11.0): an enrolled machine enforces the org's signed\n // central policy and ignores every local bypass below. Unenrolled\n // machines take the unchanged 5.10.0 path.\n const fleet = resolveFleet(env, options.home ?? homedir(), options.fleetPaths);\n if (fleet) {\n return runFleetHook<CodexPreToolUsePayload, CodexHookOutput>({\n resolution: fleet,\n payloadJson,\n adapterKind: 'codex',\n createAdapter: (adapterOptions) => new CodexAdapter(adapterOptions),\n denyOutput,\n classify: (output) =>\n output?.hookSpecificOutput?.permissionDecision === 'deny'\n ? 'deny'\n : output?.hookSpecificOutput?.permissionDecision === 'ask'\n ? 'ask'\n : 'allow',\n gatewayFactory: options.gatewayFactory,\n now: options.now,\n });\n }\n\n if (env.ASTRASYNC_GUARD_DISABLE === '1') {\n return { output: null, exitCode: 0 };\n }\n\n const envFailOpen = env.ASTRASYNC_GUARD_FAIL_OPEN === '1';\n\n let payload: CodexPreToolUsePayload;\n try {\n payload = JSON.parse(payloadJson) as CodexPreToolUsePayload;\n } catch {\n if (envFailOpen) return { output: null, exitCode: 0 };\n return {\n output: denyOutput('AstraSync Local Guard: could not parse hook payload'),\n exitCode: 0,\n };\n }\n\n const resolved = resolveGuardConfig(env, payload.cwd, options.home);\n if (!resolved) {\n // Guard not configured — never block an unconfigured machine.\n return { output: null, exitCode: 0 };\n }\n\n const failOpen = envFailOpen || resolved.settings.failOpen === true;\n\n try {\n let mode: 'local' | 'hybrid' = resolved.settings.mode === 'hybrid' ? 'hybrid' : 'local';\n if (mode === 'hybrid' && !(resolved.settings.apiBaseUrl && resolved.settings.apiKey)) {\n console.error(\n 'AstraSync Local Guard: guard.json requests hybrid mode but apiBaseUrl/apiKey are missing — running local-only'\n );\n mode = 'local';\n }\n\n const gatewayConfig = {\n mode,\n policyFile: resolved.policyFile,\n posture: resolved.settings.posture ?? 'active',\n traceEnabled: true,\n tracePath: join(resolved.guardDir, 'traces'),\n debug: false,\n ...(mode === 'hybrid' && {\n apiBaseUrl: resolved.settings.apiBaseUrl,\n apiKey: resolved.settings.apiKey,\n agentId: resolved.settings.agentId,\n }),\n };\n const gateway = options.gatewayFactory\n ? options.gatewayFactory(gatewayConfig)\n : new AstraSyncGateway(gatewayConfig);\n await gateway.initialize();\n\n const adapter = new CodexAdapter({\n ...(resolved.settings.skipTools && { skipTools: resolved.settings.skipTools }),\n ...(typeof resolved.settings.governMcp === 'boolean' && {\n governMcp: resolved.settings.governMcp,\n }),\n });\n await adapter.initialize({ gateway, adapterOptions: {} });\n\n const output = await adapter.evaluatePayload(payload);\n\n await adapter.shutdown();\n await gateway.shutdown({\n syncFlush: { limit: HYBRID_FLUSH_LIMIT, perEntryTimeoutMs: HYBRID_FLUSH_TIMEOUT_MS },\n });\n\n return { output, exitCode: 0 };\n } catch (err) {\n if (failOpen) return { output: null, exitCode: 0 };\n const detail = err instanceof Error ? err.message : String(err);\n // Explicit deny JSON, not just an exit code — Codex continues the tool\n // call on hook \"failures\", so the deny must be a valid decision.\n return {\n output: denyOutput(`AstraSync Local Guard: policy evaluation failed (${detail})`),\n exitCode: 0,\n };\n }\n}\n\n// -----------------------------------------------------------------------\n// Process entry\n// -----------------------------------------------------------------------\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve) => {\n const chunks: Buffer[] = [];\n let total = 0;\n let done = false;\n\n const finish = () => {\n if (done) return;\n done = true;\n clearTimeout(timer);\n resolve(Buffer.concat(chunks).toString('utf-8'));\n };\n\n const timer = setTimeout(finish, STDIN_TIMEOUT_MS);\n\n process.stdin.on('data', (chunk: Buffer) => {\n total += chunk.length;\n if (total > MAX_STDIN_BYTES) {\n // Oversized payload: replace with a non-JSON sentinel so the\n // parse step fails and the guard's fail posture decides.\n chunks.length = 0;\n chunks.push(Buffer.from('OVERSIZED_PAYLOAD'));\n finish();\n return;\n }\n chunks.push(chunk);\n });\n process.stdin.on('end', finish);\n process.stdin.on('error', finish);\n });\n}\n\nasync function main(): Promise<void> {\n // stdout is reserved for the hook decision JSON — route everything a\n // library might log to stderr instead.\n // eslint-disable-next-line no-console\n console.log = (...args: unknown[]) => console.error(...args);\n\n const payloadJson = await readStdin();\n const result = await processCodexHookPayload(payloadJson);\n\n if (result.output) {\n process.stdout.write(JSON.stringify(result.output));\n }\n process.exit(result.exitCode);\n}\n\n/* c8 ignore start */\nif (typeof require !== 'undefined' && require.main === module) {\n main().catch((err) => {\n // Last-resort: exit 2 is Codex's documented deny-with-stderr path, so\n // even a crash surfaces as a denial rather than Codex's fail-open.\n console.error(`AstraSync Local Guard hook crashed: ${err}`);\n process.exit(process.env.ASTRASYNC_GUARD_FAIL_OPEN === '1' ? 0 : 2);\n });\n}\n/* c8 ignore stop */\n","/**\n * AstraSync Gateway - Types for gateway modes, local evaluation, and adapter interface.\n */\n\n// ========================================================================\n// Gateway Configuration\n// ========================================================================\n\nexport type GatewayMode = 'online' | 'local' | 'hybrid';\n\n/**\n * Posture controls whether the gateway actively blocks or just monitors.\n * - active: Evaluate and enforce decisions (block/allow/review)\n * - passive: Evaluate and log but never block (telemetry-only mode)\n */\nexport type GatewayPosture = 'active' | 'passive';\n\nexport interface AstraSyncGatewayConfig {\n mode: GatewayMode;\n /** Enforcement posture: 'active' blocks actions, 'passive' logs only (default: 'active') */\n posture?: GatewayPosture;\n /** AstraSync API base URL (required for online/hybrid modes) */\n apiBaseUrl?: string;\n /** API key for authenticating with AstraSync (required for online/hybrid modes) */\n apiKey?: string;\n /**\n * ASTRA- agent id this gateway acts as. Attached to hybrid sync entries and\n * used as the default identity for online verification when the caller\n * passes no per-call astraId.\n */\n agentId?: string;\n /** Path to local PDLSS policy YAML file (required for local/hybrid modes) */\n policyFile?: string;\n /** Inline policy object (alternative to policyFile) */\n policy?: LocalPolicy;\n /** Sync interval in seconds for hybrid mode (default: 3600) */\n syncInterval?: number;\n /** Cache verification results TTL in seconds (default: 300) */\n cacheTtl?: number;\n /** Enable debug logging */\n debug?: boolean;\n /** Enable trace logging to .astrasync/traces/ (default: false) */\n traceEnabled?: boolean;\n /** Trace log directory (default: .astrasync/traces/) */\n tracePath?: string;\n /** Minimum trust score for standard access (online/hybrid) */\n minTrustScore?: number;\n /** Minimum trust score for full access (online/hybrid) */\n minTrustScoreForFull?: number;\n /** Custom headers to send with API requests */\n customHeaders?: Record<string, string>;\n /** Counterparty URL for analytics */\n counterpartyUrl?: string;\n /** Counterparty type for analytics */\n counterpartyType?: import('../types').CounterpartyType;\n}\n\n// ========================================================================\n// PDLSS Context (Agent-side action context)\n// ========================================================================\n\nexport interface PDLSSContext {\n /** Purpose category (e.g. email.send, shell.exec, file.read) */\n purpose: string;\n /** Specific action within purpose */\n action: string;\n /** Target resource, recipient, or counterparty */\n target: string;\n /** Types of data access (read, write, delete) */\n dataAccess?: string[];\n /** Network domains/IPs being accessed */\n networkAccess?: string[];\n /** Resource type (customer, order, file, directory, process) */\n resourceType?: string;\n /** Risk factors for this action */\n riskFactors?: RiskFactor[];\n /** Transaction value (if financial) */\n transactionValue?: number;\n /** Currency for transaction */\n currency?: string;\n /** Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\nexport interface RiskFactor {\n type: 'financial' | 'data_sensitivity' | 'privilege_escalation' | 'network_scope' | 'destructive';\n severity: 'low' | 'medium' | 'high' | 'critical';\n detail: string;\n}\n\n// ========================================================================\n// Verification Decision\n// ========================================================================\n\nexport interface VerificationDecision {\n recommendation: 'ALLOW' | 'DENY' | 'MANUAL_REVIEW';\n reason: string;\n trustScore?: number;\n tokenGuidance?: import('../types').TokenGuidance;\n sessionId?: string;\n /**\n * PDLSS dimensions that were evaluated. `true` = the dimension was\n * configured in the policy and therefore ran; `false` = the dimension is\n * absent from the policy and was skipped — NOT \"failed\" (a failed\n * dimension never produces an ALLOW; this field is only set on ALLOW).\n */\n evaluatedDimensions?: {\n purpose: boolean;\n scope: boolean;\n limits: boolean;\n riskThresholds: boolean;\n };\n}\n\n// ========================================================================\n// Local Policy Types (YAML format)\n// ========================================================================\n\nexport interface LocalPolicy {\n version: string;\n name: string;\n description?: string;\n purposes: LocalPurposeRule[];\n scope?: LocalScope;\n limits?: LocalLimits;\n riskThresholds?: LocalRiskThresholds;\n selfInstantiation?: LocalSelfInstantiation;\n}\n\nexport interface LocalPurposeRule {\n id: string;\n allowed: boolean;\n targets?: string[];\n blockedPatterns?: string[];\n requiresApproval?: boolean;\n}\n\nexport interface LocalScope {\n allowedDomains?: string[];\n blockedDomains?: string[];\n blockedResources?: string[];\n}\n\nexport interface LocalLimits {\n /**\n * Autonomous Limit — a transaction value at or below this is granted without\n * escalation. A value in the band `[autonomousThreshold, maxTransactionAmount)`\n * requires human approval (step-up → MANUAL_REVIEW), mirroring the backend\n * `checkWithinLimits` ladder. When omitted there is no autonomous band: every\n * positive value below the Hard Limit is granted (legacy flat-cap behaviour).\n */\n autonomousThreshold?: number;\n /**\n * Hard Limit — a transaction value at or above this is denied outright. (Named\n * `maxTransactionAmount` for backward compatibility with existing local policy\n * files; it is the SDK equivalent of the backend `approvalThreshold`.)\n */\n maxTransactionAmount?: number;\n maxRequestsPerHour?: number;\n currency?: string;\n}\n\nexport interface LocalRiskThresholds {\n autoAllow: { min: number; max: number };\n requireApproval: { min: number; max: number };\n autoBlock: { min: number; max: number };\n}\n\nexport interface LocalSelfInstantiation {\n /** Whether sub-agent spawning is allowed */\n allowed: boolean;\n /** Maximum depth of sub-agent chain */\n maxDepth?: number;\n}\n\n// ========================================================================\n// Risk Scoring Defaults (cherry-picked from trust-harness-core)\n// ========================================================================\n\n/** Base risk scores per action category */\nexport const BASE_RISK_SCORES: Record<string, number> = {\n 'file.read': 10,\n 'file.write': 40,\n 'file.delete': 70,\n 'shell.exec': 50,\n 'network.fetch': 60,\n 'network.request': 60,\n 'email.send': 45,\n 'email.read': 15,\n 'calendar.create': 20,\n 'calendar.modify': 30,\n 'database.query': 25,\n 'database.write': 55,\n 'payment.execute': 80,\n 'sub_agent.spawn': 65,\n 'code.execute': 45,\n};\n\n/** Shell commands that significantly increase risk score */\nexport const HIGH_RISK_COMMANDS = [\n 'rm',\n 'rmdir',\n 'dd',\n 'mkfs',\n 'chmod',\n 'chown',\n 'sudo',\n 'su',\n 'curl',\n 'wget',\n 'nc',\n 'netcat',\n 'ssh',\n 'scp',\n 'rsync',\n 'git push',\n 'npm publish',\n 'docker',\n 'kubectl',\n 'gh pr create',\n 'gh pr merge',\n];\n\n/** File paths that indicate sensitive data access */\nexport const SENSITIVE_PATHS = [\n '.ssh',\n '.aws',\n '.gnupg',\n '.env',\n 'credentials',\n 'secrets',\n 'password',\n '.git/config',\n '/etc',\n '/var',\n '/root',\n 'id_rsa',\n '.npmrc',\n '.pypirc',\n];\n\n// ========================================================================\n// Trace Event Types\n// ========================================================================\n\nexport interface TraceEvent {\n id: string;\n timestamp: Date;\n /**\n * 'skipped' records a tool call the guard saw but did NOT govern\n * (unmapped tool, MCP with governMcp off, skipTools). Added 10 Jul 2026\n * after an ungoverned-PowerShell gap hid behind silent skips — coverage\n * holes must be visible in passive observation.\n */\n type: 'evaluation' | 'decision' | 'error' | 'mode_switch' | 'skipped';\n context?: PDLSSContext;\n decision?: VerificationDecision;\n metadata?: Record<string, unknown>;\n}\n\n// ========================================================================\n// Adapter Interface Types\n// ========================================================================\n\nexport interface AdapterConfig {\n /** The gateway instance (handles mode routing) */\n gateway: unknown; // Typed as AstraSyncGateway at usage site to avoid circular deps\n /** Platform-specific configuration */\n adapterOptions: Record<string, unknown>;\n}\n\nexport interface AgentAction {\n /** Raw action data from the platform */\n raw: unknown;\n /** Platform identifier (e.g. 'openclaw-cli', 'cursor', 'browser') */\n platform: string;\n /** Timestamp of the action */\n timestamp: Date;\n}\n\nexport interface InterceptResult {\n /** Whether the action was intercepted */\n intercepted: boolean;\n /** Extracted PDLSS context (if intercepted) */\n context?: PDLSSContext;\n /** Reason for not intercepting (if not intercepted) */\n skipReason?: string;\n}\n\n// ========================================================================\n// Sync Queue Types (Hybrid mode)\n// ========================================================================\n\nexport interface SyncQueueEntry {\n id: string;\n context: PDLSSContext;\n decision: VerificationDecision;\n timestamp: Date;\n retryCount: number;\n status: 'pending' | 'synced' | 'failed';\n}\n","/**\n * Command-position matching for high-risk shell commands.\n *\n * Replaces the substring-based HIGH_RISK_COMMANDS check that flagged any\n * command merely *containing* a high-risk name (` su` matched \"superadmin\",\n * quoted text and heredoc bodies triggered). A high-risk entry now matches\n * only when it is the invoked command of some pipeline/list segment.\n *\n * Deliberately NOT a shell parser — pure regex/token splitting inside the\n * hook's latency budget. Known accepted misses: option arguments that survive\n * flag filtering (`git -C /tmp push`), exotic quoting/escapes.\n */\n\nimport { HIGH_RISK_COMMANDS } from '../gateway/types';\n\n/** Wrapper commands that prefix the real command; hop over them and re-check. */\nconst WRAPPERS = new Set([\n 'sudo',\n 'doas',\n 'env',\n 'nohup',\n 'time',\n 'timeout',\n 'nice',\n 'ionice',\n 'stdbuf',\n 'xargs',\n 'command',\n 'exec',\n 'builtin',\n]);\n\n/** Leading environment assignment, e.g. `FOO=bar cmd` (input is lowercased). */\nconst ASSIGN_RE = /^[a-z_][a-z0-9_]*=/;\n\nconst MAX_WRAPPER_HOPS = 4;\nconst MAX_RECURSION_DEPTH = 3;\nconst MAX_COMMAND_LENGTH = 100_000;\n\n/** Hosts considered local for the curl/wget risk downgrade (brackets pre-stripped). */\nconst LOCAL_HOST_RE = /^(localhost|127\\.0\\.0\\.1|::1|[a-z0-9.-]*\\.localhost)$/;\n\ninterface RiskList {\n singleWord: Set<string>;\n /** Sorted longest-first so `gh pr create` wins over a shorter prefix entry. */\n multiWord: string[][];\n}\n\nfunction buildRiskList(entries: readonly string[]): RiskList {\n const singleWord = new Set<string>();\n const multiWord: string[][] = [];\n for (const entry of entries) {\n const words = entry.toLowerCase().trim().split(/\\s+/);\n if (words.length === 1) singleWord.add(words[0]);\n else multiWord.push(words);\n }\n multiWord.sort((a, b) => b.length - a.length);\n return { singleWord, multiWord };\n}\n\n/** Drop heredoc bodies (`<<TAG` … `TAG`) — stdin text, not executed commands. */\nfunction stripHeredocBodies(text: string): string {\n const lines = text.split('\\n');\n const kept: string[] = [];\n let terminator: string | null = null;\n for (const line of lines) {\n if (terminator !== null) {\n if (line.trim() === terminator) terminator = null;\n continue;\n }\n kept.push(line);\n const heredoc = line.match(/<<-?\\s*['\"]?(\\w+)['\"]?/);\n if (heredoc) terminator = heredoc[1];\n }\n return kept.join('\\n');\n}\n\n/**\n * Pull out `$(…)` command substitutions (recursing into their contents via\n * `collect`) and blank their spans. No quote awareness inside the parens —\n * pragmatic depth counting only.\n */\nfunction extractDollarSubstitutions(text: string, collect: (inner: string) => void): string {\n let result = text;\n let start = result.indexOf('$(');\n let iterations = 0;\n while (start !== -1 && iterations < 50) {\n iterations++;\n let depth = 0;\n let end = result.length;\n for (let i = start + 1; i < result.length; i++) {\n if (result[i] === '(') depth++;\n else if (result[i] === ')') {\n depth--;\n if (depth === 0) {\n end = i;\n break;\n }\n }\n }\n collect(result.slice(start + 2, end));\n result = `${result.slice(0, start)} ${result.slice(Math.min(end + 1, result.length))}`;\n start = result.indexOf('$(');\n }\n return result;\n}\n\n/** Pull out backtick substitutions (odd chunks when split on `) and blank them. */\nfunction extractBacktickSubstitutions(text: string, collect: (inner: string) => void): string {\n if (!text.includes('`')) return text;\n const chunks = text.split('`');\n const kept: string[] = [];\n for (let i = 0; i < chunks.length; i++) {\n if (i % 2 === 1) collect(chunks[i]);\n else kept.push(chunks[i]);\n }\n return kept.join(' ');\n}\n\n/**\n * Reduce a command token to its matchable name: strip any leading path\n * (both separator styles — PowerShell targets arrive with backslashes) and\n * a trailing Windows executable extension, so `C:\\Tools\\curl.exe` and\n * `curl.exe` both match the `curl` high-risk entry.\n */\nfunction basename(token: string): string {\n const slash = Math.max(token.lastIndexOf('/'), token.lastIndexOf('\\\\'));\n const name = slash === -1 ? token : token.slice(slash + 1);\n return name.replace(/\\.(exe|cmd|bat|ps1)$/i, '');\n}\n\nfunction matchSegment(segment: string, list: RiskList): string | null {\n const tokens = segment.split(/\\s+/).filter((t) => /[a-z0-9]/.test(t));\n let i = 0;\n let hops = 0;\n while (i < tokens.length) {\n // Skip `export` and leading env assignments to reach the command position.\n while (i < tokens.length && (tokens[i] === 'export' || ASSIGN_RE.test(tokens[i]))) i++;\n if (i >= tokens.length) return null;\n\n const cmd = basename(tokens[i]);\n\n // Multi-word entries match against the leading non-flag tokens.\n const significant = [cmd, ...tokens.slice(i + 1).filter((t) => !t.startsWith('-'))];\n for (const entry of list.multiWord) {\n if (entry.length <= significant.length && entry.every((w, j) => significant[j] === w)) {\n return entry.join(' ');\n }\n }\n if (list.singleWord.has(cmd)) return cmd;\n\n // High-risk check ran first, so `sudo …` matches `sudo` before hopping.\n if (WRAPPERS.has(cmd) && hops < MAX_WRAPPER_HOPS) {\n hops++;\n i++;\n while (i < tokens.length && (tokens[i].startsWith('-') || ASSIGN_RE.test(tokens[i]))) i++;\n continue;\n }\n return null;\n }\n return null;\n}\n\nfunction collectMatches(\n command: string,\n list: RiskList,\n matches: Set<string>,\n depth: number\n): void {\n if (depth > MAX_RECURSION_DEPTH || command.length > MAX_COMMAND_LENGTH) return;\n\n let text = command.toLowerCase();\n text = stripHeredocBodies(text);\n\n // Substitutions are extracted (and their contents checked) BEFORE quote\n // stripping so `\"$(curl x)\"` is still evaluated in command position.\n const recurse = (inner: string) => collectMatches(inner, list, matches, depth + 1);\n text = extractDollarSubstitutions(text, recurse);\n text = extractBacktickSubstitutions(text, recurse);\n\n // Quoted spans are data, not commands; `#` comments are noise.\n text = text.replace(/'[^']*'/g, ' ').replace(/\"[^\"]*\"/g, ' ');\n text = text.replace(/(^|\\s)#[^\\n]*/g, ' ');\n\n const segments = text.split(/\\|\\||&&|[;|&\\n]|[({]/);\n for (const segment of segments) {\n const matched = matchSegment(segment, list);\n if (matched) matches.add(matched);\n }\n}\n\n/**\n * Returns every high-risk entry invoked in command position anywhere in\n * `command` (deduplicated), or an empty array.\n */\nexport function matchHighRiskCommands(\n command: string,\n highRiskCommands: readonly string[] = HIGH_RISK_COMMANDS\n): string[] {\n if (!command) return [];\n const matches = new Set<string>();\n collectMatches(command, buildRiskList(highRiskCommands), matches, 0);\n return [...matches];\n}\n\n/**\n * Returns the first high-risk entry invoked in command position, or null.\n * Convenience wrapper over {@link matchHighRiskCommands}.\n */\nexport function matchHighRiskCommand(\n command: string,\n highRiskCommands: readonly string[] = HIGH_RISK_COMMANDS\n): string | null {\n return matchHighRiskCommands(command, highRiskCommands)[0] ?? null;\n}\n\n/**\n * True when the command's network destinations are exclusively local\n * (localhost / 127.0.0.1 / ::1 / *.localhost) AND at least one destination is\n * present. Used to skip the risk-80 bump for curl/wget dev-loop probes.\n * Unparseable or absent destinations keep the bump (fail toward review).\n */\nexport function isLocalhostOnlyNetworkCommand(command: string): boolean {\n const text = command.toLowerCase();\n // Candidate destinations: explicit URLs, host:port tokens, or bare local hosts.\n const tokens = text.split(/\\s+/).map((t) => t.replace(/^[\"'`]+|[\"'`,;)]+$/g, ''));\n let localCount = 0;\n for (const token of tokens) {\n let host: string | null = null;\n if (token.includes('://')) {\n let rest = token.slice(token.indexOf('://') + 3);\n const at = rest.indexOf('@');\n if (at !== -1) rest = rest.slice(at + 1);\n host = rest.split(/[/?#]/)[0];\n } else if (/^[a-z0-9.[\\]:-]+:\\d+(\\/.*)?$/.test(token)) {\n host = token.split('/')[0];\n } else if (/^(localhost|127\\.0\\.0\\.1|\\[?::1\\]?)(\\/.*)?$/.test(token)) {\n host = token.split('/')[0];\n }\n if (host === null) continue;\n // Strip a trailing numeric port, then IPv6 brackets ([::1]:3000 → ::1).\n const bare = host.replace(/:\\d+$/, '').replace(/^\\[|\\]$/g, '');\n if (LOCAL_HOST_RE.test(bare)) {\n localCount++;\n } else {\n return false;\n }\n }\n return localCount > 0;\n}\n","/**\n * Local PDLSS Evaluator\n *\n * Evaluates agent actions against a local PDLSS policy.\n * Same logic as the cloud evaluator but runs in-process with no I/O.\n *\n * Evaluation order:\n * 1. Purpose: find matching rule, check if allowed\n * 2. Purpose: check allowed targets (if specified)\n * 3. Purpose: check blocked patterns (if specified)\n * 4. Scope: check global blocked resources/domains\n * 5. Limits: check transaction/rate limits\n * 6. Risk thresholds + approval requirements\n */\n\nimport type {\n LocalPolicy,\n PDLSSContext,\n VerificationDecision,\n LocalPurposeRule,\n} from '../gateway/types';\nimport { SENSITIVE_PATHS } from '../gateway/types';\nimport { matchHighRiskCommands, isLocalhostOnlyNetworkCommand } from './command-matcher';\n\nexport class LocalEvaluator {\n private policy: LocalPolicy;\n private requestCounts: Map<string, { count: number; windowStart: number }> = new Map();\n\n constructor(policy: LocalPolicy) {\n this.policy = policy;\n }\n\n /**\n * Update the policy (e.g. after hot-reload or sync).\n */\n updatePolicy(policy: LocalPolicy): void {\n this.policy = policy;\n }\n\n /**\n * Evaluate an action context against the loaded policy.\n */\n evaluate(context: PDLSSContext): VerificationDecision {\n // 1. Purpose: find matching rule\n const purposeRule = this.policy.purposes.find((p) => p.id === context.purpose);\n if (!purposeRule) {\n return { recommendation: 'DENY', reason: 'Purpose not in policy' };\n }\n if (!purposeRule.allowed) {\n return { recommendation: 'DENY', reason: 'Purpose explicitly blocked' };\n }\n\n // 2. Purpose: check allowed targets\n if (purposeRule.targets && !this.matchesAnyPattern(context.target, purposeRule.targets)) {\n return { recommendation: 'DENY', reason: 'Target not in allowed list' };\n }\n\n // 3. Purpose: check blocked patterns\n if (\n purposeRule.blockedPatterns &&\n this.matchesAnyPattern(context.target, purposeRule.blockedPatterns)\n ) {\n return { recommendation: 'DENY', reason: 'Target matches blocked pattern' };\n }\n\n // 4. Scope: check global blocked resources/domains\n const scopeBlock = this.checkScopeBlock(context);\n if (scopeBlock) {\n return { recommendation: 'DENY', reason: scopeBlock };\n }\n\n // 5. Limits: check transaction (autonomous/hard band) and rate limits\n const limitDecision = this.checkLimits(context);\n if (limitDecision) {\n return limitDecision;\n }\n\n // 6. Self-instantiation: check sub-agent spawning rules\n if (context.purpose === 'sub_agent.spawn' && this.policy.selfInstantiation) {\n if (!this.policy.selfInstantiation.allowed) {\n return { recommendation: 'DENY', reason: 'Sub-agent spawning is not allowed' };\n }\n const depth = (context.metadata?.subAgentDepth as number) || 0;\n if (\n this.policy.selfInstantiation.maxDepth !== undefined &&\n depth >= this.policy.selfInstantiation.maxDepth\n ) {\n return {\n recommendation: 'DENY',\n reason: `Sub-agent depth ${depth} exceeds max depth ${this.policy.selfInstantiation.maxDepth}`,\n };\n }\n }\n\n // 7. Risk thresholds + approval requirements\n if (purposeRule.requiresApproval) {\n return { recommendation: 'MANUAL_REVIEW', reason: 'Purpose requires approval' };\n }\n\n const riskDecision = this.checkRiskThresholds(context);\n if (riskDecision) {\n return riskDecision;\n }\n\n return {\n recommendation: 'ALLOW',\n // \"evaluated\": dimensions absent from the policy are skipped, not\n // failed — evaluatedDimensions below records which ones ran.\n reason: 'All evaluated PDLSS checks passed',\n evaluatedDimensions: {\n purpose: true,\n scope: !!this.policy.scope,\n limits: !!this.policy.limits,\n riskThresholds: !!this.policy.riskThresholds,\n },\n };\n }\n\n private checkScopeBlock(context: PDLSSContext): string | null {\n const scope = this.policy.scope;\n if (!scope) return null;\n\n // Check blocked domains against target and network access\n if (scope.blockedDomains) {\n const targetDomain = this.extractDomain(context.target);\n if (this.matchesAnyPattern(targetDomain, scope.blockedDomains)) {\n return `Target blocked by scope: ${context.target}`;\n }\n if (context.networkAccess) {\n for (const domain of context.networkAccess) {\n if (this.matchesAnyPattern(this.extractDomain(domain), scope.blockedDomains)) {\n return `Domain blocked by scope: ${domain}`;\n }\n }\n }\n }\n\n // Check blocked resources against target\n if (scope.blockedResources && this.matchesAnyPattern(context.target, scope.blockedResources)) {\n return `Resource blocked by scope: ${context.target}`;\n }\n\n // Check allowed domains (if specified, target must match)\n if (scope.allowedDomains && context.networkAccess) {\n for (const domain of context.networkAccess) {\n if (!this.matchesAnyPattern(this.extractDomain(domain), scope.allowedDomains)) {\n return `Domain not in allowed list: ${domain}`;\n }\n }\n }\n\n return null;\n }\n\n private checkLimits(context: PDLSSContext): VerificationDecision | null {\n const limits = this.policy.limits;\n if (!limits) return null;\n\n // Transaction-value ladder — parity with the backend `checkWithinLimits`:\n // A = Autonomous Limit (autonomousThreshold, default 0)\n // H = Hard Limit (maxTransactionAmount; falls back to A when only the\n // Autonomous Limit is declared)\n // value <= A -> autonomous (falls through — rate check still applies)\n // A < value < H -> MANUAL_REVIEW (step-up / human approval)\n // value >= H -> DENY\n // The ladder only runs when the policy declares at least one threshold; a\n // limits block with only a currency/rate cap imposes no transaction ceiling.\n const value = context.transactionValue;\n if (\n value !== undefined &&\n value > 0 &&\n (limits.autonomousThreshold !== undefined || limits.maxTransactionAmount !== undefined)\n ) {\n const autonomousThreshold = limits.autonomousThreshold ?? 0;\n const hardLimit = limits.maxTransactionAmount ?? limits.autonomousThreshold ?? 0;\n if (value > autonomousThreshold) {\n if (value >= hardLimit) {\n return {\n recommendation: 'DENY',\n reason: `Transaction value ${value} at or above Hard Limit ${hardLimit}`,\n };\n }\n return {\n recommendation: 'MANUAL_REVIEW',\n reason: `Transaction value ${value} is in the human-approval band (${autonomousThreshold}, ${hardLimit})`,\n };\n }\n }\n\n // Rate limit check\n if (limits.maxRequestsPerHour !== undefined) {\n const key = context.purpose;\n const now = Date.now();\n const entry = this.requestCounts.get(key);\n const hourMs = 3600000;\n\n if (!entry || now - entry.windowStart > hourMs) {\n this.requestCounts.set(key, { count: 1, windowStart: now });\n } else {\n entry.count++;\n if (entry.count > limits.maxRequestsPerHour) {\n return {\n recommendation: 'DENY',\n reason: `Rate limit exceeded: ${entry.count}/${limits.maxRequestsPerHour} requests per hour`,\n };\n }\n }\n }\n\n return null;\n }\n\n private checkRiskThresholds(context: PDLSSContext): VerificationDecision | null {\n if (!this.policy.riskThresholds) return null;\n\n const riskScore = this.calculateRiskScore(context);\n const thresholds = this.policy.riskThresholds;\n\n if (riskScore >= thresholds.autoBlock.min) {\n return { recommendation: 'DENY', reason: `Risk score ${riskScore} exceeds block threshold` };\n }\n\n if (riskScore >= thresholds.requireApproval.min) {\n return {\n recommendation: 'MANUAL_REVIEW',\n reason: `Risk score ${riskScore} requires approval`,\n };\n }\n\n return null;\n }\n\n private calculateRiskScore(context: PDLSSContext): number {\n let score = 0;\n\n // Explicit risk factors take priority (highest severity wins)\n if (context.riskFactors?.length) {\n const severityScores: Record<string, number> = {\n low: 10,\n medium: 40,\n high: 70,\n critical: 90,\n };\n\n for (const factor of context.riskFactors) {\n const factorScore = severityScores[factor.severity] || 0;\n if (factorScore > score) score = factorScore;\n }\n return score;\n }\n\n // Auto-detect risk from high-risk shell commands (command-position match,\n // not substring). curl/wget aimed exclusively at localhost stay below the\n // review threshold — dev-loop probes, not exfiltration surface.\n if (context.purpose === 'shell.exec' && context.target) {\n const matched = matchHighRiskCommands(context.target);\n const localProbeOnly =\n matched.length > 0 &&\n matched.every((cmd) => cmd === 'curl' || cmd === 'wget') &&\n isLocalhostOnlyNetworkCommand(context.target);\n if (matched.length > 0 && !localProbeOnly) {\n score = Math.max(score, 80);\n }\n }\n\n // Auto-detect risk from sensitive file paths (score 50 = review range).\n // Separators normalized so entries containing '/' (e.g. '.git/config')\n // match Windows backslash targets — same class as the matchGlob fix.\n if (\n (context.purpose === 'file.read' ||\n context.purpose === 'file.write' ||\n context.purpose === 'file.delete') &&\n context.target\n ) {\n const targetLower = context.target.toLowerCase().replace(/\\\\/g, '/');\n for (const sensitivePath of SENSITIVE_PATHS) {\n if (targetLower.includes(sensitivePath.toLowerCase())) {\n score = Math.max(score, 50);\n break;\n }\n }\n }\n\n return score;\n }\n\n /**\n * Extract domain from a URL-like string (strips protocol and path).\n */\n private extractDomain(value: string): string {\n let domain = value;\n // Strip protocol\n const protoIndex = domain.indexOf('://');\n if (protoIndex !== -1) domain = domain.slice(protoIndex + 3);\n // Strip path\n const slashIndex = domain.indexOf('/');\n if (slashIndex !== -1) domain = domain.slice(0, slashIndex);\n // Strip port\n const colonIndex = domain.indexOf(':');\n if (colonIndex !== -1) domain = domain.slice(0, colonIndex);\n return domain;\n }\n\n /**\n * Check if a value matches any of the given glob patterns.\n */\n private matchesAnyPattern(value: string, patterns: string[]): boolean {\n return patterns.some((pattern) => this.matchGlob(value, pattern));\n }\n\n /**\n * Simple glob pattern matching.\n * Supports * (matches any characters including / and spaces) and ? (single char).\n * Uses the same approach as the backend's matchGlobPattern.\n */\n /**\n * Home directory as a forward-slash prefix for `~` pattern expansion,\n * resolved from the environment WITHOUT importing `os` (this evaluator\n * also runs bundled inside the browser extension, where node builtins\n * don't exist — there `~` patterns stay literal, which is correct since\n * browser targets are URLs). Cached per instance.\n */\n private cachedHomePrefix: string | null | undefined;\n\n private homePrefix(): string | null {\n if (this.cachedHomePrefix !== undefined) return this.cachedHomePrefix;\n const env = typeof process !== 'undefined' ? process.env : undefined;\n const home = env?.HOME || env?.USERPROFILE;\n this.cachedHomePrefix = home ? home.replace(/\\\\/g, '/') : null;\n return this.cachedHomePrefix;\n }\n\n private matchGlob(value: string, pattern: string): boolean {\n // Two live bypasses found 11 Jul 2026 (Windows desktop verification):\n // 1. Windows targets arrive with backslashes (C:\\Users\\...\\settings.json)\n // and never matched forward-slash glob patterns — EVERY file-path\n // protection was dead on native Windows. Normalize separators on\n // both sides so Windows-authored patterns keep working too.\n // 2. `~/...` patterns were never expanded, so the default policy's\n // credential-path protections (~/.ssh/*, ~/.aws/*) matched nothing\n // on ANY platform. Expand a leading `~` to the home directory.\n value = value.replace(/\\\\/g, '/');\n pattern = pattern.replace(/\\\\/g, '/');\n if (pattern === '~' || pattern.startsWith('~/')) {\n const home = this.homePrefix();\n if (home) pattern = home + pattern.slice(1);\n }\n\n // Exact match\n if (pattern === value) return true;\n\n // Audit F-A1-13: ReDoS guard. Patterns with too many `*` segments\n // produce catastrophic-backtracking regexes (e.g. `a*a*a*a*a*a*a*a*b`\n // against `aaaaaaaa` runs in exponential time). Local policies are\n // operator-controlled so attacker access requires operator-side\n // compromise, but a copy-pasted-from-internet example pattern could\n // still DoS the gateway when matched against request input.\n const starCount = (pattern.match(/\\*/g) ?? []).length;\n if (starCount > 8) {\n return false;\n }\n\n // Convert glob to regex\n const regexStr = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&') // Escape special regex chars (except * and ?)\n .replace(/\\*/g, '.*') // * matches anything\n .replace(/\\?/g, '.'); // ? matches single char\n\n try {\n return new RegExp(`^${regexStr}$`, 'i').test(value);\n } catch {\n return false;\n }\n }\n}\n\n/**\n * Convenience: find a matching purpose rule.\n */\nexport function findPurposeRule(\n policy: LocalPolicy,\n purposeId: string\n): LocalPurposeRule | undefined {\n return policy.purposes.find((p) => p.id === purposeId);\n}\n","'use strict'\n\nfunction isNothing (subject) {\n return (typeof subject === 'undefined') || (subject === null)\n}\n\nfunction isObject (subject) {\n return (typeof subject === 'object') && (subject !== null)\n}\n\nfunction toArray (sequence) {\n if (Array.isArray(sequence)) return sequence\n else if (isNothing(sequence)) return []\n\n return [sequence]\n}\n\nfunction extend (target, source) {\n if (source) {\n const sourceKeys = Object.keys(source)\n\n for (let index = 0, length = sourceKeys.length; index < length; index += 1) {\n const key = sourceKeys[index]\n target[key] = source[key]\n }\n }\n\n return target\n}\n\nfunction repeat (string, count) {\n let result = ''\n\n for (let cycle = 0; cycle < count; cycle += 1) {\n result += string\n }\n\n return result\n}\n\nfunction isNegativeZero (number) {\n return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number)\n}\n\nmodule.exports.isNothing = isNothing\nmodule.exports.isObject = isObject\nmodule.exports.toArray = toArray\nmodule.exports.repeat = repeat\nmodule.exports.isNegativeZero = isNegativeZero\nmodule.exports.extend = extend\n","// YAML error class. http://stackoverflow.com/questions/8458984\n//\n'use strict'\n\nfunction formatError (exception, compact) {\n let where = ''\n const message = exception.reason || '(unknown reason)'\n\n if (!exception.mark) return message\n\n if (exception.mark.name) {\n where += 'in \"' + exception.mark.name + '\" '\n }\n\n where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')'\n\n if (!compact && exception.mark.snippet) {\n where += '\\n\\n' + exception.mark.snippet\n }\n\n return message + ' ' + where\n}\n\nfunction YAMLException (reason, mark) {\n // Super constructor\n Error.call(this)\n\n this.name = 'YAMLException'\n this.reason = reason\n this.mark = mark\n this.message = formatError(this, false)\n\n // Include stack trace in error object\n if (Error.captureStackTrace) {\n // Chrome and NodeJS\n Error.captureStackTrace(this, this.constructor)\n } else {\n // FF, IE 10+ and Safari 6+. Fallback for others\n this.stack = (new Error()).stack || ''\n }\n}\n\n// Inherit from Error\nYAMLException.prototype = Object.create(Error.prototype)\nYAMLException.prototype.constructor = YAMLException\n\nYAMLException.prototype.toString = function toString (compact) {\n return this.name + ': ' + formatError(this, compact)\n}\n\nmodule.exports = YAMLException\n","'use strict'\n\nconst common = require('./common')\n\n// get snippet for a single line, respecting maxLength\nfunction getLine (buffer, lineStart, lineEnd, position, maxLineLength) {\n let head = ''\n let tail = ''\n const maxHalfLength = Math.floor(maxLineLength / 2) - 1\n\n if (position - lineStart > maxHalfLength) {\n head = ' ... '\n lineStart = position - maxHalfLength + head.length\n }\n\n if (lineEnd - position > maxHalfLength) {\n tail = ' ...'\n lineEnd = position + maxHalfLength - tail.length\n }\n\n return {\n str: head + buffer.slice(lineStart, lineEnd).replace(/\\t/g, '→') + tail,\n pos: position - lineStart + head.length // relative position\n }\n}\n\nfunction padStart (string, max) {\n return common.repeat(' ', max - string.length) + string\n}\n\nfunction makeSnippet (mark, options) {\n options = Object.create(options || null)\n\n if (!mark.buffer) return null\n\n if (!options.maxLength) options.maxLength = 79\n if (typeof options.indent !== 'number') options.indent = 1\n if (typeof options.linesBefore !== 'number') options.linesBefore = 3\n if (typeof options.linesAfter !== 'number') options.linesAfter = 2\n\n const re = /\\r?\\n|\\r|\\0/g\n const lineStarts = [0]\n const lineEnds = []\n let match\n let foundLineNo = -1\n\n while ((match = re.exec(mark.buffer))) {\n lineEnds.push(match.index)\n lineStarts.push(match.index + match[0].length)\n\n if (mark.position <= match.index && foundLineNo < 0) {\n foundLineNo = lineStarts.length - 2\n }\n }\n\n if (foundLineNo < 0) foundLineNo = lineStarts.length - 1\n\n let result = ''\n const lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length\n const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3)\n\n for (let i = 1; i <= options.linesBefore; i++) {\n if (foundLineNo - i < 0) break\n const line = getLine(\n mark.buffer,\n lineStarts[foundLineNo - i],\n lineEnds[foundLineNo - i],\n mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),\n maxLineLength\n )\n result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) +\n ' | ' + line.str + '\\n' + result\n }\n\n const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength)\n result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) +\n ' | ' + line.str + '\\n'\n result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\\n'\n\n for (let i = 1; i <= options.linesAfter; i++) {\n if (foundLineNo + i >= lineEnds.length) break\n const line = getLine(\n mark.buffer,\n lineStarts[foundLineNo + i],\n lineEnds[foundLineNo + i],\n mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),\n maxLineLength\n )\n result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) +\n ' | ' + line.str + '\\n'\n }\n\n return result.replace(/\\n$/, '')\n}\n\nmodule.exports = makeSnippet\n","'use strict'\n\nconst YAMLException = require('./exception')\n\nconst TYPE_CONSTRUCTOR_OPTIONS = [\n 'kind',\n 'multi',\n 'resolve',\n 'construct',\n 'instanceOf',\n 'predicate',\n 'represent',\n 'representName',\n 'defaultStyle',\n 'styleAliases'\n]\n\nconst YAML_NODE_KINDS = [\n 'scalar',\n 'sequence',\n 'mapping'\n]\n\nfunction compileStyleAliases (map) {\n const result = {}\n\n if (map !== null) {\n Object.keys(map).forEach(function (style) {\n map[style].forEach(function (alias) {\n result[String(alias)] = style\n })\n })\n }\n\n return result\n}\n\nfunction Type (tag, options) {\n options = options || {}\n\n Object.keys(options).forEach(function (name) {\n if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {\n throw new YAMLException('Unknown option \"' + name + '\" is met in definition of \"' + tag + '\" YAML type.')\n }\n })\n\n // TODO: Add tag format check.\n this.options = options // keep original options in case user wants to extend this type later\n this.tag = tag\n this.kind = options['kind'] || null\n this.resolve = options['resolve'] || function () { return true }\n this.construct = options['construct'] || function (data) { return data }\n this.instanceOf = options['instanceOf'] || null\n this.predicate = options['predicate'] || null\n this.represent = options['represent'] || null\n this.representName = options['representName'] || null\n this.defaultStyle = options['defaultStyle'] || null\n this.multi = options['multi'] || false\n this.styleAliases = compileStyleAliases(options['styleAliases'] || null)\n\n if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {\n throw new YAMLException('Unknown kind \"' + this.kind + '\" is specified for \"' + tag + '\" YAML type.')\n }\n}\n\nmodule.exports = Type\n","'use strict'\n\nconst YAMLException = require('./exception')\nconst Type = require('./type')\n\nfunction compileList (schema, name) {\n const result = []\n\n schema[name].forEach(function (currentType) {\n let newIndex = result.length\n\n result.forEach(function (previousType, previousIndex) {\n if (previousType.tag === currentType.tag &&\n previousType.kind === currentType.kind &&\n previousType.multi === currentType.multi) {\n newIndex = previousIndex\n }\n })\n\n result[newIndex] = currentType\n })\n\n return result\n}\n\nfunction compileMap (/* lists... */) {\n const result = {\n scalar: {},\n sequence: {},\n mapping: {},\n fallback: {},\n multi: {\n scalar: [],\n sequence: [],\n mapping: [],\n fallback: []\n }\n }\n function collectType (type) {\n if (type.multi) {\n result.multi[type.kind].push(type)\n result.multi['fallback'].push(type)\n } else {\n result[type.kind][type.tag] = result['fallback'][type.tag] = type\n }\n }\n\n for (let index = 0, length = arguments.length; index < length; index += 1) {\n arguments[index].forEach(collectType)\n }\n return result\n}\n\nfunction Schema (definition) {\n return this.extend(definition)\n}\n\nSchema.prototype.extend = function extend (definition) {\n let implicit = []\n let explicit = []\n\n if (definition instanceof Type) {\n // Schema.extend(type)\n explicit.push(definition)\n } else if (Array.isArray(definition)) {\n // Schema.extend([ type1, type2, ... ])\n explicit = explicit.concat(definition)\n } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {\n // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] })\n if (definition.implicit) implicit = implicit.concat(definition.implicit)\n if (definition.explicit) explicit = explicit.concat(definition.explicit)\n } else {\n throw new YAMLException('Schema.extend argument should be a Type, [ Type ], ' +\n 'or a schema definition ({ implicit: [...], explicit: [...] })')\n }\n\n implicit.forEach(function (type) {\n if (!(type instanceof Type)) {\n throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')\n }\n\n if (type.loadKind && type.loadKind !== 'scalar') {\n throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.')\n }\n\n if (type.multi) {\n throw new YAMLException('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.')\n }\n })\n\n explicit.forEach(function (type) {\n if (!(type instanceof Type)) {\n throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')\n }\n })\n\n const result = Object.create(Schema.prototype)\n\n result.implicit = (this.implicit || []).concat(implicit)\n result.explicit = (this.explicit || []).concat(explicit)\n\n result.compiledImplicit = compileList(result, 'implicit')\n result.compiledExplicit = compileList(result, 'explicit')\n result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit)\n\n return result\n}\n\nmodule.exports = Schema\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:str', {\n kind: 'scalar',\n construct: function (data) { return data !== null ? data : '' }\n})\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:seq', {\n kind: 'sequence',\n construct: function (data) { return data !== null ? data : [] }\n})\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:map', {\n kind: 'mapping',\n construct: function (data) { return data !== null ? data : {} }\n})\n","// Standard YAML's Failsafe schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2802346\n\n'use strict'\n\nconst Schema = require('../schema')\n\nmodule.exports = new Schema({\n explicit: [\n require('../type/str'),\n require('../type/seq'),\n require('../type/map')\n ]\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlNull (data) {\n if (data === null) return true\n\n const max = data.length\n\n return (max === 1 && data === '~') ||\n (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'))\n}\n\nfunction constructYamlNull () {\n return null\n}\n\nfunction isNull (object) {\n return object === null\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:null', {\n kind: 'scalar',\n resolve: resolveYamlNull,\n construct: constructYamlNull,\n predicate: isNull,\n represent: {\n canonical: function () { return '~' },\n lowercase: function () { return 'null' },\n uppercase: function () { return 'NULL' },\n camelcase: function () { return 'Null' },\n empty: function () { return '' }\n },\n defaultStyle: 'lowercase'\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlBoolean (data) {\n if (data === null) return false\n\n const max = data.length\n\n return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||\n (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'))\n}\n\nfunction constructYamlBoolean (data) {\n return data === 'true' ||\n data === 'True' ||\n data === 'TRUE'\n}\n\nfunction isBoolean (object) {\n return Object.prototype.toString.call(object) === '[object Boolean]'\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:bool', {\n kind: 'scalar',\n resolve: resolveYamlBoolean,\n construct: constructYamlBoolean,\n predicate: isBoolean,\n represent: {\n lowercase: function (object) { return object ? 'true' : 'false' },\n uppercase: function (object) { return object ? 'TRUE' : 'FALSE' },\n camelcase: function (object) { return object ? 'True' : 'False' }\n },\n defaultStyle: 'lowercase'\n})\n","'use strict'\n\nconst common = require('../common')\nconst Type = require('../type')\n\nfunction isHexCode (c) {\n return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) ||\n ((c >= 0x41/* A */) && (c <= 0x46/* F */)) ||\n ((c >= 0x61/* a */) && (c <= 0x66/* f */))\n}\n\nfunction isOctCode (c) {\n return ((c >= 0x30/* 0 */) && (c <= 0x37/* 7 */))\n}\n\nfunction isDecCode (c) {\n return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */))\n}\n\nfunction resolveYamlInteger (data) {\n if (data === null) return false\n\n const max = data.length\n let index = 0\n let hasDigits = false\n\n if (!max) return false\n\n let ch = data[index]\n\n // sign\n if (ch === '-' || ch === '+') {\n ch = data[++index]\n }\n\n if (ch === '0') {\n // 0\n if (index + 1 === max) return true\n ch = data[++index]\n\n // base 2, base 8, base 16\n\n if (ch === 'b') {\n // base 2\n index++\n\n for (; index < max; index++) {\n ch = data[index]\n if (ch !== '0' && ch !== '1') return false\n hasDigits = true\n }\n return hasDigits && isFinite(parseYamlInteger(data))\n }\n\n if (ch === 'x') {\n // base 16\n index++\n\n for (; index < max; index++) {\n if (!isHexCode(data.charCodeAt(index))) return false\n hasDigits = true\n }\n return hasDigits && isFinite(parseYamlInteger(data))\n }\n\n if (ch === 'o') {\n // base 8\n index++\n\n for (; index < max; index++) {\n if (!isOctCode(data.charCodeAt(index))) return false\n hasDigits = true\n }\n return hasDigits && isFinite(parseYamlInteger(data))\n }\n }\n\n // base 10 (except 0)\n\n for (; index < max; index++) {\n if (!isDecCode(data.charCodeAt(index))) {\n return false\n }\n hasDigits = true\n }\n\n if (!hasDigits) return false\n\n return isFinite(parseYamlInteger(data))\n}\n\nfunction parseYamlInteger (data) {\n let value = data\n let sign = 1\n\n let ch = value[0]\n\n if (ch === '-' || ch === '+') {\n if (ch === '-') sign = -1\n value = value.slice(1)\n ch = value[0]\n }\n\n if (value === '0') return 0\n\n if (ch === '0') {\n if (value[1] === 'b') return sign * parseInt(value.slice(2), 2)\n if (value[1] === 'x') return sign * parseInt(value.slice(2), 16)\n if (value[1] === 'o') return sign * parseInt(value.slice(2), 8)\n }\n\n return sign * parseInt(value, 10)\n}\n\nfunction constructYamlInteger (data) {\n return parseYamlInteger(data)\n}\n\nfunction isInteger (object) {\n return (Object.prototype.toString.call(object)) === '[object Number]' &&\n (object % 1 === 0 && !common.isNegativeZero(object))\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:int', {\n kind: 'scalar',\n resolve: resolveYamlInteger,\n construct: constructYamlInteger,\n predicate: isInteger,\n represent: {\n binary: function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1) },\n octal: function (obj) { return obj >= 0 ? '0o' + obj.toString(8) : '-0o' + obj.toString(8).slice(1) },\n decimal: function (obj) { return obj.toString(10) },\n hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() : '-0x' + obj.toString(16).toUpperCase().slice(1) }\n },\n defaultStyle: 'decimal',\n styleAliases: {\n binary: [2, 'bin'],\n octal: [8, 'oct'],\n decimal: [10, 'dec'],\n hexadecimal: [16, 'hex']\n }\n})\n","'use strict'\n\nconst common = require('../common')\nconst Type = require('../type')\n\nconst YAML_FLOAT_PATTERN = new RegExp(\n // 2.5e4, 2.5 and integers\n '^(?:[-+]?(?:[0-9]+)(?:\\\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?' +\n // .2e4, .2\n // special case, seems not from spec\n '|\\\\.[0-9]+(?:[eE][-+]?[0-9]+)?' +\n // .inf\n '|[-+]?\\\\.(?:inf|Inf|INF)' +\n // .nan\n '|\\\\.(?:nan|NaN|NAN))$')\n\nconst YAML_FLOAT_SPECIAL_PATTERN = new RegExp(\n '^(?:' +\n // .inf\n '[-+]?\\\\.(?:inf|Inf|INF)' +\n // .nan\n '|\\\\.(?:nan|NaN|NAN))$')\n\nfunction resolveYamlFloat (data) {\n if (data === null) return false\n\n if (!YAML_FLOAT_PATTERN.test(data)) {\n return false\n }\n\n if (isFinite(parseFloat(data, 10))) {\n return true\n }\n\n return YAML_FLOAT_SPECIAL_PATTERN.test(data)\n}\n\nfunction constructYamlFloat (data) {\n let value = data.toLowerCase()\n const sign = value[0] === '-' ? -1 : 1\n\n if ('+-'.indexOf(value[0]) >= 0) {\n value = value.slice(1)\n }\n\n if (value === '.inf') {\n return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY\n } else if (value === '.nan') {\n return NaN\n }\n return sign * parseFloat(value, 10)\n}\n\nconst SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/\n\nfunction representYamlFloat (object, style) {\n if (isNaN(object)) {\n switch (style) {\n case 'lowercase': return '.nan'\n case 'uppercase': return '.NAN'\n case 'camelcase': return '.NaN'\n }\n } else if (Number.POSITIVE_INFINITY === object) {\n switch (style) {\n case 'lowercase': return '.inf'\n case 'uppercase': return '.INF'\n case 'camelcase': return '.Inf'\n }\n } else if (Number.NEGATIVE_INFINITY === object) {\n switch (style) {\n case 'lowercase': return '-.inf'\n case 'uppercase': return '-.INF'\n case 'camelcase': return '-.Inf'\n }\n } else if (common.isNegativeZero(object)) {\n return '-0.0'\n }\n\n const res = object.toString(10)\n\n // JS stringifier can build scientific format without dots: 5e-100,\n // while YAML requres dot: 5.e-100. Fix it with simple hack\n\n return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res\n}\n\nfunction isFloat (object) {\n return (Object.prototype.toString.call(object) === '[object Number]') &&\n (object % 1 !== 0 || common.isNegativeZero(object))\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:float', {\n kind: 'scalar',\n resolve: resolveYamlFloat,\n construct: constructYamlFloat,\n predicate: isFloat,\n represent: representYamlFloat,\n defaultStyle: 'lowercase'\n})\n","// Standard YAML's JSON schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2803231\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, this schema is not such strict as defined in the YAML specification.\n// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.\n\n'use strict'\n\nmodule.exports = require('./failsafe').extend({\n implicit: [\n require('../type/null'),\n require('../type/bool'),\n require('../type/int'),\n require('../type/float')\n ]\n})\n","// Standard YAML's Core schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2804923\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, Core schema has no distinctions from JSON schema is JS-YAML.\n\n'use strict'\n\nmodule.exports = require('./json')\n","'use strict'\n\nconst Type = require('../type')\n\nconst YAML_DATE_REGEXP = new RegExp(\n '^([0-9][0-9][0-9][0-9])' + // [1] year\n '-([0-9][0-9])' + // [2] month\n '-([0-9][0-9])$') // [3] day\n\nconst YAML_TIMESTAMP_REGEXP = new RegExp(\n '^([0-9][0-9][0-9][0-9])' + // [1] year\n '-([0-9][0-9]?)' + // [2] month\n '-([0-9][0-9]?)' + // [3] day\n '(?:[Tt]|[ \\\\t]+)' + // ...\n '([0-9][0-9]?)' + // [4] hour\n ':([0-9][0-9])' + // [5] minute\n ':([0-9][0-9])' + // [6] second\n '(?:\\\\.([0-9]*))?' + // [7] fraction\n '(?:[ \\\\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tzHour\n '(?::([0-9][0-9]))?))?$') // [11] tzMinute\n\nfunction resolveYamlTimestamp (data) {\n if (data === null) return false\n if (YAML_DATE_REGEXP.exec(data) !== null) return true\n if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true\n return false\n}\n\nfunction constructYamlTimestamp (data) {\n let fraction = 0\n let delta = null\n\n let match = YAML_DATE_REGEXP.exec(data)\n if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data)\n\n if (match === null) throw new Error('Date resolve error')\n\n // match: [1] year [2] month [3] day\n\n const year = +(match[1])\n const month = +(match[2]) - 1 // JS month starts with 0\n const day = +(match[3])\n\n if (!match[4]) { // no hour\n return new Date(Date.UTC(year, month, day))\n }\n\n // match: [4] hour [5] minute [6] second [7] fraction\n\n const hour = +(match[4])\n const minute = +(match[5])\n const second = +(match[6])\n\n if (match[7]) {\n fraction = match[7].slice(0, 3)\n while (fraction.length < 3) { // milli-seconds\n fraction += '0'\n }\n fraction = +fraction\n }\n\n // match: [8] tz [9] tz_sign [10] tzHour [11] tzMinute\n\n if (match[9]) {\n const tzHour = +(match[10])\n const tzMinute = +(match[11] || 0)\n delta = (tzHour * 60 + tzMinute) * 60000 // delta in mili-seconds\n if (match[9] === '-') delta = -delta\n }\n\n const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction))\n\n if (delta) date.setTime(date.getTime() - delta)\n\n return date\n}\n\nfunction representYamlTimestamp (object /*, style */) {\n return object.toISOString()\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:timestamp', {\n kind: 'scalar',\n resolve: resolveYamlTimestamp,\n construct: constructYamlTimestamp,\n instanceOf: Date,\n represent: representYamlTimestamp\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlMerge (data) {\n return data === '<<' || data === null\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:merge', {\n kind: 'scalar',\n resolve: resolveYamlMerge\n})\n","'use strict'\n\nconst Type = require('../type')\n\n// [ 64, 65, 66 ] -> [ padding, CR, LF ]\nconst BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\\n\\r'\n\nfunction resolveYamlBinary (data) {\n if (data === null) return false\n\n let bitlen = 0\n const max = data.length\n const map = BASE64_MAP\n\n // Convert one by one.\n for (let idx = 0; idx < max; idx++) {\n const code = map.indexOf(data.charAt(idx))\n\n // Skip CR/LF\n if (code > 64) continue\n\n // Fail on illegal characters\n if (code < 0) return false\n\n bitlen += 6\n }\n\n // If there are any bits left, source was corrupted\n return (bitlen % 8) === 0\n}\n\nfunction constructYamlBinary (data) {\n const input = data.replace(/[\\r\\n=]/g, '') // remove CR/LF & padding to simplify scan\n const max = input.length\n const map = BASE64_MAP\n let bits = 0\n const result = []\n\n // Collect by 6*4 bits (3 bytes)\n\n for (let idx = 0; idx < max; idx++) {\n if ((idx % 4 === 0) && idx) {\n result.push((bits >> 16) & 0xFF)\n result.push((bits >> 8) & 0xFF)\n result.push(bits & 0xFF)\n }\n\n bits = (bits << 6) | map.indexOf(input.charAt(idx))\n }\n\n // Dump tail\n\n const tailbits = (max % 4) * 6\n\n if (tailbits === 0) {\n result.push((bits >> 16) & 0xFF)\n result.push((bits >> 8) & 0xFF)\n result.push(bits & 0xFF)\n } else if (tailbits === 18) {\n result.push((bits >> 10) & 0xFF)\n result.push((bits >> 2) & 0xFF)\n } else if (tailbits === 12) {\n result.push((bits >> 4) & 0xFF)\n }\n\n return new Uint8Array(result)\n}\n\nfunction representYamlBinary (object /*, style */) {\n let result = ''\n let bits = 0\n const max = object.length\n const map = BASE64_MAP\n\n // Convert every three bytes to 4 ASCII characters.\n\n for (let idx = 0; idx < max; idx++) {\n if ((idx % 3 === 0) && idx) {\n result += map[(bits >> 18) & 0x3F]\n result += map[(bits >> 12) & 0x3F]\n result += map[(bits >> 6) & 0x3F]\n result += map[bits & 0x3F]\n }\n\n bits = (bits << 8) + object[idx]\n }\n\n // Dump tail\n\n const tail = max % 3\n\n if (tail === 0) {\n result += map[(bits >> 18) & 0x3F]\n result += map[(bits >> 12) & 0x3F]\n result += map[(bits >> 6) & 0x3F]\n result += map[bits & 0x3F]\n } else if (tail === 2) {\n result += map[(bits >> 10) & 0x3F]\n result += map[(bits >> 4) & 0x3F]\n result += map[(bits << 2) & 0x3F]\n result += map[64]\n } else if (tail === 1) {\n result += map[(bits >> 2) & 0x3F]\n result += map[(bits << 4) & 0x3F]\n result += map[64]\n result += map[64]\n }\n\n return result\n}\n\nfunction isBinary (obj) {\n return Object.prototype.toString.call(obj) === '[object Uint8Array]'\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:binary', {\n kind: 'scalar',\n resolve: resolveYamlBinary,\n construct: constructYamlBinary,\n predicate: isBinary,\n represent: representYamlBinary\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\nconst _toString = Object.prototype.toString\n\nfunction resolveYamlOmap (data) {\n if (data === null) return true\n\n const objectKeys = {}\n const object = data\n\n for (let index = 0, length = object.length; index < length; index += 1) {\n const pair = object[index]\n let pairHasKey = false\n\n if (_toString.call(pair) !== '[object Object]') return false\n\n let pairKey\n for (pairKey in pair) {\n if (_hasOwnProperty.call(pair, pairKey)) {\n if (!pairHasKey) pairHasKey = true\n else return false\n }\n }\n\n if (!pairHasKey) return false\n\n if (_hasOwnProperty.call(objectKeys, pairKey)) return false\n Object.defineProperty(objectKeys, pairKey, { value: true })\n }\n\n return true\n}\n\nfunction constructYamlOmap (data) {\n return data !== null ? data : []\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:omap', {\n kind: 'sequence',\n resolve: resolveYamlOmap,\n construct: constructYamlOmap\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _toString = Object.prototype.toString\n\nfunction resolveYamlPairs (data) {\n if (data === null) return true\n\n const object = data\n\n const result = new Array(object.length)\n\n for (let index = 0, length = object.length; index < length; index += 1) {\n const pair = object[index]\n\n if (_toString.call(pair) !== '[object Object]') return false\n\n const keys = Object.keys(pair)\n\n if (keys.length !== 1) return false\n\n result[index] = [keys[0], pair[keys[0]]]\n }\n\n return true\n}\n\nfunction constructYamlPairs (data) {\n if (data === null) return []\n\n const object = data\n const result = new Array(object.length)\n\n for (let index = 0, length = object.length; index < length; index += 1) {\n const pair = object[index]\n\n const keys = Object.keys(pair)\n\n result[index] = [keys[0], pair[keys[0]]]\n }\n\n return result\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:pairs', {\n kind: 'sequence',\n resolve: resolveYamlPairs,\n construct: constructYamlPairs\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nfunction resolveYamlSet (data) {\n if (data === null) return true\n\n const object = data\n\n for (const key in object) {\n if (_hasOwnProperty.call(object, key)) {\n if (object[key] !== null) return false\n }\n }\n\n return true\n}\n\nfunction constructYamlSet (data) {\n return data !== null ? data : {}\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:set', {\n kind: 'mapping',\n resolve: resolveYamlSet,\n construct: constructYamlSet\n})\n","// JS-YAML's default schema for `safeLoad` function.\n// It is not described in the YAML specification.\n//\n// This schema is based on standard YAML's Core schema and includes most of\n// extra types described at YAML tag repository. (http://yaml.org/type/)\n\n'use strict'\n\nmodule.exports = require('./core').extend({\n implicit: [\n require('../type/timestamp'),\n require('../type/merge')\n ],\n explicit: [\n require('../type/binary'),\n require('../type/omap'),\n require('../type/pairs'),\n require('../type/set')\n ]\n})\n","'use strict'\n\nconst common = require('./common')\nconst YAMLException = require('./exception')\nconst makeSnippet = require('./snippet')\nconst DEFAULT_SCHEMA = require('./schema/default')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nconst CONTEXT_FLOW_IN = 1\nconst CONTEXT_FLOW_OUT = 2\nconst CONTEXT_BLOCK_IN = 3\nconst CONTEXT_BLOCK_OUT = 4\n\nconst CHOMPING_CLIP = 1\nconst CHOMPING_STRIP = 2\nconst CHOMPING_KEEP = 3\n\n// eslint-disable-next-line no-control-regex\nconst PATTERN_NON_PRINTABLE = /[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x84\\x86-\\x9F\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/\nconst PATTERN_NON_ASCII_LINE_BREAKS = /[\\x85\\u2028\\u2029]/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_FLOW_INDICATORS = /[,\\[\\]{}]/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_TAG_URI = /^(?:!|[^,\\[\\]{}])(?:%[0-9a-f]{2}|[0-9a-z\\-#;/?:@&=+$,_.!~*'()\\[\\]])*$/i\n\nfunction _class (obj) { return Object.prototype.toString.call(obj) }\n\nfunction isEol (c) {\n return (c === 0x0A/* LF */) || (c === 0x0D/* CR */)\n}\n\nfunction isWhiteSpace (c) {\n return (c === 0x09/* Tab */) || (c === 0x20/* Space */)\n}\n\nfunction isWsOrEol (c) {\n return (c === 0x09/* Tab */) ||\n (c === 0x20/* Space */) ||\n (c === 0x0A/* LF */) ||\n (c === 0x0D/* CR */)\n}\n\nfunction isFlowIndicator (c) {\n return c === 0x2C/* , */ ||\n c === 0x5B/* [ */ ||\n c === 0x5D/* ] */ ||\n c === 0x7B/* { */ ||\n c === 0x7D/* } */\n}\n\nfunction fromHexCode (c) {\n if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {\n return c - 0x30\n }\n\n const lc = c | 0x20\n\n if ((lc >= 0x61/* a */) && (lc <= 0x66/* f */)) {\n return lc - 0x61 + 10\n }\n\n return -1\n}\n\nfunction escapedHexLen (c) {\n if (c === 0x78/* x */) { return 2 }\n if (c === 0x75/* u */) { return 4 }\n if (c === 0x55/* U */) { return 8 }\n return 0\n}\n\nfunction fromDecimalCode (c) {\n if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {\n return c - 0x30\n }\n\n return -1\n}\n\nfunction simpleEscapeSequence (c) {\n switch (c) {\n case 0x30/* 0 */: return '\\x00'\n case 0x61/* a */: return '\\x07'\n case 0x62/* b */: return '\\x08'\n case 0x74/* t */: return '\\x09'\n case 0x09/* Tab */: return '\\x09'\n case 0x6E/* n */: return '\\x0A'\n case 0x76/* v */: return '\\x0B'\n case 0x66/* f */: return '\\x0C'\n case 0x72/* r */: return '\\x0D'\n case 0x65/* e */: return '\\x1B'\n case 0x20/* Space */: return ' '\n case 0x22/* \" */: return '\\x22'\n case 0x2F/* / */: return '/'\n case 0x5C/* \\ */: return '\\x5C'\n case 0x4E/* N */: return '\\x85'\n case 0x5F/* _ */: return '\\xA0'\n case 0x4C/* L */: return '\\u2028'\n case 0x50/* P */: return '\\u2029'\n default: return ''\n }\n}\n\nfunction charFromCodepoint (c) {\n if (c <= 0xFFFF) {\n return String.fromCharCode(c)\n }\n // Encode UTF-16 surrogate pair\n // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF\n return String.fromCharCode(\n ((c - 0x010000) >> 10) + 0xD800,\n ((c - 0x010000) & 0x03FF) + 0xDC00\n )\n}\n\n// set a property of a literal object, while protecting against prototype pollution,\n// see https://github.com/nodeca/js-yaml/issues/164 for more details\nfunction setProperty (object, key, value) {\n // used for this specific key only because Object.defineProperty is slow\n if (key === '__proto__') {\n Object.defineProperty(object, key, {\n configurable: true,\n enumerable: true,\n writable: true,\n value: value\n })\n } else {\n object[key] = value\n }\n}\n\nconst simpleEscapeCheck = new Array(256) // integer, for fast access\nconst simpleEscapeMap = new Array(256)\nfor (let i = 0; i < 256; i++) {\n simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0\n simpleEscapeMap[i] = simpleEscapeSequence(i)\n}\n\nfunction State (input, options) {\n this.input = input\n\n this.filename = options['filename'] || null\n this.schema = options['schema'] || DEFAULT_SCHEMA\n this.onWarning = options['onWarning'] || null\n // (Hidden) Remove? makes the loader to expect YAML 1.1 documents\n // if such documents have no explicit %YAML directive\n this.legacy = options['legacy'] || false\n\n this.json = options['json'] || false\n this.listener = options['listener'] || null\n this.maxDepth = typeof options['maxDepth'] === 'number' ? options['maxDepth'] : 100\n this.maxTotalMergeKeys = typeof options['maxTotalMergeKeys'] === 'number' ? options['maxTotalMergeKeys'] : 10000\n\n this.implicitTypes = this.schema.compiledImplicit\n this.typeMap = this.schema.compiledTypeMap\n\n this.length = input.length\n this.position = 0\n this.line = 0\n this.lineStart = 0\n this.lineIndent = 0\n this.depth = 0\n this.totalMergeKeys = 0\n\n // position of first leading tab in the current line,\n // used to make sure there are no tabs in the indentation\n this.firstTabInLine = -1\n\n this.documents = []\n this.anchorMapTransactions = []\n\n /*\n this.version;\n this.checkLineBreaks;\n this.tagMap;\n this.anchorMap;\n this.tag;\n this.anchor;\n this.kind;\n this.result; */\n}\n\nfunction generateError (state, message) {\n const mark = {\n name: state.filename,\n buffer: state.input.slice(0, -1), // omit trailing \\0\n position: state.position,\n line: state.line,\n column: state.position - state.lineStart\n }\n\n mark.snippet = makeSnippet(mark)\n\n return new YAMLException(message, mark)\n}\n\nfunction throwError (state, message) {\n throw generateError(state, message)\n}\n\nfunction throwWarning (state, message) {\n if (state.onWarning) {\n state.onWarning.call(null, generateError(state, message))\n }\n}\n\nfunction storeAnchor (state, name, value) {\n const transactions = state.anchorMapTransactions\n\n if (transactions.length !== 0) {\n const transaction = transactions[transactions.length - 1]\n\n if (!_hasOwnProperty.call(transaction, name)) {\n transaction[name] = {\n existed: _hasOwnProperty.call(state.anchorMap, name),\n value: state.anchorMap[name]\n }\n }\n }\n\n state.anchorMap[name] = value\n}\n\nfunction beginAnchorTransaction (state) {\n state.anchorMapTransactions.push(Object.create(null))\n}\n\nfunction commitAnchorTransaction (state) {\n const transaction = state.anchorMapTransactions.pop()\n const transactions = state.anchorMapTransactions\n\n if (transactions.length === 0) return\n\n const parent = transactions[transactions.length - 1]\n const names = Object.keys(transaction)\n\n for (let index = 0, length = names.length; index < length; index += 1) {\n const name = names[index]\n\n if (!_hasOwnProperty.call(parent, name)) {\n parent[name] = transaction[name]\n }\n }\n}\n\nfunction rollbackAnchorTransaction (state) {\n const transaction = state.anchorMapTransactions.pop()\n const names = Object.keys(transaction)\n\n for (let index = names.length - 1; index >= 0; index -= 1) {\n const entry = transaction[names[index]]\n\n if (entry.existed) {\n state.anchorMap[names[index]] = entry.value\n } else {\n delete state.anchorMap[names[index]]\n }\n }\n}\n\nfunction snapshotState (state) {\n return {\n position: state.position,\n line: state.line,\n lineStart: state.lineStart,\n lineIndent: state.lineIndent,\n firstTabInLine: state.firstTabInLine,\n tag: state.tag,\n anchor: state.anchor,\n kind: state.kind,\n result: state.result\n }\n}\n\nfunction restoreState (state, snapshot) {\n state.position = snapshot.position\n state.line = snapshot.line\n state.lineStart = snapshot.lineStart\n state.lineIndent = snapshot.lineIndent\n state.firstTabInLine = snapshot.firstTabInLine\n state.tag = snapshot.tag\n state.anchor = snapshot.anchor\n state.kind = snapshot.kind\n state.result = snapshot.result\n}\n\nconst directiveHandlers = {\n\n YAML: function handleYamlDirective (state, name, args) {\n if (state.version !== null) {\n throwError(state, 'duplication of %YAML directive')\n }\n\n if (args.length !== 1) {\n throwError(state, 'YAML directive accepts exactly one argument')\n }\n\n const match = /^([0-9]+)\\.([0-9]+)$/.exec(args[0])\n\n if (match === null) {\n throwError(state, 'ill-formed argument of the YAML directive')\n }\n\n const major = parseInt(match[1], 10)\n const minor = parseInt(match[2], 10)\n\n if (major !== 1) {\n throwError(state, 'unacceptable YAML version of the document')\n }\n\n state.version = args[0]\n state.checkLineBreaks = (minor < 2)\n\n if (minor !== 1 && minor !== 2) {\n throwWarning(state, 'unsupported YAML version of the document')\n }\n },\n\n TAG: function handleTagDirective (state, name, args) {\n let prefix\n\n if (args.length !== 2) {\n throwError(state, 'TAG directive accepts exactly two arguments')\n }\n\n const handle = args[0]\n prefix = args[1]\n\n if (!PATTERN_TAG_HANDLE.test(handle)) {\n throwError(state, 'ill-formed tag handle (first argument) of the TAG directive')\n }\n\n if (_hasOwnProperty.call(state.tagMap, handle)) {\n throwError(state, 'there is a previously declared suffix for \"' + handle + '\" tag handle')\n }\n\n if (!PATTERN_TAG_URI.test(prefix)) {\n throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive')\n }\n\n try {\n prefix = decodeURIComponent(prefix)\n } catch (err) {\n throwError(state, 'tag prefix is malformed: ' + prefix)\n }\n\n state.tagMap[handle] = prefix\n }\n}\n\nfunction captureSegment (state, start, end, checkJson) {\n if (start < end) {\n const _result = state.input.slice(start, end)\n\n if (checkJson) {\n for (let _position = 0, _length = _result.length; _position < _length; _position += 1) {\n const _character = _result.charCodeAt(_position)\n if (!(_character === 0x09 ||\n (_character >= 0x20 && _character <= 0x10FFFF))) {\n throwError(state, 'expected valid JSON character')\n }\n }\n } else if (PATTERN_NON_PRINTABLE.test(_result)) {\n throwError(state, 'the stream contains non-printable characters')\n }\n\n state.result += _result\n }\n}\n\nfunction chargeMergeWork (state) {\n state.totalMergeKeys++\n\n if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) {\n throwError(state, 'merge keys exceeded maxTotalMergeKeys (' + state.maxTotalMergeKeys + ')')\n }\n}\n\nfunction mergeMappings (state, destination, source, overridableKeys) {\n if (!common.isObject(source)) {\n throwError(state, 'cannot merge mappings; the provided source object is unacceptable')\n }\n\n // Count the source mapping itself to bound sequences of empty mappings.\n chargeMergeWork(state)\n\n const sourceKeys = Object.keys(source)\n\n for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {\n const key = sourceKeys[index]\n\n chargeMergeWork(state)\n\n if (!_hasOwnProperty.call(destination, key)) {\n setProperty(destination, key, source[key])\n overridableKeys[key] = true\n }\n }\n}\n\nfunction storeMappingPair (state, _result, overridableKeys, keyTag, keyNode, valueNode,\n startLine, startLineStart, startPos) {\n // The output is a plain object here, so keys can only be strings.\n // We need to convert keyNode to a string, but doing so can hang the process\n // (deeply nested arrays that explode exponentially using aliases).\n if (Array.isArray(keyNode)) {\n keyNode = Array.prototype.slice.call(keyNode)\n\n for (let index = 0, quantity = keyNode.length; index < quantity; index += 1) {\n if (Array.isArray(keyNode[index])) {\n throwError(state, 'nested arrays are not supported inside keys')\n }\n\n if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') {\n keyNode[index] = '[object Object]'\n }\n }\n }\n\n // Avoid code execution in load() via toString property\n // (still use its own toString for arrays, timestamps,\n // and whatever user schema extensions happen to have @@toStringTag)\n if (typeof keyNode === 'object' && _class(keyNode) === '[object Object]') {\n keyNode = '[object Object]'\n }\n\n keyNode = String(keyNode)\n\n if (_result === null) {\n _result = {}\n }\n\n if (keyTag === 'tag:yaml.org,2002:merge') {\n if (Array.isArray(valueNode)) {\n if (valueNode.length > 100) {\n throwError(state, 'abnormal merge sequence size')\n }\n\n for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) {\n mergeMappings(state, _result, valueNode[index], overridableKeys)\n }\n } else {\n mergeMappings(state, _result, valueNode, overridableKeys)\n }\n } else {\n if (!state.json &&\n !_hasOwnProperty.call(overridableKeys, keyNode) &&\n _hasOwnProperty.call(_result, keyNode)) {\n state.line = startLine || state.line\n state.lineStart = startLineStart || state.lineStart\n state.position = startPos || state.position\n throwError(state, 'duplicated mapping key')\n }\n\n setProperty(_result, keyNode, valueNode)\n delete overridableKeys[keyNode]\n }\n\n return _result\n}\n\nfunction readLineBreak (state) {\n const ch = state.input.charCodeAt(state.position)\n\n if (ch === 0x0A/* LF */) {\n state.position++\n } else if (ch === 0x0D/* CR */) {\n state.position++\n if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {\n state.position++\n }\n } else {\n throwError(state, 'a line break is expected')\n }\n\n state.line += 1\n state.lineStart = state.position\n state.firstTabInLine = -1\n}\n\nfunction skipSeparationSpace (state, allowComments, checkIndent) {\n let lineBreaks = 0\n let ch = state.input.charCodeAt(state.position)\n\n while (ch !== 0) {\n while (isWhiteSpace(ch)) {\n if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) {\n state.firstTabInLine = state.position\n }\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (allowComments && ch === 0x23/* # */) {\n do {\n ch = state.input.charCodeAt(++state.position)\n } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0)\n }\n\n if (isEol(ch)) {\n readLineBreak(state)\n\n ch = state.input.charCodeAt(state.position)\n lineBreaks++\n state.lineIndent = 0\n\n while (ch === 0x20/* Space */) {\n state.lineIndent++\n ch = state.input.charCodeAt(++state.position)\n }\n } else {\n break\n }\n }\n\n if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {\n throwWarning(state, 'deficient indentation')\n }\n\n return lineBreaks\n}\n\nfunction testDocumentSeparator (state) {\n let _position = state.position\n let ch = state.input.charCodeAt(_position)\n\n // Condition state.position === state.lineStart is tested\n // in parent on each call, for efficiency. No needs to test here again.\n if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&\n ch === state.input.charCodeAt(_position + 1) &&\n ch === state.input.charCodeAt(_position + 2)) {\n _position += 3\n\n ch = state.input.charCodeAt(_position)\n\n if (ch === 0 || isWsOrEol(ch)) {\n return true\n }\n }\n\n return false\n}\n\nfunction writeFoldedLines (state, count) {\n if (count === 1) {\n state.result += ' '\n } else if (count > 1) {\n state.result += common.repeat('\\n', count - 1)\n }\n}\n\nfunction readPlainScalar (state, nodeIndent, withinFlowCollection) {\n let captureStart\n let captureEnd\n let hasPendingContent\n let _line\n let _lineStart\n let _lineIndent\n const _kind = state.kind\n const _result = state.result\n\n let ch = state.input.charCodeAt(state.position)\n\n if (isWsOrEol(ch) ||\n isFlowIndicator(ch) ||\n ch === 0x23/* # */ ||\n ch === 0x26/* & */ ||\n ch === 0x2A/* * */ ||\n ch === 0x21/* ! */ ||\n ch === 0x7C/* | */ ||\n ch === 0x3E/* > */ ||\n ch === 0x27/* ' */ ||\n ch === 0x22/* \" */ ||\n ch === 0x25/* % */ ||\n ch === 0x40/* @ */ ||\n ch === 0x60/* ` */) {\n return false\n }\n\n if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {\n const following = state.input.charCodeAt(state.position + 1)\n\n if (isWsOrEol(following) ||\n (withinFlowCollection && isFlowIndicator(following))) {\n return false\n }\n }\n\n state.kind = 'scalar'\n state.result = ''\n captureStart = captureEnd = state.position\n hasPendingContent = false\n\n while (ch !== 0) {\n if (ch === 0x3A/* : */) {\n const following = state.input.charCodeAt(state.position + 1)\n\n if (isWsOrEol(following) ||\n (withinFlowCollection && isFlowIndicator(following))) {\n break\n }\n } else if (ch === 0x23/* # */) {\n const preceding = state.input.charCodeAt(state.position - 1)\n\n if (isWsOrEol(preceding)) {\n break\n }\n } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||\n (withinFlowCollection && isFlowIndicator(ch))) {\n break\n } else if (isEol(ch)) {\n _line = state.line\n _lineStart = state.lineStart\n _lineIndent = state.lineIndent\n skipSeparationSpace(state, false, -1)\n\n if (state.lineIndent >= nodeIndent) {\n hasPendingContent = true\n ch = state.input.charCodeAt(state.position)\n continue\n } else {\n state.position = captureEnd\n state.line = _line\n state.lineStart = _lineStart\n state.lineIndent = _lineIndent\n break\n }\n }\n\n if (hasPendingContent) {\n captureSegment(state, captureStart, captureEnd, false)\n writeFoldedLines(state, state.line - _line)\n captureStart = captureEnd = state.position\n hasPendingContent = false\n }\n\n if (!isWhiteSpace(ch)) {\n captureEnd = state.position + 1\n }\n\n ch = state.input.charCodeAt(++state.position)\n }\n\n captureSegment(state, captureStart, captureEnd, false)\n\n if (state.result) {\n return true\n }\n\n state.kind = _kind\n state.result = _result\n return false\n}\n\nfunction readSingleQuotedScalar (state, nodeIndent) {\n let captureStart\n let captureEnd\n\n let ch = state.input.charCodeAt(state.position)\n\n if (ch !== 0x27/* ' */) {\n return false\n }\n\n state.kind = 'scalar'\n state.result = ''\n state.position++\n captureStart = captureEnd = state.position\n\n while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n if (ch === 0x27/* ' */) {\n captureSegment(state, captureStart, state.position, true)\n ch = state.input.charCodeAt(++state.position)\n\n if (ch === 0x27/* ' */) {\n captureStart = state.position\n state.position++\n captureEnd = state.position\n } else {\n return true\n }\n } else if (isEol(ch)) {\n captureSegment(state, captureStart, captureEnd, true)\n writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))\n captureStart = captureEnd = state.position\n } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n throwError(state, 'unexpected end of the document within a single quoted scalar')\n } else {\n state.position++\n if (!isWhiteSpace(ch)) {\n captureEnd = state.position\n }\n }\n }\n\n throwError(state, 'unexpected end of the stream within a single quoted scalar')\n}\n\nfunction readDoubleQuotedScalar (state, nodeIndent) {\n let captureStart\n let captureEnd\n let tmp\n\n let ch = state.input.charCodeAt(state.position)\n\n if (ch !== 0x22/* \" */) {\n return false\n }\n\n state.kind = 'scalar'\n state.result = ''\n state.position++\n captureStart = captureEnd = state.position\n\n while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n if (ch === 0x22/* \" */) {\n captureSegment(state, captureStart, state.position, true)\n state.position++\n return true\n } else if (ch === 0x5C/* \\ */) {\n captureSegment(state, captureStart, state.position, true)\n ch = state.input.charCodeAt(++state.position)\n\n if (isEol(ch)) {\n skipSeparationSpace(state, false, nodeIndent)\n\n // TODO: rework to inline fn with no type cast?\n } else if (ch < 256 && simpleEscapeCheck[ch]) {\n state.result += simpleEscapeMap[ch]\n state.position++\n } else if ((tmp = escapedHexLen(ch)) > 0) {\n let hexLength = tmp\n let hexResult = 0\n\n for (; hexLength > 0; hexLength--) {\n ch = state.input.charCodeAt(++state.position)\n\n if ((tmp = fromHexCode(ch)) >= 0) {\n hexResult = (hexResult << 4) + tmp\n } else {\n throwError(state, 'expected hexadecimal character')\n }\n }\n\n state.result += charFromCodepoint(hexResult)\n\n state.position++\n } else {\n throwError(state, 'unknown escape sequence')\n }\n\n captureStart = captureEnd = state.position\n } else if (isEol(ch)) {\n captureSegment(state, captureStart, captureEnd, true)\n writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))\n captureStart = captureEnd = state.position\n } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n throwError(state, 'unexpected end of the document within a double quoted scalar')\n } else {\n state.position++\n if (!isWhiteSpace(ch)) {\n captureEnd = state.position\n }\n }\n }\n\n throwError(state, 'unexpected end of the stream within a double quoted scalar')\n}\n\nfunction readFlowCollection (state, nodeIndent) {\n let readNext = true\n let _line\n let _lineStart\n let _pos\n const _tag = state.tag\n let _result\n const _anchor = state.anchor\n let terminator\n let isPair\n let isExplicitPair\n let isMapping\n const overridableKeys = Object.create(null)\n let keyNode\n let keyTag\n let valueNode\n\n let ch = state.input.charCodeAt(state.position)\n\n if (ch === 0x5B/* [ */) {\n terminator = 0x5D/* ] */\n isMapping = false\n _result = []\n } else if (ch === 0x7B/* { */) {\n terminator = 0x7D/* } */\n isMapping = true\n _result = {}\n } else {\n return false\n }\n\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, _result)\n }\n\n ch = state.input.charCodeAt(++state.position)\n\n while (ch !== 0) {\n skipSeparationSpace(state, true, nodeIndent)\n\n ch = state.input.charCodeAt(state.position)\n\n if (ch === terminator) {\n state.position++\n state.tag = _tag\n state.anchor = _anchor\n state.kind = isMapping ? 'mapping' : 'sequence'\n state.result = _result\n return true\n } else if (!readNext) {\n throwError(state, 'missed comma between flow collection entries')\n } else if (ch === 0x2C/* , */) {\n // \"flow collection entries can never be completely empty\", as per YAML 1.2, section 7.4\n throwError(state, \"expected the node content, but found ','\")\n }\n\n keyTag = keyNode = valueNode = null\n isPair = isExplicitPair = false\n\n if (ch === 0x3F/* ? */) {\n const following = state.input.charCodeAt(state.position + 1)\n\n if (isWsOrEol(following)) {\n isPair = isExplicitPair = true\n state.position++\n skipSeparationSpace(state, true, nodeIndent)\n }\n }\n\n _line = state.line // Save the current line.\n _lineStart = state.lineStart\n _pos = state.position\n composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)\n keyTag = state.tag\n keyNode = state.result\n skipSeparationSpace(state, true, nodeIndent)\n\n ch = state.input.charCodeAt(state.position)\n\n if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {\n isPair = true\n ch = state.input.charCodeAt(++state.position)\n skipSeparationSpace(state, true, nodeIndent)\n composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)\n valueNode = state.result\n }\n\n if (isMapping) {\n storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos)\n } else if (isPair) {\n _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos))\n } else {\n _result.push(keyNode)\n }\n\n skipSeparationSpace(state, true, nodeIndent)\n\n ch = state.input.charCodeAt(state.position)\n\n if (ch === 0x2C/* , */) {\n readNext = true\n ch = state.input.charCodeAt(++state.position)\n } else {\n readNext = false\n }\n }\n\n throwError(state, 'unexpected end of the stream within a flow collection')\n}\n\nfunction readBlockScalar (state, nodeIndent) {\n let folding\n let chomping = CHOMPING_CLIP\n let didReadContent = false\n let detectedIndent = false\n let textIndent = nodeIndent\n let emptyLines = 0\n let atMoreIndented = false\n let tmp\n\n let ch = state.input.charCodeAt(state.position)\n\n if (ch === 0x7C/* | */) {\n folding = false\n } else if (ch === 0x3E/* > */) {\n folding = true\n } else {\n return false\n }\n\n state.kind = 'scalar'\n state.result = ''\n\n while (ch !== 0) {\n ch = state.input.charCodeAt(++state.position)\n\n if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {\n if (CHOMPING_CLIP === chomping) {\n chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP\n } else {\n throwError(state, 'repeat of a chomping mode identifier')\n }\n } else if ((tmp = fromDecimalCode(ch)) >= 0) {\n if (tmp === 0) {\n throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one')\n } else if (!detectedIndent) {\n textIndent = nodeIndent + tmp - 1\n detectedIndent = true\n } else {\n throwError(state, 'repeat of an indentation width identifier')\n }\n } else {\n break\n }\n }\n\n if (isWhiteSpace(ch)) {\n do { ch = state.input.charCodeAt(++state.position) }\n while (isWhiteSpace(ch))\n\n if (ch === 0x23/* # */) {\n do { ch = state.input.charCodeAt(++state.position) }\n while (!isEol(ch) && (ch !== 0))\n }\n }\n\n while (ch !== 0) {\n readLineBreak(state)\n state.lineIndent = 0\n\n ch = state.input.charCodeAt(state.position)\n\n // eslint-disable-next-line no-unmodified-loop-condition\n while ((!detectedIndent || state.lineIndent < textIndent) &&\n (ch === 0x20/* Space */)) {\n state.lineIndent++\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (!detectedIndent && state.lineIndent > textIndent) {\n textIndent = state.lineIndent\n }\n\n if (isEol(ch)) {\n emptyLines++\n continue\n }\n\n if (!detectedIndent && textIndent === 0) {\n throwError(state, 'missing indentation for block scalar')\n }\n\n // End of the scalar.\n if (state.lineIndent < textIndent) {\n // Perform the chomping.\n if (chomping === CHOMPING_KEEP) {\n state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n } else if (chomping === CHOMPING_CLIP) {\n if (didReadContent) { // i.e. only if the scalar is not empty.\n state.result += '\\n'\n }\n }\n\n // Break this `while` cycle and go to the funciton's epilogue.\n break\n }\n\n // Folded style: use fancy rules to handle line breaks.\n if (folding) {\n // Lines starting with white space characters (more-indented lines) are not folded.\n if (isWhiteSpace(ch)) {\n atMoreIndented = true\n // except for the first content line (cf. Example 8.1)\n state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n\n // End of more-indented block.\n } else if (atMoreIndented) {\n atMoreIndented = false\n state.result += common.repeat('\\n', emptyLines + 1)\n\n // Just one line break - perceive as the same line.\n } else if (emptyLines === 0) {\n if (didReadContent) { // i.e. only if we have already read some scalar content.\n state.result += ' '\n }\n\n // Several line breaks - perceive as different lines.\n } else {\n state.result += common.repeat('\\n', emptyLines)\n }\n\n // Literal style: just add exact number of line breaks between content lines.\n } else {\n // Keep all line breaks except the header line break.\n state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n }\n\n didReadContent = true\n detectedIndent = true\n emptyLines = 0\n const captureStart = state.position\n\n while (!isEol(ch) && (ch !== 0)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n captureSegment(state, captureStart, state.position, false)\n }\n\n return true\n}\n\nfunction readBlockSequence (state, nodeIndent) {\n const _tag = state.tag\n const _anchor = state.anchor\n const _result = []\n let detected = false\n\n // there is a leading tab before this token, so it can't be a block sequence/mapping;\n // it can still be flow sequence/mapping or a scalar\n if (state.firstTabInLine !== -1) return false\n\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, _result)\n }\n\n let ch = state.input.charCodeAt(state.position)\n\n while (ch !== 0) {\n if (state.firstTabInLine !== -1) {\n state.position = state.firstTabInLine\n throwError(state, 'tab characters must not be used in indentation')\n }\n\n if (ch !== 0x2D/* - */) {\n break\n }\n\n const following = state.input.charCodeAt(state.position + 1)\n\n if (!isWsOrEol(following)) {\n break\n }\n\n detected = true\n state.position++\n\n if (skipSeparationSpace(state, true, -1)) {\n if (state.lineIndent <= nodeIndent) {\n _result.push(null)\n ch = state.input.charCodeAt(state.position)\n continue\n }\n }\n\n const _line = state.line\n composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true)\n _result.push(state.result)\n skipSeparationSpace(state, true, -1)\n\n ch = state.input.charCodeAt(state.position)\n\n if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {\n throwError(state, 'bad indentation of a sequence entry')\n } else if (state.lineIndent < nodeIndent) {\n break\n }\n }\n\n if (detected) {\n state.tag = _tag\n state.anchor = _anchor\n state.kind = 'sequence'\n state.result = _result\n return true\n }\n return false\n}\n\nfunction readBlockMapping (state, nodeIndent, flowIndent) {\n let allowCompact\n let _keyLine\n let _keyLineStart\n let _keyPos\n const _tag = state.tag\n const _anchor = state.anchor\n const _result = {}\n const overridableKeys = Object.create(null)\n let keyTag = null\n let keyNode = null\n let valueNode = null\n let atExplicitKey = false\n let detected = false\n\n // there is a leading tab before this token, so it can't be a block sequence/mapping;\n // it can still be flow sequence/mapping or a scalar\n if (state.firstTabInLine !== -1) return false\n\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, _result)\n }\n\n let ch = state.input.charCodeAt(state.position)\n\n while (ch !== 0) {\n if (!atExplicitKey && state.firstTabInLine !== -1) {\n state.position = state.firstTabInLine\n throwError(state, 'tab characters must not be used in indentation')\n }\n\n const following = state.input.charCodeAt(state.position + 1)\n const _line = state.line // Save the current line.\n\n //\n // Explicit notation case. There are two separate blocks:\n // first for the key (denoted by \"?\") and second for the value (denoted by \":\")\n //\n if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && isWsOrEol(following)) {\n if (ch === 0x3F/* ? */) {\n if (atExplicitKey) {\n storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n keyTag = keyNode = valueNode = null\n }\n\n detected = true\n atExplicitKey = true\n allowCompact = true\n } else if (atExplicitKey) {\n // i.e. 0x3A/* : */ === character after the explicit key.\n atExplicitKey = false\n allowCompact = true\n } else {\n throwError(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line')\n }\n\n state.position += 1\n ch = following\n\n //\n // Implicit notation case. Flow-style node as the key first, then \":\", and the value.\n //\n } else {\n _keyLine = state.line\n _keyLineStart = state.lineStart\n _keyPos = state.position\n\n if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {\n // Neither implicit nor explicit notation.\n // Reading is done. Go to the epilogue.\n break\n }\n\n if (state.line === _line) {\n ch = state.input.charCodeAt(state.position)\n\n while (isWhiteSpace(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (ch === 0x3A/* : */) {\n ch = state.input.charCodeAt(++state.position)\n\n if (!isWsOrEol(ch)) {\n throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping')\n }\n\n if (atExplicitKey) {\n storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n keyTag = keyNode = valueNode = null\n }\n\n detected = true\n atExplicitKey = false\n allowCompact = false\n keyTag = state.tag\n keyNode = state.result\n } else if (detected) {\n throwError(state, 'can not read an implicit mapping pair; a colon is missed')\n } else {\n state.tag = _tag\n state.anchor = _anchor\n return true // Keep the result of `composeNode`.\n }\n } else if (detected) {\n throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key')\n } else {\n state.tag = _tag\n state.anchor = _anchor\n return true // Keep the result of `composeNode`.\n }\n }\n\n //\n // Common reading code for both explicit and implicit notations.\n //\n if (state.line === _line || state.lineIndent > nodeIndent) {\n if (atExplicitKey) {\n _keyLine = state.line\n _keyLineStart = state.lineStart\n _keyPos = state.position\n }\n\n if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {\n if (atExplicitKey) {\n keyNode = state.result\n } else {\n valueNode = state.result\n }\n }\n\n if (!atExplicitKey) {\n storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos)\n keyTag = keyNode = valueNode = null\n }\n\n skipSeparationSpace(state, true, -1)\n ch = state.input.charCodeAt(state.position)\n }\n\n if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {\n throwError(state, 'bad indentation of a mapping entry')\n } else if (state.lineIndent < nodeIndent) {\n break\n }\n }\n\n //\n // Epilogue.\n //\n\n // Special case: last mapping's node contains only the key in explicit notation.\n if (atExplicitKey) {\n storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n }\n\n // Expose the resulting mapping.\n if (detected) {\n state.tag = _tag\n state.anchor = _anchor\n state.kind = 'mapping'\n state.result = _result\n }\n\n return detected\n}\n\nfunction readTagProperty (state) {\n let isVerbatim = false\n let isNamed = false\n let tagHandle\n let tagName\n\n let ch = state.input.charCodeAt(state.position)\n\n if (ch !== 0x21/* ! */) return false\n\n if (state.tag !== null) {\n throwError(state, 'duplication of a tag property')\n }\n\n ch = state.input.charCodeAt(++state.position)\n\n if (ch === 0x3C/* < */) {\n isVerbatim = true\n ch = state.input.charCodeAt(++state.position)\n } else if (ch === 0x21/* ! */) {\n isNamed = true\n tagHandle = '!!'\n ch = state.input.charCodeAt(++state.position)\n } else {\n tagHandle = '!'\n }\n\n let _position = state.position\n\n if (isVerbatim) {\n do { ch = state.input.charCodeAt(++state.position) }\n while (ch !== 0 && ch !== 0x3E/* > */)\n\n if (state.position < state.length) {\n tagName = state.input.slice(_position, state.position)\n ch = state.input.charCodeAt(++state.position)\n } else {\n throwError(state, 'unexpected end of the stream within a verbatim tag')\n }\n } else {\n while (ch !== 0 && !isWsOrEol(ch)) {\n if (ch === 0x21/* ! */) {\n if (!isNamed) {\n tagHandle = state.input.slice(_position - 1, state.position + 1)\n\n if (!PATTERN_TAG_HANDLE.test(tagHandle)) {\n throwError(state, 'named tag handle cannot contain such characters')\n }\n\n isNamed = true\n _position = state.position + 1\n } else {\n throwError(state, 'tag suffix cannot contain exclamation marks')\n }\n }\n\n ch = state.input.charCodeAt(++state.position)\n }\n\n tagName = state.input.slice(_position, state.position)\n\n if (PATTERN_FLOW_INDICATORS.test(tagName)) {\n throwError(state, 'tag suffix cannot contain flow indicator characters')\n }\n }\n\n if (tagName && !PATTERN_TAG_URI.test(tagName)) {\n throwError(state, 'tag name cannot contain such characters: ' + tagName)\n }\n\n try {\n tagName = decodeURIComponent(tagName)\n } catch (err) {\n throwError(state, 'tag name is malformed: ' + tagName)\n }\n\n if (isVerbatim) {\n state.tag = tagName\n } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {\n state.tag = state.tagMap[tagHandle] + tagName\n } else if (tagHandle === '!') {\n state.tag = '!' + tagName\n } else if (tagHandle === '!!') {\n state.tag = 'tag:yaml.org,2002:' + tagName\n } else {\n throwError(state, 'undeclared tag handle \"' + tagHandle + '\"')\n }\n\n return true\n}\n\nfunction readAnchorProperty (state) {\n let ch = state.input.charCodeAt(state.position)\n\n if (ch !== 0x26/* & */) return false\n\n if (state.anchor !== null) {\n throwError(state, 'duplication of an anchor property')\n }\n\n ch = state.input.charCodeAt(++state.position)\n const _position = state.position\n\n while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (state.position === _position) {\n throwError(state, 'name of an anchor node must contain at least one character')\n }\n\n state.anchor = state.input.slice(_position, state.position)\n return true\n}\n\nfunction readAlias (state) {\n let ch = state.input.charCodeAt(state.position)\n\n if (ch !== 0x2A/* * */) return false\n\n ch = state.input.charCodeAt(++state.position)\n const _position = state.position\n\n while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (state.position === _position) {\n throwError(state, 'name of an alias node must contain at least one character')\n }\n\n const alias = state.input.slice(_position, state.position)\n\n if (!_hasOwnProperty.call(state.anchorMap, alias)) {\n throwError(state, 'unidentified alias \"' + alias + '\"')\n }\n\n state.result = state.anchorMap[alias]\n skipSeparationSpace(state, true, -1)\n return true\n}\n\nfunction tryReadBlockMappingFromProperty (state, propertyStart, nodeIndent, flowIndent) {\n const fallbackState = snapshotState(state)\n\n beginAnchorTransaction(state)\n restoreState(state, propertyStart)\n\n // Re-read the leading properties as part of the first implicit key, not as\n // properties of the current node.\n state.tag = null\n state.anchor = null\n state.kind = null\n state.result = null\n\n if (readBlockMapping(state, nodeIndent, flowIndent) && state.kind === 'mapping') {\n commitAnchorTransaction(state)\n return true\n }\n\n rollbackAnchorTransaction(state)\n restoreState(state, fallbackState)\n return false\n}\n\nfunction composeNode (state, parentIndent, nodeContext, allowToSeek, allowCompact) {\n let allowBlockScalars\n let allowBlockCollections\n let indentStatus = 1 // 1: this>parent, 0: this=parent, -1: this<parent\n let atNewLine = false\n let hasContent = false\n let propertyStart = null\n let type\n let flowIndent\n let blockIndent\n\n if (state.depth >= state.maxDepth) {\n throwError(state, 'nesting exceeded maxDepth (' + state.maxDepth + ')')\n }\n\n state.depth += 1\n\n if (state.listener !== null) {\n state.listener('open', state)\n }\n\n state.tag = null\n state.anchor = null\n state.kind = null\n state.result = null\n\n const allowBlockStyles = allowBlockScalars = allowBlockCollections =\n CONTEXT_BLOCK_OUT === nodeContext ||\n CONTEXT_BLOCK_IN === nodeContext\n\n if (allowToSeek) {\n if (skipSeparationSpace(state, true, -1)) {\n atNewLine = true\n\n if (state.lineIndent > parentIndent) {\n indentStatus = 1\n } else if (state.lineIndent === parentIndent) {\n indentStatus = 0\n } else if (state.lineIndent < parentIndent) {\n indentStatus = -1\n }\n }\n }\n\n if (indentStatus === 1) {\n while (true) {\n const ch = state.input.charCodeAt(state.position)\n const propertyState = snapshotState(state)\n\n // A duplicate property token after a line break can be the first key of\n // a nested block mapping, e.g. `!!map\\n !!str key: value`.\n if (atNewLine &&\n ((ch === 0x21/* ! */ && state.tag !== null) ||\n (ch === 0x26/* & */ && state.anchor !== null))) {\n break\n }\n\n if (!readTagProperty(state) && !readAnchorProperty(state)) {\n break\n }\n\n if (propertyStart === null) {\n propertyStart = propertyState\n }\n\n if (skipSeparationSpace(state, true, -1)) {\n atNewLine = true\n allowBlockCollections = allowBlockStyles\n\n if (state.lineIndent > parentIndent) {\n indentStatus = 1\n } else if (state.lineIndent === parentIndent) {\n indentStatus = 0\n } else if (state.lineIndent < parentIndent) {\n indentStatus = -1\n }\n } else {\n allowBlockCollections = false\n }\n }\n }\n\n if (allowBlockCollections) {\n allowBlockCollections = atNewLine || allowCompact\n }\n\n if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {\n if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {\n flowIndent = parentIndent\n } else {\n flowIndent = parentIndent + 1\n }\n\n blockIndent = state.position - state.lineStart\n\n if (indentStatus === 1) {\n if ((allowBlockCollections &&\n (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent))) ||\n readFlowCollection(state, flowIndent)) {\n hasContent = true\n } else {\n const ch = state.input.charCodeAt(state.position)\n\n if (propertyStart !== null && allowBlockStyles && !allowBlockCollections &&\n ch !== 0x7C/* | */ && ch !== 0x3E/* > */ &&\n tryReadBlockMappingFromProperty(\n state,\n propertyStart,\n propertyStart.position - propertyStart.lineStart,\n flowIndent\n )) {\n hasContent = true\n } else if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||\n readSingleQuotedScalar(state, flowIndent) ||\n readDoubleQuotedScalar(state, flowIndent)) {\n hasContent = true\n } else if (readAlias(state)) {\n hasContent = true\n\n if (state.tag !== null || state.anchor !== null) {\n throwError(state, 'alias node should not have any properties')\n }\n } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {\n hasContent = true\n\n if (state.tag === null) {\n state.tag = '?'\n }\n }\n\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, state.result)\n }\n }\n } else if (indentStatus === 0) {\n // Special case: block sequences are allowed to have same indentation level as the parent.\n // http://www.yaml.org/spec/1.2/spec.html#id2799784\n hasContent = allowBlockCollections && readBlockSequence(state, blockIndent)\n }\n }\n\n if (state.tag === null) {\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, state.result)\n }\n } else if (state.tag === '?') {\n // Implicit resolving is not allowed for non-scalar types, and '?'\n // non-specific tag is only automatically assigned to plain scalars.\n //\n // We only need to check kind conformity in case user explicitly assigns '?'\n // tag, for example like this: \"!<?> [0]\"\n //\n if (state.result !== null && state.kind !== 'scalar') {\n throwError(state, 'unacceptable node kind for !<?> tag; it should be \"scalar\", not \"' + state.kind + '\"')\n }\n\n for (let typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {\n type = state.implicitTypes[typeIndex]\n\n if (type.resolve(state.result)) { // `state.result` updated in resolver if matched\n state.result = type.construct(state.result)\n state.tag = type.tag\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, state.result)\n }\n break\n }\n }\n } else if (state.tag !== '!') {\n if (_hasOwnProperty.call(state.typeMap[state.kind || 'fallback'], state.tag)) {\n type = state.typeMap[state.kind || 'fallback'][state.tag]\n } else {\n // looking for multi type\n type = null\n const typeList = state.typeMap.multi[state.kind || 'fallback']\n\n for (let typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) {\n if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) {\n type = typeList[typeIndex]\n break\n }\n }\n }\n\n if (!type) {\n throwError(state, 'unknown tag !<' + state.tag + '>')\n }\n\n if (state.result !== null && type.kind !== state.kind) {\n throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be \"' + type.kind + '\", not \"' + state.kind + '\"')\n }\n\n if (!type.resolve(state.result, state.tag)) { // `state.result` updated in resolver if matched\n throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag')\n } else {\n state.result = type.construct(state.result, state.tag)\n if (state.anchor !== null) {\n storeAnchor(state, state.anchor, state.result)\n }\n }\n }\n\n if (state.listener !== null) {\n state.listener('close', state)\n }\n\n state.depth -= 1\n return state.tag !== null || state.anchor !== null || hasContent\n}\n\nfunction readDocument (state) {\n const documentStart = state.position\n let hasDirectives = false\n let ch\n\n state.version = null\n state.checkLineBreaks = state.legacy\n state.tagMap = Object.create(null)\n state.anchorMap = Object.create(null)\n\n while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n skipSeparationSpace(state, true, -1)\n\n ch = state.input.charCodeAt(state.position)\n\n if (state.lineIndent > 0 || ch !== 0x25/* % */) {\n break\n }\n\n hasDirectives = true\n ch = state.input.charCodeAt(++state.position)\n let _position = state.position\n\n while (ch !== 0 && !isWsOrEol(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n const directiveName = state.input.slice(_position, state.position)\n const directiveArgs = []\n\n if (directiveName.length < 1) {\n throwError(state, 'directive name must not be less than one character in length')\n }\n\n while (ch !== 0) {\n while (isWhiteSpace(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n if (ch === 0x23/* # */) {\n do { ch = state.input.charCodeAt(++state.position) }\n while (ch !== 0 && !isEol(ch))\n break\n }\n\n if (isEol(ch)) break\n\n _position = state.position\n\n while (ch !== 0 && !isWsOrEol(ch)) {\n ch = state.input.charCodeAt(++state.position)\n }\n\n directiveArgs.push(state.input.slice(_position, state.position))\n }\n\n if (ch !== 0) readLineBreak(state)\n\n if (_hasOwnProperty.call(directiveHandlers, directiveName)) {\n directiveHandlers[directiveName](state, directiveName, directiveArgs)\n } else {\n throwWarning(state, 'unknown document directive \"' + directiveName + '\"')\n }\n }\n\n skipSeparationSpace(state, true, -1)\n\n if (state.lineIndent === 0 &&\n state.input.charCodeAt(state.position) === 0x2D/* - */ &&\n state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&\n state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {\n state.position += 3\n skipSeparationSpace(state, true, -1)\n } else if (hasDirectives) {\n throwError(state, 'directives end mark is expected')\n }\n\n composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true)\n skipSeparationSpace(state, true, -1)\n\n if (state.checkLineBreaks &&\n PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {\n throwWarning(state, 'non-ASCII line breaks are interpreted as content')\n }\n\n state.documents.push(state.result)\n\n if (state.position === state.lineStart && testDocumentSeparator(state)) {\n if (state.input.charCodeAt(state.position) === 0x2E/* . */) {\n state.position += 3\n skipSeparationSpace(state, true, -1)\n }\n return\n }\n\n if (state.position < (state.length - 1)) {\n throwError(state, 'end of the stream or a document separator is expected')\n }\n}\n\nfunction loadDocuments (input, options) {\n input = String(input)\n options = options || {}\n\n if (input.length !== 0) {\n // Add tailing `\\n` if not exists\n if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&\n input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {\n input += '\\n'\n }\n\n // Strip BOM\n if (input.charCodeAt(0) === 0xFEFF) {\n input = input.slice(1)\n }\n }\n\n const state = new State(input, options)\n\n const nullpos = input.indexOf('\\0')\n\n if (nullpos !== -1) {\n state.position = nullpos\n throwError(state, 'null byte is not allowed in input')\n }\n\n // Use 0 as string terminator. That significantly simplifies bounds check.\n state.input += '\\0'\n\n while (state.input.charCodeAt(state.position) === 0x20/* Space */) {\n state.lineIndent += 1\n state.position += 1\n }\n\n while (state.position < (state.length - 1)) {\n readDocument(state)\n }\n\n return state.documents\n}\n\nfunction loadAll (input, iterator, options) {\n if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') {\n options = iterator\n iterator = null\n }\n\n const documents = loadDocuments(input, options)\n\n if (typeof iterator !== 'function') {\n return documents\n }\n\n for (let index = 0, length = documents.length; index < length; index += 1) {\n iterator(documents[index])\n }\n}\n\nfunction load (input, options) {\n const documents = loadDocuments(input, options)\n\n if (documents.length === 0) {\n return undefined\n } else if (documents.length === 1) {\n return documents[0]\n }\n throw new YAMLException('expected a single document in the stream, but found more')\n}\n\nmodule.exports.loadAll = loadAll\nmodule.exports.load = load\n","'use strict'\n\nconst common = require('./common')\nconst YAMLException = require('./exception')\nconst DEFAULT_SCHEMA = require('./schema/default')\n\nconst _toString = Object.prototype.toString\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nconst CHAR_BOM = 0xFEFF\nconst CHAR_TAB = 0x09 /* Tab */\nconst CHAR_LINE_FEED = 0x0A /* LF */\nconst CHAR_CARRIAGE_RETURN = 0x0D /* CR */\nconst CHAR_SPACE = 0x20 /* Space */\nconst CHAR_EXCLAMATION = 0x21 /* ! */\nconst CHAR_DOUBLE_QUOTE = 0x22 /* \" */\nconst CHAR_SHARP = 0x23 /* # */\nconst CHAR_PERCENT = 0x25 /* % */\nconst CHAR_AMPERSAND = 0x26 /* & */\nconst CHAR_SINGLE_QUOTE = 0x27 /* ' */\nconst CHAR_ASTERISK = 0x2A /* * */\nconst CHAR_COMMA = 0x2C /* , */\nconst CHAR_MINUS = 0x2D /* - */\nconst CHAR_COLON = 0x3A /* : */\nconst CHAR_EQUALS = 0x3D /* = */\nconst CHAR_GREATER_THAN = 0x3E /* > */\nconst CHAR_QUESTION = 0x3F /* ? */\nconst CHAR_COMMERCIAL_AT = 0x40 /* @ */\nconst CHAR_LEFT_SQUARE_BRACKET = 0x5B /* [ */\nconst CHAR_RIGHT_SQUARE_BRACKET = 0x5D /* ] */\nconst CHAR_GRAVE_ACCENT = 0x60 /* ` */\nconst CHAR_LEFT_CURLY_BRACKET = 0x7B /* { */\nconst CHAR_VERTICAL_LINE = 0x7C /* | */\nconst CHAR_RIGHT_CURLY_BRACKET = 0x7D /* } */\n\nconst ESCAPE_SEQUENCES = {}\n\nESCAPE_SEQUENCES[0x00] = '\\\\0'\nESCAPE_SEQUENCES[0x07] = '\\\\a'\nESCAPE_SEQUENCES[0x08] = '\\\\b'\nESCAPE_SEQUENCES[0x09] = '\\\\t'\nESCAPE_SEQUENCES[0x0A] = '\\\\n'\nESCAPE_SEQUENCES[0x0B] = '\\\\v'\nESCAPE_SEQUENCES[0x0C] = '\\\\f'\nESCAPE_SEQUENCES[0x0D] = '\\\\r'\nESCAPE_SEQUENCES[0x1B] = '\\\\e'\nESCAPE_SEQUENCES[0x22] = '\\\\\"'\nESCAPE_SEQUENCES[0x5C] = '\\\\\\\\'\nESCAPE_SEQUENCES[0x85] = '\\\\N'\nESCAPE_SEQUENCES[0xA0] = '\\\\_'\nESCAPE_SEQUENCES[0x2028] = '\\\\L'\nESCAPE_SEQUENCES[0x2029] = '\\\\P'\n\nconst DEPRECATED_BOOLEANS_SYNTAX = [\n 'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',\n 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'\n]\n\nconst DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\\.[0-9_]*)?$/\n\nfunction compileStyleMap (schema, map) {\n if (map === null) return {}\n\n const result = {}\n const keys = Object.keys(map)\n\n for (let index = 0, length = keys.length; index < length; index += 1) {\n let tag = keys[index]\n let style = String(map[tag])\n\n if (tag.slice(0, 2) === '!!') {\n tag = 'tag:yaml.org,2002:' + tag.slice(2)\n }\n const type = schema.compiledTypeMap['fallback'][tag]\n\n if (type && _hasOwnProperty.call(type.styleAliases, style)) {\n style = type.styleAliases[style]\n }\n\n result[tag] = style\n }\n\n return result\n}\n\nfunction encodeHex (character) {\n let handle\n let length\n\n const string = character.toString(16).toUpperCase()\n\n if (character <= 0xFF) {\n handle = 'x'\n length = 2\n } else if (character <= 0xFFFF) {\n handle = 'u'\n length = 4\n } else if (character <= 0xFFFFFFFF) {\n handle = 'U'\n length = 8\n } else {\n throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF')\n }\n\n return '\\\\' + handle + common.repeat('0', length - string.length) + string\n}\n\nconst QUOTING_TYPE_SINGLE = 1\nconst QUOTING_TYPE_DOUBLE = 2\n\nfunction State (options) {\n this.schema = options['schema'] || DEFAULT_SCHEMA\n this.indent = Math.max(1, (options['indent'] || 2))\n this.noArrayIndent = options['noArrayIndent'] || false\n this.skipInvalid = options['skipInvalid'] || false\n this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel'])\n this.styleMap = compileStyleMap(this.schema, options['styles'] || null)\n this.sortKeys = options['sortKeys'] || false\n this.lineWidth = options['lineWidth'] || 80\n this.noRefs = options['noRefs'] || false\n this.noCompatMode = options['noCompatMode'] || false\n this.condenseFlow = options['condenseFlow'] || false\n this.quotingType = options['quotingType'] === '\"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE\n this.forceQuotes = options['forceQuotes'] || false\n this.replacer = typeof options['replacer'] === 'function' ? options['replacer'] : null\n\n this.implicitTypes = this.schema.compiledImplicit\n this.explicitTypes = this.schema.compiledExplicit\n\n this.tag = null\n this.result = ''\n\n this.duplicates = []\n this.usedDuplicates = null\n}\n\n// Indents every line in a string. Empty lines (\\n only) are not indented.\nfunction indentString (string, spaces) {\n const ind = common.repeat(' ', spaces)\n let position = 0\n let result = ''\n const length = string.length\n\n while (position < length) {\n let line\n const next = string.indexOf('\\n', position)\n if (next === -1) {\n line = string.slice(position)\n position = length\n } else {\n line = string.slice(position, next + 1)\n position = next + 1\n }\n\n if (line.length && line !== '\\n') result += ind\n\n result += line\n }\n\n return result\n}\n\nfunction generateNextLine (state, level) {\n return '\\n' + common.repeat(' ', state.indent * level)\n}\n\nfunction testImplicitResolving (state, str) {\n for (let index = 0, length = state.implicitTypes.length; index < length; index += 1) {\n const type = state.implicitTypes[index]\n\n if (type.resolve(str)) {\n return true\n }\n }\n\n return false\n}\n\n// [33] s-white ::= s-space | s-tab\nfunction isWhitespace (c) {\n return c === CHAR_SPACE || c === CHAR_TAB\n}\n\n// Returns true if the character can be printed without escaping.\n// From YAML 1.2: \"any allowed characters known to be non-printable\n// should also be escaped. [However,] This isn’t mandatory\"\n// Derived from nb-char - \\t - #x85 - #xA0 - #x2028 - #x2029.\nfunction isPrintable (c) {\n return (c >= 0x00020 && c <= 0x00007E) ||\n ((c >= 0x000A1 && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029) ||\n ((c >= 0x0E000 && c <= 0x00FFFD) && c !== CHAR_BOM) ||\n (c >= 0x10000 && c <= 0x10FFFF)\n}\n\n// [34] ns-char ::= nb-char - s-white\n// [27] nb-char ::= c-printable - b-char - c-byte-order-mark\n// [26] b-char ::= b-line-feed | b-carriage-return\n// Including s-white (for some reason, examples doesn't match specs in this aspect)\n// ns-char ::= c-printable - b-line-feed - b-carriage-return - c-byte-order-mark\nfunction isNsCharOrWhitespace (c) {\n return isPrintable(c) &&\n c !== CHAR_BOM &&\n // - b-char\n c !== CHAR_CARRIAGE_RETURN &&\n c !== CHAR_LINE_FEED\n}\n\n// [127] ns-plain-safe(c) ::= c = flow-out ⇒ ns-plain-safe-out\n// c = flow-in ⇒ ns-plain-safe-in\n// c = block-key ⇒ ns-plain-safe-out\n// c = flow-key ⇒ ns-plain-safe-in\n// [128] ns-plain-safe-out ::= ns-char\n// [129] ns-plain-safe-in ::= ns-char - c-flow-indicator\n// [130] ns-plain-char(c) ::= ( ns-plain-safe(c) - “:” - “#” )\n// | ( /* An ns-char preceding */ “#” )\n// | ( “:” /* Followed by an ns-plain-safe(c) */ )\nfunction isPlainSafe (c, prev, inblock) {\n const cIsNsCharOrWhitespace = isNsCharOrWhitespace(c)\n const cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c)\n return (\n (\n // ns-plain-safe\n inblock // c = flow-in\n ? cIsNsCharOrWhitespace\n : cIsNsCharOrWhitespace &&\n // - c-flow-indicator\n c !== CHAR_COMMA &&\n c !== CHAR_LEFT_SQUARE_BRACKET &&\n c !== CHAR_RIGHT_SQUARE_BRACKET &&\n c !== CHAR_LEFT_CURLY_BRACKET &&\n c !== CHAR_RIGHT_CURLY_BRACKET\n ) &&\n // ns-plain-char\n c !== CHAR_SHARP && // false on '#'\n !(prev === CHAR_COLON && !cIsNsChar)\n ) || // false on ': '\n (isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP) || // change to true on '[^ ]#'\n (prev === CHAR_COLON && cIsNsChar) // change to true on ':[^ ]'\n}\n\n// Simplified test for values allowed as the first character in plain style.\nfunction isPlainSafeFirst (c) {\n // Uses a subset of ns-char - c-indicator\n // where ns-char = nb-char - s-white.\n // No support of ( ( “?” | “:” | “-” ) /* Followed by an ns-plain-safe(c)) */ ) part\n return isPrintable(c) &&\n c !== CHAR_BOM &&\n !isWhitespace(c) && // - s-white\n // - (c-indicator ::=\n // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”\n c !== CHAR_MINUS &&\n c !== CHAR_QUESTION &&\n c !== CHAR_COLON &&\n c !== CHAR_COMMA &&\n c !== CHAR_LEFT_SQUARE_BRACKET &&\n c !== CHAR_RIGHT_SQUARE_BRACKET &&\n c !== CHAR_LEFT_CURLY_BRACKET &&\n c !== CHAR_RIGHT_CURLY_BRACKET &&\n // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “\"”\n c !== CHAR_SHARP &&\n c !== CHAR_AMPERSAND &&\n c !== CHAR_ASTERISK &&\n c !== CHAR_EXCLAMATION &&\n c !== CHAR_VERTICAL_LINE &&\n c !== CHAR_EQUALS &&\n c !== CHAR_GREATER_THAN &&\n c !== CHAR_SINGLE_QUOTE &&\n c !== CHAR_DOUBLE_QUOTE &&\n // | “%” | “@” | “`”)\n c !== CHAR_PERCENT &&\n c !== CHAR_COMMERCIAL_AT &&\n c !== CHAR_GRAVE_ACCENT\n}\n\n// Simplified test for values allowed as the last character in plain style.\nfunction isPlainSafeLast (c) {\n // just not whitespace or colon, it will be checked to be plain character later\n return !isWhitespace(c) && c !== CHAR_COLON\n}\n\n// Same as 'string'.codePointAt(pos), but works in older browsers.\nfunction codePointAt (string, pos) {\n const first = string.charCodeAt(pos)\n let second\n\n if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) {\n second = string.charCodeAt(pos + 1)\n if (second >= 0xDC00 && second <= 0xDFFF) {\n // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae\n return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000\n }\n }\n return first\n}\n\n// Determines whether block indentation indicator is required.\nfunction needIndentIndicator (string) {\n const leadingSpaceRe = /^\\n* /\n return leadingSpaceRe.test(string)\n}\n\nconst STYLE_PLAIN = 1\nconst STYLE_SINGLE = 2\nconst STYLE_LITERAL = 3\nconst STYLE_FOLDED = 4\nconst STYLE_DOUBLE = 5\n\n// Determines which scalar styles are possible and returns the preferred style.\n// lineWidth = -1 => no limit.\n// Pre-conditions: str.length > 0.\n// Post-conditions:\n// STYLE_PLAIN or STYLE_SINGLE => no \\n are in the string.\n// STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).\n// STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).\nfunction chooseScalarStyle (string, singleLineOnly, indentPerLevel, lineWidth,\n testAmbiguousType, quotingType, forceQuotes, inblock) {\n let i\n let char = 0\n let prevChar = null\n let hasLineBreak = false\n let hasFoldableLine = false // only checked if shouldTrackWidth\n const shouldTrackWidth = lineWidth !== -1\n let previousLineBreak = -1 // count the first line correctly\n let plain = isPlainSafeFirst(codePointAt(string, 0)) &&\n isPlainSafeLast(codePointAt(string, string.length - 1))\n\n if (singleLineOnly || forceQuotes) {\n // Case: no block styles.\n // Check for disallowed characters to rule out plain and single.\n for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n char = codePointAt(string, i)\n if (!isPrintable(char)) {\n return STYLE_DOUBLE\n }\n plain = plain && isPlainSafe(char, prevChar, inblock)\n prevChar = char\n }\n } else {\n // Case: block styles permitted.\n for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n char = codePointAt(string, i)\n if (char === CHAR_LINE_FEED) {\n hasLineBreak = true\n // Check if any line can be folded.\n if (shouldTrackWidth) {\n hasFoldableLine = hasFoldableLine ||\n // Foldable line = too long, and not more-indented.\n (i - previousLineBreak - 1 > lineWidth &&\n string[previousLineBreak + 1] !== ' ')\n previousLineBreak = i\n }\n } else if (!isPrintable(char)) {\n return STYLE_DOUBLE\n }\n plain = plain && isPlainSafe(char, prevChar, inblock)\n prevChar = char\n }\n // in case the end is missing a \\n\n hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&\n (i - previousLineBreak - 1 > lineWidth &&\n string[previousLineBreak + 1] !== ' '))\n }\n // Although every style can represent \\n without escaping, prefer block styles\n // for multiline, since they're more readable and they don't add empty lines.\n // Also prefer folding a super-long line.\n if (!hasLineBreak && !hasFoldableLine) {\n // Strings interpretable as another type have to be quoted;\n // e.g. the string 'true' vs. the boolean true.\n if (plain && !forceQuotes && !testAmbiguousType(string)) {\n return STYLE_PLAIN\n }\n return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE\n }\n // Edge case: block indentation indicator can only have one digit.\n if (indentPerLevel > 9 && needIndentIndicator(string)) {\n return STYLE_DOUBLE\n }\n // At this point we know block styles are valid.\n // Prefer literal style unless we want to fold.\n if (!forceQuotes) {\n return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL\n }\n return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE\n}\n\n// Note: line breaking/folding is implemented for only the folded style.\n// NB. We drop the last trailing newline (if any) of a returned block scalar\n// since the dumper adds its own newline. This always works:\n// • No ending newline => unaffected; already using strip \"-\" chomping.\n// • Ending newline => removed then restored.\n// Importantly, this keeps the \"+\" chomp indicator from gaining an extra line.\nfunction writeScalar (state, string, level, iskey, inblock) {\n state.dump = (function () {\n if (string.length === 0) {\n return state.quotingType === QUOTING_TYPE_DOUBLE ? '\"\"' : \"''\"\n }\n if (!state.noCompatMode) {\n if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {\n return state.quotingType === QUOTING_TYPE_DOUBLE ? ('\"' + string + '\"') : (\"'\" + string + \"'\")\n }\n }\n\n const indent = state.indent * Math.max(1, level) // no 0-indent scalars\n // As indentation gets deeper, let the width decrease monotonically\n // to the lower bound min(state.lineWidth, 40).\n // Note that this implies\n // state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.\n // state.lineWidth > 40 + state.indent: width decreases until the lower bound.\n // This behaves better than a constant minimum width which disallows narrower options,\n // or an indent threshold which causes the width to suddenly increase.\n const lineWidth = (state.lineWidth === -1)\n ? -1\n : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent)\n\n // Without knowing if keys are implicit/explicit, assume implicit for safety.\n const singleLineOnly = iskey ||\n // No block styles in flow mode.\n (state.flowLevel > -1 && level >= state.flowLevel)\n function testAmbiguity (string) {\n return testImplicitResolving(state, string)\n }\n\n switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth,\n testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {\n case STYLE_PLAIN:\n return string\n case STYLE_SINGLE:\n return \"'\" + string.replace(/'/g, \"''\") + \"'\"\n case STYLE_LITERAL:\n return '|' + blockHeader(string, state.indent) +\n dropEndingNewline(indentString(string, indent))\n case STYLE_FOLDED:\n return '>' + blockHeader(string, state.indent) +\n dropEndingNewline(indentString(foldString(string, lineWidth), indent))\n case STYLE_DOUBLE:\n return '\"' + escapeString(string, lineWidth) + '\"'\n default:\n throw new YAMLException('impossible error: invalid scalar style')\n }\n }())\n}\n\n// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.\nfunction blockHeader (string, indentPerLevel) {\n const indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : ''\n\n // note the special case: the string '\\n' counts as a \"trailing\" empty line.\n const clip = string[string.length - 1] === '\\n'\n const keep = clip && (string[string.length - 2] === '\\n' || string === '\\n')\n const chomp = keep ? '+' : (clip ? '' : '-')\n\n return indentIndicator + chomp + '\\n'\n}\n\n// (See the note for writeScalar.)\nfunction dropEndingNewline (string) {\n return string[string.length - 1] === '\\n' ? string.slice(0, -1) : string\n}\n\n// Note: a long line without a suitable break point will exceed the width limit.\n// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.\nfunction foldString (string, width) {\n // In folded style, $k$ consecutive newlines output as $k+1$ newlines—\n // unless they're before or after a more-indented line, or at the very\n // beginning or end, in which case $k$ maps to $k$.\n // Therefore, parse each chunk as newline(s) followed by a content line.\n const lineRe = /(\\n+)([^\\n]*)/g\n\n // first line (possibly an empty line)\n let result = (function () {\n let nextLF = string.indexOf('\\n')\n nextLF = nextLF !== -1 ? nextLF : string.length\n lineRe.lastIndex = nextLF\n return foldLine(string.slice(0, nextLF), width)\n }())\n // If we haven't reached the first content line yet, don't add an extra \\n.\n let prevMoreIndented = string[0] === '\\n' || string[0] === ' '\n let moreIndented\n\n // rest of the lines\n let match\n while ((match = lineRe.exec(string))) {\n const prefix = match[1]\n const line = match[2]\n\n moreIndented = (line[0] === ' ')\n result += prefix +\n ((!prevMoreIndented && !moreIndented && line !== '') ? '\\n' : '') +\n foldLine(line, width)\n prevMoreIndented = moreIndented\n }\n\n return result\n}\n\n// Greedy line breaking.\n// Picks the longest line under the limit each time,\n// otherwise settles for the shortest line over the limit.\n// NB. More-indented lines *cannot* be folded, as that would add an extra \\n.\nfunction foldLine (line, width) {\n if (line === '' || line[0] === ' ') return line\n\n // Since a more-indented line adds a \\n, breaks can't be followed by a space.\n const breakRe = / [^ ]/g // note: the match index will always be <= length-2.\n let match\n // start is an inclusive index. end, curr, and next are exclusive.\n let start = 0\n let end\n let curr = 0\n let next = 0\n let result = ''\n\n // Invariants: 0 <= start <= length-1.\n // 0 <= curr <= next <= max(0, length-2). curr - start <= width.\n // Inside the loop:\n // A match implies length >= 2, so curr and next are <= length-2.\n while ((match = breakRe.exec(line))) {\n next = match.index\n // maintain invariant: curr - start <= width\n if (next - start > width) {\n end = (curr > start) ? curr : next // derive end <= length-2\n result += '\\n' + line.slice(start, end)\n // skip the space that was output as \\n\n start = end + 1 // derive start <= length-1\n }\n curr = next\n }\n\n // By the invariants, start <= length-1, so there is something left over.\n // It is either the whole string or a part starting from non-whitespace.\n result += '\\n'\n // Insert a break if the remainder is too long and there is a break available.\n if (line.length - start > width && curr > start) {\n result += line.slice(start, curr) + '\\n' + line.slice(curr + 1)\n } else {\n result += line.slice(start)\n }\n\n return result.slice(1) // drop extra \\n joiner\n}\n\n// Escapes a double-quoted string.\nfunction escapeString (string) {\n let result = ''\n let char = 0\n\n for (let i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n char = codePointAt(string, i)\n const escapeSeq = ESCAPE_SEQUENCES[char]\n\n if (!escapeSeq && isPrintable(char)) {\n result += string[i]\n if (char >= 0x10000) result += string[i + 1]\n } else {\n result += escapeSeq || encodeHex(char)\n }\n }\n\n return result\n}\n\nfunction writeFlowSequence (state, level, object) {\n let _result = ''\n const _tag = state.tag\n\n for (let index = 0, length = object.length; index < length; index += 1) {\n let value = object[index]\n\n if (state.replacer) {\n value = state.replacer.call(object, String(index), value)\n }\n\n // Write only valid elements, put null instead of invalid elements.\n if (writeNode(state, level, value, false, false) ||\n (typeof value === 'undefined' &&\n writeNode(state, level, null, false, false))) {\n if (_result !== '') _result += ',' + (!state.condenseFlow ? ' ' : '')\n _result += state.dump\n }\n }\n\n state.tag = _tag\n state.dump = '[' + _result + ']'\n}\n\nfunction writeBlockSequence (state, level, object, compact) {\n let _result = ''\n const _tag = state.tag\n\n for (let index = 0, length = object.length; index < length; index += 1) {\n let value = object[index]\n\n if (state.replacer) {\n value = state.replacer.call(object, String(index), value)\n }\n\n // Write only valid elements, put null instead of invalid elements.\n if (writeNode(state, level + 1, value, true, true, false, true) ||\n (typeof value === 'undefined' &&\n writeNode(state, level + 1, null, true, true, false, true))) {\n if (!compact || _result !== '') {\n _result += generateNextLine(state, level)\n }\n\n if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n _result += '-'\n } else {\n _result += '- '\n }\n\n _result += state.dump\n }\n }\n\n state.tag = _tag\n state.dump = _result || '[]' // Empty sequence if no valid values.\n}\n\nfunction writeFlowMapping (state, level, object) {\n let _result = ''\n const _tag = state.tag\n const objectKeyList = Object.keys(object)\n\n for (let index = 0, length = objectKeyList.length; index < length; index += 1) {\n let pairBuffer = ''\n if (_result !== '') pairBuffer += ', '\n\n if (state.condenseFlow) pairBuffer += '\"'\n\n const objectKey = objectKeyList[index]\n let objectValue = object[objectKey]\n\n if (state.replacer) {\n objectValue = state.replacer.call(object, objectKey, objectValue)\n }\n\n if (!writeNode(state, level, objectKey, false, false)) {\n continue // Skip this pair because of invalid key;\n }\n\n if (state.dump.length > 1024) pairBuffer += '? '\n\n pairBuffer += state.dump + (state.condenseFlow ? '\"' : '') + ':' + (state.condenseFlow ? '' : ' ')\n\n if (!writeNode(state, level, objectValue, false, false)) {\n continue // Skip this pair because of invalid value.\n }\n\n pairBuffer += state.dump\n\n // Both key and value are valid.\n _result += pairBuffer\n }\n\n state.tag = _tag\n state.dump = '{' + _result + '}'\n}\n\nfunction writeBlockMapping (state, level, object, compact) {\n let _result = ''\n const _tag = state.tag\n const objectKeyList = Object.keys(object)\n\n // Allow sorting keys so that the output file is deterministic\n if (state.sortKeys === true) {\n // Default sorting\n objectKeyList.sort()\n } else if (typeof state.sortKeys === 'function') {\n // Custom sort function\n objectKeyList.sort(state.sortKeys)\n } else if (state.sortKeys) {\n // Something is wrong\n throw new YAMLException('sortKeys must be a boolean or a function')\n }\n\n for (let index = 0, length = objectKeyList.length; index < length; index += 1) {\n let pairBuffer = ''\n\n if (!compact || _result !== '') {\n pairBuffer += generateNextLine(state, level)\n }\n\n const objectKey = objectKeyList[index]\n let objectValue = object[objectKey]\n\n if (state.replacer) {\n objectValue = state.replacer.call(object, objectKey, objectValue)\n }\n\n if (!writeNode(state, level + 1, objectKey, true, true, true)) {\n continue // Skip this pair because of invalid key.\n }\n\n const explicitPair = (state.tag !== null && state.tag !== '?') ||\n (state.dump && state.dump.length > 1024)\n\n if (explicitPair) {\n if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n pairBuffer += '?'\n } else {\n pairBuffer += '? '\n }\n }\n\n pairBuffer += state.dump\n\n if (explicitPair) {\n pairBuffer += generateNextLine(state, level)\n }\n\n if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {\n continue // Skip this pair because of invalid value.\n }\n\n if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n pairBuffer += ':'\n } else {\n pairBuffer += ': '\n }\n\n pairBuffer += state.dump\n\n // Both key and value are valid.\n _result += pairBuffer\n }\n\n state.tag = _tag\n state.dump = _result || '{}' // Empty mapping if no valid pairs.\n}\n\nfunction detectType (state, object, explicit) {\n const typeList = explicit ? state.explicitTypes : state.implicitTypes\n\n for (let index = 0, length = typeList.length; index < length; index += 1) {\n const type = typeList[index]\n\n if ((type.instanceOf || type.predicate) &&\n (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&\n (!type.predicate || type.predicate(object))) {\n if (explicit) {\n if (type.multi && type.representName) {\n state.tag = type.representName(object)\n } else {\n state.tag = type.tag\n }\n } else {\n state.tag = '?'\n }\n\n if (type.represent) {\n const style = state.styleMap[type.tag] || type.defaultStyle\n\n let _result\n if (_toString.call(type.represent) === '[object Function]') {\n _result = type.represent(object, style)\n } else if (_hasOwnProperty.call(type.represent, style)) {\n _result = type.represent[style](object, style)\n } else {\n throw new YAMLException('!<' + type.tag + '> tag resolver accepts not \"' + style + '\" style')\n }\n\n state.dump = _result\n }\n\n return true\n }\n }\n\n return false\n}\n\n// Serializes `object` and writes it to global `result`.\n// Returns true on success, or false on invalid object.\n//\nfunction writeNode (state, level, object, block, compact, iskey, isblockseq) {\n state.tag = null\n state.dump = object\n\n if (!detectType(state, object, false)) {\n detectType(state, object, true)\n }\n\n const type = _toString.call(state.dump)\n const inblock = block\n\n if (block) {\n block = (state.flowLevel < 0 || state.flowLevel > level)\n }\n\n const objectOrArray = type === '[object Object]' || type === '[object Array]'\n let duplicateIndex\n let duplicate\n\n if (objectOrArray) {\n duplicateIndex = state.duplicates.indexOf(object)\n duplicate = duplicateIndex !== -1\n }\n\n if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {\n compact = false\n }\n\n if (duplicate && state.usedDuplicates[duplicateIndex]) {\n state.dump = '*ref_' + duplicateIndex\n } else {\n if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {\n state.usedDuplicates[duplicateIndex] = true\n }\n if (type === '[object Object]') {\n if (block && (Object.keys(state.dump).length !== 0)) {\n writeBlockMapping(state, level, state.dump, compact)\n if (duplicate) {\n state.dump = '&ref_' + duplicateIndex + state.dump\n }\n } else {\n writeFlowMapping(state, level, state.dump)\n if (duplicate) {\n state.dump = '&ref_' + duplicateIndex + ' ' + state.dump\n }\n }\n } else if (type === '[object Array]') {\n if (block && (state.dump.length !== 0)) {\n if (state.noArrayIndent && !isblockseq && level > 0) {\n writeBlockSequence(state, level - 1, state.dump, compact)\n } else {\n writeBlockSequence(state, level, state.dump, compact)\n }\n if (duplicate) {\n state.dump = '&ref_' + duplicateIndex + state.dump\n }\n } else {\n writeFlowSequence(state, level, state.dump)\n if (duplicate) {\n state.dump = '&ref_' + duplicateIndex + ' ' + state.dump\n }\n }\n } else if (type === '[object String]') {\n if (state.tag !== '?') {\n writeScalar(state, state.dump, level, iskey, inblock)\n }\n } else if (type === '[object Undefined]') {\n return false\n } else {\n if (state.skipInvalid) return false\n throw new YAMLException('unacceptable kind of an object to dump ' + type)\n }\n\n if (state.tag !== null && state.tag !== '?') {\n // Need to encode all characters except those allowed by the spec:\n //\n // [35] ns-dec-digit ::= [#x30-#x39] /* 0-9 */\n // [36] ns-hex-digit ::= ns-dec-digit\n // | [#x41-#x46] /* A-F */ | [#x61-#x66] /* a-f */\n // [37] ns-ascii-letter ::= [#x41-#x5A] /* A-Z */ | [#x61-#x7A] /* a-z */\n // [38] ns-word-char ::= ns-dec-digit | ns-ascii-letter | “-”\n // [39] ns-uri-char ::= “%” ns-hex-digit ns-hex-digit | ns-word-char | “#”\n // | “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,”\n // | “_” | “.” | “!” | “~” | “*” | “'” | “(” | “)” | “[” | “]”\n //\n // Also need to encode '!' because it has special meaning (end of tag prefix).\n //\n let tagStr = encodeURI(\n state.tag[0] === '!' ? state.tag.slice(1) : state.tag\n ).replace(/!/g, '%21')\n\n if (state.tag[0] === '!') {\n tagStr = '!' + tagStr\n } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') {\n tagStr = '!!' + tagStr.slice(18)\n } else {\n tagStr = '!<' + tagStr + '>'\n }\n\n state.dump = tagStr + ' ' + state.dump\n }\n }\n\n return true\n}\n\nfunction getDuplicateReferences (object, state) {\n const objects = []\n const duplicatesIndexes = []\n\n inspectNode(object, objects, duplicatesIndexes)\n\n const length = duplicatesIndexes.length\n for (let index = 0; index < length; index += 1) {\n state.duplicates.push(objects[duplicatesIndexes[index]])\n }\n state.usedDuplicates = new Array(length)\n}\n\nfunction inspectNode (object, objects, duplicatesIndexes) {\n if (object !== null && typeof object === 'object') {\n const index = objects.indexOf(object)\n if (index !== -1) {\n if (duplicatesIndexes.indexOf(index) === -1) {\n duplicatesIndexes.push(index)\n }\n } else {\n objects.push(object)\n\n if (Array.isArray(object)) {\n for (let i = 0, length = object.length; i < length; i += 1) {\n inspectNode(object[i], objects, duplicatesIndexes)\n }\n } else {\n const objectKeyList = Object.keys(object)\n\n for (let i = 0, length = objectKeyList.length; i < length; i += 1) {\n inspectNode(object[objectKeyList[i]], objects, duplicatesIndexes)\n }\n }\n }\n }\n}\n\nfunction dump (input, options) {\n options = options || {}\n\n const state = new State(options)\n\n if (!state.noRefs) getDuplicateReferences(input, state)\n\n let value = input\n\n if (state.replacer) {\n value = state.replacer.call({ '': value }, '', value)\n }\n\n if (writeNode(state, 0, value, true, true)) return state.dump + '\\n'\n\n return ''\n}\n\nmodule.exports.dump = dump\n","'use strict'\n\nconst loader = require('./lib/loader')\nconst dumper = require('./lib/dumper')\n\nfunction renamed (from, to) {\n return function () {\n throw new Error('Function yaml.' + from + ' is removed in js-yaml 4. ' +\n 'Use yaml.' + to + ' instead, which is now safe by default.')\n }\n}\n\nmodule.exports.Type = require('./lib/type')\nmodule.exports.Schema = require('./lib/schema')\nmodule.exports.FAILSAFE_SCHEMA = require('./lib/schema/failsafe')\nmodule.exports.JSON_SCHEMA = require('./lib/schema/json')\nmodule.exports.CORE_SCHEMA = require('./lib/schema/core')\nmodule.exports.DEFAULT_SCHEMA = require('./lib/schema/default')\nmodule.exports.load = loader.load\nmodule.exports.loadAll = loader.loadAll\nmodule.exports.dump = dumper.dump\nmodule.exports.YAMLException = require('./lib/exception')\n\n// Re-export all types in case user wants to create custom schema\nmodule.exports.types = {\n binary: require('./lib/type/binary'),\n float: require('./lib/type/float'),\n map: require('./lib/type/map'),\n null: require('./lib/type/null'),\n pairs: require('./lib/type/pairs'),\n set: require('./lib/type/set'),\n timestamp: require('./lib/type/timestamp'),\n bool: require('./lib/type/bool'),\n int: require('./lib/type/int'),\n merge: require('./lib/type/merge'),\n omap: require('./lib/type/omap'),\n seq: require('./lib/type/seq'),\n str: require('./lib/type/str')\n}\n\n// Removed functions from JS-YAML 3.0.x\nmodule.exports.safeLoad = renamed('safeLoad', 'load')\nmodule.exports.safeLoadAll = renamed('safeLoadAll', 'loadAll')\nmodule.exports.safeDump = renamed('safeDump', 'dump')\n","import yaml from '../index.js'\n\nconst {\n Type,\n Schema,\n FAILSAFE_SCHEMA,\n JSON_SCHEMA,\n CORE_SCHEMA,\n DEFAULT_SCHEMA,\n load,\n loadAll,\n dump,\n YAMLException,\n types,\n safeLoad,\n safeLoadAll,\n safeDump\n} = yaml\n\nexport {\n Type,\n Schema,\n FAILSAFE_SCHEMA,\n JSON_SCHEMA,\n CORE_SCHEMA,\n DEFAULT_SCHEMA,\n load,\n loadAll,\n dump,\n YAMLException,\n types,\n safeLoad,\n safeLoadAll,\n safeDump\n}\n\nexport default yaml\n","/**\n * PDLSS Policy Parser\n *\n * Parses local YAML policy files into typed LocalPolicy objects.\n * Validates against the PDLSS schema to ensure cloud compatibility.\n */\n\nimport * as yaml from 'js-yaml';\nimport { readFileSync } from 'fs';\nimport type { LocalPolicy } from '../gateway/types';\nimport { validatePolicy, type ValidationResult } from './schema';\n\nexport interface ParseResult {\n policy: LocalPolicy | null;\n validation: ValidationResult;\n rawYaml?: string;\n}\n\n/**\n * Parse a YAML string into a LocalPolicy.\n */\nexport function parseYaml(yamlContent: string): ParseResult {\n let parsed: unknown;\n\n try {\n parsed = yaml.load(yamlContent);\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Invalid YAML';\n return {\n policy: null,\n validation: { valid: false, errors: [{ path: '', message: `YAML parse error: ${message}` }] },\n rawYaml: yamlContent,\n };\n }\n\n const validation = validatePolicy(parsed);\n\n if (!validation.valid) {\n return { policy: null, validation, rawYaml: yamlContent };\n }\n\n return {\n policy: parsed as LocalPolicy,\n validation,\n rawYaml: yamlContent,\n };\n}\n\n/**\n * Parse a YAML file from disk into a LocalPolicy.\n */\nexport function parseFile(filePath: string): ParseResult {\n let content: string;\n\n try {\n content = readFileSync(filePath, 'utf-8');\n } catch (err) {\n const message = err instanceof Error ? err.message : 'File read error';\n return {\n policy: null,\n validation: { valid: false, errors: [{ path: '', message: `Failed to read policy file: ${message}` }] },\n };\n }\n\n return parseYaml(content);\n}\n\n/**\n * Convert a LocalPolicy back to YAML string (for upload to cloud).\n */\nexport function toYaml(policy: LocalPolicy): string {\n return yaml.dump(policy, { lineWidth: 120, noRefs: true });\n}\n","/**\n * PDLSS Policy Schema Validation\n *\n * Validates local YAML policy files against the PDLSS schema.\n * Ensures local policies can be uploaded to cloud without lossy transformation.\n */\n\nimport type { LocalRiskThresholds } from '../gateway/types';\n\nexport interface ValidationError {\n path: string;\n message: string;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationError[];\n}\n\n/**\n * Validate a parsed local policy object against the PDLSS schema.\n */\nexport function validatePolicy(policy: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n\n if (!policy || typeof policy !== 'object') {\n return { valid: false, errors: [{ path: '', message: 'Policy must be an object' }] };\n }\n\n const p = policy as Record<string, unknown>;\n\n // Required fields\n if (typeof p.version !== 'string') {\n errors.push({ path: 'version', message: 'version is required and must be a string' });\n }\n if (typeof p.name !== 'string') {\n errors.push({ path: 'name', message: 'name is required and must be a string' });\n }\n\n // Purposes\n if (!Array.isArray(p.purposes)) {\n errors.push({ path: 'purposes', message: 'purposes is required and must be an array' });\n } else {\n p.purposes.forEach((purpose: unknown, i: number) => {\n errors.push(...validatePurpose(purpose, `purposes[${i}]`));\n });\n }\n\n // Scope (optional)\n if (p.scope !== undefined) {\n errors.push(...validateScope(p.scope, 'scope'));\n }\n\n // Limits (optional)\n if (p.limits !== undefined) {\n errors.push(...validateLimits(p.limits, 'limits'));\n }\n\n // Risk thresholds (optional)\n if (p.riskThresholds !== undefined) {\n errors.push(...validateRiskThresholds(p.riskThresholds, 'riskThresholds'));\n }\n\n return { valid: errors.length === 0, errors };\n}\n\nfunction validatePurpose(purpose: unknown, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (!purpose || typeof purpose !== 'object') {\n return [{ path, message: 'purpose must be an object' }];\n }\n\n const p = purpose as Record<string, unknown>;\n\n if (typeof p.id !== 'string' || !p.id) {\n errors.push({ path: `${path}.id`, message: 'id is required and must be a non-empty string' });\n }\n\n if (typeof p.allowed !== 'boolean') {\n errors.push({ path: `${path}.allowed`, message: 'allowed is required and must be a boolean' });\n }\n\n if (p.targets !== undefined && !isStringArray(p.targets)) {\n errors.push({ path: `${path}.targets`, message: 'targets must be an array of strings' });\n }\n\n if (p.blockedPatterns !== undefined && !isStringArray(p.blockedPatterns)) {\n errors.push({\n path: `${path}.blockedPatterns`,\n message: 'blockedPatterns must be an array of strings',\n });\n }\n\n if (p.requiresApproval !== undefined && typeof p.requiresApproval !== 'boolean') {\n errors.push({\n path: `${path}.requiresApproval`,\n message: 'requiresApproval must be a boolean',\n });\n }\n\n return errors;\n}\n\nfunction validateScope(scope: unknown, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (typeof scope !== 'object' || scope === null) {\n return [{ path, message: 'scope must be an object' }];\n }\n\n const s = scope as Record<string, unknown>;\n\n for (const field of ['allowedDomains', 'blockedDomains', 'blockedResources']) {\n if (s[field] !== undefined && !isStringArray(s[field])) {\n errors.push({ path: `${path}.${field}`, message: `${field} must be an array of strings` });\n }\n }\n\n return errors;\n}\n\nfunction validateLimits(limits: unknown, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (typeof limits !== 'object' || limits === null) {\n return [{ path, message: 'limits must be an object' }];\n }\n\n const l = limits as Record<string, unknown>;\n\n if (l.autonomousThreshold !== undefined && typeof l.autonomousThreshold !== 'number') {\n errors.push({\n path: `${path}.autonomousThreshold`,\n message: 'autonomousThreshold must be a number',\n });\n }\n\n if (l.maxTransactionAmount !== undefined && typeof l.maxTransactionAmount !== 'number') {\n errors.push({\n path: `${path}.maxTransactionAmount`,\n message: 'maxTransactionAmount must be a number',\n });\n }\n\n // Relationship: the Autonomous Limit must not exceed the Hard Limit, else the\n // step-up band [autonomousThreshold, maxTransactionAmount) is empty/inverted.\n if (\n typeof l.autonomousThreshold === 'number' &&\n typeof l.maxTransactionAmount === 'number' &&\n l.autonomousThreshold > l.maxTransactionAmount\n ) {\n errors.push({\n path: `${path}.autonomousThreshold`,\n message:\n 'autonomousThreshold (Autonomous Limit) must be <= maxTransactionAmount (Hard Limit)',\n });\n }\n\n if (l.maxRequestsPerHour !== undefined && typeof l.maxRequestsPerHour !== 'number') {\n errors.push({\n path: `${path}.maxRequestsPerHour`,\n message: 'maxRequestsPerHour must be a number',\n });\n }\n\n if (l.currency !== undefined && typeof l.currency !== 'string') {\n errors.push({ path: `${path}.currency`, message: 'currency must be a string' });\n }\n\n return errors;\n}\n\nfunction validateRiskThresholds(thresholds: unknown, path: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (typeof thresholds !== 'object' || thresholds === null) {\n return [{ path, message: 'riskThresholds must be an object' }];\n }\n\n const t = thresholds as Record<string, unknown>;\n\n for (const range of ['autoAllow', 'requireApproval', 'autoBlock'] as const) {\n if (!t[range] || typeof t[range] !== 'object') {\n errors.push({\n path: `${path}.${range}`,\n message: `${range} is required and must be an object with min and max`,\n });\n continue;\n }\n\n const r = t[range] as Record<string, unknown>;\n if (typeof r.min !== 'number' || typeof r.max !== 'number') {\n errors.push({ path: `${path}.${range}`, message: `${range} must have numeric min and max` });\n } else if (r.min > r.max) {\n errors.push({ path: `${path}.${range}`, message: `${range}.min must be <= ${range}.max` });\n }\n }\n\n // Validate contiguous ranges (no gaps)\n if (isValidThresholdShape(t)) {\n const thresholdObj = t as unknown as LocalRiskThresholds;\n if (thresholdObj.autoAllow.max + 1 !== thresholdObj.requireApproval.min) {\n errors.push({\n path: `${path}`,\n message: `Gap between autoAllow.max (${thresholdObj.autoAllow.max}) and requireApproval.min (${thresholdObj.requireApproval.min}). Ranges must be contiguous.`,\n });\n }\n if (thresholdObj.requireApproval.max + 1 !== thresholdObj.autoBlock.min) {\n errors.push({\n path: `${path}`,\n message: `Gap between requireApproval.max (${thresholdObj.requireApproval.max}) and autoBlock.min (${thresholdObj.autoBlock.min}). Ranges must be contiguous.`,\n });\n }\n }\n\n return errors;\n}\n\nfunction isStringArray(val: unknown): val is string[] {\n return Array.isArray(val) && val.every((v) => typeof v === 'string');\n}\n\nfunction isValidThresholdShape(t: Record<string, unknown>): boolean {\n for (const key of ['autoAllow', 'requireApproval', 'autoBlock']) {\n const r = t[key];\n if (!r || typeof r !== 'object') return false;\n const range = r as Record<string, unknown>;\n if (typeof range.min !== 'number' || typeof range.max !== 'number') return false;\n }\n return true;\n}\n","/**\n * Local Mode — Evaluates actions against a local PDLSS policy file.\n * No network calls, no account required, runs entirely in-process.\n */\n\nimport type { AstraSyncGatewayConfig, PDLSSContext, VerificationDecision } from '../types';\nimport { LocalEvaluator } from '../../local-evaluator/evaluator';\nimport { parseFile } from '../../local-evaluator/pdlss-parser';\n\n/**\n * Load a local evaluator from config.\n */\nexport function loadEvaluator(config: AstraSyncGatewayConfig): LocalEvaluator {\n if (config.policy) {\n return new LocalEvaluator(config.policy);\n }\n\n if (config.policyFile) {\n const result = parseFile(config.policyFile);\n if (!result.policy) {\n const errors = result.validation.errors.map((e) => `${e.path}: ${e.message}`).join('; ');\n throw new Error(`Invalid policy file ${config.policyFile}: ${errors}`);\n }\n return new LocalEvaluator(result.policy);\n }\n\n throw new Error('Local mode requires either policyFile or policy in config');\n}\n\n/**\n * Verify locally against the loaded PDLSS policy.\n */\nexport function verifyLocal(evaluator: LocalEvaluator, context: PDLSSContext): VerificationDecision {\n return evaluator.evaluate(context);\n}\n","/**\n * AstraSync Universal Verification Gateway — Trust Level helpers.\n *\n * SDK 5.0.0: the `accessLevel` band (`none`/`restricted`/`read-only`/`standard`/\n * `full`/`internal`) was removed entirely — it never gated the access decision\n * (the server does, from a verified ID + runtime challenge + PDLSS match + trust\n * score). What remains here is the coarse trust-level badge derived from the\n * numeric trust score, used only for display.\n */\n\nimport type { TrustLevel } from './types';\n\n/**\n * Trust level score ranges\n */\nexport const TRUST_LEVEL_RANGES: Record<TrustLevel, { min: number; max: number }> = {\n BRONZE: { min: 0, max: 39 },\n SILVER: { min: 40, max: 59 },\n GOLD: { min: 60, max: 79 },\n PLATINUM: { min: 80, max: 100 },\n};\n\n/**\n * Determine trust level from score\n */\nexport function getTrustLevel(score: number): TrustLevel {\n if (score >= 80) return 'PLATINUM';\n if (score >= 60) return 'GOLD';\n if (score >= 40) return 'SILVER';\n return 'BRONZE';\n}\n","/**\n * Single source-of-truth for the SDK's\n * package version emitted on verify-access bodies (and any future\n * telemetry). Bumped alongside `package.json#version` on every release.\n *\n * Why a constant rather than `import pkg from '../package.json'`:\n * - `tsconfig.json` sets `rootDir: ./src`; importing the sibling\n * package.json fails the build with \"outside rootDir\".\n * - Build-time string replacement (tsup `define`, esbuild banner, etc.)\n * adds toolchain coupling for a trivial gain.\n * - Embedded readonly constant works in every environment (Node, browser,\n * bundlers, Deno) without runtime fs / network access.\n *\n * Release discipline: a CI lint can grep `package.json#version` against\n * this constant if the two ever diverge in the wild. A manual bump\n * is fine — bumping both in the release-ceremony commit keeps them\n * lockstep.\n */\nexport const SDK_VERSION = '5.11.0';\n","/**\n * Shared outbound-HTTP wrapper — every request the SDK makes to the\n * AstraSync backend (or anywhere else) goes through `sdkFetch` so it\n * carries an identifying User-Agent.\n *\n * Why: Node's global fetch defaults to `user-agent: node`, which is\n * indistinguishable from every other Node client on the wire. Visit\n * Intelligence observed our own SDK/beacon traffic as anonymous \"node\"\n * visits. Self-identification is the platform's own medicine.\n *\n * Browser note: some browsers filter the User-Agent request header\n * silently (never throwing), so this is a no-op there — which is correct:\n * in a browser the page's real UA is the honest identity.\n */\n\nimport { SDK_VERSION } from './version';\n\nexport const SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;\n\n/**\n * Add the SDK User-Agent without changing the SHAPE of the caller's headers\n * (plain records stay plain records) — interceptors, adapters, and tests\n * read `init.headers` as a record, and `Headers` would also lowercase names.\n */\nfunction withUserAgent(initHeaders: HeadersInit | undefined): HeadersInit {\n if (!initHeaders) return { 'user-agent': SDK_USER_AGENT };\n if (initHeaders instanceof Headers) {\n const copy = new Headers(initHeaders);\n if (!copy.has('user-agent')) copy.set('user-agent', SDK_USER_AGENT);\n return copy;\n }\n if (Array.isArray(initHeaders)) {\n const has = initHeaders.some(([name]) => name.toLowerCase() === 'user-agent');\n return has ? initHeaders : [...initHeaders, ['user-agent', SDK_USER_AGENT]];\n }\n const has = Object.keys(initHeaders).some((name) => name.toLowerCase() === 'user-agent');\n return has ? initHeaders : { 'user-agent': SDK_USER_AGENT, ...initHeaders };\n}\n\nexport const sdkFetch: typeof fetch = (input, init) =>\n fetch(input, { ...init, headers: withUserAgent(init?.headers) });\n","import { sdkFetch } from './http';\n/**\n * SDK-side discovery of canonical platform URLs via `/.well-known/agentic-commerce`.\n *\n * Fire-and-forget pre-fetch at middleware creation; first verify() awaits\n * the in-flight promise if it hasn't resolved. 60-minute TTL with\n * stale-while-revalidate background refresh.\n */\n\nexport interface WellKnownAgenticCommerce {\n registrationUrl: string;\n documentationUrl: string;\n verifyAccessUrl: string;\n /** 5.1.0: hosted AstraSync MCP bridge endpoint (absent on self-hosted backends). */\n mcpEndpoint?: string;\n /** 5.1.0: bridge connector-discovery doc (absent on self-hosted backends). */\n mcpDiscoveryUrl?: string;\n}\n\ninterface CacheEntry {\n data: WellKnownAgenticCommerce;\n fetchedAt: number;\n}\n\nconst CACHE_TTL_MS = 60 * 60 * 1000; // 60 minutes\n\nconst cache = new Map<string, CacheEntry>();\nconst inflight = new Map<string, Promise<WellKnownAgenticCommerce>>();\n\nfunction wellKnownUrl(apiBaseUrl: string): string {\n // apiBaseUrl is typically 'https://astrasync.ai/api' — strip the /api suffix\n // to get the platform root, then append /.well-known/agentic-commerce.\n const base = apiBaseUrl.replace(/\\/api\\/?$/, '');\n return `${base}/.well-known/agentic-commerce`;\n}\n\nasync function fetchWellKnown(apiBaseUrl: string): Promise<WellKnownAgenticCommerce> {\n const url = wellKnownUrl(apiBaseUrl);\n const response = await sdkFetch(url, {\n method: 'GET',\n headers: { Accept: 'application/json' },\n signal: AbortSignal.timeout(5000),\n });\n if (!response.ok) {\n throw new Error(\n `AstraSync platform must expose /.well-known/agentic-commerce; ` +\n `got ${response.status} from ${url}. SDK cannot initialise without it.`\n );\n }\n const data = (await response.json()) as Record<string, unknown>;\n if (!data.registrationUrl || !data.documentationUrl || !data.verifyAccessUrl) {\n throw new Error(\n `/.well-known/agentic-commerce response missing required fields ` +\n `(registrationUrl, documentationUrl, verifyAccessUrl).`\n );\n }\n return data as unknown as WellKnownAgenticCommerce;\n}\n\n/**\n * Start a background fetch. Returns the promise for callers that need\n * to await it (first verify() call).\n */\nexport function prefetchWellKnown(apiBaseUrl: string): Promise<WellKnownAgenticCommerce> {\n const existing = inflight.get(apiBaseUrl);\n if (existing) return existing;\n\n const promise = fetchWellKnown(apiBaseUrl)\n .then((data) => {\n cache.set(apiBaseUrl, { data, fetchedAt: Date.now() });\n inflight.delete(apiBaseUrl);\n return data;\n })\n .catch((err) => {\n inflight.delete(apiBaseUrl);\n throw err;\n });\n\n inflight.set(apiBaseUrl, promise);\n return promise;\n}\n\n/**\n * Get cached well-known URLs. If stale, triggers a background refresh\n * and returns stale data (stale-while-revalidate). If no cache exists,\n * awaits the in-flight fetch or starts a new one.\n */\nexport async function getWellKnownUrls(apiBaseUrl: string): Promise<WellKnownAgenticCommerce> {\n const entry = cache.get(apiBaseUrl);\n\n if (entry) {\n if (Date.now() - entry.fetchedAt > CACHE_TTL_MS) {\n // Stale — trigger background refresh, return stale data\n prefetchWellKnown(apiBaseUrl).catch(() => {\n // Background refresh failed — stale data remains until next request\n });\n }\n return entry.data;\n }\n\n // No cache — must await\n const pending = inflight.get(apiBaseUrl);\n if (pending) return pending;\n\n return prefetchWellKnown(apiBaseUrl);\n}\n\n/**\n * Synchronous cache read — returns cached URLs or undefined.\n * Never triggers a fetch. Used by verify() to avoid extra HTTP calls\n * in the hot path; adapters are responsible for prefetching.\n */\nexport function getCachedWellKnownUrls(apiBaseUrl: string): WellKnownAgenticCommerce | undefined {\n return cache.get(apiBaseUrl)?.data;\n}\n\n/** Reset cache — for testing only. */\nexport function _resetWellKnownCache(): void {\n cache.clear();\n inflight.clear();\n}\n","/**\n * AstraSync Universal Verification Gateway - Core Verification Logic\n *\n * This module handles the core verification logic, calling the AstraSync API\n * and processing the response into a standardized VerificationResult.\n */\n\nimport { sdkFetch } from './http';\nimport type {\n GatewayConfig,\n AgentCredentials,\n VerificationRequest,\n VerificationResult,\n VerifiedAgent,\n VerifiedDeveloper,\n VerifiedOrganization,\n GuidanceInfo,\n EnhancedVerificationResult,\n TokenGuidance,\n RuntimeChallengeResult,\n StepUpApprovalInfo,\n SettlementOutcomeInfo,\n MerchantSettlementToken,\n FulfilmentInfo,\n SettlementArtifact,\n AttemptReport,\n} from './types';\nimport { getTrustLevel } from './trust-levels';\nimport type { ObservedMetadata } from './metadata-capture';\nimport { SDK_VERSION } from './version';\nimport { getCachedWellKnownUrls, type WellKnownAgenticCommerce } from './well-known';\n\n/**\n * Default configuration values\n *\n * apiBaseUrl matches the OpenAPI authoritative server (https://astrasync.ai/api\n * for prod, https://staging.astrasync.ai/api for staging). Always include the\n * /api path prefix when overriding — registration / docs URLs are derived by\n * stripping it.\n */\nconst DEFAULT_CONFIG: Partial<GatewayConfig> = {\n apiBaseUrl: 'https://astrasync.ai/api',\n // minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.\n // cacheTtl deliberately unset. When undefined, cacheResult applies the 60s\n // default; the caller's explicit value is honoured for cacheable results.\n // Denials and step-up escalations are NEVER cached (3.6.0) regardless of\n // cacheTtl. Set cacheTtl: 0 to disable caching entirely.\n debug: false,\n};\n\n/**\n * Init self-test state. Fires once per process on first verify() call to warn\n * if apiBaseUrl is pointing at the wrong host (e.g. a marketing site that\n * 200s with text/html instead of the API).\n */\nlet initCheckPerformed = false;\n\n/** Test-only: re-arm the one-time init self-check. */\nexport function _resetInitCheck(): void {\n initCheckPerformed = false;\n}\n\n/** One-shot guard for v2.3.0 deprecation warning. */\nlet deprecationWarningShown = false;\n\nasync function performInitCheck(\n apiBaseUrl: string,\n debug?: boolean,\n strictInit?: boolean,\n apiKey?: string\n): Promise<void> {\n initCheckPerformed = true;\n try {\n const probeUrl = `${apiBaseUrl}/agents/verify-access`;\n // HEAD mirrors GET semantics (running the full request pipeline without a\n // body) so the response carries the same content-type the marketing 404\n // would return. OPTIONS often gets short-circuited by CORS-preflight\n // handlers and returns no content-type, defeating the check.\n const response = await sdkFetch(probeUrl, { method: 'HEAD' });\n const contentType = response.headers.get('content-type') ?? '';\n if (contentType.startsWith('text/html')) {\n const message =\n `[VerificationGateway] apiBaseUrl '${apiBaseUrl}' returned HTML (content-type: ${contentType}). ` +\n `This usually means apiBaseUrl is pointing at a marketing site instead of the API. ` +\n `Expected: 'https://astrasync.ai/api' (prod) or 'https://staging.astrasync.ai/api' (staging).`;\n // Audit F-A6-33: when strictInit is set, throw on misconfig instead\n // of warning + continuing. Recurring footgun per\n // `[[feedback_astrasync_api_url_canonical]]` — silent warn lets\n // misconfigured prod deploys ship with all verify-access calls\n // silently failing.\n if (strictInit) {\n throw new Error(`${message} (strictInit=true)`);\n }\n console.warn(`${message} Set disableInitChecks: true on GatewayConfig to silence.`);\n } else if (debug) {\n console.log(\n `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`\n );\n }\n\n // 4.0.0: key liveness probe. A dead API key otherwise surfaces only\n // per-request as inbound agents get turned away — the operator should\n // learn at deploy time. 404 = older backend without self-check: silent.\n if (apiKey) {\n const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check`, {\n headers: { Authorization: `Bearer ${apiKey}` },\n });\n if (selfCheck.status === 401) {\n const body = (await selfCheck.json().catch(() => ({}))) as {\n code?: string;\n message?: string;\n remediation?: { manageUrl?: string };\n };\n const message =\n `[VerificationGateway] the configured AstraSync API key was REJECTED at startup ` +\n `(${body.code ?? 'api_key_invalid'}: ${body.message ?? 'invalid key'}). Every inbound agent ` +\n `will be turned away until the key is rotated` +\n (body.remediation?.manageUrl ? ` at ${body.remediation.manageUrl}` : '') +\n `.`;\n if (strictInit) {\n throw new Error(`${message} (strictInit=true)`);\n }\n console.error(message);\n } else if (selfCheck.ok) {\n const body = (await selfCheck.json().catch(() => ({}))) as {\n daysToExpiry?: number | null;\n };\n if (typeof body.daysToExpiry === 'number' && body.daysToExpiry <= 7) {\n console.warn(\n `[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) — ` +\n `rotate it at Settings → Developer Tools before integrations start failing.`\n );\n } else if (debug) {\n console.log('[VerificationGateway] API key self-check passed');\n }\n }\n }\n } catch (err) {\n if (strictInit) {\n // strict mode propagates init failures so callers get a clear,\n // synchronous \"your config is broken\" signal at startup.\n throw err;\n }\n if (debug) {\n console.log(`[VerificationGateway] init check failed (non-blocking): ${String(err)}`);\n }\n }\n}\n\n/**\n * Simple in-memory cache for verification results\n */\nconst verificationCache = new Map<string, { result: VerificationResult; expiresAt: number }>();\n\n/**\n * Generate cache key from the full request shape.\n *\n * Historically the key was credentials-only (`astraId-apiKey-jwt`),\n * which silently returned the cached result of a prior call even when the\n * subsequent call's purpose/action/counterparty/etc. differed. That was a\n * security gap — a warm cache could serve an allow verdict for a purpose the\n * agent hadn't actually been authorised for. Key now includes every field\n * that affects the backend verdict.\n *\n * MAINTAIN: when adding a field to VerificationRequest that affects the\n * backend verdict, add it to this key. Fields that don't affect verdict\n * (e.g. requestId, timestamps, sdkVersion) don't belong here — including\n * them would needlessly thrash the cache for repeated identical requests.\n *\n * 3.12.0 (Trust Record): `attemptId` and `considerationSet` are\n * deliberately EXCLUDED — like `callerMetadata.observedMetadata` they are\n * observational pass-through that never affects the verdict, and keying on\n * a per-attempt id would defeat verdict caching entirely. Cache hits get\n * their attemptId rewritten in verify() instead (never leak a prior\n * attempt's id from a cached result).\n */\nfunction getCacheKey(request: VerificationRequest, counterpartyId?: string): string {\n const c = request.credentials;\n return [\n c.astraId || '',\n c.apiKey || '',\n c.jwt || '',\n request.purpose || '',\n request.action || '',\n request.resourceType || '',\n request.resource || '',\n request.jurisdiction || '',\n request.transactionValue ?? '',\n request.currency || '',\n // SECURITY (cross-merchant cache leak): the merchant identity is sent via\n // `config.counterpartyId`, NOT on the request, so it was previously absent\n // from the key — two verifies for the SAME agent/purpose/action/value but\n // DIFFERENT merchants collided, and a grant at a permissive merchant (low\n // trust floor) was served for a stricter one. Same bug class as the\n // duration omission (F-A1-07). counterpartyId affects the backend verdict\n // (trust floor / per-route policy), so it MUST key the cache.\n counterpartyId || '',\n request.counterpartyUrl || '',\n request.counterpartyType || '',\n request.isSubAgentRequest ? '1' : '0',\n request.parentAgentId || '',\n request.subAgentDepth ?? '',\n // Audit F-A1-07: previously-missing dimensions that DO affect the\n // backend verdict. Without these, two requests with different\n // durations (e.g. 60s vs 86400s) collided on the same cache key and\n // the shorter-duration allow served the longer-duration request.\n request.durationRequired ?? '',\n request.invocationProtocol || '',\n request.enableRuntimeChallenge ? '1' : '0',\n // callerMetadata fields contribute to risk model; include the ones\n // backend reads. sourceIp/userAgent/forwardedFor change per-request\n // so their inclusion effectively forces a re-check for any varying\n // client (the right behavior — IP-driven anomaly scoring shouldn't\n // be cached across IPs).\n request.callerMetadata?.sourceIp || '',\n request.callerMetadata?.userAgent || '',\n request.callerMetadata?.forwardedFor || '',\n request.callerMetadata?.agentCardUrl || '',\n // UAT2 Bug B (5.4.1): the commerce phase and cart identity DO affect the\n // backend verdict — the confirm leg is the ONLY leg that may execute\n // first-party settlement. Without these, a confirm within the cache TTL of\n // its start_checkout quote was served the cached quote-leg grant (no\n // settlementOutcome) and never reached the backend. Same F-A1-07 bug class.\n request.commercePhase || '',\n request.checkoutSessionId || '',\n ].join('|');\n}\n\n/**\n * Check if cached result is still valid\n */\nfunction getCachedResult(\n request: VerificationRequest,\n counterpartyId?: string\n): VerificationResult | null {\n const key = getCacheKey(request, counterpartyId);\n const cached = verificationCache.get(key);\n\n if (cached && cached.expiresAt > Date.now()) {\n return cached.result;\n }\n\n if (cached) {\n verificationCache.delete(key);\n }\n\n return null;\n}\n\n/**\n * Cache a verification result.\n *\n * 3.6.0: uniform 60s default. The earlier step-up TTL split (300s for\n * step-up verdicts) is gone — step-up verdicts are no longer cached AT ALL\n * (see the write predicate in verify()): a cached step_up_required result\n * carries a pollUrl that goes stale (consumed/expired) and, worse, keeps\n * denying retries that the owner has already approved. When `configuredTtl`\n * is set (truthy positive number), it's honoured for cacheable results.\n */\nconst DEFAULT_CACHE_TTL_SECONDS = 60;\n\nfunction cacheResult(\n request: VerificationRequest,\n result: VerificationResult,\n configuredTtl: number | undefined,\n counterpartyId?: string\n): void {\n const ttlSeconds = configuredTtl && configuredTtl > 0 ? configuredTtl : DEFAULT_CACHE_TTL_SECONDS;\n const key = getCacheKey(request, counterpartyId);\n verificationCache.set(key, {\n result,\n expiresAt: Date.now() + ttlSeconds * 1000,\n });\n}\n\n/**\n * Clear the verification cache\n */\nexport function clearCache(): void {\n verificationCache.clear();\n}\n\n/**\n * Extract agent credentials from various sources\n */\nexport function extractCredentials(\n headers: Record<string, string | string[] | undefined>,\n query?: Record<string, string | undefined>\n): AgentCredentials {\n const credentials: AgentCredentials = {};\n\n // Audit F-A1-12: ASTRA-ID shape validation. Accept only the canonical\n // pattern (ASTRA-/ASTRAE- prefix + 1-64 url-safe chars) to prevent CRLF\n // header injection or downstream interpolation surprises. Reject otherwise.\n const ASTRA_ID_PATTERN = /^ASTRAE?-[A-Za-z0-9_-]{1,64}$/;\n\n // Check for ASTRA-ID in headers (case-insensitive). Accepts the historical\n // X-Astra-Id name plus the X-Astra-AgentId / x-astra-agent-id alias the\n // partner asked for in #9a — both surface the same field.\n const astraIdHeader =\n headers['x-astra-id'] ||\n headers['X-Astra-Id'] ||\n headers['X-ASTRA-ID'] ||\n headers['x-astra-agentid'] ||\n headers['X-Astra-AgentId'] ||\n headers['x-astra-agent-id'] ||\n headers['X-Astra-Agent-Id'] ||\n headers['X-ASTRA-AGENT-ID'];\n if (astraIdHeader) {\n // Audit F-A1-11: guard array-confusion. If multiple X-Astra-Id headers\n // were sent (Express collapses to comma-joined string on most paths),\n // take only the first canonical-shaped one.\n const raw = Array.isArray(astraIdHeader)\n ? astraIdHeader[0]\n : typeof astraIdHeader === 'string'\n ? astraIdHeader\n : undefined;\n if (typeof raw === 'string' && ASTRA_ID_PATTERN.test(raw)) {\n credentials.astraId = raw;\n }\n }\n\n // Check for API key in headers\n const apiKeyHeader = headers['x-api-key'] || headers['X-Api-Key'] || headers['X-API-KEY'];\n if (apiKeyHeader) {\n credentials.apiKey = Array.isArray(apiKeyHeader) ? apiKeyHeader[0] : apiKeyHeader;\n }\n\n // Check Authorization header for Bearer token.\n // Audit F-A1-11: defensive type guard — Array.isArray gives a non-string,\n // and Express path quirks can produce undefined despite the truthy check.\n const authHeader = headers['authorization'] || headers['Authorization'];\n if (authHeader) {\n const authValue = Array.isArray(authHeader) ? authHeader[0] : authHeader;\n if (typeof authValue === 'string') {\n credentials.authorizationHeader = authValue;\n if (authValue.startsWith('Bearer ')) {\n credentials.jwt = authValue.slice(7);\n }\n }\n }\n\n // Check query parameters as fallback\n if (query) {\n if (query.astraId && !credentials.astraId) {\n credentials.astraId = query.astraId;\n }\n if (query.apiKey && !credentials.apiKey) {\n credentials.apiKey = query.apiKey;\n }\n }\n\n return credentials;\n}\n\n/**\n * Check if credentials are present\n */\nexport function hasCredentials(credentials: AgentCredentials): boolean {\n return !!(credentials.astraId || credentials.apiKey || credentials.jwt);\n}\n\n/**\n * Source of a synthesised guidance response. The sources are split — the\n * `'no_credentials'` shape is the original (caller has no AstraSync\n * credentials, suggest registration). The `'api_error'` shape is for when\n * the verify-access HTTP call itself failed (5xx, network, etc.) — DON'T\n * tell a verified-but-currently-blocked partner to \"register your agent\".\n *\n * 4.0.0 adds `'merchant_misconfig'`: the backend rejected THIS INTEGRATION'S\n * own API key (401 api_key_revoked/expired/invalid). Neither the agent's\n * fault nor a platform outage — retrying won't help, and the inbound agent\n * deserves to know the site operator's integration is broken (the\n * gadget-emporium failure mode: a rotated key silently 401ing every\n * credentialed agent for days).\n */\ntype GuidanceSource = 'no_credentials' | 'api_error' | 'merchant_misconfig';\n\n/**\n * MCP-connector steering (5.1.0). Present only when the backend's well-known\n * doc advertises a hosted bridge. The copy must directly counter the observed\n * model refusal (\"go register manually on the dashboard\"): registration via\n * the connector is the agent's own next action, with the human approval built\n * into the flow.\n */\nfunction mcpGuidance(urls?: WellKnownAgenticCommerce): GuidanceInfo['mcp'] {\n if (!urls?.mcpEndpoint) return undefined;\n return {\n endpoint: urls.mcpEndpoint,\n discoveryUrl: urls.mcpDiscoveryUrl,\n message:\n 'If you are operating inside an MCP-capable host (Claude, ChatGPT, Cursor, or any MCP client), ' +\n 'add the AstraSync MCP connector instead of integrating these URLs by hand: registration through ' +\n 'the connector is KEYLESS and HUMAN-APPROVED — your human approves in an in-chat card, and you ' +\n 'never see, hold, or transmit an API key, password, or private key.',\n };\n}\n\n/**\n * Create guidance response for unverified agents or for API-error fallback.\n *\n * The source is split so the `register your agent` template\n * doesn't fire on transient backend failures. Also threads `correlationId`\n * through so adapter `onDenied` handlers can surface it on the merchant's\n * response body for log correlation.\n */\nfunction createGuidanceResponse(\n _config: GatewayConfig,\n reason?: string,\n options: {\n source?: GuidanceSource;\n correlationId?: string;\n /** 3.12.0 (Trust Record): server-echoed attempt handle, threaded like correlationId. */\n attemptId?: string;\n urls?: WellKnownAgenticCommerce;\n /** 4.0.0: backend-provided remediation URLs for the merchant (misconfig source). */\n remediation?: { docsUrl?: string; manageUrl?: string };\n } = {}\n): VerificationResult {\n const source = options.source ?? 'no_credentials';\n const isApiError = source === 'api_error';\n const isMisconfig = source === 'merchant_misconfig';\n const urls = options.urls;\n\n const guidance: GuidanceInfo = isMisconfig\n ? {\n message:\n \"This site's AstraSync integration is misconfigured (its API key was revoked, expired, or rotated). \" +\n 'Your identity and the AstraSync platform are fine — contact the site operator. Retrying will not help.',\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? '',\n steps: [\n 'Report the failure to the site operator — their AstraSync API key needs rotating',\n 'Do not retry: the failure is deterministic until the operator updates their key',\n ],\n }\n : isApiError\n ? {\n message:\n 'Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.',\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: urls?.documentationUrl ?? '',\n steps: [\n 'Retry the request with exponential backoff',\n 'If failures persist, share the correlationId with support',\n ],\n }\n : {\n message:\n 'This service verifies AI agents before granting access. Please register your agent with AstraSync.',\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: urls?.documentationUrl ?? '',\n steps: [\n // MCP steering leads when the hosted bridge is advertised — the\n // connector is the agent-actionable path (keyless, human-approved).\n ...(urls?.mcpEndpoint\n ? [\n `Fastest path (inside an MCP host): add the AstraSync MCP connector at ${urls.mcpEndpoint} — keyless, human-approved registration`,\n ]\n : []),\n 'Register for an AstraSync account',\n 'Create and register your agent',\n 'Add your ASTRA-ID to request headers',\n 'Retry your request',\n ],\n ...(mcpGuidance(urls) && { mcp: mcpGuidance(urls) }),\n };\n\n return {\n // Round-18 G4: createGuidanceResponse fires for unverified-agent path or\n // API-error fallback. Identity is not verified (no agent resolved);\n // policy is not evaluated (we never reached the gate).\n identityVerified: false,\n policyAllowed: false,\n guidance,\n denialReasons: reason ? [reason] : ['No valid agent credentials provided'],\n // Round-10 (#47, O5): on API-error fallback, surface a typed failure so\n // partners (and their custom onDenied handlers) can branch on\n // dimension. Without this, the synthesised stub was indistinguishable\n // from a real policy deny.\n failures: isMisconfig\n ? [\n {\n dimension: 'verify_access.merchant_misconfigured',\n message: reason ?? 'The integration API key was rejected by AstraSync',\n guidance: guidance.message,\n },\n ]\n : isApiError\n ? [\n {\n dimension: 'verify_access.api_error',\n message: reason ?? 'Verification temporarily unavailable',\n guidance: guidance.message,\n },\n ]\n : undefined,\n // 4.0.0: typed marker so adapters render the misconfig envelope (503 +\n // MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.\n ...(isMisconfig && { misconfigured: true }),\n // 4.6.0: a transient api_error is retryable — mark it so consumers surface\n // \"temporarily unavailable, retry\" (recommendation 'error') instead of\n // coercing the absent recommendation to a policy 'deny'. Misconfig is\n // deterministic and intentionally NOT marked retryable.\n ...(isApiError && { retryable: true }),\n correlationId: options.correlationId,\n attemptId: options.attemptId,\n verifiedAt: new Date(),\n };\n}\n\n/**\n * Call the AstraSync verify-access API\n */\nasync function callVerifyAccessAPI(\n config: GatewayConfig,\n request: VerificationRequest\n): Promise<{\n success: boolean;\n access?: {\n allowed: boolean;\n reason?: string;\n /**\n * Aggregated denial failures (v2.9.8+). Empty / absent when allowed.\n * Each entry is `{ dimension, message, guidance? }` — see\n * `AccessFailure` for the contract.\n */\n failures?: Array<{ dimension: string; message: string; guidance?: string }>;\n requiresStepUp?: boolean;\n requiresApproval?: boolean;\n appliedPolicy?: {\n boundaryName: string;\n policyVersion: string;\n };\n counterparty?: {\n id: string;\n name: string;\n trustScoreRequirement: number;\n };\n };\n agent?: {\n kyaAgentId: string;\n astraId: string;\n name: string;\n trustScore: number;\n trustLevel: string;\n agentStatus: string;\n blockchainStatus: string;\n };\n developer?: {\n kyaOwnerId: string;\n fullName: string;\n email: string;\n identityVerified: boolean;\n trustScore: number;\n };\n organization?: {\n name: string;\n verified: boolean;\n trustScore: number;\n };\n /**\n * Structured explanation of the verification decision. Tells the merchant\n * WHY (id verified? challenge passed? request within PDLSS? trust score?)\n * without exposing thresholds, scope lists, or other-tenant counterparty\n * membership. Empty `attestations` unless the endpoint's access policy\n * declared `required_attestations`.\n */\n verificationContext?: {\n idVerified: boolean;\n runtimeChallenge: {\n status: 'passed' | 'skipped' | 'failed' | 'timeout' | 'not_configured';\n checkedAt: string | null;\n };\n pdlssCheck: {\n result: 'within' | 'exceeded' | 'denied' | 'not_evaluated';\n purpose: 'approved' | 'denied';\n scope: 'approved' | 'denied';\n };\n dynamicTrustScore: number;\n attestations: Array<{\n type: string;\n status: 'passed' | 'failed';\n /** LMAX-POC C1: underlying check timestamp for merchant freshness gates. */\n checkedAt: string;\n validUntil?: string;\n proofType: 'reference' | 'zkp';\n proof: string;\n }>;\n };\n error?: string;\n /**\n * 4.0.0: the backend 401'd this integration's OWN API key (revoked /\n * expired / invalid) — deterministic merchant-side misconfig, not a\n * transient failure. `misconfigCode` carries the backend's api_key_* code\n * and `remediation` its operator-facing URLs when present.\n */\n misconfig?: boolean;\n misconfigCode?: string;\n remediation?: { docsUrl?: string; manageUrl?: string };\n /**\n * When the verify-access server response carries a\n * correlationId on an error envelope, propagate it so the SDK can thread\n * it through createGuidanceResponse → adapter onDenied → merchant body.\n */\n correlationId?: string;\n /**\n * 3.12.0 (Trust Record): the server echoes the attempt-chain\n * handle top-level on every response branch (error envelopes included).\n */\n attemptId?: string;\n}> {\n const { credentials, ...requestData } = request;\n\n // Build the request body. agentId is omitted when not provided so the\n // server treats it as an anonymous canonical-flow call (Branch A/B/C).\n const body: Record<string, unknown> = {\n ...(credentials.astraId && { agentId: credentials.astraId }),\n ...(requestData.purpose && { purpose: requestData.purpose }),\n };\n\n // Add optional fields\n if (requestData.action) body.action = requestData.action;\n if (requestData.resourceType) body.resourceType = requestData.resourceType;\n if (requestData.resource) body.resource = requestData.resource;\n if (requestData.jurisdiction) body.jurisdiction = requestData.jurisdiction;\n if (requestData.transactionValue) body.transactionValue = requestData.transactionValue;\n if (requestData.currency) body.currency = requestData.currency;\n if (requestData.isSubAgentRequest) body.isSubAgentRequest = requestData.isSubAgentRequest;\n if (requestData.parentAgentId) body.parentAgentId = requestData.parentAgentId;\n if (requestData.subAgentDepth !== undefined) body.subAgentDepth = requestData.subAgentDepth;\n // Handshake Protocol v10 additions\n if (requestData.enableRuntimeChallenge)\n body.enableRuntimeChallenge = requestData.enableRuntimeChallenge;\n if (requestData.createSession) body.createSession = requestData.createSession;\n if (requestData.durationRequired) body.durationRequired = requestData.durationRequired;\n if (requestData.counterpartyType) body.counterpartyType = requestData.counterpartyType;\n if (requestData.counterpartyUrl) body.counterpartyUrl = requestData.counterpartyUrl;\n if (config.counterpartyId) body.counterpartyId = config.counterpartyId;\n if (requestData.runtimeChallengeOptions)\n body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;\n // Round-12 (F19): transport-vs-intent separation. MCP middleware sets\n // this to 'mcp'; non-MCP callers leave it unset.\n if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;\n // 5.3.0 (astra-pay): checkout-leg discriminator — first-party settlement\n // fires only on 'confirm'; absent keeps pre-phase server behavior.\n if (requestData.commercePhase) body.commercePhase = requestData.commercePhase;\n // Per-cart idempotency key (checkout session id) forwarded on the confirm\n // leg so concurrent confirms for one cart charge at most once.\n if (requestData.checkoutSessionId) body.checkoutSessionId = requestData.checkoutSessionId;\n // Order-plane cart lines (receipts + fulfillment email) — informational.\n if (requestData.checkoutItems) body.checkoutItems = requestData.checkoutItems;\n // 5.6.0 (astra-pay): transit-only fulfilment contact — echoed back in\n // result.fulfilment for first-party confirms, never persisted server-side.\n if (requestData.buyerEmail) body.buyerEmail = requestData.buyerEmail;\n // 3.9.0 (§33.5 #1): raw commerce artifacts forwarded verbatim — the\n // backend's Step 0.5 pipeline does the cryptographic verification\n // server-side (adapters forward, never verify locally).\n if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;\n // 3.12.0 (Trust Record, §33.5 #3): attempt-chain handle + consideration set,\n // forwarded skip-when-undefined (observedMetadata precedent) — pure\n // observational pass-through; the server echoes attemptId on every branch.\n if (requestData.attemptId) body.attemptId = requestData.attemptId;\n if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;\n\n // Round-13 (F14 closure / R13-7): emit the SDK package version on every\n // verify-access body so the backend can auto-populate `kya_counterparty.\n // sdk_version` for the calling endpoint. Body field (not User-Agent\n // header) is the canonical channel — works in Node, browser, behind\n // Cloudflare, and across SDK bundlers without environment-specific\n // header gymnastics. Backend's `validation.ts:verifyAccessSchema`\n // accepts the semver regex; the auto-pop logic is forward-only.\n body.sdkVersion = SDK_VERSION;\n\n // Forward caller metadata when present. Merges the legacy top-level\n // clientIp/userAgent into the nested block for backward compatibility.\n if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {\n const meta = {\n ...(requestData.clientIp && { sourceIp: requestData.clientIp }),\n ...(requestData.userAgent && { userAgent: requestData.userAgent }),\n ...requestData.callerMetadata,\n };\n if (Object.keys(meta).length > 0) body.callerMetadata = meta;\n }\n\n // Build headers\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...config.customHeaders,\n };\n\n // verify-access requires authentication. Use ONLY the merchant's\n // configured apiKey for outbound auth. Previously the caller's inbound\n // Authorization header took priority, which pivoted the verify-access\n // call to the caller's identity — letting an attacker who supplied\n // their own Authorization header trigger verify-access calls under\n // THEIR account and observe the resulting verdicts for arbitrary\n // lookups they triggered via the merchant. Audit F-A1-10.\n //\n // The caller-supplied JWT (if any) is already extracted to\n // credentials.jwt and travels in the verify-access request body so\n // backend can evaluate it as the agent's identity claim — separate from\n // the merchant-attribution auth on the outbound HTTPS call.\n if (config.apiKey) {\n headers['Authorization'] = `Bearer ${config.apiKey}`;\n // Legacy header kept for compatibility with any middleware that reads it directly.\n headers['X-API-Key'] = config.apiKey;\n }\n\n try {\n // 4.0.0: hard timeout — without one, a backend that accepts the\n // connection but never answers hangs the merchant's middleware and every\n // inbound agent request behind it (observed live on a partner property).\n // Timeouts land on the catch path below → api_error (fail-closed),\n // NOT misconfig. The edge adapter races its own tighter withBudget.\n const response = await sdkFetch(`${config.apiBaseUrl}/agents/verify-access`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 10_000),\n });\n\n const data = await response.json();\n\n // v2.3.8 (defect #29): treat 410 Gone as a deterministic deactivated-endpoint\n // signal. Older SDKs may treat any non-2xx as transient and retry; v2.3.8+\n // surfaces it as a structured denial with `reason: 'endpoint_deactivated'`\n // so callers can distinguish \"endpoint gone\" from \"endpoint denied this\".\n if (response.status === 410) {\n return {\n success: true,\n // 3.12.0 (Trust Record): keep the server-echoed attempt handle even on\n // the synthesised 410 deny shape (echoed on every branch).\n attemptId: typeof data?.attemptId === 'string' ? data.attemptId : undefined,\n access: {\n allowed: false,\n reason: 'endpoint_deactivated',\n failures: [\n {\n dimension: 'endpoint.deactivated',\n message:\n typeof data?.message === 'string' ? data.message : 'Endpoint has been deactivated',\n guidance:\n typeof data?.guidance === 'string'\n ? data.guidance\n : 'Reactivate via POST /api/endpoints/{id}/reactivate, or update the URL on the calling agent.',\n },\n ],\n },\n };\n }\n\n // 5.10.0: a caller-supplied agent id that isn't a canonical ASTRA-id\n // (e.g. `ASTRA-bogus123`) is a deterministic failed identity claim, not\n // an outage. Previously it fell through to the transient api_error path,\n // so the edge answered 503 \"verification unavailable — retry\" under\n // enforce; it is now an identity deny (403 + registration guidance).\n if (response.status === 400 && data?.error === 'INVALID_AGENT_ID') {\n const message =\n typeof data?.message === 'string'\n ? data.message\n : 'Agent identifier must be a canonical ASTRA-* id.';\n return {\n success: true,\n attemptId: typeof data?.attemptId === 'string' ? data.attemptId : undefined,\n access: {\n allowed: false,\n reason: 'invalid_agent_id',\n failures: [\n {\n dimension: 'identity.invalid_agent_id',\n message,\n guidance:\n typeof data?.guidance === 'string'\n ? data.guidance\n : 'Present your canonical ASTRA-* id (discover it via GET /api/agents/request-registration/{requestId} after owner approval).',\n },\n ],\n },\n };\n }\n\n if (!response.ok) {\n // 4.0.0: a 401 from verify-access can ONLY mean the backend rejected\n // THIS INTEGRATION'S own API key — agent denials come back as 200 with\n // access.allowed=false. Surface it as merchant-misconfig, not a\n // transient api_error: it is deterministic until the operator rotates\n // the key, and the \"retry with backoff\" template actively misleads.\n // Backends ≥ this round also send code: api_key_* + remediation URLs.\n if (response.status === 401) {\n return {\n success: false,\n error: data.message || data.error || 'Integration API key rejected',\n misconfig: true,\n misconfigCode: typeof data?.code === 'string' ? data.code : undefined,\n remediation:\n data?.remediation && typeof data.remediation === 'object'\n ? (data.remediation as { docsUrl?: string; manageUrl?: string })\n : undefined,\n correlationId: typeof data?.correlationId === 'string' ? data.correlationId : undefined,\n attemptId: typeof data?.attemptId === 'string' ? data.attemptId : undefined,\n };\n }\n // Round-10 (#47, O5): propagate correlationId on the error path too if\n // the server happened to include one (some 5xx error envelopes carry\n // it). Lets the SDK pass it through to the adapter onDenied handler.\n return {\n success: false,\n error: data.message || data.error || `API returned ${response.status}`,\n correlationId: typeof data?.correlationId === 'string' ? data.correlationId : undefined,\n attemptId: typeof data?.attemptId === 'string' ? data.attemptId : undefined,\n };\n }\n\n return data;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n error: `Failed to call verify-access API: ${message}`,\n };\n }\n}\n\n/**\n * Options for a single verify() call (as opposed to GatewayConfig, which is\n * per-gateway). Mirrors the Java SDK's `verify(request, bypassCache)`.\n */\nexport interface VerifyOptions {\n /**\n * Skip the cache READ for this call so the request is guaranteed to reach\n * the backend (the result is still written to the cache if cacheable).\n * Used by the step-up hold-and-poll retry: the re-verify after an approval\n * must hit the server to redeem the single-use approval.\n */\n bypassCache?: boolean;\n}\n\n/**\n * Main verification function\n */\nexport async function verify(\n config: GatewayConfig,\n request: VerificationRequest,\n options?: VerifyOptions\n): Promise<VerificationResult> {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n\n // v2.5.0: read well-known URLs from cache (prefetched by adapter at middleware creation).\n // Synchronous — never triggers a fetch. If cache is empty, guidance URLs are empty strings.\n const urls = mergedConfig.apiBaseUrl\n ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl)\n : undefined;\n\n // One-time init self-test — fire-and-forget by default, never blocks verify().\n // Audit F-A6-33: when GatewayConfig.strictInit is set, the init promise is\n // awaited and any failure throws synchronously so callers learn about\n // misconfigured apiBaseUrl on the first verify() call rather than silently\n // running with broken auth.\n if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {\n if (mergedConfig.strictInit) {\n await performInitCheck(\n mergedConfig.apiBaseUrl,\n mergedConfig.debug,\n true,\n mergedConfig.apiKey\n );\n } else {\n void performInitCheck(\n mergedConfig.apiBaseUrl,\n mergedConfig.debug,\n false,\n mergedConfig.apiKey\n );\n }\n }\n\n // Deprecation warning for v2.3.0 removed config fields. Fires once per process.\n if (\n !deprecationWarningShown &&\n (config.minTrustScore !== undefined || config.minTrustScoreForFull !== undefined)\n ) {\n deprecationWarningShown = true;\n console.warn(\n '[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 ' +\n 'and have no effect. Server is now the single source of truth for access decisions ' +\n '(verified ID + runtime challenge + PDLSS + trust score). To gate access ' +\n \"to an endpoint, configure the endpoint's trust_score_requirement server-side.\"\n );\n }\n\n // v2.3.0: anonymous traffic no longer short-circuits here. We forward the\n // request to the server with no agentId; the server applies the endpoint's\n // unverifiedAgentPolicy and returns advisory. createGuidanceResponse remains\n // as the offline fallback if the API itself fails (handled below).\n\n // Check cache first. Caching on unless caller explicitly sets cacheTtl: 0\n // to disable. Undefined falls through to the 60s default at cacheResult\n // write time. options.bypassCache skips the read only (hold-and-poll retry\n // must reach the backend to redeem its approval).\n if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {\n const cached = getCachedResult(request, mergedConfig.counterpartyId);\n if (cached) {\n if (mergedConfig.debug) {\n console.log('[VerificationGateway] Returning cached result');\n }\n // 3.12.0 (Trust Record, §33.5 #3): attemptId is excluded from the cache\n // key, so the stored result may carry a PRIOR attempt's id. Overwrite it\n // with this request's own attemptId — or drop it when this request has\n // none — a cached verdict must never leak another attempt's handle.\n // Shallow clone: never mutate the stored entry (a concurrent holder of\n // the same cached object may still be reading it).\n const hit: VerificationResult = { ...cached };\n if (request.attemptId) {\n hit.attemptId = request.attemptId;\n } else {\n delete hit.attemptId;\n }\n return hit;\n }\n }\n\n // Inject counterparty info from config if not already set in request\n const enrichedRequest = { ...request };\n if (!enrichedRequest.counterpartyUrl && mergedConfig.counterpartyUrl) {\n enrichedRequest.counterpartyUrl = mergedConfig.counterpartyUrl;\n }\n if (!enrichedRequest.counterpartyType && mergedConfig.counterpartyType) {\n enrichedRequest.counterpartyType = mergedConfig.counterpartyType;\n }\n\n // Call the API\n if (mergedConfig.debug) {\n console.log('[VerificationGateway] Calling verify-access API');\n }\n\n const apiResponse = await callVerifyAccessAPI(mergedConfig, enrichedRequest);\n\n // 3.6.0: the server emits a top-level denialReasons array on every deny\n // path (same strings as the failure messages). Non-empty → authoritative;\n // absent/empty → fall back to the client-side reconstructions below.\n const rawServerDenialReasons = (apiResponse as Record<string, unknown>).denialReasons;\n const serverDenialReasons =\n Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0\n ? (rawServerDenialReasons as string[])\n : undefined;\n\n // Handle API errors\n if (!apiResponse.success) {\n // Round-10 (#47, O5): distinguish API errors from missing-credentials.\n // The previous default tagged any failure with the \"register your\n // agent\" template, which is misleading to a verified partner whose\n // verify-access call hit a 500. The `api_error` source surfaces a\n // typed `verify_access.api_error` failure entry instead.\n // 4.0.0: a rejected merchant key gets its own source — deterministic\n // misconfig must not wear the \"temporarily unavailable, retry\" template.\n return createGuidanceResponse(mergedConfig, apiResponse.error, {\n source: apiResponse.misconfig ? 'merchant_misconfig' : 'api_error',\n correlationId: (apiResponse as { correlationId?: string }).correlationId,\n attemptId: (apiResponse as { attemptId?: string }).attemptId,\n remediation: apiResponse.remediation,\n urls,\n });\n }\n\n // Check access result\n if (!apiResponse.access?.allowed) {\n // v2.9.8 (defect M1): aggregated failures across every gate that\n // denied. Surface them on the result so the integrator can see every\n // blocker in one go instead of the previous fail-fast cascade.\n const aggregatedFailures = (apiResponse.access as Record<string, unknown> | undefined)\n ?.failures as Array<{ dimension: string; message: string; guidance?: string }> | undefined;\n // Round-18 G4: backend denied access (PDLSS or other gate); identity status\n // depends on whether the backend resolved the caller. Read from\n // verificationContext.idVerified; default false if absent (anonymous or\n // identity-fail paths land here too). policyAllowed is false by definition\n // in this branch (apiResponse.access.allowed === false).\n const idVerifiedFromBackend =\n (apiResponse.verificationContext as { idVerified?: boolean } | undefined)?.idVerified ===\n true;\n const result: EnhancedVerificationResult = {\n identityVerified: idVerifiedFromBackend,\n policyAllowed: false,\n // 3.6.0: the server now emits top-level denialReasons on every deny\n // path — prefer it verbatim; the failure-message reconstruction remains\n // as the fallback for older backends.\n denialReasons:\n serverDenialReasons ??\n (aggregatedFailures && aggregatedFailures.length > 0\n ? aggregatedFailures.map((f) => f.message)\n : apiResponse.access?.reason\n ? [apiResponse.access.reason]\n : ['Access denied']),\n failures: aggregatedFailures,\n requiresStepUp: apiResponse.access?.requiresStepUp,\n requiresApproval: apiResponse.access?.requiresApproval,\n guidance: {\n message: apiResponse.access?.reason || 'Access denied by PDLSS policy',\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: urls?.documentationUrl ?? '',\n // 5.1.0: anonymous callers land on this branch — steer MCP-hosted\n // agents to the connector (this is what the edge deny body surfaces).\n ...(mcpGuidance(urls) && { mcp: mcpGuidance(urls) }),\n },\n verifiedAt: new Date(),\n // Extract sessionId so decisions can be recorded for denials too\n sessionId: (apiResponse as Record<string, unknown>).sessionId as string | undefined,\n // Anonymous traffic has no session → correlationId is the per-attempt\n // linking key (the sessionId-equivalent for anonymous callers).\n correlationId: (apiResponse as Record<string, unknown>).correlationId as string | undefined,\n // 3.12.0 (Trust Record): server echoes the attempt-chain handle on\n // every branch — denials included (the funnel outlives one deny).\n attemptId: (apiResponse as Record<string, unknown>).attemptId as string | undefined,\n recommendation: (apiResponse as Record<string, unknown>)\n .recommendation as EnhancedVerificationResult['recommendation'],\n recommendationReasons: (apiResponse as Record<string, unknown>).recommendationReasons as\n | string[]\n | undefined,\n stepUpApproval: (apiResponse as Record<string, unknown>).stepUpApproval as\n | StepUpApprovalInfo\n | undefined,\n settlement: (apiResponse as Record<string, unknown>).settlement as\n | SettlementArtifact\n | undefined,\n settlementOutcome: (apiResponse as Record<string, unknown>).settlementOutcome as\n | SettlementOutcomeInfo\n | undefined,\n // 5.5.0 self-settlement: merchant-only material — passes through to the\n // MERCHANT caller only (bridge callers strip it before the agent plane).\n settlementToken: (apiResponse as Record<string, unknown>).settlementToken as\n | MerchantSettlementToken\n | undefined,\n // 5.6.0: fulfilment contact — merchant-only lane, same strip rule.\n fulfilment: (apiResponse as Record<string, unknown>).fulfilment as FulfilmentInfo | undefined,\n };\n\n return result;\n }\n\n // Build successful result\n const agent: VerifiedAgent | undefined = apiResponse.agent\n ? {\n astraId: apiResponse.agent.astraId,\n name: apiResponse.agent.name,\n trustScore: apiResponse.agent.trustScore,\n trustLevel: getTrustLevel(apiResponse.agent.trustScore),\n blockchainAnchored: apiResponse.agent.blockchainStatus === 'anchored',\n status: apiResponse.agent.agentStatus as VerifiedAgent['status'],\n }\n : undefined;\n\n const developer: VerifiedDeveloper | undefined = apiResponse.developer\n ? {\n astradId: apiResponse.developer.kyaOwnerId,\n name: apiResponse.developer.fullName,\n trustScore: apiResponse.developer.trustScore || 0,\n verified: apiResponse.developer.identityVerified,\n }\n : undefined;\n\n const organization: VerifiedOrganization | undefined = apiResponse.organization\n ? {\n name: apiResponse.organization.name,\n verified: apiResponse.organization.verified,\n trustScore: apiResponse.organization.trustScore,\n }\n : undefined;\n\n // Verification context — structured \"why\" the merchant gets in v2.2.4+.\n // Carries appliedPolicy (no UUIDs), pdlssCheck summary, dynamic trust score,\n // and policy-driven attestations. Replaces the old over-sharing `pdlss` block.\n const verificationContext = apiResponse.verificationContext;\n\n const result: EnhancedVerificationResult = {\n // 4.5.0 (probe F1): read idVerified from verificationContext with the\n // SAME absent⇒false default as the deny branch. The previous `!== false`\n // default manufactured `identityVerified: true` for anonymous\n // allow_full/allow_partial/audit responses (which allow access but omit\n // verificationContext entirely) — the \"anonymous caller labelled\n // verified\" defect. Every authenticated success response has carried\n // `verificationContext.idVerified: true` since v2.2.4, so a truth claim\n // this load-bearing must never be defaulted on.\n identityVerified:\n (apiResponse.verificationContext as { idVerified?: boolean } | undefined)?.idVerified ===\n true,\n policyAllowed: true,\n agent,\n developer,\n organization,\n appliedPolicy: apiResponse.access?.appliedPolicy,\n verificationContext,\n requiresStepUp: apiResponse.access?.requiresStepUp,\n requiresApproval: apiResponse.access?.requiresApproval,\n verifiedAt: new Date(),\n cacheTtl: mergedConfig.cacheTtl,\n // Handshake Protocol v10 enhanced fields (present when backend returns them)\n sessionId: (apiResponse as Record<string, unknown>).sessionId as string | undefined,\n // v2.3.10 (defect #34, round-4): anonymous responses surface correlationId\n // (no session row exists for unverified callers).\n correlationId: (apiResponse as Record<string, unknown>).correlationId as string | undefined,\n // 3.12.0 (Trust Record): server-echoed attempt-chain handle.\n attemptId: (apiResponse as Record<string, unknown>).attemptId as string | undefined,\n runtimeChallenge: (apiResponse as Record<string, unknown>).runtimeChallenge as\n | RuntimeChallengeResult\n | undefined,\n tokenGuidance: (apiResponse as Record<string, unknown>).tokenGuidance as\n | TokenGuidance\n | undefined,\n recommendation: (apiResponse as Record<string, unknown>)\n .recommendation as EnhancedVerificationResult['recommendation'],\n recommendationReasons: (apiResponse as Record<string, unknown>).recommendationReasons as\n | string[]\n | undefined,\n warningHeader: (apiResponse as Record<string, unknown>).warningHeader as\n | { name: string; value: string }\n | undefined,\n stepUpApproval: (apiResponse as Record<string, unknown>).stepUpApproval as\n | StepUpApprovalInfo\n | undefined,\n settlement: (apiResponse as Record<string, unknown>).settlement as\n | SettlementArtifact\n | undefined,\n settlementOutcome: (apiResponse as Record<string, unknown>).settlementOutcome as\n | SettlementOutcomeInfo\n | undefined,\n settlementToken: (apiResponse as Record<string, unknown>).settlementToken as\n | MerchantSettlementToken\n | undefined,\n // 5.6.0: fulfilment contact — merchant-only lane, same strip rule.\n fulfilment: (apiResponse as Record<string, unknown>).fulfilment as FulfilmentInfo | undefined,\n };\n\n // Enforce AstraSync recommendation\n if (result.recommendation === 'deny') {\n // Round-18 G4: recommendation-driven deny lands on the success-path\n // construction (identity was resolved). Flip policy only — identity stays\n // verified — so adapters return 403 (re-auth won't help; the policy\n // decision is the blocker).\n result.policyAllowed = false;\n // 3.6.0: server-sent top-level denialReasons wins; recommendationReasons\n // reconstruction is the fallback for older backends.\n result.denialReasons = serverDenialReasons ??\n result.recommendationReasons ?? ['Access denied by AstraSync recommendation'];\n result.guidance = result.runtimeChallenge\n ? {\n message: `Verification failed: ${result.runtimeChallenge.reason || 'runtime challenge failed'}`,\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: urls?.documentationUrl ?? '',\n }\n : {\n message: result.recommendationReasons?.[0] || 'Access denied by AstraSync recommendation',\n registrationUrl: urls?.registrationUrl ?? '',\n documentationUrl: urls?.documentationUrl ?? '',\n };\n } else if (result.recommendation === 'step_up_required') {\n // The escalation signal rides on `requiresStepUp` / `stepUpApproval`, not\n // on any masquerade of the (now-removed) access band.\n result.requiresStepUp = true;\n result.denialReasons = serverDenialReasons ??\n result.recommendationReasons ?? ['Step-up verification required'];\n }\n\n // Cache the result. Never cache denials (agent may fix challenge endpoint\n // and retry) NOR step-up escalations (3.6.0 — the same bug the Java SDK\n // had: a cached step_up_required verdict keeps denying retries the owner\n // has already approved, and its pollUrl goes stale once consumed/expired).\n // Escalations stay uncached even when the caller pins an explicit cacheTtl.\n const escalates =\n result.requiresStepUp === true ||\n result.requiresApproval === true ||\n result.recommendation === 'step_up_required';\n if (mergedConfig.cacheTtl !== 0 && result.recommendation !== 'deny' && !escalates) {\n cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);\n }\n\n return result;\n}\n\n/**\n * Record a counterparty's grant/deny decision for a verification session.\n * Fire-and-forget — errors are silently swallowed.\n */\nexport async function recordDecision(\n config: GatewayConfig,\n sessionId: string,\n decision: 'granted' | 'denied',\n reason?: string\n): Promise<void> {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (config.apiKey) {\n headers['Authorization'] = `Bearer ${config.apiKey}`;\n headers['X-API-Key'] = config.apiKey;\n }\n\n await sdkFetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ decision, reason }),\n }).catch(() => {\n /* fire-and-forget */\n });\n}\n\n/**\n * Report post-hoc consideration/outcome data for an attempt chain (Trust\n * Record). Use when the signal never reached verify-access: a\n * catalog served from a local cache, a transport-side deny (sku not found,\n * over budget), or a terminal outcome (settled / blocked on step-up).\n * Authenticated with the same credentials as verify(); the backend responds\n * 202 and folds the data into the attempt chain keyed by `attemptId`.\n *\n * Fire-and-forget — errors are silently swallowed, never throws.\n */\nexport async function reportAttempt(config: GatewayConfig, report: AttemptReport): Promise<void> {\n const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl!;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (config.apiKey) {\n headers['Authorization'] = `Bearer ${config.apiKey}`;\n headers['X-API-Key'] = config.apiKey;\n }\n\n // counterpartyId resolution mirrors reportUnregisteredAttempt: an explicit\n // report value wins; otherwise attribute to the configured endpoint.\n const body = {\n ...report,\n ...(!report.counterpartyId &&\n config.counterpartyId && { counterpartyId: config.counterpartyId }),\n };\n\n await sdkFetch(`${apiBaseUrl}/agents/verify-access/attempt-report`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n }).catch(() => {\n /* fire-and-forget */\n });\n}\n\n/**\n * Fetch the per-route policy for an endpoint from the AstraSync backend.\n * v2.9.7 moved policy authority into the dashboard — the SDK no longer\n * accepts `routes` from merchant-side source code, it fetches them from\n * here on init (and refreshes periodically).\n *\n * Returns `null` when the request fails for any reason — the caller decides\n * how to fall back (the middleware allows-all when no policy is loaded so\n * a misconfigured init doesn't take down the merchant's API).\n */\nexport async function fetchRoutes(\n config: GatewayConfig,\n counterpartyId: string\n): Promise<RouteAccessConfigShape[] | null> {\n if (!counterpartyId) return null;\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (config.apiKey) {\n headers['Authorization'] = `Bearer ${config.apiKey}`;\n headers['X-API-Key'] = config.apiKey;\n }\n try {\n const response = await sdkFetch(\n `${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,\n { method: 'GET', headers }\n );\n if (!response.ok) return null;\n const body = (await response.json()) as { data?: { routes?: RouteAccessConfigShape[] } };\n return body.data?.routes ?? [];\n } catch {\n return null;\n }\n}\n\n/**\n * Minimal shape of an EndpointRoute as the SDK consumes it. Mirrors the\n * server's `EndpointRoute` type and the SDK's `RouteAccessConfig` — same\n * JSON moves between server and SDK unchanged.\n */\nexport interface RouteAccessConfigShape {\n pattern: string;\n method: string;\n /** Pass through unenforced (observe). Replaces `minAccessLevel: 'none'`. */\n observe?: boolean;\n minTrustScore?: number;\n requiredPurposes?: string[];\n allowedPurposes?: string[];\n allowedJurisdictions?: string[];\n maxDuration?: number;\n maxTransactionValue?: number;\n requirePurpose?: boolean;\n /** Send-mapping — see RouteAccessConfig in types.ts. */\n purpose?: string;\n action?: string;\n}\n\n/**\n * Verify an agent AND automatically record the grant/deny decision.\n *\n * This is the recommended entry point for counterparties that call verify()\n * directly (e.g. MCP servers) rather than using createMiddleware().\n * It adds createSession: true, then fire-and-forgets the decision.\n */\nexport async function verifyAndRecord(\n config: GatewayConfig,\n request: VerificationRequest,\n options?: VerifyOptions\n): Promise<VerificationResult> {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n const result = await verify(mergedConfig, { ...request, createSession: true }, options);\n const sessionId = (result as EnhancedVerificationResult).sessionId;\n\n if (sessionId) {\n // Round-18 G4: a session is \"granted\" only if identity verified AND\n // policy allowed; either failing is a deny.\n if (result.identityVerified && result.policyAllowed) {\n recordDecision(mergedConfig, sessionId, 'granted').catch(() => {});\n } else {\n recordDecision(mergedConfig, sessionId, 'denied', result.denialReasons?.[0]).catch(() => {});\n }\n }\n\n return result;\n}\n\n/**\n * Report an unregistered agent attempt (no AstraSync credentials).\n * Called by SDK adapters when an agent is redirected to /docs/agent-access.\n * Fire-and-forget — errors are silently swallowed.\n */\nexport async function reportUnregisteredAttempt(\n config: GatewayConfig,\n data: {\n /**\n * 3.6.0: optional — the backend attributes by counterpartyId first (sent\n * from config below) and requires at least ONE of counterpartyId/URL.\n * A null/undefined URL is omitted from the body, not sent as null.\n */\n counterpartyUrl?: string;\n counterpartyType?: string;\n sourceIp?: string;\n userAgent?: string;\n requestPath?: string;\n requestMethod?: string;\n /**\n * VI uplift Part 3 — attempt-chain handle (`att_<32hex>`, from the\n * X-Astra-Attempt-Id header or an `?astra_attempt=` deep link). Joins\n * the beacon into the agent's research chain. Attribution only.\n */\n attemptId?: string;\n /** First-class referer (traffic-source reporting). */\n referer?: string;\n /** The caller's Accept header (surface-classifier input). */\n accept?: string;\n /** Self-declared platform from X-Astra-Source (attribution, never trust). */\n declaredSource?: string;\n /**\n * 3.9.0 — edge-adapter evidence fields, persisted into the\n * event's eventData by the backend: `protocol` = detected transport/\n * credential protocol; `evidence` = light crypto-free detection detail.\n */\n protocol?: string;\n evidence?: Record<string, unknown>;\n /**\n * Maximal metadata capture — the full sanitised metadata for an\n * unregistered caller (every signal legitimately visible on the wire).\n * Persisted into eventData; feeds platform attribution and (via\n * correlationId) registration auto-fill. Fire-and-forget, so free.\n */\n observedMetadata?: ObservedMetadata;\n }\n): Promise<void> {\n const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl!;\n\n const { counterpartyUrl, ...rest } = data;\n const body = {\n ...rest,\n ...(counterpartyUrl && { counterpartyUrl }),\n ...(config.counterpartyId && { counterpartyId: config.counterpartyId }),\n };\n\n await sdkFetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n }).catch(() => {\n /* fire-and-forget */\n });\n}\n\n/**\n * Report a counterparty-side PDLSS pre-check failure.\n * Called by SDK adapters when the agent's requested PDLSS exceeds\n * counterparty-defined maximums BEFORE calling verify-access.\n * Fire-and-forget — errors are silently swallowed.\n */\nexport async function reportCounterpartyPreCheckFailure(\n config: GatewayConfig,\n data: {\n agentId: string;\n counterpartyUrl: string;\n counterpartyType?: string;\n failures: Array<{\n field: string;\n requested: string | number;\n limit: string | number | string[];\n message: string;\n }>;\n requestPath?: string;\n requestMethod?: string;\n }\n): Promise<void> {\n const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl!;\n\n await sdkFetch(`${apiBaseUrl}/verification-activity/counterparty-pre-check-failure`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n }).catch(() => {\n /* fire-and-forget */\n });\n}\n\n/**\n * Quick verification — checks credentials and policy in one call.\n *\n * The return shape mirrors `VerificationResult`'s split — partners\n * writing custom handlers around `quickVerify` get the same identity/policy\n * distinction as those calling `verify()` directly. Map to HTTP status the\n * same way: `!identityVerified` → 401; `identityVerified && !policyAllowed`\n * → 403.\n */\nexport async function quickVerify(\n config: GatewayConfig,\n credentials: AgentCredentials\n): Promise<{\n identityVerified: boolean;\n policyAllowed: boolean;\n reason?: string;\n}> {\n const result = await verify(config, {\n credentials,\n purpose: 'verification',\n });\n\n return {\n identityVerified: result.identityVerified,\n policyAllowed: result.policyAllowed,\n reason: result.denialReasons?.[0],\n };\n}\n","/**\n * Step-up hold-and-poll (3.6.0) — the synchronous half of the MFA-style gate,\n * mirroring the Java SDK's `awaitStepUpApproval` / `pollStepUpStatus`.\n *\n * A verify() that comes back step_up_required carries a `stepUpApproval`\n * handle: `{ approvalId, pollUrl, expiresAt }`. The adapter HOLDS the original\n * request, polls the approval status, and on 'approved' re-verifies the same\n * request once (cache-bypassed) so the backend redeems the single-use approval\n * and returns a grant. Any other terminal outcome falls into the adapter's\n * normal fail-closed deny path.\n *\n * The poll endpoint is deliberately unauthenticated (it sits above the\n * backend router's `authenticate` middleware): the unguessable UUIDv4\n * approvalId is the capability token, and the route is rate-limited\n * (60/min/IP). No Authorization header is sent.\n */\n\nimport { sdkFetch } from '../http';\nimport { GatewayConfig, StepUpApprovalInfo, StepUpApprovalStatus, StepUpOutcome } from '../types';\n\nconst DEFAULT_POLL_INTERVAL_MS = 3000;\nconst MIN_POLL_INTERVAL_MS = 250;\nconst FALLBACK_MAX_WAIT_MS = 5 * 60 * 1000;\nconst EXPIRY_GRACE_MS = 5000;\nconst POLL_REQUEST_TIMEOUT_MS = 10_000;\n\n/** Resolve the absolute poll URL. pollUrl is server-relative\n * (`/api/step-up-approvals/poll/:id`), so join it to apiBaseUrl minus its\n * `/api` suffix (the origin) — same idiom as well-known.ts. Absolute URLs\n * pass through untouched. */\nfunction resolvePollUrl(config: GatewayConfig, pollUrl: string): string {\n if (pollUrl.startsWith('http')) return pollUrl;\n const origin = (config.apiBaseUrl ?? '').replace(/\\/api\\/?$/, '');\n return origin + pollUrl;\n}\n\n/**\n * One GET of the approval's poll endpoint. Returns the status string, or\n * null on any error / non-2xx / unparsable body — the hold loop treats null\n * as transient and just polls again.\n */\nexport async function pollStepUpStatus(\n config: GatewayConfig,\n approval: StepUpApprovalInfo\n): Promise<StepUpApprovalStatus | null> {\n if (!approval.pollUrl) return null;\n try {\n const res = await sdkFetch(resolvePollUrl(config, approval.pollUrl), {\n method: 'GET',\n signal: AbortSignal.timeout(POLL_REQUEST_TIMEOUT_MS),\n });\n if (!res.ok) return null;\n const body = (await res.json()) as Record<string, unknown>;\n // Envelope shape: { success, data: { status, resolvedAt } } — a flat\n // `status` read hangs every hold (live-UAT catch). Envelope-first with a\n // flat fallback for forward compatibility, exactly like the Java SDK.\n const data = body?.data;\n const status =\n data && typeof data === 'object' ? (data as Record<string, unknown>).status : body?.status;\n return typeof status === 'string' ? (status as StepUpApprovalStatus) : null;\n } catch {\n return null; // transient poll failure — the loop just polls again\n }\n}\n\nfunction resolveDeadline(config: GatewayConfig, approval: StepUpApprovalInfo): number {\n const now = Date.now();\n const maxWait = config.stepUpMaxWaitMs ?? 0;\n if (maxWait > 0) return now + maxWait;\n // stepUpMaxWaitMs === 0: hold until the approval itself expires (+ a small\n // grace so an approval landing at the buzzer still resolves on the next\n // poll). Missing/unparsable expiresAt → fixed 5-min fallback (Java parity).\n if (approval.expiresAt) {\n const expiry = Date.parse(approval.expiresAt);\n if (!Number.isNaN(expiry)) return Math.max(now, expiry) + EXPIRY_GRACE_MS;\n }\n return now + FALLBACK_MAX_WAIT_MS;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Block until a pending step-up approval reaches a terminal state or the wait\n * budget runs out. Returns the terminal status, or 'timeout'.\n *\n * Unknown non-pending statuses (a future backend state) still terminate the\n * hold — they are returned as-is and land in the deny path, which is the safe\n * reading of \"not approved\".\n */\nexport async function awaitStepUpApproval(\n config: GatewayConfig,\n approval: StepUpApprovalInfo\n): Promise<StepUpOutcome> {\n const deadline = resolveDeadline(config, approval);\n const pollInterval = Math.max(\n MIN_POLL_INTERVAL_MS,\n config.stepUpPollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS\n );\n\n while (Date.now() < deadline) {\n const status = await pollStepUpStatus(config, approval);\n if (status && status !== 'pending') {\n return status as StepUpOutcome;\n }\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n await sleep(Math.min(pollInterval, remaining));\n }\n return 'timeout';\n}\n","/**\n * Maximal metadata capture — the shared, edge-safe sanitiser.\n *\n * AstraSync's thesis is total metadata capture: every header and connection\n * signal an inbound agent presents is a signal we want to keep. This module is\n * the ONE place that decides what is safe to store verbatim, what is a secret\n * to drop, and what credential headers reduce to a safe *format prefix* (a\n * platform signal, never the secret itself).\n *\n * It runs in three places that must agree byte-for-byte:\n * - the edge adapter (`@astrasyncai/adapter-lambda`) — the richest capture\n * point (full CloudFront header arrays),\n * - the SDK adapters (express / nextjs) — for SDK-only merchants with no edge,\n * - (indirectly) the backend, which stores whatever the above forward.\n *\n * Pure — no Node built-ins, no I/O — so it is safe in Lambda@Edge, the browser\n * build, and Deno. Capture is cheap: at the edge and SDK it is local string\n * work, and the backend stores it on a fire-and-forget event insert, so it adds\n * ZERO verify-access decision latency. Detection (which few signals imply which\n * vendor) is a separate, curated concern — see `platform-signatures.ts`.\n */\n\n/**\n * Version of the capture semantics (what is kept, dropped, reduced, or\n * derived — and under which key names).\n *\n * Capture semantics are FROZEN within a package major version: a given\n * `schemaVersion` always means the same field vocabulary and the same\n * keep/drop/reduce rules. The number bumps only on a SEMANTIC change to\n * capture (a renamed key, a changed reduction rule) — never for additive\n * signals, and never merely because the package version moved. To tell\n * builds apart, use the `sdkVersion` already present on the verify body;\n * `schemaVersion` answers the different question \"how do I interpret this\n * stored metadata?\".\n */\nexport const CAPTURE_SCHEMA_VERSION = 1;\n\n/**\n * The captured, sanitised view of an inbound agent's request metadata. Attached\n * to verify-access / beacon payloads as `callerMetadata.observedMetadata`.\n */\nexport interface ObservedMetadata {\n /** Header name → value, secrets removed, verbatim otherwise. */\n headers: Record<string, string>;\n /**\n * Safe key-format prefix of a credential header (e.g. `sk-ant-api03`,\n * `sk-proj`, `AIza`) — a platform signal, NEVER the secret. Absent if no\n * credential header was present or none matched a known format.\n */\n apiKeyFormat?: string;\n /**\n * The subset of `headers` that are known platform-signal headers\n * (`openai-organization`, `x-goog-user-project`, `anthropic-version`, …),\n * pulled out for convenient detection + display. Values are the same\n * sanitised strings as in `headers`.\n */\n platformHeaders?: Record<string, string>;\n /**\n * Connection-layer signals (IP, ASN, country, TLS version, HTTP version,\n * device class, TLS fingerprint). Edge adapters populate this from the\n * platform's native connection surface — the authoritative source. SDK\n * adapters populate it as a fallback via {@link deriveConnectionFromHeaders}\n * when a CDN in front of the merchant injected the equivalent headers;\n * absent when neither source had anything.\n */\n connection?: Record<string, string>;\n /**\n * Number of cookie pairs the caller sent. The `cookie` header VALUE is a\n * secret and is always dropped; the COUNT is a client-shape signal\n * (browsers carry cookies, most automation carries none) that would\n * otherwise be unobservable downstream. Absent when no cookie header\n * arrived.\n */\n cookieCount?: number;\n /**\n * Query-string parameter NAMES (deduped, lowercased) — values are NEVER\n * captured (they routinely carry OAuth codes, tokens, and PII, and no\n * deny-list is complete). Names alone fingerprint client shape. Populated\n * by the edge path, which sees the raw query string.\n */\n queryKeys?: string[];\n /**\n * Query-string VALUES for parameter names the endpoint owner explicitly\n * allow-listed (`EdgeConfig.queryValueAllowlist`, seeded `utm_*` — VI\n * uplift Part 4). The default remains NO value capture; this exists so\n * campaign attribution (utm_source/medium/campaign) can be reported\n * without widening the privacy stance. Bounded 16 entries × 256 chars.\n */\n queryParams?: Record<string, string>;\n /**\n * Version of the capture semantics this object was produced under — see\n * {@link CAPTURE_SCHEMA_VERSION}. Optional for backward compatibility with\n * metadata captured before the field existed.\n */\n schemaVersion?: number;\n}\n\n/**\n * Result of sanitising a raw header map. `headers` is always present (possibly\n * empty); `apiKeyFormat` / `platformHeaders` only when a signal was found.\n */\nexport interface SanitizeHeadersResult {\n headers: Record<string, string>;\n apiKeyFormat?: string;\n platformHeaders?: Record<string, string>;\n /** Cookie-pair count; the cookie value itself is always dropped. */\n cookieCount?: number;\n}\n\n/**\n * Header names dropped entirely — genuine secrets or our own credentials that\n * describe the request's transport, not the agent. Matched case-insensitively\n * on the exact header name.\n */\nconst SECRET_HEADER_NAMES = new Set([\n 'cookie',\n 'set-cookie',\n 'x-csrf-token',\n 'proxy-authorization',\n 'x-astrasync-signature',\n 'x-astrasync-secret',\n 'x-hub-signature',\n 'x-hub-signature-256',\n // Short-lived verify dedupe token — must never persist in stored metadata.\n 'x-astra-verified-hop',\n]);\n\n/**\n * Header-name prefixes dropped entirely — our own credential / signing surface\n * (`x-astrasync-*`, `kya-*`) must never round-trip into stored metadata.\n */\nconst SECRET_HEADER_PREFIXES = ['x-astrasync-', 'kya-', 'kya_'];\n\n/**\n * Credential headers whose VALUE is a secret but whose FORMAT is a signal. We\n * keep the leading format prefix (up to the random tail) and drop the rest.\n */\nconst CREDENTIAL_HEADER_NAMES = new Set([\n 'authorization',\n 'x-api-key',\n 'x-goog-api-key',\n 'api-key',\n]);\n\n/**\n * Header names that carry a raw signature value (drop the value; the presence\n * is not worth a bloat risk). Matched as a suffix so `x-*-signature` variants\n * are covered without an exhaustive list.\n */\nfunction isSignatureHeader(name: string): boolean {\n return name === 'signature' || name.endsWith('-signature') || name.endsWith('-signature-256');\n}\n\n/**\n * Known platform-signal headers — pulled into `platformHeaders` for convenient\n * detection + display. Exact names plus a few prefixes (`x-goog-`,\n * `x-stainless-` — the OpenAI/Anthropic SDK client fingerprint headers).\n */\nconst PLATFORM_HEADER_NAMES = new Set([\n 'openai-organization',\n 'openai-project',\n 'openai-version',\n 'openai-processing-ms',\n 'anthropic-version',\n 'anthropic-beta',\n 'x-goog-user-project',\n 'x-goog-api-client',\n 'user-agent',\n 'x-agent-card-url',\n 'x-agent-provider',\n]);\n// `sec-ch-*` client hints are platform signals: Chromium forks (agentic\n// browsers included) often carry their real brand in `sec-ch-ua` even when\n// the UA string mimics stock Chrome.\nconst PLATFORM_HEADER_PREFIXES = [\n 'x-goog-',\n 'x-stainless-',\n 'x-anthropic-',\n 'x-openai-',\n 'sec-ch-',\n];\n\n/**\n * Known API-key format prefixes, longest-first so `sk-ant-api03` wins over\n * `sk-ant` and `sk-`. Each is the SAFE, non-secret leading token of a\n * credential; the random tail is never captured.\n */\nconst KEY_FORMAT_PREFIXES = [\n 'sk-ant-api03',\n 'sk-ant-api',\n 'sk-ant',\n 'sk-proj',\n 'sk-svcacct',\n 'sk-or-v1',\n 'sk-or',\n 'sk-lf',\n 'sk-',\n 'gsk_',\n 'aiza',\n 'ya29',\n 'ghp_',\n 'gho_',\n 'github_pat_',\n 'xai-',\n 'pplx-',\n 'r8_',\n 'hf_',\n 'astra-',\n 'astrae-',\n];\n\n/** Size caps — the only guard against jsonb bloat from a hostile POST. */\nexport const MAX_HEADERS = 64;\nexport const MAX_HEADER_VALUE_BYTES = 1024;\nexport const MAX_TOTAL_BYTES = 16 * 1024;\n\n/**\n * `X-Astra-Source` declared-source protocol (VI uplift Part 2). The header is\n * SELF-ASSERTED and spoofable — it buys attribution, never trust: it is never\n * read by any access decision and never conflated with fingerprint-matched\n * (`platformVendor`) or ASTRA-verified evidence. One shared validator so the\n * edge, backend, and bridge accept byte-identical values.\n */\nexport const DECLARED_SOURCE_MAX = 64;\nconst DECLARED_SOURCE_PATTERN = /^[a-z0-9][a-z0-9 ._/-]{0,63}$/;\n\nexport function normalizeDeclaredSource(value: string | undefined | null): string | undefined {\n const trimmed = value?.trim().slice(0, DECLARED_SOURCE_MAX).toLowerCase();\n return trimmed && DECLARED_SOURCE_PATTERN.test(trimmed) ? trimmed : undefined;\n}\n\nfunction byteLength(s: string): number {\n // Edge-safe (no Buffer): count UTF-8 bytes without allocating a Buffer.\n let bytes = 0;\n for (let i = 0; i < s.length; i++) {\n const code = s.charCodeAt(i);\n if (code < 0x80) bytes += 1;\n else if (code < 0x800) bytes += 2;\n else if (code >= 0xd800 && code <= 0xdbff) {\n bytes += 4;\n i++; // surrogate pair\n } else bytes += 3;\n }\n return bytes;\n}\n\n/**\n * Extract the safe key-format prefix from a credential header value. Strips a\n * leading `Bearer ` / `Basic ` scheme, then returns the longest known prefix\n * that the (lowercased) value starts with. Returns undefined for opaque values\n * (e.g. a bare UUID token) so we never guess a format we don't recognise.\n */\nexport function extractApiKeyFormat(rawValue: string): string | undefined {\n if (!rawValue) return undefined;\n let value = rawValue.trim();\n const spaceIdx = value.indexOf(' ');\n if (spaceIdx > 0) {\n const scheme = value.slice(0, spaceIdx).toLowerCase();\n if (scheme === 'bearer' || scheme === 'basic' || scheme === 'token') {\n value = value.slice(spaceIdx + 1).trim();\n }\n }\n const lower = value.toLowerCase();\n for (const prefix of KEY_FORMAT_PREFIXES) {\n if (lower.startsWith(prefix)) {\n // Return the prefix as-declared in the list (canonical casing).\n return prefix;\n }\n }\n return undefined;\n}\n\nfunction isSecretHeader(name: string): boolean {\n if (SECRET_HEADER_NAMES.has(name)) return true;\n if (SECRET_HEADER_PREFIXES.some((p) => name.startsWith(p))) return true;\n if (isSignatureHeader(name)) return true;\n return false;\n}\n\nfunction isPlatformHeader(name: string): boolean {\n if (PLATFORM_HEADER_NAMES.has(name)) return true;\n return PLATFORM_HEADER_PREFIXES.some((p) => name.startsWith(p));\n}\n\n/**\n * Sanitise a raw header map for storage. Deny-lists genuine secrets, reduces\n * credential headers to a safe format prefix, keeps everything else verbatim,\n * and enforces the size caps that bound jsonb growth.\n *\n * Accepts any string→(string|string[]|undefined) map (Node's `req.headers`,\n * CloudFront's flattened headers, a plain object). Multi-value headers are\n * joined with `, ` per RFC 7230.\n */\nexport function sanitizeHeaders(\n raw: Record<string, string | string[] | undefined> | undefined | null\n): SanitizeHeadersResult {\n const headers: Record<string, string> = {};\n const platformHeaders: Record<string, string> = {};\n let apiKeyFormat: string | undefined;\n let cookieCount: number | undefined;\n let totalBytes = 0;\n let count = 0;\n\n if (!raw) return { headers };\n\n for (const rawName of Object.keys(raw)) {\n if (count >= MAX_HEADERS) break;\n const name = rawName.toLowerCase();\n const rawValue = raw[rawName];\n if (rawValue === undefined) continue;\n const joined = Array.isArray(rawValue) ? rawValue.join(', ') : String(rawValue);\n\n // Credential headers: capture the format prefix, drop the secret.\n if (CREDENTIAL_HEADER_NAMES.has(name)) {\n const fmt = extractApiKeyFormat(joined);\n if (fmt && !apiKeyFormat) apiKeyFormat = fmt;\n continue;\n }\n\n // Cookie: the value is a secret (dropped below), but the PAIR COUNT is a\n // client-shape signal worth keeping.\n if (name === 'cookie') {\n cookieCount = joined.split(';').filter((s) => s.trim().length > 0).length;\n }\n\n // Genuine secrets: drop entirely.\n if (isSecretHeader(name)) continue;\n\n // Everything else describing the agent: keep, bounded.\n let value = joined;\n if (byteLength(value) > MAX_HEADER_VALUE_BYTES) {\n value = value.slice(0, MAX_HEADER_VALUE_BYTES);\n }\n const entryBytes = byteLength(name) + byteLength(value);\n if (totalBytes + entryBytes > MAX_TOTAL_BYTES) continue;\n totalBytes += entryBytes;\n count++;\n headers[name] = value;\n if (isPlatformHeader(name)) platformHeaders[name] = value;\n }\n\n const result: SanitizeHeadersResult = { headers };\n if (apiKeyFormat) result.apiKeyFormat = apiKeyFormat;\n if (Object.keys(platformHeaders).length > 0) result.platformHeaders = platformHeaders;\n if (cookieCount !== undefined) result.cookieCount = cookieCount;\n return result;\n}\n\n/**\n * Pull the known platform-signal headers out of an ALREADY-sanitised header\n * map. `sanitizeHeaders` already computes this as a by-product; this standalone\n * form is exported for call-sites (edge, tests) that hold a sanitised map and\n * want only the platform subset. Never re-run over raw (unsanitised) headers.\n */\nexport function extractPlatformHeaders(\n sanitized: Record<string, string> | undefined | null\n): Record<string, string> {\n const out: Record<string, string> = {};\n if (!sanitized) return out;\n for (const name of Object.keys(sanitized)) {\n if (isPlatformHeader(name.toLowerCase())) out[name.toLowerCase()] = sanitized[name];\n }\n return out;\n}\n\n/**\n * Precedence-ordered CDN header sources for each derived `connection` key.\n * First present header wins; the special `x-forwarded-for` source takes the\n * LEFTMOST (client) entry of the comma-separated chain.\n */\nconst CONNECTION_HEADER_SOURCES: ReadonlyArray<readonly [key: string, headers: readonly string[]]> =\n [\n ['ip', ['cf-connecting-ip', 'fastly-client-ip', 'true-client-ip', 'x-real-ip']],\n [\n 'country',\n ['cf-ipcountry', 'x-vercel-ip-country', 'cloudfront-viewer-country', 'fastly-geo-country'],\n ],\n ['region', ['x-vercel-ip-country-region', 'cloudfront-viewer-country-region']],\n ['countryRegionName', ['cloudfront-viewer-country-region-name']],\n ['city', ['x-vercel-ip-city', 'cloudfront-viewer-city']],\n ['latitude', ['x-vercel-ip-latitude', 'cloudfront-viewer-latitude']],\n ['longitude', ['x-vercel-ip-longitude', 'cloudfront-viewer-longitude']],\n ['postalCode', ['x-vercel-ip-postal-code', 'cloudfront-viewer-postal-code']],\n ['asn', ['cloudfront-viewer-asn']],\n ['tlsVersion', ['cloudfront-viewer-tls']],\n ['httpVersion', ['cloudfront-viewer-http-version']],\n ['timeZone', ['x-vercel-ip-timezone', 'cloudfront-viewer-time-zone']],\n ['metroCode', ['cloudfront-viewer-metro-code']],\n // TLS fingerprints can only be computed where TLS terminates. When a CDN\n // terminates TLS in front of the merchant, its fingerprint headers ARE the\n // connection-layer truth — normalising them here is the permanent design.\n // CloudFront delivers JA3/JA4 only via an origin request policy and only\n // for HTTPS viewer connections.\n ['tlsFingerprint', ['cf-ja3-hash', 'cloudfront-viewer-ja3-fingerprint']],\n ['ja4', ['cf-ja4', 'cloudfront-viewer-ja4-fingerprint']],\n // Header-structure fingerprint: browser/SDK-distinctive header ordering.\n ['headerOrder', ['cloudfront-viewer-header-order']],\n ['headerCount', ['cloudfront-viewer-header-count']],\n ];\n\n/**\n * Backend bound: observedMetadata.connection values longer than this fail\n * the platform's zod parse outright (boundedStringRecord(32, 256)), so every\n * emitter truncates — headerOrder routinely exceeds it.\n */\nexport const MAX_CONNECTION_VALUE_CHARS = 256;\n\n/**\n * Derive the connection-layer block from CDN-injected request headers.\n *\n * When a merchant's SDK-gated origin sits behind a CDN (Cloudflare, Fastly,\n * Vercel, CloudFront), the CDN has already seen the connection layer and\n * injected it as headers. This promotes those headers to the same\n * `connection` keys the edge adapters populate natively, so SDK-only\n * deployments still get IP / geo / TLS attribution. Precedence per key:\n *\n * - `ip`: `cf-connecting-ip` > `fastly-client-ip` > `true-client-ip` >\n * `x-real-ip` > `cloudfront-viewer-address` (port stripped) > leftmost\n * `x-forwarded-for`\n * - `country`: `cf-ipcountry` > `x-vercel-ip-country` >\n * `cloudfront-viewer-country` > `fastly-geo-country`\n * - `region` / `city` / `timeZone`: Vercel then CloudFront viewer headers\n * - `countryRegionName` / `asn` / `tlsVersion` / `httpVersion` /\n * `metroCode` / `headerOrder` / `headerCount`: `cloudfront-viewer-*`\n * - `tlsFingerprint`: `cf-ja3-hash` > `cloudfront-viewer-ja3-fingerprint`\n * - `ja4`: `cf-ja4` > `cloudfront-viewer-ja4-fingerprint`\n *\n * All keys are additive under `schemaVersion` 1 (the frozen-capture doctrine\n * bumps only for changed semantics, never for additive signals). Values are\n * truncated to MAX_CONNECTION_VALUE_CHARS — the platform's hard bound.\n *\n * Edge adapters keep their richer native collectors — native platform\n * signals are authoritative; this header derivation is the SDK-level\n * fallback. Header names are matched case-insensitively. Returns undefined\n * when no source header is present, so the `connection` key is simply\n * omitted (matching edge behaviour).\n */\nexport function deriveConnectionFromHeaders(\n headers: Record<string, string> | undefined | null\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n const lower: Record<string, string> = {};\n for (const name of Object.keys(headers)) {\n const value = headers[name];\n if (typeof value === 'string' && value.length > 0) lower[name.toLowerCase()] = value;\n }\n\n const connection: Record<string, string> = {};\n for (const [key, sources] of CONNECTION_HEADER_SOURCES) {\n for (const source of sources) {\n const value = lower[source]?.trim();\n if (value) {\n connection[key] = value.slice(0, MAX_CONNECTION_VALUE_CHARS);\n break;\n }\n }\n }\n // ip fallback 1: cloudfront-viewer-address arrives as ip:port — strip the\n // trailing port only (IPv6-safe), unlike the dedicated client-ip headers.\n // The port itself is kept as its own key: ephemeral-port patterns signal\n // NAT/proxy connection reuse.\n {\n const addr = lower['cloudfront-viewer-address']?.trim();\n const portMatch = addr?.match(/:(\\d+)$/);\n if (portMatch) connection.sourcePort = portMatch[1];\n if (!connection.ip && addr) connection.ip = addr.replace(/:\\d+$/, '');\n }\n // ip fallback 2: leftmost (client) hop of the x-forwarded-for chain.\n if (!connection.ip) {\n const xff = lower['x-forwarded-for'];\n const client = xff?.split(',')[0]?.trim();\n if (client) connection.ip = client;\n }\n // tlsCipher: CloudFront folds the cipher into the viewer-tls string\n // (`TLSv1.3:TLS_AES_128_GCM_SHA256:fullHandshake`). `tlsVersion` stays\n // verbatim (reducing it would be a semantic change → schema v2); the\n // cipher is pulled out additively so it is queryable on its own.\n if (!connection.tlsCipher) {\n const cipher = connection.tlsVersion?.split(':')[1];\n if (cipher) connection.tlsCipher = cipher;\n }\n\n return Object.keys(connection).length > 0 ? connection : undefined;\n}\n\n/**\n * The FULL metadata capture for one request at an SDK adapter (express /\n * nextjs / mcp): sanitised headers, the safe credential format prefix, the\n * platform-signal subset, the CDN-derived connection block, and the capture\n * schema version. This is the ONE builder all SDK adapters share, so their\n * verify-access bodies agree byte-for-byte.\n *\n * Connection derivation runs over the RAW header map (pre-cap) — the size\n * caps guard storage growth and must never hide a geo/IP header that\n * happened to arrive late in an oversized map.\n */\nexport function buildSdkObservedMetadata(\n rawHeaders: Record<string, string | string[] | undefined> | undefined | null\n): ObservedMetadata {\n const { headers, apiKeyFormat, platformHeaders, cookieCount } = sanitizeHeaders(rawHeaders);\n const flat: Record<string, string> = {};\n if (rawHeaders) {\n for (const name of Object.keys(rawHeaders)) {\n const value = rawHeaders[name];\n if (value === undefined) continue;\n flat[name.toLowerCase()] = Array.isArray(value) ? value.join(', ') : String(value);\n }\n }\n const connection = deriveConnectionFromHeaders(flat);\n return {\n headers,\n ...(apiKeyFormat && { apiKeyFormat }),\n ...(platformHeaders && { platformHeaders }),\n ...(connection && { connection }),\n ...(cookieCount !== undefined && { cookieCount }),\n schemaVersion: CAPTURE_SCHEMA_VERSION,\n };\n}\n","/**\n * Edge verification config — the per-endpoint policy the Trusted Agent\n * Gateway edge adapters (e.g. `@astrasyncai/adapter-lambda`) fetch from the\n * AstraSync dashboard to decide how much verification friction to apply\n * to inbound traffic, and where.\n *\n * Fetch pattern mirrors `well-known.ts`: TTL cache + stale-while-revalidate\n * + in-flight dedupe, with a `_reset*` hook for tests. Fail posture is\n * deliberately asymmetric: this module can NEVER put a site into enforce\n * mode on its own — enforce only ever originates from a successfully\n * fetched config, and a config that has gone stale past `maxStaleMs`\n * degrades back to observe.\n *\n * Which EdgeConfig fields each integration consumes:\n *\n * | Field | Edge adapters | SDK adapters (express/nextjs/mcp) |\n * | ------------------------------ | ------------- | --------------------------------- |\n * | `mode` (observe/enforce) | yes | — |\n * | `depth` | yes | — |\n * | `pathRules` | yes | — |\n * | `sampling.anonymousBeaconRate` | yes | yes — the SDK anonymous beacon |\n * | `failurePosture` | yes | — |\n *\n * The observe/enforce × depth posture is EDGE-ONLY by design: SDK adapters\n * enforce via the dashboard route policy (`fetchRoutes`), not via this\n * config, and consume only the `sampling` block for their anonymous\n * traffic beacon.\n */\n\nimport { sdkFetch } from './http';\nimport type { GatewayConfig } from './types';\n\n/**\n * Edge posture. Canonical Trusted Agent Gateway vocabulary:\n * `observe` ≈ the gateway's `passive` posture (verify +\n * record, enforce nothing), `enforce` ≈ `active`. New value set on a new\n * field name — do NOT reuse `GatewayPosture`'s `active`/`passive` here\n * (different field, different meaning: posture governs an agent-side\n * gateway; mode governs counterparty-side edge interception).\n */\nexport type EdgeMode = 'observe' | 'enforce';\n\n/**\n * How deep the edge checks each request — what is it → who is it → are\n * they allowed:\n * - `classify` — UA / platform-fingerprint classification only; no\n * credential handling.\n * - `authenticate` — establish who is calling: detect and parse agent\n * credentials (X-Astra-*, VI SD-JWT, RFC 9421, ACP,\n * UCP, AP2…) and verify presented AstraSync identities.\n * - `authorize` — full policy decision: credentials cryptographically\n * proven and PDLSS-evaluated via a verify-access round\n * trip. (US spelling on the wire, matching\n * `authorizeSettlement` and HTTP `Authorization`.)\n */\nexport type EdgeVerificationDepth = 'classify' | 'authenticate' | 'authorize';\n\nexport interface EdgePathRule {\n /**\n * `*`-wildcard glob matched against the request path. Matching is\n * case-INsensitive and all regex metacharacters except `*` are\n * escaped. (Deliberately diverges from the express adapter's\n * `matchRoute`, which is historically case-sensitive by default —\n * new surface ships case-insensitive matching as the default.)\n */\n pattern: string;\n /** Pass the request through untouched (static assets); mode/depth ignored. */\n skip?: boolean;\n /** Override the top-level mode for this path. */\n mode?: EdgeMode;\n /** Override the top-level depth for this path. */\n depth?: EdgeVerificationDepth;\n /**\n * Per-path beacon sampling opt-DOWN (VI uplift 1.2). The default is full\n * capture; put a fractional rate on explicitly high-volume/low-value paths\n * (static mirrors, health checks) instead of sampling commerce traffic.\n */\n sampling?: {\n /** Fraction (0..1) of anonymous-bot requests that emit a beacon. */\n anonymousBeaconRate: number;\n };\n}\n\nexport interface EdgeConfig {\n /** Shape version — bump on breaking changes. */\n version: 1;\n /** Default posture for paths no rule matches. */\n mode: EdgeMode;\n /** Default check depth for paths no rule matches. */\n depth: EdgeVerificationDepth;\n /** Ordered, first-match-wins. */\n pathRules: EdgePathRule[];\n sampling: {\n /** Fraction (0..1) of anonymous-bot requests that emit a beacon. */\n anonymousBeaconRate: number;\n };\n /**\n * Query-string parameter names whose VALUES may be captured into\n * `observedMetadata.queryParams` (VI uplift Part 4 — campaign/UTM\n * attribution). Lowercase exact names or a single trailing-`*` glob\n * (`utm_*`); ≤16 entries × ≤64 chars. ABSENT by default — the privacy\n * stance (query values dropped at capture) is unchanged unless the\n * endpoint owner explicitly configures this.\n */\n queryValueAllowlist?: string[];\n /**\n * 4.5.0: the EFFECTIVE failure posture is derived from the effective\n * mode — fail posture follows success posture. Observe fails open\n * (unreachable backend = pass-through, site never breaks); enforce fails\n * closed on verification-infrastructure failure (503\n * `VERIFICATION_UNAVAILABLE`, retry-later — see edge-core/pipeline). This\n * field is retained on the wire for adapter compatibility and as a future\n * explicit override; it is not consulted by the 4.5.x pipeline. Note the\n * distinction from CONFIG staleness: a config stale past 24h still has\n * enforce degraded to observe (`degradeToObserve`) — that is config-trust\n * hygiene, independent of runtime verification availability.\n */\n failurePosture: 'open' | 'closed';\n}\n\n/**\n * The safe default: observe-only, classification depth, nothing enforced.\n * Served by the backend when an endpoint has never been configured, and\n * used by `getEdgeConfig` whenever no config can be fetched.\n *\n * Beacon rate 1.0 (VI uplift 1.2): every anonymous hit beacons by default —\n * a sampled denominator understates anonymous traffic in every dashboard\n * tile and no toggle can reveal the dropped rows. Sampling is a deliberate\n * per-path opt-down (`EdgePathRule.sampling`) for static/high-volume paths.\n */\nexport const DEFAULT_EDGE_CONFIG: EdgeConfig = Object.freeze({\n version: 1,\n mode: 'observe',\n depth: 'classify',\n pathRules: [],\n sampling: Object.freeze({ anonymousBeaconRate: 1.0 }),\n failurePosture: 'open',\n}) as EdgeConfig;\n\nconst EDGE_MODES: readonly string[] = ['observe', 'enforce'];\nconst EDGE_DEPTHS: readonly string[] = ['classify', 'authenticate', 'authorize'];\n\nfunction isSamplingShape(value: unknown): value is { anonymousBeaconRate: number } {\n if (typeof value !== 'object' || value === null) return false;\n const rate = (value as Record<string, unknown>).anonymousBeaconRate;\n return typeof rate === 'number' && rate >= 0 && rate <= 1;\n}\n\n/** Structural guard for configs arriving over the wire. */\nexport function isEdgeConfig(value: unknown): value is EdgeConfig {\n if (typeof value !== 'object' || value === null) return false;\n const v = value as Record<string, unknown>;\n if (v.version !== 1) return false;\n if (!EDGE_MODES.includes(v.mode as string)) return false;\n if (!EDGE_DEPTHS.includes(v.depth as string)) return false;\n if (!Array.isArray(v.pathRules)) return false;\n for (const rule of v.pathRules) {\n if (typeof rule !== 'object' || rule === null) return false;\n const r = rule as Record<string, unknown>;\n if (typeof r.pattern !== 'string' || r.pattern.length === 0) return false;\n if (r.mode !== undefined && !EDGE_MODES.includes(r.mode as string)) return false;\n if (r.depth !== undefined && !EDGE_DEPTHS.includes(r.depth as string)) return false;\n if (r.sampling !== undefined && !isSamplingShape(r.sampling)) return false;\n }\n if (!isSamplingShape(v.sampling)) return false;\n if (v.queryValueAllowlist !== undefined) {\n if (\n !Array.isArray(v.queryValueAllowlist) ||\n v.queryValueAllowlist.length > 16 ||\n !v.queryValueAllowlist.every((e) => typeof e === 'string' && e.length > 0 && e.length <= 64)\n ) {\n return false;\n }\n }\n return v.failurePosture === 'open';\n}\n\nexport interface FetchEdgeConfigSuccess {\n edgeConfig: EdgeConfig;\n etag?: string;\n}\n\nexport type FetchEdgeConfigResult = FetchEdgeConfigSuccess | { notModified: true } | null;\n\n/**\n * Fetch the edge config for an endpoint from the AstraSync backend.\n * `GET {apiBaseUrl}/endpoints/:counterpartyId/edge-config` with the same\n * auth headers as `fetchRoutes`. Pass the cached `etag` to get a cheap\n * `{ notModified: true }` on 304. Returns `null` on any failure —\n * the caller decides how to fall back.\n */\nexport async function fetchEdgeConfig(\n config: Pick<GatewayConfig, 'apiBaseUrl' | 'apiKey'>,\n counterpartyId: string,\n opts?: { etag?: string; timeoutMs?: number }\n): Promise<FetchEdgeConfigResult> {\n if (!counterpartyId) return null;\n const headers: Record<string, string> = { Accept: 'application/json' };\n if (config.apiKey) {\n headers['Authorization'] = `Bearer ${config.apiKey}`;\n headers['X-API-Key'] = config.apiKey;\n }\n if (opts?.etag) headers['If-None-Match'] = opts.etag;\n try {\n const response = await sdkFetch(\n `${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/edge-config`,\n { method: 'GET', headers, signal: AbortSignal.timeout(opts?.timeoutMs ?? 5000) }\n );\n if (response.status === 304) return { notModified: true };\n if (!response.ok) return null;\n const body = (await response.json()) as { data?: { edgeConfig?: unknown } };\n const edgeConfig = body.data?.edgeConfig;\n if (!isEdgeConfig(edgeConfig)) return null;\n return { edgeConfig, etag: response.headers.get('etag') ?? undefined };\n } catch {\n return null;\n }\n}\n\ninterface CacheEntry {\n config: EdgeConfig;\n etag?: string;\n /** When the entry was last confirmed fresh (fetch or 304). */\n lastSuccessAt: number;\n}\n\nconst DEFAULT_TTL_MS = 60 * 1000;\nconst DEFAULT_MAX_STALE_MS = 24 * 60 * 60 * 1000;\n\nconst cache = new Map<string, CacheEntry>();\nconst inflight = new Map<string, Promise<void>>();\n\nfunction cacheKey(apiBaseUrl: string, counterpartyId: string): string {\n return `${apiBaseUrl}|${counterpartyId}`;\n}\n\n/** Copy of `config` with every enforce (top-level and per-rule) degraded to observe. */\nexport function degradeToObserve(config: EdgeConfig): EdgeConfig {\n if (config.mode !== 'enforce' && !config.pathRules.some((r) => r.mode === 'enforce')) {\n return config;\n }\n return {\n ...config,\n mode: 'observe',\n pathRules: config.pathRules.map((r) => (r.mode === 'enforce' ? { ...r, mode: 'observe' } : r)),\n };\n}\n\nasync function revalidate(\n config: Pick<GatewayConfig, 'apiBaseUrl' | 'apiKey'>,\n counterpartyId: string\n): Promise<void> {\n const key = cacheKey(config.apiBaseUrl, counterpartyId);\n const existing = inflight.get(key);\n if (existing) return existing;\n\n const promise = fetchEdgeConfig(config, counterpartyId, { etag: cache.get(key)?.etag })\n .then((result) => {\n if (result === null) return; // failure — cache untouched, caller falls back\n const now = Date.now();\n if ('notModified' in result) {\n const entry = cache.get(key);\n if (entry) entry.lastSuccessAt = now;\n return;\n }\n cache.set(key, { config: result.edgeConfig, etag: result.etag, lastSuccessAt: now });\n })\n .finally(() => {\n inflight.delete(key);\n });\n\n inflight.set(key, promise);\n return promise;\n}\n\n/**\n * Get the edge config for an endpoint, cached. Never throws, never blocks\n * longer than one fetch.\n *\n * - Fresh cache (within `ttlMs`) → cached config, no network.\n * - Stale cache → cached config immediately + background revalidate\n * (stale-while-revalidate). If the last successful fetch is older than\n * `maxStaleMs` (default 24h), any enforce is degraded to observe — a\n * long-dead backend can never keep a site enforcing.\n * - No cache → await one fetch; on failure return `DEFAULT_EDGE_CONFIG`\n * (observe-only). Defaults never enforce.\n */\nexport async function getEdgeConfig(\n config: Pick<GatewayConfig, 'apiBaseUrl' | 'apiKey'>,\n counterpartyId: string,\n opts?: { ttlMs?: number; maxStaleMs?: number }\n): Promise<EdgeConfig> {\n const ttlMs = opts?.ttlMs ?? DEFAULT_TTL_MS;\n const maxStaleMs = opts?.maxStaleMs ?? DEFAULT_MAX_STALE_MS;\n const key = cacheKey(config.apiBaseUrl, counterpartyId);\n\n const entry = cache.get(key);\n if (entry) {\n const age = Date.now() - entry.lastSuccessAt;\n if (age > ttlMs) {\n revalidate(config, counterpartyId).catch(() => {\n // background refresh failed — stale entry remains until next call\n });\n }\n return age > maxStaleMs ? degradeToObserve(entry.config) : entry.config;\n }\n\n await revalidate(config, counterpartyId).catch(() => {\n // fetch failed — fall through to defaults\n });\n return cache.get(key)?.config ?? DEFAULT_EDGE_CONFIG;\n}\n\n/**\n * First-match-wins path-rule lookup. Case-insensitive `*` globs with all\n * other regex metacharacters escaped (a literal `.` in a pattern matches\n * only `.`). Returns `undefined` when no rule matches — the caller applies\n * the config's top-level mode/depth.\n */\nexport function matchEdgePathRule(rules: EdgePathRule[], path: string): EdgePathRule | undefined {\n for (const rule of rules) {\n if (globToRegExp(rule.pattern).test(path)) return rule;\n }\n return undefined;\n}\n\nfunction globToRegExp(pattern: string): RegExp {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '.*');\n return new RegExp(`^${escaped}$`, 'i');\n}\n\n/** Reset cache — for testing only. */\nexport function _resetEdgeConfigCache(): void {\n cache.clear();\n inflight.clear();\n}\n","/**\n * AstraSync Universal Verification Gateway - Express Middleware\n *\n * Express.js middleware for verifying AI agents on API endpoints.\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { createMiddleware } from '@astrasyncai/verification-gateway/express';\n *\n * const app = express();\n *\n * app.use(createMiddleware({\n * apiBaseUrl: 'https://astrasync.ai/api',\n * apiKey: process.env.ASTRASYNC_API_KEY,\n * counterpartyId: 'ASTRAE-...', // your registered endpoint id\n * }));\n * ```\n *\n * Per-route policy (which paths are gated, trust floors, PDLSS purposes) is\n * configured in the AstraSync dashboard, not in code — the middleware\n * fetches it automatically on init and refreshes periodically. There is no\n * `routes` option; a `routes` key in the config object is ignored (with a\n * warning) since v2.9.7.\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport type {\n ExpressMiddlewareOptions,\n AgentCredentials,\n VerificationResult,\n EnhancedVerificationResult,\n RouteAccessConfig,\n AstraSyncCredentials,\n VerificationRequest,\n} from '../types';\nimport { awaitStepUpApproval } from './stepup-poll';\nimport {\n verify,\n extractCredentials,\n recordDecision,\n reportCounterpartyPreCheckFailure,\n fetchRoutes,\n} from '../verify';\nimport { extractHttpCredentials } from '../transport/http';\nimport { MCP_VERIFIED_HOP_HEADER, parseVerifiedHop, isVerifiedHopValidFor } from '../verified-hop';\nimport { resolveHttpPdlss, type HttpPdlssResolution } from './http-pdlss';\nimport { requiresHumanApproval, annotateApprovalRequired } from './approval-gate';\nimport { performCounterpartyPreCheck } from '../pdlss-pre-check';\nimport { prefetchWellKnown, getWellKnownUrls } from '../well-known';\nimport { buildSdkObservedMetadata } from '../metadata-capture';\nimport { createAnonymousBeacon } from './anonymous-beacon';\n\n/**\n * Extend Express Request with verification result\n */\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Express {\n interface Request {\n agentVerification?: VerificationResult;\n }\n }\n}\n\n/**\n * Default credential extractor\n */\nfunction defaultExtractCredentials(req: Request): AgentCredentials {\n return extractCredentials(\n req.headers as Record<string, string | string[] | undefined>,\n req.query as Record<string, string | undefined>\n );\n}\n\n/**\n * Extract extended AstraSync credentials (X-Astra-* headers) from Express request.\n * Returns null if no AstraSync headers are present.\n */\nexport function extractAstraSyncCredentials(req: Request): AstraSyncCredentials | null {\n return extractHttpCredentials(req.headers as Record<string, string | string[] | undefined>);\n}\n\n/** Read a possibly-array header value as a single string. */\nfunction headerValue(value: string | string[] | undefined): string | undefined {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) return value[0];\n return undefined;\n}\n\n/**\n * Resolve the canonical {purpose, action} pair for a request.\n * Replaces the gen-1 `defaultExtractPurpose` method-inference (`read_data`/\n * `write_data`) and the hardwired `action: req.method.toUpperCase()` — the\n * transport verb never travels as a PDLSS action. Full precedence chains\n * live in http-pdlss.ts.\n */\nfunction resolveRequestPdlss(\n req: Request,\n routeConfig: { purpose?: string; action?: string } | null,\n customExtractPurpose: ((req: Request) => string | undefined) | undefined,\n customExtractAction: ((req: Request) => string | undefined) | undefined\n): HttpPdlssResolution {\n return resolveHttpPdlss({\n method: req.method,\n astraPurpose: headerValue(req.headers['x-astra-purpose']),\n astraAction: headerValue(req.headers['x-astra-action']),\n legacyPurpose: headerValue(req.headers['x-purpose'] ?? req.headers['X-Purpose']),\n queryPurpose: typeof req.query.purpose === 'string' ? req.query.purpose : undefined,\n routePurpose: routeConfig?.purpose,\n routeAction: routeConfig?.action,\n hasCustomPurposeExtractor: !!customExtractPurpose,\n customPurpose: customExtractPurpose?.(req),\n hasCustomActionExtractor: !!customExtractAction,\n customAction: customExtractAction?.(req),\n });\n}\n\n/**\n * Match a route pattern against a path.\n *\n * Historically the SDK's\n * matchRoute was case-sensitive while Express's default `case sensitive\n * routing` is FALSE. A customer policy `/api/admin/*` did NOT match\n * `/api/ADMIN/users` → SDK returned `no-match` → request passed ungated →\n * Express routed it to the admin handler. The case-insensitive codepath\n * below closes the bypass.\n *\n * Ships in SHADOW MODE in SDK 2.4.13: by default the case-sensitive\n * regex is still authoritative; the case-insensitive variant is\n * computed in parallel and logged when results diverge. Follow-up\n * release flips the default to case-insensitive after 1-week\n * observation. Customers can flip early by setting\n * `caseInsensitiveRouteMatch: true` on the middleware options.\n */\nfunction matchRoute(\n pattern: string,\n path: string,\n opts?: { caseInsensitive?: boolean; correlationId?: string; logShadowDivergence?: boolean }\n): boolean {\n // Convert pattern to regex\n const regexPattern = pattern.replace(/\\*/g, '.*').replace(/\\//g, '\\\\/');\n\n const caseSensitiveRegex = new RegExp(`^${regexPattern}$`);\n const caseSensitiveResult = caseSensitiveRegex.test(path);\n\n if (!opts?.caseInsensitive && !opts?.logShadowDivergence) {\n return caseSensitiveResult;\n }\n\n const caseInsensitiveRegex = new RegExp(`^${regexPattern}$`, 'i');\n const caseInsensitiveResult = caseInsensitiveRegex.test(path);\n\n // Shadow logging: emit only when results diverge so operators can grep\n // their own logs for the bypass class without log volume spam.\n if (opts?.logShadowDivergence && caseSensitiveResult !== caseInsensitiveResult) {\n // eslint-disable-next-line no-console\n console.warn(\n `[SHADOW] matchRoute case-insensitive would change result: pattern=${pattern} path=${path} ` +\n `caseSensitive=${caseSensitiveResult} caseInsensitive=${caseInsensitiveResult} correlationId=${opts.correlationId ?? 'unknown'}`\n );\n }\n\n return opts?.caseInsensitive ? caseInsensitiveResult : caseSensitiveResult;\n}\n\n/**\n * Find the route configuration for a request\n */\nfunction findRouteConfig(\n routes: RouteAccessConfig[],\n path: string,\n method: string,\n opts?: { caseInsensitive?: boolean; correlationId?: string; logShadowDivergence?: boolean }\n): RouteAccessConfig | undefined {\n return routes.find((route) => {\n const methodMatches =\n route.method === '*' || route.method.toUpperCase() === method.toUpperCase();\n const pathMatches = matchRoute(route.pattern, path, opts);\n return methodMatches && pathMatches;\n });\n}\n\n/**\n * Default denied handler\n *\n * The response body carries the full `failures[]`\n * array and the `correlationId` so partners can render per-dimension UX\n * and tie a denial back to a server log line. Previously the merchant only\n * got the first denialReason — meaningful detail was thrown away before\n * the response left the SDK. Also stamps `X-Astra-Gateway-Mode: enforced`\n * so partners can tell a gate-evaluated denial apart from a gate-skipped\n * pass-through (the `unenforced` complement).\n */\nfunction dedupeFailures(result: VerificationResult): void {\n if (result.failures && result.failures.length > 1) {\n const seen = new Set<string>();\n result.failures = result.failures.filter((f) => {\n const key = `${f.dimension}|${f.message}|${(f as { guidance?: string }).guidance ?? ''}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n }\n if (result.denialReasons && result.denialReasons.length > 1) {\n result.denialReasons = [...new Set(result.denialReasons)];\n }\n}\n\nfunction defaultOnDenied(result: VerificationResult, _req: Request, res: Response): void {\n // 4.0.0 BREAKING: when this integration's OWN API key was rejected by the\n // backend (misconfigured marker), the inbound agent did nothing wrong and\n // re-authenticating won't help — a 401 both blames the agent and invites\n // re-auth loops. Answer 503: this site's verification layer is down, by\n // the operator's own configuration. No Retry-After — retrying is futile\n // until the operator rotates the key.\n if (result.misconfigured) {\n res.setHeader('X-Astra-Gateway-Mode', 'enforced');\n res.status(503).json({\n success: false,\n error: {\n code: 'MERCHANT_VERIFICATION_MISCONFIGURED',\n message: result.denialReasons?.[0] || \"This site's AstraSync integration is misconfigured\",\n guidance: result.guidance,\n failures: result.failures,\n correlationId: result.correlationId,\n },\n });\n return;\n }\n\n // Round-18 G4: identity-verification failures → 401 (re-authenticate);\n // identity-verified-but-policy-denied → 403 (re-auth won't help; update\n // PDLSS scope or escalate to step-up). Maps to the two distinct recovery\n // actions that HTTP middleware acts on without parsing bodies. The\n // impossible state `!identityVerified && policyAllowed` falls into the\n // `!identityVerified` branch — identity is the more-fundamental missing\n // precondition.\n const statusCode = !result.identityVerified ? 401 : 403;\n\n res.setHeader('X-Astra-Gateway-Mode', 'enforced');\n\n res.status(statusCode).json({\n success: false,\n error: {\n code: !result.identityVerified ? 'UNAUTHORIZED' : 'INSUFFICIENT_ACCESS',\n message: result.denialReasons?.[0] || 'Access denied',\n guidance: result.guidance,\n // Round-10: aggregated per-dimension detail + correlation handle.\n failures: result.failures,\n correlationId: result.correlationId,\n stepUpApproval: result.stepUpApproval,\n // 3.6.0: terminal outcome of an opt-in hold-and-poll wait (denied /\n // expired / consumed / timeout). Absent when the feature is off.\n ...(result.stepUpOutcome && { stepUpOutcome: result.stepUpOutcome }),\n },\n });\n}\n\n/**\n * Refresh interval for the remote-fetched route policy. Default: every 5\n * minutes. Override via `routesRefreshMs` on the middleware options. Each\n * middleware instance keeps its own cache; multiple instances pointing at the\n * same endpoint will each fetch independently.\n */\nconst DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1000;\n\n/**\n * Create Express middleware for agent verification.\n *\n * v2.9.7 moved per-route policy authority out of merchant-side source code\n * into the AstraSync dashboard. `createMiddleware` no longer accepts a\n * `routes` array — it fetches the endpoint's stored policy via\n * `GET /endpoints/:counterpartyId/routes` on init and refreshes\n * periodically. Policy edits in the dashboard take effect on the next\n * refresh (or sooner if the operator manually restarts the SDK).\n *\n * `counterpartyId` is required: the SDK can't know which endpoint's policy\n * to fetch without it. Local-development workflows that don't have an\n * AstraSync endpoint registered can omit it — the middleware logs a\n * one-time warning and falls through (allows all) until a policy is\n * fetchable.\n */\nexport function createMiddleware(options: ExpressMiddlewareOptions): RequestHandler {\n // Guard against configs authored for pre-2.9.7 SDKs: a `routes` array in\n // merchant source is silently dead config (the type contract rejects it at\n // literal call sites, but variable-typed configs slip through) — and dead\n // route config means the author believes paths are gated that aren't.\n if ('routes' in options) {\n // eslint-disable-next-line no-console\n console.warn(\n '[VerificationGateway] `routes` is dashboard-managed since v2.9.7; this option is ignored — ' +\n 'configure route policy in your AstraSync dashboard.'\n );\n }\n const {\n extractCredentials: customExtractCredentials,\n extractPurpose: customExtractPurpose,\n extractAction: customExtractAction,\n skipPaths = [],\n onDenied = defaultOnDenied,\n recordDecisions,\n enableRuntimeChallenge = true,\n routesRefreshMs = DEFAULT_ROUTES_REFRESH_MS,\n failOnError = 'open',\n caseInsensitiveRouteMatch = false,\n anonymousBeacon = true,\n trustVerifiedHop = false,\n verifiedHopMaxAgeMs,\n ...config\n } = options;\n\n // v2.5.0: fire-and-forget pre-fetch of well-known URLs\n if (config.apiBaseUrl) {\n prefetchWellKnown(config.apiBaseUrl).catch(() => {});\n }\n\n // Dashboard-driven anonymous-traffic beacon for the pass-through paths\n // (no matching route / route gated at `none`). Fire-and-forget: never\n // awaited, never delays next(). See ./anonymous-beacon.ts.\n const emitAnonymousBeacon = anonymousBeacon\n ? createAnonymousBeacon(config, { counterpartyType: config.counterpartyType ?? 'api' })\n : undefined;\n const beaconPassThrough = emitAnonymousBeacon\n ? (req: Request): void => {\n const xff = req.headers['x-forwarded-for'];\n const xffStr = Array.isArray(xff) ? xff.join(', ') : xff;\n emitAnonymousBeacon({\n requestPath: req.path,\n requestMethod: req.method,\n counterpartyUrl: config.counterpartyUrl || `${req.protocol}://${req.get('host')}`,\n sourceIp: req.ip ?? (xffStr ? xffStr.split(',')[0].trim() : undefined),\n rawHeaders: req.headers as Record<string, string | string[] | undefined>,\n });\n }\n : undefined;\n\n // Per-middleware-instance route cache. Populated on first fetch; refreshed\n // every `routesRefreshMs`. Until first successful fetch we hold an empty\n // array which means \"no per-route gating active\" — the middleware falls\n // through. Pre-fix the array came from merchant source, which both broke\n // the auth-boundary story (defect 24) and silently disagreed with the\n // dashboard.\n let cachedRoutes: RouteAccessConfig[] = [];\n let lastFetchAt = 0;\n let refreshing: Promise<void> | null = null;\n let warnedNoCounterparty = false;\n let warnedEmptyRoutes = false;\n\n async function refreshRoutes(): Promise<void> {\n if (!config.counterpartyId) {\n if (!warnedNoCounterparty) {\n // eslint-disable-next-line no-console\n console.warn(\n '[VerificationGateway] No counterpartyId configured — falling through (allow all). ' +\n 'Per-route policy lives in the AstraSync dashboard now; register the endpoint and ' +\n 'set counterpartyId in your middleware config to enforce policy.'\n );\n warnedNoCounterparty = true;\n }\n return;\n }\n const fetched = await fetchRoutes(config, config.counterpartyId);\n if (fetched) {\n cachedRoutes = fetched;\n lastFetchAt = Date.now();\n // v2.3.8 (defect #25): if the fetch succeeded but returned an empty\n // policy, the endpoint is registered correctly but the operator hasn't\n // configured any routes yet — every request will fall through ungated.\n // Surface this loudly once so silent pass-through can't go unnoticed.\n if (cachedRoutes.length === 0 && !warnedEmptyRoutes) {\n // Audit F-PROBE-01: app.astrasync.ai doesn't resolve in DNS today;\n // dashboard actually lives at astrasync.ai/dashboard. Use that as\n // the fallback. If DevOps provisions app.astrasync.ai later, the\n // dashboardUrl config option lets merchants override.\n const dashboard = config.dashboardUrl ?? 'https://astrasync.ai/dashboard';\n // eslint-disable-next-line no-console\n console.warn(\n `[VerificationGateway] No route policy configured for ${config.counterpartyId}. ` +\n `Gateway is in pass-through mode for ALL traffic until you add at least one route. ` +\n `Configure at ${dashboard}/dashboard/endpoints/${config.counterpartyId}/routes`\n );\n warnedEmptyRoutes = true;\n }\n }\n }\n\n // Eager first fetch so the first request after init has policy loaded.\n // Errors are swallowed (handled by fetchRoutes returning null).\n refreshing = refreshRoutes().finally(() => {\n refreshing = null;\n });\n\n return async (req: Request, res: Response, next: NextFunction): Promise<void> => {\n try {\n // Check if path should be skipped\n const shouldSkip = skipPaths.some((pattern) => matchRoute(pattern, req.path));\n if (shouldSkip) {\n return next();\n }\n\n // Wait for in-flight init fetch (only on the very first request) so we\n // don't admit traffic with no policy loaded.\n if (refreshing) {\n await refreshing.catch(() => {});\n }\n // Time-based refresh: kick off a background refresh if the cache is\n // stale. Doesn't block the current request — readers see whatever is\n // cached at this moment; the next request will see the refreshed copy.\n if (config.counterpartyId && Date.now() - lastFetchAt > routesRefreshMs) {\n refreshing = refreshRoutes().finally(() => {\n refreshing = null;\n });\n }\n\n // Find route configuration\n // Audit F-A6-31 shadow-mode wiring: pass caseInsensitive flag (default\n // false in 2.4.13) + always log divergences so merchants can grep for\n // would-have-matched results during the 1-week observation window.\n const correlationId =\n (req.headers['x-request-id'] as string | undefined) ||\n (req.headers['x-correlation-id'] as string | undefined);\n const routeConfig = findRouteConfig(cachedRoutes, req.path, req.method, {\n caseInsensitive: caseInsensitiveRouteMatch,\n logShadowDivergence: true,\n correlationId,\n });\n\n // If no route config, skip verification (allow through)\n if (!routeConfig) {\n if (config.setPassThroughHeader) {\n // Round-10 (#49, O10): `unenforced` replaces the previous\n // `pass-through` label. The previous name conflated \"gateway\n // didn't evaluate policy\" with \"request succeeded end-to-end\" —\n // the downstream handler may still return any status. The new\n // semantic describes the GATE state only.\n res.setHeader('X-Astra-Gateway-Mode', 'unenforced');\n res.setHeader(\n 'X-Astra-Gateway-Reason',\n cachedRoutes.length === 0 ? 'no-policy' : 'no-match'\n );\n }\n // Anonymous-traffic beacon: this request never reaches verify-access,\n // so bot/agent-shaped callers would otherwise be invisible to the\n // dashboard. Fire-and-forget — does not delay next().\n beaconPassThrough?.(req);\n return next();\n }\n\n // v2.5.0: resolve well-known URLs (cached; prefetched at middleware creation)\n const wellKnownUrls = config.apiBaseUrl\n ? await getWellKnownUrls(config.apiBaseUrl).catch(() => undefined)\n : undefined;\n\n // Extract credentials (hoisted from below the route-none check so the\n // round-12 F9 evaluateAlwaysIfCredentialed flag can decide whether to\n // evaluate vs short-circuit).\n const credentials = customExtractCredentials\n ? customExtractCredentials(req)\n : defaultExtractCredentials(req);\n\n // Round-12 (F9): route-none short-circuit unless the caller wants\n // evaluation-without-enforcement. With evaluateAlwaysIfCredentialed\n // set to true AND credentials present, the middleware calls\n // verify-access for audit + req.agentVerification population, then\n // proceeds without gating. Default behaviour (flag off) preserves\n // pre-F9 short-circuit semantics.\n const shouldEnforce = !routeConfig.observe;\n if (routeConfig.observe && (!config.evaluateAlwaysIfCredentialed || !credentials.astraId)) {\n if (config.setPassThroughHeader) {\n res.setHeader('X-Astra-Gateway-Mode', 'unenforced');\n res.setHeader('X-Astra-Gateway-Reason', 'route-observe');\n }\n // Anonymous-traffic beacon (see the no-route-match branch above).\n beaconPassThrough?.(req);\n return next();\n }\n\n // Inner-hop dedupe: a trusted upstream AstraSync hop (edge gateway or\n // MCP outer hop) already verified this exact ASTRA-id moments ago —\n // accept the fresh marker and skip the duplicate verify-access call.\n // Mirrors the MCP adapter contract: no req.agentVerification on a\n // hop-skip. The marker must match the request's own X-Astra-Id.\n if (trustVerifiedHop && credentials.astraId) {\n const hopRaw = req.headers[MCP_VERIFIED_HOP_HEADER.toLowerCase()];\n const hopValue =\n typeof hopRaw === 'string' ? hopRaw : Array.isArray(hopRaw) ? hopRaw[0] : undefined;\n const marker = parseVerifiedHop(hopValue);\n if (\n isVerifiedHopValidFor(marker, credentials.astraId, {\n ...(verifiedHopMaxAgeMs !== undefined ? { maxAgeMs: verifiedHopMaxAgeMs } : {}),\n })\n ) {\n return next();\n }\n }\n\n // v2.3.0: anonymous traffic no longer short-circuits client-side.\n // The server applies the endpoint's `unverifiedAgentPolicy` (deny /\n // allow_partial / allow_full) and emits the verification event +\n // blockchain record per the canonical flow. SDK forwards verbatim.\n\n // Resolve the canonical {purpose, action} pair (Bug 14, §4.6): dashboard\n // route mapping → custom extractors → agent X-Astra-* headers →\n // method-table fallback. The transport verb never travels as the action.\n const pdlssPair = resolveRequestPdlss(\n req,\n routeConfig,\n customExtractPurpose,\n customExtractAction\n );\n const purpose = pdlssPair.purpose;\n if (config.debug) {\n // Same telemetry shape as the MCP adapter — adoption tracking and\n // support triage read the *_source fields to see which integration\n // path each partner uses (route mapping vs headers vs fallback).\n // eslint-disable-next-line no-console\n console.debug('[express-middleware] pdlss resolved', {\n purpose_source: pdlssPair.purposeSource,\n resolved_purpose: pdlssPair.purpose,\n action_source: pdlssPair.actionSource,\n resolved_action: pdlssPair.action,\n });\n }\n\n // Extract full AstraSync credentials (includes PDLSS from X-Astra-* headers)\n const astraCreds = extractAstraSyncCredentials(req);\n\n // Auto-detect counterparty URL from the request if not explicitly configured.\n // Since the SDK is installed at this endpoint, we always know the origin.\n const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get('host')}`;\n\n // Step 2: Counterparty-side PDLSS pre-check — compare agent's requested PDLSS\n // against counterparty-defined maximums on the route config.\n // Rejects immediately if outside limits, BEFORE calling verify-access.\n const preCheckFailures = performCounterpartyPreCheck(routeConfig, astraCreds, purpose);\n if (preCheckFailures.length > 0) {\n // Round-18 G4: counterparty pre-check failure — request rejected\n // before reaching verify-access. Neither identity nor policy was\n // remotely verified; both axes truthfully false.\n const result: VerificationResult = {\n identityVerified: false,\n policyAllowed: false,\n denialReasons: preCheckFailures.map((f) => f.message),\n guidance: {\n message: 'Request exceeds counterparty-defined PDLSS limits.',\n registrationUrl: wellKnownUrls?.registrationUrl ?? '',\n documentationUrl: wellKnownUrls?.documentationUrl ?? '',\n },\n verifiedAt: new Date(),\n };\n\n req.agentVerification = result;\n\n // Fire-and-forget: notify AstraSync of the pre-check failure\n reportCounterpartyPreCheckFailure(config, {\n agentId: astraCreds?.agentId || credentials.astraId || 'unknown',\n counterpartyUrl,\n counterpartyType: config.counterpartyType || 'api',\n failures: preCheckFailures,\n requestPath: req.path,\n requestMethod: req.method,\n }).catch(() => {});\n\n dedupeFailures(result);\n onDenied(result, req, res);\n return;\n }\n\n // Step 3: Call AstraSync verify-access with runtime challenge enabled\n const shouldRecordDecisions = recordDecisions !== false;\n const forwardedFor = req.headers['x-forwarded-for'];\n const forwardedForStr = Array.isArray(forwardedFor) ? forwardedFor.join(', ') : forwardedFor;\n // Audit F-A6-34: previously the LEFTMOST X-Forwarded-For entry was\n // taken as the original client IP. That value is attacker-controlled\n // whenever the customer's reverse proxy doesn't strip\n // client-supplied X-Forwarded-For — an attacker prepends\n // `X-Forwarded-For: 1.1.1.1` and we audit the spoofed IP. Now we\n // prefer req.ip (which Express resolves via configured `trust proxy`\n // hop count — the customer's responsibility to set correctly per\n // their actual hop chain). XFF still provides a fallback for\n // customers without `trust proxy` configured, but emits a one-time\n // warning when used so they know to fix.\n const originalClientIp =\n req.ip ?? (forwardedForStr ? forwardedForStr.split(',')[0].trim() : undefined);\n if (!req.ip && forwardedForStr) {\n // eslint-disable-next-line no-console\n console.warn(\n '[VerificationGateway] req.ip unset — falling back to leftmost X-Forwarded-For. ' +\n 'Configure Express trust proxy correctly to avoid spoofable client IPs in audit logs.'\n );\n }\n const agentCardUrl =\n typeof req.headers['x-astrasync-agent-card'] === 'string'\n ? (req.headers['x-astrasync-agent-card'] as string)\n : undefined;\n\n // P1 (SDK 3.5.0): when extractTransactionValue is configured, include\n // the value in verify-access so PDLSS limit evaluation runs at\n // middleware time. Must return major units (dollars, not cents).\n let txValue: number | undefined;\n let txCurrency: string | undefined;\n if (config.extractTransactionValue) {\n try {\n const extracted = config.extractTransactionValue(req);\n if (extracted) {\n txValue = extracted.value;\n txCurrency = extracted.currency;\n }\n } catch (e) {\n if (config.debug) {\n // eslint-disable-next-line no-console\n console.warn('[VerificationGateway] extractTransactionValue threw:', e);\n }\n }\n }\n\n // 5.8.0 attempt-chain (X-Astra-Attempt-Id): the bridge stamps the\n // interaction-chain id on every venue call (the edge pipeline already\n // reads it). Threading it into verify-access makes this hop part of the\n // SAME chain server-side, so a step-up the human already approved for\n // the chain passes here instead of minting a second approval — the\n // two-hop approval-loop fix. Invalid values are dropped, never sent.\n const attemptHeader = req.headers['x-astra-attempt-id'];\n const inboundAttemptId =\n typeof attemptHeader === 'string' && /^att_[0-9a-f]{32}$/.test(attemptHeader)\n ? attemptHeader\n : undefined;\n\n const verificationRequest: VerificationRequest = {\n credentials,\n purpose,\n action: pdlssPair.action,\n resource: req.path,\n createSession: shouldRecordDecisions,\n counterpartyUrl,\n counterpartyType: config.counterpartyType || 'api',\n enableRuntimeChallenge,\n durationRequired: astraCreds?.pdlss?.duration?.maxSessionDuration,\n ...(txValue !== undefined && { transactionValue: txValue }),\n ...(txCurrency && { currency: txCurrency }),\n ...(inboundAttemptId && { attemptId: inboundAttemptId }),\n callerMetadata: {\n sourceIp: originalClientIp,\n userAgent: req.headers['user-agent'] as string | undefined,\n referer: req.headers.referer as string | undefined,\n host: req.headers.host as string | undefined,\n forwardedFor: forwardedForStr,\n agentCardUrl,\n // Workstream D — capture EVERY inbound header (SDK-only merchants\n // have no edge to do it upstream) plus the CDN-derived connection\n // block. Local string work, secrets stripped; out of the verify\n // cache key so it doesn't defeat caching.\n observedMetadata: buildSdkObservedMetadata(req.headers),\n },\n };\n let result = await verify(config, verificationRequest);\n\n // Attach result to request\n req.agentVerification = result;\n let sessionId = (result as EnhancedVerificationResult).sessionId;\n\n // 3.6.0 hold-and-poll (opt-in via stepUpMaxWaitMs): HOLD a step-up\n // outcome, poll the approval, and on 'approved' re-verify the same\n // request once (cache-bypassed — the retry must reach the backend to\n // redeem the single-use approval). Every non-approved outcome falls\n // through to the existing fail-closed branches below with\n // result.stepUpOutcome stamped for the deny body.\n if (\n config.stepUpMaxWaitMs !== undefined &&\n result.policyAllowed &&\n requiresHumanApproval(result) &&\n result.stepUpApproval?.pollUrl\n ) {\n const outcome = await awaitStepUpApproval(config, result.stepUpApproval);\n res.setHeader('X-Astra-Step-Up', outcome);\n if (outcome === 'approved') {\n result = await verify(config, verificationRequest, { bypassCache: true });\n req.agentVerification = result;\n sessionId = (result as EnhancedVerificationResult).sessionId;\n } else {\n result.stepUpOutcome = outcome;\n }\n }\n\n // Denied verifications short-circuit here: failing either identity OR\n // policy already means \"deny.\" We check that first.\n // 4.5.0 (probe F1 follow-through): the gate is the SERVER's decision —\n // `policyAllowed` is true exactly when the backend allowed the call\n // (every deny/guidance/api-error shape sets it false), so gating on it\n // alone preserves the endpoint policy verbatim. `identityVerified` no\n // longer gates here: anonymous callers granted by an\n // audit/allow_partial/allow_full endpoint policy are honestly\n // identity-unverified yet server-allowed, and re-deriving a deny from\n // identity would override the backend evaluator (the SDK-pre-check\n // asymmetry antipattern). Identity still picks 401-vs-403 in the deny\n // body builder.\n if (!result.policyAllowed) {\n if (shouldRecordDecisions && sessionId) {\n recordDecision(config, sessionId, 'denied', result.denialReasons?.[0]).catch(() => {});\n }\n dedupeFailures(result);\n onDenied(result, req, res);\n return;\n }\n\n // F2 direct-path fail-closed: an \"allowed-but-escalate\" outcome\n // (step-up / requires-approval, policyAllowed:true) cannot be completed\n // autonomously. The backend creates a step-up approval record and returns\n // it on `result.stepUpApproval`; deny here — symmetric with the bridge —\n // and surface the polling info in the deny response body.\n if (requiresHumanApproval(result)) {\n annotateApprovalRequired(result);\n if (shouldRecordDecisions && sessionId) {\n recordDecision(config, sessionId, 'denied', result.denialReasons?.[0]).catch(() => {});\n }\n dedupeFailures(result);\n onDenied(result, req, res);\n return;\n }\n\n // Round-12 (F9): evaluation-without-enforcement. When the route is\n // 'none' but we ran verify-access for audit, skip the gates and call\n // next() — the result is on req.agentVerification for the handler\n // to render tier-aware responses (e.g. anonymous vs verified\n // catalog view on the same path).\n if (!shouldEnforce) {\n if (config.setPassThroughHeader) {\n res.setHeader('X-Astra-Gateway-Mode', 'enforced');\n res.setHeader('X-Astra-Gateway-Reason', 'evaluated-not-enforced');\n }\n if (shouldRecordDecisions && sessionId) {\n recordDecision(config, sessionId, 'granted').catch(() => {});\n }\n return next();\n }\n\n // The access decision is the server's (identityVerified / policyAllowed,\n // above) — resting on a verified ID + runtime challenge + PDLSS match +\n // trust score. The only client-side refinement is the per-route trust\n // floor below; there is no access-level band (removed in SDK 5.0.0).\n\n // Per-route trust tightening (only refinement that still gates).\n if (routeConfig.minTrustScore && result.agent) {\n if (result.agent.trustScore < routeConfig.minTrustScore) {\n // 3.2.0: qualitative — never embed the score or the threshold in an\n // agent-visible message (trust is a system-internal signal; exposing\n // the number is a gaming vector — post-3.1.0 feedback #2).\n const trustFailure = {\n dimension: 'endpoint.trust',\n message: 'Trust below the route requirement for this endpoint.',\n guidance:\n \"Trust is below this route's floor. Trust is not overridable — the agent either meets the endpoint's trust policy or it doesn't. Raise the agent's trust via real signals (KYD, blockchain registration, agent-card), or have the operator lower the route's minTrustScore.\",\n };\n result.failures = [...(result.failures ?? []), trustFailure];\n result.denialReasons = [trustFailure.message];\n if (!result.guidance && wellKnownUrls) {\n result.guidance = {\n message: trustFailure.message,\n registrationUrl: wellKnownUrls.registrationUrl,\n documentationUrl: wellKnownUrls.documentationUrl,\n };\n }\n if (shouldRecordDecisions && sessionId) {\n recordDecision(config, sessionId, 'denied', trustFailure.message).catch(() => {});\n }\n dedupeFailures(result);\n onDenied(result, req, res);\n return;\n }\n }\n\n // All checks passed — record grant decision\n if (shouldRecordDecisions && sessionId) {\n recordDecision(config, sessionId, 'granted').catch(() => {});\n }\n // v2.3.8 (defect #26): if the endpoint's `unverifiedAgentPolicy` is\n // `'audit'` (allow + soft-launch warning), the server returns the\n // header to relay. Lift it onto the merchant's response BEFORE\n // calling next() so downstream handlers and the eventual response\n // back to the agent both carry it.\n const enhancedResult = result as EnhancedVerificationResult;\n if (enhancedResult.warningHeader) {\n res.setHeader(enhancedResult.warningHeader.name, enhancedResult.warningHeader.value);\n }\n next();\n } catch (error) {\n // Audit F-A1-06: shadow-mode logging for fail-closed default migration.\n // Always log `[SHADOW] would-have-denied` so merchants can grep their\n // own application logs for would-have-been-denied impact during the\n // observation window. Actual deny/admit behavior controlled by\n // failOnError option (default 'open' for backward compatibility).\n const errorClass = error instanceof Error ? error.constructor.name : typeof error;\n const correlationId =\n (req.headers['x-request-id'] as string | undefined) ||\n (req.headers['x-correlation-id'] as string | undefined) ||\n `gen-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n // eslint-disable-next-line no-console\n console.error('[VerificationGateway] Middleware error:', error);\n // eslint-disable-next-line no-console\n console.warn(\n `[SHADOW] would-have-denied: errorClass=${errorClass} route=${req.method}:${req.path} merchantId=${config.counterpartyId ?? 'unknown'} correlationId=${correlationId}`\n );\n\n if (failOnError === 'closed') {\n const result: VerificationResult = {\n identityVerified: false,\n policyAllowed: false,\n denialReasons: [`Verification middleware internal error: ${errorClass}`],\n failures: [\n {\n dimension: 'middleware.internal_error',\n message: `Middleware threw ${errorClass} — failing closed`,\n },\n ],\n verifiedAt: new Date(),\n correlationId,\n };\n const catchUrls = config.apiBaseUrl\n ? await getWellKnownUrls(config.apiBaseUrl).catch(() => undefined)\n : undefined;\n if (catchUrls) {\n result.guidance = {\n message: `Middleware threw ${errorClass} — failing closed`,\n registrationUrl: catchUrls.registrationUrl,\n documentationUrl: catchUrls.documentationUrl,\n };\n }\n dedupeFailures(result);\n return onDenied(result, req, res);\n }\n\n next();\n }\n };\n}\n\n// `requireAccess` and `verifyOnly` were removed in v2.9.7. Both injected a\n// local `routes` array into the merchant's source code, which is the exact\n// dual-config attack vector defect 24 closed. Per-route policy now lives in\n// the AstraSync dashboard (gated by team.role admin auth + audit + alerts).\n// To tighten a route, set its `minTrustScore` (+ purpose/jurisdiction/value\n// gates) in the dashboard. For \"verify but don't block,\" set the route to\n// `observe` (or run the endpoint in an audit `unverifiedAgentPolicy`).\n","/**\n * AstraSync Universal Verification Gateway - Next.js Middleware\n *\n * Next.js middleware for verifying AI agents on web applications.\n * Serves the verification interstitial (an HTML overlay with registration\n * guidance) to unverified web-page traffic; API routes get structured JSON.\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import { createMiddleware } from '@astrasyncai/verification-gateway/nextjs';\n *\n * export const middleware = createMiddleware({\n * apiBaseUrl: 'https://astrasync.ai/api',\n * apiKey: process.env.ASTRASYNC_API_KEY,\n * counterpartyId: 'ASTRAE-...', // per-route policy is fetched from the dashboard\n * showInterstitial: true,\n * });\n *\n * export const config = {\n * matcher: ['/api/:path*', '/dashboard/:path*'],\n * };\n * ```\n */\n\nimport type { NextRequest } from 'next/server';\nimport type {\n NextJsMiddlewareOptions,\n AgentCredentials,\n VerificationResult,\n RouteAccessConfig,\n AstraSyncCredentials,\n VerificationRequest,\n StepUpOutcome,\n} from '../types';\nimport { awaitStepUpApproval } from './stepup-poll';\nimport { verify, reportCounterpartyPreCheckFailure, fetchRoutes } from '../verify';\nimport { extractHttpCredentials } from '../transport/http';\nimport { performCounterpartyPreCheck } from '../pdlss-pre-check';\nimport { buildSdkObservedMetadata } from '../metadata-capture';\nimport { createAnonymousBeacon } from './anonymous-beacon';\nimport { resolveHttpPdlss, type HttpPdlssResolution } from './http-pdlss';\nimport { requiresHumanApproval, annotateApprovalRequired } from './approval-gate';\nimport { MCP_VERIFIED_HOP_HEADER, parseVerifiedHop, isVerifiedHopValidFor } from '../verified-hop';\n\n/**\n * HTML-escape arbitrary string for safe interpolation into HTML text or\n * attribute values. Used by the interstitial HTML generator\n * to prevent reflected XSS from attacker-influenced denial messages.\n */\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * Sanitize a URL for `href=`. Accepts only `http://` / `https://` schemes\n * (relative URLs allowed too); rejects `javascript:` / `data:` / `vbscript:`\n * and falls back to the supplied default on rejection. Then HTML-escapes\n * the result.\n */\nfunction sanitizeUrl(value: string | undefined, fallback: string): string {\n if (typeof value !== 'string' || value.length === 0) return escapeHtml(fallback);\n const trimmed = value.trim();\n if (/^javascript:|^data:|^vbscript:/i.test(trimmed)) return escapeHtml(fallback);\n if (/^https?:\\/\\//i.test(trimmed) || trimmed.startsWith('/')) {\n return escapeHtml(trimmed);\n }\n return escapeHtml(fallback);\n}\n\n/**\n * Extract credentials from Next.js request\n */\nfunction extractCredentialsFromNextRequest(request: NextRequest): AgentCredentials {\n const credentials: AgentCredentials = {};\n\n // Check for ASTRA-ID in headers\n const astraId = request.headers.get('x-astra-id') || request.headers.get('X-Astra-Id');\n if (astraId) {\n credentials.astraId = astraId;\n }\n\n // Check for API key\n const apiKey = request.headers.get('x-api-key') || request.headers.get('X-Api-Key');\n if (apiKey) {\n credentials.apiKey = apiKey;\n }\n\n // Check Authorization header\n const authHeader = request.headers.get('authorization');\n if (authHeader) {\n credentials.authorizationHeader = authHeader;\n if (authHeader.startsWith('Bearer ')) {\n credentials.jwt = authHeader.slice(7);\n }\n }\n\n // Check query parameters\n const url = new URL(request.url);\n const astraIdParam = url.searchParams.get('astraId');\n const apiKeyParam = url.searchParams.get('apiKey');\n\n if (astraIdParam && !credentials.astraId) {\n credentials.astraId = astraIdParam;\n }\n if (apiKeyParam && !credentials.apiKey) {\n credentials.apiKey = apiKeyParam;\n }\n\n return credentials;\n}\n\n/**\n * Match a route pattern against a path\n */\nfunction matchRoute(pattern: string, path: string): boolean {\n const regexPattern = pattern.replace(/\\*/g, '.*').replace(/\\//g, '\\\\/');\n\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(path);\n}\n\n/**\n * Find the route configuration for a request\n */\nfunction findRouteConfig(\n routes: RouteAccessConfig[],\n path: string,\n method: string\n): RouteAccessConfig | undefined {\n return routes.find((route) => {\n const methodMatches =\n route.method === '*' || route.method.toUpperCase() === method.toUpperCase();\n const pathMatches = matchRoute(route.pattern, path);\n return methodMatches && pathMatches;\n });\n}\n\n/**\n * Extract AstraSyncCredentials from Next.js request headers.\n * Returns null if no AstraSync headers are present.\n */\nfunction extractAstraSyncCredentialsFromNextRequest(\n request: NextRequest\n): AstraSyncCredentials | null {\n const headers: Record<string, string> = {};\n request.headers.forEach((value, key) => {\n headers[key] = value;\n });\n return extractHttpCredentials(headers);\n}\n\n/**\n * Resolve the canonical {purpose, action} pair for a request.\n * Replaces the gen-1 method-inference (`read_data`/`write_data`) and the\n * hardwired verb action — the transport verb never travels as a PDLSS\n * action. Same resolver as the express adapter (http-pdlss.ts); nextjs has\n * no custom extractors and no query-param step (never existed here).\n */\nfunction resolveNextPdlss(\n request: NextRequest,\n routeConfig: { purpose?: string; action?: string } | null\n): HttpPdlssResolution {\n return resolveHttpPdlss({\n method: request.method,\n astraPurpose: request.headers.get('x-astra-purpose') ?? undefined,\n astraAction: request.headers.get('x-astra-action') ?? undefined,\n legacyPurpose: request.headers.get('x-purpose') ?? undefined,\n routePurpose: routeConfig?.purpose,\n routeAction: routeConfig?.action,\n });\n}\n\n/**\n * Generate the verification-interstitial HTML response served to unverified\n * web-page traffic.\n */\nfunction generateInterstitialHtml(\n result: VerificationResult,\n options: NextJsMiddlewareOptions\n): string {\n // result.guidance.message may quote attacker-controlled input from the\n // backend deny path (e.g. `Purpose \"<script>...\" is not in the allowed\n // list`). HTML-escape every interpolated value; validate URLs reject\n // non-http(s) schemes to prevent `javascript:` smuggling.\n const title = escapeHtml(options.commerceShield?.title || 'AstraSync Agent Verification');\n const message = escapeHtml(\n options.commerceShield?.message ||\n result.guidance?.message ||\n \"This site verifies AI agents before granting access. We noticed you're visiting without AstraSync credentials.\"\n );\n const registrationUrl = sanitizeUrl(\n result.guidance?.registrationUrl,\n 'https://astrasync.ai/agents/register'\n );\n const docsUrl = sanitizeUrl(\n result.guidance?.documentationUrl,\n 'https://astrasync.ai/docs/agent-access'\n );\n const allowGuest = options.commerceShield?.allowGuestAccess ?? true;\n\n return `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${title}</title>\n <style>\n * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n }\n .shield-container {\n background: rgba(255, 255, 255, 0.95);\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);\n max-width: 480px;\n width: 100%;\n padding: 40px;\n text-align: center;\n }\n .shield-icon {\n font-size: 48px;\n margin-bottom: 20px;\n }\n .shield-title {\n font-size: 24px;\n font-weight: 700;\n color: #1a1a2e;\n margin-bottom: 16px;\n }\n .shield-message {\n color: #4a5568;\n line-height: 1.6;\n margin-bottom: 24px;\n }\n .shield-steps {\n text-align: left;\n background: #f7fafc;\n border-radius: 8px;\n padding: 20px;\n margin-bottom: 24px;\n }\n .shield-steps h3 {\n font-size: 14px;\n font-weight: 600;\n color: #2d3748;\n margin-bottom: 12px;\n }\n .shield-steps ol {\n padding-left: 20px;\n color: #4a5568;\n }\n .shield-steps li {\n margin-bottom: 8px;\n }\n .shield-buttons {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n .btn {\n display: inline-block;\n padding: 14px 24px;\n border-radius: 8px;\n font-weight: 600;\n text-decoration: none;\n transition: all 0.2s;\n cursor: pointer;\n border: none;\n font-size: 16px;\n }\n .btn-primary {\n background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);\n color: white;\n }\n .btn-primary:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);\n }\n .btn-secondary {\n background: #e2e8f0;\n color: #4a5568;\n }\n .btn-secondary:hover {\n background: #cbd5e0;\n }\n .shield-footer {\n margin-top: 24px;\n font-size: 14px;\n color: #718096;\n }\n .shield-footer a {\n color: #6366f1;\n text-decoration: none;\n }\n .shield-footer a:hover {\n text-decoration: underline;\n }\n </style>\n</head>\n<body>\n <div class=\"shield-container\">\n <div class=\"shield-icon\">🛡️</div>\n <h1 class=\"shield-title\">${title}</h1>\n <p class=\"shield-message\">${message}</p>\n\n <div class=\"shield-steps\">\n <h3>To get verified access:</h3>\n <ol>\n <li>Register at <a href=\"${registrationUrl}\">astrasync.ai/agents/register</a></li>\n <li>Create and register your agent</li>\n <li>Add your ASTRA-ID to request headers</li>\n <li>Refresh this page</li>\n </ol>\n </div>\n\n <div class=\"shield-buttons\">\n <a href=\"${registrationUrl}\" class=\"btn btn-primary\">Register Now</a>\n ${allowGuest ? '<button onclick=\"window.location.reload()\" class=\"btn btn-secondary\">Continue as Guest (Limited)</button>' : ''}\n </div>\n\n <p class=\"shield-footer\">\n Learn more: <a href=\"${docsUrl}\">Agent Access Documentation</a>\n </p>\n </div>\n</body>\n</html>\n `.trim();\n}\n\nconst DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1000;\n\n/**\n * Create Next.js middleware for agent verification.\n *\n * v2.9.7 moved per-route policy out of merchant-side source code into the\n * AstraSync dashboard. The middleware fetches its routes from the backend\n * via `GET /endpoints/:counterpartyId/routes` on init and refreshes\n * periodically — see `ExpressMiddlewareOptions` for the rationale (a dual\n * config source silently conflicts with dashboard policy).\n */\nexport function createMiddleware(options: NextJsMiddlewareOptions) {\n // Guard against configs authored for pre-2.9.7 SDKs: a `routes` array in\n // merchant source is silently dead config — and dead route config means\n // the author believes paths are gated that aren't.\n if ('routes' in options) {\n // eslint-disable-next-line no-console\n console.warn(\n '[VerificationGateway/Next.js] `routes` is dashboard-managed since v2.9.7; this option is ignored — ' +\n 'configure route policy in your AstraSync dashboard.'\n );\n }\n const {\n skipPaths = [],\n showInterstitial,\n showCommerceShield,\n enableRuntimeChallenge = true,\n routesRefreshMs = DEFAULT_ROUTES_REFRESH_MS,\n anonymousBeacon = true,\n trustVerifiedHop = false,\n verifiedHopMaxAgeMs,\n ...config\n } = options;\n\n // 4.1.0: `showInterstitial` supersedes the deprecated `showCommerceShield`\n // flag; the new name wins when both are set. Default remains true.\n const interstitialEnabled = showInterstitial ?? showCommerceShield ?? true;\n\n // Dashboard-driven anonymous-traffic beacon for the pass-through paths\n // (no matching route / route gated at `none`). Fire-and-forget: never\n // awaited, never delays the NextResponse. See ./anonymous-beacon.ts.\n const emitAnonymousBeacon = anonymousBeacon\n ? createAnonymousBeacon(config, { counterpartyType: config.counterpartyType ?? 'website' })\n : undefined;\n const beaconPassThrough = emitAnonymousBeacon\n ? (request: NextRequest, pathname: string): void => {\n emitAnonymousBeacon({\n requestPath: pathname,\n requestMethod: request.method,\n counterpartyUrl: config.counterpartyUrl || request.nextUrl.origin,\n sourceIp: request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || undefined,\n rawHeaders: Object.fromEntries(request.headers.entries()),\n });\n }\n : undefined;\n\n let cachedRoutes: RouteAccessConfig[] = [];\n let lastFetchAt = 0;\n let refreshing: Promise<void> | null = null;\n let warnedNoCounterparty = false;\n\n async function refreshRoutes(): Promise<void> {\n if (!config.counterpartyId) {\n if (!warnedNoCounterparty) {\n // eslint-disable-next-line no-console\n console.warn(\n '[VerificationGateway/Next.js] No counterpartyId configured — falling through (allow all). ' +\n 'Per-route policy lives in the AstraSync dashboard now; register the endpoint and ' +\n 'set counterpartyId in your middleware config to enforce policy.'\n );\n warnedNoCounterparty = true;\n }\n return;\n }\n const fetched = await fetchRoutes(config, config.counterpartyId);\n if (fetched) {\n cachedRoutes = fetched;\n lastFetchAt = Date.now();\n }\n }\n\n refreshing = refreshRoutes().finally(() => {\n refreshing = null;\n });\n\n return async function middleware(request: NextRequest) {\n // Dynamic import NextResponse to avoid build issues\n const { NextResponse } = await import('next/server');\n\n const pathname = request.nextUrl.pathname;\n\n // Check if path should be skipped\n const shouldSkip = skipPaths.some((pattern) => matchRoute(pattern, pathname));\n if (shouldSkip) {\n return NextResponse.next();\n }\n\n if (refreshing) {\n await refreshing.catch(() => {});\n }\n if (config.counterpartyId && Date.now() - lastFetchAt > routesRefreshMs) {\n refreshing = refreshRoutes().finally(() => {\n refreshing = null;\n });\n }\n\n // Find route configuration (from remote-fetched cache)\n const routeConfig = findRouteConfig(cachedRoutes, pathname, request.method);\n\n // If no route config, allow through\n if (!routeConfig) {\n // Anonymous-traffic beacon: this request never reaches verify-access,\n // so bot/agent-shaped callers would otherwise be invisible to the\n // dashboard. Fire-and-forget — does not delay the response.\n beaconPassThrough?.(request, pathname);\n return NextResponse.next();\n }\n\n // Observe-only route: pass through unenforced.\n if (routeConfig.observe) {\n // Anonymous-traffic beacon (see the no-route-match branch above).\n beaconPassThrough?.(request, pathname);\n return NextResponse.next();\n }\n\n // Extract credentials\n const credentials = extractCredentialsFromNextRequest(request);\n\n // Inner-hop dedupe: a trusted upstream AstraSync hop (edge gateway or\n // MCP outer hop) already verified this exact ASTRA-id moments ago —\n // accept the fresh marker and skip the duplicate verify-access call.\n // Mirrors the express/MCP adapter contract. The marker must match the\n // request's own X-Astra-Id.\n if (trustVerifiedHop && credentials.astraId) {\n const marker = parseVerifiedHop(request.headers.get(MCP_VERIFIED_HOP_HEADER) ?? undefined);\n if (\n isVerifiedHopValidFor(marker, credentials.astraId, {\n ...(verifiedHopMaxAgeMs !== undefined ? { maxAgeMs: verifiedHopMaxAgeMs } : {}),\n })\n ) {\n return NextResponse.next();\n }\n }\n\n // v2.3.0: anonymous traffic no longer short-circuits client-side.\n // The server applies the endpoint's `unverifiedAgentPolicy` (deny /\n // allow_partial / allow_full) and emits the verification event +\n // blockchain record per the canonical flow. SDK forwards verbatim.\n\n // Auto-detect counterparty URL from the request if not explicitly configured.\n // Since the SDK is installed at this endpoint, we always know the origin.\n const counterpartyUrl = config.counterpartyUrl || request.nextUrl.origin;\n\n // Resolve the canonical {purpose, action} pair (Bug 14, §4.6) and full\n // AstraSync credentials (includes PDLSS from X-Astra-* headers)\n const pdlssPair = resolveNextPdlss(request, routeConfig);\n const purpose = pdlssPair.purpose;\n if (config.debug) {\n // eslint-disable-next-line no-console\n console.debug('[nextjs-middleware] pdlss resolved', {\n purpose_source: pdlssPair.purposeSource,\n resolved_purpose: pdlssPair.purpose,\n action_source: pdlssPair.actionSource,\n resolved_action: pdlssPair.action,\n });\n }\n const astraCreds = extractAstraSyncCredentialsFromNextRequest(request);\n\n // Step 2: Counterparty-side PDLSS pre-check — compare agent's requested PDLSS\n // against counterparty-defined maximums on the route config.\n // Rejects immediately if outside limits, BEFORE calling verify-access.\n const preCheckFailures = performCounterpartyPreCheck(routeConfig, astraCreds, purpose);\n if (preCheckFailures.length > 0) {\n // Round-18 G4: counterparty pre-check failure — see express.ts for the\n // rationale. Neither axis verified remotely → both false.\n const preCheckResult: VerificationResult = {\n identityVerified: false,\n policyAllowed: false,\n denialReasons: preCheckFailures.map((f) => f.message),\n guidance: {\n message: 'Request exceeds counterparty-defined PDLSS limits.',\n registrationUrl: `${config.apiBaseUrl?.replace('/api', '')}/agents/register`,\n documentationUrl: `${config.apiBaseUrl?.replace('/api', '')}/docs/pdlss`,\n },\n verifiedAt: new Date(),\n };\n\n // Fire-and-forget: notify AstraSync of the pre-check failure\n reportCounterpartyPreCheckFailure(config, {\n agentId: astraCreds?.agentId || credentials.astraId || 'unknown',\n counterpartyUrl,\n counterpartyType: config.counterpartyType || 'website',\n failures: preCheckFailures,\n requestPath: pathname,\n requestMethod: request.method,\n }).catch(() => {});\n\n // For API routes, return JSON\n if (pathname.startsWith('/api/')) {\n return NextResponse.json(\n {\n success: false,\n error: {\n code: 'PDLSS_PRE_CHECK_FAILED',\n message: preCheckResult.denialReasons?.[0] || 'PDLSS pre-check failed',\n guidance: preCheckResult.guidance,\n },\n },\n { status: 403 }\n );\n }\n\n // For web pages, show the verification interstitial\n if (interstitialEnabled) {\n return new NextResponse(generateInterstitialHtml(preCheckResult, options), {\n status: 200,\n headers: {\n 'Content-Type': 'text/html',\n 'X-AstraSync-Verification': 'commerce-shield',\n },\n });\n }\n\n return NextResponse.redirect(new URL('/unauthorized', request.url));\n }\n\n // Step 3: Call AstraSync verify-access with runtime challenge enabled\n const forwardedFor = request.headers.get('x-forwarded-for') || undefined;\n const originalClientIp = forwardedFor?.split(',')[0]?.trim();\n // 5.8.0 attempt-chain (X-Astra-Attempt-Id) — see express.ts for the full\n // rationale: threading the bridge-stamped chain id lets an already-\n // approved step-up pass this hop instead of minting a second approval.\n const attemptHeader = request.headers.get('x-astra-attempt-id');\n const inboundAttemptId =\n attemptHeader && /^att_[0-9a-f]{32}$/.test(attemptHeader) ? attemptHeader : undefined;\n const verificationRequest: VerificationRequest = {\n credentials,\n purpose,\n action: pdlssPair.action,\n resource: pathname,\n counterpartyUrl,\n counterpartyType: config.counterpartyType || 'website',\n enableRuntimeChallenge,\n durationRequired: astraCreds?.pdlss?.duration?.maxSessionDuration,\n ...(inboundAttemptId && { attemptId: inboundAttemptId }),\n callerMetadata: {\n sourceIp: originalClientIp,\n userAgent: request.headers.get('user-agent') || undefined,\n referer: request.headers.get('referer') || undefined,\n host: request.headers.get('host') || undefined,\n forwardedFor,\n agentCardUrl: request.headers.get('x-astrasync-agent-card') || undefined,\n // Workstream D — full sanitised header capture + CDN-derived\n // connection block (Web Headers → plain map).\n observedMetadata: buildSdkObservedMetadata(Object.fromEntries(request.headers.entries())),\n },\n };\n let result = await verify(config, verificationRequest);\n\n // 3.6.0 hold-and-poll (opt-in via stepUpMaxWaitMs) — see express.ts for\n // the full rationale. CAUTION on edge runtimes (~25s wall-clock budget):\n // set a small stepUpMaxWaitMs or gate in a Node route handler instead.\n // On 'approved' the same request is re-verified once, cache-bypassed, so\n // the backend redeems the single-use approval.\n let stepUpHoldOutcome: StepUpOutcome | undefined;\n if (\n config.stepUpMaxWaitMs !== undefined &&\n result.policyAllowed &&\n requiresHumanApproval(result) &&\n result.stepUpApproval?.pollUrl\n ) {\n stepUpHoldOutcome = await awaitStepUpApproval(config, result.stepUpApproval);\n if (stepUpHoldOutcome === 'approved') {\n result = await verify(config, verificationRequest, { bypassCache: true });\n } else {\n result.stepUpOutcome = stepUpHoldOutcome;\n }\n }\n\n // Round-18 G4: short-circuit on either axis failing (identity-fail or\n // policy-fail) — both encode the server-side trust-floor + PDLSS decision.\n // The access decision rests on a verified ID + runtime challenge + PDLSS\n // match + trust score; there is no access-level band (removed in SDK 5.0.0).\n // Per-route tightening is `route.minTrustScore` (below).\n // F2 direct-path fail-closed: a step-up / requires-approval outcome\n // (policyAllowed:true, allowed-but-escalate) cannot be completed\n // autonomously — deny and surface stepUpApproval polling info.\n // 4.5.0: gate on the SERVER decision only (`policyAllowed`) — anonymous\n // callers allowed by an audit/allow endpoint policy are honestly\n // identity-unverified; see express.ts for the full rationale.\n const approvalRequired = result.policyAllowed && requiresHumanApproval(result);\n if (approvalRequired) annotateApprovalRequired(result);\n\n if (!result.policyAllowed || approvalRequired) {\n // 4.0.0 BREAKING (API routes): this site's OWN key was rejected —\n // answer 503 with the dedicated code so agents don't read a merchant\n // misconfig as their own auth failure (see express.defaultOnDenied).\n // Web pages keep their existing shield/redirect flow — a human page\n // view must not turn into raw JSON because the operator rotated a key.\n if (result.misconfigured && pathname.startsWith('/api/')) {\n return NextResponse.json(\n {\n success: false,\n error: {\n code: 'MERCHANT_VERIFICATION_MISCONFIGURED',\n message:\n result.denialReasons?.[0] || \"This site's AstraSync integration is misconfigured\",\n guidance: result.guidance,\n failures: result.failures,\n correlationId: result.correlationId,\n },\n },\n { status: 503 }\n );\n }\n\n // For API routes, return JSON\n if (pathname.startsWith('/api/')) {\n return NextResponse.json(\n {\n success: false,\n error: {\n // Round-18 G4: 401 → identity missing (re-auth); 403 → identity\n // OK, policy denied (update PDLSS / step up).\n code: !result.identityVerified ? 'UNAUTHORIZED' : 'POLICY_DENIED',\n message: result.denialReasons?.[0] || 'Access denied',\n guidance: result.guidance,\n failures: result.failures,\n stepUpApproval: result.stepUpApproval,\n // 3.6.0: terminal outcome of an opt-in hold-and-poll wait.\n ...(result.stepUpOutcome && { stepUpOutcome: result.stepUpOutcome }),\n },\n },\n {\n status: !result.identityVerified ? 401 : 403,\n ...(stepUpHoldOutcome && {\n headers: { 'X-Astra-Step-Up': stepUpHoldOutcome },\n }),\n }\n );\n }\n\n // For web pages, show the verification interstitial\n if (interstitialEnabled) {\n return new NextResponse(generateInterstitialHtml(result, options), {\n status: 200,\n headers: {\n 'Content-Type': 'text/html',\n 'X-AstraSync-Verification': 'commerce-shield',\n },\n });\n }\n\n // Redirect to unauthorized page\n return NextResponse.redirect(new URL('/unauthorized', request.url));\n }\n\n // All checks passed - continue with verification info in headers\n const response = NextResponse.next();\n\n // Add verification info to response headers\n // Round-18 G4: composite `verified` (identity AND policy) for legacy\n // header consumers; new headers expose each axis separately so middleware\n // chains can branch without re-running verify-access.\n response.headers.set(\n 'X-AstraSync-Verified',\n (result.identityVerified && result.policyAllowed).toString()\n );\n if (stepUpHoldOutcome) {\n response.headers.set('X-Astra-Step-Up', stepUpHoldOutcome);\n }\n response.headers.set('X-AstraSync-Identity-Verified', result.identityVerified.toString());\n response.headers.set('X-AstraSync-Policy-Allowed', result.policyAllowed.toString());\n\n if (result.agent) {\n response.headers.set('X-AstraSync-Agent-Id', result.agent.astraId);\n // 3.2.0 (post-3.1.0 feedback #2): the X-AstraSync-Trust-Score header is\n // no longer emitted — trust is a system-internal signal and this header\n // rode on the passthrough response toward the agent (gaming vector).\n }\n\n return response;\n };\n}\n\n/**\n * Helper to create matcher config\n */\nexport function createMatcherConfig(paths: string[]): { matcher: string[] } {\n return { matcher: paths };\n}\n","/**\n * RFC 9421 HTTP Message Signatures parser.\n *\n * Wraps `structured-headers` (transitive dep of http-message-signatures) to\n * parse the Signature-Input and Signature Dictionary headers per RFC 9421\n * Section 2.\n *\n * Produces structured metadata (kid, algorithm, covered components, tag,\n * created/expires/nonce, signature bytes) without verifying the signature —\n * verification lives in rfc9421-verify.ts.\n *\n * Shared by:\n * - Agent Pay (Mastercard) — kid resolves via Mastercard Agent Registry\n * - TAP (Visa) — kid resolves via Visa JWKS\n * - Web Bot Auth (generic transport substrate) — kid resolves via\n * /.well-known/http-message-signatures-directory\n */\n\nimport { parseDictionary } from 'structured-headers';\n\nexport interface RFC9421SignatureParams {\n /** The label identifying the signature in the Dictionary header (e.g. \"sig1\"). */\n label: string;\n /** Key ID used to look up the verifying key in the relevant registry. */\n kid: string;\n /** Algorithm declared in the Signature-Input params (e.g. \"ecdsa-p256-sha256\", \"ed25519\"). */\n alg?: string;\n /** Covered components, in order, per RFC 9421 Section 2.1. */\n covered: string[];\n /** Base64url-encoded signature bytes extracted from the paired Signature header. */\n signatureBase64: string;\n /** Unix seconds when the signature was created. */\n created?: number;\n /** Unix seconds when the signature expires. */\n expires?: number;\n /** Nonce (opaque string) for replay protection. */\n nonce?: string;\n /** Tag parameter. For Agent Pay/TAP this is \"browse\" or \"purchase\"; undefined otherwise. */\n tag?: 'browse' | 'purchase' | string;\n}\n\nexport interface ParsedRFC9421 {\n signatures: RFC9421SignatureParams[];\n}\n\n/**\n * Parse the RFC 9421 Signature-Input and Signature headers from a request or response.\n * Returns all signatures present (a single message may carry multiple labelled signatures).\n *\n * Returns null if either header is missing or malformed.\n */\nexport function parseRFC9421(\n headers: Record<string, string | string[] | undefined>\n): ParsedRFC9421 | null {\n const sigInput = readHeader(headers, 'signature-input');\n const sig = readHeader(headers, 'signature');\n if (!sigInput || !sig) return null;\n\n let inputDict;\n let sigDict;\n try {\n inputDict = parseDictionary(sigInput);\n sigDict = parseDictionary(sig);\n } catch {\n return null;\n }\n\n const signatures: RFC9421SignatureParams[] = [];\n\n for (const [label, entry] of inputDict) {\n // entry.value is the inner list of covered components; entry[1] is the params Map.\n const innerList = Array.isArray(entry)\n ? entry[0]\n : (entry as { value?: unknown; params?: unknown }).value;\n const params = Array.isArray(entry)\n ? entry[1]\n : (entry as { value?: unknown; params?: unknown }).params;\n if (!Array.isArray(innerList) || !params) continue;\n\n const covered: string[] = [];\n for (const item of innerList as Array<[unknown, Map<string, unknown>]>) {\n const [bare] = Array.isArray(item) ? item : [item];\n if (typeof bare === 'string') covered.push(bare);\n else if (bare && typeof bare === 'object' && 'toString' in bare) covered.push(String(bare));\n }\n\n const paramsMap = params as Map<string, unknown>;\n const kid = coerceString(paramsMap.get('keyid'));\n if (!kid) continue;\n\n const sigEntry = sigDict.get(label);\n if (!sigEntry) continue;\n\n const sigBare = Array.isArray(sigEntry) ? sigEntry[0] : (sigEntry as { value?: unknown }).value;\n const signatureBase64 = extractBase64(sigBare);\n if (!signatureBase64) continue;\n\n signatures.push({\n label,\n kid,\n alg: coerceString(paramsMap.get('alg')),\n covered,\n signatureBase64,\n created: coerceNumber(paramsMap.get('created')),\n expires: coerceNumber(paramsMap.get('expires')),\n nonce: coerceString(paramsMap.get('nonce')),\n tag: coerceString(paramsMap.get('tag')),\n });\n }\n\n if (signatures.length === 0) return null;\n return { signatures };\n}\n\nfunction readHeader(\n headers: Record<string, string | string[] | undefined>,\n name: string\n): string | null {\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === name) {\n const raw = headers[key];\n if (typeof raw === 'string') return raw;\n if (Array.isArray(raw)) return raw.join(', ');\n return null;\n }\n }\n return null;\n}\n\nfunction coerceString(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (value == null) return undefined;\n if (typeof value === 'object' && 'toString' in (value as object)) {\n const s = String(value);\n return s.length > 0 ? s : undefined;\n }\n return undefined;\n}\n\nfunction coerceNumber(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'bigint') return Number(value);\n return undefined;\n}\n\nfunction extractBase64(value: unknown): string | null {\n if (value instanceof Uint8Array) return bufferToBase64(value);\n if (value instanceof ArrayBuffer) return bufferToBase64(new Uint8Array(value));\n if (ArrayBuffer.isView(value)) {\n const v = value as ArrayBufferView;\n return bufferToBase64(new Uint8Array(v.buffer, v.byteOffset, v.byteLength));\n }\n if (typeof value === 'string') {\n if (value.startsWith(':') && value.endsWith(':')) return value.slice(1, -1);\n return value;\n }\n return null;\n}\n\nfunction bufferToBase64(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString('base64');\n}\n","/**\n * RFC 9421 HTTP Message Signatures verification.\n *\n * Wraps http-message-signatures (dhensby) verifyMessage() with a RegistryResolver\n * hook for kid → JWK lookup. Library handles canonicalization + ES256/EdDSA/\n * HMAC/RSA verification; we supply the key-finding callback and policy around\n * clock skew.\n *\n * Shared by:\n * - Agent Pay (Mastercard) — resolver = createMastercardRegistry\n * - TAP (Visa) — resolver = createVisaRegistry\n * - Web Bot Auth (generic) — resolver = createWebBotAuthRegistry\n */\n\nimport { httpbis, type VerifierFinder, type VerifyingKey } from 'http-message-signatures';\nimport type { JWK } from 'jose';\nimport type { RegistryResolver } from './registry/types';\nimport { defaultNonceStore, type NonceStore } from './nonce-store';\n\nexport interface RFC9421VerifyRequest {\n method: string;\n url: string;\n headers: Record<string, string | string[]>;\n body?: string;\n}\n\nexport interface RFC9421VerifyOptions {\n resolver: RegistryResolver;\n /** Seconds of tolerance around created/expires. Default 60 (tightened from 300). */\n clockSkewSec?: number;\n /** Injectable for deterministic tests. */\n now?: () => number;\n /** Optional replay-protection store. Defaults to in-process LRU. */\n nonceStore?: NonceStore;\n}\n\nexport interface RFC9421VerifyResult {\n ok: boolean;\n kid?: string;\n registry?: RegistryResolver['name'];\n algorithm?: string;\n error?: string;\n}\n\nexport async function verifyRFC9421(\n request: RFC9421VerifyRequest,\n options: RFC9421VerifyOptions\n): Promise<RFC9421VerifyResult> {\n const { resolver } = options;\n const tolerance = options.clockSkewSec ?? 60;\n const nowSec = options.now ? options.now() : Math.floor(Date.now() / 1000);\n const nonceStore = options.nonceStore ?? defaultNonceStore;\n\n let resolvedKid: string | undefined;\n let resolvedAlg: string | undefined;\n let replayDetected = false;\n\n const keyLookup: VerifierFinder = async (parameters) => {\n const kid = typeof parameters.keyid === 'string' ? parameters.keyid : undefined;\n if (!kid) return null;\n resolvedKid = kid;\n const alg = typeof parameters.alg === 'string' ? parameters.alg : undefined;\n if (alg) resolvedAlg = alg;\n\n const origin = safeOrigin(request.url);\n const jwk = await resolver.resolve(kid, { origin, algorithm: alg });\n if (!jwk) return null;\n\n // Check clock-skew on this specific signature's created/expires.\n // SignatureParameters may carry Date, number, or ISO string per library.\n const created = toUnixSeconds(parameters.created);\n const expires = toUnixSeconds(parameters.expires);\n if (created !== undefined && Math.abs(nowSec - created) > tolerance) return null;\n if (expires !== undefined && nowSec > expires + tolerance) return null;\n\n // Audit F-A1-05: replay protection. RFC 9421 signatures include a\n // `nonce` parameter (optional but recommended for replay-sensitive\n // contexts). When present, register kid+nonce; reject duplicates\n // within the expiry window.\n const nonce = typeof parameters.nonce === 'string' ? parameters.nonce : undefined;\n if (nonce) {\n const expiresAtMs = (expires !== undefined ? expires + tolerance : nowSec + tolerance) * 1000;\n if (nonceStore.seen(`rfc9421:${kid}:${nonce}`, expiresAtMs)) {\n replayDetected = true;\n return null;\n }\n }\n\n return jwkToVerifyingKey(kid, jwk, alg);\n };\n\n try {\n const result = await httpbis.verifyMessage(\n {\n keyLookup,\n },\n normalizeRequest(request)\n );\n if (result === true) {\n return {\n ok: true,\n kid: resolvedKid,\n registry: resolver.name,\n algorithm: resolvedAlg,\n };\n }\n return {\n ok: false,\n kid: resolvedKid,\n registry: resolver.name,\n algorithm: resolvedAlg,\n error: replayDetected\n ? 'RFC9421 signature replay — already seen within tolerance window'\n : result === false\n ? 'signature invalid'\n : 'no signature found',\n };\n } catch (err) {\n return {\n ok: false,\n kid: resolvedKid,\n registry: resolver.name,\n algorithm: resolvedAlg,\n error: err instanceof Error ? err.message : 'verification error',\n };\n }\n}\n\nfunction normalizeRequest(request: RFC9421VerifyRequest): {\n method: string;\n url: string;\n headers: Record<string, string | string[]>;\n} {\n return {\n method: request.method.toUpperCase(),\n url: request.url,\n headers: request.headers,\n };\n}\n\nfunction safeOrigin(url: string): string | undefined {\n try {\n return new URL(url).origin;\n } catch {\n return undefined;\n }\n}\n\nasync function jwkToVerifyingKey(\n id: string,\n jwk: JWK,\n alg: string | undefined\n): Promise<VerifyingKey> {\n const algorithm = alg ?? inferAlgFromJwk(jwk);\n const { subtle } = await getCrypto();\n const importAlg = webCryptoImportAlgFor(algorithm);\n const verifyAlg = webCryptoAlgFor(algorithm);\n if (!importAlg || !verifyAlg) {\n return {\n id,\n algs: alg ? [alg] : undefined,\n verify: async () => false,\n };\n }\n const key = await subtle.importKey('jwk', jwk as JsonWebKey, importAlg, false, ['verify']);\n\n return {\n id,\n algs: alg ? [alg] : undefined,\n verify: async (data: Buffer, signature: Buffer): Promise<boolean> => {\n try {\n return await subtle.verify(verifyAlg, key, toArrayBuffer(signature), toArrayBuffer(data));\n } catch {\n return false;\n }\n },\n };\n}\n\nfunction inferAlgFromJwk(jwk: JWK): string {\n if (jwk.kty === 'OKP' && jwk.crv === 'Ed25519') return 'ed25519';\n if (jwk.kty === 'EC' && jwk.crv === 'P-256') return 'ecdsa-p256-sha256';\n if (jwk.kty === 'EC' && jwk.crv === 'P-384') return 'ecdsa-p384-sha384';\n if (jwk.kty === 'RSA') return 'rsa-v1_5-sha256';\n return 'ecdsa-p256-sha256';\n}\n\nfunction webCryptoAlgFor(\n rfc9421Alg: string\n): AlgorithmIdentifier | EcdsaParams | RsaPssParams | null {\n switch (rfc9421Alg) {\n case 'ed25519':\n return { name: 'Ed25519' };\n case 'ecdsa-p256-sha256':\n return { name: 'ECDSA', hash: 'SHA-256' };\n case 'ecdsa-p384-sha384':\n return { name: 'ECDSA', hash: 'SHA-384' };\n case 'rsa-v1_5-sha256':\n return { name: 'RSASSA-PKCS1-v1_5' };\n case 'rsa-pss-sha512':\n return { name: 'RSA-PSS', saltLength: 64 };\n default:\n return null;\n }\n}\n\nfunction webCryptoImportAlgFor(\n rfc9421Alg: string\n): AlgorithmIdentifier | EcKeyImportParams | RsaHashedImportParams | null {\n switch (rfc9421Alg) {\n case 'ed25519':\n return { name: 'Ed25519' };\n case 'ecdsa-p256-sha256':\n return { name: 'ECDSA', namedCurve: 'P-256' };\n case 'ecdsa-p384-sha384':\n return { name: 'ECDSA', namedCurve: 'P-384' };\n case 'rsa-v1_5-sha256':\n return { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' };\n case 'rsa-pss-sha512':\n return { name: 'RSA-PSS', hash: 'SHA-512' };\n default:\n return null;\n }\n}\n\nfunction toArrayBuffer(buf: Buffer): ArrayBuffer {\n const out = new ArrayBuffer(buf.byteLength);\n new Uint8Array(out).set(buf);\n return out;\n}\n\nfunction toUnixSeconds(v: unknown): number | undefined {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n if (v instanceof Date) return Math.floor(v.getTime() / 1000);\n if (typeof v === 'string') {\n const parsed = Date.parse(v);\n if (Number.isFinite(parsed)) return Math.floor(parsed / 1000);\n }\n return undefined;\n}\n\nasync function getCrypto(): Promise<{ subtle: SubtleCrypto }> {\n if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.subtle) {\n return { subtle: globalThis.crypto.subtle };\n }\n // Node fallback\n const nodeCrypto = await import('node:crypto');\n return { subtle: nodeCrypto.webcrypto.subtle as SubtleCrypto };\n}\n","/**\n * Shared nonce/signature replay-protection store for transport verifiers.\n *\n * Rationale: every transport-signature verifier (RFC9421, VI, AP2, ACP,\n * MPP) validates a created/expires window, but without a seen-nonce\n * cache any captured signed request can be replayed within the (default\n * 300s, now tightened to 60s) tolerance window.\n *\n * This module ships a bounded in-memory LRU as the default. Production\n * deployments with multi-pod horizontal scaling SHOULD pass a shared store\n * (Redis-backed) via the verifier options to make replay protection global\n * rather than per-pod.\n *\n * The store interface is intentionally minimal: a single `seen(key,\n * expiresAt)` method that returns true iff the key was already recorded\n * (i.e. caller should reject as a replay). Callers compose the key from\n * whichever identifiers are unique to the signature (kid + nonce + sig\n * digest, typically).\n */\n\nexport interface NonceStore {\n /**\n * Record `key` as seen. Returns true iff the key was ALREADY present —\n * i.e. caller should reject the request as a replay. Returns false on\n * first sighting (caller should proceed).\n *\n * `expiresAtMs` is a hint for the store to evict entries that can no\n * longer cause harm (their signature window has elapsed).\n */\n seen(key: string, expiresAtMs: number): boolean;\n}\n\n/**\n * Default in-memory LRU. Per-process, lost on restart. Suitable for\n * single-pod deploys and for development; production multi-pod deploys\n * should pass a shared store.\n *\n * Capacity-bounded: once the limit is reached, the oldest entry is dropped\n * even if it hasn't yet expired. The limit (default 10k entries) is large\n * enough that meaningful replay windows shouldn't approach it; if a\n * deployment is hitting it, that's a signal to migrate to Redis.\n *\n * Also runs a lazy sweep on each `seen` call to evict entries past their\n * `expiresAtMs` — keeps memory bounded under burst load.\n */\nexport class InMemoryNonceStore implements NonceStore {\n private readonly entries = new Map<string, number>();\n private readonly capacity: number;\n private lastSweepMs = 0;\n\n constructor(capacity = 10_000) {\n this.capacity = capacity;\n }\n\n seen(key: string, expiresAtMs: number): boolean {\n const nowMs = Date.now();\n\n // Lazy sweep: at most once per second, walk expired entries.\n if (nowMs - this.lastSweepMs > 1000) {\n for (const [k, exp] of this.entries) {\n if (exp <= nowMs) this.entries.delete(k);\n }\n this.lastSweepMs = nowMs;\n }\n\n const existing = this.entries.get(key);\n if (existing !== undefined && existing > nowMs) {\n return true; // replay\n }\n\n // First sighting (or stale entry) — record + evict oldest if over capacity.\n if (this.entries.size >= this.capacity) {\n const oldest = this.entries.keys().next().value;\n if (oldest !== undefined) this.entries.delete(oldest);\n }\n this.entries.set(key, expiresAtMs);\n return false;\n }\n}\n\n/**\n * Process-wide singleton instance for convenience. Verifiers that don't\n * receive an explicit nonceStore in their options fall back to this.\n *\n * Memory-bounded at 10k entries by default; sufficient for a single pod\n * handling thousands of requests/sec where signatures only carry value\n * within their (60s default) expiry window.\n */\nexport const defaultNonceStore = new InMemoryNonceStore();\n","/**\n * VI (Verifiable Intent) SD-JWT extraction.\n *\n * Open-sourced 5 March 2026 by Mastercard + Google (v0.1-draft).\n * VI is a 3-layer SD-JWT chain:\n * L1 — issuer → wallet (credential provider)\n * L2 — user → agent (cnf.jwk binding to L3 agent key)\n * L3 — agent → merchant (payment or checkout mandate, split into L3a / L3b\n * cross-referenced via transaction_id)\n *\n * This module does EXTRACTION ONLY — it decodes SD-JWT structure and pulls\n * out the mandate type, kid, executionMode, 8 constraint types, checkoutHash\n * (constraint type 8), transactionId, and raw layers for later verification.\n *\n * Signature verification lives in vi-verify.ts; this module uses @sd-jwt's\n * sync decoder with a SHA-256 hasher for structural parsing only.\n */\n\nimport { splitSdJwt, decodeSdJwtSync } from '@sd-jwt/core';\nimport { createHash } from 'node:crypto';\nimport type { VIMandateType } from './purpose-mapping';\n\nexport type { VIMandateType };\nexport type VIExecutionMode = 'Immediate' | 'Autonomous' | 'Both';\n\nexport interface VIAllowedParty {\n id?: string;\n name?: string;\n website?: string;\n}\n\nexport interface VILineItem {\n id?: string;\n acceptableItems?: string[];\n quantity?: number;\n}\n\nexport interface VIPaymentAmount {\n currency?: string;\n min?: number;\n max?: number;\n}\n\nexport interface VIBudgetLimit {\n currency?: string;\n max?: number;\n}\n\nexport interface VIRecurrence {\n frequency?: string;\n startDate?: string;\n endDate?: string;\n maxOccurrences?: number;\n}\n\nexport interface VIConstraints {\n allowedMerchants?: VIAllowedParty[];\n allowedPayees?: VIAllowedParty[];\n lineItems?: VILineItem[];\n paymentAmount?: VIPaymentAmount;\n budgetLimit?: VIBudgetLimit;\n recurrence?: VIRecurrence;\n agentRecurrence?: VIRecurrence;\n}\n\nexport interface VIExtractedClaims {\n mandateType: VIMandateType;\n kid?: string;\n executionMode?: VIExecutionMode;\n credentialProvider?: string;\n constraints: VIConstraints;\n /** VI constraint type 8 — SHA-256 of the paired L2 checkout disclosure. */\n checkoutHash?: string;\n transactionId?: string;\n rawLayers: { l1?: string; l2?: string; l3?: string };\n}\n\n/**\n * Extract VI claims from a compact SD-JWT string.\n *\n * Input shape:\n * <jwt>~<disclosure1>~<disclosure2>~...~<kbJwt?>\n *\n * Returns null if parsing fails at any layer. Does not verify signatures.\n */\nexport function extractVIClaims(sdJwtCompact: string): VIExtractedClaims | null {\n if (!sdJwtCompact || typeof sdJwtCompact !== 'string') return null;\n\n let decoded;\n try {\n decoded = decodeSdJwtSync(sdJwtCompact, sha256Sync);\n } catch {\n return null;\n }\n\n const split = safeSplit(sdJwtCompact);\n\n const payload = (decoded.jwt?.payload ?? {}) as Record<string, unknown>;\n const disclosures = decoded.disclosures ?? [];\n\n // Apply disclosures onto payload to resolve _sd references.\n // Disclosure from @sd-jwt/core has { key, value, digest() } where digest is\n // a function — we only need key+value here, so narrow via a structural cast.\n const claims = applyDisclosures(\n payload,\n disclosures as unknown as Array<{ key?: string; value?: unknown }>\n );\n\n const mandateType = coerceMandateType(\n claims.mandate_type ?? claims.mandateType ?? payload.mandate_type ?? payload.mandateType\n );\n if (!mandateType) return null;\n\n const kid = coerceString(\n (decoded.jwt?.header as Record<string, unknown> | undefined)?.kid ?? claims.kid ?? payload.kid\n );\n\n const executionMode = coerceExecutionMode(claims.execution_mode ?? claims.executionMode);\n const credentialProvider = coerceString(claims.iss ?? payload.iss);\n\n const constraints = extractConstraints(\n (claims.constraints ?? claims.default_constraints ?? {}) as Record<string, unknown>\n );\n\n const transactionId = coerceString(claims.transaction_id ?? claims.transactionId);\n const checkoutHash = coerceString(\n claims.checkout_hash ??\n claims.conditional_transaction_id ??\n (claims.payment_reference as Record<string, unknown> | undefined)?.checkout_hash\n );\n\n return {\n mandateType,\n kid,\n executionMode,\n credentialProvider,\n constraints,\n checkoutHash,\n transactionId,\n rawLayers: split,\n };\n}\n\nfunction safeSplit(compact: string): { l1?: string; l2?: string; l3?: string } {\n try {\n const { jwt, kbJwt } = splitSdJwt(compact);\n // VI layering maps loosely: the outer JWT is L3 (agent mandate), KB-JWT\n // (if present) is the key-binding proof, and disclosures carry L2/L1 fragments.\n return { l3: jwt, l2: kbJwt };\n } catch {\n return {};\n }\n}\n\nfunction applyDisclosures(\n payload: Record<string, unknown>,\n disclosures: Array<{ key?: string; value?: unknown }>\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...payload };\n for (const d of disclosures) {\n if (d.key && d.value !== undefined && !(d.key in result)) {\n result[d.key] = d.value;\n }\n }\n return result;\n}\n\nfunction extractConstraints(raw: Record<string, unknown>): VIConstraints {\n return {\n allowedMerchants: toAllowedPartyArray(raw.allowed_merchants ?? raw.allowedMerchants),\n allowedPayees: toAllowedPartyArray(raw.allowed_payees ?? raw.allowedPayees),\n lineItems: toLineItemArray(raw.line_items ?? raw.lineItems),\n paymentAmount: toPaymentAmount(raw.payment_amount ?? raw.paymentAmount),\n budgetLimit: toBudgetLimit(raw.budget_limit ?? raw.budgetLimit ?? raw.budget),\n recurrence: toRecurrence(raw.recurrence),\n agentRecurrence: toRecurrence(raw.agent_recurrence ?? raw.agentRecurrence),\n };\n}\n\nfunction toAllowedPartyArray(v: unknown): VIAllowedParty[] | undefined {\n if (!Array.isArray(v)) return undefined;\n const out: VIAllowedParty[] = [];\n for (const item of v) {\n if (item && typeof item === 'object') {\n const r = item as Record<string, unknown>;\n out.push({\n id: coerceString(r.id),\n name: coerceString(r.name),\n website: coerceString(r.website),\n });\n }\n }\n return out.length > 0 ? out : undefined;\n}\n\nfunction toLineItemArray(v: unknown): VILineItem[] | undefined {\n if (!Array.isArray(v)) return undefined;\n const out: VILineItem[] = [];\n for (const item of v) {\n if (item && typeof item === 'object') {\n const r = item as Record<string, unknown>;\n const acc = r.acceptable_items ?? r.acceptableItems;\n out.push({\n id: coerceString(r.id),\n acceptableItems: Array.isArray(acc)\n ? (acc.filter((a) => typeof a === 'string') as string[])\n : undefined,\n quantity: coerceNumber(r.quantity),\n });\n }\n }\n return out.length > 0 ? out : undefined;\n}\n\nfunction toPaymentAmount(v: unknown): VIPaymentAmount | undefined {\n if (!v || typeof v !== 'object') return undefined;\n const r = v as Record<string, unknown>;\n return {\n currency: coerceString(r.currency),\n min: coerceNumber(r.min),\n max: coerceNumber(r.max),\n };\n}\n\nfunction toBudgetLimit(v: unknown): VIBudgetLimit | undefined {\n if (!v || typeof v !== 'object') return undefined;\n const r = v as Record<string, unknown>;\n return {\n currency: coerceString(r.currency),\n max: coerceNumber(r.max),\n };\n}\n\nfunction toRecurrence(v: unknown): VIRecurrence | undefined {\n if (!v || typeof v !== 'object') return undefined;\n const r = v as Record<string, unknown>;\n return {\n frequency: coerceString(r.frequency),\n startDate: coerceString(r.start_date ?? r.startDate),\n endDate: coerceString(r.end_date ?? r.endDate),\n maxOccurrences: coerceNumber(r.max_occurrences ?? r.maxOccurrences),\n };\n}\n\nfunction coerceMandateType(v: unknown): VIMandateType | null {\n if (v === 'checkout' || v === 'payment' || v === 'checkout.open' || v === 'payment.open') {\n return v;\n }\n return null;\n}\n\nfunction coerceExecutionMode(v: unknown): VIExecutionMode | undefined {\n return v === 'Immediate' || v === 'Autonomous' || v === 'Both' ? v : undefined;\n}\n\nfunction coerceString(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n}\n\nfunction coerceNumber(v: unknown): number | undefined {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n if (typeof v === 'string') {\n const n = Number(v);\n return Number.isFinite(n) ? n : undefined;\n }\n return undefined;\n}\n\nfunction sha256Sync(data: string | ArrayBuffer): Uint8Array {\n const buf =\n typeof data === 'string' ? Buffer.from(data, 'utf-8') : Buffer.from(new Uint8Array(data));\n const hash = createHash('sha256').update(buf).digest();\n return new Uint8Array(hash.buffer, hash.byteOffset, hash.byteLength);\n}\n","/**\n * Stripe webhook HMAC-SHA256 verifier (inline).\n *\n * Stripe-Signature header format: \"t=TIMESTAMP,v1=HEX_SIGNATURE\"\n * - t: unix seconds when Stripe signed the webhook\n * - v1: HMAC-SHA256(webhook_secret, `${t}.${payload}`) as hex\n *\n * Multiple v1 signatures can coexist during secret rotation; any match wins.\n * Default tolerance on timestamp age: 300s (matches Stripe's own default).\n *\n * Documented at docs.stripe.com — we intentionally inline ~25 LOC rather\n * than pull in the full stripe npm package (MIT but 600KB+ with deps).\n */\n\nimport { createHmac, timingSafeEqual } from 'node:crypto';\n\nexport interface VerifyStripeWebhookResult {\n ok: boolean;\n timestamp?: number;\n error?: string;\n}\n\nexport interface VerifyStripeWebhookOptions {\n toleranceSec?: number;\n /** Injectable for deterministic tests. */\n now?: () => number;\n}\n\nexport function verifyStripeWebhook(\n payload: string,\n signatureHeader: string | undefined,\n secret: string,\n options: VerifyStripeWebhookOptions = {}\n): VerifyStripeWebhookResult {\n if (!signatureHeader) return { ok: false, error: 'missing Stripe-Signature header' };\n if (!secret) return { ok: false, error: 'missing webhook secret' };\n\n const parsed = parseStripeSignature(signatureHeader);\n if (!parsed.timestamp) return { ok: false, error: 'malformed Stripe-Signature (missing t=)' };\n if (parsed.v1Signatures.length === 0) {\n return { ok: false, error: 'malformed Stripe-Signature (no v1=)' };\n }\n\n const tolerance = options.toleranceSec ?? 300;\n const now = options.now ? options.now() : Math.floor(Date.now() / 1000);\n if (Math.abs(now - parsed.timestamp) > tolerance) {\n return {\n ok: false,\n timestamp: parsed.timestamp,\n error: `timestamp outside tolerance (${tolerance}s)`,\n };\n }\n\n const signedPayload = `${parsed.timestamp}.${payload}`;\n const expected = createHmac('sha256', secret).update(signedPayload).digest();\n\n for (const candidateHex of parsed.v1Signatures) {\n const candidate = hexToBuffer(candidateHex);\n if (!candidate) continue;\n if (candidate.length !== expected.length) continue;\n if (timingSafeEqual(candidate, expected)) {\n return { ok: true, timestamp: parsed.timestamp };\n }\n }\n\n return { ok: false, timestamp: parsed.timestamp, error: 'signature mismatch' };\n}\n\ninterface ParsedStripeSignature {\n timestamp: number | null;\n v1Signatures: string[];\n}\n\nfunction parseStripeSignature(header: string): ParsedStripeSignature {\n let timestamp: number | null = null;\n const v1Signatures: string[] = [];\n for (const part of header.split(',')) {\n const [rawKey, rawValue] = part.split('=');\n if (!rawKey || !rawValue) continue;\n const key = rawKey.trim();\n const value = rawValue.trim();\n if (key === 't') {\n const n = Number(value);\n if (Number.isFinite(n)) timestamp = n;\n } else if (key === 'v1') {\n v1Signatures.push(value);\n }\n }\n return { timestamp, v1Signatures };\n}\n\nfunction hexToBuffer(hex: string): Buffer | null {\n if (!/^[0-9a-fA-F]+$/.test(hex) || hex.length % 2 !== 0) return null;\n return Buffer.from(hex, 'hex');\n}\n","/**\n * AP2 (Agent Payments Protocol) mandate extraction.\n *\n * Google-led, launched 3 April 2026 with 60+ partners (Mastercard, PayPal,\n * Coinbase, AmEx, Revolut, UnionPay, ...). AP2 ships three mandate types as\n * SD-JWTs in series:\n * - intent_mandate — user declares intent (amount, merchant category, etc.)\n * - cart_mandate — user approves a cart (specific items, totals)\n * - payment_mandate — authorizes the actual payment rail\n *\n * Mandates are cross-referenced via ids; each is an SD-JWT over ES256 (or\n * equivalent). We decode via @sd-jwt/core and extract the AP2-specific\n * shape — verification lives in ap2-verify.ts.\n */\n\nimport { decodeSdJwtSync } from '@sd-jwt/core';\nimport { createHash } from 'node:crypto';\nimport type { AP2MandateType } from './purpose-mapping';\n\nexport type { AP2MandateType };\n\nexport interface AP2PaymentDetailsTotal {\n amount?: { value?: string | number; currency?: string };\n label?: string;\n}\n\nexport interface AP2IntentMandateClaims {\n type: 'intent_mandate';\n agent_id?: string;\n user_id?: string;\n merchant_category?: string;\n allowedMerchantDomains?: string[];\n paymentMethods?: string[];\n expires?: string;\n payment_details_total?: AP2PaymentDetailsTotal;\n raw: Record<string, unknown>;\n}\n\nexport interface AP2CartMandateClaims {\n type: 'cart_mandate';\n agent_id?: string;\n intent_mandate_id?: string;\n merchant_id?: string;\n line_items?: Array<{\n id?: string;\n quantity?: number;\n price?: { value?: string | number; currency?: string };\n }>;\n payment_details_total?: AP2PaymentDetailsTotal;\n expires?: string;\n raw: Record<string, unknown>;\n}\n\nexport interface AP2PaymentMandateClaims {\n type: 'payment_mandate';\n agent_id?: string;\n cart_mandate_id?: string;\n payment_method?: string;\n payment_details_total?: AP2PaymentDetailsTotal;\n credential_provider?: string;\n raw: Record<string, unknown>;\n}\n\nexport type AP2MandateClaims =\n | AP2IntentMandateClaims\n | AP2CartMandateClaims\n | AP2PaymentMandateClaims;\n\nexport interface AP2MandateTriple {\n intent?: AP2IntentMandateClaims;\n cart?: AP2CartMandateClaims;\n payment?: AP2PaymentMandateClaims;\n rawLayers: { intentJwt?: string; cartJwt?: string; paymentJwt?: string };\n}\n\n/**\n * Extract a single AP2 mandate from a compact SD-JWT.\n * Returns null if the SD-JWT is malformed or lacks a recognized type field.\n */\nexport function extractAP2Mandate(sdJwtCompact: string): AP2MandateClaims | null {\n if (!sdJwtCompact || typeof sdJwtCompact !== 'string') return null;\n\n let decoded;\n try {\n decoded = decodeSdJwtSync(sdJwtCompact, sha256Sync);\n } catch {\n return null;\n }\n\n const payload = (decoded.jwt?.payload ?? {}) as Record<string, unknown>;\n const disclosures = decoded.disclosures ?? [];\n const claims = applyDisclosures(\n payload,\n disclosures as unknown as Array<{ key?: string; value?: unknown }>\n );\n\n const type = coerceMandateType(claims.type ?? claims.mandate_type ?? claims.mandateType);\n if (!type) return null;\n\n if (type === 'intent_mandate') return buildIntent(claims);\n if (type === 'cart_mandate') return buildCart(claims);\n return buildPayment(claims);\n}\n\nexport interface AP2MandateTripleInput {\n intent?: string;\n cart?: string;\n payment?: string;\n}\n\n/**\n * Extract an intent / cart / payment triple, returning whichever are present.\n * Does NOT enforce cross-reference consistency — that's ap2-verify.ts's job.\n */\nexport function extractAP2Mandates(input: AP2MandateTripleInput): AP2MandateTriple {\n const intent = input.intent\n ? (extractAP2Mandate(input.intent) as AP2IntentMandateClaims | null)\n : null;\n const cart = input.cart ? (extractAP2Mandate(input.cart) as AP2CartMandateClaims | null) : null;\n const payment = input.payment\n ? (extractAP2Mandate(input.payment) as AP2PaymentMandateClaims | null)\n : null;\n return {\n intent: intent ?? undefined,\n cart: cart ?? undefined,\n payment: payment ?? undefined,\n rawLayers: {\n intentJwt: input.intent,\n cartJwt: input.cart,\n paymentJwt: input.payment,\n },\n };\n}\n\nfunction buildIntent(claims: Record<string, unknown>): AP2IntentMandateClaims {\n return {\n type: 'intent_mandate',\n agent_id: coerceString(claims.agent_id ?? claims.agentId),\n user_id: coerceString(claims.user_id ?? claims.userId ?? claims.sub),\n merchant_category: coerceString(claims.merchant_category ?? claims.merchantCategory),\n allowedMerchantDomains: toStringArray(\n claims.allowed_merchant_domains ?? claims.allowedMerchantDomains\n ),\n paymentMethods: toStringArray(claims.payment_methods ?? claims.paymentMethods),\n expires: coerceString(claims.expires ?? claims.exp),\n payment_details_total: toPaymentDetails(claims.payment_details_total ?? claims.total),\n raw: claims,\n };\n}\n\nfunction buildCart(claims: Record<string, unknown>): AP2CartMandateClaims {\n return {\n type: 'cart_mandate',\n agent_id: coerceString(claims.agent_id ?? claims.agentId),\n intent_mandate_id: coerceString(claims.intent_mandate_id ?? claims.intentMandateId),\n merchant_id: coerceString(claims.merchant_id ?? claims.merchantId),\n line_items: toLineItems(claims.line_items ?? claims.lineItems),\n payment_details_total: toPaymentDetails(claims.payment_details_total ?? claims.total),\n expires: coerceString(claims.expires ?? claims.exp),\n raw: claims,\n };\n}\n\nfunction buildPayment(claims: Record<string, unknown>): AP2PaymentMandateClaims {\n return {\n type: 'payment_mandate',\n agent_id: coerceString(claims.agent_id ?? claims.agentId),\n cart_mandate_id: coerceString(claims.cart_mandate_id ?? claims.cartMandateId),\n payment_method: coerceString(claims.payment_method ?? claims.paymentMethod),\n payment_details_total: toPaymentDetails(claims.payment_details_total ?? claims.total),\n credential_provider: coerceString(claims.credential_provider ?? claims.credentialProvider),\n raw: claims,\n };\n}\n\nfunction toPaymentDetails(v: unknown): AP2PaymentDetailsTotal | undefined {\n if (!v || typeof v !== 'object') return undefined;\n const r = v as Record<string, unknown>;\n const amount = r.amount as Record<string, unknown> | undefined;\n return {\n amount: amount\n ? {\n value: coerceStringOrNumber(amount.value),\n currency: coerceString(amount.currency),\n }\n : undefined,\n label: coerceString(r.label),\n };\n}\n\nfunction toLineItems(v: unknown): AP2CartMandateClaims['line_items'] {\n if (!Array.isArray(v)) return undefined;\n const items: NonNullable<AP2CartMandateClaims['line_items']> = [];\n for (const item of v) {\n if (!item || typeof item !== 'object') continue;\n const r = item as Record<string, unknown>;\n const price = r.price as Record<string, unknown> | undefined;\n items.push({\n id: coerceString(r.id),\n quantity: coerceNumber(r.quantity),\n price: price\n ? {\n value: coerceStringOrNumber(price.value),\n currency: coerceString(price.currency),\n }\n : undefined,\n });\n }\n return items.length > 0 ? items : undefined;\n}\n\nfunction toStringArray(v: unknown): string[] | undefined {\n if (!Array.isArray(v)) return undefined;\n const out = v.filter((i): i is string => typeof i === 'string' && i.length > 0);\n return out.length > 0 ? out : undefined;\n}\n\nfunction applyDisclosures(\n payload: Record<string, unknown>,\n disclosures: Array<{ key?: string; value?: unknown }>\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...payload };\n for (const d of disclosures) {\n if (d.key && d.value !== undefined && !(d.key in result)) {\n result[d.key] = d.value;\n }\n }\n return result;\n}\n\nfunction coerceMandateType(v: unknown): AP2MandateType | null {\n if (v === 'intent_mandate' || v === 'cart_mandate' || v === 'payment_mandate') return v;\n return null;\n}\n\nfunction coerceString(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n}\n\nfunction coerceNumber(v: unknown): number | undefined {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n if (typeof v === 'string') {\n const n = Number(v);\n return Number.isFinite(n) ? n : undefined;\n }\n return undefined;\n}\n\nfunction coerceStringOrNumber(v: unknown): string | number | undefined {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n if (typeof v === 'string' && v.length > 0) return v;\n return undefined;\n}\n\nfunction sha256Sync(data: string | ArrayBuffer): Uint8Array {\n const buf =\n typeof data === 'string' ? Buffer.from(data, 'utf-8') : Buffer.from(new Uint8Array(data));\n const hash = createHash('sha256').update(buf).digest();\n return new Uint8Array(hash.buffer, hash.byteOffset, hash.byteLength);\n}\n","/**\n * MPP (Machine Payments Protocol) extractor.\n *\n * Wraps mppx (wevm) — pinned to 0.5.13, wrapped behind this adapter so\n * upgrades localise here. MPP launched March 18 2026 (Stripe + Tempo +\n * Paradigm), IETF draft-ryan-httpauth-payment-01.\n *\n * Flow:\n * Client → GET /resource\n * Server → 402 + WWW-Authenticate: Payment id=..., realm=..., method=tempo|stripe|...\n * Client → GET /resource with Authorization: Payment <base64url-json credential>\n * Server → 200 + Payment-Receipt: <base64url-json receipt>\n *\n * What we extract:\n * - Challenge: id, realm, method, intent, request{amount,currency,...}, expires, digest\n * - Credential: challenge + source (DID/chain-key) + payload (method-specific)\n * - Receipt: challengeId, method, reference (tx hash / pi_... ID), settlement\n * - Multi-method 402 offers (may be multiple WWW-Authenticate headers)\n *\n * What we do NOT verify here (pass-through):\n * - HMAC challenge binding (requires merchant's MPP_SECRET_KEY)\n * - Payment proof cryptography (Tempo tx sig, Stripe SPT, Lightning preimage)\n * — each requires upstream connectivity\n *\n * Verification (expiry + BodyDigest + source extraction) in mpp-verify.ts.\n */\n\nimport { Challenge, Credential, Receipt } from 'mppx';\n\nexport interface MPPChallengeSummary {\n id: string;\n realm: string;\n method: string;\n intent: string;\n /** Method-specific request data (amount, currency, recipient, etc.) */\n request: Record<string, unknown>;\n expires?: string;\n digest?: string;\n description?: string;\n opaque?: Record<string, string>;\n}\n\nexport interface MPPCredentialSummary {\n challenge: MPPChallengeSummary;\n /** DID or chain-native key identifying the payer. */\n source?: string;\n /** Method-specific payment proof (Tempo tx, SPT, Lightning preimage, etc.). */\n payload: unknown;\n}\n\nexport interface MPPReceiptSummary {\n method?: string;\n reference?: string;\n externalId?: string;\n status?: string;\n timestamp?: string;\n raw: Record<string, unknown>;\n}\n\nexport type MPPKind = 'challenge' | 'credential' | 'receipt' | 'error' | 'unknown';\n\nexport interface MPPRequestContext {\n kind: MPPKind;\n /** For 402 responses: one or more challenge offers. */\n challenges?: MPPChallengeSummary[];\n /** For requests with Authorization: Payment header. */\n credential?: MPPCredentialSummary;\n /** For 200 responses with Payment-Receipt header. */\n receipt?: MPPReceiptSummary;\n /** For problem+json error responses. */\n error?: { type?: string; title?: string; detail?: string };\n /** Detected payment methods offered (for multi-method 402). */\n offeredMethods?: string[];\n /** Raw body captured for BodyDigest verification in mpp-verify.ts. */\n rawBody?: string;\n}\n\nexport interface MPPRequestLike {\n method: string;\n url: string;\n headers: Record<string, string | string[] | undefined>;\n body?: unknown;\n rawBody?: string;\n}\n\nexport interface MPPResponseLike {\n status: number;\n headers: Record<string, string | string[] | undefined>;\n body?: unknown;\n rawBody?: string;\n}\n\n/**\n * Extract MPP context from an agent → merchant request.\n * Looks for `Authorization: Payment <credential>` header.\n */\nexport function extractMPPFromRequest(request: MPPRequestLike): MPPRequestContext | null {\n const auth = readHeader(request.headers, 'authorization');\n if (!auth || !/^\\s*Payment\\s+/i.test(auth)) return null;\n\n try {\n const credential = Credential.deserialize(auth);\n return {\n kind: 'credential',\n credential: {\n challenge: summarizeChallenge(credential.challenge),\n source: credential.source,\n payload: credential.payload,\n },\n rawBody: request.rawBody,\n };\n } catch {\n return { kind: 'error', error: { type: 'invalid-credential-encoding' } };\n }\n}\n\n/**\n * Extract MPP context from a merchant → agent response.\n * Handles 402 (challenge offers), 200 (receipt), 4xx (problem+json errors).\n */\nexport function extractMPPFromResponse(response: MPPResponseLike): MPPRequestContext | null {\n if (response.status === 402) {\n const challenges = collectChallenges(response);\n if (challenges.length === 0) return null;\n const methods = Array.from(new Set(challenges.map((c) => c.method)));\n return {\n kind: 'challenge',\n challenges,\n offeredMethods: methods,\n };\n }\n\n const receiptHeader = readHeader(response.headers, 'payment-receipt');\n if (receiptHeader) {\n try {\n const parsed = Receipt.deserialize(receiptHeader);\n const r = parsed as unknown as Record<string, unknown>;\n return {\n kind: 'receipt',\n receipt: {\n method: coerceString(r.method),\n reference: coerceString(r.reference),\n externalId: coerceString(r.externalId ?? r.external_id),\n status: coerceString(r.status),\n timestamp: coerceString(r.timestamp),\n raw: r,\n },\n };\n } catch {\n return { kind: 'error', error: { type: 'invalid-receipt-encoding' } };\n }\n }\n\n const contentType = readHeader(response.headers, 'content-type');\n if (contentType && /application\\/problem\\+json/i.test(contentType)) {\n const body =\n typeof response.body === 'object' && response.body !== null\n ? (response.body as Record<string, unknown>)\n : {};\n return {\n kind: 'error',\n error: {\n type: coerceString(body.type),\n title: coerceString(body.title),\n detail: coerceString(body.detail),\n },\n };\n }\n\n return null;\n}\n\n/**\n * Extract from either a request OR a response, auto-detecting which has MPP\n * artifacts. Convenience for pipeline callers.\n */\nexport function extractMPPContext(\n message:\n | { request: MPPRequestLike }\n | { response: MPPResponseLike }\n | (MPPRequestLike & Partial<MPPResponseLike>)\n): MPPRequestContext | null {\n if ('request' in message) return extractMPPFromRequest(message.request);\n if ('response' in message) return extractMPPFromResponse(message.response);\n if (typeof (message as MPPResponseLike).status === 'number') {\n return extractMPPFromResponse(message as MPPResponseLike);\n }\n return extractMPPFromRequest(message as MPPRequestLike);\n}\n\nfunction collectChallenges(response: MPPResponseLike): MPPChallengeSummary[] {\n const wwwAuth = readHeader(response.headers, 'www-authenticate');\n if (!wwwAuth) return [];\n const headers = new Headers();\n headers.set('www-authenticate', wwwAuth);\n\n const out: MPPChallengeSummary[] = [];\n try {\n const list = Challenge.fromHeadersList(headers);\n for (const ch of list) {\n out.push(summarizeChallenge(ch as unknown as Challenge.Challenge));\n }\n } catch {\n // fall through with empty list\n }\n return out;\n}\n\nfunction summarizeChallenge(\n ch: Challenge.Challenge | Record<string, unknown>\n): MPPChallengeSummary {\n const raw = ch as Record<string, unknown>;\n return {\n id: coerceString(raw.id) ?? '',\n realm: coerceString(raw.realm) ?? '',\n method: coerceString(raw.method) ?? '',\n intent: coerceString(raw.intent) ?? '',\n request: (raw.request as Record<string, unknown>) ?? {},\n expires: coerceString(raw.expires),\n digest: coerceString(raw.digest),\n description: coerceString(raw.description),\n opaque: raw.opaque as Record<string, string> | undefined,\n };\n}\n\nfunction readHeader(\n headers: Record<string, string | string[] | undefined>,\n name: string\n): string | undefined {\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === name) {\n const raw = headers[key];\n if (typeof raw === 'string') return raw;\n if (Array.isArray(raw)) return raw.join(', ');\n }\n }\n return undefined;\n}\n\nfunction coerceString(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n}\n","/**\n * MPP verification — expiry + optional BodyDigest + source extraction.\n *\n * We do NOT verify the challenge's HMAC binding (needs merchant's secret)\n * or the cryptographic payment proof (per-method, requires upstream\n * connectivity). Those are the merchant's / settlement layer's job.\n *\n * Our job: structural correctness, expiry policy, tamper detection via\n * optional BodyDigest, and identity extraction for PDLSS binding.\n */\n\nimport { BodyDigest } from 'mppx';\nimport type { MPPRequestContext } from './mpp';\nimport { defaultNonceStore, type NonceStore } from './nonce-store';\n\nexport interface MPPVerifyInput {\n context: MPPRequestContext;\n /** Raw request body to validate BodyDigest against, if the challenge declares one. */\n rawBody?: string;\n /** Seconds of clock-skew tolerance on challenge.expires. Default 60. */\n clockSkewSec?: number;\n /** Injectable for deterministic tests. */\n now?: () => number;\n /** Optional replay-protection store. Defaults to in-process LRU. */\n nonceStore?: NonceStore;\n}\n\nexport interface MPPVerifyResult {\n ok: boolean;\n expiryOk: boolean;\n bodyDigestOk: boolean | null;\n source?: string;\n method?: string;\n error?: string;\n}\n\nexport function verifyMPP(input: MPPVerifyInput): MPPVerifyResult {\n const { context } = input;\n const tolerance = input.clockSkewSec ?? 60;\n const nowSec = input.now ? input.now() : Math.floor(Date.now() / 1000);\n const nonceStore = input.nonceStore ?? defaultNonceStore;\n\n // Extract the challenge under test — for credential flow, from inside the\n // wrapped challenge; for bare challenge flow, from context.challenges[0].\n const challenge = context.credential?.challenge ?? (context.challenges && context.challenges[0]);\n const source = context.credential?.source;\n const method = challenge?.method;\n\n let expiryOk = true;\n if (challenge?.expires) {\n const parsedExpiry = Date.parse(challenge.expires);\n if (!Number.isFinite(parsedExpiry)) {\n return {\n ok: false,\n expiryOk: false,\n bodyDigestOk: null,\n source,\n method,\n error: 'unparseable challenge.expires',\n };\n }\n const expiresSec = Math.floor(parsedExpiry / 1000);\n if (nowSec > expiresSec + tolerance) {\n expiryOk = false;\n }\n }\n\n // Audit F-A1-04: previously when rawBody was present but the challenge\n // omitted `digest`, bodyDigestOk stayed `null` and was treated as OK.\n // Attacker could strip the digest field from the challenge and tamper\n // with body. Now: when rawBody is present, digest is REQUIRED.\n let bodyDigestOk: boolean | null = null;\n if (input.rawBody !== undefined) {\n if (!challenge?.digest) {\n bodyDigestOk = false;\n } else {\n try {\n if (!/^sha-256=/.test(challenge.digest)) {\n bodyDigestOk = false;\n } else {\n bodyDigestOk = BodyDigest.verify(challenge.digest as `sha-256=${string}`, input.rawBody);\n }\n } catch {\n bodyDigestOk = false;\n }\n }\n }\n\n // Audit F-A1-05: replay protection. Use challenge nonce + digest as\n // replay key when available; fall back to digest alone. Window matches\n // the expiry tolerance.\n let replayOk = true;\n if (challenge?.digest && expiryOk) {\n const replayKey = `mpp:${challenge.digest}:${(challenge as { nonce?: string }).nonce ?? ''}`;\n const expiresAt = (nowSec + tolerance) * 1000;\n if (nonceStore.seen(replayKey, expiresAt)) {\n replayOk = false;\n }\n }\n\n const ok = expiryOk && (bodyDigestOk === null || bodyDigestOk === true) && replayOk;\n const errors: string[] = [];\n if (!expiryOk) errors.push('challenge expired');\n if (bodyDigestOk === false) {\n errors.push(\n input.rawBody !== undefined && !challenge?.digest\n ? 'body digest required when rawBody present'\n : 'body digest mismatch'\n );\n }\n if (!replayOk) errors.push('MPP challenge replay — already seen within tolerance window');\n\n return {\n ok,\n expiryOk,\n bodyDigestOk,\n source,\n method,\n error: errors.length > 0 ? errors.join('; ') : undefined,\n };\n}\n","/**\n * x402 (Coinbase / Linux Foundation x402 Foundation) extractor.\n *\n * Wraps @x402/core's schema parsers. x402 Foundation launched April 2 2026\n * with v2 adding network-agnostic identifiers + multiple facilitators +\n * Bazaar discovery. MPP (Machine Payments Protocol) is the IETF-formalised\n * superset of x402; this module normalizes x402 output to MPP-shape so\n * downstream pipeline code is uniform.\n *\n * Where x402 lives on the wire:\n * - 402 response body (v2) OR `X-PAYMENT-REQUIRED` header (v1) — PaymentRequired\n * - Request body (v2) OR `X-PAYMENT` header (v1, base64) — PaymentPayload\n */\n\nimport {\n validatePaymentRequired,\n validatePaymentPayload,\n type PaymentRequired,\n type PaymentPayload,\n type PaymentRequirements,\n} from '@x402/core/schemas';\nimport { safeBase64Decode } from '@x402/core/utils';\n\nexport type X402Kind = 'required' | 'payload' | 'error' | 'unknown';\n\nexport interface X402RequirementsSummary {\n scheme: string;\n network: string;\n asset: string;\n /** Normalized to string for v1/v2 compat — v1 uses maxAmountRequired, v2 uses amount. */\n amount: string;\n payTo: string;\n maxTimeoutSeconds?: number;\n resource?: string;\n description?: string;\n}\n\nexport interface X402RequestContext {\n kind: X402Kind;\n version: 1 | 2 | null;\n /** For 402 responses: the PaymentRequired body. */\n paymentRequired?: {\n resource: string;\n accepts: X402RequirementsSummary[];\n extensions?: Record<string, unknown>;\n error?: string;\n };\n /** For request body (v2) or X-PAYMENT header (v1 base64): the PaymentPayload. */\n paymentPayload?: {\n scheme: string;\n network: string;\n /** Free-form per-scheme payload (e.g. EIP-3009 authorization, Solana tx). */\n payload: Record<string, unknown>;\n extensions?: Record<string, unknown>;\n };\n error?: { type: string; detail?: string };\n /** Whether this was parsed from a header (v1 back-compat) or body (v2). */\n source: 'header' | 'body' | null;\n}\n\nexport interface X402RequestLike {\n method?: string;\n url?: string;\n headers?: Record<string, string | string[] | undefined>;\n body?: unknown;\n}\n\nexport interface X402ResponseLike {\n status?: number;\n headers?: Record<string, string | string[] | undefined>;\n body?: unknown;\n}\n\n/**\n * Extract x402 PaymentPayload from an agent → merchant request.\n * Checks v2 body (if it parses as PaymentPayload) and v1 X-PAYMENT header.\n */\nexport function extractX402FromRequest(request: X402RequestLike): X402RequestContext | null {\n const headerValue = readHeader(request.headers, 'x-payment');\n\n // v2 body path first\n if (request.body && typeof request.body === 'object') {\n const parsed = tryParsePayload(request.body);\n if (parsed) return buildPayloadContext(parsed, 'body');\n }\n\n // v1 header path\n if (headerValue) {\n try {\n const decoded = safeBase64Decode(headerValue);\n if (decoded) {\n const json = JSON.parse(decoded);\n const parsed = tryParsePayload(json);\n if (parsed) return buildPayloadContext(parsed, 'header');\n }\n } catch {\n return {\n kind: 'error',\n version: 1,\n source: 'header',\n error: { type: 'invalid-x402-payload' },\n };\n }\n }\n\n return null;\n}\n\n/**\n * Extract x402 PaymentRequired from a merchant → agent 402 response.\n */\nexport function extractX402FromResponse(response: X402ResponseLike): X402RequestContext | null {\n if (response.status !== 402) return null;\n\n // v2 body path\n if (response.body && typeof response.body === 'object') {\n const parsed = tryParseRequired(response.body);\n if (parsed) return buildRequiredContext(parsed, 'body');\n }\n\n // v1 header path\n const headerValue = readHeader(response.headers, 'x-payment-required');\n if (headerValue) {\n try {\n const decoded = safeBase64Decode(headerValue);\n if (decoded) {\n const json = JSON.parse(decoded);\n const parsed = tryParseRequired(json);\n if (parsed) return buildRequiredContext(parsed, 'header');\n }\n } catch {\n return {\n kind: 'error',\n version: 1,\n source: 'header',\n error: { type: 'invalid-x402-required' },\n };\n }\n }\n\n return null;\n}\n\nexport function extractX402Context(\n message:\n | { request: X402RequestLike }\n | { response: X402ResponseLike }\n | (X402RequestLike & Partial<X402ResponseLike>)\n): X402RequestContext | null {\n if ('request' in message) return extractX402FromRequest(message.request);\n if ('response' in message) return extractX402FromResponse(message.response);\n if (typeof (message as X402ResponseLike).status === 'number') {\n return extractX402FromResponse(message as X402ResponseLike);\n }\n return extractX402FromRequest(message as X402RequestLike);\n}\n\nfunction tryParseRequired(data: unknown): PaymentRequired | null {\n try {\n return validatePaymentRequired(data);\n } catch {\n return null;\n }\n}\n\nfunction tryParsePayload(data: unknown): PaymentPayload | null {\n try {\n return validatePaymentPayload(data);\n } catch {\n return null;\n }\n}\n\nfunction buildRequiredContext(\n parsed: PaymentRequired,\n source: 'header' | 'body'\n): X402RequestContext {\n const asRecord = parsed as unknown as Record<string, unknown>;\n const version = coerceVersion(asRecord.x402Version);\n const accepts = (asRecord.accepts as PaymentRequirements[] | undefined) ?? [];\n return {\n kind: 'required',\n version,\n source,\n paymentRequired: {\n resource: resolveResource(asRecord.resource),\n accepts: accepts.map(summarizeRequirement),\n extensions: asRecord.extensions as Record<string, unknown> | undefined,\n error: typeof asRecord.error === 'string' ? asRecord.error : undefined,\n },\n };\n}\n\nfunction buildPayloadContext(\n parsed: PaymentPayload,\n source: 'header' | 'body'\n): X402RequestContext {\n const asRecord = parsed as unknown as Record<string, unknown>;\n const version = coerceVersion(asRecord.x402Version);\n const accepted = asRecord.accepted as PaymentRequirements | undefined;\n const payload = (asRecord.payload as Record<string, unknown>) ?? {};\n return {\n kind: 'payload',\n version,\n source,\n paymentPayload: {\n scheme: accepted?.scheme ?? (typeof asRecord.scheme === 'string' ? asRecord.scheme : ''),\n network: accepted?.network ?? (typeof asRecord.network === 'string' ? asRecord.network : ''),\n payload,\n extensions: asRecord.extensions as Record<string, unknown> | undefined,\n },\n };\n}\n\nfunction summarizeRequirement(req: PaymentRequirements): X402RequirementsSummary {\n const r = req as unknown as Record<string, unknown>;\n const amount = (r.amount ?? r.maxAmountRequired ?? '0') as string;\n return {\n scheme: (r.scheme as string) ?? '',\n network: (r.network as string) ?? '',\n asset: (r.asset as string) ?? '',\n amount: String(amount),\n payTo: (r.payTo as string) ?? '',\n maxTimeoutSeconds: typeof r.maxTimeoutSeconds === 'number' ? r.maxTimeoutSeconds : undefined,\n resource: typeof r.resource === 'string' ? r.resource : undefined,\n description: typeof r.description === 'string' ? r.description : undefined,\n };\n}\n\nfunction resolveResource(v: unknown): string {\n if (typeof v === 'string') return v;\n if (v && typeof v === 'object' && 'url' in v && typeof (v as { url: unknown }).url === 'string') {\n return (v as { url: string }).url;\n }\n return '';\n}\n\nfunction coerceVersion(v: unknown): 1 | 2 | null {\n if (v === 1 || v === 2) return v;\n return null;\n}\n\nfunction readHeader(\n headers: Record<string, string | string[] | undefined> | undefined,\n name: string\n): string | undefined {\n if (!headers) return undefined;\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === name) {\n const raw = headers[key];\n if (typeof raw === 'string') return raw;\n if (Array.isArray(raw)) return raw[0];\n }\n }\n return undefined;\n}\n","/**\n * VI (Verifiable Intent) 3-layer SD-JWT chain verification.\n *\n * VI chains: L1 (credential provider → wallet) → L2 (user → agent) → L3\n * (agent → merchant). L3 itself can split into L3a (payment mandate) + L3b\n * (checkout mandate) cross-referenced via transaction_id, with L3b carrying\n * a checkout_hash (VI constraint type 8) that must match SHA-256 of the L2\n * checkout disclosure.\n *\n * Signature primitives are delegated to @sd-jwt/core (via our extractor);\n * cnf.jwk chain-walking + cross-references + checkout_hash binding is\n * AstraSync-specific composition logic — that's the whitespace here.\n *\n * This module does NOT re-verify selective-disclosure hashes (the extractor\n * already applied them via @sd-jwt/core). It DOES verify:\n * - cnf.jwk in L1 payload points to L2's signing key (thumbprint match)\n * - cnf.jwk in L2 payload points to L3's signing key\n * - L3a.transaction_id === L3b.transaction_id (when both present)\n * - L3b.checkout_hash === SHA-256(L2 canonical checkout disclosure) — type 8\n * - mandate-level `exp` is not in the past (beyond clock skew)\n *\n * Cryptographic signature verification on each layer uses the verifier\n * callback the caller supplies (e.g. resolves via @sd-jwt/core with the\n * right JWK from the L1 issuer's JWKS).\n */\n\nimport { createHash, webcrypto } from 'node:crypto';\nimport type { JWK } from 'jose';\nimport { defaultNonceStore, type NonceStore } from './nonce-store';\n\nexport interface VILayer {\n /** Compact SD-JWT / JWS for this layer. */\n compact: string;\n /** Decoded JWT payload (already disclosure-merged). */\n payload: Record<string, unknown>;\n /** Decoded JWT header. */\n header: Record<string, unknown>;\n}\n\nexport interface VIVerifyInput {\n /**\n * Layers in chain order. L1 is REQUIRED by default —\n * without L1 there is no chain root and L2 can be verified against any\n * attacker-supplied key. Callers who have resolved L2's signing key by\n * a trusted out-of-band mechanism (wallet binding, prior protocol step)\n * MUST set `allowUnboundChain: true` AND supply `expectedL2Key`.\n */\n layers: {\n l1?: VILayer;\n l2: VILayer;\n l3a?: VILayer;\n l3b?: VILayer;\n };\n /**\n * Verifier callback invoked per layer. Should return true iff the layer's\n * JWS signature verifies against the resolved public key (for L2 this is\n * L1's cnf.jwk; for L3 this is L2's cnf.jwk; for L1 this is the issuer's\n * JWKS per `iss` claim).\n */\n verifySignature: (layer: VILayer, expectedKey: JWK | null) => Promise<boolean>;\n /**\n * Clock skew tolerance in seconds for expiry checks. Default 60s\n * (tightened from the previous 300s default).\n */\n clockSkewSec?: number;\n now?: () => number;\n /**\n * Explicit opt-in to verify a chain with L1 omitted.\n * Defaults to false. When true, `expectedL2Key` MUST also be supplied\n * (used as the expected signing key for L2 verification).\n */\n allowUnboundChain?: boolean;\n /** Required when allowUnboundChain === true. */\n expectedL2Key?: JWK;\n /** Optional replay-protection store. Defaults to in-process LRU. */\n nonceStore?: NonceStore;\n}\n\nexport interface VIVerifyResult {\n ok: boolean;\n checks: {\n l1SigOk: boolean | null;\n l2SigOk: boolean;\n l3aSigOk: boolean | null;\n l3bSigOk: boolean | null;\n l1BindsL2: boolean;\n l2BindsL3: boolean;\n l3aL3bTxnIdMatch: boolean | null;\n checkoutHashOk: boolean | null;\n expiryOk: boolean;\n };\n errors: string[];\n}\n\nexport async function verifyVIChain(input: VIVerifyInput): Promise<VIVerifyResult> {\n const errors: string[] = [];\n const tolerance = input.clockSkewSec ?? 60;\n const now = input.now ? input.now() : Math.floor(Date.now() / 1000);\n const { l1, l2, l3a, l3b } = input.layers;\n const nonceStore = input.nonceStore ?? defaultNonceStore;\n\n // Audit F-A1-02: L1 is required unless caller explicitly opts into an\n // unbound chain AND supplies the expected L2 signing key. Otherwise L2\n // would be verified against null, which most verifier callbacks\n // interpret as \"use the JWK in the JWS header\" — accepting any\n // attacker-supplied key.\n if (!l1) {\n if (!input.allowUnboundChain) {\n errors.push(\n 'L1 missing — chain root unbound (set allowUnboundChain + expectedL2Key to override)'\n );\n } else if (!input.expectedL2Key) {\n errors.push('allowUnboundChain set but expectedL2Key missing');\n }\n }\n\n // Signature verification ---------------------------------\n const l1SigOk = l1 ? await input.verifySignature(l1, null) : null;\n if (l1 && !l1SigOk) errors.push('L1 signature invalid');\n\n const l1Cnf = extractCnfJwk(l1?.payload);\n // Use L1's cnf.jwk when L1 present; otherwise (opt-in unbound chain) use\n // the caller-supplied expectedL2Key. Never null — F-A1-02.\n const l2ExpectedKey: JWK | null = l1Cnf ?? input.expectedL2Key ?? null;\n const l2SigOk = await input.verifySignature(l2, l2ExpectedKey);\n if (!l2SigOk) errors.push('L2 signature invalid');\n\n // Audit F-A1-05: replay protection on L2 signature. Use the compact JWS\n // as the nonce key; the signature is unique per request. Window matches\n // tolerance (denied replays past the window are already rejected by\n // expiry check, so we don't need to retain entries longer).\n if (l2SigOk) {\n const replayKey = `vi:l2:${l2.compact}`;\n const expiresAt = now * 1000 + tolerance * 1000;\n if (nonceStore.seen(replayKey, expiresAt)) {\n errors.push('L2 signature replay — already seen within tolerance window');\n }\n }\n\n const l2Cnf = extractCnfJwk(l2.payload);\n const l3aSigOk = l3a ? await input.verifySignature(l3a, l2Cnf ?? null) : null;\n if (l3a && !l3aSigOk) errors.push('L3a signature invalid');\n const l3bSigOk = l3b ? await input.verifySignature(l3b, l2Cnf ?? null) : null;\n if (l3b && !l3bSigOk) errors.push('L3b signature invalid');\n\n // cnf.jwk binding ----------------------------------------\n let l1BindsL2 = true;\n if (l1Cnf) {\n const l2KeyFromHeader = await jwkForLayer(l2);\n l1BindsL2 = l2KeyFromHeader ? await thumbprintsMatch(l1Cnf, l2KeyFromHeader) : false;\n if (!l1BindsL2) errors.push('L1.cnf.jwk does not bind L2 signing key');\n }\n\n let l2BindsL3 = true;\n if (l2Cnf && (l3a || l3b)) {\n const l3Layer = l3a ?? l3b!;\n const l3KeyFromHeader = await jwkForLayer(l3Layer);\n l2BindsL3 = l3KeyFromHeader ? await thumbprintsMatch(l2Cnf, l3KeyFromHeader) : false;\n if (!l2BindsL3) errors.push('L2.cnf.jwk does not bind L3 signing key');\n }\n\n // L3a/L3b cross-reference --------------------------------\n let l3aL3bTxnIdMatch: boolean | null = null;\n if (l3a && l3b) {\n const a = coerceString(l3a.payload.transaction_id ?? l3a.payload.transactionId);\n const b = coerceString(l3b.payload.transaction_id ?? l3b.payload.transactionId);\n if (a && b) {\n l3aL3bTxnIdMatch = a === b;\n if (!l3aL3bTxnIdMatch) {\n errors.push(`L3a.transaction_id (${a}) does not match L3b.transaction_id (${b})`);\n }\n }\n }\n\n // checkout_hash (VI constraint type 8) -------------------\n let checkoutHashOk: boolean | null = null;\n if (l3b) {\n const declaredHash = coerceString(\n l3b.payload.checkout_hash ??\n l3b.payload.conditional_transaction_id ??\n (l3b.payload.payment_reference as Record<string, unknown> | undefined)?.checkout_hash\n );\n if (declaredHash) {\n const computed = computeCheckoutHashFromL2(l2);\n checkoutHashOk = computed ? declaredHash === computed : false;\n if (!checkoutHashOk) {\n errors.push('L3b.checkout_hash does not match SHA-256 of L2 checkout disclosure');\n }\n }\n }\n\n // Expiry policy ------------------------------------------\n const expiryOk = checkExpiryAcross([l1, l2, l3a, l3b], tolerance, now, errors);\n\n // Audit F-A1-02 + F-A1-05: ok also requires the chain-root + replay\n // checks above to have passed (errors array captures both). Previously\n // `ok` was derived purely from individual check booleans, so the L1-\n // required errors and replay-detected errors didn't gate it.\n const noUnboundChainOrReplayErrors = !errors.some(\n (e) =>\n e.startsWith('L1 missing') ||\n e.startsWith('allowUnboundChain set') ||\n e.startsWith('L2 signature replay')\n );\n\n const ok =\n l1SigOk !== false &&\n l2SigOk &&\n l3aSigOk !== false &&\n l3bSigOk !== false &&\n l1BindsL2 &&\n l2BindsL3 &&\n l3aL3bTxnIdMatch !== false &&\n checkoutHashOk !== false &&\n expiryOk &&\n noUnboundChainOrReplayErrors;\n\n return {\n ok,\n checks: {\n l1SigOk,\n l2SigOk,\n l3aSigOk,\n l3bSigOk,\n l1BindsL2,\n l2BindsL3,\n l3aL3bTxnIdMatch,\n checkoutHashOk,\n expiryOk,\n },\n errors,\n };\n}\n\nfunction extractCnfJwk(payload: Record<string, unknown> | undefined): JWK | null {\n if (!payload) return null;\n const cnf = payload.cnf as Record<string, unknown> | undefined;\n if (!cnf) return null;\n const jwk = cnf.jwk as JWK | undefined;\n return jwk ?? null;\n}\n\nasync function jwkForLayer(layer: VILayer): Promise<JWK | null> {\n // Prefer explicit cnf.jwk in the header, then payload; fallback to null.\n const fromHeader = extractCnfJwk(layer.header);\n if (fromHeader) return fromHeader;\n const fromPayload = extractCnfJwk(layer.payload);\n return fromPayload;\n}\n\nasync function thumbprintsMatch(a: JWK, b: JWK): Promise<boolean> {\n try {\n const ta = await jwkThumbprint(a);\n const tb = await jwkThumbprint(b);\n return ta === tb;\n } catch {\n return false;\n }\n}\n\n// RFC 7638 thumbprint: SHA-256 over the canonical JSON of required JWK members.\nasync function jwkThumbprint(jwk: JWK): Promise<string> {\n const canonical = canonicalJwk(jwk);\n const bytes = new TextEncoder().encode(JSON.stringify(canonical));\n const subtle = webcrypto.subtle as SubtleCrypto;\n const buffer = await new Promise<ArrayBuffer>((resolve, reject) => {\n const source = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(source).set(bytes);\n subtle.digest('SHA-256', source).then(resolve).catch(reject);\n });\n return Buffer.from(new Uint8Array(buffer)).toString('base64url').replace(/=+$/, '');\n}\n\nfunction canonicalJwk(jwk: JWK): Record<string, string> {\n // Per RFC 7638: members must appear in lexicographic order; only required\n // fields per kty are included.\n if (jwk.kty === 'EC') {\n return { crv: jwk.crv ?? '', kty: 'EC', x: jwk.x ?? '', y: jwk.y ?? '' };\n }\n if (jwk.kty === 'OKP') {\n return { crv: jwk.crv ?? '', kty: 'OKP', x: jwk.x ?? '' };\n }\n if (jwk.kty === 'RSA') {\n return { e: jwk.e ?? '', kty: 'RSA', n: jwk.n ?? '' };\n }\n return { kty: jwk.kty ?? '' };\n}\n\nfunction computeCheckoutHashFromL2(l2: VILayer): string | null {\n const checkoutDisclosure = (l2.payload.checkout ?? l2.payload.checkout_mandate) as unknown;\n if (!checkoutDisclosure) return null;\n const canonical = canonicalStringify(checkoutDisclosure);\n const hash = createHash('sha256').update(canonical).digest('base64url').replace(/=+$/, '');\n return hash;\n}\n\nfunction canonicalStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return '[' + value.map(canonicalStringify).join(',') + ']';\n const entries = Object.entries(value as Record<string, unknown>).sort(([a], [b]) =>\n a < b ? -1 : a > b ? 1 : 0\n );\n return (\n '{' + entries.map(([k, v]) => JSON.stringify(k) + ':' + canonicalStringify(v)).join(',') + '}'\n );\n}\n\nfunction checkExpiryAcross(\n layers: Array<VILayer | undefined>,\n toleranceSec: number,\n nowSec: number,\n errors: string[]\n): boolean {\n let ok = true;\n const names = ['L1', 'L2', 'L3a', 'L3b'];\n layers.forEach((layer, idx) => {\n if (!layer) return;\n const exp = toUnixSeconds(layer.payload.exp ?? layer.payload.expires);\n if (exp === undefined) return;\n if (nowSec > exp + toleranceSec) {\n errors.push(`${names[idx]} mandate expired at ${exp}`);\n ok = false;\n }\n });\n return ok;\n}\n\nfunction toUnixSeconds(v: unknown): number | undefined {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n if (typeof v === 'string') {\n const asInt = Number(v);\n if (Number.isFinite(asInt) && asInt > 0) {\n return asInt >= 1e12 ? Math.floor(asInt / 1000) : Math.floor(asInt);\n }\n const parsed = Date.parse(v);\n if (Number.isFinite(parsed)) return Math.floor(parsed / 1000);\n }\n return undefined;\n}\n\nfunction coerceString(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n}\n","/**\n * Visa JWKS registry resolver.\n *\n * Default endpoint: https://mcp.visa.com/.well-known/jwks (per Visa TAP spec).\n * Wraps jose.createRemoteJWKSet which handles caching + rotation natively.\n */\n\nimport { createRemoteJWKSet, type JWK } from 'jose';\nimport type { RegistryResolver, ResolveContext } from './types';\n\nconst DEFAULT_VISA_JWKS_URL = 'https://mcp.visa.com/.well-known/jwks';\n\nexport interface VisaRegistryOptions {\n jwksUrl?: string;\n cacheMaxAge?: number;\n cooldownDuration?: number;\n}\n\nexport function createVisaRegistry(options: VisaRegistryOptions = {}): RegistryResolver {\n const url = new URL(options.jwksUrl ?? DEFAULT_VISA_JWKS_URL);\n const jwks = createRemoteJWKSet(url, {\n cacheMaxAge: options.cacheMaxAge,\n cooldownDuration: options.cooldownDuration,\n });\n\n return {\n name: 'visa',\n async resolve(kid: string, context?: ResolveContext): Promise<JWK | null> {\n if (!kid) return null;\n try {\n const key = await jwks({\n kid,\n alg: context?.algorithm ?? 'ES256',\n typ: 'JWT',\n });\n return exportJwkFromKeyLike(key);\n } catch {\n return null;\n }\n },\n };\n}\n\nasync function exportJwkFromKeyLike(keyLike: unknown): Promise<JWK | null> {\n if (!keyLike) return null;\n // jose returns KeyObject or CryptoKey — both export via exportJWK at caller side.\n // Runtime shape check: if it already looks like a JWK, pass through.\n if (typeof keyLike === 'object' && 'kty' in (keyLike as object)) {\n return keyLike as JWK;\n }\n const { exportJWK } = await import('jose');\n try {\n return await exportJWK(keyLike as Parameters<typeof exportJWK>[0]);\n } catch {\n return null;\n }\n}\n","/**\n * Online Mode — Delegates to the existing verify() function.\n * Full trust scoring, blockchain verification, audit trail, PDLSS evaluation via API.\n */\n\nimport type { AstraSyncGatewayConfig, PDLSSContext, VerificationDecision } from '../types';\nimport {\n verify,\n type VerificationResult,\n type VerificationRequest,\n type GatewayConfig,\n} from '../../index';\n\n/**\n * Convert gateway config to the existing GatewayConfig format.\n */\nfunction toGatewayConfig(config: AstraSyncGatewayConfig): GatewayConfig {\n return {\n apiBaseUrl: config.apiBaseUrl || 'https://api.astrasync.ai',\n apiKey: config.apiKey,\n minTrustScore: config.minTrustScore,\n minTrustScoreForFull: config.minTrustScoreForFull,\n cacheTtl: config.cacheTtl,\n debug: config.debug,\n customHeaders: config.customHeaders,\n counterpartyUrl: config.counterpartyUrl,\n counterpartyType: config.counterpartyType,\n };\n}\n\n/**\n * Convert PDLSS context to a verification request.\n *\n * Vocabulary shim (transport-layer, per the platform's canonical PDLSS\n * vocabulary): the LOCAL evaluator's purposes are dotted actions\n * (`shell.exec`, `file.write`), but the platform's wire contract is\n * purpose = bare category noun, action = dotted verb — the backend rejects\n * dotted purposes with exactly this guidance. Split dotted local purposes\n * so online verification and hybrid sync record real decisions instead of\n * vocabulary-mismatch denials. The local tool name (`context.action`, e.g.\n * `Bash`) is subsumed by the dotted action on the wire.\n */\nexport function toVerificationRequest(\n context: PDLSSContext,\n astraId?: string\n): VerificationRequest {\n const dotIndex = context.purpose.indexOf('.');\n const dotted = dotIndex > 0;\n return {\n credentials: { astraId },\n purpose: dotted ? context.purpose.slice(0, dotIndex) : context.purpose,\n action: dotted ? context.purpose : context.action,\n resourceType: context.resourceType,\n resource: context.target,\n transactionValue: context.transactionValue,\n currency: context.currency,\n createSession: true,\n };\n}\n\n/**\n * Convert verification result to a VerificationDecision.\n */\nfunction toDecision(result: VerificationResult): VerificationDecision {\n // Round-18 G4: ALLOW only when both identity AND policy pass.\n if (result.identityVerified && result.policyAllowed) {\n return {\n recommendation: 'ALLOW',\n reason: result.agent?.trustScore\n ? `Verified (trust score ${result.agent.trustScore})`\n : 'Verified',\n trustScore: result.agent?.trustScore,\n sessionId:\n 'sessionId' in result\n ? ((result as Record<string, unknown>).sessionId as string)\n : undefined,\n };\n }\n\n if (result.requiresStepUp || result.requiresApproval) {\n return {\n recommendation: 'MANUAL_REVIEW',\n reason: result.denialReasons?.[0] || 'Step-up or approval required',\n trustScore: result.agent?.trustScore,\n };\n }\n\n return {\n recommendation: 'DENY',\n reason: result.denialReasons?.[0] || 'Access denied',\n trustScore: result.agent?.trustScore,\n };\n}\n\n/**\n * Verify via the AstraSync API (online mode).\n */\nexport async function verifyOnline(\n config: AstraSyncGatewayConfig,\n context: PDLSSContext,\n astraId?: string\n): Promise<VerificationDecision> {\n const gatewayConfig = toGatewayConfig(config);\n const request = toVerificationRequest(context, astraId);\n const result = await verify(gatewayConfig, request);\n return toDecision(result);\n}\n","/**\n * Hybrid Mode — Local evaluation for speed, async API sync for trust scoring.\n *\n * Immediate: local PDLSS evaluation (< 1ms)\n * Async: queued API verification for audit trail and trust score updates\n *\n * Queue entries are persisted to disk so they survive process restarts.\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { dirname } from 'path';\nimport type {\n AstraSyncGatewayConfig,\n PDLSSContext,\n VerificationDecision,\n SyncQueueEntry,\n} from '../types';\nimport type { LocalEvaluator } from '../../local-evaluator/evaluator';\nimport { verifyOnline } from './online';\nimport { redactDeep } from '../redact';\n\nconst MAX_QUEUE_SIZE = 1000;\nconst MAX_RETRIES = 3;\n\nexport interface FlushOptions {\n /** Max entries to attempt this flush (default: all pending). */\n limit?: number;\n /**\n * Per-entry time budget in ms. A timed-out entry stays pending (no retry\n * penalty — slow network is not a failure) and ends the flush early.\n * Stateless callers (the Claude Code hook) use this to keep sync off the\n * tool-call critical path.\n */\n perEntryTimeoutMs?: number;\n}\n\nconst FLUSH_TIMEOUT = Symbol('flush-timeout');\n\nfunction delay(ms: number): Promise<typeof FLUSH_TIMEOUT> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => resolve(FLUSH_TIMEOUT), ms);\n // Don't hold the process open just for the timeout race.\n if (typeof timer.unref === 'function') timer.unref();\n });\n}\n\nexport class HybridSyncQueue {\n private queue: SyncQueueEntry[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private config: AstraSyncGatewayConfig;\n private processing = false;\n private persistPath: string | null = null;\n\n constructor(config: AstraSyncGatewayConfig, persistPath?: string) {\n this.config = config;\n this.persistPath = persistPath ?? null;\n this.loadFromDisk();\n }\n\n /**\n * Start periodic sync.\n */\n start(intervalMs: number): void {\n if (this.timer) return;\n this.timer = setInterval(() => this.flush(), intervalMs);\n }\n\n /**\n * Stop periodic sync and flush remaining entries.\n */\n async stop(flushOptions: FlushOptions = {}): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush(flushOptions);\n this.saveToDisk();\n }\n\n /**\n * Add a decision to the sync queue.\n */\n enqueue(context: PDLSSContext, decision: VerificationDecision): void {\n if (this.queue.length >= MAX_QUEUE_SIZE) {\n // Drop oldest entry\n this.queue.shift();\n }\n\n // Sync payloads leave the machine (and persist to disk while queued):\n // credential-scrub them at the boundary. Local evaluation already ran\n // on the raw text.\n this.queue.push({\n id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n context: redactDeep(context),\n decision: redactDeep(decision),\n timestamp: new Date(),\n retryCount: 0,\n status: 'pending',\n });\n\n this.saveToDisk();\n }\n\n /**\n * Flush pending entries to the API.\n */\n async flush(options: FlushOptions = {}): Promise<void> {\n if (this.processing) return;\n this.processing = true;\n\n try {\n const pending = this.queue.filter((e) => e.status === 'pending');\n const batch = typeof options.limit === 'number' ? pending.slice(0, options.limit) : pending;\n\n for (const entry of batch) {\n // Sync entries carry the guard's own identity (config.agentId) so the\n // platform attributes them instead of treating them as anonymous.\n const attempt = verifyOnline(this.config, entry.context, this.config.agentId)\n .then(() => 'synced' as const)\n .catch(() => 'error' as const);\n const result = options.perEntryTimeoutMs\n ? await Promise.race([attempt, delay(options.perEntryTimeoutMs)])\n : await attempt;\n\n if (result === FLUSH_TIMEOUT) {\n // Slow network: leave the entry pending without a retry penalty and\n // stop burning budget on the rest of the batch.\n break;\n }\n if (result === 'synced') {\n entry.status = 'synced';\n } else {\n entry.retryCount++;\n if (entry.retryCount >= MAX_RETRIES) {\n entry.status = 'failed';\n }\n }\n }\n\n // Remove synced and permanently failed entries\n this.queue = this.queue.filter((e) => e.status === 'pending');\n this.saveToDisk();\n } finally {\n this.processing = false;\n }\n }\n\n /**\n * Get queue status.\n */\n getStatus(): { pending: number; total: number } {\n return {\n pending: this.queue.filter((e) => e.status === 'pending').length,\n total: this.queue.length,\n };\n }\n\n /**\n * Load persisted queue entries from disk.\n */\n private loadFromDisk(): void {\n if (!this.persistPath) return;\n\n try {\n if (!existsSync(this.persistPath)) return;\n const data = readFileSync(this.persistPath, 'utf-8');\n const entries = JSON.parse(data) as SyncQueueEntry[];\n // Only restore pending entries\n this.queue = entries\n .filter((e) => e.status === 'pending')\n .map((e) => ({ ...e, timestamp: new Date(e.timestamp) }));\n } catch {\n // Corrupted file or read error — start with empty queue\n this.queue = [];\n }\n }\n\n /**\n * Persist queue entries to disk.\n */\n private saveToDisk(): void {\n if (!this.persistPath) return;\n\n try {\n const dir = dirname(this.persistPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(this.persistPath, JSON.stringify(this.queue, null, 2), 'utf-8');\n } catch {\n // Best-effort — don't crash if disk write fails\n }\n }\n}\n\n/**\n * Verify in hybrid mode: local eval + queued sync.\n */\nexport function verifyHybrid(\n evaluator: LocalEvaluator,\n syncQueue: HybridSyncQueue,\n context: PDLSSContext\n): VerificationDecision {\n // Local evaluation is the immediate response\n const decision = evaluator.evaluate(context);\n\n // Queue for async API sync (fire-and-forget)\n syncQueue.enqueue(context, decision);\n\n return decision;\n}\n","/**\n * Secret redaction for Local Guard trace files and hybrid sync payloads.\n *\n * Raw tool-call text (shell commands, file contents, URLs) routinely carries\n * live credentials — the passive-week traces captured a GitHub PAT and org\n * API keys verbatim. Evaluation always runs on the RAW text (policy matching\n * needs it); redaction applies only at the persistence boundaries:\n * TraceLogger writes and HybridSyncQueue enqueue.\n *\n * Deny-list philosophy mirrors metadata-capture's sanitizeHeaders: match\n * known credential shapes, replace with a typed marker, keep everything else\n * verbatim. False positives (redacting a non-secret) are acceptable; false\n * negatives are the failure mode to avoid.\n */\n\ninterface RedactionPattern {\n type: string;\n re: RegExp;\n /** Replacement; defaults to the bare marker. */\n replacement?: string;\n}\n\nconst marker = (type: string) => `[REDACTED:${type}]`;\n\nconst REDACTION_PATTERNS: RedactionPattern[] = [\n // Multi-line blocks first so later single-line patterns don't shred them.\n {\n type: 'private-key',\n re: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*?(?:-----END [A-Z ]*PRIVATE KEY-----|$)/g,\n },\n // URL userinfo credentials (https://user:pass@, x-access-token:ghp_…@).\n {\n type: 'url-credentials',\n re: /([a-z][a-z0-9+.-]*:\\/\\/)[^\\s/@]+:[^\\s/@]+@/gi,\n replacement: `$1${marker('url-credentials')}@`,\n },\n // Known token formats.\n { type: 'github-token', re: /\\bgh[pousr]_[A-Za-z0-9]{20,255}\\b/g },\n { type: 'github-token', re: /\\bgithub_pat_[A-Za-z0-9_]{20,255}\\b/g },\n { type: 'astrasync-key', re: /\\bkya_[A-Fa-f0-9]{32,128}\\b/g },\n { type: 'openai-key', re: /\\bsk-[A-Za-z0-9_-]{20,}\\b/g },\n { type: 'aws-access-key-id', re: /\\bAKIA[0-9A-Z]{16}\\b/g },\n { type: 'jwt', re: /\\beyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\b/g },\n // Bearer/token headers.\n {\n type: 'bearer-token',\n re: /\\b(bearer\\s+)[a-z0-9._~+/=-]{16,}/gi,\n replacement: `$1${marker('bearer-token')}`,\n },\n // Generic KEY=value / key: value assignments with secret-ish names.\n {\n type: 'assigned-secret',\n re: /\\b((?:password|passwd|secret|token|api[_-]?key|apikey|access[_-]?key|client[_-]?secret|private[_-]?key)\\s*[=:]\\s*)(['\"]?)[^\\s'\"&;]{8,}\\2/gi,\n replacement: `$1$2${marker('assigned-secret')}$2`,\n },\n];\n\n/**\n * Replace credential-shaped substrings in `text` with `[REDACTED:<type>]`\n * markers. Pure; safe on arbitrary text.\n */\nexport function redactSecrets(text: string): string {\n let result = text;\n for (const { type, re, replacement } of REDACTION_PATTERNS) {\n result = result.replace(re, replacement ?? marker(type));\n }\n return result;\n}\n\n/**\n * Deep-redact every string field of a JSON-ish value (objects, arrays,\n * strings). Non-string leaves (numbers, booleans, Dates, null) pass through\n * untouched. Returns a new value; the input is never mutated.\n */\nexport function redactDeep<T>(value: T): T {\n if (typeof value === 'string') {\n return redactSecrets(value) as unknown as T;\n }\n if (Array.isArray(value)) {\n return value.map((item) => redactDeep(item)) as unknown as T;\n }\n if (value !== null && typeof value === 'object' && !(value instanceof Date)) {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = redactDeep(v);\n }\n return out as unknown as T;\n }\n return value;\n}\n","/**\n * Trace Logger — append-only JSONL audit trail.\n *\n * Cherry-picked from trust-harness-core and simplified.\n * Writes evaluation events to .astrasync/traces/ as JSONL files,\n * one file per day, with rotation.\n */\n\nimport { appendFileSync, mkdirSync, existsSync, statSync, readdirSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport type { TraceEvent, PDLSSContext, VerificationDecision } from './types';\nimport { redactDeep } from './redact';\n\nconst MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB\nconst MAX_FILES = 10;\n\nexport class TraceLogger {\n private tracePath: string;\n private enabled: boolean;\n\n constructor(tracePath: string, enabled: boolean) {\n this.tracePath = tracePath;\n this.enabled = enabled;\n\n if (enabled) {\n mkdirSync(tracePath, { recursive: true });\n }\n }\n\n /**\n * Log an evaluation event.\n */\n logEvaluation(context: PDLSSContext, decision: VerificationDecision): void {\n if (!this.enabled) return;\n\n // Evaluation ran on the raw text; what hits disk is credential-scrubbed.\n // Redaction is guarded: a throw here (e.g. pathological metadata) must\n // neither lose the trace line nor fail the already-completed evaluation\n // — degrade to an error event that still records the decision outcome.\n let event: TraceEvent;\n try {\n event = {\n id: this.generateId(),\n timestamp: new Date(),\n type: 'evaluation',\n context: redactDeep(context),\n decision: redactDeep(decision),\n };\n } catch (err) {\n event = {\n id: this.generateId(),\n timestamp: new Date(),\n type: 'error',\n metadata: {\n error: `trace redaction failed: ${err instanceof Error ? err.message : String(err)}`,\n recommendation: decision.recommendation,\n purpose: context.purpose,\n action: context.action,\n },\n };\n }\n this.write(event);\n }\n\n /**\n * Log a tool call the guard saw but did not govern. One line per skip\n * keeps coverage holes (unmapped platform tools) visible in the traces\n * instead of silently indistinguishable from ALLOW.\n */\n logSkipped(toolName: string, reason: string): void {\n if (!this.enabled) return;\n\n this.write({\n id: this.generateId(),\n timestamp: new Date(),\n type: 'skipped',\n metadata: { toolName, reason },\n });\n }\n\n /**\n * Log a mode switch event.\n */\n logModeSwitch(from: string, to: string): void {\n if (!this.enabled) return;\n\n this.write({\n id: this.generateId(),\n timestamp: new Date(),\n type: 'mode_switch',\n metadata: { from, to },\n });\n }\n\n /**\n * Log an error event.\n */\n logError(error: string, context?: PDLSSContext): void {\n if (!this.enabled) return;\n\n this.write({\n id: this.generateId(),\n timestamp: new Date(),\n type: 'error',\n context,\n metadata: { error },\n });\n }\n\n private write(event: TraceEvent): void {\n let line: string;\n try {\n line = JSON.stringify(event) + '\\n';\n } catch {\n // Unserializable event — nothing sane to persist.\n return;\n }\n\n try {\n const filePath = this.getCurrentFilePath();\n\n // Rotate if needed\n if (existsSync(filePath)) {\n const stats = statSync(filePath);\n if (stats.size > MAX_FILE_SIZE) {\n this.rotate();\n }\n }\n\n // Each hook invocation is a separate process appending to the same\n // daily file; on Windows a concurrent append (or an antivirus/indexer\n // hold) throws EBUSY/EPERM. A silent drop here is how a real trace\n // line went missing during desktop verification — retry, then fall\n // back to a per-process file (same `trace-` prefix, so rotation\n // covers it), and as a last resort say so on stderr. Never silently\n // lose an audit line.\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n appendFileSync(filePath, line);\n return;\n } catch {\n // immediate retry — transient share-violations usually clear\n }\n }\n const fallbackPath = filePath.replace(/\\.jsonl$/, `-r${process.pid}.jsonl`);\n appendFileSync(fallbackPath, line);\n } catch {\n // Trace logging must never crash the gateway — but a lost audit\n // line should leave SOME evidence.\n try {\n console.error(`[AstraSync TraceLogger] failed to persist trace line: ${line.trim()}`);\n } catch {\n /* stderr unavailable — nothing left to do */\n }\n }\n }\n\n private getCurrentFilePath(): string {\n const date = new Date().toISOString().split('T')[0];\n return join(this.tracePath, `trace-${date}.jsonl`);\n }\n\n private rotate(): void {\n try {\n const files = readdirSync(this.tracePath)\n .filter((f) => f.startsWith('trace-') && f.endsWith('.jsonl'))\n .sort();\n\n while (files.length >= MAX_FILES) {\n const oldest = files.shift()!;\n unlinkSync(join(this.tracePath, oldest));\n }\n } catch {\n // Best effort rotation\n }\n }\n\n private generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n}\n","/**\n * AstraSyncGateway — Primary API surface for agent verification.\n *\n * Supports three operational modes:\n * - online: Full API-based verification with trust scoring and audit trail\n * - local: Offline PDLSS evaluation using a local policy file (no account required)\n * - hybrid: Local eval for speed + async API sync for trust scoring\n *\n * @example\n * ```typescript\n * // Local mode (free, no account)\n * const gateway = new AstraSyncGateway({ mode: 'local', policyFile: './policy.yaml' });\n * const decision = await gateway.evaluate(context);\n *\n * // Online mode (paid, full features)\n * const gateway = new AstraSyncGateway({ mode: 'online', apiKey: 'key' });\n * const decision = await gateway.evaluate(context);\n * ```\n */\n\nimport type { AstraSyncGatewayConfig, PDLSSContext, VerificationDecision } from './types';\nimport type { LocalEvaluator } from '../local-evaluator/evaluator';\nimport { loadEvaluator } from './modes/local';\nimport { verifyLocal } from './modes/local';\nimport { verifyOnline } from './modes/online';\nimport { verifyHybrid, HybridSyncQueue } from './modes/hybrid';\nimport type { FlushOptions } from './modes/hybrid';\nimport { TraceLogger } from './trace-logger';\n\nexport class AstraSyncGateway {\n private config: AstraSyncGatewayConfig;\n private evaluator: LocalEvaluator | null = null;\n private syncQueue: HybridSyncQueue | null = null;\n private traceLogger: TraceLogger | null = null;\n private initialized = false;\n\n constructor(config: AstraSyncGatewayConfig) {\n this.config = config;\n this.validateConfig();\n }\n\n private validateConfig(): void {\n const { mode } = this.config;\n\n if (mode === 'online') {\n if (!this.config.apiBaseUrl && !this.config.apiKey) {\n throw new Error('Online mode requires apiBaseUrl or apiKey');\n }\n }\n\n if (mode === 'local') {\n if (!this.config.policyFile && !this.config.policy) {\n throw new Error('Local mode requires policyFile or policy');\n }\n }\n\n if (mode === 'hybrid') {\n if (!this.config.policyFile && !this.config.policy) {\n throw new Error('Hybrid mode requires policyFile or policy');\n }\n }\n }\n\n /**\n * Initialize the gateway (loads policy files, starts sync queues).\n * Called automatically on first evaluate() if not called manually.\n */\n async initialize(): Promise<void> {\n if (this.initialized) return;\n\n const { mode } = this.config;\n\n if (mode === 'local' || mode === 'hybrid') {\n this.evaluator = loadEvaluator(this.config);\n }\n\n if (mode === 'hybrid') {\n const persistPath = this.config.tracePath\n ? `${this.config.tracePath}/../sync-queue.json`\n : '.astrasync/sync-queue.json';\n this.syncQueue = new HybridSyncQueue(this.config, persistPath);\n const intervalMs = (this.config.syncInterval || 3600) * 1000;\n this.syncQueue.start(intervalMs);\n }\n\n // Initialize trace logger\n if (this.config.traceEnabled) {\n const tracePath = this.config.tracePath || '.astrasync/traces';\n this.traceLogger = new TraceLogger(tracePath, true);\n }\n\n this.initialized = true;\n\n if (this.config.debug) {\n const posture = this.config.posture || 'active';\n console.log(`[AstraSyncGateway] Initialized in ${mode} mode (${posture})`);\n }\n }\n\n /**\n * Graceful shutdown. Flushes sync queue and cleans up resources.\n * Stateless callers (hooks) pass bounded flush options so sync never\n * sits on a tool call's critical path.\n */\n async shutdown(options?: { syncFlush?: FlushOptions }): Promise<void> {\n if (this.syncQueue) {\n await this.syncQueue.stop(options?.syncFlush ?? {});\n this.syncQueue = null;\n }\n\n this.evaluator = null;\n this.initialized = false;\n\n if (this.config.debug) {\n console.log('[AstraSyncGateway] Shut down');\n }\n }\n\n /**\n * Evaluate an action against the verification policy.\n * Routes to the appropriate mode handler.\n *\n * In passive posture, evaluation runs but always returns ALLOW\n * (the real decision is logged for telemetry).\n */\n async evaluate(context: PDLSSContext, astraId?: string): Promise<VerificationDecision> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n let decision: VerificationDecision;\n\n switch (this.config.mode) {\n case 'online':\n decision = await verifyOnline(this.config, context, astraId ?? this.config.agentId);\n break;\n\n case 'local':\n if (!this.evaluator) throw new Error('Local evaluator not initialized');\n decision = verifyLocal(this.evaluator, context);\n break;\n\n case 'hybrid':\n if (!this.evaluator || !this.syncQueue) throw new Error('Hybrid mode not initialized');\n decision = verifyHybrid(this.evaluator, this.syncQueue, context);\n break;\n\n default:\n throw new Error(`Unknown mode: ${this.config.mode}`);\n }\n\n // In passive posture, log but don't block\n if (this.config.posture === 'passive' && decision.recommendation !== 'ALLOW') {\n decision = {\n ...decision,\n recommendation: 'ALLOW',\n reason: `[PASSIVE] Would have been ${decision.recommendation}: ${decision.reason}`,\n };\n }\n\n // Trace logging — captures the final decision (including passive override)\n this.traceLogger?.logEvaluation(context, decision);\n\n return decision;\n }\n\n /**\n * Get the current mode.\n */\n get mode(): AstraSyncGatewayConfig['mode'] {\n return this.config.mode;\n }\n\n /**\n * Get the current posture (active or passive).\n */\n get posture(): 'active' | 'passive' {\n return this.config.posture || 'active';\n }\n\n /**\n * Switch modes at runtime (e.g. after upgrade from free to paid).\n */\n async switchMode(\n newMode: AstraSyncGatewayConfig['mode'],\n additionalConfig?: Partial<AstraSyncGatewayConfig>\n ): Promise<void> {\n const oldMode = this.config.mode;\n await this.shutdown();\n\n this.config = { ...this.config, ...additionalConfig, mode: newMode };\n this.validateConfig();\n await this.initialize();\n\n this.traceLogger?.logModeSwitch(oldMode, newMode);\n\n if (this.config.debug) {\n console.log(`[AstraSyncGateway] Switched to ${newMode} mode`);\n }\n }\n\n /**\n * Get sync queue status (hybrid mode only).\n */\n getSyncStatus(): { pending: number; total: number } | null {\n return this.syncQueue?.getStatus() || null;\n }\n\n /**\n * Record a tool call the calling adapter saw but did not govern\n * (unmapped tool, skipTools, MCP with governMcp off). Trace-only.\n */\n logSkippedTool(toolName: string, reason: string): void {\n this.traceLogger?.logSkipped(toolName, reason);\n }\n}\n","/**\n * Local Guard configuration resolution — shared by every hook-based\n * adapter (Claude Code, Codex CLI). Deliberately free of any process\n * entry point: hook binaries import from here, and bundling this module\n * into a bin entry must never execute anything.\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { fleetPaths, loadEnrolment, type FleetPaths } from '../fleet/enrolment-store';\nimport type { FleetEnrolment } from '../fleet/types';\n\nexport interface GuardSettings {\n posture?: 'active' | 'passive';\n failOpen?: boolean;\n skipTools?: string[];\n /** Govern MCP tools; default true (see adapter options) */\n governMcp?: boolean;\n /**\n * Gateway mode. 'local' (default) decides entirely on-device; 'hybrid'\n * decides locally AND queues redacted evaluation events for async upload\n * to the platform audit trail. Bare 'online' is deliberately not offered:\n * the guard must never block a tool call on network I/O.\n */\n mode?: 'local' | 'hybrid';\n /** AstraSync API base URL (required for hybrid), e.g. https://api.astrasync.ai */\n apiBaseUrl?: string;\n /** Org API key authenticating the sync upload (required for hybrid) */\n apiKey?: string;\n /** ASTRA- agent id the guard syncs as (recommended for hybrid) */\n agentId?: string;\n}\n\nexport interface ResolvedGuardConfig {\n policyFile: string;\n /** The .astrasync directory the policy came from (traces live here too) */\n guardDir: string;\n settings: GuardSettings;\n}\n\n/**\n * Locate the governing policy: project (.astrasync/policy.yaml under\n * CLAUDE_PROJECT_DIR, then the payload cwd) overrides the user-level\n * ~/.astrasync/policy.yaml. Returns null when no policy exists anywhere.\n */\nexport function resolveGuardConfig(\n env: NodeJS.ProcessEnv,\n payloadCwd?: string,\n home: string = homedir()\n): ResolvedGuardConfig | null {\n const candidateRoots = [env.CLAUDE_PROJECT_DIR, payloadCwd, home].filter(\n (root): root is string => typeof root === 'string' && root.length > 0\n );\n\n for (const root of candidateRoots) {\n const guardDir = join(root, '.astrasync');\n const policyFile = join(guardDir, 'policy.yaml');\n if (!existsSync(policyFile)) continue;\n\n let settings: GuardSettings = {};\n const settingsFile = join(guardDir, 'guard.json');\n if (existsSync(settingsFile)) {\n try {\n settings = JSON.parse(readFileSync(settingsFile, 'utf-8')) as GuardSettings;\n } catch {\n // A corrupt guard.json must not silently loosen the guard:\n // ignore it and run with defaults (active posture, fail-closed).\n settings = {};\n }\n }\n\n return { policyFile, guardDir, settings };\n }\n\n return null;\n}\n\n// -----------------------------------------------------------------------\n// Fleet-aware resolution (5.11.0)\n// -----------------------------------------------------------------------\n\n/** Enrolled machine: the org's signed central policy governs, nothing local. */\nexport interface FleetGuardResolution {\n kind: 'fleet';\n enrolment: FleetEnrolment;\n scope: 'machine' | 'user';\n paths: FleetPaths;\n}\n\n/** Fleet control is required (or the enrolment is unreadable) but unusable → deny. */\nexport interface FleetMissingResolution {\n kind: 'fleet-missing';\n reason: string;\n paths: FleetPaths;\n}\n\nexport interface LocalGuardResolution {\n kind: 'local';\n config: ResolvedGuardConfig;\n}\n\nexport type GuardResolution = FleetGuardResolution | FleetMissingResolution | LocalGuardResolution;\n\nexport const FLEET_ENROL_INSTRUCTION =\n 'This machine must be enrolled: run `astrasync guard enroll <token>` (token from your organisation admin)';\n\n/**\n * Fleet-only part of resolution — needs no payload, so hooks can decide the\n * fleet posture before (and regardless of) parsing the tool payload.\n * Returns null on an unenrolled machine without ASTRASYNC_FLEET_REQUIRED.\n */\nexport function resolveFleet(\n env: NodeJS.ProcessEnv,\n home: string = homedir(),\n paths: FleetPaths = fleetPaths({ home, env })\n): FleetGuardResolution | FleetMissingResolution | null {\n const loaded = loadEnrolment(paths);\n if (loaded && 'corrupt' in loaded) {\n return {\n kind: 'fleet-missing',\n reason: `fleet enrolment at ${loaded.path} is unreadable — ${FLEET_ENROL_INSTRUCTION}`,\n paths,\n };\n }\n if (loaded) return { kind: 'fleet', enrolment: loaded.enrolment, scope: loaded.scope, paths };\n if (env.ASTRASYNC_FLEET_REQUIRED === '1') {\n return { kind: 'fleet-missing', reason: FLEET_ENROL_INSTRUCTION, paths };\n }\n return null;\n}\n\n/**\n * Fleet first: an enrolled machine (machine scope wins over user scope)\n * ignores every local policy.yaml / guard.json. Otherwise the 5.10.0 local\n * resolution, unchanged. Null = the guard isn't configured at all.\n *\n * resolveGuardConfig keeps its 5.10.0 signature for existing importers.\n */\nexport function resolveGuard(\n env: NodeJS.ProcessEnv,\n payloadCwd?: string,\n home: string = homedir(),\n paths?: FleetPaths\n): GuardResolution | null {\n const fleet = resolveFleet(env, home, paths ?? fleetPaths({ home, env }));\n if (fleet) return fleet;\n const config = resolveGuardConfig(env, payloadCwd, home);\n return config ? { kind: 'local', config } : null;\n}\n","/**\n * Where fleet enrolment and the cached signed policy live.\n *\n * Machine scope (written by `astrasync guard enroll --system` / MDM) WINS\n * over user scope. The machine-scope fleet.json is world-readable (0644) —\n * the hook runs as the developer and must read the device credential; that\n * credential can only heartbeat and fetch this device's signed policy, never\n * alter it. User scope lives under ~/.astrasync/fleet/ at 0600.\n *\n * The policy cache + runtime state are user-scope (the hook must be able to\n * refresh them); tampering is caught by the signature check against the JWKS\n * pinned in the enrolment, and a missing cache is re-fetched or fails closed.\n */\n\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { homedir } from 'os';\nimport { dirname, join } from 'path';\nimport type { FleetEnrolment, FleetState } from './types';\n\nexport interface FleetPaths {\n machineDevice: string;\n machinePolicy: string;\n userDir: string;\n userDevice: string;\n userPolicy: string;\n /** Signed key-rotation chain (untrusted storage: each link is verified from the pin). */\n userKeyChain: string;\n state: string;\n}\n\nexport interface FleetPathOptions {\n home?: string;\n platform?: NodeJS.Platform;\n env?: NodeJS.ProcessEnv;\n /** Test hook: override the machine-scope directory. */\n machineDir?: string;\n}\n\nexport function machineScopeDir(\n platform: NodeJS.Platform = process.platform,\n env: NodeJS.ProcessEnv = process.env\n): string {\n if (platform === 'darwin') return '/Library/Application Support/AstraSync';\n if (platform === 'win32') return join(env.ProgramData || 'C:\\\\ProgramData', 'AstraSync');\n return '/etc/astrasync';\n}\n\nexport function fleetPaths(options: FleetPathOptions = {}): FleetPaths {\n const home = options.home ?? homedir();\n const machineDir =\n options.machineDir ??\n options.env?.ASTRASYNC_FLEET_MACHINE_DIR ??\n machineScopeDir(options.platform, options.env);\n const userDir = join(home, '.astrasync', 'fleet');\n return {\n machineDevice: join(machineDir, 'fleet.json'),\n machinePolicy: join(machineDir, 'policy.jws'),\n userDir,\n userDevice: join(userDir, 'device.json'),\n userPolicy: join(userDir, 'policy.jws'),\n userKeyChain: join(userDir, 'keychain.json'),\n state: join(userDir, 'state.json'),\n };\n}\n\nfunction isEnrolment(value: unknown): value is FleetEnrolment {\n const v = value as Partial<FleetEnrolment> | null;\n return (\n !!v &&\n typeof v.deviceId === 'string' &&\n typeof v.credential === 'string' &&\n typeof v.apiBaseUrl === 'string' &&\n !!v.org &&\n typeof v.org.ownerId === 'string' &&\n !!v.jwks &&\n Array.isArray(v.jwks.keys)\n );\n}\n\nexport interface LoadedEnrolment {\n enrolment: FleetEnrolment;\n scope: 'machine' | 'user';\n}\n\nexport interface CorruptEnrolment {\n corrupt: true;\n path: string;\n}\n\n/**\n * The machine's enrolment, machine scope first. A present-but-corrupt file\n * still counts as \"enrolled\" so the guard fails CLOSED rather than falling\n * back to developer-controlled local policy.\n */\nexport function loadEnrolment(paths: FleetPaths): LoadedEnrolment | CorruptEnrolment | null {\n const candidates: Array<[string, 'machine' | 'user']> = [\n [paths.machineDevice, 'machine'],\n [paths.userDevice, 'user'],\n ];\n for (const [path, scope] of candidates) {\n if (!existsSync(path)) continue;\n try {\n const parsed: unknown = JSON.parse(readFileSync(path, 'utf-8'));\n if (isEnrolment(parsed)) return { enrolment: parsed, scope };\n } catch {\n // fall through to corrupt\n }\n return { corrupt: true, path };\n }\n return null;\n}\n\nfunction writeFileMode(path: string, content: string, mode: number): void {\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n writeFileSync(path, content, { encoding: 'utf-8', mode });\n try {\n chmodSync(path, mode); // writeFileSync's mode only applies on create\n } catch {\n // best effort (e.g. Windows ACLs)\n }\n}\n\nexport function saveEnrolment(\n paths: FleetPaths,\n enrolment: FleetEnrolment,\n scope: 'machine' | 'user'\n): string {\n const path = scope === 'machine' ? paths.machineDevice : paths.userDevice;\n writeFileMode(path, JSON.stringify(enrolment, null, 2), scope === 'machine' ? 0o644 : 0o600);\n return path;\n}\n\n/** Cached policy JWS candidates (user cache first, then the machine baseline). */\nexport function readCachedPolicies(paths: FleetPaths): string[] {\n const out: string[] = [];\n for (const p of [paths.userPolicy, paths.machinePolicy]) {\n try {\n if (existsSync(p)) out.push(readFileSync(p, 'utf-8').trim());\n } catch {\n // unreadable → skip\n }\n }\n return out.filter(Boolean);\n}\n\nexport function writeCachedPolicy(paths: FleetPaths, jws: string): void {\n writeFileMode(paths.userPolicy, jws, 0o600);\n}\n\nexport function readKeyChain(paths: FleetPaths): string[] {\n try {\n const parsed: unknown = JSON.parse(readFileSync(paths.userKeyChain, 'utf-8'));\n return Array.isArray(parsed) ? parsed.filter((j): j is string => typeof j === 'string') : [];\n } catch {\n return [];\n }\n}\n\nexport function writeKeyChain(paths: FleetPaths, chain: string[]): void {\n writeFileMode(paths.userKeyChain, JSON.stringify(chain), 0o600);\n}\n\nexport function writeMachinePolicy(paths: FleetPaths, jws: string): void {\n writeFileMode(paths.machinePolicy, jws, 0o644);\n}\n\nexport function readState(paths: FleetPaths): FleetState {\n try {\n const parsed = JSON.parse(readFileSync(paths.state, 'utf-8')) as FleetState;\n const c = parsed.counts;\n return {\n ...parsed,\n counts: { allow: c?.allow ?? 0, deny: c?.deny ?? 0, ask: c?.ask ?? 0 },\n };\n } catch {\n return { counts: { allow: 0, deny: 0, ask: 0 } };\n }\n}\n\nexport function writeState(paths: FleetPaths, state: FleetState): void {\n try {\n writeFileMode(paths.state, JSON.stringify(state, null, 2), 0o600);\n } catch {\n // State is best-effort; never let it affect a decision.\n }\n}\n","/**\n * Fleet-mode evaluation for the hook adapters (Claude Code, Codex).\n *\n * In fleet mode the developer has no say: ASTRASYNC_GUARD_DISABLE, the env\n * or guard.json failOpen, a project/user policy.yaml and the passive\n * default are all ignored. Posture, failOpen, governMcp and skipTools come\n * only from the org's verified signed settings. No valid signed policy →\n * deny (fail closed). Entry-free module (safe to bundle into any bin).\n */\n\nimport { join } from 'path';\nimport { AstraSyncGateway } from '../gateway/gateway';\nimport type { FleetGuardResolution, FleetMissingResolution } from '../claude-code/guard-config';\nimport { SDK_VERSION } from '../version';\nimport {\n loadFleetPolicy,\n recordDecisionAndHeartbeat,\n type FleetDecision,\n type HeartbeatOutcome,\n} from './runtime';\nimport type { VerifiedFleetPolicy } from './types';\n\ntype GatewayConfig = ConstructorParameters<typeof AstraSyncGateway>[0];\n\nexport interface FleetHookAdapter<P, O> {\n initialize(ctx: {\n gateway: AstraSyncGateway;\n adapterOptions: Record<string, unknown>;\n }): Promise<void>;\n evaluatePayload(payload: P): Promise<O | null>;\n shutdown(): Promise<void>;\n}\n\nexport interface RunFleetHookArgs<P, O> {\n resolution: FleetGuardResolution | FleetMissingResolution;\n payloadJson: string;\n adapterKind: 'claude-code' | 'codex';\n createAdapter: (options: { skipTools?: string[]; governMcp?: boolean }) => FleetHookAdapter<P, O>;\n denyOutput: (reason: string) => O;\n /** Decision class of an adapter output (null = allow). */\n classify: (output: O | null) => FleetDecision;\n gatewayFactory?: (config: GatewayConfig) => AstraSyncGateway;\n now?: () => number;\n /** Test hook: observe the (awaited, budgeted) heartbeat outcome. */\n onHeartbeat?: (outcome: HeartbeatOutcome) => void;\n}\n\nexport interface FleetHookResult<O> {\n output: O | null;\n exitCode: number;\n}\n\nconst PREFIX = 'AstraSync Local Guard (organisation fleet policy)';\n\nexport async function runFleetHook<P, O>(\n args: RunFleetHookArgs<P, O>\n): Promise<FleetHookResult<O>> {\n if (args.resolution.kind === 'fleet-missing') {\n return { output: args.denyOutput(`${PREFIX}: ${args.resolution.reason}`), exitCode: 0 };\n }\n const ctx = { enrolment: args.resolution.enrolment, paths: args.resolution.paths };\n\n let verified: VerifiedFleetPolicy;\n try {\n verified = await loadFleetPolicy(ctx);\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n return {\n output: args.denyOutput(`${PREFIX}: no valid signed policy — ${detail}`),\n exitCode: 0,\n };\n }\n const { settings } = verified;\n\n const decide = async (output: O | null): Promise<FleetHookResult<O>> => {\n try {\n const outcome = await recordDecisionAndHeartbeat(ctx, verified, args.classify(output), {\n guardVersion: SDK_VERSION,\n adapterKind: args.adapterKind,\n now: args.now,\n });\n args.onHeartbeat?.(outcome);\n } catch {\n // Heartbeat is telemetry — never affects the decision.\n }\n return { output, exitCode: 0 };\n };\n\n let payload: P;\n try {\n payload = JSON.parse(args.payloadJson) as P;\n } catch {\n if (settings.failOpen) return decide(null);\n return decide(args.denyOutput(`${PREFIX}: could not parse hook payload`));\n }\n\n try {\n const gatewayConfig: GatewayConfig = {\n mode: 'local',\n policy: verified.policy,\n posture: settings.posture,\n traceEnabled: true,\n tracePath: join(args.resolution.paths.userDir, 'traces'),\n debug: false,\n };\n const gateway = args.gatewayFactory\n ? args.gatewayFactory(gatewayConfig)\n : new AstraSyncGateway(gatewayConfig);\n await gateway.initialize();\n\n const adapter = args.createAdapter({\n ...(settings.skipTools && { skipTools: settings.skipTools }),\n ...(typeof settings.governMcp === 'boolean' && { governMcp: settings.governMcp }),\n });\n await adapter.initialize({ gateway, adapterOptions: {} });\n const output = await adapter.evaluatePayload(payload);\n await adapter.shutdown();\n await gateway.shutdown();\n return decide(output);\n } catch (err) {\n if (settings.failOpen) return decide(null);\n const detail = err instanceof Error ? err.message : String(err);\n return decide(args.denyOutput(`${PREFIX}: policy evaluation failed (${detail})`));\n }\n}\n","/**\n * Fleet device API client (backend fleet-device routes). Every call is\n * bounded by a timeout — the guard must never block a tool call on network.\n */\n\nimport { sdkFetch } from '../http';\nimport type { FleetEnrolment, FleetJwks } from './types';\n\nexport class FleetApiError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly code?: string\n ) {\n super(message);\n this.name = 'FleetApiError';\n }\n}\n\nexport interface EnrolRequest {\n token: string;\n fingerprint: string;\n hostname: string;\n os: { platform: string; release: string; arch: string };\n guardVersion: string;\n adapters: Array<{ kind: string; managed: boolean; allowManagedHooksOnly?: boolean }>;\n}\n\nexport interface EnrolResponse {\n deviceId: string;\n credential: string;\n org: FleetEnrolment['org'];\n apiBaseUrl: string;\n jwks: FleetJwks;\n policyJws: string;\n heartbeatIntervalSec: number;\n}\n\nexport interface HeartbeatRequest {\n appliedSha256: string | null;\n guardVersion: string;\n adapters: EnrolRequest['adapters'];\n posture: 'active' | 'passive';\n decisionCounts: { allow: number; deny: number; ask: number };\n}\n\nexport interface HeartbeatResponse {\n activeSha256: string;\n /** The org's current signing key id (changes on rotation). */\n activeKid?: string;\n nextHeartbeatSec: number;\n}\n\nexport type PolicyFetchResult =\n | { status: 'unchanged' }\n | { status: 'ok'; policyJws: string; sha256: string; version: number; keyChain: string[] };\n\nfunction base(url: string): string {\n return url.replace(/\\/+$/, '');\n}\n\nasync function call(\n url: string,\n init: RequestInit,\n timeoutMs: number\n): Promise<{ status: number; body: unknown; headers: Headers }> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await sdkFetch(url, { ...init, signal: controller.signal });\n const text = await res.text();\n let body: unknown = text;\n try {\n body = text ? JSON.parse(text) : null;\n } catch {\n // non-JSON body\n }\n return { status: res.status, body, headers: res.headers };\n } finally {\n clearTimeout(timer);\n }\n}\n\nfunction apiError(status: number, body: unknown, what: string): FleetApiError {\n const b = (body ?? {}) as { code?: string; error?: string; message?: string };\n const code = b.code ?? (typeof b.error === 'string' ? b.error : undefined);\n return new FleetApiError(`${what} failed (${status}${code ? ` ${code}` : ''})`, status, code);\n}\n\nexport async function enrolDevice(\n apiBaseUrl: string,\n request: EnrolRequest,\n timeoutMs = 15000\n): Promise<EnrolResponse> {\n const r = await call(\n `${base(apiBaseUrl)}/fleet/enrol`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n },\n timeoutMs\n );\n if (r.status !== 201 && r.status !== 200) throw apiError(r.status, r.body, 'Enrolment');\n const data = r.body as Partial<EnrolResponse>;\n if (!data?.deviceId || !data.credential || !data.jwks || !data.policyJws) {\n throw new FleetApiError('Enrolment response is missing required fields', r.status);\n }\n return data as EnrolResponse;\n}\n\nfunction deviceHeaders(enrolment: FleetEnrolment): Record<string, string> {\n return { Authorization: `Device ${enrolment.credential}` };\n}\n\n/** The policy route's ETag value for an applied policy: `<sha256>.<kid>`. */\nexport function policyEtag(sha256: string, kid: string | undefined): string {\n return `${sha256}.${kid ?? ''}`;\n}\n\nexport async function fetchFleetPolicy(\n enrolment: FleetEnrolment,\n ifNoneMatch: string | null,\n timeoutMs = 1500\n): Promise<PolicyFetchResult> {\n const headers: Record<string, string> = deviceHeaders(enrolment);\n if (ifNoneMatch) headers['If-None-Match'] = `\"${ifNoneMatch}\"`;\n const r = await call(`${base(enrolment.apiBaseUrl)}/fleet/policy`, { headers }, timeoutMs);\n if (r.status === 304) return { status: 'unchanged' };\n if (r.status !== 200) throw apiError(r.status, r.body, 'Policy fetch');\n const data = r.body as {\n policyJws?: string;\n sha256?: string;\n version?: number;\n keyChain?: unknown;\n };\n if (!data?.policyJws) throw new FleetApiError('Policy response has no policyJws', r.status);\n return {\n status: 'ok',\n policyJws: data.policyJws,\n sha256: data.sha256 ?? '',\n version: data.version ?? 0,\n keyChain: Array.isArray(data.keyChain)\n ? data.keyChain.filter((j): j is string => typeof j === 'string')\n : [],\n };\n}\n\nexport async function sendHeartbeat(\n enrolment: FleetEnrolment,\n request: HeartbeatRequest,\n timeoutMs = 1500\n): Promise<HeartbeatResponse> {\n const r = await call(\n `${base(enrolment.apiBaseUrl)}/fleet/heartbeat`,\n {\n method: 'POST',\n headers: { ...deviceHeaders(enrolment), 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n },\n timeoutMs\n );\n if (r.status !== 200) throw apiError(r.status, r.body, 'Heartbeat');\n return r.body as HeartbeatResponse;\n}\n","/**\n * Verify a fleet policy JWS against the org's key: the JWKS pinned at\n * enrolment, advanced along the signed rotation chain (resolveFleetJwks).\n *\n * Every check is fail-closed: a wrong algorithm/typ/aud/iss/sub, a policy\n * hash mismatch, a version rollback, an invalid YAML policy or malformed\n * settings all reject — the caller then denies rather than running with a\n * policy the org didn't sign.\n */\n\nimport { createHash } from 'crypto';\nimport { compactVerify, createLocalJWKSet, type JSONWebKeySet } from 'jose';\nimport { parseYaml } from '../local-evaluator/pdlss-parser';\nimport {\n FLEET_KEYS_AUD,\n FLEET_KEYS_TYP,\n FLEET_POLICY_AUD,\n FLEET_POLICY_ISS,\n FLEET_POLICY_TYP,\n type FleetJwks,\n type FleetKeyRotationClaims,\n type FleetPolicyClaims,\n type FleetSettings,\n type VerifiedFleetPolicy,\n} from './types';\n\nexport class FleetPolicyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'FleetPolicyError';\n }\n}\n\nexport interface VerifyOptions {\n /** Accepted `sub` values: the org owner id and this device's id. */\n expectedSubs: string[];\n /** Highest ver previously accepted; anything lower is a rollback. */\n minVer?: number;\n}\n\nfunction sha256Hex(text: string): string {\n return createHash('sha256').update(text, 'utf8').digest('hex');\n}\n\nfunction parseSettings(raw: unknown): FleetSettings {\n if (!raw || typeof raw !== 'object') throw new FleetPolicyError('settings missing');\n const s = raw as Record<string, unknown>;\n if (s.posture !== 'active' && s.posture !== 'passive') {\n throw new FleetPolicyError('settings.posture must be active or passive');\n }\n if (s.failOpen !== undefined && typeof s.failOpen !== 'boolean') {\n throw new FleetPolicyError('settings.failOpen must be a boolean');\n }\n if (s.governMcp !== undefined && typeof s.governMcp !== 'boolean') {\n throw new FleetPolicyError('settings.governMcp must be a boolean');\n }\n if (\n s.skipTools !== undefined &&\n !(Array.isArray(s.skipTools) && s.skipTools.every((t) => typeof t === 'string'))\n ) {\n throw new FleetPolicyError('settings.skipTools must be a string array');\n }\n const num = (v: unknown) =>\n typeof v === 'number' && Number.isFinite(v) && v > 0 ? v : undefined;\n return {\n posture: s.posture,\n failOpen: s.failOpen === true,\n ...(typeof s.governMcp === 'boolean' && { governMcp: s.governMcp }),\n ...(Array.isArray(s.skipTools) && { skipTools: s.skipTools as string[] }),\n ...(num(s.heartbeatIntervalSec) && { heartbeatIntervalSec: num(s.heartbeatIntervalSec) }),\n ...(num(s.staleAfterSec) && { staleAfterSec: num(s.staleAfterSec) }),\n };\n}\n\nexport async function verifyFleetPolicy(\n jws: string,\n jwks: FleetJwks,\n options: VerifyOptions\n): Promise<VerifiedFleetPolicy> {\n let payloadBytes: Uint8Array;\n let header: { alg?: string; typ?: string; kid?: string };\n try {\n const keySet = createLocalJWKSet(jwks as unknown as JSONWebKeySet);\n const result = await compactVerify(jws, keySet, { algorithms: ['ES256'] });\n payloadBytes = result.payload;\n header = result.protectedHeader;\n } catch (err) {\n throw new FleetPolicyError(\n `signature verification failed (${err instanceof Error ? err.message : String(err)})`\n );\n }\n if (header.typ !== FLEET_POLICY_TYP) throw new FleetPolicyError(`unexpected typ ${header.typ}`);\n\n let claims: FleetPolicyClaims;\n try {\n claims = JSON.parse(new TextDecoder().decode(payloadBytes)) as FleetPolicyClaims;\n } catch {\n throw new FleetPolicyError('payload is not JSON');\n }\n if (claims.aud !== FLEET_POLICY_AUD) throw new FleetPolicyError(`unexpected aud ${claims.aud}`);\n if (claims.iss !== FLEET_POLICY_ISS) throw new FleetPolicyError(`unexpected iss ${claims.iss}`);\n if (!options.expectedSubs.includes(claims.sub)) {\n throw new FleetPolicyError('policy was issued for a different organisation or device');\n }\n if (!Number.isInteger(claims.ver) || claims.ver < 1) {\n throw new FleetPolicyError('ver must be a positive integer');\n }\n if (options.minVer !== undefined && claims.ver < options.minVer) {\n throw new FleetPolicyError(\n `policy version ${claims.ver} is older than the accepted version ${options.minVer} (rollback)`\n );\n }\n if (typeof claims.yaml !== 'string' || sha256Hex(claims.yaml) !== claims.sha256) {\n throw new FleetPolicyError('policy hash mismatch');\n }\n const settings = parseSettings(claims.settings);\n const parsed = parseYaml(claims.yaml);\n if (!parsed.policy) {\n const first = parsed.validation.errors[0];\n throw new FleetPolicyError(\n `signed policy is invalid${first ? ` (${first.path}: ${first.message})` : ''}`\n );\n }\n return { kid: header.kid, claims: { ...claims, settings }, policy: parsed.policy, settings, jws };\n}\n\n/**\n * The org's current key set: start at the pinned JWKS and follow each\n * rotation statement that verifies under the keys trusted so far (oldest\n * first; links from before the pin simply don't verify and are skipped).\n * Each accepted link REPLACES the trusted set, so a retired key can't sign\n * policy once the machine has seen the rotation. A link for another org\n * (sub), or any malformed link, is ignored — never trusted.\n */\nexport async function resolveFleetJwks(\n pinned: FleetJwks,\n chain: string[],\n ownerId: string\n): Promise<FleetJwks> {\n let trusted = pinned;\n let lastSeq = 0;\n for (const link of chain) {\n try {\n const { payload, protectedHeader } = await compactVerify(\n link,\n createLocalJWKSet(trusted as unknown as JSONWebKeySet),\n { algorithms: ['ES256'] }\n );\n if (protectedHeader.typ !== FLEET_KEYS_TYP) continue;\n const c = JSON.parse(new TextDecoder().decode(payload)) as FleetKeyRotationClaims;\n if (c.aud !== FLEET_KEYS_AUD || c.iss !== FLEET_POLICY_ISS || c.sub !== ownerId) continue;\n if (!Number.isInteger(c.seq) || c.seq <= lastSeq) continue;\n const keys = Array.isArray(c.keys)\n ? c.keys.filter((k) => k && k.kty === 'EC' && k.crv === 'P-256' && !('d' in k))\n : [];\n if (keys.length === 0) continue;\n trusted = { keys };\n lastSeq = c.seq;\n } catch {\n // Not signed by a trusted key (e.g. predates the pin) — skip.\n }\n }\n return trusted;\n}\n\n/**\n * The newest valid policy among candidates (user cache, machine baseline).\n * Throws the last error when none verifies.\n */\nexport async function pickNewestValid(\n candidates: string[],\n jwks: FleetJwks,\n options: VerifyOptions\n): Promise<VerifiedFleetPolicy> {\n let best: VerifiedFleetPolicy | null = null;\n let lastError: Error = new FleetPolicyError('no cached fleet policy');\n for (const jws of candidates) {\n try {\n const v = await verifyFleetPolicy(jws, jwks, options);\n if (!best || v.claims.ver > best.claims.ver) best = v;\n } catch (err) {\n lastError = err instanceof Error ? err : new FleetPolicyError(String(err));\n }\n }\n if (!best) throw lastError;\n return best;\n}\n","/**\n * Fleet mode (round 27.1): an org enrols its developers' machines; each\n * enrolled machine enforces the org's CENTRAL signed policy instead of any\n * local policy.yaml / guard.json. Wire contract: backend fleet-device routes\n * (POST /fleet/enrol, GET /fleet/policy, POST /fleet/heartbeat) and the\n * ES256 policy JWS (typ fleet-policy+jwt, aud astrasync:fleet-policy).\n */\n\nimport type { LocalPolicy } from '../gateway/types';\n\nexport const FLEET_POLICY_TYP = 'fleet-policy+jwt';\nexport const FLEET_POLICY_AUD = 'astrasync:fleet-policy';\nexport const FLEET_POLICY_ISS = 'astrasync.ai';\n/** Key rotation statement: the org's new public key, signed by the key it replaces. */\nexport const FLEET_KEYS_TYP = 'fleet-keys+jwt';\nexport const FLEET_KEYS_AUD = 'astrasync:fleet-keys';\nexport const DEFAULT_HEARTBEAT_INTERVAL_SEC = 900;\n\n/** Settings delivered INSIDE the signed policy — the only source in fleet mode. */\nexport interface FleetSettings {\n posture: 'active' | 'passive';\n failOpen: boolean;\n governMcp?: boolean;\n skipTools?: string[];\n heartbeatIntervalSec?: number;\n staleAfterSec?: number;\n}\n\nexport interface FleetJwk {\n kty: string;\n crv?: string;\n x?: string;\n y?: string;\n kid?: string;\n alg?: string;\n use?: string;\n}\n\nexport interface FleetJwks {\n keys: FleetJwk[];\n}\n\n/**\n * Persisted enrolment (device.json / fleet.json). The JWKS (the org's own\n * key) is pinned at enrolment; later keys are trusted only via the signed\n * rotation chain that starts at this pin.\n */\nexport interface FleetEnrolment {\n version: 1;\n deviceId: string;\n /** `fdc_<prefix>.<secret>` — sent as `Authorization: Device <credential>` */\n credential: string;\n org: { ownerId: string; kyoId?: string; name?: string };\n apiBaseUrl: string;\n jwks: FleetJwks;\n heartbeatIntervalSec: number;\n enrolledAt: string;\n}\n\nexport interface FleetPolicyClaims {\n iss: string;\n aud: string;\n sub: string;\n ver: number;\n sha256: string;\n yaml: string;\n settings: FleetSettings;\n iat?: number;\n}\n\nexport interface FleetKeyRotationClaims {\n iss: string;\n aud: string;\n sub: string;\n seq: number;\n prevKid: string;\n keys: FleetJwk[];\n iat?: number;\n}\n\nexport interface VerifiedFleetPolicy {\n /** The signing key id (a changed kid on the platform → refresh). */\n kid?: string;\n claims: FleetPolicyClaims;\n policy: LocalPolicy;\n settings: FleetSettings;\n jws: string;\n}\n\n/** Mutable per-user runtime state (state.json). */\nexport interface FleetState {\n lastHeartbeatAt?: string;\n appliedSha256?: string | null;\n /** Highest policy ver ever accepted — rollback guard. */\n maxVer?: number;\n counts: { allow: number; deny: number; ask: number };\n revoked?: boolean;\n lastError?: string;\n}\n","/**\n * Fleet-mode runtime shared by every hook adapter (Claude Code, Codex) and\n * the Cursor extension: load the verified central policy, then heartbeat.\n *\n * Load order: the newest cached signed policy that verifies (user cache or\n * the machine-scope baseline written at `enroll --system`); if none does,\n * one bounded fetch. No valid policy anywhere → throw → the caller denies.\n */\n\nimport { FleetApiError, fetchFleetPolicy, policyEtag, sendHeartbeat } from './client';\nimport {\n readCachedPolicies,\n readKeyChain,\n readState,\n writeCachedPolicy,\n writeKeyChain,\n writeState,\n type FleetPaths,\n} from './enrolment-store';\nimport {\n FleetPolicyError,\n pickNewestValid,\n resolveFleetJwks,\n verifyFleetPolicy,\n} from './policy-verify';\nimport {\n DEFAULT_HEARTBEAT_INTERVAL_SEC,\n type FleetEnrolment,\n type FleetJwks,\n type FleetState,\n type VerifiedFleetPolicy,\n} from './types';\n\n/** Total network budget per hook invocation for fleet sync (mirrors hybrid flush). */\nexport const FLEET_SYNC_BUDGET_MS = 1500;\n\nexport interface FleetContext {\n enrolment: FleetEnrolment;\n paths: FleetPaths;\n}\n\nfunction expectedSubs(enrolment: FleetEnrolment): string[] {\n return [enrolment.org.ownerId, enrolment.deviceId];\n}\n\n/** The org's current keys: the enrolment pin advanced along a rotation chain. */\nexport function fleetJwks(\n ctx: FleetContext,\n chain: string[] = readKeyChain(ctx.paths)\n): Promise<FleetJwks> {\n return resolveFleetJwks(ctx.enrolment.jwks, chain, ctx.enrolment.org.ownerId);\n}\n\n/**\n * Verify a freshly fetched policy under the keys its chain resolves to, then\n * persist chain + policy together (the chain only after the policy verifies).\n */\nasync function acceptFetched(\n ctx: FleetContext,\n fetched: { policyJws: string; keyChain: string[] },\n verifyOpts: { expectedSubs: string[]; minVer?: number }\n): Promise<VerifiedFleetPolicy> {\n const jwks = await fleetJwks(ctx, fetched.keyChain);\n const verified = await verifyFleetPolicy(fetched.policyJws, jwks, verifyOpts);\n if (fetched.keyChain.length > 0) writeKeyChain(ctx.paths, fetched.keyChain);\n writeCachedPolicy(ctx.paths, fetched.policyJws);\n return verified;\n}\n\nfunction remember(paths: FleetPaths, state: FleetState, verified: VerifiedFleetPolicy): void {\n state.appliedSha256 = verified.claims.sha256;\n state.maxVer = Math.max(state.maxVer ?? 0, verified.claims.ver);\n writeState(paths, state);\n}\n\n/**\n * The verified central policy for this device. Never returns an unverified\n * policy: throws FleetPolicyError (caller fails closed) when no valid signed\n * policy is available.\n */\nexport async function loadFleetPolicy(\n ctx: FleetContext,\n options: { fetchTimeoutMs?: number } = {}\n): Promise<VerifiedFleetPolicy> {\n const state = readState(ctx.paths);\n const verifyOpts = { expectedSubs: expectedSubs(ctx.enrolment), minVer: state.maxVer };\n const cached = readCachedPolicies(ctx.paths);\n\n let cacheError: Error | null = null;\n if (cached.length > 0) {\n try {\n const verified = await pickNewestValid(cached, await fleetJwks(ctx), verifyOpts);\n if (verified.claims.sha256 !== state.appliedSha256 || verified.claims.ver !== state.maxVer) {\n remember(ctx.paths, state, verified);\n }\n return verified;\n } catch (err) {\n cacheError = err instanceof Error ? err : new FleetPolicyError(String(err));\n }\n }\n\n // No usable cache — one bounded fetch of the current signed policy.\n try {\n const fetched = await fetchFleetPolicy(\n ctx.enrolment,\n null,\n options.fetchTimeoutMs ?? FLEET_SYNC_BUDGET_MS\n );\n if (fetched.status === 'ok') {\n const verified = await acceptFetched(ctx, fetched, verifyOpts);\n remember(ctx.paths, state, verified);\n return verified;\n }\n } catch (err) {\n if (err instanceof FleetApiError && err.code === 'DEVICE_REVOKED') {\n state.revoked = true;\n writeState(ctx.paths, state);\n }\n const detail = err instanceof Error ? err.message : String(err);\n throw new FleetPolicyError(\n cacheError\n ? `${cacheError.message}; refresh failed (${detail})`\n : `no fleet policy (${detail})`\n );\n }\n throw cacheError ?? new FleetPolicyError('no fleet policy available');\n}\n\nexport type FleetDecision = 'allow' | 'deny' | 'ask';\n\nexport interface HeartbeatOptions {\n guardVersion: string;\n adapterKind: 'claude-code' | 'codex' | 'cursor';\n now?: () => number;\n budgetMs?: number;\n}\n\nexport type HeartbeatOutcome = 'throttled' | 'sent' | 'refreshed' | 'revoked' | 'failed';\n\n/**\n * Count the decision and, at most once per heartbeat interval, report to\n * the platform. Runs AFTER the decision is made and within a fixed budget —\n * it can never change or delay the current decision. When the platform's\n * active policy differs from the applied one, fetch + verify + swap the\n * cache for the next invocation.\n */\nexport async function recordDecisionAndHeartbeat(\n ctx: FleetContext,\n applied: VerifiedFleetPolicy,\n /** null = heartbeat only (e.g. the Cursor extension at activation). */\n decision: FleetDecision | null,\n options: HeartbeatOptions\n): Promise<HeartbeatOutcome> {\n const now = options.now ?? Date.now;\n const state = readState(ctx.paths);\n if (decision) state.counts[decision] += 1;\n\n const intervalSec =\n applied.settings.heartbeatIntervalSec ??\n ctx.enrolment.heartbeatIntervalSec ??\n DEFAULT_HEARTBEAT_INTERVAL_SEC;\n const last = state.lastHeartbeatAt ? Date.parse(state.lastHeartbeatAt) : 0;\n if (now() - last < intervalSec * 1000) {\n writeState(ctx.paths, state);\n return 'throttled';\n }\n\n const deadline = now() + (options.budgetMs ?? FLEET_SYNC_BUDGET_MS);\n const remaining = () => Math.max(1, deadline - now());\n // Stamp first: an offline machine retries once per interval, not per call.\n state.lastHeartbeatAt = new Date(now()).toISOString();\n\n let outcome: HeartbeatOutcome = 'sent';\n try {\n const hb = await sendHeartbeat(\n ctx.enrolment,\n {\n appliedSha256: applied.claims.sha256,\n guardVersion: options.guardVersion,\n adapters: [{ kind: options.adapterKind, managed: true }],\n posture: applied.settings.posture,\n decisionCounts: { ...state.counts },\n },\n remaining()\n );\n state.counts = { allow: 0, deny: 0, ask: 0 };\n state.revoked = false;\n delete state.lastError;\n\n const policyChanged = !!hb.activeSha256 && hb.activeSha256 !== applied.claims.sha256;\n // A rotated org key: fetch the re-signed policy + the rotation chain.\n const keyChanged = !!hb.activeKid && !!applied.kid && hb.activeKid !== applied.kid;\n if (policyChanged || keyChanged) {\n const fetched = await fetchFleetPolicy(\n ctx.enrolment,\n policyEtag(applied.claims.sha256, applied.kid),\n remaining()\n );\n if (fetched.status === 'ok') {\n const verified = await acceptFetched(ctx, fetched, {\n expectedSubs: expectedSubs(ctx.enrolment),\n minVer: Math.max(state.maxVer ?? 0, applied.claims.ver),\n });\n state.appliedSha256 = verified.claims.sha256;\n state.maxVer = Math.max(state.maxVer ?? 0, verified.claims.ver);\n outcome = 'refreshed';\n }\n }\n } catch (err) {\n if (err instanceof FleetApiError && err.code === 'DEVICE_REVOKED') {\n // Keep enforcing the last good policy; surfaced by `guard fleet-status`.\n state.revoked = true;\n outcome = 'revoked';\n } else {\n state.lastError = err instanceof Error ? err.message : String(err);\n outcome = 'failed';\n }\n }\n writeState(ctx.paths, state);\n return outcome;\n}\n","/**\n * AstraSync Local Guard for Claude Code — settings.json installer.\n *\n * Merges the guard's PreToolUse hook entry into a Claude Code settings\n * file (~/.claude/settings.json or <project>/.claude/settings.json)\n * without clobbering anything else in it, and builds the default policy\n * for a coding agent.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { dirname } from 'path';\nimport type { LocalPolicy } from '../gateway/types';\nimport { DEFAULT_BLOCKED_COMMANDS, DEFAULT_BLOCKED_PATHS, RISK_PRESETS } from '../cli/wizard';\nimport { parseFile, toYaml } from '../local-evaluator/pdlss-parser';\n\n/** Substring that identifies the guard's hook entry inside settings.json */\nexport const ASTRASYNC_HOOK_MARKER = 'astrasync-claude-hook';\n\n/**\n * Tools worth spawning the hook for. Matcher-side filtering keeps\n * bookkeeping tools (TodoWrite etc.) from paying node startup cost.\n */\nexport const HOOK_MATCHER =\n 'Bash|PowerShell|Write|Edit|MultiEdit|NotebookEdit|Read|Glob|Grep|WebFetch|WebSearch|Task|Agent|mcp__.*';\n\nconst HOOK_TIMEOUT_SECONDS = 10;\n\n// -----------------------------------------------------------------------\n// Settings file shapes (only the parts we touch)\n// -----------------------------------------------------------------------\n\ninterface HookCommand {\n type: string;\n command: string;\n timeout?: number;\n [key: string]: unknown;\n}\n\ninterface HookMatcherEntry {\n matcher?: string;\n hooks?: HookCommand[];\n [key: string]: unknown;\n}\n\ninterface ClaudeSettings {\n hooks?: {\n PreToolUse?: HookMatcherEntry[];\n [key: string]: unknown;\n };\n permissions?: {\n deny?: unknown;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\nexport interface InstallResult {\n installed: boolean;\n alreadyPresent: boolean;\n updated: boolean;\n}\n\nfunction isGuardEntry(entry: HookMatcherEntry, marker: string): boolean {\n return (entry.hooks ?? []).some(\n (h) => typeof h.command === 'string' && h.command.includes(marker)\n );\n}\n\nfunction readSettings(settingsPath: string): ClaudeSettings {\n if (!existsSync(settingsPath)) return {};\n const content = readFileSync(settingsPath, 'utf-8').trim();\n if (!content) return {};\n return JSON.parse(content) as ClaudeSettings;\n}\n\nfunction writeSettings(settingsPath: string, settings: ClaudeSettings): void {\n mkdirSync(dirname(settingsPath), { recursive: true });\n writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\\n`, 'utf-8');\n}\n\nexport function buildHookEntry(\n hookCommand: string,\n matcher: string = HOOK_MATCHER,\n extraHookFields: Record<string, unknown> = {}\n): HookMatcherEntry {\n return {\n matcher,\n hooks: [\n { type: 'command', command: hookCommand, timeout: HOOK_TIMEOUT_SECONDS, ...extraHookFields },\n ],\n };\n}\n\n/**\n * Merge the guard's PreToolUse entry into a hooks settings file.\n * Claude Code's settings.json and Codex CLI's hooks.json share this JSON\n * shape (`hooks.PreToolUse[].hooks[]`), so the Codex installer reuses this\n * with its own marker/matcher. Never clobbers: preserves unknown keys,\n * foreign hooks, and other PreToolUse entries. Idempotent — re-running\n * updates our entry in place.\n *\n * Throws if the existing settings file is not valid JSON (never overwrite\n * a file we cannot faithfully rewrite).\n */\nexport function installClaudeHooks(\n settingsPath: string,\n hookCommand: string,\n marker: string = ASTRASYNC_HOOK_MARKER,\n matcher: string = HOOK_MATCHER,\n extraHookFields: Record<string, unknown> = {}\n): InstallResult {\n if (!hookCommand.includes(marker)) {\n throw new Error(\n `Hook command must reference ${marker} (got: ${hookCommand}) — ` +\n 'the marker is how install/uninstall identify the guard entry.'\n );\n }\n\n const settings = readSettings(settingsPath);\n settings.hooks = settings.hooks ?? {};\n const preToolUse = (settings.hooks.PreToolUse = settings.hooks.PreToolUse ?? []);\n\n const existing = preToolUse.find((entry) => isGuardEntry(entry, marker));\n if (existing) {\n const fresh = buildHookEntry(hookCommand, matcher, extraHookFields);\n const changed = JSON.stringify(existing) !== JSON.stringify(fresh);\n if (changed) {\n preToolUse[preToolUse.indexOf(existing)] = fresh;\n writeSettings(settingsPath, settings);\n }\n return { installed: false, alreadyPresent: true, updated: changed };\n }\n\n preToolUse.push(buildHookEntry(hookCommand, matcher, extraHookFields));\n writeSettings(settingsPath, settings);\n return { installed: true, alreadyPresent: false, updated: false };\n}\n\n/**\n * Remove the guard's PreToolUse entry. Leaves everything else untouched;\n * prunes hooks.PreToolUse / hooks only if the guard was their sole content.\n * Returns true if an entry was removed.\n */\nexport function uninstallClaudeHooks(\n settingsPath: string,\n marker: string = ASTRASYNC_HOOK_MARKER\n): boolean {\n if (!existsSync(settingsPath)) return false;\n\n let settings: ClaudeSettings;\n try {\n settings = readSettings(settingsPath);\n } catch {\n return false;\n }\n\n const preToolUse = settings.hooks?.PreToolUse;\n if (!preToolUse) return false;\n\n const remaining = preToolUse.filter((entry) => !isGuardEntry(entry, marker));\n if (remaining.length === preToolUse.length) return false;\n\n if (remaining.length > 0) {\n settings.hooks!.PreToolUse = remaining;\n } else {\n delete settings.hooks!.PreToolUse;\n if (Object.keys(settings.hooks!).length === 0) delete settings.hooks;\n }\n\n writeSettings(settingsPath, settings);\n return true;\n}\n\n// -----------------------------------------------------------------------\n// Claude Code native permission rules (settings self-protection)\n// -----------------------------------------------------------------------\n\n/**\n * Paths the guard denies via Claude Code's native permissions.deny, in\n * addition to the hook's blockedPatterns. Needed because Claude Code\n * evaluates permission rules BEFORE PreToolUse hooks, enforces them even\n * when the guard posture is passive, and rejects schema-invalid settings\n * edits without ever invoking the hook — so the hook alone cannot fully\n * protect the settings file it is registered in. A governed agent also\n * cannot remove these rules: the removal edit is itself denied\n * (runtime-verified on Claude Code 2.1.210, 2026-07-15).\n *\n * Both `~/` and `**` forms ship because bare globs are anchored relative\n * to cwd/settings-dir per the gitignore spec; unmatched forms are inert.\n */\nconst PERMISSION_DENY_PATHS = [\n '**/.claude/settings.json',\n '**/.claude/settings.local.json',\n '~/.claude/settings.json',\n '~/.claude/settings.local.json',\n '**/.astrasync/**',\n '~/.astrasync/**',\n // 5.11.0 fleet mode: enrolment + signed-policy cache (user scope is inside\n // ~/.astrasync already; listed explicitly so the intent survives edits) and\n // the machine-scope enrolment dirs. `//` = absolute from filesystem root;\n // Windows paths are matched in POSIX form (C:\\ → /c/).\n '~/.astrasync/fleet/**',\n '//etc/astrasync/**',\n '//Library/Application Support/AstraSync/**',\n '//c/ProgramData/AstraSync/**',\n];\n\n/**\n * The guard's canonical permissions.deny rule strings.\n *\n * Edit() rules only: Claude Code's file permission checks match Edit(path)\n * rules against every file-editing tool (Write/NotebookEdit included) and\n * warn at session start that Write(path) rules are never matched.\n *\n * Claude-Code-only — never install these into Codex's hooks.json, which\n * has no permissions concept. Ownership is by exact string match (deny\n * entries have no marker field), so these strings are the contract:\n * when a rule changes form, move the old string to\n * LEGACY_GUARD_PERMISSION_DENY_RULES so install/uninstall clean it up.\n */\nexport const GUARD_PERMISSION_DENY_RULES: readonly string[] = PERMISSION_DENY_PATHS.map(\n (p) => `Edit(${p})`\n);\n\n/** Rule strings shipped by previous versions, no longer canonical. */\nexport const LEGACY_GUARD_PERMISSION_DENY_RULES: readonly string[] = [];\n\nexport interface PermissionRulesResult {\n addedRules: string[];\n removedStaleRules: string[];\n changed: boolean;\n}\n\nfunction readDenyRules(settings: ClaudeSettings, settingsPath: string): string[] {\n const permissions = settings.permissions;\n if (\n permissions !== undefined &&\n (typeof permissions !== 'object' || Array.isArray(permissions) || permissions === null)\n ) {\n throw new Error(`${settingsPath}: \"permissions\" is not an object — refusing to rewrite it.`);\n }\n const deny = permissions?.deny;\n if (deny === undefined) return [];\n if (!Array.isArray(deny) || deny.some((r) => typeof r !== 'string')) {\n throw new Error(\n `${settingsPath}: \"permissions.deny\" is not an array of strings — refusing to rewrite it.`\n );\n }\n return deny as string[];\n}\n\n/**\n * Merge the guard's permissions.deny rules into a Claude Code settings\n * file. User rules keep their positions; guard rules append at the end;\n * stale (legacy-form) guard rules are dropped. Idempotent; writes only on\n * change. Throws on invalid JSON or a wrong-typed permissions block.\n *\n * These rules live in the very file they protect — mutual reinforcement\n * with the PreToolUse hook, not an independent root of trust.\n */\nexport function installClaudePermissionRules(\n settingsPath: string,\n rules: readonly string[] = GUARD_PERMISSION_DENY_RULES,\n staleRules: readonly string[] = LEGACY_GUARD_PERMISSION_DENY_RULES\n): PermissionRulesResult {\n const settings = readSettings(settingsPath);\n const deny = readDenyRules(settings, settingsPath);\n\n const stale = new Set(staleRules);\n const removedStaleRules = deny.filter((r) => stale.has(r));\n const kept = deny.filter((r) => !stale.has(r));\n\n const present = new Set(kept);\n const addedRules = rules.filter((r) => !present.has(r));\n\n const changed = addedRules.length > 0 || removedStaleRules.length > 0;\n if (changed) {\n settings.permissions = settings.permissions ?? {};\n settings.permissions.deny = [...kept, ...addedRules];\n writeSettings(settingsPath, settings);\n }\n return { addedRules, removedStaleRules, changed };\n}\n\n/**\n * Remove the guard's permissions.deny rules (canonical + legacy forms).\n * Prunes an emptied deny array / permissions object; everything else is\n * untouched. Returns the removed strings — ownership is exact-string\n * match, so a rule the user added independently is removed too; callers\n * should surface the returned list so the user can re-add their own.\n */\nexport function uninstallClaudePermissionRules(\n settingsPath: string,\n rules: readonly string[] = GUARD_PERMISSION_DENY_RULES,\n staleRules: readonly string[] = LEGACY_GUARD_PERMISSION_DENY_RULES\n): string[] {\n if (!existsSync(settingsPath)) return [];\n\n let settings: ClaudeSettings;\n let deny: string[];\n try {\n settings = readSettings(settingsPath);\n deny = readDenyRules(settings, settingsPath);\n } catch {\n return [];\n }\n if (deny.length === 0) return [];\n\n const ours = new Set([...rules, ...staleRules]);\n const removed = deny.filter((r) => ours.has(r));\n if (removed.length === 0) return [];\n\n const remaining = deny.filter((r) => !ours.has(r));\n if (remaining.length > 0) {\n settings.permissions!.deny = remaining;\n } else {\n delete settings.permissions!.deny;\n if (Object.keys(settings.permissions!).length === 0) delete settings.permissions;\n }\n\n writeSettings(settingsPath, settings);\n return removed;\n}\n\n// -----------------------------------------------------------------------\n// Default policy for a coding agent\n// -----------------------------------------------------------------------\n\n/**\n * Hook-layer patterns that keep a governed agent from disabling its own\n * guard by editing the hook config or policy. Effective only when the\n * hook fires AND posture is active — for Claude Code's own settings files\n * that is not sufficient (see GUARD_PERMISSION_DENY_RULES), so the\n * installer pairs these with native permissions.deny rules.\n */\nexport const GUARD_SELF_PROTECTION_PATTERNS = [\n '**/.claude/settings.json',\n '**/.claude/settings.local.json',\n '**/.astrasync/**',\n '**/.codex/hooks.json',\n '**/.codex/config.toml',\n];\n\n/**\n * Ensure an existing policy file's file.write rule carries the guard\n * self-protection patterns (used after the interactive wizard, whose\n * questions don't know about the guard's own files). No-op when the\n * patterns are already present or the file has no file.write rule.\n * Returns true if the file was modified.\n */\nexport function ensureGuardSelfProtection(policyPath: string): boolean {\n const parsed = parseFile(policyPath);\n if (!parsed.validation.valid || !parsed.policy) return false;\n\n const fileWrite = parsed.policy.purposes.find((p) => p.id === 'file.write');\n if (!fileWrite || !fileWrite.allowed) return false;\n\n const existing = new Set(fileWrite.blockedPatterns ?? []);\n const missing = GUARD_SELF_PROTECTION_PATTERNS.filter((p) => !existing.has(p));\n if (missing.length === 0) return false;\n\n fileWrite.blockedPatterns = [...(fileWrite.blockedPatterns ?? []), ...missing];\n writeFileSync(policyPath, toYaml(parsed.policy), 'utf-8');\n return true;\n}\n\n/**\n * Default Local Guard policy for Claude Code.\n *\n * Tuned for a coding agent that already has its own permission layer:\n * - permissive risk preset — HIGH_RISK commands (git push, curl, docker…)\n * surface as \"ask\" (Claude Code's native prompt), never auto-block;\n * - the wizard's recommended blocked commands (sudo, rm -rf, curl|bash…)\n * and credential paths (~/.ssh, ~/.aws, .env…) hard-deny;\n * - guard self-protection patterns hard-deny writes to the guard's own\n * config (backed by native permissions.deny rules for Claude Code's\n * settings files, which the hook alone cannot fully protect);\n * - MCP purposes are intentionally absent: pair with governMcp=false\n * until specific {server}.{tool} rules are added.\n */\nexport function buildDefaultClaudeCodePolicy(name = 'claude-code-local-guard'): LocalPolicy {\n const recommendedCommands = DEFAULT_BLOCKED_COMMANDS.filter((c) => c.recommended).map(\n (c) => c.pattern\n );\n const recommendedPaths = DEFAULT_BLOCKED_PATHS.filter((p) => p.recommended).map((p) => p.pattern);\n const permissive = RISK_PRESETS.find((p) => p.name === 'permissive')!;\n\n return {\n version: '1.0',\n name,\n description:\n 'AstraSync Local Guard for Claude Code — default coding-agent policy. ' +\n 'Edit freely; the hook re-reads this file on every tool call.',\n purposes: [\n {\n id: 'file.read',\n allowed: true,\n blockedPatterns: recommendedPaths,\n },\n {\n id: 'file.write',\n allowed: true,\n blockedPatterns: [...GUARD_SELF_PROTECTION_PATTERNS, ...recommendedPaths],\n },\n {\n id: 'shell.exec',\n allowed: true,\n blockedPatterns: recommendedCommands,\n },\n { id: 'network.request', allowed: true },\n { id: 'sub_agent.spawn', allowed: true },\n ],\n riskThresholds: permissive.thresholds,\n };\n}\n","/**\n * AstraSync Local Guard for Codex CLI — hooks.json installer.\n *\n * Codex reads hooks from ~/.codex/hooks.json (user scope) or\n * <repo>/.codex/hooks.json (project scope) with the SAME JSON shape as\n * Claude Code's settings.json (`hooks.PreToolUse[].hooks[]`), so the merge\n * and uninstall machinery is shared with the Claude Code installer — only\n * the marker, matcher, and file location differ.\n *\n * The policy itself is shared with every other Local Guard adapter on the\n * machine: ~/.astrasync/policy.yaml + guard.json. One policy per user.\n */\n\nimport { installClaudeHooks, uninstallClaudeHooks } from '../claude-code/settings-installer';\nimport type { InstallResult } from '../claude-code/settings-installer';\n\n/** Substring that identifies the guard's hook entry inside hooks.json */\nexport const ASTRASYNC_CODEX_HOOK_MARKER = 'astrasync-codex-hook';\n\n/**\n * Tools worth spawning the hook for. Codex matchers are regexes over\n * tool_name; bookkeeping tools (update_plan) never pay node startup cost.\n */\nexport const CODEX_HOOK_MATCHER = 'Bash|apply_patch|Edit|Write|web_search|mcp__.*';\n\n/** Shown in the Codex TUI while the hook runs. */\nconst CODEX_STATUS_MESSAGE = 'AstraSync Local Guard';\n\n/**\n * Merge the guard's PreToolUse entry into a Codex hooks.json file.\n * Same never-clobber/idempotent semantics as the Claude Code installer.\n */\nexport function installCodexHooks(hooksPath: string, hookCommand: string): InstallResult {\n return installClaudeHooks(\n hooksPath,\n hookCommand,\n ASTRASYNC_CODEX_HOOK_MARKER,\n CODEX_HOOK_MATCHER,\n {\n statusMessage: CODEX_STATUS_MESSAGE,\n }\n );\n}\n\n/** Remove the guard's PreToolUse entry from a Codex hooks.json file. */\nexport function uninstallCodexHooks(hooksPath: string): boolean {\n return uninstallClaudeHooks(hooksPath, ASTRASYNC_CODEX_HOOK_MARKER);\n}\n"],"mappings":";;;;;;;;AAsEO,IAAM,4BAA4B;;;AC1DzC,IAAM,mBAA2C;AAAA;AAAA,EAE/C,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,SAAS;AAAA,EACT,eAAe;AAAA,EACf,sBAAsB;AAAA;AAAA,EAGtB,WAAW;AAAA,EACX,WAAW;AAAA;AAAA,EAGX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,WAAW;AAAA;AAAA,EAGX,aAAa;AAAA,EACb,aAAa;AAAA;AAAA,EAGb,cAAc;AAAA,EACd,OAAO;AAAA,EACP,aAAa;AAAA;AAAA,EAGb,YAAY;AAAA,EACZ,YAAY;AAAA;AAAA,EAGZ,cAAc;AAAA;AAAA,EAGd,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAGhB,iBAAiB;AACnB;AAMO,SAAS,iBAAiB,UAA0B;AACzD,SAAO,iBAAiB,QAAQ,KAAK,QAAQ,QAAQ;AACvD;AAMO,SAAS,qBAAqB,UAAwC;AAC3E,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACtD,QAAI,EAAE,QAAQ,mBAAmB;AAC/B,uBAAiB,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AACF;AAUO,SAAS,cAAc,UAAkB,MAAuC;AACrF,QAAM,UAAU,iBAAiB,QAAQ;AAEzC,MAAI,QAAQ,WAAW,QAAQ,GAAG;AAChC,WAAO,OAAO,KAAK,WAAW,KAAK,OAAO,KAAK,UAAU,EAAE;AAAA,EAC7D;AAEA,MAAI,QAAQ,WAAW,OAAO,GAAG;AAC/B,WAAO,OAAO,KAAK,QAAQ,KAAK,QAAQ,KAAK,YAAY,KAAK,aAAa,EAAE;AAAA,EAC/E;AAEA,MAAI,QAAQ,WAAW,UAAU,GAAG;AAClC,WAAO,OAAO,KAAK,OAAO,KAAK,YAAY,KAAK,OAAO,EAAE;AAAA,EAC3D;AAEA,MAAI,QAAQ,WAAW,QAAQ,GAAG;AAChC,WAAO,OAAO,KAAK,MAAM,KAAK,aAAa,KAAK,WAAW,EAAE;AAAA,EAC/D;AAEA,MAAI,QAAQ,WAAW,WAAW,GAAG;AACnC,WAAO,OAAO,KAAK,SAAS,KAAK,SAAS,EAAE;AAAA,EAC9C;AAEA,MAAI,QAAQ,WAAW,UAAU,GAAG;AAClC,WAAO,OAAO,KAAK,eAAe,KAAK,YAAY,KAAK,UAAU,EAAE;AAAA,EACtE;AAGA,MAAI,KAAK,QAAS,QAAO,OAAO,KAAK,OAAO;AAC5C,MAAI,KAAK,KAAM,QAAO,OAAO,KAAK,IAAI;AACtC,MAAI,KAAK,IAAK,QAAO,OAAO,KAAK,GAAG;AAGpC,aAAW,OAAO,OAAO,OAAO,IAAI,GAAG;AACrC,QAAI,OAAO,QAAQ,YAAY,IAAI,SAAS,EAAG,QAAO;AAAA,EACxD;AACA,SAAO;AACT;AAUO,SAAS,sBAAsB,QAAsC;AAC1E,MAAI;AACF,QAAI,OAAO,WAAW,SAAS,KAAK,OAAO,WAAW,UAAU,GAAG;AACjE,YAAM,MAAM,IAAI,IAAI,MAAM;AAC1B,aAAO,CAAC,IAAI,QAAQ;AAAA,IACtB;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;;;AC5FO,SAAS,WAAW,UAAiC;AAC1D,QAAM,QAAQ,qBAAqB,KAAK,QAAQ;AAChD,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,GAAG,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AAChC;;;AClCO,IAAM,iBAAyC;AAAA,EACpD,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,EACN,OAAO;AAAA,EACP,YAAY;AACd;AAEA,IAAI,aAAa;AAMV,SAAS,wBAA8B;AAC5C,MAAI,WAAY;AAChB,uBAAqB,cAAc;AACnC,eAAa;AACf;AAQO,SAAS,uBAAuB,WAA6B;AAClE,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK;AACX,MAAI;AACJ,UAAQ,QAAQ,GAAG,KAAK,SAAS,OAAO,MAAM;AAC5C,UAAM,IAAI,MAAM,CAAC,EAAE,KAAK;AACxB,QAAI,EAAG,OAAM,KAAK,CAAC;AAAA,EACrB;AACA,SAAO;AACT;;;AC+BO,IAAM,8BAA8B,oBAAI,IAAI,CAAC,WAAW,mBAAmB,CAAC;AAO5E,IAAM,qBAAqB,CAAC,aAAa;AAwBzC,IAAM,eAAN,MAA8C;AAAA,EASnD,YAAY,SAA+B;AAR3C,SAAS,mBAAmB;AAM5B,SAAQ,aAAa;AAGnB,SAAK,YAAY,IAAI,IAAI,SAAS,aAAa,kBAAkB;AACjE,SAAK,iBAAiB,SAAS,kBAAkB;AACjD,SAAK,YAAY,SAAS,aAAa;AACvC,0BAAsB;AAAA,EACxB;AAAA,EAEA,IAAI,YAAqB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,WAAW,QAAsC;AACrD,SAAK,UAAU,OAAO;AAEtB,QAAI,MAAM,QAAQ,OAAO,eAAe,SAAS,GAAG;AAClD,WAAK,YAAY,IAAI,IAAI,OAAO,eAAe,SAAqB;AAAA,IACtE;AACA,QAAI,OAAO,OAAO,eAAe,mBAAmB,WAAW;AAC7D,WAAK,iBAAiB,OAAO,eAAe;AAAA,IAC9C;AAEA,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAM,WAA0B;AAC9B,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAM,gBAAgB,QAA+C;AACnE,UAAM,MAAM,OAAO;AAEnB,QAAI,CAAC,OAAO,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,WAAW,GAAG;AAC3E,aAAO,EAAE,aAAa,OAAO,YAAY,0BAA0B;AAAA,IACrE;AAEA,QAAI,KAAK,UAAU,IAAI,IAAI,SAAS,GAAG;AACrC,aAAO,EAAE,aAAa,OAAO,YAAY,QAAQ,IAAI,SAAS,mBAAmB;AAAA,IACnF;AAEA,UAAM,QAAQ,WAAW,IAAI,SAAS,MAAM;AAC5C,QAAI,SAAS,CAAC,KAAK,WAAW;AAC5B,aAAO,EAAE,aAAa,OAAO,YAAY,yCAAyC;AAAA,IACpF;AAEA,UAAM,WAAW,IAAI,aAAa,kBAAkB;AACpD,QAAI,CAAC,YAAY,CAAC,KAAK,gBAAgB;AACrC,aAAO;AAAA,QACL,aAAa;AAAA,QACb,YAAY,iBAAiB,IAAI,SAAS;AAAA,MAC5C;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,eAAe,MAAM;AAC1C,WAAO,EAAE,aAAa,MAAM,QAAQ;AAAA,EACtC;AAAA,EAEA,eAAe,QAAmC;AAChD,UAAM,MAAM,OAAO;AACnB,WAAO,KAAK,aAAa,KAAK,cAAc,IAAI,WAAW,IAAI,cAAc,CAAC,CAAC,CAAC;AAAA,EAClF;AAAA,EAEQ,aAAa,KAA6B,QAA8B;AAC9E,UAAM,WAAW,IAAI;AACrB,UAAM,aAAa,WAAW,QAAQ;AACtC,UAAM,UAAU,cAAc,iBAAiB,QAAQ;AACvD,UAAM,gBAAgB,sBAAsB,MAAM;AAElD,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA,GAAI,iBAAiB,EAAE,cAAc;AAAA,MACrC,UAAU;AAAA,QACR,GAAI,IAAI,cAAc,EAAE,WAAW,IAAI,WAAW;AAAA,QAClD,GAAI,IAAI,OAAO,EAAE,KAAK,IAAI,IAAI;AAAA,QAC9B,GAAI,IAAI,mBAAmB,EAAE,gBAAgB,IAAI,gBAAgB;AAAA,QACjE,GAAI,IAAI,SAAS,EAAE,OAAO,IAAI,MAAM;AAAA,QACpC,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,qBACE,UACA,gBACwB;AACxB,YAAQ,SAAS,gBAAgB;AAAA,MAC/B,KAAK;AACH,eAAO;AAAA,UACL,oBAAoB;AAAA,YAClB,eAAe;AAAA,YACf,oBAAoB;AAAA,YACpB,0BAA0B,0BAA0B,SAAS,MAAM;AAAA,UACrE;AAAA,QACF;AAAA,MACF,KAAK;AACH,YAAI,kBAAkB,4BAA4B,IAAI,cAAc,GAAG;AACrE,iBAAO;AAAA,YACL,oBAAoB;AAAA,cAClB,eAAe;AAAA,cACf,oBAAoB;AAAA,cACpB,0BACE,4CAA4C,SAAS,MAAM,2CACxB,cAAc;AAAA,YAErD;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBAAgB,SAAkE;AACtF,UAAM,SAAsB;AAAA,MAC1B,KAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAW,oBAAI,KAAK;AAAA,IACtB;AAEA,UAAM,eAAe,MAAM,KAAK,gBAAgB,MAAM;AACtD,QAAI,CAAC,aAAa,eAAe,CAAC,aAAa,SAAS;AAGtD,WAAK,QAAQ,eAAe,QAAQ,WAAW,aAAa,cAAc,iBAAiB;AAC3F,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,MAAM,KAAK,2BAA2B,SAAS,aAAa,OAAO;AACpF,WAAO,KAAK,qBAAqB,UAAU,QAAQ,eAAe;AAAA,EACpE;AAAA,EAEA,MAAc,2BACZ,SACA,SAC+B;AAC/B,UAAM,YACJ,QAAQ,cAAc,gBAClB;AAAA,MACG,QAAQ,YAAwC,WAC9C,QAAQ,YAAwC,SACjD;AAAA,IACJ,IACA;AACN,UAAM,aAAa,YAAY,uBAAuB,SAAS,IAAI,CAAC;AAEpE,QAAI,WAAW,WAAW,GAAG;AAC3B,aAAO,KAAK,QAAQ,SAAS,OAAO;AAAA,IACtC;AAGA,QAAI,QAAqC;AACzC,UAAM,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,MAAM,EAAE;AACnD,eAAW,QAAQ,YAAY;AAC7B,YAAM,WAAW,MAAM,KAAK,QAAQ,SAAS,KAAK,aAAa,SAAS,IAAI,CAAC;AAC7E,UAAI,CAAC,SAAS,KAAK,SAAS,cAAc,IAAI,KAAK,MAAM,cAAc,GAAG;AACxE,gBAAQ;AAAA,MACV;AACA,UAAI,MAAM,mBAAmB,OAAQ;AAAA,IACvC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBAAgB,WAAgD;AAAA,EAEtE;AACF;;;ACpSA,SAAS,WAAAA,gBAAe;AACxB,SAAS,QAAAC,aAAY;;;ACmLd,IAAM,qBAAqB;AAAA,EAChC;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;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,kBAAkB;AAAA,EAC7B;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;;;AC/NA,IAAM,WAAW,oBAAI,IAAI;AAAA,EACvB;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,CAAC;AAGD,IAAM,YAAY;AAElB,IAAM,mBAAmB;AACzB,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB;AAG3B,IAAM,gBAAgB;AAQtB,SAAS,cAAc,SAAsC;AAC3D,QAAM,aAAa,oBAAI,IAAY;AACnC,QAAM,YAAwB,CAAC;AAC/B,aAAW,SAAS,SAAS;AAC3B,UAAM,QAAQ,MAAM,YAAY,EAAE,KAAK,EAAE,MAAM,KAAK;AACpD,QAAI,MAAM,WAAW,EAAG,YAAW,IAAI,MAAM,CAAC,CAAC;AAAA,QAC1C,WAAU,KAAK,KAAK;AAAA,EAC3B;AACA,YAAU,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC5C,SAAO,EAAE,YAAY,UAAU;AACjC;AAGA,SAAS,mBAAmB,MAAsB;AAChD,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,OAAiB,CAAC;AACxB,MAAI,aAA4B;AAChC,aAAW,QAAQ,OAAO;AACxB,QAAI,eAAe,MAAM;AACvB,UAAI,KAAK,KAAK,MAAM,WAAY,cAAa;AAC7C;AAAA,IACF;AACA,SAAK,KAAK,IAAI;AACd,UAAM,UAAU,KAAK,MAAM,wBAAwB;AACnD,QAAI,QAAS,cAAa,QAAQ,CAAC;AAAA,EACrC;AACA,SAAO,KAAK,KAAK,IAAI;AACvB;AAOA,SAAS,2BAA2B,MAAc,SAA0C;AAC1F,MAAI,SAAS;AACb,MAAI,QAAQ,OAAO,QAAQ,IAAI;AAC/B,MAAI,aAAa;AACjB,SAAO,UAAU,MAAM,aAAa,IAAI;AACtC;AACA,QAAI,QAAQ;AACZ,QAAI,MAAM,OAAO;AACjB,aAAS,IAAI,QAAQ,GAAG,IAAI,OAAO,QAAQ,KAAK;AAC9C,UAAI,OAAO,CAAC,MAAM,IAAK;AAAA,eACd,OAAO,CAAC,MAAM,KAAK;AAC1B;AACA,YAAI,UAAU,GAAG;AACf,gBAAM;AACN;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,YAAQ,OAAO,MAAM,QAAQ,GAAG,GAAG,CAAC;AACpC,aAAS,GAAG,OAAO,MAAM,GAAG,KAAK,CAAC,IAAI,OAAO,MAAM,KAAK,IAAI,MAAM,GAAG,OAAO,MAAM,CAAC,CAAC;AACpF,YAAQ,OAAO,QAAQ,IAAI;AAAA,EAC7B;AACA,SAAO;AACT;AAGA,SAAS,6BAA6B,MAAc,SAA0C;AAC5F,MAAI,CAAC,KAAK,SAAS,GAAG,EAAG,QAAO;AAChC,QAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QAAM,OAAiB,CAAC;AACxB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,QAAI,IAAI,MAAM,EAAG,SAAQ,OAAO,CAAC,CAAC;AAAA,QAC7B,MAAK,KAAK,OAAO,CAAC,CAAC;AAAA,EAC1B;AACA,SAAO,KAAK,KAAK,GAAG;AACtB;AAQA,SAAS,SAAS,OAAuB;AACvC,QAAM,QAAQ,KAAK,IAAI,MAAM,YAAY,GAAG,GAAG,MAAM,YAAY,IAAI,CAAC;AACtE,QAAM,OAAO,UAAU,KAAK,QAAQ,MAAM,MAAM,QAAQ,CAAC;AACzD,SAAO,KAAK,QAAQ,yBAAyB,EAAE;AACjD;AAEA,SAAS,aAAa,SAAiB,MAA+B;AACpE,QAAM,SAAS,QAAQ,MAAM,KAAK,EAAE,OAAO,CAAC,MAAM,WAAW,KAAK,CAAC,CAAC;AACpE,MAAI,IAAI;AACR,MAAI,OAAO;AACX,SAAO,IAAI,OAAO,QAAQ;AAExB,WAAO,IAAI,OAAO,WAAW,OAAO,CAAC,MAAM,YAAY,UAAU,KAAK,OAAO,CAAC,CAAC,GAAI;AACnF,QAAI,KAAK,OAAO,OAAQ,QAAO;AAE/B,UAAM,MAAM,SAAS,OAAO,CAAC,CAAC;AAG9B,UAAM,cAAc,CAAC,KAAK,GAAG,OAAO,MAAM,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC;AAClF,eAAW,SAAS,KAAK,WAAW;AAClC,UAAI,MAAM,UAAU,YAAY,UAAU,MAAM,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,GAAG;AACrF,eAAO,MAAM,KAAK,GAAG;AAAA,MACvB;AAAA,IACF;AACA,QAAI,KAAK,WAAW,IAAI,GAAG,EAAG,QAAO;AAGrC,QAAI,SAAS,IAAI,GAAG,KAAK,OAAO,kBAAkB;AAChD;AACA;AACA,aAAO,IAAI,OAAO,WAAW,OAAO,CAAC,EAAE,WAAW,GAAG,KAAK,UAAU,KAAK,OAAO,CAAC,CAAC,GAAI;AACtF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,eACP,SACA,MACA,SACA,OACM;AACN,MAAI,QAAQ,uBAAuB,QAAQ,SAAS,mBAAoB;AAExE,MAAI,OAAO,QAAQ,YAAY;AAC/B,SAAO,mBAAmB,IAAI;AAI9B,QAAM,UAAU,CAAC,UAAkB,eAAe,OAAO,MAAM,SAAS,QAAQ,CAAC;AACjF,SAAO,2BAA2B,MAAM,OAAO;AAC/C,SAAO,6BAA6B,MAAM,OAAO;AAGjD,SAAO,KAAK,QAAQ,YAAY,GAAG,EAAE,QAAQ,YAAY,GAAG;AAC5D,SAAO,KAAK,QAAQ,kBAAkB,GAAG;AAEzC,QAAM,WAAW,KAAK,MAAM,sBAAsB;AAClD,aAAW,WAAW,UAAU;AAC9B,UAAM,UAAU,aAAa,SAAS,IAAI;AAC1C,QAAI,QAAS,SAAQ,IAAI,OAAO;AAAA,EAClC;AACF;AAMO,SAAS,sBACd,SACA,mBAAsC,oBAC5B;AACV,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,QAAM,UAAU,oBAAI,IAAY;AAChC,iBAAe,SAAS,cAAc,gBAAgB,GAAG,SAAS,CAAC;AACnE,SAAO,CAAC,GAAG,OAAO;AACpB;AAmBO,SAAS,8BAA8B,SAA0B;AACtE,QAAM,OAAO,QAAQ,YAAY;AAEjC,QAAM,SAAS,KAAK,MAAM,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,uBAAuB,EAAE,CAAC;AAChF,MAAI,aAAa;AACjB,aAAW,SAAS,QAAQ;AAC1B,QAAI,OAAsB;AAC1B,QAAI,MAAM,SAAS,KAAK,GAAG;AACzB,UAAI,OAAO,MAAM,MAAM,MAAM,QAAQ,KAAK,IAAI,CAAC;AAC/C,YAAM,KAAK,KAAK,QAAQ,GAAG;AAC3B,UAAI,OAAO,GAAI,QAAO,KAAK,MAAM,KAAK,CAAC;AACvC,aAAO,KAAK,MAAM,OAAO,EAAE,CAAC;AAAA,IAC9B,WAAW,+BAA+B,KAAK,KAAK,GAAG;AACrD,aAAO,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,IAC3B,WAAW,8CAA8C,KAAK,KAAK,GAAG;AACpE,aAAO,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,IAC3B;AACA,QAAI,SAAS,KAAM;AAEnB,UAAM,OAAO,KAAK,QAAQ,SAAS,EAAE,EAAE,QAAQ,YAAY,EAAE;AAC7D,QAAI,cAAc,KAAK,IAAI,GAAG;AAC5B;AAAA,IACF,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,aAAa;AACtB;;;ACjOO,IAAM,iBAAN,MAAqB;AAAA,EAI1B,YAAY,QAAqB;AAFjC,SAAQ,gBAAqE,oBAAI,IAAI;AAGnF,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,QAA2B;AACtC,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,SAA6C;AAEpD,UAAM,cAAc,KAAK,OAAO,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ,OAAO;AAC7E,QAAI,CAAC,aAAa;AAChB,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,wBAAwB;AAAA,IACnE;AACA,QAAI,CAAC,YAAY,SAAS;AACxB,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,6BAA6B;AAAA,IACxE;AAGA,QAAI,YAAY,WAAW,CAAC,KAAK,kBAAkB,QAAQ,QAAQ,YAAY,OAAO,GAAG;AACvF,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,6BAA6B;AAAA,IACxE;AAGA,QACE,YAAY,mBACZ,KAAK,kBAAkB,QAAQ,QAAQ,YAAY,eAAe,GAClE;AACA,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,iCAAiC;AAAA,IAC5E;AAGA,UAAM,aAAa,KAAK,gBAAgB,OAAO;AAC/C,QAAI,YAAY;AACd,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,WAAW;AAAA,IACtD;AAGA,UAAM,gBAAgB,KAAK,YAAY,OAAO;AAC9C,QAAI,eAAe;AACjB,aAAO;AAAA,IACT;AAGA,QAAI,QAAQ,YAAY,qBAAqB,KAAK,OAAO,mBAAmB;AAC1E,UAAI,CAAC,KAAK,OAAO,kBAAkB,SAAS;AAC1C,eAAO,EAAE,gBAAgB,QAAQ,QAAQ,oCAAoC;AAAA,MAC/E;AACA,YAAM,QAAS,QAAQ,UAAU,iBAA4B;AAC7D,UACE,KAAK,OAAO,kBAAkB,aAAa,UAC3C,SAAS,KAAK,OAAO,kBAAkB,UACvC;AACA,eAAO;AAAA,UACL,gBAAgB;AAAA,UAChB,QAAQ,mBAAmB,KAAK,sBAAsB,KAAK,OAAO,kBAAkB,QAAQ;AAAA,QAC9F;AAAA,MACF;AAAA,IACF;AAGA,QAAI,YAAY,kBAAkB;AAChC,aAAO,EAAE,gBAAgB,iBAAiB,QAAQ,4BAA4B;AAAA,IAChF;AAEA,UAAM,eAAe,KAAK,oBAAoB,OAAO;AACrD,QAAI,cAAc;AAChB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,gBAAgB;AAAA;AAAA;AAAA,MAGhB,QAAQ;AAAA,MACR,qBAAqB;AAAA,QACnB,SAAS;AAAA,QACT,OAAO,CAAC,CAAC,KAAK,OAAO;AAAA,QACrB,QAAQ,CAAC,CAAC,KAAK,OAAO;AAAA,QACtB,gBAAgB,CAAC,CAAC,KAAK,OAAO;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAAgB,SAAsC;AAC5D,UAAM,QAAQ,KAAK,OAAO;AAC1B,QAAI,CAAC,MAAO,QAAO;AAGnB,QAAI,MAAM,gBAAgB;AACxB,YAAM,eAAe,KAAK,cAAc,QAAQ,MAAM;AACtD,UAAI,KAAK,kBAAkB,cAAc,MAAM,cAAc,GAAG;AAC9D,eAAO,4BAA4B,QAAQ,MAAM;AAAA,MACnD;AACA,UAAI,QAAQ,eAAe;AACzB,mBAAW,UAAU,QAAQ,eAAe;AAC1C,cAAI,KAAK,kBAAkB,KAAK,cAAc,MAAM,GAAG,MAAM,cAAc,GAAG;AAC5E,mBAAO,4BAA4B,MAAM;AAAA,UAC3C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,MAAM,oBAAoB,KAAK,kBAAkB,QAAQ,QAAQ,MAAM,gBAAgB,GAAG;AAC5F,aAAO,8BAA8B,QAAQ,MAAM;AAAA,IACrD;AAGA,QAAI,MAAM,kBAAkB,QAAQ,eAAe;AACjD,iBAAW,UAAU,QAAQ,eAAe;AAC1C,YAAI,CAAC,KAAK,kBAAkB,KAAK,cAAc,MAAM,GAAG,MAAM,cAAc,GAAG;AAC7E,iBAAO,+BAA+B,MAAM;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,YAAY,SAAoD;AACtE,UAAM,SAAS,KAAK,OAAO;AAC3B,QAAI,CAAC,OAAQ,QAAO;AAWpB,UAAM,QAAQ,QAAQ;AACtB,QACE,UAAU,UACV,QAAQ,MACP,OAAO,wBAAwB,UAAa,OAAO,yBAAyB,SAC7E;AACA,YAAM,sBAAsB,OAAO,uBAAuB;AAC1D,YAAM,YAAY,OAAO,wBAAwB,OAAO,uBAAuB;AAC/E,UAAI,QAAQ,qBAAqB;AAC/B,YAAI,SAAS,WAAW;AACtB,iBAAO;AAAA,YACL,gBAAgB;AAAA,YAChB,QAAQ,qBAAqB,KAAK,2BAA2B,SAAS;AAAA,UACxE;AAAA,QACF;AACA,eAAO;AAAA,UACL,gBAAgB;AAAA,UAChB,QAAQ,qBAAqB,KAAK,mCAAmC,mBAAmB,KAAK,SAAS;AAAA,QACxG;AAAA,MACF;AAAA,IACF;AAGA,QAAI,OAAO,uBAAuB,QAAW;AAC3C,YAAM,MAAM,QAAQ;AACpB,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,QAAQ,KAAK,cAAc,IAAI,GAAG;AACxC,YAAM,SAAS;AAEf,UAAI,CAAC,SAAS,MAAM,MAAM,cAAc,QAAQ;AAC9C,aAAK,cAAc,IAAI,KAAK,EAAE,OAAO,GAAG,aAAa,IAAI,CAAC;AAAA,MAC5D,OAAO;AACL,cAAM;AACN,YAAI,MAAM,QAAQ,OAAO,oBAAoB;AAC3C,iBAAO;AAAA,YACL,gBAAgB;AAAA,YAChB,QAAQ,wBAAwB,MAAM,KAAK,IAAI,OAAO,kBAAkB;AAAA,UAC1E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,oBAAoB,SAAoD;AAC9E,QAAI,CAAC,KAAK,OAAO,eAAgB,QAAO;AAExC,UAAM,YAAY,KAAK,mBAAmB,OAAO;AACjD,UAAM,aAAa,KAAK,OAAO;AAE/B,QAAI,aAAa,WAAW,UAAU,KAAK;AACzC,aAAO,EAAE,gBAAgB,QAAQ,QAAQ,cAAc,SAAS,2BAA2B;AAAA,IAC7F;AAEA,QAAI,aAAa,WAAW,gBAAgB,KAAK;AAC/C,aAAO;AAAA,QACL,gBAAgB;AAAA,QAChB,QAAQ,cAAc,SAAS;AAAA,MACjC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAmB,SAA+B;AACxD,QAAI,QAAQ;AAGZ,QAAI,QAAQ,aAAa,QAAQ;AAC/B,YAAM,iBAAyC;AAAA,QAC7C,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,UAAU;AAAA,MACZ;AAEA,iBAAW,UAAU,QAAQ,aAAa;AACxC,cAAM,cAAc,eAAe,OAAO,QAAQ,KAAK;AACvD,YAAI,cAAc,MAAO,SAAQ;AAAA,MACnC;AACA,aAAO;AAAA,IACT;AAKA,QAAI,QAAQ,YAAY,gBAAgB,QAAQ,QAAQ;AACtD,YAAM,UAAU,sBAAsB,QAAQ,MAAM;AACpD,YAAM,iBACJ,QAAQ,SAAS,KACjB,QAAQ,MAAM,CAAC,QAAQ,QAAQ,UAAU,QAAQ,MAAM,KACvD,8BAA8B,QAAQ,MAAM;AAC9C,UAAI,QAAQ,SAAS,KAAK,CAAC,gBAAgB;AACzC,gBAAQ,KAAK,IAAI,OAAO,EAAE;AAAA,MAC5B;AAAA,IACF;AAKA,SACG,QAAQ,YAAY,eACnB,QAAQ,YAAY,gBACpB,QAAQ,YAAY,kBACtB,QAAQ,QACR;AACA,YAAM,cAAc,QAAQ,OAAO,YAAY,EAAE,QAAQ,OAAO,GAAG;AACnE,iBAAW,iBAAiB,iBAAiB;AAC3C,YAAI,YAAY,SAAS,cAAc,YAAY,CAAC,GAAG;AACrD,kBAAQ,KAAK,IAAI,OAAO,EAAE;AAC1B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,OAAuB;AAC3C,QAAI,SAAS;AAEb,UAAM,aAAa,OAAO,QAAQ,KAAK;AACvC,QAAI,eAAe,GAAI,UAAS,OAAO,MAAM,aAAa,CAAC;AAE3D,UAAM,aAAa,OAAO,QAAQ,GAAG;AACrC,QAAI,eAAe,GAAI,UAAS,OAAO,MAAM,GAAG,UAAU;AAE1D,UAAM,aAAa,OAAO,QAAQ,GAAG;AACrC,QAAI,eAAe,GAAI,UAAS,OAAO,MAAM,GAAG,UAAU;AAC1D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB,OAAe,UAA6B;AACpE,WAAO,SAAS,KAAK,CAAC,YAAY,KAAK,UAAU,OAAO,OAAO,CAAC;AAAA,EAClE;AAAA,EAgBQ,aAA4B;AAClC,QAAI,KAAK,qBAAqB,OAAW,QAAO,KAAK;AACrD,UAAM,MAAM,OAAO,YAAY,cAAc,QAAQ,MAAM;AAC3D,UAAM,OAAO,KAAK,QAAQ,KAAK;AAC/B,SAAK,mBAAmB,OAAO,KAAK,QAAQ,OAAO,GAAG,IAAI;AAC1D,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,UAAU,OAAe,SAA0B;AASzD,YAAQ,MAAM,QAAQ,OAAO,GAAG;AAChC,cAAU,QAAQ,QAAQ,OAAO,GAAG;AACpC,QAAI,YAAY,OAAO,QAAQ,WAAW,IAAI,GAAG;AAC/C,YAAM,OAAO,KAAK,WAAW;AAC7B,UAAI,KAAM,WAAU,OAAO,QAAQ,MAAM,CAAC;AAAA,IAC5C;AAGA,QAAI,YAAY,MAAO,QAAO;AAQ9B,UAAM,aAAa,QAAQ,MAAM,KAAK,KAAK,CAAC,GAAG;AAC/C,QAAI,YAAY,GAAG;AACjB,aAAO;AAAA,IACT;AAGA,UAAM,WAAW,QACd,QAAQ,qBAAqB,MAAM,EACnC,QAAQ,OAAO,IAAI,EACnB,QAAQ,OAAO,GAAG;AAErB,QAAI;AACF,aAAO,IAAI,OAAO,IAAI,QAAQ,KAAK,GAAG,EAAE,KAAK,KAAK;AAAA,IACpD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;;;;;;;;;;;ACpXA,WAAS,UAAW,SAAS;AAC3B,WAAQ,OAAO,YAAY,eAAiB,YAAY;EAC1D;AAEA,WAAS,SAAU,SAAS;AAC1B,WAAQ,OAAO,YAAY,YAAc,YAAY;EACvD;AAEA,WAAS,QAAS,UAAU;AAC1B,QAAI,MAAM,QAAQ,QAAQ,EAAG,QAAO;aAC3B,UAAU,QAAQ,EAAG,QAAO,CAAA;AAErC,WAAO,CAAC,QAAQ;EAClB;AAEA,WAAS,OAAQ,QAAQ,QAAQ;AAC/B,QAAI,QAAQ;AACV,YAAM,aAAa,OAAO,KAAK,MAAM;AAErC,eAAS,QAAQ,GAAG,SAAS,WAAW,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AAC1E,cAAM,MAAM,WAAW,KAAK;AAC5B,eAAO,GAAG,IAAI,OAAO,GAAG;MAC9B;IACA;AAEE,WAAO;EACT;AAEA,WAAS,OAAQ,QAAQ,OAAO;AAC9B,QAAI,SAAS;AAEb,aAAS,QAAQ,GAAG,QAAQ,OAAO,SAAS,GAAG;AAC7C,gBAAU;IACd;AAEE,WAAO;EACT;AAEA,WAAS,eAAgB,QAAQ;AAC/B,WAAQ,WAAW,KAAO,OAAO,sBAAsB,IAAI;EAC7D;AAEA,SAAA,YAA2B;AAC3B,SAAA,WAA0B;AAC1B,SAAA,UAAyB;AACzB,SAAA,SAAwB;AACxB,SAAA,iBAAgC;AAChC,SAAA,SAAwB;;;;;;;;AC7CxB,WAAS,YAAaC,YAAW,SAAS;AACxC,QAAI,QAAQ;AACZ,UAAM,UAAUA,WAAU,UAAU;AAEpC,QAAI,CAACA,WAAU,KAAM,QAAO;AAE5B,QAAIA,WAAU,KAAK,MAAM;AACvB,eAAS,SAASA,WAAU,KAAK,OAAO;IAC5C;AAEE,aAAS,OAAOA,WAAU,KAAK,OAAO,KAAK,OAAOA,WAAU,KAAK,SAAS,KAAK;AAE/E,QAAI,CAAC,WAAWA,WAAU,KAAK,SAAS;AACtC,eAAS,SAASA,WAAU,KAAK;IACrC;AAEE,WAAO,UAAU,MAAM;EACzB;AAEA,WAASC,eAAe,QAAQ,MAAM;AAEpC,UAAM,KAAK,IAAI;AAEf,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,UAAU,YAAY,MAAM,KAAK;AAGtC,QAAI,MAAM,mBAAmB;AAE3B,YAAM,kBAAkB,MAAM,KAAK,WAAW;IAClD,OAAS;AAEL,WAAK,QAAS,IAAI,MAAK,EAAI,SAAS;IACxC;EACA;AAGAA,iBAAc,YAAY,OAAO,OAAO,MAAM,SAAS;AACvDA,iBAAc,UAAU,cAAcA;AAEtCA,iBAAc,UAAU,WAAW,SAAS,SAAU,SAAS;AAC7D,WAAO,KAAK,OAAO,OAAO,YAAY,MAAM,OAAO;EACrD;AAEA,cAAiBA;;;;;;;;AChDjB,QAAMC,UAASC,cAAA;AAGf,WAAS,QAAS,QAAQ,WAAW,SAAS,UAAU,eAAe;AACrE,QAAI,OAAO;AACX,QAAI,OAAO;AACX,UAAM,gBAAgB,KAAK,MAAM,gBAAgB,CAAC,IAAI;AAEtD,QAAI,WAAW,YAAY,eAAe;AACxC,aAAO;AACP,kBAAY,WAAW,gBAAgB,KAAK;IAChD;AAEE,QAAI,UAAU,WAAW,eAAe;AACtC,aAAO;AACP,gBAAU,WAAW,gBAAgB,KAAK;IAC9C;AAEE,WAAO;MACL,KAAK,OAAO,OAAO,MAAM,WAAW,OAAO,EAAE,QAAQ,OAAO,QAAG,IAAI;MACnE,KAAK,WAAW,YAAY,KAAK;;IACrC;EACA;AAEA,WAAS,SAAU,QAAQ,KAAK;AAC9B,WAAOD,QAAO,OAAO,KAAK,MAAM,OAAO,MAAM,IAAI;EACnD;AAEA,WAAS,YAAa,MAAM,SAAS;AACnC,cAAU,OAAO,OAAO,WAAW,IAAI;AAEvC,QAAI,CAAC,KAAK,OAAQ,QAAO;AAEzB,QAAI,CAAC,QAAQ,UAAW,SAAQ,YAAY;AAC5C,QAAI,OAAO,QAAQ,WAAW,SAAU,SAAQ,SAAS;AACzD,QAAI,OAAO,QAAQ,gBAAgB,SAAU,SAAQ,cAAc;AACnE,QAAI,OAAO,QAAQ,eAAe,SAAU,SAAQ,aAAa;AAEjE,UAAM,KAAK;AACX,UAAM,aAAa,CAAC,CAAC;AACrB,UAAM,WAAW,CAAA;AACjB,QAAI;AACJ,QAAI,cAAc;AAElB,WAAQ,QAAQ,GAAG,KAAK,KAAK,MAAM,GAAI;AACrC,eAAS,KAAK,MAAM,KAAK;AACzB,iBAAW,KAAK,MAAM,QAAQ,MAAM,CAAC,EAAE,MAAM;AAE7C,UAAI,KAAK,YAAY,MAAM,SAAS,cAAc,GAAG;AACnD,sBAAc,WAAW,SAAS;MACxC;IACA;AAEE,QAAI,cAAc,EAAG,eAAc,WAAW,SAAS;AAEvD,QAAI,SAAS;AACb,UAAM,eAAe,KAAK,IAAI,KAAK,OAAO,QAAQ,YAAY,SAAS,MAAM,EAAE,SAAQ,EAAG;AAC1F,UAAM,gBAAgB,QAAQ,aAAa,QAAQ,SAAS,eAAe;AAE3E,aAAS,IAAI,GAAG,KAAK,QAAQ,aAAa,KAAK;AAC7C,UAAI,cAAc,IAAI,EAAG;AACzB,YAAME,QAAO;QACX,KAAK;QACL,WAAW,cAAc,CAAC;QAC1B,SAAS,cAAc,CAAC;QACxB,KAAK,YAAY,WAAW,WAAW,IAAI,WAAW,cAAc,CAAC;QACrE;MACN;AACI,eAASF,QAAO,OAAO,KAAK,QAAQ,MAAM,IAAI,UAAU,KAAK,OAAO,IAAI,GAAG,SAAQ,GAAI,YAAY,IACjG,QAAQE,MAAK,MAAM,OAAO;IAChC;AAEE,UAAM,OAAO,QAAQ,KAAK,QAAQ,WAAW,WAAW,GAAG,SAAS,WAAW,GAAG,KAAK,UAAU,aAAa;AAC9G,cAAUF,QAAO,OAAO,KAAK,QAAQ,MAAM,IAAI,UAAU,KAAK,OAAO,GAAG,SAAQ,GAAI,YAAY,IAC9F,QAAQ,KAAK,MAAM;AACrB,cAAUA,QAAO,OAAO,KAAK,QAAQ,SAAS,eAAe,IAAI,KAAK,GAAG,IAAI;AAE7E,aAAS,IAAI,GAAG,KAAK,QAAQ,YAAY,KAAK;AAC5C,UAAI,cAAc,KAAK,SAAS,OAAQ;AACxC,YAAME,QAAO;QACX,KAAK;QACL,WAAW,cAAc,CAAC;QAC1B,SAAS,cAAc,CAAC;QACxB,KAAK,YAAY,WAAW,WAAW,IAAI,WAAW,cAAc,CAAC;QACrE;MACN;AACI,gBAAUF,QAAO,OAAO,KAAK,QAAQ,MAAM,IAAI,UAAU,KAAK,OAAO,IAAI,GAAG,SAAQ,GAAI,YAAY,IAClG,QAAQE,MAAK,MAAM;IACzB;AAEE,WAAO,OAAO,QAAQ,OAAO,EAAE;EACjC;AAEA,YAAiB;;;;;;;;AC7FjB,QAAMH,iBAAgBE,iBAAA;AAEtB,QAAM,2BAA2B;IAC/B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;EACF;AAEA,QAAM,kBAAkB;IACtB;IACA;IACA;EACF;AAEA,WAAS,oBAAqBE,MAAK;AACjC,UAAM,SAAS,CAAA;AAEf,QAAIA,SAAQ,MAAM;AAChB,aAAO,KAAKA,IAAG,EAAE,QAAQ,SAAU,OAAO;AACxCA,aAAI,KAAK,EAAE,QAAQ,SAAU,OAAO;AAClC,iBAAO,OAAO,KAAK,CAAC,IAAI;QAChC,CAAO;MACP,CAAK;IACL;AAEE,WAAO;EACT;AAEA,WAASC,MAAM,KAAK,SAAS;AAC3B,cAAU,WAAW,CAAA;AAErB,WAAO,KAAK,OAAO,EAAE,QAAQ,SAAU,MAAM;AAC3C,UAAI,yBAAyB,QAAQ,IAAI,MAAM,IAAI;AACjD,cAAM,IAAIL,eAAc,qBAAqB,OAAO,gCAAgC,MAAM,cAAc;MAC9G;IACA,CAAG;AAGD,SAAK,UAAU;AACf,SAAK,MAAM;AACX,SAAK,OAAO,QAAQ,MAAM,KAAK;AAC/B,SAAK,UAAU,QAAQ,SAAS,KAAK,WAAY;AAAE,aAAO;IAAI;AAC9D,SAAK,YAAY,QAAQ,WAAW,KAAK,SAAU,MAAM;AAAE,aAAO;IAAI;AACtE,SAAK,aAAa,QAAQ,YAAY,KAAK;AAC3C,SAAK,YAAY,QAAQ,WAAW,KAAK;AACzC,SAAK,YAAY,QAAQ,WAAW,KAAK;AACzC,SAAK,gBAAgB,QAAQ,eAAe,KAAK;AACjD,SAAK,eAAe,QAAQ,cAAc,KAAK;AAC/C,SAAK,QAAQ,QAAQ,OAAO,KAAK;AACjC,SAAK,eAAe,oBAAoB,QAAQ,cAAc,KAAK,IAAI;AAEvE,QAAI,gBAAgB,QAAQ,KAAK,IAAI,MAAM,IAAI;AAC7C,YAAM,IAAIA,eAAc,mBAAmB,KAAK,OAAO,yBAAyB,MAAM,cAAc;IACxG;EACA;AAEA,SAAiBK;;;;;;;;AC/DjB,QAAML,iBAAgBE,iBAAA;AACtB,QAAMG,QAAOC,YAAA;AAEb,WAAS,YAAaC,SAAQ,MAAM;AAClC,UAAM,SAAS,CAAA;AAEfA,YAAO,IAAI,EAAE,QAAQ,SAAU,aAAa;AAC1C,UAAI,WAAW,OAAO;AAEtB,aAAO,QAAQ,SAAU,cAAc,eAAe;AACpD,YAAI,aAAa,QAAQ,YAAY,OACjC,aAAa,SAAS,YAAY,QAClC,aAAa,UAAU,YAAY,OAAO;AAC5C,qBAAW;QACnB;MACA,CAAK;AAED,aAAO,QAAQ,IAAI;IACvB,CAAG;AAED,WAAO;EACT;AAEA,WAAS,aAA4B;AACnC,UAAM,SAAS;MACb,QAAQ,CAAA;MACR,UAAU,CAAA;MACV,SAAS,CAAA;MACT,UAAU,CAAA;MACV,OAAO;QACL,QAAQ,CAAA;QACR,UAAU,CAAA;QACV,SAAS,CAAA;QACT,UAAU,CAAA;MAChB;IACA;AACE,aAAS,YAAaC,OAAM;AAC1B,UAAIA,MAAK,OAAO;AACd,eAAO,MAAMA,MAAK,IAAI,EAAE,KAAKA,KAAI;AACjC,eAAO,MAAM,UAAU,EAAE,KAAKA,KAAI;MACxC,OAAW;AACL,eAAOA,MAAK,IAAI,EAAEA,MAAK,GAAG,IAAI,OAAO,UAAU,EAAEA,MAAK,GAAG,IAAIA;MACnE;IACA;AAEE,aAAS,QAAQ,GAAG,SAAS,UAAU,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACzE,gBAAU,KAAK,EAAE,QAAQ,WAAW;IACxC;AACE,WAAO;EACT;AAEA,WAASC,QAAQ,YAAY;AAC3B,WAAO,KAAK,OAAO,UAAU;EAC/B;AAEAA,UAAO,UAAU,SAAS,SAAS,OAAQ,YAAY;AACrD,QAAI,WAAW,CAAA;AACf,QAAI,WAAW,CAAA;AAEf,QAAI,sBAAsBJ,OAAM;AAE9B,eAAS,KAAK,UAAU;IAC5B,WAAa,MAAM,QAAQ,UAAU,GAAG;AAEpC,iBAAW,SAAS,OAAO,UAAU;IACzC,WAAa,eAAe,MAAM,QAAQ,WAAW,QAAQ,KAAK,MAAM,QAAQ,WAAW,QAAQ,IAAI;AAEnG,UAAI,WAAW,SAAU,YAAW,SAAS,OAAO,WAAW,QAAQ;AACvE,UAAI,WAAW,SAAU,YAAW,SAAS,OAAO,WAAW,QAAQ;IAC3E,OAAS;AACL,YAAM,IAAIL,eAAc,kHACyC;IACrE;AAEE,aAAS,QAAQ,SAAUQ,OAAM;AAC/B,UAAI,EAAEA,iBAAgBH,QAAO;AAC3B,cAAM,IAAIL,eAAc,oFAAoF;MAClH;AAEI,UAAIQ,MAAK,YAAYA,MAAK,aAAa,UAAU;AAC/C,cAAM,IAAIR,eAAc,iHAAiH;MAC/I;AAEI,UAAIQ,MAAK,OAAO;AACd,cAAM,IAAIR,eAAc,oGAAoG;MAClI;IACA,CAAG;AAED,aAAS,QAAQ,SAAUQ,OAAM;AAC/B,UAAI,EAAEA,iBAAgBH,QAAO;AAC3B,cAAM,IAAIL,eAAc,oFAAoF;MAClH;IACA,CAAG;AAED,UAAM,SAAS,OAAO,OAAOS,QAAO,SAAS;AAE7C,WAAO,YAAY,KAAK,YAAY,CAAA,GAAI,OAAO,QAAQ;AACvD,WAAO,YAAY,KAAK,YAAY,CAAA,GAAI,OAAO,QAAQ;AAEvD,WAAO,mBAAmB,YAAY,QAAQ,UAAU;AACxD,WAAO,mBAAmB,YAAY,QAAQ,UAAU;AACxD,WAAO,kBAAkB,WAAW,OAAO,kBAAkB,OAAO,gBAAgB;AAEpF,WAAO;EACT;AAEA,WAAiBA;;;;;;;;AC1GjB,QAAMJ,QAAOH,YAAA;AAEb,QAAiB,IAAIG,MAAK,yBAAyB;IACjD,MAAM;IACN,WAAW,SAAU,MAAM;AAAE,aAAO,SAAS,OAAO,OAAO;IAAE;EAAA,CAC9D;;;;;;;;ACLD,QAAMA,QAAOH,YAAA;AAEb,QAAiB,IAAIG,MAAK,yBAAyB;IACjD,MAAM;IACN,WAAW,SAAU,MAAM;AAAE,aAAO,SAAS,OAAO,OAAO,CAAA;IAAE;EAAA,CAC9D;;;;;;;;ACLD,QAAMA,QAAOH,YAAA;AAEb,QAAiB,IAAIG,MAAK,yBAAyB;IACjD,MAAM;IACN,WAAW,SAAU,MAAM;AAAE,aAAO,SAAS,OAAO,OAAO,CAAA;IAAE;EAAA,CAC9D;;;;;;;;ACFD,QAAMI,UAASP,cAAA;AAEf,aAAiB,IAAIO,QAAO;IAC1B,UAAU;MACRH,WAAA;MACAI,WAAA;MACAC,WAAA;IACJ;EAAA,CACC;;;;;;;;ACXD,QAAMN,QAAOH,YAAA;AAEb,WAAS,gBAAiB,MAAM;AAC9B,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,MAAM,KAAK;AAEjB,WAAQ,QAAQ,KAAK,SAAS,OACtB,QAAQ,MAAM,SAAS,UAAU,SAAS,UAAU,SAAS;EACvE;AAEA,WAAS,oBAAqB;AAC5B,WAAO;EACT;AAEA,WAAS,OAAQ,QAAQ;AACvB,WAAO,WAAW;EACpB;AAEA,UAAiB,IAAIG,MAAK,0BAA0B;IAClD,MAAM;IACN,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;MACT,WAAW,WAAY;AAAE,eAAO;MAAG;MACnC,WAAW,WAAY;AAAE,eAAO;MAAM;MACtC,WAAW,WAAY;AAAE,eAAO;MAAM;MACtC,WAAW,WAAY;AAAE,eAAO;MAAM;MACtC,OAAO,WAAY;AAAE,eAAO;MAAE;IAAA;IAEhC,cAAc;EAAA,CACf;;;;;;;;AChCD,QAAMA,QAAOH,YAAA;AAEb,WAAS,mBAAoB,MAAM;AACjC,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,MAAM,KAAK;AAEjB,WAAQ,QAAQ,MAAM,SAAS,UAAU,SAAS,UAAU,SAAS,WAC7D,QAAQ,MAAM,SAAS,WAAW,SAAS,WAAW,SAAS;EACzE;AAEA,WAAS,qBAAsB,MAAM;AACnC,WAAO,SAAS,UACT,SAAS,UACT,SAAS;EAClB;AAEA,WAAS,UAAW,QAAQ;AAC1B,WAAO,OAAO,UAAU,SAAS,KAAK,MAAM,MAAM;EACpD;AAEA,SAAiB,IAAIG,MAAK,0BAA0B;IAClD,MAAM;IACN,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;MACT,WAAW,SAAU,QAAQ;AAAE,eAAO,SAAS,SAAS;MAAO;MAC/D,WAAW,SAAU,QAAQ;AAAE,eAAO,SAAS,SAAS;MAAO;MAC/D,WAAW,SAAU,QAAQ;AAAE,eAAO,SAAS,SAAS;MAAO;IAAA;IAEjE,cAAc;EAAA,CACf;;;;;;;;AChCD,QAAMJ,UAASC,cAAA;AACf,QAAMG,QAAOC,YAAA;AAEb,WAAS,UAAW,GAAG;AACrB,WAAS,KAAK,MAAiB,KAAK,MAC3B,KAAK,MAAiB,KAAK,MAC3B,KAAK,MAAiB,KAAK;EACtC;AAEA,WAAS,UAAW,GAAG;AACrB,WAAS,KAAK,MAAiB,KAAK;EACtC;AAEA,WAAS,UAAW,GAAG;AACrB,WAAS,KAAK,MAAiB,KAAK;EACtC;AAEA,WAAS,mBAAoB,MAAM;AACjC,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,MAAM,KAAK;AACjB,QAAI,QAAQ;AACZ,QAAI,YAAY;AAEhB,QAAI,CAAC,IAAK,QAAO;AAEjB,QAAI,KAAK,KAAK,KAAK;AAGnB,QAAI,OAAO,OAAO,OAAO,KAAK;AAC5B,WAAK,KAAK,EAAE,KAAK;IACrB;AAEE,QAAI,OAAO,KAAK;AAEd,UAAI,QAAQ,MAAM,IAAK,QAAO;AAC9B,WAAK,KAAK,EAAE,KAAK;AAIjB,UAAI,OAAO,KAAK;AAEd;AAEA,eAAO,QAAQ,KAAK,SAAS;AAC3B,eAAK,KAAK,KAAK;AACf,cAAI,OAAO,OAAO,OAAO,IAAK,QAAO;AACrC,sBAAY;QACpB;AACM,eAAO,aAAa,SAAS,iBAAiB,IAAI,CAAC;MACzD;AAEI,UAAI,OAAO,KAAK;AAEd;AAEA,eAAO,QAAQ,KAAK,SAAS;AAC3B,cAAI,CAAC,UAAU,KAAK,WAAW,KAAK,CAAC,EAAG,QAAO;AAC/C,sBAAY;QACpB;AACM,eAAO,aAAa,SAAS,iBAAiB,IAAI,CAAC;MACzD;AAEI,UAAI,OAAO,KAAK;AAEd;AAEA,eAAO,QAAQ,KAAK,SAAS;AAC3B,cAAI,CAAC,UAAU,KAAK,WAAW,KAAK,CAAC,EAAG,QAAO;AAC/C,sBAAY;QACpB;AACM,eAAO,aAAa,SAAS,iBAAiB,IAAI,CAAC;MACzD;IACA;AAIE,WAAO,QAAQ,KAAK,SAAS;AAC3B,UAAI,CAAC,UAAU,KAAK,WAAW,KAAK,CAAC,GAAG;AACtC,eAAO;MACb;AACI,kBAAY;IAChB;AAEE,QAAI,CAAC,UAAW,QAAO;AAEvB,WAAO,SAAS,iBAAiB,IAAI,CAAC;EACxC;AAEA,WAAS,iBAAkB,MAAM;AAC/B,QAAI,QAAQ;AACZ,QAAI,OAAO;AAEX,QAAI,KAAK,MAAM,CAAC;AAEhB,QAAI,OAAO,OAAO,OAAO,KAAK;AAC5B,UAAI,OAAO,IAAK,QAAO;AACvB,cAAQ,MAAM,MAAM,CAAC;AACrB,WAAK,MAAM,CAAC;IAChB;AAEE,QAAI,UAAU,IAAK,QAAO;AAE1B,QAAI,OAAO,KAAK;AACd,UAAI,MAAM,CAAC,MAAM,IAAK,QAAO,OAAO,SAAS,MAAM,MAAM,CAAC,GAAG,CAAC;AAC9D,UAAI,MAAM,CAAC,MAAM,IAAK,QAAO,OAAO,SAAS,MAAM,MAAM,CAAC,GAAG,EAAE;AAC/D,UAAI,MAAM,CAAC,MAAM,IAAK,QAAO,OAAO,SAAS,MAAM,MAAM,CAAC,GAAG,CAAC;IAClE;AAEE,WAAO,OAAO,SAAS,OAAO,EAAE;EAClC;AAEA,WAAS,qBAAsB,MAAM;AACnC,WAAO,iBAAiB,IAAI;EAC9B;AAEA,WAAS,UAAW,QAAQ;AAC1B,WAAQ,OAAO,UAAU,SAAS,KAAK,MAAM,MAAO,sBAC5C,SAAS,MAAM,KAAK,CAACL,QAAO,eAAe,MAAM;EAC3D;AAEA,QAAiB,IAAII,MAAK,yBAAyB;IACjD,MAAM;IACN,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;MACT,QAAQ,SAAU,KAAK;AAAE,eAAO,OAAO,IAAI,OAAO,IAAI,SAAS,CAAC,IAAI,QAAQ,IAAI,SAAS,CAAC,EAAE,MAAM,CAAC;MAAC;MACpG,OAAO,SAAU,KAAK;AAAE,eAAO,OAAO,IAAI,OAAO,IAAI,SAAS,CAAC,IAAI,QAAQ,IAAI,SAAS,CAAC,EAAE,MAAM,CAAC;MAAC;MACnG,SAAS,SAAU,KAAK;AAAE,eAAO,IAAI,SAAS,EAAE;MAAC;MACjD,aAAa,SAAU,KAAK;AAAE,eAAO,OAAO,IAAI,OAAO,IAAI,SAAS,EAAE,EAAE,YAAA,IAAgB,QAAQ,IAAI,SAAS,EAAE,EAAE,YAAW,EAAG,MAAM,CAAC;MAAC;IAAA;IAEzI,cAAc;IACd,cAAc;MACZ,QAAQ,CAAC,GAAG,KAAK;MACjB,OAAO,CAAC,GAAG,KAAK;MAChB,SAAS,CAAC,IAAI,KAAK;MACnB,aAAa,CAAC,IAAI,KAAK;IAC3B;EAAA,CACC;;;;;;;;AC3ID,QAAMJ,UAASC,cAAA;AACf,QAAMG,QAAOC,YAAA;AAEb,QAAM,qBAAqB,IAAI;;IAE7B;EAOuB;AAEzB,QAAM,6BAA6B,IAAI;IACrC;EAIuB;AAEzB,WAAS,iBAAkB,MAAM;AAC/B,QAAI,SAAS,KAAM,QAAO;AAE1B,QAAI,CAAC,mBAAmB,KAAK,IAAI,GAAG;AAClC,aAAO;IACX;AAEE,QAAI,SAAS,WAAW,MAAM,EAAE,CAAC,GAAG;AAClC,aAAO;IACX;AAEE,WAAO,2BAA2B,KAAK,IAAI;EAC7C;AAEA,WAAS,mBAAoB,MAAM;AACjC,QAAI,QAAQ,KAAK,YAAW;AAC5B,UAAM,OAAO,MAAM,CAAC,MAAM,MAAM,KAAK;AAErC,QAAI,KAAK,QAAQ,MAAM,CAAC,CAAC,KAAK,GAAG;AAC/B,cAAQ,MAAM,MAAM,CAAC;IACzB;AAEE,QAAI,UAAU,QAAQ;AACpB,aAAQ,SAAS,IAAK,OAAO,oBAAoB,OAAO;IAC5D,WAAa,UAAU,QAAQ;AAC3B,aAAO;IACX;AACE,WAAO,OAAO,WAAW,OAAO,EAAE;EACpC;AAEA,QAAM,yBAAyB;AAE/B,WAAS,mBAAoB,QAAQ,OAAO;AAC1C,QAAI,MAAM,MAAM,GAAG;AACjB,cAAQ,OAAK;QACX,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;MAC/B;IACA,WAAa,OAAO,sBAAsB,QAAQ;AAC9C,cAAQ,OAAK;QACX,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;MAC/B;IACA,WAAa,OAAO,sBAAsB,QAAQ;AAC9C,cAAQ,OAAK;QACX,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;QACzB,KAAK;AAAa,iBAAO;MAC/B;IACA,WAAaL,QAAO,eAAe,MAAM,GAAG;AACxC,aAAO;IACX;AAEE,UAAM,MAAM,OAAO,SAAS,EAAE;AAK9B,WAAO,uBAAuB,KAAK,GAAG,IAAI,IAAI,QAAQ,KAAK,IAAI,IAAI;EACrE;AAEA,WAAS,QAAS,QAAQ;AACxB,WAAQ,OAAO,UAAU,SAAS,KAAK,MAAM,MAAM,sBAC3C,SAAS,MAAM,KAAKA,QAAO,eAAe,MAAM;EAC1D;AAEA,UAAiB,IAAII,MAAK,2BAA2B;IACnD,MAAM;IACN,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;IACX,cAAc;EAAA,CACf;;;;;;;;ACzFD,SAAiBH,gBAAA,EAAsB,OAAO;IAC5C,UAAU;MACRI,aAAA;MACAI,YAAA;MACAC,WAAA;MACAC,aAAA;IACJ;EAAA,CACC;;;;;;;;ACRD,SAAiBV,YAAA;;;;;;;;ACNjB,QAAMG,QAAOH,YAAA;AAEb,QAAM,mBAAmB,IAAI;IAC3B;EAEgB;AAElB,QAAM,wBAAwB,IAAI;IAChC;EASwB;AAE1B,WAAS,qBAAsB,MAAM;AACnC,QAAI,SAAS,KAAM,QAAO;AAC1B,QAAI,iBAAiB,KAAK,IAAI,MAAM,KAAM,QAAO;AACjD,QAAI,sBAAsB,KAAK,IAAI,MAAM,KAAM,QAAO;AACtD,WAAO;EACT;AAEA,WAAS,uBAAwB,MAAM;AACrC,QAAI,WAAW;AACf,QAAI,QAAQ;AAEZ,QAAI,QAAQ,iBAAiB,KAAK,IAAI;AACtC,QAAI,UAAU,KAAM,SAAQ,sBAAsB,KAAK,IAAI;AAE3D,QAAI,UAAU,KAAM,OAAM,IAAI,MAAM,oBAAoB;AAIxD,UAAM,OAAO,CAAE,MAAM,CAAC;AACtB,UAAM,QAAQ,CAAE,MAAM,CAAC,IAAK;AAC5B,UAAM,MAAM,CAAE,MAAM,CAAC;AAErB,QAAI,CAAC,MAAM,CAAC,GAAG;AACb,aAAO,IAAI,KAAK,KAAK,IAAI,MAAM,OAAO,GAAG,CAAC;IAC9C;AAIE,UAAM,OAAO,CAAE,MAAM,CAAC;AACtB,UAAM,SAAS,CAAE,MAAM,CAAC;AACxB,UAAM,SAAS,CAAE,MAAM,CAAC;AAExB,QAAI,MAAM,CAAC,GAAG;AACZ,iBAAW,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC;AAC9B,aAAO,SAAS,SAAS,GAAG;AAC1B,oBAAY;MAClB;AACI,iBAAW,CAAC;IAChB;AAIE,QAAI,MAAM,CAAC,GAAG;AACZ,YAAM,SAAS,CAAE,MAAM,EAAE;AACzB,YAAM,WAAW,EAAE,MAAM,EAAE,KAAK;AAChC,eAAS,SAAS,KAAK,YAAY;AACnC,UAAI,MAAM,CAAC,MAAM,IAAK,SAAQ,CAAC;IACnC;AAEE,UAAM,OAAO,IAAI,KAAK,KAAK,IAAI,MAAM,OAAO,KAAK,MAAM,QAAQ,QAAQ,QAAQ,CAAC;AAEhF,QAAI,MAAO,MAAK,QAAQ,KAAK,QAAO,IAAK,KAAK;AAE9C,WAAO;EACT;AAEA,WAAS,uBAAwB,QAAqB;AACpD,WAAO,OAAO,YAAW;EAC3B;AAEA,cAAiB,IAAIG,MAAK,+BAA+B;IACvD,MAAM;IACN,SAAS;IACT,WAAW;IACX,YAAY;IACZ,WAAW;EAAA,CACZ;;;;;;;;ACrFD,QAAMA,QAAOH,YAAA;AAEb,WAAS,iBAAkB,MAAM;AAC/B,WAAO,SAAS,QAAQ,SAAS;EACnC;AAEA,UAAiB,IAAIG,MAAK,2BAA2B;IACnD,MAAM;IACN,SAAS;EAAA,CACV;;;;;;;;ACTD,QAAMA,QAAOH,YAAA;AAGb,QAAM,aAAa;AAEnB,WAAS,kBAAmB,MAAM;AAChC,QAAI,SAAS,KAAM,QAAO;AAE1B,QAAI,SAAS;AACb,UAAM,MAAM,KAAK;AACjB,UAAME,OAAM;AAGZ,aAAS,MAAM,GAAG,MAAM,KAAK,OAAO;AAClC,YAAM,OAAOA,KAAI,QAAQ,KAAK,OAAO,GAAG,CAAC;AAGzC,UAAI,OAAO,GAAI;AAGf,UAAI,OAAO,EAAG,QAAO;AAErB,gBAAU;IACd;AAGE,WAAQ,SAAS,MAAO;EAC1B;AAEA,WAAS,oBAAqB,MAAM;AAClC,UAAM,QAAQ,KAAK,QAAQ,YAAY,EAAE;AACzC,UAAM,MAAM,MAAM;AAClB,UAAMA,OAAM;AACZ,QAAI,OAAO;AACX,UAAM,SAAS,CAAA;AAIf,aAAS,MAAM,GAAG,MAAM,KAAK,OAAO;AAClC,UAAK,MAAM,MAAM,KAAM,KAAK;AAC1B,eAAO,KAAM,QAAQ,KAAM,GAAI;AAC/B,eAAO,KAAM,QAAQ,IAAK,GAAI;AAC9B,eAAO,KAAK,OAAO,GAAI;MAC7B;AAEI,aAAQ,QAAQ,IAAKA,KAAI,QAAQ,MAAM,OAAO,GAAG,CAAC;IACtD;AAIE,UAAM,WAAY,MAAM,IAAK;AAE7B,QAAI,aAAa,GAAG;AAClB,aAAO,KAAM,QAAQ,KAAM,GAAI;AAC/B,aAAO,KAAM,QAAQ,IAAK,GAAI;AAC9B,aAAO,KAAK,OAAO,GAAI;IAC3B,WAAa,aAAa,IAAI;AAC1B,aAAO,KAAM,QAAQ,KAAM,GAAI;AAC/B,aAAO,KAAM,QAAQ,IAAK,GAAI;IAClC,WAAa,aAAa,IAAI;AAC1B,aAAO,KAAM,QAAQ,IAAK,GAAI;IAClC;AAEE,WAAO,IAAI,WAAW,MAAM;EAC9B;AAEA,WAAS,oBAAqB,QAAqB;AACjD,QAAI,SAAS;AACb,QAAI,OAAO;AACX,UAAM,MAAM,OAAO;AACnB,UAAMA,OAAM;AAIZ,aAAS,MAAM,GAAG,MAAM,KAAK,OAAO;AAClC,UAAK,MAAM,MAAM,KAAM,KAAK;AAC1B,kBAAUA,KAAK,QAAQ,KAAM,EAAI;AACjC,kBAAUA,KAAK,QAAQ,KAAM,EAAI;AACjC,kBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,kBAAUA,KAAI,OAAO,EAAI;MAC/B;AAEI,cAAQ,QAAQ,KAAK,OAAO,GAAG;IACnC;AAIE,UAAM,OAAO,MAAM;AAEnB,QAAI,SAAS,GAAG;AACd,gBAAUA,KAAK,QAAQ,KAAM,EAAI;AACjC,gBAAUA,KAAK,QAAQ,KAAM,EAAI;AACjC,gBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,gBAAUA,KAAI,OAAO,EAAI;IAC7B,WAAa,SAAS,GAAG;AACrB,gBAAUA,KAAK,QAAQ,KAAM,EAAI;AACjC,gBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,gBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,gBAAUA,KAAI,EAAE;IACpB,WAAa,SAAS,GAAG;AACrB,gBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,gBAAUA,KAAK,QAAQ,IAAK,EAAI;AAChC,gBAAUA,KAAI,EAAE;AAChB,gBAAUA,KAAI,EAAE;IACpB;AAEE,WAAO;EACT;AAEA,WAAS,SAAU,KAAK;AACtB,WAAO,OAAO,UAAU,SAAS,KAAK,GAAG,MAAM;EACjD;AAEA,WAAiB,IAAIC,MAAK,4BAA4B;IACpD,MAAM;IACN,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;EAAA,CACZ;;;;;;;;ACvHD,QAAMA,QAAOH,YAAA;AAEb,QAAM,kBAAkB,OAAO,UAAU;AACzC,QAAM,YAAY,OAAO,UAAU;AAEnC,WAAS,gBAAiB,MAAM;AAC9B,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,aAAa,CAAA;AACnB,UAAM,SAAS;AAEf,aAAS,QAAQ,GAAG,SAAS,OAAO,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtE,YAAM,OAAO,OAAO,KAAK;AACzB,UAAI,aAAa;AAEjB,UAAI,UAAU,KAAK,IAAI,MAAM,kBAAmB,QAAO;AAEvD,UAAI;AACJ,WAAK,WAAW,MAAM;AACpB,YAAI,gBAAgB,KAAK,MAAM,OAAO,GAAG;AACvC,cAAI,CAAC,WAAY,cAAa;cACzB,QAAO;QACpB;MACA;AAEI,UAAI,CAAC,WAAY,QAAO;AAExB,UAAI,gBAAgB,KAAK,YAAY,OAAO,EAAG,QAAO;AACtD,aAAO,eAAe,YAAY,SAAS,EAAE,OAAO,KAAI,CAAE;IAC9D;AAEE,WAAO;EACT;AAEA,WAAS,kBAAmB,MAAM;AAChC,WAAO,SAAS,OAAO,OAAO,CAAA;EAChC;AAEA,SAAiB,IAAIG,MAAK,0BAA0B;IAClD,MAAM;IACN,SAAS;IACT,WAAW;EAAA,CACZ;;;;;;;;AC1CD,QAAMA,QAAOH,YAAA;AAEb,QAAM,YAAY,OAAO,UAAU;AAEnC,WAAS,iBAAkB,MAAM;AAC/B,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,SAAS;AAEf,UAAM,SAAS,IAAI,MAAM,OAAO,MAAM;AAEtC,aAAS,QAAQ,GAAG,SAAS,OAAO,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtE,YAAM,OAAO,OAAO,KAAK;AAEzB,UAAI,UAAU,KAAK,IAAI,MAAM,kBAAmB,QAAO;AAEvD,YAAM,OAAO,OAAO,KAAK,IAAI;AAE7B,UAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,aAAO,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC;IAC3C;AAEE,WAAO;EACT;AAEA,WAAS,mBAAoB,MAAM;AACjC,QAAI,SAAS,KAAM,QAAO,CAAA;AAE1B,UAAM,SAAS;AACf,UAAM,SAAS,IAAI,MAAM,OAAO,MAAM;AAEtC,aAAS,QAAQ,GAAG,SAAS,OAAO,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtE,YAAM,OAAO,OAAO,KAAK;AAEzB,YAAM,OAAO,OAAO,KAAK,IAAI;AAE7B,aAAO,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC;IAC3C;AAEE,WAAO;EACT;AAEA,UAAiB,IAAIG,MAAK,2BAA2B;IACnD,MAAM;IACN,SAAS;IACT,WAAW;EAAA,CACZ;;;;;;;;AC/CD,QAAMA,QAAOH,YAAA;AAEb,QAAM,kBAAkB,OAAO,UAAU;AAEzC,WAAS,eAAgB,MAAM;AAC7B,QAAI,SAAS,KAAM,QAAO;AAE1B,UAAM,SAAS;AAEf,eAAW,OAAO,QAAQ;AACxB,UAAI,gBAAgB,KAAK,QAAQ,GAAG,GAAG;AACrC,YAAI,OAAO,GAAG,MAAM,KAAM,QAAO;MACvC;IACA;AAEE,WAAO;EACT;AAEA,WAAS,iBAAkB,MAAM;AAC/B,WAAO,SAAS,OAAO,OAAO,CAAA;EAChC;AAEA,QAAiB,IAAIG,MAAK,yBAAyB;IACjD,MAAM;IACN,SAAS;IACT,WAAW;EAAA,CACZ;;;;;;;;ACpBD,aAAiBH,YAAA,EAAkB,OAAO;IACxC,UAAU;MACRI,iBAAA;MACAI,aAAA;IAAA;IAEF,UAAU;MACRC,cAAA;MACAC,YAAA;MACAC,aAAA;MACAC,WAAA;IACJ;EAAA,CACC;;;;;;;ACjBD,QAAMb,UAASC,cAAA;AACf,QAAMF,iBAAgBM,iBAAA;AACtB,QAAM,cAAcI,eAAA;AACpB,QAAMK,kBAAiBJ,gBAAA;AAEvB,QAAM,kBAAkB,OAAO,UAAU;AAEzC,QAAM,kBAAkB;AACxB,QAAM,mBAAmB;AACzB,QAAM,mBAAmB;AACzB,QAAM,oBAAoB;AAE1B,QAAM,gBAAgB;AACtB,QAAM,iBAAiB;AACvB,QAAM,gBAAgB;AAGtB,QAAM,wBAAwB;AAC9B,QAAM,gCAAgC;AAEtC,QAAM,0BAA0B;AAEhC,QAAM,qBAAqB;AAE3B,QAAM,kBAAkB;AAExB,WAAS,OAAQ,KAAK;AAAE,WAAO,OAAO,UAAU,SAAS,KAAK,GAAG;EAAC;AAElE,WAAS,MAAO,GAAG;AACjB,WAAQ,MAAM,MAAkB,MAAM;EACxC;AAEA,WAAS,aAAc,GAAG;AACxB,WAAQ,MAAM,KAAmB,MAAM;EACzC;AAEA,WAAS,UAAW,GAAG;AACrB,WAAQ,MAAM,KACN,MAAM,MACN,MAAM,MACN,MAAM;EAChB;AAEA,WAAS,gBAAiB,GAAG;AAC3B,WAAO,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,OACN,MAAM;EACf;AAEA,WAAS,YAAa,GAAG;AACvB,QAAK,KAAK,MAAiB,KAAK,IAAc;AAC5C,aAAO,IAAI;IACf;AAEE,UAAM,KAAK,IAAI;AAEf,QAAK,MAAM,MAAiB,MAAM,KAAc;AAC9C,aAAO,KAAK,KAAO;IACvB;AAEE,WAAO;EACT;AAEA,WAAS,cAAe,GAAG;AACzB,QAAI,MAAM,KAAa;AAAE,aAAO;IAAC;AACjC,QAAI,MAAM,KAAa;AAAE,aAAO;IAAC;AACjC,QAAI,MAAM,IAAa;AAAE,aAAO;IAAC;AACjC,WAAO;EACT;AAEA,WAAS,gBAAiB,GAAG;AAC3B,QAAK,KAAK,MAAiB,KAAK,IAAc;AAC5C,aAAO,IAAI;IACf;AAEE,WAAO;EACT;AAEA,WAAS,qBAAsB,GAAG;AAChC,YAAQ,GAAC;MACP,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAe,eAAO;MAC3B,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAiB,eAAO;MAC7B,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB,KAAK;AAAa,eAAO;MACzB;AAAS,eAAO;IACpB;EACA;AAEA,WAAS,kBAAmB,GAAG;AAC7B,QAAI,KAAK,OAAQ;AACf,aAAO,OAAO,aAAa,CAAC;IAChC;AAGE,WAAO,OAAO;OACV,IAAI,SAAa,MAAM;OACvB,IAAI,QAAY,QAAU;IAChC;EACA;AAIA,WAAS,YAAa,QAAQ,KAAK,OAAO;AAExC,QAAI,QAAQ,aAAa;AACvB,aAAO,eAAe,QAAQ,KAAK;QACjC,cAAc;QACd,YAAY;QACZ,UAAU;QACV;MAAA,CACD;IACL,OAAS;AACL,aAAO,GAAG,IAAI;IAClB;EACA;AAEA,QAAM,oBAAoB,IAAI,MAAM,GAAG;AACvC,QAAM,kBAAkB,IAAI,MAAM,GAAG;AACrC,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,sBAAkB,CAAC,IAAI,qBAAqB,CAAC,IAAI,IAAI;AACrD,oBAAgB,CAAC,IAAI,qBAAqB,CAAC;EAC7C;AAEA,WAAS,MAAO,OAAO,SAAS;AAC9B,SAAK,QAAQ;AAEb,SAAK,WAAW,QAAQ,UAAU,KAAK;AACvC,SAAK,SAAS,QAAQ,QAAQ,KAAKI;AACnC,SAAK,YAAY,QAAQ,WAAW,KAAK;AAGzC,SAAK,SAAS,QAAQ,QAAQ,KAAK;AAEnC,SAAK,OAAO,QAAQ,MAAM,KAAK;AAC/B,SAAK,WAAW,QAAQ,UAAU,KAAK;AACvC,SAAK,WAAW,OAAO,QAAQ,UAAU,MAAM,WAAW,QAAQ,UAAU,IAAI;AAChF,SAAK,oBAAoB,OAAO,QAAQ,mBAAmB,MAAM,WAAW,QAAQ,mBAAmB,IAAI;AAE3G,SAAK,gBAAgB,KAAK,OAAO;AACjC,SAAK,UAAU,KAAK,OAAO;AAE3B,SAAK,SAAS,MAAM;AACpB,SAAK,WAAW;AAChB,SAAK,OAAO;AACZ,SAAK,YAAY;AACjB,SAAK,aAAa;AAClB,SAAK,QAAQ;AACb,SAAK,iBAAiB;AAItB,SAAK,iBAAiB;AAEtB,SAAK,YAAY,CAAA;AACjB,SAAK,wBAAwB,CAAA;EAW/B;AAEA,WAAS,cAAe,OAAO,SAAS;AACtC,UAAM,OAAO;MACX,MAAM,MAAM;MACZ,QAAQ,MAAM,MAAM,MAAM,GAAG,EAAE;;MAC/B,UAAU,MAAM;MAChB,MAAM,MAAM;MACZ,QAAQ,MAAM,WAAW,MAAM;IACnC;AAEE,SAAK,UAAU,YAAY,IAAI;AAE/B,WAAO,IAAIf,eAAc,SAAS,IAAI;EACxC;AAEA,WAAS,WAAY,OAAO,SAAS;AACnC,UAAM,cAAc,OAAO,OAAO;EACpC;AAEA,WAAS,aAAc,OAAO,SAAS;AACrC,QAAI,MAAM,WAAW;AACnB,YAAM,UAAU,KAAK,MAAM,cAAc,OAAO,OAAO,CAAC;IAC5D;EACA;AAEA,WAAS,YAAa,OAAO,MAAM,OAAO;AACxC,UAAM,eAAe,MAAM;AAE3B,QAAI,aAAa,WAAW,GAAG;AAC7B,YAAM,cAAc,aAAa,aAAa,SAAS,CAAC;AAExD,UAAI,CAAC,gBAAgB,KAAK,aAAa,IAAI,GAAG;AAC5C,oBAAY,IAAI,IAAI;UAClB,SAAS,gBAAgB,KAAK,MAAM,WAAW,IAAI;UACnD,OAAO,MAAM,UAAU,IAAI;QACnC;MACA;IACA;AAEE,UAAM,UAAU,IAAI,IAAI;EAC1B;AAEA,WAAS,uBAAwB,OAAO;AACtC,UAAM,sBAAsB,KAAK,uBAAO,OAAO,IAAI,CAAC;EACtD;AAEA,WAAS,wBAAyB,OAAO;AACvC,UAAM,cAAc,MAAM,sBAAsB,IAAG;AACnD,UAAM,eAAe,MAAM;AAE3B,QAAI,aAAa,WAAW,EAAG;AAE/B,UAAM,SAAS,aAAa,aAAa,SAAS,CAAC;AACnD,UAAM,QAAQ,OAAO,KAAK,WAAW;AAErC,aAAS,QAAQ,GAAG,SAAS,MAAM,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACrE,YAAM,OAAO,MAAM,KAAK;AAExB,UAAI,CAAC,gBAAgB,KAAK,QAAQ,IAAI,GAAG;AACvC,eAAO,IAAI,IAAI,YAAY,IAAI;MACrC;IACA;EACA;AAEA,WAAS,0BAA2B,OAAO;AACzC,UAAM,cAAc,MAAM,sBAAsB,IAAG;AACnD,UAAM,QAAQ,OAAO,KAAK,WAAW;AAErC,aAAS,QAAQ,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AACzD,YAAM,QAAQ,YAAY,MAAM,KAAK,CAAC;AAEtC,UAAI,MAAM,SAAS;AACjB,cAAM,UAAU,MAAM,KAAK,CAAC,IAAI,MAAM;MAC5C,OAAW;AACL,eAAO,MAAM,UAAU,MAAM,KAAK,CAAC;MACzC;IACA;EACA;AAEA,WAAS,cAAe,OAAO;AAC7B,WAAO;MACL,UAAU,MAAM;MAChB,MAAM,MAAM;MACZ,WAAW,MAAM;MACjB,YAAY,MAAM;MAClB,gBAAgB,MAAM;MACtB,KAAK,MAAM;MACX,QAAQ,MAAM;MACd,MAAM,MAAM;MACZ,QAAQ,MAAM;IAClB;EACA;AAEA,WAAS,aAAc,OAAO,UAAU;AACtC,UAAM,WAAW,SAAS;AAC1B,UAAM,OAAO,SAAS;AACtB,UAAM,YAAY,SAAS;AAC3B,UAAM,aAAa,SAAS;AAC5B,UAAM,iBAAiB,SAAS;AAChC,UAAM,MAAM,SAAS;AACrB,UAAM,SAAS,SAAS;AACxB,UAAM,OAAO,SAAS;AACtB,UAAM,SAAS,SAAS;EAC1B;AAEA,QAAM,oBAAoB;IAExB,MAAM,SAAS,oBAAqB,OAAO,MAAM,MAAM;AACrD,UAAI,MAAM,YAAY,MAAM;AAC1B,mBAAW,OAAO,gCAAgC;MACxD;AAEI,UAAI,KAAK,WAAW,GAAG;AACrB,mBAAW,OAAO,6CAA6C;MACrE;AAEI,YAAM,QAAQ,uBAAuB,KAAK,KAAK,CAAC,CAAC;AAEjD,UAAI,UAAU,MAAM;AAClB,mBAAW,OAAO,2CAA2C;MACnE;AAEI,YAAM,QAAQ,SAAS,MAAM,CAAC,GAAG,EAAE;AACnC,YAAM,QAAQ,SAAS,MAAM,CAAC,GAAG,EAAE;AAEnC,UAAI,UAAU,GAAG;AACf,mBAAW,OAAO,2CAA2C;MACnE;AAEI,YAAM,UAAU,KAAK,CAAC;AACtB,YAAM,kBAAmB,QAAQ;AAEjC,UAAI,UAAU,KAAK,UAAU,GAAG;AAC9B,qBAAa,OAAO,0CAA0C;MACpE;IACA;IAEE,KAAK,SAAS,mBAAoB,OAAO,MAAM,MAAM;AACnD,UAAI;AAEJ,UAAI,KAAK,WAAW,GAAG;AACrB,mBAAW,OAAO,6CAA6C;MACrE;AAEI,YAAM,SAAS,KAAK,CAAC;AACrB,eAAS,KAAK,CAAC;AAEf,UAAI,CAAC,mBAAmB,KAAK,MAAM,GAAG;AACpC,mBAAW,OAAO,6DAA6D;MACrF;AAEI,UAAI,gBAAgB,KAAK,MAAM,QAAQ,MAAM,GAAG;AAC9C,mBAAW,OAAO,gDAAgD,SAAS,cAAc;MAC/F;AAEI,UAAI,CAAC,gBAAgB,KAAK,MAAM,GAAG;AACjC,mBAAW,OAAO,8DAA8D;MACtF;AAEI,UAAI;AACF,iBAAS,mBAAmB,MAAM;MACxC,SAAa,KAAK;AACZ,mBAAW,OAAO,8BAA8B,MAAM;MAC5D;AAEI,YAAM,OAAO,MAAM,IAAI;IAC3B;EACA;AAEA,WAAS,eAAgB,OAAO,OAAO,KAAK,WAAW;AACrD,QAAI,QAAQ,KAAK;AACf,YAAM,UAAU,MAAM,MAAM,MAAM,OAAO,GAAG;AAE5C,UAAI,WAAW;AACb,iBAAS,YAAY,GAAG,UAAU,QAAQ,QAAQ,YAAY,SAAS,aAAa,GAAG;AACrF,gBAAM,aAAa,QAAQ,WAAW,SAAS;AAC/C,cAAI,EAAE,eAAe,KACd,cAAc,MAAQ,cAAc,UAAY;AACrD,uBAAW,OAAO,+BAA+B;UAC3D;QACA;MACA,WAAe,sBAAsB,KAAK,OAAO,GAAG;AAC9C,mBAAW,OAAO,8CAA8C;MACtE;AAEI,YAAM,UAAU;IACpB;EACA;AAEA,WAAS,gBAAiB,OAAO;AAC/B,UAAM;AAEN,QAAI,MAAM,sBAAsB,MAAM,MAAM,iBAAiB,MAAM,mBAAmB;AACpF,iBAAW,OAAO,4CAA4C,MAAM,oBAAoB,GAAG;IAC/F;EACA;AAEA,WAAS,cAAe,OAAO,aAAa,QAAQ,iBAAiB;AACnE,QAAI,CAACC,QAAO,SAAS,MAAM,GAAG;AAC5B,iBAAW,OAAO,mEAAmE;IACzF;AAGE,oBAAgB,KAAK;AAErB,UAAM,aAAa,OAAO,KAAK,MAAM;AAErC,aAAS,QAAQ,GAAG,WAAW,WAAW,QAAQ,QAAQ,UAAU,SAAS,GAAG;AAC9E,YAAM,MAAM,WAAW,KAAK;AAE5B,sBAAgB,KAAK;AAErB,UAAI,CAAC,gBAAgB,KAAK,aAAa,GAAG,GAAG;AAC3C,oBAAY,aAAa,KAAK,OAAO,GAAG,CAAC;AACzC,wBAAgB,GAAG,IAAI;MAC7B;IACA;EACA;AAEA,WAAS,iBAAkB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,WAC3E,WAAW,gBAAgB,UAAU;AAIrC,QAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,gBAAU,MAAM,UAAU,MAAM,KAAK,OAAO;AAE5C,eAAS,QAAQ,GAAG,WAAW,QAAQ,QAAQ,QAAQ,UAAU,SAAS,GAAG;AAC3E,YAAI,MAAM,QAAQ,QAAQ,KAAK,CAAC,GAAG;AACjC,qBAAW,OAAO,6CAA6C;QACvE;AAEM,YAAI,OAAO,YAAY,YAAY,OAAO,QAAQ,KAAK,CAAC,MAAM,mBAAmB;AAC/E,kBAAQ,KAAK,IAAI;QACzB;MACA;IACA;AAKE,QAAI,OAAO,YAAY,YAAY,OAAO,OAAO,MAAM,mBAAmB;AACxE,gBAAU;IACd;AAEE,cAAU,OAAO,OAAO;AAExB,QAAI,YAAY,MAAM;AACpB,gBAAU,CAAA;IACd;AAEE,QAAI,WAAW,2BAA2B;AACxC,UAAI,MAAM,QAAQ,SAAS,GAAG;AAC5B,YAAI,UAAU,SAAS,KAAK;AAC1B,qBAAW,OAAO,8BAA8B;QACxD;AAEM,iBAAS,QAAQ,GAAG,WAAW,UAAU,QAAQ,QAAQ,UAAU,SAAS,GAAG;AAC7E,wBAAc,OAAO,SAAS,UAAU,KAAK,GAAG,eAAe;QACvE;MACA,OAAW;AACL,sBAAc,OAAO,SAAS,WAAW,eAAe;MAC9D;IACA,OAAS;AACL,UAAI,CAAC,MAAM,QACP,CAAC,gBAAgB,KAAK,iBAAiB,OAAO,KAC9C,gBAAgB,KAAK,SAAS,OAAO,GAAG;AAC1C,cAAM,OAAO,aAAa,MAAM;AAChC,cAAM,YAAY,kBAAkB,MAAM;AAC1C,cAAM,WAAW,YAAY,MAAM;AACnC,mBAAW,OAAO,wBAAwB;MAChD;AAEI,kBAAY,SAAS,SAAS,SAAS;AACvC,aAAO,gBAAgB,OAAO;IAClC;AAEE,WAAO;EACT;AAEA,WAAS,cAAe,OAAO;AAC7B,UAAM,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAEhD,QAAI,OAAO,IAAc;AACvB,YAAM;IACV,WAAa,OAAO,IAAc;AAC9B,YAAM;AACN,UAAI,MAAM,MAAM,WAAW,MAAM,QAAQ,MAAM,IAAc;AAC3D,cAAM;MACZ;IACA,OAAS;AACL,iBAAW,OAAO,0BAA0B;IAChD;AAEE,UAAM,QAAQ;AACd,UAAM,YAAY,MAAM;AACxB,UAAM,iBAAiB;EACzB;AAEA,WAAS,oBAAqB,OAAO,eAAe,aAAa;AAC/D,QAAI,aAAa;AACjB,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,WAAO,OAAO,GAAG;AACf,aAAO,aAAa,EAAE,GAAG;AACvB,YAAI,OAAO,KAAiB,MAAM,mBAAmB,IAAI;AACvD,gBAAM,iBAAiB,MAAM;QACrC;AACM,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD;AAEI,UAAI,iBAAiB,OAAO,IAAa;AACvC,WAAG;AACD,eAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;QACpD,SAAe,OAAO,MAAgB,OAAO,MAAgB,OAAO;MACpE;AAEI,UAAI,MAAM,EAAE,GAAG;AACb,sBAAc,KAAK;AAEnB,aAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAC1C;AACA,cAAM,aAAa;AAEnB,eAAO,OAAO,IAAiB;AAC7B,gBAAM;AACN,eAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;QACpD;MACA,OAAW;AACL;MACN;IACA;AAEE,QAAI,gBAAgB,MAAM,eAAe,KAAK,MAAM,aAAa,aAAa;AAC5E,mBAAa,OAAO,uBAAuB;IAC/C;AAEE,WAAO;EACT;AAEA,WAAS,sBAAuB,OAAO;AACrC,QAAI,YAAY,MAAM;AACtB,QAAI,KAAK,MAAM,MAAM,WAAW,SAAS;AAIzC,SAAK,OAAO,MAAe,OAAO,OAC9B,OAAO,MAAM,MAAM,WAAW,YAAY,CAAC,KAC3C,OAAO,MAAM,MAAM,WAAW,YAAY,CAAC,GAAG;AAChD,mBAAa;AAEb,WAAK,MAAM,MAAM,WAAW,SAAS;AAErC,UAAI,OAAO,KAAK,UAAU,EAAE,GAAG;AAC7B,eAAO;MACb;IACA;AAEE,WAAO;EACT;AAEA,WAAS,iBAAkB,OAAO,OAAO;AACvC,QAAI,UAAU,GAAG;AACf,YAAM,UAAU;IACpB,WAAa,QAAQ,GAAG;AACpB,YAAM,UAAUA,QAAO,OAAO,MAAM,QAAQ,CAAC;IACjD;EACA;AAEA,WAAS,gBAAiB,OAAO,YAAY,sBAAsB;AACjE,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAM,QAAQ,MAAM;AACpB,UAAM,UAAU,MAAM;AAEtB,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,UAAU,EAAE,KACZ,gBAAgB,EAAE,KAClB,OAAO,MACP,OAAO,MACP,OAAO,MACP,OAAO,MACP,OAAO,OACP,OAAO,MACP,OAAO,MACP,OAAO,MACP,OAAO,MACP,OAAO,MACP,OAAO,IAAa;AACtB,aAAO;IACX;AAEE,QAAI,OAAO,MAAe,OAAO,IAAa;AAC5C,YAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAE3D,UAAI,UAAU,SAAS,KAClB,wBAAwB,gBAAgB,SAAS,GAAI;AACxD,eAAO;MACb;IACA;AAEE,UAAM,OAAO;AACb,UAAM,SAAS;AACf,mBAAe,aAAa,MAAM;AAClC,wBAAoB;AAEpB,WAAO,OAAO,GAAG;AACf,UAAI,OAAO,IAAa;AACtB,cAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAE3D,YAAI,UAAU,SAAS,KAClB,wBAAwB,gBAAgB,SAAS,GAAI;AACxD;QACR;MACA,WAAe,OAAO,IAAa;AAC7B,cAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAE3D,YAAI,UAAU,SAAS,GAAG;AACxB;QACR;MACA,WAAgB,MAAM,aAAa,MAAM,aAAa,sBAAsB,KAAK,KACjE,wBAAwB,gBAAgB,EAAE,GAAI;AACxD;MACN,WAAe,MAAM,EAAE,GAAG;AACpB,gBAAQ,MAAM;AACd,qBAAa,MAAM;AACnB,sBAAc,MAAM;AACpB,4BAAoB,OAAO,OAAO,EAAE;AAEpC,YAAI,MAAM,cAAc,YAAY;AAClC,8BAAoB;AACpB,eAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAC1C;QACR,OAAa;AACL,gBAAM,WAAW;AACjB,gBAAM,OAAO;AACb,gBAAM,YAAY;AAClB,gBAAM,aAAa;AACnB;QACR;MACA;AAEI,UAAI,mBAAmB;AACrB,uBAAe,OAAO,cAAc,YAAY,KAAK;AACrD,yBAAiB,OAAO,MAAM,OAAO,KAAK;AAC1C,uBAAe,aAAa,MAAM;AAClC,4BAAoB;MAC1B;AAEI,UAAI,CAAC,aAAa,EAAE,GAAG;AACrB,qBAAa,MAAM,WAAW;MACpC;AAEI,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;IAChD;AAEE,mBAAe,OAAO,cAAc,YAAY,KAAK;AAErD,QAAI,MAAM,QAAQ;AAChB,aAAO;IACX;AAEE,UAAM,OAAO;AACb,UAAM,SAAS;AACf,WAAO;EACT;AAEA,WAAS,uBAAwB,OAAO,YAAY;AAClD,QAAI;AACJ,QAAI;AAEJ,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,IAAa;AACtB,aAAO;IACX;AAEE,UAAM,OAAO;AACb,UAAM,SAAS;AACf,UAAM;AACN,mBAAe,aAAa,MAAM;AAElC,YAAQ,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ,OAAO,GAAG;AAC1D,UAAI,OAAO,IAAa;AACtB,uBAAe,OAAO,cAAc,MAAM,UAAU,IAAI;AACxD,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,YAAI,OAAO,IAAa;AACtB,yBAAe,MAAM;AACrB,gBAAM;AACN,uBAAa,MAAM;QAC3B,OAAa;AACL,iBAAO;QACf;MACA,WAAe,MAAM,EAAE,GAAG;AACpB,uBAAe,OAAO,cAAc,YAAY,IAAI;AACpD,yBAAiB,OAAO,oBAAoB,OAAO,OAAO,UAAU,CAAC;AACrE,uBAAe,aAAa,MAAM;MACxC,WAAe,MAAM,aAAa,MAAM,aAAa,sBAAsB,KAAK,GAAG;AAC7E,mBAAW,OAAO,8DAA8D;MACtF,OAAW;AACL,cAAM;AACN,YAAI,CAAC,aAAa,EAAE,GAAG;AACrB,uBAAa,MAAM;QAC3B;MACA;IACA;AAEE,eAAW,OAAO,4DAA4D;EAChF;AAEA,WAAS,uBAAwB,OAAO,YAAY;AAClD,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,IAAa;AACtB,aAAO;IACX;AAEE,UAAM,OAAO;AACb,UAAM,SAAS;AACf,UAAM;AACN,mBAAe,aAAa,MAAM;AAElC,YAAQ,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ,OAAO,GAAG;AAC1D,UAAI,OAAO,IAAa;AACtB,uBAAe,OAAO,cAAc,MAAM,UAAU,IAAI;AACxD,cAAM;AACN,eAAO;MACb,WAAe,OAAO,IAAa;AAC7B,uBAAe,OAAO,cAAc,MAAM,UAAU,IAAI;AACxD,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,YAAI,MAAM,EAAE,GAAG;AACb,8BAAoB,OAAO,OAAO,UAAU;QAGpD,WAAiB,KAAK,OAAO,kBAAkB,EAAE,GAAG;AAC5C,gBAAM,UAAU,gBAAgB,EAAE;AAClC,gBAAM;QACd,YAAkB,MAAM,cAAc,EAAE,KAAK,GAAG;AACxC,cAAI,YAAY;AAChB,cAAI,YAAY;AAEhB,iBAAO,YAAY,GAAG,aAAa;AACjC,iBAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,iBAAK,MAAM,YAAY,EAAE,MAAM,GAAG;AAChC,2BAAa,aAAa,KAAK;YAC3C,OAAiB;AACL,yBAAW,OAAO,gCAAgC;YAC9D;UACA;AAEQ,gBAAM,UAAU,kBAAkB,SAAS;AAE3C,gBAAM;QACd,OAAa;AACL,qBAAW,OAAO,yBAAyB;QACnD;AAEM,uBAAe,aAAa,MAAM;MACxC,WAAe,MAAM,EAAE,GAAG;AACpB,uBAAe,OAAO,cAAc,YAAY,IAAI;AACpD,yBAAiB,OAAO,oBAAoB,OAAO,OAAO,UAAU,CAAC;AACrE,uBAAe,aAAa,MAAM;MACxC,WAAe,MAAM,aAAa,MAAM,aAAa,sBAAsB,KAAK,GAAG;AAC7E,mBAAW,OAAO,8DAA8D;MACtF,OAAW;AACL,cAAM;AACN,YAAI,CAAC,aAAa,EAAE,GAAG;AACrB,uBAAa,MAAM;QAC3B;MACA;IACA;AAEE,eAAW,OAAO,4DAA4D;EAChF;AAEA,WAAS,mBAAoB,OAAO,YAAY;AAC9C,QAAI,WAAW;AACf,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAM,OAAO,MAAM;AACnB,QAAI;AACJ,UAAM,UAAU,MAAM;AACtB,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAM,kBAAkB,uBAAO,OAAO,IAAI;AAC1C,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,IAAa;AACtB,mBAAa;AACb,kBAAY;AACZ,gBAAU,CAAA;IACd,WAAa,OAAO,KAAa;AAC7B,mBAAa;AACb,kBAAY;AACZ,gBAAU,CAAA;IACd,OAAS;AACL,aAAO;IACX;AAEE,QAAI,MAAM,WAAW,MAAM;AACzB,kBAAY,OAAO,MAAM,QAAQ,OAAO;IAC5C;AAEE,SAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,WAAO,OAAO,GAAG;AACf,0BAAoB,OAAO,MAAM,UAAU;AAE3C,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,UAAI,OAAO,YAAY;AACrB,cAAM;AACN,cAAM,MAAM;AACZ,cAAM,SAAS;AACf,cAAM,OAAO,YAAY,YAAY;AACrC,cAAM,SAAS;AACf,eAAO;MACb,WAAe,CAAC,UAAU;AACpB,mBAAW,OAAO,8CAA8C;MACtE,WAAe,OAAO,IAAa;AAE7B,mBAAW,OAAO,0CAA0C;MAClE;AAEI,eAAS,UAAU,YAAY;AAC/B,eAAS,iBAAiB;AAE1B,UAAI,OAAO,IAAa;AACtB,cAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAE3D,YAAI,UAAU,SAAS,GAAG;AACxB,mBAAS,iBAAiB;AAC1B,gBAAM;AACN,8BAAoB,OAAO,MAAM,UAAU;QACnD;MACA;AAEI,cAAQ,MAAM;AACd,mBAAa,MAAM;AACnB,aAAO,MAAM;AACb,kBAAY,OAAO,YAAY,iBAAiB,OAAO,IAAI;AAC3D,eAAS,MAAM;AACf,gBAAU,MAAM;AAChB,0BAAoB,OAAO,MAAM,UAAU;AAE3C,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,WAAK,kBAAkB,MAAM,SAAS,UAAU,OAAO,IAAa;AAClE,iBAAS;AACT,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAC5C,4BAAoB,OAAO,MAAM,UAAU;AAC3C,oBAAY,OAAO,YAAY,iBAAiB,OAAO,IAAI;AAC3D,oBAAY,MAAM;MACxB;AAEI,UAAI,WAAW;AACb,yBAAiB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,WAAW,OAAO,YAAY,IAAI;MAC3G,WAAe,QAAQ;AACjB,gBAAQ,KAAK,iBAAiB,OAAO,MAAM,iBAAiB,QAAQ,SAAS,WAAW,OAAO,YAAY,IAAI,CAAC;MACtH,OAAW;AACL,gBAAQ,KAAK,OAAO;MAC1B;AAEI,0BAAoB,OAAO,MAAM,UAAU;AAE3C,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,UAAI,OAAO,IAAa;AACtB,mBAAW;AACX,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD,OAAW;AACL,mBAAW;MACjB;IACA;AAEE,eAAW,OAAO,uDAAuD;EAC3E;AAEA,WAAS,gBAAiB,OAAO,YAAY;AAC3C,QAAI;AACJ,QAAI,WAAW;AACf,QAAI,iBAAiB;AACrB,QAAI,iBAAiB;AACrB,QAAI,aAAa;AACjB,QAAI,aAAa;AACjB,QAAI,iBAAiB;AACrB,QAAI;AAEJ,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,KAAa;AACtB,gBAAU;IACd,WAAa,OAAO,IAAa;AAC7B,gBAAU;IACd,OAAS;AACL,aAAO;IACX;AAEE,UAAM,OAAO;AACb,UAAM,SAAS;AAEf,WAAO,OAAO,GAAG;AACf,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,UAAI,OAAO,MAAe,OAAO,IAAa;AAC5C,YAAI,kBAAkB,UAAU;AAC9B,qBAAY,OAAO,KAAe,gBAAgB;QAC1D,OAAa;AACL,qBAAW,OAAO,sCAAsC;QAChE;MACA,YAAgB,MAAM,gBAAgB,EAAE,MAAM,GAAG;AAC3C,YAAI,QAAQ,GAAG;AACb,qBAAW,OAAO,8EAA8E;QACxG,WAAiB,CAAC,gBAAgB;AAC1B,uBAAa,aAAa,MAAM;AAChC,2BAAiB;QACzB,OAAa;AACL,qBAAW,OAAO,2CAA2C;QACrE;MACA,OAAW;AACL;MACN;IACA;AAEE,QAAI,aAAa,EAAE,GAAG;AACpB,SAAG;AAAE,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAAC,SAC3C,aAAa,EAAE;AAEtB,UAAI,OAAO,IAAa;AACtB,WAAG;AAAE,eAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;QAAC,SAC3C,CAAC,MAAM,EAAE,KAAM,OAAO;MACnC;IACA;AAEE,WAAO,OAAO,GAAG;AACf,oBAAc,KAAK;AACnB,YAAM,aAAa;AAEnB,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAG1C,cAAQ,CAAC,kBAAkB,MAAM,aAAa,eACtC,OAAO,IAAkB;AAC/B,cAAM;AACN,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD;AAEI,UAAI,CAAC,kBAAkB,MAAM,aAAa,YAAY;AACpD,qBAAa,MAAM;MACzB;AAEI,UAAI,MAAM,EAAE,GAAG;AACb;AACA;MACN;AAEI,UAAI,CAAC,kBAAkB,eAAe,GAAG;AACvC,mBAAW,OAAO,sCAAsC;MAC9D;AAGI,UAAI,MAAM,aAAa,YAAY;AAEjC,YAAI,aAAa,eAAe;AAC9B,gBAAM,UAAUA,QAAO,OAAO,MAAM,iBAAiB,IAAI,aAAa,UAAU;QACxF,WAAiB,aAAa,eAAe;AACrC,cAAI,gBAAgB;AAClB,kBAAM,UAAU;UAC1B;QACA;AAGM;MACN;AAGI,UAAI,SAAS;AAEX,YAAI,aAAa,EAAE,GAAG;AACpB,2BAAiB;AAEjB,gBAAM,UAAUA,QAAO,OAAO,MAAM,iBAAiB,IAAI,aAAa,UAAU;QAGxF,WAAiB,gBAAgB;AACzB,2BAAiB;AACjB,gBAAM,UAAUA,QAAO,OAAO,MAAM,aAAa,CAAC;QAG1D,WAAiB,eAAe,GAAG;AAC3B,cAAI,gBAAgB;AAClB,kBAAM,UAAU;UAC1B;QAGA,OAAa;AACL,gBAAM,UAAUA,QAAO,OAAO,MAAM,UAAU;QACtD;MAGA,OAAW;AAEL,cAAM,UAAUA,QAAO,OAAO,MAAM,iBAAiB,IAAI,aAAa,UAAU;MACtF;AAEI,uBAAiB;AACjB,uBAAiB;AACjB,mBAAa;AACb,YAAM,eAAe,MAAM;AAE3B,aAAO,CAAC,MAAM,EAAE,KAAM,OAAO,GAAI;AAC/B,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD;AAEI,qBAAe,OAAO,cAAc,MAAM,UAAU,KAAK;IAC7D;AAEE,WAAO;EACT;AAEA,WAAS,kBAAmB,OAAO,YAAY;AAC7C,UAAM,OAAO,MAAM;AACnB,UAAM,UAAU,MAAM;AACtB,UAAM,UAAU,CAAA;AAChB,QAAI,WAAW;AAIf,QAAI,MAAM,mBAAmB,GAAI,QAAO;AAExC,QAAI,MAAM,WAAW,MAAM;AACzB,kBAAY,OAAO,MAAM,QAAQ,OAAO;IAC5C;AAEE,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,WAAO,OAAO,GAAG;AACf,UAAI,MAAM,mBAAmB,IAAI;AAC/B,cAAM,WAAW,MAAM;AACvB,mBAAW,OAAO,gDAAgD;MACxE;AAEI,UAAI,OAAO,IAAa;AACtB;MACN;AAEI,YAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAE3D,UAAI,CAAC,UAAU,SAAS,GAAG;AACzB;MACN;AAEI,iBAAW;AACX,YAAM;AAEN,UAAI,oBAAoB,OAAO,MAAM,EAAE,GAAG;AACxC,YAAI,MAAM,cAAc,YAAY;AAClC,kBAAQ,KAAK,IAAI;AACjB,eAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAC1C;QACR;MACA;AAEI,YAAM,QAAQ,MAAM;AACpB,kBAAY,OAAO,YAAY,kBAAkB,OAAO,IAAI;AAC5D,cAAQ,KAAK,MAAM,MAAM;AACzB,0BAAoB,OAAO,MAAM,EAAE;AAEnC,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,WAAK,MAAM,SAAS,SAAS,MAAM,aAAa,eAAgB,OAAO,GAAI;AACzE,mBAAW,OAAO,qCAAqC;MAC7D,WAAe,MAAM,aAAa,YAAY;AACxC;MACN;IACA;AAEE,QAAI,UAAU;AACZ,YAAM,MAAM;AACZ,YAAM,SAAS;AACf,YAAM,OAAO;AACb,YAAM,SAAS;AACf,aAAO;IACX;AACE,WAAO;EACT;AAEA,WAAS,iBAAkB,OAAO,YAAY,YAAY;AACxD,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,UAAM,OAAO,MAAM;AACnB,UAAM,UAAU,MAAM;AACtB,UAAM,UAAU,CAAA;AAChB,UAAM,kBAAkB,uBAAO,OAAO,IAAI;AAC1C,QAAI,SAAS;AACb,QAAI,UAAU;AACd,QAAI,YAAY;AAChB,QAAI,gBAAgB;AACpB,QAAI,WAAW;AAIf,QAAI,MAAM,mBAAmB,GAAI,QAAO;AAExC,QAAI,MAAM,WAAW,MAAM;AACzB,kBAAY,OAAO,MAAM,QAAQ,OAAO;IAC5C;AAEE,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,WAAO,OAAO,GAAG;AACf,UAAI,CAAC,iBAAiB,MAAM,mBAAmB,IAAI;AACjD,cAAM,WAAW,MAAM;AACvB,mBAAW,OAAO,gDAAgD;MACxE;AAEI,YAAM,YAAY,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC;AAC3D,YAAM,QAAQ,MAAM;AAMpB,WAAK,OAAO,MAAe,OAAO,OAAgB,UAAU,SAAS,GAAG;AACtE,YAAI,OAAO,IAAa;AACtB,cAAI,eAAe;AACjB,6BAAiB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,MAAM,UAAU,eAAe,OAAO;AACzG,qBAAS,UAAU,YAAY;UACzC;AAEQ,qBAAW;AACX,0BAAgB;AAChB,yBAAe;QACvB,WAAiB,eAAe;AAExB,0BAAgB;AAChB,yBAAe;QACvB,OAAa;AACL,qBAAW,OAAO,mGAAmG;QAC7H;AAEM,cAAM,YAAY;AAClB,aAAK;MAKX,OAAW;AACL,mBAAW,MAAM;AACjB,wBAAgB,MAAM;AACtB,kBAAU,MAAM;AAEhB,YAAI,CAAC,YAAY,OAAO,YAAY,kBAAkB,OAAO,IAAI,GAAG;AAGlE;QACR;AAEM,YAAI,MAAM,SAAS,OAAO;AACxB,eAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,iBAAO,aAAa,EAAE,GAAG;AACvB,iBAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;UACtD;AAEQ,cAAI,OAAO,IAAa;AACtB,iBAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,gBAAI,CAAC,UAAU,EAAE,GAAG;AAClB,yBAAW,OAAO,yFAAyF;YACvH;AAEU,gBAAI,eAAe;AACjB,+BAAiB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,MAAM,UAAU,eAAe,OAAO;AACzG,uBAAS,UAAU,YAAY;YAC3C;AAEU,uBAAW;AACX,4BAAgB;AAChB,2BAAe;AACf,qBAAS,MAAM;AACf,sBAAU,MAAM;UAC1B,WAAmB,UAAU;AACnB,uBAAW,OAAO,0DAA0D;UACtF,OAAe;AACL,kBAAM,MAAM;AACZ,kBAAM,SAAS;AACf,mBAAO;UACjB;QACA,WAAiB,UAAU;AACnB,qBAAW,OAAO,gFAAgF;QAC1G,OAAa;AACL,gBAAM,MAAM;AACZ,gBAAM,SAAS;AACf,iBAAO;QACf;MACA;AAKI,UAAI,MAAM,SAAS,SAAS,MAAM,aAAa,YAAY;AACzD,YAAI,eAAe;AACjB,qBAAW,MAAM;AACjB,0BAAgB,MAAM;AACtB,oBAAU,MAAM;QACxB;AAEM,YAAI,YAAY,OAAO,YAAY,mBAAmB,MAAM,YAAY,GAAG;AACzE,cAAI,eAAe;AACjB,sBAAU,MAAM;UAC1B,OAAe;AACL,wBAAY,MAAM;UAC5B;QACA;AAEM,YAAI,CAAC,eAAe;AAClB,2BAAiB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,WAAW,UAAU,eAAe,OAAO;AAC9G,mBAAS,UAAU,YAAY;QACvC;AAEM,4BAAoB,OAAO,MAAM,EAAE;AACnC,aAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;MAChD;AAEI,WAAK,MAAM,SAAS,SAAS,MAAM,aAAa,eAAgB,OAAO,GAAI;AACzE,mBAAW,OAAO,oCAAoC;MAC5D,WAAe,MAAM,aAAa,YAAY;AACxC;MACN;IACA;AAOE,QAAI,eAAe;AACjB,uBAAiB,OAAO,SAAS,iBAAiB,QAAQ,SAAS,MAAM,UAAU,eAAe,OAAO;IAC7G;AAGE,QAAI,UAAU;AACZ,YAAM,MAAM;AACZ,YAAM,SAAS;AACf,YAAM,OAAO;AACb,YAAM,SAAS;IACnB;AAEE,WAAO;EACT;AAEA,WAAS,gBAAiB,OAAO;AAC/B,QAAI,aAAa;AACjB,QAAI,UAAU;AACd,QAAI;AACJ,QAAI;AAEJ,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,GAAa,QAAO;AAE/B,QAAI,MAAM,QAAQ,MAAM;AACtB,iBAAW,OAAO,+BAA+B;IACrD;AAEE,SAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAE5C,QAAI,OAAO,IAAa;AACtB,mBAAa;AACb,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;IAChD,WAAa,OAAO,IAAa;AAC7B,gBAAU;AACV,kBAAY;AACZ,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;IAChD,OAAS;AACL,kBAAY;IAChB;AAEE,QAAI,YAAY,MAAM;AAEtB,QAAI,YAAY;AACd,SAAG;AAAE,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAAC,SAC3C,OAAO,KAAK,OAAO;AAE1B,UAAI,MAAM,WAAW,MAAM,QAAQ;AACjC,kBAAU,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ;AACrD,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD,OAAW;AACL,mBAAW,OAAO,oDAAoD;MAC5E;IACA,OAAS;AACL,aAAO,OAAO,KAAK,CAAC,UAAU,EAAE,GAAG;AACjC,YAAI,OAAO,IAAa;AACtB,cAAI,CAAC,SAAS;AACZ,wBAAY,MAAM,MAAM,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC;AAE/D,gBAAI,CAAC,mBAAmB,KAAK,SAAS,GAAG;AACvC,yBAAW,OAAO,iDAAiD;YAC/E;AAEU,sBAAU;AACV,wBAAY,MAAM,WAAW;UACvC,OAAe;AACL,uBAAW,OAAO,6CAA6C;UACzE;QACA;AAEM,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD;AAEI,gBAAU,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ;AAErD,UAAI,wBAAwB,KAAK,OAAO,GAAG;AACzC,mBAAW,OAAO,qDAAqD;MAC7E;IACA;AAEE,QAAI,WAAW,CAAC,gBAAgB,KAAK,OAAO,GAAG;AAC7C,iBAAW,OAAO,8CAA8C,OAAO;IAC3E;AAEE,QAAI;AACF,gBAAU,mBAAmB,OAAO;IACxC,SAAW,KAAK;AACZ,iBAAW,OAAO,4BAA4B,OAAO;IACzD;AAEE,QAAI,YAAY;AACd,YAAM,MAAM;IAChB,WAAa,gBAAgB,KAAK,MAAM,QAAQ,SAAS,GAAG;AACxD,YAAM,MAAM,MAAM,OAAO,SAAS,IAAI;IAC1C,WAAa,cAAc,KAAK;AAC5B,YAAM,MAAM,MAAM;IACtB,WAAa,cAAc,MAAM;AAC7B,YAAM,MAAM,uBAAuB;IACvC,OAAS;AACL,iBAAW,OAAO,4BAA4B,YAAY,GAAG;IACjE;AAEE,WAAO;EACT;AAEA,WAAS,mBAAoB,OAAO;AAClC,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,GAAa,QAAO;AAE/B,QAAI,MAAM,WAAW,MAAM;AACzB,iBAAW,OAAO,mCAAmC;IACzD;AAEE,SAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAC5C,UAAM,YAAY,MAAM;AAExB,WAAO,OAAO,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,gBAAgB,EAAE,GAAG;AACzD,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;IAChD;AAEE,QAAI,MAAM,aAAa,WAAW;AAChC,iBAAW,OAAO,4DAA4D;IAClF;AAEE,UAAM,SAAS,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ;AAC1D,WAAO;EACT;AAEA,WAAS,UAAW,OAAO;AACzB,QAAI,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE9C,QAAI,OAAO,GAAa,QAAO;AAE/B,SAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAC5C,UAAM,YAAY,MAAM;AAExB,WAAO,OAAO,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,gBAAgB,EAAE,GAAG;AACzD,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;IAChD;AAEE,QAAI,MAAM,aAAa,WAAW;AAChC,iBAAW,OAAO,2DAA2D;IACjF;AAEE,UAAM,QAAQ,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ;AAEzD,QAAI,CAAC,gBAAgB,KAAK,MAAM,WAAW,KAAK,GAAG;AACjD,iBAAW,OAAO,yBAAyB,QAAQ,GAAG;IAC1D;AAEE,UAAM,SAAS,MAAM,UAAU,KAAK;AACpC,wBAAoB,OAAO,MAAM,EAAE;AACnC,WAAO;EACT;AAEA,WAAS,gCAAiC,OAAO,eAAe,YAAY,YAAY;AACtF,UAAM,gBAAgB,cAAc,KAAK;AAEzC,2BAAuB,KAAK;AAC5B,iBAAa,OAAO,aAAa;AAIjC,UAAM,MAAM;AACZ,UAAM,SAAS;AACf,UAAM,OAAO;AACb,UAAM,SAAS;AAEf,QAAI,iBAAiB,OAAO,YAAY,UAAU,KAAK,MAAM,SAAS,WAAW;AAC/E,8BAAwB,KAAK;AAC7B,aAAO;IACX;AAEE,8BAA0B,KAAK;AAC/B,iBAAa,OAAO,aAAa;AACjC,WAAO;EACT;AAEA,WAAS,YAAa,OAAO,cAAc,aAAa,aAAa,cAAc;AACjF,QAAI;AACJ,QAAI;AACJ,QAAI,eAAe;AACnB,QAAI,YAAY;AAChB,QAAI,aAAa;AACjB,QAAI,gBAAgB;AACpB,QAAIO;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,MAAM,SAAS,MAAM,UAAU;AACjC,iBAAW,OAAO,gCAAgC,MAAM,WAAW,GAAG;IAC1E;AAEE,UAAM,SAAS;AAEf,QAAI,MAAM,aAAa,MAAM;AAC3B,YAAM,SAAS,QAAQ,KAAK;IAChC;AAEE,UAAM,MAAM;AACZ,UAAM,SAAS;AACf,UAAM,OAAO;AACb,UAAM,SAAS;AAEf,UAAM,mBAAmB,oBAAoB,wBAC3C,sBAAsB,eACtB,qBAAqB;AAEvB,QAAI,aAAa;AACf,UAAI,oBAAoB,OAAO,MAAM,EAAE,GAAG;AACxC,oBAAY;AAEZ,YAAI,MAAM,aAAa,cAAc;AACnC,yBAAe;QACvB,WAAiB,MAAM,eAAe,cAAc;AAC5C,yBAAe;QACvB,WAAiB,MAAM,aAAa,cAAc;AAC1C,yBAAe;QACvB;MACA;IACA;AAEE,QAAI,iBAAiB,GAAG;AACtB,aAAO,MAAM;AACX,cAAM,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAChD,cAAM,gBAAgB,cAAc,KAAK;AAIzC,YAAI,cACE,OAAO,MAAe,MAAM,QAAQ,QACpC,OAAO,MAAe,MAAM,WAAW,OAAQ;AACnD;QACR;AAEM,YAAI,CAAC,gBAAgB,KAAK,KAAK,CAAC,mBAAmB,KAAK,GAAG;AACzD;QACR;AAEM,YAAI,kBAAkB,MAAM;AAC1B,0BAAgB;QACxB;AAEM,YAAI,oBAAoB,OAAO,MAAM,EAAE,GAAG;AACxC,sBAAY;AACZ,kCAAwB;AAExB,cAAI,MAAM,aAAa,cAAc;AACnC,2BAAe;UACzB,WAAmB,MAAM,eAAe,cAAc;AAC5C,2BAAe;UACzB,WAAmB,MAAM,aAAa,cAAc;AAC1C,2BAAe;UACzB;QACA,OAAa;AACL,kCAAwB;QAChC;MACA;IACA;AAEE,QAAI,uBAAuB;AACzB,8BAAwB,aAAa;IACzC;AAEE,QAAI,iBAAiB,KAAK,sBAAsB,aAAa;AAC3D,UAAI,oBAAoB,eAAe,qBAAqB,aAAa;AACvE,qBAAa;MACnB,OAAW;AACL,qBAAa,eAAe;MAClC;AAEI,oBAAc,MAAM,WAAW,MAAM;AAErC,UAAI,iBAAiB,GAAG;AACtB,YAAK,0BACA,kBAAkB,OAAO,WAAW,KAAK,iBAAiB,OAAO,aAAa,UAAU,MACzF,mBAAmB,OAAO,UAAU,GAAG;AACzC,uBAAa;QACrB,OAAa;AACL,gBAAM,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAEhD,cAAI,kBAAkB,QAAQ,oBAAoB,CAAC,yBAC/C,OAAO,OAAe,OAAO,MAC7B;YACE;YACA;YACA,cAAc,WAAW,cAAc;YACvC;UACd,GAAe;AACL,yBAAa;UACvB,WAAoB,qBAAqB,gBAAgB,OAAO,UAAU,KAC9D,uBAAuB,OAAO,UAAU,KACxC,uBAAuB,OAAO,UAAU,GAAG;AAC7C,yBAAa;UACvB,WAAmB,UAAU,KAAK,GAAG;AAC3B,yBAAa;AAEb,gBAAI,MAAM,QAAQ,QAAQ,MAAM,WAAW,MAAM;AAC/C,yBAAW,OAAO,2CAA2C;YACzE;UACA,WAAmB,gBAAgB,OAAO,YAAY,oBAAoB,WAAW,GAAG;AAC9E,yBAAa;AAEb,gBAAI,MAAM,QAAQ,MAAM;AACtB,oBAAM,MAAM;YACxB;UACA;AAEQ,cAAI,MAAM,WAAW,MAAM;AACzB,wBAAY,OAAO,MAAM,QAAQ,MAAM,MAAM;UACvD;QACA;MACA,WAAe,iBAAiB,GAAG;AAG7B,qBAAa,yBAAyB,kBAAkB,OAAO,WAAW;MAChF;IACA;AAEE,QAAI,MAAM,QAAQ,MAAM;AACtB,UAAI,MAAM,WAAW,MAAM;AACzB,oBAAY,OAAO,MAAM,QAAQ,MAAM,MAAM;MACnD;IACA,WAAa,MAAM,QAAQ,KAAK;AAO5B,UAAI,MAAM,WAAW,QAAQ,MAAM,SAAS,UAAU;AACpD,mBAAW,OAAO,sEAAsE,MAAM,OAAO,GAAG;MAC9G;AAEI,eAAS,YAAY,GAAG,eAAe,MAAM,cAAc,QAAQ,YAAY,cAAc,aAAa,GAAG;AAC3GA,gBAAO,MAAM,cAAc,SAAS;AAEpC,YAAIA,MAAK,QAAQ,MAAM,MAAM,GAAG;AAC9B,gBAAM,SAASA,MAAK,UAAU,MAAM,MAAM;AAC1C,gBAAM,MAAMA,MAAK;AACjB,cAAI,MAAM,WAAW,MAAM;AACzB,wBAAY,OAAO,MAAM,QAAQ,MAAM,MAAM;UACvD;AACQ;QACR;MACA;IACA,WAAa,MAAM,QAAQ,KAAK;AAC5B,UAAI,gBAAgB,KAAK,MAAM,QAAQ,MAAM,QAAQ,UAAU,GAAG,MAAM,GAAG,GAAG;AAC5EA,gBAAO,MAAM,QAAQ,MAAM,QAAQ,UAAU,EAAE,MAAM,GAAG;MAC9D,OAAW;AAELA,gBAAO;AACP,cAAM,WAAW,MAAM,QAAQ,MAAM,MAAM,QAAQ,UAAU;AAE7D,iBAAS,YAAY,GAAG,eAAe,SAAS,QAAQ,YAAY,cAAc,aAAa,GAAG;AAChG,cAAI,MAAM,IAAI,MAAM,GAAG,SAAS,SAAS,EAAE,IAAI,MAAM,MAAM,SAAS,SAAS,EAAE,KAAK;AAClFA,oBAAO,SAAS,SAAS;AACzB;UACV;QACA;MACA;AAEI,UAAI,CAACA,OAAM;AACT,mBAAW,OAAO,mBAAmB,MAAM,MAAM,GAAG;MAC1D;AAEI,UAAI,MAAM,WAAW,QAAQA,MAAK,SAAS,MAAM,MAAM;AACrD,mBAAW,OAAO,kCAAkC,MAAM,MAAM,0BAA0BA,MAAK,OAAO,aAAa,MAAM,OAAO,GAAG;MACzI;AAEI,UAAI,CAACA,MAAK,QAAQ,MAAM,QAAQ,MAAM,GAAG,GAAG;AAC1C,mBAAW,OAAO,kCAAkC,MAAM,MAAM,gBAAgB;MACtF,OAAW;AACL,cAAM,SAASA,MAAK,UAAU,MAAM,QAAQ,MAAM,GAAG;AACrD,YAAI,MAAM,WAAW,MAAM;AACzB,sBAAY,OAAO,MAAM,QAAQ,MAAM,MAAM;QACrD;MACA;IACA;AAEE,QAAI,MAAM,aAAa,MAAM;AAC3B,YAAM,SAAS,SAAS,KAAK;IACjC;AAEE,UAAM,SAAS;AACf,WAAO,MAAM,QAAQ,QAAQ,MAAM,WAAW,QAAQ;EACxD;AAEA,WAAS,aAAc,OAAO;AAC5B,UAAM,gBAAgB,MAAM;AAC5B,QAAI,gBAAgB;AACpB,QAAI;AAEJ,UAAM,UAAU;AAChB,UAAM,kBAAkB,MAAM;AAC9B,UAAM,SAAS,uBAAO,OAAO,IAAI;AACjC,UAAM,YAAY,uBAAO,OAAO,IAAI;AAEpC,YAAQ,KAAK,MAAM,MAAM,WAAW,MAAM,QAAQ,OAAO,GAAG;AAC1D,0BAAoB,OAAO,MAAM,EAAE;AAEnC,WAAK,MAAM,MAAM,WAAW,MAAM,QAAQ;AAE1C,UAAI,MAAM,aAAa,KAAK,OAAO,IAAa;AAC9C;MACN;AAEI,sBAAgB;AAChB,WAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;AAC5C,UAAI,YAAY,MAAM;AAEtB,aAAO,OAAO,KAAK,CAAC,UAAU,EAAE,GAAG;AACjC,aAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;MAClD;AAEI,YAAM,gBAAgB,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ;AACjE,YAAM,gBAAgB,CAAA;AAEtB,UAAI,cAAc,SAAS,GAAG;AAC5B,mBAAW,OAAO,8DAA8D;MACtF;AAEI,aAAO,OAAO,GAAG;AACf,eAAO,aAAa,EAAE,GAAG;AACvB,eAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;QACpD;AAEM,YAAI,OAAO,IAAa;AACtB,aAAG;AAAE,iBAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;UAAC,SAC3C,OAAO,KAAK,CAAC,MAAM,EAAE;AAC5B;QACR;AAEM,YAAI,MAAM,EAAE,EAAG;AAEf,oBAAY,MAAM;AAElB,eAAO,OAAO,KAAK,CAAC,UAAU,EAAE,GAAG;AACjC,eAAK,MAAM,MAAM,WAAW,EAAE,MAAM,QAAQ;QACpD;AAEM,sBAAc,KAAK,MAAM,MAAM,MAAM,WAAW,MAAM,QAAQ,CAAC;MACrE;AAEI,UAAI,OAAO,EAAG,eAAc,KAAK;AAEjC,UAAI,gBAAgB,KAAK,mBAAmB,aAAa,GAAG;AAC1D,0BAAkB,aAAa,EAAE,OAAO,eAAe,aAAa;MAC1E,OAAW;AACL,qBAAa,OAAO,iCAAiC,gBAAgB,GAAG;MAC9E;IACA;AAEE,wBAAoB,OAAO,MAAM,EAAE;AAEnC,QAAI,MAAM,eAAe,KACrB,MAAM,MAAM,WAAW,MAAM,QAAQ,MAAM,MAC3C,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC,MAAM,MAC/C,MAAM,MAAM,WAAW,MAAM,WAAW,CAAC,MAAM,IAAa;AAC9D,YAAM,YAAY;AAClB,0BAAoB,OAAO,MAAM,EAAE;IACvC,WAAa,eAAe;AACxB,iBAAW,OAAO,iCAAiC;IACvD;AAEE,gBAAY,OAAO,MAAM,aAAa,GAAG,mBAAmB,OAAO,IAAI;AACvE,wBAAoB,OAAO,MAAM,EAAE;AAEnC,QAAI,MAAM,mBACN,8BAA8B,KAAK,MAAM,MAAM,MAAM,eAAe,MAAM,QAAQ,CAAC,GAAG;AACxF,mBAAa,OAAO,kDAAkD;IAC1E;AAEE,UAAM,UAAU,KAAK,MAAM,MAAM;AAEjC,QAAI,MAAM,aAAa,MAAM,aAAa,sBAAsB,KAAK,GAAG;AACtE,UAAI,MAAM,MAAM,WAAW,MAAM,QAAQ,MAAM,IAAa;AAC1D,cAAM,YAAY;AAClB,4BAAoB,OAAO,MAAM,EAAE;MACzC;AACI;IACJ;AAEE,QAAI,MAAM,WAAY,MAAM,SAAS,GAAI;AACvC,iBAAW,OAAO,uDAAuD;IAC7E;EACA;AAEA,WAAS,cAAe,OAAO,SAAS;AACtC,YAAQ,OAAO,KAAK;AACpB,cAAU,WAAW,CAAA;AAErB,QAAI,MAAM,WAAW,GAAG;AAEtB,UAAI,MAAM,WAAW,MAAM,SAAS,CAAC,MAAM,MACvC,MAAM,WAAW,MAAM,SAAS,CAAC,MAAM,IAAc;AACvD,iBAAS;MACf;AAGI,UAAI,MAAM,WAAW,CAAC,MAAM,OAAQ;AAClC,gBAAQ,MAAM,MAAM,CAAC;MAC3B;IACA;AAEE,UAAM,QAAQ,IAAI,MAAM,OAAO,OAAO;AAEtC,UAAM,UAAU,MAAM,QAAQ,IAAI;AAElC,QAAI,YAAY,IAAI;AAClB,YAAM,WAAW;AACjB,iBAAW,OAAO,mCAAmC;IACzD;AAGE,UAAM,SAAS;AAEf,WAAO,MAAM,MAAM,WAAW,MAAM,QAAQ,MAAM,IAAiB;AACjE,YAAM,cAAc;AACpB,YAAM,YAAY;IACtB;AAEE,WAAO,MAAM,WAAY,MAAM,SAAS,GAAI;AAC1C,mBAAa,KAAK;IACtB;AAEE,WAAO,MAAM;EACf;AAEA,WAASQ,SAAS,OAAO,UAAU,SAAS;AAC1C,QAAI,aAAa,QAAQ,OAAO,aAAa,YAAY,OAAO,YAAY,aAAa;AACvF,gBAAU;AACV,iBAAW;IACf;AAEE,UAAM,YAAY,cAAc,OAAO,OAAO;AAE9C,QAAI,OAAO,aAAa,YAAY;AAClC,aAAO;IACX;AAEE,aAAS,QAAQ,GAAG,SAAS,UAAU,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACzE,eAAS,UAAU,KAAK,CAAC;IAC7B;EACA;AAEA,WAASC,MAAM,OAAO,SAAS;AAC7B,UAAM,YAAY,cAAc,OAAO,OAAO;AAE9C,QAAI,UAAU,WAAW,GAAG;AAC1B,aAAO;IACX,WAAa,UAAU,WAAW,GAAG;AACjC,aAAO,UAAU,CAAC;IACtB;AACE,UAAM,IAAIjB,eAAc,0DAA0D;EACpF;AAEA,SAAA,UAAyBgB;AACzB,SAAA,OAAsBC;;;;;;;;ACxwDtB,QAAMhB,UAASC,cAAA;AACf,QAAMF,iBAAgBM,iBAAA;AACtB,QAAMS,kBAAiBL,gBAAA;AAEvB,QAAM,YAAY,OAAO,UAAU;AACnC,QAAM,kBAAkB,OAAO,UAAU;AAEzC,QAAM,WAAW;AACjB,QAAM,WAAW;AACjB,QAAM,iBAAiB;AACvB,QAAM,uBAAuB;AAC7B,QAAM,aAAa;AACnB,QAAM,mBAAmB;AACzB,QAAM,oBAAoB;AAC1B,QAAM,aAAa;AACnB,QAAM,eAAe;AACrB,QAAM,iBAAiB;AACvB,QAAM,oBAAoB;AAC1B,QAAM,gBAAgB;AACtB,QAAM,aAAa;AACnB,QAAM,aAAa;AACnB,QAAM,aAAa;AACnB,QAAM,cAAc;AACpB,QAAM,oBAAoB;AAC1B,QAAM,gBAAgB;AACtB,QAAM,qBAAqB;AAC3B,QAAM,2BAA2B;AACjC,QAAM,4BAA4B;AAClC,QAAM,oBAAoB;AAC1B,QAAM,0BAA0B;AAChC,QAAM,qBAAqB;AAC3B,QAAM,2BAA2B;AAEjC,QAAM,mBAAmB,CAAA;AAEzB,mBAAiB,CAAI,IAAI;AACzB,mBAAiB,CAAI,IAAI;AACzB,mBAAiB,CAAI,IAAI;AACzB,mBAAiB,CAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,EAAI,IAAI;AACzB,mBAAiB,GAAI,IAAI;AACzB,mBAAiB,GAAI,IAAI;AACzB,mBAAiB,IAAM,IAAI;AAC3B,mBAAiB,IAAM,IAAI;AAE3B,QAAM,6BAA6B;IACjC;IAAK;IAAK;IAAO;IAAO;IAAO;IAAM;IAAM;IAC3C;IAAK;IAAK;IAAM;IAAM;IAAM;IAAO;IAAO;EAC5C;AAEA,QAAM,2BAA2B;AAEjC,WAAS,gBAAiBH,SAAQH,MAAK;AACrC,QAAIA,SAAQ,KAAM,QAAO,CAAA;AAEzB,UAAM,SAAS,CAAA;AACf,UAAM,OAAO,OAAO,KAAKA,IAAG;AAE5B,aAAS,QAAQ,GAAG,SAAS,KAAK,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACpE,UAAI,MAAM,KAAK,KAAK;AACpB,UAAI,QAAQ,OAAOA,KAAI,GAAG,CAAC;AAE3B,UAAI,IAAI,MAAM,GAAG,CAAC,MAAM,MAAM;AAC5B,cAAM,uBAAuB,IAAI,MAAM,CAAC;MAC9C;AACI,YAAMI,QAAOD,QAAO,gBAAgB,UAAU,EAAE,GAAG;AAEnD,UAAIC,SAAQ,gBAAgB,KAAKA,MAAK,cAAc,KAAK,GAAG;AAC1D,gBAAQA,MAAK,aAAa,KAAK;MACrC;AAEI,aAAO,GAAG,IAAI;IAClB;AAEE,WAAO;EACT;AAEA,WAAS,UAAW,WAAW;AAC7B,QAAI;AACJ,QAAI;AAEJ,UAAM,SAAS,UAAU,SAAS,EAAE,EAAE,YAAW;AAEjD,QAAI,aAAa,KAAM;AACrB,eAAS;AACT,eAAS;IACb,WAAa,aAAa,OAAQ;AAC9B,eAAS;AACT,eAAS;IACb,WAAa,aAAa,YAAY;AAClC,eAAS;AACT,eAAS;IACb,OAAS;AACL,YAAM,IAAIR,eAAc,+DAA+D;IAC3F;AAEE,WAAO,OAAO,SAASC,QAAO,OAAO,KAAK,SAAS,OAAO,MAAM,IAAI;EACtE;AAEA,QAAM,sBAAsB;AAC5B,QAAM,sBAAsB;AAE5B,WAAS,MAAO,SAAS;AACvB,SAAK,SAAS,QAAQ,QAAQ,KAAKc;AACnC,SAAK,SAAS,KAAK,IAAI,GAAI,QAAQ,QAAQ,KAAK,CAAC;AACjD,SAAK,gBAAgB,QAAQ,eAAe,KAAK;AACjD,SAAK,cAAc,QAAQ,aAAa,KAAK;AAC7C,SAAK,YAAad,QAAO,UAAU,QAAQ,WAAW,CAAC,IAAI,KAAK,QAAQ,WAAW;AACnF,SAAK,WAAW,gBAAgB,KAAK,QAAQ,QAAQ,QAAQ,KAAK,IAAI;AACtE,SAAK,WAAW,QAAQ,UAAU,KAAK;AACvC,SAAK,YAAY,QAAQ,WAAW,KAAK;AACzC,SAAK,SAAS,QAAQ,QAAQ,KAAK;AACnC,SAAK,eAAe,QAAQ,cAAc,KAAK;AAC/C,SAAK,eAAe,QAAQ,cAAc,KAAK;AAC/C,SAAK,cAAc,QAAQ,aAAa,MAAM,MAAM,sBAAsB;AAC1E,SAAK,cAAc,QAAQ,aAAa,KAAK;AAC7C,SAAK,WAAW,OAAO,QAAQ,UAAU,MAAM,aAAa,QAAQ,UAAU,IAAI;AAElF,SAAK,gBAAgB,KAAK,OAAO;AACjC,SAAK,gBAAgB,KAAK,OAAO;AAEjC,SAAK,MAAM;AACX,SAAK,SAAS;AAEd,SAAK,aAAa,CAAA;AAClB,SAAK,iBAAiB;EACxB;AAGA,WAAS,aAAc,QAAQ,QAAQ;AACrC,UAAM,MAAMA,QAAO,OAAO,KAAK,MAAM;AACrC,QAAI,WAAW;AACf,QAAI,SAAS;AACb,UAAM,SAAS,OAAO;AAEtB,WAAO,WAAW,QAAQ;AACxB,UAAI;AACJ,YAAM,OAAO,OAAO,QAAQ,MAAM,QAAQ;AAC1C,UAAI,SAAS,IAAI;AACf,eAAO,OAAO,MAAM,QAAQ;AAC5B,mBAAW;MACjB,OAAW;AACL,eAAO,OAAO,MAAM,UAAU,OAAO,CAAC;AACtC,mBAAW,OAAO;MACxB;AAEI,UAAI,KAAK,UAAU,SAAS,KAAM,WAAU;AAE5C,gBAAU;IACd;AAEE,WAAO;EACT;AAEA,WAAS,iBAAkB,OAAO,OAAO;AACvC,WAAO,OAAOA,QAAO,OAAO,KAAK,MAAM,SAAS,KAAK;EACvD;AAEA,WAAS,sBAAuB,OAAOiB,MAAK;AAC1C,aAAS,QAAQ,GAAG,SAAS,MAAM,cAAc,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACnF,YAAMV,QAAO,MAAM,cAAc,KAAK;AAEtC,UAAIA,MAAK,QAAQU,IAAG,GAAG;AACrB,eAAO;MACb;IACA;AAEE,WAAO;EACT;AAGA,WAAS,aAAc,GAAG;AACxB,WAAO,MAAM,cAAc,MAAM;EACnC;AAMA,WAAS,YAAa,GAAG;AACvB,WAAQ,KAAK,MAAW,KAAK,OACzB,KAAK,OAAW,KAAK,SAAa,MAAM,QAAU,MAAM,QACxD,KAAK,SAAW,KAAK,SAAa,MAAM,YACzC,KAAK,SAAW,KAAK;EAC1B;AAOA,WAAS,qBAAsB,GAAG;AAChC,WAAO,YAAY,CAAC,KAClB,MAAM;IAEN,MAAM,wBACN,MAAM;EACV;AAWA,WAAS,YAAa,GAAG,MAAM,SAAS;AACtC,UAAM,wBAAwB,qBAAqB,CAAC;AACpD,UAAM,YAAY,yBAAyB,CAAC,aAAa,CAAC;AAC1D;;OAGI,UACI,wBACA;MAEA,MAAM,cACN,MAAM,4BACN,MAAM,6BACN,MAAM,2BACN,MAAM;MAGZ,MAAM;MACN,EAAE,SAAS,cAAc,CAAC;MAE3B,qBAAqB,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,MAAM;MAC3D,SAAS,cAAc;;EAC1B;AAGA,WAAS,iBAAkB,GAAG;AAI5B,WAAO,YAAY,CAAC,KAClB,MAAM,YACN,CAAC,aAAa,CAAC;;;IAGf,MAAM,cACN,MAAM,iBACN,MAAM,cACN,MAAM,cACN,MAAM,4BACN,MAAM,6BACN,MAAM,2BACN,MAAM;IAEN,MAAM,cACN,MAAM,kBACN,MAAM,iBACN,MAAM,oBACN,MAAM,sBACN,MAAM,eACN,MAAM,qBACN,MAAM,qBACN,MAAM;IAEN,MAAM,gBACN,MAAM,sBACN,MAAM;EACV;AAGA,WAAS,gBAAiB,GAAG;AAE3B,WAAO,CAAC,aAAa,CAAC,KAAK,MAAM;EACnC;AAGA,WAAS,YAAa,QAAQ,KAAK;AACjC,UAAM,QAAQ,OAAO,WAAW,GAAG;AACnC,QAAI;AAEJ,QAAI,SAAS,SAAU,SAAS,SAAU,MAAM,IAAI,OAAO,QAAQ;AACjE,eAAS,OAAO,WAAW,MAAM,CAAC;AAClC,UAAI,UAAU,SAAU,UAAU,OAAQ;AAExC,gBAAQ,QAAQ,SAAU,OAAQ,SAAS,QAAS;MAC1D;IACA;AACE,WAAO;EACT;AAGA,WAAS,oBAAqB,QAAQ;AACpC,UAAM,iBAAiB;AACvB,WAAO,eAAe,KAAK,MAAM;EACnC;AAEA,QAAM,cAAc;AACpB,QAAM,eAAe;AACrB,QAAM,gBAAgB;AACtB,QAAM,eAAe;AACrB,QAAM,eAAe;AASrB,WAAS,kBAAmB,QAAQ,gBAAgB,gBAAgB,WAClE,mBAAmB,aAAa,aAAa,SAAS;AACtD,QAAI;AACJ,QAAI,OAAO;AACX,QAAI,WAAW;AACf,QAAI,eAAe;AACnB,QAAI,kBAAkB;AACtB,UAAM,mBAAmB,cAAc;AACvC,QAAI,oBAAoB;AACxB,QAAI,QAAQ,iBAAiB,YAAY,QAAQ,CAAC,CAAC,KACjD,gBAAgB,YAAY,QAAQ,OAAO,SAAS,CAAC,CAAC;AAExD,QAAI,kBAAkB,aAAa;AAGjC,WAAK,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,QAAU,KAAK,IAAI,KAAK;AAC7D,eAAO,YAAY,QAAQ,CAAC;AAC5B,YAAI,CAAC,YAAY,IAAI,GAAG;AACtB,iBAAO;QACf;AACM,gBAAQ,SAAS,YAAY,MAAM,UAAU,OAAO;AACpD,mBAAW;MACjB;IACA,OAAS;AAEL,WAAK,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,QAAU,KAAK,IAAI,KAAK;AAC7D,eAAO,YAAY,QAAQ,CAAC;AAC5B,YAAI,SAAS,gBAAgB;AAC3B,yBAAe;AAEf,cAAI,kBAAkB;AACpB,8BAAkB;YAEf,IAAI,oBAAoB,IAAI,aAC5B,OAAO,oBAAoB,CAAC,MAAM;AACrC,gCAAoB;UAC9B;QACA,WAAiB,CAAC,YAAY,IAAI,GAAG;AAC7B,iBAAO;QACf;AACM,gBAAQ,SAAS,YAAY,MAAM,UAAU,OAAO;AACpD,mBAAW;MACjB;AAEI,wBAAkB,mBAAoB,qBACnC,IAAI,oBAAoB,IAAI,aAC5B,OAAO,oBAAoB,CAAC,MAAM;IACzC;AAIE,QAAI,CAAC,gBAAgB,CAAC,iBAAiB;AAGrC,UAAI,SAAS,CAAC,eAAe,CAAC,kBAAkB,MAAM,GAAG;AACvD,eAAO;MACb;AACI,aAAO,gBAAgB,sBAAsB,eAAe;IAChE;AAEE,QAAI,iBAAiB,KAAK,oBAAoB,MAAM,GAAG;AACrD,aAAO;IACX;AAGE,QAAI,CAAC,aAAa;AAChB,aAAO,kBAAkB,eAAe;IAC5C;AACE,WAAO,gBAAgB,sBAAsB,eAAe;EAC9D;AAQA,WAAS,YAAa,OAAO,QAAQ,OAAO,OAAO,SAAS;AAC1D,UAAM,QAAQ,WAAY;AACxB,UAAI,OAAO,WAAW,GAAG;AACvB,eAAO,MAAM,gBAAgB,sBAAsB,OAAO;MAChE;AACI,UAAI,CAAC,MAAM,cAAc;AACvB,YAAI,2BAA2B,QAAQ,MAAM,MAAM,MAAM,yBAAyB,KAAK,MAAM,GAAG;AAC9F,iBAAO,MAAM,gBAAgB,sBAAuB,MAAM,SAAS,MAAQ,MAAM,SAAS;QAClG;MACA;AAEI,YAAM,SAAS,MAAM,SAAS,KAAK,IAAI,GAAG,KAAK;AAQ/C,YAAM,YAAa,MAAM,cAAc,KACnC,KACA,KAAK,IAAI,KAAK,IAAI,MAAM,WAAW,EAAE,GAAG,MAAM,YAAY,MAAM;AAGpE,YAAM,iBAAiB;MAEpB,MAAM,YAAY,MAAM,SAAS,MAAM;AAC1C,eAAS,cAAeC,SAAQ;AAC9B,eAAO,sBAAsB,OAAOA,OAAM;MAChD;AAEI,cAAQ;QAAkB;QAAQ;QAAgB,MAAM;QAAQ;QAC9D;QAAe,MAAM;QAAa,MAAM,eAAe,CAAC;QAAO;MAAO,GAAC;QACvE,KAAK;AACH,iBAAO;QACT,KAAK;AACH,iBAAO,MAAM,OAAO,QAAQ,MAAM,IAAI,IAAI;QAC5C,KAAK;AACH,iBAAO,MAAM,YAAY,QAAQ,MAAM,MAAM,IAC3C,kBAAkB,aAAa,QAAQ,MAAM,CAAC;QAClD,KAAK;AACH,iBAAO,MAAM,YAAY,QAAQ,MAAM,MAAM,IAC3C,kBAAkB,aAAa,WAAW,QAAQ,SAAS,GAAG,MAAM,CAAC;QACzE,KAAK;AACH,iBAAO,MAAM,aAAa,MAAiB,IAAI;QACjD;AACE,gBAAM,IAAInB,eAAc,wCAAwC;MACxE;IACA,GAAG;EACH;AAGA,WAAS,YAAa,QAAQ,gBAAgB;AAC5C,UAAM,kBAAkB,oBAAoB,MAAM,IAAI,OAAO,cAAc,IAAI;AAG/E,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC,MAAM;AAC3C,UAAM,OAAO,SAAS,OAAO,OAAO,SAAS,CAAC,MAAM,QAAQ,WAAW;AACvE,UAAM,QAAQ,OAAO,MAAO,OAAO,KAAK;AAExC,WAAO,kBAAkB,QAAQ;EACnC;AAGA,WAAS,kBAAmB,QAAQ;AAClC,WAAO,OAAO,OAAO,SAAS,CAAC,MAAM,OAAO,OAAO,MAAM,GAAG,EAAE,IAAI;EACpE;AAIA,WAAS,WAAY,QAAQ,OAAO;AAKlC,UAAM,SAAS;AAGf,QAAI,UAAU,WAAY;AACxB,UAAI,SAAS,OAAO,QAAQ,IAAI;AAChC,eAAS,WAAW,KAAK,SAAS,OAAO;AACzC,aAAO,YAAY;AACnB,aAAO,SAAS,OAAO,MAAM,GAAG,MAAM,GAAG,KAAK;IAClD,GAAG;AAED,QAAI,mBAAmB,OAAO,CAAC,MAAM,QAAQ,OAAO,CAAC,MAAM;AAC3D,QAAI;AAGJ,QAAI;AACJ,WAAQ,QAAQ,OAAO,KAAK,MAAM,GAAI;AACpC,YAAM,SAAS,MAAM,CAAC;AACtB,YAAM,OAAO,MAAM,CAAC;AAEpB,qBAAgB,KAAK,CAAC,MAAM;AAC5B,gBAAU,UACN,CAAC,oBAAoB,CAAC,gBAAgB,SAAS,KAAM,OAAO,MAC9D,SAAS,MAAM,KAAK;AACtB,yBAAmB;IACvB;AAEE,WAAO;EACT;AAMA,WAAS,SAAU,MAAM,OAAO;AAC9B,QAAI,SAAS,MAAM,KAAK,CAAC,MAAM,IAAK,QAAO;AAG3C,UAAM,UAAU;AAChB,QAAI;AAEJ,QAAI,QAAQ;AACZ,QAAI;AACJ,QAAI,OAAO;AACX,QAAI,OAAO;AACX,QAAI,SAAS;AAMb,WAAQ,QAAQ,QAAQ,KAAK,IAAI,GAAI;AACnC,aAAO,MAAM;AAEb,UAAI,OAAO,QAAQ,OAAO;AACxB,cAAO,OAAO,QAAS,OAAO;AAC9B,kBAAU,OAAO,KAAK,MAAM,OAAO,GAAG;AAEtC,gBAAQ,MAAM;MACpB;AACI,aAAO;IACX;AAIE,cAAU;AAEV,QAAI,KAAK,SAAS,QAAQ,SAAS,OAAO,OAAO;AAC/C,gBAAU,KAAK,MAAM,OAAO,IAAI,IAAI,OAAO,KAAK,MAAM,OAAO,CAAC;IAClE,OAAS;AACL,gBAAU,KAAK,MAAM,KAAK;IAC9B;AAEE,WAAO,OAAO,MAAM,CAAC;EACvB;AAGA,WAAS,aAAc,QAAQ;AAC7B,QAAI,SAAS;AACb,QAAI,OAAO;AAEX,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,QAAU,KAAK,IAAI,KAAK;AACjE,aAAO,YAAY,QAAQ,CAAC;AAC5B,YAAM,YAAY,iBAAiB,IAAI;AAEvC,UAAI,CAAC,aAAa,YAAY,IAAI,GAAG;AACnC,kBAAU,OAAO,CAAC;AAClB,YAAI,QAAQ,MAAS,WAAU,OAAO,IAAI,CAAC;MACjD,OAAW;AACL,kBAAU,aAAa,UAAU,IAAI;MAC3C;IACA;AAEE,WAAO;EACT;AAEA,WAAS,kBAAmB,OAAO,OAAO,QAAQ;AAChD,QAAI,UAAU;AACd,UAAM,OAAO,MAAM;AAEnB,aAAS,QAAQ,GAAG,SAAS,OAAO,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtE,UAAI,QAAQ,OAAO,KAAK;AAExB,UAAI,MAAM,UAAU;AAClB,gBAAQ,MAAM,SAAS,KAAK,QAAQ,OAAO,KAAK,GAAG,KAAK;MAC9D;AAGI,UAAI,UAAU,OAAO,OAAO,OAAO,OAAO,KAAK,KAC1C,OAAO,UAAU,eACjB,UAAU,OAAO,OAAO,MAAM,OAAO,KAAK,GAAI;AACjD,YAAI,YAAY,GAAI,YAAW,OAAO,CAAC,MAAM,eAAe,MAAM;AAClE,mBAAW,MAAM;MACvB;IACA;AAEE,UAAM,MAAM;AACZ,UAAM,OAAO,MAAM,UAAU;EAC/B;AAEA,WAAS,mBAAoB,OAAO,OAAO,QAAQ,SAAS;AAC1D,QAAI,UAAU;AACd,UAAM,OAAO,MAAM;AAEnB,aAAS,QAAQ,GAAG,SAAS,OAAO,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACtE,UAAI,QAAQ,OAAO,KAAK;AAExB,UAAI,MAAM,UAAU;AAClB,gBAAQ,MAAM,SAAS,KAAK,QAAQ,OAAO,KAAK,GAAG,KAAK;MAC9D;AAGI,UAAI,UAAU,OAAO,QAAQ,GAAG,OAAO,MAAM,MAAM,OAAO,IAAI,KACzD,OAAO,UAAU,eACjB,UAAU,OAAO,QAAQ,GAAG,MAAM,MAAM,MAAM,OAAO,IAAI,GAAI;AAChE,YAAI,CAAC,WAAW,YAAY,IAAI;AAC9B,qBAAW,iBAAiB,OAAO,KAAK;QAChD;AAEM,YAAI,MAAM,QAAQ,mBAAmB,MAAM,KAAK,WAAW,CAAC,GAAG;AAC7D,qBAAW;QACnB,OAAa;AACL,qBAAW;QACnB;AAEM,mBAAW,MAAM;MACvB;IACA;AAEE,UAAM,MAAM;AACZ,UAAM,OAAO,WAAW;EAC1B;AAEA,WAAS,iBAAkB,OAAO,OAAO,QAAQ;AAC/C,QAAI,UAAU;AACd,UAAM,OAAO,MAAM;AACnB,UAAM,gBAAgB,OAAO,KAAK,MAAM;AAExC,aAAS,QAAQ,GAAG,SAAS,cAAc,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AAC7E,UAAI,aAAa;AACjB,UAAI,YAAY,GAAI,eAAc;AAElC,UAAI,MAAM,aAAc,eAAc;AAEtC,YAAM,YAAY,cAAc,KAAK;AACrC,UAAI,cAAc,OAAO,SAAS;AAElC,UAAI,MAAM,UAAU;AAClB,sBAAc,MAAM,SAAS,KAAK,QAAQ,WAAW,WAAW;MACtE;AAEI,UAAI,CAAC,UAAU,OAAO,OAAO,WAAW,OAAO,KAAK,GAAG;AACrD;MACN;AAEI,UAAI,MAAM,KAAK,SAAS,KAAM,eAAc;AAE5C,oBAAc,MAAM,QAAQ,MAAM,eAAe,MAAM,MAAM,OAAO,MAAM,eAAe,KAAK;AAE9F,UAAI,CAAC,UAAU,OAAO,OAAO,aAAa,OAAO,KAAK,GAAG;AACvD;MACN;AAEI,oBAAc,MAAM;AAGpB,iBAAW;IACf;AAEE,UAAM,MAAM;AACZ,UAAM,OAAO,MAAM,UAAU;EAC/B;AAEA,WAAS,kBAAmB,OAAO,OAAO,QAAQ,SAAS;AACzD,QAAI,UAAU;AACd,UAAM,OAAO,MAAM;AACnB,UAAM,gBAAgB,OAAO,KAAK,MAAM;AAGxC,QAAI,MAAM,aAAa,MAAM;AAE3B,oBAAc,KAAI;IACtB,WAAa,OAAO,MAAM,aAAa,YAAY;AAE/C,oBAAc,KAAK,MAAM,QAAQ;IACrC,WAAa,MAAM,UAAU;AAEzB,YAAM,IAAIA,eAAc,0CAA0C;IACtE;AAEE,aAAS,QAAQ,GAAG,SAAS,cAAc,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AAC7E,UAAI,aAAa;AAEjB,UAAI,CAAC,WAAW,YAAY,IAAI;AAC9B,sBAAc,iBAAiB,OAAO,KAAK;MACjD;AAEI,YAAM,YAAY,cAAc,KAAK;AACrC,UAAI,cAAc,OAAO,SAAS;AAElC,UAAI,MAAM,UAAU;AAClB,sBAAc,MAAM,SAAS,KAAK,QAAQ,WAAW,WAAW;MACtE;AAEI,UAAI,CAAC,UAAU,OAAO,QAAQ,GAAG,WAAW,MAAM,MAAM,IAAI,GAAG;AAC7D;MACN;AAEI,YAAM,eAAgB,MAAM,QAAQ,QAAQ,MAAM,QAAQ,OAC1C,MAAM,QAAQ,MAAM,KAAK,SAAS;AAElD,UAAI,cAAc;AAChB,YAAI,MAAM,QAAQ,mBAAmB,MAAM,KAAK,WAAW,CAAC,GAAG;AAC7D,wBAAc;QACtB,OAAa;AACL,wBAAc;QACtB;MACA;AAEI,oBAAc,MAAM;AAEpB,UAAI,cAAc;AAChB,sBAAc,iBAAiB,OAAO,KAAK;MACjD;AAEI,UAAI,CAAC,UAAU,OAAO,QAAQ,GAAG,aAAa,MAAM,YAAY,GAAG;AACjE;MACN;AAEI,UAAI,MAAM,QAAQ,mBAAmB,MAAM,KAAK,WAAW,CAAC,GAAG;AAC7D,sBAAc;MACpB,OAAW;AACL,sBAAc;MACpB;AAEI,oBAAc,MAAM;AAGpB,iBAAW;IACf;AAEE,UAAM,MAAM;AACZ,UAAM,OAAO,WAAW;EAC1B;AAEA,WAAS,WAAY,OAAO,QAAQ,UAAU;AAC5C,UAAM,WAAW,WAAW,MAAM,gBAAgB,MAAM;AAExD,aAAS,QAAQ,GAAG,SAAS,SAAS,QAAQ,QAAQ,QAAQ,SAAS,GAAG;AACxE,YAAMQ,QAAO,SAAS,KAAK;AAE3B,WAAKA,MAAK,cAAcA,MAAK,eACxB,CAACA,MAAK,cAAgB,OAAO,WAAW,YAAc,kBAAkBA,MAAK,gBAC7E,CAACA,MAAK,aAAaA,MAAK,UAAU,MAAM,IAAI;AAC/C,YAAI,UAAU;AACZ,cAAIA,MAAK,SAASA,MAAK,eAAe;AACpC,kBAAM,MAAMA,MAAK,cAAc,MAAM;UAC/C,OAAe;AACL,kBAAM,MAAMA,MAAK;UAC3B;QACA,OAAa;AACL,gBAAM,MAAM;QACpB;AAEM,YAAIA,MAAK,WAAW;AAClB,gBAAM,QAAQ,MAAM,SAASA,MAAK,GAAG,KAAKA,MAAK;AAE/C,cAAI;AACJ,cAAI,UAAU,KAAKA,MAAK,SAAS,MAAM,qBAAqB;AAC1D,sBAAUA,MAAK,UAAU,QAAQ,KAAK;UAChD,WAAmB,gBAAgB,KAAKA,MAAK,WAAW,KAAK,GAAG;AACtD,sBAAUA,MAAK,UAAU,KAAK,EAAE,QAAQ,KAAK;UACvD,OAAe;AACL,kBAAM,IAAIR,eAAc,OAAOQ,MAAK,MAAM,iCAAiC,QAAQ,SAAS;UACtG;AAEQ,gBAAM,OAAO;QACrB;AAEM,eAAO;MACb;IACA;AAEE,WAAO;EACT;AAKA,WAAS,UAAW,OAAO,OAAO,QAAQ,OAAO,SAAS,OAAO,YAAY;AAC3E,UAAM,MAAM;AACZ,UAAM,OAAO;AAEb,QAAI,CAAC,WAAW,OAAO,QAAQ,KAAK,GAAG;AACrC,iBAAW,OAAO,QAAQ,IAAI;IAClC;AAEE,UAAMA,QAAO,UAAU,KAAK,MAAM,IAAI;AACtC,UAAM,UAAU;AAEhB,QAAI,OAAO;AACT,cAAS,MAAM,YAAY,KAAK,MAAM,YAAY;IACtD;AAEE,UAAM,gBAAgBA,UAAS,qBAAqBA,UAAS;AAC7D,QAAI;AACJ,QAAI;AAEJ,QAAI,eAAe;AACjB,uBAAiB,MAAM,WAAW,QAAQ,MAAM;AAChD,kBAAY,mBAAmB;IACnC;AAEE,QAAK,MAAM,QAAQ,QAAQ,MAAM,QAAQ,OAAQ,aAAc,MAAM,WAAW,KAAK,QAAQ,GAAI;AAC/F,gBAAU;IACd;AAEE,QAAI,aAAa,MAAM,eAAe,cAAc,GAAG;AACrD,YAAM,OAAO,UAAU;IAC3B,OAAS;AACL,UAAI,iBAAiB,aAAa,CAAC,MAAM,eAAe,cAAc,GAAG;AACvE,cAAM,eAAe,cAAc,IAAI;MAC7C;AACI,UAAIA,UAAS,mBAAmB;AAC9B,YAAI,SAAU,OAAO,KAAK,MAAM,IAAI,EAAE,WAAW,GAAI;AACnD,4BAAkB,OAAO,OAAO,MAAM,MAAM,OAAO;AACnD,cAAI,WAAW;AACb,kBAAM,OAAO,UAAU,iBAAiB,MAAM;UACxD;QACA,OAAa;AACL,2BAAiB,OAAO,OAAO,MAAM,IAAI;AACzC,cAAI,WAAW;AACb,kBAAM,OAAO,UAAU,iBAAiB,MAAM,MAAM;UAC9D;QACA;MACA,WAAeA,UAAS,kBAAkB;AACpC,YAAI,SAAU,MAAM,KAAK,WAAW,GAAI;AACtC,cAAI,MAAM,iBAAiB,CAAC,cAAc,QAAQ,GAAG;AACnD,+BAAmB,OAAO,QAAQ,GAAG,MAAM,MAAM,OAAO;UAClE,OAAe;AACL,+BAAmB,OAAO,OAAO,MAAM,MAAM,OAAO;UAC9D;AACQ,cAAI,WAAW;AACb,kBAAM,OAAO,UAAU,iBAAiB,MAAM;UACxD;QACA,OAAa;AACL,4BAAkB,OAAO,OAAO,MAAM,IAAI;AAC1C,cAAI,WAAW;AACb,kBAAM,OAAO,UAAU,iBAAiB,MAAM,MAAM;UAC9D;QACA;MACA,WAAeA,UAAS,mBAAmB;AACrC,YAAI,MAAM,QAAQ,KAAK;AACrB,sBAAY,OAAO,MAAM,MAAM,OAAO,OAAO,OAAO;QAC5D;MACA,WAAeA,UAAS,sBAAsB;AACxC,eAAO;MACb,OAAW;AACL,YAAI,MAAM,YAAa,QAAO;AAC9B,cAAM,IAAIR,eAAc,4CAA4CQ,KAAI;MAC9E;AAEI,UAAI,MAAM,QAAQ,QAAQ,MAAM,QAAQ,KAAK;AAc3C,YAAI,SAAS;UACX,MAAM,IAAI,CAAC,MAAM,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,MAAM;QAC1D,EAAQ,QAAQ,MAAM,KAAK;AAErB,YAAI,MAAM,IAAI,CAAC,MAAM,KAAK;AACxB,mBAAS,MAAM;QACvB,WAAiB,OAAO,MAAM,GAAG,EAAE,MAAM,sBAAsB;AACvD,mBAAS,OAAO,OAAO,MAAM,EAAE;QACvC,OAAa;AACL,mBAAS,OAAO,SAAS;QACjC;AAEM,cAAM,OAAO,SAAS,MAAM,MAAM;MACxC;IACA;AAEE,WAAO;EACT;AAEA,WAAS,uBAAwB,QAAQ,OAAO;AAC9C,UAAM,UAAU,CAAA;AAChB,UAAM,oBAAoB,CAAA;AAE1B,gBAAY,QAAQ,SAAS,iBAAiB;AAE9C,UAAM,SAAS,kBAAkB;AACjC,aAAS,QAAQ,GAAG,QAAQ,QAAQ,SAAS,GAAG;AAC9C,YAAM,WAAW,KAAK,QAAQ,kBAAkB,KAAK,CAAC,CAAC;IAC3D;AACE,UAAM,iBAAiB,IAAI,MAAM,MAAM;EACzC;AAEA,WAAS,YAAa,QAAQ,SAAS,mBAAmB;AACxD,QAAI,WAAW,QAAQ,OAAO,WAAW,UAAU;AACjD,YAAM,QAAQ,QAAQ,QAAQ,MAAM;AACpC,UAAI,UAAU,IAAI;AAChB,YAAI,kBAAkB,QAAQ,KAAK,MAAM,IAAI;AAC3C,4BAAkB,KAAK,KAAK;QACpC;MACA,OAAW;AACL,gBAAQ,KAAK,MAAM;AAEnB,YAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,mBAAS,IAAI,GAAG,SAAS,OAAO,QAAQ,IAAI,QAAQ,KAAK,GAAG;AAC1D,wBAAY,OAAO,CAAC,GAAG,SAAS,iBAAiB;UAC3D;QACA,OAAa;AACL,gBAAM,gBAAgB,OAAO,KAAK,MAAM;AAExC,mBAAS,IAAI,GAAG,SAAS,cAAc,QAAQ,IAAI,QAAQ,KAAK,GAAG;AACjE,wBAAY,OAAO,cAAc,CAAC,CAAC,GAAG,SAAS,iBAAiB;UAC1E;QACA;MACA;IACA;EACA;AAEA,WAASY,MAAM,OAAO,SAAS;AAC7B,cAAU,WAAW,CAAA;AAErB,UAAM,QAAQ,IAAI,MAAM,OAAO;AAE/B,QAAI,CAAC,MAAM,OAAQ,wBAAuB,OAAO,KAAK;AAEtD,QAAI,QAAQ;AAEZ,QAAI,MAAM,UAAU;AAClB,cAAQ,MAAM,SAAS,KAAK,EAAE,IAAI,MAAK,GAAI,IAAI,KAAK;IACxD;AAEE,QAAI,UAAU,OAAO,GAAG,OAAO,MAAM,IAAI,EAAG,QAAO,MAAM,OAAO;AAEhE,WAAO;EACT;AAEA,SAAA,OAAsBA;;;;;;;ACt6BtB,QAAMC,UAASnB,cAAA;AACf,QAAMoB,UAAShB,cAAA;AAEf,WAAS,QAAS,MAAM,IAAI;AAC1B,WAAO,WAAY;AACjB,YAAM,IAAI,MAAM,mBAAmB,OAAO,wCAC1B,KAAK,yCAAyC;IAClE;EACA;AAEA,SAAA,OAAsBI,YAAA;AACtB,SAAA,SAAwBC,cAAA;AACxB,SAAA,kBAAiCC,gBAAA;AACjC,SAAA,cAA6BC,YAAA;AAC7B,SAAA,cAA6BC,YAAA;AAC7B,SAAA,iBAAgCS,gBAAA;AAChC,SAAA,OAAsBF,QAAO;AAC7B,SAAA,UAAyBA,QAAO;AAChC,SAAA,OAAsBC,QAAO;AAC7B,SAAA,gBAA+BE,iBAAA;AAG/B,SAAA,QAAuB;IACrB,QAAQC,cAAA;IACR,OAAOC,aAAA;IACP,KAAKC,WAAA;IACL,MAAMC,aAAA;IACN,OAAOC,aAAA;IACP,KAAKC,WAAA;IACL,WAAWC,iBAAA;IACX,MAAMC,YAAA;IACN,KAAKC,WAAA;IACL,OAAOC,aAAA;IACP,MAAMC,YAAA;IACN,KAAKC,WAAA;IACL,KAAKC,WAAA;EACP;AAGA,SAAA,WAA0B,QAAQ,YAAY,MAAM;AACpD,SAAA,cAA6B,QAAQ,eAAe,SAAS;AAC7D,SAAA,WAA0B,QAAQ,YAAY,MAAM;;;;;ACzC/C,IAAC;EACJ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AACF,IAAI;;;ACTJ,SAAS,oBAAoB;;;ACctB,SAAS,eAAe,QAAmC;AAChE,QAAM,SAA4B,CAAC;AAEnC,MAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,WAAO,EAAE,OAAO,OAAO,QAAQ,CAAC,EAAE,MAAM,IAAI,SAAS,2BAA2B,CAAC,EAAE;AAAA,EACrF;AAEA,QAAM,IAAI;AAGV,MAAI,OAAO,EAAE,YAAY,UAAU;AACjC,WAAO,KAAK,EAAE,MAAM,WAAW,SAAS,2CAA2C,CAAC;AAAA,EACtF;AACA,MAAI,OAAO,EAAE,SAAS,UAAU;AAC9B,WAAO,KAAK,EAAE,MAAM,QAAQ,SAAS,wCAAwC,CAAC;AAAA,EAChF;AAGA,MAAI,CAAC,MAAM,QAAQ,EAAE,QAAQ,GAAG;AAC9B,WAAO,KAAK,EAAE,MAAM,YAAY,SAAS,4CAA4C,CAAC;AAAA,EACxF,OAAO;AACL,MAAE,SAAS,QAAQ,CAAC,SAAkB,MAAc;AAClD,aAAO,KAAK,GAAG,gBAAgB,SAAS,YAAY,CAAC,GAAG,CAAC;AAAA,IAC3D,CAAC;AAAA,EACH;AAGA,MAAI,EAAE,UAAU,QAAW;AACzB,WAAO,KAAK,GAAG,cAAc,EAAE,OAAO,OAAO,CAAC;AAAA,EAChD;AAGA,MAAI,EAAE,WAAW,QAAW;AAC1B,WAAO,KAAK,GAAG,eAAe,EAAE,QAAQ,QAAQ,CAAC;AAAA,EACnD;AAGA,MAAI,EAAE,mBAAmB,QAAW;AAClC,WAAO,KAAK,GAAG,uBAAuB,EAAE,gBAAgB,gBAAgB,CAAC;AAAA,EAC3E;AAEA,SAAO,EAAE,OAAO,OAAO,WAAW,GAAG,OAAO;AAC9C;AAEA,SAAS,gBAAgB,SAAkB,MAAiC;AAC1E,QAAM,SAA4B,CAAC;AAEnC,MAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,WAAO,CAAC,EAAE,MAAM,SAAS,4BAA4B,CAAC;AAAA,EACxD;AAEA,QAAM,IAAI;AAEV,MAAI,OAAO,EAAE,OAAO,YAAY,CAAC,EAAE,IAAI;AACrC,WAAO,KAAK,EAAE,MAAM,GAAG,IAAI,OAAO,SAAS,gDAAgD,CAAC;AAAA,EAC9F;AAEA,MAAI,OAAO,EAAE,YAAY,WAAW;AAClC,WAAO,KAAK,EAAE,MAAM,GAAG,IAAI,YAAY,SAAS,4CAA4C,CAAC;AAAA,EAC/F;AAEA,MAAI,EAAE,YAAY,UAAa,CAAC,cAAc,EAAE,OAAO,GAAG;AACxD,WAAO,KAAK,EAAE,MAAM,GAAG,IAAI,YAAY,SAAS,sCAAsC,CAAC;AAAA,EACzF;AAEA,MAAI,EAAE,oBAAoB,UAAa,CAAC,cAAc,EAAE,eAAe,GAAG;AACxE,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,MAAI,EAAE,qBAAqB,UAAa,OAAO,EAAE,qBAAqB,WAAW;AAC/E,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,cAAc,OAAgB,MAAiC;AACtE,QAAM,SAA4B,CAAC;AAEnC,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO,CAAC,EAAE,MAAM,SAAS,0BAA0B,CAAC;AAAA,EACtD;AAEA,QAAM,IAAI;AAEV,aAAW,SAAS,CAAC,kBAAkB,kBAAkB,kBAAkB,GAAG;AAC5E,QAAI,EAAE,KAAK,MAAM,UAAa,CAAC,cAAc,EAAE,KAAK,CAAC,GAAG;AACtD,aAAO,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,KAAK,IAAI,SAAS,GAAG,KAAK,+BAA+B,CAAC;AAAA,IAC3F;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,QAAiB,MAAiC;AACxE,QAAM,SAA4B,CAAC;AAEnC,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,WAAO,CAAC,EAAE,MAAM,SAAS,2BAA2B,CAAC;AAAA,EACvD;AAEA,QAAM,IAAI;AAEV,MAAI,EAAE,wBAAwB,UAAa,OAAO,EAAE,wBAAwB,UAAU;AACpF,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,MAAI,EAAE,yBAAyB,UAAa,OAAO,EAAE,yBAAyB,UAAU;AACtF,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAIA,MACE,OAAO,EAAE,wBAAwB,YACjC,OAAO,EAAE,yBAAyB,YAClC,EAAE,sBAAsB,EAAE,sBAC1B;AACA,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SACE;AAAA,IACJ,CAAC;AAAA,EACH;AAEA,MAAI,EAAE,uBAAuB,UAAa,OAAO,EAAE,uBAAuB,UAAU;AAClF,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,MAAI,EAAE,aAAa,UAAa,OAAO,EAAE,aAAa,UAAU;AAC9D,WAAO,KAAK,EAAE,MAAM,GAAG,IAAI,aAAa,SAAS,4BAA4B,CAAC;AAAA,EAChF;AAEA,SAAO;AACT;AAEA,SAAS,uBAAuB,YAAqB,MAAiC;AACpF,QAAM,SAA4B,CAAC;AAEnC,MAAI,OAAO,eAAe,YAAY,eAAe,MAAM;AACzD,WAAO,CAAC,EAAE,MAAM,SAAS,mCAAmC,CAAC;AAAA,EAC/D;AAEA,QAAM,IAAI;AAEV,aAAW,SAAS,CAAC,aAAa,mBAAmB,WAAW,GAAY;AAC1E,QAAI,CAAC,EAAE,KAAK,KAAK,OAAO,EAAE,KAAK,MAAM,UAAU;AAC7C,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,IAAI,IAAI,KAAK;AAAA,QACtB,SAAS,GAAG,KAAK;AAAA,MACnB,CAAC;AACD;AAAA,IACF;AAEA,UAAM,IAAI,EAAE,KAAK;AACjB,QAAI,OAAO,EAAE,QAAQ,YAAY,OAAO,EAAE,QAAQ,UAAU;AAC1D,aAAO,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,KAAK,IAAI,SAAS,GAAG,KAAK,iCAAiC,CAAC;AAAA,IAC7F,WAAW,EAAE,MAAM,EAAE,KAAK;AACxB,aAAO,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,KAAK,IAAI,SAAS,GAAG,KAAK,mBAAmB,KAAK,OAAO,CAAC;AAAA,IAC3F;AAAA,EACF;AAGA,MAAI,sBAAsB,CAAC,GAAG;AAC5B,UAAM,eAAe;AACrB,QAAI,aAAa,UAAU,MAAM,MAAM,aAAa,gBAAgB,KAAK;AACvE,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,IAAI;AAAA,QACb,SAAS,8BAA8B,aAAa,UAAU,GAAG,8BAA8B,aAAa,gBAAgB,GAAG;AAAA,MACjI,CAAC;AAAA,IACH;AACA,QAAI,aAAa,gBAAgB,MAAM,MAAM,aAAa,UAAU,KAAK;AACvE,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,IAAI;AAAA,QACb,SAAS,oCAAoC,aAAa,gBAAgB,GAAG,wBAAwB,aAAa,UAAU,GAAG;AAAA,MACjI,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,cAAc,KAA+B;AACpD,SAAO,MAAM,QAAQ,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ;AACrE;AAEA,SAAS,sBAAsB,GAAqC;AAClE,aAAW,OAAO,CAAC,aAAa,mBAAmB,WAAW,GAAG;AAC/D,UAAM,IAAI,EAAE,GAAG;AACf,QAAI,CAAC,KAAK,OAAO,MAAM,SAAU,QAAO;AACxC,UAAM,QAAQ;AACd,QAAI,OAAO,MAAM,QAAQ,YAAY,OAAO,MAAM,QAAQ,SAAU,QAAO;AAAA,EAC7E;AACA,SAAO;AACT;;;ADlNO,SAAS,UAAU,aAAkC;AAC1D,MAAI;AAEJ,MAAI;AACF,aAAc,KAAK,WAAW;AAAA,EAChC,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,YAAY,EAAE,OAAO,OAAO,QAAQ,CAAC,EAAE,MAAM,IAAI,SAAS,qBAAqB,OAAO,GAAG,CAAC,EAAE;AAAA,MAC5F,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,aAAa,eAAe,MAAM;AAExC,MAAI,CAAC,WAAW,OAAO;AACrB,WAAO,EAAE,QAAQ,MAAM,YAAY,SAAS,YAAY;AAAA,EAC1D;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAKO,SAAS,UAAU,UAA+B;AACvD,MAAI;AAEJ,MAAI;AACF,cAAU,aAAa,UAAU,OAAO;AAAA,EAC1C,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,YAAY,EAAE,OAAO,OAAO,QAAQ,CAAC,EAAE,MAAM,IAAI,SAAS,+BAA+B,OAAO,GAAG,CAAC,EAAE;AAAA,IACxG;AAAA,EACF;AAEA,SAAO,UAAU,OAAO;AAC1B;;;AErDO,SAAS,cAAc,QAAgD;AAC5E,MAAI,OAAO,QAAQ;AACjB,WAAO,IAAI,eAAe,OAAO,MAAM;AAAA,EACzC;AAEA,MAAI,OAAO,YAAY;AACrB,UAAM,SAAS,UAAU,OAAO,UAAU;AAC1C,QAAI,CAAC,OAAO,QAAQ;AAClB,YAAM,SAAS,OAAO,WAAW,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AACvF,YAAM,IAAI,MAAM,uBAAuB,OAAO,UAAU,KAAK,MAAM,EAAE;AAAA,IACvE;AACA,WAAO,IAAI,eAAe,OAAO,MAAM;AAAA,EACzC;AAEA,QAAM,IAAI,MAAM,2DAA2D;AAC7E;AAKO,SAAS,YAAY,WAA2B,SAA6C;AAClG,SAAO,UAAU,SAAS,OAAO;AACnC;;;ACTO,SAAS,cAAc,OAA2B;AACvD,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,SAAO;AACT;;;ACZO,IAAM,cAAc;;;ACDpB,IAAM,iBAAiB,iBAAiB,WAAW;AAO1D,SAAS,cAAc,aAAmD;AACxE,MAAI,CAAC,YAAa,QAAO,EAAE,cAAc,eAAe;AACxD,MAAI,uBAAuB,SAAS;AAClC,UAAM,OAAO,IAAI,QAAQ,WAAW;AACpC,QAAI,CAAC,KAAK,IAAI,YAAY,EAAG,MAAK,IAAI,cAAc,cAAc;AAClE,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,WAAW,GAAG;AAC9B,UAAMC,OAAM,YAAY,KAAK,CAAC,CAAC,IAAI,MAAM,KAAK,YAAY,MAAM,YAAY;AAC5E,WAAOA,OAAM,cAAc,CAAC,GAAG,aAAa,CAAC,cAAc,cAAc,CAAC;AAAA,EAC5E;AACA,QAAM,MAAM,OAAO,KAAK,WAAW,EAAE,KAAK,CAAC,SAAS,KAAK,YAAY,MAAM,YAAY;AACvF,SAAO,MAAM,cAAc,EAAE,cAAc,gBAAgB,GAAG,YAAY;AAC5E;AAEO,IAAM,WAAyB,CAAC,OAAO,SAC5C,MAAM,OAAO,EAAE,GAAG,MAAM,SAAS,cAAc,MAAM,OAAO,EAAE,CAAC;;;AChBjE,IAAM,eAAe,KAAK,KAAK;AAE/B,IAAM,QAAQ,oBAAI,IAAwB;AAsFnC,SAAS,uBAAuB,YAA0D;AAC/F,SAAO,MAAM,IAAI,UAAU,GAAG;AAChC;;;AC1EA,IAAM,iBAAyC;AAAA,EAC7C,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMZ,OAAO;AACT;AAOA,IAAI,qBAAqB;AAQzB,IAAI,0BAA0B;AAE9B,eAAe,iBACb,YACA,OACA,YACA,QACe;AACf,uBAAqB;AACrB,MAAI;AACF,UAAM,WAAW,GAAG,UAAU;AAK9B,UAAM,WAAW,MAAM,SAAS,UAAU,EAAE,QAAQ,OAAO,CAAC;AAC5D,UAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,QAAI,YAAY,WAAW,WAAW,GAAG;AACvC,YAAM,UACJ,qCAAqC,UAAU,kCAAkC,WAAW;AAQ9F,UAAI,YAAY;AACd,cAAM,IAAI,MAAM,GAAG,OAAO,oBAAoB;AAAA,MAChD;AACA,cAAQ,KAAK,GAAG,OAAO,2DAA2D;AAAA,IACpF,WAAW,OAAO;AAChB,cAAQ;AAAA,QACN,+CAA+C,UAAU,mBAAmB,WAAW;AAAA,MACzF;AAAA,IACF;AAKA,QAAI,QAAQ;AACV,YAAM,YAAY,MAAM,SAAS,GAAG,UAAU,oCAAoC;AAAA,QAChF,SAAS,EAAE,eAAe,UAAU,MAAM,GAAG;AAAA,MAC/C,CAAC;AACD,UAAI,UAAU,WAAW,KAAK;AAC5B,cAAM,OAAQ,MAAM,UAAU,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAKrD,cAAM,UACJ,mFACI,KAAK,QAAQ,iBAAiB,KAAK,KAAK,WAAW,aAAa,yEAEnE,KAAK,aAAa,YAAY,OAAO,KAAK,YAAY,SAAS,KAAK,MACrE;AACF,YAAI,YAAY;AACd,gBAAM,IAAI,MAAM,GAAG,OAAO,oBAAoB;AAAA,QAChD;AACA,gBAAQ,MAAM,OAAO;AAAA,MACvB,WAAW,UAAU,IAAI;AACvB,cAAM,OAAQ,MAAM,UAAU,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAGrD,YAAI,OAAO,KAAK,iBAAiB,YAAY,KAAK,gBAAgB,GAAG;AACnE,kBAAQ;AAAA,YACN,qEAAqE,KAAK,YAAY;AAAA,UAExF;AAAA,QACF,WAAW,OAAO;AAChB,kBAAQ,IAAI,iDAAiD;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,YAAY;AAGd,YAAM;AAAA,IACR;AACA,QAAI,OAAO;AACT,cAAQ,IAAI,2DAA2D,OAAO,GAAG,CAAC,EAAE;AAAA,IACtF;AAAA,EACF;AACF;AAKA,IAAM,oBAAoB,oBAAI,IAA+D;AAwB7F,SAAS,YAAY,SAA8B,gBAAiC;AAClF,QAAM,IAAI,QAAQ;AAClB,SAAO;AAAA,IACL,EAAE,WAAW;AAAA,IACb,EAAE,UAAU;AAAA,IACZ,EAAE,OAAO;AAAA,IACT,QAAQ,WAAW;AAAA,IACnB,QAAQ,UAAU;AAAA,IAClB,QAAQ,gBAAgB;AAAA,IACxB,QAAQ,YAAY;AAAA,IACpB,QAAQ,gBAAgB;AAAA,IACxB,QAAQ,oBAAoB;AAAA,IAC5B,QAAQ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQpB,kBAAkB;AAAA,IAClB,QAAQ,mBAAmB;AAAA,IAC3B,QAAQ,oBAAoB;AAAA,IAC5B,QAAQ,oBAAoB,MAAM;AAAA,IAClC,QAAQ,iBAAiB;AAAA,IACzB,QAAQ,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,IAKzB,QAAQ,oBAAoB;AAAA,IAC5B,QAAQ,sBAAsB;AAAA,IAC9B,QAAQ,yBAAyB,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMvC,QAAQ,gBAAgB,YAAY;AAAA,IACpC,QAAQ,gBAAgB,aAAa;AAAA,IACrC,QAAQ,gBAAgB,gBAAgB;AAAA,IACxC,QAAQ,gBAAgB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMxC,QAAQ,iBAAiB;AAAA,IACzB,QAAQ,qBAAqB;AAAA,EAC/B,EAAE,KAAK,GAAG;AACZ;AAKA,SAAS,gBACP,SACA,gBAC2B;AAC3B,QAAM,MAAM,YAAY,SAAS,cAAc;AAC/C,QAAM,SAAS,kBAAkB,IAAI,GAAG;AAExC,MAAI,UAAU,OAAO,YAAY,KAAK,IAAI,GAAG;AAC3C,WAAO,OAAO;AAAA,EAChB;AAEA,MAAI,QAAQ;AACV,sBAAkB,OAAO,GAAG;AAAA,EAC9B;AAEA,SAAO;AACT;AAYA,IAAM,4BAA4B;AAElC,SAAS,YACP,SACA,QACA,eACA,gBACM;AACN,QAAM,aAAa,iBAAiB,gBAAgB,IAAI,gBAAgB;AACxE,QAAM,MAAM,YAAY,SAAS,cAAc;AAC/C,oBAAkB,IAAI,KAAK;AAAA,IACzB;AAAA,IACA,WAAW,KAAK,IAAI,IAAI,aAAa;AAAA,EACvC,CAAC;AACH;AAgHA,SAAS,YAAY,MAAsD;AACzE,MAAI,CAAC,MAAM,YAAa,QAAO;AAC/B,SAAO;AAAA,IACL,UAAU,KAAK;AAAA,IACf,cAAc,KAAK;AAAA,IACnB,SACE;AAAA,EAIJ;AACF;AAUA,SAAS,uBACP,SACA,QACA,UAQI,CAAC,GACe;AACpB,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,aAAa,WAAW;AAC9B,QAAM,cAAc,WAAW;AAC/B,QAAM,OAAO,QAAQ;AAErB,QAAM,WAAyB,cAC3B;AAAA,IACE,SACE;AAAA,IAEF,iBAAiB,MAAM,mBAAmB;AAAA,IAC1C,kBAAkB,QAAQ,aAAa,WAAW,MAAM,oBAAoB;AAAA,IAC5E,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF,IACA,aACE;AAAA,IACE,SACE;AAAA,IACF,iBAAiB,MAAM,mBAAmB;AAAA,IAC1C,kBAAkB,MAAM,oBAAoB;AAAA,IAC5C,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF,IACA;AAAA,IACE,SACE;AAAA,IACF,iBAAiB,MAAM,mBAAmB;AAAA,IAC1C,kBAAkB,MAAM,oBAAoB;AAAA,IAC5C,OAAO;AAAA;AAAA;AAAA,MAGL,GAAI,MAAM,cACN;AAAA,QACE,yEAAyE,KAAK,WAAW;AAAA,MAC3F,IACA,CAAC;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,GAAI,YAAY,IAAI,KAAK,EAAE,KAAK,YAAY,IAAI,EAAE;AAAA,EACpD;AAEN,SAAO;AAAA;AAAA;AAAA;AAAA,IAIL,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf;AAAA,IACA,eAAe,SAAS,CAAC,MAAM,IAAI,CAAC,qCAAqC;AAAA;AAAA;AAAA;AAAA;AAAA,IAKzE,UAAU,cACN;AAAA,MACE;AAAA,QACE,WAAW;AAAA,QACX,SAAS,UAAU;AAAA,QACnB,UAAU,SAAS;AAAA,MACrB;AAAA,IACF,IACA,aACE;AAAA,MACE;AAAA,QACE,WAAW;AAAA,QACX,SAAS,UAAU;AAAA,QACnB,UAAU,SAAS;AAAA,MACrB;AAAA,IACF,IACA;AAAA;AAAA;AAAA,IAGN,GAAI,eAAe,EAAE,eAAe,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,IAKzC,GAAI,cAAc,EAAE,WAAW,KAAK;AAAA,IACpC,eAAe,QAAQ;AAAA,IACvB,WAAW,QAAQ;AAAA,IACnB,YAAY,oBAAI,KAAK;AAAA,EACvB;AACF;AAKA,eAAe,oBACb,QACA,SA+FC;AACD,QAAM,EAAE,aAAa,GAAG,YAAY,IAAI;AAIxC,QAAM,OAAgC;AAAA,IACpC,GAAI,YAAY,WAAW,EAAE,SAAS,YAAY,QAAQ;AAAA,IAC1D,GAAI,YAAY,WAAW,EAAE,SAAS,YAAY,QAAQ;AAAA,EAC5D;AAGA,MAAI,YAAY,OAAQ,MAAK,SAAS,YAAY;AAClD,MAAI,YAAY,aAAc,MAAK,eAAe,YAAY;AAC9D,MAAI,YAAY,SAAU,MAAK,WAAW,YAAY;AACtD,MAAI,YAAY,aAAc,MAAK,eAAe,YAAY;AAC9D,MAAI,YAAY,iBAAkB,MAAK,mBAAmB,YAAY;AACtE,MAAI,YAAY,SAAU,MAAK,WAAW,YAAY;AACtD,MAAI,YAAY,kBAAmB,MAAK,oBAAoB,YAAY;AACxE,MAAI,YAAY,cAAe,MAAK,gBAAgB,YAAY;AAChE,MAAI,YAAY,kBAAkB,OAAW,MAAK,gBAAgB,YAAY;AAE9E,MAAI,YAAY;AACd,SAAK,yBAAyB,YAAY;AAC5C,MAAI,YAAY,cAAe,MAAK,gBAAgB,YAAY;AAChE,MAAI,YAAY,iBAAkB,MAAK,mBAAmB,YAAY;AACtE,MAAI,YAAY,iBAAkB,MAAK,mBAAmB,YAAY;AACtE,MAAI,YAAY,gBAAiB,MAAK,kBAAkB,YAAY;AACpE,MAAI,OAAO,eAAgB,MAAK,iBAAiB,OAAO;AACxD,MAAI,YAAY;AACd,SAAK,0BAA0B,YAAY;AAG7C,MAAI,YAAY,mBAAoB,MAAK,qBAAqB,YAAY;AAG1E,MAAI,YAAY,cAAe,MAAK,gBAAgB,YAAY;AAGhE,MAAI,YAAY,kBAAmB,MAAK,oBAAoB,YAAY;AAExE,MAAI,YAAY,cAAe,MAAK,gBAAgB,YAAY;AAGhE,MAAI,YAAY,WAAY,MAAK,aAAa,YAAY;AAI1D,MAAI,YAAY,kBAAmB,MAAK,oBAAoB,YAAY;AAIxE,MAAI,YAAY,UAAW,MAAK,YAAY,YAAY;AACxD,MAAI,YAAY,iBAAkB,MAAK,mBAAmB,YAAY;AAStE,OAAK,aAAa;AAIlB,MAAI,YAAY,kBAAkB,YAAY,YAAY,YAAY,WAAW;AAC/E,UAAM,OAAO;AAAA,MACX,GAAI,YAAY,YAAY,EAAE,UAAU,YAAY,SAAS;AAAA,MAC7D,GAAI,YAAY,aAAa,EAAE,WAAW,YAAY,UAAU;AAAA,MAChE,GAAG,YAAY;AAAA,IACjB;AACA,QAAI,OAAO,KAAK,IAAI,EAAE,SAAS,EAAG,MAAK,iBAAiB;AAAA,EAC1D;AAGA,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,GAAG,OAAO;AAAA,EACZ;AAcA,MAAI,OAAO,QAAQ;AACjB,YAAQ,eAAe,IAAI,UAAU,OAAO,MAAM;AAElD,YAAQ,WAAW,IAAI,OAAO;AAAA,EAChC;AAEA,MAAI;AAMF,UAAM,WAAW,MAAM,SAAS,GAAG,OAAO,UAAU,yBAAyB;AAAA,MAC3E,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ,YAAY,QAAQ,OAAO,mBAAmB,GAAM;AAAA,IAC9D,CAAC;AAED,UAAM,OAAO,MAAM,SAAS,KAAK;AAMjC,QAAI,SAAS,WAAW,KAAK;AAC3B,aAAO;AAAA,QACL,SAAS;AAAA;AAAA;AAAA,QAGT,WAAW,OAAO,MAAM,cAAc,WAAW,KAAK,YAAY;AAAA,QAClE,QAAQ;AAAA,UACN,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,UAAU;AAAA,YACR;AAAA,cACE,WAAW;AAAA,cACX,SACE,OAAO,MAAM,YAAY,WAAW,KAAK,UAAU;AAAA,cACrD,UACE,OAAO,MAAM,aAAa,WACtB,KAAK,WACL;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAOA,QAAI,SAAS,WAAW,OAAO,MAAM,UAAU,oBAAoB;AACjE,YAAM,UACJ,OAAO,MAAM,YAAY,WACrB,KAAK,UACL;AACN,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,OAAO,MAAM,cAAc,WAAW,KAAK,YAAY;AAAA,QAClE,QAAQ;AAAA,UACN,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,UAAU;AAAA,YACR;AAAA,cACE,WAAW;AAAA,cACX;AAAA,cACA,UACE,OAAO,MAAM,aAAa,WACtB,KAAK,WACL;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,IAAI;AAOhB,UAAI,SAAS,WAAW,KAAK;AAC3B,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,KAAK,WAAW,KAAK,SAAS;AAAA,UACrC,WAAW;AAAA,UACX,eAAe,OAAO,MAAM,SAAS,WAAW,KAAK,OAAO;AAAA,UAC5D,aACE,MAAM,eAAe,OAAO,KAAK,gBAAgB,WAC5C,KAAK,cACN;AAAA,UACN,eAAe,OAAO,MAAM,kBAAkB,WAAW,KAAK,gBAAgB;AAAA,UAC9E,WAAW,OAAO,MAAM,cAAc,WAAW,KAAK,YAAY;AAAA,QACpE;AAAA,MACF;AAIA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,KAAK,WAAW,KAAK,SAAS,gBAAgB,SAAS,MAAM;AAAA,QACpE,eAAe,OAAO,MAAM,kBAAkB,WAAW,KAAK,gBAAgB;AAAA,QAC9E,WAAW,OAAO,MAAM,cAAc,WAAW,KAAK,YAAY;AAAA,MACpE;AAAA,IACF;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,qCAAqC,OAAO;AAAA,IACrD;AAAA,EACF;AACF;AAmBA,eAAsB,OACpB,QACA,SACA,SAC6B;AAC7B,QAAM,eAAe,EAAE,GAAG,gBAAgB,GAAG,OAAO;AAIpD,QAAM,OAAO,aAAa,aACtB,uBAAuB,aAAa,UAAU,IAC9C;AAOJ,MAAI,CAAC,sBAAsB,CAAC,aAAa,qBAAqB,aAAa,YAAY;AACrF,QAAI,aAAa,YAAY;AAC3B,YAAM;AAAA,QACJ,aAAa;AAAA,QACb,aAAa;AAAA,QACb;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF,OAAO;AACL,WAAK;AAAA,QACH,aAAa;AAAA,QACb,aAAa;AAAA,QACb;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MACE,CAAC,4BACA,OAAO,kBAAkB,UAAa,OAAO,yBAAyB,SACvE;AACA,8BAA0B;AAC1B,YAAQ;AAAA,MACN;AAAA,IAIF;AAAA,EACF;AAWA,MAAI,aAAa,aAAa,KAAK,CAAC,SAAS,aAAa;AACxD,UAAM,SAAS,gBAAgB,SAAS,aAAa,cAAc;AACnE,QAAI,QAAQ;AACV,UAAI,aAAa,OAAO;AACtB,gBAAQ,IAAI,+CAA+C;AAAA,MAC7D;AAOA,YAAM,MAA0B,EAAE,GAAG,OAAO;AAC5C,UAAI,QAAQ,WAAW;AACrB,YAAI,YAAY,QAAQ;AAAA,MAC1B,OAAO;AACL,eAAO,IAAI;AAAA,MACb;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,kBAAkB,EAAE,GAAG,QAAQ;AACrC,MAAI,CAAC,gBAAgB,mBAAmB,aAAa,iBAAiB;AACpE,oBAAgB,kBAAkB,aAAa;AAAA,EACjD;AACA,MAAI,CAAC,gBAAgB,oBAAoB,aAAa,kBAAkB;AACtE,oBAAgB,mBAAmB,aAAa;AAAA,EAClD;AAGA,MAAI,aAAa,OAAO;AACtB,YAAQ,IAAI,iDAAiD;AAAA,EAC/D;AAEA,QAAM,cAAc,MAAM,oBAAoB,cAAc,eAAe;AAK3E,QAAM,yBAA0B,YAAwC;AACxE,QAAM,sBACJ,MAAM,QAAQ,sBAAsB,KAAK,uBAAuB,SAAS,IACpE,yBACD;AAGN,MAAI,CAAC,YAAY,SAAS;AAQxB,WAAO,uBAAuB,cAAc,YAAY,OAAO;AAAA,MAC7D,QAAQ,YAAY,YAAY,uBAAuB;AAAA,MACvD,eAAgB,YAA2C;AAAA,MAC3D,WAAY,YAAuC;AAAA,MACnD,aAAa,YAAY;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH;AAGA,MAAI,CAAC,YAAY,QAAQ,SAAS;AAIhC,UAAM,qBAAsB,YAAY,QACpC;AAMJ,UAAM,wBACH,YAAY,qBAA8D,eAC3E;AACF,UAAMC,UAAqC;AAAA,MACzC,kBAAkB;AAAA,MAClB,eAAe;AAAA;AAAA;AAAA;AAAA,MAIf,eACE,wBACC,sBAAsB,mBAAmB,SAAS,IAC/C,mBAAmB,IAAI,CAAC,MAAM,EAAE,OAAO,IACvC,YAAY,QAAQ,SAClB,CAAC,YAAY,OAAO,MAAM,IAC1B,CAAC,eAAe;AAAA,MACxB,UAAU;AAAA,MACV,gBAAgB,YAAY,QAAQ;AAAA,MACpC,kBAAkB,YAAY,QAAQ;AAAA,MACtC,UAAU;AAAA,QACR,SAAS,YAAY,QAAQ,UAAU;AAAA,QACvC,iBAAiB,MAAM,mBAAmB;AAAA,QAC1C,kBAAkB,MAAM,oBAAoB;AAAA;AAAA;AAAA,QAG5C,GAAI,YAAY,IAAI,KAAK,EAAE,KAAK,YAAY,IAAI,EAAE;AAAA,MACpD;AAAA,MACA,YAAY,oBAAI,KAAK;AAAA;AAAA,MAErB,WAAY,YAAwC;AAAA;AAAA;AAAA,MAGpD,eAAgB,YAAwC;AAAA;AAAA;AAAA,MAGxD,WAAY,YAAwC;AAAA,MACpD,gBAAiB,YACd;AAAA,MACH,uBAAwB,YAAwC;AAAA,MAGhE,gBAAiB,YAAwC;AAAA,MAGzD,YAAa,YAAwC;AAAA,MAGrD,mBAAoB,YAAwC;AAAA;AAAA;AAAA,MAK5D,iBAAkB,YAAwC;AAAA;AAAA,MAI1D,YAAa,YAAwC;AAAA,IACvD;AAEA,WAAOA;AAAA,EACT;AAGA,QAAM,QAAmC,YAAY,QACjD;AAAA,IACE,SAAS,YAAY,MAAM;AAAA,IAC3B,MAAM,YAAY,MAAM;AAAA,IACxB,YAAY,YAAY,MAAM;AAAA,IAC9B,YAAY,cAAc,YAAY,MAAM,UAAU;AAAA,IACtD,oBAAoB,YAAY,MAAM,qBAAqB;AAAA,IAC3D,QAAQ,YAAY,MAAM;AAAA,EAC5B,IACA;AAEJ,QAAM,YAA2C,YAAY,YACzD;AAAA,IACE,UAAU,YAAY,UAAU;AAAA,IAChC,MAAM,YAAY,UAAU;AAAA,IAC5B,YAAY,YAAY,UAAU,cAAc;AAAA,IAChD,UAAU,YAAY,UAAU;AAAA,EAClC,IACA;AAEJ,QAAM,eAAiD,YAAY,eAC/D;AAAA,IACE,MAAM,YAAY,aAAa;AAAA,IAC/B,UAAU,YAAY,aAAa;AAAA,IACnC,YAAY,YAAY,aAAa;AAAA,EACvC,IACA;AAKJ,QAAM,sBAAsB,YAAY;AAExC,QAAM,SAAqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASzC,kBACG,YAAY,qBAA8D,eAC3E;AAAA,IACF,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,YAAY,QAAQ;AAAA,IACnC;AAAA,IACA,gBAAgB,YAAY,QAAQ;AAAA,IACpC,kBAAkB,YAAY,QAAQ;AAAA,IACtC,YAAY,oBAAI,KAAK;AAAA,IACrB,UAAU,aAAa;AAAA;AAAA,IAEvB,WAAY,YAAwC;AAAA;AAAA;AAAA,IAGpD,eAAgB,YAAwC;AAAA;AAAA,IAExD,WAAY,YAAwC;AAAA,IACpD,kBAAmB,YAAwC;AAAA,IAG3D,eAAgB,YAAwC;AAAA,IAGxD,gBAAiB,YACd;AAAA,IACH,uBAAwB,YAAwC;AAAA,IAGhE,eAAgB,YAAwC;AAAA,IAGxD,gBAAiB,YAAwC;AAAA,IAGzD,YAAa,YAAwC;AAAA,IAGrD,mBAAoB,YAAwC;AAAA,IAG5D,iBAAkB,YAAwC;AAAA;AAAA,IAI1D,YAAa,YAAwC;AAAA,EACvD;AAGA,MAAI,OAAO,mBAAmB,QAAQ;AAKpC,WAAO,gBAAgB;AAGvB,WAAO,gBAAgB,uBACrB,OAAO,yBAAyB,CAAC,2CAA2C;AAC9E,WAAO,WAAW,OAAO,mBACrB;AAAA,MACE,SAAS,wBAAwB,OAAO,iBAAiB,UAAU,0BAA0B;AAAA,MAC7F,iBAAiB,MAAM,mBAAmB;AAAA,MAC1C,kBAAkB,MAAM,oBAAoB;AAAA,IAC9C,IACA;AAAA,MACE,SAAS,OAAO,wBAAwB,CAAC,KAAK;AAAA,MAC9C,iBAAiB,MAAM,mBAAmB;AAAA,MAC1C,kBAAkB,MAAM,oBAAoB;AAAA,IAC9C;AAAA,EACN,WAAW,OAAO,mBAAmB,oBAAoB;AAGvD,WAAO,iBAAiB;AACxB,WAAO,gBAAgB,uBACrB,OAAO,yBAAyB,CAAC,+BAA+B;AAAA,EACpE;AAOA,QAAM,YACJ,OAAO,mBAAmB,QAC1B,OAAO,qBAAqB,QAC5B,OAAO,mBAAmB;AAC5B,MAAI,aAAa,aAAa,KAAK,OAAO,mBAAmB,UAAU,CAAC,WAAW;AACjF,gBAAY,SAAS,QAAQ,aAAa,UAAU,aAAa,cAAc;AAAA,EACjF;AAEA,SAAO;AACT;;;ACloCA,IAAM,uBAAuB,IAAI,KAAK;;;ACgM/B,IAAM,kBAAkB,KAAK;;;ACpF7B,IAAM,sBAAkC,OAAO,OAAO;AAAA,EAC3D,SAAS;AAAA,EACT,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW,CAAC;AAAA,EACZ,UAAU,OAAO,OAAO,EAAE,qBAAqB,EAAI,CAAC;AAAA,EACpD,gBAAgB;AAClB,CAAC;AAyFD,IAAM,iBAAiB,KAAK;AAC5B,IAAM,uBAAuB,KAAK,KAAK,KAAK;;;ACsC5C,IAAM,4BAA4B,IAAI,KAAK;;;ACkF3C,IAAMC,6BAA4B,IAAI,KAAK;;;ACzU3C,SAAS,uBAAuB;;;ACJhC,SAAS,eAAuD;;;AC+BzD,IAAM,qBAAN,MAA+C;AAAA,EAKpD,YAAY,WAAW,KAAQ;AAJ/B,SAAiB,UAAU,oBAAI,IAAoB;AAEnD,SAAQ,cAAc;AAGpB,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,KAAK,KAAa,aAA8B;AAC9C,UAAM,QAAQ,KAAK,IAAI;AAGvB,QAAI,QAAQ,KAAK,cAAc,KAAM;AACnC,iBAAW,CAAC,GAAG,GAAG,KAAK,KAAK,SAAS;AACnC,YAAI,OAAO,MAAO,MAAK,QAAQ,OAAO,CAAC;AAAA,MACzC;AACA,WAAK,cAAc;AAAA,IACrB;AAEA,UAAM,WAAW,KAAK,QAAQ,IAAI,GAAG;AACrC,QAAI,aAAa,UAAa,WAAW,OAAO;AAC9C,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,QAAQ,QAAQ,KAAK,UAAU;AACtC,YAAM,SAAS,KAAK,QAAQ,KAAK,EAAE,KAAK,EAAE;AAC1C,UAAI,WAAW,OAAW,MAAK,QAAQ,OAAO,MAAM;AAAA,IACtD;AACA,SAAK,QAAQ,IAAI,KAAK,WAAW;AACjC,WAAO;AAAA,EACT;AACF;AAUO,IAAM,oBAAoB,IAAI,mBAAmB;;;ACtExD,SAAS,YAAY,uBAAuB;AAC5C,SAAS,kBAAkB;;;ACL3B,SAAS,YAAY,uBAAuB;;;ACC5C,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,cAAAC,mBAAkB;;;ACW3B,SAAS,WAAW,YAAY,eAAe;;;AChB/C,SAAS,kBAAkB;;;ACG3B;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AACP,SAAS,wBAAwB;;;ACKjC,SAAS,cAAAC,aAAY,iBAAiB;;;ACnBtC,SAAS,0BAAoC;;;ACS7C,SAAS,gBAAgB,QAA+C;AACtE,SAAO;AAAA,IACL,YAAY,OAAO,cAAc;AAAA,IACjC,QAAQ,OAAO;AAAA,IACf,eAAe,OAAO;AAAA,IACtB,sBAAsB,OAAO;AAAA,IAC7B,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO;AAAA,IACd,eAAe,OAAO;AAAA,IACtB,iBAAiB,OAAO;AAAA,IACxB,kBAAkB,OAAO;AAAA,EAC3B;AACF;AAcO,SAAS,sBACd,SACA,SACqB;AACrB,QAAM,WAAW,QAAQ,QAAQ,QAAQ,GAAG;AAC5C,QAAM,SAAS,WAAW;AAC1B,SAAO;AAAA,IACL,aAAa,EAAE,QAAQ;AAAA,IACvB,SAAS,SAAS,QAAQ,QAAQ,MAAM,GAAG,QAAQ,IAAI,QAAQ;AAAA,IAC/D,QAAQ,SAAS,QAAQ,UAAU,QAAQ;AAAA,IAC3C,cAAc,QAAQ;AAAA,IACtB,UAAU,QAAQ;AAAA,IAClB,kBAAkB,QAAQ;AAAA,IAC1B,UAAU,QAAQ;AAAA,IAClB,eAAe;AAAA,EACjB;AACF;AAKA,SAAS,WAAW,QAAkD;AAEpE,MAAI,OAAO,oBAAoB,OAAO,eAAe;AACnD,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,QAAQ,OAAO,OAAO,aAClB,yBAAyB,OAAO,MAAM,UAAU,MAChD;AAAA,MACJ,YAAY,OAAO,OAAO;AAAA,MAC1B,WACE,eAAe,SACT,OAAmC,YACrC;AAAA,IACR;AAAA,EACF;AAEA,MAAI,OAAO,kBAAkB,OAAO,kBAAkB;AACpD,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,QAAQ,OAAO,gBAAgB,CAAC,KAAK;AAAA,MACrC,YAAY,OAAO,OAAO;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,gBAAgB;AAAA,IAChB,QAAQ,OAAO,gBAAgB,CAAC,KAAK;AAAA,IACrC,YAAY,OAAO,OAAO;AAAA,EAC5B;AACF;AAKA,eAAsB,aACpB,QACA,SACA,SAC+B;AAC/B,QAAM,gBAAgB,gBAAgB,MAAM;AAC5C,QAAM,UAAU,sBAAsB,SAAS,OAAO;AACtD,QAAM,SAAS,MAAM,OAAO,eAAe,OAAO;AAClD,SAAO,WAAW,MAAM;AAC1B;;;ACjGA,SAAS,YAAY,gBAAAC,eAAc,eAAe,iBAAiB;AACnE,SAAS,eAAe;;;ACYxB,IAAM,SAAS,CAACC,UAAiB,aAAaA,KAAI;AAElD,IAAM,qBAAyC;AAAA;AAAA,EAE7C;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,EACN;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,aAAa,KAAK,OAAO,iBAAiB,CAAC;AAAA,EAC7C;AAAA;AAAA,EAEA,EAAE,MAAM,gBAAgB,IAAI,qCAAqC;AAAA,EACjE,EAAE,MAAM,gBAAgB,IAAI,uCAAuC;AAAA,EACnE,EAAE,MAAM,iBAAiB,IAAI,+BAA+B;AAAA,EAC5D,EAAE,MAAM,cAAc,IAAI,6BAA6B;AAAA,EACvD,EAAE,MAAM,qBAAqB,IAAI,wBAAwB;AAAA,EACzD,EAAE,MAAM,OAAO,IAAI,qEAAqE;AAAA;AAAA,EAExF;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,aAAa,KAAK,OAAO,cAAc,CAAC;AAAA,EAC1C;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,aAAa,OAAO,OAAO,iBAAiB,CAAC;AAAA,EAC/C;AACF;AAMO,SAAS,cAAc,MAAsB;AAClD,MAAI,SAAS;AACb,aAAW,EAAE,MAAAA,OAAM,IAAI,YAAY,KAAK,oBAAoB;AAC1D,aAAS,OAAO,QAAQ,IAAI,eAAe,OAAOA,KAAI,CAAC;AAAA,EACzD;AACA,SAAO;AACT;AAOO,SAAS,WAAc,OAAa;AACzC,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,cAAc,KAAK;AAAA,EAC5B;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,SAAS,WAAW,IAAI,CAAC;AAAA,EAC7C;AACA,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,EAAE,iBAAiB,OAAO;AAC3E,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACrE,UAAI,CAAC,IAAI,WAAW,CAAC;AAAA,IACvB;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;ADpEA,IAAM,iBAAiB;AACvB,IAAM,cAAc;AAcpB,IAAM,gBAAgB,uBAAO,eAAe;AAE5C,SAAS,MAAM,IAA2C;AACxD,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,QAAQ,WAAW,MAAM,QAAQ,aAAa,GAAG,EAAE;AAEzD,QAAI,OAAO,MAAM,UAAU,WAAY,OAAM,MAAM;AAAA,EACrD,CAAC;AACH;AAEO,IAAM,kBAAN,MAAsB;AAAA,EAO3B,YAAY,QAAgC,aAAsB;AANlE,SAAQ,QAA0B,CAAC;AACnC,SAAQ,QAA+C;AAEvD,SAAQ,aAAa;AACrB,SAAQ,cAA6B;AAGnC,SAAK,SAAS;AACd,SAAK,cAAc,eAAe;AAClC,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAA0B;AAC9B,QAAI,KAAK,MAAO;AAChB,SAAK,QAAQ,YAAY,MAAM,KAAK,MAAM,GAAG,UAAU;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,eAA6B,CAAC,GAAkB;AACzD,QAAI,KAAK,OAAO;AACd,oBAAc,KAAK,KAAK;AACxB,WAAK,QAAQ;AAAA,IACf;AACA,UAAM,KAAK,MAAM,YAAY;AAC7B,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,SAAuB,UAAsC;AACnE,QAAI,KAAK,MAAM,UAAU,gBAAgB;AAEvC,WAAK,MAAM,MAAM;AAAA,IACnB;AAKA,SAAK,MAAM,KAAK;AAAA,MACd,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,MAC3D,SAAS,WAAW,OAAO;AAAA,MAC3B,UAAU,WAAW,QAAQ;AAAA,MAC7B,WAAW,oBAAI,KAAK;AAAA,MACpB,YAAY;AAAA,MACZ,QAAQ;AAAA,IACV,CAAC;AAED,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAM,UAAwB,CAAC,GAAkB;AACrD,QAAI,KAAK,WAAY;AACrB,SAAK,aAAa;AAElB,QAAI;AACF,YAAM,UAAU,KAAK,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AAC/D,YAAM,QAAQ,OAAO,QAAQ,UAAU,WAAW,QAAQ,MAAM,GAAG,QAAQ,KAAK,IAAI;AAEpF,iBAAW,SAAS,OAAO;AAGzB,cAAM,UAAU,aAAa,KAAK,QAAQ,MAAM,SAAS,KAAK,OAAO,OAAO,EACzE,KAAK,MAAM,QAAiB,EAC5B,MAAM,MAAM,OAAgB;AAC/B,cAAM,SAAS,QAAQ,oBACnB,MAAM,QAAQ,KAAK,CAAC,SAAS,MAAM,QAAQ,iBAAiB,CAAC,CAAC,IAC9D,MAAM;AAEV,YAAI,WAAW,eAAe;AAG5B;AAAA,QACF;AACA,YAAI,WAAW,UAAU;AACvB,gBAAM,SAAS;AAAA,QACjB,OAAO;AACL,gBAAM;AACN,cAAI,MAAM,cAAc,aAAa;AACnC,kBAAM,SAAS;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAGA,WAAK,QAAQ,KAAK,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AAC5D,WAAK,WAAW;AAAA,IAClB,UAAE;AACA,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAgD;AAC9C,WAAO;AAAA,MACL,SAAS,KAAK,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE;AAAA,MAC1D,OAAO,KAAK,MAAM;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,QAAI,CAAC,KAAK,YAAa;AAEvB,QAAI;AACF,UAAI,CAAC,WAAW,KAAK,WAAW,EAAG;AACnC,YAAM,OAAOC,cAAa,KAAK,aAAa,OAAO;AACnD,YAAM,UAAU,KAAK,MAAM,IAAI;AAE/B,WAAK,QAAQ,QACV,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EACpC,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,WAAW,IAAI,KAAK,EAAE,SAAS,EAAE,EAAE;AAAA,IAC5D,QAAQ;AAEN,WAAK,QAAQ,CAAC;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAmB;AACzB,QAAI,CAAC,KAAK,YAAa;AAEvB,QAAI;AACF,YAAM,MAAM,QAAQ,KAAK,WAAW;AACpC,UAAI,CAAC,WAAW,GAAG,EAAG,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACxD,oBAAc,KAAK,aAAa,KAAK,UAAU,KAAK,OAAO,MAAM,CAAC,GAAG,OAAO;AAAA,IAC9E,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAKO,SAAS,aACd,WACA,WACA,SACsB;AAEtB,QAAM,WAAW,UAAU,SAAS,OAAO;AAG3C,YAAU,QAAQ,SAAS,QAAQ;AAEnC,SAAO;AACT;;;AExMA,SAAS,gBAAgB,aAAAC,YAAW,cAAAC,aAAY,UAAU,aAAa,kBAAkB;AACzF,SAAS,YAAY;AAIrB,IAAM,gBAAgB,KAAK,OAAO;AAClC,IAAM,YAAY;AAEX,IAAM,cAAN,MAAkB;AAAA,EAIvB,YAAY,WAAmB,SAAkB;AAC/C,SAAK,YAAY;AACjB,SAAK,UAAU;AAEf,QAAI,SAAS;AACX,MAAAC,WAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,SAAuB,UAAsC;AACzE,QAAI,CAAC,KAAK,QAAS;AAMnB,QAAI;AACJ,QAAI;AACF,cAAQ;AAAA,QACN,IAAI,KAAK,WAAW;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,SAAS,WAAW,OAAO;AAAA,QAC3B,UAAU,WAAW,QAAQ;AAAA,MAC/B;AAAA,IACF,SAAS,KAAK;AACZ,cAAQ;AAAA,QACN,IAAI,KAAK,WAAW;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,UAAU;AAAA,UACR,OAAO,2BAA2B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UAClF,gBAAgB,SAAS;AAAA,UACzB,SAAS,QAAQ;AAAA,UACjB,QAAQ,QAAQ;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AACA,SAAK,MAAM,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,UAAkB,QAAsB;AACjD,QAAI,CAAC,KAAK,QAAS;AAEnB,SAAK,MAAM;AAAA,MACT,IAAI,KAAK,WAAW;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,MACpB,MAAM;AAAA,MACN,UAAU,EAAE,UAAU,OAAO;AAAA,IAC/B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,MAAc,IAAkB;AAC5C,QAAI,CAAC,KAAK,QAAS;AAEnB,SAAK,MAAM;AAAA,MACT,IAAI,KAAK,WAAW;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,MACpB,MAAM;AAAA,MACN,UAAU,EAAE,MAAM,GAAG;AAAA,IACvB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,OAAe,SAA8B;AACpD,QAAI,CAAC,KAAK,QAAS;AAEnB,SAAK,MAAM;AAAA,MACT,IAAI,KAAK,WAAW;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,MACpB,MAAM;AAAA,MACN;AAAA,MACA,UAAU,EAAE,MAAM;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEQ,MAAM,OAAyB;AACrC,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,UAAU,KAAK,IAAI;AAAA,IACjC,QAAQ;AAEN;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,KAAK,mBAAmB;AAGzC,UAAIC,YAAW,QAAQ,GAAG;AACxB,cAAM,QAAQ,SAAS,QAAQ;AAC/B,YAAI,MAAM,OAAO,eAAe;AAC9B,eAAK,OAAO;AAAA,QACd;AAAA,MACF;AASA,eAAS,UAAU,GAAG,UAAU,GAAG,WAAW;AAC5C,YAAI;AACF,yBAAe,UAAU,IAAI;AAC7B;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AACA,YAAM,eAAe,SAAS,QAAQ,YAAY,KAAK,QAAQ,GAAG,QAAQ;AAC1E,qBAAe,cAAc,IAAI;AAAA,IACnC,QAAQ;AAGN,UAAI;AACF,gBAAQ,MAAM,yDAAyD,KAAK,KAAK,CAAC,EAAE;AAAA,MACtF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,qBAA6B;AACnC,UAAM,QAAO,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAClD,WAAO,KAAK,KAAK,WAAW,SAAS,IAAI,QAAQ;AAAA,EACnD;AAAA,EAEQ,SAAe;AACrB,QAAI;AACF,YAAM,QAAQ,YAAY,KAAK,SAAS,EACrC,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ,KAAK,EAAE,SAAS,QAAQ,CAAC,EAC5D,KAAK;AAER,aAAO,MAAM,UAAU,WAAW;AAChC,cAAM,SAAS,MAAM,MAAM;AAC3B,mBAAW,KAAK,KAAK,WAAW,MAAM,CAAC;AAAA,MACzC;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,aAAqB;AAC3B,WAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,EAChE;AACF;;;ACvJO,IAAM,mBAAN,MAAuB;AAAA,EAO5B,YAAY,QAAgC;AAL5C,SAAQ,YAAmC;AAC3C,SAAQ,YAAoC;AAC5C,SAAQ,cAAkC;AAC1C,SAAQ,cAAc;AAGpB,SAAK,SAAS;AACd,SAAK,eAAe;AAAA,EACtB;AAAA,EAEQ,iBAAuB;AAC7B,UAAM,EAAE,KAAK,IAAI,KAAK;AAEtB,QAAI,SAAS,UAAU;AACrB,UAAI,CAAC,KAAK,OAAO,cAAc,CAAC,KAAK,OAAO,QAAQ;AAClD,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AAAA,IACF;AAEA,QAAI,SAAS,SAAS;AACpB,UAAI,CAAC,KAAK,OAAO,cAAc,CAAC,KAAK,OAAO,QAAQ;AAClD,cAAM,IAAI,MAAM,0CAA0C;AAAA,MAC5D;AAAA,IACF;AAEA,QAAI,SAAS,UAAU;AACrB,UAAI,CAAC,KAAK,OAAO,cAAc,CAAC,KAAK,OAAO,QAAQ;AAClD,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAA4B;AAChC,QAAI,KAAK,YAAa;AAEtB,UAAM,EAAE,KAAK,IAAI,KAAK;AAEtB,QAAI,SAAS,WAAW,SAAS,UAAU;AACzC,WAAK,YAAY,cAAc,KAAK,MAAM;AAAA,IAC5C;AAEA,QAAI,SAAS,UAAU;AACrB,YAAM,cAAc,KAAK,OAAO,YAC5B,GAAG,KAAK,OAAO,SAAS,wBACxB;AACJ,WAAK,YAAY,IAAI,gBAAgB,KAAK,QAAQ,WAAW;AAC7D,YAAM,cAAc,KAAK,OAAO,gBAAgB,QAAQ;AACxD,WAAK,UAAU,MAAM,UAAU;AAAA,IACjC;AAGA,QAAI,KAAK,OAAO,cAAc;AAC5B,YAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,WAAK,cAAc,IAAI,YAAY,WAAW,IAAI;AAAA,IACpD;AAEA,SAAK,cAAc;AAEnB,QAAI,KAAK,OAAO,OAAO;AACrB,YAAM,UAAU,KAAK,OAAO,WAAW;AACvC,cAAQ,IAAI,qCAAqC,IAAI,UAAU,OAAO,GAAG;AAAA,IAC3E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAAS,SAAuD;AACpE,QAAI,KAAK,WAAW;AAClB,YAAM,KAAK,UAAU,KAAK,SAAS,aAAa,CAAC,CAAC;AAClD,WAAK,YAAY;AAAA,IACnB;AAEA,SAAK,YAAY;AACjB,SAAK,cAAc;AAEnB,QAAI,KAAK,OAAO,OAAO;AACrB,cAAQ,IAAI,8BAA8B;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAAS,SAAuB,SAAiD;AACrF,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,KAAK,WAAW;AAAA,IACxB;AAEA,QAAI;AAEJ,YAAQ,KAAK,OAAO,MAAM;AAAA,MACxB,KAAK;AACH,mBAAW,MAAM,aAAa,KAAK,QAAQ,SAAS,WAAW,KAAK,OAAO,OAAO;AAClF;AAAA,MAEF,KAAK;AACH,YAAI,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,iCAAiC;AACtE,mBAAW,YAAY,KAAK,WAAW,OAAO;AAC9C;AAAA,MAEF,KAAK;AACH,YAAI,CAAC,KAAK,aAAa,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,6BAA6B;AACrF,mBAAW,aAAa,KAAK,WAAW,KAAK,WAAW,OAAO;AAC/D;AAAA,MAEF;AACE,cAAM,IAAI,MAAM,iBAAiB,KAAK,OAAO,IAAI,EAAE;AAAA,IACvD;AAGA,QAAI,KAAK,OAAO,YAAY,aAAa,SAAS,mBAAmB,SAAS;AAC5E,iBAAW;AAAA,QACT,GAAG;AAAA,QACH,gBAAgB;AAAA,QAChB,QAAQ,6BAA6B,SAAS,cAAc,KAAK,SAAS,MAAM;AAAA,MAClF;AAAA,IACF;AAGA,SAAK,aAAa,cAAc,SAAS,QAAQ;AAEjD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAuC;AACzC,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAgC;AAClC,WAAO,KAAK,OAAO,WAAW;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WACJ,SACA,kBACe;AACf,UAAM,UAAU,KAAK,OAAO;AAC5B,UAAM,KAAK,SAAS;AAEpB,SAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAG,kBAAkB,MAAM,QAAQ;AACnE,SAAK,eAAe;AACpB,UAAM,KAAK,WAAW;AAEtB,SAAK,aAAa,cAAc,SAAS,OAAO;AAEhD,QAAI,KAAK,OAAO,OAAO;AACrB,cAAQ,IAAI,kCAAkC,OAAO,OAAO;AAAA,IAC9D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAA2D;AACzD,WAAO,KAAK,WAAW,UAAU,KAAK;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe,UAAkB,QAAsB;AACrD,SAAK,aAAa,WAAW,UAAU,MAAM;AAAA,EAC/C;AACF;;;AChNA,SAAS,cAAAC,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,aAAY;;;ACKrB,SAAS,WAAW,cAAAC,aAAY,aAAAC,YAAW,gBAAAC,eAAc,iBAAAC,sBAAqB;AAC9E,SAAS,eAAe;AACxB,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAsBvB,SAAS,gBACd,WAA4B,QAAQ,UACpC,MAAyB,QAAQ,KACzB;AACR,MAAI,aAAa,SAAU,QAAO;AAClC,MAAI,aAAa,QAAS,QAAOA,MAAK,IAAI,eAAe,mBAAmB,WAAW;AACvF,SAAO;AACT;AAEO,SAAS,WAAW,UAA4B,CAAC,GAAe;AACrE,QAAM,OAAO,QAAQ,QAAQ,QAAQ;AACrC,QAAM,aACJ,QAAQ,cACR,QAAQ,KAAK,+BACb,gBAAgB,QAAQ,UAAU,QAAQ,GAAG;AAC/C,QAAM,UAAUA,MAAK,MAAM,cAAc,OAAO;AAChD,SAAO;AAAA,IACL,eAAeA,MAAK,YAAY,YAAY;AAAA,IAC5C,eAAeA,MAAK,YAAY,YAAY;AAAA,IAC5C;AAAA,IACA,YAAYA,MAAK,SAAS,aAAa;AAAA,IACvC,YAAYA,MAAK,SAAS,YAAY;AAAA,IACtC,cAAcA,MAAK,SAAS,eAAe;AAAA,IAC3C,OAAOA,MAAK,SAAS,YAAY;AAAA,EACnC;AACF;AAEA,SAAS,YAAY,OAAyC;AAC5D,QAAM,IAAI;AACV,SACE,CAAC,CAAC,KACF,OAAO,EAAE,aAAa,YACtB,OAAO,EAAE,eAAe,YACxB,OAAO,EAAE,eAAe,YACxB,CAAC,CAAC,EAAE,OACJ,OAAO,EAAE,IAAI,YAAY,YACzB,CAAC,CAAC,EAAE,QACJ,MAAM,QAAQ,EAAE,KAAK,IAAI;AAE7B;AAiBO,SAAS,cAAc,OAA8D;AAC1F,QAAM,aAAkD;AAAA,IACtD,CAAC,MAAM,eAAe,SAAS;AAAA,IAC/B,CAAC,MAAM,YAAY,MAAM;AAAA,EAC3B;AACA,aAAW,CAAC,MAAM,KAAK,KAAK,YAAY;AACtC,QAAI,CAACL,YAAW,IAAI,EAAG;AACvB,QAAI;AACF,YAAM,SAAkB,KAAK,MAAME,cAAa,MAAM,OAAO,CAAC;AAC9D,UAAI,YAAY,MAAM,EAAG,QAAO,EAAE,WAAW,QAAQ,MAAM;AAAA,IAC7D,QAAQ;AAAA,IAER;AACA,WAAO,EAAE,SAAS,MAAM,KAAK;AAAA,EAC/B;AACA,SAAO;AACT;AAEA,SAAS,cAAc,MAAc,SAAiB,MAAoB;AACxE,EAAAD,WAAUG,SAAQ,IAAI,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACzD,EAAAD,eAAc,MAAM,SAAS,EAAE,UAAU,SAAS,KAAK,CAAC;AACxD,MAAI;AACF,cAAU,MAAM,IAAI;AAAA,EACtB,QAAQ;AAAA,EAER;AACF;AAaO,SAAS,mBAAmB,OAA6B;AAC9D,QAAM,MAAgB,CAAC;AACvB,aAAW,KAAK,CAAC,MAAM,YAAY,MAAM,aAAa,GAAG;AACvD,QAAI;AACF,UAAIG,YAAW,CAAC,EAAG,KAAI,KAAKC,cAAa,GAAG,OAAO,EAAE,KAAK,CAAC;AAAA,IAC7D,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO,IAAI,OAAO,OAAO;AAC3B;AAEO,SAAS,kBAAkB,OAAmB,KAAmB;AACtE,gBAAc,MAAM,YAAY,KAAK,GAAK;AAC5C;AAEO,SAAS,aAAa,OAA6B;AACxD,MAAI;AACF,UAAM,SAAkB,KAAK,MAAMA,cAAa,MAAM,cAAc,OAAO,CAAC;AAC5E,WAAO,MAAM,QAAQ,MAAM,IAAI,OAAO,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IAAI,CAAC;AAAA,EAC7F,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEO,SAAS,cAAc,OAAmB,OAAuB;AACtE,gBAAc,MAAM,cAAc,KAAK,UAAU,KAAK,GAAG,GAAK;AAChE;AAMO,SAAS,UAAU,OAA+B;AACvD,MAAI;AACF,UAAM,SAAS,KAAK,MAAMC,cAAa,MAAM,OAAO,OAAO,CAAC;AAC5D,UAAM,IAAI,OAAO;AACjB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,OAAO,EAAE;AAAA,IACvE;AAAA,EACF,QAAQ;AACN,WAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,EAAE,EAAE;AAAA,EACjD;AACF;AAEO,SAAS,WAAW,OAAmB,OAAyB;AACrE,MAAI;AACF,kBAAc,MAAM,OAAO,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG,GAAK;AAAA,EAClE,QAAQ;AAAA,EAER;AACF;;;AD3IO,SAAS,mBACd,KACA,YACA,OAAeC,SAAQ,GACK;AAC5B,QAAM,iBAAiB,CAAC,IAAI,oBAAoB,YAAY,IAAI,EAAE;AAAA,IAChE,CAAC,SAAyB,OAAO,SAAS,YAAY,KAAK,SAAS;AAAA,EACtE;AAEA,aAAW,QAAQ,gBAAgB;AACjC,UAAM,WAAWC,MAAK,MAAM,YAAY;AACxC,UAAM,aAAaA,MAAK,UAAU,aAAa;AAC/C,QAAI,CAACC,YAAW,UAAU,EAAG;AAE7B,QAAI,WAA0B,CAAC;AAC/B,UAAM,eAAeD,MAAK,UAAU,YAAY;AAChD,QAAIC,YAAW,YAAY,GAAG;AAC5B,UAAI;AACF,mBAAW,KAAK,MAAMC,cAAa,cAAc,OAAO,CAAC;AAAA,MAC3D,QAAQ;AAGN,mBAAW,CAAC;AAAA,MACd;AAAA,IACF;AAEA,WAAO,EAAE,YAAY,UAAU,SAAS;AAAA,EAC1C;AAEA,SAAO;AACT;AA4BO,IAAM,0BACX;AAOK,SAAS,aACd,KACA,OAAeH,SAAQ,GACvB,QAAoB,WAAW,EAAE,MAAM,IAAI,CAAC,GACU;AACtD,QAAM,SAAS,cAAc,KAAK;AAClC,MAAI,UAAU,aAAa,QAAQ;AACjC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,sBAAsB,OAAO,IAAI,yBAAoB,uBAAuB;AAAA,MACpF;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAQ,QAAO,EAAE,MAAM,SAAS,WAAW,OAAO,WAAW,OAAO,OAAO,OAAO,MAAM;AAC5F,MAAI,IAAI,6BAA6B,KAAK;AACxC,WAAO,EAAE,MAAM,iBAAiB,QAAQ,yBAAyB,MAAM;AAAA,EACzE;AACA,SAAO;AACT;;;AExHA,SAAS,QAAAI,aAAY;;;ACFd,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YACE,SACS,QACA,MACT;AACA,UAAM,OAAO;AAHJ;AACA;AAGT,SAAK,OAAO;AAAA,EACd;AACF;AAwCA,SAAS,KAAK,KAAqB;AACjC,SAAO,IAAI,QAAQ,QAAQ,EAAE;AAC/B;AAEA,eAAe,KACb,KACA,MACA,WAC8D;AAC9D,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAC5D,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,KAAK,EAAE,GAAG,MAAM,QAAQ,WAAW,OAAO,CAAC;AACtE,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,OAAgB;AACpB,QAAI;AACF,aAAO,OAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IACnC,QAAQ;AAAA,IAER;AACA,WAAO,EAAE,QAAQ,IAAI,QAAQ,MAAM,SAAS,IAAI,QAAQ;AAAA,EAC1D,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACF;AAEA,SAAS,SAAS,QAAgB,MAAe,MAA6B;AAC5E,QAAM,IAAK,QAAQ,CAAC;AACpB,QAAM,OAAO,EAAE,SAAS,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ;AAChE,SAAO,IAAI,cAAc,GAAG,IAAI,YAAY,MAAM,GAAG,OAAO,IAAI,IAAI,KAAK,EAAE,KAAK,QAAQ,IAAI;AAC9F;AAwBA,SAAS,cAAc,WAAmD;AACxE,SAAO,EAAE,eAAe,UAAU,UAAU,UAAU,GAAG;AAC3D;AAGO,SAAS,WAAW,QAAgB,KAAiC;AAC1E,SAAO,GAAG,MAAM,IAAI,OAAO,EAAE;AAC/B;AAEA,eAAsB,iBACpB,WACA,aACA,YAAY,MACgB;AAC5B,QAAM,UAAkC,cAAc,SAAS;AAC/D,MAAI,YAAa,SAAQ,eAAe,IAAI,IAAI,WAAW;AAC3D,QAAM,IAAI,MAAM,KAAK,GAAG,KAAK,UAAU,UAAU,CAAC,iBAAiB,EAAE,QAAQ,GAAG,SAAS;AACzF,MAAI,EAAE,WAAW,IAAK,QAAO,EAAE,QAAQ,YAAY;AACnD,MAAI,EAAE,WAAW,IAAK,OAAM,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc;AACrE,QAAM,OAAO,EAAE;AAMf,MAAI,CAAC,MAAM,UAAW,OAAM,IAAI,cAAc,oCAAoC,EAAE,MAAM;AAC1F,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,WAAW,KAAK;AAAA,IAChB,QAAQ,KAAK,UAAU;AAAA,IACvB,SAAS,KAAK,WAAW;AAAA,IACzB,UAAU,MAAM,QAAQ,KAAK,QAAQ,IACjC,KAAK,SAAS,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IAC9D,CAAC;AAAA,EACP;AACF;AAEA,eAAsB,cACpB,WACA,SACA,YAAY,MACgB;AAC5B,QAAM,IAAI,MAAM;AAAA,IACd,GAAG,KAAK,UAAU,UAAU,CAAC;AAAA,IAC7B;AAAA,MACE,QAAQ;AAAA,MACR,SAAS,EAAE,GAAG,cAAc,SAAS,GAAG,gBAAgB,mBAAmB;AAAA,MAC3E,MAAM,KAAK,UAAU,OAAO;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AACA,MAAI,EAAE,WAAW,IAAK,OAAM,SAAS,EAAE,QAAQ,EAAE,MAAM,WAAW;AAClE,SAAO,EAAE;AACX;;;AC1JA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,eAAe,yBAA6C;;;ACD9D,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAEzB,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AACvB,IAAM,iCAAiC;;;ADUvC,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AASA,SAAS,UAAU,MAAsB;AACvC,SAAOC,YAAW,QAAQ,EAAE,OAAO,MAAM,MAAM,EAAE,OAAO,KAAK;AAC/D;AAEA,SAAS,cAAc,KAA6B;AAClD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,OAAM,IAAI,iBAAiB,kBAAkB;AAClF,QAAM,IAAI;AACV,MAAI,EAAE,YAAY,YAAY,EAAE,YAAY,WAAW;AACrD,UAAM,IAAI,iBAAiB,4CAA4C;AAAA,EACzE;AACA,MAAI,EAAE,aAAa,UAAa,OAAO,EAAE,aAAa,WAAW;AAC/D,UAAM,IAAI,iBAAiB,qCAAqC;AAAA,EAClE;AACA,MAAI,EAAE,cAAc,UAAa,OAAO,EAAE,cAAc,WAAW;AACjE,UAAM,IAAI,iBAAiB,sCAAsC;AAAA,EACnE;AACA,MACE,EAAE,cAAc,UAChB,EAAE,MAAM,QAAQ,EAAE,SAAS,KAAK,EAAE,UAAU,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ,IAC9E;AACA,UAAM,IAAI,iBAAiB,2CAA2C;AAAA,EACxE;AACA,QAAM,MAAM,CAAC,MACX,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,KAAK,IAAI,IAAI,IAAI;AAC7D,SAAO;AAAA,IACL,SAAS,EAAE;AAAA,IACX,UAAU,EAAE,aAAa;AAAA,IACzB,GAAI,OAAO,EAAE,cAAc,aAAa,EAAE,WAAW,EAAE,UAAU;AAAA,IACjE,GAAI,MAAM,QAAQ,EAAE,SAAS,KAAK,EAAE,WAAW,EAAE,UAAsB;AAAA,IACvE,GAAI,IAAI,EAAE,oBAAoB,KAAK,EAAE,sBAAsB,IAAI,EAAE,oBAAoB,EAAE;AAAA,IACvF,GAAI,IAAI,EAAE,aAAa,KAAK,EAAE,eAAe,IAAI,EAAE,aAAa,EAAE;AAAA,EACpE;AACF;AAEA,eAAsB,kBACpB,KACA,MACA,SAC8B;AAC9B,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,kBAAkB,IAAgC;AACjE,UAAM,SAAS,MAAM,cAAc,KAAK,QAAQ,EAAE,YAAY,CAAC,OAAO,EAAE,CAAC;AACzE,mBAAe,OAAO;AACtB,aAAS,OAAO;AAAA,EAClB,SAAS,KAAK;AACZ,UAAM,IAAI;AAAA,MACR,kCAAkC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACpF;AAAA,EACF;AACA,MAAI,OAAO,QAAQ,iBAAkB,OAAM,IAAI,iBAAiB,kBAAkB,OAAO,GAAG,EAAE;AAE9F,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,IAAI,YAAY,EAAE,OAAO,YAAY,CAAC;AAAA,EAC5D,QAAQ;AACN,UAAM,IAAI,iBAAiB,qBAAqB;AAAA,EAClD;AACA,MAAI,OAAO,QAAQ,iBAAkB,OAAM,IAAI,iBAAiB,kBAAkB,OAAO,GAAG,EAAE;AAC9F,MAAI,OAAO,QAAQ,iBAAkB,OAAM,IAAI,iBAAiB,kBAAkB,OAAO,GAAG,EAAE;AAC9F,MAAI,CAAC,QAAQ,aAAa,SAAS,OAAO,GAAG,GAAG;AAC9C,UAAM,IAAI,iBAAiB,0DAA0D;AAAA,EACvF;AACA,MAAI,CAAC,OAAO,UAAU,OAAO,GAAG,KAAK,OAAO,MAAM,GAAG;AACnD,UAAM,IAAI,iBAAiB,gCAAgC;AAAA,EAC7D;AACA,MAAI,QAAQ,WAAW,UAAa,OAAO,MAAM,QAAQ,QAAQ;AAC/D,UAAM,IAAI;AAAA,MACR,kBAAkB,OAAO,GAAG,uCAAuC,QAAQ,MAAM;AAAA,IACnF;AAAA,EACF;AACA,MAAI,OAAO,OAAO,SAAS,YAAY,UAAU,OAAO,IAAI,MAAM,OAAO,QAAQ;AAC/E,UAAM,IAAI,iBAAiB,sBAAsB;AAAA,EACnD;AACA,QAAM,WAAW,cAAc,OAAO,QAAQ;AAC9C,QAAM,SAAS,UAAU,OAAO,IAAI;AACpC,MAAI,CAAC,OAAO,QAAQ;AAClB,UAAM,QAAQ,OAAO,WAAW,OAAO,CAAC;AACxC,UAAM,IAAI;AAAA,MACR,2BAA2B,QAAQ,KAAK,MAAM,IAAI,KAAK,MAAM,OAAO,MAAM,EAAE;AAAA,IAC9E;AAAA,EACF;AACA,SAAO,EAAE,KAAK,OAAO,KAAK,QAAQ,EAAE,GAAG,QAAQ,SAAS,GAAG,QAAQ,OAAO,QAAQ,UAAU,IAAI;AAClG;AAUA,eAAsB,iBACpB,QACA,OACA,SACoB;AACpB,MAAI,UAAU;AACd,MAAI,UAAU;AACd,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,YAAM,EAAE,SAAS,gBAAgB,IAAI,MAAM;AAAA,QACzC;AAAA,QACA,kBAAkB,OAAmC;AAAA,QACrD,EAAE,YAAY,CAAC,OAAO,EAAE;AAAA,MAC1B;AACA,UAAI,gBAAgB,QAAQ,eAAgB;AAC5C,YAAM,IAAI,KAAK,MAAM,IAAI,YAAY,EAAE,OAAO,OAAO,CAAC;AACtD,UAAI,EAAE,QAAQ,kBAAkB,EAAE,QAAQ,oBAAoB,EAAE,QAAQ,QAAS;AACjF,UAAI,CAAC,OAAO,UAAU,EAAE,GAAG,KAAK,EAAE,OAAO,QAAS;AAClD,YAAM,OAAO,MAAM,QAAQ,EAAE,IAAI,IAC7B,EAAE,KAAK,OAAO,CAAC,MAAM,KAAK,EAAE,QAAQ,QAAQ,EAAE,QAAQ,WAAW,EAAE,OAAO,EAAE,IAC5E,CAAC;AACL,UAAI,KAAK,WAAW,EAAG;AACvB,gBAAU,EAAE,KAAK;AACjB,gBAAU,EAAE;AAAA,IACd,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAMA,eAAsB,gBACpB,YACA,MACA,SAC8B;AAC9B,MAAI,OAAmC;AACvC,MAAI,YAAmB,IAAI,iBAAiB,wBAAwB;AACpE,aAAW,OAAO,YAAY;AAC5B,QAAI;AACF,YAAM,IAAI,MAAM,kBAAkB,KAAK,MAAM,OAAO;AACpD,UAAI,CAAC,QAAQ,EAAE,OAAO,MAAM,KAAK,OAAO,IAAK,QAAO;AAAA,IACtD,SAAS,KAAK;AACZ,kBAAY,eAAe,QAAQ,MAAM,IAAI,iBAAiB,OAAO,GAAG,CAAC;AAAA,IAC3E;AAAA,EACF;AACA,MAAI,CAAC,KAAM,OAAM;AACjB,SAAO;AACT;;;AExJO,IAAM,uBAAuB;AAOpC,SAAS,aAAa,WAAqC;AACzD,SAAO,CAAC,UAAU,IAAI,SAAS,UAAU,QAAQ;AACnD;AAGO,SAAS,UACd,KACA,QAAkB,aAAa,IAAI,KAAK,GACpB;AACpB,SAAO,iBAAiB,IAAI,UAAU,MAAM,OAAO,IAAI,UAAU,IAAI,OAAO;AAC9E;AAMA,eAAe,cACb,KACA,SACA,YAC8B;AAC9B,QAAM,OAAO,MAAM,UAAU,KAAK,QAAQ,QAAQ;AAClD,QAAM,WAAW,MAAM,kBAAkB,QAAQ,WAAW,MAAM,UAAU;AAC5E,MAAI,QAAQ,SAAS,SAAS,EAAG,eAAc,IAAI,OAAO,QAAQ,QAAQ;AAC1E,oBAAkB,IAAI,OAAO,QAAQ,SAAS;AAC9C,SAAO;AACT;AAEA,SAAS,SAAS,OAAmB,OAAmB,UAAqC;AAC3F,QAAM,gBAAgB,SAAS,OAAO;AACtC,QAAM,SAAS,KAAK,IAAI,MAAM,UAAU,GAAG,SAAS,OAAO,GAAG;AAC9D,aAAW,OAAO,KAAK;AACzB;AAOA,eAAsB,gBACpB,KACA,UAAuC,CAAC,GACV;AAC9B,QAAM,QAAQ,UAAU,IAAI,KAAK;AACjC,QAAM,aAAa,EAAE,cAAc,aAAa,IAAI,SAAS,GAAG,QAAQ,MAAM,OAAO;AACrF,QAAM,SAAS,mBAAmB,IAAI,KAAK;AAE3C,MAAI,aAA2B;AAC/B,MAAI,OAAO,SAAS,GAAG;AACrB,QAAI;AACF,YAAM,WAAW,MAAM,gBAAgB,QAAQ,MAAM,UAAU,GAAG,GAAG,UAAU;AAC/E,UAAI,SAAS,OAAO,WAAW,MAAM,iBAAiB,SAAS,OAAO,QAAQ,MAAM,QAAQ;AAC1F,iBAAS,IAAI,OAAO,OAAO,QAAQ;AAAA,MACrC;AACA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,mBAAa,eAAe,QAAQ,MAAM,IAAI,iBAAiB,OAAO,GAAG,CAAC;AAAA,IAC5E;AAAA,EACF;AAGA,MAAI;AACF,UAAM,UAAU,MAAM;AAAA,MACpB,IAAI;AAAA,MACJ;AAAA,MACA,QAAQ,kBAAkB;AAAA,IAC5B;AACA,QAAI,QAAQ,WAAW,MAAM;AAC3B,YAAM,WAAW,MAAM,cAAc,KAAK,SAAS,UAAU;AAC7D,eAAS,IAAI,OAAO,OAAO,QAAQ;AACnC,aAAO;AAAA,IACT;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,eAAe,iBAAiB,IAAI,SAAS,kBAAkB;AACjE,YAAM,UAAU;AAChB,iBAAW,IAAI,OAAO,KAAK;AAAA,IAC7B;AACA,UAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,UAAM,IAAI;AAAA,MACR,aACI,GAAG,WAAW,OAAO,qBAAqB,MAAM,MAChD,oBAAoB,MAAM;AAAA,IAChC;AAAA,EACF;AACA,QAAM,cAAc,IAAI,iBAAiB,2BAA2B;AACtE;AAoBA,eAAsB,2BACpB,KACA,SAEA,UACA,SAC2B;AAC3B,QAAM,MAAM,QAAQ,OAAO,KAAK;AAChC,QAAM,QAAQ,UAAU,IAAI,KAAK;AACjC,MAAI,SAAU,OAAM,OAAO,QAAQ,KAAK;AAExC,QAAM,cACJ,QAAQ,SAAS,wBACjB,IAAI,UAAU,wBACd;AACF,QAAM,OAAO,MAAM,kBAAkB,KAAK,MAAM,MAAM,eAAe,IAAI;AACzE,MAAI,IAAI,IAAI,OAAO,cAAc,KAAM;AACrC,eAAW,IAAI,OAAO,KAAK;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,IAAI,KAAK,QAAQ,YAAY;AAC9C,QAAM,YAAY,MAAM,KAAK,IAAI,GAAG,WAAW,IAAI,CAAC;AAEpD,QAAM,kBAAkB,IAAI,KAAK,IAAI,CAAC,EAAE,YAAY;AAEpD,MAAI,UAA4B;AAChC,MAAI;AACF,UAAM,KAAK,MAAM;AAAA,MACf,IAAI;AAAA,MACJ;AAAA,QACE,eAAe,QAAQ,OAAO;AAAA,QAC9B,cAAc,QAAQ;AAAA,QACtB,UAAU,CAAC,EAAE,MAAM,QAAQ,aAAa,SAAS,KAAK,CAAC;AAAA,QACvD,SAAS,QAAQ,SAAS;AAAA,QAC1B,gBAAgB,EAAE,GAAG,MAAM,OAAO;AAAA,MACpC;AAAA,MACA,UAAU;AAAA,IACZ;AACA,UAAM,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,EAAE;AAC3C,UAAM,UAAU;AAChB,WAAO,MAAM;AAEb,UAAM,gBAAgB,CAAC,CAAC,GAAG,gBAAgB,GAAG,iBAAiB,QAAQ,OAAO;AAE9E,UAAM,aAAa,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,QAAQ,OAAO,GAAG,cAAc,QAAQ;AAC/E,QAAI,iBAAiB,YAAY;AAC/B,YAAM,UAAU,MAAM;AAAA,QACpB,IAAI;AAAA,QACJ,WAAW,QAAQ,OAAO,QAAQ,QAAQ,GAAG;AAAA,QAC7C,UAAU;AAAA,MACZ;AACA,UAAI,QAAQ,WAAW,MAAM;AAC3B,cAAM,WAAW,MAAM,cAAc,KAAK,SAAS;AAAA,UACjD,cAAc,aAAa,IAAI,SAAS;AAAA,UACxC,QAAQ,KAAK,IAAI,MAAM,UAAU,GAAG,QAAQ,OAAO,GAAG;AAAA,QACxD,CAAC;AACD,cAAM,gBAAgB,SAAS,OAAO;AACtC,cAAM,SAAS,KAAK,IAAI,MAAM,UAAU,GAAG,SAAS,OAAO,GAAG;AAC9D,kBAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,eAAe,iBAAiB,IAAI,SAAS,kBAAkB;AAEjE,YAAM,UAAU;AAChB,gBAAU;AAAA,IACZ,OAAO;AACL,YAAM,YAAY,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACjE,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,aAAW,IAAI,OAAO,KAAK;AAC3B,SAAO;AACT;;;AJxKA,IAAM,SAAS;AAEf,eAAsB,aACpB,MAC6B;AAC7B,MAAI,KAAK,WAAW,SAAS,iBAAiB;AAC5C,WAAO,EAAE,QAAQ,KAAK,WAAW,GAAG,MAAM,KAAK,KAAK,WAAW,MAAM,EAAE,GAAG,UAAU,EAAE;AAAA,EACxF;AACA,QAAM,MAAM,EAAE,WAAW,KAAK,WAAW,WAAW,OAAO,KAAK,WAAW,MAAM;AAEjF,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,gBAAgB,GAAG;AAAA,EACtC,SAAS,KAAK;AACZ,UAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,WAAO;AAAA,MACL,QAAQ,KAAK,WAAW,GAAG,MAAM,mCAA8B,MAAM,EAAE;AAAA,MACvE,UAAU;AAAA,IACZ;AAAA,EACF;AACA,QAAM,EAAE,SAAS,IAAI;AAErB,QAAM,SAAS,OAAO,WAAkD;AACtE,QAAI;AACF,YAAM,UAAU,MAAM,2BAA2B,KAAK,UAAU,KAAK,SAAS,MAAM,GAAG;AAAA,QACrF,cAAc;AAAA,QACd,aAAa,KAAK;AAAA,QAClB,KAAK,KAAK;AAAA,MACZ,CAAC;AACD,WAAK,cAAc,OAAO;AAAA,IAC5B,QAAQ;AAAA,IAER;AACA,WAAO,EAAE,QAAQ,UAAU,EAAE;AAAA,EAC/B;AAEA,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,MAAM,KAAK,WAAW;AAAA,EACvC,QAAQ;AACN,QAAI,SAAS,SAAU,QAAO,OAAO,IAAI;AACzC,WAAO,OAAO,KAAK,WAAW,GAAG,MAAM,gCAAgC,CAAC;AAAA,EAC1E;AAEA,MAAI;AACF,UAAM,gBAA+B;AAAA,MACnC,MAAM;AAAA,MACN,QAAQ,SAAS;AAAA,MACjB,SAAS,SAAS;AAAA,MAClB,cAAc;AAAA,MACd,WAAWC,MAAK,KAAK,WAAW,MAAM,SAAS,QAAQ;AAAA,MACvD,OAAO;AAAA,IACT;AACA,UAAM,UAAU,KAAK,iBACjB,KAAK,eAAe,aAAa,IACjC,IAAI,iBAAiB,aAAa;AACtC,UAAM,QAAQ,WAAW;AAEzB,UAAM,UAAU,KAAK,cAAc;AAAA,MACjC,GAAI,SAAS,aAAa,EAAE,WAAW,SAAS,UAAU;AAAA,MAC1D,GAAI,OAAO,SAAS,cAAc,aAAa,EAAE,WAAW,SAAS,UAAU;AAAA,IACjF,CAAC;AACD,UAAM,QAAQ,WAAW,EAAE,SAAS,gBAAgB,CAAC,EAAE,CAAC;AACxD,UAAM,SAAS,MAAM,QAAQ,gBAAgB,OAAO;AACpD,UAAM,QAAQ,SAAS;AACvB,UAAM,QAAQ,SAAS;AACvB,WAAO,OAAO,MAAM;AAAA,EACtB,SAAS,KAAK;AACZ,QAAI,SAAS,SAAU,QAAO,OAAO,IAAI;AACzC,UAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,WAAO,OAAO,KAAK,WAAW,GAAG,MAAM,+BAA+B,MAAM,GAAG,CAAC;AAAA,EAClF;AACF;;;A7DhGA,IAAM,kBAAkB,OAAO;AAC/B,IAAM,mBAAmB;AAGzB,IAAM,qBAAqB;AAC3B,IAAM,0BAA0B;AAkBhC,SAAS,WAAW,QAAiC;AACnD,SAAO;AAAA,IACL,oBAAoB;AAAA,MAClB,eAAe;AAAA,MACf,oBAAoB;AAAA,MACpB,0BAA0B;AAAA,IAC5B;AAAA,EACF;AACF;AAEA,eAAsB,wBACpB,aACA,UAAmC,CAAC,GACH;AACjC,QAAM,MAAM,QAAQ,OAAO,QAAQ;AAKnC,QAAM,QAAQ,aAAa,KAAK,QAAQ,QAAQC,SAAQ,GAAG,QAAQ,UAAU;AAC7E,MAAI,OAAO;AACT,WAAO,aAAsD;AAAA,MAC3D,YAAY;AAAA,MACZ;AAAA,MACA,aAAa;AAAA,MACb,eAAe,CAAC,mBAAmB,IAAI,aAAa,cAAc;AAAA,MAClE;AAAA,MACA,UAAU,CAAC,WACT,QAAQ,oBAAoB,uBAAuB,SAC/C,SACA,QAAQ,oBAAoB,uBAAuB,QACjD,QACA;AAAA,MACR,gBAAgB,QAAQ;AAAA,MACxB,KAAK,QAAQ;AAAA,IACf,CAAC;AAAA,EACH;AAEA,MAAI,IAAI,4BAA4B,KAAK;AACvC,WAAO,EAAE,QAAQ,MAAM,UAAU,EAAE;AAAA,EACrC;AAEA,QAAM,cAAc,IAAI,8BAA8B;AAEtD,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,MAAM,WAAW;AAAA,EAClC,QAAQ;AACN,QAAI,YAAa,QAAO,EAAE,QAAQ,MAAM,UAAU,EAAE;AACpD,WAAO;AAAA,MACL,QAAQ,WAAW,qDAAqD;AAAA,MACxE,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,WAAW,mBAAmB,KAAK,QAAQ,KAAK,QAAQ,IAAI;AAClE,MAAI,CAAC,UAAU;AAEb,WAAO,EAAE,QAAQ,MAAM,UAAU,EAAE;AAAA,EACrC;AAEA,QAAM,WAAW,eAAe,SAAS,SAAS,aAAa;AAE/D,MAAI;AACF,QAAI,OAA2B,SAAS,SAAS,SAAS,WAAW,WAAW;AAChF,QAAI,SAAS,YAAY,EAAE,SAAS,SAAS,cAAc,SAAS,SAAS,SAAS;AACpF,cAAQ;AAAA,QACN;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA,YAAY,SAAS;AAAA,MACrB,SAAS,SAAS,SAAS,WAAW;AAAA,MACtC,cAAc;AAAA,MACd,WAAWC,MAAK,SAAS,UAAU,QAAQ;AAAA,MAC3C,OAAO;AAAA,MACP,GAAI,SAAS,YAAY;AAAA,QACvB,YAAY,SAAS,SAAS;AAAA,QAC9B,QAAQ,SAAS,SAAS;AAAA,QAC1B,SAAS,SAAS,SAAS;AAAA,MAC7B;AAAA,IACF;AACA,UAAM,UAAU,QAAQ,iBACpB,QAAQ,eAAe,aAAa,IACpC,IAAI,iBAAiB,aAAa;AACtC,UAAM,QAAQ,WAAW;AAEzB,UAAM,UAAU,IAAI,aAAa;AAAA,MAC/B,GAAI,SAAS,SAAS,aAAa,EAAE,WAAW,SAAS,SAAS,UAAU;AAAA,MAC5E,GAAI,OAAO,SAAS,SAAS,cAAc,aAAa;AAAA,QACtD,WAAW,SAAS,SAAS;AAAA,MAC/B;AAAA,IACF,CAAC;AACD,UAAM,QAAQ,WAAW,EAAE,SAAS,gBAAgB,CAAC,EAAE,CAAC;AAExD,UAAM,SAAS,MAAM,QAAQ,gBAAgB,OAAO;AAEpD,UAAM,QAAQ,SAAS;AACvB,UAAM,QAAQ,SAAS;AAAA,MACrB,WAAW,EAAE,OAAO,oBAAoB,mBAAmB,wBAAwB;AAAA,IACrF,CAAC;AAED,WAAO,EAAE,QAAQ,UAAU,EAAE;AAAA,EAC/B,SAAS,KAAK;AACZ,QAAI,SAAU,QAAO,EAAE,QAAQ,MAAM,UAAU,EAAE;AACjD,UAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAG9D,WAAO;AAAA,MACL,QAAQ,WAAW,oDAAoD,MAAM,GAAG;AAAA,MAChF,UAAU;AAAA,IACZ;AAAA,EACF;AACF;AAMA,SAAS,YAA6B;AACpC,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,SAAmB,CAAC;AAC1B,QAAI,QAAQ;AACZ,QAAI,OAAO;AAEX,UAAM,SAAS,MAAM;AACnB,UAAI,KAAM;AACV,aAAO;AACP,mBAAa,KAAK;AAClB,cAAQ,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO,CAAC;AAAA,IACjD;AAEA,UAAM,QAAQ,WAAW,QAAQ,gBAAgB;AAEjD,YAAQ,MAAM,GAAG,QAAQ,CAAC,UAAkB;AAC1C,eAAS,MAAM;AACf,UAAI,QAAQ,iBAAiB;AAG3B,eAAO,SAAS;AAChB,eAAO,KAAK,OAAO,KAAK,mBAAmB,CAAC;AAC5C,eAAO;AACP;AAAA,MACF;AACA,aAAO,KAAK,KAAK;AAAA,IACnB,CAAC;AACD,YAAQ,MAAM,GAAG,OAAO,MAAM;AAC9B,YAAQ,MAAM,GAAG,SAAS,MAAM;AAAA,EAClC,CAAC;AACH;AAEA,eAAe,OAAsB;AAInC,UAAQ,MAAM,IAAI,SAAoB,QAAQ,MAAM,GAAG,IAAI;AAE3D,QAAM,cAAc,MAAM,UAAU;AACpC,QAAM,SAAS,MAAM,wBAAwB,WAAW;AAExD,MAAI,OAAO,QAAQ;AACjB,YAAQ,OAAO,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC;AAAA,EACpD;AACA,UAAQ,KAAK,OAAO,QAAQ;AAC9B;AAGA,IAAI,OAAO,cAAY,eAAe,UAAQ,SAAS,QAAQ;AAC7D,OAAK,EAAE,MAAM,CAAC,QAAQ;AAGpB,YAAQ,MAAM,uCAAuC,GAAG,EAAE;AAC1D,YAAQ,KAAK,QAAQ,IAAI,8BAA8B,MAAM,IAAI,CAAC;AAAA,EACpE,CAAC;AACH;;;AkE3NA,SAAS,cAAAC,aAAY,aAAAC,YAAW,gBAAAC,eAAc,iBAAAC,sBAAqB;AACnE,SAAS,WAAAC,gBAAe;AAMjB,IAAM,wBAAwB;AAM9B,IAAM,eACX;AAEF,IAAM,uBAAuB;AAqC7B,SAAS,aAAa,OAAyBC,SAAyB;AACtE,UAAQ,MAAM,SAAS,CAAC,GAAG;AAAA,IACzB,CAAC,MAAM,OAAO,EAAE,YAAY,YAAY,EAAE,QAAQ,SAASA,OAAM;AAAA,EACnE;AACF;AAEA,SAAS,aAAa,cAAsC;AAC1D,MAAI,CAACC,YAAW,YAAY,EAAG,QAAO,CAAC;AACvC,QAAM,UAAUC,cAAa,cAAc,OAAO,EAAE,KAAK;AACzD,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,SAAO,KAAK,MAAM,OAAO;AAC3B;AAEA,SAAS,cAAc,cAAsB,UAAgC;AAC3E,EAAAC,WAAUC,SAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AACpD,EAAAC,eAAc,cAAc,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,GAAM,OAAO;AAC/E;AAEO,SAAS,eACd,aACA,UAAkB,cAClB,kBAA2C,CAAC,GAC1B;AAClB,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,MACL,EAAE,MAAM,WAAW,SAAS,aAAa,SAAS,sBAAsB,GAAG,gBAAgB;AAAA,IAC7F;AAAA,EACF;AACF;AAaO,SAAS,mBACd,cACA,aACAL,UAAiB,uBACjB,UAAkB,cAClB,kBAA2C,CAAC,GAC7B;AACf,MAAI,CAAC,YAAY,SAASA,OAAM,GAAG;AACjC,UAAM,IAAI;AAAA,MACR,+BAA+BA,OAAM,UAAU,WAAW;AAAA,IAE5D;AAAA,EACF;AAEA,QAAM,WAAW,aAAa,YAAY;AAC1C,WAAS,QAAQ,SAAS,SAAS,CAAC;AACpC,QAAM,aAAc,SAAS,MAAM,aAAa,SAAS,MAAM,cAAc,CAAC;AAE9E,QAAM,WAAW,WAAW,KAAK,CAAC,UAAU,aAAa,OAAOA,OAAM,CAAC;AACvE,MAAI,UAAU;AACZ,UAAM,QAAQ,eAAe,aAAa,SAAS,eAAe;AAClE,UAAM,UAAU,KAAK,UAAU,QAAQ,MAAM,KAAK,UAAU,KAAK;AACjE,QAAI,SAAS;AACX,iBAAW,WAAW,QAAQ,QAAQ,CAAC,IAAI;AAC3C,oBAAc,cAAc,QAAQ;AAAA,IACtC;AACA,WAAO,EAAE,WAAW,OAAO,gBAAgB,MAAM,SAAS,QAAQ;AAAA,EACpE;AAEA,aAAW,KAAK,eAAe,aAAa,SAAS,eAAe,CAAC;AACrE,gBAAc,cAAc,QAAQ;AACpC,SAAO,EAAE,WAAW,MAAM,gBAAgB,OAAO,SAAS,MAAM;AAClE;AAOO,SAAS,qBACd,cACAA,UAAiB,uBACR;AACT,MAAI,CAACC,YAAW,YAAY,EAAG,QAAO;AAEtC,MAAI;AACJ,MAAI;AACF,eAAW,aAAa,YAAY;AAAA,EACtC,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,SAAS,OAAO;AACnC,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,YAAY,WAAW,OAAO,CAAC,UAAU,CAAC,aAAa,OAAOD,OAAM,CAAC;AAC3E,MAAI,UAAU,WAAW,WAAW,OAAQ,QAAO;AAEnD,MAAI,UAAU,SAAS,GAAG;AACxB,aAAS,MAAO,aAAa;AAAA,EAC/B,OAAO;AACL,WAAO,SAAS,MAAO;AACvB,QAAI,OAAO,KAAK,SAAS,KAAM,EAAE,WAAW,EAAG,QAAO,SAAS;AAAA,EACjE;AAEA,gBAAc,cAAc,QAAQ;AACpC,SAAO;AACT;AAmBA,IAAM,wBAAwB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAeO,IAAM,8BAAiD,sBAAsB;AAAA,EAClF,CAAC,MAAM,QAAQ,CAAC;AAClB;;;AC7MO,IAAM,8BAA8B;AAMpC,IAAM,qBAAqB;AAGlC,IAAM,uBAAuB;AAMtB,SAAS,kBAAkB,WAAmB,aAAoC;AACvF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACE,eAAe;AAAA,IACjB;AAAA,EACF;AACF;AAGO,SAAS,oBAAoB,WAA4B;AAC9D,SAAO,qBAAqB,WAAW,2BAA2B;AACpE;","names":["homedir","join","exception","YAMLException","common","require$$0","line","map","Type","require$$1","schema","type","Schema","require$$2","require$$3","require$$4","require$$5","require$$6","DEFAULT_SCHEMA","loadAll","load","str","string","dump","loader","dumper","require$$7","require$$8","require$$9","require$$10","require$$11","require$$12","require$$13","require$$14","require$$15","require$$16","require$$17","require$$18","require$$19","require$$20","require$$21","has","result","DEFAULT_ROUTES_REFRESH_MS","decodeSdJwtSync","createHash","createHash","readFileSync","type","readFileSync","mkdirSync","existsSync","mkdirSync","existsSync","existsSync","readFileSync","homedir","join","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","existsSync","readFileSync","readFileSync","homedir","join","existsSync","readFileSync","join","createHash","createHash","join","homedir","join","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","marker","existsSync","readFileSync","mkdirSync","dirname","writeFileSync"]}
|