@apicircle/core 1.0.8 → 1.1.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/README.md +4 -4
- package/dist/{chunk-L5DQT7V6.js → chunk-T6A4ICRL.js} +5 -5
- package/dist/chunk-T6A4ICRL.js.map +1 -0
- package/dist/index.cjs +995 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +219 -8
- package/dist/index.d.ts +219 -8
- package/dist/index.js +965 -77
- package/dist/index.js.map +1 -1
- package/dist/{patches-ysO3y8pG.d.cts → patches-B3VGNVgf.d.cts} +74 -1
- package/dist/{patches-ysO3y8pG.d.ts → patches-B3VGNVgf.d.ts} +74 -1
- package/dist/workspace/file-backed.cjs +4 -4
- package/dist/workspace/file-backed.cjs.map +1 -1
- package/dist/workspace/file-backed.d.cts +5 -1
- package/dist/workspace/file-backed.d.ts +5 -1
- package/dist/workspace/file-backed.js +1 -1
- package/dist/workspace/registry.cjs +13 -33
- package/dist/workspace/registry.cjs.map +1 -1
- package/dist/workspace/registry.d.cts +13 -26
- package/dist/workspace/registry.d.ts +13 -26
- package/dist/workspace/registry.js +9 -30
- package/dist/workspace/registry.js.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-L5DQT7V6.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/request/bodyTypeContentType.ts","../src/request/headersDictionary.ts","../src/auth/awsSigV4.ts","../src/auth/hawk.ts","../src/auth/jwt.ts","../src/auth/_legacyHashes.ts","../src/auth/ntlm.ts","../src/auth/oauth2/fetchToken.ts","../src/auth/oauth2/grants.ts","../src/request/applyAuth.ts","../src/request/platformDetection.ts","../src/request/autoHeaders.ts","../src/request/buildRequest.ts","../src/environment/variableResolver.ts","../src/request/preSendValidation.ts","../src/auth/_sha512_256.ts","../src/auth/digest.ts","../src/request/executeRequest.ts","../src/request/requestRunAdapter.ts","../src/auth/oauth2/pkce.ts","../src/request/resolveInheritedAuth.ts","../src/request/parseCurl.ts","../src/import/postmanCollection.ts","../src/import/postmanEnvironment.ts","../src/import/insomniaCollection.ts","../src/import/apicircleFolder.ts","../src/export/folderExportCredentials.ts","../src/export/folderExport.ts","../src/import/apicircleEnvironment.ts","../src/assertions/runAssertions.ts","../src/environment/extractContext.ts","../src/secrets/crypto.ts","../src/git/branchNames.ts","../src/git/serializeWorkspace.ts","../src/git/parseWorkspaceJson.ts","../src/git/redactWorkspace.ts","../src/git/collectAttachments.ts","../src/release/semver.ts","../src/release/publishRelease.ts","../src/editors/contentTypeLanguageMap.ts","../src/editors/graphqlSchemaParser.ts","../src/git/threeWayDiff.ts","../src/git/summarizeUnpushedChanges.ts","../src/git/linkedThreeWayMerge.ts","../src/workspace/applyMutation.ts","../src/workspace/apicircleFolderImport.ts","../src/workspace/runPlan.ts","../src/transform/toon.ts","../src/transform/yaml.ts","../src/transform/csv.ts","../src/transform/computeSavings.ts"],"sourcesContent":["import type { BodyType } from '@apicircle/shared';\n\n// Single source of truth for body-type ↔ Content-Type mapping. The Editor\n// uses this to (a) seed the Content-Type header when the user picks a body\n// type and (b) reverse-resolve a body type when the user edits the\n// Content-Type header by hand.\n\nexport type HeaderEntry = { key: string; value: string; enabled: boolean };\n\nconst BODY_TYPE_TO_CONTENT_TYPE: Record<BodyType, string | null> = {\n none: null,\n json: 'application/json',\n text: 'text/plain',\n xml: 'application/xml',\n graphql: 'application/graphql',\n 'form-data': 'multipart/form-data',\n urlencoded: 'application/x-www-form-urlencoded',\n binary: 'application/octet-stream',\n};\n\nexport function getContentTypeForBodyType(bodyType: BodyType): string | null {\n return BODY_TYPE_TO_CONTENT_TYPE[bodyType];\n}\n\n/**\n * Reverse-map a Content-Type header value to a BodyType, or null if it\n * doesn't match any known type. Strips parameters (e.g. `;charset=utf-8`)\n * and is case-insensitive.\n */\nexport function getBodyTypeForContentType(contentType: string): BodyType | null {\n const main = contentType.toLowerCase().split(';')[0]?.trim();\n if (!main) return null;\n switch (main) {\n case 'application/json':\n return 'json';\n case 'text/plain':\n return 'text';\n case 'application/xml':\n case 'text/xml':\n return 'xml';\n case 'application/graphql':\n return 'graphql';\n case 'multipart/form-data':\n return 'form-data';\n case 'application/x-www-form-urlencoded':\n return 'urlencoded';\n case 'application/octet-stream':\n return 'binary';\n default:\n return null;\n }\n}\n\n/**\n * Apply (or remove) the Content-Type header on a header list to match the\n * given body type. Pure — returns a new array.\n *\n * - bodyType=none → strips any existing Content-Type entry.\n * - existing Content-Type entry → updated value, preserving order.\n * - no Content-Type entry → appended.\n */\nexport function applyContentTypeForBodyType(\n headers: HeaderEntry[],\n bodyType: BodyType,\n): HeaderEntry[] {\n const target = getContentTypeForBodyType(bodyType);\n const idx = headers.findIndex((h) => h.key.trim().toLowerCase() === 'content-type');\n\n if (target === null) {\n return idx === -1 ? headers : headers.filter((_, i) => i !== idx);\n }\n\n if (idx === -1) {\n return [...headers, { key: 'Content-Type', value: target, enabled: true }];\n }\n\n return headers.map((entry, i) =>\n i === idx ? { ...entry, value: target, enabled: true } : entry,\n );\n}\n","/**\n * HTTP Headers dictionary — used for autocomplete in the Headers editor.\n *\n * Each entry maps a header name to its known values (empty array = free text).\n * Values that depend on context (e.g. specific MIME types) provide a curated\n * set of the most common options.\n */\n\nexport interface HeaderEntry {\n name: string;\n description: string;\n values: string[];\n /**\n * `browser` — Forbidden by the Fetch spec; browsers silently ignore any\n * attempt to set this header from JavaScript. On Desktop (native\n * HTTP layer) the restriction does NOT apply — the header can\n * still be set manually.\n *\n * `app` — Automatically injected by API Circle Studio at send-time (see\n * autoHeaders.ts). Users can override these in the Headers tab\n * and their value will take precedence.\n *\n * Omitted — Fully user-controlled on both Web and Desktop.\n */\n reserved?: 'browser' | 'app';\n /** Short note shown in the autocomplete to explain the reservation. */\n reservedNote?: string;\n}\n\nexport const HTTP_HEADERS_MAP: HeaderEntry[] = [\n // ── Request headers ────────────────────────────────────────────────────────\n {\n name: 'Accept',\n description: 'Media types the client accepts',\n values: [\n 'application/json',\n 'application/xml',\n 'text/html',\n 'text/plain',\n 'text/csv',\n 'application/octet-stream',\n 'multipart/form-data',\n 'application/x-www-form-urlencoded',\n 'application/graphql',\n 'image/png',\n 'image/jpeg',\n 'image/webp',\n 'image/gif',\n 'image/svg+xml',\n '*/*',\n ],\n },\n {\n name: 'Accept-Encoding',\n description: 'Acceptable content encodings',\n values: ['gzip', 'deflate', 'br', 'zstd', 'identity', 'gzip, deflate, br'],\n reserved: 'browser',\n reservedNote: 'Set automatically by the browser; ignored in web fetch',\n },\n {\n name: 'Accept-Language',\n description: 'Acceptable human languages',\n values: ['en', 'en-US', 'en-GB', 'fr', 'de', 'ja', 'zh-CN', 'es', '*'],\n },\n {\n name: 'Authorization',\n description: 'Authentication credentials',\n values: ['Bearer ', 'Basic ', 'Digest ', 'NTLM ', 'AWS4-HMAC-SHA256 ', 'ApiKey '],\n },\n {\n name: 'Cache-Control',\n description: 'Directives for caching mechanisms',\n values: [\n 'no-cache',\n 'no-store',\n 'max-age=0',\n 'max-age=3600',\n 'must-revalidate',\n 'private',\n 'public',\n 'no-cache, no-store, must-revalidate',\n ],\n },\n {\n name: 'Connection',\n description: 'Control options for the current connection',\n values: ['keep-alive', 'close', 'upgrade'],\n reserved: 'browser',\n reservedNote: 'Forbidden by Fetch spec; browser controls connection management',\n },\n {\n name: 'Content-Encoding',\n description: 'Encoding applied to the body',\n values: ['gzip', 'deflate', 'br', 'identity'],\n },\n {\n name: 'Content-Length',\n description: 'Size of the request body in bytes',\n values: [],\n reserved: 'browser',\n reservedNote: 'Computed automatically; ignored in web fetch',\n },\n {\n name: 'Content-Type',\n description: 'Media type of the request body',\n values: [\n 'application/json',\n 'application/xml',\n 'text/xml',\n 'text/html',\n 'text/plain',\n 'text/csv',\n 'application/x-www-form-urlencoded',\n 'multipart/form-data',\n 'application/octet-stream',\n 'application/graphql',\n 'application/ld+json',\n 'application/vnd.api+json',\n 'application/problem+json',\n ],\n },\n {\n name: 'Cookie',\n description: 'HTTP cookies sent by the client',\n values: [],\n reserved: 'browser',\n reservedNote: 'Managed by the browser cookie jar; forbidden in web fetch',\n },\n {\n name: 'Host',\n description: 'Host and port of the target server',\n values: [],\n reserved: 'browser',\n reservedNote: 'Derived from the request URL; forbidden in web fetch',\n },\n {\n name: 'If-Match',\n description: 'Conditional request based on ETag',\n values: ['*'],\n },\n {\n name: 'If-Modified-Since',\n description: 'Conditional GET if modified after this date',\n values: [],\n },\n {\n name: 'If-None-Match',\n description: 'Conditional request — only respond if ETag differs',\n values: ['*'],\n },\n {\n name: 'If-Unmodified-Since',\n description: 'Conditional request based on date',\n values: [],\n },\n {\n name: 'Origin',\n description: 'Origin of the cross-origin request',\n values: ['http://app.studio.apicircle.dev', 'https://app.studio.apicircle.dev'],\n reserved: 'browser',\n reservedNote: 'Set by browser on cross-origin requests; auto-fed on Desktop',\n },\n {\n name: 'Prefer',\n description: 'Client preferences for server behaviour',\n values: [\n 'respond-async',\n 'return=representation',\n 'return=minimal',\n 'handling=strict',\n 'handling=lenient',\n ],\n },\n {\n name: 'Range',\n description: 'Request partial content',\n values: ['bytes=0-', 'bytes=0-1023'],\n },\n {\n name: 'Referer',\n description: 'URL of the page making the request',\n values: ['http://app.studio.apicircle.dev/'],\n reserved: 'browser',\n reservedNote: 'Set by browser from document context; auto-fed on Desktop',\n },\n {\n name: 'User-Agent',\n description: 'Client application identifier',\n values: [\n 'API Circle Studio/1.0.0',\n 'Mozilla/5.0 (compatible; API Circle Studio)',\n 'curl/8.0.0',\n ],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch; settable in Desktop (native) requests',\n },\n {\n name: 'X-API-Key',\n description: 'API key for authentication',\n values: [],\n },\n {\n name: 'X-Client-Name',\n description: 'Auto-fed: client application name',\n values: ['API Circle Studio'],\n reserved: 'app',\n reservedNote: 'Injected automatically; your value overrides it',\n },\n {\n name: 'X-Client-Platform',\n description: 'Auto-fed: runtime platform',\n values: ['desktop', 'web'],\n reserved: 'app',\n reservedNote: 'Injected automatically; your value overrides it',\n },\n {\n name: 'X-Client-Version',\n description: 'Auto-fed: application version',\n values: ['1.0.0'],\n reserved: 'app',\n reservedNote: 'Injected automatically; your value overrides it',\n },\n {\n name: 'X-Correlation-Id',\n description: 'Correlation ID for distributed tracing',\n values: [],\n },\n {\n name: 'X-Custom-Auth',\n description: 'Custom authentication header',\n values: [],\n },\n {\n name: 'X-Forwarded-For',\n description: 'Originating IP in proxy chains',\n values: [],\n },\n {\n name: 'X-Forwarded-Host',\n description: 'Originating host in proxy chains',\n values: [],\n },\n {\n name: 'X-Forwarded-Proto',\n description: 'Originating protocol in proxy chains',\n values: ['http', 'https'],\n },\n {\n name: 'X-Request-ID',\n description: 'Unique identifier for this request',\n values: [],\n },\n {\n name: 'X-Trace-Span-Id',\n description: 'Auto-fed: distributed trace span ID (generated per send)',\n values: [],\n reserved: 'app',\n reservedNote: 'Regenerated on every send; cannot be stored or overridden',\n },\n {\n name: 'traceparent',\n description: 'W3C Trace Context parent (auto-fed per send)',\n values: [],\n reserved: 'app',\n reservedNote: 'Regenerated on every send; your value overrides it',\n },\n // ── Conditional / caching ─────────────────────────────────────────────────\n {\n name: 'Pragma',\n description: 'Legacy cache control (HTTP/1.0)',\n values: ['no-cache'],\n },\n {\n name: 'Expires',\n description: 'Date/time after which the response is stale',\n values: [],\n },\n {\n name: 'Date',\n description: 'Date and time the message was sent',\n values: [],\n reserved: 'browser',\n reservedNote: 'Set by the HTTP stack; forbidden in web fetch',\n },\n {\n name: 'Age',\n description: 'Seconds the object has been in a proxy cache',\n values: [],\n },\n {\n name: 'Last-Modified',\n description: 'Date the resource was last modified',\n values: [],\n },\n {\n name: 'Vary',\n description: 'Headers that determine cache key',\n values: ['Accept', 'Accept-Encoding', 'Accept-Language', 'Origin', '*'],\n },\n // ── Transfer / encoding ───────────────────────────────────────────────────\n {\n name: 'Transfer-Encoding',\n description: 'Transfer encoding applied to the message body',\n values: ['chunked', 'compress', 'deflate', 'gzip', 'identity'],\n reserved: 'browser',\n reservedNote: 'Managed by the HTTP stack; forbidden in web fetch',\n },\n {\n name: 'TE',\n description: 'Transfer encodings the client can accept',\n values: ['trailers', 'deflate', 'gzip'],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch',\n },\n {\n name: 'Trailer',\n description: 'Headers included in the trailer of a chunked transfer',\n values: [],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch',\n },\n {\n name: 'Upgrade',\n description: 'Protocol upgrade request',\n values: ['websocket', 'HTTP/2.0', 'h2c'],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch; use WebSocket API instead',\n },\n // ── Proxy / forwarding ────────────────────────────────────────────────────\n {\n name: 'Forwarded',\n description: 'Standard proxy forwarding header (replaces X-Forwarded-*)',\n values: [],\n },\n {\n name: 'Max-Forwards',\n description: 'Maximum number of proxy hops for TRACE/OPTIONS',\n values: ['10'],\n },\n {\n name: 'Proxy-Authorization',\n description: 'Credentials for authenticating with a proxy',\n values: ['Basic ', 'Bearer '],\n reserved: 'browser',\n reservedNote: 'Proxy-* headers are forbidden in web fetch',\n },\n {\n name: 'Via',\n description: 'Proxies/gateways this message has passed through',\n values: [],\n reserved: 'browser',\n reservedNote: 'Set by proxy infrastructure; forbidden in web fetch',\n },\n // ── Content negotiation (extra) ───────────────────────────────────────────\n {\n name: 'Accept-Charset',\n description: 'Character sets the client accepts',\n values: ['utf-8', 'iso-8859-1', '*'],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch',\n },\n {\n name: 'Accept-Ranges',\n description: 'Whether partial requests are supported',\n values: ['bytes', 'none'],\n },\n // ── Content description ───────────────────────────────────────────────────\n {\n name: 'Allow',\n description: 'HTTP methods supported by the resource',\n values: ['GET, HEAD', 'GET, POST', 'GET, POST, PUT, DELETE, OPTIONS'],\n },\n {\n name: 'Content-Disposition',\n description: 'How content should be displayed / filename hint',\n values: ['inline', 'attachment', 'attachment; filename=\"file.bin\"'],\n },\n {\n name: 'Content-Language',\n description: 'Language(s) of the response body',\n values: ['en', 'en-US', 'fr', 'de'],\n },\n {\n name: 'Content-Location',\n description: 'Alternate URL for the returned data',\n values: [],\n },\n {\n name: 'Content-Range',\n description: 'Byte range of a partial content response',\n values: [],\n },\n // ── Security ──────────────────────────────────────────────────────────────\n {\n name: 'Strict-Transport-Security',\n description: 'HSTS: force HTTPS for future requests',\n values: [\n 'max-age=31536000',\n 'max-age=31536000; includeSubDomains',\n 'max-age=31536000; includeSubDomains; preload',\n ],\n },\n {\n name: 'Content-Security-Policy',\n description: 'Restrict sources of content to mitigate XSS',\n values: [\"default-src 'self'\", \"default-src 'self'; script-src 'none'\"],\n },\n {\n name: 'X-Content-Type-Options',\n description: 'Prevent MIME-type sniffing',\n values: ['nosniff'],\n },\n {\n name: 'X-Frame-Options',\n description: 'Prevent clickjacking via iframes',\n values: ['DENY', 'SAMEORIGIN'],\n },\n {\n name: 'X-XSS-Protection',\n description: 'Legacy XSS filter hint for older browsers',\n values: ['0', '1', '1; mode=block'],\n },\n {\n name: 'Permissions-Policy',\n description: 'Control browser feature permissions',\n values: ['geolocation=(), microphone=()', 'interest-cohort=()'],\n },\n {\n name: 'Cross-Origin-Opener-Policy',\n description: 'Control browsing context group sharing',\n values: ['same-origin', 'same-origin-allow-popups', 'unsafe-none'],\n },\n {\n name: 'Cross-Origin-Resource-Policy',\n description: 'Control cross-origin resource loading',\n values: ['same-origin', 'same-site', 'cross-origin'],\n },\n {\n name: 'Cross-Origin-Embedder-Policy',\n description: 'Require CORP for sub-resources',\n values: ['require-corp', 'unsafe-none'],\n },\n {\n name: 'DNT',\n description: 'Do Not Track signal',\n values: ['1', '0'],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch',\n },\n // ── Cookies ───────────────────────────────────────────────────────────────\n {\n name: 'Set-Cookie',\n description: 'Set an HTTP cookie on the client',\n values: [],\n },\n // ── Server info ───────────────────────────────────────────────────────────\n {\n name: 'Server',\n description: 'Software handling the request',\n values: ['nginx', 'Apache', 'Caddy', 'Kestrel'],\n },\n {\n name: 'X-Powered-By',\n description: 'Technology powering the server',\n values: ['Express', 'Hono', 'Next.js', 'ASP.NET'],\n },\n // ── Distributed tracing (extra) ───────────────────────────────────────────\n {\n name: 'tracestate',\n description: 'W3C Trace Context vendor state',\n values: [],\n },\n {\n name: 'baggage',\n description: 'W3C Baggage propagation header',\n values: [],\n },\n // ── Link / pre-load ───────────────────────────────────────────────────────\n {\n name: 'Link',\n description: 'Related resource links (preload, pagination, canonical)',\n values: ['</api>; rel=\"preload\"', '</next>; rel=\"next\"'],\n },\n // ── Fetch metadata (browser-set, may be forwarded) ───────────────────────\n {\n name: 'Sec-Fetch-Dest',\n description: 'Fetch metadata: destination of the request',\n values: ['empty', 'document', 'fetch', 'image', 'script'],\n },\n {\n name: 'Sec-Fetch-Mode',\n description: 'Fetch metadata: request mode',\n values: ['cors', 'navigate', 'no-cors', 'same-origin'],\n },\n {\n name: 'Sec-Fetch-Site',\n description: 'Fetch metadata: origin relationship',\n values: ['cross-site', 'same-origin', 'same-site', 'none'],\n },\n {\n name: 'Sec-Fetch-User',\n description: 'Fetch metadata: whether triggered by user action',\n values: ['?1'],\n },\n // ── Misc request ─────────────────────────────────────────────────────────\n {\n name: 'Expect',\n description: 'Expected behaviour from the server before sending the body',\n values: ['100-continue'],\n },\n {\n name: 'From',\n description: 'Email of the user controlling the requesting agent',\n values: [],\n },\n {\n name: 'Keep-Alive',\n description: 'Parameters for persistent connections',\n values: ['timeout=5', 'timeout=5, max=1000'],\n },\n // ── Common response headers ───────────────────────────────────────────────\n {\n name: 'Access-Control-Allow-Origin',\n description: 'CORS: allowed origins',\n values: ['*', 'http://app.studio.apicircle.dev', 'https://app.studio.apicircle.dev'],\n },\n {\n name: 'Access-Control-Allow-Methods',\n description: 'CORS: allowed HTTP methods',\n values: ['GET, POST, PUT, DELETE, OPTIONS', 'GET, POST, OPTIONS', '*'],\n },\n {\n name: 'Access-Control-Allow-Headers',\n description: 'CORS: allowed request headers',\n values: ['Content-Type, Authorization', 'Content-Type, Authorization, X-API-Key', '*'],\n },\n {\n name: 'Access-Control-Allow-Credentials',\n description: 'CORS: whether credentials are allowed',\n values: ['true', 'false'],\n },\n {\n name: 'Access-Control-Expose-Headers',\n description: 'CORS: headers exposed to the client',\n values: ['Content-Type, X-Request-ID', 'Authorization'],\n },\n {\n name: 'Access-Control-Max-Age',\n description: 'CORS: how long preflight results can be cached (seconds)',\n values: ['3600', '86400'],\n },\n {\n name: 'Access-Control-Request-Headers',\n description: 'CORS preflight: headers to be included in actual request',\n values: [],\n },\n {\n name: 'Access-Control-Request-Method',\n description: 'CORS preflight: method to be used in actual request',\n values: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],\n },\n {\n name: 'ETag',\n description: 'Entity tag for cache validation',\n values: [],\n },\n {\n name: 'Location',\n description: 'URL to redirect to',\n values: [],\n },\n {\n name: 'Retry-After',\n description: 'When to retry after 429/503',\n values: ['30', '60', '120'],\n },\n {\n name: 'WWW-Authenticate',\n description: 'Authentication challenge',\n values: ['Basic realm=\"API\"', 'Bearer', 'Digest', 'NTLM'],\n },\n {\n name: 'Proxy-Authenticate',\n description: 'Proxy authentication challenge',\n values: ['Basic realm=\"Proxy\"'],\n },\n {\n name: 'Warning',\n description: 'Advisory about possible problems with the message',\n values: ['110 - \"Response is Stale\"', '214 - \"Transformation Applied\"'],\n },\n // ── Reporting ─────────────────────────────────────────────────────────────\n {\n name: 'NEL',\n description: 'Network Error Logging configuration',\n values: [],\n },\n {\n name: 'Report-To',\n description: 'Endpoint for reporting API events',\n values: [],\n },\n];\n\n/** Lower-cased name → HeaderEntry lookup. */\nconst HEADER_MAP = new Map<string, HeaderEntry>(\n HTTP_HEADERS_MAP.map((h) => [h.name.toLowerCase(), h]),\n);\n\n/**\n * Headers that are auto-fed at send-time should not appear in suggestions — the\n * user cannot meaningfully set them (they are injected automatically by the app).\n */\nconst SUGGESTABLE_HEADERS = HTTP_HEADERS_MAP.filter((h) => h.reserved !== 'app').sort((a, b) =>\n a.name.localeCompare(b.name),\n);\n\n/**\n * Lower-cased names of headers that meaningfully appear on responses.\n * Drives `mode: 'response'` filtering for `suggestHeaders` — used by the\n * mock response editor so its key autocomplete surfaces only headers a\n * server would realistically set.\n *\n * Mix of two groups:\n * • Headers that are response-only (Set-Cookie, ETag, Location, etc.).\n * • Headers that exist on both sides but where the server-side use is\n * the dominant case (Content-Type, Cache-Control, Vary, etc.).\n */\nconst RESPONSE_HEADER_NAMES = new Set([\n // Content + caching\n 'content-type',\n 'content-length',\n 'content-encoding',\n 'content-disposition',\n 'content-language',\n 'content-location',\n 'cache-control',\n 'expires',\n 'last-modified',\n 'etag',\n 'vary',\n 'age',\n 'pragma',\n // Auth + cookies\n 'set-cookie',\n 'www-authenticate',\n 'proxy-authenticate',\n // Connection / framing\n 'server',\n 'date',\n 'connection',\n 'keep-alive',\n 'transfer-encoding',\n 'upgrade',\n // CORS (response side)\n 'access-control-allow-origin',\n 'access-control-allow-methods',\n 'access-control-allow-headers',\n 'access-control-allow-credentials',\n 'access-control-expose-headers',\n 'access-control-max-age',\n // Redirect + retry\n 'location',\n 'retry-after',\n 'allow',\n // Security\n 'strict-transport-security',\n 'content-security-policy',\n 'x-frame-options',\n 'x-content-type-options',\n 'referrer-policy',\n 'permissions-policy',\n // Observability + reporting\n 'nel',\n 'report-to',\n 'warning',\n // Custom-x catch-alls users frequently set\n 'x-request-id',\n 'x-correlation-id',\n 'x-rate-limit-limit',\n 'x-rate-limit-remaining',\n 'x-rate-limit-reset',\n]);\n\n/** Filtered view of the suggestable headers, scoped to response-side names. */\nconst SUGGESTABLE_RESPONSE_HEADERS = SUGGESTABLE_HEADERS.filter((h) =>\n RESPONSE_HEADER_NAMES.has(h.name.toLowerCase()),\n);\n\nexport type HeaderSuggestionMode = 'request' | 'response';\n\n/**\n * Suggest header names by case-insensitive prefix. Empty prefix returns the\n * full suggestable list; auto-fed (`reserved: 'app'`) headers are excluded.\n * An optional `limit` caps the number of filtered (non-empty prefix) results.\n *\n * `mode` filters by whether the header is request- or response-side\n * relevant. Defaults to `'request'` for back-compat with the request\n * editor's existing call sites.\n */\nexport function suggestHeaders(\n prefix: string,\n limit?: number,\n mode: HeaderSuggestionMode = 'request',\n): HeaderEntry[] {\n const source = mode === 'response' ? SUGGESTABLE_RESPONSE_HEADERS : SUGGESTABLE_HEADERS;\n const lower = prefix.toLowerCase().trim();\n if (!lower) return limit !== undefined ? source.slice(0, limit) : source;\n const filtered = source.filter((h) => h.name.toLowerCase().startsWith(lower));\n return limit !== undefined ? filtered.slice(0, limit) : filtered;\n}\n\n/**\n * Get the known values for a specific header name (case-insensitive).\n * Returns an empty array when the header has no predefined values (free text).\n */\nexport function getHeaderValues(headerName: string): string[] {\n return HEADER_MAP.get(headerName.toLowerCase().trim())?.values ?? [];\n}\n\n/**\n * Returns the HeaderEntry for an exact name match, or undefined.\n */\nexport function getHeaderEntry(headerName: string): HeaderEntry | undefined {\n return HEADER_MAP.get(headerName.toLowerCase().trim());\n}\n","/**\n * AWS Signature Version 4 — request signing for AWS APIs.\n *\n * SigV4 is per-request HMAC chain over a canonical-request string. The\n * server (or a STS-issued temporary credentials provider) verifies the\n * signature using the same algorithm, so request integrity is end-to-end\n * without any callback / handshake.\n *\n * canonical = METHOD\\nPATH\\nQUERY\\nHEADERS\\nSIGNED_HEADERS\\nPAYLOAD_HASH\n * stringToSign = \"AWS4-HMAC-SHA256\\n{amzDate}\\n{credScope}\\n{sha256(canonical)}\"\n * kSigning = HMAC(HMAC(HMAC(HMAC(\"AWS4{secret}\", date), region), service), \"aws4_request\")\n * signature = hex(HMAC(kSigning, stringToSign))\n *\n * Two delivery modes:\n * - `header`: sets `Authorization: AWS4-HMAC-SHA256 Credential=..., SignedHeaders=..., Signature=...`\n * - `query`: rewrites the URL with `X-Amz-*` query params (presigned URL).\n *\n * Body hashing only runs in `header` mode (presigned URLs always\n * advertise `UNSIGNED-PAYLOAD`). Streaming / chunked bodies fall through\n * to `UNSIGNED-PAYLOAD` because we'd otherwise have to buffer the entire\n * stream before signing.\n */\n\n/**\n * Body shapes we can hash for SigV4 payload signing. Anything we can't\n * read as bytes synchronously goes to `UNSIGNED-PAYLOAD` — AWS accepts\n * that as long as `x-amz-content-sha256: UNSIGNED-PAYLOAD` is in the\n * signed headers. ReadableStream falls into this bucket since draining\n * it before signing would consume the body before fetch can send it.\n */\nexport type SigV4Body =\n | string\n | ArrayBuffer\n | Uint8Array\n | Blob\n | URLSearchParams\n | FormData\n | ReadableStream<Uint8Array>\n | null\n | undefined;\n\nexport interface SigV4SignArgs {\n method: string;\n url: string;\n /** Existing request headers — passed through and merged with SigV4 additions. */\n headers: Record<string, string>;\n /**\n * Body for payload hashing. `string`, `ArrayBuffer`, `Uint8Array`,\n * `Blob`, and `URLSearchParams` are hashed verbatim. `FormData` and\n * `ReadableStream` fall through to `UNSIGNED-PAYLOAD` — AWS accepts\n * that signing mode and many AWS SDKs default to it for streaming.\n */\n body?: SigV4Body;\n accessKeyId: string;\n secretAccessKey: string;\n region: string;\n service: string;\n /** STS-issued session token; copied to `X-Amz-Security-Token`. */\n sessionToken?: string;\n /** Where to put the signature — header (default) or query (presigned URL). */\n addTo?: 'header' | 'query';\n /**\n * S3 specifically does NOT collapse double slashes or normalize dot\n * segments — it treats `bucket/foo//bar` as a different object from\n * `bucket/foo/bar`. Set true when `service: 's3'` to preserve the\n * raw path. Default false (matches non-S3 services like execute-api).\n *\n * If you don't pass this and `service === 's3'`, we auto-enable it —\n * the common case for S3 callers is \"preserve my path exactly\".\n */\n preservePathSlashes?: boolean;\n /**\n * Override `now` for tests. The amz-date stamp must be the SAME instant\n * used to build the credential scope, so we capture once.\n */\n now?: Date;\n}\n\nexport interface SigV4SignResult {\n url: string;\n headers: Record<string, string>;\n}\n\nconst EMPTY_PAYLOAD_HASH = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';\n\nexport async function applyAwsSigV4(args: SigV4SignArgs): Promise<SigV4SignResult> {\n let parsed: URL;\n try {\n parsed = new URL(args.url);\n } catch {\n throw new Error(`AWS SigV4: invalid URL: ${args.url}`);\n }\n\n const enc = new TextEncoder();\n const now = args.now ?? new Date();\n const amzDate = now.toISOString().replace(/[:-]|\\.\\d{3}/g, '');\n const dateStamp = amzDate.slice(0, 8);\n const isQuery = args.addTo === 'query';\n\n const payloadHash = isQuery ? 'UNSIGNED-PAYLOAD' : await computeBodyHash(args.body);\n const credScope = `${dateStamp}/${args.region}/${args.service}/aws4_request`;\n\n // Signed headers map — start with host (always signed). In header\n // mode we add x-amz-date + x-amz-content-sha256 (required by S3 /\n // DynamoDB; tolerated everywhere else) and the optional session token.\n // We THEN fold in user-set request headers because real AWS requests\n // routinely require Range / Content-Type / Cache-Control / etc to be\n // in SignedHeaders — without that the server gets a hash mismatch and\n // returns 403 SignatureDoesNotMatch. We exclude `Authorization` (we\n // produce it) and any `host` the caller may have set (we own it).\n const signedMap: Record<string, string> = {\n host: parsed.hostname + (parsed.port ? `:${parsed.port}` : ''),\n };\n if (!isQuery) {\n signedMap['x-amz-date'] = amzDate;\n signedMap['x-amz-content-sha256'] = payloadHash;\n if (args.sessionToken) signedMap['x-amz-security-token'] = args.sessionToken;\n }\n // Fold caller's headers into the signed set. AWS spec normalizes:\n // lowercase header name, trim leading/trailing whitespace, collapse\n // internal whitespace runs to a single space.\n for (const [rawKey, rawValue] of Object.entries(args.headers)) {\n const key = rawKey.toLowerCase();\n if (key === 'authorization' || key === 'host') continue;\n if (key in signedMap) continue; // don't overwrite our own additions\n signedMap[key] = rawValue.replace(/\\s+/g, ' ').trim();\n }\n const signedHeaderNames = Object.keys(signedMap).sort();\n const canonicalHeaders = signedHeaderNames.map((k) => `${k}:${signedMap[k]}\\n`).join('');\n const signedHeadersList = signedHeaderNames.join(';');\n\n // Query params — preserve existing + add X-Amz-* in query mode.\n const qEntries: Array<[string, string]> = [];\n parsed.searchParams.forEach((v, k) => qEntries.push([k, v]));\n if (isQuery) {\n qEntries.push(['X-Amz-Algorithm', 'AWS4-HMAC-SHA256']);\n qEntries.push(['X-Amz-Credential', `${args.accessKeyId}/${credScope}`]);\n qEntries.push(['X-Amz-Date', amzDate]);\n qEntries.push(['X-Amz-Expires', '3600']);\n qEntries.push(['X-Amz-SignedHeaders', signedHeadersList]);\n if (args.sessionToken) qEntries.push(['X-Amz-Security-Token', args.sessionToken]);\n }\n qEntries.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));\n const canonicalQS = qEntries\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&');\n\n const preserveSlashes = args.preservePathSlashes ?? args.service === 's3';\n const canonicalUri = canonicalizePath(parsed.pathname, preserveSlashes);\n const canonicalReq = [\n args.method.toUpperCase(),\n canonicalUri,\n canonicalQS,\n canonicalHeaders,\n signedHeadersList,\n payloadHash,\n ].join('\\n');\n\n const stringToSign = ['AWS4-HMAC-SHA256', amzDate, credScope, await sha256Hex(canonicalReq)].join(\n '\\n',\n );\n\n // Derive the per-request signing key by chaining HMACs.\n const kDate = await hmacSha256(enc.encode(`AWS4${args.secretAccessKey}`), dateStamp);\n const kRegion = await hmacSha256(kDate, args.region);\n const kService = await hmacSha256(kRegion, args.service);\n const kSigning = await hmacSha256(kService, 'aws4_request');\n const signature = bufToHex(await hmacSha256(kSigning, stringToSign));\n\n const nextHeaders = { ...args.headers };\n let nextUrl = args.url;\n\n if (isQuery) {\n qEntries.push(['X-Amz-Signature', signature]);\n qEntries.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));\n const qs = qEntries\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&');\n nextUrl = `${parsed.origin}${parsed.pathname}?${qs}${parsed.hash}`;\n } else {\n // Lowercase header names match AWS SDK / boto3 / common request\n // tooling conventions. HTTP headers are case-insensitive, but staying\n // consistent simplifies test assertions and downstream string-match\n // header inspection.\n nextHeaders['x-amz-date'] = amzDate;\n nextHeaders['x-amz-content-sha256'] = payloadHash;\n if (args.sessionToken) nextHeaders['x-amz-security-token'] = args.sessionToken;\n nextHeaders['Authorization'] =\n `AWS4-HMAC-SHA256 Credential=${args.accessKeyId}/${credScope}, SignedHeaders=${signedHeadersList}, Signature=${signature}`;\n }\n return { url: nextUrl, headers: nextHeaders };\n}\n\n// ── helpers ────────────────────────────────────────────────────────────────────\n\nasync function computeBodyHash(body: SigV4Body): Promise<string> {\n if (body == null) return EMPTY_PAYLOAD_HASH;\n if (typeof body === 'string') return sha256HexBuf(new TextEncoder().encode(body));\n if (body instanceof ArrayBuffer) return sha256HexBuf(new Uint8Array(body));\n if (body instanceof Uint8Array) return sha256HexBuf(body);\n if (typeof Blob !== 'undefined' && body instanceof Blob) {\n const ab = await body.arrayBuffer();\n return sha256HexBuf(new Uint8Array(ab));\n }\n if (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams) {\n return sha256HexBuf(new TextEncoder().encode(body.toString()));\n }\n // FormData / ReadableStream — can't be deterministically hashed\n // pre-fetch (FormData boundary is generated by fetch, ReadableStream\n // is one-shot). AWS accepts UNSIGNED-PAYLOAD in these cases as long\n // as the magic constant is in the signed headers.\n return 'UNSIGNED-PAYLOAD';\n}\n\n/**\n * Canonicalize a request path per AWS SigV4 §6 (Task 1).\n *\n * Rules (general services):\n * - Empty path becomes \"/\".\n * - Each segment is URI-encoded with the unreserved set per RFC 3986\n * (preserving `/`, encoding everything else). Components ALREADY\n * percent-encoded by the user pass through — we don't double-encode.\n * - \".\" segments are removed; \"..\" segments collapse the previous\n * segment.\n * - Leading slash is preserved; trailing slash is preserved.\n * - Empty segments (consecutive `/`) are collapsed to one.\n *\n * S3 mode (`preserveSlashes: true`):\n * - Empty segments are PRESERVED — S3 treats `bucket/foo//bar` as a\n * distinct object key from `bucket/foo/bar`. The canonical URI must\n * match the raw path bytes for the signature to validate against\n * what S3 actually stored.\n * - \".\" and \"..\" segments are still encoded as path components\n * (S3 doesn't apply RFC 3986 dot-segment removal).\n */\nfunction canonicalizePath(path: string, preserveSlashes: boolean): string {\n if (!path || path === '') return '/';\n if (preserveSlashes) {\n // Encode each segment but keep all separators verbatim (including\n // empty segments from `//`).\n return path\n .split('/')\n .map((seg) => awsUriEncode(seg, /* preserveSlash */ false))\n .join('/');\n }\n const isAbsolute = path.startsWith('/');\n const trailingSlash = path.endsWith('/') && path !== '/';\n const segments: string[] = [];\n for (const seg of path.split('/')) {\n if (seg === '' || seg === '.') continue;\n if (seg === '..') {\n segments.pop();\n continue;\n }\n segments.push(awsUriEncode(seg, /* preserveSlash */ false));\n }\n let out = (isAbsolute ? '/' : '') + segments.join('/');\n if (trailingSlash && !out.endsWith('/')) out += '/';\n if (!out) out = '/';\n return out;\n}\n\n/**\n * URI-encode per AWS SigV4 spec — same as RFC 3986 unreserved set\n * (`A-Z a-z 0-9 - _ . ~`). `encodeURIComponent` covers most of this but\n * leaves `!*'()` un-encoded, so we patch those.\n */\nfunction awsUriEncode(s: string, preserveSlash: boolean): string {\n let encoded = encodeURIComponent(s).replace(\n /[!'()*]/g,\n (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`,\n );\n if (preserveSlash) encoded = encoded.replace(/%2F/g, '/');\n return encoded;\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n return sha256HexBuf(new TextEncoder().encode(input));\n}\n\nasync function sha256HexBuf(bytes: Uint8Array): Promise<string> {\n const buf = bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength,\n ) as ArrayBuffer;\n const hash = await crypto.subtle.digest('SHA-256', buf);\n return bufToHex(hash);\n}\n\nasync function hmacSha256(key: Uint8Array | ArrayBuffer, message: string): Promise<ArrayBuffer> {\n const keyBuf =\n key instanceof Uint8Array\n ? (key.buffer.slice(key.byteOffset, key.byteOffset + key.byteLength) as ArrayBuffer)\n : key;\n const cryptoKey = await crypto.subtle.importKey(\n 'raw',\n keyBuf,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n const msg = new TextEncoder().encode(message);\n const msgBuf = msg.buffer.slice(msg.byteOffset, msg.byteOffset + msg.byteLength);\n return crypto.subtle.sign('HMAC', cryptoKey, msgBuf);\n}\n\nfunction bufToHex(buf: ArrayBuffer): string {\n return Array.from(new Uint8Array(buf), (b) => b.toString(16).padStart(2, '0')).join('');\n}\n","/**\n * Hawk authentication scheme (https://github.com/mozilla/hawk).\n *\n * Hawk uses an HMAC of a normalized request string keyed by a shared\n * secret. Unlike Digest / NTLM there's no challenge round-trip — every\n * request is signed independently using:\n *\n * normalized = \"hawk.1.header\\n{ts}\\n{nonce}\\n{METHOD}\\n{path?query}\\n\n * {host-lc}\\n{port}\\n{payload-hash}\\n{ext}\\n\"\n * mac = base64(HMAC-{algorithm}(secret, normalized))\n *\n * We default to SHA-256 (the modern recommendation); SHA-1 is supported\n * for interop with legacy Hawk servers. Body-payload hashing is a future\n * extension — for now we always pass an empty payload-hash, which the\n * server must verify by setting `Hash: \"\"` or skipping payload validation.\n */\n\nexport interface HawkSignArgs {\n method: string;\n /**\n * Full request URL — we extract scheme/host/port/path/query from this\n * since the normalized string needs lowercase host + numeric port.\n */\n url: string;\n hawkId: string;\n hawkKey: string;\n algorithm?: 'sha256' | 'sha1';\n /**\n * Override for the timestamp (Unix seconds). Tests pass a fixed value;\n * production callers either omit (use `Date.now()`) or apply\n * `timestampOffset` to compensate for client-server clock skew.\n */\n timestamp?: number;\n /**\n * 8 hex chars by default; tests pass a fixed value. The server tracks\n * (id, ts, nonce) tuples to detect replay, so even fixed tests are\n * one-shot.\n */\n nonce?: string;\n /** Optional `app=` and `dlg=` directives for delegated requests. */\n app?: string;\n delegation?: string;\n /** Optional `ext=` directive for application-specific data. */\n ext?: string;\n /**\n * Optional payload + content-type for body-binding. When present, the\n * normalized request string includes a `hash=BASE64(H(payload))` line\n * AND we emit a `hash=\"…\"` directive in the Authorization header.\n * Servers configured with body-binding reject requests that lack this;\n * leaving the field undefined preserves the prior behavior (server\n * must accept body-less signing).\n */\n payload?: {\n body: string | ArrayBuffer | Uint8Array;\n contentType: string;\n };\n}\n\nexport async function buildHawkAuthHeader(args: HawkSignArgs): Promise<string> {\n let parsed: URL;\n try {\n parsed = new URL(args.url);\n } catch {\n throw new Error(`Hawk: invalid URL: ${args.url}`);\n }\n\n const port = parsed.port || (parsed.protocol === 'https:' ? '443' : '80');\n const ts = String(args.timestamp ?? Math.floor(Date.now() / 1000));\n const nonce = args.nonce ?? randomHex(4);\n const ext = args.ext ?? '';\n const resource = `${parsed.pathname}${parsed.search}${parsed.hash}`;\n const algorithm = args.algorithm ?? 'sha256';\n const subtleAlgo = algorithm === 'sha1' ? 'SHA-1' : 'SHA-256';\n\n // Optional payload-hash per Hawk spec §3.2.5: H = base64(SHA(\n // \"hawk.1.payload\\n\" + content-type + \"\\n\" + body + \"\\n\"\n // )). Body-bound servers verify the request body matches by re-running\n // the same hash. When `args.payload` is undefined we emit an empty\n // payload-hash line — the server must be configured to accept that.\n let payloadHash = '';\n if (args.payload) {\n const normalizedContentType =\n args.payload.contentType.split(';')[0]?.trim().toLowerCase() ?? '';\n const bodyText = bodyToString(args.payload.body);\n const payloadString = `hawk.1.payload\\n${normalizedContentType}\\n${bodyText}\\n`;\n const payloadBytes = new TextEncoder().encode(payloadString);\n const hashBuf = await crypto.subtle.digest(\n subtleAlgo,\n payloadBytes.buffer.slice(\n payloadBytes.byteOffset,\n payloadBytes.byteOffset + payloadBytes.byteLength,\n ),\n );\n payloadHash = bufToBase64(hashBuf);\n }\n\n // RFC-style normalized string. Every component is on its own line and\n // a trailing newline closes the buffer (required by the spec).\n //\n // Phase 11 fix: when `app` / `dlg` are present they MUST be appended to\n // the normalized string AFTER `ext`, per Hawk v1 §3.2.1. Without this,\n // a man-in-the-middle can forge or strip the `app=` / `dlg=` directives\n // without invalidating the MAC — and servers that route by `app=` (most\n // multi-tenant Hawk deployments) trust whatever the attacker substituted.\n // We always emit the lines when the directives are present; servers\n // that don't use them ignore the extra components anyway because they\n // re-derive the normalized string from the same directives.\n const normalizedLines: string[] = [\n 'hawk.1.header',\n ts,\n nonce,\n args.method.toUpperCase(),\n resource,\n parsed.hostname.toLowerCase(),\n port,\n payloadHash,\n ext,\n ];\n if (args.app !== undefined && args.app !== '') {\n normalizedLines.push(args.app);\n // The spec requires `dlg` only after `app` — we emit an empty line\n // for `dlg` when absent so the field positions remain spec-compliant.\n normalizedLines.push(args.delegation ?? '');\n } else if (args.delegation) {\n // `dlg` without `app` is non-standard — Hawk's spec doesn't define a\n // canonical normalized form for that combination. Most servers reject\n // it, but for interop with implementations that allow it we emit an\n // empty `app` line followed by `dlg`. This is best-effort.\n normalizedLines.push('');\n normalizedLines.push(args.delegation);\n }\n const normalized = normalizedLines.join('\\n') + '\\n';\n\n const macBuf = await hmacSign(subtleAlgo, args.hawkKey, normalized);\n const mac = bufToBase64(macBuf);\n\n // Field order follows the Hawk reference impl: id, ts, nonce, optional\n // hash / ext / app / dlg directives, mac last. RFC doesn't mandate the\n // order but every interop server we've tested parses in this sequence\n // and a few brittle ones reject anything else.\n const parts = [\n `id=\"${escapeQuoted(args.hawkId)}\"`,\n `ts=\"${ts}\"`,\n `nonce=\"${escapeQuoted(nonce)}\"`,\n ];\n if (payloadHash) parts.push(`hash=\"${payloadHash}\"`);\n if (ext) parts.push(`ext=\"${escapeQuoted(ext)}\"`);\n if (args.app) parts.push(`app=\"${escapeQuoted(args.app)}\"`);\n if (args.delegation) parts.push(`dlg=\"${escapeQuoted(args.delegation)}\"`);\n parts.push(`mac=\"${mac}\"`);\n return `Hawk ${parts.join(', ')}`;\n}\n\nasync function hmacSign(\n algorithm: 'SHA-256' | 'SHA-1',\n key: string,\n message: string,\n): Promise<ArrayBuffer> {\n const enc = new TextEncoder();\n const keyBytes = enc.encode(key);\n const cryptoKey = await crypto.subtle.importKey(\n 'raw',\n keyBytes.buffer.slice(keyBytes.byteOffset, keyBytes.byteOffset + keyBytes.byteLength),\n { name: 'HMAC', hash: algorithm },\n false,\n ['sign'],\n );\n const msgBytes = enc.encode(message);\n return crypto.subtle.sign(\n 'HMAC',\n cryptoKey,\n msgBytes.buffer.slice(msgBytes.byteOffset, msgBytes.byteOffset + msgBytes.byteLength),\n );\n}\n\nfunction bufToBase64(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n let s = '';\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);\n return btoa(s);\n}\n\nfunction randomHex(byteLen: number): string {\n const buf = new Uint8Array(byteLen);\n crypto.getRandomValues(buf);\n return Array.from(buf, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nfunction escapeQuoted(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n\n/**\n * Coerce a payload body shape into a UTF-8 string for hashing. Hawk's\n * payload-hash spec (§3.2.5) is byte-oriented; we treat strings as UTF-8\n * and ArrayBuffer / Uint8Array as raw bytes decoded with the default\n * decoder. Other body shapes (FormData / ReadableStream) are not\n * supported here — callers should serialize to a string before signing.\n */\nfunction bodyToString(body: string | ArrayBuffer | Uint8Array): string {\n if (typeof body === 'string') return body;\n const bytes = body instanceof Uint8Array ? body : new Uint8Array(body);\n return new TextDecoder().decode(bytes);\n}\n","/**\n * JWT (RFC 7519) signing — Bearer token generation.\n *\n * This is the \"self-signed assertion\" variant of `jwt-bearer` auth: the\n * client mints a JWT signed with its own key, then sends it as\n * `Authorization: Bearer <jwt>`. Different from OAuth2 JWT-bearer flow\n * (RFC 7523) where the JWT is exchanged at a token endpoint for an\n * access token — that flow goes through `auth/oauth2/grants.ts` and\n * uses this signer to mint the assertion.\n *\n * Algorithms:\n * - HS256 / HS384 / HS512: HMAC with shared secret (most common).\n * - RS256 / RS384 / RS512: RSA-SHA — caller supplies a private key\n * in PKCS#8 PEM. Imported via `crypto.subtle.importKey`.\n * - ES256 / ES384 / ES512: ECDSA-P256/384/521 — same PKCS#8 path.\n * - **none**: refused. Always reject `alg: \"none\"` regardless of caller\n * intent — RFC 8725 §3.1 calls this out as the canonical JWT mistake.\n *\n * The header `typ` defaults to `\"JWT\"`; callers can override via the\n * `additionalHeaders` arg to set e.g. `kid` for key discovery.\n */\n\nexport type JwtAlgorithm =\n | 'HS256'\n | 'HS384'\n | 'HS512'\n | 'RS256'\n | 'RS384'\n | 'RS512'\n | 'PS256'\n | 'PS384'\n | 'PS512'\n | 'ES256'\n | 'ES384'\n | 'ES512'\n | 'EdDSA';\n\nexport interface JwtSignArgs {\n /** Signing algorithm — must match the key material in `secretOrKey`. */\n algorithm: JwtAlgorithm;\n /**\n * Shared secret for HMAC (HS256/384/512) or PEM-encoded PKCS#8\n * private key for RSA / ECDSA. For HMAC, plain UTF-8 strings work;\n * for asymmetric, the PEM must include the BEGIN/END markers.\n */\n secretOrKey: string;\n /** Token claims. `iat` is auto-added when missing; `exp` is left to the caller. */\n payload: Record<string, unknown>;\n /** Extra header fields beyond `alg` and `typ` (e.g. `kid`, `cty`). */\n additionalHeaders?: Record<string, unknown>;\n}\n\nconst HMAC_ALGS: Readonly<Record<string, string>> = {\n HS256: 'SHA-256',\n HS384: 'SHA-384',\n HS512: 'SHA-512',\n};\n\nconst RSA_ALGS: Readonly<Record<string, string>> = {\n RS256: 'SHA-256',\n RS384: 'SHA-384',\n RS512: 'SHA-512',\n};\n\n/**\n * RSA-PSS (RFC 7518 §3.5). Salt length per spec is `hLen` — the hash\n * function's digest length in bytes (32 for SHA-256, 48 for SHA-384,\n * 64 for SHA-512). WebCrypto's RSA-PSS expects the salt length in bytes.\n */\nconst RSA_PSS_ALGS: Readonly<Record<string, { hash: string; saltLength: number }>> = {\n PS256: { hash: 'SHA-256', saltLength: 32 },\n PS384: { hash: 'SHA-384', saltLength: 48 },\n PS512: { hash: 'SHA-512', saltLength: 64 },\n};\n\nconst EC_CURVES: Readonly<Record<string, { hash: string; namedCurve: string }>> = {\n ES256: { hash: 'SHA-256', namedCurve: 'P-256' },\n ES384: { hash: 'SHA-384', namedCurve: 'P-384' },\n ES512: { hash: 'SHA-512', namedCurve: 'P-521' },\n};\n\nexport async function signJwt(args: JwtSignArgs): Promise<string> {\n const header = {\n alg: args.algorithm,\n typ: 'JWT',\n ...(args.additionalHeaders ?? {}),\n };\n // RFC 8725 §3.1 — never honor `alg: \"none\"`. We reject it even if\n // someone explicitly passes it; the only safe behavior is to refuse.\n if ((args.algorithm as string).toLowerCase() === 'none') {\n throw new Error('JWT alg \"none\" is not supported (RFC 8725 §3.1)');\n }\n const payload: Record<string, unknown> = { iat: Math.floor(Date.now() / 1000), ...args.payload };\n\n const headerSegment = base64UrlEncode(new TextEncoder().encode(JSON.stringify(header)));\n const payloadSegment = base64UrlEncode(new TextEncoder().encode(JSON.stringify(payload)));\n const signingInput = `${headerSegment}.${payloadSegment}`;\n\n const sigBytes = await sign(args.algorithm, args.secretOrKey, signingInput);\n return `${signingInput}.${base64UrlEncode(new Uint8Array(sigBytes))}`;\n}\n\nasync function sign(\n algorithm: JwtAlgorithm,\n secretOrKey: string,\n signingInput: string,\n): Promise<ArrayBuffer> {\n const enc = new TextEncoder();\n const data = enc.encode(signingInput);\n const dataBuf = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);\n\n if (algorithm in HMAC_ALGS) {\n const keyBytes = enc.encode(secretOrKey);\n const keyBuf = keyBytes.buffer.slice(\n keyBytes.byteOffset,\n keyBytes.byteOffset + keyBytes.byteLength,\n );\n const key = await crypto.subtle.importKey(\n 'raw',\n keyBuf,\n { name: 'HMAC', hash: HMAC_ALGS[algorithm] },\n false,\n ['sign'],\n );\n return crypto.subtle.sign('HMAC', key, dataBuf);\n }\n\n if (algorithm in RSA_ALGS) {\n const key = await importPkcs8(secretOrKey, {\n name: 'RSASSA-PKCS1-v1_5',\n hash: RSA_ALGS[algorithm],\n });\n return crypto.subtle.sign('RSASSA-PKCS1-v1_5', key, dataBuf);\n }\n\n if (algorithm in RSA_PSS_ALGS) {\n const { hash, saltLength } = RSA_PSS_ALGS[algorithm];\n const key = await importPkcs8(secretOrKey, { name: 'RSA-PSS', hash });\n return crypto.subtle.sign({ name: 'RSA-PSS', saltLength }, key, dataBuf);\n }\n\n if (algorithm === 'EdDSA') {\n // RFC 8037 — JWS with Ed25519. WebCrypto's Ed25519 support landed\n // in modern browsers (Chrome 113+, Firefox 130+, Safari 17+) and\n // Node 22+. The PKCS#8 PEM the user pastes must encode an Ed25519\n // private key (OID 1.3.101.112).\n const key = await importPkcs8(secretOrKey, { name: 'Ed25519' });\n return crypto.subtle.sign('Ed25519', key, dataBuf);\n }\n\n if (algorithm in EC_CURVES) {\n const { hash, namedCurve } = EC_CURVES[algorithm];\n const key = await importPkcs8(secretOrKey, { name: 'ECDSA', namedCurve });\n // ECDSA over JWT is JWS-style: r || s, fixed-length (curve-specific).\n const sig = await crypto.subtle.sign({ name: 'ECDSA', hash }, key, dataBuf);\n return sig;\n }\n\n throw new Error(`JWT algorithm not supported: ${algorithm}`);\n}\n\nasync function importPkcs8(\n pem: string,\n algorithm: { name: string; hash?: string; namedCurve?: string },\n): Promise<CryptoKey> {\n // Encrypted PKCS#8 PEMs (`BEGIN ENCRYPTED PRIVATE KEY`) wrap the\n // private key with a passphrase-derived key — WebCrypto can't import\n // them. Surface a clear actionable error rather than confusing the\n // user with a base64-decode failure on the encrypted blob.\n if (/-----BEGIN ENCRYPTED [A-Z ]+-----/.test(pem)) {\n throw new Error(\n 'JWT: encrypted PEM keys are not supported. Decrypt with `openssl pkcs8 -in key.pem -out plain.pem` and paste the unencrypted form.',\n );\n }\n // RSA PKCS#1 PEMs (`BEGIN RSA PRIVATE KEY`) are NOT PKCS#8 — WebCrypto\n // requires PKCS#8. Catch the common confusion explicitly.\n if (/-----BEGIN RSA PRIVATE KEY-----/.test(pem)) {\n throw new Error(\n 'JWT: PKCS#1 RSA PEM (`BEGIN RSA PRIVATE KEY`) is not supported. Convert with `openssl pkcs8 -topk8 -in key.pem -out pkcs8.pem -nocrypt`.',\n );\n }\n // Extract the BEGIN/END envelope's contents — everything outside\n // those markers (Bag Attributes, comments, blank lines) is ignored.\n // If the markers are missing, fall back to \"use the whole input\"\n // so a user pasting raw base64 still works.\n const envelope = /-----BEGIN [A-Z ]+-----([\\s\\S]*?)-----END [A-Z ]+-----/.exec(pem);\n const body = envelope ? envelope[1] : pem;\n const stripped = body.replace(/\\s+/g, '');\n if (!stripped) {\n throw new Error('JWT: PEM key is empty after stripping headers/whitespace');\n }\n let der: Uint8Array;\n try {\n const raw = atob(stripped);\n der = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) der[i] = raw.charCodeAt(i);\n } catch {\n throw new Error('JWT: PEM key is not valid base64');\n }\n return crypto.subtle.importKey(\n 'pkcs8',\n der.buffer.slice(der.byteOffset, der.byteOffset + der.byteLength) as ArrayBuffer,\n algorithm,\n false,\n ['sign'],\n );\n}\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let s = '';\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);\n return btoa(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n","/**\n * Legacy MD5 / MD4 + HMAC-MD5 — required for Digest auth (RFC 7616) and\n * NTLMv2 (RFC 4178). Both are obsolete cryptographically but mandated\n * for interop with servers that still use them. Implemented inline so\n * we don't take a runtime dep for two specific protocols, and so the\n * web bundle stays browser-safe (WebCrypto doesn't expose MD5/MD4).\n *\n * Internal module — not exported from the package barrel. Importers go\n * through `digest.ts` / `ntlm.ts`. Algorithms ported verbatim from the\n * v1 reference (`studio_old/packages/core/src/request/executionEngine.ts`)\n * which was tested against RFC vectors in production.\n *\n * Do NOT use these for any new use case — they're leaks of legacy\n * protocols, kept here for compatibility only.\n */\n\n// ── MD5 (RFC 1321) ─────────────────────────────────────────────────────────────\nexport function md5(str: string): string {\n function safeAdd(x: number, y: number) {\n const lsw = (x & 0xffff) + (y & 0xffff);\n const msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n return (msw << 16) | (lsw & 0xffff);\n }\n const rol = (n: number, c: number) => (n << c) | (n >>> (32 - c));\n const cmn = (q: number, a: number, b: number, x: number, s: number, t: number) =>\n safeAdd(rol(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);\n const ff = (a: number, b: number, c: number, d: number, x: number, s: number, t: number) =>\n cmn((b & c) | (~b & d), a, b, x, s, t);\n const gg = (a: number, b: number, c: number, d: number, x: number, s: number, t: number) =>\n cmn((b & d) | (c & ~d), a, b, x, s, t);\n const hh = (a: number, b: number, c: number, d: number, x: number, s: number, t: number) =>\n cmn(b ^ c ^ d, a, b, x, s, t);\n const ii = (a: number, b: number, c: number, d: number, x: number, s: number, t: number) =>\n cmn(c ^ (b | ~d), a, b, x, s, t);\n\n const n = str.length;\n const nblk = ((n + 8) >> 6) + 1;\n const blks = new Array<number>(nblk * 16).fill(0);\n for (let i = 0; i < n; i++) {\n blks[i >> 2] = (blks[i >> 2] ?? 0) | (str.charCodeAt(i) << ((i % 4) * 8));\n }\n blks[n >> 2] = (blks[n >> 2] ?? 0) | (0x80 << ((n % 4) * 8));\n blks[nblk * 16 - 2] = n * 8;\n\n let a = 0x67452301,\n b = 0xefcdab89,\n c = 0x98badcfe,\n d = 0x10325476;\n for (let i = 0; i < blks.length; i += 16) {\n const [oa, ob, oc, od] = [a, b, c, d];\n const x = blks.slice(i, i + 16);\n a = ff(a, b, c, d, x[0], 7, 0xd76aa478);\n d = ff(d, a, b, c, x[1], 12, 0xe8c7b756);\n c = ff(c, d, a, b, x[2], 17, 0x242070db);\n b = ff(b, c, d, a, x[3], 22, 0xc1bdceee);\n a = ff(a, b, c, d, x[4], 7, 0xf57c0faf);\n d = ff(d, a, b, c, x[5], 12, 0x4787c62a);\n c = ff(c, d, a, b, x[6], 17, 0xa8304613);\n b = ff(b, c, d, a, x[7], 22, 0xfd469501);\n a = ff(a, b, c, d, x[8], 7, 0x698098d8);\n d = ff(d, a, b, c, x[9], 12, 0x8b44f7af);\n c = ff(c, d, a, b, x[10], 17, 0xffff5bb1);\n b = ff(b, c, d, a, x[11], 22, 0x895cd7be);\n a = ff(a, b, c, d, x[12], 7, 0x6b901122);\n d = ff(d, a, b, c, x[13], 12, 0xfd987193);\n c = ff(c, d, a, b, x[14], 17, 0xa679438e);\n b = ff(b, c, d, a, x[15], 22, 0x49b40821);\n a = gg(a, b, c, d, x[1], 5, 0xf61e2562);\n d = gg(d, a, b, c, x[6], 9, 0xc040b340);\n c = gg(c, d, a, b, x[11], 14, 0x265e5a51);\n b = gg(b, c, d, a, x[0], 20, 0xe9b6c7aa);\n a = gg(a, b, c, d, x[5], 5, 0xd62f105d);\n d = gg(d, a, b, c, x[10], 9, 0x02441453);\n c = gg(c, d, a, b, x[15], 14, 0xd8a1e681);\n b = gg(b, c, d, a, x[4], 20, 0xe7d3fbc8);\n a = gg(a, b, c, d, x[9], 5, 0x21e1cde6);\n d = gg(d, a, b, c, x[14], 9, 0xc33707d6);\n c = gg(c, d, a, b, x[3], 14, 0xf4d50d87);\n b = gg(b, c, d, a, x[8], 20, 0x455a14ed);\n a = gg(a, b, c, d, x[13], 5, 0xa9e3e905);\n d = gg(d, a, b, c, x[2], 9, 0xfcefa3f8);\n c = gg(c, d, a, b, x[7], 14, 0x676f02d9);\n b = gg(b, c, d, a, x[12], 20, 0x8d2a4c8a);\n a = hh(a, b, c, d, x[5], 4, 0xfffa3942);\n d = hh(d, a, b, c, x[8], 11, 0x8771f681);\n c = hh(c, d, a, b, x[11], 16, 0x6d9d6122);\n b = hh(b, c, d, a, x[14], 23, 0xfde5380c);\n a = hh(a, b, c, d, x[1], 4, 0xa4beea44);\n d = hh(d, a, b, c, x[4], 11, 0x4bdecfa9);\n c = hh(c, d, a, b, x[7], 16, 0xf6bb4b60);\n b = hh(b, c, d, a, x[10], 23, 0xbebfbc70);\n a = hh(a, b, c, d, x[13], 4, 0x289b7ec6);\n d = hh(d, a, b, c, x[0], 11, 0xeaa127fa);\n c = hh(c, d, a, b, x[3], 16, 0xd4ef3085);\n b = hh(b, c, d, a, x[6], 23, 0x04881d05);\n a = hh(a, b, c, d, x[9], 4, 0xd9d4d039);\n d = hh(d, a, b, c, x[12], 11, 0xe6db99e5);\n c = hh(c, d, a, b, x[15], 16, 0x1fa27cf8);\n b = hh(b, c, d, a, x[2], 23, 0xc4ac5665);\n a = ii(a, b, c, d, x[0], 6, 0xf4292244);\n d = ii(d, a, b, c, x[7], 10, 0x432aff97);\n c = ii(c, d, a, b, x[14], 15, 0xab9423a7);\n b = ii(b, c, d, a, x[5], 21, 0xfc93a039);\n a = ii(a, b, c, d, x[12], 6, 0x655b59c3);\n d = ii(d, a, b, c, x[3], 10, 0x8f0ccc92);\n c = ii(c, d, a, b, x[10], 15, 0xffeff47d);\n b = ii(b, c, d, a, x[1], 21, 0x85845dd1);\n a = ii(a, b, c, d, x[8], 6, 0x6fa87e4f);\n d = ii(d, a, b, c, x[15], 10, 0xfe2ce6e0);\n c = ii(c, d, a, b, x[6], 15, 0xa3014314);\n b = ii(b, c, d, a, x[13], 21, 0x4e0811a1);\n a = ii(a, b, c, d, x[4], 6, 0xf7537e82);\n d = ii(d, a, b, c, x[11], 10, 0xbd3af235);\n c = ii(c, d, a, b, x[2], 15, 0x2ad7d2bb);\n b = ii(b, c, d, a, x[9], 21, 0xeb86d391);\n a = safeAdd(a, oa);\n b = safeAdd(b, ob);\n c = safeAdd(c, oc);\n d = safeAdd(d, od);\n }\n const hex = (v: number) =>\n [v, v >>> 8, v >>> 16, v >>> 24].map((n) => (n & 0xff).toString(16).padStart(2, '0')).join('');\n return hex(a) + hex(b) + hex(c) + hex(d);\n}\n\n// ── MD4 (RFC 1320) — used for NTLM NT-hash ─────────────────────────────────────\nexport function md4(input: Uint8Array): Uint8Array {\n const rol = (x: number, n: number): number => ((x << n) | (x >>> (32 - n))) >>> 0;\n const add = (x: number, y: number): number => (x + y) >>> 0;\n const F = (x: number, y: number, z: number): number => ((x & y) | (~x & z)) >>> 0;\n const G = (x: number, y: number, z: number): number => ((x & y) | (x & z) | (y & z)) >>> 0;\n const H = (x: number, y: number, z: number): number => (x ^ y ^ z) >>> 0;\n const padLen = (56 - ((input.length + 1) % 64) + 64) % 64;\n const buf = new Uint8Array(input.length + 1 + padLen + 8);\n buf.set(input);\n buf[input.length] = 0x80;\n const v = new DataView(buf.buffer);\n v.setUint32(buf.length - 8, (input.length * 8) >>> 0, true);\n v.setUint32(buf.length - 4, Math.floor(input.length / 0x20000000), true);\n let a = 0x67452301,\n b = 0xefcdab89,\n c = 0x98badcfe,\n d = 0x10325476;\n for (let i = 0; i < buf.length; i += 64) {\n const x = Array.from({ length: 16 }, (_, k) => v.getUint32(i + k * 4, true));\n const [sa, sb, sc, sd] = [a, b, c, d];\n a = rol(add(add(a, F(b, c, d)), x[0]), 3);\n d = rol(add(add(d, F(a, b, c)), x[1]), 7);\n c = rol(add(add(c, F(d, a, b)), x[2]), 11);\n b = rol(add(add(b, F(c, d, a)), x[3]), 19);\n a = rol(add(add(a, F(b, c, d)), x[4]), 3);\n d = rol(add(add(d, F(a, b, c)), x[5]), 7);\n c = rol(add(add(c, F(d, a, b)), x[6]), 11);\n b = rol(add(add(b, F(c, d, a)), x[7]), 19);\n a = rol(add(add(a, F(b, c, d)), x[8]), 3);\n d = rol(add(add(d, F(a, b, c)), x[9]), 7);\n c = rol(add(add(c, F(d, a, b)), x[10]), 11);\n b = rol(add(add(b, F(c, d, a)), x[11]), 19);\n a = rol(add(add(a, F(b, c, d)), x[12]), 3);\n d = rol(add(add(d, F(a, b, c)), x[13]), 7);\n c = rol(add(add(c, F(d, a, b)), x[14]), 11);\n b = rol(add(add(b, F(c, d, a)), x[15]), 19);\n const C2 = 0x5a827999;\n a = rol(add(add(add(a, G(b, c, d)), x[0]), C2), 3);\n d = rol(add(add(add(d, G(a, b, c)), x[4]), C2), 5);\n c = rol(add(add(add(c, G(d, a, b)), x[8]), C2), 9);\n b = rol(add(add(add(b, G(c, d, a)), x[12]), C2), 13);\n a = rol(add(add(add(a, G(b, c, d)), x[1]), C2), 3);\n d = rol(add(add(add(d, G(a, b, c)), x[5]), C2), 5);\n c = rol(add(add(add(c, G(d, a, b)), x[9]), C2), 9);\n b = rol(add(add(add(b, G(c, d, a)), x[13]), C2), 13);\n a = rol(add(add(add(a, G(b, c, d)), x[2]), C2), 3);\n d = rol(add(add(add(d, G(a, b, c)), x[6]), C2), 5);\n c = rol(add(add(add(c, G(d, a, b)), x[10]), C2), 9);\n b = rol(add(add(add(b, G(c, d, a)), x[14]), C2), 13);\n a = rol(add(add(add(a, G(b, c, d)), x[3]), C2), 3);\n d = rol(add(add(add(d, G(a, b, c)), x[7]), C2), 5);\n c = rol(add(add(add(c, G(d, a, b)), x[11]), C2), 9);\n b = rol(add(add(add(b, G(c, d, a)), x[15]), C2), 13);\n const C3 = 0x6ed9eba1;\n a = rol(add(add(add(a, H(b, c, d)), x[0]), C3), 3);\n d = rol(add(add(add(d, H(a, b, c)), x[8]), C3), 9);\n c = rol(add(add(add(c, H(d, a, b)), x[4]), C3), 11);\n b = rol(add(add(add(b, H(c, d, a)), x[12]), C3), 15);\n a = rol(add(add(add(a, H(b, c, d)), x[2]), C3), 3);\n d = rol(add(add(add(d, H(a, b, c)), x[10]), C3), 9);\n c = rol(add(add(add(c, H(d, a, b)), x[6]), C3), 11);\n b = rol(add(add(add(b, H(c, d, a)), x[14]), C3), 15);\n a = rol(add(add(add(a, H(b, c, d)), x[1]), C3), 3);\n d = rol(add(add(add(d, H(a, b, c)), x[9]), C3), 9);\n c = rol(add(add(add(c, H(d, a, b)), x[5]), C3), 11);\n b = rol(add(add(add(b, H(c, d, a)), x[13]), C3), 15);\n a = rol(add(add(add(a, H(b, c, d)), x[3]), C3), 3);\n d = rol(add(add(add(d, H(a, b, c)), x[11]), C3), 9);\n c = rol(add(add(add(c, H(d, a, b)), x[7]), C3), 11);\n b = rol(add(add(add(b, H(c, d, a)), x[15]), C3), 15);\n a = add(a, sa);\n b = add(b, sb);\n c = add(c, sc);\n d = add(d, sd);\n }\n const out = new Uint8Array(16);\n const ov = new DataView(out.buffer);\n ov.setUint32(0, a, true);\n ov.setUint32(4, b, true);\n ov.setUint32(8, c, true);\n ov.setUint32(12, d, true);\n return out;\n}\n\n/** MD5 over arbitrary bytes — used as the inner hash for HMAC-MD5 (NTLMv2). */\nexport function md5Bytes(input: Uint8Array): Uint8Array {\n const str = Array.from(input, (b) => String.fromCharCode(b)).join('');\n const hex = md5(str);\n const out = new Uint8Array(16);\n for (let i = 0; i < 16; i++) out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n return out;\n}\n\n/** HMAC-MD5 (RFC 2104) — used by NTLMv2 hash chain. */\nexport function hmacMd5(key: Uint8Array, data: Uint8Array): Uint8Array {\n const B = 64;\n const k = key.length > B ? md5Bytes(key) : key;\n const kPad = new Uint8Array(B);\n kPad.set(k);\n const ipad = kPad.map((b) => b ^ 0x36);\n const opad = kPad.map((b) => b ^ 0x5c);\n const inner = new Uint8Array(B + data.length);\n inner.set(ipad);\n inner.set(data, B);\n const outer = new Uint8Array(B + 16);\n outer.set(opad);\n outer.set(md5Bytes(inner), B);\n return md5Bytes(outer);\n}\n","import { md4, hmacMd5 } from './_legacyHashes';\n\n/**\n * NTLM (Windows Integrated Authentication) — NTLMv2 only.\n *\n * NTLM is a stateful 3-way handshake over a single TCP connection:\n * 1. Client sends Type-1 Negotiate message (advertise flags, domain, workstation)\n * 2. Server responds 401 with `WWW-Authenticate: NTLM <base64 Type-2>` carrying\n * the server challenge (8 random bytes) + target info.\n * 3. Client sends Type-3 Authenticate message containing the NTProofStr\n * (HMAC-MD5 of `serverChallenge + blob` using the NTLMv2 hash).\n *\n * The handshake itself lives in `executeRequest` because it requires\n * connection affinity (NTLM auth is tied to the underlying TCP socket).\n * This module owns only the message construction + parsing.\n *\n * Implementation ported from the v1 reference; algorithm validated\n * against the Microsoft `[MS-NLMP]` worked example.\n */\n\n/** NTLM v2 negotiate flags — UNICODE | OEM | REQUEST_TARGET | NTLM. */\nconst NTLM_FLAGS = 0x00000207;\n\n/**\n * Build the raw Type-1 Negotiate message bytes. The engine retains these\n * for MIC computation in the Type-3 step ([MS-NLMP] §3.1.5.1.2 hashes\n * `Type1 || Type2 || Type3`), then base64-encodes for the wire.\n */\nexport function buildNtlmType1NegotiateBytes(domain: string, workstation: string): Uint8Array {\n const domainBytes = utf16le(domain.toUpperCase());\n const wsBytes = utf16le(workstation.toUpperCase());\n const buf = new Uint8Array(32 + domainBytes.length + wsBytes.length);\n buf.set([78, 84, 76, 77, 83, 83, 80, 0]); // \"NTLMSSP\\0\"\n writeLE32(buf, 8, 1); // type = 1\n writeLE32(buf, 12, NTLM_FLAGS);\n writeLE16(buf, 16, domainBytes.length);\n writeLE16(buf, 18, domainBytes.length);\n writeLE32(buf, 20, 32 + wsBytes.length);\n writeLE16(buf, 24, wsBytes.length);\n writeLE16(buf, 26, wsBytes.length);\n writeLE32(buf, 28, 32);\n buf.set(wsBytes, 32);\n buf.set(domainBytes, 32 + wsBytes.length);\n return buf;\n}\n\n/**\n * Build the Type-1 Negotiate message, base64-encoded for use as\n * `Authorization: NTLM <value>`. Sent by the client to advertise its\n * capabilities and trigger the server's challenge response.\n */\nexport function buildNtlmType1Negotiate(domain: string, workstation: string): string {\n return base64Encode(buildNtlmType1NegotiateBytes(domain, workstation));\n}\n\n/**\n * base64-decode an NTLM message into raw bytes. Exposed for engines that\n * recover Type-1 / Type-2 byte buffers from previously-sent / received\n * `Authorization` / `WWW-Authenticate` headers (the MIC computation\n * needs the raw bytes, not the base64 form).\n */\nexport function decodeNtlmBase64(value: string): Uint8Array {\n return base64Decode(value);\n}\n\nexport interface NtlmType2Challenge {\n /** 8-byte server challenge nonce. */\n challenge: Uint8Array;\n /**\n * Variable-length AV_PAIR target-info block. Echoed verbatim in the\n * Type-3 NTLMv2 blob so the server can verify the response.\n */\n targetInfo: Uint8Array;\n /**\n * Original raw bytes of the entire Type-2 message — required when the\n * caller wants to compute a MIC over `Type1 || Type2 || Type3` per\n * [MS-NLMP] §3.1.5.1.2. Set automatically by `parseNtlmType2Challenge`.\n * Optional so callers constructing the challenge literal in tests can\n * skip it; MIC computation needs the parser-produced form.\n */\n rawBytes?: Uint8Array;\n}\n\n/**\n * Parse the Type-2 Challenge message extracted from the server's\n * `WWW-Authenticate: NTLM <base64>` reply. Returns the server challenge\n * + target info bytes that feed into Type-3 construction.\n */\nexport function parseNtlmType2Challenge(base64: string): NtlmType2Challenge {\n const bytes = base64Decode(base64);\n if (bytes.length < 48) {\n throw new Error('NTLM Type-2 message too short');\n }\n const v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const challenge = bytes.slice(24, 32);\n // Target info security buffer at offset 40 (length, max-length, offset).\n const tiLen = v.getUint16(40, true);\n const tiOff = v.getUint32(44, true);\n const targetInfo =\n tiLen > 0 && tiOff + tiLen <= bytes.length\n ? bytes.slice(tiOff, tiOff + tiLen)\n : new Uint8Array(0);\n return { challenge, targetInfo, rawBytes: bytes };\n}\n\nexport interface BuildNtlmType3Args {\n username: string;\n password: string;\n domain: string;\n workstation: string;\n challenge: NtlmType2Challenge;\n /** Override for the 8-byte client challenge — tests pass a fixed value. */\n clientChallenge?: Uint8Array;\n /** Override for the timestamp (ms since epoch) — tests pass a fixed value. */\n timestampMs?: number;\n /**\n * Raw bytes of the Type-1 Negotiate message we sent in the previous\n * round. When BOTH this and `type2Message` are provided, we emit a\n * 16-byte MIC at offset 72 of the Type-3 message and set MsvAvFlags\n * bit 0x2 in the AV_PAIR target info — required by hardened Win Server\n * 2019+ AD configurations per [MS-NLMP] §3.1.5.1.2. When either is\n * absent we preserve the legacy \"no MIC\" layout for back-compat with\n * older servers that reject the longer header.\n */\n type1Message?: Uint8Array;\n /** Raw bytes of the Type-2 Challenge message — paired with `type1Message`. */\n type2Message?: Uint8Array;\n}\n\n/**\n * Build the Type-3 Authenticate message (NTLMv2). Computes the NTLMv2\n * hash, the NTProofStr (HMAC-MD5 over server-challenge + blob), and\n * packs everything into the binary message format. Returns base64 for\n * use as `Authorization: NTLM <value>`.\n */\nexport function buildNtlmType3Authenticate(args: BuildNtlmType3Args): string {\n const { username, password, domain, workstation, challenge } = args;\n\n // NT hash = MD4(UTF-16LE(password)).\n const ntHash = md4(utf16le(password));\n\n // NTLMv2 hash = HMAC-MD5(NT hash, UTF-16LE(upper(username) + domain)).\n const identity = concat(utf16le(username.toUpperCase()), utf16le(domain));\n const ntlmV2Hash = hmacMd5(ntHash, identity);\n\n const clientChallenge = args.clientChallenge ?? randomBytes(8);\n\n // NTLMv2 blob — RFC 4178 / [MS-NLMP] §2.2.2.7.\n const ts = BigInt(args.timestampMs ?? Date.now()) * 10000n + 116444736000000000n;\n const tsBytes = new Uint8Array(8);\n for (let i = 0; i < 8; i++) tsBytes[i] = Number((ts >> BigInt(i * 8)) & 0xffn);\n\n // [MS-NLMP] §3.1.5.1.2 — when the server's target info doesn't already\n // include MsvAvTimestamp, we MUST inject one before the EOL marker so\n // hardened Win Server 2019+ AD configs accept the response. Servers\n // that already include their own timestamp take precedence, so we\n // only inject when absent. AvId 7 = MsvAvTimestamp (8-byte FILETIME).\n const withTimestamp = ensureTimestampAvPair(challenge.targetInfo, tsBytes);\n // When MIC is enabled (caller passed Type-1 + Type-2 bytes), we also\n // set MsvAvFlags bit 0x2 — [MS-NLMP] §2.2.2.1 — to advertise that this\n // Type-3 carries a MIC. AvId 6 = MsvAvFlags (4-byte little-endian).\n const emitMic = !!(args.type1Message && args.type2Message);\n const enrichedTargetInfo = emitMic\n ? ensureMsvAvFlagsBit(withTimestamp, 0x00000002)\n : withTimestamp;\n\n const blob = new Uint8Array(28 + enrichedTargetInfo.length);\n blob[0] = 1;\n blob[1] = 1; // signature\n // bytes 2-7 are reserved zero (already set by Uint8Array default).\n for (let i = 0; i < 8; i++) blob[8 + i] = tsBytes[i]!;\n for (let i = 0; i < 8; i++) blob[16 + i] = clientChallenge[i]!;\n // bytes 24-27 reserved zero.\n blob.set(enrichedTargetInfo, 28);\n\n // NTProofStr = HMAC-MD5(NTLMv2 hash, serverChallenge + blob).\n const proofInput = concat(challenge.challenge, blob);\n const ntProofStr = hmacMd5(ntlmV2Hash, proofInput);\n\n // NT response = NTProofStr || blob.\n const ntResponse = concat(ntProofStr, blob);\n\n const domainBytes = utf16le(domain);\n const userBytes = utf16le(username);\n const wsBytes = utf16le(workstation);\n const lmResponse = new Uint8Array(24); // empty LM response — NTLMv2 doesn't use LM.\n\n // Layout offsets — fixed header is 72 bytes (Signature..Version) without\n // MIC, 88 bytes when MIC is present (Version followed by 16-byte MIC).\n // [MS-NLMP] §2.2.1.3.\n const baseOff = emitMic ? 88 : 72;\n const domainOff = baseOff;\n const userOff = domainOff + domainBytes.length;\n const wsOff = userOff + userBytes.length;\n const lmOff = wsOff + wsBytes.length;\n const ntOff = lmOff + lmResponse.length;\n const totalLen = ntOff + ntResponse.length;\n\n const msg = new Uint8Array(totalLen);\n msg.set([78, 84, 76, 77, 83, 83, 80, 0]); // \"NTLMSSP\\0\"\n writeLE32(msg, 8, 3); // type = 3\n\n writeSecurityBuffer(msg, 12, lmResponse.length, lmOff);\n writeSecurityBuffer(msg, 20, ntResponse.length, ntOff);\n writeSecurityBuffer(msg, 28, domainBytes.length, domainOff);\n writeSecurityBuffer(msg, 36, userBytes.length, userOff);\n writeSecurityBuffer(msg, 44, wsBytes.length, wsOff);\n writeLE32(msg, 60, NTLM_FLAGS);\n\n msg.set(domainBytes, domainOff);\n msg.set(userBytes, userOff);\n msg.set(wsBytes, wsOff);\n msg.set(lmResponse, lmOff);\n msg.set(ntResponse, ntOff);\n\n // MIC computation — [MS-NLMP] §3.1.5.1.2. Done last so the message body\n // is finalized before we hash it. The MIC field at offset 72-87 is\n // already zeroed (Uint8Array default), which is exactly what the spec\n // requires during hashing. We patch the computed MIC in place.\n //\n // For NTLMv2 without NEGOTIATE_KEY_EXCH (our flag set 0x00000207):\n // SessionBaseKey = HMAC-MD5(NTLMv2Hash, NTProofStr)\n // KeyExchangeKey = SessionBaseKey\n // ExportedSessionKey = KeyExchangeKey (no RC4 wrap — NEGOTIATE_KEY_EXCH absent)\n // MIC = HMAC-MD5(ExportedSessionKey, Type1 || Type2 || Type3-zero-MIC)\n if (emitMic) {\n const sessionBaseKey = hmacMd5(ntlmV2Hash, ntProofStr);\n const concatenated = concat(concat(args.type1Message!, args.type2Message!), msg);\n const mic = hmacMd5(sessionBaseKey, concatenated);\n for (let i = 0; i < 16; i++) msg[72 + i] = mic[i]!;\n }\n\n return base64Encode(msg);\n}\n\n// ── helpers ────────────────────────────────────────────────────────────────────\n\n/**\n * AV_PAIR walker — scans `targetInfo` for an existing MsvAvTimestamp\n * (AvId 7). If found, leaves it alone (the server's value wins). If\n * absent, splices in `[AvId=7][AvLen=8][8 bytes timestamp]` immediately\n * before the EOL pair (AvId 0, AvLen 0).\n */\nfunction ensureTimestampAvPair(targetInfo: Uint8Array, tsBytes: Uint8Array): Uint8Array {\n // Empty target info — emit timestamp + EOL.\n if (targetInfo.length === 0) {\n const out = new Uint8Array(12 + 4);\n writeLE16(out, 0, 7); // AvId = MsvAvTimestamp\n writeLE16(out, 2, 8); // AvLen = 8\n for (let i = 0; i < 8; i++) out[4 + i] = tsBytes[i]!;\n // EOL pair at the tail.\n return out;\n }\n\n // Walk pairs to look for AvId=7. Each pair: 2-byte AvId, 2-byte AvLen,\n // AvLen bytes of value. AvId 0 (EOL) terminates.\n let cursor = 0;\n let eolOffset = -1;\n let hasTimestamp = false;\n while (cursor + 4 <= targetInfo.length) {\n const avId = targetInfo[cursor] | (targetInfo[cursor + 1] << 8);\n const avLen = targetInfo[cursor + 2] | (targetInfo[cursor + 3] << 8);\n if (avId === 0) {\n eolOffset = cursor;\n break;\n }\n if (avId === 7) hasTimestamp = true;\n cursor += 4 + avLen;\n }\n\n if (hasTimestamp) return targetInfo;\n if (eolOffset < 0) {\n // Malformed — no EOL. Append timestamp + EOL conservatively.\n const out = new Uint8Array(targetInfo.length + 12 + 4);\n out.set(targetInfo);\n writeLE16(out, targetInfo.length, 7);\n writeLE16(out, targetInfo.length + 2, 8);\n for (let i = 0; i < 8; i++) out[targetInfo.length + 4 + i] = tsBytes[i]!;\n return out;\n }\n\n // Splice timestamp pair in before the EOL.\n const out = new Uint8Array(targetInfo.length + 12);\n out.set(targetInfo.subarray(0, eolOffset));\n writeLE16(out, eolOffset, 7);\n writeLE16(out, eolOffset + 2, 8);\n for (let i = 0; i < 8; i++) out[eolOffset + 4 + i] = tsBytes[i]!;\n out.set(targetInfo.subarray(eolOffset), eolOffset + 12);\n return out;\n}\n\n/**\n * AV_PAIR walker — sets bits in the MsvAvFlags pair (AvId 6, AvLen 4).\n * Inserts a fresh pair before the EOL marker if absent. Used to advertise\n * MIC presence (`bit 0x2`) per [MS-NLMP] §2.2.2.1.\n *\n * Assumes `targetInfo` ends with the EOL pair (AvId=0, AvLen=0). Callers\n * pass timestamp-enriched target info — `ensureTimestampAvPair` already\n * enforces a well-formed EOL.\n */\nfunction ensureMsvAvFlagsBit(targetInfo: Uint8Array, bit: number): Uint8Array {\n let cursor = 0;\n let eolOffset = -1;\n let flagsOffset = -1;\n while (cursor + 4 <= targetInfo.length) {\n const avId = targetInfo[cursor] | (targetInfo[cursor + 1] << 8);\n const avLen = targetInfo[cursor + 2] | (targetInfo[cursor + 3] << 8);\n if (avId === 0) {\n eolOffset = cursor;\n break;\n }\n if (avId === 6 && avLen === 4) flagsOffset = cursor + 4;\n cursor += 4 + avLen;\n }\n\n if (flagsOffset >= 0) {\n // OR our bit into the existing 4-byte LE flags value.\n const existing =\n targetInfo[flagsOffset] |\n (targetInfo[flagsOffset + 1] << 8) |\n (targetInfo[flagsOffset + 2] << 16) |\n (targetInfo[flagsOffset + 3] << 24);\n const merged = (existing | bit) >>> 0;\n const out = new Uint8Array(targetInfo);\n writeLE32(out, flagsOffset, merged);\n return out;\n }\n\n // No MsvAvFlags pair — splice a new one before EOL (or append if EOL\n // somehow absent). 8 bytes total: 2-byte AvId, 2-byte AvLen, 4-byte value.\n if (eolOffset < 0) {\n const out = new Uint8Array(targetInfo.length + 8 + 4);\n out.set(targetInfo);\n writeLE16(out, targetInfo.length, 6);\n writeLE16(out, targetInfo.length + 2, 4);\n writeLE32(out, targetInfo.length + 4, bit);\n return out;\n }\n const out = new Uint8Array(targetInfo.length + 8);\n out.set(targetInfo.subarray(0, eolOffset));\n writeLE16(out, eolOffset, 6);\n writeLE16(out, eolOffset + 2, 4);\n writeLE32(out, eolOffset + 4, bit);\n out.set(targetInfo.subarray(eolOffset), eolOffset + 8);\n return out;\n}\n\nfunction utf16le(str: string): Uint8Array {\n const buf = new Uint8Array(str.length * 2);\n for (let i = 0; i < str.length; i++) {\n const c = str.charCodeAt(i);\n buf[i * 2] = c & 0xff;\n buf[i * 2 + 1] = (c >> 8) & 0xff;\n }\n return buf;\n}\n\nfunction writeLE32(buf: Uint8Array, off: number, v: number): void {\n buf[off] = v & 0xff;\n buf[off + 1] = (v >> 8) & 0xff;\n buf[off + 2] = (v >> 16) & 0xff;\n buf[off + 3] = (v >> 24) & 0xff;\n}\n\nfunction writeLE16(buf: Uint8Array, off: number, v: number): void {\n buf[off] = v & 0xff;\n buf[off + 1] = (v >> 8) & 0xff;\n}\n\n/** Length, allocated-length, offset triple per `[MS-NLMP]` security buffer layout. */\nfunction writeSecurityBuffer(\n buf: Uint8Array,\n off: number,\n length: number,\n payloadOff: number,\n): void {\n writeLE16(buf, off, length);\n writeLE16(buf, off + 2, length);\n writeLE32(buf, off + 4, payloadOff);\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a);\n out.set(b, a.length);\n return out;\n}\n\nfunction randomBytes(n: number): Uint8Array {\n const out = new Uint8Array(n);\n crypto.getRandomValues(out);\n return out;\n}\n\nfunction base64Encode(bytes: Uint8Array): string {\n let s = '';\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);\n return btoa(s);\n}\n\nfunction base64Decode(s: string): Uint8Array {\n const raw = atob(s);\n const out = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) out[i] = raw.charCodeAt(i);\n return out;\n}\n","/**\n * The single token-endpoint client used by every OAuth2 grant.\n *\n * RFC 6749 §4 endpoints accept `application/x-www-form-urlencoded` with\n * `grant_type` plus grant-specific fields. Client credentials may go in\n * the Authorization header (`client_secret_basic`) or the body\n * (`client_secret_post`); some IdPs only accept one or the other, so the\n * caller picks via `clientAuthMethod`.\n *\n * On success the IdP returns:\n *\n * { access_token, token_type, expires_in?, refresh_token?, scope? }\n *\n * On failure (RFC 6749 §5.2):\n *\n * { error, error_description?, error_uri? } with HTTP 400/401\n *\n * We surface the failure as an Error whose `.message` includes both\n * `error` and `error_description` so the UI can show \"invalid_grant: bad\n * code\" without parsing JSON itself. The structured response is also\n * attached to `.cause` for callers who need to dispatch on `error_code`\n * (e.g. device flow's `authorization_pending` / `slow_down` cases).\n */\n\nexport interface OAuth2TokenResponse {\n accessToken: string;\n tokenType: string;\n expiresIn?: number;\n refreshToken?: string;\n scope?: string;\n /** Captured raw response — useful for OpenID Connect `id_token` etc. */\n raw: Record<string, unknown>;\n}\n\nexport interface OAuth2ErrorResponse {\n error: string;\n errorDescription?: string;\n errorUri?: string;\n /** HTTP status the IdP returned (400, 401, 403, …). */\n status: number;\n /** Captured raw body — useful for diagnostics and grant-specific dispatch. */\n raw: Record<string, unknown>;\n}\n\n/**\n * Pre-signed client-assertion JWT for `private_key_jwt` client\n * authentication (RFC 7521 §4.2 / RFC 7523 §2.2). The auth tab signs\n * the assertion locally via `signJwt` and passes it here; we add the\n * required `client_assertion` + `client_assertion_type` body fields.\n * Used in place of `clientSecret` — the IdP verifies the assertion\n * against the registered public key.\n */\nexport interface ClientAssertion {\n /** The signed JWT (header.payload.signature) — output of `signJwt`. */\n jwt: string;\n /** RFC 7523 mandates this exact value. Other types exist (e.g. SAML2) but aren't used here. */\n type?: string;\n}\n\nexport interface FetchOAuth2TokenArgs {\n tokenUrl: string;\n /**\n * Grant-specific body fields. `grant_type` MUST be set by the caller —\n * this helper doesn't infer it. Value type is `URLSearchParams` so the\n * caller controls the exact wire format and can reuse the same body\n * for retry / refresh paths.\n */\n body: URLSearchParams;\n clientId: string;\n /**\n * Confidential clients only. Public clients (PKCE in a SPA) leave this\n * undefined — the IdP recognizes the client by id alone.\n */\n clientSecret?: string;\n /**\n * Where to put the client credentials. `header` = HTTP Basic with\n * `id:secret`. `body` = `client_id` + `client_secret` URL-form fields.\n * Defaults to `header` (the RFC's preferred method).\n *\n * Ignored when `clientAssertion` is set — assertion takes precedence\n * because mixing both is a misconfiguration the server will reject.\n */\n clientAuthMethod?: 'header' | 'body';\n /**\n * Optional `private_key_jwt` style client authentication. When set,\n * the body carries `client_assertion` + `client_assertion_type` and\n * `clientSecret` is NOT sent. Used by Azure AD, GCP, and any IdP\n * that prefers signed assertions over shared secrets.\n */\n clientAssertion?: ClientAssertion;\n /** Optional extra parameters appended to the body — IdP-specific knobs. */\n extraParams?: Record<string, string>;\n /** Override fetch for tests / desktop bridge. */\n fetchImpl?: typeof fetch;\n /** Per-call abort. Composed with the global request signal upstream. */\n signal?: AbortSignal;\n}\n\n/**\n * OAuth2 token endpoint failure. The structured `errorBody` carries the\n * error code (`invalid_grant`, `authorization_pending`, etc) plus\n * `error_description` / `error_uri` and the HTTP status — callers can\n * dispatch on `errorBody.error` for grant-specific behavior (device\n * flow's `authorization_pending` / `slow_down`, refresh re-auth, etc).\n *\n * Naming note: we deliberately don't shadow the standard `Error.cause`\n * field. Callers using TypeScript can still use `instanceof` + the\n * `errorBody` accessor; callers reading the `cause` property get the\n * standard \"what was the original exception\" semantics.\n */\nexport class OAuth2TokenError extends Error {\n readonly errorBody: OAuth2ErrorResponse;\n constructor(errorBody: OAuth2ErrorResponse) {\n const desc = errorBody.errorDescription ? `: ${errorBody.errorDescription}` : '';\n super(`${errorBody.error}${desc}`);\n this.name = 'OAuth2TokenError';\n this.errorBody = errorBody;\n }\n}\n\nexport async function fetchOAuth2Token(args: FetchOAuth2TokenArgs): Promise<OAuth2TokenResponse> {\n const fetchImpl = args.fetchImpl ?? globalThis.fetch;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n };\n const method = args.clientAuthMethod ?? 'header';\n\n // Clone body so caller's URLSearchParams stays unchanged after we\n // append `client_id`/`client_secret`/extraParams.\n const body = new URLSearchParams(args.body.toString());\n\n if (args.clientAssertion) {\n // private_key_jwt: signed assertion takes precedence over secret.\n // RFC 7521 §4.2 mandates both fields in the body.\n body.set('client_id', args.clientId);\n body.set(\n 'client_assertion_type',\n args.clientAssertion.type ?? 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',\n );\n body.set('client_assertion', args.clientAssertion.jwt);\n } else if (method === 'header' && args.clientSecret) {\n headers['Authorization'] = `Basic ${base64(`${args.clientId}:${args.clientSecret}`)}`;\n // Public clients still need to identify themselves in body — RFC 6749 §3.2.1.\n body.set('client_id', args.clientId);\n } else {\n body.set('client_id', args.clientId);\n if (args.clientSecret) body.set('client_secret', args.clientSecret);\n }\n\n if (args.extraParams) {\n for (const [k, v] of Object.entries(args.extraParams)) body.set(k, v);\n }\n\n const response = await fetchImpl(args.tokenUrl, {\n method: 'POST',\n headers,\n body: body.toString(),\n signal: args.signal,\n });\n\n let raw: Record<string, unknown> = {};\n let parsedJson = false;\n try {\n raw = (await response.json()) as Record<string, unknown>;\n parsedJson = true;\n } catch {\n parsedJson = false;\n }\n\n // RFC 6750 §3 — the IdP MAY return errors via `WWW-Authenticate: Bearer\n // error=\"...\"` with no JSON body. Parse that as a fallback so users\n // don't see \"invalid_response: non-JSON\" when the IdP is well-behaved\n // by spec but didn't include a JSON body.\n if (!parsedJson && !response.ok) {\n const wwwAuth = response.headers.get('www-authenticate');\n const parsed = wwwAuth ? parseBearerAuthError(wwwAuth) : null;\n if (parsed) {\n throw new OAuth2TokenError({\n error: parsed.error,\n errorDescription: parsed.errorDescription,\n errorUri: parsed.errorUri,\n status: response.status,\n raw: { ...parsed },\n });\n }\n throw new OAuth2TokenError({\n error: 'invalid_response',\n errorDescription: `IdP returned non-JSON ${response.status} response`,\n status: response.status,\n raw,\n });\n }\n if (!parsedJson) {\n throw new OAuth2TokenError({\n error: 'invalid_response',\n errorDescription: 'IdP returned non-JSON success response',\n status: response.status,\n raw,\n });\n }\n\n if (!response.ok || typeof raw['error'] === 'string') {\n throw new OAuth2TokenError({\n error: typeof raw['error'] === 'string' ? raw['error'] : 'invalid_grant',\n errorDescription:\n typeof raw['error_description'] === 'string' ? raw['error_description'] : undefined,\n errorUri: typeof raw['error_uri'] === 'string' ? raw['error_uri'] : undefined,\n status: response.status,\n raw,\n });\n }\n\n if (typeof raw['access_token'] !== 'string') {\n throw new OAuth2TokenError({\n error: 'invalid_response',\n errorDescription: 'Token endpoint returned no access_token',\n status: response.status,\n raw,\n });\n }\n\n return {\n accessToken: raw['access_token'],\n tokenType: typeof raw['token_type'] === 'string' ? raw['token_type'] : 'Bearer',\n expiresIn: typeof raw['expires_in'] === 'number' ? raw['expires_in'] : undefined,\n refreshToken: typeof raw['refresh_token'] === 'string' ? raw['refresh_token'] : undefined,\n scope: typeof raw['scope'] === 'string' ? raw['scope'] : undefined,\n raw,\n };\n}\n\n/**\n * Extract `error=\"...\"` / `error_description=\"...\"` / `error_uri=\"...\"`\n * directives from a `WWW-Authenticate: Bearer ...` header value. Returns\n * null when the header isn't a Bearer challenge or carries no error\n * directive — callers fall back to the generic invalid_response error.\n */\nfunction parseBearerAuthError(\n wwwAuth: string,\n): { error: string; errorDescription?: string; errorUri?: string } | null {\n if (!/^bearer\\b/i.test(wwwAuth.trim())) return null;\n const directives: Record<string, string> = {};\n const re = /(\\w+)\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|([^\\s,]+))/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(wwwAuth)) !== null) {\n directives[m[1].toLowerCase()] =\n m[2] !== undefined ? m[2].replace(/\\\\(.)/g, '$1') : (m[3] ?? '');\n }\n if (!directives['error']) return null;\n return {\n error: directives['error'],\n errorDescription: directives['error_description'],\n errorUri: directives['error_uri'],\n };\n}\n\nfunction base64(text: string): string {\n // UTF-8 → base64. `btoa` is byte-oriented (Latin-1), so we have to encode\n // the string to bytes first. The previous `btoa(unescape(encodeURIComponent(text)))`\n // hack relied on the deprecated `unescape` global; this path uses\n // `TextEncoder` instead, which is the standard since ES2017 and is\n // present in every runtime we ship into.\n if (typeof btoa === 'function' && typeof TextEncoder !== 'undefined') {\n const bytes = new TextEncoder().encode(text);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n return btoa(binary);\n }\n // Same Node/Buffer fallback shape as applyAuth — kept defensive.\n const buf = (\n globalThis as unknown as {\n Buffer?: { from: (data: string, encoding?: string) => { toString: (e: string) => string } };\n }\n ).Buffer;\n if (!buf) throw new Error('Neither btoa nor Buffer is available in this runtime');\n return buf.from(text, 'utf8').toString('base64');\n}\n","/**\n * Per-grant OAuth2 runners. Each function POSTs to the token endpoint\n * with the body shape RFC 6749 specifies for that grant, and returns a\n * normalized `OAuth2TokenResponse`. Callbacks (browser redirects to\n * `redirect_uri?code=...`) and device-code polling intervals are the\n * caller's job — these runners ONLY exchange.\n *\n * Refresh handling is in `refreshToken()` rather than per-grant: the\n * refresh-token grant is identical regardless of which grant minted the\n * original token.\n */\n\nimport { OAuth2TokenError, fetchOAuth2Token, type OAuth2TokenResponse } from './fetchToken';\n\ntype ClientAuthMethod = 'header' | 'body';\ntype FetchImpl = typeof fetch;\n\nexport interface ClientCredentialsArgs {\n tokenUrl: string;\n clientId: string;\n clientSecret: string;\n scope?: string;\n clientAuthMethod?: ClientAuthMethod;\n extraParams?: Record<string, string>;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n}\n\n/** RFC 6749 §4.4 — machine-to-machine, no user. */\nexport async function runClientCredentials(\n args: ClientCredentialsArgs,\n): Promise<OAuth2TokenResponse> {\n const body = new URLSearchParams({ grant_type: 'client_credentials' });\n if (args.scope?.trim()) body.set('scope', args.scope.trim());\n return fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: args.clientAuthMethod ?? 'header',\n extraParams: args.extraParams,\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n}\n\nexport interface RopcArgs {\n tokenUrl: string;\n clientId: string;\n clientSecret?: string;\n username: string;\n password: string;\n scope?: string;\n clientAuthMethod?: ClientAuthMethod;\n extraParams?: Record<string, string>;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n}\n\n/**\n * RFC 6749 §4.3 — Resource Owner Password Credentials. Marked DEPRECATED\n * in OAuth 2.1; we support it because legacy IdPs still require it for\n * specific testing / migration scenarios. The auth panel surfaces a\n * warning banner about the deprecation.\n */\nexport async function runRopc(args: RopcArgs): Promise<OAuth2TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'password',\n username: args.username,\n password: args.password,\n });\n if (args.scope?.trim()) body.set('scope', args.scope.trim());\n return fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: args.clientAuthMethod ?? 'header',\n extraParams: args.extraParams,\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n}\n\nexport interface AuthCodeExchangeArgs {\n tokenUrl: string;\n clientId: string;\n clientSecret?: string;\n /** The `code` value the IdP redirected back with. */\n code: string;\n /** Must match the redirect_uri sent in the initial /authorize request. */\n redirectUri: string;\n clientAuthMethod?: ClientAuthMethod;\n extraParams?: Record<string, string>;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n}\n\n/** RFC 6749 §4.1 — Authorization Code grant. */\nexport async function exchangeAuthCode(args: AuthCodeExchangeArgs): Promise<OAuth2TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code: args.code,\n redirect_uri: args.redirectUri,\n });\n return fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: args.clientAuthMethod ?? 'header',\n extraParams: args.extraParams,\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n}\n\nexport interface PkceExchangeArgs extends AuthCodeExchangeArgs {\n /** The verifier we generated when constructing the auth URL. */\n codeVerifier: string;\n}\n\n/**\n * RFC 7636 — Authorization Code with PKCE. Same body as plain auth-code\n * plus `code_verifier`. clientSecret is optional (public clients omit it).\n */\nexport async function exchangePkce(args: PkceExchangeArgs): Promise<OAuth2TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code: args.code,\n redirect_uri: args.redirectUri,\n code_verifier: args.codeVerifier,\n });\n return fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: args.clientAuthMethod ?? 'header',\n extraParams: args.extraParams,\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n}\n\nexport interface DeviceAuthorizationResponse {\n deviceCode: string;\n userCode: string;\n verificationUri: string;\n /** Optional convenience URI with the user_code already embedded. */\n verificationUriComplete?: string;\n /** Seconds the device should poll the token endpoint. */\n interval: number;\n /** Seconds before deviceCode expires. */\n expiresIn: number;\n raw: Record<string, unknown>;\n}\n\nexport interface DeviceAuthorizationArgs {\n deviceAuthorizationUrl: string;\n clientId: string;\n clientSecret?: string;\n scope?: string;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n}\n\n/**\n * RFC 8628 §3.1 — Device Authorization Request. Returns the device_code\n * + user_code so the caller can show the user_code + verification URI to\n * a human, then poll the token endpoint with `pollDeviceFlow`.\n */\nexport async function requestDeviceAuthorization(\n args: DeviceAuthorizationArgs,\n): Promise<DeviceAuthorizationResponse> {\n const fetchImpl = args.fetchImpl ?? globalThis.fetch;\n const body = new URLSearchParams({ client_id: args.clientId });\n if (args.scope?.trim()) body.set('scope', args.scope.trim());\n if (args.clientSecret) body.set('client_secret', args.clientSecret);\n\n const response = await fetchImpl(args.deviceAuthorizationUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n },\n body: body.toString(),\n signal: args.signal,\n });\n\n let raw: Record<string, unknown> = {};\n try {\n raw = (await response.json()) as Record<string, unknown>;\n } catch {\n throw new OAuth2TokenError({\n error: 'invalid_response',\n errorDescription: 'Device authorization endpoint returned non-JSON',\n status: response.status,\n raw,\n });\n }\n\n if (!response.ok || typeof raw['error'] === 'string') {\n throw new OAuth2TokenError({\n error: typeof raw['error'] === 'string' ? raw['error'] : 'invalid_response',\n errorDescription:\n typeof raw['error_description'] === 'string' ? raw['error_description'] : undefined,\n status: response.status,\n raw,\n });\n }\n\n if (typeof raw['device_code'] !== 'string' || typeof raw['user_code'] !== 'string') {\n throw new OAuth2TokenError({\n error: 'invalid_response',\n errorDescription: 'Device authorization response missing device_code or user_code',\n status: response.status,\n raw,\n });\n }\n\n return {\n deviceCode: raw['device_code'],\n userCode: raw['user_code'],\n verificationUri:\n (raw['verification_uri'] as string | undefined) ??\n (raw['verification_url'] as string | undefined) ??\n '',\n verificationUriComplete:\n typeof raw['verification_uri_complete'] === 'string'\n ? raw['verification_uri_complete']\n : undefined,\n interval: typeof raw['interval'] === 'number' ? raw['interval'] : 5,\n expiresIn: typeof raw['expires_in'] === 'number' ? raw['expires_in'] : 600,\n raw,\n };\n}\n\nexport interface PollDeviceFlowArgs {\n tokenUrl: string;\n clientId: string;\n clientSecret?: string;\n deviceCode: string;\n /** Initial poll interval in seconds. Bumped to `interval + 5` on `slow_down`. */\n intervalSeconds: number;\n /** Max overall wait. When elapsed, throws an `OAuth2TokenError` of error=\"expired_token\". */\n maxWaitMs?: number;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n /**\n * Optional progress callback fired on every poll cycle. UI uses this\n * to update the visible \"still waiting…\" indicator and tick down the\n * remaining time. Receives `{ pollCount, elapsedMs, lastError }` —\n * `lastError` is set when the IdP responded `slow_down` so the UI\n * can hint the user to wait.\n */\n onPoll?: (info: { pollCount: number; elapsedMs: number; lastError?: string }) => void;\n /** Test seam — overrides `setTimeout` / `Date.now` for fake clocks. */\n scheduler?: {\n sleep: (ms: number) => Promise<void>;\n now: () => number;\n };\n}\n\nconst DEVICE_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code';\n\n/**\n * RFC 8628 §3.4 — poll the token endpoint until the user authorizes the\n * device, then return the token. Honors `authorization_pending` /\n * `slow_down` / `access_denied` / `expired_token`.\n */\nexport async function pollDeviceFlow(args: PollDeviceFlowArgs): Promise<OAuth2TokenResponse> {\n const sleep = args.scheduler?.sleep ?? ((ms: number) => new Promise((r) => setTimeout(r, ms)));\n const now = args.scheduler?.now ?? (() => Date.now());\n const start = now();\n let interval = args.intervalSeconds;\n let pollCount = 0;\n\n while (true) {\n pollCount++;\n args.onPoll?.({ pollCount, elapsedMs: now() - start });\n if (args.signal?.aborted) {\n throw new OAuth2TokenError({\n error: 'aborted',\n errorDescription: 'Device flow polling was aborted',\n status: 0,\n raw: {},\n });\n }\n if (args.maxWaitMs !== undefined && now() - start > args.maxWaitMs) {\n throw new OAuth2TokenError({\n error: 'expired_token',\n errorDescription: 'Device flow exceeded maxWaitMs',\n status: 0,\n raw: {},\n });\n }\n\n const body = new URLSearchParams({\n grant_type: DEVICE_GRANT_TYPE,\n device_code: args.deviceCode,\n });\n try {\n return await fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: 'body',\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n } catch (err) {\n if (!(err instanceof OAuth2TokenError)) throw err;\n if (err.errorBody.error === 'authorization_pending') {\n await sleep(interval * 1000);\n continue;\n }\n if (err.errorBody.error === 'slow_down') {\n interval += 5;\n await sleep(interval * 1000);\n continue;\n }\n // expired_token / access_denied / invalid_grant / etc — terminal.\n throw err;\n }\n }\n}\n\nexport interface RefreshTokenArgs {\n tokenUrl: string;\n clientId: string;\n clientSecret?: string;\n refreshToken: string;\n /** Some IdPs require the original scope on refresh. */\n scope?: string;\n clientAuthMethod?: ClientAuthMethod;\n extraParams?: Record<string, string>;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n}\n\n/**\n * RFC 6749 §6 — refresh a previously obtained token. Identical wire\n * shape regardless of the grant that minted the original token; the\n * caller decides when to call it (typical heuristic: when\n * `expiresAt < now + 60s`).\n */\nexport async function refreshToken(args: RefreshTokenArgs): Promise<OAuth2TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: args.refreshToken,\n });\n if (args.scope?.trim()) body.set('scope', args.scope.trim());\n return fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: args.clientAuthMethod ?? 'header',\n extraParams: args.extraParams,\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n}\n\n/**\n * Build the `/authorize` URL the user is redirected to for auth-code or\n * implicit flows. PKCE callers append `code_challenge` + `code_challenge_method`\n * via `extraParams`. Doesn't open a browser — that's the host bridge's job.\n */\nexport function buildAuthorizeUrl(args: {\n authorizeUrl: string;\n clientId: string;\n redirectUri: string;\n responseType: 'code' | 'token';\n scope?: string;\n state?: string;\n extraParams?: Record<string, string>;\n}): string {\n const url = new URL(args.authorizeUrl);\n url.searchParams.set('client_id', args.clientId);\n url.searchParams.set('redirect_uri', args.redirectUri);\n url.searchParams.set('response_type', args.responseType);\n if (args.scope) url.searchParams.set('scope', args.scope);\n if (args.state) url.searchParams.set('state', args.state);\n if (args.extraParams) {\n for (const [k, v] of Object.entries(args.extraParams)) url.searchParams.set(k, v);\n }\n return url.toString();\n}\n","// Translate a RequestAuth into outbound headers / query / cookies.\n//\n// Pure function — given a RequestAuth and the partially-built request, it\n// returns a new partially-built request with auth applied. The signing\n// primitives live in `../auth/*` so this module is mostly orchestration:\n// pick the right helper for the auth type and stitch its output into the\n// request.\n//\n// Three categories of auth types:\n// 1. Token / shared-secret (bearer, basic, api-key, custom-header,\n// oauth2-*, jwt-bearer, hawk, aws-sigv4): everything we need is in\n// `auth` already; we sign + return one headers object.\n// 2. Challenge-response that bootstraps from an unauthenticated send\n// (digest): we send no auth on the first request and let\n// executeRequest's 401-retry loop run buildDigestAuthHeader after\n// reading the server's WWW-Authenticate.\n// 3. Challenge-response that bootstraps from a Type-1 Negotiate (ntlm):\n// we attach the Type-1 here so the server immediately challenges\n// with Type-2; executeRequest then computes Type-3 and re-sends.\n\nimport type { RequestAuth } from '@apicircle/shared';\nimport { applyAwsSigV4 } from '../auth/awsSigV4';\nimport { buildHawkAuthHeader } from '../auth/hawk';\nimport { signJwt } from '../auth/jwt';\nimport { buildNtlmType1Negotiate } from '../auth/ntlm';\nimport { refreshToken as runRefreshToken } from '../auth/oauth2/grants';\nimport { OAuth2TokenError, type OAuth2TokenResponse } from '../auth/oauth2/fetchToken';\n\nexport interface AuthApplyTarget {\n url: string;\n method: string;\n headers: Record<string, string>;\n body: BodyInit | null;\n}\n\nexport interface AuthApplyOptions {\n /**\n * Called when applyAuth refreshes an expired OAuth2 access token. The\n * store wires this to persist the new accessToken / refreshToken /\n * expiresAt onto the request's auth payload — without it the refresh\n * works for THIS request but the next request would re-refresh because\n * the in-memory state didn't catch up.\n */\n onTokenRefreshed?: (\n auth: Extract<\n RequestAuth,\n | { type: 'oauth2-client-credentials' }\n | { type: 'oauth2-auth-code' }\n | { type: 'oauth2-pkce' }\n | { type: 'oauth2-password' }\n | { type: 'oauth2-implicit' }\n | { type: 'oauth2-device' }\n >,\n next: {\n accessToken: string;\n tokenType: string;\n refreshToken?: string;\n expiresAt: number;\n obtainedScope?: string;\n },\n ) => void | Promise<void>;\n /**\n * Test seam for the refresh fetch. When omitted, the global fetch is\n * used (matching production behavior).\n */\n fetchImpl?: typeof fetch;\n /**\n * Refresh tokens when they have less than this many milliseconds left.\n * Default: 60_000 (1 min). Set to 0 to disable proactive refresh.\n */\n refreshLeewayMs?: number;\n}\n\nexport interface AuthApplyResult {\n url: string;\n headers: Record<string, string>;\n /**\n * Non-fatal warnings raised while applying auth (bad JWT key, malformed\n * payload JSON, etc). The request still goes out — usually unauthenticated\n * — but executeRequest surfaces these to the user so they don't see a\n * mysterious 401 with no clue why their auth config didn't apply.\n */\n warnings?: AuthApplyWarning[];\n}\n\nexport interface AuthApplyWarning {\n /** Stable code so callers can match without parsing message strings. */\n code:\n | 'jwt-payload-json-invalid'\n | 'jwt-headers-json-invalid'\n | 'jwt-sign-failed'\n | 'hawk-url-invalid'\n | 'oauth2-refresh-failed';\n /** Human-readable message — safe to surface in the UI. */\n message: string;\n}\n\nfunction setHeader(\n headers: Record<string, string>,\n key: string,\n value: string,\n): Record<string, string> {\n // Replace any existing header with the same name (case-insensitive) so a\n // stale Authorization from the headers tab doesn't ride alongside auth.\n const lower = key.toLowerCase();\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() !== lower) out[k] = v;\n }\n out[key] = value;\n return out;\n}\n\n/**\n * Inspect an OAuth2 auth's expiry; if it's within `refreshLeewayMs` of\n * now AND a refreshToken is on file, swap in a freshly-refreshed token.\n * Failures are silent — applyAuth still tries to apply whatever token\n * we have, the user gets a 401, and the auth panel surfaces the\n * staleness via the token-state summary.\n *\n * Returns the refreshed auth (caller swaps it in for the rest of the\n * apply pass), or null when no refresh fired.\n */\n/**\n * In-flight refresh dedupe map. Keyed by `tokenUrl|clientId|refreshToken`\n * so two concurrent sends with the same expiring token coalesce into a\n * single POST against the IdP. Without this, N parallel sends with an\n * expired token = N parallel refresh requests, which most IdPs rate-\n * limit and which wastes a refresh_token if the IdP rotates them per\n * call. The map is process-local; cleared as soon as the refresh\n * settles either way.\n */\nconst inflightRefreshes = new Map<string, Promise<OAuth2TokenResponse>>();\n\nasync function maybeAutoRefresh(\n auth: RequestAuth,\n opts: AuthApplyOptions,\n warnings: AuthApplyWarning[],\n): Promise<RequestAuth | null> {\n if (\n auth.type !== 'oauth2-client-credentials' &&\n auth.type !== 'oauth2-auth-code' &&\n auth.type !== 'oauth2-pkce' &&\n auth.type !== 'oauth2-password' &&\n auth.type !== 'oauth2-device'\n ) {\n return null;\n }\n // implicit doesn't issue refresh_tokens — skip.\n const expiresAt = (auth as { expiresAt?: number }).expiresAt ?? 0;\n if (expiresAt <= 0) return null;\n const leeway = opts.refreshLeewayMs ?? 60_000;\n if (Date.now() + leeway < expiresAt) return null;\n const refreshTokenValue = (auth as { refreshToken?: string }).refreshToken ?? '';\n if (!refreshTokenValue.trim()) return null;\n try {\n const dedupeKey = `${auth.tokenUrl}|${auth.clientId}|${refreshTokenValue}`;\n const existing = inflightRefreshes.get(dedupeKey);\n const refreshPromise =\n existing ??\n runRefreshToken({\n tokenUrl: auth.tokenUrl,\n clientId: auth.clientId,\n clientSecret: (auth as { clientSecret?: string }).clientSecret || undefined,\n refreshToken: refreshTokenValue,\n scope: (auth as { scope?: string }).scope || undefined,\n fetchImpl: opts.fetchImpl,\n });\n if (!existing) {\n inflightRefreshes.set(dedupeKey, refreshPromise);\n // Always clear the entry once the promise settles, success or\n // failure. We MUST attach a catch as well — otherwise a refresh\n // rejection would propagate as an unhandled-rejection warning\n // (we await `refreshPromise` directly below, but the fan-out\n // `.finally(...)` here is its own promise chain that needs\n // explicit error consumption).\n refreshPromise\n .catch(() => {\n /* ignored — caller awaits the original promise and surfaces */\n })\n .finally(() => {\n inflightRefreshes.delete(dedupeKey);\n });\n }\n const next = await refreshPromise;\n const merged = {\n ...auth,\n accessToken: next.accessToken,\n tokenType: next.tokenType,\n refreshToken: next.refreshToken ?? refreshTokenValue,\n expiresAt: next.expiresIn ? Date.now() + next.expiresIn * 1000 : 0,\n obtainedScope: next.scope ?? (auth as { obtainedScope?: string }).obtainedScope ?? '',\n } as RequestAuth;\n if (opts.onTokenRefreshed) {\n try {\n await opts.onTokenRefreshed(\n merged as Parameters<NonNullable<AuthApplyOptions['onTokenRefreshed']>>[0],\n {\n accessToken: next.accessToken,\n tokenType: next.tokenType,\n refreshToken: next.refreshToken,\n expiresAt: next.expiresIn ? Date.now() + next.expiresIn * 1000 : 0,\n obtainedScope: next.scope,\n },\n );\n } catch {\n // Persistence failures shouldn't block the request — the\n // refreshed token still applies for THIS send.\n }\n }\n return merged;\n } catch (err) {\n // Refresh failed — surface to the user via authWarnings so they can\n // see WHY their request went out unauthenticated. Falls through with\n // the original (stale) token; the request will hit a 401 but at\n // least the user has a clear refresh-failure message in the panel.\n const message =\n err instanceof OAuth2TokenError\n ? `OAuth2 token refresh failed: ${err.message}`\n : `OAuth2 token refresh failed: ${err instanceof Error ? err.message : String(err)}`;\n warnings.push({ code: 'oauth2-refresh-failed', message });\n return null;\n }\n}\n\n/** Read a header by name case-insensitively. */\nfunction findHeaderValue(headers: Record<string, string>, key: string): string | undefined {\n const lower = key.toLowerCase();\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() === lower) return v;\n }\n return undefined;\n}\n\nfunction appendQueryParam(rawUrl: string, key: string, value: string): string {\n try {\n const parsed = new URL(rawUrl);\n parsed.searchParams.append(key, value);\n return parsed.toString();\n } catch {\n const sep = rawUrl.includes('?') ? '&' : '?';\n return `${rawUrl}${sep}${encodeURIComponent(key)}=${encodeURIComponent(value)}`;\n }\n}\n\nfunction appendCookie(\n headers: Record<string, string>,\n key: string,\n value: string,\n): Record<string, string> {\n const existing = Object.entries(headers).find(([k]) => k.toLowerCase() === 'cookie');\n const pair = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;\n if (existing) {\n const [k, v] = existing;\n return { ...headers, [k]: `${v}; ${pair}` };\n }\n return { ...headers, Cookie: pair };\n}\n\n// btoa exists everywhere we run today (browsers, Node ≥ 18). The Buffer\n// fallback is kept for the unlikely case of a sandbox that strips both —\n// we'd rather degrade with a clear message than silently send no auth.\nfunction nodeBufferToBase64(input: string | Uint8Array): string {\n const buf = (\n globalThis as unknown as {\n Buffer?: {\n from: (data: string | Uint8Array, encoding?: string) => { toString: (e: string) => string };\n };\n }\n ).Buffer;\n if (!buf) throw new Error('Neither btoa nor Buffer is available in this runtime');\n if (typeof input === 'string') return buf.from(input, 'utf8').toString('base64');\n return buf.from(input).toString('base64');\n}\n\nfunction base64(text: string): string {\n if (typeof btoa === 'function') {\n // btoa expects Latin-1; encodeURIComponent → escape lifts UTF-8 input\n // through that gauntlet without losing bytes.\n return btoa(unescape(encodeURIComponent(text)));\n }\n return nodeBufferToBase64(text);\n}\n\n// ── jwt-bearer plumbing ────────────────────────────────────────────────────────\n\n/**\n * Either return the user-supplied pre-computed token, or sign a fresh\n * one using the algorithm + key the auth config specifies. Returns the\n * token plus any warnings raised along the way (malformed JSON, signing\n * failure). Token is null when there's nothing to send; warnings are\n * non-empty when the config was malformed in a way the user should see.\n */\nasync function buildJwtToken(\n auth: Extract<RequestAuth, { type: 'jwt-bearer' }>,\n): Promise<{ token: string | null; warnings: AuthApplyWarning[] }> {\n const warnings: AuthApplyWarning[] = [];\n if (auth.token.trim().length > 0) return { token: auth.token.trim(), warnings };\n if (!auth.algorithm || !auth.secretOrKey) return { token: null, warnings };\n let payload: Record<string, unknown> = {};\n let extraHeaders: Record<string, unknown> = {};\n if (auth.payload.trim()) {\n try {\n payload = JSON.parse(auth.payload) as Record<string, unknown>;\n } catch (err) {\n warnings.push({\n code: 'jwt-payload-json-invalid',\n message: `JWT payload is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n });\n return { token: null, warnings };\n }\n }\n if (auth.jwtHeaders.trim()) {\n try {\n extraHeaders = JSON.parse(auth.jwtHeaders) as Record<string, unknown>;\n } catch (err) {\n warnings.push({\n code: 'jwt-headers-json-invalid',\n message: `JWT additional-headers is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n });\n return { token: null, warnings };\n }\n }\n try {\n const token = await signJwt({\n algorithm: auth.algorithm,\n secretOrKey: auth.secretOrKey,\n payload,\n additionalHeaders: extraHeaders,\n });\n return { token, warnings };\n } catch (err) {\n warnings.push({\n code: 'jwt-sign-failed',\n message: `JWT signing failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n return { token: null, warnings };\n }\n}\n\n// ── Public entry point ────────────────────────────────────────────────────────\n\nexport async function applyAuth(\n target: AuthApplyTarget,\n auth: RequestAuth,\n opts: AuthApplyOptions = {},\n): Promise<AuthApplyResult> {\n // Warnings collected as we go — emitted on the result so executeRequest\n // can surface them in `ExecutionResult.authWarnings` (UI displays\n // them next to the response). Refresh failures, JWT signing errors,\n // and Hawk URL parse failures all flow through here.\n const warnings: AuthApplyWarning[] = [];\n\n // Auto-refresh OAuth2 tokens that are expired or about to expire. The\n // refresh fires BEFORE the auth-injection switch below so the refreshed\n // accessToken is what we end up putting on the wire.\n const refreshed = await maybeAutoRefresh(auth, opts, warnings);\n if (refreshed) auth = refreshed;\n\n const result = await applyAuthBody(target, auth, opts, warnings);\n if (warnings.length > 0) {\n return {\n ...result,\n warnings: [...(result.warnings ?? []), ...warnings],\n };\n }\n return result;\n}\n\n/**\n * Inner switch — split out from `applyAuth` so the outer wrapper can\n * combine post-refresh warnings with per-type warnings without\n * re-walking the auth shape.\n */\nasync function applyAuthBody(\n target: AuthApplyTarget,\n auth: RequestAuth,\n opts: AuthApplyOptions,\n warnings: AuthApplyWarning[],\n): Promise<AuthApplyResult> {\n void warnings; // body-level switch doesn't push warnings today; refresh + JWT helpers do.\n void opts;\n switch (auth.type) {\n case 'none':\n case 'inherit': // inheritance is resolved upstream; if we still see it here, do nothing\n return { url: target.url, headers: target.headers };\n\n case 'bearer': {\n if (!auth.token.trim()) return { url: target.url, headers: target.headers };\n return {\n url: target.url,\n headers: setHeader(target.headers, 'Authorization', `Bearer ${auth.token.trim()}`),\n };\n }\n\n case 'basic': {\n const credentials = `${auth.username}:${auth.password}`;\n return {\n url: target.url,\n headers: setHeader(target.headers, 'Authorization', `Basic ${base64(credentials)}`),\n };\n }\n\n case 'api-key': {\n if (!auth.key.trim()) return { url: target.url, headers: target.headers };\n if (auth.addTo === 'query') {\n return { url: appendQueryParam(target.url, auth.key, auth.value), headers: target.headers };\n }\n if (auth.addTo === 'cookie') {\n return { url: target.url, headers: appendCookie(target.headers, auth.key, auth.value) };\n }\n return { url: target.url, headers: setHeader(target.headers, auth.key, auth.value) };\n }\n\n case 'custom-header': {\n if (!auth.key.trim()) return { url: target.url, headers: target.headers };\n return { url: target.url, headers: setHeader(target.headers, auth.key, auth.value) };\n }\n\n case 'oauth2-client-credentials':\n case 'oauth2-auth-code':\n case 'oauth2-pkce':\n case 'oauth2-password':\n case 'oauth2-implicit':\n case 'oauth2-device': {\n if (!auth.accessToken.trim()) return { url: target.url, headers: target.headers };\n const tokenType = auth.tokenType?.trim() || 'Bearer';\n return {\n url: target.url,\n headers: setHeader(\n target.headers,\n 'Authorization',\n `${tokenType} ${auth.accessToken.trim()}`,\n ),\n };\n }\n\n case 'aws-sigv4': {\n if (!auth.accessKeyId || !auth.secretAccessKey || !auth.region || !auth.service) {\n return { url: target.url, headers: target.headers };\n }\n // Pass the body through as-is — the signer accepts every BodyInit\n // shape and falls back to UNSIGNED-PAYLOAD for FormData /\n // ReadableStream where pre-fetch hashing isn't possible.\n const signed = await applyAwsSigV4({\n method: target.method,\n url: target.url,\n headers: target.headers,\n body: target.body as Parameters<typeof applyAwsSigV4>[0]['body'],\n accessKeyId: auth.accessKeyId,\n secretAccessKey: auth.secretAccessKey,\n region: auth.region,\n service: auth.service,\n sessionToken: auth.sessionToken || undefined,\n addTo: auth.addTo,\n });\n return { url: signed.url, headers: signed.headers };\n }\n\n case 'hawk': {\n if (!auth.hawkId || !auth.hawkKey) return { url: target.url, headers: target.headers };\n try {\n // When bindPayload is on AND the body is hashable, fold the body\n // into the MAC. We pull the content-type from the request's own\n // headers (case-insensitively); if the body is FormData /\n // ReadableStream we can't hash pre-fetch — silently fall back to\n // header-only signing, same as Hawk reference clients.\n let payload: { body: string | ArrayBuffer | Uint8Array; contentType: string } | undefined;\n if (auth.bindPayload && target.body != null) {\n const ct = findHeaderValue(target.headers, 'content-type') ?? 'application/octet-stream';\n if (typeof target.body === 'string') payload = { body: target.body, contentType: ct };\n else if (target.body instanceof ArrayBuffer)\n payload = { body: target.body, contentType: ct };\n else if (target.body instanceof Uint8Array)\n payload = { body: target.body, contentType: ct };\n else if (typeof URLSearchParams !== 'undefined' && target.body instanceof URLSearchParams)\n payload = {\n body: target.body.toString(),\n contentType: 'application/x-www-form-urlencoded',\n };\n }\n const headerValue = await buildHawkAuthHeader({\n method: target.method,\n url: target.url,\n hawkId: auth.hawkId,\n hawkKey: auth.hawkKey,\n algorithm: auth.algorithm,\n ext: auth.ext,\n payload,\n });\n return {\n url: target.url,\n headers: setHeader(target.headers, 'Authorization', headerValue),\n };\n } catch {\n // Malformed URL etc. — let the request fly without auth.\n return { url: target.url, headers: target.headers };\n }\n }\n\n case 'jwt-bearer': {\n const { token, warnings } = await buildJwtToken(auth);\n if (!token) {\n return { url: target.url, headers: target.headers, warnings };\n }\n return {\n url: target.url,\n headers: setHeader(target.headers, 'Authorization', `Bearer ${token}`),\n warnings: warnings.length ? warnings : undefined,\n };\n }\n\n case 'digest':\n // Digest is challenge-driven: send unauthenticated. executeRequest's\n // 401-retry path inspects WWW-Authenticate, runs buildDigestAuthHeader,\n // and re-fetches with the right Authorization on its own.\n return { url: target.url, headers: target.headers };\n\n case 'ntlm': {\n // NTLM bootstraps from a Type-1 Negotiate so the server immediately\n // returns 401 + Type-2 challenge. Sending nothing would let the\n // server respond with a generic auth-required error that's\n // indistinguishable from \"credentials wrong\"; emitting Type-1\n // explicitly lights up the handshake.\n const type1 = buildNtlmType1Negotiate(auth.domain, auth.workstation);\n return {\n url: target.url,\n headers: setHeader(target.headers, 'Authorization', `NTLM ${type1}`),\n };\n }\n }\n}\n","/**\n * Detect whether the host is the API Circle Studio Desktop shell.\n *\n * The Electron preload script attaches a bridge object on `globalThis.apicircleDesktop`\n * (see `apps/desktop/src/main/preload.ts`). The web app exposes nothing, so a\n * presence check is sufficient — we don't need to inspect the bridge's shape.\n */\nexport function isDesktop(): boolean {\n if (typeof globalThis === 'undefined') return false;\n return (globalThis as { apicircleDesktop?: unknown }).apicircleDesktop != null;\n}\n","/**\n * Auto-fed request headers — platform-specific, non-editable, not stored.\n *\n * These headers are injected at send-time by the execution engine:\n * • They are NEVER written to IndexedDB or Git remote.\n * • A new X-Trace-Span-Id and traceparent are generated for every send.\n * • They do NOT appear in the user-visible \"Headers\" editor tab — the\n * HeadersTab \"Auto-fed at send\" aside lists them for reference only.\n *\n * User-set headers always win: if the user typed `X-Client-Version` into the\n * Headers tab, the auto value is suppressed.\n */\n\nimport { isDesktop } from './platformDetection';\n\nconst APP_VERSION = '1.0.0'; // Keep in sync with package.json `version`.\nconst APP_NAME = 'API Circle Studio';\n\n/** Canonical desktop origin used in requests (also used by the native HTTP layer). */\nexport const DESKTOP_APP_ORIGIN = 'http://app.studio.apicircle.dev';\n\n/**\n * Generate a random hex span-id (16 hex chars = 64 bits, compatible with\n * W3C Trace Context `traceparent` and OpenTelemetry span-id format).\n */\nexport function generateSpanId(): string {\n const bytes = new Uint8Array(8);\n crypto.getRandomValues(bytes);\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Generate a W3C traceparent header value.\n * Format: 00-<trace-id (32 hex)>-<span-id (16 hex)>-01\n */\nexport function generateTraceParent(): string {\n const traceId = Array.from(crypto.getRandomValues(new Uint8Array(16)))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n const spanId = generateSpanId();\n return `00-${traceId}-${spanId}-01`;\n}\n\n/**\n * Override hooks for tests — let test code feed deterministic values\n * for span-id / traceparent / platform without monkey-patching `crypto`.\n * Production code never passes these.\n */\nexport interface AutoHeaderOverrides {\n spanId?: string;\n traceparent?: string;\n platform?: 'desktop' | 'web';\n version?: string;\n name?: string;\n}\n\n/**\n * Returns the set of auto-fed headers for a single request execution.\n * Call this once per send — `X-Trace-Span-Id` and `traceparent` are\n * re-generated on every invocation.\n *\n * @param userHeaders The headers the user has configured so auto-headers\n * do NOT override anything the user has explicitly set.\n * @param overrides Test-only override hooks; never set in production.\n */\nexport function buildAutoHeaders(\n userHeaders: Record<string, string>,\n overrides: AutoHeaderOverrides = {},\n): Record<string, string> {\n const auto: Record<string, string> = {};\n const userLower = Object.fromEntries(\n Object.keys(userHeaders).map((k) => [k.toLowerCase(), true]),\n );\n\n // ── Platform identity ─────────────────────────────────────────────────────\n if (!userLower['x-client-name']) {\n auto['X-Client-Name'] = overrides.name ?? APP_NAME;\n }\n if (!userLower['x-client-platform']) {\n auto['X-Client-Platform'] = overrides.platform ?? (isDesktop() ? 'desktop' : 'web');\n }\n if (!userLower['x-client-version']) {\n auto['X-Client-Version'] = overrides.version ?? APP_VERSION;\n }\n\n // ── Distributed tracing (auto-generated per send) ─────────────────────────\n // Always generate fresh — never reuse a stored value.\n auto['X-Trace-Span-Id'] = overrides.spanId ?? generateSpanId();\n if (!userLower['traceparent']) {\n auto['traceparent'] = overrides.traceparent ?? generateTraceParent();\n }\n\n // ── Origin / Referer (desktop only — the native HTTP layer also injects\n // these, but we set them here so the request preview shows accurate\n // values) ─────────────────────────────────────────────────────────────\n const platform = overrides.platform ?? (isDesktop() ? 'desktop' : 'web');\n if (platform === 'desktop') {\n if (!userLower['origin']) {\n auto['Origin'] = DESKTOP_APP_ORIGIN;\n }\n if (!userLower['referer']) {\n auto['Referer'] = `${DESKTOP_APP_ORIGIN}/`;\n }\n }\n\n return auto;\n}\n\n/**\n * Merge auto-headers into user headers. User-defined values always win —\n * auto-headers only fill gaps.\n */\nexport function mergeWithAutoHeaders(\n userHeaders: Record<string, string>,\n overrides: AutoHeaderOverrides = {},\n): Record<string, string> {\n return { ...buildAutoHeaders(userHeaders, overrides), ...userHeaders };\n}\n","import type { Request as ApiRequest } from '@apicircle/shared';\nimport { applyAuth, type AuthApplyOptions, type AuthApplyWarning } from './applyAuth';\nimport { mergeWithAutoHeaders, type AutoHeaderOverrides } from './autoHeaders';\n\nexport interface BuiltRequest {\n url: string;\n method: string;\n headers: Record<string, string>;\n body: BodyInit | null;\n /**\n * Non-fatal warnings raised by applyAuth (bad JWT key, malformed\n * payload JSON, etc). executeRequest forwards these into\n * `ExecutionResult.authWarnings` so the UI can surface them alongside\n * the response — without them, a misconfigured JWT silently produces\n * a 401 with no clue why.\n */\n authWarnings: AuthApplyWarning[];\n}\n\n/**\n * Resolves an attachment slotId to a Blob (with filename for form-data).\n * The host reads this from IndexedDB; the CLI reads it from its filesystem\n * cache. A null return means \"not downloaded\" and becomes a hard execution\n * failure.\n */\nexport type AttachmentResolver = (\n slotId: string,\n) => Promise<{ blob: Blob; filename: string } | null>;\n\nfunction missingAttachmentMessage(slotId: string, filename?: string): string {\n const label = filename ? `${filename} (${slotId})` : slotId;\n return (\n `Attachment ${label} is required for this request but is not downloaded locally. ` +\n 'Download the missing attachments before sending or running the plan.'\n );\n}\n\nasync function requireAttachment(\n slotId: string,\n resolveAttachment: AttachmentResolver | undefined,\n filename?: string,\n): Promise<{ blob: Blob; filename: string }> {\n if (!resolveAttachment) {\n throw new Error(missingAttachmentMessage(slotId, filename));\n }\n const file = await resolveAttachment(slotId);\n if (!file) {\n throw new Error(missingAttachmentMessage(slotId, filename));\n }\n return file;\n}\n\n/**\n * Match URL placeholders in either Express-style (`:name`) or OpenAPI-style\n * (`{name}`). Names follow `[A-Za-z_][\\w-]*`. The negative lookbehind/lookahead\n * on `{...}` excludes our `{{var}}` template-variable syntax, which sits\n * between two curlies and would otherwise match incorrectly.\n *\n * We also restrict the scan to the URL's *path portion* (everything before\n * the first `?`) — query values often contain `{{NAME}}` references, and we\n * never want those classified as path params.\n */\nconst PATH_PLACEHOLDER = /(?::([A-Za-z_][\\w-]*)|(?<!\\{)\\{([A-Za-z_][\\w-]*)\\}(?!\\}))/g;\n\nfunction splitOnQuery(rawUrl: string): { path: string; rest: string } {\n const q = rawUrl.indexOf('?');\n if (q < 0) return { path: rawUrl, rest: '' };\n return { path: rawUrl.slice(0, q), rest: rawUrl.slice(q) };\n}\n\n/**\n * Split a typed URL into the base part (everything before `?`) and a\n * structured query-row list. Used by the editor's URL input to keep the\n * URL field and the Query Params sub-tab in sync — when the user types or\n * pastes `?key=val`, the rows surface in the Params list automatically.\n *\n * Variable references like `{{NAME}}` in keys or values are preserved\n * verbatim — they stay templated and resolve at send time. We use\n * permissive splitting (split on `&` then on the first `=`) rather than\n * `URLSearchParams` because URLSearchParams percent-decodes `{{` into `{{`\n * fine but also collapses whitespace and strips empty keys, which fights\n * the user's intent during in-progress typing.\n */\nexport function parseUrlQuery(rawUrl: string): {\n base: string;\n query: Array<{ key: string; value: string; enabled: boolean }>;\n} {\n const q = rawUrl.indexOf('?');\n if (q < 0) return { base: rawUrl, query: [] };\n const base = rawUrl.slice(0, q);\n const queryString = rawUrl.slice(q + 1);\n // Strip a trailing `#fragment` if present — fragments aren't sent over the\n // wire and would otherwise leak into the last query row's value.\n const hashIdx = queryString.indexOf('#');\n const cleaned = hashIdx >= 0 ? queryString.slice(0, hashIdx) : queryString;\n if (cleaned.length === 0) return { base, query: [] };\n const rows = cleaned.split('&').map((segment) => {\n const eq = segment.indexOf('=');\n const key = eq < 0 ? segment : segment.slice(0, eq);\n const value = eq < 0 ? '' : segment.slice(eq + 1);\n return {\n // Decode percent-encoded keys/values but leave `{{var}}` alone — those\n // never get percent-encoded by Postman/curl pastes.\n key: tryDecode(key),\n value: tryDecode(value),\n enabled: true,\n };\n });\n return { base, query: rows };\n}\n\nfunction tryDecode(s: string): string {\n try {\n return decodeURIComponent(s);\n } catch {\n return s;\n }\n}\n\n/**\n * Inverse of `parseUrlQuery`. Renders the structured query rows back into a\n * URL-bar-friendly string, skipping disabled or empty-key rows. Values are\n * left as-is (no double-encoding) — `composeUrl` runs at send time and\n * handles wire encoding properly.\n */\nexport function composeUrlWithQuery(\n base: string,\n query: ReadonlyArray<{ key: string; value: string; enabled: boolean }>,\n): string {\n const enabled = query.filter((q) => q.enabled && q.key.trim().length > 0);\n if (enabled.length === 0) return base;\n const rendered = enabled.map((q) => `${q.key}=${q.value}`).join('&');\n return `${base}?${rendered}`;\n}\n\n/** Extract the placeholder names appearing in a URL, in document order, deduped. */\nexport function findPathPlaceholders(rawUrl: string): string[] {\n const { path } = splitOnQuery(rawUrl);\n const seen = new Set<string>();\n const out: string[] = [];\n PATH_PLACEHOLDER.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = PATH_PLACEHOLDER.exec(path)) !== null) {\n const name = m[1] ?? m[2];\n if (name && !seen.has(name)) {\n seen.add(name);\n out.push(name);\n }\n }\n return out;\n}\n\n/**\n * Substitute `:name` and `{name}` placeholders in a URL's path with the\n * matching values from `pathParams`. The query string passes through\n * untouched — a `{{var}}` in there is a variable reference, not a path\n * placeholder. Missing keys substitute to empty string; the Editor surfaces\n * unbound placeholders as a UI warning, not a runtime error.\n */\nexport function applyPathParams(rawUrl: string, pathParams: Record<string, string>): string {\n const { path, rest } = splitOnQuery(rawUrl);\n PATH_PLACEHOLDER.lastIndex = 0;\n const substituted = path.replace(PATH_PLACEHOLDER, (_full, exprName, braceName) => {\n const name = (exprName ?? braceName) as string;\n const value = pathParams[name];\n return value === undefined ? '' : encodeURIComponent(value);\n });\n return substituted + rest;\n}\n\n// RFC 7230 §3.2.6 \"token\" — valid characters for an HTTP header field-name.\n// Rejecting names outside this set keeps a `{{var}}` resolution that ends up\n// containing `:` or a control char from corrupting the wire format / smuggling\n// a second header line on a future native HTTP layer.\nconst HEADER_TOKEN_RE = /^[A-Za-z0-9!#$%&'*+\\-.^_`|~]+$/;\n\n/** Strip ASCII control characters (CR/LF/NUL/etc.) from a value that's about\n * to be put on an HTTP wire. RFC 7230 forbids CR/LF in header values; CR/LF\n * in a Cookie value also breaks the `; key=value; …` framing. Body content\n * goes through a different code path and is NOT sanitised here — line\n * breaks in a JSON / text body are legitimate. */\nfunction sanitizeWireValue(v: string): string {\n // Strip everything ASCII < 0x20 except HT (0x09 — tab, occasionally legit\n // inside header values per the spec). Strictly speaking even tab in a\n // header value is questionable; we keep it to avoid surprising the user.\n // 0x7F (DEL) is also stripped.\n // eslint-disable-next-line no-control-regex -- intentional: stripping CTLs is the whole point\n return v.replace(/[\\x00-\\x08\\x0A-\\x1F\\x7F]/g, '');\n}\n\n/**\n * Build a `Cookie` header value from a list of name/value pairs. Skips\n * disabled or empty-key rows. Returns the empty string when nothing applies.\n * Per RFC 6265, cookie values may not contain CTL chars or `;` (which is the\n * row separator) — we strip CTLs and also strip `;` from values to keep the\n * row framing intact when a {{var}} resolves to something containing one.\n */\nexport function composeCookieHeader(\n rows: ReadonlyArray<{ key: string; value: string; enabled: boolean }>,\n): string {\n return rows\n .filter((r) => r.enabled && r.key.trim().length > 0)\n .map((r) => {\n // The key has already been trimmed; strip any CTLs and `;` / `=` /\n // whitespace it might have picked up from a variable resolution.\n // eslint-disable-next-line no-control-regex -- intentional: stripping CTLs is the whole point\n const safeKey = r.key.trim().replace(/[\\x00-\\x20;=]/g, '');\n const safeValue = sanitizeWireValue(r.value).replace(/;/g, '');\n return `${safeKey}=${safeValue}`;\n })\n .filter((s) => s.length > 1) // `=` alone after sanitisation is meaningless\n .join('; ');\n}\n\nexport function composeUrl(\n rawUrl: string,\n params: ReadonlyArray<{ key: string; value: string; enabled: boolean }>,\n): string {\n const enabled = params.filter((p) => p.enabled && p.key.trim().length > 0);\n if (enabled.length === 0) return rawUrl;\n\n let parsed: URL | null = null;\n try {\n parsed = new URL(rawUrl);\n } catch {\n parsed = null;\n }\n if (parsed) {\n for (const p of enabled) parsed.searchParams.append(p.key, p.value);\n return parsed.toString();\n }\n\n const query = enabled\n .map((p) => `${encodeURIComponent(p.key)}=${encodeURIComponent(p.value)}`)\n .join('&');\n if (query.length === 0) return rawUrl;\n return rawUrl.includes('?') ? `${rawUrl}&${query}` : `${rawUrl}?${query}`;\n}\n\nexport function composeHeaders(\n rows: ReadonlyArray<{ key: string; value: string; enabled: boolean }>,\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const row of rows) {\n if (!row.enabled) continue;\n const k = row.key.trim();\n if (!k) continue;\n // Reject header names that don't fit RFC 7230's token grammar. A\n // resolved `{{var}}` could otherwise carry `:` / CR/LF / space and\n // smuggle a second header on a future native HTTP layer. Browser\n // fetch already throws on this — defending here gives us deterministic\n // skip-the-row behaviour AND covers any future non-fetch executor.\n if (!HEADER_TOKEN_RE.test(k)) continue;\n out[k] = sanitizeWireValue(row.value);\n }\n return out;\n}\n\n/**\n * Strip Content-Type from a header set. Used for form-data and binary bodies\n * where the browser must set Content-Type itself (multipart boundary, blob's\n * own type) — a manually-set header would corrupt the request.\n */\nfunction stripContentType(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (k.trim().toLowerCase() === 'content-type') continue;\n out[k] = v;\n }\n return out;\n}\n\n/**\n * Serialize a request body for fetch(). Async because form-data and binary\n * may need to read attachment blobs from the host's storage layer.\n */\nexport async function composeBody(\n body: ApiRequest['body'],\n resolveAttachment?: AttachmentResolver,\n): Promise<BodyInit | null> {\n if (body.type === 'none') return null;\n\n if (body.type === 'json' || body.type === 'text' || body.type === 'xml') {\n return body.content;\n }\n\n if (body.type === 'graphql') {\n // Standard GraphQL-over-HTTP envelope: `{ \"query\": string, \"variables\": object|null }`.\n // The variables pane in the editor is plain JSON; if it doesn't parse,\n // we send `null` so the server reports the parse error rather than the\n // request silently failing on our side.\n let variables: unknown = undefined;\n if (body.variables && body.variables.trim().length > 0) {\n try {\n variables = JSON.parse(body.variables);\n } catch {\n variables = null;\n }\n }\n return JSON.stringify({\n query: body.content,\n ...(variables !== undefined ? { variables } : {}),\n });\n }\n\n if (body.type === 'urlencoded') {\n const params = new URLSearchParams();\n for (const line of body.content.split(/\\r?\\n/)) {\n const eq = line.indexOf('=');\n if (eq === -1) continue;\n const key = line.slice(0, eq).trim();\n const value = line.slice(eq + 1);\n if (!key) continue;\n params.append(key, value);\n }\n return params.toString();\n }\n\n if (body.type === 'form-data') {\n const fd = new FormData();\n for (const row of body.formRows ?? []) {\n if (!row.enabled || !row.key.trim()) continue;\n if (row.kind === 'text') {\n fd.append(row.key, row.value);\n } else if (row.slotId) {\n const file = await requireAttachment(row.slotId, resolveAttachment, row.filename);\n fd.append(row.key, file.blob, file.filename);\n }\n }\n return fd;\n }\n\n if (body.type === 'binary') {\n if (body.attachment?.slotId) {\n const file = await requireAttachment(\n body.attachment.slotId,\n resolveAttachment,\n body.attachment.filename,\n );\n return file.blob;\n }\n return null;\n }\n\n return null;\n}\n\nexport interface BuildRequestOptions {\n resolveAttachment?: AttachmentResolver;\n /**\n * applyAuth options — most importantly the `onTokenRefreshed`\n * callback that lets the store persist refreshed OAuth2 tokens.\n * Forwarded as-is.\n */\n authOptions?: AuthApplyOptions;\n /**\n * Test-only override hooks for the auto-fed headers. Lets specs feed\n * deterministic values for `X-Trace-Span-Id`, `traceparent`, and\n * `X-Client-Platform`. Production callers omit this.\n */\n autoHeaderOverrides?: AutoHeaderOverrides;\n}\n\nexport async function buildRequest(\n req: ApiRequest,\n opts: BuildRequestOptions = {},\n): Promise<BuiltRequest> {\n const baseHeaders = composeHeaders(req.headers);\n // Merge cookies into a single Cookie header. A user-set Cookie row in the\n // headers list wins (no override) — that's the natural escape hatch when\n // someone wants full control over the wire format.\n const headers = ((): Record<string, string> => {\n const cookieValue = composeCookieHeader(req.cookies ?? []);\n if (!cookieValue) return baseHeaders;\n const hasUserCookie = Object.keys(baseHeaders).some((k) => k.toLowerCase() === 'cookie');\n return hasUserCookie ? baseHeaders : { ...baseHeaders, Cookie: cookieValue };\n })();\n // GET and HEAD requests cannot carry a body on the fetch transport —\n // the WHATWG `Request` constructor throws `TypeError: Request with\n // GET/HEAD method cannot have body`. If the user configured a body and\n // then switched the method, drop the body silently rather than letting\n // the whole send fail. (Other tools — Postman, curl — behave the same.)\n const methodAllowsBody = req.method !== 'GET' && req.method !== 'HEAD';\n const body = methodAllowsBody ? await composeBody(req.body, opts.resolveAttachment) : null;\n // Strip the Content-Type header when it describes a payload that won't\n // reach the wire:\n // - form-data / binary: fetch must set Content-Type itself (multipart\n // boundary, Blob's own type) — a user-set value would corrupt it;\n // - GET / HEAD carrying a configured body: the body was just dropped\n // above, so its body-type Content-Type now describes nothing.\n // A Content-Type with no body behind it (`body.type === 'none'`) is a\n // plain user-set header — keep it; the browser sends it on GET too.\n const stripBodyContentType =\n req.body.type === 'form-data' ||\n req.body.type === 'binary' ||\n (!methodAllowsBody && req.body.type !== 'none');\n const sanitizedHeaders = stripBodyContentType ? stripContentType(headers) : headers;\n const urlWithPath = applyPathParams(req.url, req.pathParams ?? {});\n const url = composeUrl(urlWithPath, req.query);\n\n // Auth runs last — schemes like AWS SigV4 read the final URL + headers +\n // body to compute their signature. Older synced docs may lack `auth`;\n // workspace store hydration normalises it, but be defensive here too.\n const auth = req.auth ?? { type: 'none' };\n const applied = await applyAuth(\n { url, method: req.method, headers: sanitizedHeaders, body },\n auth,\n opts.authOptions,\n );\n\n return {\n url: applied.url,\n method: req.method,\n headers: mergeWithAutoHeaders(applied.headers, opts.autoHeaderOverrides),\n body,\n authWarnings: applied.warnings ?? [],\n };\n}\n","// Variable substitution for request fields.\n//\n// `{{NAME}}` placeholders are resolved against a layered scope. The default\n// precedence (matches the plan's \"Global priority\" rule) is:\n//\n// 1. contextVars — defined inline on the request itself\n// 2. activeEnv — currently-selected environment's variables\n// 3. priorityEnvs[*] — fallback chain (other environments in user-set\n// order). First match wins.\n//\n// Plan-level overrides (P6) plug in by passing a different priorityEnvs\n// list — execution plans build their own ordered scope and pass it as the\n// outermost wins. The `contextVars` layer is always highest priority.\n//\n// Secrets are surfaced as a fourth layer: a `secrets` map of decrypted\n// values keyed by secret label. The Secret Vault hands these in pre-decrypted\n// for the duration of one send so this layer doesn't need crypto.\n\nexport interface ResolutionScope {\n contextVars: Record<string, string>;\n activeEnv: Record<string, string>;\n priorityEnvs: Array<Record<string, string>>;\n secrets: Record<string, string>;\n}\n\nexport interface ResolveResult {\n value: string;\n /** Names that were referenced but not found in any scope. */\n missing: string[];\n}\n\nconst PLACEHOLDER = /\\{\\{\\s*([A-Za-z_][\\w.-]*)\\s*\\}\\}/g;\n\nexport function lookup(scope: ResolutionScope, name: string): string | undefined {\n if (Object.prototype.hasOwnProperty.call(scope.contextVars, name)) {\n return scope.contextVars[name];\n }\n if (Object.prototype.hasOwnProperty.call(scope.activeEnv, name)) {\n return scope.activeEnv[name];\n }\n for (const env of scope.priorityEnvs) {\n if (Object.prototype.hasOwnProperty.call(env, name)) return env[name];\n }\n if (Object.prototype.hasOwnProperty.call(scope.secrets, name)) {\n return scope.secrets[name];\n }\n return undefined;\n}\n\n/**\n * Replace every `{{NAME}}` in `input` with its resolved value. Unknown names\n * are left as-is in the output (so the user can see which placeholder didn't\n * resolve) and reported via `missing`.\n */\nexport function resolveString(input: string, scope: ResolutionScope): ResolveResult {\n const missing = new Set<string>();\n const value = input.replace(PLACEHOLDER, (match, name: string) => {\n const resolved = lookup(scope, name);\n if (resolved === undefined) {\n missing.add(name);\n return match;\n }\n return resolved;\n });\n return { value, missing: [...missing] };\n}\n\n/**\n * Resolve placeholders in every string value of an object (one level deep).\n * Used for header / param row arrays — both keys and values are resolved.\n * Returns a flat list of all missing names across the inputs.\n */\nexport function resolveStringMap(\n obj: Record<string, string>,\n scope: ResolutionScope,\n): { result: Record<string, string>; missing: string[] } {\n const out: Record<string, string> = {};\n const missing = new Set<string>();\n for (const [key, value] of Object.entries(obj)) {\n const k = resolveString(key, scope);\n const v = resolveString(value, scope);\n out[k.value] = v.value;\n for (const m of k.missing) missing.add(m);\n for (const m of v.missing) missing.add(m);\n }\n return { result: out, missing: [...missing] };\n}\n\n/**\n * Build a ResolutionScope from a Workspace + a per-request context-vars\n * list. Optional plan-level priority overrides take precedence over the\n * workspace's global priority order.\n *\n * `secrets` is passed in already-decrypted because resolveString runs\n * synchronously — decryption happens once before send.\n */\nexport function buildScope(args: {\n contextVars: ReadonlyArray<{ key: string; value: string }>;\n environments: Record<string, Record<string, string>>;\n activeEnvName: string | null;\n priorityOrder: string[];\n secrets?: Record<string, string>;\n}): ResolutionScope {\n const ctx: Record<string, string> = {};\n for (const v of args.contextVars) {\n if (v.key) ctx[v.key] = v.value;\n }\n const activeEnv =\n args.activeEnvName && args.environments[args.activeEnvName]\n ? args.environments[args.activeEnvName]\n : {};\n const priorityEnvs = args.priorityOrder\n .filter((name) => name !== args.activeEnvName)\n .map((name) => args.environments[name] ?? {});\n return {\n contextVars: ctx,\n activeEnv: activeEnv ?? {},\n priorityEnvs,\n secrets: args.secrets ?? {},\n };\n}\n\n// --- Autocomplete ------------------------------------------------------\n\nexport type VariableSource = 'context' | 'active-env' | 'priority-env' | 'secret';\n\nexport interface VariableSuggestion {\n key: string;\n source: VariableSource;\n /** Display-only — secrets always show as the placeholder string. */\n preview: string;\n}\n\nconst SECRET_PREVIEW = '••••';\n\n/**\n * Walk a ResolutionScope in precedence order and produce one suggestion\n * per unique key. Used by the editor's `{{` autocomplete and Monaco's\n * completion provider.\n */\nexport function collectVariableSuggestions(scope: ResolutionScope): VariableSuggestion[] {\n const seen = new Map<string, VariableSuggestion>();\n const push = (key: string, source: VariableSource, preview: string) => {\n if (!seen.has(key)) seen.set(key, { key, source, preview });\n };\n for (const [k, v] of Object.entries(scope.contextVars)) {\n push(k, 'context', v);\n }\n for (const [k, v] of Object.entries(scope.activeEnv)) {\n push(k, 'active-env', v);\n }\n for (const env of scope.priorityEnvs) {\n for (const [k, v] of Object.entries(env)) {\n push(k, 'priority-env', v);\n }\n }\n for (const k of Object.keys(scope.secrets)) {\n push(k, 'secret', SECRET_PREVIEW);\n }\n return [...seen.values()].sort((a, b) => a.key.localeCompare(b.key));\n}\n\n/**\n * Suggestions to show given a cursor position inside a text field. Returns\n * `null` when the cursor isn't inside an open `{{ … }}` token, so callers\n * can hide the popup. When inside a token, returns matches filtered by the\n * partial token text.\n */\nexport function getVariableAutocomplete(\n text: string,\n cursorPosition: number,\n scope: ResolutionScope,\n): VariableSuggestion[] | null {\n const before = text.slice(0, cursorPosition);\n const openIdx = before.lastIndexOf('{{');\n if (openIdx === -1) return null;\n const fragment = before.slice(openIdx + 2);\n // If the user already closed the token, don't suggest anymore.\n if (fragment.includes('}}')) return null;\n const query = fragment.trim().toLowerCase();\n return collectVariableSuggestions(scope).filter((s) =>\n query.length === 0 ? true : s.key.toLowerCase().includes(query),\n );\n}\n","// Pre-send validation. Lints a Request against the resolved variable\n// scope and returns warnings (non-blocking) and blockers (Send is\n// disabled until they're cleared).\n//\n// Rules — keep them simple, fast, and grounded in the actual request shape:\n// 1. Every `{{var}}` reference in URL / headers / query / cookies / body\n// resolves in the active scope. Unresolved → warning.\n// 2. Every path placeholder (`{name}` or `:name`) has a non-empty value\n// in `pathParams`. Empty → warning.\n// 3. If body type ∈ {json, xml, urlencoded, graphql} but the user-set\n// Content-Type doesn't match the body type, warn.\n// 4. If auth.type requires fields (token/key/etc.) and they're blank,\n// block. Without these the request will fail at send-time.\n//\n// Returns warnings + blockers separately so the UI can render them\n// distinctly: warnings are yellow + Send-still-allowed, blockers are\n// red + Send-disabled.\n\nimport type { Request as ApiRequest } from '@apicircle/shared';\nimport { findPathPlaceholders } from './buildRequest';\nimport { resolveString, type ResolutionScope } from '../environment/variableResolver';\n\nexport interface PreSendWarning {\n kind:\n | 'unresolved-variable'\n | 'unbound-path-param'\n | 'content-type-mismatch'\n | 'url-embedded-credentials';\n message: string;\n}\n\nexport interface PreSendBlocker {\n kind: 'auth-fields-missing' | 'unparseable-url' | 'empty-url';\n message: string;\n}\n\nexport interface PreSendValidationResult {\n warnings: PreSendWarning[];\n blockers: PreSendBlocker[];\n}\n\n/** Inputs to the validator — the request + resolution scope. */\nexport interface PreSendValidationInput {\n request: ApiRequest;\n scope: ResolutionScope;\n}\n\nconst TYPED_BODY_CT: Record<string, string[]> = {\n json: ['application/json', 'application/ld+json', 'application/vnd.api+json'],\n xml: ['application/xml', 'text/xml'],\n urlencoded: ['application/x-www-form-urlencoded'],\n graphql: ['application/graphql', 'application/json'],\n};\n\nfunction collectMissing(value: string, scope: ResolutionScope): string[] {\n return resolveString(value, scope).missing;\n}\n\nexport function preSendValidation({\n request,\n scope,\n}: PreSendValidationInput): PreSendValidationResult {\n const warnings: PreSendWarning[] = [];\n const blockers: PreSendBlocker[] = [];\n\n // Rule 0: URL is required. Empty URL is always a blocker — without it\n // there is nothing to send. Unparseable URLs (after variable resolution)\n // are also blockers, since the fetch layer would throw on send.\n const urlTrimmed = request.url.trim();\n if (urlTrimmed === '') {\n blockers.push({ kind: 'empty-url', message: 'URL is required.' });\n } else {\n const { value: resolvedUrl, missing: urlMissing } = resolveString(request.url, scope);\n // Only attempt to parse if the URL has no unresolved {{var}} references —\n // otherwise the warning from Rule 1 is the right signal, not a blocker.\n if (urlMissing.length === 0) {\n try {\n // URL constructor throws on malformed input. Accept relative paths\n // (starting with /) since the runtime may be configured with a base.\n if (!resolvedUrl.startsWith('/')) {\n const parsed = new URL(resolvedUrl);\n // Embedded user:pass@host credentials persist into history and\n // get sent on the wire as Basic auth (Chromium converts the\n // userinfo into an `Authorization` header). Warn the user so\n // they can move the credentials into the Auth tab instead,\n // where they go through the Secret Vault and aren't echoed in\n // history records.\n if (parsed.username || parsed.password) {\n warnings.push({\n kind: 'url-embedded-credentials',\n message:\n 'URL contains embedded user:pass credentials. These are sent as Basic auth ' +\n 'and persisted into request history. Move them to the Auth tab to keep them out of stored runs.',\n });\n }\n }\n } catch {\n blockers.push({\n kind: 'unparseable-url',\n message: `URL \"${resolvedUrl}\" is not a valid URL.`,\n });\n }\n }\n }\n\n // Rule 1: unresolved variables in URL / headers / query / cookies / body.\n const unresolved = new Set<string>();\n for (const name of collectMissing(request.url, scope)) unresolved.add(name);\n for (const row of request.headers ?? []) {\n if (!row.enabled) continue;\n for (const n of collectMissing(row.key, scope)) unresolved.add(n);\n for (const n of collectMissing(row.value, scope)) unresolved.add(n);\n }\n for (const row of request.query ?? []) {\n if (!row.enabled) continue;\n for (const n of collectMissing(row.key, scope)) unresolved.add(n);\n for (const n of collectMissing(row.value, scope)) unresolved.add(n);\n }\n for (const row of request.cookies ?? []) {\n if (!row.enabled) continue;\n for (const n of collectMissing(row.key, scope)) unresolved.add(n);\n for (const n of collectMissing(row.value, scope)) unresolved.add(n);\n }\n if (request.body && 'content' in request.body && typeof request.body.content === 'string') {\n for (const n of collectMissing(request.body.content, scope)) unresolved.add(n);\n }\n for (const name of unresolved) {\n warnings.push({\n kind: 'unresolved-variable',\n message: `Variable \"${name}\" is referenced but not defined in the active scope.`,\n });\n }\n\n // Rule 2: unbound path placeholders.\n const placeholders = findPathPlaceholders(request.url);\n const pathParams = request.pathParams ?? {};\n for (const name of placeholders) {\n const value = pathParams[name];\n if (value === undefined || value.trim() === '') {\n warnings.push({\n kind: 'unbound-path-param',\n message: `Path parameter \"${name}\" is empty; the URL segment will collapse.`,\n });\n }\n }\n\n // Rule 3: Content-Type vs body type alignment (only when user has\n // explicitly set a Content-Type header).\n const userCt = (request.headers ?? [])\n .filter((r) => r.enabled && r.key.trim().toLowerCase() === 'content-type')\n .map((r) => r.value.trim().toLowerCase())[0];\n if (userCt && request.body) {\n const allowed = TYPED_BODY_CT[request.body.type];\n if (allowed && !allowed.some((ct) => userCt.startsWith(ct))) {\n warnings.push({\n kind: 'content-type-mismatch',\n message: `Body type \"${request.body.type}\" but Content-Type is \"${userCt}\". This may cause the server to reject the request.`,\n });\n }\n }\n\n // Rule 4: blank auth fields for types that require them.\n const auth = request.auth;\n if (auth) {\n if (auth.type === 'bearer' && !auth.token?.trim()) {\n blockers.push({ kind: 'auth-fields-missing', message: 'Bearer token is empty.' });\n } else if (auth.type === 'basic') {\n if (!auth.username?.trim() || !auth.password?.trim()) {\n blockers.push({\n kind: 'auth-fields-missing',\n message: 'Basic auth requires both username and password.',\n });\n }\n } else if (auth.type === 'api-key') {\n if (!auth.key?.trim() || !auth.value?.trim()) {\n blockers.push({\n kind: 'auth-fields-missing',\n message: 'API key auth requires both name and value.',\n });\n }\n } else if (auth.type === 'custom-header') {\n if (!auth.key?.trim()) {\n blockers.push({\n kind: 'auth-fields-missing',\n message: 'Custom header auth requires a header name.',\n });\n }\n }\n }\n\n return { warnings, blockers };\n}\n","/**\n * SHA-512/256 — FIPS 180-4 §6.7. Required by HTTP Digest auth (RFC 7616\n * §3.5.1) which mandates the FIPS 180-4 truncation variant, NOT a naive\n * truncation of SHA-512. The two differ because SHA-512/256 uses\n * different initial hash values (IVs); the round function is identical\n * to SHA-512.\n *\n * WebCrypto exposes SHA-512 but not SHA-512/256, and there's no API to\n * supply custom IVs, so we implement the full compression function\n * inline. Ported from the FIPS 180-4 specification, validated against\n * the canonical NIST test vectors:\n *\n * SHA-512/256(\"abc\") = 53048e2681941ef99b2e29b76b4c7dde\n * 9f2492c4d6311e9cc4571d9f0fe8b22a\n *\n * Internal module — not exported from the package barrel. Imported by\n * `digest.ts` for `algorithm=SHA-512-256` Digest challenges. Performance\n * is not critical here (Digest auth is rare and inputs are tiny), so we\n * use BigInt arithmetic for clarity over a hand-rolled 64-bit emulation.\n */\n\nconst MASK64 = 0xffffffffffffffffn;\n\n/** SHA-512/256 IVs per FIPS 180-4 §5.3.6.2 (different from SHA-512's). */\nconst IV: ReadonlyArray<bigint> = [\n 0x22312194fc2bf72cn,\n 0x9f555fa3c84c64c2n,\n 0x2393b86b6f53b151n,\n 0x963877195940eabdn,\n 0x96283ee2a88effe3n,\n 0xbe5e1e2553863992n,\n 0x2b0199fc2c85b8aan,\n 0x0eb72ddc81c52ca2n,\n];\n\n/** SHA-512 / SHA-512/256 share the same 80 round constants (FIPS 180-4 §4.2.3). */\nconst K: ReadonlyArray<bigint> = [\n 0x428a2f98d728ae22n,\n 0x7137449123ef65cdn,\n 0xb5c0fbcfec4d3b2fn,\n 0xe9b5dba58189dbbcn,\n 0x3956c25bf348b538n,\n 0x59f111f1b605d019n,\n 0x923f82a4af194f9bn,\n 0xab1c5ed5da6d8118n,\n 0xd807aa98a3030242n,\n 0x12835b0145706fben,\n 0x243185be4ee4b28cn,\n 0x550c7dc3d5ffb4e2n,\n 0x72be5d74f27b896fn,\n 0x80deb1fe3b1696b1n,\n 0x9bdc06a725c71235n,\n 0xc19bf174cf692694n,\n 0xe49b69c19ef14ad2n,\n 0xefbe4786384f25e3n,\n 0x0fc19dc68b8cd5b5n,\n 0x240ca1cc77ac9c65n,\n 0x2de92c6f592b0275n,\n 0x4a7484aa6ea6e483n,\n 0x5cb0a9dcbd41fbd4n,\n 0x76f988da831153b5n,\n 0x983e5152ee66dfabn,\n 0xa831c66d2db43210n,\n 0xb00327c898fb213fn,\n 0xbf597fc7beef0ee4n,\n 0xc6e00bf33da88fc2n,\n 0xd5a79147930aa725n,\n 0x06ca6351e003826fn,\n 0x142929670a0e6e70n,\n 0x27b70a8546d22ffcn,\n 0x2e1b21385c26c926n,\n 0x4d2c6dfc5ac42aedn,\n 0x53380d139d95b3dfn,\n 0x650a73548baf63den,\n 0x766a0abb3c77b2a8n,\n 0x81c2c92e47edaee6n,\n 0x92722c851482353bn,\n 0xa2bfe8a14cf10364n,\n 0xa81a664bbc423001n,\n 0xc24b8b70d0f89791n,\n 0xc76c51a30654be30n,\n 0xd192e819d6ef5218n,\n 0xd69906245565a910n,\n 0xf40e35855771202an,\n 0x106aa07032bbd1b8n,\n 0x19a4c116b8d2d0c8n,\n 0x1e376c085141ab53n,\n 0x2748774cdf8eeb99n,\n 0x34b0bcb5e19b48a8n,\n 0x391c0cb3c5c95a63n,\n 0x4ed8aa4ae3418acbn,\n 0x5b9cca4f7763e373n,\n 0x682e6ff3d6b2b8a3n,\n 0x748f82ee5defb2fcn,\n 0x78a5636f43172f60n,\n 0x84c87814a1f0ab72n,\n 0x8cc702081a6439ecn,\n 0x90befffa23631e28n,\n 0xa4506cebde82bde9n,\n 0xbef9a3f7b2c67915n,\n 0xc67178f2e372532bn,\n 0xca273eceea26619cn,\n 0xd186b8c721c0c207n,\n 0xeada7dd6cde0eb1en,\n 0xf57d4f7fee6ed178n,\n 0x06f067aa72176fban,\n 0x0a637dc5a2c898a6n,\n 0x113f9804bef90daen,\n 0x1b710b35131c471bn,\n 0x28db77f523047d84n,\n 0x32caab7b40c72493n,\n 0x3c9ebe0a15c9bebcn,\n 0x431d67c49c100d4cn,\n 0x4cc5d4becb3e42b6n,\n 0x597f299cfc657e2an,\n 0x5fcb6fab3ad6faecn,\n 0x6c44198c4a475817n,\n];\n\nfunction ror64(x: bigint, n: bigint): bigint {\n return ((x >> n) | (x << (64n - n))) & MASK64;\n}\n\nfunction shr64(x: bigint, n: bigint): bigint {\n return (x >> n) & MASK64;\n}\n\n/**\n * Compute the SHA-512/256 digest of `bytes` and return it as a 64-char\n * lowercase hex string. Public surface — `digest.ts` calls this for\n * `algorithm=SHA-512-256` HA1/HA2 hashing.\n */\nexport function sha512_256(bytes: Uint8Array): string {\n // Padding (FIPS 180-4 §5.1.2): append 0x80, zero-pad to 128|112 bytes,\n // then a 128-bit big-endian length. We never approach 2^64 input bytes\n // in practice, so the high 64 bits of the length are always zero.\n const msgLen = bytes.length;\n const bitLen = BigInt(msgLen) * 8n;\n // After the 0x80 byte we want the total length to be ≡ 112 (mod 128)\n // so the appended 16-byte length field puts the message at a multiple\n // of 128 bytes (one 1024-bit block).\n let padBytes = 112 - ((msgLen + 1) % 128);\n if (padBytes < 0) padBytes += 128;\n const padded = new Uint8Array(msgLen + 1 + padBytes + 16);\n padded.set(bytes);\n padded[msgLen] = 0x80;\n // High 64 bits of length: zero. Low 64 bits: bitLen, big-endian.\n for (let i = 0; i < 8; i++) {\n padded[padded.length - 1 - i] = Number((bitLen >> BigInt(i * 8)) & 0xffn);\n }\n\n let h: bigint[] = [...IV];\n\n // Process each 1024-bit (128-byte) block. `W` is the message schedule;\n // 80 BigInt words filled in below before any read.\n const W: bigint[] = new Array<bigint>(80);\n for (let block = 0; block < padded.length; block += 128) {\n // Initial 16 message-schedule words are big-endian 64-bit slices.\n for (let t = 0; t < 16; t++) {\n let w = 0n;\n for (let j = 0; j < 8; j++) {\n w = (w << 8n) | BigInt(padded[block + t * 8 + j]);\n }\n W[t] = w;\n }\n // Extend to 80 words via the message-schedule recurrence.\n for (let t = 16; t < 80; t++) {\n const wm15 = W[t - 15];\n const wm2 = W[t - 2];\n const s0 = ror64(wm15, 1n) ^ ror64(wm15, 8n) ^ shr64(wm15, 7n);\n const s1 = ror64(wm2, 19n) ^ ror64(wm2, 61n) ^ shr64(wm2, 6n);\n W[t] = (W[t - 16] + s0 + W[t - 7] + s1) & MASK64;\n }\n\n let a = h[0];\n let b = h[1];\n let c = h[2];\n let d = h[3];\n let e = h[4];\n let f = h[5];\n let g = h[6];\n let hh = h[7];\n\n for (let t = 0; t < 80; t++) {\n const S1 = ror64(e, 14n) ^ ror64(e, 18n) ^ ror64(e, 41n);\n const ch = (e & f) ^ (~e & MASK64 & g);\n const T1 = (hh + S1 + ch + K[t] + W[t]) & MASK64;\n const S0 = ror64(a, 28n) ^ ror64(a, 34n) ^ ror64(a, 39n);\n const maj = (a & b) ^ (a & c) ^ (b & c);\n const T2 = (S0 + maj) & MASK64;\n hh = g;\n g = f;\n f = e;\n e = (d + T1) & MASK64;\n d = c;\n c = b;\n b = a;\n a = (T1 + T2) & MASK64;\n }\n\n h = [\n (h[0] + a) & MASK64,\n (h[1] + b) & MASK64,\n (h[2] + c) & MASK64,\n (h[3] + d) & MASK64,\n (h[4] + e) & MASK64,\n (h[5] + f) & MASK64,\n (h[6] + g) & MASK64,\n (h[7] + hh) & MASK64,\n ];\n }\n\n // SHA-512/256 output: first 256 bits = first 4 H values, big-endian hex.\n let out = '';\n for (let i = 0; i < 4; i++) out += h[i].toString(16).padStart(16, '0');\n return out;\n}\n","import { md5 } from './_legacyHashes';\nimport { sha512_256 } from './_sha512_256';\n\n/**\n * HTTP Digest Access Authentication (RFC 7616, supersedes RFC 2617).\n *\n * Digest is a challenge-response scheme: the client makes a request, the\n * server responds 401 with `WWW-Authenticate: Digest ...`, and the client\n * retries with `Authorization: Digest ...` carrying a hash of the\n * credentials + the server-supplied nonce. This module owns the parsing\n * of the challenge directives and the construction of the response\n * header. The challenge round-trip itself lives in `executeRequest` —\n * it's the engine's job to fire the first request, see the 401, call\n * back here, and re-send.\n *\n * Algorithm support: MD5 (default), MD5-sess, SHA-256, SHA-256-sess,\n * SHA-512-256, and the `-sess` variants. MD5 is required for interop\n * with the long tail of legacy servers; the implementation is in the\n * private `_legacyHashes` module so the rest of the codebase doesn't\n * grow new MD5 callsites.\n */\n\nexport interface DigestChallenge {\n realm: string;\n nonce: string;\n /** Comma-separated list per RFC 7616; the first one we recognize wins. */\n qop?: string;\n opaque?: string;\n algorithm?: string;\n /** Server-supplied opaque token returned verbatim in the response. */\n domain?: string;\n /** Stale=true means the previous nonce expired but credentials are still valid. */\n stale?: string;\n /** Any directives we don't model end up here for diagnostics. */\n [extra: string]: string | undefined;\n}\n\n/**\n * Parse the value of a `WWW-Authenticate: Digest ...` header into its\n * directives. The header may appear with or without the `Digest ` prefix\n * (callers sometimes strip it); both forms work.\n *\n * Quoted values have the surrounding quotes removed; unquoted values are\n * taken as-is up to the next comma or whitespace. Unknown directives are\n * preserved on the returned object so diagnostics can surface them.\n */\nexport function parseDigestChallenge(header: string): DigestChallenge {\n const stripped = header.replace(/^\\s*Digest\\s+/i, '');\n const params: Record<string, string> = {};\n const re = /(\\w+)\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|([^\\s,]+))/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(stripped)) !== null) {\n const key = m[1].toLowerCase();\n const value = m[2] !== undefined ? m[2].replace(/\\\\(.)/g, '$1') : (m[3] ?? '');\n params[key] = value;\n }\n return {\n realm: params['realm'] ?? '',\n nonce: params['nonce'] ?? '',\n qop: params['qop'],\n opaque: params['opaque'],\n algorithm: params['algorithm'],\n domain: params['domain'],\n stale: params['stale'],\n ...params,\n };\n}\n\n/**\n * Algorithm preference order for multi-challenge servers (RFC 7616 §3.7\n * + RFC 7235 §4.1). When a server offers more than one `WWW-Authenticate:\n * Digest` header, the client SHOULD pick the strongest. We rank\n * SHA-512-256 highest (256-bit truncated SHA-512), then SHA-256, then\n * MD5 last — MD5 is GPU-crackable for weak passwords against a captured\n * nonce so we only fall back to it when the server offers nothing else.\n *\n * The `-sess` variants are equivalent in strength to their base; we\n * preserve the server's choice within an algorithm family.\n */\nconst ALGO_RANK: Record<string, number> = {\n 'sha-512-256': 3,\n 'sha-512-256-sess': 3,\n 'sha-256': 2,\n 'sha-256-sess': 2,\n md5: 1,\n 'md5-sess': 1,\n};\n\n/**\n * Pick the strongest Digest challenge from a stacked-header response.\n *\n * `wwwAuthHeaders` is the raw value of every `WWW-Authenticate` header the\n * server sent. The `fetch` API folds multiple headers of the same name\n * into a comma-joined string, but `Digest` challenges themselves contain\n * commas (in `qop=auth,auth-int` etc.), so we can't naively split on\n * comma. Instead we look for the literal token `Digest ` at the start of\n * the trimmed string AND inside the string preceded by `, ` (no other\n * authentication scheme uses that prefix). Each split candidate is\n * parsed; we keep the one with the highest algorithm rank.\n *\n * Falls back to a single parse when only one Digest challenge is found,\n * matching the existing single-challenge behaviour byte-for-byte.\n */\nexport function selectStrongestDigestChallenge(wwwAuthHeader: string): DigestChallenge | null {\n const stripped = wwwAuthHeader.trim();\n if (!stripped) return null;\n // Split on `, Digest ` boundaries — preserves the first challenge as-is\n // and slices subsequent ones. Adding `Digest ` back to each piece so\n // `parseDigestChallenge` can strip the prefix uniformly.\n const pieces = stripped\n .split(/,\\s*(?=Digest\\s)/i)\n .map((p) => p.trim())\n .filter(Boolean);\n if (pieces.length === 0) return null;\n let best: DigestChallenge | null = null;\n let bestRank = -1;\n for (const piece of pieces) {\n const challenge = parseDigestChallenge(piece);\n if (!challenge.realm || !challenge.nonce) continue;\n const algoRaw = (challenge.algorithm ?? 'MD5').toLowerCase();\n const rank = ALGO_RANK[algoRaw] ?? 0;\n if (rank > bestRank) {\n best = challenge;\n bestRank = rank;\n }\n }\n return best;\n}\n\nexport interface BuildDigestArgs {\n method: string;\n /** Request URI as it appears on the wire (path + query, not the full URL). */\n uri: string;\n username: string;\n password: string;\n challenge: DigestChallenge;\n /**\n * Override for the client nonce. If omitted, 16 random hex chars are\n * generated via `crypto.getRandomValues`. Tests pass a fixed value to\n * make the resulting header deterministic.\n */\n cnonce?: string;\n /**\n * Nonce-count, per RFC 7616 §3.4. Each request reusing the same server\n * nonce should bump nc; we default to 1 because the engine clears the\n * stored challenge when the server rotates the nonce. 8 hex chars,\n * lowercase.\n */\n nc?: string;\n /**\n * Body for `qop=auth-int` (entity-body hash). Ignored for `qop=auth`.\n * Strings, `Uint8Array`, `ArrayBuffer`, and `Blob` are all hashable;\n * if `null`/`undefined` we still emit auth-int but with the empty-body\n * hash. FormData / ReadableStream callers should serialize first\n * (auth-int requires the EXACT bytes the server will see).\n */\n entityBody?: string | Uint8Array | ArrayBuffer | Blob | null;\n}\n\nconst SUPPORTED_ALGOS = new Set([\n 'md5',\n 'md5-sess',\n 'sha-256',\n 'sha-256-sess',\n 'sha-512-256',\n 'sha-512-256-sess',\n]);\n\n/**\n * Build the `Authorization: Digest ...` header value (without the\n * `Authorization:` prefix — caller prepends it).\n *\n * Returns a string ready to put on the wire. Throws when the challenge\n * specifies an algorithm we don't support; the engine should surface\n * that as a \"this server's auth scheme isn't supported yet\" error\n * rather than retrying forever.\n */\nexport async function buildDigestAuthHeader(args: BuildDigestArgs): Promise<string> {\n const { method, uri, username, password, challenge } = args;\n const algorithmRaw = (challenge.algorithm ?? 'MD5').toLowerCase();\n if (!SUPPORTED_ALGOS.has(algorithmRaw)) {\n throw new Error(`Digest algorithm not supported: ${challenge.algorithm}`);\n }\n // Phase 11 hardening: surface a console warning whenever the server\n // selects MD5 (or MD5-sess). MD5 is the spec default but is GPU-\n // crackable for weak passwords — a MITM that swaps nonces effectively\n // gets a free password-cracking oracle. We can't refuse the server's\n // choice (that would break interop with the long tail of legacy\n // appliances that only speak MD5), but we MUST make sure the operator\n // knows what's happening. A future Auth follow-up wires this through\n // the structured `authWarnings` channel and surfaces a UI banner; for\n // now the dev-console message is the visibility floor.\n if (algorithmRaw === 'md5' || algorithmRaw === 'md5-sess') {\n console.warn(\n '[apicircle] Digest auth: server selected MD5 — credentials are vulnerable to ' +\n 'GPU offline cracking against the captured nonce. Ask the server operator to ' +\n 'offer SHA-256 (RFC 7616) or SHA-512-256.',\n );\n }\n const isSess = algorithmRaw.endsWith('-sess');\n const baseAlgo = algorithmRaw.replace(/-sess$/, '');\n\n const qop = pickQop(challenge.qop);\n const cnonce = args.cnonce ?? randomHex(8);\n const nc = (args.nc ?? '00000001').toLowerCase();\n\n const hash = (s: string) => digestHash(baseAlgo, s);\n\n // HA1: identity hash. `-sess` variants re-hash with the nonces so that\n // the long-term password isn't reused across sessions.\n let ha1 = await hash(`${username}:${challenge.realm}:${password}`);\n if (isSess) ha1 = await hash(`${ha1}:${challenge.nonce}:${cnonce}`);\n\n // HA2: method + URI (+ entity-body hash for auth-int).\n let ha2: string;\n if (qop === 'auth-int') {\n const bodyBytes = await coerceEntityBody(args.entityBody);\n const bodyHash = await hashBytes(baseAlgo, bodyBytes);\n ha2 = await hash(`${method}:${uri}:${bodyHash}`);\n } else {\n ha2 = await hash(`${method}:${uri}`);\n }\n\n const response = qop\n ? await hash(`${ha1}:${challenge.nonce}:${nc}:${cnonce}:${qop}:${ha2}`)\n : await hash(`${ha1}:${challenge.nonce}:${ha2}`);\n\n const parts: string[] = [\n `username=\"${escapeQuotedString(username)}\"`,\n `realm=\"${escapeQuotedString(challenge.realm)}\"`,\n `nonce=\"${escapeQuotedString(challenge.nonce)}\"`,\n `uri=\"${escapeQuotedString(uri)}\"`,\n `response=\"${response}\"`,\n ];\n if (challenge.algorithm) parts.push(`algorithm=${challenge.algorithm}`);\n if (qop) parts.push(`qop=${qop}`, `nc=${nc}`, `cnonce=\"${escapeQuotedString(cnonce)}\"`);\n if (challenge.opaque) parts.push(`opaque=\"${escapeQuotedString(challenge.opaque)}\"`);\n return `Digest ${parts.join(', ')}`;\n}\n\nfunction pickQop(qopHeader: string | undefined): 'auth' | 'auth-int' | '' {\n if (!qopHeader) return '';\n const options = qopHeader.split(',').map((s) => s.trim().toLowerCase());\n // Prefer auth over auth-int because auth-int requires hashing the\n // request body which most clients don't do; servers that support both\n // accept either.\n if (options.includes('auth')) return 'auth';\n if (options.includes('auth-int')) return 'auth-int';\n return '';\n}\n\nasync function digestHash(baseAlgo: string, input: string): Promise<string> {\n if (baseAlgo === 'md5') return md5(input);\n return hashBytes(baseAlgo, new TextEncoder().encode(input));\n}\n\nasync function hashBytes(baseAlgo: string, bytes: Uint8Array): Promise<string> {\n if (baseAlgo === 'md5') {\n // MD5 over raw bytes — feed the bytes as a Latin-1 string so md5()'s\n // string-mode walks each byte as a code point. This matches the\n // standard interpretation: MD5 is byte-oriented; UTF-8 string input\n // is just bytes that happen to be UTF-8.\n let s = '';\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);\n return md5(s);\n }\n if (baseAlgo === 'sha-512-256') {\n // FIPS 180-4 SHA-512/256 — distinct from a naive truncation of\n // SHA-512 because it uses different IVs. RFC 7616 §3.5.1 mandates\n // this exact variant for `algorithm=SHA-512-256` Digest challenges.\n return sha512_256(bytes);\n }\n // SHA-256 (RFC 7616 §3.5.1) — WebCrypto handles this natively.\n const buf = bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength,\n ) as ArrayBuffer;\n const hash = await crypto.subtle.digest('SHA-256', buf);\n const out = new Uint8Array(hash);\n return Array.from(out, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nasync function coerceEntityBody(\n body: string | Uint8Array | ArrayBuffer | Blob | null | undefined,\n): Promise<Uint8Array> {\n if (body == null) return new Uint8Array(0);\n if (typeof body === 'string') return new TextEncoder().encode(body);\n if (body instanceof Uint8Array) return body;\n if (body instanceof ArrayBuffer) return new Uint8Array(body);\n if (typeof Blob !== 'undefined' && body instanceof Blob) {\n return new Uint8Array(await body.arrayBuffer());\n }\n // Unknown body shape — refuse rather than silently hashing\n // `[object Object]`. The typed contract above is exhaustive, so reaching\n // here means the caller passed something the type system didn't catch\n // (FormData, ReadableStream, …). Auth-int requires the EXACT bytes the\n // server will see, so a wrong hash here is worse than a clear error.\n throw new Error(\n `Digest auth-int: unsupported entity-body type ${typeof body === 'object' && body !== null ? body.constructor.name : typeof body}; serialize to string/Uint8Array/ArrayBuffer/Blob first`,\n );\n}\n\nfunction randomHex(byteLen: number): string {\n const buf = new Uint8Array(byteLen);\n crypto.getRandomValues(buf);\n return Array.from(buf, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\n/** Escape backslashes and double-quotes for RFC 7616 quoted-string values. */\nfunction escapeQuotedString(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n","import type { Request as ApiRequest } from '@apicircle/shared';\nimport { buildRequest, type AttachmentResolver } from './buildRequest';\nimport type { AutoHeaderOverrides } from './autoHeaders';\nimport { type AuthApplyOptions, type AuthApplyWarning } from './applyAuth';\nimport {\n buildDigestAuthHeader,\n parseDigestChallenge,\n selectStrongestDigestChallenge,\n} from '../auth/digest';\nimport {\n buildNtlmType3Authenticate,\n decodeNtlmBase64,\n parseNtlmType2Challenge,\n} from '../auth/ntlm';\n\nexport interface ExecutionResult {\n startedAt: string;\n durationMs: number;\n status: number | null; // null when the request never completed (network error)\n ok: boolean;\n statusText: string;\n headers: Record<string, string>;\n body: string;\n bodyKind: 'json' | 'text' | 'binary' | 'empty';\n error?: string;\n url: string;\n method: string;\n /**\n * Non-fatal warnings from applyAuth (e.g. malformed JWT key, bad\n * payload JSON). Empty array when auth applied cleanly. UI surfaces\n * these alongside the response so users can see WHY their request\n * went out unauthenticated.\n */\n authWarnings: AuthApplyWarning[];\n /**\n * True when the response body exceeded `MAX_RESPONSE_BODY_BYTES` and we\n * stopped reading. The `body` field still contains the prefix we did\n * read — callers should render a \"Response truncated at X MB\" badge.\n * Omitted when the body was read in full.\n */\n responseTruncated?: boolean;\n}\n\nexport interface ExecuteOptions {\n fetchImpl?: typeof fetch;\n // Hard timeout in ms. Defaults to 30s; null disables.\n timeoutMs?: number | null;\n signal?: AbortSignal;\n // Resolver for form-data file rows and binary bodies. When a request\n // references a file slot and the resolver is missing or returns null, the\n // send fails loudly instead of silently omitting the file.\n resolveAttachment?: AttachmentResolver;\n /**\n * applyAuth options — `onTokenRefreshed` is the important one for\n * production: the store wires it to persist refreshed OAuth2 tokens\n * back into `RequestAuth` so subsequent sends see the new state.\n */\n authOptions?: AuthApplyOptions;\n /**\n * Test-only override hooks for the auto-fed headers. Lets specs feed\n * deterministic values for `X-Trace-Span-Id`, `traceparent`, etc.\n * Production callers omit this.\n */\n autoHeaderOverrides?: AutoHeaderOverrides;\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Hard cap on the response body we'll buffer. An attacker-controlled server\n * can stream gigabytes with chunked transfer-encoding; we abort the read\n * once we cross this threshold and surface the truncation in the result. */\nconst MAX_RESPONSE_BODY_BYTES = 50 * 1024 * 1024;\n\n/** Max redirects we'll follow before giving up. RFC 7231 §6.4 doesn't\n * mandate a number; 10 matches what curl uses by default. */\nconst MAX_REDIRECTS = 10;\n\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\n/** Headers we strip on every cross-origin redirect — they carry credentials\n * that the new origin must not see. */\nconst CROSS_ORIGIN_STRIP_HEADERS = new Set([\n 'authorization',\n 'cookie',\n 'proxy-authorization',\n 'x-api-key',\n 'x-auth-token',\n]);\n\nfunction sameOrigin(a: string, b: string): boolean {\n try {\n const ua = new URL(a);\n const ub = new URL(b);\n return ua.protocol === ub.protocol && ua.host === ub.host;\n } catch {\n return false;\n }\n}\n\nfunction stripCrossOriginHeaders(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (CROSS_ORIGIN_STRIP_HEADERS.has(k.toLowerCase())) continue;\n out[k] = v;\n }\n return out;\n}\n\n/** Resolve a (possibly relative) Location-header value against the request\n * URL. The fetch spec uses the URL of the response that produced the\n * redirect; we honour that by passing the current `from`. */\nfunction resolveLocation(from: string, location: string): string | null {\n try {\n return new URL(location, from).toString();\n } catch {\n return null;\n }\n}\n\n/** True when running inside a browser-style fetch implementation, where\n * `redirect: 'manual'` yields an opaqueredirect response that we can't\n * read headers/status from. Node's undici exposes those fields fully so\n * the manual redirect loop can drive the chain itself. */\nfunction isBrowserRuntime(): boolean {\n return typeof window !== 'undefined' && typeof window.document !== 'undefined';\n}\n\n/**\n * Execute a request through the browser's fetch (or an injected impl for\n * tests). Returns a flat ExecutionResult — never throws for HTTP errors.\n * Network failures and timeouts are captured into result.error with status=null.\n *\n * Challenge-driven auth (Digest, NTLM) is handled here: when the first\n * fetch returns 401 with a recognized `WWW-Authenticate` scheme, we\n * compute the response header and re-fetch once. NTLM further requires a\n * second retry to send the Type-3 Authenticate after the Type-2\n * Challenge — that's transparent to the caller, the returned result\n * reflects the FINAL response.\n */\nexport async function executeRequest(\n req: ApiRequest,\n opts: ExecuteOptions = {},\n): Promise<ExecutionResult> {\n const fetchImpl = opts.fetchImpl ?? globalThis.fetch;\n const timeoutMs = opts.timeoutMs === undefined ? DEFAULT_TIMEOUT_MS : opts.timeoutMs;\n\n const startedAt = new Date().toISOString();\n const t0 =\n typeof performance !== 'undefined' && typeof performance.now === 'function'\n ? performance.now()\n : Date.now();\n\n let built: Awaited<ReturnType<typeof buildRequest>> | null = null;\n const controller = new AbortController();\n const externalAbort = () => controller.abort(opts.signal!.reason);\n if (opts.signal) {\n if (opts.signal.aborted) controller.abort(opts.signal.reason);\n else opts.signal.addEventListener('abort', externalAbort, { once: true });\n }\n let timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n\n try {\n built = await buildRequest(req, {\n resolveAttachment: opts.resolveAttachment,\n authOptions: opts.authOptions,\n autoHeaderOverrides: opts.autoHeaderOverrides,\n });\n const builtRequest = built;\n timeoutHandle =\n timeoutMs === null\n ? null\n : setTimeout(\n () => controller.abort(new Error(`Request timed out after ${timeoutMs}ms`)),\n timeoutMs,\n );\n // Redirect handling has to fork by runtime:\n //\n // - In Node fetch the spec's default `redirect: 'follow'` preserves\n // `Authorization` / `Cookie` headers across cross-origin redirects,\n // so a `302 Location: https://attacker/` from a legitimate host\n // would exfiltrate the bearer/basic credential. We pass\n // `redirect: 'manual'`, walk the chain ourselves, and strip\n // credential headers at each cross-origin hop.\n //\n // - Browser fetch returns an opaqueredirect response when given\n // `redirect: 'manual'` (type === 'opaqueredirect', status === 0,\n // headers unreadable), so the same code path stalls before the\n // first hop. Browsers already strip `Authorization` across\n // cross-origin redirects per the Fetch spec §4.4 step 13, so we\n // delegate to the platform with `redirect: 'follow'` instead of\n // trying to drive the chain ourselves.\n const redirectMode: RequestRedirect = isBrowserRuntime() ? 'follow' : 'manual';\n let currentUrl = builtRequest.url;\n let currentHeaders: Record<string, string> = { ...builtRequest.headers };\n let currentMethod = builtRequest.method;\n let currentBody: BodyInit | null = builtRequest.body;\n let response = await fetchImpl(currentUrl, {\n method: currentMethod,\n headers: currentHeaders,\n body: currentBody,\n signal: controller.signal,\n redirect: redirectMode,\n });\n let redirectCount = 0;\n while (REDIRECT_STATUSES.has(response.status) && redirectCount < MAX_REDIRECTS) {\n const location = response.headers.get('location');\n if (!location) break;\n const nextUrl = resolveLocation(currentUrl, location);\n if (!nextUrl) break;\n // 303 always converts to GET with no body. 301/302 also convert\n // non-GET to GET for most browsers (legacy compat). 307/308 preserve\n // method + body.\n const preserveMethod = response.status === 307 || response.status === 308;\n const nextMethod = preserveMethod ? currentMethod : currentMethod === 'HEAD' ? 'HEAD' : 'GET';\n const nextBody = preserveMethod ? currentBody : null;\n const isCrossOrigin = !sameOrigin(currentUrl, nextUrl);\n const nextHeaders = isCrossOrigin\n ? stripCrossOriginHeaders(currentHeaders)\n : { ...currentHeaders };\n // Drain the previous response body so the underlying socket isn't\n // left holding bytes.\n try {\n await response.text();\n } catch {\n /* ignore */\n }\n currentUrl = nextUrl;\n currentHeaders = nextHeaders;\n currentMethod = nextMethod;\n currentBody = nextBody;\n response = await fetchImpl(currentUrl, {\n method: currentMethod,\n headers: currentHeaders,\n body: currentBody,\n signal: controller.signal,\n redirect: redirectMode,\n });\n redirectCount++;\n }\n if (REDIRECT_STATUSES.has(response.status)) {\n // Hit the cap — surface as an error rather than silently returning\n // the redirect response (which the caller wouldn't know what to do\n // with).\n throw new Error(`Too many redirects (>${MAX_REDIRECTS})`);\n }\n\n // Auth-challenge retry loop. Acts only on 401 with a matching\n // scheme. We allow up to 2 retries:\n // - 1st: standard challenge response (Digest or NTLM Type-3).\n // - 2nd: only fires when Digest server replies `stale=true` with\n // a fresh nonce. RFC 7616 §3.4 requires the client to retry\n // with the new nonce + bumped nc. Anything beyond that is a\n // real auth failure we surface as-is.\n const challengeAuth = req.auth;\n let retryCount = 0;\n let nc = '00000001';\n while (\n response.status === 401 &&\n challengeAuth &&\n (challengeAuth.type === 'digest' || challengeAuth.type === 'ntlm') &&\n retryCount < 2\n ) {\n const wwwAuth = response.headers.get('www-authenticate');\n if (!wwwAuth) break;\n\n // Stop after first retry unless the server explicitly says stale=true.\n // Use the strongest-challenge selector so a multi-algo server's stale\n // signal on the SHA-256 challenge isn't missed because we happened\n // to grab the MD5 one first.\n if (retryCount === 1) {\n const challenge = selectStrongestDigestChallenge(wwwAuth) ?? parseDigestChallenge(wwwAuth);\n if (!/^true$/i.test(challenge.stale ?? '')) break;\n nc = bumpNc(nc);\n }\n\n const retried = await runChallengeRetry({\n fetchImpl,\n builtUrl: currentUrl,\n builtMethod: currentMethod,\n builtHeaders: currentHeaders,\n builtBody: currentBody,\n signal: controller.signal,\n wwwAuth,\n auth: challengeAuth,\n previousResponse: response,\n nc,\n });\n if (!retried) break;\n\n // Drain the previous response body so the underlying connection\n // isn't left holding bytes. Failure here is benign in a test\n // setting (mocked Response) and rare in real fetch — swallow\n // silently rather than emitting console output from a library.\n try {\n await response.text();\n } catch {\n /* ignore — drain failure shouldn't block the retry */\n }\n response = retried;\n retryCount++;\n }\n\n const headers: Record<string, string> = {};\n response.headers.forEach((v, k) => {\n headers[k] = v;\n });\n const contentType = headers['content-type'] ?? '';\n // Stream the body via a reader so we can abort the read once we cross\n // `MAX_RESPONSE_BODY_BYTES`. The previous `await response.text()` would\n // happily buffer a gigabyte attacker-controlled stream into a single\n // string and OOM the renderer. We still build a string (the existing\n // ExecutionResult contract expects one) but cap how much we accept.\n const { text, truncated } = await readResponseCapped(response);\n const bodyKind: ExecutionResult['bodyKind'] =\n text.length === 0\n ? 'empty'\n : contentType.includes('json') ||\n contentType.includes('xml') ||\n contentType.startsWith('text/')\n ? contentType.includes('json')\n ? 'json'\n : 'text'\n : 'binary';\n const t1 =\n typeof performance !== 'undefined' && typeof performance.now === 'function'\n ? performance.now()\n : Date.now();\n return {\n startedAt,\n durationMs: Math.max(0, Math.round(t1 - t0)),\n status: response.status,\n ok: response.ok,\n statusText: response.statusText,\n headers,\n body: text,\n bodyKind,\n url: currentUrl,\n method: currentMethod,\n authWarnings: builtRequest.authWarnings,\n ...(truncated ? { responseTruncated: true } : {}),\n };\n } catch (err) {\n const t1 =\n typeof performance !== 'undefined' && typeof performance.now === 'function'\n ? performance.now()\n : Date.now();\n return {\n startedAt,\n durationMs: Math.max(0, Math.round(t1 - t0)),\n status: null,\n ok: false,\n statusText: '',\n headers: {},\n body: '',\n bodyKind: 'empty',\n error: err instanceof Error ? err.message : String(err),\n // We may have already followed redirects before throwing — report the\n // last URL we tried so the user sees where the error originated.\n url: built?.url ?? req.url,\n method: built?.method ?? req.method,\n authWarnings: built?.authWarnings ?? [],\n };\n } finally {\n if (timeoutHandle !== null) clearTimeout(timeoutHandle);\n if (opts.signal) opts.signal.removeEventListener('abort', externalAbort);\n }\n}\n\n/**\n * One-shot retry that consumes the WWW-Authenticate from a 401 response\n * and runs the matching challenge protocol:\n *\n * - Digest: parse the directives, build an `Authorization: Digest …`\n * from the user's credentials, refetch once.\n * - NTLM: parse the Type-2 from `WWW-Authenticate: NTLM <base64>`,\n * build the Type-3 with the user's credentials + workstation, refetch\n * on the SAME connection (we can't enforce that from `fetch` alone,\n * but most servers accept the Type-3 anyway because the cookie/socket\n * reuse is best-effort under HTTP/2 multiplexing).\n *\n * Returns null when the challenge isn't one we handle (e.g. unrelated\n * 401 from a Bearer expiry); caller falls through with the original 401.\n */\nasync function runChallengeRetry(args: {\n fetchImpl: typeof fetch;\n builtUrl: string;\n builtMethod: string;\n builtHeaders: Record<string, string>;\n builtBody: BodyInit | null;\n signal: AbortSignal;\n wwwAuth: string;\n auth: Extract<ApiRequest['auth'], { type: 'digest' } | { type: 'ntlm' }>;\n previousResponse: Response;\n /** Optional nc override (8 hex chars) — bumped across stale=true retries. */\n nc?: string;\n}): Promise<Response | null> {\n if (args.auth.type === 'digest' && /^digest\\b/i.test(args.wwwAuth)) {\n // Pick the strongest challenge when the server stacks multiple\n // `WWW-Authenticate: Digest` headers (SHA-512-256 / SHA-256 / MD5).\n // For single-challenge servers this returns the same challenge that\n // `parseDigestChallenge` would have produced, so single-algo flows\n // are unchanged.\n const challenge =\n selectStrongestDigestChallenge(args.wwwAuth) ?? parseDigestChallenge(args.wwwAuth);\n if (!challenge.realm || !challenge.nonce) return null;\n const uri = new URL(args.builtUrl).pathname + new URL(args.builtUrl).search;\n // Digest auth-int requires the entity body bytes — string, binary,\n // and Blob all flow through. FormData and one-shot ReadableStream\n // bodies were consumed by the first fetch and CAN'T be replayed —\n // we surface that as an explicit failure rather than silently\n // sending an empty body that the server would reject anyway.\n let entityBody: string | Uint8Array | ArrayBuffer | Blob | null = null;\n const b = args.builtBody;\n if (typeof b === 'string') entityBody = b;\n else if (b instanceof Uint8Array || b instanceof ArrayBuffer) entityBody = b;\n else if (typeof Blob !== 'undefined' && b instanceof Blob) entityBody = b;\n else if (b != null && /\\bauth-int\\b/i.test(challenge.qop ?? '')) {\n // Server requires auth-int but we can't hash the body — fail\n // loudly instead of silently sending an empty hash.\n throw new Error(\n 'Digest auth-int retry needs a hashable body (string / Blob / Uint8Array). ' +\n 'Streaming bodies are consumed by the first fetch and cannot be replayed.',\n );\n }\n const authHeader = await buildDigestAuthHeader({\n method: args.builtMethod,\n uri,\n username: args.auth.username,\n password: args.auth.password,\n challenge,\n entityBody,\n // Pass the previous nonce-count so a `stale=true` retry can bump\n // it appropriately. First retry from a fresh challenge defaults\n // to nc=00000001.\n nc: args.nc,\n });\n return args.fetchImpl(args.builtUrl, {\n method: args.builtMethod,\n headers: setHeaderCaseInsensitive(args.builtHeaders, 'Authorization', authHeader),\n body: args.builtBody,\n signal: args.signal,\n });\n }\n\n if (args.auth.type === 'ntlm' && /^ntlm\\s+/i.test(args.wwwAuth)) {\n const type2Base64 = args.wwwAuth.replace(/^ntlm\\s+/i, '').trim();\n if (!type2Base64) return null;\n let type2;\n try {\n type2 = parseNtlmType2Challenge(type2Base64);\n } catch {\n return null;\n }\n // Recover Type-1 bytes from the Authorization header we sent on the\n // request that triggered this 401. When present, we hand both\n // Type-1 + Type-2 raw bytes into the Type-3 builder so it computes\n // and embeds the MIC per [MS-NLMP] §3.1.5.1.2. When the original\n // request didn't carry an NTLM Authorization (very rare — applyAuth\n // always emits one for `auth.type === 'ntlm'`), we skip MIC and\n // fall back to legacy Type-3 layout.\n const sentAuth = readHeaderCaseInsensitive(args.builtHeaders, 'Authorization');\n const type1Match = sentAuth?.match(/^ntlm\\s+(.+)$/i);\n let type1Bytes: Uint8Array | undefined;\n if (type1Match) {\n try {\n type1Bytes = decodeNtlmBase64(type1Match[1].trim());\n } catch {\n type1Bytes = undefined;\n }\n }\n const type3 = buildNtlmType3Authenticate({\n username: args.auth.username,\n password: args.auth.password,\n domain: args.auth.domain,\n workstation: args.auth.workstation,\n challenge: type2,\n type1Message: type1Bytes,\n type2Message: type1Bytes ? type2.rawBytes : undefined,\n });\n return args.fetchImpl(args.builtUrl, {\n method: args.builtMethod,\n headers: setHeaderCaseInsensitive(args.builtHeaders, 'Authorization', `NTLM ${type3}`),\n body: args.builtBody,\n signal: args.signal,\n });\n }\n\n return null;\n}\n\nfunction setHeaderCaseInsensitive(\n headers: Record<string, string>,\n key: string,\n value: string,\n): Record<string, string> {\n const lower = key.toLowerCase();\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() !== lower) out[k] = v;\n }\n out[key] = value;\n return out;\n}\n\nfunction readHeaderCaseInsensitive(\n headers: Record<string, string>,\n key: string,\n): string | undefined {\n const lower = key.toLowerCase();\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() === lower) return v;\n }\n return undefined;\n}\n\n/** Bump the 8-hex-char nonce-count by 1 (e.g. \"00000001\" → \"00000002\"). */\nfunction bumpNc(nc: string): string {\n const next = parseInt(nc, 16) + 1;\n return next.toString(16).padStart(8, '0');\n}\n\n/**\n * Read a Response body with a hard byte cap. Returns the decoded UTF-8\n * string plus a `truncated` flag. We stream via the body reader so a\n * gigabyte chunked-encoded stream from a hostile server doesn't OOM us —\n * once we've accumulated `MAX_RESPONSE_BODY_BYTES`, we cancel the read and\n * keep the prefix we already have.\n *\n * Fallback path: when the runtime doesn't expose `response.body` (older\n * fetch polyfills, certain test stubs), defer to `response.text()` — the\n * caller is on their own to know they're not facing a hostile server.\n */\nasync function readResponseCapped(\n response: Response,\n): Promise<{ text: string; truncated: boolean }> {\n const body = response.body;\n if (!body || typeof body.getReader !== 'function') {\n // No stream — best-effort. The cap won't fire in this branch, but\n // the response.text() call still resolves to whatever the runtime\n // already buffered.\n return { text: await response.text(), truncated: false };\n }\n const reader = body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n let truncated = false;\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\n total += value.byteLength;\n chunks.push(value);\n if (total >= MAX_RESPONSE_BODY_BYTES) {\n truncated = true;\n try {\n await reader.cancel();\n } catch {\n /* cancel may not be supported in every runtime */\n }\n break;\n }\n }\n } catch {\n // Read errored mid-stream — keep what we have and surface the chunks\n // we've already captured. The outer try/catch in executeRequest will\n // see the underlying network error if there is one.\n }\n // Concatenate + UTF-8 decode. We only need the bytes we kept; if we hit\n // the cap we trim to exactly `MAX_RESPONSE_BODY_BYTES` so the boundary\n // is deterministic for users (otherwise we'd return slightly over the\n // limit on the final chunk).\n const totalLen = truncated ? MAX_RESPONSE_BODY_BYTES : total;\n const out = new Uint8Array(totalLen);\n let offset = 0;\n for (const c of chunks) {\n if (offset >= totalLen) break;\n const slice = offset + c.byteLength > totalLen ? c.subarray(0, totalLen - offset) : c;\n out.set(slice, offset);\n offset += slice.byteLength;\n }\n const text = new TextDecoder('utf-8', { fatal: false }).decode(out);\n return { text, truncated };\n}\n","import type { RequestRun } from '@apicircle/shared';\nimport type { ExecutionResult } from './executeRequest';\n\n/**\n * Adapt a stored `RequestRun` into the `ExecutionResult` shape that\n * `ResponseViewer` consumes. `RequestRun` is the persisted, post-mortem\n * record (kept on `WorkspaceLocal.history` and capped); `ExecutionResult`\n * is the live in-flight value the editor receives. Both expose the same\n * conceptual fields, so the History and Execution detail views can lean\n * on the same renderer instead of forking the layout.\n *\n * The body is `responseBodyPreview` (already capped by\n * `RUN_BODY_PREVIEW_LIMIT`); the editor will show a truncation hint when\n * `RequestRun.responseTruncated` is true.\n */\nexport function requestRunToExecutionResult(run: RequestRun): ExecutionResult {\n return {\n startedAt: run.startedAt,\n durationMs: run.durationMs,\n status: run.status,\n ok: run.ok,\n statusText: run.statusText,\n headers: run.responseHeaders,\n body: run.responseBodyPreview,\n bodyKind: run.responseBodyKind,\n error: run.error,\n url: run.url,\n method: run.method,\n // Historical runs predate the auth-warnings feature; surfacing an\n // empty list is the honest answer (we don't know if there were\n // warnings at the time).\n authWarnings: [],\n };\n}\n","/**\n * PKCE (Proof Key for Code Exchange — RFC 7636) primitives.\n *\n * Authorization-code grant adds a `code_verifier` (43–128 random URL-safe\n * chars) generated on the client. The auth request carries a derived\n * `code_challenge` (either the verifier itself for `plain`, or\n * `BASE64URL(SHA-256(verifier))` for `S256`); the token-exchange request\n * carries the verifier itself. The server confirms `H(verifier) === challenge`\n * before issuing tokens, neutralizing intercepted authorization codes.\n *\n * S256 is the only method we recommend; `plain` exists in the spec for\n * environments without SHA-256 (basically none today). We support both\n * because some legacy IdPs still negotiate `plain` even when S256 is\n * available.\n */\n\n// 64-character subset of the RFC 7636 unreserved set. The drop from 66\n// (the spec's max) to 64 lets us mask with `& 0x3f` instead of `% 66`,\n// which avoids modulo bias — `byte % 66` maps values 0..189 to two chars\n// each and 190..255 to one char each, so two characters appear ~1.34× more\n// often than the rest. Microscopic in 64-byte verifiers, but trivial to fix.\nconst VERIFIER_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n\n/**\n * Generate a fresh PKCE code verifier — 43..128 random characters from\n * the unreserved URL set (RFC 3986 §2.3). Default length is 64, well\n * inside the spec's allowed range.\n *\n * Sampling is uniform: we mask each random byte with `& 0x3f` to project\n * onto exactly 64 alphabet positions, so every alphabet character is\n * equally likely. The earlier `% 66` implementation introduced a small\n * but measurable modulo bias.\n */\nexport function generateCodeVerifier(length: number = 64): string {\n if (length < 43 || length > 128) {\n throw new Error(`PKCE verifier length must be 43..128 (got ${length})`);\n }\n const bytes = new Uint8Array(length);\n crypto.getRandomValues(bytes);\n let out = '';\n for (let i = 0; i < length; i++) {\n out += VERIFIER_ALPHABET[bytes[i] & 0x3f];\n }\n return out;\n}\n\nexport type PkceMethod = 'S256' | 'plain';\n\n/**\n * Compute the `code_challenge` that pairs with a verifier. The browser's\n * SubtleCrypto handles SHA-256; for `plain` we just echo the verifier.\n */\nexport async function computeCodeChallenge(\n verifier: string,\n method: PkceMethod = 'S256',\n): Promise<string> {\n if (method === 'plain') return verifier;\n const data = new TextEncoder().encode(verifier);\n const hash = await crypto.subtle.digest(\n 'SHA-256',\n data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength),\n );\n return base64UrlEncode(new Uint8Array(hash));\n}\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let s = '';\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);\n return btoa(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n","// Resolve a request's auth by walking up the folder chain when the request\n// itself sets `inherit`. Returns the first explicit (non-`inherit`,\n// non-`none`) auth found on an ancestor folder. Falls back to `{ type: 'none' }`\n// when the chain has nothing to inherit from.\n//\n// Pure function — same input always yields the same output. Used by the\n// workspace executor *before* calling `buildRequest`, so the request reaches\n// the wire with a concrete auth.\n\nimport type { Folder, RequestAuth } from '@apicircle/shared';\n\nconst NONE: RequestAuth = { type: 'none' };\n\nexport interface ResolveInheritedAuthArgs {\n /** The request's stated auth (may be `{ type: 'inherit' }`). */\n requestAuth: RequestAuth;\n /** The folderId the request lives in (null if at the root). */\n folderId: string | null;\n /** All known folders, keyed by id. */\n folders: Record<string, Folder>;\n}\n\n/**\n * If `requestAuth` is anything other than `inherit`, returns it unchanged.\n * Otherwise walks up the folder chain looking for the first folder whose\n * own `auth` is set and is not itself `inherit` or `none`. Folders with\n * `inherit` or `none` auth are transparent (skipped, walk continues).\n */\nexport function resolveInheritedAuth({\n requestAuth,\n folderId,\n folders,\n}: ResolveInheritedAuthArgs): RequestAuth {\n if (requestAuth.type !== 'inherit') return requestAuth;\n\n // Walk up from folderId. Bail at root (parentId === null) or first concrete auth.\n let cursor = folderId;\n const visited = new Set<string>();\n while (cursor !== null) {\n if (visited.has(cursor)) {\n // Defensive: cycle in folder.parentId would otherwise loop forever.\n // The data model says this shouldn't happen, but cheap to guard.\n break;\n }\n visited.add(cursor);\n const folder = folders[cursor];\n if (!folder) break;\n const auth = folder.auth;\n if (auth && auth.type !== 'inherit' && auth.type !== 'none') return auth;\n cursor = folder.parentId;\n }\n return NONE;\n}\n","// Parse a `curl` invocation into a partial Request shape. Handles the\n// flags real-world cURL output uses (Postman/Browser/Burp/Chrome dev-tools\n// \"Copy as cURL\"): -X / --request, -H, -d / --data / --data-raw /\n// --data-binary / --data-urlencode, --json, -F (multipart), -u (basic),\n// --url, and bare URL positional args. Multi-line input with `\\`\n// continuations is normalised first.\n//\n// Pure module — no UI / Monaco / fetch coupling. Returns the partial\n// Request fields the editor needs (method, url, headers, body, auth)\n// plus a list of unrecognised tokens so the caller can surface them.\n\nimport type { Request as ApiRequest, RequestAuth, RequestBody } from '@apicircle/shared';\nimport { applyContentTypeForBodyType } from './bodyTypeContentType';\n\nexport interface ParsedCurl {\n method: ApiRequest['method'];\n url: string;\n headers: ApiRequest['headers'];\n query: ApiRequest['query'];\n body: RequestBody;\n auth: RequestAuth;\n /** Unrecognised flags / fragments — the UI can show these as a warning. */\n warnings: string[];\n}\n\nconst HTTP_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']);\n\n/**\n * Tokenise a shell-style argv from a string. Handles single/double quotes,\n * backslash escapes, and whitespace-splitting. Doesn't try to be a full\n * POSIX shell — `$VAR` expansion, command substitution, and globs all\n * pass through verbatim.\n */\nexport function tokenizeCurl(input: string): string[] {\n const tokens: string[] = [];\n let buf = '';\n let i = 0;\n let quote: '\"' | \"'\" | null = null;\n let inToken = false;\n\n const flush = () => {\n if (inToken) tokens.push(buf);\n buf = '';\n inToken = false;\n };\n\n while (i < input.length) {\n const ch = input[i];\n\n // Strip line continuations (`\\` immediately before \\n) when not in a\n // single-quoted region. Normalise CRLF to LF first via the regex below.\n if (quote !== \"'\" && ch === '\\\\' && (input[i + 1] === '\\n' || input[i + 1] === undefined)) {\n i += 2;\n continue;\n }\n\n if (quote) {\n if (ch === quote) {\n quote = null;\n inToken = true;\n i += 1;\n continue;\n }\n if (quote === '\"' && ch === '\\\\' && i + 1 < input.length) {\n // Inside double quotes, backslash escapes the next character.\n buf += input[i + 1];\n i += 2;\n continue;\n }\n buf += ch;\n i += 1;\n continue;\n }\n\n if (ch === '\"' || ch === \"'\") {\n quote = ch;\n inToken = true;\n i += 1;\n continue;\n }\n\n if (ch === '\\\\' && i + 1 < input.length) {\n buf += input[i + 1];\n inToken = true;\n i += 2;\n continue;\n }\n\n if (/\\s/.test(ch)) {\n flush();\n i += 1;\n continue;\n }\n\n buf += ch;\n inToken = true;\n i += 1;\n }\n flush();\n return tokens;\n}\n\nfunction parseHeader(line: string): { key: string; value: string } | null {\n const colon = line.indexOf(':');\n if (colon === -1) return null;\n return {\n key: line.slice(0, colon).trim(),\n value: line.slice(colon + 1).trim(),\n };\n}\n\nfunction parseUrlEncodedBody(raw: string): { body: string; contentType: string } {\n // `--data-urlencode key=value` is sent as application/x-www-form-urlencoded.\n // Multiple --data flags concatenate with `&` — that's handled by the caller.\n return { body: raw, contentType: 'application/x-www-form-urlencoded' };\n}\n\nfunction detectBodyType(body: string, contentType: string): RequestBody['type'] {\n const ct = contentType.toLowerCase();\n if (ct.includes('json')) return 'json';\n if (ct.includes('xml')) return 'xml';\n if (ct.includes('graphql')) return 'graphql';\n if (ct.includes('form-urlencoded')) return 'urlencoded';\n // Heuristic: starts with `{` or `[` → likely JSON even if Content-Type is\n // missing (real-world Postman copy-as-cURL sometimes drops the header).\n const trimmed = body.trim();\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) return 'json';\n if (trimmed.startsWith('<')) return 'xml';\n return 'text';\n}\n\nexport function parseCurl(input: string): ParsedCurl {\n // Normalise CRLF → LF and trim a leading `$ ` prompt that copy-paste\n // sometimes carries.\n const normalised = input.replace(/\\r\\n?/g, '\\n').replace(/^\\s*\\$\\s*/, '');\n const tokens = tokenizeCurl(normalised);\n\n const out: ParsedCurl = {\n method: 'GET',\n url: '',\n headers: [],\n query: [],\n body: { type: 'none', content: '' },\n auth: { type: 'none' },\n warnings: [],\n };\n\n if (tokens.length === 0) {\n out.warnings.push('Empty cURL command');\n return out;\n }\n // Skip the leading `curl` token.\n let i = tokens[0]?.toLowerCase() === 'curl' ? 1 : 0;\n\n // Body accumulators, kept separate so the urlencoded composer can tell a\n // field separator (`&` between `-d` fields) from a literal `&` inside a\n // `--data-urlencode` value: `-d`/`--data` flags carry `&`-separated fields\n // (curl's wire format), `--data-urlencode` carries one discrete field each,\n // `--json` is a verbatim JSON document.\n const dataFlags: string[] = [];\n const urlencodeFields: string[] = [];\n let jsonContent: string | null = null;\n let bodyContentType = '';\n let methodExplicit = false;\n const formRows: NonNullable<RequestBody['formRows']> = [];\n\n const consume = (): string | null => (i < tokens.length ? tokens[i++] : null);\n\n while (i < tokens.length) {\n const tok = tokens[i++];\n\n if (tok === '-X' || tok === '--request') {\n const m = consume();\n if (m && HTTP_METHODS.has(m.toUpperCase())) {\n out.method = m.toUpperCase() as ApiRequest['method'];\n methodExplicit = true;\n } else if (m) {\n out.warnings.push(`Unsupported method \"${m}\"`);\n }\n continue;\n }\n\n if (tok === '-H' || tok === '--header') {\n const v = consume();\n if (!v) continue;\n const parsed = parseHeader(v);\n if (parsed) {\n out.headers.push({ ...parsed, enabled: true });\n } else {\n out.warnings.push(`Skipped malformed header: ${v}`);\n }\n continue;\n }\n\n if (tok === '-d' || tok === '--data' || tok === '--data-raw' || tok === '--data-binary') {\n const v = consume();\n if (v == null) continue;\n dataFlags.push(v);\n continue;\n }\n\n if (tok === '--data-urlencode') {\n const v = consume();\n if (v == null) continue;\n const { body, contentType } = parseUrlEncodedBody(v);\n urlencodeFields.push(body);\n if (!bodyContentType) bodyContentType = contentType;\n continue;\n }\n\n if (tok === '--json') {\n const v = consume();\n if (v == null) continue;\n jsonContent = v;\n continue;\n }\n\n if (tok === '-F' || tok === '--form') {\n const v = consume();\n if (v == null) continue;\n const eq = v.indexOf('=');\n if (eq === -1) {\n out.warnings.push(`Skipped malformed -F: ${v}`);\n continue;\n }\n const key = v.slice(0, eq);\n const value = v.slice(eq + 1);\n // `-F field=@/path` is a file row — we can't reach the file from\n // a paste-import (no FS access in browser), so flag it as a warning\n // and add a placeholder text row keyed by file path. The user can\n // re-attach via the Form-Data UI.\n if (value.startsWith('@')) {\n out.warnings.push(\n `File field \"${key}\" needs manual attach — paste-import can't reach the local file (${value.slice(1)})`,\n );\n formRows.push({ kind: 'file', key, slotId: null, enabled: true });\n } else {\n formRows.push({ kind: 'text', key, value, enabled: true });\n }\n continue;\n }\n\n if (tok === '-u' || tok === '--user') {\n const creds = consume();\n if (!creds) continue;\n const colon = creds.indexOf(':');\n if (colon === -1) {\n out.auth = { type: 'basic', username: creds, password: '' };\n } else {\n out.auth = {\n type: 'basic',\n username: creds.slice(0, colon),\n password: creds.slice(colon + 1),\n };\n }\n continue;\n }\n\n if (tok === '--url') {\n const v = consume();\n if (v) out.url = v;\n continue;\n }\n\n if (\n tok === '--compressed' ||\n tok === '-i' ||\n tok === '--include' ||\n tok === '-s' ||\n tok === '--silent' ||\n tok === '-k' ||\n tok === '--insecure' ||\n tok === '-L' ||\n tok === '--location' ||\n tok === '--verbose' ||\n tok === '-v'\n ) {\n // Output / network flags that don't change request shape.\n continue;\n }\n\n if (tok === '-A' || tok === '--user-agent') {\n const v = consume();\n if (v) out.headers.push({ key: 'User-Agent', value: v, enabled: true });\n continue;\n }\n\n if (tok === '-e' || tok === '--referer') {\n const v = consume();\n if (v) out.headers.push({ key: 'Referer', value: v, enabled: true });\n continue;\n }\n\n if (tok === '-b' || tok === '--cookie') {\n const v = consume();\n if (v) out.headers.push({ key: 'Cookie', value: v, enabled: true });\n continue;\n }\n\n if (tok.startsWith('-')) {\n // Unrecognised flag — many cURL output flags take a value, but we\n // can't tell without a reference table. Surface it.\n out.warnings.push(`Ignored unrecognised flag: ${tok}`);\n continue;\n }\n\n // Bare token = URL (the first one wins; subsequent bare tokens are\n // ignored with a warning).\n if (!out.url) {\n out.url = tok;\n } else {\n out.warnings.push(`Ignored extra positional argument: ${tok}`);\n }\n }\n\n if (!out.url) {\n out.warnings.push('No URL found in cURL command');\n }\n\n // Promote method to POST when a body is present and -X wasn't given —\n // matches cURL's own default.\n if (\n !methodExplicit &&\n (jsonContent !== null ||\n dataFlags.length > 0 ||\n urlencodeFields.length > 0 ||\n formRows.length > 0)\n ) {\n out.method = 'POST';\n }\n\n // Split off query string from the URL into the query[] array. The editor\n // shows params separately so the user can toggle them.\n if (out.url.includes('?')) {\n const [base, qs] = out.url.split('?', 2);\n out.url = base!;\n if (qs) {\n for (const pair of qs.split('&')) {\n if (!pair) continue;\n const eq = pair.indexOf('=');\n const key = decodeURIComponent(eq === -1 ? pair : pair.slice(0, eq));\n const value = eq === -1 ? '' : decodeURIComponent(pair.slice(eq + 1));\n out.query.push({ key, value, enabled: true });\n }\n }\n }\n\n // Compose the body. For form-data: the rows are the body. For everything\n // else, refine the type from the Content-Type header (if user supplied one)\n // or the body shape.\n if (formRows.length > 0) {\n out.body = { type: 'form-data', content: '', formRows };\n } else if (jsonContent !== null) {\n out.body = { type: 'json', content: jsonContent };\n const userContentType = out.headers.find((h) => h.key.toLowerCase() === 'content-type')?.value;\n if (!userContentType) {\n out.headers = applyContentTypeForBodyType(out.headers, 'json');\n }\n } else if (dataFlags.length > 0 || urlencodeFields.length > 0) {\n const userContentType = out.headers.find((h) => h.key.toLowerCase() === 'content-type')?.value;\n const effectiveContentType = userContentType ?? bodyContentType;\n // curl's `-d` family concatenates its fields with `&` on the wire.\n const wireBody = dataFlags.join('&');\n const detectedType: RequestBody['type'] =\n urlencodeFields.length > 0 ? 'urlencoded' : detectBodyType(wireBody, effectiveContentType);\n if (detectedType === 'urlencoded') {\n // Store the raw, newline-delimited `key=value` form `composeBody`\n // expects. `-d` fields are `&`-separated on the wire; `--data-urlencode`\n // fields are already discrete and may carry a literal `&` in a value.\n const fields = [...dataFlags.flatMap((v) => v.split('&')), ...urlencodeFields].filter(\n (f) => f !== '',\n );\n out.body = { type: 'urlencoded', content: fields.join('\\n') };\n } else {\n out.body = { type: detectedType, content: wireBody };\n }\n if (!userContentType) {\n // Auto-fill Content-Type so the request doesn't go out without one.\n out.headers = applyContentTypeForBodyType(out.headers, detectedType);\n }\n }\n\n return out;\n}\n","// Postman v2.1 collection import. Translates the Postman shape into the\n// minimal subset our editor knows how to render: folders + requests with\n// method/url/headers/body. Auth conversion is best-effort (Bearer, Basic,\n// API key); unknown auth types fall through to `{ type: 'none' }`.\n//\n// Reference: https://schema.postman.com/collection/json/v2.1.0/collection.json\n//\n// Exported `parsePostmanCollection` returns either a typed result we can hand\n// to a workspace builder, or a list of warnings. We never throw on\n// recoverable issues — the caller decides whether to surface them.\n\nimport type { BodyType, HttpMethod, RequestAuth, RequestBody } from '@apicircle/shared';\n\nconst POSTMAN_V2_1_SCHEMA_PATTERN = /collection\\/v2(?:\\.[0-9]+)*/;\n\nexport interface ImportedRequest {\n name: string;\n method: HttpMethod;\n url: string;\n headers: Array<{ key: string; value: string; enabled: boolean }>;\n query: Array<{ key: string; value: string; enabled: boolean }>;\n body: RequestBody;\n auth: RequestAuth;\n}\n\nexport interface ImportedFolder {\n name: string;\n /** Index path from root (deterministic id assignment is the caller's job). */\n pathIds: number[];\n parentPathIds: number[] | null;\n}\n\nexport interface ParsedPostmanCollection {\n collectionName: string;\n folders: ImportedFolder[];\n requests: Array<ImportedRequest & { folderPathIds: number[] | null }>;\n warnings: string[];\n}\n\nconst HTTP_METHODS = new Set<HttpMethod>([\n 'GET',\n 'POST',\n 'PUT',\n 'PATCH',\n 'DELETE',\n 'HEAD',\n 'OPTIONS',\n]);\n\ninterface PostmanItem {\n name?: string;\n item?: PostmanItem[];\n request?: PostmanRequest | string;\n auth?: PostmanAuth;\n}\n\ninterface PostmanRequest {\n method?: string;\n url?: PostmanUrl | string;\n header?: Array<{ key?: string; value?: string; disabled?: boolean }>;\n body?: PostmanBody;\n auth?: PostmanAuth;\n}\n\ninterface PostmanUrl {\n raw?: string;\n host?: string[] | string;\n path?: string[] | string;\n protocol?: string;\n query?: Array<{ key?: string; value?: string; disabled?: boolean }>;\n}\n\ninterface PostmanBody {\n mode?: 'raw' | 'urlencoded' | 'formdata' | 'graphql' | 'binary' | 'file';\n raw?: string;\n options?: { raw?: { language?: string } };\n urlencoded?: Array<{ key?: string; value?: string; disabled?: boolean }>;\n formdata?: Array<{ key?: string; value?: string; type?: 'text' | 'file'; disabled?: boolean }>;\n graphql?: { query?: string; variables?: string };\n}\n\ninterface PostmanAuth {\n type?: string;\n bearer?: Array<{ key?: string; value?: string }>;\n basic?: Array<{ key?: string; value?: string }>;\n apikey?: Array<{ key?: string; value?: string }>;\n}\n\ninterface PostmanCollectionDoc {\n info?: { name?: string; schema?: string };\n item?: PostmanItem[];\n}\n\nexport function isPostmanV2Collection(doc: unknown): boolean {\n if (!doc || typeof doc !== 'object') return false;\n const info = (doc as PostmanCollectionDoc).info;\n if (!info || typeof info.schema !== 'string') return false;\n return POSTMAN_V2_1_SCHEMA_PATTERN.test(info.schema);\n}\n\nexport function parsePostmanCollection(input: string): ParsedPostmanCollection {\n const warnings: string[] = [];\n let parsed: PostmanCollectionDoc;\n try {\n parsed = JSON.parse(input) as PostmanCollectionDoc;\n } catch (err) {\n throw new Error(`Couldn't parse JSON: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!isPostmanV2Collection(parsed)) {\n throw new Error(\n 'Unsupported format. Expected a Postman v2.1 collection (info.schema must include \"collection/v2\"). Use Postman → Export → Collection v2.1.',\n );\n }\n\n const collectionName =\n (parsed.info?.name ?? 'Imported collection').trim() || 'Imported collection';\n const folders: ImportedFolder[] = [];\n const requests: ParsedPostmanCollection['requests'] = [];\n\n const walk = (items: PostmanItem[] | undefined, parentPathIds: number[] | null): void => {\n if (!items || items.length === 0) return;\n items.forEach((item, idx) => {\n const pathIds = parentPathIds ? [...parentPathIds, idx] : [idx];\n // Item is a folder when it has nested items.\n if (Array.isArray(item.item)) {\n folders.push({\n name: (item.name ?? 'Untitled folder').trim() || 'Untitled folder',\n pathIds,\n parentPathIds: parentPathIds,\n });\n walk(item.item, pathIds);\n return;\n }\n const built = buildRequest(item, warnings);\n if (built) requests.push({ ...built, folderPathIds: parentPathIds });\n });\n };\n walk(parsed.item, null);\n\n return { collectionName, folders, requests, warnings };\n}\n\nfunction buildRequest(item: PostmanItem, warnings: string[]): ImportedRequest | null {\n const raw = item.request;\n if (!raw) return null;\n if (typeof raw === 'string') {\n return {\n name: (item.name ?? 'Untitled').trim() || 'Untitled',\n method: 'GET',\n url: raw,\n headers: [],\n query: [],\n body: { type: 'none', content: '' },\n auth: { type: 'none' },\n };\n }\n const method = parseMethod(raw.method, warnings, item.name);\n const { url, query } = parseUrl(raw.url);\n const headers = (raw.header ?? [])\n .filter((h): h is { key?: string; value?: string; disabled?: boolean } => Boolean(h))\n .map((h) => ({\n key: (h.key ?? '').trim(),\n value: h.value ?? '',\n enabled: !h.disabled,\n }))\n .filter((h) => h.key.length > 0);\n const body = parseBody(raw.body, warnings, item.name);\n const auth = parseAuth(raw.auth ?? item.auth, warnings, item.name);\n return {\n name: (item.name ?? 'Untitled').trim() || 'Untitled',\n method,\n url,\n headers,\n query,\n body,\n auth,\n };\n}\n\nfunction parseMethod(method: string | undefined, warnings: string[], name?: string): HttpMethod {\n const upper = (method ?? 'GET').toUpperCase();\n if ((HTTP_METHODS as Set<string>).has(upper)) return upper as HttpMethod;\n warnings.push(`Unsupported method \"${method}\" on \"${name ?? 'unknown'}\" — defaulted to GET.`);\n return 'GET';\n}\n\nfunction parseUrl(url: PostmanUrl | string | undefined): {\n url: string;\n query: ImportedRequest['query'];\n} {\n if (!url) return { url: '', query: [] };\n if (typeof url === 'string') return { url, query: [] };\n // Prefer .raw when present — Postman keeps the original spelling there.\n let assembled = url.raw ?? '';\n if (!assembled) {\n const proto = url.protocol ? `${url.protocol}://` : '';\n const host = Array.isArray(url.host) ? url.host.join('.') : (url.host ?? '');\n const path = Array.isArray(url.path) ? url.path.join('/') : (url.path ?? '').replace(/^\\//, '');\n assembled = `${proto}${host}${path ? `/${path}` : ''}`;\n }\n // Strip query string from URL if both raw and structured query are present —\n // we'll re-emit query rows below from the structured list.\n const queryRows = (url.query ?? [])\n .filter((q): q is { key?: string; value?: string; disabled?: boolean } => Boolean(q))\n .map((q) => ({\n key: (q.key ?? '').trim(),\n value: q.value ?? '',\n enabled: !q.disabled,\n }))\n .filter((q) => q.key.length > 0);\n if (queryRows.length > 0 && assembled.includes('?')) {\n assembled = assembled.split('?')[0];\n }\n return { url: assembled, query: queryRows };\n}\n\nfunction parseBody(body: PostmanBody | undefined, warnings: string[], name?: string): RequestBody {\n if (!body || !body.mode) return { type: 'none', content: '' };\n switch (body.mode) {\n case 'raw': {\n const lang = body.options?.raw?.language ?? '';\n const type: BodyType =\n lang === 'json' ? 'json' : lang === 'xml' ? 'xml' : lang === 'graphql' ? 'graphql' : 'text';\n return { type, content: body.raw ?? '' };\n }\n case 'urlencoded': {\n // `body.content` for urlencoded is raw, newline-delimited `key=value`\n // lines — `buildRequest.composeBody` percent-encodes them at send\n // time. Encoding here would double-encode the wire body.\n const rows = body.urlencoded ?? [];\n const content = rows\n .filter((r) => !r.disabled && (r.key ?? '').length > 0)\n .map((r) => `${r.key ?? ''}=${r.value ?? ''}`)\n .join('\\n');\n return { type: 'urlencoded', content };\n }\n case 'graphql': {\n return {\n type: 'graphql',\n content: body.graphql?.query ?? '',\n variables: body.graphql?.variables ?? '',\n };\n }\n case 'formdata': {\n // Form-data file rows can't round-trip without the actual file blob —\n // we drop them here with a warning. Text rows survive as form rows.\n const rows = (body.formdata ?? [])\n .filter((r) => (r.key ?? '').length > 0)\n .map((r) => {\n if (r.type === 'file') {\n warnings.push(\n `Skipped form-data file row \"${r.key}\" on \"${name ?? 'unknown'}\" — re-attach the file in the editor.`,\n );\n return null;\n }\n return {\n kind: 'text' as const,\n key: r.key ?? '',\n value: r.value ?? '',\n enabled: !r.disabled,\n };\n })\n .filter(\n (r): r is { kind: 'text'; key: string; value: string; enabled: boolean } => r !== null,\n );\n return { type: 'form-data', content: '', formRows: rows };\n }\n case 'binary':\n case 'file': {\n warnings.push(\n `Binary body on \"${name ?? 'unknown'}\" not imported — re-attach the file in the editor.`,\n );\n return { type: 'binary', content: '' };\n }\n default:\n warnings.push(\n `Unsupported body mode \"${String((body as { mode: unknown }).mode)}\" on \"${name ?? 'unknown'}\" — body skipped.`,\n );\n return { type: 'none', content: '' };\n }\n}\n\nfunction parseAuth(auth: PostmanAuth | undefined, warnings: string[], name?: string): RequestAuth {\n if (!auth || !auth.type) return { type: 'none' };\n const valueOf = (\n rows: Array<{ key?: string; value?: string }> | undefined,\n key: string,\n ): string => {\n const found = rows?.find((r) => r.key === key);\n return (found?.value ?? '').toString();\n };\n switch (auth.type) {\n case 'bearer':\n return { type: 'bearer', token: valueOf(auth.bearer, 'token') };\n case 'basic':\n return {\n type: 'basic',\n username: valueOf(auth.basic, 'username'),\n password: valueOf(auth.basic, 'password'),\n };\n case 'apikey': {\n const inLocation = (valueOf(auth.apikey, 'in') || 'header').toLowerCase();\n const addTo: 'header' | 'query' | 'cookie' =\n inLocation === 'query' ? 'query' : inLocation === 'cookie' ? 'cookie' : 'header';\n return {\n type: 'api-key',\n key: valueOf(auth.apikey, 'key'),\n value: valueOf(auth.apikey, 'value'),\n addTo,\n };\n }\n case 'noauth':\n return { type: 'none' };\n default:\n warnings.push(\n `Unsupported auth type \"${auth.type}\" on \"${name ?? 'unknown'}\" — set to None. Configure manually in the editor.`,\n );\n return { type: 'none' };\n }\n}\n","// Postman environment import. The Postman environment JSON shape is:\n// { id, name, values: [{ key, value, enabled?, type? }], _postman_variable_scope: 'environment' }\n// We map this onto our Environment type — values become variables, with the\n// `enabled` flag respected (disabled rows are skipped). Postman's `type` field\n// (`secret` etc.) is dropped here — bring values in plaintext; the user can\n// bind to a Vault key after import via the existing Encrypt button.\n\nimport type { EnvironmentVariable } from '@apicircle/shared';\n\nexport interface ParsedPostmanEnvironment {\n /** Suggested env name; the user can change at import time. */\n name: string;\n variables: EnvironmentVariable[];\n warnings: string[];\n}\n\ninterface PostmanEnvDoc {\n name?: string;\n values?: Array<{ key?: string; value?: string; enabled?: boolean; type?: string }>;\n _postman_variable_scope?: string;\n}\n\nexport function isPostmanEnvironment(doc: unknown): boolean {\n if (!doc || typeof doc !== 'object') return false;\n const d = doc as PostmanEnvDoc;\n // The scope field is the cleanest signal. Some exports omit it but include\n // a `name` + `values` array — accept those too as long as `values` looks\n // like an env variable list.\n if (d._postman_variable_scope === 'environment') return true;\n return typeof d.name === 'string' && Array.isArray(d.values);\n}\n\nexport function parsePostmanEnvironment(input: string): ParsedPostmanEnvironment {\n const warnings: string[] = [];\n let parsed: PostmanEnvDoc;\n try {\n parsed = JSON.parse(input) as PostmanEnvDoc;\n } catch (err) {\n throw new Error(`Couldn't parse JSON: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!isPostmanEnvironment(parsed)) {\n throw new Error(\n 'Unsupported format. Expected a Postman environment JSON. Use Postman → Environments → Export.',\n );\n }\n const name = (parsed.name ?? 'Imported environment').trim() || 'Imported environment';\n const variables: EnvironmentVariable[] = [];\n for (const row of parsed.values ?? []) {\n const key = (row.key ?? '').trim();\n if (!key) continue;\n if (row.enabled === false) continue;\n if (row.type === 'secret') {\n warnings.push(\n `\"${key}\" was a Postman secret — imported as plaintext. Bind it to a Vault key in the Environments page if you want to keep it secret.`,\n );\n }\n variables.push({\n key,\n value: row.value ?? '',\n encrypted: false,\n });\n }\n return { name, variables, warnings };\n}\n","// Insomnia v4 export import. Translates the Insomnia \"export\" shape into\n// the same `ParsedPostmanCollection` structure our workspace builder\n// already accepts, so the importer doesn't need a second code path.\n//\n// Reference shape:\n// {\n// \"_type\": \"export\",\n// \"__export_format\": 4,\n// \"resources\": [\n// { \"_type\": \"request\", \"_id\": \"req_...\", \"name\": \"...\", \"method\": \"GET\",\n// \"url\": \"https://...\", \"headers\": [{ name, value }], \"body\": {...},\n// \"parentId\": \"fld_...\" | \"wrk_...\" },\n// { \"_type\": \"request_group\", \"_id\": \"fld_...\", \"name\": \"Auth\",\n// \"parentId\": \"wrk_...\" | \"fld_...\" },\n// { \"_type\": \"workspace\", \"_id\": \"wrk_...\", \"name\": \"...\" },\n// { \"_type\": \"environment\", ... }\n// ]\n// }\n//\n// We surface workspaces + request_groups as folders; requests as requests.\n// Environments live in `insomniaEnvironment.ts`.\n\nimport type { BodyType, HttpMethod, RequestAuth, RequestBody } from '@apicircle/shared';\nimport type { ImportedFolder, ImportedRequest, ParsedPostmanCollection } from './postmanCollection';\n\nconst HTTP_METHODS = new Set<HttpMethod>([\n 'GET',\n 'POST',\n 'PUT',\n 'PATCH',\n 'DELETE',\n 'HEAD',\n 'OPTIONS',\n]);\n\ninterface InsomniaResource {\n _type?: string;\n _id?: string;\n name?: string;\n parentId?: string;\n // Request fields\n method?: string;\n url?: string;\n headers?: Array<{ name?: string; value?: string; disabled?: boolean }>;\n parameters?: Array<{ name?: string; value?: string; disabled?: boolean }>;\n body?: {\n mimeType?: string;\n text?: string;\n params?: Array<{ name?: string; value?: string; disabled?: boolean; type?: string }>;\n };\n authentication?: {\n type?: string;\n token?: string;\n username?: string;\n password?: string;\n key?: string;\n value?: string;\n addTo?: string;\n };\n}\n\ninterface InsomniaExport {\n _type?: string;\n __export_format?: number;\n resources?: InsomniaResource[];\n}\n\nexport function isInsomniaExport(doc: unknown): boolean {\n if (!doc || typeof doc !== 'object') return false;\n const d = doc as InsomniaExport;\n return d._type === 'export' && Array.isArray(d.resources);\n}\n\nexport function parseInsomniaCollection(input: string): ParsedPostmanCollection {\n const warnings: string[] = [];\n let parsed: InsomniaExport;\n try {\n parsed = JSON.parse(input) as InsomniaExport;\n } catch (err) {\n throw new Error(`Couldn't parse JSON: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!isInsomniaExport(parsed)) {\n throw new Error(\n 'Unsupported format. Expected an Insomnia export (`_type: \"export\"` + `resources` array). Use Insomnia → Application → Preferences → Data → Export Data.',\n );\n }\n const resources = parsed.resources ?? [];\n\n // Build id → resource map for parent walks.\n const byId = new Map<string, InsomniaResource>();\n for (const r of resources) if (r._id) byId.set(r._id, r);\n\n // The \"workspace\" resource is the top-level folder; we surface it as the\n // wrapper when present. Otherwise the import lands at the root.\n const workspace = resources.find((r) => r._type === 'workspace');\n const collectionName = workspace?.name?.trim() || 'Imported collection';\n\n // Walk-up the parent chain to compute a folder index path. Each folder\n // gets an array of indices so descendants can find their parent in the\n // post-flat structure expected by our store.\n const folders: ImportedFolder[] = [];\n const folderIndexById = new Map<string, number[]>();\n // The synthetic root has empty path; workspace's children land directly\n // inside the wrapper folder we'll create later.\n if (workspace?._id) folderIndexById.set(workspace._id, []);\n\n // First pass: collect folders (request_group resources), in declaration\n // order. Postman uses index paths but Insomnia is flat — we synthesize\n // the same shape.\n let folderCounter = 0;\n for (const r of resources) {\n if (r._type !== 'request_group') continue;\n const parentPath = r.parentId ? (folderIndexById.get(r.parentId) ?? null) : null;\n const ourPath = parentPath ? [...parentPath, folderCounter++] : [folderCounter++];\n folderIndexById.set(r._id ?? '', ourPath);\n folders.push({\n name: (r.name ?? 'Untitled folder').trim() || 'Untitled folder',\n pathIds: ourPath,\n parentPathIds: parentPath,\n });\n }\n\n // Second pass: collect requests.\n const requests: ParsedPostmanCollection['requests'] = [];\n for (const r of resources) {\n if (r._type !== 'request') continue;\n const built = buildRequest(r, warnings);\n if (!built) continue;\n const parentPath = r.parentId ? (folderIndexById.get(r.parentId) ?? null) : null;\n requests.push({ ...built, folderPathIds: parentPath });\n }\n\n return { collectionName, folders, requests, warnings };\n}\n\nfunction buildRequest(r: InsomniaResource, warnings: string[]): ImportedRequest | null {\n const method = parseMethod(r.method, warnings, r.name);\n const url = (r.url ?? '').trim();\n const headers = (r.headers ?? [])\n .filter((h): h is { name?: string; value?: string; disabled?: boolean } => Boolean(h))\n .map((h) => ({\n key: (h.name ?? '').trim(),\n value: h.value ?? '',\n enabled: !h.disabled,\n }))\n .filter((h) => h.key.length > 0);\n const query = (r.parameters ?? [])\n .filter((p): p is { name?: string; value?: string; disabled?: boolean } => Boolean(p))\n .map((p) => ({\n key: (p.name ?? '').trim(),\n value: p.value ?? '',\n enabled: !p.disabled,\n }))\n .filter((p) => p.key.length > 0);\n const body = parseBody(r.body, warnings, r.name);\n const auth = parseAuth(r.authentication, warnings, r.name);\n return {\n name: (r.name ?? 'Untitled').trim() || 'Untitled',\n method,\n url,\n headers,\n query,\n body,\n auth,\n };\n}\n\nfunction parseMethod(method: string | undefined, warnings: string[], name?: string): HttpMethod {\n const upper = (method ?? 'GET').toUpperCase();\n if ((HTTP_METHODS as Set<string>).has(upper)) return upper as HttpMethod;\n warnings.push(`Unsupported method \"${method}\" on \"${name ?? 'unknown'}\" — defaulted to GET.`);\n return 'GET';\n}\n\nfunction parseBody(body: InsomniaResource['body'], warnings: string[], name?: string): RequestBody {\n if (!body || (!body.mimeType && !body.text && !body.params)) {\n return { type: 'none', content: '' };\n }\n const mime = (body.mimeType ?? '').toLowerCase();\n if (mime.includes('json')) return { type: 'json', content: body.text ?? '' };\n if (mime.includes('xml')) return { type: 'xml', content: body.text ?? '' };\n if (mime.includes('graphql')) {\n // Insomnia stores GraphQL queries as raw text under text=`{\"query\":\"...\",\n // \"variables\": {...}}`. Try to split.\n try {\n const obj = JSON.parse(body.text ?? '{}') as { query?: string; variables?: unknown };\n return {\n type: 'graphql',\n content: obj.query ?? '',\n variables:\n obj.variables === undefined\n ? ''\n : typeof obj.variables === 'string'\n ? obj.variables\n : JSON.stringify(obj.variables, null, 2),\n };\n } catch {\n return { type: 'graphql', content: body.text ?? '' };\n }\n }\n if (mime.includes('x-www-form-urlencoded')) {\n // `body.content` for urlencoded is raw, newline-delimited `key=value`\n // lines — `buildRequest.composeBody` percent-encodes them at send time.\n const rows = body.params ?? [];\n const content = rows\n .filter((r) => !r.disabled && (r.name ?? '').length > 0)\n .map((r) => `${r.name ?? ''}=${r.value ?? ''}`)\n .join('\\n');\n return { type: 'urlencoded', content };\n }\n if (mime.includes('multipart/form-data')) {\n const rows = (body.params ?? [])\n .filter((p) => (p.name ?? '').length > 0)\n .map((p) => {\n if (p.type === 'file') {\n warnings.push(\n `Skipped form-data file row \"${p.name}\" on \"${name ?? 'unknown'}\" — re-attach the file in the editor.`,\n );\n return null;\n }\n return {\n kind: 'text' as const,\n key: p.name ?? '',\n value: p.value ?? '',\n enabled: !p.disabled,\n };\n })\n .filter(\n (r): r is { kind: 'text'; key: string; value: string; enabled: boolean } => r !== null,\n );\n return { type: 'form-data', content: '', formRows: rows };\n }\n // Anything else: treat as text body.\n const looksLikeText = body.text !== undefined;\n if (!looksLikeText) {\n warnings.push(\n `Body mime \"${body.mimeType}\" on \"${name ?? 'unknown'}\" not imported — re-attach in the editor.`,\n );\n return { type: 'binary', content: '' };\n }\n // Try to guess body type from content prefix when mime is missing/text.\n const text = body.text ?? '';\n const trimmed = text.trim();\n let type: BodyType = 'text';\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) type = 'json';\n else if (trimmed.startsWith('<')) type = 'xml';\n return { type, content: text };\n}\n\nfunction parseAuth(\n auth: InsomniaResource['authentication'],\n warnings: string[],\n name?: string,\n): RequestAuth {\n if (!auth || !auth.type) return { type: 'none' };\n switch (auth.type) {\n case 'bearer':\n return { type: 'bearer', token: auth.token ?? '' };\n case 'basic':\n return {\n type: 'basic',\n username: auth.username ?? '',\n password: auth.password ?? '',\n };\n case 'apikey': {\n const addTo: 'header' | 'query' | 'cookie' =\n auth.addTo === 'queryParams' ? 'query' : auth.addTo === 'cookie' ? 'cookie' : 'header';\n return {\n type: 'api-key',\n key: auth.key ?? '',\n value: auth.value ?? '',\n addTo,\n };\n }\n case 'none':\n return { type: 'none' };\n default:\n warnings.push(\n `Unsupported auth type \"${auth.type}\" on \"${name ?? 'unknown'}\" — set to None. Configure manually in the editor.`,\n );\n return { type: 'none' };\n }\n}\n","// Importer for the `apicircle.folder/v1` JSON envelope produced by\n// `collectFolderExport` in `../export/folderExport.ts`.\n//\n// Pure parser — no IndexedDB / store dependencies. Validates the\n// envelope, allocates fresh ids for every folder/request/dependency so\n// the destination workspace stays collision-free, and remaps every\n// cross-entity reference (request.bodySchemaId, request.graphqlSchemaId,\n// body.attachment.globalFileAssetId, form-row globalFileAssetId,\n// folder.parentId / request.folderId) onto the new ids.\n//\n// The caller (`importApicircleFolder` in the workspace store) walks the\n// resulting `ParsedApicircleFolderExport` and grafts it into the active\n// `WorkspaceSynced`, applying name-based dedupe for global assets to\n// avoid silently shadowing the destination's existing library entries.\n\nimport type {\n Folder,\n GlobalFileAsset,\n GlobalGraphQL,\n GlobalSchema,\n Request as ApiRequest,\n} from '@apicircle/shared';\nimport { generateId } from '@apicircle/shared';\nimport {\n APICIRCLE_FOLDER_EXPORT_FORMAT,\n type ApicircleFolderExportV1,\n} from '../export/folderExport';\n\nexport interface ParsedApicircleFolderExport {\n /** The exported root folder, already assigned a fresh id. */\n rootFolder: {\n id: string;\n name: string;\n auth?: Folder['auth'];\n };\n /** Descendant folders with fresh ids + remapped parentIds. */\n subfolders: Folder[];\n /** Requests with fresh ids + remapped folderIds + remapped asset refs. */\n requests: ApiRequest[];\n /** Dependencies, ids freshly minted. */\n dependencies: {\n schemas: GlobalSchema[];\n graphql: GlobalGraphQL[];\n files: GlobalFileAsset[];\n };\n /** Source envelope's `source.folderName` — used for display copy. */\n sourceFolderName: string;\n /**\n * Notes the parser surfaced about the import — e.g. a stale dependency\n * reference that no longer existed in the source envelope. Importers\n * forward these to the UI as soft warnings.\n */\n warnings: string[];\n}\n\n/** Lightweight discriminator — `true` when `doc.format === 'apicircle.folder/v1'`. */\nexport function isApicircleFolderExport(doc: unknown): doc is ApicircleFolderExportV1 {\n if (!doc || typeof doc !== 'object') return false;\n const d = doc as { format?: unknown };\n return d.format === APICIRCLE_FOLDER_EXPORT_FORMAT;\n}\n\n/**\n * Parse + validate a raw JSON string. Throws with a single, user-readable\n * message when the input is malformed; otherwise returns a parsed shape\n * ready for the store to graft in.\n *\n * `idGenerator` is overridable for deterministic tests; defaults to\n * `generateId()` from `@apicircle/shared`.\n */\nexport function parseApicircleFolderExport(\n input: string,\n options: { idGenerator?: () => string } = {},\n): ParsedApicircleFolderExport {\n let doc: unknown;\n try {\n doc = JSON.parse(input);\n } catch (err) {\n throw new Error(`Couldn't parse JSON: ${err instanceof Error ? err.message : String(err)}`);\n }\n return parseApicircleFolderExportDoc(doc, options);\n}\n\n/**\n * Same as `parseApicircleFolderExport` but skips the JSON.parse step —\n * used by callers that already deserialized the document. Splitting the\n * entry points keeps the validation logic identical.\n */\nexport function parseApicircleFolderExportDoc(\n doc: unknown,\n options: { idGenerator?: () => string } = {},\n): ParsedApicircleFolderExport {\n const id = options.idGenerator ?? generateId;\n\n if (!isApicircleFolderExport(doc)) {\n throw new Error(\n `Unsupported format. Expected an API Circle folder export (\"format\": \"${APICIRCLE_FOLDER_EXPORT_FORMAT}\").`,\n );\n }\n\n const envelope = doc;\n validateEnvelopeShape(envelope);\n\n const warnings: string[] = [];\n\n // --- Allocate fresh ids -----------------------------------------------\n const folderIdMap = new Map<string, string>();\n folderIdMap.set(envelope.source.folderId, id());\n for (const f of envelope.folder.subfolders) folderIdMap.set(f.id, id());\n\n const requestIdMap = new Map<string, string>();\n for (const r of envelope.folder.requests) requestIdMap.set(r.id, id());\n\n const schemaIdMap = new Map<string, string>();\n for (const s of envelope.dependencies.schemas) schemaIdMap.set(s.id, id());\n const graphqlIdMap = new Map<string, string>();\n for (const g of envelope.dependencies.graphql) graphqlIdMap.set(g.id, id());\n const fileIdMap = new Map<string, string>();\n for (const f of envelope.dependencies.files) fileIdMap.set(f.id, id());\n\n // --- Remap subfolders --------------------------------------------------\n const rootFolderId = folderIdMap.get(envelope.source.folderId)!;\n const subfolders: Folder[] = envelope.folder.subfolders.map((f) => {\n const newId = folderIdMap.get(f.id)!;\n // parentId === source.folderId → remap to the new root.\n // parentId === some other source folder id → remap to its new id.\n // parentId === null (legacy export at root) → attach under new root.\n let newParentId: string | null;\n if (f.parentId === null) {\n newParentId = rootFolderId;\n } else {\n const mapped = folderIdMap.get(f.parentId);\n if (!mapped) {\n warnings.push(\n `Subfolder \"${f.name}\" referenced parentId \"${f.parentId}\" that wasn't present in the export — reattached under \"${envelope.folder.name}\".`,\n );\n newParentId = rootFolderId;\n } else {\n newParentId = mapped;\n }\n }\n return {\n ...f,\n id: newId,\n parentId: newParentId,\n auth: f.auth ? { ...f.auth } : undefined,\n };\n });\n\n // --- Remap dependencies -----------------------------------------------\n const schemas: GlobalSchema[] = envelope.dependencies.schemas.map((s) => ({\n ...s,\n id: schemaIdMap.get(s.id)!,\n }));\n const graphql: GlobalGraphQL[] = envelope.dependencies.graphql.map((g) => ({\n ...g,\n id: graphqlIdMap.get(g.id)!,\n }));\n const files: GlobalFileAsset[] = envelope.dependencies.files.map((f) => ({\n ...f,\n id: fileIdMap.get(f.id)!,\n }));\n\n // --- Remap requests ----------------------------------------------------\n const requests: ApiRequest[] = envelope.folder.requests.map((r) => {\n const newId = requestIdMap.get(r.id)!;\n // folderId may be null (legacy export at root) — attach to new root.\n let newFolderId: string | null;\n if (r.folderId === null) {\n newFolderId = rootFolderId;\n } else {\n const mapped = folderIdMap.get(r.folderId);\n if (!mapped) {\n warnings.push(\n `Request \"${r.name}\" referenced folderId \"${r.folderId}\" that wasn't present in the export — reattached under \"${envelope.folder.name}\".`,\n );\n newFolderId = rootFolderId;\n } else {\n newFolderId = mapped;\n }\n }\n\n const bodySchemaId = remapDependencyRef(\n r.bodySchemaId,\n schemaIdMap,\n `Request \"${r.name}\".bodySchemaId`,\n warnings,\n );\n const graphqlSchemaId = remapDependencyRef(\n r.graphqlSchemaId,\n graphqlIdMap,\n `Request \"${r.name}\".graphqlSchemaId`,\n warnings,\n );\n\n return {\n ...r,\n id: newId,\n folderId: newFolderId,\n bodySchemaId,\n graphqlSchemaId,\n headers: r.headers.map((h) => ({ ...h })),\n query: r.query.map((q) => ({ ...q })),\n pathParams: r.pathParams ? { ...r.pathParams } : undefined,\n cookies: r.cookies ? r.cookies.map((c) => ({ ...c })) : undefined,\n body: remapBodyFileRefs(r.body, fileIdMap, r.name, warnings),\n auth: { ...r.auth },\n contextVars: r.contextVars.map((v) => ({ ...v })),\n extractions: r.extractions.map((e) => ({ ...e })),\n assertions: r.assertions.map((a) => ({ ...a })),\n };\n });\n\n return {\n rootFolder: {\n id: rootFolderId,\n name: envelope.folder.name,\n auth: envelope.folder.auth ? { ...envelope.folder.auth } : undefined,\n },\n subfolders,\n requests,\n dependencies: { schemas, graphql, files },\n sourceFolderName: envelope.source.folderName,\n warnings,\n };\n}\n\n// -- internals --------------------------------------------------------------\n\nfunction validateEnvelopeShape(envelope: ApicircleFolderExportV1): void {\n if (!envelope.folder || typeof envelope.folder !== 'object') {\n throw new Error('API Circle folder export is missing the \"folder\" section.');\n }\n if (typeof envelope.folder.name !== 'string' || envelope.folder.name.length === 0) {\n throw new Error('API Circle folder export must have a non-empty \"folder.name\".');\n }\n if (!Array.isArray(envelope.folder.subfolders)) {\n throw new Error('API Circle folder export must have a \"folder.subfolders\" array.');\n }\n if (!Array.isArray(envelope.folder.requests)) {\n throw new Error('API Circle folder export must have a \"folder.requests\" array.');\n }\n if (!envelope.dependencies || typeof envelope.dependencies !== 'object') {\n throw new Error('API Circle folder export is missing the \"dependencies\" section.');\n }\n if (\n !Array.isArray(envelope.dependencies.schemas) ||\n !Array.isArray(envelope.dependencies.graphql) ||\n !Array.isArray(envelope.dependencies.files)\n ) {\n throw new Error(\n 'API Circle folder export \"dependencies\" must have schemas / graphql / files arrays.',\n );\n }\n if (!envelope.source || typeof envelope.source !== 'object') {\n throw new Error('API Circle folder export is missing the \"source\" section.');\n }\n if (\n typeof envelope.source.folderId !== 'string' ||\n typeof envelope.source.folderName !== 'string'\n ) {\n throw new Error('API Circle folder export \"source\" must include \"folderId\" and \"folderName\".');\n }\n}\n\nfunction remapDependencyRef(\n value: string | null | undefined,\n map: Map<string, string>,\n label: string,\n warnings: string[],\n): string | null | undefined {\n if (value === null || value === undefined) return value;\n const mapped = map.get(value);\n if (mapped) return mapped;\n warnings.push(\n `${label} referenced a dependency (\"${value}\") that wasn't embedded in the export — reference dropped on import.`,\n );\n return null;\n}\n\nfunction remapBodyFileRefs(\n body: ApiRequest['body'],\n fileIdMap: Map<string, string>,\n requestName: string,\n warnings: string[],\n): ApiRequest['body'] {\n if (body.type === 'binary') {\n if (!body.attachment) return { ...body };\n const oldId = body.attachment.globalFileAssetId;\n let nextGlobalFileAssetId: string | null | undefined = oldId;\n if (oldId) {\n const mapped = fileIdMap.get(oldId);\n if (mapped) {\n nextGlobalFileAssetId = mapped;\n } else {\n warnings.push(\n `Request \"${requestName}\".body.attachment referenced file asset \"${oldId}\" that wasn't embedded in the export — re-attach the file after import.`,\n );\n nextGlobalFileAssetId = null;\n }\n }\n return {\n ...body,\n attachment: {\n ...body.attachment,\n // Reset slotId — the destination workspace owns its own slots.\n slotId: null,\n globalFileAssetId: nextGlobalFileAssetId,\n },\n };\n }\n if (body.type === 'form-data') {\n const formRows = body.formRows?.map((row) => {\n if (row.kind !== 'file') return { ...row };\n const oldId = row.globalFileAssetId;\n let nextGlobalFileAssetId: string | null | undefined = oldId;\n if (oldId) {\n const mapped = fileIdMap.get(oldId);\n if (mapped) {\n nextGlobalFileAssetId = mapped;\n } else {\n warnings.push(\n `Request \"${requestName}\" form-data row \"${row.key}\" referenced file asset \"${oldId}\" that wasn't embedded in the export — re-attach the file after import.`,\n );\n nextGlobalFileAssetId = null;\n }\n }\n return {\n ...row,\n slotId: null,\n globalFileAssetId: nextGlobalFileAssetId,\n };\n });\n return { ...body, formRows };\n }\n return { ...body };\n}\n","// Credential detection + opt-in redaction for `apicircle.folder/v1`\n// exports.\n//\n// The export envelope copies `RequestAuth` verbatim from the source\n// workspace, which means it can carry live secrets (bearer tokens,\n// OAuth2 client secrets / refresh tokens, AWS secret keys, NTLM\n// passwords, JWT signing material, …). Letting a user click \"Download\"\n// without confronting them with what's about to leave the workspace is\n// the same kind of bug `redactForGit` exists to prevent on the Git path\n// — except the export path is a *user-initiated* share, so the right\n// model is opt-in inclusion rather than silent redaction.\n//\n// Two pure helpers below:\n//\n// 1. `collectFolderExportCredentials(envelope)` — enumerates every\n// credential-bearing field inside the envelope's `folder.auth`,\n// `subfolders[*].auth`, and `requests[*].auth`. Returns one\n// `FolderExportCredential` per field, with a stable composite id\n// the UI can use as a React key and as the index into the\n// include-set.\n//\n// 2. `redactFolderExportCredentials(envelope, include)` — returns a\n// new envelope with EVERY detected credential blanked, except\n// the ones whose ids appear in `include`. Pure; safe to call on\n// partial envelopes. The default-redact-all semantics match the\n// Modal's UI: every checkbox starts unchecked, so by default the\n// downloaded file carries zero secrets.\n\nimport type { RequestAuth } from '@apicircle/shared';\nimport type { ApicircleFolderExportV1 } from './folderExport';\n\n/**\n * One credential-bearing field discovered inside an export envelope.\n *\n * `id` is a stable composite that survives ordering / re-serialization\n * — UIs can use it as the React key and as the `include` set member.\n *\n * Format:\n * - Root folder auth: `folder:<envelope.source.folderId>.<authType>.<field>`\n * - Subfolder auth: `folder:<subfolder.id>.<authType>.<field>`\n * - Request auth: `request:<request.id>.<authType>.<field>`\n */\nexport interface FolderExportCredential {\n id: string;\n /** Where the credential lives in the envelope. */\n scope: 'root-folder' | 'subfolder' | 'request';\n /** Discriminator of the auth variant that owns the field. */\n authType: RequestAuth['type'];\n /** Field name on the auth object (e.g. \"token\", \"password\", \"clientSecret\"). */\n field: string;\n /** Human-readable label for the UI (\"Bearer · token\"). */\n label: string;\n /**\n * Where this credential belongs to. For requests this is the\n * request name; for folders it's the folder name. UIs use this to\n * group rows so the user can see which entity is leaking what.\n */\n ownerName: string;\n /** Source-workspace id of the request/folder that owns this field. */\n ownerId: string;\n}\n\n/**\n * Sorted, stable list of every credential-bearing field in the envelope.\n *\n * Determinism: rows are ordered by `(scope-rank, ownerName, field)` so\n * the same envelope always produces the same UI row order. Re-running\n * the detector after the user toggles include-checkboxes returns the\n * same list with the same ids — the UI never needs to remap state.\n *\n * Pure — does not mutate the envelope.\n */\nexport function collectFolderExportCredentials(\n envelope: ApicircleFolderExportV1,\n): FolderExportCredential[] {\n const out: FolderExportCredential[] = [];\n\n if (envelope.folder.auth) {\n out.push(\n ...authCredentialFields(envelope.folder.auth).map((f) =>\n buildCredential(\n 'root-folder',\n envelope.source.folderId,\n envelope.folder.name,\n envelope.folder.auth as RequestAuth,\n f,\n ),\n ),\n );\n }\n for (const sub of envelope.folder.subfolders) {\n if (!sub.auth) continue;\n out.push(\n ...authCredentialFields(sub.auth).map((f) =>\n buildCredential('subfolder', sub.id, sub.name, sub.auth as RequestAuth, f),\n ),\n );\n }\n for (const req of envelope.folder.requests) {\n out.push(\n ...authCredentialFields(req.auth).map((f) =>\n buildCredential('request', req.id, req.name, req.auth, f),\n ),\n );\n }\n\n return out.sort(credentialCompare);\n}\n\n/**\n * Return a new envelope with every credential-bearing field blanked,\n * except for fields whose `id` appears in `includeIds`. The default\n * (empty `includeIds`) redacts everything — that's the safe default\n * the modal uses when the user hasn't explicitly opted any credential\n * in.\n *\n * The redaction shape mirrors `redactForGit`: credential FIELDS go to\n * `''`, identity fields (`clientId`, `username`, `tokenUrl`, …) stay so\n * the importer still knows which IdP the request originally talked to.\n */\nexport function redactFolderExportCredentials(\n envelope: ApicircleFolderExportV1,\n includeIds: ReadonlySet<string> = new Set(),\n): ApicircleFolderExportV1 {\n const next: ApicircleFolderExportV1 = {\n ...envelope,\n folder: {\n ...envelope.folder,\n auth: envelope.folder.auth\n ? redactAuthForScope(\n envelope.folder.auth,\n credentialIdsFor('root-folder', envelope.source.folderId, envelope.folder.auth),\n includeIds,\n )\n : envelope.folder.auth,\n subfolders: envelope.folder.subfolders.map((sub) => {\n if (!sub.auth) return sub;\n const ids = credentialIdsFor('subfolder', sub.id, sub.auth);\n return {\n ...sub,\n auth: redactAuthForScope(sub.auth, ids, includeIds),\n };\n }),\n requests: envelope.folder.requests.map((req) => ({\n ...req,\n auth: redactAuthForScope(\n req.auth,\n credentialIdsFor('request', req.id, req.auth),\n includeIds,\n ),\n })),\n },\n };\n return next;\n}\n\n// -- internals --------------------------------------------------------------\n\ninterface CredentialFieldDescriptor {\n field: string;\n /** Short variant label used in the UI (\"Bearer · token\"). */\n label: string;\n}\n\n/**\n * Return the credential-bearing fields for a given auth variant. Order\n * matters — the UI renders rows in this order so semantically-related\n * fields stay grouped (e.g. `clientSecret` first, then `accessToken`,\n * then `refreshToken` for OAuth2).\n */\nfunction authCredentialFields(auth: RequestAuth): CredentialFieldDescriptor[] {\n switch (auth.type) {\n case 'none':\n case 'inherit':\n case 'custom-header':\n // `custom-header.value` could be a secret but `redactForGit` also\n // refuses to redact it — users wanting secret semantics should\n // route through Secret Vault + variable interpolation. Same\n // policy here.\n return [];\n case 'basic':\n return [{ field: 'password', label: 'Basic · password' }];\n case 'bearer':\n return auth.token ? [{ field: 'token', label: 'Bearer · token' }] : [];\n case 'api-key':\n return auth.value ? [{ field: 'value', label: 'API key · value' }] : [];\n case 'digest':\n return [{ field: 'password', label: 'Digest · password' }];\n case 'ntlm':\n return [{ field: 'password', label: 'NTLM · password' }];\n case 'hawk':\n return auth.hawkKey ? [{ field: 'hawkKey', label: 'Hawk · hawkKey' }] : [];\n case 'jwt-bearer':\n return [\n ...(auth.secretOrKey ? [{ field: 'secretOrKey', label: 'JWT · secretOrKey' }] : []),\n ...(auth.token ? [{ field: 'token', label: 'JWT · token' }] : []),\n ];\n case 'aws-sigv4':\n return [\n ...(auth.secretAccessKey\n ? [{ field: 'secretAccessKey', label: 'AWS SigV4 · secretAccessKey' }]\n : []),\n ...(auth.sessionToken\n ? [{ field: 'sessionToken', label: 'AWS SigV4 · sessionToken' }]\n : []),\n ];\n case 'oauth2-client-credentials':\n case 'oauth2-auth-code':\n case 'oauth2-pkce':\n return [\n ...(auth.clientSecret\n ? [{ field: 'clientSecret', label: `${auth.type} · clientSecret` }]\n : []),\n ...(auth.accessToken\n ? [{ field: 'accessToken', label: `${auth.type} · accessToken` }]\n : []),\n ...(auth.refreshToken\n ? [{ field: 'refreshToken', label: `${auth.type} · refreshToken` }]\n : []),\n ];\n case 'oauth2-password':\n return [\n ...(auth.clientSecret\n ? [{ field: 'clientSecret', label: 'oauth2-password · clientSecret' }]\n : []),\n ...(auth.password ? [{ field: 'password', label: 'oauth2-password · password' }] : []),\n ...(auth.accessToken\n ? [{ field: 'accessToken', label: 'oauth2-password · accessToken' }]\n : []),\n ...(auth.refreshToken\n ? [{ field: 'refreshToken', label: 'oauth2-password · refreshToken' }]\n : []),\n ];\n case 'oauth2-implicit':\n return auth.accessToken\n ? [{ field: 'accessToken', label: 'oauth2-implicit · accessToken' }]\n : [];\n case 'oauth2-device':\n return [\n ...(auth.accessToken\n ? [{ field: 'accessToken', label: 'oauth2-device · accessToken' }]\n : []),\n ...(auth.refreshToken\n ? [{ field: 'refreshToken', label: 'oauth2-device · refreshToken' }]\n : []),\n ];\n default:\n // Exhaustiveness fallback — same shape as `redactAuthForScope`\n // below. Any synthetic value reaching this arm has no known\n // credential fields, so we surface an empty list.\n return [];\n }\n}\n\nfunction buildCredential(\n scope: FolderExportCredential['scope'],\n ownerId: string,\n ownerName: string,\n auth: RequestAuth,\n desc: CredentialFieldDescriptor,\n): FolderExportCredential {\n const prefix = scope === 'request' ? 'request' : 'folder';\n return {\n id: `${prefix}:${ownerId}.${auth.type}.${desc.field}`,\n scope,\n authType: auth.type,\n field: desc.field,\n label: desc.label,\n ownerName,\n ownerId,\n };\n}\n\nfunction credentialIdsFor(\n scope: FolderExportCredential['scope'],\n ownerId: string,\n auth: RequestAuth,\n): Map<string, string> {\n const ids = new Map<string, string>(); // field -> id\n const prefix = scope === 'request' ? 'request' : 'folder';\n for (const desc of authCredentialFields(auth)) {\n ids.set(desc.field, `${prefix}:${ownerId}.${auth.type}.${desc.field}`);\n }\n return ids;\n}\n\n/**\n * Apply redaction to a single auth value. Any credential field whose\n * id is in `includeIds` is preserved verbatim; the rest are blanked.\n * Variants with no credential fields (`none` / `inherit` / `custom-header`\n * + the unknown-variant default) fall through unchanged.\n */\nfunction redactAuthForScope(\n auth: RequestAuth,\n ids: Map<string, string>,\n includeIds: ReadonlySet<string>,\n): RequestAuth {\n const shouldBlank = (field: string): boolean => {\n const id = ids.get(field);\n return !!id && !includeIds.has(id);\n };\n\n // Spread per-variant so TS keeps each branch's exact shape.\n switch (auth.type) {\n case 'none':\n case 'inherit':\n case 'custom-header':\n return auth;\n case 'basic':\n return shouldBlank('password') ? { ...auth, password: '' } : auth;\n case 'bearer':\n return shouldBlank('token') ? { ...auth, token: '' } : auth;\n case 'api-key':\n return shouldBlank('value') ? { ...auth, value: '' } : auth;\n case 'digest':\n return shouldBlank('password') ? { ...auth, password: '' } : auth;\n case 'ntlm':\n return shouldBlank('password') ? { ...auth, password: '' } : auth;\n case 'hawk':\n return shouldBlank('hawkKey') ? { ...auth, hawkKey: '' } : auth;\n case 'jwt-bearer':\n return {\n ...auth,\n secretOrKey: shouldBlank('secretOrKey') ? '' : auth.secretOrKey,\n token: shouldBlank('token') ? '' : auth.token,\n };\n case 'aws-sigv4':\n return {\n ...auth,\n secretAccessKey: shouldBlank('secretAccessKey') ? '' : auth.secretAccessKey,\n sessionToken: shouldBlank('sessionToken') ? '' : auth.sessionToken,\n };\n case 'oauth2-client-credentials':\n case 'oauth2-auth-code':\n case 'oauth2-pkce':\n return {\n ...auth,\n clientSecret: shouldBlank('clientSecret') ? '' : auth.clientSecret,\n accessToken: shouldBlank('accessToken') ? '' : auth.accessToken,\n refreshToken: shouldBlank('refreshToken') ? '' : auth.refreshToken,\n };\n case 'oauth2-password':\n return {\n ...auth,\n clientSecret: shouldBlank('clientSecret') ? '' : auth.clientSecret,\n password: shouldBlank('password') ? '' : auth.password,\n accessToken: shouldBlank('accessToken') ? '' : auth.accessToken,\n refreshToken: shouldBlank('refreshToken') ? '' : auth.refreshToken,\n };\n case 'oauth2-implicit':\n return {\n ...auth,\n accessToken: shouldBlank('accessToken') ? '' : auth.accessToken,\n };\n case 'oauth2-device':\n return {\n ...auth,\n accessToken: shouldBlank('accessToken') ? '' : auth.accessToken,\n refreshToken: shouldBlank('refreshToken') ? '' : auth.refreshToken,\n };\n default:\n // The discriminated union above is exhaustive. An unknown-variant\n // value can only reach this arm via a deliberate cast (e.g. a\n // future auth type added without wiring this switch); we return\n // it unchanged rather than throwing so the export still produces\n // a valid envelope.\n return auth;\n }\n}\n\nfunction scopeRank(scope: FolderExportCredential['scope']): number {\n if (scope === 'root-folder') return 0;\n if (scope === 'subfolder') return 1;\n return 2;\n}\n\nfunction credentialCompare(a: FolderExportCredential, b: FolderExportCredential): number {\n const r = scopeRank(a.scope) - scopeRank(b.scope);\n if (r !== 0) return r;\n // Tiebreak by owner name only — within a single owner we rely on\n // JS's stable Array.prototype.sort to preserve the per-variant field\n // order from `authCredentialFields` (which puts e.g. clientSecret →\n // accessToken → refreshToken in semantic order).\n return a.ownerName.localeCompare(b.ownerName, undefined, { sensitivity: 'base' });\n}\n","// Folder → JSON export (API Circle exchange format `apicircle.folder/v1`).\n//\n// Produces a self-describing envelope a teammate can import back into any\n// other API Circle workspace via `ImportModal` / the headless\n// `parseApicircleFolderExport` parser. The envelope is intentionally\n// additive on top of the existing `'apicircle'` source-format slot in\n// `ImportModal` — round-tripping an export through a fresh workspace must\n// not silently drop fields.\n//\n// Embedded vs. referenced dependencies:\n// - JSON Schemas + GraphQL definitions are pure text. We embed the full\n// entity so the importer can recreate them in the destination\n// workspace without any extra user action.\n// - Global file assets carry BYTES outside `workspace.synced.json` (Git\n// LFS sidecar under `.apicircle/attachments/<slotId>`). The envelope\n// therefore captures only metadata (name, filename, size, mimeType,\n// sha256) so the importer can show the user a clear \"re-attach these\n// files\" cue. Bytes never travel through the JSON.\n//\n// All envelope `id` fields refer to the SOURCE workspace's ids. The\n// importer is expected to remint them on its side to avoid collisions\n// (`apicircleFolder.ts` does this).\n\nimport type {\n Folder,\n GlobalFileAsset,\n GlobalGraphQL,\n GlobalSchema,\n Request as ApiRequest,\n WorkspaceSynced,\n} from '@apicircle/shared';\nimport {\n collectFolderExportCredentials,\n type FolderExportCredential,\n} from './folderExportCredentials';\n\n/** Envelope discriminator. Bump the version suffix on a breaking shape change. */\nexport const APICIRCLE_FOLDER_EXPORT_FORMAT = 'apicircle.folder/v1';\n\nexport interface ApicircleFolderExportV1 {\n format: typeof APICIRCLE_FOLDER_EXPORT_FORMAT;\n /** ISO timestamp of when the export was generated. */\n exportedAt: string;\n /** App version that produced the export (free-form string). */\n appVersion: string;\n /** Loose breadcrumb back to the source — never required by importers. */\n source: {\n workspaceId: string;\n folderId: string;\n folderName: string;\n };\n folder: {\n /** Display name of the exported root folder. */\n name: string;\n /** Folder-level auth, if any was set on the source root folder. */\n auth?: Folder['auth'];\n /**\n * Descendant folders (NOT including the root). `parentId` is the\n * source workspace's id of the parent — when it equals `source.folderId`\n * the folder lives directly under the exported root.\n */\n subfolders: Folder[];\n /**\n * All requests inside the exported subtree. `folderId` is the source\n * id of the immediate parent folder; the importer remaps it onto the\n * destination workspace's freshly-minted ids.\n */\n requests: ApiRequest[];\n };\n /**\n * Captured global-asset dependencies referenced by the exported\n * requests. Schemas/GraphQL travel embedded; files travel\n * metadata-only.\n */\n dependencies: ApicircleFolderExportDependencies;\n}\n\nexport interface ApicircleFolderExportDependencies {\n schemas: GlobalSchema[];\n graphql: GlobalGraphQL[];\n /**\n * File-asset METADATA only. The `slotId` is preserved so the importer\n * can correlate against an existing slot on the destination side if\n * one happens to match; otherwise the user is prompted to re-attach.\n */\n files: GlobalFileAsset[];\n}\n\n/**\n * Plain-language summary of what the export contains, surfaced inside the\n * Export Folder modal so the user knows exactly what's leaving the\n * workspace before they click Download.\n */\nexport interface FolderExportReport {\n folderName: string;\n requestCount: number;\n subfolderCount: number;\n /** Total folder count INCLUDING the exported root. */\n totalFolderCount: number;\n dependencies: {\n schemas: Array<{ id: string; name: string }>;\n graphql: Array<{ id: string; name: string; kind: GlobalGraphQL['kind'] }>;\n files: Array<{\n id: string;\n name: string;\n filename: string;\n size: number;\n mimeType: string;\n }>;\n };\n /** Convenience flag — `true` when any dependency was captured. */\n hasDependencies: boolean;\n /**\n * Every credential-bearing field detected inside the envelope's auth\n * blocks (root folder, subfolders, requests). Surfaced by the export\n * modal so the user can opt-in per-field before the file leaves the\n * workspace. Defaults to \"redact everything\" — see\n * `redactFolderExportCredentials`.\n */\n credentials: FolderExportCredential[];\n /** Convenience flag — `true` when any credential was detected. */\n hasCredentials: boolean;\n}\n\nexport interface CollectFolderExportArgs {\n synced: WorkspaceSynced;\n folderId: string;\n /** Defaults to `new Date().toISOString()` — overridable for deterministic tests. */\n now?: string;\n /** Defaults to `'apicircle-studio'` — overridable for deterministic tests. */\n appVersion?: string;\n}\n\nexport interface CollectFolderExportResult {\n envelope: ApicircleFolderExportV1;\n report: FolderExportReport;\n}\n\n/**\n * Walk the subtree rooted at `folderId`, collect its requests + descendant\n * folders, gather every referenced global-asset dependency, and assemble\n * a self-describing export envelope.\n *\n * Returns `null` when `folderId` doesn't exist — UI callers should treat\n * that as a no-op (the source folder was deleted between menu open and\n * click).\n */\nexport function collectFolderExport(\n args: CollectFolderExportArgs,\n): CollectFolderExportResult | null {\n const { synced, folderId } = args;\n const root = synced.collections.folders[folderId];\n if (!root) return null;\n\n const now = args.now ?? new Date().toISOString();\n const appVersion = args.appVersion ?? 'apicircle-studio';\n\n // Walk the descendant folder graph by parentId chain — same idiom\n // `removeFolder` / `duplicateFolder` use.\n const folderIds = new Set<string>([folderId]);\n let grew = true;\n while (grew) {\n grew = false;\n for (const f of Object.values(synced.collections.folders)) {\n if (folderIds.has(f.id)) continue;\n if (f.parentId && folderIds.has(f.parentId)) {\n folderIds.add(f.id);\n grew = true;\n }\n }\n }\n\n // Descendants don't include the root itself — the root carries its own\n // `name` / `auth` on `envelope.folder.*`.\n const subfolders: Folder[] = [];\n for (const f of Object.values(synced.collections.folders)) {\n if (f.id !== folderId && folderIds.has(f.id)) subfolders.push(cloneFolder(f));\n }\n\n const requests: ApiRequest[] = [];\n for (const r of Object.values(synced.collections.requests)) {\n if (r.folderId && folderIds.has(r.folderId)) requests.push(cloneRequest(r));\n }\n\n const dependencies = collectDependencies(synced, requests);\n\n const envelope: ApicircleFolderExportV1 = {\n format: APICIRCLE_FOLDER_EXPORT_FORMAT,\n exportedAt: now,\n appVersion,\n source: {\n workspaceId: synced.workspaceId,\n folderId,\n folderName: root.name,\n },\n folder: {\n name: root.name,\n auth: root.auth,\n subfolders,\n requests,\n },\n dependencies,\n };\n\n const report = buildReport(envelope);\n return { envelope, report };\n}\n\n/** JSON-stringify an envelope with stable, human-friendly formatting (2-space indent). */\nexport function serializeFolderExport(envelope: ApicircleFolderExportV1): string {\n return JSON.stringify(envelope, null, 2);\n}\n\n/** Filename the UI uses for the downloaded file. Slugifies the folder name. */\nexport function suggestFolderExportFilename(envelope: ApicircleFolderExportV1): string {\n const slug = envelope.folder.name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n const base = slug || 'folder';\n return `${base}.apicircle.json`;\n}\n\n// -- internals --------------------------------------------------------------\n\nfunction cloneFolder(f: Folder): Folder {\n return {\n ...f,\n auth: f.auth ? { ...f.auth } : undefined,\n };\n}\n\nfunction cloneRequest(r: ApiRequest): ApiRequest {\n return {\n ...r,\n headers: r.headers.map((h) => ({ ...h })),\n query: r.query.map((q) => ({ ...q })),\n pathParams: r.pathParams ? { ...r.pathParams } : undefined,\n cookies: r.cookies ? r.cookies.map((c) => ({ ...c })) : undefined,\n body: cloneBody(r.body),\n auth: { ...r.auth },\n contextVars: r.contextVars.map((v) => ({ ...v })),\n extractions: r.extractions.map((e) => ({ ...e })),\n assertions: r.assertions.map((a) => ({ ...a })),\n };\n}\n\nfunction cloneBody(body: ApiRequest['body']): ApiRequest['body'] {\n if (body.type === 'form-data') {\n return {\n ...body,\n formRows: body.formRows?.map((row) => ({ ...row })) ?? body.formRows,\n };\n }\n if (body.type === 'binary') {\n return {\n ...body,\n attachment: body.attachment ? { ...body.attachment } : undefined,\n };\n }\n return { ...body };\n}\n\nfunction collectDependencies(\n synced: WorkspaceSynced,\n requests: ApiRequest[],\n): ApicircleFolderExportDependencies {\n const schemaIds = new Set<string>();\n const graphqlIds = new Set<string>();\n const fileIds = new Set<string>();\n\n for (const r of requests) {\n if (r.bodySchemaId) schemaIds.add(r.bodySchemaId);\n if (r.graphqlSchemaId) graphqlIds.add(r.graphqlSchemaId);\n if (r.body.type === 'binary' && r.body.attachment?.globalFileAssetId) {\n fileIds.add(r.body.attachment.globalFileAssetId);\n }\n if (r.body.type === 'form-data' && r.body.formRows) {\n for (const row of r.body.formRows) {\n if (row.kind === 'file' && row.globalFileAssetId) fileIds.add(row.globalFileAssetId);\n }\n }\n }\n\n const assets = synced.globalAssets;\n const schemas: GlobalSchema[] = [];\n for (const id of schemaIds) {\n const s = assets.schemas[id];\n if (s) schemas.push({ ...s });\n }\n const graphql: GlobalGraphQL[] = [];\n for (const id of graphqlIds) {\n const g = assets.graphql[id];\n if (g) graphql.push({ ...g });\n }\n const files: GlobalFileAsset[] = [];\n for (const id of fileIds) {\n const f = assets.files?.[id];\n if (f) files.push({ ...f });\n }\n\n // Stable ordering — name then id — so identical workspaces produce\n // identical JSON regardless of Object.values iteration order.\n schemas.sort(byNameThenId);\n graphql.sort(byNameThenId);\n files.sort(byNameThenId);\n\n return { schemas, graphql, files };\n}\n\nfunction byNameThenId<T extends { id: string; name: string }>(a: T, b: T): number {\n const c = a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });\n return c !== 0 ? c : a.id.localeCompare(b.id);\n}\n\nfunction buildReport(envelope: ApicircleFolderExportV1): FolderExportReport {\n const subfolderCount = envelope.folder.subfolders.length;\n const requestCount = envelope.folder.requests.length;\n const totalFolderCount = subfolderCount + 1; // include the exported root\n const credentials = collectFolderExportCredentials(envelope);\n\n return {\n folderName: envelope.folder.name,\n requestCount,\n subfolderCount,\n totalFolderCount,\n dependencies: {\n schemas: envelope.dependencies.schemas.map((s) => ({ id: s.id, name: s.name })),\n graphql: envelope.dependencies.graphql.map((g) => ({\n id: g.id,\n name: g.name,\n kind: g.kind,\n })),\n files: envelope.dependencies.files.map((f) => ({\n id: f.id,\n name: f.name,\n filename: f.filename,\n size: f.size,\n mimeType: f.mimeType,\n })),\n },\n hasDependencies:\n envelope.dependencies.schemas.length > 0 ||\n envelope.dependencies.graphql.length > 0 ||\n envelope.dependencies.files.length > 0,\n credentials,\n hasCredentials: credentials.length > 0,\n };\n}\n","// Importer for the `apicircleEnvironment: 1 | 2` JSON envelope produced by\n// `exportEnvironment` in `../../../ui-components/src/store/envActions.ts`\n// (and by the MCP `environment.export` tool in\n// `../../../mcp-server/src/tools/crud.ts`). Sister parser to\n// `./apicircleFolder.ts` — same surface, different document.\n//\n// Shape (v2 — current, matches Git push/pull) — encrypted rows carry their\n// ciphertext + the per-slot salt so the destination can attempt the same\n// decrypt the request-execute path would (derive a key from the LOCAL slot\n// plaintext + the SOURCE salt, then AES-GCM unwrap):\n//\n// {\n// \"apicircleEnvironment\": 2,\n// \"name\": \"dev\",\n// \"variables\": [\n// { \"key\": \"API_BASE\", \"value\": \"https://api.example.com\", \"encrypted\": false },\n// {\n// \"key\": \"TOKEN\",\n// \"encrypted\": true,\n// \"value\": \"enc:v1:<iv>:<ciphertext>\",\n// \"secretKeyId\": \"sec_abc\",\n// \"secret\": { \"label\": \"PROD_TOKEN\", \"salt\": \"base64salt==\" }\n// }\n// ]\n// }\n//\n// Shape (v1 — legacy, surface-only) — encrypted rows carry slot METADATA\n// but not the ciphertext or salt, so the destination must prompt the user\n// for a plaintext value during import. Still supported so existing exports\n// continue to import without surprise:\n//\n// {\n// \"apicircleEnvironment\": 1,\n// \"name\": \"dev\",\n// \"variables\": [\n// { \"key\": \"TOKEN\", \"encrypted\": true, \"secretKeyId\": \"sec_abc\", \"secret\": { \"label\": \"PROD_TOKEN\" } }\n// ]\n// }\n//\n// Plain rows round-trip in full in both versions. Encrypted rows surface an\n// `encryptedBindingHint` so the caller can match against the destination's\n// vault. v2 hints additionally carry `ciphertext` + `salt` so the importer\n// can land the encrypted row directly; v1 hints fall back to the prompt-the-\n// user-for-value path.\n\nimport type { EnvironmentVariable } from '@apicircle/shared';\n\nexport interface ParsedApicircleEnvironment {\n name: string;\n /**\n * The variables that should land in the destination env, in the same\n * order as the source. Encrypted rows arrive with the SOURCE'S\n * `secretKeyId`; the caller is responsible for re-pointing the binding\n * to a destination-local slot id (or leaving it dangling until the user\n * fixes it).\n *\n * In v2, encrypted rows arrive with their ciphertext intact in `value`;\n * the importer can choose to land it as-is so the request-execute path\n * decrypts naturally when the user provides the matching slot value.\n * In v1, encrypted rows arrive with `value: ''` and the importer must\n * surface a pendingBinding for the user to type a fresh plaintext.\n */\n variables: EnvironmentVariable[];\n /**\n * Per encrypted row, the slot metadata the export carried. The store\n * action uses this to (a) reuse an existing destination slot by label\n * match, (b) reuse by `originSecretKeyId` for same-workspace re-imports,\n * or (c) surface a pendingBinding so the UI can prompt the user.\n * Indices line up with `variables` for the corresponding row only —\n * plain rows do not appear here.\n */\n encryptedBindingHints: EncryptedBindingHint[];\n /**\n * The envelope version the export advertised — `1` (label-only, prompt\n * user for value) or `2` (ciphertext + salt carry, attempt decrypt with\n * local slot value). Importers fork on this to decide whether to land\n * the ciphertext or surface a pendingBinding.\n */\n payloadVersion: 1 | 2;\n /**\n * Soft notes the parser surfaced about the import — dropped rows,\n * demoted encrypted rows, etc. Importers forward these to the UI as\n * warnings.\n */\n warnings: string[];\n}\n\nexport interface EncryptedBindingHint {\n /** The var the hint belongs to (matches the row's `key`). */\n varKey: string;\n /**\n * The slot's display label from the source workspace. Older exports\n * (before `secret.label` shipped) didn't carry this; the parser falls\n * back to `varKey` so the UI always has SOMETHING to render.\n */\n label: string;\n /**\n * The slot id the source workspace bound to. Useful for round-tripping\n * inside the same workspace (the destination's slot id matches), but\n * meaningless on a different machine. Optional — newer exports may\n * stop carrying it once enough time passes.\n */\n originSecretKeyId?: string;\n /** `true` when the export carried no `secret.label` and the label was synthesized. */\n labelFromFallback: boolean;\n /**\n * v2 only: the source's ciphertext (`enc:v1:<iv>:<base64>`) so the\n * destination can land an encrypted row whose value the user can\n * decrypt by providing the matching slot plaintext. `null` on v1 — the\n * caller must instead prompt the user for a plaintext value and\n * re-encrypt locally.\n */\n ciphertext: string | null;\n /**\n * v2 only: the source slot's salt (base64). Required to derive the same\n * AES-GCM key the source used. `null` on v1.\n */\n salt: string | null;\n}\n\ninterface ApicircleEnvDoc {\n apicircleEnvironment?: unknown;\n name?: unknown;\n variables?: unknown;\n}\n\ninterface RawVarRow {\n key?: unknown;\n value?: unknown;\n encrypted?: unknown;\n secretKeyId?: unknown;\n secret?: unknown;\n}\n\n/** Lightweight discriminator — `true` when `doc.apicircleEnvironment` is 1 or 2. */\nexport function isApicircleEnvironment(doc: unknown): doc is {\n apicircleEnvironment: 1 | 2;\n name: string;\n variables: unknown[];\n} {\n if (!doc || typeof doc !== 'object') return false;\n const d = doc as ApicircleEnvDoc;\n return (\n (d.apicircleEnvironment === 1 || d.apicircleEnvironment === 2) &&\n typeof d.name === 'string' &&\n Array.isArray(d.variables)\n );\n}\n\n/**\n * Parse + validate a raw JSON string. Throws with a single, user-readable\n * message when the input is malformed; otherwise returns a parsed shape\n * ready for the store to graft in.\n */\nexport function parseApicircleEnvironment(input: string): ParsedApicircleEnvironment {\n let doc: unknown;\n try {\n doc = JSON.parse(input);\n } catch (err) {\n throw new Error(`Couldn't parse JSON: ${err instanceof Error ? err.message : String(err)}`);\n }\n return parseApicircleEnvironmentDoc(doc);\n}\n\n/**\n * Same as `parseApicircleEnvironment` but skips the JSON.parse step —\n * used by callers that already deserialized the document.\n */\nexport function parseApicircleEnvironmentDoc(doc: unknown): ParsedApicircleEnvironment {\n if (!isApicircleEnvironment(doc)) {\n throw new Error(\n 'Unsupported format. Expected an API Circle environment export (\"apicircleEnvironment\": 1 or 2).',\n );\n }\n\n const name = doc.name.trim();\n if (!name) {\n throw new Error('API Circle environment export must have a non-empty \"name\".');\n }\n\n const payloadVersion: 1 | 2 = doc.apicircleEnvironment;\n const warnings: string[] = [];\n const variables: EnvironmentVariable[] = [];\n const encryptedBindingHints: EncryptedBindingHint[] = [];\n\n for (let i = 0; i < doc.variables.length; i += 1) {\n const raw = doc.variables[i] as RawVarRow;\n if (!raw || typeof raw !== 'object') {\n warnings.push(`Row #${i + 1} was not an object — dropped.`);\n continue;\n }\n const key = typeof raw.key === 'string' ? raw.key.trim() : '';\n if (!key) {\n warnings.push(`Row #${i + 1} had no key — dropped.`);\n continue;\n }\n if (raw.encrypted === true) {\n const secretKeyId = typeof raw.secretKeyId === 'string' ? raw.secretKeyId : '';\n const labelFromSecret = readLabelFromSecretField(raw.secret);\n // v2 ciphertext + salt are optional even on a v2 doc — defensive\n // for documents authored by tools that flip to v2 without filling\n // them in. When either is missing we degrade to v1-style handling\n // for that row.\n const ciphertext =\n payloadVersion === 2 && typeof raw.value === 'string' && raw.value.startsWith('enc:')\n ? raw.value\n : null;\n const salt = payloadVersion === 2 ? readSaltFromSecretField(raw.secret) : null;\n if (!secretKeyId && !labelFromSecret) {\n // Truly dangling — no id and no label means there's nothing to\n // prompt the user with and nothing to bind. Demote to a plain\n // empty row so the env still loads with the var declared.\n warnings.push(\n `\"${key}\" was marked encrypted but carried no secretKeyId and no secret label — imported as an empty plain variable. Re-bind it under Environments after import.`,\n );\n variables.push({ key, value: '', encrypted: false });\n continue;\n }\n // Encrypted row: keep the source's secretKeyId on the var so\n // same-workspace re-imports stay bound. The store action resolves\n // hints against the destination's vault and re-points the id\n // (or surfaces the row as a pending binding) before persisting.\n //\n // v2: carry the ciphertext through to `value` so the importer can\n // land it directly (and the request-execute decrypt path takes\n // over once the user provides the slot value). v1: empty string —\n // importer must prompt for a plaintext value.\n variables.push({\n key,\n value: ciphertext ?? '',\n encrypted: true,\n secretKeyId: secretKeyId || undefined,\n });\n const labelFromFallback = !labelFromSecret;\n encryptedBindingHints.push({\n varKey: key,\n label: labelFromSecret ?? key,\n originSecretKeyId: secretKeyId || undefined,\n labelFromFallback,\n ciphertext,\n salt,\n });\n continue;\n }\n // Plain row.\n variables.push({\n key,\n value: typeof raw.value === 'string' ? raw.value : '',\n encrypted: false,\n });\n }\n\n return { name, variables, encryptedBindingHints, payloadVersion, warnings };\n}\n\nfunction readLabelFromSecretField(field: unknown): string | null {\n if (!field || typeof field !== 'object') return null;\n const f = field as { label?: unknown };\n if (typeof f.label !== 'string') return null;\n const trimmed = f.label.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction readSaltFromSecretField(field: unknown): string | null {\n if (!field || typeof field !== 'object') return null;\n const f = field as { salt?: unknown };\n if (typeof f.salt !== 'string') return null;\n const trimmed = f.salt.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n","import type { Assertion } from '@apicircle/shared';\nimport type { ExecutionResult } from '../request/executeRequest';\n\n/**\n * Result of evaluating one assertion against a response. Carries a snapshot\n * of the assertion definition so downstream UI (History detail view, run\n * exports, plan reports) can render the verdict without joining back to the\n * source request — which may have been renamed, edited, or deleted by the\n * time the user looks at history.\n */\nexport interface AssertionResult {\n assertionId: string;\n kind: Assertion['kind'];\n op: Assertion['op'];\n target?: string;\n expected: string | number;\n passed: boolean;\n /**\n * Human-readable explanation. Always populated by `runAssertions` — pass\n * cases get positive descriptions (\"status: 200 equals 200\"), fail cases\n * get the diff. Optional in the type because the persisted shape in\n * `RequestRun.assertions` predates this and may carry undefined for older\n * history entries.\n */\n detail?: string;\n}\n\nexport function runAssertions(\n assertions: ReadonlyArray<Assertion>,\n exec: ExecutionResult,\n): AssertionResult[] {\n return assertions.map((a) => runOne(a, exec));\n}\n\nfunction runOne(a: Assertion, exec: ExecutionResult): AssertionResult {\n switch (a.kind) {\n case 'status':\n return checkStatus(a, exec);\n case 'duration':\n return checkDuration(a, exec);\n case 'header':\n return checkHeader(a, exec);\n case 'json-path':\n return checkJsonPath(a, exec);\n }\n}\n\nfunction snapshot(\n a: Assertion,\n): Pick<AssertionResult, 'assertionId' | 'kind' | 'op' | 'target' | 'expected'> {\n return {\n assertionId: a.id,\n kind: a.kind,\n op: a.op,\n target: a.target,\n expected: a.expected,\n };\n}\n\nfunction pass(a: Assertion, detail: string): AssertionResult {\n return { ...snapshot(a), passed: true, detail };\n}\nfunction fail(a: Assertion, detail: string): AssertionResult {\n return { ...snapshot(a), passed: false, detail };\n}\n\nfunction checkStatus(a: Assertion, exec: ExecutionResult): AssertionResult {\n const got = exec.status;\n if (got === null) return fail(a, `request did not complete (got null status)`);\n return compareNumber(a, got, 'status');\n}\n\nfunction checkDuration(a: Assertion, exec: ExecutionResult): AssertionResult {\n return compareNumber(a, exec.durationMs, 'duration');\n}\n\nfunction checkHeader(a: Assertion, exec: ExecutionResult): AssertionResult {\n if (!a.target) return fail(a, 'header assertion missing target header name');\n const value = exec.headers[a.target.toLowerCase()] ?? exec.headers[a.target];\n if (value === undefined) {\n if (a.op === 'not-equals')\n return pass(a, `header \"${a.target}\" not present (passes not-equals)`);\n return fail(a, `header \"${a.target}\" not present`);\n }\n return compareString(a, value, `header \"${a.target}\"`);\n}\n\nfunction checkJsonPath(a: Assertion, exec: ExecutionResult): AssertionResult {\n if (!a.target) return fail(a, 'json-path assertion missing path');\n let parsed: unknown;\n try {\n parsed = JSON.parse(exec.body);\n } catch {\n return fail(a, 'response body is not valid JSON');\n }\n const value = readJsonPath(parsed, a.target);\n if (value === undefined) {\n if (a.op === 'not-equals') return pass(a, `path \"${a.target}\" not found (passes not-equals)`);\n return fail(a, `path \"${a.target}\" not found in response`);\n }\n if (typeof value === 'number') return compareNumber(a, value, `path \"${a.target}\"`);\n // For non-primitive values (objects, arrays), serialize as JSON so the\n // user gets a meaningful diff string rather than `[object Object]`.\n const serialized =\n typeof value === 'string'\n ? value\n : typeof value === 'boolean'\n ? String(value)\n : value === null\n ? 'null'\n : JSON.stringify(value);\n return compareString(a, serialized, `path \"${a.target}\"`);\n}\n\nfunction compareNumber(a: Assertion, actual: number, label: string): AssertionResult {\n const expected = Number(a.expected);\n if (!Number.isFinite(expected))\n return fail(a, `${label}: expected a number, got \"${a.expected}\"`);\n switch (a.op) {\n case 'equals':\n return actual === expected\n ? pass(a, `${label}: ${actual} equals ${expected}`)\n : fail(a, `${label}: expected ${expected}, got ${actual}`);\n case 'not-equals':\n return actual !== expected\n ? pass(a, `${label}: ${actual} does not equal ${expected}`)\n : fail(a, `${label}: expected not to equal ${expected}`);\n case 'lt':\n return actual < expected\n ? pass(a, `${label}: ${actual} < ${expected}`)\n : fail(a, `${label}: expected < ${expected}, got ${actual}`);\n case 'gt':\n return actual > expected\n ? pass(a, `${label}: ${actual} > ${expected}`)\n : fail(a, `${label}: expected > ${expected}, got ${actual}`);\n case 'contains':\n case 'matches':\n return fail(a, `${label}: op \"${a.op}\" not supported for numeric values`);\n }\n}\n\nfunction compareString(a: Assertion, actual: string, label: string): AssertionResult {\n const expected = String(a.expected);\n switch (a.op) {\n case 'equals':\n return actual === expected\n ? pass(a, `${label}: \"${actual}\" equals \"${expected}\"`)\n : fail(a, `${label}: expected \"${expected}\", got \"${actual}\"`);\n case 'not-equals':\n return actual !== expected\n ? pass(a, `${label}: \"${actual}\" does not equal \"${expected}\"`)\n : fail(a, `${label}: expected not to equal \"${expected}\"`);\n case 'contains':\n return actual.includes(expected)\n ? pass(a, `${label}: \"${actual}\" contains \"${expected}\"`)\n : fail(a, `${label}: expected to contain \"${expected}\", got \"${actual}\"`);\n case 'matches': {\n let re: RegExp;\n try {\n re = new RegExp(expected);\n } catch {\n return fail(a, `${label}: expected pattern is not a valid regex: ${expected}`);\n }\n return re.test(actual)\n ? pass(a, `${label}: \"${actual}\" matches /${expected}/`)\n : fail(a, `${label}: did not match pattern /${expected}/`);\n }\n case 'lt':\n case 'gt':\n return fail(a, `${label}: op \"${a.op}\" not supported for string values`);\n }\n}\n\n/**\n * Read a dotted-path value from a JSON tree. Supports `a.b.c` and bracket\n * indexing `arr[0]`. Returns `undefined` for missing segments.\n */\nexport function readJsonPath(root: unknown, path: string): unknown {\n if (!path || path === '$' || path === '.') return root;\n const trimmed = path.startsWith('$.')\n ? path.slice(2)\n : path.startsWith('$')\n ? path.slice(1)\n : path;\n const segments = trimmed\n .replace(/\\[(\\d+)\\]/g, '.$1')\n .split('.')\n .filter((s) => s.length > 0);\n let current: unknown = root;\n for (const seg of segments) {\n if (current === null || typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[seg];\n if (current === undefined) return undefined;\n }\n return current;\n}\n","// Extract values from an ExecutionResult per the request's `extractions`\n// list and return a `Record<string, string>` keyed by the user-supplied\n// `variable` names. Failures are non-fatal — a path that doesn't resolve\n// produces an empty string and a warning so the rest of the chain still\n// runs (matches v1's ResponseExtractor semantics).\n\nimport type { ContextExtraction } from '@apicircle/shared';\nimport type { ExecutionResult } from '../request/executeRequest';\nimport { readJsonPath } from '../assertions/runAssertions';\n\nexport interface ContextExtractionResult {\n extracted: Record<string, string>;\n warnings: string[];\n}\n\nfunction findHeader(headers: Record<string, string>, name: string): string | undefined {\n const lower = name.toLowerCase();\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() === lower) return v;\n }\n return undefined;\n}\n\nfunction readCookie(headers: Record<string, string>, name: string): string | undefined {\n // The browser strips Set-Cookie from cross-origin responses, but for\n // same-origin we may see it. Cookie *requests* are echoed too, so we\n // also check a `cookie` header for symmetry.\n const sources = [findHeader(headers, 'set-cookie'), findHeader(headers, 'cookie')].filter(\n (v): v is string => Boolean(v),\n );\n for (const raw of sources) {\n for (const part of raw.split(/;\\s*/)) {\n const eq = part.indexOf('=');\n if (eq === -1) continue;\n const key = part.slice(0, eq).trim();\n if (key === name) return part.slice(eq + 1);\n }\n }\n return undefined;\n}\n\nfunction stringify(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n return JSON.stringify(value);\n}\n\nexport function extractContext(\n result: ExecutionResult,\n extractions: ReadonlyArray<ContextExtraction>,\n): ContextExtractionResult {\n const extracted: Record<string, string> = {};\n const warnings: string[] = [];\n\n for (const config of extractions) {\n if (!config.enabled) continue;\n const variable = config.variable.trim();\n if (!variable) {\n warnings.push('Skipping extraction with empty variable name');\n continue;\n }\n\n let value: string | undefined;\n switch (config.source) {\n case 'status':\n value = result.status === null ? '' : String(result.status);\n break;\n case 'header':\n value = findHeader(result.headers, config.path.trim());\n if (value === undefined) {\n warnings.push(`Header \"${config.path}\" not found for \"${variable}\"`);\n }\n break;\n case 'cookie':\n value = readCookie(result.headers, config.path.trim());\n if (value === undefined) {\n warnings.push(`Cookie \"${config.path}\" not found for \"${variable}\"`);\n }\n break;\n case 'body': {\n if (result.body.length === 0) {\n warnings.push(`Body is empty — skipping \"${variable}\"`);\n break;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(result.body);\n } catch {\n warnings.push(`Body is not JSON — cannot extract \"${variable}\"`);\n break;\n }\n const found = readJsonPath(parsed, config.path);\n if (found === undefined) {\n warnings.push(`Body path \"${config.path}\" did not resolve for \"${variable}\"`);\n } else {\n value = stringify(found);\n }\n break;\n }\n }\n\n // When the extraction failed (value is undefined), DON'T bind the\n // variable. Binding it to '' produces a silent defined-as-empty\n // result, which surfaces in downstream {{var}} usage as an empty\n // value — easy to mistake for a real value of \"\". Skipping the\n // binding instead lets resolveString leave the placeholder verbatim,\n // so the user sees \"{{var}}\" in the URL/body and immediately notices\n // the broken extraction. Warnings are still emitted for telemetry.\n if (value !== undefined) {\n extracted[variable] = value;\n }\n }\n\n return { extracted, warnings };\n}\n","// AES-GCM encryption helpers used by:\n// - Encrypted environment variables (ciphertext lives in workspace.json,\n// pushed to Git; decryption key never leaves the local browser).\n// - Secret Vault entries (ciphertext in IDB only, never pushed).\n//\n// All helpers take a CryptoKey as input — key generation + persistence is\n// the host's responsibility (see ui-components/persistence/secretKey.ts).\n\nconst IV_BYTES = 12; // 96-bit IV is the recommended size for AES-GCM\nconst SALT_BYTES = 16;\nconst PBKDF2_ITERATIONS = 210_000; // OWASP 2024 recommendation for SHA-256\nconst ALG = 'AES-GCM';\n\nexport interface EncryptedPayload {\n iv: string; // base64\n ciphertext: string; // base64\n}\n\n/**\n * Encrypt a UTF-8 string with the given AES-GCM key. Returns base64-encoded\n * iv + ciphertext, safe to embed in JSON / push to Git.\n */\nexport async function encryptString(plaintext: string, key: CryptoKey): Promise<EncryptedPayload> {\n const iv = crypto.getRandomValues(new Uint8Array(IV_BYTES));\n const data = new TextEncoder().encode(plaintext);\n const cipher = await crypto.subtle.encrypt(\n { name: ALG, iv: iv as unknown as BufferSource },\n key,\n data,\n );\n return {\n iv: bytesToBase64(iv),\n ciphertext: bytesToBase64(new Uint8Array(cipher)),\n };\n}\n\n/**\n * Decrypt a payload produced by `encryptString`. Throws on bad key, tampered\n * ciphertext, or malformed input.\n */\nexport async function decryptString(payload: EncryptedPayload, key: CryptoKey): Promise<string> {\n const iv = base64ToBytes(payload.iv);\n const ciphertext = base64ToBytes(payload.ciphertext);\n const plain = await crypto.subtle.decrypt(\n { name: ALG, iv: iv as unknown as BufferSource },\n key,\n ciphertext as unknown as BufferSource,\n );\n return new TextDecoder().decode(plain);\n}\n\n/**\n * Generate a fresh AES-GCM 256-bit key. The host persists it (typically as\n * a JWK in IndexedDB) so subsequent sessions can decrypt prior values.\n */\nexport function generateAesKey(): Promise<CryptoKey> {\n return crypto.subtle.generateKey({ name: ALG, length: 256 }, true, ['encrypt', 'decrypt']);\n}\n\n/**\n * Generate a fresh per-slot salt (16 random bytes, base64-encoded). Salts are\n * stored in `synced.secretKeys[id].salt` — they're not secret, but they do\n * need to be stable for the slot's lifetime so ciphertext encrypted on one\n * device is decryptable on another.\n */\nexport function generateSlotSalt(): string {\n const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES));\n return bytesToBase64(salt);\n}\n\n/**\n * Derive an AES-GCM key from a slot's plaintext value via PBKDF2-SHA-256.\n * The salt is base64 and travels through Git in `synced.secretKeys[id].salt`;\n * the value is user-supplied and never leaves the device. Same `(value,\n * salt)` pair always derives the same key, so a teammate cloning the repo\n * gets matching keys once they enter the slot value on their machine.\n */\nexport async function deriveKeyFromSlotValue(\n value: string,\n saltBase64: string,\n): Promise<CryptoKey> {\n const baseKey = await crypto.subtle.importKey(\n 'raw',\n new TextEncoder().encode(value) as unknown as BufferSource,\n 'PBKDF2',\n false,\n ['deriveKey'],\n );\n const salt = base64ToBytes(saltBase64);\n return crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt as unknown as BufferSource,\n iterations: PBKDF2_ITERATIONS,\n hash: 'SHA-256',\n },\n baseKey,\n { name: ALG, length: 256 },\n false,\n ['encrypt', 'decrypt'],\n );\n}\n\n/** Export an AES-GCM key as a JSON Web Key (for IDB storage). */\nexport async function exportKey(key: CryptoKey): Promise<JsonWebKey> {\n return crypto.subtle.exportKey('jwk', key);\n}\n\n/** Import an AES-GCM key previously exported via `exportKey`. */\nexport function importKey(jwk: JsonWebKey): Promise<CryptoKey> {\n return crypto.subtle.importKey('jwk', jwk, { name: ALG }, true, ['encrypt', 'decrypt']);\n}\n\n/**\n * Serialize an EncryptedPayload to a single string we can store in\n * `Environment.variables[i].value`. The schema is `enc:v1:<iv>:<ciphertext>`\n * — versioned so we can rotate algorithms later without ambiguity.\n */\nexport function serializePayload(payload: EncryptedPayload): string {\n return `enc:v1:${payload.iv}:${payload.ciphertext}`;\n}\n\nexport function tryParsePayload(value: string): EncryptedPayload | null {\n if (!value.startsWith('enc:v1:')) return null;\n const parts = value.split(':');\n if (parts.length !== 4) return null;\n return { iv: parts[2], ciphertext: parts[3] };\n}\n\n// --- internal --------------------------------------------------------------\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const b of bytes) binary += String.fromCharCode(b);\n return btoa(binary);\n}\n\nfunction base64ToBytes(b64: string): Uint8Array {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);\n return out;\n}\n","// Branch-name generator for the auto-create-from-main flow.\n//\n// Format: `apicircle/<slug>-<6char-id>`, where:\n// - <slug> is the workspace's local display name normalised to lowercase\n// ASCII alphanumerics joined by hyphens. Empty slugs fall back to\n// `workspace`. The display name comes from the local registry — git\n// no longer carries a workspace name, since the name is per-machine.\n// - <6char-id> is a short random suffix that keeps subsequent branches from\n// colliding when a user creates more than one working branch from the\n// same workspace.\n//\n// The generator is pure and deterministic given an `idGen` function — tests\n// inject a fixed id so assertions are stable.\n\nconst SLUG_FALLBACK = 'workspace';\nconst SUFFIX_LEN = 6;\n\n/**\n * Validate a branch name against GitHub's ref rules. Returns null when the\n * name is acceptable, otherwise a short reason. We enforce a stricter\n * subset (no spaces, ASCII only, length ≤ 100) so the auto-generated names\n * always pass.\n */\nexport function validateBranchName(name: string): string | null {\n if (!name) return 'Branch name is required';\n if (name.length > 100) return 'Branch name is too long (max 100 chars)';\n if (/\\s/.test(name)) return 'Branch name cannot contain whitespace';\n // Control chars + Git-disallowed punctuation are intentional in this class.\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1f\\x7f~^:?*\\\\[\\]]/.test(name)) return 'Branch name has illegal characters';\n if (name.startsWith('-') || name.startsWith('/')) return 'Branch name cannot start with - or /';\n if (name.endsWith('.') || name.endsWith('/') || name.endsWith('.lock'))\n return 'Branch name cannot end with . or / or .lock';\n if (name.includes('..') || name.includes('//') || name.includes('@{'))\n return 'Branch name has invalid sequence';\n return null;\n}\n\n/** Lowercase ASCII slug, hyphenated, no leading/trailing/double hyphens. */\nexport function slugify(input: string): string {\n const slug = input\n .toLowerCase()\n .normalize('NFKD')\n .replace(/[̀-ͯ]/g, '') // strip combining marks (accents)\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return slug || SLUG_FALLBACK;\n}\n\nexport interface BranchNameOptions {\n /** The workspace's local display name (from the registry entry). */\n displayName: string;\n /** Inject a fixed id in tests; defaults to 6 random hex chars. */\n idGen?: () => string;\n}\n\nexport function generateWorkingBranchName(opts: BranchNameOptions): string {\n const slug = slugify(opts.displayName);\n const id = (opts.idGen ?? randomHex)();\n return `apicircle/${slug}-${id}`;\n}\n\nfunction randomHex(): string {\n const bytes = new Uint8Array(Math.ceil(SUFFIX_LEN / 2));\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\n crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0'))\n .join('')\n .slice(0, SUFFIX_LEN);\n}\n","import type { WorkspaceSynced } from '@apicircle/shared';\n\n// Canonical serializer for the workspace.json that lands in Git. Stable\n// key order so re-pushing the same logical state produces byte-identical\n// JSON, which means GitHub diffs stay minimal across pushes.\n//\n// The plan §2 commits to a single `workspace.json` at the repo root; this\n// function is the only place that decides its on-disk shape.\n\nconst INDENT = 2;\n\n/**\n * Stringify a WorkspaceSynced doc with deeply-sorted object keys + 2-space\n * indent + trailing newline (so editors don't re-stamp the file when the\n * user opens it). Arrays preserve their existing order — that's part of\n * the workspace's user-visible shape (priority list, tree children, etc).\n */\nexport function serializeWorkspaceForGit(synced: WorkspaceSynced): string {\n return `${stringifySorted(synced)}\\n`;\n}\n\nfunction stringifySorted(value: unknown): string {\n return JSON.stringify(value, sortedReplacer, INDENT);\n}\n\nfunction sortedReplacer(this: unknown, _key: string, value: unknown): unknown {\n if (value === null || typeof value !== 'object') return value;\n if (Array.isArray(value)) return value;\n // Sort plain objects' keys; non-plain objects (e.g. dates) pass through\n // as-is via JSON.stringify's default coercion.\n const proto = Object.getPrototypeOf(value) as object | null;\n if (proto !== Object.prototype && proto !== null) return value;\n const source = value as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(source).sort()) {\n const v: unknown = source[k];\n out[k] = v;\n }\n return out;\n}\n","// Safe parser for any `workspace.json` we read from a Git remote.\n//\n// Threat: the workspace.json file on the remote is whatever a collaborator\n// (or anyone with write access to the repo) pushed. Treating it as a\n// trusted `WorkspaceSynced` and merging it into store state is a primary\n// attack surface — three audit findings clustered here:\n//\n// 1. JSON content can carry `\"__proto__\"` / `\"constructor\"` keys that\n// pollute Object.prototype when shallow-merged or even just iterated\n// with `for...in`. We strip those keys at parse time via a reviver.\n//\n// 2. `JSON.parse(x) as WorkspaceSynced` is a TypeScript-only lie. The\n// remote could have any shape — empty object, deeply-nested arrays,\n// missing required fields. We enforce a minimum shape that matches\n// what every downstream consumer (three-way diff, schema-version\n// migrations, store rehydrate) relies on.\n//\n// 3. A malicious workspace.json can be massive (gigabytes of nested\n// junk) — we cap the input string length before JSON.parse even\n// runs so a hostile blob can't OOM the renderer.\n//\n// We deliberately don't enforce a full Zod schema — the WorkspaceSynced\n// type is hundreds of fields and would balloon this module. The audit's\n// concrete asks are (a) prototype-pollution defense and (b) reject docs\n// that aren't structurally workspaces. Both are achieved here.\n\nimport type { WorkspaceSynced } from '@apicircle/shared';\n\n/** Hard cap on the JSON string length we'll accept. 16 MiB is generous\n * for any realistic workspace doc — Git tooling chokes on much smaller\n * files anyway. Reject anything past this rather than letting the parser\n * walk megabytes of attacker-controlled bytes. */\nconst MAX_WORKSPACE_JSON_BYTES = 16 * 1024 * 1024;\n\n/** Names of object keys we drop at parse time. Setting `__proto__`,\n * `constructor`, or `prototype` as an OWN property doesn't mutate\n * Object.prototype the same way `__proto__` assignment does, but `for...in`\n * iteration / shallow-merge code can still surprise itself. Dropping them\n * at the reviver boundary is the safest place. */\nconst FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** Error thrown when the input fails any of our checks. `code` lets the UI\n * branch on the specific failure (oversized, bad JSON, wrong shape, etc.)\n * without parsing the message string. */\nexport class RemoteWorkspaceParseError extends Error {\n constructor(\n message: string,\n readonly code:\n | 'oversized'\n | 'invalid-json'\n | 'not-object'\n | 'missing-workspace-id'\n | 'missing-collections'\n | 'missing-environments',\n ) {\n super(message);\n this.name = 'RemoteWorkspaceParseError';\n }\n}\n\n/**\n * Parse a remote `workspace.json` and return a `WorkspaceSynced` we can\n * safely merge into store state. Throws `RemoteWorkspaceParseError` on\n * any failure — callers should catch and surface to the user as a\n * \"this workspace was modified by an incompatible version\" message.\n *\n * The returned object is NOT a deep clone of the input; if any nested\n * object had a `__proto__` etc. key, that key was dropped at the reviver\n * level. Strings, numbers, and arrays pass through unchanged.\n *\n * The function is intentionally PERMISSIVE about unknown fields — newer\n * versions of Studio may add fields we don't know about, and we want\n * those workspaces to remain readable. We only enforce the fields the\n * existing codebase positively requires.\n */\nexport function parseWorkspaceJson(content: string): WorkspaceSynced {\n if (content.length > MAX_WORKSPACE_JSON_BYTES) {\n throw new RemoteWorkspaceParseError(\n `Workspace document exceeds ${MAX_WORKSPACE_JSON_BYTES} bytes (got ${content.length})`,\n 'oversized',\n );\n }\n let raw: unknown;\n try {\n // The reviver runs once per (key, value) pair. Returning `undefined`\n // drops the property. This is the canonical way to strip dangerous\n // keys at parse time — V8 doesn't even attach the value to the parent\n // object. Cheaper and safer than walking the tree afterwards.\n raw = JSON.parse(content, (key: string, value: unknown) => {\n if (FORBIDDEN_KEYS.has(key)) return undefined;\n return value;\n });\n } catch (err) {\n throw new RemoteWorkspaceParseError(\n `Remote workspace.json is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n 'invalid-json',\n );\n }\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n throw new RemoteWorkspaceParseError('Remote workspace.json is not a JSON object', 'not-object');\n }\n const obj = raw as Record<string, unknown>;\n\n // Minimum shape: every field below is read unconditionally by the store\n // and three-way diff. A missing one means we're either looking at a\n // half-empty doc or a totally different schema; either way we refuse.\n if (typeof obj.workspaceId !== 'string' || obj.workspaceId.length === 0) {\n throw new RemoteWorkspaceParseError(\n 'Remote workspace.json is missing workspaceId',\n 'missing-workspace-id',\n );\n }\n if (\n typeof obj.collections !== 'object' ||\n obj.collections === null ||\n Array.isArray(obj.collections)\n ) {\n throw new RemoteWorkspaceParseError(\n 'Remote workspace.json is missing or malformed `collections`',\n 'missing-collections',\n );\n }\n if (\n typeof obj.environments !== 'object' ||\n obj.environments === null ||\n Array.isArray(obj.environments)\n ) {\n throw new RemoteWorkspaceParseError(\n 'Remote workspace.json is missing or malformed `environments`',\n 'missing-environments',\n );\n }\n\n // Shape passes — return the parsed value cast to the workspace type.\n // Unknown fields are preserved; the consumer is responsible for any\n // schema-version handling.\n return obj as unknown as WorkspaceSynced;\n}\n","// Redact secret-bearing fields from a `WorkspaceSynced` before it goes to\n// Git. The pushed `workspace.json` is visible to every collaborator (and to\n// the world on public repos), so it CANNOT carry passwords, bearer tokens,\n// client secrets, AWS keys, Hawk keys, JWT signing keys, OAuth2 refresh\n// tokens — none of it.\n//\n// Design:\n//\n// 1. `redactForGit(synced)` walks every Request.auth and returns a copy\n// with the credential-bearing fields blanked to `''`. Identity\n// fields (clientId, username, tokenUrl, authUrl, etc.) are kept —\n// they're not secrets and consumers need them to know which IdP to\n// talk to.\n//\n// 2. `assertNoPlaintextCredentials(serialized)` is a fail-closed lint\n// pass over the already-serialised JSON. If any credential-only\n// field name appears with a non-empty value, push is refused.\n// Defends against:\n// - a future RequestAuth variant we forget to wire into redactForGit\n// - a future workspace-state field that ends up carrying secrets\n// - any path that bypasses redactForGit by mistake\n//\n// Pre-launch tradeoff: we accept that pulling from git will surface\n// requests with blank credentials. The user re-supplies them from the\n// Secret Vault locally. A future Phase 8 follow-up will introduce a\n// `{{!SECRET:<id>}}` placeholder system so the vault auto-fills on pull.\n\nimport type { RequestAuth, WorkspaceSynced } from '@apicircle/shared';\n\n/** Field names that ALWAYS carry a credential when non-empty. Used by the\n * serialised-output lint pass below. Names like `value`, `token` (in\n * `JwtBearerAuth.token` it's a pre-computed JWT — also a credential) and\n * `key` are deliberately NOT in this list because they appear in many\n * non-credential contexts (header rows, secret-vault metadata, etc.); the\n * redactor takes care of those structurally rather than by regex. */\nconst PLAINTEXT_CREDENTIAL_FIELD_NAMES = [\n 'password',\n 'clientSecret',\n 'secretAccessKey',\n 'sessionToken',\n 'refreshToken',\n 'accessToken',\n 'hawkKey',\n 'secretOrKey',\n] as const;\n\n/**\n * Return a copy of `synced` with every credential-bearing field in every\n * Request.auth blanked to ''. Identity fields are preserved. Pure — does\n * not mutate the input. Safe to call on partially-shaped workspaces.\n */\nexport function redactForGit(synced: WorkspaceSynced): WorkspaceSynced {\n const requests: WorkspaceSynced['collections']['requests'] = {};\n for (const [id, req] of Object.entries(synced.collections.requests)) {\n requests[id] = { ...req, auth: redactAuth(req.auth) };\n }\n // Folders carry auth too (folder-level auth inheritance). Redact those.\n const folders: WorkspaceSynced['collections']['folders'] = {};\n for (const [id, folder] of Object.entries(synced.collections.folders)) {\n folders[id] = folder.auth ? { ...folder, auth: redactAuth(folder.auth) } : { ...folder };\n }\n return {\n ...synced,\n collections: { ...synced.collections, requests, folders },\n };\n}\n\nfunction redactAuth(auth: RequestAuth): RequestAuth {\n switch (auth.type) {\n case 'none':\n case 'inherit':\n case 'custom-header':\n // Custom header `value` is user-typed text — could be a secret but\n // the redactor can't know. Users wanting secret semantics should\n // use the Secret Vault + variable interpolation. Same applies to\n // api-key.value below.\n return auth;\n case 'basic':\n return { ...auth, password: '' };\n case 'bearer':\n return { ...auth, token: '' };\n case 'api-key':\n // api-key.value is the credential. Blank it.\n return { ...auth, value: '' };\n case 'digest':\n case 'ntlm':\n return { ...auth, password: '' };\n case 'hawk':\n return { ...auth, hawkKey: '' };\n case 'jwt-bearer':\n // Blank both the signing key AND the pre-computed token — both are\n // credential material (the token is what's actually sent on the\n // wire; the key lets you mint more of them).\n return { ...auth, secretOrKey: '', token: '' };\n case 'aws-sigv4':\n return { ...auth, secretAccessKey: '', sessionToken: '' };\n case 'oauth2-client-credentials':\n case 'oauth2-auth-code':\n case 'oauth2-pkce':\n return { ...auth, clientSecret: '', accessToken: '', refreshToken: '' };\n case 'oauth2-password':\n return { ...auth, clientSecret: '', password: '', accessToken: '', refreshToken: '' };\n case 'oauth2-implicit':\n // Implicit grant has no clientSecret + no refreshToken in the type.\n return { ...auth, accessToken: '' };\n case 'oauth2-device':\n // Device flow is public-client by design — no clientSecret in the\n // type. Just blank the tokens.\n return { ...auth, accessToken: '', refreshToken: '' };\n default: {\n // Exhaustiveness check — if a new auth variant is added without a\n // case here, TypeScript flags the assignment below.\n const _exhaustive: never = auth;\n void _exhaustive;\n return auth;\n }\n }\n}\n\n/**\n * Scan the already-serialised workspace JSON for any credential-only\n * field name with a non-empty value. Throws if found — the push path\n * should treat the throw as fatal (refuse to upload).\n *\n * The match is intentionally narrow: only the names in\n * `PLAINTEXT_CREDENTIAL_FIELD_NAMES`, only with a NON-EMPTY string value.\n * An empty-string credential (`\"password\":\"\"`) is acceptable — that's\n * what `redactForGit` produces.\n *\n * Implementation note: we use a regex rather than walking the parsed\n * tree because (a) the input has already been serialised, and (b) the\n * regex catches every nesting level without us having to know the shape.\n * The risk of false positives is bounded because the field names are\n * specific (no `value` / `token` / `key` in the list).\n */\nexport function assertNoPlaintextCredentials(serialized: string): void {\n for (const name of PLAINTEXT_CREDENTIAL_FIELD_NAMES) {\n // `\"name\":\"<at least one char that isn't a closing quote>\"`\n // We allow any chars in the value (incl. escaped) — the test is\n // \"is the value non-empty?\". A zero-length value (`\"\"`) doesn't match.\n const re = new RegExp(`\"${name}\"\\\\s*:\\\\s*\"(?:[^\"\\\\\\\\]|\\\\\\\\.)+\"`);\n const match = re.exec(serialized);\n if (match) {\n throw new Error(\n `Refusing to push workspace.json: credential field \"${name}\" carries a non-empty value. ` +\n `This is a redaction bug — every plaintext credential MUST be blanked before serialisation.`,\n );\n }\n }\n}\n","import type { MockResponseBody, MockResponseConfig, WorkspaceSynced } from '@apicircle/shared';\n\n// Attachment slots referenced by the synced doc. Push (P4.3b) walks\n// every request body and bundles each referenced blob into the same\n// Git Tree commit as workspace.json — so the repo always carries a\n// self-consistent snapshot.\n\nexport interface AttachmentSlotRef {\n slotId: string;\n sha256?: string;\n filename?: string;\n mimeType?: string;\n size?: number;\n}\n\n/**\n * Walk every request in the synced doc and return one entry per unique\n * attachment slotId it references. Form-data file rows and the binary\n * body's attachment ref both contribute. Duplicates (same slotId\n * referenced twice — defensive only; slot ids are normally unique) are\n * collapsed; the first occurrence wins.\n */\nexport function collectAttachmentSlots(synced: WorkspaceSynced): AttachmentSlotRef[] {\n const seen = new Map<string, AttachmentSlotRef>();\n for (const req of Object.values(synced.collections.requests)) {\n if (req.body.type === 'form-data' && req.body.formRows) {\n for (const row of req.body.formRows) {\n if (row.kind === 'file' && row.slotId && !seen.has(row.slotId)) {\n seen.set(row.slotId, {\n slotId: row.slotId,\n sha256: row.sha256,\n filename: row.filename,\n mimeType: row.mimeType,\n size: row.size,\n });\n }\n }\n }\n if (req.body.type === 'binary') {\n const ref = req.body.attachment;\n if (ref?.slotId && !seen.has(ref.slotId)) {\n seen.set(ref.slotId, {\n slotId: ref.slotId,\n sha256: ref.sha256,\n filename: ref.filename,\n mimeType: ref.mimeType,\n size: ref.size,\n });\n }\n }\n }\n for (const server of Object.values(synced.mockServers ?? {})) {\n for (const endpoint of server.endpoints) {\n collectMockResponseAttachment(endpoint.defaultResponse, seen);\n for (const rule of endpoint.requestValidation ?? []) {\n collectMockResponseAttachment(rule.failResponse, seen);\n }\n for (const rule of endpoint.responseRules ?? []) {\n collectMockResponseAttachment(rule.response, seen);\n }\n }\n }\n for (const file of Object.values(synced.globalAssets.files ?? {})) {\n if (!seen.has(file.slotId)) {\n seen.set(file.slotId, {\n slotId: file.slotId,\n sha256: file.sha256,\n filename: file.filename,\n mimeType: file.mimeType,\n size: file.size,\n });\n }\n }\n return [...seen.values()];\n}\n\nfunction collectMockResponseAttachment(\n response: MockResponseConfig | null | undefined,\n seen: Map<string, AttachmentSlotRef>,\n): void {\n collectMockResponseBodyAttachment(response?.body, seen);\n}\n\nfunction collectMockResponseBodyAttachment(\n body: MockResponseBody | null | undefined,\n seen: Map<string, AttachmentSlotRef>,\n): void {\n if (body?.type !== 'binary') return;\n const ref = body.attachment;\n if (!ref?.slotId || seen.has(ref.slotId)) return;\n seen.set(ref.slotId, {\n slotId: ref.slotId,\n sha256: ref.sha256,\n filename: ref.filename,\n mimeType: ref.mimeType,\n size: ref.size,\n });\n}\n","// Tiny semver helpers — we only need parse + compare. Pulling in the\n// full `semver` package adds 30+ KB for behavior we use in two spots.\n\nconst SEMVER_RE = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+([0-9A-Za-z.-]+))?$/;\n\nexport interface ParsedVersion {\n major: number;\n minor: number;\n patch: number;\n prerelease: string | null;\n build: string | null;\n}\n\nexport function parseSemver(version: string): ParsedVersion | null {\n const m = SEMVER_RE.exec(version.trim());\n if (!m) return null;\n return {\n major: Number(m[1]),\n minor: Number(m[2]),\n patch: Number(m[3]),\n prerelease: m[4] ?? null,\n build: m[5] ?? null,\n };\n}\n\nexport function isValidSemver(version: string): boolean {\n return parseSemver(version) !== null;\n}\n\n/**\n * Compare two semver strings. Returns negative if `a < b`, positive if\n * `a > b`, 0 if equal. Build metadata is ignored (per semver spec). A\n * prerelease label sorts BEFORE its corresponding release (1.0.0-rc.1 <\n * 1.0.0). Within prereleases, dot-separated identifiers compare numeric\n * vs string per the spec.\n */\nexport function compareSemver(a: string, b: string): number {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) return a.localeCompare(b);\n if (pa.major !== pb.major) return pa.major - pb.major;\n if (pa.minor !== pb.minor) return pa.minor - pb.minor;\n if (pa.patch !== pb.patch) return pa.patch - pb.patch;\n // Prerelease ordering: a release > a prerelease of the same triple.\n if (pa.prerelease === null && pb.prerelease === null) return 0;\n if (pa.prerelease === null) return 1;\n if (pb.prerelease === null) return -1;\n return comparePrereleaseIdentifiers(pa.prerelease, pb.prerelease);\n}\n\nfunction comparePrereleaseIdentifiers(a: string, b: string): number {\n const aIds = a.split('.');\n const bIds = b.split('.');\n const len = Math.max(aIds.length, bIds.length);\n for (let i = 0; i < len; i++) {\n const ai = aIds[i];\n const bi = bIds[i];\n if (ai === undefined) return -1;\n if (bi === undefined) return 1;\n const aNum = /^\\d+$/.test(ai) ? Number(ai) : null;\n const bNum = /^\\d+$/.test(bi) ? Number(bi) : null;\n if (aNum !== null && bNum !== null) {\n if (aNum !== bNum) return aNum - bNum;\n } else if (aNum !== null) {\n return -1; // numeric sorts before alpha\n } else if (bNum !== null) {\n return 1;\n } else if (ai !== bi) {\n return ai.localeCompare(bi);\n }\n }\n return 0;\n}\n\n/** Sort an array of semver strings — newest first (descending). */\nexport function sortVersionsDesc(versions: readonly string[]): string[] {\n return [...versions].sort((a, b) => compareSemver(b, a));\n}\n","import type { ReleaseHistory, ReleaseVersion, WorkspaceSynced } from '@apicircle/shared';\nimport { serializeWorkspaceForGit } from '../git/serializeWorkspace';\nimport { isValidSemver } from './semver';\n\n// Workspace-self release publishing. The synced doc is the source of\n// truth; releases.self carries the ledger; the published version's\n// `workspaceSnapshot` is the SHA-256 of the canonical pre-publish\n// workspace.json so consumers can verify integrity.\n\nexport interface PublishReleaseArgs {\n version: string;\n notes: string;\n /** Optional bookkeeping — the git commit SHA the release points at. */\n sha?: string;\n /** Optional bookkeeping — git tag name (the source of truth is the ledger). */\n tagName?: string;\n publishedAt?: string;\n}\n\n/**\n * Append a new release to `synced.releases.self.versions` and bump\n * `currentVersion`. Pure — does not touch IDB or Git.\n *\n * Throws on invalid semver, duplicate version, or invalid notes shape.\n */\nexport async function publishRelease(\n synced: WorkspaceSynced,\n args: PublishReleaseArgs,\n): Promise<WorkspaceSynced> {\n const version = args.version.trim();\n if (!isValidSemver(version)) {\n throw new Error(`Invalid semver: ${args.version}`);\n }\n const ledger = synced.releases.self ?? emptyLedger();\n if (ledger.versions.some((v) => v.version === version)) {\n throw new Error(`Version ${version} already exists in this workspace's release ledger`);\n }\n\n // The snapshot represents the doc *as of the moment of publishing*: we\n // stamp the SHA before writing the new version entry so it's a stable\n // fingerprint of the workspace data the release is built on.\n const snapshotSource = serializeWorkspaceForGit(synced);\n const workspaceSnapshot = await sha256Hex(snapshotSource);\n\n const entry: ReleaseVersion = {\n version,\n publishedAt: args.publishedAt ?? new Date().toISOString(),\n notes: args.notes,\n workspaceSnapshot,\n deprecated: false,\n yanked: false,\n ...(args.sha ? { sha: args.sha } : {}),\n ...(args.tagName ? { tagName: args.tagName } : {}),\n };\n\n const next: ReleaseHistory = {\n versions: [...ledger.versions, entry],\n currentVersion: version,\n };\n return {\n ...synced,\n releases: { ...synced.releases, self: next },\n meta: { ...synced.meta, updatedAt: entry.publishedAt },\n };\n}\n\n/** Flip the `deprecated` flag on a version. Soft signal — version is still installable. */\nexport function deprecateRelease(synced: WorkspaceSynced, version: string): WorkspaceSynced {\n return mapReleaseVersion(synced, version, (v) => ({ ...v, deprecated: true }));\n}\n\n/**\n * Flip the `yanked` flag on a version. Hard signal — consumers should\n * be told this version is broken / unsafe and offered a different one.\n */\nexport function yankRelease(synced: WorkspaceSynced, version: string): WorkspaceSynced {\n return mapReleaseVersion(synced, version, (v) => ({ ...v, yanked: true }));\n}\n\nfunction mapReleaseVersion(\n synced: WorkspaceSynced,\n version: string,\n fn: (v: ReleaseVersion) => ReleaseVersion,\n): WorkspaceSynced {\n const ledger = synced.releases.self;\n if (!ledger) throw new Error('No releases to modify');\n const idx = ledger.versions.findIndex((v) => v.version === version);\n if (idx === -1) throw new Error(`Version ${version} not found`);\n const versions = [...ledger.versions];\n versions[idx] = fn(versions[idx]);\n return {\n ...synced,\n releases: { ...synced.releases, self: { ...ledger, versions } },\n meta: { ...synced.meta, updatedAt: new Date().toISOString() },\n };\n}\n\nfunction emptyLedger(): ReleaseHistory {\n return { versions: [], currentVersion: null };\n}\n\nasync function sha256Hex(text: string): Promise<string> {\n const bytes = new TextEncoder().encode(text);\n const digest = await crypto.subtle.digest('SHA-256', bytes);\n return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');\n}\n","// Maps Content-Type → Monaco language id for syntax highlighting +\n// language services (JSON validation, etc). Pure module — no Monaco\n// import here so the helper is usable in non-browser contexts (e.g.\n// the mock server's response shaping).\n\nexport type MonacoLanguage =\n | 'json'\n | 'xml'\n | 'html'\n | 'graphql'\n | 'javascript'\n | 'yaml'\n | 'plaintext';\n\nconst CONTENT_TYPE_LANGUAGE_MAP: Readonly<Record<string, MonacoLanguage>> = {\n 'application/json': 'json',\n 'application/xml': 'xml',\n 'text/xml': 'xml',\n 'text/html': 'html',\n 'application/graphql': 'graphql',\n 'application/javascript': 'javascript',\n 'text/javascript': 'javascript',\n // YAML and TOON share Monaco's YAML highlighter — TOON is a tabular\n // superset of compact YAML and reads correctly under YAML rules.\n 'application/x-yaml': 'yaml',\n 'application/yaml': 'yaml',\n 'text/yaml': 'yaml',\n 'text/x-yaml': 'yaml',\n 'text/plain': 'plaintext',\n};\n\nexport function normalizeContentType(contentType?: string): string {\n if (!contentType) return '';\n return contentType.toLowerCase().split(';')[0]?.trim() ?? '';\n}\n\nexport function getLanguageFromContentType(contentType?: string): MonacoLanguage {\n const normalized = normalizeContentType(contentType);\n if (!normalized) return 'plaintext';\n const direct = CONTENT_TYPE_LANGUAGE_MAP[normalized];\n if (direct) return direct;\n // +json / +xml suffixes per RFC 6838.\n if (normalized.endsWith('+json')) return 'json';\n if (normalized.endsWith('+xml')) return 'xml';\n return 'plaintext';\n}\n\n/**\n * Map a workspace BodyType to its Monaco language. Used by the editor\n * to set the right syntax highlighter even before Content-Type lands.\n */\nexport function getLanguageFromBodyType(\n bodyType: 'none' | 'json' | 'text' | 'urlencoded' | 'form-data' | 'binary' | 'xml' | 'graphql',\n): MonacoLanguage {\n switch (bodyType) {\n case 'json':\n return 'json';\n case 'xml':\n return 'xml';\n case 'graphql':\n return 'graphql';\n case 'text':\n case 'urlencoded':\n case 'form-data':\n case 'binary':\n case 'none':\n return 'plaintext';\n }\n}\n\nexport const supportedContentTypeLanguageMap = CONTENT_TYPE_LANGUAGE_MAP;\n","// Lightweight GraphQL schema parser for editor autocomplete. Two inputs\n// supported:\n//\n// 1. SDL (`type Query { ... }`): a forgiving regex-based extractor — we\n// don't ship a full GraphQL grammar; we just want enough information\n// to power \"what fields does this type expose?\" completions.\n//\n// 2. Introspection JSON (the result of `query IntrospectionQuery`): we\n// consume the official shape, so completions are accurate.\n//\n// Output is a flat shape consumable by Monaco's completion provider —\n// types, fields per type, root operation type names, and a list of\n// scalar / enum names.\n\nexport interface GraphQLSchemaInfo {\n /** Object/Interface types and their fields. */\n types: Map<string, { fields: GraphQLField[] }>;\n /** Top-level operations (Query, Mutation, Subscription). */\n rootTypes: { query?: string; mutation?: string; subscription?: string };\n /** Scalar + enum names. */\n scalars: string[];\n enums: string[];\n}\n\nexport interface GraphQLField {\n name: string;\n type: string;\n description?: string;\n}\n\nconst EMPTY: GraphQLSchemaInfo = {\n types: new Map(),\n rootTypes: {},\n scalars: [],\n enums: [],\n};\n\nexport function parseGraphqlSchema(\n source: string,\n kind: 'sdl' | 'introspection',\n): GraphQLSchemaInfo {\n if (!source.trim()) return EMPTY;\n if (kind === 'introspection') return parseIntrospection(source);\n return parseSdl(source);\n}\n\n// --- SDL parser ---------------------------------------------------------\n\nfunction parseSdl(source: string): GraphQLSchemaInfo {\n const types = new Map<string, { fields: GraphQLField[] }>();\n const rootTypes: GraphQLSchemaInfo['rootTypes'] = {\n query: 'Query',\n mutation: 'Mutation',\n subscription: 'Subscription',\n };\n const scalars: string[] = [];\n const enums: string[] = [];\n\n // Strip block + line comments.\n const text = source.replace(/\"\"\"[\\s\\S]*?\"\"\"/g, '').replace(/^\\s*#.*$/gm, '');\n\n // schema { query: A, mutation: B, subscription: C }\n const schemaMatch = /schema\\s*\\{([\\s\\S]*?)\\}/.exec(text);\n if (schemaMatch) {\n const inner = schemaMatch[1] ?? '';\n for (const line of inner.split(/\\r?\\n/)) {\n const m = /(query|mutation|subscription)\\s*:\\s*(\\w+)/.exec(line);\n if (m) (rootTypes as Record<string, string>)[m[1]] = m[2]!;\n }\n }\n\n const typeRegex = /\\b(type|interface)\\s+(\\w+)(?:\\s+implements\\s+[\\w\\s&]+?)?\\s*\\{([\\s\\S]*?)\\}/g;\n let match: RegExpExecArray | null;\n while ((match = typeRegex.exec(text))) {\n const typeName = match[2];\n const body = match[3];\n const fields: GraphQLField[] = [];\n for (const line of body.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const fm = /^(\\w+)(?:\\s*\\([^)]*\\))?\\s*:\\s*([^\\s,]+)/.exec(trimmed);\n if (fm) {\n fields.push({ name: fm[1], type: fm[2] });\n }\n }\n types.set(typeName, { fields });\n }\n\n for (const m of text.matchAll(/\\bscalar\\s+(\\w+)/g)) scalars.push(m[1]);\n for (const m of text.matchAll(/\\benum\\s+(\\w+)\\s*\\{[\\s\\S]*?\\}/g)) enums.push(m[1]);\n\n return { types, rootTypes, scalars, enums };\n}\n\n// --- Introspection parser ----------------------------------------------\n\ninterface IntrospectionType {\n kind: string;\n name: string;\n description?: string;\n fields?: Array<{\n name: string;\n description?: string;\n type: { name?: string; ofType?: { name?: string } };\n }>;\n}\n\ninterface IntrospectionRoot {\n __schema?: {\n queryType?: { name: string };\n mutationType?: { name: string } | null;\n subscriptionType?: { name: string } | null;\n types: IntrospectionType[];\n };\n data?: {\n __schema?: IntrospectionRoot['__schema'];\n };\n}\n\nfunction parseIntrospection(source: string): GraphQLSchemaInfo {\n let parsed: IntrospectionRoot;\n try {\n parsed = JSON.parse(source) as IntrospectionRoot;\n } catch {\n return EMPTY;\n }\n const schema = parsed.__schema ?? parsed.data?.__schema;\n if (!schema) return EMPTY;\n\n const types = new Map<string, { fields: GraphQLField[] }>();\n const scalars: string[] = [];\n const enums: string[] = [];\n\n for (const t of schema.types) {\n if (!t.name || t.name.startsWith('__')) continue;\n if (t.kind === 'OBJECT' || t.kind === 'INTERFACE') {\n types.set(t.name, {\n fields: (t.fields ?? []).map((f) => ({\n name: f.name,\n type: typeName(f.type) ?? 'Unknown',\n description: f.description,\n })),\n });\n } else if (t.kind === 'SCALAR') {\n scalars.push(t.name);\n } else if (t.kind === 'ENUM') {\n enums.push(t.name);\n }\n }\n\n return {\n types,\n rootTypes: {\n query: schema.queryType?.name,\n mutation: schema.mutationType?.name,\n subscription: schema.subscriptionType?.name,\n },\n scalars,\n enums,\n };\n}\n\nfunction typeName(\n t: { name?: string; ofType?: { name?: string } } | undefined,\n): string | undefined {\n if (!t) return undefined;\n if (t.name) return t.name;\n return typeName(t.ofType);\n}\n","import type { RequestAuth, WorkspaceSynced } from '@apicircle/shared';\n\n// 3-way diff for the refresh / pull flow (plan §3.5). The \"base\" is the\n// snapshot from the last successful pull, captured in\n// `WorkspaceLocal.sync.lastPulledSnapshot`. We diff each top-level bucket\n// of the synced doc against base on both sides; entries that only one\n// side touched fast-forward, entries both sides touched in different\n// ways become conflicts the user must resolve.\n\nexport type DiffStatus = 'unchanged' | 'local-only' | 'remote-only' | 'both-equal' | 'conflict';\n\nexport type EntityBucket =\n | 'request'\n | 'folder'\n | 'environment'\n | 'linkedWorkspace'\n | 'mockServer'\n | 'executionPlan'\n | 'secretKey'\n | 'globalSchema'\n | 'globalGraphql'\n | 'globalFile'\n | 'linkedRequestOverride'\n | 'linkedEnvOverride'\n | 'releasePerLink'\n | 'tree'\n | 'environmentsActive'\n | 'environmentsPriority'\n | 'releaseSelf'\n | 'secretCrypto';\n\nexport interface DiffEntry {\n bucket: EntityBucket;\n /** Entity id within the bucket. Empty string for singleton buckets. */\n key: string;\n status: DiffStatus;\n /** Human-readable label for the resolver UI. */\n label: string;\n base: unknown;\n local: unknown;\n remote: unknown;\n}\n\nexport interface ThreeWayDiff {\n entries: DiffEntry[];\n conflicts: DiffEntry[];\n}\n\nexport type ConflictResolution = 'mine' | 'theirs';\n\ntype TreeChild = WorkspaceSynced['collections']['tree']['children'][number];\n\n/** Map keyed by `bucket:key` (e.g. `request:r-1`, `releaseSelf:`). */\nexport type ResolutionMap = Record<string, ConflictResolution>;\n\n/**\n * Stable JSON for structural-equality checks. Same replacer the git\n * serializer uses — sorted object keys, arrays preserved verbatim.\n */\nfunction canonicalize(value: unknown): string {\n return JSON.stringify(value, sortedReplacer);\n}\n\nfunction sortedReplacer(this: unknown, _key: string, value: unknown): unknown {\n if (value === null || typeof value !== 'object') return value;\n if (Array.isArray(value)) return value;\n const proto = Object.getPrototypeOf(value) as object | null;\n if (proto !== Object.prototype && proto !== null) return value;\n const source = value as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(source).sort()) out[k] = source[k];\n return out;\n}\n\nfunction structurallyEqual(a: unknown, b: unknown): boolean {\n return canonicalize(a) === canonicalize(b);\n}\n\ninterface DictBucketSpec {\n bucket: EntityBucket;\n // Keys are exposed via the Spec so tests don't have to rebuild it.\n extract(s: WorkspaceSynced): Record<string, unknown>;\n label(key: string, value: unknown): string;\n}\n\ninterface SingletonSpec {\n bucket: EntityBucket;\n key: string;\n label: string;\n extract(s: WorkspaceSynced): unknown;\n}\n\nconst dictBuckets: DictBucketSpec[] = [\n {\n bucket: 'request',\n extract: (s) => s.collections.requests,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n bucket: 'folder',\n extract: (s) => s.collections.folders,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n bucket: 'environment',\n extract: (s) => s.environments.items,\n label: (key) => key,\n },\n {\n bucket: 'linkedWorkspace',\n extract: (s) => s.linkedWorkspaces,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n bucket: 'mockServer',\n extract: (s) => s.mockServers,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n // Plan definitions live in `synced.executionPlans` post-hydrate. The\n // field is typed optional because pre-migration workspaces persisted\n // plans on `WorkspaceLocal` only; coerce a missing dict to `{}` so the\n // diff engine treats \"absent\" and \"empty\" identically.\n bucket: 'executionPlan',\n extract: (s) => s.executionPlans ?? {},\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n // Secret-key slot metadata (label + KDF salt). Values are device-local\n // and never travel through git — only the slot identity does, so\n // collaborators see consistent labels for the same id.\n bucket: 'secretKey',\n extract: (s) => s.secretKeys ?? {},\n label: (key, value) => {\n const v = value as { label?: string } | undefined;\n return v?.label ?? key;\n },\n },\n {\n // Reusable JSON Schemas registered at workspace scope.\n bucket: 'globalSchema',\n extract: (s) => s.globalAssets.schemas,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n // Reusable GraphQL schema docs registered at workspace scope.\n bucket: 'globalGraphql',\n extract: (s) => s.globalAssets.graphql,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n // Reusable file assets registered at workspace scope. The metadata\n // travels in workspace.json; bytes travel as Git blobs by slotId.\n bucket: 'globalFile',\n extract: (s) => s.globalAssets.files ?? {},\n label: (key, value) => {\n const v = value as { name?: string; filename?: string } | undefined;\n return v?.name ?? v?.filename ?? key;\n },\n },\n {\n // Consumer-side patches to a linked workspace's requests. Keyed\n // `${linkedWorkspaceId}:${requestId}`; the label leans on the key\n // since the override itself doesn't carry a name.\n bucket: 'linkedRequestOverride',\n extract: (s) => s.linkedOverrides.requests,\n label: (key) => `linked request override (${key})`,\n },\n {\n // Per-variable overrides for linked-workspace env vars. Keyed\n // `${linkedWorkspaceId}:${envName}:${varKey}`.\n bucket: 'linkedEnvOverride',\n extract: (s) => s.linkedOverrides.environmentVars,\n label: (key) => `linked env var override (${key})`,\n },\n {\n // Cached release ledgers for each linked workspace. Keyed by\n // linkedWorkspaceId. Refreshes via the link card's \"Refresh ledger\"\n // surface change here too.\n bucket: 'releasePerLink',\n extract: (s) => s.releases.perLink,\n label: (key) => `linked release ledger (${key})`,\n },\n];\n\nconst singletons: SingletonSpec[] = [\n { bucket: 'tree', key: '', label: 'Folder tree', extract: (s) => s.collections.tree },\n {\n bucket: 'environmentsActive',\n key: '',\n label: 'Active environment',\n extract: (s) => s.environments.activeName,\n },\n {\n bucket: 'environmentsPriority',\n key: '',\n label: 'Environment priority',\n extract: (s) => s.environments.priorityOrder,\n },\n {\n bucket: 'releaseSelf',\n key: '',\n label: 'Release ledger',\n extract: (s) => s.releases.self,\n },\n {\n // Workspace passphrase metadata (KDF + verifier — never the secret\n // itself). Travels through git so a collaborator who pulls knows the\n // passphrase exists and can prompt for it on first decrypt.\n bucket: 'secretCrypto',\n key: '',\n label: 'Workspace passphrase',\n extract: (s) => s.secretCrypto ?? null,\n },\n];\n\n/**\n * Compute the per-entity diff. Returns every entity touched on at least\n * one side, plus a flat list of conflicts (subset of entries with status\n * 'conflict') for the resolver.\n *\n * `base` is the lastPulledSnapshot. When null (first refresh ever), every\n * remote entity that doesn't match local becomes a conflict — there's no\n * shared ancestor to pick a side automatically.\n */\nexport function computeThreeWayDiff(\n base: WorkspaceSynced | null,\n local: WorkspaceSynced,\n remote: WorkspaceSynced,\n): ThreeWayDiff {\n const entries: DiffEntry[] = [];\n\n for (const spec of dictBuckets) {\n const baseDict = base ? spec.extract(base) : {};\n const localDict = spec.extract(local);\n const remoteDict = spec.extract(remote);\n const allKeys = new Set([\n ...Object.keys(baseDict),\n ...Object.keys(localDict),\n ...Object.keys(remoteDict),\n ]);\n for (const key of allKeys) {\n const b = baseDict[key];\n const l = localDict[key];\n const r = remoteDict[key];\n const status = classify(base !== null, b, l, r);\n if (status === 'unchanged') continue;\n const labelSource = l ?? r ?? b;\n entries.push({\n bucket: spec.bucket,\n key,\n status,\n label: spec.label(key, labelSource),\n base: b,\n local: l,\n remote: r,\n });\n }\n }\n\n for (const spec of singletons) {\n const b = base ? spec.extract(base) : undefined;\n const l = spec.extract(local);\n const r = spec.extract(remote);\n const status = classify(base !== null, b, l, r);\n if (status === 'unchanged') continue;\n entries.push({\n bucket: spec.bucket,\n key: spec.key,\n status,\n label: spec.label,\n base: b,\n local: l,\n remote: r,\n });\n }\n\n resolveAutoMergeableTreeConflict(entries, base, local, remote);\n const conflicts = entries.filter((e) => e.status === 'conflict');\n return { entries, conflicts };\n}\n\nfunction classify(hasBase: boolean, base: unknown, local: unknown, remote: unknown): DiffStatus {\n const localUndef = local === undefined;\n const remoteUndef = remote === undefined;\n if (localUndef && remoteUndef) return 'unchanged';\n\n // Without a shared base, we can't tell who changed what — anything that\n // doesn't already match becomes a conflict. (Equal values are fine.)\n if (!hasBase) {\n if (structurallyEqual(local, remote)) return 'unchanged';\n if (localUndef) return 'remote-only';\n if (remoteUndef) return 'local-only';\n return 'conflict';\n }\n\n const localChanged = !structurallyEqual(base, local);\n const remoteChanged = !structurallyEqual(base, remote);\n if (!localChanged && !remoteChanged) return 'unchanged';\n if (!localChanged && remoteChanged) return 'remote-only';\n if (localChanged && !remoteChanged) return 'local-only';\n // Both changed.\n if (structurallyEqual(local, remote)) return 'both-equal';\n return 'conflict';\n}\n\nfunction resolveAutoMergeableTreeConflict(\n entries: DiffEntry[],\n base: WorkspaceSynced | null,\n local: WorkspaceSynced,\n remote: WorkspaceSynced,\n): void {\n if (!base) return;\n const treeEntry = entries.find((entry) => entry.bucket === 'tree' && entry.status === 'conflict');\n if (!treeEntry) return;\n const merged = mergeRootTreeMembershipIfSafe(base, local, remote, entries);\n if (!merged) return;\n treeEntry.status = 'remote-only';\n treeEntry.remote = merged;\n}\n\nfunction mergeRootTreeMembershipIfSafe(\n base: WorkspaceSynced,\n local: WorkspaceSynced,\n remote: WorkspaceSynced,\n entries: DiffEntry[],\n): WorkspaceSynced['collections']['tree'] | null {\n const baseChildren = base.collections.tree.children;\n const localChildren = local.collections.tree.children;\n const remoteChildren = remote.collections.tree.children;\n const baseKeys = treeKeySet(baseChildren);\n const localKeys = treeKeySet(localChildren);\n const remoteKeys = treeKeySet(remoteChildren);\n if (!baseKeys || !localKeys || !remoteKeys) return null;\n\n const changed = new Set<string>();\n for (const key of new Set([...baseKeys, ...localKeys, ...remoteKeys])) {\n const localChanged = baseKeys.has(key) !== localKeys.has(key);\n const remoteChanged = baseKeys.has(key) !== remoteKeys.has(key);\n if (!localChanged && !remoteChanged) continue;\n if (localChanged && remoteChanged) return null;\n const entry = bucketEntryForTreeChild(entries, key);\n if (!entry || entry.status === 'conflict') return null;\n if (localChanged && entry.status !== 'local-only') return null;\n if (remoteChanged && entry.status !== 'remote-only') return null;\n changed.add(key);\n }\n if (changed.size === 0) return null;\n\n const stableBaseOrder = baseChildren.map(treeChildKey).filter((key) => !changed.has(key));\n if (\n !sameOrder(\n localChildren.map(treeChildKey).filter((key) => !changed.has(key)),\n stableBaseOrder,\n )\n ) {\n return null;\n }\n if (\n !sameOrder(\n remoteChildren.map(treeChildKey).filter((key) => !changed.has(key)),\n stableBaseOrder,\n )\n ) {\n return null;\n }\n\n let children = [...localChildren];\n for (const child of remoteChildren) {\n const key = treeChildKey(child);\n if (!changed.has(key) || !remoteKeys.has(key)) continue;\n if (!children.some((existing) => treeChildKey(existing) === key)) children.push(child);\n }\n for (const key of changed) {\n if (remoteKeys.has(key)) continue;\n const entry = bucketEntryForTreeChild(entries, key);\n if (entry?.status === 'remote-only') {\n children = children.filter((child) => treeChildKey(child) !== key);\n }\n }\n return { ...local.collections.tree, children };\n}\n\nfunction bucketEntryForTreeChild(entries: DiffEntry[], key: string): DiffEntry | undefined {\n const [kind, id] = key.split(':', 2);\n if (kind !== 'request' && kind !== 'folder') return undefined;\n return entries.find((entry) => entry.bucket === kind && entry.key === id);\n}\n\nfunction treeKeySet(children: TreeChild[]): Set<string> | null {\n const keys = new Set<string>();\n for (const child of children) {\n const key = treeChildKey(child);\n if (keys.has(key)) return null;\n keys.add(key);\n }\n return keys;\n}\n\nfunction treeChildKey(child: TreeChild): string {\n return `${child.kind}:${child.id}`;\n}\n\nfunction sameOrder(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((value, index) => value === b[index]);\n}\n\n/**\n * Apply a fully-resolved diff: take fast-forwards (remote-only) into\n * local, keep local-only changes verbatim, and resolve every conflict\n * via the supplied `resolutions` map (`bucket:key` → 'mine' | 'theirs').\n *\n * Throws when any conflict is missing a resolution — the caller is\n * expected to populate the modal first.\n */\nexport function applyMerge(\n local: WorkspaceSynced,\n remote: WorkspaceSynced,\n diff: ThreeWayDiff,\n resolutions: ResolutionMap,\n): WorkspaceSynced {\n let merged: WorkspaceSynced = local;\n for (const entry of diff.entries) {\n const id = `${entry.bucket}:${entry.key}`;\n let chosen: 'mine' | 'theirs';\n if (entry.status === 'remote-only') {\n chosen = 'theirs';\n } else if (entry.status === 'local-only' || entry.status === 'both-equal') {\n chosen = 'mine';\n } else {\n const r = resolutions[id];\n if (!r) throw new Error(`Missing resolution for ${id}`);\n chosen = r;\n }\n merged = applyEntry(merged, remote, entry, chosen);\n }\n return merged;\n}\n\n/**\n * Distinguishes the two outcomes a merge can have for a dict entry:\n * - `upsert` — the entry now exists in the dict (added or modified).\n * `parent` tells us if it belongs at root or inside a folder.\n * - `remove` — the entry was deleted from the dict.\n * Without this discriminator, \"value === undefined\" can't be told apart from\n * \"value present with parent === null\" — and root-level deletes would silently\n * get re-added by the reconciler.\n */\ntype TreeOp = { kind: 'upsert'; parent: string | null } | { kind: 'remove' };\n\n/**\n * Keep `tree.children` consistent with the requests/folders dict when a\n * merge inserts, modifies, or removes an entry. The sidebar derives the\n * visible list from two parallel sources — `tree.children` (root) and\n * `folderId/parentId` chains (nested). Without this reconciliation, a\n * pull that adds a top-level request leaves the dict updated but the\n * tree untouched, so the request becomes an \"orphan\" — present in the\n * unpushed-changes strip but invisible in the editor sidebar.\n *\n * Cases handled:\n * - upsert at root: add to tree.children if missing\n * - upsert nested: strip any stale root reference (entry can't be in two\n * places at once)\n * - remove: strip from tree.children if present\n */\nfunction reconcileTreeForEntry(\n tree: WorkspaceSynced['collections']['tree'],\n kind: 'folder' | 'request',\n id: string,\n op: TreeOp,\n): WorkspaceSynced['collections']['tree'] {\n const inTree = tree.children.some((c) => c.kind === kind && c.id === id);\n if (op.kind === 'upsert' && op.parent === null) {\n if (inTree) return tree;\n return { ...tree, children: [...tree.children, { kind, id }] };\n }\n // Nested upsert OR remove: ensure no stale root reference.\n if (!inTree) return tree;\n return {\n ...tree,\n children: tree.children.filter((c) => !(c.kind === kind && c.id === id)),\n };\n}\n\nfunction applyEntry(\n local: WorkspaceSynced,\n remote: WorkspaceSynced,\n entry: DiffEntry,\n chosen: 'mine' | 'theirs',\n): WorkspaceSynced {\n if (chosen === 'mine') return local;\n // chosen === 'theirs': overwrite the entity in `local` with the remote value.\n const value = entry.remote;\n switch (entry.bucket) {\n case 'request': {\n const requests = { ...local.collections.requests };\n const treeOp: TreeOp =\n value === undefined\n ? { kind: 'remove' }\n : { kind: 'upsert', parent: (value as { folderId: string | null }).folderId ?? null };\n if (value === undefined) delete requests[entry.key];\n else {\n const remoteRequest = value as (typeof requests)[string];\n const localRequest = local.collections.requests[entry.key];\n requests[entry.key] =\n localRequest && remoteRequest.auth\n ? {\n ...remoteRequest,\n auth: preserveLocalCredentialPlaceholders(localRequest.auth, remoteRequest.auth),\n }\n : remoteRequest;\n }\n const tree = reconcileTreeForEntry(local.collections.tree, 'request', entry.key, treeOp);\n return { ...local, collections: { ...local.collections, requests, tree } };\n }\n case 'folder': {\n const folders = { ...local.collections.folders };\n const treeOp: TreeOp =\n value === undefined\n ? { kind: 'remove' }\n : { kind: 'upsert', parent: (value as { parentId: string | null }).parentId ?? null };\n if (value === undefined) delete folders[entry.key];\n else {\n const remoteFolder = value as (typeof folders)[string];\n const localFolder = local.collections.folders[entry.key];\n folders[entry.key] =\n localFolder?.auth && remoteFolder.auth\n ? {\n ...remoteFolder,\n auth: preserveLocalCredentialPlaceholders(localFolder.auth, remoteFolder.auth),\n }\n : remoteFolder;\n }\n const tree = reconcileTreeForEntry(local.collections.tree, 'folder', entry.key, treeOp);\n return { ...local, collections: { ...local.collections, folders, tree } };\n }\n case 'environment': {\n const items = { ...local.environments.items };\n if (value === undefined) delete items[entry.key];\n else items[entry.key] = value as (typeof items)[string];\n return { ...local, environments: { ...local.environments, items } };\n }\n case 'linkedWorkspace': {\n const linkedWorkspaces = { ...local.linkedWorkspaces };\n if (value === undefined) delete linkedWorkspaces[entry.key];\n else linkedWorkspaces[entry.key] = value as (typeof linkedWorkspaces)[string];\n return { ...local, linkedWorkspaces };\n }\n case 'mockServer': {\n const mockServers = { ...local.mockServers };\n if (value === undefined) delete mockServers[entry.key];\n else mockServers[entry.key] = value as (typeof mockServers)[string];\n return { ...local, mockServers };\n }\n case 'executionPlan': {\n // executionPlans is optional in the type — start from `{}` rather\n // than `undefined` so we never write a non-dict value back.\n const executionPlans = { ...(local.executionPlans ?? {}) };\n if (value === undefined) delete executionPlans[entry.key];\n else\n executionPlans[entry.key] = value as NonNullable<WorkspaceSynced['executionPlans']>[string];\n return { ...local, executionPlans };\n }\n case 'secretKey': {\n // secretKeys is optional in the type — coerce missing to {} so a\n // remote that hasn't ever populated the field doesn't smuggle in\n // an undefined.\n const secretKeys = { ...(local.secretKeys ?? {}) };\n if (value === undefined) delete secretKeys[entry.key];\n else secretKeys[entry.key] = value as NonNullable<WorkspaceSynced['secretKeys']>[string];\n return { ...local, secretKeys };\n }\n case 'globalSchema': {\n const schemas = { ...local.globalAssets.schemas };\n if (value === undefined) delete schemas[entry.key];\n else schemas[entry.key] = value as (typeof schemas)[string];\n return { ...local, globalAssets: { ...local.globalAssets, schemas } };\n }\n case 'globalGraphql': {\n const graphql = { ...local.globalAssets.graphql };\n if (value === undefined) delete graphql[entry.key];\n else graphql[entry.key] = value as (typeof graphql)[string];\n return { ...local, globalAssets: { ...local.globalAssets, graphql } };\n }\n case 'globalFile': {\n const files = { ...(local.globalAssets.files ?? {}) };\n if (value === undefined) delete files[entry.key];\n else\n files[entry.key] = value as NonNullable<WorkspaceSynced['globalAssets']['files']>[string];\n return { ...local, globalAssets: { ...local.globalAssets, files } };\n }\n case 'linkedRequestOverride': {\n const requests = { ...local.linkedOverrides.requests };\n if (value === undefined) delete requests[entry.key];\n else requests[entry.key] = value as (typeof requests)[string];\n return { ...local, linkedOverrides: { ...local.linkedOverrides, requests } };\n }\n case 'linkedEnvOverride': {\n const environmentVars = { ...local.linkedOverrides.environmentVars };\n if (value === undefined) delete environmentVars[entry.key];\n else environmentVars[entry.key] = value as (typeof environmentVars)[string];\n return { ...local, linkedOverrides: { ...local.linkedOverrides, environmentVars } };\n }\n case 'releasePerLink': {\n const perLink = { ...local.releases.perLink };\n if (value === undefined) delete perLink[entry.key];\n else perLink[entry.key] = value as (typeof perLink)[string];\n return { ...local, releases: { ...local.releases, perLink } };\n }\n case 'tree':\n return {\n ...local,\n collections: {\n ...local.collections,\n tree: (value as WorkspaceSynced['collections']['tree']) ?? remote.collections.tree,\n },\n };\n case 'environmentsActive':\n return {\n ...local,\n environments: { ...local.environments, activeName: remote.environments.activeName },\n };\n case 'environmentsPriority':\n return {\n ...local,\n environments: {\n ...local.environments,\n priorityOrder: remote.environments.priorityOrder,\n },\n };\n case 'releaseSelf':\n return { ...local, releases: { ...local.releases, self: remote.releases.self } };\n case 'secretCrypto':\n return { ...local, secretCrypto: remote.secretCrypto ?? null };\n }\n}\n\nfunction preserveLocalCredentialPlaceholders(\n localAuth: RequestAuth,\n remoteAuth: RequestAuth,\n): RequestAuth {\n if (localAuth.type !== remoteAuth.type) return remoteAuth;\n switch (remoteAuth.type) {\n case 'basic':\n case 'digest':\n case 'ntlm':\n return preserveBlankStringFields(localAuth, remoteAuth, ['password']);\n case 'bearer':\n return preserveBlankStringFields(localAuth, remoteAuth, ['token']);\n case 'api-key':\n return preserveBlankStringFields(localAuth, remoteAuth, ['value']);\n case 'hawk':\n return preserveBlankStringFields(localAuth, remoteAuth, ['hawkKey']);\n case 'jwt-bearer':\n return preserveBlankStringFields(localAuth, remoteAuth, ['secretOrKey', 'token']);\n case 'aws-sigv4':\n return preserveBlankStringFields(localAuth, remoteAuth, ['secretAccessKey', 'sessionToken']);\n case 'oauth2-client-credentials':\n case 'oauth2-auth-code':\n case 'oauth2-pkce':\n return preserveBlankStringFields(localAuth, remoteAuth, [\n 'clientSecret',\n 'accessToken',\n 'refreshToken',\n ]);\n case 'oauth2-password':\n return preserveBlankStringFields(localAuth, remoteAuth, [\n 'clientSecret',\n 'password',\n 'accessToken',\n 'refreshToken',\n ]);\n case 'oauth2-implicit':\n return preserveBlankStringFields(localAuth, remoteAuth, ['accessToken']);\n case 'oauth2-device':\n return preserveBlankStringFields(localAuth, remoteAuth, ['accessToken', 'refreshToken']);\n case 'none':\n case 'inherit':\n case 'custom-header':\n return remoteAuth;\n default: {\n const _exhaustive: never = remoteAuth;\n void _exhaustive;\n return remoteAuth;\n }\n }\n}\n\nfunction preserveBlankStringFields<T extends RequestAuth>(\n localAuth: T,\n remoteAuth: T,\n fields: string[],\n): T {\n const next = { ...remoteAuth } as Record<string, unknown>;\n const local = localAuth as Record<string, unknown>;\n for (const field of fields) {\n if (next[field] === '' && typeof local[field] === 'string' && local[field] !== '') {\n next[field] = local[field];\n }\n }\n return next as T;\n}\n","import type { WorkspaceSynced } from '@apicircle/shared';\nimport { redactForGit } from './redactWorkspace';\nimport { type EntityBucket, computeThreeWayDiff } from './threeWayDiff';\n\n// Pre-push diff summary: compares the consumer's currently-edited synced\n// doc against the last-pulled snapshot to enumerate every uncommitted\n// change. Powers the BranchCard's \"+N added · ~M modified · -K removed\"\n// strip (B.3) and the side-by-side preview modal beneath it.\n//\n// Pure — caller decides when to recompute (typically on every store\n// mutation; cheap enough to skip debouncing for typical workspace\n// sizes).\n\nexport interface UnpushedChange {\n bucket: EntityBucket;\n /** Entity id within the bucket; empty string for singletons (tree, etc.). */\n key: string;\n label: string;\n kind: 'added' | 'modified' | 'removed';\n base: unknown;\n local: unknown;\n}\n\nexport interface UnpushedSummary {\n added: number;\n modified: number;\n removed: number;\n total: number;\n /** Per-entry list, sorted by bucket then label so the preview list renders predictably. */\n changes: UnpushedChange[];\n computedAt: string;\n}\n\nconst BUCKET_ORDER: EntityBucket[] = [\n 'tree',\n 'request',\n 'folder',\n 'environment',\n 'environmentsActive',\n 'environmentsPriority',\n 'linkedWorkspace',\n 'linkedRequestOverride',\n 'linkedEnvOverride',\n 'mockServer',\n 'executionPlan',\n 'globalSchema',\n 'globalGraphql',\n 'globalFile',\n 'secretKey',\n 'secretCrypto',\n 'releaseSelf',\n 'releasePerLink',\n];\n\nconst EMPTY_SUMMARY: UnpushedSummary = {\n added: 0,\n modified: 0,\n removed: 0,\n total: 0,\n changes: [],\n computedAt: new Date(0).toISOString(),\n};\n\nexport function summarizeUnpushedChanges(\n base: WorkspaceSynced | null,\n current: WorkspaceSynced,\n options: { now?: () => Date } = {},\n): UnpushedSummary {\n const now = options.now ?? (() => new Date());\n // The push path writes a redacted workspace.json. Compare the same synced\n // intent here so local-only credential values do not appear as phantom\n // unpushed changes after a refresh/merge preserves them in memory.\n const gitCurrent = redactForGit(current);\n if (!base) {\n // No upstream yet (workspace was just created or never pulled).\n // Everything in `current` counts as \"added\" — walking the buckets\n // directly is simpler than feeding an empty-shape doc to the diff\n // engine.\n return summarizeAllAsAdded(gitCurrent, now().toISOString());\n }\n // Reuse the existing 3-way diff with `remote = base` so every entry\n // is either 'unchanged' or 'local-only'. We then translate\n // 'local-only' into added / modified / removed by inspecting which of\n // base / local is undefined.\n const gitBase = redactForGit(base);\n const diff = computeThreeWayDiff(gitBase, gitCurrent, gitBase);\n const changes: UnpushedChange[] = [];\n for (const entry of diff.entries) {\n if (entry.status !== 'local-only') continue;\n // Treat null and undefined alike as \"absent\" for kind classification.\n // The `releaseSelf` singleton extracts to `null` when no ledger\n // exists — without nullish-aware logic, the first publish (null →\n // ledger) gets labeled \"modified\" instead of \"added\", which the\n // strip then under-counts in its \"+N added\" badge.\n const baseAbsent = entry.base === undefined || entry.base === null;\n const localAbsent = entry.local === undefined || entry.local === null;\n let kind: UnpushedChange['kind'];\n if (baseAbsent && !localAbsent) kind = 'added';\n else if (!baseAbsent && localAbsent) kind = 'removed';\n else kind = 'modified';\n changes.push({\n bucket: entry.bucket,\n key: entry.key,\n label: entry.label,\n kind,\n base: entry.base,\n local: entry.local,\n });\n }\n return finalize(changes, now().toISOString());\n}\n\n/**\n * Cheap \"anything to push?\" check for the BranchCard badge. Avoids\n * recomputing the full preview list when the caller only needs a\n * boolean. Identity short-circuits on referential equality of `current`\n * and `base` — common when the store hasn't mutated since pull.\n */\nexport function hasUnpushedChanges(\n base: WorkspaceSynced | null,\n current: WorkspaceSynced,\n): boolean {\n if (current === base) return false;\n return summarizeUnpushedChanges(base, current).total > 0;\n}\n\nfunction summarizeAllAsAdded(synced: WorkspaceSynced, computedAt: string): UnpushedSummary {\n const changes: UnpushedChange[] = [];\n for (const [id, req] of Object.entries(synced.collections.requests)) {\n changes.push({\n bucket: 'request',\n key: id,\n label: req.name || id,\n kind: 'added',\n base: undefined,\n local: req,\n });\n }\n for (const [id, folder] of Object.entries(synced.collections.folders)) {\n changes.push({\n bucket: 'folder',\n key: id,\n label: folder.name || id,\n kind: 'added',\n base: undefined,\n local: folder,\n });\n }\n for (const [name, env] of Object.entries(synced.environments.items)) {\n changes.push({\n bucket: 'environment',\n key: name,\n label: name,\n kind: 'added',\n base: undefined,\n local: env,\n });\n }\n for (const [id, link] of Object.entries(synced.linkedWorkspaces)) {\n changes.push({\n bucket: 'linkedWorkspace',\n key: id,\n label: link.name || id,\n kind: 'added',\n base: undefined,\n local: link,\n });\n }\n for (const [id, server] of Object.entries(synced.mockServers)) {\n changes.push({\n bucket: 'mockServer',\n key: id,\n label: server.name || id,\n kind: 'added',\n base: undefined,\n local: server,\n });\n }\n // executionPlans is optional in the synced doc — pre-migration workspaces\n // may not have hydrated it yet. Treat absent as the empty dict (no plans\n // to report) rather than crashing on Object.entries(undefined).\n for (const [id, plan] of Object.entries(synced.executionPlans ?? {})) {\n changes.push({\n bucket: 'executionPlan',\n key: id,\n label: plan.name || id,\n kind: 'added',\n base: undefined,\n local: plan,\n });\n }\n // secretKeys is also optional pre-migration; same treatment as plans.\n for (const [id, meta] of Object.entries(synced.secretKeys ?? {})) {\n changes.push({\n bucket: 'secretKey',\n key: id,\n label: meta.label || id,\n kind: 'added',\n base: undefined,\n local: meta,\n });\n }\n for (const [id, schema] of Object.entries(synced.globalAssets.schemas)) {\n changes.push({\n bucket: 'globalSchema',\n key: id,\n label: schema.name || id,\n kind: 'added',\n base: undefined,\n local: schema,\n });\n }\n for (const [id, gql] of Object.entries(synced.globalAssets.graphql)) {\n changes.push({\n bucket: 'globalGraphql',\n key: id,\n label: gql.name || id,\n kind: 'added',\n base: undefined,\n local: gql,\n });\n }\n for (const [id, file] of Object.entries(synced.globalAssets.files ?? {})) {\n changes.push({\n bucket: 'globalFile',\n key: id,\n label: file.name || file.filename || id,\n kind: 'added',\n base: undefined,\n local: file,\n });\n }\n for (const [key, override] of Object.entries(synced.linkedOverrides.requests)) {\n changes.push({\n bucket: 'linkedRequestOverride',\n key,\n label: `linked request override (${key})`,\n kind: 'added',\n base: undefined,\n local: override,\n });\n }\n for (const [key, override] of Object.entries(synced.linkedOverrides.environmentVars)) {\n changes.push({\n bucket: 'linkedEnvOverride',\n key,\n label: `linked env var override (${key})`,\n kind: 'added',\n base: undefined,\n local: override,\n });\n }\n for (const [linkId, ledger] of Object.entries(synced.releases.perLink)) {\n changes.push({\n bucket: 'releasePerLink',\n key: linkId,\n label: `linked release ledger (${linkId})`,\n kind: 'added',\n base: undefined,\n local: ledger,\n });\n }\n // Singletons that only count when they're non-default. We only report\n // the tree when it's non-empty — otherwise every fresh workspace would\n // claim a singleton \"add\".\n if (synced.collections.tree.children.length > 0) {\n changes.push({\n bucket: 'tree',\n key: '',\n label: 'Folder tree',\n kind: 'added',\n base: undefined,\n local: synced.collections.tree,\n });\n }\n if (synced.releases.self) {\n changes.push({\n bucket: 'releaseSelf',\n key: '',\n label: 'Release ledger',\n kind: 'added',\n base: undefined,\n local: synced.releases.self,\n });\n }\n // Workspace passphrase: only counts when actually set. A null/absent\n // value is the no-passphrase default — don't claim a singleton \"add\"\n // for every fresh workspace.\n if (synced.secretCrypto) {\n changes.push({\n bucket: 'secretCrypto',\n key: '',\n label: 'Workspace passphrase',\n kind: 'added',\n base: undefined,\n local: synced.secretCrypto,\n });\n }\n return finalize(changes, computedAt);\n}\n\nfunction finalize(changes: UnpushedChange[], computedAt: string): UnpushedSummary {\n changes.sort((a, b) => {\n const ba = BUCKET_ORDER.indexOf(a.bucket);\n const bb = BUCKET_ORDER.indexOf(b.bucket);\n if (ba !== bb) return ba - bb;\n return a.label.localeCompare(b.label, undefined, { sensitivity: 'base' });\n });\n let added = 0;\n let modified = 0;\n let removed = 0;\n for (const c of changes) {\n if (c.kind === 'added') added += 1;\n else if (c.kind === 'modified') modified += 1;\n else removed += 1;\n }\n return { added, modified, removed, total: changes.length, changes, computedAt };\n}\n\n/** Stable empty value for callers that want to default-render an empty summary. */\nexport const EMPTY_UNPUSHED_SUMMARY = EMPTY_SUMMARY;\n","// Three-way merge for linked-workspace updates.\n//\n// When a consumer wants to bump their pinned version of a linked workspace\n// to a newer one, we classify every request / env-var / folder against\n// THREE inputs:\n//\n// • base — the consumer's currently-pinned snapshot of the source.\n// • target — the source's published snapshot at the new version.\n// • override — the consumer's local modifications (only requests +\n// env-vars carry overrides; folders are source-pinned).\n//\n// Each entity gets one status:\n//\n// unchanged base ≡ target AND no override → no-op\n// source-only base ≠ target AND no override → fast-forward\n// local-only base ≡ target AND override → keep mine\n// both-changed base ≠ target AND override → user picks\n// new-in-source base missing, target present → adopt new entity\n// removed-in-source base present, target missing → orphan\n//\n// \"both-changed\" intentionally lumps clean-merge and conflict together\n// for the first cut — letting the user explicitly accept-source or\n// keep-mine is loud and safe. Auto-merging non-overlapping field edits\n// is a follow-on slice (lands cleanly on top of this same data shape).\n\nimport type {\n EnvironmentVariable,\n EnvironmentVariableOverride,\n Folder,\n LinkedSnapshot,\n Request as ApiRequest,\n RequestOverride,\n} from '@apicircle/shared';\n\nexport type LinkedUpdateStatus =\n | 'unchanged'\n | 'source-only'\n | 'local-only'\n | 'both-changed'\n | 'new-in-source'\n | 'removed-in-source';\n\nexport type LinkedUpdateBucket = 'request' | 'folder' | 'environment-var';\n\nexport interface LinkedUpdateEntry<TBase = unknown, TTarget = unknown, TOverride = unknown> {\n bucket: LinkedUpdateBucket;\n /** Identifier scoped to the bucket. For env-var, format `<envName>:<varKey>`. */\n key: string;\n label: string;\n status: LinkedUpdateStatus;\n base: TBase | null;\n target: TTarget | null;\n override: TOverride | null;\n}\n\nexport interface LinkedUpdatePreview {\n fromVersion: string | null;\n toVersion: string;\n entries: LinkedUpdateEntry[];\n /** Quick counts for the modal summary line. */\n summary: Record<LinkedUpdateStatus, number>;\n}\n\nexport interface PreviewArgs {\n fromVersion: string | null;\n toVersion: string;\n base: LinkedSnapshot | null;\n target: LinkedSnapshot;\n /** All request overrides keyed by `${linkedWorkspaceId}:${itemId}` — caller pre-filters to one link. */\n requestOverrides: RequestOverride[];\n /** All env-var overrides for this link. */\n envVarOverrides: EnvironmentVariableOverride[];\n}\n\n/**\n * Pure function — returns a structured preview of every change between\n * `base` and `target`, classified by status and annotated with the\n * consumer's overrides where applicable. Caller renders the modal and\n * collects resolutions for `both-changed` entries.\n */\nexport function previewLinkedUpdate(args: PreviewArgs): LinkedUpdatePreview {\n const entries: LinkedUpdateEntry[] = [];\n\n // --- Requests ----------------------------------------------------------\n const baseRequests = args.base?.collections.requests ?? {};\n const targetRequests = args.target.collections.requests;\n const overrideByItem = new Map<string, RequestOverride>(\n args.requestOverrides.map((o) => [o.itemId, o]),\n );\n const allRequestIds = new Set([...Object.keys(baseRequests), ...Object.keys(targetRequests)]);\n for (const id of allRequestIds) {\n const base = baseRequests[id] ?? null;\n const target = targetRequests[id] ?? null;\n const override = overrideByItem.get(id) ?? null;\n const status = classifyRequest(base, target, override);\n if (status === 'unchanged') continue;\n entries.push({\n bucket: 'request',\n key: id,\n label: target?.name ?? base?.name ?? id,\n status,\n base,\n target,\n override,\n });\n }\n\n // --- Folders -----------------------------------------------------------\n // Folders aren't overridable today — every change is either source-only\n // (consumer adopts) or removed-in-source (orphan). They always classify\n // cleanly without a user decision.\n const baseFolders = args.base?.collections.folders ?? {};\n const targetFolders = args.target.collections.folders;\n const allFolderIds = new Set([...Object.keys(baseFolders), ...Object.keys(targetFolders)]);\n for (const id of allFolderIds) {\n const base = baseFolders[id] ?? null;\n const target = targetFolders[id] ?? null;\n const status = classifyFolder(base, target);\n if (status === 'unchanged') continue;\n entries.push({\n bucket: 'folder',\n key: id,\n label: target?.name ?? base?.name ?? id,\n status,\n base,\n target,\n override: null,\n });\n }\n\n // --- Environment variables --------------------------------------------\n const baseEnvs = args.base?.environments.items ?? {};\n const targetEnvs = args.target.environments.items;\n const allEnvNames = new Set([...Object.keys(baseEnvs), ...Object.keys(targetEnvs)]);\n for (const envName of allEnvNames) {\n const baseVars = baseEnvs[envName]?.variables ?? [];\n const targetVars = targetEnvs[envName]?.variables ?? [];\n const overrides = args.envVarOverrides.filter((o) => o.envName === envName);\n const allKeys = new Set<string>([\n ...baseVars.map((v) => v.key),\n ...targetVars.map((v) => v.key),\n ...overrides.map((o) => o.varKey),\n ]);\n const baseByKey = new Map(baseVars.map((v) => [v.key, v]));\n const targetByKey = new Map(targetVars.map((v) => [v.key, v]));\n const overrideByKey = new Map(overrides.map((o) => [o.varKey, o]));\n for (const varKey of allKeys) {\n const base = baseByKey.get(varKey) ?? null;\n const target = targetByKey.get(varKey) ?? null;\n const override = overrideByKey.get(varKey) ?? null;\n const status = classifyEnvVar(base, target, override);\n if (status === 'unchanged') continue;\n entries.push({\n bucket: 'environment-var',\n key: `${envName}:${varKey}`,\n label: `${envName} → ${varKey}`,\n status,\n base,\n target,\n override,\n });\n }\n }\n\n const summary: Record<LinkedUpdateStatus, number> = {\n unchanged: 0,\n 'source-only': 0,\n 'local-only': 0,\n 'both-changed': 0,\n 'new-in-source': 0,\n 'removed-in-source': 0,\n };\n for (const e of entries) summary[e.status] += 1;\n\n return {\n fromVersion: args.fromVersion,\n toVersion: args.toVersion,\n entries,\n summary,\n };\n}\n\nfunction classifyRequest(\n base: ApiRequest | null,\n target: ApiRequest | null,\n override: RequestOverride | null,\n): LinkedUpdateStatus {\n if (!base && target) return 'new-in-source';\n if (base && !target) return 'removed-in-source';\n if (!base || !target) return 'unchanged';\n const sourceChanged = !structurallyEqual(base, target);\n const hasOverride = override !== null && Object.keys(override.patch).length > 0;\n if (!sourceChanged && !hasOverride) return 'unchanged';\n if (!sourceChanged && hasOverride) return 'local-only';\n if (sourceChanged && !hasOverride) return 'source-only';\n return 'both-changed';\n}\n\nfunction classifyFolder(base: Folder | null, target: Folder | null): LinkedUpdateStatus {\n if (!base && target) return 'new-in-source';\n if (base && !target) return 'removed-in-source';\n if (!base || !target) return 'unchanged';\n return structurallyEqual(base, target) ? 'unchanged' : 'source-only';\n}\n\nfunction classifyEnvVar(\n base: EnvironmentVariable | null,\n target: EnvironmentVariable | null,\n override: EnvironmentVariableOverride | null,\n): LinkedUpdateStatus {\n // Consumer-only addition (no source counterpart, override exists, not removed).\n if (!base && !target && override && !override.removed) return 'local-only';\n if (!base && target) return 'new-in-source';\n if (base && !target) return 'removed-in-source';\n if (!base || !target) return 'unchanged';\n const sourceChanged = !structurallyEqual(base, target);\n const hasOverride = override !== null;\n if (!sourceChanged && !hasOverride) return 'unchanged';\n if (!sourceChanged && hasOverride) return 'local-only';\n if (sourceChanged && !hasOverride) return 'source-only';\n return 'both-changed';\n}\n\n/**\n * Map status → 'mine' | 'theirs' for entries the user has resolved.\n * 'mine' = keep the override / orphan. 'theirs' = adopt source.\n *\n * `source-only`, `new-in-source`, and `local-only` don't need a\n * resolution (auto-applied), so this map is keyed only by entries that\n * are `both-changed` or `removed-in-source` (the latter optionally lets\n * the user keep their override as a consumer-only request — a rarer\n * choice).\n */\nexport type LinkedUpdateResolutionMap = Record<string, 'mine' | 'theirs'>;\n\nexport interface ApplyArgs {\n base: LinkedSnapshot | null;\n target: LinkedSnapshot;\n preview: LinkedUpdatePreview;\n resolutions: LinkedUpdateResolutionMap;\n /** All overrides for this link, BEFORE the apply. */\n requestOverrides: RequestOverride[];\n envVarOverrides: EnvironmentVariableOverride[];\n}\n\nexport interface ApplyResult {\n /** New canonical snapshot to cache (replaces base). */\n nextSnapshot: LinkedSnapshot;\n /** Override entries the consumer keeps after applying. */\n nextRequestOverrides: RequestOverride[];\n nextEnvVarOverrides: EnvironmentVariableOverride[];\n /** Per-entry record of what we did, surfaced to the toast / activity log. */\n log: Array<{ entryKey: string; bucket: LinkedUpdateBucket; action: string }>;\n}\n\n/**\n * Apply a fully-resolved preview. Pure — does not touch IDB or the store.\n *\n * Throws when any `both-changed` entry is missing a resolution.\n */\nexport function applyLinkedUpdate(args: ApplyArgs): ApplyResult {\n const log: ApplyResult['log'] = [];\n const requestOverridesByItem = new Map<string, RequestOverride>(\n args.requestOverrides.map((o) => [o.itemId, o]),\n );\n const envVarOverridesByKey = new Map<string, EnvironmentVariableOverride>(\n args.envVarOverrides.map((o) => [`${o.envName}:${o.varKey}`, o]),\n );\n\n for (const entry of args.preview.entries) {\n const id = `${entry.bucket}:${entry.key}`;\n if (entry.status === 'unchanged') continue;\n if (entry.status === 'source-only' || entry.status === 'new-in-source') {\n // Adopting target — nothing to do beyond replacing the snapshot.\n log.push({ entryKey: id, bucket: entry.bucket, action: 'adopt-source' });\n continue;\n }\n if (entry.status === 'local-only') {\n log.push({ entryKey: id, bucket: entry.bucket, action: 'keep-mine' });\n continue;\n }\n\n if (entry.status === 'removed-in-source') {\n // Default for orphans is to drop the override (nothing to override\n // if the source request is gone). Consumer can opt-in to keeping it\n // by supplying a 'mine' resolution explicitly.\n const choice = args.resolutions[id] ?? 'theirs';\n if (choice === 'theirs') {\n if (entry.bucket === 'request') requestOverridesByItem.delete(entry.key);\n else if (entry.bucket === 'environment-var') envVarOverridesByKey.delete(entry.key);\n log.push({ entryKey: id, bucket: entry.bucket, action: 'drop-orphan' });\n } else {\n log.push({ entryKey: id, bucket: entry.bucket, action: 'keep-orphan' });\n }\n continue;\n }\n\n if (entry.status === 'both-changed') {\n const choice = args.resolutions[id];\n if (!choice) {\n throw new Error(\n `applyLinkedUpdate: unresolved both-changed entry \"${entry.label}\" (${id})`,\n );\n }\n if (choice === 'theirs') {\n if (entry.bucket === 'request') requestOverridesByItem.delete(entry.key);\n else if (entry.bucket === 'environment-var') envVarOverridesByKey.delete(entry.key);\n log.push({ entryKey: id, bucket: entry.bucket, action: 'accept-source' });\n } else {\n log.push({ entryKey: id, bucket: entry.bucket, action: 'keep-mine' });\n }\n }\n }\n\n return {\n nextSnapshot: args.target,\n nextRequestOverrides: [...requestOverridesByItem.values()],\n nextEnvVarOverrides: [...envVarOverridesByKey.values()],\n log,\n };\n}\n\n/**\n * Stable structural equality. JSON.stringify is good enough here because\n * every diffable field is a plain JSON value (no Dates, no class\n * instances, no functions). Object key ordering is preserved by V8's\n * insertion-order semantics for string keys.\n *\n * The `serializeWorkspace` canonical sort happens at push time, not at\n * diff time — this is intra-doc comparison, not byte equality with git.\n */\nfunction structurallyEqual(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n","import type {\n EnvPriorityRef,\n Folder,\n FolderNode,\n Request as ApiRequest,\n WorkspaceLocal,\n WorkspaceSnapshot,\n WorkspaceSnapshotTrigger,\n WorkspaceSynced,\n} from '@apicircle/shared';\nimport { envPriorityKey, generateId } from '@apicircle/shared';\nimport type { WorkspacePatch, WorkspaceState } from './patches';\nimport {\n importApicircleFolderInto,\n type ImportApicircleFolderResult,\n} from './apicircleFolderImport';\nimport type { ParsedApicircleFolderExport } from '../import/apicircleFolder';\n\n// =============================================================================\n// applyMutation — single dispatch over every workspace patch.\n//\n// Pure: does not touch IDB, the network, or `Date.now` indirectly through\n// imports. The `now` parameter is injectable so tests can pin timestamps and\n// so the orchestrator stays deterministic when called multiple times in a\n// batch (e.g. an MCP tool handler applying several patches in sequence).\n//\n// `changedIds` carries the entity ids touched by the patch (request id,\n// folder id, environment name, plan id, mock id, etc). Callers use it to\n// invalidate caches, trigger autosave, or report results back to MCP\n// clients.\n// =============================================================================\n\nexport interface ApplyMutationOptions {\n /** ISO timestamp to stamp into `updatedAt`. Defaults to the current time. */\n now?: string;\n}\n\nexport interface ApplyMutationResult {\n next: WorkspaceState;\n changedIds: string[];\n}\n\nexport function applyMutation(\n state: WorkspaceState,\n patch: WorkspacePatch,\n options: ApplyMutationOptions = {},\n): ApplyMutationResult {\n const now = options.now ?? new Date().toISOString();\n switch (patch.kind) {\n case 'request.create':\n return applyRequestCreate(state, patch.request, now);\n case 'request.update':\n return applyRequestUpdate(state, patch.id, patch.patch, now);\n case 'request.delete':\n return applyRequestDelete(state, patch.id, now);\n case 'folder.create':\n return applyFolderCreate(state, patch.folder, now);\n case 'folder.delete':\n return applyFolderDelete(state, patch.id, now);\n case 'folder.move':\n return applyFolderMove(state, patch.id, patch.newParentId, now);\n case 'folder.import_apicircle':\n return applyFolderImportApicircle(state, patch.parsed, patch.parentFolderId, now);\n case 'environment.upsert':\n return applyEnvUpsert(state, patch.environment, now);\n case 'environment.delete':\n return applyEnvDelete(state, patch.name, now);\n case 'environment.setActive':\n return applyEnvSetActive(state, patch.name, now);\n case 'environment.setPriority':\n return applyEnvSetPriority(state, patch.order, now);\n case 'secretKey.upsert':\n return applySecretKeyUpsert(state, patch.meta, now);\n case 'assertion.upsert':\n return applyAssertionUpsert(state, patch.requestId, patch.assertion, now);\n case 'assertion.delete':\n return applyAssertionDelete(state, patch.requestId, patch.assertionId, now);\n case 'mock.upsert':\n return applyMockUpsert(state, patch.mock, now);\n case 'mock.delete':\n return applyMockDelete(state, patch.id, now);\n case 'plan.upsert':\n return applyPlanUpsert(state, patch.plan, now);\n case 'plan.delete':\n return applyPlanDelete(state, patch.id);\n case 'history.delete_run':\n return applyHistoryDeleteRun(state, patch.runId);\n case 'history.delete_plan_run':\n return applyHistoryDeletePlanRun(state, patch.planRunId);\n case 'history.purge':\n return applyHistoryPurge(state, patch.olderThanMs);\n case 'snapshot.capture':\n return applySnapshotCapture(state, patch, now);\n case 'snapshot.delete':\n return applySnapshotDelete(state, patch.id);\n case 'snapshot.restore':\n return applySnapshotRestore(state, patch.id, now);\n case 'snapshot.set_max_bytes':\n return applySnapshotSetMaxBytes(state, patch.maxBytes);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Request handlers\n// ---------------------------------------------------------------------------\n\nfunction applyRequestCreate(\n state: WorkspaceState,\n request: ApiRequest,\n now: string,\n): ApplyMutationResult {\n if (state.synced.collections.requests[request.id]) {\n return { next: state, changedIds: [] };\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n requests: { ...state.synced.collections.requests, [request.id]: request },\n tree: pushTreeChild(state.synced.collections.tree, { kind: 'request', id: request.id }),\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [request.id] };\n}\n\nfunction applyRequestUpdate(\n state: WorkspaceState,\n id: string,\n patch: Partial<Omit<ApiRequest, 'id' | 'createdAt'>>,\n now: string,\n): ApplyMutationResult {\n const existing = state.synced.collections.requests[id];\n if (!existing) {\n return { next: state, changedIds: [] };\n }\n const updated: ApiRequest = {\n ...existing,\n ...patch,\n id: existing.id,\n createdAt: existing.createdAt,\n updatedAt: now,\n };\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n requests: { ...state.synced.collections.requests, [id]: updated },\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [id] };\n}\n\nfunction applyRequestDelete(state: WorkspaceState, id: string, now: string): ApplyMutationResult {\n if (!state.synced.collections.requests[id]) {\n return { next: state, changedIds: [] };\n }\n const requests = { ...state.synced.collections.requests };\n delete requests[id];\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n requests,\n tree: removeTreeChild(state.synced.collections.tree, { kind: 'request', id }),\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n // Linked-request overrides live on `synced.linkedOverrides.requests`\n // and are keyed by the LINKED workspace's request id, not by an owned\n // request id. Deleting an owned request never touches them.\n return { next: { ...state, synced }, changedIds: [id] };\n}\n\n// ---------------------------------------------------------------------------\n// Folder handlers\n// ---------------------------------------------------------------------------\n\nfunction applyFolderCreate(\n state: WorkspaceState,\n folder: Folder,\n now: string,\n): ApplyMutationResult {\n if (state.synced.collections.folders[folder.id]) {\n return { next: state, changedIds: [] };\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n folders: { ...state.synced.collections.folders, [folder.id]: folder },\n tree: pushTreeChild(state.synced.collections.tree, { kind: 'folder', id: folder.id }),\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [folder.id] };\n}\n\nfunction applyFolderDelete(state: WorkspaceState, id: string, now: string): ApplyMutationResult {\n if (!state.synced.collections.folders[id]) {\n return { next: state, changedIds: [] };\n }\n const folders = { ...state.synced.collections.folders };\n delete folders[id];\n // Reparent any direct children to the deleted folder's parent.\n const deleted = state.synced.collections.folders[id];\n const reparented: Record<string, Folder> = {};\n for (const [fid, f] of Object.entries(folders)) {\n if (f.parentId === id) {\n reparented[fid] = { ...f, parentId: deleted.parentId };\n } else {\n reparented[fid] = f;\n }\n }\n const requests = { ...state.synced.collections.requests };\n for (const [rid, r] of Object.entries(requests)) {\n if (r.folderId === id) {\n requests[rid] = { ...r, folderId: deleted.parentId };\n }\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n folders: reparented,\n requests,\n tree: removeTreeChild(state.synced.collections.tree, { kind: 'folder', id }),\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [id] };\n}\n\nfunction applyFolderMove(\n state: WorkspaceState,\n id: string,\n newParentId: string | null,\n now: string,\n): ApplyMutationResult {\n const folder = state.synced.collections.folders[id];\n if (!folder) {\n return { next: state, changedIds: [] };\n }\n if (folder.parentId === newParentId) {\n return { next: state, changedIds: [] };\n }\n // Reject self-parenting.\n if (newParentId === id) {\n return { next: state, changedIds: [] };\n }\n // Reject creating a cycle: walk up newParent's chain; if we hit `id`, abort.\n let cursor: string | null = newParentId;\n const folders = state.synced.collections.folders;\n while (cursor !== null) {\n if (cursor === id) return { next: state, changedIds: [] };\n cursor = folders[cursor]?.parentId ?? null;\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n folders: {\n ...state.synced.collections.folders,\n [id]: { ...folder, parentId: newParentId },\n },\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [id] };\n}\n\n/**\n * Result-shape escape hatch for the `folder.import_apicircle` handler:\n * the underlying graft helper returns a richer object than the rest of\n * the reducers. We surface only the root + descendant ids through\n * `ApplyMutationResult.changedIds`. Clients that need the full counts\n * or re-attachment list should call `importApicircleFolderInto`\n * directly — the patch path is intentionally lossy so every reducer\n * has the same `{ next, changedIds }` shape.\n */\nfunction applyFolderImportApicircle(\n state: WorkspaceState,\n parsed: ParsedApicircleFolderExport,\n parentFolderId: string | null,\n now: string,\n): ApplyMutationResult {\n const result: ImportApicircleFolderResult = importApicircleFolderInto(\n state.synced,\n parsed,\n parentFolderId,\n );\n const synced: WorkspaceSynced = {\n ...result.synced,\n meta: { ...result.synced.meta, updatedAt: now },\n };\n const changedIds = [\n result.rootFolderId,\n ...parsed.subfolders.map((f) => f.id),\n ...parsed.requests.map((r) => r.id),\n ];\n return { next: { ...state, synced }, changedIds };\n}\n\n// ---------------------------------------------------------------------------\n// Environment handlers\n// ---------------------------------------------------------------------------\n\nfunction applyEnvUpsert(\n state: WorkspaceState,\n environment: {\n name: string;\n variables: Array<{ key: string; value: string; encrypted: boolean }>;\n },\n now: string,\n): ApplyMutationResult {\n const trimmed = environment.name.trim();\n if (!trimmed) {\n return { next: state, changedIds: [] };\n }\n const isNew = !state.synced.environments.items[trimmed];\n const synced: WorkspaceSynced = {\n ...state.synced,\n environments: {\n ...state.synced.environments,\n items: {\n ...state.synced.environments.items,\n [trimmed]: { ...environment, name: trimmed },\n },\n // Newly-created envs land at the end of the priority list so they're\n // always reachable. Existing envs keep their position.\n priorityOrder:\n isNew &&\n !state.synced.environments.priorityOrder.some(\n (r) => r.kind === 'local' && r.name === trimmed,\n )\n ? [...state.synced.environments.priorityOrder, { kind: 'local', name: trimmed }]\n : state.synced.environments.priorityOrder,\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [trimmed] };\n}\n\nfunction applyEnvDelete(state: WorkspaceState, name: string, now: string): ApplyMutationResult {\n if (!state.synced.environments.items[name]) {\n return { next: state, changedIds: [] };\n }\n const items = { ...state.synced.environments.items };\n delete items[name];\n const synced: WorkspaceSynced = {\n ...state.synced,\n environments: {\n ...state.synced.environments,\n items,\n activeName:\n state.synced.environments.activeName === name ? null : state.synced.environments.activeName,\n priorityOrder: state.synced.environments.priorityOrder.filter(\n (r) => !(r.kind === 'local' && r.name === name),\n ),\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [name] };\n}\n\nfunction applyEnvSetActive(\n state: WorkspaceState,\n name: string | null,\n now: string,\n): ApplyMutationResult {\n if (name !== null && !state.synced.environments.items[name]) {\n return { next: state, changedIds: [] };\n }\n if (state.synced.environments.activeName === name) {\n return { next: state, changedIds: [] };\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n environments: { ...state.synced.environments, activeName: name },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: name ? [name] : [] };\n}\n\nfunction applyEnvSetPriority(\n state: WorkspaceState,\n order: EnvPriorityRef[],\n now: string,\n): ApplyMutationResult {\n // Filter against:\n // - local envs: must be in `state.synced.environments.items`\n // - linked envs: pass through unconditionally — the snapshot lives in\n // `WorkspaceLocal.linkedCollections` which this reducer can't see.\n // Stale linked refs are dropped at resolve time (handled by\n // parseEnvPriorityKey returning null for unknown shapes).\n // Dedupe across both kinds via composite key.\n const knownLocal = new Set(Object.keys(state.synced.environments.items));\n const seen = new Set<string>();\n const filtered = order.filter((ref) => {\n const key = envPriorityKey(ref);\n if (seen.has(key)) return false;\n if (ref.kind === 'local' && !knownLocal.has(ref.name)) return false;\n seen.add(key);\n return true;\n });\n const synced: WorkspaceSynced = {\n ...state.synced,\n environments: { ...state.synced.environments, priorityOrder: filtered },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: filtered.map(envPriorityKey) };\n}\n\n// ---------------------------------------------------------------------------\n// Secret-vault slot handlers\n// ---------------------------------------------------------------------------\n\nfunction applySecretKeyUpsert(\n state: WorkspaceState,\n meta: { id: string; label: string; salt: string; createdAt: string },\n now: string,\n): ApplyMutationResult {\n // Defensive: an empty id or label would corrupt the slot map. Drop\n // silently so an MCP client batching multiple slot upserts doesn't\n // poison the workspace on a single malformed row.\n if (!meta.id || !meta.label.trim() || !meta.salt) {\n return { next: state, changedIds: [] };\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n secretKeys: {\n ...(state.synced.secretKeys ?? {}),\n [meta.id]: { ...meta, label: meta.label.trim() },\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [meta.id] };\n}\n\n// ---------------------------------------------------------------------------\n// Assertion handlers\n// ---------------------------------------------------------------------------\n\nfunction applyAssertionUpsert(\n state: WorkspaceState,\n requestId: string,\n assertion: { id: string; kind: string; op: string; expected: string | number; target?: string },\n now: string,\n): ApplyMutationResult {\n const request = state.synced.collections.requests[requestId];\n if (!request) {\n return { next: state, changedIds: [] };\n }\n const idx = request.assertions.findIndex((a) => a.id === assertion.id);\n const next = [...request.assertions];\n if (idx === -1) {\n next.push(assertion as ApiRequest['assertions'][number]);\n } else {\n next[idx] = assertion as ApiRequest['assertions'][number];\n }\n return applyRequestUpdate(state, requestId, { assertions: next }, now);\n}\n\nfunction applyAssertionDelete(\n state: WorkspaceState,\n requestId: string,\n assertionId: string,\n now: string,\n): ApplyMutationResult {\n const request = state.synced.collections.requests[requestId];\n if (!request) {\n return { next: state, changedIds: [] };\n }\n const next = request.assertions.filter((a) => a.id !== assertionId);\n if (next.length === request.assertions.length) {\n return { next: state, changedIds: [] };\n }\n return applyRequestUpdate(state, requestId, { assertions: next }, now);\n}\n\n// ---------------------------------------------------------------------------\n// Mock handlers\n// ---------------------------------------------------------------------------\n\nfunction applyMockUpsert(\n state: WorkspaceState,\n mock: { id: string },\n now: string,\n): ApplyMutationResult {\n const synced: WorkspaceSynced = {\n ...state.synced,\n mockServers: {\n ...state.synced.mockServers,\n [mock.id]: mock as WorkspaceSynced['mockServers'][string],\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [mock.id] };\n}\n\nfunction applyMockDelete(state: WorkspaceState, id: string, now: string): ApplyMutationResult {\n if (!state.synced.mockServers[id]) {\n return { next: state, changedIds: [] };\n }\n const mockServers = { ...state.synced.mockServers };\n delete mockServers[id];\n const synced: WorkspaceSynced = {\n ...state.synced,\n mockServers,\n meta: { ...state.synced.meta, updatedAt: now },\n };\n // Also clear runtime entry — a deleted definition can't have a live runtime.\n const local: WorkspaceLocal = state.local.mockRuntime.active[id]\n ? {\n ...state.local,\n mockRuntime: {\n active: Object.fromEntries(\n Object.entries(state.local.mockRuntime.active).filter(([k]) => k !== id),\n ),\n },\n }\n : state.local;\n return { next: { synced, local }, changedIds: [id] };\n}\n\n// ---------------------------------------------------------------------------\n// Plan handlers (WorkspaceLocal — never pushed to git)\n// ---------------------------------------------------------------------------\n\nfunction applyPlanUpsert(\n state: WorkspaceState,\n plan: { id: string },\n now: string,\n): ApplyMutationResult {\n const existing = state.local.executionPlans[plan.id];\n const merged = existing\n ? { ...existing, ...plan, id: existing.id, createdAt: existing.createdAt, updatedAt: now }\n : { ...plan, updatedAt: now };\n const local: WorkspaceLocal = {\n ...state.local,\n executionPlans: {\n ...state.local.executionPlans,\n [plan.id]: merged as WorkspaceLocal['executionPlans'][string],\n },\n };\n return { next: { ...state, local }, changedIds: [plan.id] };\n}\n\nfunction applyPlanDelete(state: WorkspaceState, id: string): ApplyMutationResult {\n if (!state.local.executionPlans[id]) {\n return { next: state, changedIds: [] };\n }\n const next = { ...state.local.executionPlans };\n delete next[id];\n // Drop history rows too — they'd dangle to a non-existent plan.\n const planRuns = state.local.history.planRuns.filter((r) => r.planId !== id);\n const local: WorkspaceLocal = {\n ...state.local,\n executionPlans: next,\n history: { ...state.local.history, planRuns },\n };\n return { next: { ...state, local }, changedIds: [id] };\n}\n\n// ---------------------------------------------------------------------------\n// Tree helpers\n// ---------------------------------------------------------------------------\n\nfunction pushTreeChild(\n tree: FolderNode,\n child: { kind: 'folder' | 'request'; id: string },\n): FolderNode {\n return { ...tree, children: [...tree.children, child] };\n}\n\nfunction removeTreeChild(\n tree: FolderNode,\n child: { kind: 'folder' | 'request'; id: string },\n): FolderNode {\n return {\n ...tree,\n children: tree.children.filter((c) => !(c.kind === child.kind && c.id === child.id)),\n };\n}\n\n// ---------------------------------------------------------------------------\n// History handlers (WorkspaceLocal — never pushed to git). Each is pure: drop\n// the matching row(s) and return the new state. The MCP host uses these to\n// expose \"delete a single run\" and \"purge older than N days\" so users can\n// keep their local IDB footprint bounded.\n// ---------------------------------------------------------------------------\n\nfunction applyHistoryDeleteRun(state: WorkspaceState, runId: string): ApplyMutationResult {\n const before = state.local.history.requestRuns;\n const after = before.filter((r) => r.id !== runId);\n if (after.length === before.length) {\n return { next: state, changedIds: [] };\n }\n const local: WorkspaceLocal = {\n ...state.local,\n history: { ...state.local.history, requestRuns: after },\n };\n return { next: { ...state, local }, changedIds: [runId] };\n}\n\nfunction applyHistoryDeletePlanRun(state: WorkspaceState, planRunId: string): ApplyMutationResult {\n const before = state.local.history.planRuns;\n const after = before.filter((r) => r.id !== planRunId);\n if (after.length === before.length) {\n return { next: state, changedIds: [] };\n }\n const local: WorkspaceLocal = {\n ...state.local,\n history: { ...state.local.history, planRuns: after },\n };\n return { next: { ...state, local }, changedIds: [planRunId] };\n}\n\n// ---------------------------------------------------------------------------\n// Snapshot handlers (WorkspaceLocal.snapshots — never pushed to git). Each\n// snapshot is a verbatim copy of `synced` plus metadata. Capture pushes a\n// new entry and evicts oldest until total size is under `maxBytes`. Restore\n// replaces `synced` with the snapshot's stored doc and clears\n// `local.sync.lastPulledSnapshot` so the next push surfaces the restore as\n// a logical re-fork rather than a no-op.\n// ---------------------------------------------------------------------------\n\nfunction approxJsonByteLength(value: unknown): number {\n // JSON.stringify is the closest proxy to what IDB will persist; encoding\n // costs are ~1 byte/char for ASCII payloads. Multi-byte chars under-count\n // slightly, which is fine — the cap is a soft eviction trigger, not a\n // hard quota.\n try {\n return JSON.stringify(value).length;\n } catch {\n return 0;\n }\n}\n\nfunction evictSnapshotsToCap(\n entries: WorkspaceSnapshot[],\n maxBytes: number,\n): { entries: WorkspaceSnapshot[]; evictedIds: string[] } {\n if (!Number.isFinite(maxBytes) || maxBytes <= 0) {\n return { entries, evictedIds: [] };\n }\n let total = entries.reduce((sum, e) => sum + e.sizeBytes, 0);\n if (total <= maxBytes) return { entries, evictedIds: [] };\n // Sort oldest-first so we drop the front of the list. We rebuild the\n // array rather than mutating it in place.\n const sorted = [...entries].sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n const evictedIds: string[] = [];\n while (total > maxBytes && sorted.length > 0) {\n const dropped = sorted.shift()!;\n evictedIds.push(dropped.id);\n total -= dropped.sizeBytes;\n }\n // Restore newest-first ordering so callers' \"first entry is most recent\"\n // assumption holds (the History panel renders in this order).\n return {\n entries: sorted.sort((a, b) => b.createdAt.localeCompare(a.createdAt)),\n evictedIds,\n };\n}\n\nfunction applySnapshotCapture(\n state: WorkspaceState,\n args: { trigger: WorkspaceSnapshotTrigger; note?: string; id?: string },\n now: string,\n): ApplyMutationResult {\n const id = args.id ?? generateId();\n const snapshot: WorkspaceSnapshot = {\n id,\n createdAt: now,\n triggeredBy: args.trigger,\n note: args.note,\n workspaceSyncedSnapshot: state.synced,\n sizeBytes: approxJsonByteLength(state.synced),\n };\n const ledger = state.local.snapshots;\n // Newest-first so the History panel can iterate without sorting.\n const merged = [snapshot, ...ledger.entries];\n const { entries, evictedIds } = evictSnapshotsToCap(merged, ledger.maxBytes);\n const local: WorkspaceLocal = {\n ...state.local,\n snapshots: { ...ledger, entries },\n };\n return { next: { ...state, local }, changedIds: [id, ...evictedIds] };\n}\n\nfunction applySnapshotDelete(state: WorkspaceState, id: string): ApplyMutationResult {\n const before = state.local.snapshots.entries;\n const after = before.filter((s) => s.id !== id);\n if (after.length === before.length) {\n return { next: state, changedIds: [] };\n }\n const local: WorkspaceLocal = {\n ...state.local,\n snapshots: { ...state.local.snapshots, entries: after },\n };\n return { next: { ...state, local }, changedIds: [id] };\n}\n\nfunction applySnapshotRestore(state: WorkspaceState, id: string, now: string): ApplyMutationResult {\n const target = state.local.snapshots.entries.find((s) => s.id === id);\n if (!target) {\n return { next: state, changedIds: [] };\n }\n // The synced doc replaces wholesale. The snapshot's own meta.updatedAt\n // is preserved so the user can see how stale the restored state was;\n // top-level workspace updatedAt re-stamps to `now` so downstream\n // consumers (the diff summary, last-pull tracker) see the change.\n const synced: WorkspaceSynced = {\n ...target.workspaceSyncedSnapshot,\n meta: { ...target.workspaceSyncedSnapshot.meta, updatedAt: now },\n };\n // Restore is logically a re-fork: anything in the upstream remote will\n // diverge from our restored state. Clear `lastPulledSnapshot` so the\n // diff summary surfaces every restored entry as \"new\" against remote.\n const local: WorkspaceLocal = {\n ...state.local,\n sync: {\n ...state.local.sync,\n lastPulledSnapshot: null,\n lastPulledSha: null,\n },\n };\n return { next: { synced, local }, changedIds: [id] };\n}\n\nfunction applySnapshotSetMaxBytes(state: WorkspaceState, maxBytes: number): ApplyMutationResult {\n if (maxBytes < 0) maxBytes = 0;\n const ledger = state.local.snapshots;\n const { entries, evictedIds } = evictSnapshotsToCap(ledger.entries, maxBytes);\n const local: WorkspaceLocal = {\n ...state.local,\n snapshots: { entries, maxBytes },\n };\n return { next: { ...state, local }, changedIds: evictedIds };\n}\n\nfunction applyHistoryPurge(state: WorkspaceState, olderThanMs: number): ApplyMutationResult {\n // `olderThanMs` is the cutoff age in milliseconds. Runs whose `startedAt`\n // is older than `now - olderThanMs` get dropped. Pass 0 to clear\n // everything; pass Number.POSITIVE_INFINITY to be a no-op.\n const cutoff = Date.now() - olderThanMs;\n const dropped: string[] = [];\n const requestRuns = state.local.history.requestRuns.filter((r) => {\n const t = Date.parse(r.startedAt);\n if (Number.isFinite(t) && t < cutoff) {\n dropped.push(r.id);\n return false;\n }\n return true;\n });\n const planRuns = state.local.history.planRuns.filter((r) => {\n const t = Date.parse(r.startedAt);\n if (Number.isFinite(t) && t < cutoff) {\n dropped.push(r.id);\n return false;\n }\n return true;\n });\n if (dropped.length === 0) {\n return { next: state, changedIds: [] };\n }\n const local: WorkspaceLocal = {\n ...state.local,\n history: { ...state.local.history, requestRuns, planRuns },\n };\n return { next: { ...state, local }, changedIds: dropped };\n}\n","// Pure workspace-graft logic for the `apicircle.folder/v1` envelope —\n// the bridge between `parseApicircleFolderExport` (which produces a\n// `ParsedApicircleFolderExport` with fresh ids + warnings) and the\n// destination `WorkspaceSynced` it lands in.\n//\n// Three things it does that the parser can't:\n//\n// 1. Uniquify the imported root folder name against the destination\n// parent (mirrors how `importPostmanCollection` wraps the imported\n// tree).\n// 2. Merge dependencies into `globalAssets`. Schemas + GraphQL\n// definitions reuse an existing entry when the name + content match\n// verbatim, so re-importing the same file does not pile up\n// duplicates; otherwise they're added with the parser-minted id.\n// 3. Rewrite cross-entity references (request.bodySchemaId,\n// request.graphqlSchemaId, body.attachment.globalFileAssetId,\n// form-row globalFileAssetId) onto the post-merge ids so the\n// workspace stays internally consistent.\n//\n// Pure — does not depend on IndexedDB, the React store, or any UI\n// helper. The MCP tool, CLI subcommand, and Zustand store all funnel\n// through this same function.\n\nimport type {\n Folder,\n GlobalFileAsset,\n GlobalGraphQL,\n GlobalSchema,\n Request as ApiRequest,\n WorkspaceSynced,\n} from '@apicircle/shared';\nimport type { ParsedApicircleFolderExport } from '../import/apicircleFolder';\n\nexport interface ImportApicircleFolderResult {\n synced: WorkspaceSynced;\n /** Id of the newly-created root folder in the destination workspace. */\n rootFolderId: string;\n /** Final display name (uniquified) of the imported root folder. */\n rootFolderName: string;\n counts: {\n folders: number; // includes the root\n requests: number;\n schemasAdded: number;\n schemasReused: number;\n graphqlAdded: number;\n graphqlReused: number;\n filesAdded: number;\n filesReused: number;\n };\n /**\n * File-asset ids whose metadata landed in `globalAssets.files`\n * without a backing slot (because the export envelope carries\n * metadata only — bytes stay in their Git LFS sidecar). UIs use this\n * to surface a \"re-attach these files\" cue after import.\n */\n filesRequiringReattachment: string[];\n}\n\n/**\n * Graft a parsed API Circle folder export into `synced` under\n * `parentFolderId` (root when `null`). Returns the patched workspace +\n * counts the UI / CLI / MCP can surface.\n */\nexport function importApicircleFolderInto(\n synced: WorkspaceSynced,\n parsed: ParsedApicircleFolderExport,\n parentFolderId: string | null,\n): ImportApicircleFolderResult {\n let cur = synced;\n\n // 1) Merge dependencies — build remap maps from parser-minted id to\n // final destination id. When a content match is found we reuse the\n // existing asset; otherwise we add a fresh entry with the parser's\n // id (which is already collision-free thanks to generateId()).\n const schemaRemap = new Map<string, string>();\n const graphqlRemap = new Map<string, string>();\n const fileRemap = new Map<string, string>();\n let schemasAdded = 0;\n let schemasReused = 0;\n let graphqlAdded = 0;\n let graphqlReused = 0;\n let filesAdded = 0;\n let filesReused = 0;\n const filesRequiringReattachment: string[] = [];\n\n const now = new Date().toISOString();\n\n for (const incoming of parsed.dependencies.schemas) {\n const existing = findMatchingSchema(cur, incoming);\n if (existing) {\n schemaRemap.set(incoming.id, existing.id);\n schemasReused += 1;\n continue;\n }\n cur = mergeGlobalSchema(cur, incoming, now);\n schemaRemap.set(incoming.id, incoming.id);\n schemasAdded += 1;\n }\n for (const incoming of parsed.dependencies.graphql) {\n const existing = findMatchingGraphQL(cur, incoming);\n if (existing) {\n graphqlRemap.set(incoming.id, existing.id);\n graphqlReused += 1;\n continue;\n }\n cur = mergeGlobalGraphQL(cur, incoming, now);\n graphqlRemap.set(incoming.id, incoming.id);\n graphqlAdded += 1;\n }\n for (const incoming of parsed.dependencies.files) {\n const existing = findMatchingFile(cur, incoming);\n if (existing) {\n fileRemap.set(incoming.id, existing.id);\n filesReused += 1;\n continue;\n }\n cur = mergeGlobalFile(cur, incoming, now);\n fileRemap.set(incoming.id, incoming.id);\n filesAdded += 1;\n filesRequiringReattachment.push(incoming.id);\n }\n\n // 2) Insert the root folder (with a uniquified name + the import's auth).\n const rootName = uniquifyFolderName(cur, parentFolderId, parsed.rootFolder.name);\n const root: Folder = {\n id: parsed.rootFolder.id,\n name: rootName,\n parentId: parentFolderId,\n auth: parsed.rootFolder.auth ? { ...parsed.rootFolder.auth } : undefined,\n };\n cur = insertFolder(cur, root, /* attachToTree */ parentFolderId === null);\n\n // 3) Insert subfolders. The parser pinned every parentId on a\n // destination id from the same export, so a single pass suffices.\n for (const f of parsed.subfolders) {\n cur = insertFolder(cur, f, /* attachToTree */ false);\n }\n\n // 4) Insert requests with dependency references rewritten through the\n // merge maps. Schema/GraphQL/file refs were already parser-mapped to\n // the \"incoming.id\"; this pass swaps in the reused-id where a\n // duplicate was detected.\n for (const r of parsed.requests) {\n const rewritten: ApiRequest = {\n ...r,\n bodySchemaId: rewriteRef(r.bodySchemaId, schemaRemap),\n graphqlSchemaId: rewriteRef(r.graphqlSchemaId, graphqlRemap),\n body: rewriteBodyFileRefs(r.body, fileRemap),\n };\n cur = insertRequest(cur, rewritten);\n }\n\n return {\n synced: { ...cur, meta: { ...cur.meta, updatedAt: now } },\n rootFolderId: root.id,\n rootFolderName: rootName,\n counts: {\n folders: parsed.subfolders.length + 1,\n requests: parsed.requests.length,\n schemasAdded,\n schemasReused,\n graphqlAdded,\n graphqlReused,\n filesAdded,\n filesReused,\n },\n filesRequiringReattachment,\n };\n}\n\n// -- internals --------------------------------------------------------------\n\n/**\n * Returns true when `name` is unused for that kind within `parentFolderId`\n * (case-insensitive, whitespace-trimmed). Matches the same check\n * `editorActions.isNameAvailableInFolder` performs — kept inline so this\n * module has no UI dependency.\n */\nfunction isFolderNameAvailable(\n synced: WorkspaceSynced,\n parentFolderId: string | null,\n name: string,\n): boolean {\n const trimmed = name.trim().toLowerCase();\n if (!trimmed) return false;\n for (const node of Object.values(synced.collections.folders)) {\n if (node.parentId !== parentFolderId) continue;\n if (node.name.trim().toLowerCase() === trimmed) return false;\n }\n return true;\n}\n\nfunction uniquifyFolderName(\n synced: WorkspaceSynced,\n parentFolderId: string | null,\n desired: string,\n): string {\n if (isFolderNameAvailable(synced, parentFolderId, desired)) return desired;\n let n = 2;\n while (!isFolderNameAvailable(synced, parentFolderId, `${desired} (${n})`)) {\n n += 1;\n if (n > 999) return `${desired} (${n})`;\n }\n return `${desired} (${n})`;\n}\n\nfunction insertFolder(\n synced: WorkspaceSynced,\n folder: Folder,\n attachToTree: boolean,\n): WorkspaceSynced {\n const folders = { ...synced.collections.folders, [folder.id]: folder };\n const tree = attachToTree\n ? {\n ...synced.collections.tree,\n children: [...synced.collections.tree.children, { kind: 'folder' as const, id: folder.id }],\n }\n : synced.collections.tree;\n return {\n ...synced,\n collections: { ...synced.collections, folders, tree },\n };\n}\n\nfunction insertRequest(synced: WorkspaceSynced, request: ApiRequest): WorkspaceSynced {\n return {\n ...synced,\n collections: {\n ...synced.collections,\n requests: { ...synced.collections.requests, [request.id]: request },\n },\n };\n}\n\nfunction withGlobalAssets(synced: WorkspaceSynced): WorkspaceSynced['globalAssets'] {\n return synced.globalAssets ?? { schemas: {}, graphql: {}, files: {} };\n}\n\nfunction findMatchingSchema(synced: WorkspaceSynced, candidate: GlobalSchema): GlobalSchema | null {\n const ga = withGlobalAssets(synced);\n for (const existing of Object.values(ga.schemas)) {\n if (existing.name === candidate.name && existing.schema === candidate.schema) {\n return existing;\n }\n }\n return null;\n}\n\nfunction findMatchingGraphQL(\n synced: WorkspaceSynced,\n candidate: GlobalGraphQL,\n): GlobalGraphQL | null {\n const ga = withGlobalAssets(synced);\n for (const existing of Object.values(ga.graphql)) {\n if (\n existing.name === candidate.name &&\n existing.kind === candidate.kind &&\n existing.source === candidate.source\n ) {\n return existing;\n }\n }\n return null;\n}\n\nfunction findMatchingFile(\n synced: WorkspaceSynced,\n candidate: GlobalFileAsset,\n): GlobalFileAsset | null {\n const ga = withGlobalAssets(synced);\n const files = ga.files ?? {};\n for (const existing of Object.values(files)) {\n if (\n existing.name === candidate.name &&\n existing.filename === candidate.filename &&\n existing.size === candidate.size\n ) {\n return existing;\n }\n }\n return null;\n}\n\nfunction mergeGlobalSchema(\n synced: WorkspaceSynced,\n schema: GlobalSchema,\n now: string,\n): WorkspaceSynced {\n const ga = withGlobalAssets(synced);\n return {\n ...synced,\n globalAssets: {\n ...ga,\n schemas: { ...ga.schemas, [schema.id]: { ...schema, updatedAt: now } },\n },\n };\n}\n\nfunction mergeGlobalGraphQL(\n synced: WorkspaceSynced,\n graphql: GlobalGraphQL,\n now: string,\n): WorkspaceSynced {\n const ga = withGlobalAssets(synced);\n return {\n ...synced,\n globalAssets: {\n ...ga,\n graphql: { ...ga.graphql, [graphql.id]: { ...graphql, updatedAt: now } },\n },\n };\n}\n\nfunction mergeGlobalFile(\n synced: WorkspaceSynced,\n file: GlobalFileAsset,\n now: string,\n): WorkspaceSynced {\n const ga = withGlobalAssets(synced);\n const files = ga.files ?? {};\n return {\n ...synced,\n globalAssets: {\n ...ga,\n files: { ...files, [file.id]: { ...file, updatedAt: now } },\n },\n };\n}\n\nfunction rewriteRef(\n value: string | null | undefined,\n remap: Map<string, string>,\n): string | null | undefined {\n if (value === null || value === undefined) return value;\n return remap.get(value) ?? value;\n}\n\nfunction rewriteBodyFileRefs(\n body: ApiRequest['body'],\n remap: Map<string, string>,\n): ApiRequest['body'] {\n if (body.type === 'binary') {\n if (!body.attachment) return body;\n const rewritten = rewriteRef(body.attachment.globalFileAssetId, remap);\n if (rewritten === body.attachment.globalFileAssetId) return body;\n return {\n ...body,\n attachment: { ...body.attachment, globalFileAssetId: rewritten },\n };\n }\n if (body.type === 'form-data' && body.formRows) {\n let mutated = false;\n const next = body.formRows.map((row) => {\n if (row.kind !== 'file') return row;\n const rewritten = rewriteRef(row.globalFileAssetId, remap);\n if (rewritten === row.globalFileAssetId) return row;\n mutated = true;\n return { ...row, globalFileAssetId: rewritten };\n });\n return mutated ? { ...body, formRows: next } : body;\n }\n return body;\n}\n","import type {\n Environment,\n EnvPriorityRef,\n ExecutionPlan,\n PlanRun,\n Request as ApiRequest,\n RequestAuth,\n RequestOverridePatch,\n RequestRun,\n WorkspaceLocal,\n WorkspaceSynced,\n} from '@apicircle/shared';\nimport { envPriorityKey, generateId, RUN_BODY_PREVIEW_LIMIT } from '@apicircle/shared';\nimport { executeRequest, type ExecutionResult } from '../request/executeRequest';\nimport type { AttachmentResolver } from '../request/buildRequest';\nimport { runAssertions, type AssertionResult } from '../assertions/runAssertions';\nimport { extractContext } from '../environment/extractContext';\nimport { resolveInheritedAuth } from '../request/resolveInheritedAuth';\nimport { buildScope, resolveString } from '../environment/variableResolver';\nimport type { WorkspaceState } from './patches';\n\n// =============================================================================\n// runPlan — the headless execution-plan runner.\n//\n// The browser/desktop store has its own `runPlan` (workspaceStore.ts) wired to\n// IndexedDB secret crypto, AbortControllers, and live UI state. This one is the\n// runtime-agnostic engine: it takes a plain `WorkspaceState`, executes a plan's\n// steps with `executeRequest`, and returns the `PlanRun` plus the workspace\n// with history + refreshed tokens folded in. The CLI (`apicircle run`) drives\n// it; a hosted runtime or the MCP host could too.\n//\n// Secrets: encrypted env-var ciphertext is never decrypted here. Callers supply\n// plaintext keyed by `secretKeyId` (the CLI sources these from\n// `APICIRCLE_SECRET_<id>` / `--secrets`). An encrypted var with no supplied\n// value is omitted from scope, so `{{VAR}}` surfaces as an unresolved\n// placeholder rather than leaking ciphertext onto the wire.\n// =============================================================================\n\n// History buffer caps — mirror the store's circular-buffer behaviour so a CLI\n// that runs plans repeatedly doesn't grow workspace.local.json unbounded.\nconst MAX_REQUEST_RUNS = 500;\nconst MAX_PLAN_RUNS = 200;\n\n/**\n * Best-known identity of whoever launched a plan run. Recorded for display\n * and handed to the `authorize` hook. `unknown` is the headless default when\n * no GitHub session or OS user can be determined.\n */\nexport interface RunActor {\n kind: 'github' | 'os' | 'unknown';\n /** GitHub login, OS username, or 'unknown'. */\n name: string;\n}\n\nexport const ANONYMOUS_ACTOR: RunActor = { kind: 'unknown', name: 'unknown' };\n\n/**\n * Thrown by an `authorize` hook to deny a run. `runPlan` lets it propagate\n * untouched so callers (the CLI) can map it to a distinct exit code. Today no\n * built-in hook throws it — it exists for the per-user run restrictions that\n * are planned but not yet designed.\n */\nexport class PlanRunDeniedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PlanRunDeniedError';\n }\n}\n\n/** Context handed to the `authorize` hook before any HTTP request fires. */\nexport interface PlanRunAuthorizationContext {\n planId: string;\n plan: ExecutionPlan;\n actor: RunActor;\n state: WorkspaceState;\n}\n\nexport interface RunPlanOptions {\n /** Evaluate the per-request assertions. Defaults to `true`. */\n withAssertions?: boolean;\n /**\n * Halt the run after the first failed step — including missing / linked\n * steps — regardless of the plan's own `stopOnAssertionFailure`. This is\n * the `apicircle run --bail` behaviour. Defaults to `false`.\n */\n bail?: boolean;\n /**\n * Name of a local environment to layer on top of the run's env priority\n * order (highest precedence). Used by `apicircle run --env <name>`. A name\n * with no matching environment simply contributes nothing.\n */\n env?: string;\n /** Injected fetch — defaults to `globalThis.fetch`. Tests pass a stub. */\n fetchImpl?: typeof fetch;\n /** Aborts the run between steps and the in-flight request. */\n signal?: AbortSignal;\n /** Per-request hard timeout in ms. `null` disables. Defaults to executeRequest's 30s. */\n timeoutMs?: number | null;\n /** Resolver for local and linked attachment bytes used by file/binary bodies. */\n resolveAttachment?: AttachmentResolver;\n /** Plaintext secret values keyed by `secretKeyId`, for encrypted env vars. */\n secretsById?: Record<string, string>;\n /** Identity of whoever launched the run. Defaults to {@link ANONYMOUS_ACTOR}. */\n actor?: RunActor;\n /**\n * Authorization seam. Called once, before the first request, with the\n * resolved plan + actor. Throw (ideally {@link PlanRunDeniedError}) to deny\n * the run. Omit for an unrestricted run — the current default everywhere.\n */\n authorize?: (ctx: PlanRunAuthorizationContext) => void | Promise<void>;\n /** Invoked after each step settles — lets a CLI stream progress live. */\n onStep?: (step: PlanStepResult) => void;\n}\n\nexport interface PlanStepResult {\n /** Index into `plan.steps` — stable even when steps are skipped. */\n stepIndex: number;\n requestId: string;\n requestName: string;\n requestMethod: string;\n /** True when the step was skipped via `enabled: false`. */\n skipped: boolean;\n /** Execution result, or `null` for a skipped / unresolvable step. */\n result: ExecutionResult | null;\n assertionResults: AssertionResult[];\n /** `{{VAR}}` placeholders that didn't resolve in url / headers / query / body / auth. */\n missingVariables: string[];\n /** True when the request succeeded and (if enabled) every assertion passed. */\n passed: boolean;\n /** Set when the step couldn't run at all (missing / linked / unsupported). */\n error?: string;\n}\n\nexport interface RunPlanResult {\n planRun: PlanRun;\n /** One entry per step, including skipped ones (in `plan.steps` order). */\n steps: PlanStepResult[];\n /**\n * Workspace with the plan-run + request-runs appended to history and any\n * refreshed OAuth2 tokens persisted onto `synced`. Save this back to disk.\n */\n nextState: WorkspaceState;\n /** True when every executed (non-skipped) step passed. Vacuously true when none ran. */\n passed: boolean;\n}\n\nexport type ResolvePlanRefResult =\n | { ok: true; id: string; plan: ExecutionPlan }\n | { ok: false; error: string; available: string[] };\n\n/**\n * Resolve a user-supplied plan reference (a plan id, or a plan name) against a\n * workspace. Name matching is case-insensitive and trimmed; an ambiguous name\n * (two plans share it) is rejected so the caller can ask for an id instead.\n */\nexport function resolvePlanRef(synced: WorkspaceSynced, ref: string): ResolvePlanRefResult {\n const plans = synced.executionPlans ?? {};\n const entries = Object.entries(plans);\n const available = entries.map(([, p]) => p.name);\n if (entries.length === 0) {\n return { ok: false, error: 'This workspace has no execution plans.', available };\n }\n const direct = plans[ref];\n if (direct) return { ok: true, id: ref, plan: direct };\n\n const wanted = ref.trim().toLowerCase();\n const byName = entries.filter(([, p]) => p.name.trim().toLowerCase() === wanted);\n if (byName.length === 1) return { ok: true, id: byName[0][0], plan: byName[0][1] };\n if (byName.length > 1) {\n return {\n ok: false,\n error: `Plan name \"${ref}\" is ambiguous — ${byName.length} plans share it. Pass the plan id instead.`,\n available,\n };\n }\n return { ok: false, error: `No plan named \"${ref}\" in this workspace.`, available };\n}\n\nfunction lookupPlanStepRequest(\n step: { requestId: string; linkedWorkspaceId?: string },\n synced: WorkspaceSynced,\n local: WorkspaceLocal,\n): {\n request: ApiRequest | null;\n linkedEnvironments?: WorkspaceSynced['environments'];\n linkedFolders?: WorkspaceSynced['collections']['folders'];\n linkedGlobalAssets?: WorkspaceSynced['globalAssets'];\n error?: string;\n} {\n if (!step.linkedWorkspaceId) {\n const request = synced.collections.requests[step.requestId];\n return request\n ? { request }\n : { request: null, error: 'Request no longer exists in workspace.' };\n }\n\n const link = synced.linkedWorkspaces[step.linkedWorkspaceId];\n if (!link) return { request: null, error: 'Linked workspace was unlinked.' };\n\n const snapshot = local.linkedCollections[step.linkedWorkspaceId];\n if (!snapshot) {\n return {\n request: null,\n error: `No cached snapshot for \"${link.name}\". Refresh the link before running this plan.`,\n };\n }\n\n const baseRequest = snapshot.collections.requests[step.requestId];\n if (!baseRequest) {\n return {\n request: null,\n error: `Request not present in the cached snapshot of \"${link.name}\".`,\n };\n }\n\n const overrideKey = `${step.linkedWorkspaceId}:${step.requestId}`;\n const override = synced.linkedOverrides.requests[overrideKey];\n const request = override ? mergeRequestOverride(baseRequest, override.patch) : baseRequest;\n return {\n request,\n linkedEnvironments: applyEnvironmentOverrides(\n snapshot.environments,\n step.linkedWorkspaceId,\n synced,\n ),\n linkedFolders: snapshot.collections.folders,\n linkedGlobalAssets: snapshot.globalAssets,\n };\n}\n\nfunction mergeRequestOverride(base: ApiRequest, patch: RequestOverridePatch): ApiRequest {\n const merged: ApiRequest = { ...base };\n if (patch.name !== undefined) merged.name = patch.name;\n if (patch.method !== undefined) merged.method = patch.method;\n if (patch.url !== undefined) merged.url = patch.url;\n if (patch.headers !== undefined) merged.headers = patch.headers;\n if (patch.query !== undefined) merged.query = patch.query;\n if (patch.pathParams !== undefined) merged.pathParams = patch.pathParams;\n if (patch.cookies !== undefined) merged.cookies = patch.cookies;\n if (patch.body !== undefined) merged.body = patch.body;\n if (patch.auth !== undefined) merged.auth = patch.auth;\n if (patch.contextVars !== undefined) merged.contextVars = patch.contextVars;\n if (patch.extractions !== undefined) merged.extractions = patch.extractions;\n if (patch.assertions !== undefined) merged.assertions = patch.assertions;\n return merged;\n}\n\nfunction applyEnvironmentOverrides(\n source: WorkspaceSynced['environments'],\n linkedWorkspaceId: string,\n synced: WorkspaceSynced,\n): WorkspaceSynced['environments'] {\n const overrides = Object.values(synced.linkedOverrides.environmentVars).filter(\n (override) => override.linkedWorkspaceId === linkedWorkspaceId,\n );\n if (overrides.length === 0) return source;\n\n const items: WorkspaceSynced['environments']['items'] = {};\n for (const [envName, env] of Object.entries(source.items)) {\n const envOverrides = overrides.filter((override) => override.envName === envName);\n if (envOverrides.length === 0) {\n items[envName] = env;\n continue;\n }\n\n const removed = new Set(\n envOverrides.filter((override) => override.removed).map((override) => override.varKey),\n );\n const replaceMap = new Map<string, (typeof envOverrides)[number]>();\n for (const override of envOverrides) {\n if (!override.removed) replaceMap.set(override.varKey, override);\n }\n const variables: Environment['variables'] = [];\n const seenKeys = new Set<string>();\n for (const variable of env.variables) {\n if (removed.has(variable.key)) continue;\n const override = replaceMap.get(variable.key);\n if (override) {\n variables.push({\n key: variable.key,\n value: override.value ?? variable.value,\n encrypted: override.encrypted ?? variable.encrypted,\n ...(override.secretKeyId !== undefined\n ? { secretKeyId: override.secretKeyId }\n : variable.secretKeyId !== undefined\n ? { secretKeyId: variable.secretKeyId }\n : {}),\n });\n } else {\n variables.push(variable);\n }\n seenKeys.add(variable.key);\n }\n\n for (const override of envOverrides) {\n if (override.removed || seenKeys.has(override.varKey)) continue;\n variables.push({\n key: override.varKey,\n value: override.value ?? '',\n encrypted: override.encrypted ?? false,\n ...(override.secretKeyId !== undefined ? { secretKeyId: override.secretKeyId } : {}),\n });\n }\n items[envName] = { ...env, variables };\n }\n return { ...source, items };\n}\n\n/**\n * Execute every enabled step of `planId` against the workspace. Never throws\n * for HTTP / assertion failures — those land in the returned step results.\n * Throws only for a missing plan or a denial from the `authorize` hook.\n */\nexport async function runPlan(\n state: WorkspaceState,\n planId: string,\n opts: RunPlanOptions = {},\n): Promise<RunPlanResult> {\n const plan = state.synced.executionPlans?.[planId];\n if (!plan) throw new Error(`Plan \"${planId}\" not found in workspace`);\n\n const actor = opts.actor ?? ANONYMOUS_ACTOR;\n if (opts.authorize) {\n await opts.authorize({ planId, plan, actor, state });\n }\n\n const withAssertions = opts.withAssertions ?? true;\n const bail = opts.bail ?? false;\n // The plan's own stop flag only halts on a *failed assertion*; --bail halts\n // on any failed step. Both feed the post-step break below.\n const stopOnAssertion = withAssertions && (plan.stopOnAssertionFailure ?? false);\n const secretsById = opts.secretsById ?? {};\n const flatEnvs = buildEnvMaps(state.synced, secretsById, state.local);\n const secretsByLabel = buildSecretsByLabel(state.synced, secretsById);\n\n // Env priority for this run: the plan's overlay (or the workspace order),\n // with an optional `--env` environment layered on top at highest precedence.\n const baseRefs =\n plan.envPriorityOrder.length > 0\n ? plan.envPriorityOrder\n : state.synced.environments.priorityOrder;\n const envRefs: readonly EnvPriorityRef[] = opts.env\n ? [{ kind: 'local', name: opts.env }, ...baseRefs]\n : baseRefs;\n\n const startedAt = new Date().toISOString();\n const planRunId = generateId();\n const t0 = Date.now();\n\n const stepRecords: PlanRun['steps'] = [];\n const newRequestRuns: RequestRun[] = [];\n const stepResults: PlanStepResult[] = [];\n\n // Rolling state across steps: extracted context vars feed the next step's\n // resolver; refreshed OAuth2 tokens replace the request's stored auth.\n let globalContext = { ...state.local.globalContext };\n let requests = state.synced.collections.requests;\n const tokenRefreshes = new Map<string, RequestAuth>();\n\n const record = (step: PlanStepResult): void => {\n stepResults.push(step);\n opts.onStep?.(step);\n };\n\n for (let i = 0; i < plan.steps.length; i++) {\n const step = plan.steps[i];\n\n // Disabled steps stay in the plan but contribute nothing to the run —\n // no request-run, no PlanRun.steps entry. Matches the store's runPlan.\n if (step.enabled === false) {\n const req = requests[step.requestId];\n record({\n stepIndex: i,\n requestId: step.requestId,\n requestName: req?.name ?? '(unknown request)',\n requestMethod: req?.method ?? '—',\n skipped: true,\n result: null,\n assertionResults: [],\n missingVariables: [],\n passed: true,\n });\n continue;\n }\n\n if (opts.signal?.aborted) break;\n\n const lookup = lookupPlanStepRequest(step, state.synced, state.local);\n const baseRequest = lookup.request;\n if (!baseRequest) {\n const runId = generateId();\n const error = lookup.error ?? 'Request no longer exists in workspace.';\n newRequestRuns.push(orphanRun(runId, step.requestId, error));\n stepRecords.push({ requestRunId: runId, passed: false });\n record({\n stepIndex: i,\n requestId: step.requestId,\n requestName: step.linkedWorkspaceId ? '(linked request)' : '(missing request)',\n requestMethod: '—',\n skipped: false,\n result: null,\n assertionResults: [],\n missingVariables: [],\n passed: false,\n error,\n });\n if (bail) break;\n continue;\n }\n\n const resolveSynced: WorkspaceSynced =\n step.linkedWorkspaceId && lookup.linkedEnvironments\n ? {\n ...state.synced,\n environments: lookup.linkedEnvironments,\n globalAssets: lookup.linkedGlobalAssets ?? state.synced.globalAssets,\n collections: {\n ...state.synced.collections,\n folders: lookup.linkedFolders ?? {},\n },\n }\n : state.synced;\n const stepEnvRefs =\n step.linkedWorkspaceId && plan.envPriorityOrder.length === 0\n ? (lookup.linkedEnvironments?.priorityOrder ?? envRefs)\n : envRefs;\n\n const { request: resolved, missing } = resolveRequest(\n baseRequest,\n resolveSynced,\n plan,\n stepEnvRefs,\n globalContext,\n step.linkedWorkspaceId ? buildEnvMaps(resolveSynced, secretsById, state.local) : flatEnvs,\n secretsByLabel,\n );\n\n const result = await executeRequest(resolved, {\n fetchImpl: opts.fetchImpl,\n signal: opts.signal,\n timeoutMs: opts.timeoutMs,\n resolveAttachment: opts.resolveAttachment,\n authOptions: {\n onTokenRefreshed: (refreshedAuth) => {\n if (!step.linkedWorkspaceId) tokenRefreshes.set(baseRequest.id, refreshedAuth);\n },\n },\n });\n\n const assertionResults = withAssertions ? runAssertions(baseRequest.assertions, result) : [];\n const passed = result.ok && (!withAssertions || assertionResults.every((a) => a.passed));\n const requestRun = buildRequestRun(resolved, result, assertionResults);\n newRequestRuns.push(requestRun);\n stepRecords.push({ requestRunId: requestRun.id, passed });\n record({\n stepIndex: i,\n requestId: baseRequest.id,\n requestName: baseRequest.name,\n requestMethod: baseRequest.method,\n skipped: false,\n result,\n assertionResults,\n missingVariables: missing,\n passed,\n });\n\n // Carry extracted context vars into the rolling scope for the next step.\n if (baseRequest.extractions.length > 0) {\n const { extracted } = extractContext(result, baseRequest.extractions);\n globalContext = { ...globalContext, ...extracted };\n }\n\n // Fold a refreshed token back into `requests` so a later step reusing the\n // same request sees the fresh access token instead of re-refreshing.\n const refreshed = step.linkedWorkspaceId ? undefined : tokenRefreshes.get(baseRequest.id);\n if (refreshed) {\n requests = {\n ...requests,\n [baseRequest.id]: { ...requests[baseRequest.id], auth: refreshed },\n };\n }\n\n if ((bail || stopOnAssertion) && !passed) break;\n }\n\n const planRun: PlanRun = {\n id: planRunId,\n planId,\n startedAt,\n durationMs: Date.now() - t0,\n withAssertions,\n steps: stepRecords,\n };\n\n // Newest-first history, same convention the store uses. Request-runs are\n // reversed so the last step to run sits at index 0.\n const requestRuns = [...newRequestRuns]\n .reverse()\n .concat(state.local.history.requestRuns)\n .slice(0, MAX_REQUEST_RUNS);\n const planRuns = [planRun, ...state.local.history.planRuns].slice(0, MAX_PLAN_RUNS);\n\n const nextState: WorkspaceState = {\n synced:\n tokenRefreshes.size > 0\n ? {\n ...state.synced,\n collections: { ...state.synced.collections, requests },\n meta: { ...state.synced.meta, updatedAt: new Date().toISOString() },\n }\n : state.synced,\n local: {\n ...state.local,\n globalContext,\n history: { ...state.local.history, requestRuns, planRuns },\n },\n };\n\n const executed = stepResults.filter((s) => !s.skipped);\n const passed = executed.every((s) => s.passed);\n\n return { planRun, steps: stepResults, nextState, passed };\n}\n\n// ---------------------------------------------------------------------------\n// variable resolution (headless — no IndexedDB / WebCrypto)\n// ---------------------------------------------------------------------------\n\n/**\n * Flatten the workspace's local environments into the `envPriorityKey`-keyed\n * map `buildScope` expects. Encrypted vars are substituted with the supplied\n * plaintext; an encrypted var with no supplied secret is omitted so the\n * `{{VAR}}` reference surfaces as unresolved instead of leaking ciphertext.\n */\nfunction buildEnvMaps(\n synced: WorkspaceSynced,\n secretsById: Record<string, string>,\n local?: WorkspaceLocal,\n): Record<string, Record<string, string>> {\n const flat: Record<string, Record<string, string>> = {};\n for (const [name, env] of Object.entries(synced.environments.items)) {\n const vars: Record<string, string> = {};\n for (const v of env.variables) {\n if (!v.key) continue;\n if (v.encrypted) {\n const supplied = v.secretKeyId ? secretsById[v.secretKeyId] : undefined;\n if (supplied === undefined) continue;\n vars[v.key] = supplied;\n } else {\n vars[v.key] = v.value;\n }\n }\n flat[envPriorityKey({ kind: 'local', name })] = vars;\n }\n if (local) {\n for (const [linkId, snapshot] of Object.entries(local.linkedCollections)) {\n const overridden = applyEnvironmentOverrides(snapshot.environments, linkId, synced);\n for (const [envName, env] of Object.entries(overridden.items)) {\n const vars: Record<string, string> = {};\n for (const variable of env.variables) {\n if (!variable.key) continue;\n if (variable.encrypted) {\n const supplied = variable.secretKeyId ? secretsById[variable.secretKeyId] : undefined;\n if (supplied === undefined) continue;\n vars[variable.key] = supplied;\n } else {\n vars[variable.key] = variable.value;\n }\n }\n flat[envPriorityKey({ kind: 'linked', linkedWorkspaceId: linkId, envName })] = vars;\n }\n }\n }\n return flat;\n}\n\n/** Project supplied secrets onto their human labels for direct `{{Label}}` refs. */\nfunction buildSecretsByLabel(\n synced: WorkspaceSynced,\n secretsById: Record<string, string>,\n): Record<string, string> {\n const meta = synced.secretKeys ?? {};\n const byLabel: Record<string, string> = {};\n for (const [id, value] of Object.entries(secretsById)) {\n const label = meta[id]?.label;\n if (label) byLabel[label] = value;\n }\n return byLabel;\n}\n\n/**\n * Interpolate `{{var}}` placeholders across a request's url, headers, query,\n * body, and auth fields. Resolver precedence (highest first): per-request\n * contextVars → plan variables → rolling globalContext → env priority list →\n * secret labels. Path params and cookies are left verbatim — same as the\n * store's `resolveRequest`.\n */\nfunction resolveRequest(\n request: ApiRequest,\n synced: WorkspaceSynced,\n plan: ExecutionPlan,\n envRefs: readonly EnvPriorityRef[],\n globalContext: Record<string, string>,\n flatEnvs: Record<string, Record<string, string>>,\n secretsByLabel: Record<string, string>,\n): { request: ApiRequest; missing: string[] } {\n // contextVars layering (low → high): globalContext, plan vars, request vars.\n const ctxMap: Record<string, string> = { ...globalContext };\n for (const v of plan.variables ?? []) {\n if (v.key) ctxMap[v.key] = v.value;\n }\n for (const v of request.contextVars) {\n if (v.key) ctxMap[v.key] = v.value;\n }\n\n const scope = buildScope({\n contextVars: Object.entries(ctxMap).map(([key, value]) => ({ key, value })),\n environments: flatEnvs,\n activeEnvName: null,\n priorityOrder: envRefs.map(envPriorityKey),\n secrets: secretsByLabel,\n });\n\n const missing = new Set<string>();\n const sub = (input: string): string => {\n const { value, missing: m } = resolveString(input, scope);\n for (const name of m) missing.add(name);\n return value;\n };\n\n const url = sub(request.url);\n const headers = request.headers.map((h) => ({\n ...h,\n key: sub(h.key),\n value: sub(h.value),\n }));\n const query = request.query.map((q) => ({\n ...q,\n key: sub(q.key),\n value: sub(q.value),\n }));\n\n let body = request.body;\n if (\n body.type === 'json' ||\n body.type === 'text' ||\n body.type === 'xml' ||\n body.type === 'graphql' ||\n body.type === 'urlencoded'\n ) {\n body = { ...body, content: sub(body.content) };\n } else if (body.type === 'form-data' && body.formRows) {\n body = {\n ...body,\n formRows: body.formRows.map((row) =>\n row.kind === 'text'\n ? { ...row, key: sub(row.key), value: sub(row.value) }\n : { ...row, key: sub(row.key) },\n ),\n };\n }\n\n const inheritedAuth = resolveInheritedAuth({\n requestAuth: request.auth ?? { type: 'none' },\n folderId: request.folderId,\n folders: synced.collections.folders,\n });\n const auth = resolveAuthVariables(inheritedAuth, sub);\n\n return { request: { ...request, url, headers, query, body, auth }, missing: [...missing] };\n}\n\n/** Interpolate `{{var}}` in every string-valued auth field; `type` is left verbatim. */\nfunction resolveAuthVariables(auth: RequestAuth, sub: (input: string) => string): RequestAuth {\n const resolved: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(auth)) {\n resolved[key] = key !== 'type' && typeof value === 'string' ? sub(value) : value;\n }\n return resolved as unknown as RequestAuth;\n}\n\n// ---------------------------------------------------------------------------\n// RequestRun construction\n// ---------------------------------------------------------------------------\n\nfunction orphanRun(id: string, requestId: string, error: string): RequestRun {\n return {\n id,\n requestId,\n startedAt: new Date().toISOString(),\n durationMs: 0,\n status: null,\n statusText: '',\n ok: false,\n error,\n url: '',\n method: '',\n requestHeaders: {},\n requestBodyPreview: null,\n responseHeaders: {},\n responseBodyPreview: '',\n responseBodyKind: 'empty',\n responseTruncated: false,\n assertions: [],\n };\n}\n\nfunction buildRequestRun(\n resolved: ApiRequest,\n result: ExecutionResult,\n assertions: RequestRun['assertions'],\n): RequestRun {\n const { preview, truncated } = clampPreview(result.body ?? '');\n return {\n id: generateId(),\n requestId: resolved.id,\n startedAt: result.startedAt,\n durationMs: result.durationMs,\n status: result.status,\n statusText: result.statusText,\n ok: result.ok,\n error: result.error,\n url: redactUrlCredentials(result.url),\n method: result.method,\n requestHeaders: composeWireHeaders(resolved.headers),\n requestBodyPreview: previewRequestBody(resolved),\n responseHeaders: result.headers,\n responseBodyPreview: preview,\n responseBodyKind: result.bodyKind,\n responseTruncated: truncated,\n assertions,\n };\n}\n\nfunction clampPreview(value: string): { preview: string; truncated: boolean } {\n if (value.length <= RUN_BODY_PREVIEW_LIMIT) return { preview: value, truncated: false };\n return { preview: value.slice(0, RUN_BODY_PREVIEW_LIMIT), truncated: true };\n}\n\n/** Strip `user:pass@` userinfo before a URL enters persisted history. */\nfunction redactUrlCredentials(url: string): string {\n try {\n const parsed = new URL(url);\n if (parsed.username || parsed.password) {\n parsed.username = '';\n parsed.password = '';\n return parsed.toString();\n }\n } catch {\n /* not a parseable URL — leave it alone */\n }\n return url;\n}\n\nfunction composeWireHeaders(\n rows: ReadonlyArray<{ key: string; value: string; enabled: boolean }>,\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const row of rows) {\n if (!row.enabled) continue;\n const k = row.key.trim();\n if (k) out[k] = row.value;\n }\n return out;\n}\n\nfunction previewRequestBody(req: ApiRequest): string | null {\n const body = req.body;\n if (\n body.type === 'json' ||\n body.type === 'text' ||\n body.type === 'xml' ||\n body.type === 'urlencoded'\n ) {\n return clampPreview(body.content ?? '').preview;\n }\n if (body.type === 'graphql') {\n const envelope = JSON.stringify(\n { query: body.content ?? '', variables: body.variables ?? '' },\n null,\n 2,\n );\n return clampPreview(envelope).preview;\n }\n return null;\n}\n","/**\n * Token Oriented Object Notation (TOON) encoder.\n *\n * Compact, indentation-based serialization that drops most of JSON's\n * structural noise (quotes around keys/values where unambiguous, braces,\n * commas, colons-with-spaces). Optimized for LLM token budgets and\n * eyeballing — typical JSON shrinks 25–50% when re-encoded.\n *\n * Two encoding shapes are produced:\n *\n * - **Tabular** for arrays of homogeneous flat objects (common API list\n * payloads). The header lists keys once, the rows list values once:\n *\n * users[2]{id,name,active}:\n * 1,Alice,true\n * 2,Bob,false\n *\n * - **Indented** for everything else:\n *\n * meta:\n * page: 1\n * items:\n * - id: 1\n * name: Alice\n *\n * Strings are quoted only when they contain characters that would otherwise\n * break the line shape (commas, colons, leading/trailing whitespace, etc.).\n * Output is intentionally lossless for round-tripping primitive types — but\n * a TOON decoder is out of scope for this module: the encoder exists so the\n * UI can show an \"X% smaller\" hint and an optional preview.\n */\n\ntype Json = string | number | boolean | null | Json[] | { [key: string]: Json };\n\nconst INDENT = ' ';\n\nfunction isFlatPrimitive(v: unknown): v is string | number | boolean | null {\n return v === null || ['string', 'number', 'boolean'].includes(typeof v);\n}\n\nfunction isFlatObject(v: unknown): v is Record<string, string | number | boolean | null> {\n if (v === null || typeof v !== 'object' || Array.isArray(v)) return false;\n return Object.values(v).every(isFlatPrimitive);\n}\n\n/**\n * An array is \"tabular\" if it has ≥ 2 entries, all entries are flat\n * objects, and they share the same key set. Single-row arrays fall back\n * to the indented form because the header overhead doesn't pay off.\n */\nfunction tabularKeys(arr: unknown[]): string[] | null {\n if (arr.length < 2) return null;\n if (!arr.every(isFlatObject)) return null;\n const keys = Object.keys(arr[0]);\n if (keys.length === 0) return null;\n for (let i = 1; i < arr.length; i++) {\n const rowKeys = Object.keys(arr[i]);\n if (rowKeys.length !== keys.length) return null;\n for (const k of keys) if (!(k in (arr[i] as object))) return null;\n }\n return keys;\n}\n\nconst SAFE_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;\nconst NEEDS_QUOTING = /[,:\\n\\r\"]|^\\s|\\s$/;\n\nfunction encodeKey(k: string): string {\n return SAFE_KEY.test(k) ? k : JSON.stringify(k);\n}\n\nfunction encodeScalar(v: string | number | boolean | null): string {\n if (v === null) return 'null';\n if (typeof v === 'boolean' || typeof v === 'number') return String(v);\n // Reserved word collisions — quote so re-decode is unambiguous.\n if (v === 'null' || v === 'true' || v === 'false' || v === '') return JSON.stringify(v);\n if (NEEDS_QUOTING.test(v)) return JSON.stringify(v);\n return v;\n}\n\nfunction encodeRowValue(v: string | number | boolean | null): string {\n // Tabular rows are comma-separated; quoting rules are stricter.\n return encodeScalar(v);\n}\n\nfunction encodeNode(value: Json, indent: string): string {\n if (isFlatPrimitive(value)) return encodeScalar(value);\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]';\n const keys = tabularKeys(value);\n if (keys) {\n const header = `[${value.length}]{${keys.map(encodeKey).join(',')}}:`;\n const rows = value.map(\n (row) =>\n indent +\n INDENT +\n keys.map((k) => encodeRowValue((row as Record<string, Json>)[k] as never)).join(','),\n );\n return `${header}\\n${rows.join('\\n')}`;\n }\n return value\n .map((item) => {\n if (isFlatPrimitive(item) || Array.isArray(item)) {\n return `${indent}- ${encodeNode(item, indent + INDENT)}`;\n }\n // Object child: first line goes after `- `, rest stays where the\n // recursive call put it (already at indent + INDENT, aligned under\n // the bullet). The first line carries an extra indent we need to\n // strip so `- ` itself stands in for those two columns.\n const encoded = encodeNode(item, indent + INDENT);\n const innerIndent = indent + INDENT;\n const lines = encoded.split('\\n');\n const [first, ...rest] = lines;\n const firstStripped = first.startsWith(innerIndent)\n ? first.slice(innerIndent.length)\n : first;\n return [`${indent}- ${firstStripped}`, ...rest].join('\\n');\n })\n .join('\\n');\n }\n // Object.\n const entries = Object.entries(value);\n if (entries.length === 0) return '{}';\n return entries\n .map(([k, v]) => {\n if (isFlatPrimitive(v)) return `${indent}${encodeKey(k)}: ${encodeScalar(v)}`;\n if (Array.isArray(v) && v.length === 0) return `${indent}${encodeKey(k)}: []`;\n if (!Array.isArray(v) && typeof v === 'object' && Object.keys(v).length === 0) {\n return `${indent}${encodeKey(k)}: {}`;\n }\n // Tabular array → header sits on the same line; rows below.\n if (Array.isArray(v)) {\n const keys = tabularKeys(v);\n if (keys) {\n const header = `${indent}${encodeKey(k)}[${v.length}]{${keys.map(encodeKey).join(',')}}:`;\n const rows = v.map(\n (row) =>\n indent +\n INDENT +\n keys\n .map((rk) => encodeRowValue((row as Record<string, Json>)[rk] as never))\n .join(','),\n );\n return `${header}\\n${rows.join('\\n')}`;\n }\n }\n const child = encodeNode(v, indent + INDENT);\n return `${indent}${encodeKey(k)}:\\n${child}`;\n })\n .join('\\n');\n}\n\nexport function toToon(value: Json): string {\n if (isFlatPrimitive(value)) return encodeScalar(value);\n if (Array.isArray(value) && value.length === 0) return '[]';\n if (!Array.isArray(value) && typeof value === 'object' && Object.keys(value).length === 0) {\n return '{}';\n }\n return encodeNode(value, '');\n}\n","/**\n * Minimal block-style YAML encoder. Sibling of `toon.ts` — same job\n * (compact, indentation-based representation of JSON-shaped data) but\n * sticks to standard YAML syntax instead of TOON's tabular shorthand,\n * so the user can compare the two.\n *\n * For arrays of homogeneous flat objects YAML still emits one list item\n * per row (unlike TOON's `name[count]{cols}: rows` table), so YAML is\n * usually slightly larger than TOON on tabular payloads but identical or\n * very close on nested ones. Keeping both gives the user the full picture\n * when deciding which format to feed downstream.\n */\n\ntype Json = string | number | boolean | null | Json[] | { [key: string]: Json };\n\nconst INDENT = ' ';\n\nconst SAFE_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;\n// YAML's plain scalar restrictions: leading/trailing whitespace, special\n// indicators (`,`, `[`, `]`, `{`, `}`, `&`, `*`, `!`, `|`, `>`, `'`, `\"`,\n// `#`, `%`, `@`, `\\``, `?`, `:` followed by space, leading `-`/space).\n// We use a permissive screen — anything ambiguous gets JSON-quoted, which\n// is valid YAML.\nconst NEEDS_QUOTING = /[:#,&*!|>'\"`%@\\n\\r\\t]|^[-?\\s]|\\s$|^$/;\n\nfunction isFlatPrimitive(v: unknown): v is string | number | boolean | null {\n return v === null || ['string', 'number', 'boolean'].includes(typeof v);\n}\n\nfunction encodeKey(k: string): string {\n return SAFE_KEY.test(k) ? k : JSON.stringify(k);\n}\n\nfunction encodeScalar(v: string | number | boolean | null): string {\n if (v === null) return 'null';\n if (typeof v === 'boolean' || typeof v === 'number') return String(v);\n // Reserved word collisions — YAML 1.1 treats these as booleans.\n if (/^(null|true|false|yes|no|on|off|~)$/i.test(v)) return JSON.stringify(v);\n if (NEEDS_QUOTING.test(v)) return JSON.stringify(v);\n // Numeric-looking strings need quoting so they don't deserialize as numbers.\n if (/^-?\\d+(\\.\\d+)?([eE][+-]?\\d+)?$/.test(v)) return JSON.stringify(v);\n return v;\n}\n\nfunction encodeNode(value: Json, indent: string): string {\n if (isFlatPrimitive(value)) return encodeScalar(value);\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]';\n return value\n .map((item) => {\n if (isFlatPrimitive(item)) return `${indent}- ${encodeScalar(item)}`;\n if (Array.isArray(item) && item.length === 0) return `${indent}- []`;\n if (\n !Array.isArray(item) &&\n typeof item === 'object' &&\n item !== null &&\n Object.keys(item).length === 0\n ) {\n return `${indent}- {}`;\n }\n const encoded = encodeNode(item, indent + INDENT);\n const innerIndent = indent + INDENT;\n const lines = encoded.split('\\n');\n const [first, ...rest] = lines;\n const firstStripped = first.startsWith(innerIndent)\n ? first.slice(innerIndent.length)\n : first;\n return [`${indent}- ${firstStripped}`, ...rest].join('\\n');\n })\n .join('\\n');\n }\n // Object.\n const entries = Object.entries(value);\n if (entries.length === 0) return '{}';\n return entries\n .map(([k, v]) => {\n if (isFlatPrimitive(v)) return `${indent}${encodeKey(k)}: ${encodeScalar(v)}`;\n if (Array.isArray(v) && v.length === 0) return `${indent}${encodeKey(k)}: []`;\n if (!Array.isArray(v) && typeof v === 'object' && Object.keys(v).length === 0) {\n return `${indent}${encodeKey(k)}: {}`;\n }\n const child = encodeNode(v, indent + INDENT);\n return `${indent}${encodeKey(k)}:\\n${child}`;\n })\n .join('\\n');\n}\n\nexport function toYaml(value: Json): string {\n if (isFlatPrimitive(value)) return encodeScalar(value);\n if (Array.isArray(value) && value.length === 0) return '[]';\n if (!Array.isArray(value) && typeof value === 'object' && Object.keys(value).length === 0) {\n return '{}';\n }\n return encodeNode(value, '');\n}\n","/**\n * Minimal RFC 4180-ish CSV encoder, used purely as a \"what if you sent\n * this as CSV\" savings preview. Returns null when the input isn't an\n * array of homogeneous flat objects — CSV only makes sense for tabular\n * data, and forcing it on nested JSON would either lose information or\n * inflate the payload, defeating the point of the savings hint.\n */\n\ntype Json = string | number | boolean | null | Json[] | { [key: string]: Json };\n\nfunction isFlat(v: unknown): v is string | number | boolean | null {\n return v === null || ['string', 'number', 'boolean'].includes(typeof v);\n}\n\nfunction isFlatRow(v: unknown): v is Record<string, string | number | boolean | null> {\n if (v === null || typeof v !== 'object' || Array.isArray(v)) return false;\n return Object.values(v).every(isFlat);\n}\n\nconst NEEDS_QUOTING = /[\",\\r\\n]/;\n\nfunction escapeCell(v: string | number | boolean | null): string {\n if (v === null) return '';\n const s = typeof v === 'string' ? v : String(v);\n return NEEDS_QUOTING.test(s) ? `\"${s.replace(/\"/g, '\"\"')}\"` : s;\n}\n\nexport function toCsv(value: Json): string | null {\n if (!Array.isArray(value) || value.length === 0) return null;\n if (!value.every(isFlatRow)) return null;\n\n const keys = Object.keys(value[0]);\n if (keys.length === 0) return null;\n for (let i = 1; i < value.length; i++) {\n const row = value[i] as Record<string, unknown>;\n if (Object.keys(row).length !== keys.length) return null;\n for (const k of keys) if (!(k in row)) return null;\n }\n\n const lines = [keys.map(escapeCell).join(',')];\n for (const row of value) {\n lines.push(keys.map((k) => escapeCell((row as Record<string, Json>)[k] as never)).join(','));\n }\n return lines.join('\\n');\n}\n","import { utf8ByteLength } from '@apicircle/shared';\nimport { toToon } from './toon';\nimport { toYaml } from './yaml';\nimport { toCsv } from './csv';\n\n/**\n * Output formats we measure savings for. Minification is NOT in this\n * list on purpose — stripping whitespace from pretty-printed JSON isn't\n * a \"transformation\", it's the wire-effective baseline most APIs already\n * send. Comparing TOON/YAML/CSV against pretty JSON would inflate the\n * apparent savings; we always normalize to minified JSON first.\n */\nexport type TransformFormat = 'toon' | 'yaml' | 'csv';\n\nexport interface TransformCandidate {\n format: TransformFormat;\n /** Encoded payload. Available so the UI can offer \"view\" / \"copy\". */\n preview: string;\n /** UTF-8 bytes of `preview`. */\n bytes: number;\n /**\n * Bytes saved vs `minifiedBytes` (the wire baseline), expressed as a\n * percentage with one decimal. Clamped at 0 — candidates that don't\n * beat the baseline are dropped from `candidates` entirely.\n */\n percentSaved: number;\n}\n\nexport interface TransformSavings {\n /** UTF-8 bytes of the body as received (may be pretty-printed). */\n originalBytes: number;\n /**\n * UTF-8 bytes of the same body re-emitted as compact JSON. This is\n * the honest wire-baseline — most APIs already send minified JSON,\n * and any \"transformation savings\" should be measured against that,\n * not against a verbose pretty-printed version. When `originalBytes ===\n * minifiedBytes`, the wire body was already compact; when they differ,\n * the UI can surface that delta separately as a \"minify only\" tip\n * without mixing it into transformation savings.\n */\n minifiedBytes: number;\n /** Sorted by percentSaved descending. Empty when nothing beats minified. */\n candidates: TransformCandidate[];\n}\n\n/**\n * Compute savings candidates for a response body. Only JSON-shaped\n * content is inspected — binary, plain text, and HTML return an empty\n * candidate list. Pure, no side effects.\n *\n * Baselines:\n * - `originalBytes` : received-as-is. What the editor is currently rendering.\n * - `minifiedBytes` : what the wire would have carried with whitespace stripped.\n * - `candidates[].percentSaved` : measured against `minifiedBytes`. So a\n * \"20% smaller as TOON\" claim means TOON beats compact JSON by 20%,\n * not that it beats pretty JSON by 20%.\n */\nexport function computeTransformSavings(body: string, contentType?: string): TransformSavings {\n const originalBytes = utf8ByteLength(body);\n if (!isJsonLike(body, contentType)) {\n return { originalBytes, minifiedBytes: originalBytes, candidates: [] };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n return { originalBytes, minifiedBytes: originalBytes, candidates: [] };\n }\n\n const minified = JSON.stringify(parsed);\n const minifiedBytes = utf8ByteLength(minified);\n\n const candidates: TransformCandidate[] = [];\n\n try {\n const toon = toToon(parsed as Parameters<typeof toToon>[0]);\n if (toon && toon !== minified) {\n candidates.push(makeCandidate('toon', toon, minifiedBytes));\n }\n } catch {\n // Encoder bug shouldn't break the response panel — silently skip.\n }\n\n try {\n const yaml = toYaml(parsed as Parameters<typeof toYaml>[0]);\n if (yaml && yaml !== minified) {\n candidates.push(makeCandidate('yaml', yaml, minifiedBytes));\n }\n } catch {\n // Same: don't crash the panel on an encoder hiccup.\n }\n\n const csv = toCsv(parsed as Parameters<typeof toCsv>[0]);\n if (csv) {\n candidates.push(makeCandidate('csv', csv, minifiedBytes));\n }\n\n return {\n originalBytes,\n minifiedBytes,\n candidates: candidates\n .filter((c) => c.bytes < minifiedBytes)\n .sort((a, b) => b.percentSaved - a.percentSaved),\n };\n}\n\nfunction makeCandidate(\n format: TransformFormat,\n preview: string,\n baselineBytes: number,\n): TransformCandidate {\n const bytes = utf8ByteLength(preview);\n const ratio = baselineBytes === 0 ? 0 : 1 - bytes / baselineBytes;\n return {\n format,\n preview,\n bytes,\n percentSaved: Math.max(0, Math.round(ratio * 1000) / 10),\n };\n}\n\nfunction isJsonLike(body: string, contentType?: string): boolean {\n if (contentType && /\\bjson\\b/i.test(contentType)) return true;\n // Best-effort sniff for missing/wrong content-type: strict trim, then\n // require an opening brace/bracket. Avoids accidentally trying to JSON\n // parse an HTML page.\n const trimmed = body.trim();\n if (!trimmed) return false;\n return trimmed.startsWith('{') || trimmed.startsWith('[');\n}\n\nexport const TRANSFORM_FORMAT_LABELS: Record<TransformFormat, string> = {\n toon: 'TOON',\n yaml: 'YAML',\n csv: 'CSV',\n};\n"],"mappings":"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AACnD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;AACjD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;AAClD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE;AAClD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;AACnD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;AACjD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;AACjD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE;AAClD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;AACnD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;AACjD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;AAClD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE;AAClD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAA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","names":["n","c","a","b","d","base64","out","base64","warnings","randomHex","base64UrlEncode","HTTP_METHODS","buildRequest","HTTP_METHODS","buildRequest","parseMethod","parseBody","parseAuth","randomHex","sha256Hex","typeName","sortedReplacer","structurallyEqual","generateId","generateId","snapshot","envPriorityKey","generateId","request","snapshot","generateId","lookup","passed","envPriorityKey","INDENT","INDENT","SAFE_KEY","NEEDS_QUOTING","isFlatPrimitive","encodeKey","encodeScalar","encodeNode","NEEDS_QUOTING"]}
|
|
1
|
+
{"version":3,"sources":["../src/request/bodyTypeContentType.ts","../src/request/headersDictionary.ts","../src/auth/awsSigV4.ts","../src/auth/hawk.ts","../src/auth/jwt.ts","../src/auth/_legacyHashes.ts","../src/auth/ntlm.ts","../src/auth/oauth2/fetchToken.ts","../src/auth/oauth2/grants.ts","../src/request/applyAuth.ts","../src/request/platformDetection.ts","../src/request/autoHeaders.ts","../src/request/buildRequest.ts","../src/environment/variableResolver.ts","../src/request/resolveInheritedAuth.ts","../src/request/preSendValidation.ts","../src/auth/_sha512_256.ts","../src/auth/digest.ts","../src/request/executeRequest.ts","../src/request/requestRunAdapter.ts","../src/auth/oauth2/pkce.ts","../src/request/parseCurl.ts","../src/import/postmanCollection.ts","../src/import/postmanEnvironment.ts","../src/import/insomniaCollection.ts","../src/import/apicircleFolder.ts","../src/export/folderExportCredentials.ts","../src/export/folderExport.ts","../src/import/apicircleEnvironment.ts","../src/assertions/runAssertions.ts","../src/environment/extractContext.ts","../src/environment/resolveRequest.ts","../src/secrets/crypto.ts","../src/secrets/passphraseKey.ts","../src/git/branchNames.ts","../src/git/serializeWorkspace.ts","../src/git/repoPaths.ts","../src/git/parseWorkspaceJson.ts","../src/git/redactWorkspace.ts","../src/git/collectAttachments.ts","../src/release/semver.ts","../src/release/publishRelease.ts","../src/linked/linkedSnapshot.ts","../src/linked/requestOverride.ts","../src/editors/contentTypeLanguageMap.ts","../src/editors/graphqlSchemaParser.ts","../src/git/threeWayDiff.ts","../src/git/summarizeUnpushedChanges.ts","../src/git/linkedThreeWayMerge.ts","../src/workspace/applyMutation.ts","../src/workspace/apicircleFolderImport.ts","../src/workspace/runPlan.ts","../src/transform/toon.ts","../src/transform/yaml.ts","../src/transform/csv.ts","../src/transform/computeSavings.ts"],"sourcesContent":["import type { BodyType } from '@apicircle/shared';\n\n// Single source of truth for body-type ↔ Content-Type mapping. The Editor\n// uses this to (a) seed the Content-Type header when the user picks a body\n// type and (b) reverse-resolve a body type when the user edits the\n// Content-Type header by hand.\n\nexport type HeaderEntry = { key: string; value: string; enabled: boolean };\n\nconst BODY_TYPE_TO_CONTENT_TYPE: Record<BodyType, string | null> = {\n none: null,\n json: 'application/json',\n text: 'text/plain',\n xml: 'application/xml',\n graphql: 'application/graphql',\n 'form-data': 'multipart/form-data',\n urlencoded: 'application/x-www-form-urlencoded',\n binary: 'application/octet-stream',\n};\n\nexport function getContentTypeForBodyType(bodyType: BodyType): string | null {\n return BODY_TYPE_TO_CONTENT_TYPE[bodyType];\n}\n\n/**\n * Reverse-map a Content-Type header value to a BodyType, or null if it\n * doesn't match any known type. Strips parameters (e.g. `;charset=utf-8`)\n * and is case-insensitive.\n */\nexport function getBodyTypeForContentType(contentType: string): BodyType | null {\n const main = contentType.toLowerCase().split(';')[0]?.trim();\n if (!main) return null;\n switch (main) {\n case 'application/json':\n return 'json';\n case 'text/plain':\n return 'text';\n case 'application/xml':\n case 'text/xml':\n return 'xml';\n case 'application/graphql':\n return 'graphql';\n case 'multipart/form-data':\n return 'form-data';\n case 'application/x-www-form-urlencoded':\n return 'urlencoded';\n case 'application/octet-stream':\n return 'binary';\n default:\n return null;\n }\n}\n\n/**\n * Apply (or remove) the Content-Type header on a header list to match the\n * given body type. Pure — returns a new array.\n *\n * - bodyType=none → strips any existing Content-Type entry.\n * - existing Content-Type entry → updated value, preserving order.\n * - no Content-Type entry → appended.\n */\nexport function applyContentTypeForBodyType(\n headers: HeaderEntry[],\n bodyType: BodyType,\n): HeaderEntry[] {\n const target = getContentTypeForBodyType(bodyType);\n const idx = headers.findIndex((h) => h.key.trim().toLowerCase() === 'content-type');\n\n if (target === null) {\n return idx === -1 ? headers : headers.filter((_, i) => i !== idx);\n }\n\n if (idx === -1) {\n return [...headers, { key: 'Content-Type', value: target, enabled: true }];\n }\n\n return headers.map((entry, i) =>\n i === idx ? { ...entry, value: target, enabled: true } : entry,\n );\n}\n","/**\n * HTTP Headers dictionary — used for autocomplete in the Headers editor.\n *\n * Each entry maps a header name to its known values (empty array = free text).\n * Values that depend on context (e.g. specific MIME types) provide a curated\n * set of the most common options.\n */\n\nexport interface HeaderEntry {\n name: string;\n description: string;\n values: string[];\n /**\n * `browser` — Forbidden by the Fetch spec; browsers silently ignore any\n * attempt to set this header from JavaScript. On Desktop (native\n * HTTP layer) the restriction does NOT apply — the header can\n * still be set manually.\n *\n * `app` — Automatically injected by API Circle Studio at send-time (see\n * autoHeaders.ts). Users can override these in the Headers tab\n * and their value will take precedence.\n *\n * Omitted — Fully user-controlled on both Web and Desktop.\n */\n reserved?: 'browser' | 'app';\n /** Short note shown in the autocomplete to explain the reservation. */\n reservedNote?: string;\n}\n\nexport const HTTP_HEADERS_MAP: HeaderEntry[] = [\n // ── Request headers ────────────────────────────────────────────────────────\n {\n name: 'Accept',\n description: 'Media types the client accepts',\n values: [\n 'application/json',\n 'application/xml',\n 'text/html',\n 'text/plain',\n 'text/csv',\n 'application/octet-stream',\n 'multipart/form-data',\n 'application/x-www-form-urlencoded',\n 'application/graphql',\n 'image/png',\n 'image/jpeg',\n 'image/webp',\n 'image/gif',\n 'image/svg+xml',\n '*/*',\n ],\n },\n {\n name: 'Accept-Encoding',\n description: 'Acceptable content encodings',\n values: ['gzip', 'deflate', 'br', 'zstd', 'identity', 'gzip, deflate, br'],\n reserved: 'browser',\n reservedNote: 'Set automatically by the browser; ignored in web fetch',\n },\n {\n name: 'Accept-Language',\n description: 'Acceptable human languages',\n values: ['en', 'en-US', 'en-GB', 'fr', 'de', 'ja', 'zh-CN', 'es', '*'],\n },\n {\n name: 'Authorization',\n description: 'Authentication credentials',\n values: ['Bearer ', 'Basic ', 'Digest ', 'NTLM ', 'AWS4-HMAC-SHA256 ', 'ApiKey '],\n },\n {\n name: 'Cache-Control',\n description: 'Directives for caching mechanisms',\n values: [\n 'no-cache',\n 'no-store',\n 'max-age=0',\n 'max-age=3600',\n 'must-revalidate',\n 'private',\n 'public',\n 'no-cache, no-store, must-revalidate',\n ],\n },\n {\n name: 'Connection',\n description: 'Control options for the current connection',\n values: ['keep-alive', 'close', 'upgrade'],\n reserved: 'browser',\n reservedNote: 'Forbidden by Fetch spec; browser controls connection management',\n },\n {\n name: 'Content-Encoding',\n description: 'Encoding applied to the body',\n values: ['gzip', 'deflate', 'br', 'identity'],\n },\n {\n name: 'Content-Length',\n description: 'Size of the request body in bytes',\n values: [],\n reserved: 'browser',\n reservedNote: 'Computed automatically; ignored in web fetch',\n },\n {\n name: 'Content-Type',\n description: 'Media type of the request body',\n values: [\n 'application/json',\n 'application/xml',\n 'text/xml',\n 'text/html',\n 'text/plain',\n 'text/csv',\n 'application/x-www-form-urlencoded',\n 'multipart/form-data',\n 'application/octet-stream',\n 'application/graphql',\n 'application/ld+json',\n 'application/vnd.api+json',\n 'application/problem+json',\n ],\n },\n {\n name: 'Cookie',\n description: 'HTTP cookies sent by the client',\n values: [],\n reserved: 'browser',\n reservedNote: 'Managed by the browser cookie jar; forbidden in web fetch',\n },\n {\n name: 'Host',\n description: 'Host and port of the target server',\n values: [],\n reserved: 'browser',\n reservedNote: 'Derived from the request URL; forbidden in web fetch',\n },\n {\n name: 'If-Match',\n description: 'Conditional request based on ETag',\n values: ['*'],\n },\n {\n name: 'If-Modified-Since',\n description: 'Conditional GET if modified after this date',\n values: [],\n },\n {\n name: 'If-None-Match',\n description: 'Conditional request — only respond if ETag differs',\n values: ['*'],\n },\n {\n name: 'If-Unmodified-Since',\n description: 'Conditional request based on date',\n values: [],\n },\n {\n name: 'Origin',\n description: 'Origin of the cross-origin request',\n values: ['http://app.studio.apicircle.dev', 'https://app.studio.apicircle.dev'],\n reserved: 'browser',\n reservedNote: 'Set by browser on cross-origin requests; auto-fed on Desktop',\n },\n {\n name: 'Prefer',\n description: 'Client preferences for server behaviour',\n values: [\n 'respond-async',\n 'return=representation',\n 'return=minimal',\n 'handling=strict',\n 'handling=lenient',\n ],\n },\n {\n name: 'Range',\n description: 'Request partial content',\n values: ['bytes=0-', 'bytes=0-1023'],\n },\n {\n name: 'Referer',\n description: 'URL of the page making the request',\n values: ['http://app.studio.apicircle.dev/'],\n reserved: 'browser',\n reservedNote: 'Set by browser from document context; auto-fed on Desktop',\n },\n {\n name: 'User-Agent',\n description: 'Client application identifier',\n values: [\n 'API Circle Studio/1.0.0',\n 'Mozilla/5.0 (compatible; API Circle Studio)',\n 'curl/8.0.0',\n ],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch; settable in Desktop (native) requests',\n },\n {\n name: 'X-API-Key',\n description: 'API key for authentication',\n values: [],\n },\n {\n name: 'X-Client-Name',\n description: 'Auto-fed: client application name',\n values: ['API Circle Studio'],\n reserved: 'app',\n reservedNote: 'Injected automatically; your value overrides it',\n },\n {\n name: 'X-Client-Platform',\n description: 'Auto-fed: runtime platform',\n values: ['desktop', 'web'],\n reserved: 'app',\n reservedNote: 'Injected automatically; your value overrides it',\n },\n {\n name: 'X-Client-Version',\n description: 'Auto-fed: application version',\n values: ['1.0.0'],\n reserved: 'app',\n reservedNote: 'Injected automatically; your value overrides it',\n },\n {\n name: 'X-Correlation-Id',\n description: 'Correlation ID for distributed tracing',\n values: [],\n },\n {\n name: 'X-Custom-Auth',\n description: 'Custom authentication header',\n values: [],\n },\n {\n name: 'X-Forwarded-For',\n description: 'Originating IP in proxy chains',\n values: [],\n },\n {\n name: 'X-Forwarded-Host',\n description: 'Originating host in proxy chains',\n values: [],\n },\n {\n name: 'X-Forwarded-Proto',\n description: 'Originating protocol in proxy chains',\n values: ['http', 'https'],\n },\n {\n name: 'X-Request-ID',\n description: 'Unique identifier for this request',\n values: [],\n },\n {\n name: 'X-Trace-Span-Id',\n description: 'Auto-fed: distributed trace span ID (generated per send)',\n values: [],\n reserved: 'app',\n reservedNote: 'Regenerated on every send; cannot be stored or overridden',\n },\n {\n name: 'traceparent',\n description: 'W3C Trace Context parent (auto-fed per send)',\n values: [],\n reserved: 'app',\n reservedNote: 'Regenerated on every send; your value overrides it',\n },\n // ── Conditional / caching ─────────────────────────────────────────────────\n {\n name: 'Pragma',\n description: 'Legacy cache control (HTTP/1.0)',\n values: ['no-cache'],\n },\n {\n name: 'Expires',\n description: 'Date/time after which the response is stale',\n values: [],\n },\n {\n name: 'Date',\n description: 'Date and time the message was sent',\n values: [],\n reserved: 'browser',\n reservedNote: 'Set by the HTTP stack; forbidden in web fetch',\n },\n {\n name: 'Age',\n description: 'Seconds the object has been in a proxy cache',\n values: [],\n },\n {\n name: 'Last-Modified',\n description: 'Date the resource was last modified',\n values: [],\n },\n {\n name: 'Vary',\n description: 'Headers that determine cache key',\n values: ['Accept', 'Accept-Encoding', 'Accept-Language', 'Origin', '*'],\n },\n // ── Transfer / encoding ───────────────────────────────────────────────────\n {\n name: 'Transfer-Encoding',\n description: 'Transfer encoding applied to the message body',\n values: ['chunked', 'compress', 'deflate', 'gzip', 'identity'],\n reserved: 'browser',\n reservedNote: 'Managed by the HTTP stack; forbidden in web fetch',\n },\n {\n name: 'TE',\n description: 'Transfer encodings the client can accept',\n values: ['trailers', 'deflate', 'gzip'],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch',\n },\n {\n name: 'Trailer',\n description: 'Headers included in the trailer of a chunked transfer',\n values: [],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch',\n },\n {\n name: 'Upgrade',\n description: 'Protocol upgrade request',\n values: ['websocket', 'HTTP/2.0', 'h2c'],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch; use WebSocket API instead',\n },\n // ── Proxy / forwarding ────────────────────────────────────────────────────\n {\n name: 'Forwarded',\n description: 'Standard proxy forwarding header (replaces X-Forwarded-*)',\n values: [],\n },\n {\n name: 'Max-Forwards',\n description: 'Maximum number of proxy hops for TRACE/OPTIONS',\n values: ['10'],\n },\n {\n name: 'Proxy-Authorization',\n description: 'Credentials for authenticating with a proxy',\n values: ['Basic ', 'Bearer '],\n reserved: 'browser',\n reservedNote: 'Proxy-* headers are forbidden in web fetch',\n },\n {\n name: 'Via',\n description: 'Proxies/gateways this message has passed through',\n values: [],\n reserved: 'browser',\n reservedNote: 'Set by proxy infrastructure; forbidden in web fetch',\n },\n // ── Content negotiation (extra) ───────────────────────────────────────────\n {\n name: 'Accept-Charset',\n description: 'Character sets the client accepts',\n values: ['utf-8', 'iso-8859-1', '*'],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch',\n },\n {\n name: 'Accept-Ranges',\n description: 'Whether partial requests are supported',\n values: ['bytes', 'none'],\n },\n // ── Content description ───────────────────────────────────────────────────\n {\n name: 'Allow',\n description: 'HTTP methods supported by the resource',\n values: ['GET, HEAD', 'GET, POST', 'GET, POST, PUT, DELETE, OPTIONS'],\n },\n {\n name: 'Content-Disposition',\n description: 'How content should be displayed / filename hint',\n values: ['inline', 'attachment', 'attachment; filename=\"file.bin\"'],\n },\n {\n name: 'Content-Language',\n description: 'Language(s) of the response body',\n values: ['en', 'en-US', 'fr', 'de'],\n },\n {\n name: 'Content-Location',\n description: 'Alternate URL for the returned data',\n values: [],\n },\n {\n name: 'Content-Range',\n description: 'Byte range of a partial content response',\n values: [],\n },\n // ── Security ──────────────────────────────────────────────────────────────\n {\n name: 'Strict-Transport-Security',\n description: 'HSTS: force HTTPS for future requests',\n values: [\n 'max-age=31536000',\n 'max-age=31536000; includeSubDomains',\n 'max-age=31536000; includeSubDomains; preload',\n ],\n },\n {\n name: 'Content-Security-Policy',\n description: 'Restrict sources of content to mitigate XSS',\n values: [\"default-src 'self'\", \"default-src 'self'; script-src 'none'\"],\n },\n {\n name: 'X-Content-Type-Options',\n description: 'Prevent MIME-type sniffing',\n values: ['nosniff'],\n },\n {\n name: 'X-Frame-Options',\n description: 'Prevent clickjacking via iframes',\n values: ['DENY', 'SAMEORIGIN'],\n },\n {\n name: 'X-XSS-Protection',\n description: 'Legacy XSS filter hint for older browsers',\n values: ['0', '1', '1; mode=block'],\n },\n {\n name: 'Permissions-Policy',\n description: 'Control browser feature permissions',\n values: ['geolocation=(), microphone=()', 'interest-cohort=()'],\n },\n {\n name: 'Cross-Origin-Opener-Policy',\n description: 'Control browsing context group sharing',\n values: ['same-origin', 'same-origin-allow-popups', 'unsafe-none'],\n },\n {\n name: 'Cross-Origin-Resource-Policy',\n description: 'Control cross-origin resource loading',\n values: ['same-origin', 'same-site', 'cross-origin'],\n },\n {\n name: 'Cross-Origin-Embedder-Policy',\n description: 'Require CORP for sub-resources',\n values: ['require-corp', 'unsafe-none'],\n },\n {\n name: 'DNT',\n description: 'Do Not Track signal',\n values: ['1', '0'],\n reserved: 'browser',\n reservedNote: 'Forbidden in web fetch',\n },\n // ── Cookies ───────────────────────────────────────────────────────────────\n {\n name: 'Set-Cookie',\n description: 'Set an HTTP cookie on the client',\n values: [],\n },\n // ── Server info ───────────────────────────────────────────────────────────\n {\n name: 'Server',\n description: 'Software handling the request',\n values: ['nginx', 'Apache', 'Caddy', 'Kestrel'],\n },\n {\n name: 'X-Powered-By',\n description: 'Technology powering the server',\n values: ['Express', 'Hono', 'Next.js', 'ASP.NET'],\n },\n // ── Distributed tracing (extra) ───────────────────────────────────────────\n {\n name: 'tracestate',\n description: 'W3C Trace Context vendor state',\n values: [],\n },\n {\n name: 'baggage',\n description: 'W3C Baggage propagation header',\n values: [],\n },\n // ── Link / pre-load ───────────────────────────────────────────────────────\n {\n name: 'Link',\n description: 'Related resource links (preload, pagination, canonical)',\n values: ['</api>; rel=\"preload\"', '</next>; rel=\"next\"'],\n },\n // ── Fetch metadata (browser-set, may be forwarded) ───────────────────────\n {\n name: 'Sec-Fetch-Dest',\n description: 'Fetch metadata: destination of the request',\n values: ['empty', 'document', 'fetch', 'image', 'script'],\n },\n {\n name: 'Sec-Fetch-Mode',\n description: 'Fetch metadata: request mode',\n values: ['cors', 'navigate', 'no-cors', 'same-origin'],\n },\n {\n name: 'Sec-Fetch-Site',\n description: 'Fetch metadata: origin relationship',\n values: ['cross-site', 'same-origin', 'same-site', 'none'],\n },\n {\n name: 'Sec-Fetch-User',\n description: 'Fetch metadata: whether triggered by user action',\n values: ['?1'],\n },\n // ── Misc request ─────────────────────────────────────────────────────────\n {\n name: 'Expect',\n description: 'Expected behaviour from the server before sending the body',\n values: ['100-continue'],\n },\n {\n name: 'From',\n description: 'Email of the user controlling the requesting agent',\n values: [],\n },\n {\n name: 'Keep-Alive',\n description: 'Parameters for persistent connections',\n values: ['timeout=5', 'timeout=5, max=1000'],\n },\n // ── Common response headers ───────────────────────────────────────────────\n {\n name: 'Access-Control-Allow-Origin',\n description: 'CORS: allowed origins',\n values: ['*', 'http://app.studio.apicircle.dev', 'https://app.studio.apicircle.dev'],\n },\n {\n name: 'Access-Control-Allow-Methods',\n description: 'CORS: allowed HTTP methods',\n values: ['GET, POST, PUT, DELETE, OPTIONS', 'GET, POST, OPTIONS', '*'],\n },\n {\n name: 'Access-Control-Allow-Headers',\n description: 'CORS: allowed request headers',\n values: ['Content-Type, Authorization', 'Content-Type, Authorization, X-API-Key', '*'],\n },\n {\n name: 'Access-Control-Allow-Credentials',\n description: 'CORS: whether credentials are allowed',\n values: ['true', 'false'],\n },\n {\n name: 'Access-Control-Expose-Headers',\n description: 'CORS: headers exposed to the client',\n values: ['Content-Type, X-Request-ID', 'Authorization'],\n },\n {\n name: 'Access-Control-Max-Age',\n description: 'CORS: how long preflight results can be cached (seconds)',\n values: ['3600', '86400'],\n },\n {\n name: 'Access-Control-Request-Headers',\n description: 'CORS preflight: headers to be included in actual request',\n values: [],\n },\n {\n name: 'Access-Control-Request-Method',\n description: 'CORS preflight: method to be used in actual request',\n values: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],\n },\n {\n name: 'ETag',\n description: 'Entity tag for cache validation',\n values: [],\n },\n {\n name: 'Location',\n description: 'URL to redirect to',\n values: [],\n },\n {\n name: 'Retry-After',\n description: 'When to retry after 429/503',\n values: ['30', '60', '120'],\n },\n {\n name: 'WWW-Authenticate',\n description: 'Authentication challenge',\n values: ['Basic realm=\"API\"', 'Bearer', 'Digest', 'NTLM'],\n },\n {\n name: 'Proxy-Authenticate',\n description: 'Proxy authentication challenge',\n values: ['Basic realm=\"Proxy\"'],\n },\n {\n name: 'Warning',\n description: 'Advisory about possible problems with the message',\n values: ['110 - \"Response is Stale\"', '214 - \"Transformation Applied\"'],\n },\n // ── Reporting ─────────────────────────────────────────────────────────────\n {\n name: 'NEL',\n description: 'Network Error Logging configuration',\n values: [],\n },\n {\n name: 'Report-To',\n description: 'Endpoint for reporting API events',\n values: [],\n },\n];\n\n/** Lower-cased name → HeaderEntry lookup. */\nconst HEADER_MAP = new Map<string, HeaderEntry>(\n HTTP_HEADERS_MAP.map((h) => [h.name.toLowerCase(), h]),\n);\n\n/**\n * Headers that are auto-fed at send-time should not appear in suggestions — the\n * user cannot meaningfully set them (they are injected automatically by the app).\n */\nconst SUGGESTABLE_HEADERS = HTTP_HEADERS_MAP.filter((h) => h.reserved !== 'app').sort((a, b) =>\n a.name.localeCompare(b.name),\n);\n\n/**\n * Lower-cased names of headers that meaningfully appear on responses.\n * Drives `mode: 'response'` filtering for `suggestHeaders` — used by the\n * mock response editor so its key autocomplete surfaces only headers a\n * server would realistically set.\n *\n * Mix of two groups:\n * • Headers that are response-only (Set-Cookie, ETag, Location, etc.).\n * • Headers that exist on both sides but where the server-side use is\n * the dominant case (Content-Type, Cache-Control, Vary, etc.).\n */\nconst RESPONSE_HEADER_NAMES = new Set([\n // Content + caching\n 'content-type',\n 'content-length',\n 'content-encoding',\n 'content-disposition',\n 'content-language',\n 'content-location',\n 'cache-control',\n 'expires',\n 'last-modified',\n 'etag',\n 'vary',\n 'age',\n 'pragma',\n // Auth + cookies\n 'set-cookie',\n 'www-authenticate',\n 'proxy-authenticate',\n // Connection / framing\n 'server',\n 'date',\n 'connection',\n 'keep-alive',\n 'transfer-encoding',\n 'upgrade',\n // CORS (response side)\n 'access-control-allow-origin',\n 'access-control-allow-methods',\n 'access-control-allow-headers',\n 'access-control-allow-credentials',\n 'access-control-expose-headers',\n 'access-control-max-age',\n // Redirect + retry\n 'location',\n 'retry-after',\n 'allow',\n // Security\n 'strict-transport-security',\n 'content-security-policy',\n 'x-frame-options',\n 'x-content-type-options',\n 'referrer-policy',\n 'permissions-policy',\n // Observability + reporting\n 'nel',\n 'report-to',\n 'warning',\n // Custom-x catch-alls users frequently set\n 'x-request-id',\n 'x-correlation-id',\n 'x-rate-limit-limit',\n 'x-rate-limit-remaining',\n 'x-rate-limit-reset',\n]);\n\n/** Filtered view of the suggestable headers, scoped to response-side names. */\nconst SUGGESTABLE_RESPONSE_HEADERS = SUGGESTABLE_HEADERS.filter((h) =>\n RESPONSE_HEADER_NAMES.has(h.name.toLowerCase()),\n);\n\nexport type HeaderSuggestionMode = 'request' | 'response';\n\n/**\n * Suggest header names by case-insensitive prefix. Empty prefix returns the\n * full suggestable list; auto-fed (`reserved: 'app'`) headers are excluded.\n * An optional `limit` caps the number of filtered (non-empty prefix) results.\n *\n * `mode` filters by whether the header is request- or response-side\n * relevant. Defaults to `'request'` for back-compat with the request\n * editor's existing call sites.\n */\nexport function suggestHeaders(\n prefix: string,\n limit?: number,\n mode: HeaderSuggestionMode = 'request',\n): HeaderEntry[] {\n const source = mode === 'response' ? SUGGESTABLE_RESPONSE_HEADERS : SUGGESTABLE_HEADERS;\n const lower = prefix.toLowerCase().trim();\n if (!lower) return limit !== undefined ? source.slice(0, limit) : source;\n const filtered = source.filter((h) => h.name.toLowerCase().startsWith(lower));\n return limit !== undefined ? filtered.slice(0, limit) : filtered;\n}\n\n/**\n * Get the known values for a specific header name (case-insensitive).\n * Returns an empty array when the header has no predefined values (free text).\n */\nexport function getHeaderValues(headerName: string): string[] {\n return HEADER_MAP.get(headerName.toLowerCase().trim())?.values ?? [];\n}\n\n/**\n * Returns the HeaderEntry for an exact name match, or undefined.\n */\nexport function getHeaderEntry(headerName: string): HeaderEntry | undefined {\n return HEADER_MAP.get(headerName.toLowerCase().trim());\n}\n","/**\n * AWS Signature Version 4 — request signing for AWS APIs.\n *\n * SigV4 is per-request HMAC chain over a canonical-request string. The\n * server (or a STS-issued temporary credentials provider) verifies the\n * signature using the same algorithm, so request integrity is end-to-end\n * without any callback / handshake.\n *\n * canonical = METHOD\\nPATH\\nQUERY\\nHEADERS\\nSIGNED_HEADERS\\nPAYLOAD_HASH\n * stringToSign = \"AWS4-HMAC-SHA256\\n{amzDate}\\n{credScope}\\n{sha256(canonical)}\"\n * kSigning = HMAC(HMAC(HMAC(HMAC(\"AWS4{secret}\", date), region), service), \"aws4_request\")\n * signature = hex(HMAC(kSigning, stringToSign))\n *\n * Two delivery modes:\n * - `header`: sets `Authorization: AWS4-HMAC-SHA256 Credential=..., SignedHeaders=..., Signature=...`\n * - `query`: rewrites the URL with `X-Amz-*` query params (presigned URL).\n *\n * Body hashing only runs in `header` mode (presigned URLs always\n * advertise `UNSIGNED-PAYLOAD`). Streaming / chunked bodies fall through\n * to `UNSIGNED-PAYLOAD` because we'd otherwise have to buffer the entire\n * stream before signing.\n */\n\n/**\n * Body shapes we can hash for SigV4 payload signing. Anything we can't\n * read as bytes synchronously goes to `UNSIGNED-PAYLOAD` — AWS accepts\n * that as long as `x-amz-content-sha256: UNSIGNED-PAYLOAD` is in the\n * signed headers. ReadableStream falls into this bucket since draining\n * it before signing would consume the body before fetch can send it.\n */\nexport type SigV4Body =\n | string\n | ArrayBuffer\n | Uint8Array\n | Blob\n | URLSearchParams\n | FormData\n | ReadableStream<Uint8Array>\n | null\n | undefined;\n\nexport interface SigV4SignArgs {\n method: string;\n url: string;\n /** Existing request headers — passed through and merged with SigV4 additions. */\n headers: Record<string, string>;\n /**\n * Body for payload hashing. `string`, `ArrayBuffer`, `Uint8Array`,\n * `Blob`, and `URLSearchParams` are hashed verbatim. `FormData` and\n * `ReadableStream` fall through to `UNSIGNED-PAYLOAD` — AWS accepts\n * that signing mode and many AWS SDKs default to it for streaming.\n */\n body?: SigV4Body;\n accessKeyId: string;\n secretAccessKey: string;\n region: string;\n service: string;\n /** STS-issued session token; copied to `X-Amz-Security-Token`. */\n sessionToken?: string;\n /** Where to put the signature — header (default) or query (presigned URL). */\n addTo?: 'header' | 'query';\n /**\n * S3 specifically does NOT collapse double slashes or normalize dot\n * segments — it treats `bucket/foo//bar` as a different object from\n * `bucket/foo/bar`. Set true when `service: 's3'` to preserve the\n * raw path. Default false (matches non-S3 services like execute-api).\n *\n * If you don't pass this and `service === 's3'`, we auto-enable it —\n * the common case for S3 callers is \"preserve my path exactly\".\n */\n preservePathSlashes?: boolean;\n /**\n * Override `now` for tests. The amz-date stamp must be the SAME instant\n * used to build the credential scope, so we capture once.\n */\n now?: Date;\n}\n\nexport interface SigV4SignResult {\n url: string;\n headers: Record<string, string>;\n}\n\nconst EMPTY_PAYLOAD_HASH = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';\n\nexport async function applyAwsSigV4(args: SigV4SignArgs): Promise<SigV4SignResult> {\n let parsed: URL;\n try {\n parsed = new URL(args.url);\n } catch {\n throw new Error(`AWS SigV4: invalid URL: ${args.url}`);\n }\n\n const enc = new TextEncoder();\n const now = args.now ?? new Date();\n const amzDate = now.toISOString().replace(/[:-]|\\.\\d{3}/g, '');\n const dateStamp = amzDate.slice(0, 8);\n const isQuery = args.addTo === 'query';\n\n const payloadHash = isQuery ? 'UNSIGNED-PAYLOAD' : await computeBodyHash(args.body);\n const credScope = `${dateStamp}/${args.region}/${args.service}/aws4_request`;\n\n // Signed headers map — start with host (always signed). In header\n // mode we add x-amz-date + x-amz-content-sha256 (required by S3 /\n // DynamoDB; tolerated everywhere else) and the optional session token.\n // We THEN fold in user-set request headers because real AWS requests\n // routinely require Range / Content-Type / Cache-Control / etc to be\n // in SignedHeaders — without that the server gets a hash mismatch and\n // returns 403 SignatureDoesNotMatch. We exclude `Authorization` (we\n // produce it) and any `host` the caller may have set (we own it).\n const signedMap: Record<string, string> = {\n host: parsed.hostname + (parsed.port ? `:${parsed.port}` : ''),\n };\n if (!isQuery) {\n signedMap['x-amz-date'] = amzDate;\n signedMap['x-amz-content-sha256'] = payloadHash;\n if (args.sessionToken) signedMap['x-amz-security-token'] = args.sessionToken;\n }\n // Fold caller's headers into the signed set. AWS spec normalizes:\n // lowercase header name, trim leading/trailing whitespace, collapse\n // internal whitespace runs to a single space.\n for (const [rawKey, rawValue] of Object.entries(args.headers)) {\n const key = rawKey.toLowerCase();\n if (key === 'authorization' || key === 'host') continue;\n if (key in signedMap) continue; // don't overwrite our own additions\n signedMap[key] = rawValue.replace(/\\s+/g, ' ').trim();\n }\n const signedHeaderNames = Object.keys(signedMap).sort();\n const canonicalHeaders = signedHeaderNames.map((k) => `${k}:${signedMap[k]}\\n`).join('');\n const signedHeadersList = signedHeaderNames.join(';');\n\n // Query params — preserve existing + add X-Amz-* in query mode.\n const qEntries: Array<[string, string]> = [];\n parsed.searchParams.forEach((v, k) => qEntries.push([k, v]));\n if (isQuery) {\n qEntries.push(['X-Amz-Algorithm', 'AWS4-HMAC-SHA256']);\n qEntries.push(['X-Amz-Credential', `${args.accessKeyId}/${credScope}`]);\n qEntries.push(['X-Amz-Date', amzDate]);\n qEntries.push(['X-Amz-Expires', '3600']);\n qEntries.push(['X-Amz-SignedHeaders', signedHeadersList]);\n if (args.sessionToken) qEntries.push(['X-Amz-Security-Token', args.sessionToken]);\n }\n qEntries.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));\n const canonicalQS = qEntries\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&');\n\n const preserveSlashes = args.preservePathSlashes ?? args.service === 's3';\n const canonicalUri = canonicalizePath(parsed.pathname, preserveSlashes);\n const canonicalReq = [\n args.method.toUpperCase(),\n canonicalUri,\n canonicalQS,\n canonicalHeaders,\n signedHeadersList,\n payloadHash,\n ].join('\\n');\n\n const stringToSign = ['AWS4-HMAC-SHA256', amzDate, credScope, await sha256Hex(canonicalReq)].join(\n '\\n',\n );\n\n // Derive the per-request signing key by chaining HMACs.\n const kDate = await hmacSha256(enc.encode(`AWS4${args.secretAccessKey}`), dateStamp);\n const kRegion = await hmacSha256(kDate, args.region);\n const kService = await hmacSha256(kRegion, args.service);\n const kSigning = await hmacSha256(kService, 'aws4_request');\n const signature = bufToHex(await hmacSha256(kSigning, stringToSign));\n\n const nextHeaders = { ...args.headers };\n let nextUrl = args.url;\n\n if (isQuery) {\n qEntries.push(['X-Amz-Signature', signature]);\n qEntries.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));\n const qs = qEntries\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&');\n nextUrl = `${parsed.origin}${parsed.pathname}?${qs}${parsed.hash}`;\n } else {\n // Lowercase header names match AWS SDK / boto3 / common request\n // tooling conventions. HTTP headers are case-insensitive, but staying\n // consistent simplifies test assertions and downstream string-match\n // header inspection.\n nextHeaders['x-amz-date'] = amzDate;\n nextHeaders['x-amz-content-sha256'] = payloadHash;\n if (args.sessionToken) nextHeaders['x-amz-security-token'] = args.sessionToken;\n nextHeaders['Authorization'] =\n `AWS4-HMAC-SHA256 Credential=${args.accessKeyId}/${credScope}, SignedHeaders=${signedHeadersList}, Signature=${signature}`;\n }\n return { url: nextUrl, headers: nextHeaders };\n}\n\n// ── helpers ────────────────────────────────────────────────────────────────────\n\nasync function computeBodyHash(body: SigV4Body): Promise<string> {\n if (body == null) return EMPTY_PAYLOAD_HASH;\n if (typeof body === 'string') return sha256HexBuf(new TextEncoder().encode(body));\n if (body instanceof ArrayBuffer) return sha256HexBuf(new Uint8Array(body));\n if (body instanceof Uint8Array) return sha256HexBuf(body);\n if (typeof Blob !== 'undefined' && body instanceof Blob) {\n const ab = await body.arrayBuffer();\n return sha256HexBuf(new Uint8Array(ab));\n }\n if (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams) {\n return sha256HexBuf(new TextEncoder().encode(body.toString()));\n }\n // FormData / ReadableStream — can't be deterministically hashed\n // pre-fetch (FormData boundary is generated by fetch, ReadableStream\n // is one-shot). AWS accepts UNSIGNED-PAYLOAD in these cases as long\n // as the magic constant is in the signed headers.\n return 'UNSIGNED-PAYLOAD';\n}\n\n/**\n * Canonicalize a request path per AWS SigV4 §6 (Task 1).\n *\n * Rules (general services):\n * - Empty path becomes \"/\".\n * - Each segment is URI-encoded with the unreserved set per RFC 3986\n * (preserving `/`, encoding everything else). Components ALREADY\n * percent-encoded by the user pass through — we don't double-encode.\n * - \".\" segments are removed; \"..\" segments collapse the previous\n * segment.\n * - Leading slash is preserved; trailing slash is preserved.\n * - Empty segments (consecutive `/`) are collapsed to one.\n *\n * S3 mode (`preserveSlashes: true`):\n * - Empty segments are PRESERVED — S3 treats `bucket/foo//bar` as a\n * distinct object key from `bucket/foo/bar`. The canonical URI must\n * match the raw path bytes for the signature to validate against\n * what S3 actually stored.\n * - \".\" and \"..\" segments are still encoded as path components\n * (S3 doesn't apply RFC 3986 dot-segment removal).\n */\nfunction canonicalizePath(path: string, preserveSlashes: boolean): string {\n if (!path || path === '') return '/';\n if (preserveSlashes) {\n // Encode each segment but keep all separators verbatim (including\n // empty segments from `//`).\n return path\n .split('/')\n .map((seg) => awsUriEncode(seg, /* preserveSlash */ false))\n .join('/');\n }\n const isAbsolute = path.startsWith('/');\n const trailingSlash = path.endsWith('/') && path !== '/';\n const segments: string[] = [];\n for (const seg of path.split('/')) {\n if (seg === '' || seg === '.') continue;\n if (seg === '..') {\n segments.pop();\n continue;\n }\n segments.push(awsUriEncode(seg, /* preserveSlash */ false));\n }\n let out = (isAbsolute ? '/' : '') + segments.join('/');\n if (trailingSlash && !out.endsWith('/')) out += '/';\n if (!out) out = '/';\n return out;\n}\n\n/**\n * URI-encode per AWS SigV4 spec — same as RFC 3986 unreserved set\n * (`A-Z a-z 0-9 - _ . ~`). `encodeURIComponent` covers most of this but\n * leaves `!*'()` un-encoded, so we patch those.\n */\nfunction awsUriEncode(s: string, preserveSlash: boolean): string {\n let encoded = encodeURIComponent(s).replace(\n /[!'()*]/g,\n (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`,\n );\n if (preserveSlash) encoded = encoded.replace(/%2F/g, '/');\n return encoded;\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n return sha256HexBuf(new TextEncoder().encode(input));\n}\n\nasync function sha256HexBuf(bytes: Uint8Array): Promise<string> {\n const buf = bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength,\n ) as ArrayBuffer;\n const hash = await crypto.subtle.digest('SHA-256', buf);\n return bufToHex(hash);\n}\n\nasync function hmacSha256(key: Uint8Array | ArrayBuffer, message: string): Promise<ArrayBuffer> {\n const keyBuf =\n key instanceof Uint8Array\n ? (key.buffer.slice(key.byteOffset, key.byteOffset + key.byteLength) as ArrayBuffer)\n : key;\n const cryptoKey = await crypto.subtle.importKey(\n 'raw',\n keyBuf,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n const msg = new TextEncoder().encode(message);\n const msgBuf = msg.buffer.slice(msg.byteOffset, msg.byteOffset + msg.byteLength);\n return crypto.subtle.sign('HMAC', cryptoKey, msgBuf);\n}\n\nfunction bufToHex(buf: ArrayBuffer): string {\n return Array.from(new Uint8Array(buf), (b) => b.toString(16).padStart(2, '0')).join('');\n}\n","/**\n * Hawk authentication scheme (https://github.com/mozilla/hawk).\n *\n * Hawk uses an HMAC of a normalized request string keyed by a shared\n * secret. Unlike Digest / NTLM there's no challenge round-trip — every\n * request is signed independently using:\n *\n * normalized = \"hawk.1.header\\n{ts}\\n{nonce}\\n{METHOD}\\n{path?query}\\n\n * {host-lc}\\n{port}\\n{payload-hash}\\n{ext}\\n\"\n * mac = base64(HMAC-{algorithm}(secret, normalized))\n *\n * We default to SHA-256 (the modern recommendation); SHA-1 is supported\n * for interop with legacy Hawk servers. Body-payload hashing is a future\n * extension — for now we always pass an empty payload-hash, which the\n * server must verify by setting `Hash: \"\"` or skipping payload validation.\n */\n\nexport interface HawkSignArgs {\n method: string;\n /**\n * Full request URL — we extract scheme/host/port/path/query from this\n * since the normalized string needs lowercase host + numeric port.\n */\n url: string;\n hawkId: string;\n hawkKey: string;\n algorithm?: 'sha256' | 'sha1';\n /**\n * Override for the timestamp (Unix seconds). Tests pass a fixed value;\n * production callers either omit (use `Date.now()`) or apply\n * `timestampOffset` to compensate for client-server clock skew.\n */\n timestamp?: number;\n /**\n * 8 hex chars by default; tests pass a fixed value. The server tracks\n * (id, ts, nonce) tuples to detect replay, so even fixed tests are\n * one-shot.\n */\n nonce?: string;\n /** Optional `app=` and `dlg=` directives for delegated requests. */\n app?: string;\n delegation?: string;\n /** Optional `ext=` directive for application-specific data. */\n ext?: string;\n /**\n * Optional payload + content-type for body-binding. When present, the\n * normalized request string includes a `hash=BASE64(H(payload))` line\n * AND we emit a `hash=\"…\"` directive in the Authorization header.\n * Servers configured with body-binding reject requests that lack this;\n * leaving the field undefined preserves the prior behavior (server\n * must accept body-less signing).\n */\n payload?: {\n body: string | ArrayBuffer | Uint8Array;\n contentType: string;\n };\n}\n\nexport async function buildHawkAuthHeader(args: HawkSignArgs): Promise<string> {\n let parsed: URL;\n try {\n parsed = new URL(args.url);\n } catch {\n throw new Error(`Hawk: invalid URL: ${args.url}`);\n }\n\n const port = parsed.port || (parsed.protocol === 'https:' ? '443' : '80');\n const ts = String(args.timestamp ?? Math.floor(Date.now() / 1000));\n const nonce = args.nonce ?? randomHex(4);\n const ext = args.ext ?? '';\n const resource = `${parsed.pathname}${parsed.search}${parsed.hash}`;\n const algorithm = args.algorithm ?? 'sha256';\n const subtleAlgo = algorithm === 'sha1' ? 'SHA-1' : 'SHA-256';\n\n // Optional payload-hash per Hawk spec §3.2.5: H = base64(SHA(\n // \"hawk.1.payload\\n\" + content-type + \"\\n\" + body + \"\\n\"\n // )). Body-bound servers verify the request body matches by re-running\n // the same hash. When `args.payload` is undefined we emit an empty\n // payload-hash line — the server must be configured to accept that.\n let payloadHash = '';\n if (args.payload) {\n const normalizedContentType =\n args.payload.contentType.split(';')[0]?.trim().toLowerCase() ?? '';\n const bodyText = bodyToString(args.payload.body);\n const payloadString = `hawk.1.payload\\n${normalizedContentType}\\n${bodyText}\\n`;\n const payloadBytes = new TextEncoder().encode(payloadString);\n const hashBuf = await crypto.subtle.digest(\n subtleAlgo,\n payloadBytes.buffer.slice(\n payloadBytes.byteOffset,\n payloadBytes.byteOffset + payloadBytes.byteLength,\n ),\n );\n payloadHash = bufToBase64(hashBuf);\n }\n\n // RFC-style normalized string. Every component is on its own line and\n // a trailing newline closes the buffer (required by the spec).\n //\n // Phase 11 fix: when `app` / `dlg` are present they MUST be appended to\n // the normalized string AFTER `ext`, per Hawk v1 §3.2.1. Without this,\n // a man-in-the-middle can forge or strip the `app=` / `dlg=` directives\n // without invalidating the MAC — and servers that route by `app=` (most\n // multi-tenant Hawk deployments) trust whatever the attacker substituted.\n // We always emit the lines when the directives are present; servers\n // that don't use them ignore the extra components anyway because they\n // re-derive the normalized string from the same directives.\n const normalizedLines: string[] = [\n 'hawk.1.header',\n ts,\n nonce,\n args.method.toUpperCase(),\n resource,\n parsed.hostname.toLowerCase(),\n port,\n payloadHash,\n ext,\n ];\n if (args.app !== undefined && args.app !== '') {\n normalizedLines.push(args.app);\n // The spec requires `dlg` only after `app` — we emit an empty line\n // for `dlg` when absent so the field positions remain spec-compliant.\n normalizedLines.push(args.delegation ?? '');\n } else if (args.delegation) {\n // `dlg` without `app` is non-standard — Hawk's spec doesn't define a\n // canonical normalized form for that combination. Most servers reject\n // it, but for interop with implementations that allow it we emit an\n // empty `app` line followed by `dlg`. This is best-effort.\n normalizedLines.push('');\n normalizedLines.push(args.delegation);\n }\n const normalized = normalizedLines.join('\\n') + '\\n';\n\n const macBuf = await hmacSign(subtleAlgo, args.hawkKey, normalized);\n const mac = bufToBase64(macBuf);\n\n // Field order follows the Hawk reference impl: id, ts, nonce, optional\n // hash / ext / app / dlg directives, mac last. RFC doesn't mandate the\n // order but every interop server we've tested parses in this sequence\n // and a few brittle ones reject anything else.\n const parts = [\n `id=\"${escapeQuoted(args.hawkId)}\"`,\n `ts=\"${ts}\"`,\n `nonce=\"${escapeQuoted(nonce)}\"`,\n ];\n if (payloadHash) parts.push(`hash=\"${payloadHash}\"`);\n if (ext) parts.push(`ext=\"${escapeQuoted(ext)}\"`);\n if (args.app) parts.push(`app=\"${escapeQuoted(args.app)}\"`);\n if (args.delegation) parts.push(`dlg=\"${escapeQuoted(args.delegation)}\"`);\n parts.push(`mac=\"${mac}\"`);\n return `Hawk ${parts.join(', ')}`;\n}\n\nasync function hmacSign(\n algorithm: 'SHA-256' | 'SHA-1',\n key: string,\n message: string,\n): Promise<ArrayBuffer> {\n const enc = new TextEncoder();\n const keyBytes = enc.encode(key);\n const cryptoKey = await crypto.subtle.importKey(\n 'raw',\n keyBytes.buffer.slice(keyBytes.byteOffset, keyBytes.byteOffset + keyBytes.byteLength),\n { name: 'HMAC', hash: algorithm },\n false,\n ['sign'],\n );\n const msgBytes = enc.encode(message);\n return crypto.subtle.sign(\n 'HMAC',\n cryptoKey,\n msgBytes.buffer.slice(msgBytes.byteOffset, msgBytes.byteOffset + msgBytes.byteLength),\n );\n}\n\nfunction bufToBase64(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n let s = '';\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);\n return btoa(s);\n}\n\nfunction randomHex(byteLen: number): string {\n const buf = new Uint8Array(byteLen);\n crypto.getRandomValues(buf);\n return Array.from(buf, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nfunction escapeQuoted(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n\n/**\n * Coerce a payload body shape into a UTF-8 string for hashing. Hawk's\n * payload-hash spec (§3.2.5) is byte-oriented; we treat strings as UTF-8\n * and ArrayBuffer / Uint8Array as raw bytes decoded with the default\n * decoder. Other body shapes (FormData / ReadableStream) are not\n * supported here — callers should serialize to a string before signing.\n */\nfunction bodyToString(body: string | ArrayBuffer | Uint8Array): string {\n if (typeof body === 'string') return body;\n const bytes = body instanceof Uint8Array ? body : new Uint8Array(body);\n return new TextDecoder().decode(bytes);\n}\n","/**\n * JWT (RFC 7519) signing — Bearer token generation.\n *\n * This is the \"self-signed assertion\" variant of `jwt-bearer` auth: the\n * client mints a JWT signed with its own key, then sends it as\n * `Authorization: Bearer <jwt>`. Different from OAuth2 JWT-bearer flow\n * (RFC 7523) where the JWT is exchanged at a token endpoint for an\n * access token — that flow goes through `auth/oauth2/grants.ts` and\n * uses this signer to mint the assertion.\n *\n * Algorithms:\n * - HS256 / HS384 / HS512: HMAC with shared secret (most common).\n * - RS256 / RS384 / RS512: RSA-SHA — caller supplies a private key\n * in PKCS#8 PEM. Imported via `crypto.subtle.importKey`.\n * - ES256 / ES384 / ES512: ECDSA-P256/384/521 — same PKCS#8 path.\n * - **none**: refused. Always reject `alg: \"none\"` regardless of caller\n * intent — RFC 8725 §3.1 calls this out as the canonical JWT mistake.\n *\n * The header `typ` defaults to `\"JWT\"`; callers can override via the\n * `additionalHeaders` arg to set e.g. `kid` for key discovery.\n */\n\nexport type JwtAlgorithm =\n | 'HS256'\n | 'HS384'\n | 'HS512'\n | 'RS256'\n | 'RS384'\n | 'RS512'\n | 'PS256'\n | 'PS384'\n | 'PS512'\n | 'ES256'\n | 'ES384'\n | 'ES512'\n | 'EdDSA';\n\nexport interface JwtSignArgs {\n /** Signing algorithm — must match the key material in `secretOrKey`. */\n algorithm: JwtAlgorithm;\n /**\n * Shared secret for HMAC (HS256/384/512) or PEM-encoded PKCS#8\n * private key for RSA / ECDSA. For HMAC, plain UTF-8 strings work;\n * for asymmetric, the PEM must include the BEGIN/END markers.\n */\n secretOrKey: string;\n /** Token claims. `iat` is auto-added when missing; `exp` is left to the caller. */\n payload: Record<string, unknown>;\n /** Extra header fields beyond `alg` and `typ` (e.g. `kid`, `cty`). */\n additionalHeaders?: Record<string, unknown>;\n}\n\nconst HMAC_ALGS: Readonly<Record<string, string>> = {\n HS256: 'SHA-256',\n HS384: 'SHA-384',\n HS512: 'SHA-512',\n};\n\nconst RSA_ALGS: Readonly<Record<string, string>> = {\n RS256: 'SHA-256',\n RS384: 'SHA-384',\n RS512: 'SHA-512',\n};\n\n/**\n * RSA-PSS (RFC 7518 §3.5). Salt length per spec is `hLen` — the hash\n * function's digest length in bytes (32 for SHA-256, 48 for SHA-384,\n * 64 for SHA-512). WebCrypto's RSA-PSS expects the salt length in bytes.\n */\nconst RSA_PSS_ALGS: Readonly<Record<string, { hash: string; saltLength: number }>> = {\n PS256: { hash: 'SHA-256', saltLength: 32 },\n PS384: { hash: 'SHA-384', saltLength: 48 },\n PS512: { hash: 'SHA-512', saltLength: 64 },\n};\n\nconst EC_CURVES: Readonly<Record<string, { hash: string; namedCurve: string }>> = {\n ES256: { hash: 'SHA-256', namedCurve: 'P-256' },\n ES384: { hash: 'SHA-384', namedCurve: 'P-384' },\n ES512: { hash: 'SHA-512', namedCurve: 'P-521' },\n};\n\nexport async function signJwt(args: JwtSignArgs): Promise<string> {\n const header = {\n alg: args.algorithm,\n typ: 'JWT',\n ...(args.additionalHeaders ?? {}),\n };\n // RFC 8725 §3.1 — never honor `alg: \"none\"`. We reject it even if\n // someone explicitly passes it; the only safe behavior is to refuse.\n if ((args.algorithm as string).toLowerCase() === 'none') {\n throw new Error('JWT alg \"none\" is not supported (RFC 8725 §3.1)');\n }\n const payload: Record<string, unknown> = { iat: Math.floor(Date.now() / 1000), ...args.payload };\n\n const headerSegment = base64UrlEncode(new TextEncoder().encode(JSON.stringify(header)));\n const payloadSegment = base64UrlEncode(new TextEncoder().encode(JSON.stringify(payload)));\n const signingInput = `${headerSegment}.${payloadSegment}`;\n\n const sigBytes = await sign(args.algorithm, args.secretOrKey, signingInput);\n return `${signingInput}.${base64UrlEncode(new Uint8Array(sigBytes))}`;\n}\n\nasync function sign(\n algorithm: JwtAlgorithm,\n secretOrKey: string,\n signingInput: string,\n): Promise<ArrayBuffer> {\n const enc = new TextEncoder();\n const data = enc.encode(signingInput);\n const dataBuf = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);\n\n if (algorithm in HMAC_ALGS) {\n const keyBytes = enc.encode(secretOrKey);\n const keyBuf = keyBytes.buffer.slice(\n keyBytes.byteOffset,\n keyBytes.byteOffset + keyBytes.byteLength,\n );\n const key = await crypto.subtle.importKey(\n 'raw',\n keyBuf,\n { name: 'HMAC', hash: HMAC_ALGS[algorithm] },\n false,\n ['sign'],\n );\n return crypto.subtle.sign('HMAC', key, dataBuf);\n }\n\n if (algorithm in RSA_ALGS) {\n const key = await importPkcs8(secretOrKey, {\n name: 'RSASSA-PKCS1-v1_5',\n hash: RSA_ALGS[algorithm],\n });\n return crypto.subtle.sign('RSASSA-PKCS1-v1_5', key, dataBuf);\n }\n\n if (algorithm in RSA_PSS_ALGS) {\n const { hash, saltLength } = RSA_PSS_ALGS[algorithm];\n const key = await importPkcs8(secretOrKey, { name: 'RSA-PSS', hash });\n return crypto.subtle.sign({ name: 'RSA-PSS', saltLength }, key, dataBuf);\n }\n\n if (algorithm === 'EdDSA') {\n // RFC 8037 — JWS with Ed25519. WebCrypto's Ed25519 support landed\n // in modern browsers (Chrome 113+, Firefox 130+, Safari 17+) and\n // Node 22+. The PKCS#8 PEM the user pastes must encode an Ed25519\n // private key (OID 1.3.101.112).\n const key = await importPkcs8(secretOrKey, { name: 'Ed25519' });\n return crypto.subtle.sign('Ed25519', key, dataBuf);\n }\n\n if (algorithm in EC_CURVES) {\n const { hash, namedCurve } = EC_CURVES[algorithm];\n const key = await importPkcs8(secretOrKey, { name: 'ECDSA', namedCurve });\n // ECDSA over JWT is JWS-style: r || s, fixed-length (curve-specific).\n const sig = await crypto.subtle.sign({ name: 'ECDSA', hash }, key, dataBuf);\n return sig;\n }\n\n throw new Error(`JWT algorithm not supported: ${algorithm}`);\n}\n\nasync function importPkcs8(\n pem: string,\n algorithm: { name: string; hash?: string; namedCurve?: string },\n): Promise<CryptoKey> {\n // Encrypted PKCS#8 PEMs (`BEGIN ENCRYPTED PRIVATE KEY`) wrap the\n // private key with a passphrase-derived key — WebCrypto can't import\n // them. Surface a clear actionable error rather than confusing the\n // user with a base64-decode failure on the encrypted blob.\n if (/-----BEGIN ENCRYPTED [A-Z ]+-----/.test(pem)) {\n throw new Error(\n 'JWT: encrypted PEM keys are not supported. Decrypt with `openssl pkcs8 -in key.pem -out plain.pem` and paste the unencrypted form.',\n );\n }\n // RSA PKCS#1 PEMs (`BEGIN RSA PRIVATE KEY`) are NOT PKCS#8 — WebCrypto\n // requires PKCS#8. Catch the common confusion explicitly.\n if (/-----BEGIN RSA PRIVATE KEY-----/.test(pem)) {\n throw new Error(\n 'JWT: PKCS#1 RSA PEM (`BEGIN RSA PRIVATE KEY`) is not supported. Convert with `openssl pkcs8 -topk8 -in key.pem -out pkcs8.pem -nocrypt`.',\n );\n }\n // Extract the BEGIN/END envelope's contents — everything outside\n // those markers (Bag Attributes, comments, blank lines) is ignored.\n // If the markers are missing, fall back to \"use the whole input\"\n // so a user pasting raw base64 still works.\n //\n // Manual indexOf scan instead of `/-----BEGIN […]-----([\\s\\S]*?)-----END […]-----/`\n // so CodeQL's polynomial-regex detector doesn't flag the lazy `[\\s\\S]*?`\n // when the PEM contains multiple BEGIN markers.\n const body = extractPemBody(pem);\n const stripped = body.replace(/\\s+/g, '');\n if (!stripped) {\n throw new Error('JWT: PEM key is empty after stripping headers/whitespace');\n }\n let der: Uint8Array;\n try {\n const raw = atob(stripped);\n der = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) der[i] = raw.charCodeAt(i);\n } catch {\n throw new Error('JWT: PEM key is not valid base64');\n }\n return crypto.subtle.importKey(\n 'pkcs8',\n der.buffer.slice(der.byteOffset, der.byteOffset + der.byteLength) as ArrayBuffer,\n algorithm,\n false,\n ['sign'],\n );\n}\n\n/**\n * Find the body between the first `-----BEGIN …-----` line and the next\n * `-----END …-----` line. Falls back to the whole input when either marker\n * is missing. Hand-written O(n) scan; avoids regex-based extraction so\n * CodeQL doesn't flag a polynomial pattern.\n */\nfunction extractPemBody(pem: string): string {\n const BEGIN = '-----BEGIN ';\n const END = '-----END ';\n const FENCE = '-----';\n const beginAt = pem.indexOf(BEGIN);\n if (beginAt === -1) return pem;\n const beginHeaderEnd = pem.indexOf(FENCE, beginAt + BEGIN.length);\n if (beginHeaderEnd === -1) return pem;\n const bodyStart = beginHeaderEnd + FENCE.length;\n const endAt = pem.indexOf(END, bodyStart);\n if (endAt === -1) return pem;\n return pem.slice(bodyStart, endAt);\n}\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let s = '';\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);\n return btoa(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n","/**\n * Legacy MD5 / MD4 + HMAC-MD5 — required for Digest auth (RFC 7616) and\n * NTLMv2 (RFC 4178). Both are obsolete cryptographically but mandated\n * for interop with servers that still use them. Implemented inline so\n * we don't take a runtime dep for two specific protocols, and so the\n * web bundle stays browser-safe (WebCrypto doesn't expose MD5/MD4).\n *\n * Internal module — not exported from the package barrel. Importers go\n * through `digest.ts` / `ntlm.ts`. Algorithms ported verbatim from the\n * v1 reference (`studio_old/packages/core/src/request/executionEngine.ts`)\n * which was tested against RFC vectors in production.\n *\n * Do NOT use these for any new use case — they're leaks of legacy\n * protocols, kept here for compatibility only.\n */\n\n// ── MD5 (RFC 1321) ─────────────────────────────────────────────────────────────\nexport function md5(str: string): string {\n function safeAdd(x: number, y: number) {\n const lsw = (x & 0xffff) + (y & 0xffff);\n const msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n return (msw << 16) | (lsw & 0xffff);\n }\n const rol = (n: number, c: number) => (n << c) | (n >>> (32 - c));\n const cmn = (q: number, a: number, b: number, x: number, s: number, t: number) =>\n safeAdd(rol(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);\n const ff = (a: number, b: number, c: number, d: number, x: number, s: number, t: number) =>\n cmn((b & c) | (~b & d), a, b, x, s, t);\n const gg = (a: number, b: number, c: number, d: number, x: number, s: number, t: number) =>\n cmn((b & d) | (c & ~d), a, b, x, s, t);\n const hh = (a: number, b: number, c: number, d: number, x: number, s: number, t: number) =>\n cmn(b ^ c ^ d, a, b, x, s, t);\n const ii = (a: number, b: number, c: number, d: number, x: number, s: number, t: number) =>\n cmn(c ^ (b | ~d), a, b, x, s, t);\n\n const n = str.length;\n const nblk = ((n + 8) >> 6) + 1;\n const blks = new Array<number>(nblk * 16).fill(0);\n for (let i = 0; i < n; i++) {\n blks[i >> 2] = (blks[i >> 2] ?? 0) | (str.charCodeAt(i) << ((i % 4) * 8));\n }\n blks[n >> 2] = (blks[n >> 2] ?? 0) | (0x80 << ((n % 4) * 8));\n blks[nblk * 16 - 2] = n * 8;\n\n let a = 0x67452301,\n b = 0xefcdab89,\n c = 0x98badcfe,\n d = 0x10325476;\n for (let i = 0; i < blks.length; i += 16) {\n const [oa, ob, oc, od] = [a, b, c, d];\n const x = blks.slice(i, i + 16);\n a = ff(a, b, c, d, x[0], 7, 0xd76aa478);\n d = ff(d, a, b, c, x[1], 12, 0xe8c7b756);\n c = ff(c, d, a, b, x[2], 17, 0x242070db);\n b = ff(b, c, d, a, x[3], 22, 0xc1bdceee);\n a = ff(a, b, c, d, x[4], 7, 0xf57c0faf);\n d = ff(d, a, b, c, x[5], 12, 0x4787c62a);\n c = ff(c, d, a, b, x[6], 17, 0xa8304613);\n b = ff(b, c, d, a, x[7], 22, 0xfd469501);\n a = ff(a, b, c, d, x[8], 7, 0x698098d8);\n d = ff(d, a, b, c, x[9], 12, 0x8b44f7af);\n c = ff(c, d, a, b, x[10], 17, 0xffff5bb1);\n b = ff(b, c, d, a, x[11], 22, 0x895cd7be);\n a = ff(a, b, c, d, x[12], 7, 0x6b901122);\n d = ff(d, a, b, c, x[13], 12, 0xfd987193);\n c = ff(c, d, a, b, x[14], 17, 0xa679438e);\n b = ff(b, c, d, a, x[15], 22, 0x49b40821);\n a = gg(a, b, c, d, x[1], 5, 0xf61e2562);\n d = gg(d, a, b, c, x[6], 9, 0xc040b340);\n c = gg(c, d, a, b, x[11], 14, 0x265e5a51);\n b = gg(b, c, d, a, x[0], 20, 0xe9b6c7aa);\n a = gg(a, b, c, d, x[5], 5, 0xd62f105d);\n d = gg(d, a, b, c, x[10], 9, 0x02441453);\n c = gg(c, d, a, b, x[15], 14, 0xd8a1e681);\n b = gg(b, c, d, a, x[4], 20, 0xe7d3fbc8);\n a = gg(a, b, c, d, x[9], 5, 0x21e1cde6);\n d = gg(d, a, b, c, x[14], 9, 0xc33707d6);\n c = gg(c, d, a, b, x[3], 14, 0xf4d50d87);\n b = gg(b, c, d, a, x[8], 20, 0x455a14ed);\n a = gg(a, b, c, d, x[13], 5, 0xa9e3e905);\n d = gg(d, a, b, c, x[2], 9, 0xfcefa3f8);\n c = gg(c, d, a, b, x[7], 14, 0x676f02d9);\n b = gg(b, c, d, a, x[12], 20, 0x8d2a4c8a);\n a = hh(a, b, c, d, x[5], 4, 0xfffa3942);\n d = hh(d, a, b, c, x[8], 11, 0x8771f681);\n c = hh(c, d, a, b, x[11], 16, 0x6d9d6122);\n b = hh(b, c, d, a, x[14], 23, 0xfde5380c);\n a = hh(a, b, c, d, x[1], 4, 0xa4beea44);\n d = hh(d, a, b, c, x[4], 11, 0x4bdecfa9);\n c = hh(c, d, a, b, x[7], 16, 0xf6bb4b60);\n b = hh(b, c, d, a, x[10], 23, 0xbebfbc70);\n a = hh(a, b, c, d, x[13], 4, 0x289b7ec6);\n d = hh(d, a, b, c, x[0], 11, 0xeaa127fa);\n c = hh(c, d, a, b, x[3], 16, 0xd4ef3085);\n b = hh(b, c, d, a, x[6], 23, 0x04881d05);\n a = hh(a, b, c, d, x[9], 4, 0xd9d4d039);\n d = hh(d, a, b, c, x[12], 11, 0xe6db99e5);\n c = hh(c, d, a, b, x[15], 16, 0x1fa27cf8);\n b = hh(b, c, d, a, x[2], 23, 0xc4ac5665);\n a = ii(a, b, c, d, x[0], 6, 0xf4292244);\n d = ii(d, a, b, c, x[7], 10, 0x432aff97);\n c = ii(c, d, a, b, x[14], 15, 0xab9423a7);\n b = ii(b, c, d, a, x[5], 21, 0xfc93a039);\n a = ii(a, b, c, d, x[12], 6, 0x655b59c3);\n d = ii(d, a, b, c, x[3], 10, 0x8f0ccc92);\n c = ii(c, d, a, b, x[10], 15, 0xffeff47d);\n b = ii(b, c, d, a, x[1], 21, 0x85845dd1);\n a = ii(a, b, c, d, x[8], 6, 0x6fa87e4f);\n d = ii(d, a, b, c, x[15], 10, 0xfe2ce6e0);\n c = ii(c, d, a, b, x[6], 15, 0xa3014314);\n b = ii(b, c, d, a, x[13], 21, 0x4e0811a1);\n a = ii(a, b, c, d, x[4], 6, 0xf7537e82);\n d = ii(d, a, b, c, x[11], 10, 0xbd3af235);\n c = ii(c, d, a, b, x[2], 15, 0x2ad7d2bb);\n b = ii(b, c, d, a, x[9], 21, 0xeb86d391);\n a = safeAdd(a, oa);\n b = safeAdd(b, ob);\n c = safeAdd(c, oc);\n d = safeAdd(d, od);\n }\n const hex = (v: number) =>\n [v, v >>> 8, v >>> 16, v >>> 24].map((n) => (n & 0xff).toString(16).padStart(2, '0')).join('');\n return hex(a) + hex(b) + hex(c) + hex(d);\n}\n\n// ── MD4 (RFC 1320) — used for NTLM NT-hash ─────────────────────────────────────\nexport function md4(input: Uint8Array): Uint8Array {\n const rol = (x: number, n: number): number => ((x << n) | (x >>> (32 - n))) >>> 0;\n const add = (x: number, y: number): number => (x + y) >>> 0;\n const F = (x: number, y: number, z: number): number => ((x & y) | (~x & z)) >>> 0;\n const G = (x: number, y: number, z: number): number => ((x & y) | (x & z) | (y & z)) >>> 0;\n const H = (x: number, y: number, z: number): number => (x ^ y ^ z) >>> 0;\n const padLen = (56 - ((input.length + 1) % 64) + 64) % 64;\n const buf = new Uint8Array(input.length + 1 + padLen + 8);\n buf.set(input);\n buf[input.length] = 0x80;\n const v = new DataView(buf.buffer);\n v.setUint32(buf.length - 8, (input.length * 8) >>> 0, true);\n v.setUint32(buf.length - 4, Math.floor(input.length / 0x20000000), true);\n let a = 0x67452301,\n b = 0xefcdab89,\n c = 0x98badcfe,\n d = 0x10325476;\n for (let i = 0; i < buf.length; i += 64) {\n const x = Array.from({ length: 16 }, (_, k) => v.getUint32(i + k * 4, true));\n const [sa, sb, sc, sd] = [a, b, c, d];\n a = rol(add(add(a, F(b, c, d)), x[0]), 3);\n d = rol(add(add(d, F(a, b, c)), x[1]), 7);\n c = rol(add(add(c, F(d, a, b)), x[2]), 11);\n b = rol(add(add(b, F(c, d, a)), x[3]), 19);\n a = rol(add(add(a, F(b, c, d)), x[4]), 3);\n d = rol(add(add(d, F(a, b, c)), x[5]), 7);\n c = rol(add(add(c, F(d, a, b)), x[6]), 11);\n b = rol(add(add(b, F(c, d, a)), x[7]), 19);\n a = rol(add(add(a, F(b, c, d)), x[8]), 3);\n d = rol(add(add(d, F(a, b, c)), x[9]), 7);\n c = rol(add(add(c, F(d, a, b)), x[10]), 11);\n b = rol(add(add(b, F(c, d, a)), x[11]), 19);\n a = rol(add(add(a, F(b, c, d)), x[12]), 3);\n d = rol(add(add(d, F(a, b, c)), x[13]), 7);\n c = rol(add(add(c, F(d, a, b)), x[14]), 11);\n b = rol(add(add(b, F(c, d, a)), x[15]), 19);\n const C2 = 0x5a827999;\n a = rol(add(add(add(a, G(b, c, d)), x[0]), C2), 3);\n d = rol(add(add(add(d, G(a, b, c)), x[4]), C2), 5);\n c = rol(add(add(add(c, G(d, a, b)), x[8]), C2), 9);\n b = rol(add(add(add(b, G(c, d, a)), x[12]), C2), 13);\n a = rol(add(add(add(a, G(b, c, d)), x[1]), C2), 3);\n d = rol(add(add(add(d, G(a, b, c)), x[5]), C2), 5);\n c = rol(add(add(add(c, G(d, a, b)), x[9]), C2), 9);\n b = rol(add(add(add(b, G(c, d, a)), x[13]), C2), 13);\n a = rol(add(add(add(a, G(b, c, d)), x[2]), C2), 3);\n d = rol(add(add(add(d, G(a, b, c)), x[6]), C2), 5);\n c = rol(add(add(add(c, G(d, a, b)), x[10]), C2), 9);\n b = rol(add(add(add(b, G(c, d, a)), x[14]), C2), 13);\n a = rol(add(add(add(a, G(b, c, d)), x[3]), C2), 3);\n d = rol(add(add(add(d, G(a, b, c)), x[7]), C2), 5);\n c = rol(add(add(add(c, G(d, a, b)), x[11]), C2), 9);\n b = rol(add(add(add(b, G(c, d, a)), x[15]), C2), 13);\n const C3 = 0x6ed9eba1;\n a = rol(add(add(add(a, H(b, c, d)), x[0]), C3), 3);\n d = rol(add(add(add(d, H(a, b, c)), x[8]), C3), 9);\n c = rol(add(add(add(c, H(d, a, b)), x[4]), C3), 11);\n b = rol(add(add(add(b, H(c, d, a)), x[12]), C3), 15);\n a = rol(add(add(add(a, H(b, c, d)), x[2]), C3), 3);\n d = rol(add(add(add(d, H(a, b, c)), x[10]), C3), 9);\n c = rol(add(add(add(c, H(d, a, b)), x[6]), C3), 11);\n b = rol(add(add(add(b, H(c, d, a)), x[14]), C3), 15);\n a = rol(add(add(add(a, H(b, c, d)), x[1]), C3), 3);\n d = rol(add(add(add(d, H(a, b, c)), x[9]), C3), 9);\n c = rol(add(add(add(c, H(d, a, b)), x[5]), C3), 11);\n b = rol(add(add(add(b, H(c, d, a)), x[13]), C3), 15);\n a = rol(add(add(add(a, H(b, c, d)), x[3]), C3), 3);\n d = rol(add(add(add(d, H(a, b, c)), x[11]), C3), 9);\n c = rol(add(add(add(c, H(d, a, b)), x[7]), C3), 11);\n b = rol(add(add(add(b, H(c, d, a)), x[15]), C3), 15);\n a = add(a, sa);\n b = add(b, sb);\n c = add(c, sc);\n d = add(d, sd);\n }\n const out = new Uint8Array(16);\n const ov = new DataView(out.buffer);\n ov.setUint32(0, a, true);\n ov.setUint32(4, b, true);\n ov.setUint32(8, c, true);\n ov.setUint32(12, d, true);\n return out;\n}\n\n/** MD5 over arbitrary bytes — used as the inner hash for HMAC-MD5 (NTLMv2). */\nexport function md5Bytes(input: Uint8Array): Uint8Array {\n const str = Array.from(input, (b) => String.fromCharCode(b)).join('');\n const hex = md5(str);\n const out = new Uint8Array(16);\n for (let i = 0; i < 16; i++) out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n return out;\n}\n\n/** HMAC-MD5 (RFC 2104) — used by NTLMv2 hash chain. */\nexport function hmacMd5(key: Uint8Array, data: Uint8Array): Uint8Array {\n const B = 64;\n const k = key.length > B ? md5Bytes(key) : key;\n const kPad = new Uint8Array(B);\n kPad.set(k);\n const ipad = kPad.map((b) => b ^ 0x36);\n const opad = kPad.map((b) => b ^ 0x5c);\n const inner = new Uint8Array(B + data.length);\n inner.set(ipad);\n inner.set(data, B);\n const outer = new Uint8Array(B + 16);\n outer.set(opad);\n outer.set(md5Bytes(inner), B);\n return md5Bytes(outer);\n}\n","import { md4, hmacMd5 } from './_legacyHashes';\n\n/**\n * NTLM (Windows Integrated Authentication) — NTLMv2 only.\n *\n * NTLM is a stateful 3-way handshake over a single TCP connection:\n * 1. Client sends Type-1 Negotiate message (advertise flags, domain, workstation)\n * 2. Server responds 401 with `WWW-Authenticate: NTLM <base64 Type-2>` carrying\n * the server challenge (8 random bytes) + target info.\n * 3. Client sends Type-3 Authenticate message containing the NTProofStr\n * (HMAC-MD5 of `serverChallenge + blob` using the NTLMv2 hash).\n *\n * The handshake itself lives in `executeRequest` because it requires\n * connection affinity (NTLM auth is tied to the underlying TCP socket).\n * This module owns only the message construction + parsing.\n *\n * Implementation ported from the v1 reference; algorithm validated\n * against the Microsoft `[MS-NLMP]` worked example.\n */\n\n/** NTLM v2 negotiate flags — UNICODE | OEM | REQUEST_TARGET | NTLM. */\nconst NTLM_FLAGS = 0x00000207;\n\n/**\n * Build the raw Type-1 Negotiate message bytes. The engine retains these\n * for MIC computation in the Type-3 step ([MS-NLMP] §3.1.5.1.2 hashes\n * `Type1 || Type2 || Type3`), then base64-encodes for the wire.\n */\nexport function buildNtlmType1NegotiateBytes(domain: string, workstation: string): Uint8Array {\n const domainBytes = utf16le(domain.toUpperCase());\n const wsBytes = utf16le(workstation.toUpperCase());\n const buf = new Uint8Array(32 + domainBytes.length + wsBytes.length);\n buf.set([78, 84, 76, 77, 83, 83, 80, 0]); // \"NTLMSSP\\0\"\n writeLE32(buf, 8, 1); // type = 1\n writeLE32(buf, 12, NTLM_FLAGS);\n writeLE16(buf, 16, domainBytes.length);\n writeLE16(buf, 18, domainBytes.length);\n writeLE32(buf, 20, 32 + wsBytes.length);\n writeLE16(buf, 24, wsBytes.length);\n writeLE16(buf, 26, wsBytes.length);\n writeLE32(buf, 28, 32);\n buf.set(wsBytes, 32);\n buf.set(domainBytes, 32 + wsBytes.length);\n return buf;\n}\n\n/**\n * Build the Type-1 Negotiate message, base64-encoded for use as\n * `Authorization: NTLM <value>`. Sent by the client to advertise its\n * capabilities and trigger the server's challenge response.\n */\nexport function buildNtlmType1Negotiate(domain: string, workstation: string): string {\n return base64Encode(buildNtlmType1NegotiateBytes(domain, workstation));\n}\n\n/**\n * base64-decode an NTLM message into raw bytes. Exposed for engines that\n * recover Type-1 / Type-2 byte buffers from previously-sent / received\n * `Authorization` / `WWW-Authenticate` headers (the MIC computation\n * needs the raw bytes, not the base64 form).\n */\nexport function decodeNtlmBase64(value: string): Uint8Array {\n return base64Decode(value);\n}\n\nexport interface NtlmType2Challenge {\n /** 8-byte server challenge nonce. */\n challenge: Uint8Array;\n /**\n * Variable-length AV_PAIR target-info block. Echoed verbatim in the\n * Type-3 NTLMv2 blob so the server can verify the response.\n */\n targetInfo: Uint8Array;\n /**\n * Original raw bytes of the entire Type-2 message — required when the\n * caller wants to compute a MIC over `Type1 || Type2 || Type3` per\n * [MS-NLMP] §3.1.5.1.2. Set automatically by `parseNtlmType2Challenge`.\n * Optional so callers constructing the challenge literal in tests can\n * skip it; MIC computation needs the parser-produced form.\n */\n rawBytes?: Uint8Array;\n}\n\n/**\n * Parse the Type-2 Challenge message extracted from the server's\n * `WWW-Authenticate: NTLM <base64>` reply. Returns the server challenge\n * + target info bytes that feed into Type-3 construction.\n */\nexport function parseNtlmType2Challenge(base64: string): NtlmType2Challenge {\n const bytes = base64Decode(base64);\n if (bytes.length < 48) {\n throw new Error('NTLM Type-2 message too short');\n }\n const v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const challenge = bytes.slice(24, 32);\n // Target info security buffer at offset 40 (length, max-length, offset).\n const tiLen = v.getUint16(40, true);\n const tiOff = v.getUint32(44, true);\n const targetInfo =\n tiLen > 0 && tiOff + tiLen <= bytes.length\n ? bytes.slice(tiOff, tiOff + tiLen)\n : new Uint8Array(0);\n return { challenge, targetInfo, rawBytes: bytes };\n}\n\nexport interface BuildNtlmType3Args {\n username: string;\n password: string;\n domain: string;\n workstation: string;\n challenge: NtlmType2Challenge;\n /** Override for the 8-byte client challenge — tests pass a fixed value. */\n clientChallenge?: Uint8Array;\n /** Override for the timestamp (ms since epoch) — tests pass a fixed value. */\n timestampMs?: number;\n /**\n * Raw bytes of the Type-1 Negotiate message we sent in the previous\n * round. When BOTH this and `type2Message` are provided, we emit a\n * 16-byte MIC at offset 72 of the Type-3 message and set MsvAvFlags\n * bit 0x2 in the AV_PAIR target info — required by hardened Win Server\n * 2019+ AD configurations per [MS-NLMP] §3.1.5.1.2. When either is\n * absent we preserve the legacy \"no MIC\" layout for back-compat with\n * older servers that reject the longer header.\n */\n type1Message?: Uint8Array;\n /** Raw bytes of the Type-2 Challenge message — paired with `type1Message`. */\n type2Message?: Uint8Array;\n}\n\n/**\n * Build the Type-3 Authenticate message (NTLMv2). Computes the NTLMv2\n * hash, the NTProofStr (HMAC-MD5 over server-challenge + blob), and\n * packs everything into the binary message format. Returns base64 for\n * use as `Authorization: NTLM <value>`.\n */\nexport function buildNtlmType3Authenticate(args: BuildNtlmType3Args): string {\n const { username, password, domain, workstation, challenge } = args;\n\n // NT hash = MD4(UTF-16LE(password)).\n const ntHash = md4(utf16le(password));\n\n // NTLMv2 hash = HMAC-MD5(NT hash, UTF-16LE(upper(username) + domain)).\n const identity = concat(utf16le(username.toUpperCase()), utf16le(domain));\n const ntlmV2Hash = hmacMd5(ntHash, identity);\n\n const clientChallenge = args.clientChallenge ?? randomBytes(8);\n\n // NTLMv2 blob — RFC 4178 / [MS-NLMP] §2.2.2.7.\n const ts = BigInt(args.timestampMs ?? Date.now()) * 10000n + 116444736000000000n;\n const tsBytes = new Uint8Array(8);\n for (let i = 0; i < 8; i++) tsBytes[i] = Number((ts >> BigInt(i * 8)) & 0xffn);\n\n // [MS-NLMP] §3.1.5.1.2 — when the server's target info doesn't already\n // include MsvAvTimestamp, we MUST inject one before the EOL marker so\n // hardened Win Server 2019+ AD configs accept the response. Servers\n // that already include their own timestamp take precedence, so we\n // only inject when absent. AvId 7 = MsvAvTimestamp (8-byte FILETIME).\n const withTimestamp = ensureTimestampAvPair(challenge.targetInfo, tsBytes);\n // When MIC is enabled (caller passed Type-1 + Type-2 bytes), we also\n // set MsvAvFlags bit 0x2 — [MS-NLMP] §2.2.2.1 — to advertise that this\n // Type-3 carries a MIC. AvId 6 = MsvAvFlags (4-byte little-endian).\n const emitMic = !!(args.type1Message && args.type2Message);\n const enrichedTargetInfo = emitMic\n ? ensureMsvAvFlagsBit(withTimestamp, 0x00000002)\n : withTimestamp;\n\n const blob = new Uint8Array(28 + enrichedTargetInfo.length);\n blob[0] = 1;\n blob[1] = 1; // signature\n // bytes 2-7 are reserved zero (already set by Uint8Array default).\n for (let i = 0; i < 8; i++) blob[8 + i] = tsBytes[i]!;\n for (let i = 0; i < 8; i++) blob[16 + i] = clientChallenge[i]!;\n // bytes 24-27 reserved zero.\n blob.set(enrichedTargetInfo, 28);\n\n // NTProofStr = HMAC-MD5(NTLMv2 hash, serverChallenge + blob).\n const proofInput = concat(challenge.challenge, blob);\n const ntProofStr = hmacMd5(ntlmV2Hash, proofInput);\n\n // NT response = NTProofStr || blob.\n const ntResponse = concat(ntProofStr, blob);\n\n const domainBytes = utf16le(domain);\n const userBytes = utf16le(username);\n const wsBytes = utf16le(workstation);\n const lmResponse = new Uint8Array(24); // empty LM response — NTLMv2 doesn't use LM.\n\n // Layout offsets — fixed header is 72 bytes (Signature..Version) without\n // MIC, 88 bytes when MIC is present (Version followed by 16-byte MIC).\n // [MS-NLMP] §2.2.1.3.\n const baseOff = emitMic ? 88 : 72;\n const domainOff = baseOff;\n const userOff = domainOff + domainBytes.length;\n const wsOff = userOff + userBytes.length;\n const lmOff = wsOff + wsBytes.length;\n const ntOff = lmOff + lmResponse.length;\n const totalLen = ntOff + ntResponse.length;\n\n const msg = new Uint8Array(totalLen);\n msg.set([78, 84, 76, 77, 83, 83, 80, 0]); // \"NTLMSSP\\0\"\n writeLE32(msg, 8, 3); // type = 3\n\n writeSecurityBuffer(msg, 12, lmResponse.length, lmOff);\n writeSecurityBuffer(msg, 20, ntResponse.length, ntOff);\n writeSecurityBuffer(msg, 28, domainBytes.length, domainOff);\n writeSecurityBuffer(msg, 36, userBytes.length, userOff);\n writeSecurityBuffer(msg, 44, wsBytes.length, wsOff);\n writeLE32(msg, 60, NTLM_FLAGS);\n\n msg.set(domainBytes, domainOff);\n msg.set(userBytes, userOff);\n msg.set(wsBytes, wsOff);\n msg.set(lmResponse, lmOff);\n msg.set(ntResponse, ntOff);\n\n // MIC computation — [MS-NLMP] §3.1.5.1.2. Done last so the message body\n // is finalized before we hash it. The MIC field at offset 72-87 is\n // already zeroed (Uint8Array default), which is exactly what the spec\n // requires during hashing. We patch the computed MIC in place.\n //\n // For NTLMv2 without NEGOTIATE_KEY_EXCH (our flag set 0x00000207):\n // SessionBaseKey = HMAC-MD5(NTLMv2Hash, NTProofStr)\n // KeyExchangeKey = SessionBaseKey\n // ExportedSessionKey = KeyExchangeKey (no RC4 wrap — NEGOTIATE_KEY_EXCH absent)\n // MIC = HMAC-MD5(ExportedSessionKey, Type1 || Type2 || Type3-zero-MIC)\n if (emitMic) {\n const sessionBaseKey = hmacMd5(ntlmV2Hash, ntProofStr);\n const concatenated = concat(concat(args.type1Message!, args.type2Message!), msg);\n const mic = hmacMd5(sessionBaseKey, concatenated);\n for (let i = 0; i < 16; i++) msg[72 + i] = mic[i]!;\n }\n\n return base64Encode(msg);\n}\n\n// ── helpers ────────────────────────────────────────────────────────────────────\n\n/**\n * AV_PAIR walker — scans `targetInfo` for an existing MsvAvTimestamp\n * (AvId 7). If found, leaves it alone (the server's value wins). If\n * absent, splices in `[AvId=7][AvLen=8][8 bytes timestamp]` immediately\n * before the EOL pair (AvId 0, AvLen 0).\n */\nfunction ensureTimestampAvPair(targetInfo: Uint8Array, tsBytes: Uint8Array): Uint8Array {\n // Empty target info — emit timestamp + EOL.\n if (targetInfo.length === 0) {\n const out = new Uint8Array(12 + 4);\n writeLE16(out, 0, 7); // AvId = MsvAvTimestamp\n writeLE16(out, 2, 8); // AvLen = 8\n for (let i = 0; i < 8; i++) out[4 + i] = tsBytes[i]!;\n // EOL pair at the tail.\n return out;\n }\n\n // Walk pairs to look for AvId=7. Each pair: 2-byte AvId, 2-byte AvLen,\n // AvLen bytes of value. AvId 0 (EOL) terminates.\n let cursor = 0;\n let eolOffset = -1;\n let hasTimestamp = false;\n while (cursor + 4 <= targetInfo.length) {\n const avId = targetInfo[cursor] | (targetInfo[cursor + 1] << 8);\n const avLen = targetInfo[cursor + 2] | (targetInfo[cursor + 3] << 8);\n if (avId === 0) {\n eolOffset = cursor;\n break;\n }\n if (avId === 7) hasTimestamp = true;\n cursor += 4 + avLen;\n }\n\n if (hasTimestamp) return targetInfo;\n if (eolOffset < 0) {\n // Malformed — no EOL. Append timestamp + EOL conservatively.\n const out = new Uint8Array(targetInfo.length + 12 + 4);\n out.set(targetInfo);\n writeLE16(out, targetInfo.length, 7);\n writeLE16(out, targetInfo.length + 2, 8);\n for (let i = 0; i < 8; i++) out[targetInfo.length + 4 + i] = tsBytes[i]!;\n return out;\n }\n\n // Splice timestamp pair in before the EOL.\n const out = new Uint8Array(targetInfo.length + 12);\n out.set(targetInfo.subarray(0, eolOffset));\n writeLE16(out, eolOffset, 7);\n writeLE16(out, eolOffset + 2, 8);\n for (let i = 0; i < 8; i++) out[eolOffset + 4 + i] = tsBytes[i]!;\n out.set(targetInfo.subarray(eolOffset), eolOffset + 12);\n return out;\n}\n\n/**\n * AV_PAIR walker — sets bits in the MsvAvFlags pair (AvId 6, AvLen 4).\n * Inserts a fresh pair before the EOL marker if absent. Used to advertise\n * MIC presence (`bit 0x2`) per [MS-NLMP] §2.2.2.1.\n *\n * Assumes `targetInfo` ends with the EOL pair (AvId=0, AvLen=0). Callers\n * pass timestamp-enriched target info — `ensureTimestampAvPair` already\n * enforces a well-formed EOL.\n */\nfunction ensureMsvAvFlagsBit(targetInfo: Uint8Array, bit: number): Uint8Array {\n let cursor = 0;\n let eolOffset = -1;\n let flagsOffset = -1;\n while (cursor + 4 <= targetInfo.length) {\n const avId = targetInfo[cursor] | (targetInfo[cursor + 1] << 8);\n const avLen = targetInfo[cursor + 2] | (targetInfo[cursor + 3] << 8);\n if (avId === 0) {\n eolOffset = cursor;\n break;\n }\n if (avId === 6 && avLen === 4) flagsOffset = cursor + 4;\n cursor += 4 + avLen;\n }\n\n if (flagsOffset >= 0) {\n // OR our bit into the existing 4-byte LE flags value.\n const existing =\n targetInfo[flagsOffset] |\n (targetInfo[flagsOffset + 1] << 8) |\n (targetInfo[flagsOffset + 2] << 16) |\n (targetInfo[flagsOffset + 3] << 24);\n const merged = (existing | bit) >>> 0;\n const out = new Uint8Array(targetInfo);\n writeLE32(out, flagsOffset, merged);\n return out;\n }\n\n // No MsvAvFlags pair — splice a new one before EOL (or append if EOL\n // somehow absent). 8 bytes total: 2-byte AvId, 2-byte AvLen, 4-byte value.\n if (eolOffset < 0) {\n const out = new Uint8Array(targetInfo.length + 8 + 4);\n out.set(targetInfo);\n writeLE16(out, targetInfo.length, 6);\n writeLE16(out, targetInfo.length + 2, 4);\n writeLE32(out, targetInfo.length + 4, bit);\n return out;\n }\n const out = new Uint8Array(targetInfo.length + 8);\n out.set(targetInfo.subarray(0, eolOffset));\n writeLE16(out, eolOffset, 6);\n writeLE16(out, eolOffset + 2, 4);\n writeLE32(out, eolOffset + 4, bit);\n out.set(targetInfo.subarray(eolOffset), eolOffset + 8);\n return out;\n}\n\nfunction utf16le(str: string): Uint8Array {\n const buf = new Uint8Array(str.length * 2);\n for (let i = 0; i < str.length; i++) {\n const c = str.charCodeAt(i);\n buf[i * 2] = c & 0xff;\n buf[i * 2 + 1] = (c >> 8) & 0xff;\n }\n return buf;\n}\n\nfunction writeLE32(buf: Uint8Array, off: number, v: number): void {\n buf[off] = v & 0xff;\n buf[off + 1] = (v >> 8) & 0xff;\n buf[off + 2] = (v >> 16) & 0xff;\n buf[off + 3] = (v >> 24) & 0xff;\n}\n\nfunction writeLE16(buf: Uint8Array, off: number, v: number): void {\n buf[off] = v & 0xff;\n buf[off + 1] = (v >> 8) & 0xff;\n}\n\n/** Length, allocated-length, offset triple per `[MS-NLMP]` security buffer layout. */\nfunction writeSecurityBuffer(\n buf: Uint8Array,\n off: number,\n length: number,\n payloadOff: number,\n): void {\n writeLE16(buf, off, length);\n writeLE16(buf, off + 2, length);\n writeLE32(buf, off + 4, payloadOff);\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a);\n out.set(b, a.length);\n return out;\n}\n\nfunction randomBytes(n: number): Uint8Array {\n const out = new Uint8Array(n);\n crypto.getRandomValues(out);\n return out;\n}\n\nfunction base64Encode(bytes: Uint8Array): string {\n let s = '';\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);\n return btoa(s);\n}\n\nfunction base64Decode(s: string): Uint8Array {\n const raw = atob(s);\n const out = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) out[i] = raw.charCodeAt(i);\n return out;\n}\n","/**\n * The single token-endpoint client used by every OAuth2 grant.\n *\n * RFC 6749 §4 endpoints accept `application/x-www-form-urlencoded` with\n * `grant_type` plus grant-specific fields. Client credentials may go in\n * the Authorization header (`client_secret_basic`) or the body\n * (`client_secret_post`); some IdPs only accept one or the other, so the\n * caller picks via `clientAuthMethod`.\n *\n * On success the IdP returns:\n *\n * { access_token, token_type, expires_in?, refresh_token?, scope? }\n *\n * On failure (RFC 6749 §5.2):\n *\n * { error, error_description?, error_uri? } with HTTP 400/401\n *\n * We surface the failure as an Error whose `.message` includes both\n * `error` and `error_description` so the UI can show \"invalid_grant: bad\n * code\" without parsing JSON itself. The structured response is also\n * attached to `.cause` for callers who need to dispatch on `error_code`\n * (e.g. device flow's `authorization_pending` / `slow_down` cases).\n */\n\nexport interface OAuth2TokenResponse {\n accessToken: string;\n tokenType: string;\n expiresIn?: number;\n refreshToken?: string;\n scope?: string;\n /** Captured raw response — useful for OpenID Connect `id_token` etc. */\n raw: Record<string, unknown>;\n}\n\nexport interface OAuth2ErrorResponse {\n error: string;\n errorDescription?: string;\n errorUri?: string;\n /** HTTP status the IdP returned (400, 401, 403, …). */\n status: number;\n /** Captured raw body — useful for diagnostics and grant-specific dispatch. */\n raw: Record<string, unknown>;\n}\n\n/**\n * Pre-signed client-assertion JWT for `private_key_jwt` client\n * authentication (RFC 7521 §4.2 / RFC 7523 §2.2). The auth tab signs\n * the assertion locally via `signJwt` and passes it here; we add the\n * required `client_assertion` + `client_assertion_type` body fields.\n * Used in place of `clientSecret` — the IdP verifies the assertion\n * against the registered public key.\n */\nexport interface ClientAssertion {\n /** The signed JWT (header.payload.signature) — output of `signJwt`. */\n jwt: string;\n /** RFC 7523 mandates this exact value. Other types exist (e.g. SAML2) but aren't used here. */\n type?: string;\n}\n\nexport interface FetchOAuth2TokenArgs {\n tokenUrl: string;\n /**\n * Grant-specific body fields. `grant_type` MUST be set by the caller —\n * this helper doesn't infer it. Value type is `URLSearchParams` so the\n * caller controls the exact wire format and can reuse the same body\n * for retry / refresh paths.\n */\n body: URLSearchParams;\n clientId: string;\n /**\n * Confidential clients only. Public clients (PKCE in a SPA) leave this\n * undefined — the IdP recognizes the client by id alone.\n */\n clientSecret?: string;\n /**\n * Where to put the client credentials. `header` = HTTP Basic with\n * `id:secret`. `body` = `client_id` + `client_secret` URL-form fields.\n * Defaults to `header` (the RFC's preferred method).\n *\n * Ignored when `clientAssertion` is set — assertion takes precedence\n * because mixing both is a misconfiguration the server will reject.\n */\n clientAuthMethod?: 'header' | 'body';\n /**\n * Optional `private_key_jwt` style client authentication. When set,\n * the body carries `client_assertion` + `client_assertion_type` and\n * `clientSecret` is NOT sent. Used by Azure AD, GCP, and any IdP\n * that prefers signed assertions over shared secrets.\n */\n clientAssertion?: ClientAssertion;\n /** Optional extra parameters appended to the body — IdP-specific knobs. */\n extraParams?: Record<string, string>;\n /** Override fetch for tests / desktop bridge. */\n fetchImpl?: typeof fetch;\n /** Per-call abort. Composed with the global request signal upstream. */\n signal?: AbortSignal;\n}\n\n/**\n * OAuth2 token endpoint failure. The structured `errorBody` carries the\n * error code (`invalid_grant`, `authorization_pending`, etc) plus\n * `error_description` / `error_uri` and the HTTP status — callers can\n * dispatch on `errorBody.error` for grant-specific behavior (device\n * flow's `authorization_pending` / `slow_down`, refresh re-auth, etc).\n *\n * Naming note: we deliberately don't shadow the standard `Error.cause`\n * field. Callers using TypeScript can still use `instanceof` + the\n * `errorBody` accessor; callers reading the `cause` property get the\n * standard \"what was the original exception\" semantics.\n */\nexport class OAuth2TokenError extends Error {\n readonly errorBody: OAuth2ErrorResponse;\n constructor(errorBody: OAuth2ErrorResponse) {\n const desc = errorBody.errorDescription ? `: ${errorBody.errorDescription}` : '';\n super(`${errorBody.error}${desc}`);\n this.name = 'OAuth2TokenError';\n this.errorBody = errorBody;\n }\n}\n\nexport async function fetchOAuth2Token(args: FetchOAuth2TokenArgs): Promise<OAuth2TokenResponse> {\n const fetchImpl = args.fetchImpl ?? globalThis.fetch;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n };\n const method = args.clientAuthMethod ?? 'header';\n\n // Clone body so caller's URLSearchParams stays unchanged after we\n // append `client_id`/`client_secret`/extraParams.\n const body = new URLSearchParams(args.body.toString());\n\n if (args.clientAssertion) {\n // private_key_jwt: signed assertion takes precedence over secret.\n // RFC 7521 §4.2 mandates both fields in the body.\n body.set('client_id', args.clientId);\n body.set(\n 'client_assertion_type',\n args.clientAssertion.type ?? 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',\n );\n body.set('client_assertion', args.clientAssertion.jwt);\n } else if (method === 'header' && args.clientSecret) {\n headers['Authorization'] = `Basic ${base64(`${args.clientId}:${args.clientSecret}`)}`;\n // Public clients still need to identify themselves in body — RFC 6749 §3.2.1.\n body.set('client_id', args.clientId);\n } else {\n body.set('client_id', args.clientId);\n if (args.clientSecret) body.set('client_secret', args.clientSecret);\n }\n\n if (args.extraParams) {\n for (const [k, v] of Object.entries(args.extraParams)) body.set(k, v);\n }\n\n const tokenUrlParsed = new URL(args.tokenUrl);\n if (tokenUrlParsed.protocol !== 'https:' && tokenUrlParsed.protocol !== 'http:') {\n throw new Error(`Token URL must use HTTP or HTTPS, got ${tokenUrlParsed.protocol}`);\n }\n\n const response = await fetchImpl(args.tokenUrl, {\n method: 'POST',\n headers,\n body: body.toString(),\n signal: args.signal,\n });\n\n let raw: Record<string, unknown> = {};\n let parsedJson = false;\n try {\n raw = (await response.json()) as Record<string, unknown>;\n parsedJson = true;\n } catch {\n parsedJson = false;\n }\n\n // RFC 6750 §3 — the IdP MAY return errors via `WWW-Authenticate: Bearer\n // error=\"...\"` with no JSON body. Parse that as a fallback so users\n // don't see \"invalid_response: non-JSON\" when the IdP is well-behaved\n // by spec but didn't include a JSON body.\n if (!parsedJson && !response.ok) {\n const wwwAuth = response.headers.get('www-authenticate');\n const parsed = wwwAuth ? parseBearerAuthError(wwwAuth) : null;\n if (parsed) {\n throw new OAuth2TokenError({\n error: parsed.error,\n errorDescription: parsed.errorDescription,\n errorUri: parsed.errorUri,\n status: response.status,\n raw: { ...parsed },\n });\n }\n throw new OAuth2TokenError({\n error: 'invalid_response',\n errorDescription: `IdP returned non-JSON ${response.status} response`,\n status: response.status,\n raw,\n });\n }\n if (!parsedJson) {\n throw new OAuth2TokenError({\n error: 'invalid_response',\n errorDescription: 'IdP returned non-JSON success response',\n status: response.status,\n raw,\n });\n }\n\n if (!response.ok || typeof raw['error'] === 'string') {\n throw new OAuth2TokenError({\n error: typeof raw['error'] === 'string' ? raw['error'] : 'invalid_grant',\n errorDescription:\n typeof raw['error_description'] === 'string' ? raw['error_description'] : undefined,\n errorUri: typeof raw['error_uri'] === 'string' ? raw['error_uri'] : undefined,\n status: response.status,\n raw,\n });\n }\n\n if (typeof raw['access_token'] !== 'string') {\n throw new OAuth2TokenError({\n error: 'invalid_response',\n errorDescription: 'Token endpoint returned no access_token',\n status: response.status,\n raw,\n });\n }\n\n return {\n accessToken: raw['access_token'],\n tokenType: typeof raw['token_type'] === 'string' ? raw['token_type'] : 'Bearer',\n expiresIn: typeof raw['expires_in'] === 'number' ? raw['expires_in'] : undefined,\n refreshToken: typeof raw['refresh_token'] === 'string' ? raw['refresh_token'] : undefined,\n scope: typeof raw['scope'] === 'string' ? raw['scope'] : undefined,\n raw,\n };\n}\n\n/**\n * Extract `error=\"...\"` / `error_description=\"...\"` / `error_uri=\"...\"`\n * directives from a `WWW-Authenticate: Bearer ...` header value. Returns\n * null when the header isn't a Bearer challenge or carries no error\n * directive — callers fall back to the generic invalid_response error.\n */\nfunction parseBearerAuthError(\n wwwAuth: string,\n): { error: string; errorDescription?: string; errorUri?: string } | null {\n if (!/^bearer\\b/i.test(wwwAuth.trim())) return null;\n const directives: Record<string, string> = {};\n const re = /(\\w+)\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|([^\\s,]+))/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(wwwAuth)) !== null) {\n directives[m[1].toLowerCase()] =\n m[2] !== undefined ? m[2].replace(/\\\\(.)/g, '$1') : (m[3] ?? '');\n }\n if (!directives['error']) return null;\n return {\n error: directives['error'],\n errorDescription: directives['error_description'],\n errorUri: directives['error_uri'],\n };\n}\n\nfunction base64(text: string): string {\n // UTF-8 → base64. `btoa` is byte-oriented (Latin-1), so we have to encode\n // the string to bytes first. The previous `btoa(unescape(encodeURIComponent(text)))`\n // hack relied on the deprecated `unescape` global; this path uses\n // `TextEncoder` instead, which is the standard since ES2017 and is\n // present in every runtime we ship into.\n if (typeof btoa === 'function' && typeof TextEncoder !== 'undefined') {\n const bytes = new TextEncoder().encode(text);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n return btoa(binary);\n }\n // Same Node/Buffer fallback shape as applyAuth — kept defensive.\n const buf = (\n globalThis as unknown as {\n Buffer?: { from: (data: string, encoding?: string) => { toString: (e: string) => string } };\n }\n ).Buffer;\n if (!buf) throw new Error('Neither btoa nor Buffer is available in this runtime');\n return buf.from(text, 'utf8').toString('base64');\n}\n","/**\n * Per-grant OAuth2 runners. Each function POSTs to the token endpoint\n * with the body shape RFC 6749 specifies for that grant, and returns a\n * normalized `OAuth2TokenResponse`. Callbacks (browser redirects to\n * `redirect_uri?code=...`) and device-code polling intervals are the\n * caller's job — these runners ONLY exchange.\n *\n * Refresh handling is in `refreshToken()` rather than per-grant: the\n * refresh-token grant is identical regardless of which grant minted the\n * original token.\n */\n\nimport { OAuth2TokenError, fetchOAuth2Token, type OAuth2TokenResponse } from './fetchToken';\n\ntype ClientAuthMethod = 'header' | 'body';\ntype FetchImpl = typeof fetch;\n\nexport interface ClientCredentialsArgs {\n tokenUrl: string;\n clientId: string;\n clientSecret: string;\n scope?: string;\n clientAuthMethod?: ClientAuthMethod;\n extraParams?: Record<string, string>;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n}\n\n/** RFC 6749 §4.4 — machine-to-machine, no user. */\nexport async function runClientCredentials(\n args: ClientCredentialsArgs,\n): Promise<OAuth2TokenResponse> {\n const body = new URLSearchParams({ grant_type: 'client_credentials' });\n if (args.scope?.trim()) body.set('scope', args.scope.trim());\n return fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: args.clientAuthMethod ?? 'header',\n extraParams: args.extraParams,\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n}\n\nexport interface RopcArgs {\n tokenUrl: string;\n clientId: string;\n clientSecret?: string;\n username: string;\n password: string;\n scope?: string;\n clientAuthMethod?: ClientAuthMethod;\n extraParams?: Record<string, string>;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n}\n\n/**\n * RFC 6749 §4.3 — Resource Owner Password Credentials. Marked DEPRECATED\n * in OAuth 2.1; we support it because legacy IdPs still require it for\n * specific testing / migration scenarios. The auth panel surfaces a\n * warning banner about the deprecation.\n */\nexport async function runRopc(args: RopcArgs): Promise<OAuth2TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'password',\n username: args.username,\n password: args.password,\n });\n if (args.scope?.trim()) body.set('scope', args.scope.trim());\n return fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: args.clientAuthMethod ?? 'header',\n extraParams: args.extraParams,\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n}\n\nexport interface AuthCodeExchangeArgs {\n tokenUrl: string;\n clientId: string;\n clientSecret?: string;\n /** The `code` value the IdP redirected back with. */\n code: string;\n /** Must match the redirect_uri sent in the initial /authorize request. */\n redirectUri: string;\n clientAuthMethod?: ClientAuthMethod;\n extraParams?: Record<string, string>;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n}\n\n/** RFC 6749 §4.1 — Authorization Code grant. */\nexport async function exchangeAuthCode(args: AuthCodeExchangeArgs): Promise<OAuth2TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code: args.code,\n redirect_uri: args.redirectUri,\n });\n return fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: args.clientAuthMethod ?? 'header',\n extraParams: args.extraParams,\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n}\n\nexport interface PkceExchangeArgs extends AuthCodeExchangeArgs {\n /** The verifier we generated when constructing the auth URL. */\n codeVerifier: string;\n}\n\n/**\n * RFC 7636 — Authorization Code with PKCE. Same body as plain auth-code\n * plus `code_verifier`. clientSecret is optional (public clients omit it).\n */\nexport async function exchangePkce(args: PkceExchangeArgs): Promise<OAuth2TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code: args.code,\n redirect_uri: args.redirectUri,\n code_verifier: args.codeVerifier,\n });\n return fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: args.clientAuthMethod ?? 'header',\n extraParams: args.extraParams,\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n}\n\nexport interface DeviceAuthorizationResponse {\n deviceCode: string;\n userCode: string;\n verificationUri: string;\n /** Optional convenience URI with the user_code already embedded. */\n verificationUriComplete?: string;\n /** Seconds the device should poll the token endpoint. */\n interval: number;\n /** Seconds before deviceCode expires. */\n expiresIn: number;\n raw: Record<string, unknown>;\n}\n\nexport interface DeviceAuthorizationArgs {\n deviceAuthorizationUrl: string;\n clientId: string;\n clientSecret?: string;\n scope?: string;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n}\n\n/**\n * RFC 8628 §3.1 — Device Authorization Request. Returns the device_code\n * + user_code so the caller can show the user_code + verification URI to\n * a human, then poll the token endpoint with `pollDeviceFlow`.\n */\nexport async function requestDeviceAuthorization(\n args: DeviceAuthorizationArgs,\n): Promise<DeviceAuthorizationResponse> {\n const fetchImpl = args.fetchImpl ?? globalThis.fetch;\n const body = new URLSearchParams({ client_id: args.clientId });\n if (args.scope?.trim()) body.set('scope', args.scope.trim());\n if (args.clientSecret) body.set('client_secret', args.clientSecret);\n\n const response = await fetchImpl(args.deviceAuthorizationUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n },\n body: body.toString(),\n signal: args.signal,\n });\n\n let raw: Record<string, unknown> = {};\n try {\n raw = (await response.json()) as Record<string, unknown>;\n } catch {\n throw new OAuth2TokenError({\n error: 'invalid_response',\n errorDescription: 'Device authorization endpoint returned non-JSON',\n status: response.status,\n raw,\n });\n }\n\n if (!response.ok || typeof raw['error'] === 'string') {\n throw new OAuth2TokenError({\n error: typeof raw['error'] === 'string' ? raw['error'] : 'invalid_response',\n errorDescription:\n typeof raw['error_description'] === 'string' ? raw['error_description'] : undefined,\n status: response.status,\n raw,\n });\n }\n\n if (typeof raw['device_code'] !== 'string' || typeof raw['user_code'] !== 'string') {\n throw new OAuth2TokenError({\n error: 'invalid_response',\n errorDescription: 'Device authorization response missing device_code or user_code',\n status: response.status,\n raw,\n });\n }\n\n return {\n deviceCode: raw['device_code'],\n userCode: raw['user_code'],\n verificationUri:\n (raw['verification_uri'] as string | undefined) ??\n (raw['verification_url'] as string | undefined) ??\n '',\n verificationUriComplete:\n typeof raw['verification_uri_complete'] === 'string'\n ? raw['verification_uri_complete']\n : undefined,\n interval: typeof raw['interval'] === 'number' ? raw['interval'] : 5,\n expiresIn: typeof raw['expires_in'] === 'number' ? raw['expires_in'] : 600,\n raw,\n };\n}\n\nexport interface PollDeviceFlowArgs {\n tokenUrl: string;\n clientId: string;\n clientSecret?: string;\n deviceCode: string;\n /** Initial poll interval in seconds. Bumped to `interval + 5` on `slow_down`. */\n intervalSeconds: number;\n /** Max overall wait. When elapsed, throws an `OAuth2TokenError` of error=\"expired_token\". */\n maxWaitMs?: number;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n /**\n * Optional progress callback fired on every poll cycle. UI uses this\n * to update the visible \"still waiting…\" indicator and tick down the\n * remaining time. Receives `{ pollCount, elapsedMs, lastError }` —\n * `lastError` is set when the IdP responded `slow_down` so the UI\n * can hint the user to wait.\n */\n onPoll?: (info: { pollCount: number; elapsedMs: number; lastError?: string }) => void;\n /** Test seam — overrides `setTimeout` / `Date.now` for fake clocks. */\n scheduler?: {\n sleep: (ms: number) => Promise<void>;\n now: () => number;\n };\n}\n\nconst DEVICE_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code';\n\n/**\n * RFC 8628 §3.4 — poll the token endpoint until the user authorizes the\n * device, then return the token. Honors `authorization_pending` /\n * `slow_down` / `access_denied` / `expired_token`.\n */\nexport async function pollDeviceFlow(args: PollDeviceFlowArgs): Promise<OAuth2TokenResponse> {\n const sleep = args.scheduler?.sleep ?? ((ms: number) => new Promise((r) => setTimeout(r, ms)));\n const now = args.scheduler?.now ?? (() => Date.now());\n const start = now();\n let interval = args.intervalSeconds;\n let pollCount = 0;\n\n while (true) {\n pollCount++;\n args.onPoll?.({ pollCount, elapsedMs: now() - start });\n if (args.signal?.aborted) {\n throw new OAuth2TokenError({\n error: 'aborted',\n errorDescription: 'Device flow polling was aborted',\n status: 0,\n raw: {},\n });\n }\n if (args.maxWaitMs !== undefined && now() - start > args.maxWaitMs) {\n throw new OAuth2TokenError({\n error: 'expired_token',\n errorDescription: 'Device flow exceeded maxWaitMs',\n status: 0,\n raw: {},\n });\n }\n\n const body = new URLSearchParams({\n grant_type: DEVICE_GRANT_TYPE,\n device_code: args.deviceCode,\n });\n try {\n return await fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: 'body',\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n } catch (err) {\n if (!(err instanceof OAuth2TokenError)) throw err;\n if (err.errorBody.error === 'authorization_pending') {\n await sleep(interval * 1000);\n continue;\n }\n if (err.errorBody.error === 'slow_down') {\n interval += 5;\n await sleep(interval * 1000);\n continue;\n }\n // expired_token / access_denied / invalid_grant / etc — terminal.\n throw err;\n }\n }\n}\n\nexport interface RefreshTokenArgs {\n tokenUrl: string;\n clientId: string;\n clientSecret?: string;\n refreshToken: string;\n /** Some IdPs require the original scope on refresh. */\n scope?: string;\n clientAuthMethod?: ClientAuthMethod;\n extraParams?: Record<string, string>;\n fetchImpl?: FetchImpl;\n signal?: AbortSignal;\n}\n\n/**\n * RFC 6749 §6 — refresh a previously obtained token. Identical wire\n * shape regardless of the grant that minted the original token; the\n * caller decides when to call it (typical heuristic: when\n * `expiresAt < now + 60s`).\n */\nexport async function refreshToken(args: RefreshTokenArgs): Promise<OAuth2TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: args.refreshToken,\n });\n if (args.scope?.trim()) body.set('scope', args.scope.trim());\n return fetchOAuth2Token({\n tokenUrl: args.tokenUrl,\n body,\n clientId: args.clientId,\n clientSecret: args.clientSecret,\n clientAuthMethod: args.clientAuthMethod ?? 'header',\n extraParams: args.extraParams,\n fetchImpl: args.fetchImpl,\n signal: args.signal,\n });\n}\n\n/**\n * Build the `/authorize` URL the user is redirected to for auth-code or\n * implicit flows. PKCE callers append `code_challenge` + `code_challenge_method`\n * via `extraParams`. Doesn't open a browser — that's the host bridge's job.\n */\nexport function buildAuthorizeUrl(args: {\n authorizeUrl: string;\n clientId: string;\n redirectUri: string;\n responseType: 'code' | 'token';\n scope?: string;\n state?: string;\n extraParams?: Record<string, string>;\n}): string {\n const url = new URL(args.authorizeUrl);\n url.searchParams.set('client_id', args.clientId);\n url.searchParams.set('redirect_uri', args.redirectUri);\n url.searchParams.set('response_type', args.responseType);\n if (args.scope) url.searchParams.set('scope', args.scope);\n if (args.state) url.searchParams.set('state', args.state);\n if (args.extraParams) {\n for (const [k, v] of Object.entries(args.extraParams)) url.searchParams.set(k, v);\n }\n return url.toString();\n}\n","// Translate a RequestAuth into outbound headers / query / cookies.\n//\n// Pure function — given a RequestAuth and the partially-built request, it\n// returns a new partially-built request with auth applied. The signing\n// primitives live in `../auth/*` so this module is mostly orchestration:\n// pick the right helper for the auth type and stitch its output into the\n// request.\n//\n// Three categories of auth types:\n// 1. Token / shared-secret (bearer, basic, api-key, custom-header,\n// oauth2-*, jwt-bearer, hawk, aws-sigv4): everything we need is in\n// `auth` already; we sign + return one headers object.\n// 2. Challenge-response that bootstraps from an unauthenticated send\n// (digest): we send no auth on the first request and let\n// executeRequest's 401-retry loop run buildDigestAuthHeader after\n// reading the server's WWW-Authenticate.\n// 3. Challenge-response that bootstraps from a Type-1 Negotiate (ntlm):\n// we attach the Type-1 here so the server immediately challenges\n// with Type-2; executeRequest then computes Type-3 and re-sends.\n\nimport type { RequestAuth } from '@apicircle/shared';\nimport { applyAwsSigV4 } from '../auth/awsSigV4';\nimport { buildHawkAuthHeader } from '../auth/hawk';\nimport { signJwt } from '../auth/jwt';\nimport { buildNtlmType1Negotiate } from '../auth/ntlm';\nimport { refreshToken as runRefreshToken } from '../auth/oauth2/grants';\nimport { OAuth2TokenError, type OAuth2TokenResponse } from '../auth/oauth2/fetchToken';\n\nexport interface AuthApplyTarget {\n url: string;\n method: string;\n headers: Record<string, string>;\n body: BodyInit | null;\n}\n\nexport interface AuthApplyOptions {\n /**\n * Called when applyAuth refreshes an expired OAuth2 access token. The\n * store wires this to persist the new accessToken / refreshToken /\n * expiresAt onto the request's auth payload — without it the refresh\n * works for THIS request but the next request would re-refresh because\n * the in-memory state didn't catch up.\n */\n onTokenRefreshed?: (\n auth: Extract<\n RequestAuth,\n | { type: 'oauth2-client-credentials' }\n | { type: 'oauth2-auth-code' }\n | { type: 'oauth2-pkce' }\n | { type: 'oauth2-password' }\n | { type: 'oauth2-implicit' }\n | { type: 'oauth2-device' }\n >,\n next: {\n accessToken: string;\n tokenType: string;\n refreshToken?: string;\n expiresAt: number;\n obtainedScope?: string;\n },\n ) => void | Promise<void>;\n /**\n * Test seam for the refresh fetch. When omitted, the global fetch is\n * used (matching production behavior).\n */\n fetchImpl?: typeof fetch;\n /**\n * Refresh tokens when they have less than this many milliseconds left.\n * Default: 60_000 (1 min). Set to 0 to disable proactive refresh.\n */\n refreshLeewayMs?: number;\n}\n\nexport interface AuthApplyResult {\n url: string;\n headers: Record<string, string>;\n /**\n * Non-fatal warnings raised while applying auth (bad JWT key, malformed\n * payload JSON, etc). The request still goes out — usually unauthenticated\n * — but executeRequest surfaces these to the user so they don't see a\n * mysterious 401 with no clue why their auth config didn't apply.\n */\n warnings?: AuthApplyWarning[];\n}\n\nexport interface AuthApplyWarning {\n /** Stable code so callers can match without parsing message strings. */\n code:\n | 'jwt-payload-json-invalid'\n | 'jwt-headers-json-invalid'\n | 'jwt-sign-failed'\n | 'hawk-url-invalid'\n | 'oauth2-refresh-failed';\n /** Human-readable message — safe to surface in the UI. */\n message: string;\n}\n\nfunction setHeader(\n headers: Record<string, string>,\n key: string,\n value: string,\n): Record<string, string> {\n // Replace any existing header with the same name (case-insensitive) so a\n // stale Authorization from the headers tab doesn't ride alongside auth.\n const lower = key.toLowerCase();\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() !== lower) out[k] = v;\n }\n out[key] = value;\n return out;\n}\n\n/**\n * Inspect an OAuth2 auth's expiry; if it's within `refreshLeewayMs` of\n * now AND a refreshToken is on file, swap in a freshly-refreshed token.\n * Failures are silent — applyAuth still tries to apply whatever token\n * we have, the user gets a 401, and the auth panel surfaces the\n * staleness via the token-state summary.\n *\n * Returns the refreshed auth (caller swaps it in for the rest of the\n * apply pass), or null when no refresh fired.\n */\n/**\n * In-flight refresh dedupe map. Keyed by `tokenUrl|clientId|refreshToken`\n * so two concurrent sends with the same expiring token coalesce into a\n * single POST against the IdP. Without this, N parallel sends with an\n * expired token = N parallel refresh requests, which most IdPs rate-\n * limit and which wastes a refresh_token if the IdP rotates them per\n * call. The map is process-local; cleared as soon as the refresh\n * settles either way.\n */\nconst inflightRefreshes = new Map<string, Promise<OAuth2TokenResponse>>();\n\nasync function maybeAutoRefresh(\n auth: RequestAuth,\n opts: AuthApplyOptions,\n warnings: AuthApplyWarning[],\n): Promise<RequestAuth | null> {\n if (\n auth.type !== 'oauth2-client-credentials' &&\n auth.type !== 'oauth2-auth-code' &&\n auth.type !== 'oauth2-pkce' &&\n auth.type !== 'oauth2-password' &&\n auth.type !== 'oauth2-device'\n ) {\n return null;\n }\n // implicit doesn't issue refresh_tokens — skip.\n const expiresAt = (auth as { expiresAt?: number }).expiresAt ?? 0;\n if (expiresAt <= 0) return null;\n const leeway = opts.refreshLeewayMs ?? 60_000;\n if (Date.now() + leeway < expiresAt) return null;\n const refreshTokenValue = (auth as { refreshToken?: string }).refreshToken ?? '';\n if (!refreshTokenValue.trim()) return null;\n try {\n const dedupeKey = `${auth.tokenUrl}|${auth.clientId}|${refreshTokenValue}`;\n const existing = inflightRefreshes.get(dedupeKey);\n const refreshPromise =\n existing ??\n runRefreshToken({\n tokenUrl: auth.tokenUrl,\n clientId: auth.clientId,\n clientSecret: (auth as { clientSecret?: string }).clientSecret || undefined,\n refreshToken: refreshTokenValue,\n scope: (auth as { scope?: string }).scope || undefined,\n fetchImpl: opts.fetchImpl,\n });\n if (!existing) {\n inflightRefreshes.set(dedupeKey, refreshPromise);\n // Always clear the entry once the promise settles, success or\n // failure. We MUST attach a catch as well — otherwise a refresh\n // rejection would propagate as an unhandled-rejection warning\n // (we await `refreshPromise` directly below, but the fan-out\n // `.finally(...)` here is its own promise chain that needs\n // explicit error consumption).\n refreshPromise\n .catch(() => {\n /* ignored — caller awaits the original promise and surfaces */\n })\n .finally(() => {\n inflightRefreshes.delete(dedupeKey);\n });\n }\n const next = await refreshPromise;\n const merged = {\n ...auth,\n accessToken: next.accessToken,\n tokenType: next.tokenType,\n refreshToken: next.refreshToken ?? refreshTokenValue,\n expiresAt: next.expiresIn ? Date.now() + next.expiresIn * 1000 : 0,\n obtainedScope: next.scope ?? (auth as { obtainedScope?: string }).obtainedScope ?? '',\n } as RequestAuth;\n if (opts.onTokenRefreshed) {\n try {\n await opts.onTokenRefreshed(\n merged as Parameters<NonNullable<AuthApplyOptions['onTokenRefreshed']>>[0],\n {\n accessToken: next.accessToken,\n tokenType: next.tokenType,\n refreshToken: next.refreshToken,\n expiresAt: next.expiresIn ? Date.now() + next.expiresIn * 1000 : 0,\n obtainedScope: next.scope,\n },\n );\n } catch {\n // Persistence failures shouldn't block the request — the\n // refreshed token still applies for THIS send.\n }\n }\n return merged;\n } catch (err) {\n // Refresh failed — surface to the user via authWarnings so they can\n // see WHY their request went out unauthenticated. Falls through with\n // the original (stale) token; the request will hit a 401 but at\n // least the user has a clear refresh-failure message in the panel.\n const message =\n err instanceof OAuth2TokenError\n ? `OAuth2 token refresh failed: ${err.message}`\n : `OAuth2 token refresh failed: ${err instanceof Error ? err.message : String(err)}`;\n warnings.push({ code: 'oauth2-refresh-failed', message });\n return null;\n }\n}\n\n/** Read a header by name case-insensitively. */\nfunction findHeaderValue(headers: Record<string, string>, key: string): string | undefined {\n const lower = key.toLowerCase();\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() === lower) return v;\n }\n return undefined;\n}\n\nfunction appendQueryParam(rawUrl: string, key: string, value: string): string {\n try {\n const parsed = new URL(rawUrl);\n parsed.searchParams.append(key, value);\n return parsed.toString();\n } catch {\n const sep = rawUrl.includes('?') ? '&' : '?';\n return `${rawUrl}${sep}${encodeURIComponent(key)}=${encodeURIComponent(value)}`;\n }\n}\n\nfunction appendCookie(\n headers: Record<string, string>,\n key: string,\n value: string,\n): Record<string, string> {\n const existing = Object.entries(headers).find(([k]) => k.toLowerCase() === 'cookie');\n const pair = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;\n if (existing) {\n const [k, v] = existing;\n return { ...headers, [k]: `${v}; ${pair}` };\n }\n return { ...headers, Cookie: pair };\n}\n\n// btoa exists everywhere we run today (browsers, Node ≥ 18). The Buffer\n// fallback is kept for the unlikely case of a sandbox that strips both —\n// we'd rather degrade with a clear message than silently send no auth.\nfunction nodeBufferToBase64(input: string | Uint8Array): string {\n const buf = (\n globalThis as unknown as {\n Buffer?: {\n from: (data: string | Uint8Array, encoding?: string) => { toString: (e: string) => string };\n };\n }\n ).Buffer;\n if (!buf) throw new Error('Neither btoa nor Buffer is available in this runtime');\n if (typeof input === 'string') return buf.from(input, 'utf8').toString('base64');\n return buf.from(input).toString('base64');\n}\n\nfunction base64(text: string): string {\n if (typeof btoa === 'function') {\n // btoa expects Latin-1; encodeURIComponent → escape lifts UTF-8 input\n // through that gauntlet without losing bytes.\n return btoa(unescape(encodeURIComponent(text)));\n }\n return nodeBufferToBase64(text);\n}\n\n// ── jwt-bearer plumbing ────────────────────────────────────────────────────────\n\n/**\n * Either return the user-supplied pre-computed token, or sign a fresh\n * one using the algorithm + key the auth config specifies. Returns the\n * token plus any warnings raised along the way (malformed JSON, signing\n * failure). Token is null when there's nothing to send; warnings are\n * non-empty when the config was malformed in a way the user should see.\n */\nasync function buildJwtToken(\n auth: Extract<RequestAuth, { type: 'jwt-bearer' }>,\n): Promise<{ token: string | null; warnings: AuthApplyWarning[] }> {\n const warnings: AuthApplyWarning[] = [];\n if (auth.token.trim().length > 0) return { token: auth.token.trim(), warnings };\n if (!auth.algorithm || !auth.secretOrKey) return { token: null, warnings };\n let payload: Record<string, unknown> = {};\n let extraHeaders: Record<string, unknown> = {};\n if (auth.payload.trim()) {\n try {\n payload = JSON.parse(auth.payload) as Record<string, unknown>;\n } catch (err) {\n warnings.push({\n code: 'jwt-payload-json-invalid',\n message: `JWT payload is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n });\n return { token: null, warnings };\n }\n }\n if (auth.jwtHeaders.trim()) {\n try {\n extraHeaders = JSON.parse(auth.jwtHeaders) as Record<string, unknown>;\n } catch (err) {\n warnings.push({\n code: 'jwt-headers-json-invalid',\n message: `JWT additional-headers is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n });\n return { token: null, warnings };\n }\n }\n try {\n const token = await signJwt({\n algorithm: auth.algorithm,\n secretOrKey: auth.secretOrKey,\n payload,\n additionalHeaders: extraHeaders,\n });\n return { token, warnings };\n } catch (err) {\n warnings.push({\n code: 'jwt-sign-failed',\n message: `JWT signing failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n return { token: null, warnings };\n }\n}\n\n// ── Public entry point ────────────────────────────────────────────────────────\n\nexport async function applyAuth(\n target: AuthApplyTarget,\n auth: RequestAuth,\n opts: AuthApplyOptions = {},\n): Promise<AuthApplyResult> {\n // Warnings collected as we go — emitted on the result so executeRequest\n // can surface them in `ExecutionResult.authWarnings` (UI displays\n // them next to the response). Refresh failures, JWT signing errors,\n // and Hawk URL parse failures all flow through here.\n const warnings: AuthApplyWarning[] = [];\n\n // Auto-refresh OAuth2 tokens that are expired or about to expire. The\n // refresh fires BEFORE the auth-injection switch below so the refreshed\n // accessToken is what we end up putting on the wire.\n const refreshed = await maybeAutoRefresh(auth, opts, warnings);\n if (refreshed) auth = refreshed;\n\n const result = await applyAuthBody(target, auth, opts, warnings);\n if (warnings.length > 0) {\n return {\n ...result,\n warnings: [...(result.warnings ?? []), ...warnings],\n };\n }\n return result;\n}\n\n/**\n * Inner switch — split out from `applyAuth` so the outer wrapper can\n * combine post-refresh warnings with per-type warnings without\n * re-walking the auth shape.\n */\nasync function applyAuthBody(\n target: AuthApplyTarget,\n auth: RequestAuth,\n opts: AuthApplyOptions,\n warnings: AuthApplyWarning[],\n): Promise<AuthApplyResult> {\n void warnings; // body-level switch doesn't push warnings today; refresh + JWT helpers do.\n void opts;\n switch (auth.type) {\n case 'none':\n case 'inherit': // inheritance is resolved upstream; if we still see it here, do nothing\n return { url: target.url, headers: target.headers };\n\n case 'bearer': {\n if (!auth.token.trim()) return { url: target.url, headers: target.headers };\n return {\n url: target.url,\n headers: setHeader(target.headers, 'Authorization', `Bearer ${auth.token.trim()}`),\n };\n }\n\n case 'basic': {\n const credentials = `${auth.username}:${auth.password}`;\n return {\n url: target.url,\n headers: setHeader(target.headers, 'Authorization', `Basic ${base64(credentials)}`),\n };\n }\n\n case 'api-key': {\n if (!auth.key.trim()) return { url: target.url, headers: target.headers };\n if (auth.addTo === 'query') {\n return { url: appendQueryParam(target.url, auth.key, auth.value), headers: target.headers };\n }\n if (auth.addTo === 'cookie') {\n return { url: target.url, headers: appendCookie(target.headers, auth.key, auth.value) };\n }\n return { url: target.url, headers: setHeader(target.headers, auth.key, auth.value) };\n }\n\n case 'custom-header': {\n if (!auth.key.trim()) return { url: target.url, headers: target.headers };\n return { url: target.url, headers: setHeader(target.headers, auth.key, auth.value) };\n }\n\n case 'oauth2-client-credentials':\n case 'oauth2-auth-code':\n case 'oauth2-pkce':\n case 'oauth2-password':\n case 'oauth2-implicit':\n case 'oauth2-device': {\n if (!auth.accessToken.trim()) return { url: target.url, headers: target.headers };\n const tokenType = auth.tokenType?.trim() || 'Bearer';\n return {\n url: target.url,\n headers: setHeader(\n target.headers,\n 'Authorization',\n `${tokenType} ${auth.accessToken.trim()}`,\n ),\n };\n }\n\n case 'aws-sigv4': {\n if (!auth.accessKeyId || !auth.secretAccessKey || !auth.region || !auth.service) {\n return { url: target.url, headers: target.headers };\n }\n // Pass the body through as-is — the signer accepts every BodyInit\n // shape and falls back to UNSIGNED-PAYLOAD for FormData /\n // ReadableStream where pre-fetch hashing isn't possible.\n const signed = await applyAwsSigV4({\n method: target.method,\n url: target.url,\n headers: target.headers,\n body: target.body as Parameters<typeof applyAwsSigV4>[0]['body'],\n accessKeyId: auth.accessKeyId,\n secretAccessKey: auth.secretAccessKey,\n region: auth.region,\n service: auth.service,\n sessionToken: auth.sessionToken || undefined,\n addTo: auth.addTo,\n });\n return { url: signed.url, headers: signed.headers };\n }\n\n case 'hawk': {\n if (!auth.hawkId || !auth.hawkKey) return { url: target.url, headers: target.headers };\n try {\n // When bindPayload is on AND the body is hashable, fold the body\n // into the MAC. We pull the content-type from the request's own\n // headers (case-insensitively); if the body is FormData /\n // ReadableStream we can't hash pre-fetch — silently fall back to\n // header-only signing, same as Hawk reference clients.\n let payload: { body: string | ArrayBuffer | Uint8Array; contentType: string } | undefined;\n if (auth.bindPayload && target.body != null) {\n const ct = findHeaderValue(target.headers, 'content-type') ?? 'application/octet-stream';\n if (typeof target.body === 'string') payload = { body: target.body, contentType: ct };\n else if (target.body instanceof ArrayBuffer)\n payload = { body: target.body, contentType: ct };\n else if (target.body instanceof Uint8Array)\n payload = { body: target.body, contentType: ct };\n else if (typeof URLSearchParams !== 'undefined' && target.body instanceof URLSearchParams)\n payload = {\n body: target.body.toString(),\n contentType: 'application/x-www-form-urlencoded',\n };\n }\n const headerValue = await buildHawkAuthHeader({\n method: target.method,\n url: target.url,\n hawkId: auth.hawkId,\n hawkKey: auth.hawkKey,\n algorithm: auth.algorithm,\n ext: auth.ext,\n payload,\n });\n return {\n url: target.url,\n headers: setHeader(target.headers, 'Authorization', headerValue),\n };\n } catch {\n // Malformed URL etc. — let the request fly without auth.\n return { url: target.url, headers: target.headers };\n }\n }\n\n case 'jwt-bearer': {\n const { token, warnings } = await buildJwtToken(auth);\n if (!token) {\n return { url: target.url, headers: target.headers, warnings };\n }\n return {\n url: target.url,\n headers: setHeader(target.headers, 'Authorization', `Bearer ${token}`),\n warnings: warnings.length ? warnings : undefined,\n };\n }\n\n case 'digest':\n // Digest is challenge-driven: send unauthenticated. executeRequest's\n // 401-retry path inspects WWW-Authenticate, runs buildDigestAuthHeader,\n // and re-fetches with the right Authorization on its own.\n return { url: target.url, headers: target.headers };\n\n case 'ntlm': {\n // NTLM bootstraps from a Type-1 Negotiate so the server immediately\n // returns 401 + Type-2 challenge. Sending nothing would let the\n // server respond with a generic auth-required error that's\n // indistinguishable from \"credentials wrong\"; emitting Type-1\n // explicitly lights up the handshake.\n const type1 = buildNtlmType1Negotiate(auth.domain, auth.workstation);\n return {\n url: target.url,\n headers: setHeader(target.headers, 'Authorization', `NTLM ${type1}`),\n };\n }\n }\n}\n","/**\n * Detect whether the host is the API Circle Studio Desktop shell.\n *\n * The Electron preload script attaches a bridge object on `globalThis.apicircleDesktop`\n * (see `apps/desktop/src/main/preload.ts`). The web app exposes nothing, so a\n * presence check is sufficient — we don't need to inspect the bridge's shape.\n */\nexport function isDesktop(): boolean {\n if (typeof globalThis === 'undefined') return false;\n return (globalThis as { apicircleDesktop?: unknown }).apicircleDesktop != null;\n}\n","/**\n * Auto-fed request headers — platform-specific, non-editable, not stored.\n *\n * These headers are injected at send-time by the execution engine:\n * • They are NEVER written to IndexedDB or Git remote.\n * • A new X-Trace-Span-Id and traceparent are generated for every send.\n * • They do NOT appear in the user-visible \"Headers\" editor tab — the\n * HeadersTab \"Auto-fed at send\" aside lists them for reference only.\n *\n * User-set headers always win: if the user typed `X-Client-Version` into the\n * Headers tab, the auto value is suppressed.\n */\n\nimport { isDesktop } from './platformDetection';\n\nconst APP_VERSION = '1.0.0'; // Keep in sync with package.json `version`.\nconst APP_NAME = 'API Circle Studio';\n\n/** Canonical desktop origin used in requests (also used by the native HTTP layer). */\nexport const DESKTOP_APP_ORIGIN = 'http://app.studio.apicircle.dev';\n\n/**\n * Generate a random hex span-id (16 hex chars = 64 bits, compatible with\n * W3C Trace Context `traceparent` and OpenTelemetry span-id format).\n */\nexport function generateSpanId(): string {\n const bytes = new Uint8Array(8);\n crypto.getRandomValues(bytes);\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Generate a W3C traceparent header value.\n * Format: 00-<trace-id (32 hex)>-<span-id (16 hex)>-01\n */\nexport function generateTraceParent(): string {\n const traceId = Array.from(crypto.getRandomValues(new Uint8Array(16)))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n const spanId = generateSpanId();\n return `00-${traceId}-${spanId}-01`;\n}\n\n/**\n * Override hooks for tests — let test code feed deterministic values\n * for span-id / traceparent / platform without monkey-patching `crypto`.\n * Production code never passes these.\n */\nexport interface AutoHeaderOverrides {\n spanId?: string;\n traceparent?: string;\n platform?: 'desktop' | 'web';\n version?: string;\n name?: string;\n}\n\n/**\n * Returns the set of auto-fed headers for a single request execution.\n * Call this once per send — `X-Trace-Span-Id` and `traceparent` are\n * re-generated on every invocation.\n *\n * @param userHeaders The headers the user has configured so auto-headers\n * do NOT override anything the user has explicitly set.\n * @param overrides Test-only override hooks; never set in production.\n */\nexport function buildAutoHeaders(\n userHeaders: Record<string, string>,\n overrides: AutoHeaderOverrides = {},\n): Record<string, string> {\n const auto: Record<string, string> = {};\n const userLower = Object.fromEntries(\n Object.keys(userHeaders).map((k) => [k.toLowerCase(), true]),\n );\n\n // ── Platform identity ─────────────────────────────────────────────────────\n if (!userLower['x-client-name']) {\n auto['X-Client-Name'] = overrides.name ?? APP_NAME;\n }\n if (!userLower['x-client-platform']) {\n auto['X-Client-Platform'] = overrides.platform ?? (isDesktop() ? 'desktop' : 'web');\n }\n if (!userLower['x-client-version']) {\n auto['X-Client-Version'] = overrides.version ?? APP_VERSION;\n }\n\n // ── Distributed tracing (auto-generated per send) ─────────────────────────\n // Always generate fresh — never reuse a stored value.\n auto['X-Trace-Span-Id'] = overrides.spanId ?? generateSpanId();\n if (!userLower['traceparent']) {\n auto['traceparent'] = overrides.traceparent ?? generateTraceParent();\n }\n\n // ── Origin / Referer (desktop only — the native HTTP layer also injects\n // these, but we set them here so the request preview shows accurate\n // values) ─────────────────────────────────────────────────────────────\n const platform = overrides.platform ?? (isDesktop() ? 'desktop' : 'web');\n if (platform === 'desktop') {\n if (!userLower['origin']) {\n auto['Origin'] = DESKTOP_APP_ORIGIN;\n }\n if (!userLower['referer']) {\n auto['Referer'] = `${DESKTOP_APP_ORIGIN}/`;\n }\n }\n\n return auto;\n}\n\n/**\n * Merge auto-headers into user headers. User-defined values always win —\n * auto-headers only fill gaps.\n */\nexport function mergeWithAutoHeaders(\n userHeaders: Record<string, string>,\n overrides: AutoHeaderOverrides = {},\n): Record<string, string> {\n return { ...buildAutoHeaders(userHeaders, overrides), ...userHeaders };\n}\n","import type { Request as ApiRequest } from '@apicircle/shared';\nimport { applyAuth, type AuthApplyOptions, type AuthApplyWarning } from './applyAuth';\nimport { mergeWithAutoHeaders, type AutoHeaderOverrides } from './autoHeaders';\n\nexport interface BuiltRequest {\n url: string;\n method: string;\n headers: Record<string, string>;\n body: BodyInit | null;\n /**\n * Non-fatal warnings raised by applyAuth (bad JWT key, malformed\n * payload JSON, etc). executeRequest forwards these into\n * `ExecutionResult.authWarnings` so the UI can surface them alongside\n * the response — without them, a misconfigured JWT silently produces\n * a 401 with no clue why.\n */\n authWarnings: AuthApplyWarning[];\n}\n\n/**\n * Resolves an attachment slotId to a Blob (with filename for form-data).\n * The host reads this from IndexedDB; the CLI reads it from its filesystem\n * cache. A null return means \"not downloaded\" and becomes a hard execution\n * failure.\n */\nexport type AttachmentResolver = (\n slotId: string,\n) => Promise<{ blob: Blob; filename: string } | null>;\n\nfunction missingAttachmentMessage(slotId: string, filename?: string): string {\n const label = filename ? `${filename} (${slotId})` : slotId;\n return (\n `Attachment ${label} is required for this request but is not downloaded locally. ` +\n 'Download the missing attachments before sending or running the plan.'\n );\n}\n\nasync function requireAttachment(\n slotId: string,\n resolveAttachment: AttachmentResolver | undefined,\n filename?: string,\n): Promise<{ blob: Blob; filename: string }> {\n if (!resolveAttachment) {\n throw new Error(missingAttachmentMessage(slotId, filename));\n }\n const file = await resolveAttachment(slotId);\n if (!file) {\n throw new Error(missingAttachmentMessage(slotId, filename));\n }\n return file;\n}\n\n/**\n * Match URL placeholders in either Express-style (`:name`) or OpenAPI-style\n * (`{name}`). Names follow `[A-Za-z_][\\w-]*`. The negative lookbehind/lookahead\n * on `{...}` excludes our `{{var}}` template-variable syntax, which sits\n * between two curlies and would otherwise match incorrectly.\n *\n * We also restrict the scan to the URL's *path portion* (everything before\n * the first `?`) — query values often contain `{{NAME}}` references, and we\n * never want those classified as path params.\n */\nconst PATH_PLACEHOLDER = /(?::([A-Za-z_][\\w-]*)|(?<!\\{)\\{([A-Za-z_][\\w-]*)\\}(?!\\}))/g;\n\nfunction splitOnQuery(rawUrl: string): { path: string; rest: string } {\n const q = rawUrl.indexOf('?');\n if (q < 0) return { path: rawUrl, rest: '' };\n return { path: rawUrl.slice(0, q), rest: rawUrl.slice(q) };\n}\n\n/**\n * Split a typed URL into the base part (everything before `?`) and a\n * structured query-row list. Used by the editor's URL input to keep the\n * URL field and the Query Params sub-tab in sync — when the user types or\n * pastes `?key=val`, the rows surface in the Params list automatically.\n *\n * Variable references like `{{NAME}}` in keys or values are preserved\n * verbatim — they stay templated and resolve at send time. We use\n * permissive splitting (split on `&` then on the first `=`) rather than\n * `URLSearchParams` because URLSearchParams percent-decodes `{{` into `{{`\n * fine but also collapses whitespace and strips empty keys, which fights\n * the user's intent during in-progress typing.\n */\nexport function parseUrlQuery(rawUrl: string): {\n base: string;\n query: Array<{ key: string; value: string; enabled: boolean }>;\n} {\n const q = rawUrl.indexOf('?');\n if (q < 0) return { base: rawUrl, query: [] };\n const base = rawUrl.slice(0, q);\n const queryString = rawUrl.slice(q + 1);\n // Strip a trailing `#fragment` if present — fragments aren't sent over the\n // wire and would otherwise leak into the last query row's value.\n const hashIdx = queryString.indexOf('#');\n const cleaned = hashIdx >= 0 ? queryString.slice(0, hashIdx) : queryString;\n if (cleaned.length === 0) return { base, query: [] };\n const rows = cleaned.split('&').map((segment) => {\n const eq = segment.indexOf('=');\n const key = eq < 0 ? segment : segment.slice(0, eq);\n const value = eq < 0 ? '' : segment.slice(eq + 1);\n return {\n // Decode percent-encoded keys/values but leave `{{var}}` alone — those\n // never get percent-encoded by Postman/curl pastes.\n key: tryDecode(key),\n value: tryDecode(value),\n enabled: true,\n };\n });\n return { base, query: rows };\n}\n\nfunction tryDecode(s: string): string {\n try {\n return decodeURIComponent(s);\n } catch {\n return s;\n }\n}\n\n/**\n * Inverse of `parseUrlQuery`. Renders the structured query rows back into a\n * URL-bar-friendly string, skipping disabled or empty-key rows. Values are\n * left as-is (no double-encoding) — `composeUrl` runs at send time and\n * handles wire encoding properly.\n */\nexport function composeUrlWithQuery(\n base: string,\n query: ReadonlyArray<{ key: string; value: string; enabled: boolean }>,\n): string {\n const enabled = query.filter((q) => q.enabled && q.key.trim().length > 0);\n if (enabled.length === 0) return base;\n const rendered = enabled.map((q) => `${q.key}=${q.value}`).join('&');\n return `${base}?${rendered}`;\n}\n\n/** Extract the placeholder names appearing in a URL, in document order, deduped. */\nexport function findPathPlaceholders(rawUrl: string): string[] {\n const { path } = splitOnQuery(rawUrl);\n const seen = new Set<string>();\n const out: string[] = [];\n PATH_PLACEHOLDER.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = PATH_PLACEHOLDER.exec(path)) !== null) {\n const name = m[1] ?? m[2];\n if (name && !seen.has(name)) {\n seen.add(name);\n out.push(name);\n }\n }\n return out;\n}\n\n/**\n * Substitute `:name` and `{name}` placeholders in a URL's path with the\n * matching values from `pathParams`. The query string passes through\n * untouched — a `{{var}}` in there is a variable reference, not a path\n * placeholder. Missing keys substitute to empty string; the Editor surfaces\n * unbound placeholders as a UI warning, not a runtime error.\n */\nexport function applyPathParams(rawUrl: string, pathParams: Record<string, string>): string {\n const { path, rest } = splitOnQuery(rawUrl);\n PATH_PLACEHOLDER.lastIndex = 0;\n const substituted = path.replace(PATH_PLACEHOLDER, (_full, exprName, braceName) => {\n const name = (exprName ?? braceName) as string;\n const value = pathParams[name];\n return value === undefined ? '' : encodeURIComponent(value);\n });\n return substituted + rest;\n}\n\n// RFC 7230 §3.2.6 \"token\" — valid characters for an HTTP header field-name.\n// Rejecting names outside this set keeps a `{{var}}` resolution that ends up\n// containing `:` or a control char from corrupting the wire format / smuggling\n// a second header line on a future native HTTP layer.\nconst HEADER_TOKEN_RE = /^[A-Za-z0-9!#$%&'*+\\-.^_`|~]+$/;\n\n/** Strip ASCII control characters (CR/LF/NUL/etc.) from a value that's about\n * to be put on an HTTP wire. RFC 7230 forbids CR/LF in header values; CR/LF\n * in a Cookie value also breaks the `; key=value; …` framing. Body content\n * goes through a different code path and is NOT sanitised here — line\n * breaks in a JSON / text body are legitimate. */\nfunction sanitizeWireValue(v: string): string {\n // Strip everything ASCII < 0x20 except HT (0x09 — tab, occasionally legit\n // inside header values per the spec). Strictly speaking even tab in a\n // header value is questionable; we keep it to avoid surprising the user.\n // 0x7F (DEL) is also stripped.\n // eslint-disable-next-line no-control-regex -- intentional: stripping CTLs is the whole point\n return v.replace(/[\\x00-\\x08\\x0A-\\x1F\\x7F]/g, '');\n}\n\n/**\n * Build a `Cookie` header value from a list of name/value pairs. Skips\n * disabled or empty-key rows. Returns the empty string when nothing applies.\n * Per RFC 6265, cookie values may not contain CTL chars or `;` (which is the\n * row separator) — we strip CTLs and also strip `;` from values to keep the\n * row framing intact when a {{var}} resolves to something containing one.\n */\nexport function composeCookieHeader(\n rows: ReadonlyArray<{ key: string; value: string; enabled: boolean }>,\n): string {\n return rows\n .filter((r) => r.enabled && r.key.trim().length > 0)\n .map((r) => {\n // The key has already been trimmed; strip any CTLs and `;` / `=` /\n // whitespace it might have picked up from a variable resolution.\n // eslint-disable-next-line no-control-regex -- intentional: stripping CTLs is the whole point\n const safeKey = r.key.trim().replace(/[\\x00-\\x20;=]/g, '');\n const safeValue = sanitizeWireValue(r.value).replace(/;/g, '');\n return `${safeKey}=${safeValue}`;\n })\n .filter((s) => s.length > 1) // `=` alone after sanitisation is meaningless\n .join('; ');\n}\n\nexport function composeUrl(\n rawUrl: string,\n params: ReadonlyArray<{ key: string; value: string; enabled: boolean }>,\n): string {\n const enabled = params.filter((p) => p.enabled && p.key.trim().length > 0);\n if (enabled.length === 0) return rawUrl;\n\n let parsed: URL | null = null;\n try {\n parsed = new URL(rawUrl);\n } catch {\n parsed = null;\n }\n if (parsed) {\n for (const p of enabled) parsed.searchParams.append(p.key, p.value);\n return parsed.toString();\n }\n\n const query = enabled\n .map((p) => `${encodeURIComponent(p.key)}=${encodeURIComponent(p.value)}`)\n .join('&');\n if (query.length === 0) return rawUrl;\n return rawUrl.includes('?') ? `${rawUrl}&${query}` : `${rawUrl}?${query}`;\n}\n\nexport function composeHeaders(\n rows: ReadonlyArray<{ key: string; value: string; enabled: boolean }>,\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const row of rows) {\n if (!row.enabled) continue;\n const k = row.key.trim();\n if (!k) continue;\n // Reject header names that don't fit RFC 7230's token grammar. A\n // resolved `{{var}}` could otherwise carry `:` / CR/LF / space and\n // smuggle a second header on a future native HTTP layer. Browser\n // fetch already throws on this — defending here gives us deterministic\n // skip-the-row behaviour AND covers any future non-fetch executor.\n if (!HEADER_TOKEN_RE.test(k)) continue;\n out[k] = sanitizeWireValue(row.value);\n }\n return out;\n}\n\n/**\n * Strip Content-Type from a header set. Used for form-data and binary bodies\n * where the browser must set Content-Type itself (multipart boundary, blob's\n * own type) — a manually-set header would corrupt the request.\n */\nfunction stripContentType(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (k.trim().toLowerCase() === 'content-type') continue;\n out[k] = v;\n }\n return out;\n}\n\n/**\n * Serialize a request body for fetch(). Async because form-data and binary\n * may need to read attachment blobs from the host's storage layer.\n */\nexport async function composeBody(\n body: ApiRequest['body'],\n resolveAttachment?: AttachmentResolver,\n): Promise<BodyInit | null> {\n if (body.type === 'none') return null;\n\n if (body.type === 'json' || body.type === 'text' || body.type === 'xml') {\n return body.content;\n }\n\n if (body.type === 'graphql') {\n // Standard GraphQL-over-HTTP envelope: `{ \"query\": string, \"variables\": object|null }`.\n // The variables pane in the editor is plain JSON; if it doesn't parse,\n // we send `null` so the server reports the parse error rather than the\n // request silently failing on our side.\n let variables: unknown = undefined;\n if (body.variables && body.variables.trim().length > 0) {\n try {\n variables = JSON.parse(body.variables);\n } catch {\n variables = null;\n }\n }\n return JSON.stringify({\n query: body.content,\n ...(variables !== undefined ? { variables } : {}),\n });\n }\n\n if (body.type === 'urlencoded') {\n const params = new URLSearchParams();\n for (const line of body.content.split(/\\r?\\n/)) {\n const eq = line.indexOf('=');\n if (eq === -1) continue;\n const key = line.slice(0, eq).trim();\n const value = line.slice(eq + 1);\n if (!key) continue;\n params.append(key, value);\n }\n return params.toString();\n }\n\n if (body.type === 'form-data') {\n const fd = new FormData();\n for (const row of body.formRows ?? []) {\n if (!row.enabled || !row.key.trim()) continue;\n if (row.kind === 'text') {\n fd.append(row.key, row.value);\n } else if (row.slotId) {\n const file = await requireAttachment(row.slotId, resolveAttachment, row.filename);\n fd.append(row.key, file.blob, file.filename);\n }\n }\n return fd;\n }\n\n if (body.type === 'binary') {\n if (body.attachment?.slotId) {\n const file = await requireAttachment(\n body.attachment.slotId,\n resolveAttachment,\n body.attachment.filename,\n );\n return file.blob;\n }\n return null;\n }\n\n return null;\n}\n\nexport interface BuildRequestOptions {\n resolveAttachment?: AttachmentResolver;\n /**\n * applyAuth options — most importantly the `onTokenRefreshed`\n * callback that lets the store persist refreshed OAuth2 tokens.\n * Forwarded as-is.\n */\n authOptions?: AuthApplyOptions;\n /**\n * Test-only override hooks for the auto-fed headers. Lets specs feed\n * deterministic values for `X-Trace-Span-Id`, `traceparent`, and\n * `X-Client-Platform`. Production callers omit this.\n */\n autoHeaderOverrides?: AutoHeaderOverrides;\n}\n\nexport async function buildRequest(\n req: ApiRequest,\n opts: BuildRequestOptions = {},\n): Promise<BuiltRequest> {\n const baseHeaders = composeHeaders(req.headers);\n // Merge cookies into a single Cookie header. A user-set Cookie row in the\n // headers list wins (no override) — that's the natural escape hatch when\n // someone wants full control over the wire format.\n const headers = ((): Record<string, string> => {\n const cookieValue = composeCookieHeader(req.cookies ?? []);\n if (!cookieValue) return baseHeaders;\n const hasUserCookie = Object.keys(baseHeaders).some((k) => k.toLowerCase() === 'cookie');\n return hasUserCookie ? baseHeaders : { ...baseHeaders, Cookie: cookieValue };\n })();\n // GET and HEAD requests cannot carry a body on the fetch transport —\n // the WHATWG `Request` constructor throws `TypeError: Request with\n // GET/HEAD method cannot have body`. If the user configured a body and\n // then switched the method, drop the body silently rather than letting\n // the whole send fail. (Other tools — Postman, curl — behave the same.)\n const methodAllowsBody = req.method !== 'GET' && req.method !== 'HEAD';\n const body = methodAllowsBody ? await composeBody(req.body, opts.resolveAttachment) : null;\n // Strip the Content-Type header when it describes a payload that won't\n // reach the wire:\n // - form-data / binary: fetch must set Content-Type itself (multipart\n // boundary, Blob's own type) — a user-set value would corrupt it;\n // - GET / HEAD carrying a configured body: the body was just dropped\n // above, so its body-type Content-Type now describes nothing.\n // A Content-Type with no body behind it (`body.type === 'none'`) is a\n // plain user-set header — keep it; the browser sends it on GET too.\n const stripBodyContentType =\n req.body.type === 'form-data' ||\n req.body.type === 'binary' ||\n (!methodAllowsBody && req.body.type !== 'none');\n const sanitizedHeaders = stripBodyContentType ? stripContentType(headers) : headers;\n const urlWithPath = applyPathParams(req.url, req.pathParams ?? {});\n const url = composeUrl(urlWithPath, req.query);\n\n // Auth runs last — schemes like AWS SigV4 read the final URL + headers +\n // body to compute their signature. Older synced docs may lack `auth`;\n // workspace store hydration normalises it, but be defensive here too.\n const auth = req.auth ?? { type: 'none' };\n const applied = await applyAuth(\n { url, method: req.method, headers: sanitizedHeaders, body },\n auth,\n opts.authOptions,\n );\n\n return {\n url: applied.url,\n method: req.method,\n headers: mergeWithAutoHeaders(applied.headers, opts.autoHeaderOverrides),\n body,\n authWarnings: applied.warnings ?? [],\n };\n}\n","// Variable substitution for request fields.\n//\n// `{{NAME}}` placeholders are resolved against a layered scope. The default\n// precedence (matches the plan's \"Global priority\" rule) is:\n//\n// 1. contextVars — defined inline on the request itself\n// 2. activeEnv — currently-selected environment's variables\n// 3. priorityEnvs[*] — fallback chain (other environments in user-set\n// order). First match wins.\n//\n// Plan-level overrides (P6) plug in by passing a different priorityEnvs\n// list — execution plans build their own ordered scope and pass it as the\n// outermost wins. The `contextVars` layer is always highest priority.\n//\n// Secrets are surfaced as a fourth layer: a `secrets` map of decrypted\n// values keyed by secret label. The Secret Vault hands these in pre-decrypted\n// for the duration of one send so this layer doesn't need crypto.\n\nexport interface ResolutionScope {\n contextVars: Record<string, string>;\n activeEnv: Record<string, string>;\n priorityEnvs: Array<Record<string, string>>;\n secrets: Record<string, string>;\n}\n\nexport interface ResolveResult {\n value: string;\n /** Names that were referenced but not found in any scope. */\n missing: string[];\n}\n\nconst PLACEHOLDER = /\\{\\{\\s*([A-Za-z_][\\w.-]*)\\s*\\}\\}/g;\n\nexport function lookup(scope: ResolutionScope, name: string): string | undefined {\n if (Object.prototype.hasOwnProperty.call(scope.contextVars, name)) {\n return scope.contextVars[name];\n }\n if (Object.prototype.hasOwnProperty.call(scope.activeEnv, name)) {\n return scope.activeEnv[name];\n }\n for (const env of scope.priorityEnvs) {\n if (Object.prototype.hasOwnProperty.call(env, name)) return env[name];\n }\n if (Object.prototype.hasOwnProperty.call(scope.secrets, name)) {\n return scope.secrets[name];\n }\n return undefined;\n}\n\n/**\n * Replace every `{{NAME}}` in `input` with its resolved value. Unknown names\n * are left as-is in the output (so the user can see which placeholder didn't\n * resolve) and reported via `missing`.\n */\nexport function resolveString(input: string, scope: ResolutionScope): ResolveResult {\n const missing = new Set<string>();\n const value = input.replace(PLACEHOLDER, (match, name: string) => {\n const resolved = lookup(scope, name);\n if (resolved === undefined) {\n missing.add(name);\n return match;\n }\n return resolved;\n });\n return { value, missing: [...missing] };\n}\n\n/**\n * Resolve placeholders in every string value of an object (one level deep).\n * Used for header / param row arrays — both keys and values are resolved.\n * Returns a flat list of all missing names across the inputs.\n */\nexport function resolveStringMap(\n obj: Record<string, string>,\n scope: ResolutionScope,\n): { result: Record<string, string>; missing: string[] } {\n const out: Record<string, string> = {};\n const missing = new Set<string>();\n for (const [key, value] of Object.entries(obj)) {\n const k = resolveString(key, scope);\n const v = resolveString(value, scope);\n out[k.value] = v.value;\n for (const m of k.missing) missing.add(m);\n for (const m of v.missing) missing.add(m);\n }\n return { result: out, missing: [...missing] };\n}\n\n/**\n * Build a ResolutionScope from a Workspace + a per-request context-vars\n * list. Optional plan-level priority overrides take precedence over the\n * workspace's global priority order.\n *\n * `secrets` is passed in already-decrypted because resolveString runs\n * synchronously — decryption happens once before send.\n */\nexport function buildScope(args: {\n contextVars: ReadonlyArray<{ key: string; value: string }>;\n environments: Record<string, Record<string, string>>;\n activeEnvName: string | null;\n priorityOrder: string[];\n secrets?: Record<string, string>;\n}): ResolutionScope {\n const ctx: Record<string, string> = {};\n for (const v of args.contextVars) {\n if (v.key) ctx[v.key] = v.value;\n }\n const activeEnv =\n args.activeEnvName && args.environments[args.activeEnvName]\n ? args.environments[args.activeEnvName]\n : {};\n const priorityEnvs = args.priorityOrder\n .filter((name) => name !== args.activeEnvName)\n .map((name) => args.environments[name] ?? {});\n return {\n contextVars: ctx,\n activeEnv: activeEnv ?? {},\n priorityEnvs,\n secrets: args.secrets ?? {},\n };\n}\n\n// --- Autocomplete ------------------------------------------------------\n\nexport type VariableSource = 'context' | 'active-env' | 'priority-env' | 'secret';\n\nexport interface VariableSuggestion {\n key: string;\n source: VariableSource;\n /** Display-only — secrets always show as the placeholder string. */\n preview: string;\n}\n\nconst SECRET_PREVIEW = '••••';\n\n/**\n * Walk a ResolutionScope in precedence order and produce one suggestion\n * per unique key. Used by the editor's `{{` autocomplete and Monaco's\n * completion provider.\n */\nexport function collectVariableSuggestions(scope: ResolutionScope): VariableSuggestion[] {\n const seen = new Map<string, VariableSuggestion>();\n const push = (key: string, source: VariableSource, preview: string) => {\n if (!seen.has(key)) seen.set(key, { key, source, preview });\n };\n for (const [k, v] of Object.entries(scope.contextVars)) {\n push(k, 'context', v);\n }\n for (const [k, v] of Object.entries(scope.activeEnv)) {\n push(k, 'active-env', v);\n }\n for (const env of scope.priorityEnvs) {\n for (const [k, v] of Object.entries(env)) {\n push(k, 'priority-env', v);\n }\n }\n for (const k of Object.keys(scope.secrets)) {\n push(k, 'secret', SECRET_PREVIEW);\n }\n return [...seen.values()].sort((a, b) => a.key.localeCompare(b.key));\n}\n\n/**\n * Suggestions to show given a cursor position inside a text field. Returns\n * `null` when the cursor isn't inside an open `{{ … }}` token, so callers\n * can hide the popup. When inside a token, returns matches filtered by the\n * partial token text.\n */\nexport function getVariableAutocomplete(\n text: string,\n cursorPosition: number,\n scope: ResolutionScope,\n): VariableSuggestion[] | null {\n const before = text.slice(0, cursorPosition);\n const openIdx = before.lastIndexOf('{{');\n if (openIdx === -1) return null;\n const fragment = before.slice(openIdx + 2);\n // If the user already closed the token, don't suggest anymore.\n if (fragment.includes('}}')) return null;\n const query = fragment.trim().toLowerCase();\n return collectVariableSuggestions(scope).filter((s) =>\n query.length === 0 ? true : s.key.toLowerCase().includes(query),\n );\n}\n","// Resolve a request's auth by walking up the folder chain when the request\n// itself sets `inherit`. Returns the first explicit (non-`inherit`,\n// non-`none`) auth found on an ancestor folder. Falls back to `{ type: 'none' }`\n// when the chain has nothing to inherit from.\n//\n// Pure function — same input always yields the same output. Used by the\n// workspace executor *before* calling `buildRequest`, so the request reaches\n// the wire with a concrete auth.\n\nimport type { Folder, RequestAuth } from '@apicircle/shared';\n\nconst NONE: RequestAuth = { type: 'none' };\n\nexport interface ResolveInheritedAuthArgs {\n /** The request's stated auth (may be `{ type: 'inherit' }`). */\n requestAuth: RequestAuth;\n /** The folderId the request lives in (null if at the root). */\n folderId: string | null;\n /** All known folders, keyed by id. */\n folders: Record<string, Folder>;\n}\n\n/**\n * If `requestAuth` is anything other than `inherit`, returns it unchanged.\n * Otherwise walks up the folder chain looking for the first folder whose\n * own `auth` is set and is not itself `inherit` or `none`. Folders with\n * `inherit` or `none` auth are transparent (skipped, walk continues).\n */\nexport function resolveInheritedAuth({\n requestAuth,\n folderId,\n folders,\n}: ResolveInheritedAuthArgs): RequestAuth {\n if (requestAuth.type !== 'inherit') return requestAuth;\n\n // Walk up from folderId. Bail at root (parentId === null) or first concrete auth.\n let cursor = folderId;\n const visited = new Set<string>();\n while (cursor !== null) {\n if (visited.has(cursor)) {\n // Defensive: cycle in folder.parentId would otherwise loop forever.\n // The data model says this shouldn't happen, but cheap to guard.\n break;\n }\n visited.add(cursor);\n const folder = folders[cursor];\n if (!folder) break;\n const auth = folder.auth;\n if (auth && auth.type !== 'inherit' && auth.type !== 'none') return auth;\n cursor = folder.parentId;\n }\n return NONE;\n}\n","// Pre-send validation. Lints a Request against the resolved variable\n// scope and returns warnings (non-blocking) and blockers (Send is\n// disabled until they're cleared).\n//\n// Rules — keep them simple, fast, and grounded in the actual request shape:\n// 1. Every `{{var}}` reference in URL / headers / query / cookies / body\n// resolves in the active scope. Unresolved → warning.\n// 2. Every path placeholder (`{name}` or `:name`) has a non-empty value\n// in `pathParams`. Empty → warning.\n// 3. If body type ∈ {json, xml, urlencoded, graphql} but the user-set\n// Content-Type doesn't match the body type, warn.\n// 4. If auth.type requires fields (token/key/etc.) and they're blank,\n// block. Without these the request will fail at send-time.\n//\n// Returns warnings + blockers separately so the UI can render them\n// distinctly: warnings are yellow + Send-still-allowed, blockers are\n// red + Send-disabled.\n\nimport type { Folder, Request as ApiRequest } from '@apicircle/shared';\nimport { findPathPlaceholders } from './buildRequest';\nimport { resolveString, type ResolutionScope } from '../environment/variableResolver';\nimport { resolveInheritedAuth } from './resolveInheritedAuth';\n\nexport interface PreSendWarning {\n kind:\n | 'unresolved-variable'\n | 'unbound-path-param'\n | 'content-type-mismatch'\n | 'url-embedded-credentials';\n message: string;\n}\n\nexport interface PreSendBlocker {\n kind: 'auth-fields-missing' | 'unparseable-url' | 'empty-url';\n message: string;\n}\n\nexport interface PreSendValidationResult {\n warnings: PreSendWarning[];\n blockers: PreSendBlocker[];\n}\n\n/** Inputs to the validator — the request + resolution scope. */\nexport interface PreSendValidationInput {\n request: ApiRequest;\n scope: ResolutionScope;\n /**\n * Folder map keyed by id. When provided AND the request's `auth.type` is\n * `inherit`, the validator resolves the upward chain via\n * `resolveInheritedAuth` and validates the EFFECTIVE auth's field\n * completeness — so an empty-token folder bearer doesn't slip past the\n * pre-send check. Omit for callers that don't have folder context (legacy\n * tests, ad-hoc plan steps), and the validator falls back to checking the\n * declared auth as-is.\n */\n folders?: Record<string, Folder>;\n}\n\nconst TYPED_BODY_CT: Record<string, string[]> = {\n json: ['application/json', 'application/ld+json', 'application/vnd.api+json'],\n xml: ['application/xml', 'text/xml'],\n urlencoded: ['application/x-www-form-urlencoded'],\n graphql: ['application/graphql', 'application/json'],\n};\n\nfunction collectMissing(value: string, scope: ResolutionScope): string[] {\n return resolveString(value, scope).missing;\n}\n\nexport function preSendValidation({\n request,\n scope,\n folders,\n}: PreSendValidationInput): PreSendValidationResult {\n const warnings: PreSendWarning[] = [];\n const blockers: PreSendBlocker[] = [];\n\n // Rule 0: URL is required. Empty URL is always a blocker — without it\n // there is nothing to send. Unparseable URLs (after variable resolution)\n // are also blockers, since the fetch layer would throw on send.\n const urlTrimmed = request.url.trim();\n if (urlTrimmed === '') {\n blockers.push({ kind: 'empty-url', message: 'URL is required.' });\n } else {\n const { value: resolvedUrl, missing: urlMissing } = resolveString(request.url, scope);\n // Only attempt to parse if the URL has no unresolved {{var}} references —\n // otherwise the warning from Rule 1 is the right signal, not a blocker.\n if (urlMissing.length === 0) {\n try {\n // URL constructor throws on malformed input. Accept relative paths\n // (starting with /) since the runtime may be configured with a base.\n if (!resolvedUrl.startsWith('/')) {\n const parsed = new URL(resolvedUrl);\n // Embedded user:pass@host credentials persist into history and\n // get sent on the wire as Basic auth (Chromium converts the\n // userinfo into an `Authorization` header). Warn the user so\n // they can move the credentials into the Auth tab instead,\n // where they go through the Secret Vault and aren't echoed in\n // history records.\n if (parsed.username || parsed.password) {\n warnings.push({\n kind: 'url-embedded-credentials',\n message:\n 'URL contains embedded user:pass credentials. These are sent as Basic auth ' +\n 'and persisted into request history. Move them to the Auth tab to keep them out of stored runs.',\n });\n }\n }\n } catch {\n blockers.push({\n kind: 'unparseable-url',\n message: `URL \"${resolvedUrl}\" is not a valid URL.`,\n });\n }\n }\n }\n\n // Rule 1: unresolved variables in URL / headers / query / cookies / body.\n const unresolved = new Set<string>();\n for (const name of collectMissing(request.url, scope)) unresolved.add(name);\n for (const row of request.headers ?? []) {\n if (!row.enabled) continue;\n for (const n of collectMissing(row.key, scope)) unresolved.add(n);\n for (const n of collectMissing(row.value, scope)) unresolved.add(n);\n }\n for (const row of request.query ?? []) {\n if (!row.enabled) continue;\n for (const n of collectMissing(row.key, scope)) unresolved.add(n);\n for (const n of collectMissing(row.value, scope)) unresolved.add(n);\n }\n for (const row of request.cookies ?? []) {\n if (!row.enabled) continue;\n for (const n of collectMissing(row.key, scope)) unresolved.add(n);\n for (const n of collectMissing(row.value, scope)) unresolved.add(n);\n }\n if (request.body && 'content' in request.body && typeof request.body.content === 'string') {\n for (const n of collectMissing(request.body.content, scope)) unresolved.add(n);\n }\n for (const name of unresolved) {\n warnings.push({\n kind: 'unresolved-variable',\n message: `Variable \"${name}\" is referenced but not defined in the active scope.`,\n });\n }\n\n // Rule 2: unbound path placeholders.\n const placeholders = findPathPlaceholders(request.url);\n const pathParams = request.pathParams ?? {};\n for (const name of placeholders) {\n const value = pathParams[name];\n if (value === undefined || value.trim() === '') {\n warnings.push({\n kind: 'unbound-path-param',\n message: `Path parameter \"${name}\" is empty; the URL segment will collapse.`,\n });\n }\n }\n\n // Rule 3: Content-Type vs body type alignment (only when user has\n // explicitly set a Content-Type header).\n const userCt = (request.headers ?? [])\n .filter((r) => r.enabled && r.key.trim().toLowerCase() === 'content-type')\n .map((r) => r.value.trim().toLowerCase())[0];\n if (userCt && request.body) {\n const allowed = TYPED_BODY_CT[request.body.type];\n if (allowed && !allowed.some((ct) => userCt.startsWith(ct))) {\n warnings.push({\n kind: 'content-type-mismatch',\n message: `Body type \"${request.body.type}\" but Content-Type is \"${userCt}\". This may cause the server to reject the request.`,\n });\n }\n }\n\n // Rule 4: blank auth fields for types that require them. When the request\n // declares `auth.type === 'inherit'` AND the caller provided `folders`,\n // resolve through the inherit chain so a folder-level bearer with an\n // empty token gets caught here instead of slipping through to fail on the\n // wire. When `folders` is omitted (legacy callers), we fall back to the\n // declared auth — same behavior as before.\n let effectiveAuth = request.auth;\n let resolvedFromInherit = false;\n if (folders && effectiveAuth?.type === 'inherit') {\n effectiveAuth = resolveInheritedAuth({\n requestAuth: { type: 'inherit' },\n folderId: request.folderId,\n folders,\n });\n resolvedFromInherit = true;\n }\n const auth = effectiveAuth;\n const inheritedNote = resolvedFromInherit ? ' (resolved from folder-level auth)' : '';\n if (auth) {\n if (auth.type === 'bearer' && !auth.token?.trim()) {\n blockers.push({\n kind: 'auth-fields-missing',\n message: `Bearer token is empty.${inheritedNote}`,\n });\n } else if (auth.type === 'basic') {\n if (!auth.username?.trim() || !auth.password?.trim()) {\n blockers.push({\n kind: 'auth-fields-missing',\n message: `Basic auth requires both username and password.${inheritedNote}`,\n });\n }\n } else if (auth.type === 'api-key') {\n if (!auth.key?.trim() || !auth.value?.trim()) {\n blockers.push({\n kind: 'auth-fields-missing',\n message: `API key auth requires both name and value.${inheritedNote}`,\n });\n }\n } else if (auth.type === 'custom-header') {\n if (!auth.key?.trim()) {\n blockers.push({\n kind: 'auth-fields-missing',\n message: `Custom header auth requires a header name.${inheritedNote}`,\n });\n }\n }\n }\n\n return { warnings, blockers };\n}\n","/**\n * SHA-512/256 — FIPS 180-4 §6.7. Required by HTTP Digest auth (RFC 7616\n * §3.5.1) which mandates the FIPS 180-4 truncation variant, NOT a naive\n * truncation of SHA-512. The two differ because SHA-512/256 uses\n * different initial hash values (IVs); the round function is identical\n * to SHA-512.\n *\n * WebCrypto exposes SHA-512 but not SHA-512/256, and there's no API to\n * supply custom IVs, so we implement the full compression function\n * inline. Ported from the FIPS 180-4 specification, validated against\n * the canonical NIST test vectors:\n *\n * SHA-512/256(\"abc\") = 53048e2681941ef99b2e29b76b4c7dde\n * 9f2492c4d6311e9cc4571d9f0fe8b22a\n *\n * Internal module — not exported from the package barrel. Imported by\n * `digest.ts` for `algorithm=SHA-512-256` Digest challenges. Performance\n * is not critical here (Digest auth is rare and inputs are tiny), so we\n * use BigInt arithmetic for clarity over a hand-rolled 64-bit emulation.\n */\n\nconst MASK64 = 0xffffffffffffffffn;\n\n/** SHA-512/256 IVs per FIPS 180-4 §5.3.6.2 (different from SHA-512's). */\nconst IV: ReadonlyArray<bigint> = [\n 0x22312194fc2bf72cn,\n 0x9f555fa3c84c64c2n,\n 0x2393b86b6f53b151n,\n 0x963877195940eabdn,\n 0x96283ee2a88effe3n,\n 0xbe5e1e2553863992n,\n 0x2b0199fc2c85b8aan,\n 0x0eb72ddc81c52ca2n,\n];\n\n/** SHA-512 / SHA-512/256 share the same 80 round constants (FIPS 180-4 §4.2.3). */\nconst K: ReadonlyArray<bigint> = [\n 0x428a2f98d728ae22n,\n 0x7137449123ef65cdn,\n 0xb5c0fbcfec4d3b2fn,\n 0xe9b5dba58189dbbcn,\n 0x3956c25bf348b538n,\n 0x59f111f1b605d019n,\n 0x923f82a4af194f9bn,\n 0xab1c5ed5da6d8118n,\n 0xd807aa98a3030242n,\n 0x12835b0145706fben,\n 0x243185be4ee4b28cn,\n 0x550c7dc3d5ffb4e2n,\n 0x72be5d74f27b896fn,\n 0x80deb1fe3b1696b1n,\n 0x9bdc06a725c71235n,\n 0xc19bf174cf692694n,\n 0xe49b69c19ef14ad2n,\n 0xefbe4786384f25e3n,\n 0x0fc19dc68b8cd5b5n,\n 0x240ca1cc77ac9c65n,\n 0x2de92c6f592b0275n,\n 0x4a7484aa6ea6e483n,\n 0x5cb0a9dcbd41fbd4n,\n 0x76f988da831153b5n,\n 0x983e5152ee66dfabn,\n 0xa831c66d2db43210n,\n 0xb00327c898fb213fn,\n 0xbf597fc7beef0ee4n,\n 0xc6e00bf33da88fc2n,\n 0xd5a79147930aa725n,\n 0x06ca6351e003826fn,\n 0x142929670a0e6e70n,\n 0x27b70a8546d22ffcn,\n 0x2e1b21385c26c926n,\n 0x4d2c6dfc5ac42aedn,\n 0x53380d139d95b3dfn,\n 0x650a73548baf63den,\n 0x766a0abb3c77b2a8n,\n 0x81c2c92e47edaee6n,\n 0x92722c851482353bn,\n 0xa2bfe8a14cf10364n,\n 0xa81a664bbc423001n,\n 0xc24b8b70d0f89791n,\n 0xc76c51a30654be30n,\n 0xd192e819d6ef5218n,\n 0xd69906245565a910n,\n 0xf40e35855771202an,\n 0x106aa07032bbd1b8n,\n 0x19a4c116b8d2d0c8n,\n 0x1e376c085141ab53n,\n 0x2748774cdf8eeb99n,\n 0x34b0bcb5e19b48a8n,\n 0x391c0cb3c5c95a63n,\n 0x4ed8aa4ae3418acbn,\n 0x5b9cca4f7763e373n,\n 0x682e6ff3d6b2b8a3n,\n 0x748f82ee5defb2fcn,\n 0x78a5636f43172f60n,\n 0x84c87814a1f0ab72n,\n 0x8cc702081a6439ecn,\n 0x90befffa23631e28n,\n 0xa4506cebde82bde9n,\n 0xbef9a3f7b2c67915n,\n 0xc67178f2e372532bn,\n 0xca273eceea26619cn,\n 0xd186b8c721c0c207n,\n 0xeada7dd6cde0eb1en,\n 0xf57d4f7fee6ed178n,\n 0x06f067aa72176fban,\n 0x0a637dc5a2c898a6n,\n 0x113f9804bef90daen,\n 0x1b710b35131c471bn,\n 0x28db77f523047d84n,\n 0x32caab7b40c72493n,\n 0x3c9ebe0a15c9bebcn,\n 0x431d67c49c100d4cn,\n 0x4cc5d4becb3e42b6n,\n 0x597f299cfc657e2an,\n 0x5fcb6fab3ad6faecn,\n 0x6c44198c4a475817n,\n];\n\nfunction ror64(x: bigint, n: bigint): bigint {\n return ((x >> n) | (x << (64n - n))) & MASK64;\n}\n\nfunction shr64(x: bigint, n: bigint): bigint {\n return (x >> n) & MASK64;\n}\n\n/**\n * Compute the SHA-512/256 digest of `bytes` and return it as a 64-char\n * lowercase hex string. Public surface — `digest.ts` calls this for\n * `algorithm=SHA-512-256` HA1/HA2 hashing.\n */\nexport function sha512_256(bytes: Uint8Array): string {\n // Padding (FIPS 180-4 §5.1.2): append 0x80, zero-pad to 128|112 bytes,\n // then a 128-bit big-endian length. We never approach 2^64 input bytes\n // in practice, so the high 64 bits of the length are always zero.\n const msgLen = bytes.length;\n const bitLen = BigInt(msgLen) * 8n;\n // After the 0x80 byte we want the total length to be ≡ 112 (mod 128)\n // so the appended 16-byte length field puts the message at a multiple\n // of 128 bytes (one 1024-bit block).\n let padBytes = 112 - ((msgLen + 1) % 128);\n if (padBytes < 0) padBytes += 128;\n const padded = new Uint8Array(msgLen + 1 + padBytes + 16);\n padded.set(bytes);\n padded[msgLen] = 0x80;\n // High 64 bits of length: zero. Low 64 bits: bitLen, big-endian.\n for (let i = 0; i < 8; i++) {\n padded[padded.length - 1 - i] = Number((bitLen >> BigInt(i * 8)) & 0xffn);\n }\n\n let h: bigint[] = [...IV];\n\n // Process each 1024-bit (128-byte) block. `W` is the message schedule;\n // 80 BigInt words filled in below before any read.\n const W: bigint[] = new Array<bigint>(80);\n for (let block = 0; block < padded.length; block += 128) {\n // Initial 16 message-schedule words are big-endian 64-bit slices.\n for (let t = 0; t < 16; t++) {\n let w = 0n;\n for (let j = 0; j < 8; j++) {\n w = (w << 8n) | BigInt(padded[block + t * 8 + j]);\n }\n W[t] = w;\n }\n // Extend to 80 words via the message-schedule recurrence.\n for (let t = 16; t < 80; t++) {\n const wm15 = W[t - 15];\n const wm2 = W[t - 2];\n const s0 = ror64(wm15, 1n) ^ ror64(wm15, 8n) ^ shr64(wm15, 7n);\n const s1 = ror64(wm2, 19n) ^ ror64(wm2, 61n) ^ shr64(wm2, 6n);\n W[t] = (W[t - 16] + s0 + W[t - 7] + s1) & MASK64;\n }\n\n let a = h[0];\n let b = h[1];\n let c = h[2];\n let d = h[3];\n let e = h[4];\n let f = h[5];\n let g = h[6];\n let hh = h[7];\n\n for (let t = 0; t < 80; t++) {\n const S1 = ror64(e, 14n) ^ ror64(e, 18n) ^ ror64(e, 41n);\n const ch = (e & f) ^ (~e & MASK64 & g);\n const T1 = (hh + S1 + ch + K[t] + W[t]) & MASK64;\n const S0 = ror64(a, 28n) ^ ror64(a, 34n) ^ ror64(a, 39n);\n const maj = (a & b) ^ (a & c) ^ (b & c);\n const T2 = (S0 + maj) & MASK64;\n hh = g;\n g = f;\n f = e;\n e = (d + T1) & MASK64;\n d = c;\n c = b;\n b = a;\n a = (T1 + T2) & MASK64;\n }\n\n h = [\n (h[0] + a) & MASK64,\n (h[1] + b) & MASK64,\n (h[2] + c) & MASK64,\n (h[3] + d) & MASK64,\n (h[4] + e) & MASK64,\n (h[5] + f) & MASK64,\n (h[6] + g) & MASK64,\n (h[7] + hh) & MASK64,\n ];\n }\n\n // SHA-512/256 output: first 256 bits = first 4 H values, big-endian hex.\n let out = '';\n for (let i = 0; i < 4; i++) out += h[i].toString(16).padStart(16, '0');\n return out;\n}\n","import { md5 } from './_legacyHashes';\nimport { sha512_256 } from './_sha512_256';\n\n/**\n * HTTP Digest Access Authentication (RFC 7616, supersedes RFC 2617).\n *\n * Digest is a challenge-response scheme: the client makes a request, the\n * server responds 401 with `WWW-Authenticate: Digest ...`, and the client\n * retries with `Authorization: Digest ...` carrying a hash of the\n * credentials + the server-supplied nonce. This module owns the parsing\n * of the challenge directives and the construction of the response\n * header. The challenge round-trip itself lives in `executeRequest` —\n * it's the engine's job to fire the first request, see the 401, call\n * back here, and re-send.\n *\n * Algorithm support: MD5 (default), MD5-sess, SHA-256, SHA-256-sess,\n * SHA-512-256, and the `-sess` variants. MD5 is required for interop\n * with the long tail of legacy servers; the implementation is in the\n * private `_legacyHashes` module so the rest of the codebase doesn't\n * grow new MD5 callsites.\n */\n\nexport interface DigestChallenge {\n realm: string;\n nonce: string;\n /** Comma-separated list per RFC 7616; the first one we recognize wins. */\n qop?: string;\n opaque?: string;\n algorithm?: string;\n /** Server-supplied opaque token returned verbatim in the response. */\n domain?: string;\n /** Stale=true means the previous nonce expired but credentials are still valid. */\n stale?: string;\n /** Any directives we don't model end up here for diagnostics. */\n [extra: string]: string | undefined;\n}\n\n/**\n * Parse the value of a `WWW-Authenticate: Digest ...` header into its\n * directives. The header may appear with or without the `Digest ` prefix\n * (callers sometimes strip it); both forms work.\n *\n * Quoted values have the surrounding quotes removed; unquoted values are\n * taken as-is up to the next comma or whitespace. Unknown directives are\n * preserved on the returned object so diagnostics can surface them.\n */\nexport function parseDigestChallenge(header: string): DigestChallenge {\n const stripped = header.replace(/^\\s*Digest\\s+/i, '');\n const params: Record<string, string> = {};\n const re = /(\\w+)\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|([^\\s,]+))/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(stripped)) !== null) {\n const key = m[1].toLowerCase();\n const value = m[2] !== undefined ? m[2].replace(/\\\\(.)/g, '$1') : (m[3] ?? '');\n params[key] = value;\n }\n return {\n realm: params['realm'] ?? '',\n nonce: params['nonce'] ?? '',\n qop: params['qop'],\n opaque: params['opaque'],\n algorithm: params['algorithm'],\n domain: params['domain'],\n stale: params['stale'],\n ...params,\n };\n}\n\n/**\n * Algorithm preference order for multi-challenge servers (RFC 7616 §3.7\n * + RFC 7235 §4.1). When a server offers more than one `WWW-Authenticate:\n * Digest` header, the client SHOULD pick the strongest. We rank\n * SHA-512-256 highest (256-bit truncated SHA-512), then SHA-256, then\n * MD5 last — MD5 is GPU-crackable for weak passwords against a captured\n * nonce so we only fall back to it when the server offers nothing else.\n *\n * The `-sess` variants are equivalent in strength to their base; we\n * preserve the server's choice within an algorithm family.\n */\nconst ALGO_RANK: Record<string, number> = {\n 'sha-512-256': 3,\n 'sha-512-256-sess': 3,\n 'sha-256': 2,\n 'sha-256-sess': 2,\n md5: 1,\n 'md5-sess': 1,\n};\n\n/**\n * Pick the strongest Digest challenge from a stacked-header response.\n *\n * `wwwAuthHeaders` is the raw value of every `WWW-Authenticate` header the\n * server sent. The `fetch` API folds multiple headers of the same name\n * into a comma-joined string, but `Digest` challenges themselves contain\n * commas (in `qop=auth,auth-int` etc.), so we can't naively split on\n * comma. Instead we look for the literal token `Digest ` at the start of\n * the trimmed string AND inside the string preceded by `, ` (no other\n * authentication scheme uses that prefix). Each split candidate is\n * parsed; we keep the one with the highest algorithm rank.\n *\n * Falls back to a single parse when only one Digest challenge is found,\n * matching the existing single-challenge behaviour byte-for-byte.\n */\nexport function selectStrongestDigestChallenge(wwwAuthHeader: string): DigestChallenge | null {\n const stripped = wwwAuthHeader.trim();\n if (!stripped) return null;\n // Split on `, Digest ` boundaries — preserves the first challenge as-is\n // and slices subsequent ones. Adding `Digest ` back to each piece so\n // `parseDigestChallenge` can strip the prefix uniformly.\n const pieces = stripped\n .split(/,\\s*(?=Digest\\s)/i)\n .map((p) => p.trim())\n .filter(Boolean);\n if (pieces.length === 0) return null;\n let best: DigestChallenge | null = null;\n let bestRank = -1;\n for (const piece of pieces) {\n const challenge = parseDigestChallenge(piece);\n if (!challenge.realm || !challenge.nonce) continue;\n const algoRaw = (challenge.algorithm ?? 'MD5').toLowerCase();\n const rank = ALGO_RANK[algoRaw] ?? 0;\n if (rank > bestRank) {\n best = challenge;\n bestRank = rank;\n }\n }\n return best;\n}\n\nexport interface BuildDigestArgs {\n method: string;\n /** Request URI as it appears on the wire (path + query, not the full URL). */\n uri: string;\n username: string;\n password: string;\n challenge: DigestChallenge;\n /**\n * Override for the client nonce. If omitted, 16 random hex chars are\n * generated via `crypto.getRandomValues`. Tests pass a fixed value to\n * make the resulting header deterministic.\n */\n cnonce?: string;\n /**\n * Nonce-count, per RFC 7616 §3.4. Each request reusing the same server\n * nonce should bump nc; we default to 1 because the engine clears the\n * stored challenge when the server rotates the nonce. 8 hex chars,\n * lowercase.\n */\n nc?: string;\n /**\n * Body for `qop=auth-int` (entity-body hash). Ignored for `qop=auth`.\n * Strings, `Uint8Array`, `ArrayBuffer`, and `Blob` are all hashable;\n * if `null`/`undefined` we still emit auth-int but with the empty-body\n * hash. FormData / ReadableStream callers should serialize first\n * (auth-int requires the EXACT bytes the server will see).\n */\n entityBody?: string | Uint8Array | ArrayBuffer | Blob | null;\n}\n\nconst SUPPORTED_ALGOS = new Set([\n 'md5',\n 'md5-sess',\n 'sha-256',\n 'sha-256-sess',\n 'sha-512-256',\n 'sha-512-256-sess',\n]);\n\n/**\n * Build the `Authorization: Digest ...` header value (without the\n * `Authorization:` prefix — caller prepends it).\n *\n * Returns a string ready to put on the wire. Throws when the challenge\n * specifies an algorithm we don't support; the engine should surface\n * that as a \"this server's auth scheme isn't supported yet\" error\n * rather than retrying forever.\n */\nexport async function buildDigestAuthHeader(args: BuildDigestArgs): Promise<string> {\n const { method, uri, username, password, challenge } = args;\n const algorithmRaw = (challenge.algorithm ?? 'MD5').toLowerCase();\n if (!SUPPORTED_ALGOS.has(algorithmRaw)) {\n throw new Error(`Digest algorithm not supported: ${challenge.algorithm}`);\n }\n // Phase 11 hardening: surface a console warning whenever the server\n // selects MD5 (or MD5-sess). MD5 is the spec default but is GPU-\n // crackable for weak passwords — a MITM that swaps nonces effectively\n // gets a free password-cracking oracle. We can't refuse the server's\n // choice (that would break interop with the long tail of legacy\n // appliances that only speak MD5), but we MUST make sure the operator\n // knows what's happening. A future Auth follow-up wires this through\n // the structured `authWarnings` channel and surfaces a UI banner; for\n // now the dev-console message is the visibility floor.\n if (algorithmRaw === 'md5' || algorithmRaw === 'md5-sess') {\n console.warn(\n '[apicircle] Digest auth: server selected MD5 — credentials are vulnerable to ' +\n 'GPU offline cracking against the captured nonce. Ask the server operator to ' +\n 'offer SHA-256 (RFC 7616) or SHA-512-256.',\n );\n }\n const isSess = algorithmRaw.endsWith('-sess');\n const baseAlgo = algorithmRaw.replace(/-sess$/, '');\n\n const qop = pickQop(challenge.qop);\n const cnonce = args.cnonce ?? randomHex(8);\n const nc = (args.nc ?? '00000001').toLowerCase();\n\n const hash = (s: string) => digestHash(baseAlgo, s);\n\n // HA1: identity hash. `-sess` variants re-hash with the nonces so that\n // the long-term password isn't reused across sessions.\n let ha1 = await hash(`${username}:${challenge.realm}:${password}`);\n if (isSess) ha1 = await hash(`${ha1}:${challenge.nonce}:${cnonce}`);\n\n // HA2: method + URI (+ entity-body hash for auth-int).\n let ha2: string;\n if (qop === 'auth-int') {\n const bodyBytes = await coerceEntityBody(args.entityBody);\n const bodyHash = await hashBytes(baseAlgo, bodyBytes);\n ha2 = await hash(`${method}:${uri}:${bodyHash}`);\n } else {\n ha2 = await hash(`${method}:${uri}`);\n }\n\n const response = qop\n ? await hash(`${ha1}:${challenge.nonce}:${nc}:${cnonce}:${qop}:${ha2}`)\n : await hash(`${ha1}:${challenge.nonce}:${ha2}`);\n\n const parts: string[] = [\n `username=\"${escapeQuotedString(username)}\"`,\n `realm=\"${escapeQuotedString(challenge.realm)}\"`,\n `nonce=\"${escapeQuotedString(challenge.nonce)}\"`,\n `uri=\"${escapeQuotedString(uri)}\"`,\n `response=\"${response}\"`,\n ];\n if (challenge.algorithm) parts.push(`algorithm=${challenge.algorithm}`);\n if (qop) parts.push(`qop=${qop}`, `nc=${nc}`, `cnonce=\"${escapeQuotedString(cnonce)}\"`);\n if (challenge.opaque) parts.push(`opaque=\"${escapeQuotedString(challenge.opaque)}\"`);\n return `Digest ${parts.join(', ')}`;\n}\n\nfunction pickQop(qopHeader: string | undefined): 'auth' | 'auth-int' | '' {\n if (!qopHeader) return '';\n const options = qopHeader.split(',').map((s) => s.trim().toLowerCase());\n // Prefer auth over auth-int because auth-int requires hashing the\n // request body which most clients don't do; servers that support both\n // accept either.\n if (options.includes('auth')) return 'auth';\n if (options.includes('auth-int')) return 'auth-int';\n return '';\n}\n\nasync function digestHash(baseAlgo: string, input: string): Promise<string> {\n if (baseAlgo === 'md5') return md5(input);\n return hashBytes(baseAlgo, new TextEncoder().encode(input));\n}\n\nasync function hashBytes(baseAlgo: string, bytes: Uint8Array): Promise<string> {\n if (baseAlgo === 'md5') {\n // MD5 over raw bytes — feed the bytes as a Latin-1 string so md5()'s\n // string-mode walks each byte as a code point. This matches the\n // standard interpretation: MD5 is byte-oriented; UTF-8 string input\n // is just bytes that happen to be UTF-8.\n let s = '';\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);\n return md5(s);\n }\n if (baseAlgo === 'sha-512-256') {\n // FIPS 180-4 SHA-512/256 — distinct from a naive truncation of\n // SHA-512 because it uses different IVs. RFC 7616 §3.5.1 mandates\n // this exact variant for `algorithm=SHA-512-256` Digest challenges.\n return sha512_256(bytes);\n }\n // SHA-256 (RFC 7616 §3.5.1) — WebCrypto handles this natively.\n const buf = bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength,\n ) as ArrayBuffer;\n const hash = await crypto.subtle.digest('SHA-256', buf);\n const out = new Uint8Array(hash);\n return Array.from(out, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nasync function coerceEntityBody(\n body: string | Uint8Array | ArrayBuffer | Blob | null | undefined,\n): Promise<Uint8Array> {\n if (body == null) return new Uint8Array(0);\n if (typeof body === 'string') return new TextEncoder().encode(body);\n if (body instanceof Uint8Array) return body;\n if (body instanceof ArrayBuffer) return new Uint8Array(body);\n if (typeof Blob !== 'undefined' && body instanceof Blob) {\n return new Uint8Array(await body.arrayBuffer());\n }\n // Unknown body shape — refuse rather than silently hashing\n // `[object Object]`. The typed contract above is exhaustive, so reaching\n // here means the caller passed something the type system didn't catch\n // (FormData, ReadableStream, …). Auth-int requires the EXACT bytes the\n // server will see, so a wrong hash here is worse than a clear error.\n throw new Error(\n `Digest auth-int: unsupported entity-body type ${typeof body === 'object' && body !== null ? body.constructor.name : typeof body}; serialize to string/Uint8Array/ArrayBuffer/Blob first`,\n );\n}\n\nfunction randomHex(byteLen: number): string {\n const buf = new Uint8Array(byteLen);\n crypto.getRandomValues(buf);\n return Array.from(buf, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\n/** Escape backslashes and double-quotes for RFC 7616 quoted-string values. */\nfunction escapeQuotedString(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n","import type { Request as ApiRequest } from '@apicircle/shared';\nimport { buildRequest, type AttachmentResolver } from './buildRequest';\nimport type { AutoHeaderOverrides } from './autoHeaders';\nimport { type AuthApplyOptions, type AuthApplyWarning } from './applyAuth';\nimport {\n buildDigestAuthHeader,\n parseDigestChallenge,\n selectStrongestDigestChallenge,\n} from '../auth/digest';\nimport {\n buildNtlmType3Authenticate,\n decodeNtlmBase64,\n parseNtlmType2Challenge,\n} from '../auth/ntlm';\n\nexport interface ExecutionResult {\n startedAt: string;\n durationMs: number;\n status: number | null; // null when the request never completed (network error)\n ok: boolean;\n statusText: string;\n headers: Record<string, string>;\n body: string;\n bodyKind: 'json' | 'text' | 'binary' | 'empty';\n error?: string;\n url: string;\n method: string;\n /**\n * Non-fatal warnings from applyAuth (e.g. malformed JWT key, bad\n * payload JSON). Empty array when auth applied cleanly. UI surfaces\n * these alongside the response so users can see WHY their request\n * went out unauthenticated.\n */\n authWarnings: AuthApplyWarning[];\n /**\n * True when the response body exceeded `MAX_RESPONSE_BODY_BYTES` and we\n * stopped reading. The `body` field still contains the prefix we did\n * read — callers should render a \"Response truncated at X MB\" badge.\n * Omitted when the body was read in full.\n */\n responseTruncated?: boolean;\n}\n\nexport interface ExecuteOptions {\n fetchImpl?: typeof fetch;\n // Hard timeout in ms. Defaults to 30s; null disables.\n timeoutMs?: number | null;\n signal?: AbortSignal;\n // Resolver for form-data file rows and binary bodies. When a request\n // references a file slot and the resolver is missing or returns null, the\n // send fails loudly instead of silently omitting the file.\n resolveAttachment?: AttachmentResolver;\n /**\n * applyAuth options — `onTokenRefreshed` is the important one for\n * production: the store wires it to persist refreshed OAuth2 tokens\n * back into `RequestAuth` so subsequent sends see the new state.\n */\n authOptions?: AuthApplyOptions;\n /**\n * Test-only override hooks for the auto-fed headers. Lets specs feed\n * deterministic values for `X-Trace-Span-Id`, `traceparent`, etc.\n * Production callers omit this.\n */\n autoHeaderOverrides?: AutoHeaderOverrides;\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Hard cap on the response body we'll buffer. An attacker-controlled server\n * can stream gigabytes with chunked transfer-encoding; we abort the read\n * once we cross this threshold and surface the truncation in the result. */\nconst MAX_RESPONSE_BODY_BYTES = 50 * 1024 * 1024;\n\n/** Max redirects we'll follow before giving up. RFC 7231 §6.4 doesn't\n * mandate a number; 10 matches what curl uses by default. */\nconst MAX_REDIRECTS = 10;\n\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\n/** Headers we strip on every cross-origin redirect — they carry credentials\n * that the new origin must not see. */\nconst CROSS_ORIGIN_STRIP_HEADERS = new Set([\n 'authorization',\n 'cookie',\n 'proxy-authorization',\n 'x-api-key',\n 'x-auth-token',\n]);\n\nfunction sameOrigin(a: string, b: string): boolean {\n try {\n const ua = new URL(a);\n const ub = new URL(b);\n return ua.protocol === ub.protocol && ua.host === ub.host;\n } catch {\n return false;\n }\n}\n\nfunction stripCrossOriginHeaders(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (CROSS_ORIGIN_STRIP_HEADERS.has(k.toLowerCase())) continue;\n out[k] = v;\n }\n return out;\n}\n\n/** Resolve a (possibly relative) Location-header value against the request\n * URL. The fetch spec uses the URL of the response that produced the\n * redirect; we honour that by passing the current `from`. */\nfunction resolveLocation(from: string, location: string): string | null {\n try {\n return new URL(location, from).toString();\n } catch {\n return null;\n }\n}\n\n/** True when running inside a browser-style fetch implementation, where\n * `redirect: 'manual'` yields an opaqueredirect response that we can't\n * read headers/status from. Node's undici exposes those fields fully so\n * the manual redirect loop can drive the chain itself. */\nfunction isBrowserRuntime(): boolean {\n return typeof window !== 'undefined' && typeof window.document !== 'undefined';\n}\n\n/**\n * Execute a request through the browser's fetch (or an injected impl for\n * tests). Returns a flat ExecutionResult — never throws for HTTP errors.\n * Network failures and timeouts are captured into result.error with status=null.\n *\n * Challenge-driven auth (Digest, NTLM) is handled here: when the first\n * fetch returns 401 with a recognized `WWW-Authenticate` scheme, we\n * compute the response header and re-fetch once. NTLM further requires a\n * second retry to send the Type-3 Authenticate after the Type-2\n * Challenge — that's transparent to the caller, the returned result\n * reflects the FINAL response.\n */\nexport async function executeRequest(\n req: ApiRequest,\n opts: ExecuteOptions = {},\n): Promise<ExecutionResult> {\n const fetchImpl = opts.fetchImpl ?? globalThis.fetch;\n const timeoutMs = opts.timeoutMs === undefined ? DEFAULT_TIMEOUT_MS : opts.timeoutMs;\n\n const startedAt = new Date().toISOString();\n const t0 =\n typeof performance !== 'undefined' && typeof performance.now === 'function'\n ? performance.now()\n : Date.now();\n\n let built: Awaited<ReturnType<typeof buildRequest>> | null = null;\n const controller = new AbortController();\n const externalAbort = () => controller.abort(opts.signal!.reason);\n if (opts.signal) {\n if (opts.signal.aborted) controller.abort(opts.signal.reason);\n else opts.signal.addEventListener('abort', externalAbort, { once: true });\n }\n let timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n\n try {\n built = await buildRequest(req, {\n resolveAttachment: opts.resolveAttachment,\n authOptions: opts.authOptions,\n autoHeaderOverrides: opts.autoHeaderOverrides,\n });\n const builtRequest = built;\n timeoutHandle =\n timeoutMs === null\n ? null\n : setTimeout(\n () => controller.abort(new Error(`Request timed out after ${timeoutMs}ms`)),\n timeoutMs,\n );\n // Redirect handling has to fork by runtime:\n //\n // - In Node fetch the spec's default `redirect: 'follow'` preserves\n // `Authorization` / `Cookie` headers across cross-origin redirects,\n // so a `302 Location: https://attacker/` from a legitimate host\n // would exfiltrate the bearer/basic credential. We pass\n // `redirect: 'manual'`, walk the chain ourselves, and strip\n // credential headers at each cross-origin hop.\n //\n // - Browser fetch returns an opaqueredirect response when given\n // `redirect: 'manual'` (type === 'opaqueredirect', status === 0,\n // headers unreadable), so the same code path stalls before the\n // first hop. Browsers already strip `Authorization` across\n // cross-origin redirects per the Fetch spec §4.4 step 13, so we\n // delegate to the platform with `redirect: 'follow'` instead of\n // trying to drive the chain ourselves.\n const redirectMode: RequestRedirect = isBrowserRuntime() ? 'follow' : 'manual';\n let currentUrl = builtRequest.url;\n try {\n const parsedUrl = new URL(currentUrl);\n if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {\n throw new Error(`Unsupported URL scheme: ${parsedUrl.protocol}`);\n }\n } catch (e) {\n if (e instanceof Error && e.message.startsWith('Unsupported URL scheme')) throw e;\n throw new Error(`Invalid request URL: ${currentUrl}`);\n }\n let currentHeaders: Record<string, string> = { ...builtRequest.headers };\n let currentMethod = builtRequest.method;\n let currentBody: BodyInit | null = builtRequest.body;\n let response = await fetchImpl(currentUrl, {\n method: currentMethod,\n headers: currentHeaders,\n body: currentBody,\n signal: controller.signal,\n redirect: redirectMode,\n });\n let redirectCount = 0;\n while (REDIRECT_STATUSES.has(response.status) && redirectCount < MAX_REDIRECTS) {\n const location = response.headers.get('location');\n if (!location) break;\n const nextUrl = resolveLocation(currentUrl, location);\n if (!nextUrl) break;\n // 303 always converts to GET with no body. 301/302 also convert\n // non-GET to GET for most browsers (legacy compat). 307/308 preserve\n // method + body.\n const preserveMethod = response.status === 307 || response.status === 308;\n const nextMethod = preserveMethod ? currentMethod : currentMethod === 'HEAD' ? 'HEAD' : 'GET';\n const nextBody = preserveMethod ? currentBody : null;\n const isCrossOrigin = !sameOrigin(currentUrl, nextUrl);\n const nextHeaders = isCrossOrigin\n ? stripCrossOriginHeaders(currentHeaders)\n : { ...currentHeaders };\n // Drain the previous response body so the underlying socket isn't\n // left holding bytes.\n try {\n await response.text();\n } catch {\n /* ignore */\n }\n currentUrl = nextUrl;\n currentHeaders = nextHeaders;\n currentMethod = nextMethod;\n currentBody = nextBody;\n response = await fetchImpl(currentUrl, {\n method: currentMethod,\n headers: currentHeaders,\n body: currentBody,\n signal: controller.signal,\n redirect: redirectMode,\n });\n redirectCount++;\n }\n if (REDIRECT_STATUSES.has(response.status)) {\n // Hit the cap — surface as an error rather than silently returning\n // the redirect response (which the caller wouldn't know what to do\n // with).\n throw new Error(`Too many redirects (>${MAX_REDIRECTS})`);\n }\n\n // Auth-challenge retry loop. Acts only on 401 with a matching\n // scheme. We allow up to 2 retries:\n // - 1st: standard challenge response (Digest or NTLM Type-3).\n // - 2nd: only fires when Digest server replies `stale=true` with\n // a fresh nonce. RFC 7616 §3.4 requires the client to retry\n // with the new nonce + bumped nc. Anything beyond that is a\n // real auth failure we surface as-is.\n const challengeAuth = req.auth;\n let retryCount = 0;\n let nc = '00000001';\n while (\n response.status === 401 &&\n challengeAuth &&\n (challengeAuth.type === 'digest' || challengeAuth.type === 'ntlm') &&\n retryCount < 2\n ) {\n const wwwAuth = response.headers.get('www-authenticate');\n if (!wwwAuth) break;\n\n // Stop after first retry unless the server explicitly says stale=true.\n // Use the strongest-challenge selector so a multi-algo server's stale\n // signal on the SHA-256 challenge isn't missed because we happened\n // to grab the MD5 one first.\n if (retryCount === 1) {\n const challenge = selectStrongestDigestChallenge(wwwAuth) ?? parseDigestChallenge(wwwAuth);\n if (!/^true$/i.test(challenge.stale ?? '')) break;\n nc = bumpNc(nc);\n }\n\n const retried = await runChallengeRetry({\n fetchImpl,\n builtUrl: currentUrl,\n builtMethod: currentMethod,\n builtHeaders: currentHeaders,\n builtBody: currentBody,\n signal: controller.signal,\n wwwAuth,\n auth: challengeAuth,\n previousResponse: response,\n nc,\n });\n if (!retried) break;\n\n // Drain the previous response body so the underlying connection\n // isn't left holding bytes. Failure here is benign in a test\n // setting (mocked Response) and rare in real fetch — swallow\n // silently rather than emitting console output from a library.\n try {\n await response.text();\n } catch {\n /* ignore — drain failure shouldn't block the retry */\n }\n response = retried;\n retryCount++;\n }\n\n const headers: Record<string, string> = {};\n response.headers.forEach((v, k) => {\n headers[k] = v;\n });\n const contentType = headers['content-type'] ?? '';\n // Stream the body via a reader so we can abort the read once we cross\n // `MAX_RESPONSE_BODY_BYTES`. The previous `await response.text()` would\n // happily buffer a gigabyte attacker-controlled stream into a single\n // string and OOM the renderer. We still build a string (the existing\n // ExecutionResult contract expects one) but cap how much we accept.\n const { text, truncated } = await readResponseCapped(response);\n const bodyKind: ExecutionResult['bodyKind'] =\n text.length === 0\n ? 'empty'\n : contentType.includes('json') ||\n contentType.includes('xml') ||\n contentType.startsWith('text/')\n ? contentType.includes('json')\n ? 'json'\n : 'text'\n : 'binary';\n const t1 =\n typeof performance !== 'undefined' && typeof performance.now === 'function'\n ? performance.now()\n : Date.now();\n return {\n startedAt,\n durationMs: Math.max(0, Math.round(t1 - t0)),\n status: response.status,\n ok: response.ok,\n statusText: response.statusText,\n headers,\n body: text,\n bodyKind,\n url: currentUrl,\n method: currentMethod,\n authWarnings: builtRequest.authWarnings,\n ...(truncated ? { responseTruncated: true } : {}),\n };\n } catch (err) {\n const t1 =\n typeof performance !== 'undefined' && typeof performance.now === 'function'\n ? performance.now()\n : Date.now();\n return {\n startedAt,\n durationMs: Math.max(0, Math.round(t1 - t0)),\n status: null,\n ok: false,\n statusText: '',\n headers: {},\n body: '',\n bodyKind: 'empty',\n error: err instanceof Error ? err.message : String(err),\n // We may have already followed redirects before throwing — report the\n // last URL we tried so the user sees where the error originated.\n url: built?.url ?? req.url,\n method: built?.method ?? req.method,\n authWarnings: built?.authWarnings ?? [],\n };\n } finally {\n if (timeoutHandle !== null) clearTimeout(timeoutHandle);\n if (opts.signal) opts.signal.removeEventListener('abort', externalAbort);\n }\n}\n\n/**\n * One-shot retry that consumes the WWW-Authenticate from a 401 response\n * and runs the matching challenge protocol:\n *\n * - Digest: parse the directives, build an `Authorization: Digest …`\n * from the user's credentials, refetch once.\n * - NTLM: parse the Type-2 from `WWW-Authenticate: NTLM <base64>`,\n * build the Type-3 with the user's credentials + workstation, refetch\n * on the SAME connection (we can't enforce that from `fetch` alone,\n * but most servers accept the Type-3 anyway because the cookie/socket\n * reuse is best-effort under HTTP/2 multiplexing).\n *\n * Returns null when the challenge isn't one we handle (e.g. unrelated\n * 401 from a Bearer expiry); caller falls through with the original 401.\n */\nasync function runChallengeRetry(args: {\n fetchImpl: typeof fetch;\n builtUrl: string;\n builtMethod: string;\n builtHeaders: Record<string, string>;\n builtBody: BodyInit | null;\n signal: AbortSignal;\n wwwAuth: string;\n auth: Extract<ApiRequest['auth'], { type: 'digest' } | { type: 'ntlm' }>;\n previousResponse: Response;\n /** Optional nc override (8 hex chars) — bumped across stale=true retries. */\n nc?: string;\n}): Promise<Response | null> {\n if (args.auth.type === 'digest' && /^digest\\b/i.test(args.wwwAuth)) {\n // Pick the strongest challenge when the server stacks multiple\n // `WWW-Authenticate: Digest` headers (SHA-512-256 / SHA-256 / MD5).\n // For single-challenge servers this returns the same challenge that\n // `parseDigestChallenge` would have produced, so single-algo flows\n // are unchanged.\n const challenge =\n selectStrongestDigestChallenge(args.wwwAuth) ?? parseDigestChallenge(args.wwwAuth);\n if (!challenge.realm || !challenge.nonce) return null;\n const uri = new URL(args.builtUrl).pathname + new URL(args.builtUrl).search;\n // Digest auth-int requires the entity body bytes — string, binary,\n // and Blob all flow through. FormData and one-shot ReadableStream\n // bodies were consumed by the first fetch and CAN'T be replayed —\n // we surface that as an explicit failure rather than silently\n // sending an empty body that the server would reject anyway.\n let entityBody: string | Uint8Array | ArrayBuffer | Blob | null = null;\n const b = args.builtBody;\n if (typeof b === 'string') entityBody = b;\n else if (b instanceof Uint8Array || b instanceof ArrayBuffer) entityBody = b;\n else if (typeof Blob !== 'undefined' && b instanceof Blob) entityBody = b;\n else if (b != null && /\\bauth-int\\b/i.test(challenge.qop ?? '')) {\n // Server requires auth-int but we can't hash the body — fail\n // loudly instead of silently sending an empty hash.\n throw new Error(\n 'Digest auth-int retry needs a hashable body (string / Blob / Uint8Array). ' +\n 'Streaming bodies are consumed by the first fetch and cannot be replayed.',\n );\n }\n const authHeader = await buildDigestAuthHeader({\n method: args.builtMethod,\n uri,\n username: args.auth.username,\n password: args.auth.password,\n challenge,\n entityBody,\n // Pass the previous nonce-count so a `stale=true` retry can bump\n // it appropriately. First retry from a fresh challenge defaults\n // to nc=00000001.\n nc: args.nc,\n });\n return args.fetchImpl(args.builtUrl, {\n method: args.builtMethod,\n headers: setHeaderCaseInsensitive(args.builtHeaders, 'Authorization', authHeader),\n body: args.builtBody,\n signal: args.signal,\n });\n }\n\n if (args.auth.type === 'ntlm' && /^ntlm\\s+/i.test(args.wwwAuth)) {\n const type2Base64 = args.wwwAuth.replace(/^ntlm\\s+/i, '').trim();\n if (!type2Base64) return null;\n let type2;\n try {\n type2 = parseNtlmType2Challenge(type2Base64);\n } catch {\n return null;\n }\n // Recover Type-1 bytes from the Authorization header we sent on the\n // request that triggered this 401. When present, we hand both\n // Type-1 + Type-2 raw bytes into the Type-3 builder so it computes\n // and embeds the MIC per [MS-NLMP] §3.1.5.1.2. When the original\n // request didn't carry an NTLM Authorization (very rare — applyAuth\n // always emits one for `auth.type === 'ntlm'`), we skip MIC and\n // fall back to legacy Type-3 layout.\n const sentAuth = readHeaderCaseInsensitive(args.builtHeaders, 'Authorization');\n const type1Match = sentAuth?.match(/^ntlm\\s+(.+)$/i);\n let type1Bytes: Uint8Array | undefined;\n if (type1Match) {\n try {\n type1Bytes = decodeNtlmBase64(type1Match[1].trim());\n } catch {\n type1Bytes = undefined;\n }\n }\n const type3 = buildNtlmType3Authenticate({\n username: args.auth.username,\n password: args.auth.password,\n domain: args.auth.domain,\n workstation: args.auth.workstation,\n challenge: type2,\n type1Message: type1Bytes,\n type2Message: type1Bytes ? type2.rawBytes : undefined,\n });\n return args.fetchImpl(args.builtUrl, {\n method: args.builtMethod,\n headers: setHeaderCaseInsensitive(args.builtHeaders, 'Authorization', `NTLM ${type3}`),\n body: args.builtBody,\n signal: args.signal,\n });\n }\n\n return null;\n}\n\nfunction setHeaderCaseInsensitive(\n headers: Record<string, string>,\n key: string,\n value: string,\n): Record<string, string> {\n const lower = key.toLowerCase();\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() !== lower) out[k] = v;\n }\n out[key] = value;\n return out;\n}\n\nfunction readHeaderCaseInsensitive(\n headers: Record<string, string>,\n key: string,\n): string | undefined {\n const lower = key.toLowerCase();\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() === lower) return v;\n }\n return undefined;\n}\n\n/** Bump the 8-hex-char nonce-count by 1 (e.g. \"00000001\" → \"00000002\"). */\nfunction bumpNc(nc: string): string {\n const next = parseInt(nc, 16) + 1;\n return next.toString(16).padStart(8, '0');\n}\n\n/**\n * Read a Response body with a hard byte cap. Returns the decoded UTF-8\n * string plus a `truncated` flag. We stream via the body reader so a\n * gigabyte chunked-encoded stream from a hostile server doesn't OOM us —\n * once we've accumulated `MAX_RESPONSE_BODY_BYTES`, we cancel the read and\n * keep the prefix we already have.\n *\n * Fallback path: when the runtime doesn't expose `response.body` (older\n * fetch polyfills, certain test stubs), defer to `response.text()` — the\n * caller is on their own to know they're not facing a hostile server.\n */\nasync function readResponseCapped(\n response: Response,\n): Promise<{ text: string; truncated: boolean }> {\n const body = response.body;\n if (!body || typeof body.getReader !== 'function') {\n // No stream — best-effort. The cap won't fire in this branch, but\n // the response.text() call still resolves to whatever the runtime\n // already buffered.\n return { text: await response.text(), truncated: false };\n }\n const reader = body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n let truncated = false;\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\n total += value.byteLength;\n chunks.push(value);\n if (total >= MAX_RESPONSE_BODY_BYTES) {\n truncated = true;\n try {\n await reader.cancel();\n } catch {\n /* cancel may not be supported in every runtime */\n }\n break;\n }\n }\n } catch {\n // Read errored mid-stream — keep what we have and surface the chunks\n // we've already captured. The outer try/catch in executeRequest will\n // see the underlying network error if there is one.\n }\n // Concatenate + UTF-8 decode. We only need the bytes we kept; if we hit\n // the cap we trim to exactly `MAX_RESPONSE_BODY_BYTES` so the boundary\n // is deterministic for users (otherwise we'd return slightly over the\n // limit on the final chunk).\n const totalLen = truncated ? MAX_RESPONSE_BODY_BYTES : total;\n const out = new Uint8Array(totalLen);\n let offset = 0;\n for (const c of chunks) {\n if (offset >= totalLen) break;\n const slice = offset + c.byteLength > totalLen ? c.subarray(0, totalLen - offset) : c;\n out.set(slice, offset);\n offset += slice.byteLength;\n }\n const text = new TextDecoder('utf-8', { fatal: false }).decode(out);\n return { text, truncated };\n}\n","import type { RequestRun } from '@apicircle/shared';\nimport type { ExecutionResult } from './executeRequest';\n\n/**\n * Adapt a stored `RequestRun` into the `ExecutionResult` shape that\n * `ResponseViewer` consumes. `RequestRun` is the persisted, post-mortem\n * record (kept on `WorkspaceLocal.history` and capped); `ExecutionResult`\n * is the live in-flight value the editor receives. Both expose the same\n * conceptual fields, so the History and Execution detail views can lean\n * on the same renderer instead of forking the layout.\n *\n * The body is `responseBodyPreview` (already capped by\n * `RUN_BODY_PREVIEW_LIMIT`); the editor will show a truncation hint when\n * `RequestRun.responseTruncated` is true.\n */\nexport function requestRunToExecutionResult(run: RequestRun): ExecutionResult {\n return {\n startedAt: run.startedAt,\n durationMs: run.durationMs,\n status: run.status,\n ok: run.ok,\n statusText: run.statusText,\n headers: run.responseHeaders,\n body: run.responseBodyPreview,\n bodyKind: run.responseBodyKind,\n error: run.error,\n url: run.url,\n method: run.method,\n // Historical runs predate the auth-warnings feature; surfacing an\n // empty list is the honest answer (we don't know if there were\n // warnings at the time).\n authWarnings: [],\n };\n}\n","/**\n * PKCE (Proof Key for Code Exchange — RFC 7636) primitives.\n *\n * Authorization-code grant adds a `code_verifier` (43–128 random URL-safe\n * chars) generated on the client. The auth request carries a derived\n * `code_challenge` (either the verifier itself for `plain`, or\n * `BASE64URL(SHA-256(verifier))` for `S256`); the token-exchange request\n * carries the verifier itself. The server confirms `H(verifier) === challenge`\n * before issuing tokens, neutralizing intercepted authorization codes.\n *\n * S256 is the only method we recommend; `plain` exists in the spec for\n * environments without SHA-256 (basically none today). We support both\n * because some legacy IdPs still negotiate `plain` even when S256 is\n * available.\n */\n\n// 64-character subset of the RFC 7636 unreserved set. The drop from 66\n// (the spec's max) to 64 lets us mask with `& 0x3f` instead of `% 66`,\n// which avoids modulo bias — `byte % 66` maps values 0..189 to two chars\n// each and 190..255 to one char each, so two characters appear ~1.34× more\n// often than the rest. Microscopic in 64-byte verifiers, but trivial to fix.\nconst VERIFIER_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n\n/**\n * Generate a fresh PKCE code verifier — 43..128 random characters from\n * the unreserved URL set (RFC 3986 §2.3). Default length is 64, well\n * inside the spec's allowed range.\n *\n * Sampling is uniform: we mask each random byte with `& 0x3f` to project\n * onto exactly 64 alphabet positions, so every alphabet character is\n * equally likely. The earlier `% 66` implementation introduced a small\n * but measurable modulo bias.\n */\nexport function generateCodeVerifier(length: number = 64): string {\n if (length < 43 || length > 128) {\n throw new Error(`PKCE verifier length must be 43..128 (got ${length})`);\n }\n const bytes = new Uint8Array(length);\n crypto.getRandomValues(bytes);\n let out = '';\n for (let i = 0; i < length; i++) {\n out += VERIFIER_ALPHABET[bytes[i] & 0x3f];\n }\n return out;\n}\n\nexport type PkceMethod = 'S256' | 'plain';\n\n/**\n * Compute the `code_challenge` that pairs with a verifier. The browser's\n * SubtleCrypto handles SHA-256; for `plain` we just echo the verifier.\n */\nexport async function computeCodeChallenge(\n verifier: string,\n method: PkceMethod = 'S256',\n): Promise<string> {\n if (method === 'plain') return verifier;\n const data = new TextEncoder().encode(verifier);\n const hash = await crypto.subtle.digest(\n 'SHA-256',\n data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength),\n );\n return base64UrlEncode(new Uint8Array(hash));\n}\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let s = '';\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);\n return btoa(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n","// Parse a `curl` invocation into a partial Request shape. Handles the\n// flags real-world cURL output uses (Postman/Browser/Burp/Chrome dev-tools\n// \"Copy as cURL\"): -X / --request, -H, -d / --data / --data-raw /\n// --data-binary / --data-urlencode, --json, -F (multipart), -u (basic),\n// --url, and bare URL positional args. Multi-line input with `\\`\n// continuations is normalised first.\n//\n// Pure module — no UI / Monaco / fetch coupling. Returns the partial\n// Request fields the editor needs (method, url, headers, body, auth)\n// plus a list of unrecognised tokens so the caller can surface them.\n\nimport type { Request as ApiRequest, RequestAuth, RequestBody } from '@apicircle/shared';\nimport { applyContentTypeForBodyType } from './bodyTypeContentType';\n\nexport interface ParsedCurl {\n method: ApiRequest['method'];\n url: string;\n headers: ApiRequest['headers'];\n query: ApiRequest['query'];\n body: RequestBody;\n auth: RequestAuth;\n /** Unrecognised flags / fragments — the UI can show these as a warning. */\n warnings: string[];\n}\n\nconst HTTP_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']);\n\n/**\n * Tokenise a shell-style argv from a string. Handles single/double quotes,\n * backslash escapes, and whitespace-splitting. Doesn't try to be a full\n * POSIX shell — `$VAR` expansion, command substitution, and globs all\n * pass through verbatim.\n */\nexport function tokenizeCurl(input: string): string[] {\n const tokens: string[] = [];\n let buf = '';\n let i = 0;\n let quote: '\"' | \"'\" | null = null;\n let inToken = false;\n\n const flush = () => {\n if (inToken) tokens.push(buf);\n buf = '';\n inToken = false;\n };\n\n while (i < input.length) {\n const ch = input[i];\n\n // Strip line continuations (`\\` immediately before \\n) when not in a\n // single-quoted region. Normalise CRLF to LF first via the regex below.\n if (quote !== \"'\" && ch === '\\\\' && (input[i + 1] === '\\n' || input[i + 1] === undefined)) {\n i += 2;\n continue;\n }\n\n if (quote) {\n if (ch === quote) {\n quote = null;\n inToken = true;\n i += 1;\n continue;\n }\n if (quote === '\"' && ch === '\\\\' && i + 1 < input.length) {\n // Inside double quotes, backslash escapes the next character.\n buf += input[i + 1];\n i += 2;\n continue;\n }\n buf += ch;\n i += 1;\n continue;\n }\n\n if (ch === '\"' || ch === \"'\") {\n quote = ch;\n inToken = true;\n i += 1;\n continue;\n }\n\n if (ch === '\\\\' && i + 1 < input.length) {\n buf += input[i + 1];\n inToken = true;\n i += 2;\n continue;\n }\n\n if (/\\s/.test(ch)) {\n flush();\n i += 1;\n continue;\n }\n\n buf += ch;\n inToken = true;\n i += 1;\n }\n flush();\n return tokens;\n}\n\nfunction parseHeader(line: string): { key: string; value: string } | null {\n const colon = line.indexOf(':');\n if (colon === -1) return null;\n return {\n key: line.slice(0, colon).trim(),\n value: line.slice(colon + 1).trim(),\n };\n}\n\nfunction parseUrlEncodedBody(raw: string): { body: string; contentType: string } {\n // `--data-urlencode key=value` is sent as application/x-www-form-urlencoded.\n // Multiple --data flags concatenate with `&` — that's handled by the caller.\n return { body: raw, contentType: 'application/x-www-form-urlencoded' };\n}\n\nfunction detectBodyType(body: string, contentType: string): RequestBody['type'] {\n const ct = contentType.toLowerCase();\n if (ct.includes('json')) return 'json';\n if (ct.includes('xml')) return 'xml';\n if (ct.includes('graphql')) return 'graphql';\n if (ct.includes('form-urlencoded')) return 'urlencoded';\n // Heuristic: starts with `{` or `[` → likely JSON even if Content-Type is\n // missing (real-world Postman copy-as-cURL sometimes drops the header).\n const trimmed = body.trim();\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) return 'json';\n if (trimmed.startsWith('<')) return 'xml';\n return 'text';\n}\n\nexport function parseCurl(input: string): ParsedCurl {\n // Normalise CRLF → LF and trim a leading `$ ` prompt that copy-paste\n // sometimes carries.\n const normalised = input.replace(/\\r\\n?/g, '\\n').replace(/^\\s*\\$\\s*/, '');\n const tokens = tokenizeCurl(normalised);\n\n const out: ParsedCurl = {\n method: 'GET',\n url: '',\n headers: [],\n query: [],\n body: { type: 'none', content: '' },\n auth: { type: 'none' },\n warnings: [],\n };\n\n if (tokens.length === 0) {\n out.warnings.push('Empty cURL command');\n return out;\n }\n // Skip the leading `curl` token.\n let i = tokens[0]?.toLowerCase() === 'curl' ? 1 : 0;\n\n // Body accumulators, kept separate so the urlencoded composer can tell a\n // field separator (`&` between `-d` fields) from a literal `&` inside a\n // `--data-urlencode` value: `-d`/`--data` flags carry `&`-separated fields\n // (curl's wire format), `--data-urlencode` carries one discrete field each,\n // `--json` is a verbatim JSON document.\n const dataFlags: string[] = [];\n const urlencodeFields: string[] = [];\n let jsonContent: string | null = null;\n let bodyContentType = '';\n let methodExplicit = false;\n const formRows: NonNullable<RequestBody['formRows']> = [];\n\n const consume = (): string | null => (i < tokens.length ? tokens[i++] : null);\n\n while (i < tokens.length) {\n const tok = tokens[i++];\n\n if (tok === '-X' || tok === '--request') {\n const m = consume();\n if (m && HTTP_METHODS.has(m.toUpperCase())) {\n out.method = m.toUpperCase() as ApiRequest['method'];\n methodExplicit = true;\n } else if (m) {\n out.warnings.push(`Unsupported method \"${m}\"`);\n }\n continue;\n }\n\n if (tok === '-H' || tok === '--header') {\n const v = consume();\n if (!v) continue;\n const parsed = parseHeader(v);\n if (parsed) {\n out.headers.push({ ...parsed, enabled: true });\n } else {\n out.warnings.push(`Skipped malformed header: ${v}`);\n }\n continue;\n }\n\n if (tok === '-d' || tok === '--data' || tok === '--data-raw' || tok === '--data-binary') {\n const v = consume();\n if (v == null) continue;\n dataFlags.push(v);\n continue;\n }\n\n if (tok === '--data-urlencode') {\n const v = consume();\n if (v == null) continue;\n const { body, contentType } = parseUrlEncodedBody(v);\n urlencodeFields.push(body);\n if (!bodyContentType) bodyContentType = contentType;\n continue;\n }\n\n if (tok === '--json') {\n const v = consume();\n if (v == null) continue;\n jsonContent = v;\n continue;\n }\n\n if (tok === '-F' || tok === '--form') {\n const v = consume();\n if (v == null) continue;\n const eq = v.indexOf('=');\n if (eq === -1) {\n out.warnings.push(`Skipped malformed -F: ${v}`);\n continue;\n }\n const key = v.slice(0, eq);\n const value = v.slice(eq + 1);\n // `-F field=@/path` is a file row — we can't reach the file from\n // a paste-import (no FS access in browser), so flag it as a warning\n // and add a placeholder text row keyed by file path. The user can\n // re-attach via the Form-Data UI.\n if (value.startsWith('@')) {\n out.warnings.push(\n `File field \"${key}\" needs manual attach — paste-import can't reach the local file (${value.slice(1)})`,\n );\n formRows.push({ kind: 'file', key, slotId: null, enabled: true });\n } else {\n formRows.push({ kind: 'text', key, value, enabled: true });\n }\n continue;\n }\n\n if (tok === '-u' || tok === '--user') {\n const creds = consume();\n if (!creds) continue;\n const colon = creds.indexOf(':');\n if (colon === -1) {\n out.auth = { type: 'basic', username: creds, password: '' };\n } else {\n out.auth = {\n type: 'basic',\n username: creds.slice(0, colon),\n password: creds.slice(colon + 1),\n };\n }\n continue;\n }\n\n if (tok === '--url') {\n const v = consume();\n if (v) out.url = v;\n continue;\n }\n\n if (\n tok === '--compressed' ||\n tok === '-i' ||\n tok === '--include' ||\n tok === '-s' ||\n tok === '--silent' ||\n tok === '-k' ||\n tok === '--insecure' ||\n tok === '-L' ||\n tok === '--location' ||\n tok === '--verbose' ||\n tok === '-v'\n ) {\n // Output / network flags that don't change request shape.\n continue;\n }\n\n if (tok === '-A' || tok === '--user-agent') {\n const v = consume();\n if (v) out.headers.push({ key: 'User-Agent', value: v, enabled: true });\n continue;\n }\n\n if (tok === '-e' || tok === '--referer') {\n const v = consume();\n if (v) out.headers.push({ key: 'Referer', value: v, enabled: true });\n continue;\n }\n\n if (tok === '-b' || tok === '--cookie') {\n const v = consume();\n if (v) out.headers.push({ key: 'Cookie', value: v, enabled: true });\n continue;\n }\n\n if (tok.startsWith('-')) {\n // Unrecognised flag — many cURL output flags take a value, but we\n // can't tell without a reference table. Surface it.\n out.warnings.push(`Ignored unrecognised flag: ${tok}`);\n continue;\n }\n\n // Bare token = URL (the first one wins; subsequent bare tokens are\n // ignored with a warning).\n if (!out.url) {\n out.url = tok;\n } else {\n out.warnings.push(`Ignored extra positional argument: ${tok}`);\n }\n }\n\n if (!out.url) {\n out.warnings.push('No URL found in cURL command');\n }\n\n // Promote method to POST when a body is present and -X wasn't given —\n // matches cURL's own default.\n if (\n !methodExplicit &&\n (jsonContent !== null ||\n dataFlags.length > 0 ||\n urlencodeFields.length > 0 ||\n formRows.length > 0)\n ) {\n out.method = 'POST';\n }\n\n // Split off query string from the URL into the query[] array. The editor\n // shows params separately so the user can toggle them.\n if (out.url.includes('?')) {\n const [base, qs] = out.url.split('?', 2);\n out.url = base!;\n if (qs) {\n for (const pair of qs.split('&')) {\n if (!pair) continue;\n const eq = pair.indexOf('=');\n const key = decodeURIComponent(eq === -1 ? pair : pair.slice(0, eq));\n const value = eq === -1 ? '' : decodeURIComponent(pair.slice(eq + 1));\n out.query.push({ key, value, enabled: true });\n }\n }\n }\n\n // Compose the body. For form-data: the rows are the body. For everything\n // else, refine the type from the Content-Type header (if user supplied one)\n // or the body shape.\n if (formRows.length > 0) {\n out.body = { type: 'form-data', content: '', formRows };\n } else if (jsonContent !== null) {\n out.body = { type: 'json', content: jsonContent };\n const userContentType = out.headers.find((h) => h.key.toLowerCase() === 'content-type')?.value;\n if (!userContentType) {\n out.headers = applyContentTypeForBodyType(out.headers, 'json');\n }\n } else if (dataFlags.length > 0 || urlencodeFields.length > 0) {\n const userContentType = out.headers.find((h) => h.key.toLowerCase() === 'content-type')?.value;\n const effectiveContentType = userContentType ?? bodyContentType;\n // curl's `-d` family concatenates its fields with `&` on the wire.\n const wireBody = dataFlags.join('&');\n const detectedType: RequestBody['type'] =\n urlencodeFields.length > 0 ? 'urlencoded' : detectBodyType(wireBody, effectiveContentType);\n if (detectedType === 'urlencoded') {\n // Store the raw, newline-delimited `key=value` form `composeBody`\n // expects. `-d` fields are `&`-separated on the wire; `--data-urlencode`\n // fields are already discrete and may carry a literal `&` in a value.\n const fields = [...dataFlags.flatMap((v) => v.split('&')), ...urlencodeFields].filter(\n (f) => f !== '',\n );\n out.body = { type: 'urlencoded', content: fields.join('\\n') };\n } else {\n out.body = { type: detectedType, content: wireBody };\n }\n if (!userContentType) {\n // Auto-fill Content-Type so the request doesn't go out without one.\n out.headers = applyContentTypeForBodyType(out.headers, detectedType);\n }\n }\n\n return out;\n}\n","// Postman v2.1 collection import. Translates the Postman shape into the\n// minimal subset our editor knows how to render: folders + requests with\n// method/url/headers/body. Auth conversion is best-effort (Bearer, Basic,\n// API key); unknown auth types fall through to `{ type: 'none' }`.\n//\n// Reference: https://schema.postman.com/collection/json/v2.1.0/collection.json\n//\n// Exported `parsePostmanCollection` returns either a typed result we can hand\n// to a workspace builder, or a list of warnings. We never throw on\n// recoverable issues — the caller decides whether to surface them.\n\nimport type { BodyType, HttpMethod, RequestAuth, RequestBody } from '@apicircle/shared';\n\nconst POSTMAN_V2_1_SCHEMA_PATTERN = /collection\\/v2(?:\\.[0-9]+)*/;\n\nexport interface ImportedRequest {\n name: string;\n method: HttpMethod;\n url: string;\n headers: Array<{ key: string; value: string; enabled: boolean }>;\n query: Array<{ key: string; value: string; enabled: boolean }>;\n body: RequestBody;\n auth: RequestAuth;\n}\n\nexport interface ImportedFolder {\n name: string;\n /** Index path from root (deterministic id assignment is the caller's job). */\n pathIds: number[];\n parentPathIds: number[] | null;\n /**\n * Folder-level auth captured from the source. Postman v2.1 folders can\n * carry an `auth` field that descendant requests inherit; Insomnia\n * request_group resources expose the same via `authentication`. When\n * present, the importer maps it to `Folder.auth` and descendant requests\n * with no explicit auth resolve via `resolveInheritedAuth` instead of\n * being wired to a duplicate copy.\n */\n auth?: RequestAuth;\n}\n\nexport interface ParsedPostmanCollection {\n collectionName: string;\n folders: ImportedFolder[];\n requests: Array<ImportedRequest & { folderPathIds: number[] | null }>;\n warnings: string[];\n}\n\nconst HTTP_METHODS = new Set<HttpMethod>([\n 'GET',\n 'POST',\n 'PUT',\n 'PATCH',\n 'DELETE',\n 'HEAD',\n 'OPTIONS',\n]);\n\ninterface PostmanItem {\n name?: string;\n item?: PostmanItem[];\n request?: PostmanRequest | string;\n auth?: PostmanAuth;\n}\n\ninterface PostmanRequest {\n method?: string;\n url?: PostmanUrl | string;\n header?: Array<{ key?: string; value?: string; disabled?: boolean }>;\n body?: PostmanBody;\n auth?: PostmanAuth;\n}\n\ninterface PostmanUrl {\n raw?: string;\n host?: string[] | string;\n path?: string[] | string;\n protocol?: string;\n query?: Array<{ key?: string; value?: string; disabled?: boolean }>;\n}\n\ninterface PostmanBody {\n mode?: 'raw' | 'urlencoded' | 'formdata' | 'graphql' | 'binary' | 'file';\n raw?: string;\n options?: { raw?: { language?: string } };\n urlencoded?: Array<{ key?: string; value?: string; disabled?: boolean }>;\n formdata?: Array<{ key?: string; value?: string; type?: 'text' | 'file'; disabled?: boolean }>;\n graphql?: { query?: string; variables?: string };\n}\n\ninterface PostmanAuth {\n type?: string;\n bearer?: Array<{ key?: string; value?: string }>;\n basic?: Array<{ key?: string; value?: string }>;\n apikey?: Array<{ key?: string; value?: string }>;\n}\n\ninterface PostmanCollectionDoc {\n info?: { name?: string; schema?: string };\n item?: PostmanItem[];\n}\n\nexport function isPostmanV2Collection(doc: unknown): boolean {\n if (!doc || typeof doc !== 'object') return false;\n const info = (doc as PostmanCollectionDoc).info;\n if (!info || typeof info.schema !== 'string') return false;\n return POSTMAN_V2_1_SCHEMA_PATTERN.test(info.schema);\n}\n\nexport function parsePostmanCollection(input: string): ParsedPostmanCollection {\n const warnings: string[] = [];\n let parsed: PostmanCollectionDoc;\n try {\n parsed = JSON.parse(input) as PostmanCollectionDoc;\n } catch (err) {\n throw new Error(`Couldn't parse JSON: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!isPostmanV2Collection(parsed)) {\n throw new Error(\n 'Unsupported format. Expected a Postman v2.1 collection (info.schema must include \"collection/v2\"). Use Postman → Export → Collection v2.1.',\n );\n }\n\n const collectionName =\n (parsed.info?.name ?? 'Imported collection').trim() || 'Imported collection';\n const folders: ImportedFolder[] = [];\n const requests: ParsedPostmanCollection['requests'] = [];\n\n const walk = (items: PostmanItem[] | undefined, parentPathIds: number[] | null): void => {\n if (!items || items.length === 0) return;\n items.forEach((item, idx) => {\n const pathIds = parentPathIds ? [...parentPathIds, idx] : [idx];\n // Item is a folder when it has nested items.\n if (Array.isArray(item.item)) {\n // Postman v2.1 folder-level auth: when present, it surfaces here as\n // `item.auth`. Map to Folder.auth so descendant requests can resolve\n // via `inherit` instead of carrying a per-request copy.\n const folderAuth = item.auth ? parseAuth(item.auth, warnings, item.name) : undefined;\n folders.push({\n name: (item.name ?? 'Untitled folder').trim() || 'Untitled folder',\n pathIds,\n parentPathIds: parentPathIds,\n ...(folderAuth && folderAuth.type !== 'none' ? { auth: folderAuth } : {}),\n });\n walk(item.item, pathIds);\n return;\n }\n const built = buildRequest(item, warnings);\n if (built) requests.push({ ...built, folderPathIds: parentPathIds });\n });\n };\n walk(parsed.item, null);\n\n return { collectionName, folders, requests, warnings };\n}\n\nfunction buildRequest(item: PostmanItem, warnings: string[]): ImportedRequest | null {\n const raw = item.request;\n if (!raw) return null;\n if (typeof raw === 'string') {\n return {\n name: (item.name ?? 'Untitled').trim() || 'Untitled',\n method: 'GET',\n url: raw,\n headers: [],\n query: [],\n body: { type: 'none', content: '' },\n auth: { type: 'none' },\n };\n }\n const method = parseMethod(raw.method, warnings, item.name);\n const { url, query } = parseUrl(raw.url);\n const headers = (raw.header ?? [])\n .filter((h): h is { key?: string; value?: string; disabled?: boolean } => Boolean(h))\n .map((h) => ({\n key: (h.key ?? '').trim(),\n value: h.value ?? '',\n enabled: !h.disabled,\n }))\n .filter((h) => h.key.length > 0);\n const body = parseBody(raw.body, warnings, item.name);\n const auth = parseAuth(raw.auth ?? item.auth, warnings, item.name);\n return {\n name: (item.name ?? 'Untitled').trim() || 'Untitled',\n method,\n url,\n headers,\n query,\n body,\n auth,\n };\n}\n\nfunction parseMethod(method: string | undefined, warnings: string[], name?: string): HttpMethod {\n const upper = (method ?? 'GET').toUpperCase();\n if ((HTTP_METHODS as Set<string>).has(upper)) return upper as HttpMethod;\n warnings.push(`Unsupported method \"${method}\" on \"${name ?? 'unknown'}\" — defaulted to GET.`);\n return 'GET';\n}\n\nfunction parseUrl(url: PostmanUrl | string | undefined): {\n url: string;\n query: ImportedRequest['query'];\n} {\n if (!url) return { url: '', query: [] };\n if (typeof url === 'string') return { url, query: [] };\n // Prefer .raw when present — Postman keeps the original spelling there.\n let assembled = url.raw ?? '';\n if (!assembled) {\n const proto = url.protocol ? `${url.protocol}://` : '';\n const host = Array.isArray(url.host) ? url.host.join('.') : (url.host ?? '');\n const path = Array.isArray(url.path) ? url.path.join('/') : (url.path ?? '').replace(/^\\//, '');\n assembled = `${proto}${host}${path ? `/${path}` : ''}`;\n }\n // Strip query string from URL if both raw and structured query are present —\n // we'll re-emit query rows below from the structured list.\n const queryRows = (url.query ?? [])\n .filter((q): q is { key?: string; value?: string; disabled?: boolean } => Boolean(q))\n .map((q) => ({\n key: (q.key ?? '').trim(),\n value: q.value ?? '',\n enabled: !q.disabled,\n }))\n .filter((q) => q.key.length > 0);\n if (queryRows.length > 0 && assembled.includes('?')) {\n assembled = assembled.split('?')[0];\n }\n return { url: assembled, query: queryRows };\n}\n\nfunction parseBody(body: PostmanBody | undefined, warnings: string[], name?: string): RequestBody {\n if (!body || !body.mode) return { type: 'none', content: '' };\n switch (body.mode) {\n case 'raw': {\n const lang = body.options?.raw?.language ?? '';\n const type: BodyType =\n lang === 'json' ? 'json' : lang === 'xml' ? 'xml' : lang === 'graphql' ? 'graphql' : 'text';\n return { type, content: body.raw ?? '' };\n }\n case 'urlencoded': {\n // `body.content` for urlencoded is raw, newline-delimited `key=value`\n // lines — `buildRequest.composeBody` percent-encodes them at send\n // time. Encoding here would double-encode the wire body.\n const rows = body.urlencoded ?? [];\n const content = rows\n .filter((r) => !r.disabled && (r.key ?? '').length > 0)\n .map((r) => `${r.key ?? ''}=${r.value ?? ''}`)\n .join('\\n');\n return { type: 'urlencoded', content };\n }\n case 'graphql': {\n return {\n type: 'graphql',\n content: body.graphql?.query ?? '',\n variables: body.graphql?.variables ?? '',\n };\n }\n case 'formdata': {\n // Form-data file rows can't round-trip without the actual file blob —\n // we drop them here with a warning. Text rows survive as form rows.\n const rows = (body.formdata ?? [])\n .filter((r) => (r.key ?? '').length > 0)\n .map((r) => {\n if (r.type === 'file') {\n warnings.push(\n `Skipped form-data file row \"${r.key}\" on \"${name ?? 'unknown'}\" — re-attach the file in the editor.`,\n );\n return null;\n }\n return {\n kind: 'text' as const,\n key: r.key ?? '',\n value: r.value ?? '',\n enabled: !r.disabled,\n };\n })\n .filter(\n (r): r is { kind: 'text'; key: string; value: string; enabled: boolean } => r !== null,\n );\n return { type: 'form-data', content: '', formRows: rows };\n }\n case 'binary':\n case 'file': {\n warnings.push(\n `Binary body on \"${name ?? 'unknown'}\" not imported — re-attach the file in the editor.`,\n );\n return { type: 'binary', content: '' };\n }\n default:\n warnings.push(\n `Unsupported body mode \"${String((body as { mode: unknown }).mode)}\" on \"${name ?? 'unknown'}\" — body skipped.`,\n );\n return { type: 'none', content: '' };\n }\n}\n\nfunction parseAuth(auth: PostmanAuth | undefined, warnings: string[], name?: string): RequestAuth {\n if (!auth || !auth.type) return { type: 'none' };\n const valueOf = (\n rows: Array<{ key?: string; value?: string }> | undefined,\n key: string,\n ): string => {\n const found = rows?.find((r) => r.key === key);\n return (found?.value ?? '').toString();\n };\n switch (auth.type) {\n case 'bearer':\n return { type: 'bearer', token: valueOf(auth.bearer, 'token') };\n case 'basic':\n return {\n type: 'basic',\n username: valueOf(auth.basic, 'username'),\n password: valueOf(auth.basic, 'password'),\n };\n case 'apikey': {\n const inLocation = (valueOf(auth.apikey, 'in') || 'header').toLowerCase();\n const addTo: 'header' | 'query' | 'cookie' =\n inLocation === 'query' ? 'query' : inLocation === 'cookie' ? 'cookie' : 'header';\n return {\n type: 'api-key',\n key: valueOf(auth.apikey, 'key'),\n value: valueOf(auth.apikey, 'value'),\n addTo,\n };\n }\n case 'noauth':\n return { type: 'none' };\n default:\n warnings.push(\n `Unsupported auth type \"${auth.type}\" on \"${name ?? 'unknown'}\" — set to None. Configure manually in the editor.`,\n );\n return { type: 'none' };\n }\n}\n","// Postman environment import. The Postman environment JSON shape is:\n// { id, name, values: [{ key, value, enabled?, type? }], _postman_variable_scope: 'environment' }\n// We map this onto our Environment type — values become variables, with the\n// `enabled` flag respected (disabled rows are skipped). Postman's `type` field\n// (`secret` etc.) is dropped here — bring values in plaintext; the user can\n// bind to a Vault key after import via the existing Encrypt button.\n\nimport type { EnvironmentVariable } from '@apicircle/shared';\n\nexport interface ParsedPostmanEnvironment {\n /** Suggested env name; the user can change at import time. */\n name: string;\n variables: EnvironmentVariable[];\n warnings: string[];\n}\n\ninterface PostmanEnvDoc {\n name?: string;\n values?: Array<{ key?: string; value?: string; enabled?: boolean; type?: string }>;\n _postman_variable_scope?: string;\n}\n\nexport function isPostmanEnvironment(doc: unknown): boolean {\n if (!doc || typeof doc !== 'object') return false;\n const d = doc as PostmanEnvDoc;\n // The scope field is the cleanest signal. Some exports omit it but include\n // a `name` + `values` array — accept those too as long as `values` looks\n // like an env variable list.\n if (d._postman_variable_scope === 'environment') return true;\n return typeof d.name === 'string' && Array.isArray(d.values);\n}\n\nexport function parsePostmanEnvironment(input: string): ParsedPostmanEnvironment {\n const warnings: string[] = [];\n let parsed: PostmanEnvDoc;\n try {\n parsed = JSON.parse(input) as PostmanEnvDoc;\n } catch (err) {\n throw new Error(`Couldn't parse JSON: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!isPostmanEnvironment(parsed)) {\n throw new Error(\n 'Unsupported format. Expected a Postman environment JSON. Use Postman → Environments → Export.',\n );\n }\n const name = (parsed.name ?? 'Imported environment').trim() || 'Imported environment';\n const variables: EnvironmentVariable[] = [];\n for (const row of parsed.values ?? []) {\n const key = (row.key ?? '').trim();\n if (!key) continue;\n if (row.enabled === false) continue;\n if (row.type === 'secret') {\n warnings.push(\n `\"${key}\" was a Postman secret — imported as plaintext. Bind it to a Vault key in the Environments page if you want to keep it secret.`,\n );\n }\n variables.push({\n key,\n value: row.value ?? '',\n encrypted: false,\n });\n }\n return { name, variables, warnings };\n}\n","// Insomnia v4 export import. Translates the Insomnia \"export\" shape into\n// the same `ParsedPostmanCollection` structure our workspace builder\n// already accepts, so the importer doesn't need a second code path.\n//\n// Reference shape:\n// {\n// \"_type\": \"export\",\n// \"__export_format\": 4,\n// \"resources\": [\n// { \"_type\": \"request\", \"_id\": \"req_...\", \"name\": \"...\", \"method\": \"GET\",\n// \"url\": \"https://...\", \"headers\": [{ name, value }], \"body\": {...},\n// \"parentId\": \"fld_...\" | \"wrk_...\" },\n// { \"_type\": \"request_group\", \"_id\": \"fld_...\", \"name\": \"Auth\",\n// \"parentId\": \"wrk_...\" | \"fld_...\" },\n// { \"_type\": \"workspace\", \"_id\": \"wrk_...\", \"name\": \"...\" },\n// { \"_type\": \"environment\", ... }\n// ]\n// }\n//\n// We surface workspaces + request_groups as folders; requests as requests.\n// Environments live in `insomniaEnvironment.ts`.\n\nimport type { BodyType, HttpMethod, RequestAuth, RequestBody } from '@apicircle/shared';\nimport type { ImportedFolder, ImportedRequest, ParsedPostmanCollection } from './postmanCollection';\n\nconst HTTP_METHODS = new Set<HttpMethod>([\n 'GET',\n 'POST',\n 'PUT',\n 'PATCH',\n 'DELETE',\n 'HEAD',\n 'OPTIONS',\n]);\n\ninterface InsomniaResource {\n _type?: string;\n _id?: string;\n name?: string;\n parentId?: string;\n // Request fields\n method?: string;\n url?: string;\n headers?: Array<{ name?: string; value?: string; disabled?: boolean }>;\n parameters?: Array<{ name?: string; value?: string; disabled?: boolean }>;\n body?: {\n mimeType?: string;\n text?: string;\n params?: Array<{ name?: string; value?: string; disabled?: boolean; type?: string }>;\n };\n authentication?: {\n type?: string;\n token?: string;\n username?: string;\n password?: string;\n key?: string;\n value?: string;\n addTo?: string;\n };\n}\n\ninterface InsomniaExport {\n _type?: string;\n __export_format?: number;\n resources?: InsomniaResource[];\n}\n\nexport function isInsomniaExport(doc: unknown): boolean {\n if (!doc || typeof doc !== 'object') return false;\n const d = doc as InsomniaExport;\n return d._type === 'export' && Array.isArray(d.resources);\n}\n\nexport function parseInsomniaCollection(input: string): ParsedPostmanCollection {\n const warnings: string[] = [];\n let parsed: InsomniaExport;\n try {\n parsed = JSON.parse(input) as InsomniaExport;\n } catch (err) {\n throw new Error(`Couldn't parse JSON: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!isInsomniaExport(parsed)) {\n throw new Error(\n 'Unsupported format. Expected an Insomnia export (`_type: \"export\"` + `resources` array). Use Insomnia → Application → Preferences → Data → Export Data.',\n );\n }\n const resources = parsed.resources ?? [];\n\n // Build id → resource map for parent walks.\n const byId = new Map<string, InsomniaResource>();\n for (const r of resources) if (r._id) byId.set(r._id, r);\n\n // The \"workspace\" resource is the top-level folder; we surface it as the\n // wrapper when present. Otherwise the import lands at the root.\n const workspace = resources.find((r) => r._type === 'workspace');\n const collectionName = workspace?.name?.trim() || 'Imported collection';\n\n // Walk-up the parent chain to compute a folder index path. Each folder\n // gets an array of indices so descendants can find their parent in the\n // post-flat structure expected by our store.\n const folders: ImportedFolder[] = [];\n const folderIndexById = new Map<string, number[]>();\n // The synthetic root has empty path; workspace's children land directly\n // inside the wrapper folder we'll create later.\n if (workspace?._id) folderIndexById.set(workspace._id, []);\n\n // First pass: collect folders (request_group resources), in declaration\n // order. Postman uses index paths but Insomnia is flat — we synthesize\n // the same shape.\n let folderCounter = 0;\n for (const r of resources) {\n if (r._type !== 'request_group') continue;\n const parentPath = r.parentId ? (folderIndexById.get(r.parentId) ?? null) : null;\n const ourPath = parentPath ? [...parentPath, folderCounter++] : [folderCounter++];\n folderIndexById.set(r._id ?? '', ourPath);\n // Insomnia request_group resources can carry an `authentication` field\n // that descendants inherit. Map it to Folder.auth via the same parseAuth\n // path used for requests; `none`-typed auth (or absent) leaves the\n // ImportedFolder without an auth property so the apply-side doesn't\n // spuriously set Folder.auth.\n const folderAuth = r.authentication ? parseAuth(r.authentication, warnings, r.name) : undefined;\n folders.push({\n name: (r.name ?? 'Untitled folder').trim() || 'Untitled folder',\n pathIds: ourPath,\n parentPathIds: parentPath,\n ...(folderAuth && folderAuth.type !== 'none' ? { auth: folderAuth } : {}),\n });\n }\n\n // Second pass: collect requests.\n const requests: ParsedPostmanCollection['requests'] = [];\n for (const r of resources) {\n if (r._type !== 'request') continue;\n const built = buildRequest(r, warnings);\n if (!built) continue;\n const parentPath = r.parentId ? (folderIndexById.get(r.parentId) ?? null) : null;\n requests.push({ ...built, folderPathIds: parentPath });\n }\n\n return { collectionName, folders, requests, warnings };\n}\n\nfunction buildRequest(r: InsomniaResource, warnings: string[]): ImportedRequest | null {\n const method = parseMethod(r.method, warnings, r.name);\n const url = (r.url ?? '').trim();\n const headers = (r.headers ?? [])\n .filter((h): h is { name?: string; value?: string; disabled?: boolean } => Boolean(h))\n .map((h) => ({\n key: (h.name ?? '').trim(),\n value: h.value ?? '',\n enabled: !h.disabled,\n }))\n .filter((h) => h.key.length > 0);\n const query = (r.parameters ?? [])\n .filter((p): p is { name?: string; value?: string; disabled?: boolean } => Boolean(p))\n .map((p) => ({\n key: (p.name ?? '').trim(),\n value: p.value ?? '',\n enabled: !p.disabled,\n }))\n .filter((p) => p.key.length > 0);\n const body = parseBody(r.body, warnings, r.name);\n const auth = parseAuth(r.authentication, warnings, r.name);\n return {\n name: (r.name ?? 'Untitled').trim() || 'Untitled',\n method,\n url,\n headers,\n query,\n body,\n auth,\n };\n}\n\nfunction parseMethod(method: string | undefined, warnings: string[], name?: string): HttpMethod {\n const upper = (method ?? 'GET').toUpperCase();\n if ((HTTP_METHODS as Set<string>).has(upper)) return upper as HttpMethod;\n warnings.push(`Unsupported method \"${method}\" on \"${name ?? 'unknown'}\" — defaulted to GET.`);\n return 'GET';\n}\n\nfunction parseBody(body: InsomniaResource['body'], warnings: string[], name?: string): RequestBody {\n if (!body || (!body.mimeType && !body.text && !body.params)) {\n return { type: 'none', content: '' };\n }\n const mime = (body.mimeType ?? '').toLowerCase();\n if (mime.includes('json')) return { type: 'json', content: body.text ?? '' };\n if (mime.includes('xml')) return { type: 'xml', content: body.text ?? '' };\n if (mime.includes('graphql')) {\n // Insomnia stores GraphQL queries as raw text under text=`{\"query\":\"...\",\n // \"variables\": {...}}`. Try to split.\n try {\n const obj = JSON.parse(body.text ?? '{}') as { query?: string; variables?: unknown };\n return {\n type: 'graphql',\n content: obj.query ?? '',\n variables:\n obj.variables === undefined\n ? ''\n : typeof obj.variables === 'string'\n ? obj.variables\n : JSON.stringify(obj.variables, null, 2),\n };\n } catch {\n return { type: 'graphql', content: body.text ?? '' };\n }\n }\n if (mime.includes('x-www-form-urlencoded')) {\n // `body.content` for urlencoded is raw, newline-delimited `key=value`\n // lines — `buildRequest.composeBody` percent-encodes them at send time.\n const rows = body.params ?? [];\n const content = rows\n .filter((r) => !r.disabled && (r.name ?? '').length > 0)\n .map((r) => `${r.name ?? ''}=${r.value ?? ''}`)\n .join('\\n');\n return { type: 'urlencoded', content };\n }\n if (mime.includes('multipart/form-data')) {\n const rows = (body.params ?? [])\n .filter((p) => (p.name ?? '').length > 0)\n .map((p) => {\n if (p.type === 'file') {\n warnings.push(\n `Skipped form-data file row \"${p.name}\" on \"${name ?? 'unknown'}\" — re-attach the file in the editor.`,\n );\n return null;\n }\n return {\n kind: 'text' as const,\n key: p.name ?? '',\n value: p.value ?? '',\n enabled: !p.disabled,\n };\n })\n .filter(\n (r): r is { kind: 'text'; key: string; value: string; enabled: boolean } => r !== null,\n );\n return { type: 'form-data', content: '', formRows: rows };\n }\n // Anything else: treat as text body.\n const looksLikeText = body.text !== undefined;\n if (!looksLikeText) {\n warnings.push(\n `Body mime \"${body.mimeType}\" on \"${name ?? 'unknown'}\" not imported — re-attach in the editor.`,\n );\n return { type: 'binary', content: '' };\n }\n // Try to guess body type from content prefix when mime is missing/text.\n const text = body.text ?? '';\n const trimmed = text.trim();\n let type: BodyType = 'text';\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) type = 'json';\n else if (trimmed.startsWith('<')) type = 'xml';\n return { type, content: text };\n}\n\nfunction parseAuth(\n auth: InsomniaResource['authentication'],\n warnings: string[],\n name?: string,\n): RequestAuth {\n if (!auth || !auth.type) return { type: 'none' };\n switch (auth.type) {\n case 'bearer':\n return { type: 'bearer', token: auth.token ?? '' };\n case 'basic':\n return {\n type: 'basic',\n username: auth.username ?? '',\n password: auth.password ?? '',\n };\n case 'apikey': {\n const addTo: 'header' | 'query' | 'cookie' =\n auth.addTo === 'queryParams' ? 'query' : auth.addTo === 'cookie' ? 'cookie' : 'header';\n return {\n type: 'api-key',\n key: auth.key ?? '',\n value: auth.value ?? '',\n addTo,\n };\n }\n case 'none':\n return { type: 'none' };\n default:\n warnings.push(\n `Unsupported auth type \"${auth.type}\" on \"${name ?? 'unknown'}\" — set to None. Configure manually in the editor.`,\n );\n return { type: 'none' };\n }\n}\n","// Importer for the `apicircle.folder/v1` JSON envelope produced by\n// `collectFolderExport` in `../export/folderExport.ts`.\n//\n// Pure parser — no IndexedDB / store dependencies. Validates the\n// envelope, allocates fresh ids for every folder/request/dependency so\n// the destination workspace stays collision-free, and remaps every\n// cross-entity reference (request.bodySchemaId, request.graphqlSchemaId,\n// body.attachment.globalFileAssetId, form-row globalFileAssetId,\n// folder.parentId / request.folderId) onto the new ids.\n//\n// The caller (`importApicircleFolder` in the workspace store) walks the\n// resulting `ParsedApicircleFolderExport` and grafts it into the active\n// `WorkspaceSynced`, applying name-based dedupe for global assets to\n// avoid silently shadowing the destination's existing library entries.\n\nimport type {\n Folder,\n GlobalFileAsset,\n GlobalGraphQL,\n GlobalSchema,\n Request as ApiRequest,\n} from '@apicircle/shared';\nimport { generateId } from '@apicircle/shared';\nimport {\n APICIRCLE_FOLDER_EXPORT_FORMAT,\n type ApicircleFolderExportV1,\n} from '../export/folderExport';\n\nexport interface ParsedApicircleFolderExport {\n /** The exported root folder, already assigned a fresh id. */\n rootFolder: {\n id: string;\n name: string;\n auth?: Folder['auth'];\n };\n /** Descendant folders with fresh ids + remapped parentIds. */\n subfolders: Folder[];\n /** Requests with fresh ids + remapped folderIds + remapped asset refs. */\n requests: ApiRequest[];\n /** Dependencies, ids freshly minted. */\n dependencies: {\n schemas: GlobalSchema[];\n graphql: GlobalGraphQL[];\n files: GlobalFileAsset[];\n };\n /** Source envelope's `source.folderName` — used for display copy. */\n sourceFolderName: string;\n /**\n * Notes the parser surfaced about the import — e.g. a stale dependency\n * reference that no longer existed in the source envelope. Importers\n * forward these to the UI as soft warnings.\n */\n warnings: string[];\n}\n\n/** Lightweight discriminator — `true` when `doc.format === 'apicircle.folder/v1'`. */\nexport function isApicircleFolderExport(doc: unknown): doc is ApicircleFolderExportV1 {\n if (!doc || typeof doc !== 'object') return false;\n const d = doc as { format?: unknown };\n return d.format === APICIRCLE_FOLDER_EXPORT_FORMAT;\n}\n\n/**\n * Parse + validate a raw JSON string. Throws with a single, user-readable\n * message when the input is malformed; otherwise returns a parsed shape\n * ready for the store to graft in.\n *\n * `idGenerator` is overridable for deterministic tests; defaults to\n * `generateId()` from `@apicircle/shared`.\n */\nexport function parseApicircleFolderExport(\n input: string,\n options: { idGenerator?: () => string } = {},\n): ParsedApicircleFolderExport {\n let doc: unknown;\n try {\n doc = JSON.parse(input);\n } catch (err) {\n throw new Error(`Couldn't parse JSON: ${err instanceof Error ? err.message : String(err)}`);\n }\n return parseApicircleFolderExportDoc(doc, options);\n}\n\n/**\n * Same as `parseApicircleFolderExport` but skips the JSON.parse step —\n * used by callers that already deserialized the document. Splitting the\n * entry points keeps the validation logic identical.\n */\nexport function parseApicircleFolderExportDoc(\n doc: unknown,\n options: { idGenerator?: () => string } = {},\n): ParsedApicircleFolderExport {\n const id = options.idGenerator ?? generateId;\n\n if (!isApicircleFolderExport(doc)) {\n throw new Error(\n `Unsupported format. Expected an API Circle folder export (\"format\": \"${APICIRCLE_FOLDER_EXPORT_FORMAT}\").`,\n );\n }\n\n const envelope = doc;\n validateEnvelopeShape(envelope);\n\n const warnings: string[] = [];\n\n // --- Allocate fresh ids -----------------------------------------------\n const folderIdMap = new Map<string, string>();\n folderIdMap.set(envelope.source.folderId, id());\n for (const f of envelope.folder.subfolders) folderIdMap.set(f.id, id());\n\n const requestIdMap = new Map<string, string>();\n for (const r of envelope.folder.requests) requestIdMap.set(r.id, id());\n\n const schemaIdMap = new Map<string, string>();\n for (const s of envelope.dependencies.schemas) schemaIdMap.set(s.id, id());\n const graphqlIdMap = new Map<string, string>();\n for (const g of envelope.dependencies.graphql) graphqlIdMap.set(g.id, id());\n const fileIdMap = new Map<string, string>();\n for (const f of envelope.dependencies.files) fileIdMap.set(f.id, id());\n\n // --- Remap subfolders --------------------------------------------------\n const rootFolderId = folderIdMap.get(envelope.source.folderId)!;\n const subfolders: Folder[] = envelope.folder.subfolders.map((f) => {\n const newId = folderIdMap.get(f.id)!;\n // parentId === source.folderId → remap to the new root.\n // parentId === some other source folder id → remap to its new id.\n // parentId === null (legacy export at root) → attach under new root.\n let newParentId: string | null;\n if (f.parentId === null) {\n newParentId = rootFolderId;\n } else {\n const mapped = folderIdMap.get(f.parentId);\n if (!mapped) {\n warnings.push(\n `Subfolder \"${f.name}\" referenced parentId \"${f.parentId}\" that wasn't present in the export — reattached under \"${envelope.folder.name}\".`,\n );\n newParentId = rootFolderId;\n } else {\n newParentId = mapped;\n }\n }\n return {\n ...f,\n id: newId,\n parentId: newParentId,\n auth: f.auth ? { ...f.auth } : undefined,\n };\n });\n\n // --- Remap dependencies -----------------------------------------------\n const schemas: GlobalSchema[] = envelope.dependencies.schemas.map((s) => ({\n ...s,\n id: schemaIdMap.get(s.id)!,\n }));\n const graphql: GlobalGraphQL[] = envelope.dependencies.graphql.map((g) => ({\n ...g,\n id: graphqlIdMap.get(g.id)!,\n }));\n const files: GlobalFileAsset[] = envelope.dependencies.files.map((f) => ({\n ...f,\n id: fileIdMap.get(f.id)!,\n }));\n\n // --- Remap requests ----------------------------------------------------\n const requests: ApiRequest[] = envelope.folder.requests.map((r) => {\n const newId = requestIdMap.get(r.id)!;\n // folderId may be null (legacy export at root) — attach to new root.\n let newFolderId: string | null;\n if (r.folderId === null) {\n newFolderId = rootFolderId;\n } else {\n const mapped = folderIdMap.get(r.folderId);\n if (!mapped) {\n warnings.push(\n `Request \"${r.name}\" referenced folderId \"${r.folderId}\" that wasn't present in the export — reattached under \"${envelope.folder.name}\".`,\n );\n newFolderId = rootFolderId;\n } else {\n newFolderId = mapped;\n }\n }\n\n const bodySchemaId = remapDependencyRef(\n r.bodySchemaId,\n schemaIdMap,\n `Request \"${r.name}\".bodySchemaId`,\n warnings,\n );\n const graphqlSchemaId = remapDependencyRef(\n r.graphqlSchemaId,\n graphqlIdMap,\n `Request \"${r.name}\".graphqlSchemaId`,\n warnings,\n );\n\n return {\n ...r,\n id: newId,\n folderId: newFolderId,\n bodySchemaId,\n graphqlSchemaId,\n headers: r.headers.map((h) => ({ ...h })),\n query: r.query.map((q) => ({ ...q })),\n pathParams: r.pathParams ? { ...r.pathParams } : undefined,\n cookies: r.cookies ? r.cookies.map((c) => ({ ...c })) : undefined,\n body: remapBodyFileRefs(r.body, fileIdMap, r.name, warnings),\n auth: { ...r.auth },\n contextVars: r.contextVars.map((v) => ({ ...v })),\n extractions: r.extractions.map((e) => ({ ...e })),\n assertions: r.assertions.map((a) => ({ ...a })),\n };\n });\n\n return {\n rootFolder: {\n id: rootFolderId,\n name: envelope.folder.name,\n auth: envelope.folder.auth ? { ...envelope.folder.auth } : undefined,\n },\n subfolders,\n requests,\n dependencies: { schemas, graphql, files },\n sourceFolderName: envelope.source.folderName,\n warnings,\n };\n}\n\n// -- internals --------------------------------------------------------------\n\nfunction validateEnvelopeShape(envelope: ApicircleFolderExportV1): void {\n if (!envelope.folder || typeof envelope.folder !== 'object') {\n throw new Error('API Circle folder export is missing the \"folder\" section.');\n }\n if (typeof envelope.folder.name !== 'string' || envelope.folder.name.length === 0) {\n throw new Error('API Circle folder export must have a non-empty \"folder.name\".');\n }\n if (!Array.isArray(envelope.folder.subfolders)) {\n throw new Error('API Circle folder export must have a \"folder.subfolders\" array.');\n }\n if (!Array.isArray(envelope.folder.requests)) {\n throw new Error('API Circle folder export must have a \"folder.requests\" array.');\n }\n if (!envelope.dependencies || typeof envelope.dependencies !== 'object') {\n throw new Error('API Circle folder export is missing the \"dependencies\" section.');\n }\n if (\n !Array.isArray(envelope.dependencies.schemas) ||\n !Array.isArray(envelope.dependencies.graphql) ||\n !Array.isArray(envelope.dependencies.files)\n ) {\n throw new Error(\n 'API Circle folder export \"dependencies\" must have schemas / graphql / files arrays.',\n );\n }\n if (!envelope.source || typeof envelope.source !== 'object') {\n throw new Error('API Circle folder export is missing the \"source\" section.');\n }\n if (\n typeof envelope.source.folderId !== 'string' ||\n typeof envelope.source.folderName !== 'string'\n ) {\n throw new Error('API Circle folder export \"source\" must include \"folderId\" and \"folderName\".');\n }\n}\n\nfunction remapDependencyRef(\n value: string | null | undefined,\n map: Map<string, string>,\n label: string,\n warnings: string[],\n): string | null | undefined {\n if (value === null || value === undefined) return value;\n const mapped = map.get(value);\n if (mapped) return mapped;\n warnings.push(\n `${label} referenced a dependency (\"${value}\") that wasn't embedded in the export — reference dropped on import.`,\n );\n return null;\n}\n\nfunction remapBodyFileRefs(\n body: ApiRequest['body'],\n fileIdMap: Map<string, string>,\n requestName: string,\n warnings: string[],\n): ApiRequest['body'] {\n if (body.type === 'binary') {\n if (!body.attachment) return { ...body };\n const oldId = body.attachment.globalFileAssetId;\n let nextGlobalFileAssetId: string | null | undefined = oldId;\n if (oldId) {\n const mapped = fileIdMap.get(oldId);\n if (mapped) {\n nextGlobalFileAssetId = mapped;\n } else {\n warnings.push(\n `Request \"${requestName}\".body.attachment referenced file asset \"${oldId}\" that wasn't embedded in the export — re-attach the file after import.`,\n );\n nextGlobalFileAssetId = null;\n }\n }\n return {\n ...body,\n attachment: {\n ...body.attachment,\n // Reset slotId — the destination workspace owns its own slots.\n slotId: null,\n globalFileAssetId: nextGlobalFileAssetId,\n },\n };\n }\n if (body.type === 'form-data') {\n const formRows = body.formRows?.map((row) => {\n if (row.kind !== 'file') return { ...row };\n const oldId = row.globalFileAssetId;\n let nextGlobalFileAssetId: string | null | undefined = oldId;\n if (oldId) {\n const mapped = fileIdMap.get(oldId);\n if (mapped) {\n nextGlobalFileAssetId = mapped;\n } else {\n warnings.push(\n `Request \"${requestName}\" form-data row \"${row.key}\" referenced file asset \"${oldId}\" that wasn't embedded in the export — re-attach the file after import.`,\n );\n nextGlobalFileAssetId = null;\n }\n }\n return {\n ...row,\n slotId: null,\n globalFileAssetId: nextGlobalFileAssetId,\n };\n });\n return { ...body, formRows };\n }\n return { ...body };\n}\n","// Credential detection + opt-in redaction for `apicircle.folder/v1`\n// exports.\n//\n// The export envelope copies `RequestAuth` verbatim from the source\n// workspace, which means it can carry live secrets (bearer tokens,\n// OAuth2 client secrets / refresh tokens, AWS secret keys, NTLM\n// passwords, JWT signing material, …). Letting a user click \"Download\"\n// without confronting them with what's about to leave the workspace is\n// the same kind of bug `redactForGit` exists to prevent on the Git path\n// — except the export path is a *user-initiated* share, so the right\n// model is opt-in inclusion rather than silent redaction.\n//\n// Two pure helpers below:\n//\n// 1. `collectFolderExportCredentials(envelope)` — enumerates every\n// credential-bearing field inside the envelope's `folder.auth`,\n// `subfolders[*].auth`, and `requests[*].auth`. Returns one\n// `FolderExportCredential` per field, with a stable composite id\n// the UI can use as a React key and as the index into the\n// include-set.\n//\n// 2. `redactFolderExportCredentials(envelope, include)` — returns a\n// new envelope with EVERY detected credential blanked, except\n// the ones whose ids appear in `include`. Pure; safe to call on\n// partial envelopes. The default-redact-all semantics match the\n// Modal's UI: every checkbox starts unchecked, so by default the\n// downloaded file carries zero secrets.\n\nimport type { RequestAuth } from '@apicircle/shared';\nimport type { ApicircleFolderExportV1 } from './folderExport';\n\n/**\n * One credential-bearing field discovered inside an export envelope.\n *\n * `id` is a stable composite that survives ordering / re-serialization\n * — UIs can use it as the React key and as the `include` set member.\n *\n * Format:\n * - Root folder auth: `folder:<envelope.source.folderId>.<authType>.<field>`\n * - Subfolder auth: `folder:<subfolder.id>.<authType>.<field>`\n * - Request auth: `request:<request.id>.<authType>.<field>`\n */\nexport interface FolderExportCredential {\n id: string;\n /** Where the credential lives in the envelope. */\n scope: 'root-folder' | 'subfolder' | 'request';\n /** Discriminator of the auth variant that owns the field. */\n authType: RequestAuth['type'];\n /** Field name on the auth object (e.g. \"token\", \"password\", \"clientSecret\"). */\n field: string;\n /** Human-readable label for the UI (\"Bearer · token\"). */\n label: string;\n /**\n * Where this credential belongs to. For requests this is the\n * request name; for folders it's the folder name. UIs use this to\n * group rows so the user can see which entity is leaking what.\n */\n ownerName: string;\n /** Source-workspace id of the request/folder that owns this field. */\n ownerId: string;\n}\n\n/**\n * Sorted, stable list of every credential-bearing field in the envelope.\n *\n * Determinism: rows are ordered by `(scope-rank, ownerName, field)` so\n * the same envelope always produces the same UI row order. Re-running\n * the detector after the user toggles include-checkboxes returns the\n * same list with the same ids — the UI never needs to remap state.\n *\n * Pure — does not mutate the envelope.\n */\nexport function collectFolderExportCredentials(\n envelope: ApicircleFolderExportV1,\n): FolderExportCredential[] {\n const out: FolderExportCredential[] = [];\n\n if (envelope.folder.auth) {\n out.push(\n ...authCredentialFields(envelope.folder.auth).map((f) =>\n buildCredential(\n 'root-folder',\n envelope.source.folderId,\n envelope.folder.name,\n envelope.folder.auth as RequestAuth,\n f,\n ),\n ),\n );\n }\n for (const sub of envelope.folder.subfolders) {\n if (!sub.auth) continue;\n out.push(\n ...authCredentialFields(sub.auth).map((f) =>\n buildCredential('subfolder', sub.id, sub.name, sub.auth as RequestAuth, f),\n ),\n );\n }\n for (const req of envelope.folder.requests) {\n out.push(\n ...authCredentialFields(req.auth).map((f) =>\n buildCredential('request', req.id, req.name, req.auth, f),\n ),\n );\n }\n\n return out.sort(credentialCompare);\n}\n\n/**\n * Return a new envelope with every credential-bearing field blanked,\n * except for fields whose `id` appears in `includeIds`. The default\n * (empty `includeIds`) redacts everything — that's the safe default\n * the modal uses when the user hasn't explicitly opted any credential\n * in.\n *\n * The redaction shape mirrors `redactForGit`: credential FIELDS go to\n * `''`, identity fields (`clientId`, `username`, `tokenUrl`, …) stay so\n * the importer still knows which IdP the request originally talked to.\n */\nexport function redactFolderExportCredentials(\n envelope: ApicircleFolderExportV1,\n includeIds: ReadonlySet<string> = new Set(),\n): ApicircleFolderExportV1 {\n const next: ApicircleFolderExportV1 = {\n ...envelope,\n folder: {\n ...envelope.folder,\n auth: envelope.folder.auth\n ? redactAuthForScope(\n envelope.folder.auth,\n credentialIdsFor('root-folder', envelope.source.folderId, envelope.folder.auth),\n includeIds,\n )\n : envelope.folder.auth,\n subfolders: envelope.folder.subfolders.map((sub) => {\n if (!sub.auth) return sub;\n const ids = credentialIdsFor('subfolder', sub.id, sub.auth);\n return {\n ...sub,\n auth: redactAuthForScope(sub.auth, ids, includeIds),\n };\n }),\n requests: envelope.folder.requests.map((req) => ({\n ...req,\n auth: redactAuthForScope(\n req.auth,\n credentialIdsFor('request', req.id, req.auth),\n includeIds,\n ),\n })),\n },\n };\n return next;\n}\n\n// -- internals --------------------------------------------------------------\n\ninterface CredentialFieldDescriptor {\n field: string;\n /** Short variant label used in the UI (\"Bearer · token\"). */\n label: string;\n}\n\n/**\n * Return the credential-bearing fields for a given auth variant. Order\n * matters — the UI renders rows in this order so semantically-related\n * fields stay grouped (e.g. `clientSecret` first, then `accessToken`,\n * then `refreshToken` for OAuth2).\n */\nfunction authCredentialFields(auth: RequestAuth): CredentialFieldDescriptor[] {\n switch (auth.type) {\n case 'none':\n case 'inherit':\n case 'custom-header':\n // `custom-header.value` could be a secret but `redactForGit` also\n // refuses to redact it — users wanting secret semantics should\n // route through Secret Vault + variable interpolation. Same\n // policy here.\n return [];\n case 'basic':\n return [{ field: 'password', label: 'Basic · password' }];\n case 'bearer':\n return auth.token ? [{ field: 'token', label: 'Bearer · token' }] : [];\n case 'api-key':\n return auth.value ? [{ field: 'value', label: 'API key · value' }] : [];\n case 'digest':\n return [{ field: 'password', label: 'Digest · password' }];\n case 'ntlm':\n return [{ field: 'password', label: 'NTLM · password' }];\n case 'hawk':\n return auth.hawkKey ? [{ field: 'hawkKey', label: 'Hawk · hawkKey' }] : [];\n case 'jwt-bearer':\n return [\n ...(auth.secretOrKey ? [{ field: 'secretOrKey', label: 'JWT · secretOrKey' }] : []),\n ...(auth.token ? [{ field: 'token', label: 'JWT · token' }] : []),\n ];\n case 'aws-sigv4':\n return [\n ...(auth.secretAccessKey\n ? [{ field: 'secretAccessKey', label: 'AWS SigV4 · secretAccessKey' }]\n : []),\n ...(auth.sessionToken\n ? [{ field: 'sessionToken', label: 'AWS SigV4 · sessionToken' }]\n : []),\n ];\n case 'oauth2-client-credentials':\n case 'oauth2-auth-code':\n case 'oauth2-pkce':\n return [\n ...(auth.clientSecret\n ? [{ field: 'clientSecret', label: `${auth.type} · clientSecret` }]\n : []),\n ...(auth.accessToken\n ? [{ field: 'accessToken', label: `${auth.type} · accessToken` }]\n : []),\n ...(auth.refreshToken\n ? [{ field: 'refreshToken', label: `${auth.type} · refreshToken` }]\n : []),\n ];\n case 'oauth2-password':\n return [\n ...(auth.clientSecret\n ? [{ field: 'clientSecret', label: 'oauth2-password · clientSecret' }]\n : []),\n ...(auth.password ? [{ field: 'password', label: 'oauth2-password · password' }] : []),\n ...(auth.accessToken\n ? [{ field: 'accessToken', label: 'oauth2-password · accessToken' }]\n : []),\n ...(auth.refreshToken\n ? [{ field: 'refreshToken', label: 'oauth2-password · refreshToken' }]\n : []),\n ];\n case 'oauth2-implicit':\n return auth.accessToken\n ? [{ field: 'accessToken', label: 'oauth2-implicit · accessToken' }]\n : [];\n case 'oauth2-device':\n return [\n ...(auth.accessToken\n ? [{ field: 'accessToken', label: 'oauth2-device · accessToken' }]\n : []),\n ...(auth.refreshToken\n ? [{ field: 'refreshToken', label: 'oauth2-device · refreshToken' }]\n : []),\n ];\n default:\n // Exhaustiveness fallback — same shape as `redactAuthForScope`\n // below. Any synthetic value reaching this arm has no known\n // credential fields, so we surface an empty list.\n return [];\n }\n}\n\nfunction buildCredential(\n scope: FolderExportCredential['scope'],\n ownerId: string,\n ownerName: string,\n auth: RequestAuth,\n desc: CredentialFieldDescriptor,\n): FolderExportCredential {\n const prefix = scope === 'request' ? 'request' : 'folder';\n return {\n id: `${prefix}:${ownerId}.${auth.type}.${desc.field}`,\n scope,\n authType: auth.type,\n field: desc.field,\n label: desc.label,\n ownerName,\n ownerId,\n };\n}\n\nfunction credentialIdsFor(\n scope: FolderExportCredential['scope'],\n ownerId: string,\n auth: RequestAuth,\n): Map<string, string> {\n const ids = new Map<string, string>(); // field -> id\n const prefix = scope === 'request' ? 'request' : 'folder';\n for (const desc of authCredentialFields(auth)) {\n ids.set(desc.field, `${prefix}:${ownerId}.${auth.type}.${desc.field}`);\n }\n return ids;\n}\n\n/**\n * Apply redaction to a single auth value. Any credential field whose\n * id is in `includeIds` is preserved verbatim; the rest are blanked.\n * Variants with no credential fields (`none` / `inherit` / `custom-header`\n * + the unknown-variant default) fall through unchanged.\n */\nfunction redactAuthForScope(\n auth: RequestAuth,\n ids: Map<string, string>,\n includeIds: ReadonlySet<string>,\n): RequestAuth {\n const shouldBlank = (field: string): boolean => {\n const id = ids.get(field);\n return !!id && !includeIds.has(id);\n };\n\n // Spread per-variant so TS keeps each branch's exact shape.\n switch (auth.type) {\n case 'none':\n case 'inherit':\n case 'custom-header':\n return auth;\n case 'basic':\n return shouldBlank('password') ? { ...auth, password: '' } : auth;\n case 'bearer':\n return shouldBlank('token') ? { ...auth, token: '' } : auth;\n case 'api-key':\n return shouldBlank('value') ? { ...auth, value: '' } : auth;\n case 'digest':\n return shouldBlank('password') ? { ...auth, password: '' } : auth;\n case 'ntlm':\n return shouldBlank('password') ? { ...auth, password: '' } : auth;\n case 'hawk':\n return shouldBlank('hawkKey') ? { ...auth, hawkKey: '' } : auth;\n case 'jwt-bearer':\n return {\n ...auth,\n secretOrKey: shouldBlank('secretOrKey') ? '' : auth.secretOrKey,\n token: shouldBlank('token') ? '' : auth.token,\n };\n case 'aws-sigv4':\n return {\n ...auth,\n secretAccessKey: shouldBlank('secretAccessKey') ? '' : auth.secretAccessKey,\n sessionToken: shouldBlank('sessionToken') ? '' : auth.sessionToken,\n };\n case 'oauth2-client-credentials':\n case 'oauth2-auth-code':\n case 'oauth2-pkce':\n return {\n ...auth,\n clientSecret: shouldBlank('clientSecret') ? '' : auth.clientSecret,\n accessToken: shouldBlank('accessToken') ? '' : auth.accessToken,\n refreshToken: shouldBlank('refreshToken') ? '' : auth.refreshToken,\n };\n case 'oauth2-password':\n return {\n ...auth,\n clientSecret: shouldBlank('clientSecret') ? '' : auth.clientSecret,\n password: shouldBlank('password') ? '' : auth.password,\n accessToken: shouldBlank('accessToken') ? '' : auth.accessToken,\n refreshToken: shouldBlank('refreshToken') ? '' : auth.refreshToken,\n };\n case 'oauth2-implicit':\n return {\n ...auth,\n accessToken: shouldBlank('accessToken') ? '' : auth.accessToken,\n };\n case 'oauth2-device':\n return {\n ...auth,\n accessToken: shouldBlank('accessToken') ? '' : auth.accessToken,\n refreshToken: shouldBlank('refreshToken') ? '' : auth.refreshToken,\n };\n default:\n // The discriminated union above is exhaustive. An unknown-variant\n // value can only reach this arm via a deliberate cast (e.g. a\n // future auth type added without wiring this switch); we return\n // it unchanged rather than throwing so the export still produces\n // a valid envelope.\n return auth;\n }\n}\n\nfunction scopeRank(scope: FolderExportCredential['scope']): number {\n if (scope === 'root-folder') return 0;\n if (scope === 'subfolder') return 1;\n return 2;\n}\n\nfunction credentialCompare(a: FolderExportCredential, b: FolderExportCredential): number {\n const r = scopeRank(a.scope) - scopeRank(b.scope);\n if (r !== 0) return r;\n // Tiebreak by owner name only — within a single owner we rely on\n // JS's stable Array.prototype.sort to preserve the per-variant field\n // order from `authCredentialFields` (which puts e.g. clientSecret →\n // accessToken → refreshToken in semantic order).\n return a.ownerName.localeCompare(b.ownerName, undefined, { sensitivity: 'base' });\n}\n","// Folder → JSON export (API Circle exchange format `apicircle.folder/v1`).\n//\n// Produces a self-describing envelope a teammate can import back into any\n// other API Circle workspace via `ImportModal` / the headless\n// `parseApicircleFolderExport` parser. The envelope is intentionally\n// additive on top of the existing `'apicircle'` source-format slot in\n// `ImportModal` — round-tripping an export through a fresh workspace must\n// not silently drop fields.\n//\n// Embedded vs. referenced dependencies:\n// - JSON Schemas + GraphQL definitions are pure text. We embed the full\n// entity so the importer can recreate them in the destination\n// workspace without any extra user action.\n// - Global file assets carry BYTES outside `workspace.json` (Git\n// LFS sidecar under `.apicircle/workspace-<id>/attachments/<slotId>`). The envelope\n// therefore captures only metadata (name, filename, size, mimeType,\n// sha256) so the importer can show the user a clear \"re-attach these\n// files\" cue. Bytes never travel through the JSON.\n//\n// All envelope `id` fields refer to the SOURCE workspace's ids. The\n// importer is expected to remint them on its side to avoid collisions\n// (`apicircleFolder.ts` does this).\n\nimport type {\n Folder,\n GlobalFileAsset,\n GlobalGraphQL,\n GlobalSchema,\n Request as ApiRequest,\n WorkspaceSynced,\n} from '@apicircle/shared';\nimport {\n collectFolderExportCredentials,\n type FolderExportCredential,\n} from './folderExportCredentials';\n\n/** Envelope discriminator. Bump the version suffix on a breaking shape change. */\nexport const APICIRCLE_FOLDER_EXPORT_FORMAT = 'apicircle.folder/v1';\n\nexport interface ApicircleFolderExportV1 {\n format: typeof APICIRCLE_FOLDER_EXPORT_FORMAT;\n /** ISO timestamp of when the export was generated. */\n exportedAt: string;\n /** App version that produced the export (free-form string). */\n appVersion: string;\n /** Loose breadcrumb back to the source — never required by importers. */\n source: {\n workspaceId: string;\n folderId: string;\n folderName: string;\n };\n folder: {\n /** Display name of the exported root folder. */\n name: string;\n /** Folder-level auth, if any was set on the source root folder. */\n auth?: Folder['auth'];\n /**\n * Descendant folders (NOT including the root). `parentId` is the\n * source workspace's id of the parent — when it equals `source.folderId`\n * the folder lives directly under the exported root.\n */\n subfolders: Folder[];\n /**\n * All requests inside the exported subtree. `folderId` is the source\n * id of the immediate parent folder; the importer remaps it onto the\n * destination workspace's freshly-minted ids.\n */\n requests: ApiRequest[];\n };\n /**\n * Captured global-asset dependencies referenced by the exported\n * requests. Schemas/GraphQL travel embedded; files travel\n * metadata-only.\n */\n dependencies: ApicircleFolderExportDependencies;\n}\n\nexport interface ApicircleFolderExportDependencies {\n schemas: GlobalSchema[];\n graphql: GlobalGraphQL[];\n /**\n * File-asset METADATA only. The `slotId` is preserved so the importer\n * can correlate against an existing slot on the destination side if\n * one happens to match; otherwise the user is prompted to re-attach.\n */\n files: GlobalFileAsset[];\n}\n\n/**\n * Plain-language summary of what the export contains, surfaced inside the\n * Export Folder modal so the user knows exactly what's leaving the\n * workspace before they click Download.\n */\nexport interface FolderExportReport {\n folderName: string;\n requestCount: number;\n subfolderCount: number;\n /** Total folder count INCLUDING the exported root. */\n totalFolderCount: number;\n dependencies: {\n schemas: Array<{ id: string; name: string }>;\n graphql: Array<{ id: string; name: string; kind: GlobalGraphQL['kind'] }>;\n files: Array<{\n id: string;\n name: string;\n filename: string;\n size: number;\n mimeType: string;\n }>;\n };\n /** Convenience flag — `true` when any dependency was captured. */\n hasDependencies: boolean;\n /**\n * Every credential-bearing field detected inside the envelope's auth\n * blocks (root folder, subfolders, requests). Surfaced by the export\n * modal so the user can opt-in per-field before the file leaves the\n * workspace. Defaults to \"redact everything\" — see\n * `redactFolderExportCredentials`.\n */\n credentials: FolderExportCredential[];\n /** Convenience flag — `true` when any credential was detected. */\n hasCredentials: boolean;\n}\n\nexport interface CollectFolderExportArgs {\n synced: WorkspaceSynced;\n folderId: string;\n /** Defaults to `new Date().toISOString()` — overridable for deterministic tests. */\n now?: string;\n /** Defaults to `'apicircle-studio'` — overridable for deterministic tests. */\n appVersion?: string;\n}\n\nexport interface CollectFolderExportResult {\n envelope: ApicircleFolderExportV1;\n report: FolderExportReport;\n}\n\n/**\n * Walk the subtree rooted at `folderId`, collect its requests + descendant\n * folders, gather every referenced global-asset dependency, and assemble\n * a self-describing export envelope.\n *\n * Returns `null` when `folderId` doesn't exist — UI callers should treat\n * that as a no-op (the source folder was deleted between menu open and\n * click).\n */\nexport function collectFolderExport(\n args: CollectFolderExportArgs,\n): CollectFolderExportResult | null {\n const { synced, folderId } = args;\n const root = synced.collections.folders[folderId];\n if (!root) return null;\n\n const now = args.now ?? new Date().toISOString();\n const appVersion = args.appVersion ?? 'apicircle-studio';\n\n // Walk the descendant folder graph by parentId chain — same idiom\n // `removeFolder` / `duplicateFolder` use.\n const folderIds = new Set<string>([folderId]);\n let grew = true;\n while (grew) {\n grew = false;\n for (const f of Object.values(synced.collections.folders)) {\n if (folderIds.has(f.id)) continue;\n if (f.parentId && folderIds.has(f.parentId)) {\n folderIds.add(f.id);\n grew = true;\n }\n }\n }\n\n // Descendants don't include the root itself — the root carries its own\n // `name` / `auth` on `envelope.folder.*`.\n const subfolders: Folder[] = [];\n for (const f of Object.values(synced.collections.folders)) {\n if (f.id !== folderId && folderIds.has(f.id)) subfolders.push(cloneFolder(f));\n }\n\n const requests: ApiRequest[] = [];\n for (const r of Object.values(synced.collections.requests)) {\n if (r.folderId && folderIds.has(r.folderId)) requests.push(cloneRequest(r));\n }\n\n const dependencies = collectDependencies(synced, requests);\n\n const envelope: ApicircleFolderExportV1 = {\n format: APICIRCLE_FOLDER_EXPORT_FORMAT,\n exportedAt: now,\n appVersion,\n source: {\n workspaceId: synced.workspaceId,\n folderId,\n folderName: root.name,\n },\n folder: {\n name: root.name,\n auth: root.auth,\n subfolders,\n requests,\n },\n dependencies,\n };\n\n const report = buildReport(envelope);\n return { envelope, report };\n}\n\n/** JSON-stringify an envelope with stable, human-friendly formatting (2-space indent). */\nexport function serializeFolderExport(envelope: ApicircleFolderExportV1): string {\n return JSON.stringify(envelope, null, 2);\n}\n\n/** Filename the UI uses for the downloaded file. Slugifies the folder name. */\nexport function suggestFolderExportFilename(envelope: ApicircleFolderExportV1): string {\n const slug = envelope.folder.name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-/, '')\n .replace(/-$/, '');\n const base = slug || 'folder';\n return `${base}.apicircle.json`;\n}\n\n// -- internals --------------------------------------------------------------\n\nfunction cloneFolder(f: Folder): Folder {\n return {\n ...f,\n auth: f.auth ? { ...f.auth } : undefined,\n };\n}\n\nfunction cloneRequest(r: ApiRequest): ApiRequest {\n return {\n ...r,\n headers: r.headers.map((h) => ({ ...h })),\n query: r.query.map((q) => ({ ...q })),\n pathParams: r.pathParams ? { ...r.pathParams } : undefined,\n cookies: r.cookies ? r.cookies.map((c) => ({ ...c })) : undefined,\n body: cloneBody(r.body),\n auth: { ...r.auth },\n contextVars: r.contextVars.map((v) => ({ ...v })),\n extractions: r.extractions.map((e) => ({ ...e })),\n assertions: r.assertions.map((a) => ({ ...a })),\n };\n}\n\nfunction cloneBody(body: ApiRequest['body']): ApiRequest['body'] {\n if (body.type === 'form-data') {\n return {\n ...body,\n formRows: body.formRows?.map((row) => ({ ...row })) ?? body.formRows,\n };\n }\n if (body.type === 'binary') {\n return {\n ...body,\n attachment: body.attachment ? { ...body.attachment } : undefined,\n };\n }\n return { ...body };\n}\n\nfunction collectDependencies(\n synced: WorkspaceSynced,\n requests: ApiRequest[],\n): ApicircleFolderExportDependencies {\n const schemaIds = new Set<string>();\n const graphqlIds = new Set<string>();\n const fileIds = new Set<string>();\n\n for (const r of requests) {\n if (r.bodySchemaId) schemaIds.add(r.bodySchemaId);\n if (r.graphqlSchemaId) graphqlIds.add(r.graphqlSchemaId);\n if (r.body.type === 'binary' && r.body.attachment?.globalFileAssetId) {\n fileIds.add(r.body.attachment.globalFileAssetId);\n }\n if (r.body.type === 'form-data' && r.body.formRows) {\n for (const row of r.body.formRows) {\n if (row.kind === 'file' && row.globalFileAssetId) fileIds.add(row.globalFileAssetId);\n }\n }\n }\n\n const assets = synced.globalAssets;\n const schemas: GlobalSchema[] = [];\n for (const id of schemaIds) {\n const s = assets.schemas[id];\n if (s) schemas.push({ ...s });\n }\n const graphql: GlobalGraphQL[] = [];\n for (const id of graphqlIds) {\n const g = assets.graphql[id];\n if (g) graphql.push({ ...g });\n }\n const files: GlobalFileAsset[] = [];\n for (const id of fileIds) {\n const f = assets.files?.[id];\n if (f) files.push({ ...f });\n }\n\n // Stable ordering — name then id — so identical workspaces produce\n // identical JSON regardless of Object.values iteration order.\n schemas.sort(byNameThenId);\n graphql.sort(byNameThenId);\n files.sort(byNameThenId);\n\n return { schemas, graphql, files };\n}\n\nfunction byNameThenId<T extends { id: string; name: string }>(a: T, b: T): number {\n const c = a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });\n return c !== 0 ? c : a.id.localeCompare(b.id);\n}\n\nfunction buildReport(envelope: ApicircleFolderExportV1): FolderExportReport {\n const subfolderCount = envelope.folder.subfolders.length;\n const requestCount = envelope.folder.requests.length;\n const totalFolderCount = subfolderCount + 1; // include the exported root\n const credentials = collectFolderExportCredentials(envelope);\n\n return {\n folderName: envelope.folder.name,\n requestCount,\n subfolderCount,\n totalFolderCount,\n dependencies: {\n schemas: envelope.dependencies.schemas.map((s) => ({ id: s.id, name: s.name })),\n graphql: envelope.dependencies.graphql.map((g) => ({\n id: g.id,\n name: g.name,\n kind: g.kind,\n })),\n files: envelope.dependencies.files.map((f) => ({\n id: f.id,\n name: f.name,\n filename: f.filename,\n size: f.size,\n mimeType: f.mimeType,\n })),\n },\n hasDependencies:\n envelope.dependencies.schemas.length > 0 ||\n envelope.dependencies.graphql.length > 0 ||\n envelope.dependencies.files.length > 0,\n credentials,\n hasCredentials: credentials.length > 0,\n };\n}\n","// Importer for the `apicircleEnvironment: 1 | 2` JSON envelope produced by\n// `exportEnvironment` in `../../../ui-components/src/store/envActions.ts`\n// (and by the MCP `environment.export` tool in\n// `../../../mcp-server/src/tools/crud.ts`). Sister parser to\n// `./apicircleFolder.ts` — same surface, different document.\n//\n// Shape (v2 — current, matches Git push/pull) — encrypted rows carry their\n// ciphertext + the per-slot salt so the destination can attempt the same\n// decrypt the request-execute path would (derive a key from the LOCAL slot\n// plaintext + the SOURCE salt, then AES-GCM unwrap):\n//\n// {\n// \"apicircleEnvironment\": 2,\n// \"name\": \"dev\",\n// \"variables\": [\n// { \"key\": \"API_BASE\", \"value\": \"https://api.example.com\", \"encrypted\": false },\n// {\n// \"key\": \"TOKEN\",\n// \"encrypted\": true,\n// \"value\": \"enc:v1:<iv>:<ciphertext>\",\n// \"secretKeyId\": \"sec_abc\",\n// \"secret\": { \"label\": \"PROD_TOKEN\", \"salt\": \"base64salt==\" }\n// }\n// ]\n// }\n//\n// Shape (v1 — legacy, surface-only) — encrypted rows carry slot METADATA\n// but not the ciphertext or salt, so the destination must prompt the user\n// for a plaintext value during import. Still supported so existing exports\n// continue to import without surprise:\n//\n// {\n// \"apicircleEnvironment\": 1,\n// \"name\": \"dev\",\n// \"variables\": [\n// { \"key\": \"TOKEN\", \"encrypted\": true, \"secretKeyId\": \"sec_abc\", \"secret\": { \"label\": \"PROD_TOKEN\" } }\n// ]\n// }\n//\n// Plain rows round-trip in full in both versions. Encrypted rows surface an\n// `encryptedBindingHint` so the caller can match against the destination's\n// vault. v2 hints additionally carry `ciphertext` + `salt` so the importer\n// can land the encrypted row directly; v1 hints fall back to the prompt-the-\n// user-for-value path.\n\nimport type { EnvironmentVariable } from '@apicircle/shared';\n\nexport interface ParsedApicircleEnvironment {\n name: string;\n /**\n * The variables that should land in the destination env, in the same\n * order as the source. Encrypted rows arrive with the SOURCE'S\n * `secretKeyId`; the caller is responsible for re-pointing the binding\n * to a destination-local slot id (or leaving it dangling until the user\n * fixes it).\n *\n * In v2, encrypted rows arrive with their ciphertext intact in `value`;\n * the importer can choose to land it as-is so the request-execute path\n * decrypts naturally when the user provides the matching slot value.\n * In v1, encrypted rows arrive with `value: ''` and the importer must\n * surface a pendingBinding for the user to type a fresh plaintext.\n */\n variables: EnvironmentVariable[];\n /**\n * Per encrypted row, the slot metadata the export carried. The store\n * action uses this to (a) reuse an existing destination slot by label\n * match, (b) reuse by `originSecretKeyId` for same-workspace re-imports,\n * or (c) surface a pendingBinding so the UI can prompt the user.\n * Indices line up with `variables` for the corresponding row only —\n * plain rows do not appear here.\n */\n encryptedBindingHints: EncryptedBindingHint[];\n /**\n * The envelope version the export advertised — `1` (label-only, prompt\n * user for value) or `2` (ciphertext + salt carry, attempt decrypt with\n * local slot value). Importers fork on this to decide whether to land\n * the ciphertext or surface a pendingBinding.\n */\n payloadVersion: 1 | 2;\n /**\n * Soft notes the parser surfaced about the import — dropped rows,\n * demoted encrypted rows, etc. Importers forward these to the UI as\n * warnings.\n */\n warnings: string[];\n}\n\nexport interface EncryptedBindingHint {\n /** The var the hint belongs to (matches the row's `key`). */\n varKey: string;\n /**\n * The slot's display label from the source workspace. Older exports\n * (before `secret.label` shipped) didn't carry this; the parser falls\n * back to `varKey` so the UI always has SOMETHING to render.\n */\n label: string;\n /**\n * The slot id the source workspace bound to. Useful for round-tripping\n * inside the same workspace (the destination's slot id matches), but\n * meaningless on a different machine. Optional — newer exports may\n * stop carrying it once enough time passes.\n */\n originSecretKeyId?: string;\n /** `true` when the export carried no `secret.label` and the label was synthesized. */\n labelFromFallback: boolean;\n /**\n * v2 only: the source's ciphertext (`enc:v1:<iv>:<base64>`) so the\n * destination can land an encrypted row whose value the user can\n * decrypt by providing the matching slot plaintext. `null` on v1 — the\n * caller must instead prompt the user for a plaintext value and\n * re-encrypt locally.\n */\n ciphertext: string | null;\n /**\n * v2 only: the source slot's salt (base64). Required to derive the same\n * AES-GCM key the source used. `null` on v1.\n */\n salt: string | null;\n}\n\ninterface ApicircleEnvDoc {\n apicircleEnvironment?: unknown;\n name?: unknown;\n variables?: unknown;\n}\n\ninterface RawVarRow {\n key?: unknown;\n value?: unknown;\n encrypted?: unknown;\n secretKeyId?: unknown;\n secret?: unknown;\n}\n\n/** Lightweight discriminator — `true` when `doc.apicircleEnvironment` is 1 or 2. */\nexport function isApicircleEnvironment(doc: unknown): doc is {\n apicircleEnvironment: 1 | 2;\n name: string;\n variables: unknown[];\n} {\n if (!doc || typeof doc !== 'object') return false;\n const d = doc as ApicircleEnvDoc;\n return (\n (d.apicircleEnvironment === 1 || d.apicircleEnvironment === 2) &&\n typeof d.name === 'string' &&\n Array.isArray(d.variables)\n );\n}\n\n/**\n * Parse + validate a raw JSON string. Throws with a single, user-readable\n * message when the input is malformed; otherwise returns a parsed shape\n * ready for the store to graft in.\n */\nexport function parseApicircleEnvironment(input: string): ParsedApicircleEnvironment {\n let doc: unknown;\n try {\n doc = JSON.parse(input);\n } catch (err) {\n throw new Error(`Couldn't parse JSON: ${err instanceof Error ? err.message : String(err)}`);\n }\n return parseApicircleEnvironmentDoc(doc);\n}\n\n/**\n * Same as `parseApicircleEnvironment` but skips the JSON.parse step —\n * used by callers that already deserialized the document.\n */\nexport function parseApicircleEnvironmentDoc(doc: unknown): ParsedApicircleEnvironment {\n if (!isApicircleEnvironment(doc)) {\n throw new Error(\n 'Unsupported format. Expected an API Circle environment export (\"apicircleEnvironment\": 1 or 2).',\n );\n }\n\n const name = doc.name.trim();\n if (!name) {\n throw new Error('API Circle environment export must have a non-empty \"name\".');\n }\n\n const payloadVersion: 1 | 2 = doc.apicircleEnvironment;\n const warnings: string[] = [];\n const variables: EnvironmentVariable[] = [];\n const encryptedBindingHints: EncryptedBindingHint[] = [];\n\n for (let i = 0; i < doc.variables.length; i += 1) {\n const raw = doc.variables[i] as RawVarRow;\n if (!raw || typeof raw !== 'object') {\n warnings.push(`Row #${i + 1} was not an object — dropped.`);\n continue;\n }\n const key = typeof raw.key === 'string' ? raw.key.trim() : '';\n if (!key) {\n warnings.push(`Row #${i + 1} had no key — dropped.`);\n continue;\n }\n if (raw.encrypted === true) {\n const secretKeyId = typeof raw.secretKeyId === 'string' ? raw.secretKeyId : '';\n const labelFromSecret = readLabelFromSecretField(raw.secret);\n // v2 ciphertext + salt are optional even on a v2 doc — defensive\n // for documents authored by tools that flip to v2 without filling\n // them in. When either is missing we degrade to v1-style handling\n // for that row.\n const ciphertext =\n payloadVersion === 2 && typeof raw.value === 'string' && raw.value.startsWith('enc:')\n ? raw.value\n : null;\n const salt = payloadVersion === 2 ? readSaltFromSecretField(raw.secret) : null;\n if (!secretKeyId && !labelFromSecret) {\n // Truly dangling — no id and no label means there's nothing to\n // prompt the user with and nothing to bind. Demote to a plain\n // empty row so the env still loads with the var declared.\n warnings.push(\n `\"${key}\" was marked encrypted but carried no secretKeyId and no secret label — imported as an empty plain variable. Re-bind it under Environments after import.`,\n );\n variables.push({ key, value: '', encrypted: false });\n continue;\n }\n // Encrypted row: keep the source's secretKeyId on the var so\n // same-workspace re-imports stay bound. The store action resolves\n // hints against the destination's vault and re-points the id\n // (or surfaces the row as a pending binding) before persisting.\n //\n // v2: carry the ciphertext through to `value` so the importer can\n // land it directly (and the request-execute decrypt path takes\n // over once the user provides the slot value). v1: empty string —\n // importer must prompt for a plaintext value.\n variables.push({\n key,\n value: ciphertext ?? '',\n encrypted: true,\n secretKeyId: secretKeyId || undefined,\n });\n const labelFromFallback = !labelFromSecret;\n encryptedBindingHints.push({\n varKey: key,\n label: labelFromSecret ?? key,\n originSecretKeyId: secretKeyId || undefined,\n labelFromFallback,\n ciphertext,\n salt,\n });\n continue;\n }\n // Plain row.\n variables.push({\n key,\n value: typeof raw.value === 'string' ? raw.value : '',\n encrypted: false,\n });\n }\n\n return { name, variables, encryptedBindingHints, payloadVersion, warnings };\n}\n\nfunction readLabelFromSecretField(field: unknown): string | null {\n if (!field || typeof field !== 'object') return null;\n const f = field as { label?: unknown };\n if (typeof f.label !== 'string') return null;\n const trimmed = f.label.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction readSaltFromSecretField(field: unknown): string | null {\n if (!field || typeof field !== 'object') return null;\n const f = field as { salt?: unknown };\n if (typeof f.salt !== 'string') return null;\n const trimmed = f.salt.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n","import type { Assertion } from '@apicircle/shared';\nimport type { ExecutionResult } from '../request/executeRequest';\n\n/**\n * Result of evaluating one assertion against a response. Carries a snapshot\n * of the assertion definition so downstream UI (History detail view, run\n * exports, plan reports) can render the verdict without joining back to the\n * source request — which may have been renamed, edited, or deleted by the\n * time the user looks at history.\n */\nexport interface AssertionResult {\n assertionId: string;\n kind: Assertion['kind'];\n op: Assertion['op'];\n target?: string;\n expected: string | number;\n passed: boolean;\n /**\n * Human-readable explanation. Always populated by `runAssertions` — pass\n * cases get positive descriptions (\"status: 200 equals 200\"), fail cases\n * get the diff. Optional in the type because the persisted shape in\n * `RequestRun.assertions` predates this and may carry undefined for older\n * history entries.\n */\n detail?: string;\n}\n\nexport function runAssertions(\n assertions: ReadonlyArray<Assertion>,\n exec: ExecutionResult,\n): AssertionResult[] {\n return assertions.map((a) => runOne(a, exec));\n}\n\nfunction runOne(a: Assertion, exec: ExecutionResult): AssertionResult {\n switch (a.kind) {\n case 'status':\n return checkStatus(a, exec);\n case 'duration':\n return checkDuration(a, exec);\n case 'header':\n return checkHeader(a, exec);\n case 'json-path':\n return checkJsonPath(a, exec);\n }\n}\n\nfunction snapshot(\n a: Assertion,\n): Pick<AssertionResult, 'assertionId' | 'kind' | 'op' | 'target' | 'expected'> {\n return {\n assertionId: a.id,\n kind: a.kind,\n op: a.op,\n target: a.target,\n expected: a.expected,\n };\n}\n\nfunction pass(a: Assertion, detail: string): AssertionResult {\n return { ...snapshot(a), passed: true, detail };\n}\nfunction fail(a: Assertion, detail: string): AssertionResult {\n return { ...snapshot(a), passed: false, detail };\n}\n\nfunction checkStatus(a: Assertion, exec: ExecutionResult): AssertionResult {\n const got = exec.status;\n if (got === null) return fail(a, `request did not complete (got null status)`);\n return compareNumber(a, got, 'status');\n}\n\nfunction checkDuration(a: Assertion, exec: ExecutionResult): AssertionResult {\n return compareNumber(a, exec.durationMs, 'duration');\n}\n\nfunction checkHeader(a: Assertion, exec: ExecutionResult): AssertionResult {\n if (!a.target) return fail(a, 'header assertion missing target header name');\n const value = exec.headers[a.target.toLowerCase()] ?? exec.headers[a.target];\n if (value === undefined) {\n if (a.op === 'not-equals')\n return pass(a, `header \"${a.target}\" not present (passes not-equals)`);\n return fail(a, `header \"${a.target}\" not present`);\n }\n return compareString(a, value, `header \"${a.target}\"`);\n}\n\nfunction checkJsonPath(a: Assertion, exec: ExecutionResult): AssertionResult {\n if (!a.target) return fail(a, 'json-path assertion missing path');\n let parsed: unknown;\n try {\n parsed = JSON.parse(exec.body);\n } catch {\n return fail(a, 'response body is not valid JSON');\n }\n const value = readJsonPath(parsed, a.target);\n if (value === undefined) {\n if (a.op === 'not-equals') return pass(a, `path \"${a.target}\" not found (passes not-equals)`);\n return fail(a, `path \"${a.target}\" not found in response`);\n }\n if (typeof value === 'number') return compareNumber(a, value, `path \"${a.target}\"`);\n // For non-primitive values (objects, arrays), serialize as JSON so the\n // user gets a meaningful diff string rather than `[object Object]`.\n const serialized =\n typeof value === 'string'\n ? value\n : typeof value === 'boolean'\n ? String(value)\n : value === null\n ? 'null'\n : JSON.stringify(value);\n return compareString(a, serialized, `path \"${a.target}\"`);\n}\n\nfunction compareNumber(a: Assertion, actual: number, label: string): AssertionResult {\n const expected = Number(a.expected);\n if (!Number.isFinite(expected))\n return fail(a, `${label}: expected a number, got \"${a.expected}\"`);\n switch (a.op) {\n case 'equals':\n return actual === expected\n ? pass(a, `${label}: ${actual} equals ${expected}`)\n : fail(a, `${label}: expected ${expected}, got ${actual}`);\n case 'not-equals':\n return actual !== expected\n ? pass(a, `${label}: ${actual} does not equal ${expected}`)\n : fail(a, `${label}: expected not to equal ${expected}`);\n case 'lt':\n return actual < expected\n ? pass(a, `${label}: ${actual} < ${expected}`)\n : fail(a, `${label}: expected < ${expected}, got ${actual}`);\n case 'gt':\n return actual > expected\n ? pass(a, `${label}: ${actual} > ${expected}`)\n : fail(a, `${label}: expected > ${expected}, got ${actual}`);\n case 'contains':\n case 'matches':\n return fail(a, `${label}: op \"${a.op}\" not supported for numeric values`);\n }\n}\n\nfunction compareString(a: Assertion, actual: string, label: string): AssertionResult {\n const expected = String(a.expected);\n switch (a.op) {\n case 'equals':\n return actual === expected\n ? pass(a, `${label}: \"${actual}\" equals \"${expected}\"`)\n : fail(a, `${label}: expected \"${expected}\", got \"${actual}\"`);\n case 'not-equals':\n return actual !== expected\n ? pass(a, `${label}: \"${actual}\" does not equal \"${expected}\"`)\n : fail(a, `${label}: expected not to equal \"${expected}\"`);\n case 'contains':\n return actual.includes(expected)\n ? pass(a, `${label}: \"${actual}\" contains \"${expected}\"`)\n : fail(a, `${label}: expected to contain \"${expected}\", got \"${actual}\"`);\n case 'matches': {\n let re: RegExp;\n try {\n re = new RegExp(expected);\n } catch {\n return fail(a, `${label}: expected pattern is not a valid regex: ${expected}`);\n }\n return re.test(actual)\n ? pass(a, `${label}: \"${actual}\" matches /${expected}/`)\n : fail(a, `${label}: did not match pattern /${expected}/`);\n }\n case 'lt':\n case 'gt':\n return fail(a, `${label}: op \"${a.op}\" not supported for string values`);\n }\n}\n\n/**\n * Read a dotted-path value from a JSON tree. Supports `a.b.c` and bracket\n * indexing `arr[0]`. Returns `undefined` for missing segments.\n */\nexport function readJsonPath(root: unknown, path: string): unknown {\n if (!path || path === '$' || path === '.') return root;\n const trimmed = path.startsWith('$.')\n ? path.slice(2)\n : path.startsWith('$')\n ? path.slice(1)\n : path;\n const segments = trimmed\n .replace(/\\[(\\d+)\\]/g, '.$1')\n .split('.')\n .filter((s) => s.length > 0);\n let current: unknown = root;\n for (const seg of segments) {\n if (current === null || typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[seg];\n if (current === undefined) return undefined;\n }\n return current;\n}\n","// Extract values from an ExecutionResult per the request's `extractions`\n// list and return a `Record<string, string>` keyed by the user-supplied\n// `variable` names. Failures are non-fatal — a path that doesn't resolve\n// produces an empty string and a warning so the rest of the chain still\n// runs (matches v1's ResponseExtractor semantics).\n\nimport type { ContextExtraction } from '@apicircle/shared';\nimport type { ExecutionResult } from '../request/executeRequest';\nimport { readJsonPath } from '../assertions/runAssertions';\n\nexport interface ContextExtractionResult {\n extracted: Record<string, string>;\n warnings: string[];\n}\n\nfunction findHeader(headers: Record<string, string>, name: string): string | undefined {\n const lower = name.toLowerCase();\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() === lower) return v;\n }\n return undefined;\n}\n\nfunction readCookie(headers: Record<string, string>, name: string): string | undefined {\n // The browser strips Set-Cookie from cross-origin responses, but for\n // same-origin we may see it. Cookie *requests* are echoed too, so we\n // also check a `cookie` header for symmetry.\n const sources = [findHeader(headers, 'set-cookie'), findHeader(headers, 'cookie')].filter(\n (v): v is string => Boolean(v),\n );\n for (const raw of sources) {\n for (const part of raw.split(/;\\s*/)) {\n const eq = part.indexOf('=');\n if (eq === -1) continue;\n const key = part.slice(0, eq).trim();\n if (key === name) return part.slice(eq + 1);\n }\n }\n return undefined;\n}\n\nfunction stringify(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n return JSON.stringify(value);\n}\n\nexport function extractContext(\n result: ExecutionResult,\n extractions: ReadonlyArray<ContextExtraction>,\n): ContextExtractionResult {\n const extracted: Record<string, string> = {};\n const warnings: string[] = [];\n\n for (const config of extractions) {\n if (!config.enabled) continue;\n const variable = config.variable.trim();\n if (!variable) {\n warnings.push('Skipping extraction with empty variable name');\n continue;\n }\n\n let value: string | undefined;\n switch (config.source) {\n case 'status':\n value = result.status === null ? '' : String(result.status);\n break;\n case 'header':\n value = findHeader(result.headers, config.path.trim());\n if (value === undefined) {\n warnings.push(`Header \"${config.path}\" not found for \"${variable}\"`);\n }\n break;\n case 'cookie':\n value = readCookie(result.headers, config.path.trim());\n if (value === undefined) {\n warnings.push(`Cookie \"${config.path}\" not found for \"${variable}\"`);\n }\n break;\n case 'body': {\n if (result.body.length === 0) {\n warnings.push(`Body is empty — skipping \"${variable}\"`);\n break;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(result.body);\n } catch {\n warnings.push(`Body is not JSON — cannot extract \"${variable}\"`);\n break;\n }\n const found = readJsonPath(parsed, config.path);\n if (found === undefined) {\n warnings.push(`Body path \"${config.path}\" did not resolve for \"${variable}\"`);\n } else {\n value = stringify(found);\n }\n break;\n }\n }\n\n // When the extraction failed (value is undefined), DON'T bind the\n // variable. Binding it to '' produces a silent defined-as-empty\n // result, which surfaces in downstream {{var}} usage as an empty\n // value — easy to mistake for a real value of \"\". Skipping the\n // binding instead lets resolveString leave the placeholder verbatim,\n // so the user sees \"{{var}}\" in the URL/body and immediately notices\n // the broken extraction. Warnings are still emitted for telemetry.\n if (value !== undefined) {\n extracted[variable] = value;\n }\n }\n\n return { extracted, warnings };\n}\n","import type {\n EnvPriorityRef,\n Environment,\n Request as ApiRequest,\n RequestAuth,\n RequestBody,\n WorkspaceSynced,\n} from '@apicircle/shared';\nimport { envPriorityKey } from '@apicircle/shared';\nimport { resolveInheritedAuth } from '../request/resolveInheritedAuth';\nimport { buildScope, resolveString, type ResolutionScope } from './variableResolver';\n\n// =============================================================================\n// Pure send-time resolver.\n//\n// Builds a `ResolutionScope` from the workspace + caller-supplied decrypted\n// envs/secrets, then interpolates `{{var}}` placeholders in url, headers,\n// query, body, and auth fields. Folder-level auth inheritance is resolved\n// here too. The caller owns the vault (decryption is host-specific — web,\n// desktop, and VS Code all decrypt differently); this function takes the\n// already-decrypted flat maps and is therefore synchronous + portable.\n// =============================================================================\n\nexport interface ResolveRequestArgs {\n request: ApiRequest;\n synced: WorkspaceSynced;\n /** Plaintext local envs: `{ envName: { varKey: value } }`. */\n localEnvs: Record<string, Record<string, string>>;\n /**\n * Plaintext linked envs keyed by linkedWorkspaceId, then envName. Caller\n * is expected to have already applied any linkedOverrides.environmentVars\n * (use `applyLinkedEnvironmentOverrides` from this module first).\n */\n linkedEnvs?: Record<string, Record<string, Record<string, string>>>;\n /** Plaintext secrets keyed by their display label (vault-decrypted). */\n secrets?: Record<string, string>;\n /**\n * `globalContext` (latest-write-wins extractions) + plan variables\n * (optional) — sit between request.contextVars and the env layer.\n */\n globalContext?: Record<string, string>;\n planVariables?: ReadonlyArray<{ key: string; value: string }>;\n /** Plan-level priority overrides take precedence when non-empty. */\n envPriorityOverride?: readonly EnvPriorityRef[];\n}\n\nexport interface ResolvedRequestResult {\n request: ApiRequest;\n scope: ResolutionScope;\n missing: string[];\n}\n\nexport function resolveRequestForExecution(args: ResolveRequestArgs): ResolvedRequestResult {\n const refs =\n args.envPriorityOverride && args.envPriorityOverride.length > 0\n ? args.envPriorityOverride\n : args.synced.environments.priorityOrder;\n\n // Flatten local + linked envs into one keyed map the resolver can index by\n // composite key — matches the priority list's `EnvPriorityRef` shape.\n const flatEnvs: Record<string, Record<string, string>> = {};\n for (const [name, vars] of Object.entries(args.localEnvs)) {\n flatEnvs[envPriorityKey({ kind: 'local', name })] = vars;\n }\n for (const [linkId, byEnv] of Object.entries(args.linkedEnvs ?? {})) {\n for (const [envName, vars] of Object.entries(byEnv)) {\n flatEnvs[envPriorityKey({ kind: 'linked', linkedWorkspaceId: linkId, envName })] = vars;\n }\n }\n\n // contextVars: globalContext < plan vars < request.contextVars.\n const ctxMap: Record<string, string> = { ...(args.globalContext ?? {}) };\n for (const v of args.planVariables ?? []) {\n if (v.key) ctxMap[v.key] = v.value;\n }\n for (const v of args.request.contextVars) {\n if (v.key) ctxMap[v.key] = v.value;\n }\n const contextVars = Object.entries(ctxMap).map(([key, value]) => ({ key, value }));\n\n const scope = buildScope({\n contextVars,\n environments: flatEnvs,\n activeEnvName: null, // priorityOrder is the sole list the resolver consults.\n priorityOrder: refs.map(envPriorityKey),\n secrets: args.secrets ?? {},\n });\n\n const missing = new Set<string>();\n const interp = (s: string): string => {\n const r = resolveString(s, scope);\n for (const m of r.missing) missing.add(m);\n return r.value;\n };\n\n const url = interp(args.request.url);\n const headers = args.request.headers.map((h) => ({\n ...h,\n key: interp(h.key),\n value: interp(h.value),\n }));\n const query = args.request.query.map((q) => ({\n ...q,\n key: interp(q.key),\n value: interp(q.value),\n }));\n\n let body: RequestBody = args.request.body;\n if (\n body.type === 'json' ||\n body.type === 'text' ||\n body.type === 'xml' ||\n body.type === 'graphql' ||\n body.type === 'urlencoded'\n ) {\n body = { ...body, content: interp(body.content) };\n } else if (body.type === 'form-data' && body.formRows) {\n body = {\n ...body,\n formRows: body.formRows.map((row) =>\n row.kind === 'text'\n ? { ...row, key: interp(row.key), value: interp(row.value) }\n : { ...row, key: interp(row.key) },\n ),\n };\n }\n\n // Auth: resolve folder inheritance, then interpolate every string field\n // (so a `{{token}}` typed into Bearer / Basic / API-key works).\n const inheritedAuth = resolveInheritedAuth({\n requestAuth: args.request.auth ?? { type: 'none' },\n folderId: args.request.folderId,\n folders: args.synced.collections.folders,\n });\n const auth = interpolateAuthVariables(inheritedAuth, interp);\n\n return {\n request: { ...args.request, url, headers, query, body, auth },\n scope,\n missing: [...missing],\n };\n}\n\nfunction interpolateAuthVariables(auth: RequestAuth, interp: (s: string) => string): RequestAuth {\n const resolved: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(auth)) {\n // `type` is the discriminant — never templated.\n resolved[key] = key !== 'type' && typeof value === 'string' ? interp(value) : value;\n }\n return resolved as unknown as RequestAuth;\n}\n\n// ---------------------------------------------------------------------------\n// Linked-env override application (pure)\n// ---------------------------------------------------------------------------\n\n/**\n * Layer `synced.linkedOverrides.environmentVars` entries onto a source env\n * map for one linked workspace. Used by the host to prepare the plaintext\n * `linkedEnvs` argument before calling `resolveRequestForExecution`.\n */\nexport function applyLinkedEnvironmentOverrides(\n source: WorkspaceSynced['environments'],\n linkedWorkspaceId: string,\n synced: WorkspaceSynced,\n): WorkspaceSynced['environments'] {\n const overrides = Object.values(synced.linkedOverrides.environmentVars).filter(\n (o) => o.linkedWorkspaceId === linkedWorkspaceId,\n );\n if (overrides.length === 0) return source;\n const items: WorkspaceSynced['environments']['items'] = {};\n for (const [envName, env] of Object.entries(source.items)) {\n const envOverrides = overrides.filter((o) => o.envName === envName);\n if (envOverrides.length === 0) {\n items[envName] = env;\n continue;\n }\n const removed = new Set(envOverrides.filter((o) => o.removed).map((o) => o.varKey));\n const replaceMap = new Map(envOverrides.filter((o) => !o.removed).map((o) => [o.varKey, o]));\n const variables: Environment['variables'] = [];\n const seenKeys = new Set<string>();\n for (const v of env.variables) {\n if (removed.has(v.key)) continue;\n const ov = replaceMap.get(v.key);\n if (ov) {\n variables.push({\n key: v.key,\n value: ov.value ?? v.value,\n encrypted: ov.encrypted ?? v.encrypted,\n ...(ov.secretKeyId !== undefined\n ? { secretKeyId: ov.secretKeyId }\n : v.secretKeyId !== undefined\n ? { secretKeyId: v.secretKeyId }\n : {}),\n });\n } else {\n variables.push(v);\n }\n seenKeys.add(v.key);\n }\n for (const ov of envOverrides) {\n if (ov.removed) continue;\n if (seenKeys.has(ov.varKey)) continue;\n variables.push({\n key: ov.varKey,\n value: ov.value ?? '',\n encrypted: ov.encrypted ?? false,\n ...(ov.secretKeyId !== undefined ? { secretKeyId: ov.secretKeyId } : {}),\n });\n }\n items[envName] = { ...env, variables };\n }\n return { ...source, items };\n}\n\n/**\n * Strip an envs map down to its plaintext key→value pairs, dropping any\n * variable still marked `encrypted: true` (the host's vault layer should have\n * decrypted those in advance). Returns the plaintext map the resolver\n * consumes.\n */\nexport function plaintextEnvMap(\n source: WorkspaceSynced['environments'],\n): Record<string, Record<string, string>> {\n const out: Record<string, Record<string, string>> = {};\n for (const [name, env] of Object.entries(source.items)) {\n const vars: Record<string, string> = {};\n for (const v of env.variables) {\n if (v.encrypted) continue; // host did not decrypt this row; skip silently.\n vars[v.key] = v.value;\n }\n out[name] = vars;\n }\n return out;\n}\n","// AES-GCM encryption helpers used by:\n// - Encrypted environment variables (ciphertext lives in workspace.json,\n// pushed to Git; decryption key never leaves the local browser).\n// - Secret Vault entries (ciphertext in IDB only, never pushed).\n//\n// All helpers take a CryptoKey as input — key generation + persistence is\n// the host's responsibility (see ui-components/persistence/secretKey.ts).\n\nconst IV_BYTES = 12; // 96-bit IV is the recommended size for AES-GCM\nconst SALT_BYTES = 16;\nconst PBKDF2_ITERATIONS = 210_000; // OWASP 2024 recommendation for SHA-256\nconst ALG = 'AES-GCM';\n\nexport interface EncryptedPayload {\n iv: string; // base64\n ciphertext: string; // base64\n}\n\n/**\n * Encrypt a UTF-8 string with the given AES-GCM key. Returns base64-encoded\n * iv + ciphertext, safe to embed in JSON / push to Git.\n */\nexport async function encryptString(plaintext: string, key: CryptoKey): Promise<EncryptedPayload> {\n const iv = crypto.getRandomValues(new Uint8Array(IV_BYTES));\n const data = new TextEncoder().encode(plaintext);\n const cipher = await crypto.subtle.encrypt(\n { name: ALG, iv: iv as unknown as BufferSource },\n key,\n data,\n );\n return {\n iv: bytesToBase64(iv),\n ciphertext: bytesToBase64(new Uint8Array(cipher)),\n };\n}\n\n/**\n * Decrypt a payload produced by `encryptString`. Throws on bad key, tampered\n * ciphertext, or malformed input.\n */\nexport async function decryptString(payload: EncryptedPayload, key: CryptoKey): Promise<string> {\n const iv = base64ToBytes(payload.iv);\n const ciphertext = base64ToBytes(payload.ciphertext);\n const plain = await crypto.subtle.decrypt(\n { name: ALG, iv: iv as unknown as BufferSource },\n key,\n ciphertext as unknown as BufferSource,\n );\n return new TextDecoder().decode(plain);\n}\n\n/**\n * Generate a fresh AES-GCM 256-bit key. The host persists it (typically as\n * a JWK in IndexedDB) so subsequent sessions can decrypt prior values.\n */\nexport function generateAesKey(): Promise<CryptoKey> {\n return crypto.subtle.generateKey({ name: ALG, length: 256 }, true, ['encrypt', 'decrypt']);\n}\n\n/**\n * Generate a fresh per-slot salt (16 random bytes, base64-encoded). Salts are\n * stored in `synced.secretKeys[id].salt` — they're not secret, but they do\n * need to be stable for the slot's lifetime so ciphertext encrypted on one\n * device is decryptable on another.\n */\nexport function generateSlotSalt(): string {\n const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES));\n return bytesToBase64(salt);\n}\n\n/**\n * Derive an AES-GCM key from a slot's plaintext value via PBKDF2-SHA-256.\n * The salt is base64 and travels through Git in `synced.secretKeys[id].salt`;\n * the value is user-supplied and never leaves the device. Same `(value,\n * salt)` pair always derives the same key, so a teammate cloning the repo\n * gets matching keys once they enter the slot value on their machine.\n */\nexport async function deriveKeyFromSlotValue(\n value: string,\n saltBase64: string,\n): Promise<CryptoKey> {\n const baseKey = await crypto.subtle.importKey(\n 'raw',\n new TextEncoder().encode(value) as unknown as BufferSource,\n 'PBKDF2',\n false,\n ['deriveKey'],\n );\n const salt = base64ToBytes(saltBase64);\n return crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt as unknown as BufferSource,\n iterations: PBKDF2_ITERATIONS,\n hash: 'SHA-256',\n },\n baseKey,\n { name: ALG, length: 256 },\n false,\n ['encrypt', 'decrypt'],\n );\n}\n\n/** Export an AES-GCM key as a JSON Web Key (for IDB storage). */\nexport async function exportKey(key: CryptoKey): Promise<JsonWebKey> {\n return crypto.subtle.exportKey('jwk', key);\n}\n\n/** Import an AES-GCM key previously exported via `exportKey`. */\nexport function importKey(jwk: JsonWebKey): Promise<CryptoKey> {\n return crypto.subtle.importKey('jwk', jwk, { name: ALG }, true, ['encrypt', 'decrypt']);\n}\n\n/**\n * Serialize an EncryptedPayload to a single string we can store in\n * `Environment.variables[i].value`. The schema is `enc:v1:<iv>:<ciphertext>`\n * — versioned so we can rotate algorithms later without ambiguity.\n */\nexport function serializePayload(payload: EncryptedPayload): string {\n return `enc:v1:${payload.iv}:${payload.ciphertext}`;\n}\n\nexport function tryParsePayload(value: string): EncryptedPayload | null {\n if (!value.startsWith('enc:v1:')) return null;\n const parts = value.split(':');\n if (parts.length !== 4) return null;\n return { iv: parts[2], ciphertext: parts[3] };\n}\n\n// --- internal --------------------------------------------------------------\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const b of bytes) binary += String.fromCharCode(b);\n return btoa(binary);\n}\n\nfunction base64ToBytes(b64: string): Uint8Array {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);\n return out;\n}\n","// Workspace-passphrase secret model.\n//\n// The master AES-GCM key is *derived* from a user-supplied passphrase\n// plus a per-workspace salt, so encrypted secret values can travel through\n// git unchanged and any teammate who knows the passphrase can decrypt\n// them. Lose the passphrase, lose the secrets — there is no recovery.\n//\n// Storage shape on the workspace (synced.secretCrypto):\n// {\n// kdf: 'pbkdf2-sha256-v1',\n// salt: base64(16 random bytes),\n// iterations: 1_200_000,\n// verifier: base64(AES-GCM(sentinel, derivedKey, zero-IV))\n// }\n//\n// The verifier lets us reject a wrong passphrase up front instead of\n// failing every decrypt downstream with an opaque \"bad tag\" error.\n//\n// The passphrase itself is held only in renderer / process memory\n// (Zustand store on desktop/web; VsCodeVaultManager in the extension).\n// It is NEVER serialised to disk. On app restart the user is prompted\n// to re-enter it before any secret can be touched.\n//\n// Phase 4 promotion (2026-06): moved here from\n// `packages/ui-components/src/persistence/passphraseKey.ts` so the VS\n// Code extension (`apps/vscode`) — which cannot depend on the\n// workspace-private `@apicircle/ui-components` — can drive the same\n// unlock flow from its host process.\n\nconst PBKDF2_HASH = 'SHA-256';\n// PBKDF2 iteration count for newly-created workspaces. The passphrase\n// verifier ships in the synced doc (so any teammate can validate the\n// passphrase without contacting the owner), which means the verifier —\n// and therefore an offline brute-force oracle — is in every clone of\n// the repo. 1.2M keeps per-attempt cost above ~1s on commodity GPU\n// hardware. Existing workspaces keep their original iteration count\n// (it's stamped into `SecretCrypto`).\nconst PBKDF2_ITERATIONS = 1_200_000;\nconst SALT_BYTES = 16;\nconst VERIFIER_SENTINEL = 'apicircle/passphrase-verifier/v1';\n\nexport interface SecretCrypto {\n kdf: 'pbkdf2-sha256-v1';\n /** Base64-encoded random salt; 16 bytes. */\n salt: string;\n /** PBKDF2 iteration count baked at workspace-creation time. */\n iterations: number;\n /** Base64-encoded AES-GCM(sentinel, derivedKey, zero-IV). */\n verifier: string;\n}\n\nfunction base64Encode(bytes: Uint8Array): string {\n let binary = '';\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n return btoa(binary);\n}\n\nfunction base64Decode(b64: string): Uint8Array {\n const binary = atob(b64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n\nfunction utf8Bytes(s: string): Uint8Array {\n return new TextEncoder().encode(s);\n}\n\n/**\n * Derive an AES-GCM key from a passphrase + salt + iteration count. Pure;\n * no caching here — the caller (the store / VS Code VaultManager) holds\n * the unlocked key for the session.\n */\nasync function deriveKey(\n passphrase: string,\n salt: Uint8Array,\n iterations: number,\n): Promise<CryptoKey> {\n // The casts to BufferSource are a TS-only concession: TS 5+ types\n // Uint8Array as generic over ArrayBufferLike (which includes\n // SharedArrayBuffer), while WebCrypto's BufferSource only accepts the\n // non-shared variant. At runtime our buffers are always ArrayBuffer.\n const baseKey = await crypto.subtle.importKey(\n 'raw',\n utf8Bytes(passphrase) as BufferSource,\n { name: 'PBKDF2' },\n false,\n ['deriveKey'],\n );\n return crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt as BufferSource,\n iterations,\n hash: PBKDF2_HASH,\n },\n baseKey,\n { name: 'AES-GCM', length: 256 },\n /* extractable */ false,\n ['encrypt', 'decrypt'],\n );\n}\n\n/**\n * Compute the verifier — encrypts a fixed sentinel under the derived key\n * with a zero IV and stores the GCM tag (concatenated with ciphertext).\n * Comparing this against the stored verifier is a constant-cost way to\n * tell a right passphrase from a wrong one without exposing the key.\n *\n * Note: GCM with a zero IV is *fine here* because we use the key for one\n * single byte of input that's always the same — there is no encryption\n * uniqueness requirement. We do NOT reuse this IV for any real ciphertext.\n */\nasync function computeVerifier(key: CryptoKey): Promise<string> {\n const iv = new Uint8Array(12); // 12 zero bytes — only used here\n const ct = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: iv as BufferSource },\n key,\n utf8Bytes(VERIFIER_SENTINEL) as BufferSource,\n );\n return base64Encode(new Uint8Array(ct));\n}\n\n/**\n * Initialise the workspace's secret crypto state. Called the first time\n * the user creates a passphrase (new workspace or first secret added in\n * a workspace that hasn't set one).\n *\n * Returns the SecretCrypto blob to persist in workspace.json **and** the\n * derived key so the caller can immediately use it.\n *\n * The `iterations` override exists for tests — production callers should\n * always use the default `PBKDF2_ITERATIONS` (OWASP floor). Tests pin a\n * smaller count so the suite stays fast under parallel load; the\n * algorithm path is identical either way.\n */\nexport async function initSecretCrypto(\n passphrase: string,\n iterations: number = PBKDF2_ITERATIONS,\n): Promise<{ crypto: SecretCrypto; key: CryptoKey }> {\n if (passphrase.length === 0) throw new Error('Passphrase cannot be empty');\n if (iterations < 1) throw new Error('iterations must be >= 1');\n const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES));\n const key = await deriveKey(passphrase, salt, iterations);\n const verifier = await computeVerifier(key);\n return {\n crypto: {\n kdf: 'pbkdf2-sha256-v1',\n salt: base64Encode(salt),\n iterations,\n verifier,\n },\n key,\n };\n}\n\n/**\n * Unlock the workspace given a passphrase + the stored SecretCrypto blob.\n *\n * Returns `{ ok: true, key }` on a successful passphrase match (verifier\n * matches), `{ ok: false }` on any mismatch — wrong passphrase, corrupt\n * blob, unsupported KDF. The caller surfaces the right UX for each.\n */\nexport async function unlockSecretCrypto(\n passphrase: string,\n blob: SecretCrypto,\n): Promise<{ ok: true; key: CryptoKey } | { ok: false; reason: string }> {\n if (blob.kdf !== 'pbkdf2-sha256-v1') {\n return { ok: false, reason: `Unsupported KDF: ${String(blob.kdf)}` };\n }\n let salt: Uint8Array;\n try {\n salt = base64Decode(blob.salt);\n } catch {\n return { ok: false, reason: 'Workspace secret salt is corrupt.' };\n }\n let key: CryptoKey;\n try {\n key = await deriveKey(passphrase, salt, blob.iterations);\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : 'Key derivation failed' };\n }\n const verifier = await computeVerifier(key);\n if (verifier !== blob.verifier) {\n return { ok: false, reason: 'Wrong passphrase.' };\n }\n return { ok: true, key };\n}\n","// Branch-name generator for the auto-create-from-main flow.\n//\n// Format: `apicircle/<slug>-<6char-id>`, where:\n// - <slug> is the workspace's local display name normalised to lowercase\n// ASCII alphanumerics joined by hyphens. Empty slugs fall back to\n// `workspace`. The display name comes from the local registry — git\n// no longer carries a workspace name, since the name is per-machine.\n// - <6char-id> is a short random suffix that keeps subsequent branches from\n// colliding when a user creates more than one working branch from the\n// same workspace.\n//\n// The generator is pure and deterministic given an `idGen` function — tests\n// inject a fixed id so assertions are stable.\n\nconst SLUG_FALLBACK = 'workspace';\nconst SUFFIX_LEN = 6;\n\n/**\n * Validate a branch name against GitHub's ref rules. Returns null when the\n * name is acceptable, otherwise a short reason. We enforce a stricter\n * subset (no spaces, ASCII only, length ≤ 100) so the auto-generated names\n * always pass.\n */\nexport function validateBranchName(name: string): string | null {\n if (!name) return 'Branch name is required';\n if (name.length > 100) return 'Branch name is too long (max 100 chars)';\n if (/\\s/.test(name)) return 'Branch name cannot contain whitespace';\n // Control chars + Git-disallowed punctuation are intentional in this class.\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1f\\x7f~^:?*\\\\[\\]]/.test(name)) return 'Branch name has illegal characters';\n if (name.startsWith('-') || name.startsWith('/')) return 'Branch name cannot start with - or /';\n if (name.endsWith('.') || name.endsWith('/') || name.endsWith('.lock'))\n return 'Branch name cannot end with . or / or .lock';\n if (name.includes('..') || name.includes('//') || name.includes('@{'))\n return 'Branch name has invalid sequence';\n return null;\n}\n\n/** Lowercase ASCII slug, hyphenated, no leading/trailing/double hyphens. */\nexport function slugify(input: string): string {\n const slug = input\n .toLowerCase()\n .normalize('NFKD')\n .replace(/[̀-ͯ]/g, '') // strip combining marks (accents)\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return slug || SLUG_FALLBACK;\n}\n\nexport interface BranchNameOptions {\n /** The workspace's local display name (from the registry entry). */\n displayName: string;\n /** Inject a fixed id in tests; defaults to 6 random hex chars. */\n idGen?: () => string;\n}\n\nexport function generateWorkingBranchName(opts: BranchNameOptions): string {\n const slug = slugify(opts.displayName);\n const id = (opts.idGen ?? randomHex)();\n return `apicircle/${slug}-${id}`;\n}\n\nfunction randomHex(): string {\n const bytes = new Uint8Array(Math.ceil(SUFFIX_LEN / 2));\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\n crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0'))\n .join('')\n .slice(0, SUFFIX_LEN);\n}\n","import type { WorkspaceSynced } from '@apicircle/shared';\n\n// Canonical serializer for the workspace.json that lands in Git. Stable\n// key order so re-pushing the same logical state produces byte-identical\n// JSON, which means GitHub diffs stay minimal across pushes.\n//\n// The on-disk path lives in `repoPaths.ts` (`.apicircle/workspace-<id>/workspace.json`).\n// This function only decides the bytes; callers pick the path.\n\nconst INDENT = 2;\n\n/**\n * Stringify a WorkspaceSynced doc with deeply-sorted object keys + 2-space\n * indent + trailing newline (so editors don't re-stamp the file when the\n * user opens it). Arrays preserve their existing order — that's part of\n * the workspace's user-visible shape (priority list, tree children, etc).\n */\nexport function serializeWorkspaceForGit(synced: WorkspaceSynced): string {\n return `${stringifySorted(synced)}\\n`;\n}\n\nfunction stringifySorted(value: unknown): string {\n return JSON.stringify(value, sortedReplacer, INDENT);\n}\n\nfunction sortedReplacer(this: unknown, _key: string, value: unknown): unknown {\n if (value === null || typeof value !== 'object') return value;\n if (Array.isArray(value)) return value;\n // Sort plain objects' keys; non-plain objects (e.g. dates) pass through\n // as-is via JSON.stringify's default coercion.\n const proto = Object.getPrototypeOf(value) as object | null;\n if (proto !== Object.prototype && proto !== null) return value;\n const source = value as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(source).sort()) {\n const v: unknown = source[k];\n out[k] = v;\n }\n return out;\n}\n","// Canonical repo paths for everything API Circle Studio writes into a\n// user's GitHub repo. Every file lives under a single `.apicircle/`\n// dotfolder at the repo root so the repo can also host READMEs, CI\n// configs, and unrelated tooling at the root without colliding with our\n// payload.\n//\n// Layout:\n// .apicircle/\n// registry.json\n// workspace-<id>/\n// workspace.json\n// attachments/\n// <slotId>\n\n/** The dotfolder under the repo root that owns every API-Circle-managed\n * file in a Git-backed workspace. */\nexport const WORKSPACE_DIR = '.apicircle';\n\n/** Path to the workspace registry inside a repo / root. */\nexport const REGISTRY_JSON_PATH = `${WORKSPACE_DIR}/registry.json`;\n\n/** On-disk path for the synced workspace document inside a Git repo. */\nexport function workspaceJsonPath(workspaceId: string): string {\n return `${WORKSPACE_DIR}/workspace-${workspaceId}/workspace.json`;\n}\n\n/** Directory holding per-attachment blob files (`<slotId>`). */\nexport function attachmentsDir(workspaceId: string): string {\n return `${WORKSPACE_DIR}/workspace-${workspaceId}/attachments`;\n}\n\n/** Build the on-disk path for a single attachment slot. Caller is\n * responsible for URL-encoding when this is passed to the GitHub\n * Contents API. */\nexport function attachmentPath(workspaceId: string, slotId: string): string {\n return `${attachmentsDir(workspaceId)}/${slotId}`;\n}\n\n/**\n * Parse a registry JSON string (fetched from a remote repo's\n * `.apicircle/registry.json`) and return the active workspace ID.\n * Falls back to the first entry when `activeWorkspaceId` is null.\n * Returns `null` if the registry is empty or unparseable.\n */\nexport function parseRegistryActiveId(registryJsonContent: string): string | null {\n try {\n const parsed = JSON.parse(registryJsonContent) as {\n activeWorkspaceId?: string | null;\n workspaces?: Array<{ id: string }>;\n };\n return parsed.activeWorkspaceId ?? parsed.workspaces?.[0]?.id ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Two-step resolution of a remote workspace.json path. Pass a generic\n * file-fetcher so this stays decoupled from any particular API client.\n *\n * 1. Fetches `registry.json` from the remote `.apicircle/` dir.\n * 2. Parses it to find the active workspace ID.\n * 3. Fetches `workspace-<id>/workspace.json`.\n *\n * Returns `{ workspaceId, content }` on success, or `{ error }` on failure.\n */\nexport async function fetchRemoteWorkspaceJson(\n fetchFile: (repoPath: string) => Promise<string | null>,\n): Promise<{ workspaceId: string; content: string } | { error: string }> {\n const registryContent = await fetchFile(REGISTRY_JSON_PATH);\n if (registryContent === null) return { error: 'No .apicircle/registry.json found in repo' };\n const wsId = parseRegistryActiveId(registryContent);\n if (!wsId) return { error: 'Registry is empty — no workspaces found' };\n const wsContent = await fetchFile(workspaceJsonPath(wsId));\n if (wsContent === null) return { error: `No workspace.json at .apicircle/workspace-${wsId}/` };\n return { workspaceId: wsId, content: wsContent };\n}\n","// Safe parser for any `workspace.json` we read from a Git remote.\n//\n// Threat: the workspace.json file on the remote is whatever a collaborator\n// (or anyone with write access to the repo) pushed. Treating it as a\n// trusted `WorkspaceSynced` and merging it into store state is a primary\n// attack surface — three audit findings clustered here:\n//\n// 1. JSON content can carry `\"__proto__\"` / `\"constructor\"` keys that\n// pollute Object.prototype when shallow-merged or even just iterated\n// with `for...in`. We strip those keys at parse time via a reviver.\n//\n// 2. `JSON.parse(x) as WorkspaceSynced` is a TypeScript-only lie. The\n// remote could have any shape — empty object, deeply-nested arrays,\n// missing required fields. We enforce a minimum shape that matches\n// what every downstream consumer (three-way diff, schema-version\n// migrations, store rehydrate) relies on.\n//\n// 3. A malicious workspace.json can be massive (gigabytes of nested\n// junk) — we cap the input string length before JSON.parse even\n// runs so a hostile blob can't OOM the renderer.\n//\n// We deliberately don't enforce a full Zod schema — the WorkspaceSynced\n// type is hundreds of fields and would balloon this module. The audit's\n// concrete asks are (a) prototype-pollution defense and (b) reject docs\n// that aren't structurally workspaces. Both are achieved here.\n\nimport type { WorkspaceSynced } from '@apicircle/shared';\n\n/** Hard cap on the JSON string length we'll accept. 16 MiB is generous\n * for any realistic workspace doc — Git tooling chokes on much smaller\n * files anyway. Reject anything past this rather than letting the parser\n * walk megabytes of attacker-controlled bytes. */\nconst MAX_WORKSPACE_JSON_BYTES = 16 * 1024 * 1024;\n\n/** Names of object keys we drop at parse time. Setting `__proto__`,\n * `constructor`, or `prototype` as an OWN property doesn't mutate\n * Object.prototype the same way `__proto__` assignment does, but `for...in`\n * iteration / shallow-merge code can still surprise itself. Dropping them\n * at the reviver boundary is the safest place. */\nconst FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** Error thrown when the input fails any of our checks. `code` lets the UI\n * branch on the specific failure (oversized, bad JSON, wrong shape, etc.)\n * without parsing the message string. */\nexport class RemoteWorkspaceParseError extends Error {\n constructor(\n message: string,\n readonly code:\n | 'oversized'\n | 'invalid-json'\n | 'not-object'\n | 'missing-workspace-id'\n | 'missing-collections'\n | 'missing-environments',\n ) {\n super(message);\n this.name = 'RemoteWorkspaceParseError';\n }\n}\n\n/**\n * Parse a remote `workspace.json` and return a `WorkspaceSynced` we can\n * safely merge into store state. Throws `RemoteWorkspaceParseError` on\n * any failure — callers should catch and surface to the user as a\n * \"this workspace was modified by an incompatible version\" message.\n *\n * The returned object is NOT a deep clone of the input; if any nested\n * object had a `__proto__` etc. key, that key was dropped at the reviver\n * level. Strings, numbers, and arrays pass through unchanged.\n *\n * The function is intentionally PERMISSIVE about unknown fields — newer\n * versions of Studio may add fields we don't know about, and we want\n * those workspaces to remain readable. We only enforce the fields the\n * existing codebase positively requires.\n */\nexport function parseWorkspaceJson(content: string): WorkspaceSynced {\n if (content.length > MAX_WORKSPACE_JSON_BYTES) {\n throw new RemoteWorkspaceParseError(\n `Workspace document exceeds ${MAX_WORKSPACE_JSON_BYTES} bytes (got ${content.length})`,\n 'oversized',\n );\n }\n let raw: unknown;\n try {\n // The reviver runs once per (key, value) pair. Returning `undefined`\n // drops the property. This is the canonical way to strip dangerous\n // keys at parse time — V8 doesn't even attach the value to the parent\n // object. Cheaper and safer than walking the tree afterwards.\n raw = JSON.parse(content, (key: string, value: unknown) => {\n if (FORBIDDEN_KEYS.has(key)) return undefined;\n return value;\n });\n } catch (err) {\n throw new RemoteWorkspaceParseError(\n `Remote workspace.json is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n 'invalid-json',\n );\n }\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n throw new RemoteWorkspaceParseError('Remote workspace.json is not a JSON object', 'not-object');\n }\n const obj = raw as Record<string, unknown>;\n\n // Minimum shape: every field below is read unconditionally by the store\n // and three-way diff. A missing one means we're either looking at a\n // half-empty doc or a totally different schema; either way we refuse.\n if (typeof obj.workspaceId !== 'string' || obj.workspaceId.length === 0) {\n throw new RemoteWorkspaceParseError(\n 'Remote workspace.json is missing workspaceId',\n 'missing-workspace-id',\n );\n }\n if (\n typeof obj.collections !== 'object' ||\n obj.collections === null ||\n Array.isArray(obj.collections)\n ) {\n throw new RemoteWorkspaceParseError(\n 'Remote workspace.json is missing or malformed `collections`',\n 'missing-collections',\n );\n }\n if (\n typeof obj.environments !== 'object' ||\n obj.environments === null ||\n Array.isArray(obj.environments)\n ) {\n throw new RemoteWorkspaceParseError(\n 'Remote workspace.json is missing or malformed `environments`',\n 'missing-environments',\n );\n }\n\n // Shape passes — return the parsed value cast to the workspace type.\n // Unknown fields are preserved; the consumer is responsible for any\n // schema-version handling.\n return obj as unknown as WorkspaceSynced;\n}\n","// Redact secret-bearing fields from a `WorkspaceSynced` before it goes to\n// Git. The pushed `workspace.json` is visible to every collaborator (and to\n// the world on public repos), so it CANNOT carry passwords, bearer tokens,\n// client secrets, AWS keys, Hawk keys, JWT signing keys, OAuth2 refresh\n// tokens — none of it.\n//\n// Design:\n//\n// 1. `redactForGit(synced)` walks every Request.auth and returns a copy\n// with the credential-bearing fields blanked to `''`. Identity\n// fields (clientId, username, tokenUrl, authUrl, etc.) are kept —\n// they're not secrets and consumers need them to know which IdP to\n// talk to.\n//\n// 2. `assertNoPlaintextCredentials(serialized)` is a fail-closed lint\n// pass over the already-serialised JSON. If any credential-only\n// field name appears with a non-empty value, push is refused.\n// Defends against:\n// - a future RequestAuth variant we forget to wire into redactForGit\n// - a future workspace-state field that ends up carrying secrets\n// - any path that bypasses redactForGit by mistake\n//\n// Pre-launch tradeoff: we accept that pulling from git will surface\n// requests with blank credentials. The user re-supplies them from the\n// Secret Vault locally. A future Phase 8 follow-up will introduce a\n// `{{!SECRET:<id>}}` placeholder system so the vault auto-fills on pull.\n\nimport type { RequestAuth, WorkspaceSynced } from '@apicircle/shared';\n\n/** Field names that ALWAYS carry a credential when non-empty. Used by the\n * serialised-output lint pass below. Names like `value`, `token` (in\n * `JwtBearerAuth.token` it's a pre-computed JWT — also a credential) and\n * `key` are deliberately NOT in this list because they appear in many\n * non-credential contexts (header rows, secret-vault metadata, etc.); the\n * redactor takes care of those structurally rather than by regex. */\nconst PLAINTEXT_CREDENTIAL_FIELD_NAMES = [\n 'password',\n 'clientSecret',\n 'secretAccessKey',\n 'sessionToken',\n 'refreshToken',\n 'accessToken',\n 'hawkKey',\n 'secretOrKey',\n] as const;\n\n/**\n * Return a copy of `synced` with every credential-bearing field in every\n * Request.auth blanked to ''. Identity fields are preserved. Pure — does\n * not mutate the input. Safe to call on partially-shaped workspaces.\n */\nexport function redactForGit(synced: WorkspaceSynced): WorkspaceSynced {\n const requests: WorkspaceSynced['collections']['requests'] = {};\n for (const [id, req] of Object.entries(synced.collections.requests)) {\n requests[id] = { ...req, auth: redactAuth(req.auth) };\n }\n // Folders carry auth too (folder-level auth inheritance). Redact those.\n const folders: WorkspaceSynced['collections']['folders'] = {};\n for (const [id, folder] of Object.entries(synced.collections.folders)) {\n folders[id] = folder.auth ? { ...folder, auth: redactAuth(folder.auth) } : { ...folder };\n }\n return {\n ...synced,\n collections: { ...synced.collections, requests, folders },\n };\n}\n\nfunction redactAuth(auth: RequestAuth): RequestAuth {\n switch (auth.type) {\n case 'none':\n case 'inherit':\n case 'custom-header':\n // Custom header `value` is user-typed text — could be a secret but\n // the redactor can't know. Users wanting secret semantics should\n // use the Secret Vault + variable interpolation. Same applies to\n // api-key.value below.\n return auth;\n case 'basic':\n return { ...auth, password: '' };\n case 'bearer':\n return { ...auth, token: '' };\n case 'api-key':\n // api-key.value is the credential. Blank it.\n return { ...auth, value: '' };\n case 'digest':\n case 'ntlm':\n return { ...auth, password: '' };\n case 'hawk':\n return { ...auth, hawkKey: '' };\n case 'jwt-bearer':\n // Blank both the signing key AND the pre-computed token — both are\n // credential material (the token is what's actually sent on the\n // wire; the key lets you mint more of them).\n return { ...auth, secretOrKey: '', token: '' };\n case 'aws-sigv4':\n return { ...auth, secretAccessKey: '', sessionToken: '' };\n case 'oauth2-client-credentials':\n case 'oauth2-auth-code':\n case 'oauth2-pkce':\n return { ...auth, clientSecret: '', accessToken: '', refreshToken: '' };\n case 'oauth2-password':\n return { ...auth, clientSecret: '', password: '', accessToken: '', refreshToken: '' };\n case 'oauth2-implicit':\n // Implicit grant has no clientSecret + no refreshToken in the type.\n return { ...auth, accessToken: '' };\n case 'oauth2-device':\n // Device flow is public-client by design — no clientSecret in the\n // type. Just blank the tokens.\n return { ...auth, accessToken: '', refreshToken: '' };\n default: {\n // Exhaustiveness check — if a new auth variant is added without a\n // case here, TypeScript flags the assignment below.\n const _exhaustive: never = auth;\n void _exhaustive;\n return auth;\n }\n }\n}\n\n/**\n * Scan the already-serialised workspace JSON for any credential-only\n * field name with a non-empty value. Throws if found — the push path\n * should treat the throw as fatal (refuse to upload).\n *\n * The match is intentionally narrow: only the names in\n * `PLAINTEXT_CREDENTIAL_FIELD_NAMES`, only with a NON-EMPTY string value.\n * An empty-string credential (`\"password\":\"\"`) is acceptable — that's\n * what `redactForGit` produces.\n *\n * Implementation note: we use a regex rather than walking the parsed\n * tree because (a) the input has already been serialised, and (b) the\n * regex catches every nesting level without us having to know the shape.\n * The risk of false positives is bounded because the field names are\n * specific (no `value` / `token` / `key` in the list).\n */\nexport function assertNoPlaintextCredentials(serialized: string): void {\n for (const name of PLAINTEXT_CREDENTIAL_FIELD_NAMES) {\n // `\"name\":\"<at least one char that isn't a closing quote>\"`\n // We allow any chars in the value (incl. escaped) — the test is\n // \"is the value non-empty?\". A zero-length value (`\"\"`) doesn't match.\n const re = new RegExp(`\"${name}\"\\\\s*:\\\\s*\"(?:[^\"\\\\\\\\]|\\\\\\\\.)+\"`);\n const match = re.exec(serialized);\n if (match) {\n throw new Error(\n `Refusing to push workspace.json: credential field \"${name}\" carries a non-empty value. ` +\n `This is a redaction bug — every plaintext credential MUST be blanked before serialisation.`,\n );\n }\n }\n}\n","import type { MockResponseBody, MockResponseConfig, WorkspaceSynced } from '@apicircle/shared';\n\n// Attachment slots referenced by the synced doc. Push (P4.3b) walks\n// every request body and bundles each referenced blob into the same\n// Git Tree commit as workspace.json — so the repo always carries a\n// self-consistent snapshot.\n\nexport interface AttachmentSlotRef {\n slotId: string;\n sha256?: string;\n filename?: string;\n mimeType?: string;\n size?: number;\n}\n\n/**\n * Walk every request in the synced doc and return one entry per unique\n * attachment slotId it references. Form-data file rows and the binary\n * body's attachment ref both contribute. Duplicates (same slotId\n * referenced twice — defensive only; slot ids are normally unique) are\n * collapsed; the first occurrence wins.\n */\nexport function collectAttachmentSlots(synced: WorkspaceSynced): AttachmentSlotRef[] {\n const seen = new Map<string, AttachmentSlotRef>();\n for (const req of Object.values(synced.collections.requests)) {\n if (req.body.type === 'form-data' && req.body.formRows) {\n for (const row of req.body.formRows) {\n if (row.kind === 'file' && row.slotId && !seen.has(row.slotId)) {\n seen.set(row.slotId, {\n slotId: row.slotId,\n sha256: row.sha256,\n filename: row.filename,\n mimeType: row.mimeType,\n size: row.size,\n });\n }\n }\n }\n if (req.body.type === 'binary') {\n const ref = req.body.attachment;\n if (ref?.slotId && !seen.has(ref.slotId)) {\n seen.set(ref.slotId, {\n slotId: ref.slotId,\n sha256: ref.sha256,\n filename: ref.filename,\n mimeType: ref.mimeType,\n size: ref.size,\n });\n }\n }\n }\n for (const server of Object.values(synced.mockServers ?? {})) {\n for (const endpoint of server.endpoints) {\n collectMockResponseAttachment(endpoint.defaultResponse, seen);\n for (const rule of endpoint.requestValidation ?? []) {\n collectMockResponseAttachment(rule.failResponse, seen);\n }\n for (const rule of endpoint.responseRules ?? []) {\n collectMockResponseAttachment(rule.response, seen);\n }\n }\n }\n for (const file of Object.values(synced.globalAssets.files ?? {})) {\n if (!seen.has(file.slotId)) {\n seen.set(file.slotId, {\n slotId: file.slotId,\n sha256: file.sha256,\n filename: file.filename,\n mimeType: file.mimeType,\n size: file.size,\n });\n }\n }\n return [...seen.values()];\n}\n\nfunction collectMockResponseAttachment(\n response: MockResponseConfig | null | undefined,\n seen: Map<string, AttachmentSlotRef>,\n): void {\n collectMockResponseBodyAttachment(response?.body, seen);\n}\n\nfunction collectMockResponseBodyAttachment(\n body: MockResponseBody | null | undefined,\n seen: Map<string, AttachmentSlotRef>,\n): void {\n if (body?.type !== 'binary') return;\n const ref = body.attachment;\n if (!ref?.slotId || seen.has(ref.slotId)) return;\n seen.set(ref.slotId, {\n slotId: ref.slotId,\n sha256: ref.sha256,\n filename: ref.filename,\n mimeType: ref.mimeType,\n size: ref.size,\n });\n}\n","// Tiny semver helpers — we only need parse + compare. Pulling in the\n// full `semver` package adds 30+ KB for behavior we use in two spots.\n\nconst SEMVER_RE = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+([0-9A-Za-z.-]+))?$/;\n\nexport interface ParsedVersion {\n major: number;\n minor: number;\n patch: number;\n prerelease: string | null;\n build: string | null;\n}\n\nexport function parseSemver(version: string): ParsedVersion | null {\n const m = SEMVER_RE.exec(version.trim());\n if (!m) return null;\n return {\n major: Number(m[1]),\n minor: Number(m[2]),\n patch: Number(m[3]),\n prerelease: m[4] ?? null,\n build: m[5] ?? null,\n };\n}\n\nexport function isValidSemver(version: string): boolean {\n return parseSemver(version) !== null;\n}\n\n/**\n * Compare two semver strings. Returns negative if `a < b`, positive if\n * `a > b`, 0 if equal. Build metadata is ignored (per semver spec). A\n * prerelease label sorts BEFORE its corresponding release (1.0.0-rc.1 <\n * 1.0.0). Within prereleases, dot-separated identifiers compare numeric\n * vs string per the spec.\n */\nexport function compareSemver(a: string, b: string): number {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) return a.localeCompare(b);\n if (pa.major !== pb.major) return pa.major - pb.major;\n if (pa.minor !== pb.minor) return pa.minor - pb.minor;\n if (pa.patch !== pb.patch) return pa.patch - pb.patch;\n // Prerelease ordering: a release > a prerelease of the same triple.\n if (pa.prerelease === null && pb.prerelease === null) return 0;\n if (pa.prerelease === null) return 1;\n if (pb.prerelease === null) return -1;\n return comparePrereleaseIdentifiers(pa.prerelease, pb.prerelease);\n}\n\nfunction comparePrereleaseIdentifiers(a: string, b: string): number {\n const aIds = a.split('.');\n const bIds = b.split('.');\n const len = Math.max(aIds.length, bIds.length);\n for (let i = 0; i < len; i++) {\n const ai = aIds[i];\n const bi = bIds[i];\n if (ai === undefined) return -1;\n if (bi === undefined) return 1;\n const aNum = /^\\d+$/.test(ai) ? Number(ai) : null;\n const bNum = /^\\d+$/.test(bi) ? Number(bi) : null;\n if (aNum !== null && bNum !== null) {\n if (aNum !== bNum) return aNum - bNum;\n } else if (aNum !== null) {\n return -1; // numeric sorts before alpha\n } else if (bNum !== null) {\n return 1;\n } else if (ai !== bi) {\n return ai.localeCompare(bi);\n }\n }\n return 0;\n}\n\n/** Sort an array of semver strings — newest first (descending). */\nexport function sortVersionsDesc(versions: readonly string[]): string[] {\n return [...versions].sort((a, b) => compareSemver(b, a));\n}\n","import type { ReleaseHistory, ReleaseVersion, WorkspaceSynced } from '@apicircle/shared';\nimport { serializeWorkspaceForGit } from '../git/serializeWorkspace';\nimport { isValidSemver } from './semver';\n\n// Workspace-self release publishing. The synced doc is the source of\n// truth; releases.self carries the ledger; the published version's\n// `workspaceSnapshot` is the SHA-256 of the canonical pre-publish\n// workspace.json so consumers can verify integrity.\n\nexport interface PublishReleaseArgs {\n version: string;\n notes: string;\n /** Optional bookkeeping — the git commit SHA the release points at. */\n sha?: string;\n /** Optional bookkeeping — git tag name (the source of truth is the ledger). */\n tagName?: string;\n publishedAt?: string;\n}\n\n/**\n * Build a fully-formed `ReleaseVersion` entry for `synced` — computing the\n * SHA-256 `workspaceSnapshot` of the canonical pre-publish workspace.json.\n *\n * This is the async half of publishing, split out so the sync mutation path\n * (`applyMutation` → `appendReleaseEntry`) stays pure: headless writers\n * (VS Code / MCP / CLI) call `buildReleaseEntry` first, then route the\n * resulting entry through the `release.publish` patch.\n *\n * Throws on invalid semver.\n */\nexport async function buildReleaseEntry(\n synced: WorkspaceSynced,\n args: PublishReleaseArgs,\n): Promise<ReleaseVersion> {\n const version = args.version.trim();\n if (!isValidSemver(version)) {\n throw new Error(`Invalid semver: ${args.version}`);\n }\n // The snapshot represents the doc *as of the moment of publishing*: we\n // stamp the SHA before writing the new version entry so it's a stable\n // fingerprint of the workspace data the release is built on.\n const snapshotSource = serializeWorkspaceForGit(synced);\n const workspaceSnapshot = await sha256Hex(snapshotSource);\n\n return {\n version,\n publishedAt: args.publishedAt ?? new Date().toISOString(),\n notes: args.notes,\n workspaceSnapshot,\n deprecated: false,\n yanked: false,\n ...(args.sha ? { sha: args.sha } : {}),\n ...(args.tagName ? { tagName: args.tagName } : {}),\n };\n}\n\n/**\n * Append a pre-built `ReleaseVersion` to `synced.releases.self.versions` and\n * bump `currentVersion`. Pure + synchronous — the SHA was already computed by\n * `buildReleaseEntry`, so this is safe to call from `applyMutation`.\n *\n * `now` defaults to the entry's own `publishedAt` so the convenience\n * `publishRelease` wrapper keeps its original stamping; `applyMutation`\n * passes its injected timestamp for deterministic batches.\n *\n * Throws on invalid semver or a duplicate version.\n */\nexport function appendReleaseEntry(\n synced: WorkspaceSynced,\n entry: ReleaseVersion,\n now: string = entry.publishedAt,\n): WorkspaceSynced {\n if (!isValidSemver(entry.version)) {\n throw new Error(`Invalid semver: ${entry.version}`);\n }\n const ledger = synced.releases.self ?? emptyLedger();\n if (ledger.versions.some((v) => v.version === entry.version)) {\n throw new Error(`Version ${entry.version} already exists in this workspace's release ledger`);\n }\n const next: ReleaseHistory = {\n versions: [...ledger.versions, entry],\n currentVersion: entry.version,\n };\n return {\n ...synced,\n releases: { ...synced.releases, self: next },\n meta: { ...synced.meta, updatedAt: now },\n };\n}\n\n/**\n * Append a new release to `synced.releases.self.versions` and bump\n * `currentVersion`. Convenience wrapper = `buildReleaseEntry` +\n * `appendReleaseEntry`. Pure — does not touch IDB or Git.\n *\n * Throws on invalid semver, duplicate version, or invalid notes shape.\n */\nexport async function publishRelease(\n synced: WorkspaceSynced,\n args: PublishReleaseArgs,\n): Promise<WorkspaceSynced> {\n const entry = await buildReleaseEntry(synced, args);\n return appendReleaseEntry(synced, entry);\n}\n\n/** Flip the `deprecated` flag on a version. Soft signal — version is still installable. */\nexport function deprecateRelease(\n synced: WorkspaceSynced,\n version: string,\n now: string = new Date().toISOString(),\n): WorkspaceSynced {\n return mapReleaseVersion(synced, version, (v) => ({ ...v, deprecated: true }), now);\n}\n\n/**\n * Flip the `yanked` flag on a version. Hard signal — consumers should\n * be told this version is broken / unsafe and offered a different one.\n */\nexport function yankRelease(\n synced: WorkspaceSynced,\n version: string,\n now: string = new Date().toISOString(),\n): WorkspaceSynced {\n return mapReleaseVersion(synced, version, (v) => ({ ...v, yanked: true }), now);\n}\n\nfunction mapReleaseVersion(\n synced: WorkspaceSynced,\n version: string,\n fn: (v: ReleaseVersion) => ReleaseVersion,\n now: string,\n): WorkspaceSynced {\n const ledger = synced.releases.self;\n if (!ledger) throw new Error('No releases to modify');\n const idx = ledger.versions.findIndex((v) => v.version === version);\n if (idx === -1) throw new Error(`Version ${version} not found`);\n const versions = [...ledger.versions];\n versions[idx] = fn(versions[idx]);\n return {\n ...synced,\n releases: { ...synced.releases, self: { ...ledger, versions } },\n meta: { ...synced.meta, updatedAt: now },\n };\n}\n\nfunction emptyLedger(): ReleaseHistory {\n return { versions: [], currentVersion: null };\n}\n\nasync function sha256Hex(text: string): Promise<string> {\n const bytes = new TextEncoder().encode(text);\n const digest = await crypto.subtle.digest('SHA-256', bytes);\n return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');\n}\n","import type {\n LinkedSnapshot,\n LinkedWorkspace,\n ReleaseHistory,\n SecretKeyMeta,\n WorkspaceSynced,\n} from '@apicircle/shared';\n\n// =============================================================================\n// Linked-workspace snapshot helpers — the PURE half of the link/refresh flow.\n//\n// `parseLinkedWorkspaceJson` decodes a remote `.apicircle/workspace-<id>/workspace.json`\n// (fetched over the GitHub API by the host) into the slices a consumer needs:\n// the release ledger, the collections + environments tree, the secret-key\n// registry, and the global-asset library. `buildLinkedSnapshot` turns that +\n// the link record into the `LinkedSnapshot` cached in\n// `WorkspaceLocal.linkedCollections`.\n//\n// Both are pure + network-free so the UI store, the VS Code extension, and the\n// CLI share one implementation. The network fetch + applyMutation write live\n// in the caller.\n// =============================================================================\n\nexport interface LinkedWorkspaceProbe {\n workspaceId?: string;\n releases?: { self?: ReleaseHistory | null };\n collections?: WorkspaceSynced['collections'];\n environments?: WorkspaceSynced['environments'];\n secretKeys?: Record<string, SecretKeyMeta>;\n globalAssets?: WorkspaceSynced['globalAssets'];\n}\n\nconst LINKED_FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\nconst MAX_LINKED_JSON_BYTES = 16 * 1024 * 1024;\n\n/**\n * Parse + sanitize a remote workspace.json string into the slices a linked\n * consumer reads. Throws on oversized input, invalid JSON, or a non-object\n * root. Prototype-pollution keys are stripped at parse time.\n */\nexport function parseLinkedWorkspaceJson(text: string): LinkedWorkspaceProbe {\n if (text.length > MAX_LINKED_JSON_BYTES) {\n throw new Error('Remote workspace.json exceeds 16 MiB');\n }\n let raw: unknown;\n try {\n raw = JSON.parse(text, (key: string, value: unknown) =>\n LINKED_FORBIDDEN_KEYS.has(key) ? undefined : value,\n );\n } catch {\n throw new Error('Remote workspace.json is not valid JSON');\n }\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n throw new Error('Remote workspace.json is not an object');\n }\n const obj = raw as Record<string, unknown>;\n const asObject = <T>(v: unknown): T | undefined =>\n typeof v === 'object' && v !== null ? (v as T) : undefined;\n return {\n workspaceId: typeof obj.workspaceId === 'string' ? obj.workspaceId : undefined,\n releases: asObject<{ self?: ReleaseHistory | null }>(obj.releases),\n collections: asObject<WorkspaceSynced['collections']>(obj.collections),\n environments: asObject<WorkspaceSynced['environments']>(obj.environments),\n secretKeys: asObject<Record<string, SecretKeyMeta>>(obj.secretKeys),\n globalAssets: asObject<WorkspaceSynced['globalAssets']>(obj.globalAssets),\n };\n}\n\n/** The cached ledger from a probe, defaulting to an empty ledger. */\nexport function ledgerFromProbe(parsed: LinkedWorkspaceProbe): ReleaseHistory {\n return parsed.releases?.self ?? { versions: [], currentVersion: null };\n}\n\n/**\n * Build the `LinkedSnapshot` cached in `WorkspaceLocal.linkedCollections` from\n * a parsed probe + the link record. Returns null when the source has neither\n * collections nor environments to cache.\n */\nexport function buildLinkedSnapshot(\n parsed: LinkedWorkspaceProbe,\n link: LinkedWorkspace,\n): LinkedSnapshot | null {\n if (!parsed.collections && !parsed.environments) return null;\n return {\n pulledAt: link.linkedAt,\n ref: link.pinnedVersion ? `v${link.pinnedVersion}` : `HEAD@${link.source.branch}`,\n collections: parsed.collections ?? {\n tree: { id: 'remote-root', type: 'root', children: [] },\n requests: {},\n folders: {},\n },\n environments: parsed.environments ?? {\n items: {},\n activeName: null,\n priorityOrder: [],\n },\n ...(parsed.secretKeys ? { secretKeys: parsed.secretKeys } : {}),\n ...(parsed.globalAssets ? { globalAssets: parsed.globalAssets } : {}),\n };\n}\n","import type { Request as ApiRequest, RequestOverridePatch } from '@apicircle/shared';\n\n// =============================================================================\n// Linked-request override helpers — the field-level delta a consumer layers on\n// top of a linked workspace's source request.\n//\n// mergeRequestOverride(base, patch) → the EFFECTIVE request the consumer\n// sees / sends (source + their edits).\n// computeRequestOverridePatch(base, → the delta that reproduces `effective`\n// effective) from `base` (only diverging fields).\n//\n// The two are inverses: merge(base, compute(base, eff)) ≡ eff. Pure + shared by\n// runPlan, the web editor, and the VS Code linked-request projection so the\n// override semantics never drift.\n// =============================================================================\n\n// The overridable fields — must mirror `RequestOverridePatch` in\n// `@apicircle/shared` (identity / asset-ref fields are NOT overridable).\nconst OVERRIDABLE_FIELDS = [\n 'name',\n 'method',\n 'url',\n 'headers',\n 'query',\n 'pathParams',\n 'cookies',\n 'body',\n 'auth',\n 'contextVars',\n 'extractions',\n 'assertions',\n] as const;\n\ntype OverridableField = (typeof OVERRIDABLE_FIELDS)[number];\n\n/** Layer a consumer's override patch onto a source request. */\nexport function mergeRequestOverride(base: ApiRequest, patch: RequestOverridePatch): ApiRequest {\n const merged: ApiRequest = { ...base };\n const p = patch as Record<string, unknown>;\n const target = merged as unknown as Record<string, unknown>;\n for (const field of OVERRIDABLE_FIELDS) {\n if (p[field] !== undefined) target[field] = p[field];\n }\n return merged;\n}\n\n/**\n * Compute the minimal override patch that turns `base` into `effective` —\n * only the overridable fields that structurally differ. Returns `{}` when the\n * effective request is identical to the source (caller drops the override).\n */\nexport function computeRequestOverridePatch(\n base: ApiRequest,\n effective: ApiRequest,\n): RequestOverridePatch {\n const baseRec: Record<string, unknown> = { ...base };\n const effRec: Record<string, unknown> = { ...effective };\n const patch: RequestOverridePatch = {};\n const patchRec = patch as Record<string, unknown>;\n for (const field of OVERRIDABLE_FIELDS) {\n if (JSON.stringify(baseRec[field]) !== JSON.stringify(effRec[field])) {\n patchRec[field] = effRec[field];\n }\n }\n return patch;\n}\n\n/** True when an override patch has no diverging fields (safe to drop). */\nexport function isEmptyOverridePatch(patch: RequestOverridePatch): boolean {\n return (\n Object.keys(patch).filter((k) => OVERRIDABLE_FIELDS.includes(k as OverridableField)).length ===\n 0\n );\n}\n","// Maps Content-Type → Monaco language id for syntax highlighting +\n// language services (JSON validation, etc). Pure module — no Monaco\n// import here so the helper is usable in non-browser contexts (e.g.\n// the mock server's response shaping).\n\nexport type MonacoLanguage =\n | 'json'\n | 'xml'\n | 'html'\n | 'graphql'\n | 'javascript'\n | 'yaml'\n | 'plaintext';\n\nconst CONTENT_TYPE_LANGUAGE_MAP: Readonly<Record<string, MonacoLanguage>> = {\n 'application/json': 'json',\n 'application/xml': 'xml',\n 'text/xml': 'xml',\n 'text/html': 'html',\n 'application/graphql': 'graphql',\n 'application/javascript': 'javascript',\n 'text/javascript': 'javascript',\n // YAML and TOON share Monaco's YAML highlighter — TOON is a tabular\n // superset of compact YAML and reads correctly under YAML rules.\n 'application/x-yaml': 'yaml',\n 'application/yaml': 'yaml',\n 'text/yaml': 'yaml',\n 'text/x-yaml': 'yaml',\n 'text/plain': 'plaintext',\n};\n\nexport function normalizeContentType(contentType?: string): string {\n if (!contentType) return '';\n return contentType.toLowerCase().split(';')[0]?.trim() ?? '';\n}\n\nexport function getLanguageFromContentType(contentType?: string): MonacoLanguage {\n const normalized = normalizeContentType(contentType);\n if (!normalized) return 'plaintext';\n const direct = CONTENT_TYPE_LANGUAGE_MAP[normalized];\n if (direct) return direct;\n // +json / +xml suffixes per RFC 6838.\n if (normalized.endsWith('+json')) return 'json';\n if (normalized.endsWith('+xml')) return 'xml';\n return 'plaintext';\n}\n\n/**\n * Map a workspace BodyType to its Monaco language. Used by the editor\n * to set the right syntax highlighter even before Content-Type lands.\n */\nexport function getLanguageFromBodyType(\n bodyType: 'none' | 'json' | 'text' | 'urlencoded' | 'form-data' | 'binary' | 'xml' | 'graphql',\n): MonacoLanguage {\n switch (bodyType) {\n case 'json':\n return 'json';\n case 'xml':\n return 'xml';\n case 'graphql':\n return 'graphql';\n case 'text':\n case 'urlencoded':\n case 'form-data':\n case 'binary':\n case 'none':\n return 'plaintext';\n }\n}\n\nexport const supportedContentTypeLanguageMap = CONTENT_TYPE_LANGUAGE_MAP;\n","// Lightweight GraphQL schema parser for editor autocomplete. Two inputs\n// supported:\n//\n// 1. SDL (`type Query { ... }`): a forgiving regex-based extractor — we\n// don't ship a full GraphQL grammar; we just want enough information\n// to power \"what fields does this type expose?\" completions.\n//\n// 2. Introspection JSON (the result of `query IntrospectionQuery`): we\n// consume the official shape, so completions are accurate.\n//\n// Output is a flat shape consumable by Monaco's completion provider —\n// types, fields per type, root operation type names, and a list of\n// scalar / enum names.\n\nexport interface GraphQLSchemaInfo {\n /** Object/Interface types and their fields. */\n types: Map<string, { fields: GraphQLField[] }>;\n /** Top-level operations (Query, Mutation, Subscription). */\n rootTypes: { query?: string; mutation?: string; subscription?: string };\n /** Scalar + enum names. */\n scalars: string[];\n enums: string[];\n}\n\nexport interface GraphQLField {\n name: string;\n type: string;\n description?: string;\n}\n\nconst EMPTY: GraphQLSchemaInfo = {\n types: new Map(),\n rootTypes: {},\n scalars: [],\n enums: [],\n};\n\nexport function parseGraphqlSchema(\n source: string,\n kind: 'sdl' | 'introspection',\n): GraphQLSchemaInfo {\n if (!source.trim()) return EMPTY;\n if (kind === 'introspection') return parseIntrospection(source);\n return parseSdl(source);\n}\n\n// --- SDL parser ---------------------------------------------------------\n\nfunction parseSdl(source: string): GraphQLSchemaInfo {\n const types = new Map<string, { fields: GraphQLField[] }>();\n const rootTypes: GraphQLSchemaInfo['rootTypes'] = {\n query: 'Query',\n mutation: 'Mutation',\n subscription: 'Subscription',\n };\n const scalars: string[] = [];\n const enums: string[] = [];\n\n // Strip block + line comments.\n const text = source.replace(/\"\"\"[\\s\\S]*?\"\"\"/g, '').replace(/^\\s*#.*$/gm, '');\n\n // schema { query: A, mutation: B, subscription: C }\n const schemaMatch = /schema\\s*\\{([\\s\\S]*?)\\}/.exec(text);\n if (schemaMatch) {\n const inner = schemaMatch[1] ?? '';\n for (const line of inner.split(/\\r?\\n/)) {\n const m = /(query|mutation|subscription)\\s*:\\s*(\\w+)/.exec(line);\n if (m) (rootTypes as Record<string, string>)[m[1]] = m[2]!;\n }\n }\n\n const typeRegex = /\\b(type|interface)\\s+(\\w+)(?:\\s+implements\\s+[\\w\\s&]+?)?\\s*\\{([\\s\\S]*?)\\}/g;\n let match: RegExpExecArray | null;\n while ((match = typeRegex.exec(text))) {\n const typeName = match[2];\n const body = match[3];\n const fields: GraphQLField[] = [];\n for (const line of body.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const fm = /^(\\w+)(?:\\s*\\([^)]*\\))?\\s*:\\s*([^\\s,]+)/.exec(trimmed);\n if (fm) {\n fields.push({ name: fm[1], type: fm[2] });\n }\n }\n types.set(typeName, { fields });\n }\n\n for (const m of text.matchAll(/\\bscalar\\s+(\\w+)/g)) scalars.push(m[1]);\n for (const m of text.matchAll(/\\benum\\s+(\\w+)\\s*\\{[\\s\\S]*?\\}/g)) enums.push(m[1]);\n\n return { types, rootTypes, scalars, enums };\n}\n\n// --- Introspection parser ----------------------------------------------\n\ninterface IntrospectionType {\n kind: string;\n name: string;\n description?: string;\n fields?: Array<{\n name: string;\n description?: string;\n type: { name?: string; ofType?: { name?: string } };\n }>;\n}\n\ninterface IntrospectionRoot {\n __schema?: {\n queryType?: { name: string };\n mutationType?: { name: string } | null;\n subscriptionType?: { name: string } | null;\n types: IntrospectionType[];\n };\n data?: {\n __schema?: IntrospectionRoot['__schema'];\n };\n}\n\nfunction parseIntrospection(source: string): GraphQLSchemaInfo {\n let parsed: IntrospectionRoot;\n try {\n parsed = JSON.parse(source) as IntrospectionRoot;\n } catch {\n return EMPTY;\n }\n const schema = parsed.__schema ?? parsed.data?.__schema;\n if (!schema) return EMPTY;\n\n const types = new Map<string, { fields: GraphQLField[] }>();\n const scalars: string[] = [];\n const enums: string[] = [];\n\n for (const t of schema.types) {\n if (!t.name || t.name.startsWith('__')) continue;\n if (t.kind === 'OBJECT' || t.kind === 'INTERFACE') {\n types.set(t.name, {\n fields: (t.fields ?? []).map((f) => ({\n name: f.name,\n type: typeName(f.type) ?? 'Unknown',\n description: f.description,\n })),\n });\n } else if (t.kind === 'SCALAR') {\n scalars.push(t.name);\n } else if (t.kind === 'ENUM') {\n enums.push(t.name);\n }\n }\n\n return {\n types,\n rootTypes: {\n query: schema.queryType?.name,\n mutation: schema.mutationType?.name,\n subscription: schema.subscriptionType?.name,\n },\n scalars,\n enums,\n };\n}\n\nfunction typeName(\n t: { name?: string; ofType?: { name?: string } } | undefined,\n): string | undefined {\n if (!t) return undefined;\n if (t.name) return t.name;\n return typeName(t.ofType);\n}\n","import type { RequestAuth, WorkspaceSynced } from '@apicircle/shared';\n\n// 3-way diff for the refresh / pull flow (plan §3.5). The \"base\" is the\n// snapshot from the last successful pull, captured in\n// `WorkspaceLocal.sync.lastPulledSnapshot`. We diff each top-level bucket\n// of the synced doc against base on both sides; entries that only one\n// side touched fast-forward, entries both sides touched in different\n// ways become conflicts the user must resolve.\n\nexport type DiffStatus = 'unchanged' | 'local-only' | 'remote-only' | 'both-equal' | 'conflict';\n\nexport type EntityBucket =\n | 'request'\n | 'folder'\n | 'environment'\n | 'linkedWorkspace'\n | 'mockServer'\n | 'executionPlan'\n | 'secretKey'\n | 'globalSchema'\n | 'globalGraphql'\n | 'globalFile'\n | 'linkedRequestOverride'\n | 'linkedEnvOverride'\n | 'releasePerLink'\n | 'tree'\n | 'environmentsActive'\n | 'environmentsPriority'\n | 'releaseSelf'\n | 'secretCrypto';\n\nexport interface DiffEntry {\n bucket: EntityBucket;\n /** Entity id within the bucket. Empty string for singleton buckets. */\n key: string;\n status: DiffStatus;\n /** Human-readable label for the resolver UI. */\n label: string;\n base: unknown;\n local: unknown;\n remote: unknown;\n}\n\nexport interface ThreeWayDiff {\n entries: DiffEntry[];\n conflicts: DiffEntry[];\n}\n\nexport type ConflictResolution = 'mine' | 'theirs';\n\ntype TreeChild = WorkspaceSynced['collections']['tree']['children'][number];\n\n/** Map keyed by `bucket:key` (e.g. `request:r-1`, `releaseSelf:`). */\nexport type ResolutionMap = Record<string, ConflictResolution>;\n\n/**\n * Stable JSON for structural-equality checks. Same replacer the git\n * serializer uses — sorted object keys, arrays preserved verbatim.\n */\nfunction canonicalize(value: unknown): string {\n return JSON.stringify(value, sortedReplacer);\n}\n\nfunction sortedReplacer(this: unknown, _key: string, value: unknown): unknown {\n if (value === null || typeof value !== 'object') return value;\n if (Array.isArray(value)) return value;\n const proto = Object.getPrototypeOf(value) as object | null;\n if (proto !== Object.prototype && proto !== null) return value;\n const source = value as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(source).sort()) out[k] = source[k];\n return out;\n}\n\nfunction structurallyEqual(a: unknown, b: unknown): boolean {\n return canonicalize(a) === canonicalize(b);\n}\n\ninterface DictBucketSpec {\n bucket: EntityBucket;\n // Keys are exposed via the Spec so tests don't have to rebuild it.\n extract(s: WorkspaceSynced): Record<string, unknown>;\n label(key: string, value: unknown): string;\n}\n\ninterface SingletonSpec {\n bucket: EntityBucket;\n key: string;\n label: string;\n extract(s: WorkspaceSynced): unknown;\n}\n\nconst dictBuckets: DictBucketSpec[] = [\n {\n bucket: 'request',\n extract: (s) => s.collections.requests,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n bucket: 'folder',\n extract: (s) => s.collections.folders,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n bucket: 'environment',\n extract: (s) => s.environments.items,\n label: (key) => key,\n },\n {\n bucket: 'linkedWorkspace',\n extract: (s) => s.linkedWorkspaces,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n bucket: 'mockServer',\n extract: (s) => s.mockServers,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n // Plan definitions live in `synced.executionPlans` post-hydrate. The\n // field is typed optional because pre-migration workspaces persisted\n // plans on `WorkspaceLocal` only; coerce a missing dict to `{}` so the\n // diff engine treats \"absent\" and \"empty\" identically.\n bucket: 'executionPlan',\n extract: (s) => s.executionPlans ?? {},\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n // Secret-key slot metadata (label + KDF salt). Values are device-local\n // and never travel through git — only the slot identity does, so\n // collaborators see consistent labels for the same id.\n bucket: 'secretKey',\n extract: (s) => s.secretKeys ?? {},\n label: (key, value) => {\n const v = value as { label?: string } | undefined;\n return v?.label ?? key;\n },\n },\n {\n // Reusable JSON Schemas registered at workspace scope.\n bucket: 'globalSchema',\n extract: (s) => s.globalAssets.schemas,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n // Reusable GraphQL schema docs registered at workspace scope.\n bucket: 'globalGraphql',\n extract: (s) => s.globalAssets.graphql,\n label: (key, value) => {\n const v = value as { name?: string } | undefined;\n return v?.name ?? key;\n },\n },\n {\n // Reusable file assets registered at workspace scope. The metadata\n // travels in workspace.json; bytes travel as Git blobs by slotId.\n bucket: 'globalFile',\n extract: (s) => s.globalAssets.files ?? {},\n label: (key, value) => {\n const v = value as { name?: string; filename?: string } | undefined;\n return v?.name ?? v?.filename ?? key;\n },\n },\n {\n // Consumer-side patches to a linked workspace's requests. Keyed\n // `${linkedWorkspaceId}:${requestId}`; the label leans on the key\n // since the override itself doesn't carry a name.\n bucket: 'linkedRequestOverride',\n extract: (s) => s.linkedOverrides.requests,\n label: (key) => `linked request override (${key})`,\n },\n {\n // Per-variable overrides for linked-workspace env vars. Keyed\n // `${linkedWorkspaceId}:${envName}:${varKey}`.\n bucket: 'linkedEnvOverride',\n extract: (s) => s.linkedOverrides.environmentVars,\n label: (key) => `linked env var override (${key})`,\n },\n {\n // Cached release ledgers for each linked workspace. Keyed by\n // linkedWorkspaceId. Refreshes via the link card's \"Refresh ledger\"\n // surface change here too.\n bucket: 'releasePerLink',\n extract: (s) => s.releases.perLink,\n label: (key) => `linked release ledger (${key})`,\n },\n];\n\nconst singletons: SingletonSpec[] = [\n { bucket: 'tree', key: '', label: 'Folder tree', extract: (s) => s.collections.tree },\n {\n bucket: 'environmentsActive',\n key: '',\n label: 'Active environment',\n extract: (s) => s.environments.activeName,\n },\n {\n bucket: 'environmentsPriority',\n key: '',\n label: 'Environment priority',\n extract: (s) => s.environments.priorityOrder,\n },\n {\n bucket: 'releaseSelf',\n key: '',\n label: 'Release ledger',\n extract: (s) => s.releases.self,\n },\n {\n // Workspace passphrase metadata (KDF + verifier — never the secret\n // itself). Travels through git so a collaborator who pulls knows the\n // passphrase exists and can prompt for it on first decrypt.\n bucket: 'secretCrypto',\n key: '',\n label: 'Workspace passphrase',\n extract: (s) => s.secretCrypto ?? null,\n },\n];\n\n/**\n * Compute the per-entity diff. Returns every entity touched on at least\n * one side, plus a flat list of conflicts (subset of entries with status\n * 'conflict') for the resolver.\n *\n * `base` is the lastPulledSnapshot. When null (first refresh ever), every\n * remote entity that doesn't match local becomes a conflict — there's no\n * shared ancestor to pick a side automatically.\n */\nexport function computeThreeWayDiff(\n base: WorkspaceSynced | null,\n local: WorkspaceSynced,\n remote: WorkspaceSynced,\n): ThreeWayDiff {\n const entries: DiffEntry[] = [];\n\n for (const spec of dictBuckets) {\n const baseDict = base ? spec.extract(base) : {};\n const localDict = spec.extract(local);\n const remoteDict = spec.extract(remote);\n const allKeys = new Set([\n ...Object.keys(baseDict),\n ...Object.keys(localDict),\n ...Object.keys(remoteDict),\n ]);\n for (const key of allKeys) {\n const b = baseDict[key];\n const l = localDict[key];\n const r = remoteDict[key];\n const status = classify(base !== null, b, l, r);\n if (status === 'unchanged') continue;\n const labelSource = l ?? r ?? b;\n entries.push({\n bucket: spec.bucket,\n key,\n status,\n label: spec.label(key, labelSource),\n base: b,\n local: l,\n remote: r,\n });\n }\n }\n\n for (const spec of singletons) {\n const b = base ? spec.extract(base) : undefined;\n const l = spec.extract(local);\n const r = spec.extract(remote);\n const status = classify(base !== null, b, l, r);\n if (status === 'unchanged') continue;\n entries.push({\n bucket: spec.bucket,\n key: spec.key,\n status,\n label: spec.label,\n base: b,\n local: l,\n remote: r,\n });\n }\n\n resolveAutoMergeableTreeConflict(entries, base, local, remote);\n const conflicts = entries.filter((e) => e.status === 'conflict');\n return { entries, conflicts };\n}\n\nfunction classify(hasBase: boolean, base: unknown, local: unknown, remote: unknown): DiffStatus {\n const localUndef = local === undefined;\n const remoteUndef = remote === undefined;\n if (localUndef && remoteUndef) return 'unchanged';\n\n // Without a shared base, we can't tell who changed what — anything that\n // doesn't already match becomes a conflict. (Equal values are fine.)\n if (!hasBase) {\n if (structurallyEqual(local, remote)) return 'unchanged';\n if (localUndef) return 'remote-only';\n if (remoteUndef) return 'local-only';\n return 'conflict';\n }\n\n const localChanged = !structurallyEqual(base, local);\n const remoteChanged = !structurallyEqual(base, remote);\n if (!localChanged && !remoteChanged) return 'unchanged';\n if (!localChanged && remoteChanged) return 'remote-only';\n if (localChanged && !remoteChanged) return 'local-only';\n // Both changed.\n if (structurallyEqual(local, remote)) return 'both-equal';\n return 'conflict';\n}\n\nfunction resolveAutoMergeableTreeConflict(\n entries: DiffEntry[],\n base: WorkspaceSynced | null,\n local: WorkspaceSynced,\n remote: WorkspaceSynced,\n): void {\n if (!base) return;\n const treeEntry = entries.find((entry) => entry.bucket === 'tree' && entry.status === 'conflict');\n if (!treeEntry) return;\n const merged = mergeRootTreeMembershipIfSafe(base, local, remote, entries);\n if (!merged) return;\n treeEntry.status = 'remote-only';\n treeEntry.remote = merged;\n}\n\nfunction mergeRootTreeMembershipIfSafe(\n base: WorkspaceSynced,\n local: WorkspaceSynced,\n remote: WorkspaceSynced,\n entries: DiffEntry[],\n): WorkspaceSynced['collections']['tree'] | null {\n const baseChildren = base.collections.tree.children;\n const localChildren = local.collections.tree.children;\n const remoteChildren = remote.collections.tree.children;\n const baseKeys = treeKeySet(baseChildren);\n const localKeys = treeKeySet(localChildren);\n const remoteKeys = treeKeySet(remoteChildren);\n if (!baseKeys || !localKeys || !remoteKeys) return null;\n\n const changed = new Set<string>();\n for (const key of new Set([...baseKeys, ...localKeys, ...remoteKeys])) {\n const localChanged = baseKeys.has(key) !== localKeys.has(key);\n const remoteChanged = baseKeys.has(key) !== remoteKeys.has(key);\n if (!localChanged && !remoteChanged) continue;\n if (localChanged && remoteChanged) return null;\n const entry = bucketEntryForTreeChild(entries, key);\n if (!entry || entry.status === 'conflict') return null;\n if (localChanged && entry.status !== 'local-only') return null;\n if (remoteChanged && entry.status !== 'remote-only') return null;\n changed.add(key);\n }\n if (changed.size === 0) return null;\n\n const stableBaseOrder = baseChildren.map(treeChildKey).filter((key) => !changed.has(key));\n if (\n !sameOrder(\n localChildren.map(treeChildKey).filter((key) => !changed.has(key)),\n stableBaseOrder,\n )\n ) {\n return null;\n }\n if (\n !sameOrder(\n remoteChildren.map(treeChildKey).filter((key) => !changed.has(key)),\n stableBaseOrder,\n )\n ) {\n return null;\n }\n\n let children = [...localChildren];\n for (const child of remoteChildren) {\n const key = treeChildKey(child);\n if (!changed.has(key) || !remoteKeys.has(key)) continue;\n if (!children.some((existing) => treeChildKey(existing) === key)) children.push(child);\n }\n for (const key of changed) {\n if (remoteKeys.has(key)) continue;\n const entry = bucketEntryForTreeChild(entries, key);\n if (entry?.status === 'remote-only') {\n children = children.filter((child) => treeChildKey(child) !== key);\n }\n }\n return { ...local.collections.tree, children };\n}\n\nfunction bucketEntryForTreeChild(entries: DiffEntry[], key: string): DiffEntry | undefined {\n const [kind, id] = key.split(':', 2);\n if (kind !== 'request' && kind !== 'folder') return undefined;\n return entries.find((entry) => entry.bucket === kind && entry.key === id);\n}\n\nfunction treeKeySet(children: TreeChild[]): Set<string> | null {\n const keys = new Set<string>();\n for (const child of children) {\n const key = treeChildKey(child);\n if (keys.has(key)) return null;\n keys.add(key);\n }\n return keys;\n}\n\nfunction treeChildKey(child: TreeChild): string {\n return `${child.kind}:${child.id}`;\n}\n\nfunction sameOrder(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((value, index) => value === b[index]);\n}\n\n/**\n * Apply a fully-resolved diff: take fast-forwards (remote-only) into\n * local, keep local-only changes verbatim, and resolve every conflict\n * via the supplied `resolutions` map (`bucket:key` → 'mine' | 'theirs').\n *\n * Throws when any conflict is missing a resolution — the caller is\n * expected to populate the modal first.\n */\nexport function applyMerge(\n local: WorkspaceSynced,\n remote: WorkspaceSynced,\n diff: ThreeWayDiff,\n resolutions: ResolutionMap,\n): WorkspaceSynced {\n let merged: WorkspaceSynced = local;\n for (const entry of diff.entries) {\n const id = `${entry.bucket}:${entry.key}`;\n let chosen: 'mine' | 'theirs';\n if (entry.status === 'remote-only') {\n chosen = 'theirs';\n } else if (entry.status === 'local-only' || entry.status === 'both-equal') {\n chosen = 'mine';\n } else {\n const r = resolutions[id];\n if (!r) throw new Error(`Missing resolution for ${id}`);\n chosen = r;\n }\n merged = applyEntry(merged, remote, entry, chosen);\n }\n return merged;\n}\n\n/**\n * Distinguishes the two outcomes a merge can have for a dict entry:\n * - `upsert` — the entry now exists in the dict (added or modified).\n * `parent` tells us if it belongs at root or inside a folder.\n * - `remove` — the entry was deleted from the dict.\n * Without this discriminator, \"value === undefined\" can't be told apart from\n * \"value present with parent === null\" — and root-level deletes would silently\n * get re-added by the reconciler.\n */\ntype TreeOp = { kind: 'upsert'; parent: string | null } | { kind: 'remove' };\n\n/**\n * Keep `tree.children` consistent with the requests/folders dict when a\n * merge inserts, modifies, or removes an entry. The sidebar derives the\n * visible list from two parallel sources — `tree.children` (root) and\n * `folderId/parentId` chains (nested). Without this reconciliation, a\n * pull that adds a top-level request leaves the dict updated but the\n * tree untouched, so the request becomes an \"orphan\" — present in the\n * unpushed-changes strip but invisible in the editor sidebar.\n *\n * Cases handled:\n * - upsert at root: add to tree.children if missing\n * - upsert nested: strip any stale root reference (entry can't be in two\n * places at once)\n * - remove: strip from tree.children if present\n */\nfunction reconcileTreeForEntry(\n tree: WorkspaceSynced['collections']['tree'],\n kind: 'folder' | 'request',\n id: string,\n op: TreeOp,\n): WorkspaceSynced['collections']['tree'] {\n const inTree = tree.children.some((c) => c.kind === kind && c.id === id);\n if (op.kind === 'upsert' && op.parent === null) {\n if (inTree) return tree;\n return { ...tree, children: [...tree.children, { kind, id }] };\n }\n // Nested upsert OR remove: ensure no stale root reference.\n if (!inTree) return tree;\n return {\n ...tree,\n children: tree.children.filter((c) => !(c.kind === kind && c.id === id)),\n };\n}\n\nfunction applyEntry(\n local: WorkspaceSynced,\n remote: WorkspaceSynced,\n entry: DiffEntry,\n chosen: 'mine' | 'theirs',\n): WorkspaceSynced {\n if (chosen === 'mine') return local;\n // chosen === 'theirs': overwrite the entity in `local` with the remote value.\n const value = entry.remote;\n switch (entry.bucket) {\n case 'request': {\n const requests = { ...local.collections.requests };\n const treeOp: TreeOp =\n value === undefined\n ? { kind: 'remove' }\n : { kind: 'upsert', parent: (value as { folderId: string | null }).folderId ?? null };\n if (value === undefined) delete requests[entry.key];\n else {\n const remoteRequest = value as (typeof requests)[string];\n const localRequest = local.collections.requests[entry.key];\n requests[entry.key] =\n localRequest && remoteRequest.auth\n ? {\n ...remoteRequest,\n auth: preserveLocalCredentialPlaceholders(localRequest.auth, remoteRequest.auth),\n }\n : remoteRequest;\n }\n const tree = reconcileTreeForEntry(local.collections.tree, 'request', entry.key, treeOp);\n return { ...local, collections: { ...local.collections, requests, tree } };\n }\n case 'folder': {\n const folders = { ...local.collections.folders };\n const treeOp: TreeOp =\n value === undefined\n ? { kind: 'remove' }\n : { kind: 'upsert', parent: (value as { parentId: string | null }).parentId ?? null };\n if (value === undefined) delete folders[entry.key];\n else {\n const remoteFolder = value as (typeof folders)[string];\n const localFolder = local.collections.folders[entry.key];\n folders[entry.key] =\n localFolder?.auth && remoteFolder.auth\n ? {\n ...remoteFolder,\n auth: preserveLocalCredentialPlaceholders(localFolder.auth, remoteFolder.auth),\n }\n : remoteFolder;\n }\n const tree = reconcileTreeForEntry(local.collections.tree, 'folder', entry.key, treeOp);\n return { ...local, collections: { ...local.collections, folders, tree } };\n }\n case 'environment': {\n const items = { ...local.environments.items };\n if (value === undefined) delete items[entry.key];\n else items[entry.key] = value as (typeof items)[string];\n return { ...local, environments: { ...local.environments, items } };\n }\n case 'linkedWorkspace': {\n const linkedWorkspaces = { ...local.linkedWorkspaces };\n if (value === undefined) delete linkedWorkspaces[entry.key];\n else linkedWorkspaces[entry.key] = value as (typeof linkedWorkspaces)[string];\n return { ...local, linkedWorkspaces };\n }\n case 'mockServer': {\n const mockServers = { ...local.mockServers };\n if (value === undefined) delete mockServers[entry.key];\n else mockServers[entry.key] = value as (typeof mockServers)[string];\n return { ...local, mockServers };\n }\n case 'executionPlan': {\n // executionPlans is optional in the type — start from `{}` rather\n // than `undefined` so we never write a non-dict value back.\n const executionPlans = { ...(local.executionPlans ?? {}) };\n if (value === undefined) delete executionPlans[entry.key];\n else\n executionPlans[entry.key] = value as NonNullable<WorkspaceSynced['executionPlans']>[string];\n return { ...local, executionPlans };\n }\n case 'secretKey': {\n // secretKeys is optional in the type — coerce missing to {} so a\n // remote that hasn't ever populated the field doesn't smuggle in\n // an undefined.\n const secretKeys = { ...(local.secretKeys ?? {}) };\n if (value === undefined) delete secretKeys[entry.key];\n else secretKeys[entry.key] = value as NonNullable<WorkspaceSynced['secretKeys']>[string];\n return { ...local, secretKeys };\n }\n case 'globalSchema': {\n const schemas = { ...local.globalAssets.schemas };\n if (value === undefined) delete schemas[entry.key];\n else schemas[entry.key] = value as (typeof schemas)[string];\n return { ...local, globalAssets: { ...local.globalAssets, schemas } };\n }\n case 'globalGraphql': {\n const graphql = { ...local.globalAssets.graphql };\n if (value === undefined) delete graphql[entry.key];\n else graphql[entry.key] = value as (typeof graphql)[string];\n return { ...local, globalAssets: { ...local.globalAssets, graphql } };\n }\n case 'globalFile': {\n const files = { ...(local.globalAssets.files ?? {}) };\n if (value === undefined) delete files[entry.key];\n else\n files[entry.key] = value as NonNullable<WorkspaceSynced['globalAssets']['files']>[string];\n return { ...local, globalAssets: { ...local.globalAssets, files } };\n }\n case 'linkedRequestOverride': {\n const requests = { ...local.linkedOverrides.requests };\n if (value === undefined) delete requests[entry.key];\n else requests[entry.key] = value as (typeof requests)[string];\n return { ...local, linkedOverrides: { ...local.linkedOverrides, requests } };\n }\n case 'linkedEnvOverride': {\n const environmentVars = { ...local.linkedOverrides.environmentVars };\n if (value === undefined) delete environmentVars[entry.key];\n else environmentVars[entry.key] = value as (typeof environmentVars)[string];\n return { ...local, linkedOverrides: { ...local.linkedOverrides, environmentVars } };\n }\n case 'releasePerLink': {\n const perLink = { ...local.releases.perLink };\n if (value === undefined) delete perLink[entry.key];\n else perLink[entry.key] = value as (typeof perLink)[string];\n return { ...local, releases: { ...local.releases, perLink } };\n }\n case 'tree':\n return {\n ...local,\n collections: {\n ...local.collections,\n tree: (value as WorkspaceSynced['collections']['tree']) ?? remote.collections.tree,\n },\n };\n case 'environmentsActive':\n return {\n ...local,\n environments: { ...local.environments, activeName: remote.environments.activeName },\n };\n case 'environmentsPriority':\n return {\n ...local,\n environments: {\n ...local.environments,\n priorityOrder: remote.environments.priorityOrder,\n },\n };\n case 'releaseSelf':\n return { ...local, releases: { ...local.releases, self: remote.releases.self } };\n case 'secretCrypto':\n return { ...local, secretCrypto: remote.secretCrypto ?? null };\n }\n}\n\nfunction preserveLocalCredentialPlaceholders(\n localAuth: RequestAuth,\n remoteAuth: RequestAuth,\n): RequestAuth {\n if (localAuth.type !== remoteAuth.type) return remoteAuth;\n switch (remoteAuth.type) {\n case 'basic':\n case 'digest':\n case 'ntlm':\n return preserveBlankStringFields(localAuth, remoteAuth, ['password']);\n case 'bearer':\n return preserveBlankStringFields(localAuth, remoteAuth, ['token']);\n case 'api-key':\n return preserveBlankStringFields(localAuth, remoteAuth, ['value']);\n case 'hawk':\n return preserveBlankStringFields(localAuth, remoteAuth, ['hawkKey']);\n case 'jwt-bearer':\n return preserveBlankStringFields(localAuth, remoteAuth, ['secretOrKey', 'token']);\n case 'aws-sigv4':\n return preserveBlankStringFields(localAuth, remoteAuth, ['secretAccessKey', 'sessionToken']);\n case 'oauth2-client-credentials':\n case 'oauth2-auth-code':\n case 'oauth2-pkce':\n return preserveBlankStringFields(localAuth, remoteAuth, [\n 'clientSecret',\n 'accessToken',\n 'refreshToken',\n ]);\n case 'oauth2-password':\n return preserveBlankStringFields(localAuth, remoteAuth, [\n 'clientSecret',\n 'password',\n 'accessToken',\n 'refreshToken',\n ]);\n case 'oauth2-implicit':\n return preserveBlankStringFields(localAuth, remoteAuth, ['accessToken']);\n case 'oauth2-device':\n return preserveBlankStringFields(localAuth, remoteAuth, ['accessToken', 'refreshToken']);\n case 'none':\n case 'inherit':\n case 'custom-header':\n return remoteAuth;\n default: {\n const _exhaustive: never = remoteAuth;\n void _exhaustive;\n return remoteAuth;\n }\n }\n}\n\nfunction preserveBlankStringFields<T extends RequestAuth>(\n localAuth: T,\n remoteAuth: T,\n fields: string[],\n): T {\n const next = { ...remoteAuth } as Record<string, unknown>;\n const local = localAuth as Record<string, unknown>;\n for (const field of fields) {\n if (next[field] === '' && typeof local[field] === 'string' && local[field] !== '') {\n next[field] = local[field];\n }\n }\n return next as T;\n}\n","import type { WorkspaceSynced } from '@apicircle/shared';\nimport { redactForGit } from './redactWorkspace';\nimport { type EntityBucket, computeThreeWayDiff } from './threeWayDiff';\n\n// Pre-push diff summary: compares the consumer's currently-edited synced\n// doc against the last-pulled snapshot to enumerate every uncommitted\n// change. Powers the BranchCard's \"+N added · ~M modified · -K removed\"\n// strip (B.3) and the side-by-side preview modal beneath it.\n//\n// Pure — caller decides when to recompute (typically on every store\n// mutation; cheap enough to skip debouncing for typical workspace\n// sizes).\n\nexport interface UnpushedChange {\n bucket: EntityBucket;\n /** Entity id within the bucket; empty string for singletons (tree, etc.). */\n key: string;\n label: string;\n kind: 'added' | 'modified' | 'removed';\n base: unknown;\n local: unknown;\n}\n\nexport interface UnpushedSummary {\n added: number;\n modified: number;\n removed: number;\n total: number;\n /** Per-entry list, sorted by bucket then label so the preview list renders predictably. */\n changes: UnpushedChange[];\n computedAt: string;\n}\n\nconst BUCKET_ORDER: EntityBucket[] = [\n 'tree',\n 'request',\n 'folder',\n 'environment',\n 'environmentsActive',\n 'environmentsPriority',\n 'linkedWorkspace',\n 'linkedRequestOverride',\n 'linkedEnvOverride',\n 'mockServer',\n 'executionPlan',\n 'globalSchema',\n 'globalGraphql',\n 'globalFile',\n 'secretKey',\n 'secretCrypto',\n 'releaseSelf',\n 'releasePerLink',\n];\n\nconst EMPTY_SUMMARY: UnpushedSummary = {\n added: 0,\n modified: 0,\n removed: 0,\n total: 0,\n changes: [],\n computedAt: new Date(0).toISOString(),\n};\n\nexport function summarizeUnpushedChanges(\n base: WorkspaceSynced | null,\n current: WorkspaceSynced,\n options: { now?: () => Date } = {},\n): UnpushedSummary {\n const now = options.now ?? (() => new Date());\n // The push path writes a redacted workspace.json. Compare the same synced\n // intent here so local-only credential values do not appear as phantom\n // unpushed changes after a refresh/merge preserves them in memory.\n const gitCurrent = redactForGit(current);\n if (!base) {\n // No upstream yet (workspace was just created or never pulled).\n // Everything in `current` counts as \"added\" — walking the buckets\n // directly is simpler than feeding an empty-shape doc to the diff\n // engine.\n return summarizeAllAsAdded(gitCurrent, now().toISOString());\n }\n // Reuse the existing 3-way diff with `remote = base` so every entry\n // is either 'unchanged' or 'local-only'. We then translate\n // 'local-only' into added / modified / removed by inspecting which of\n // base / local is undefined.\n const gitBase = redactForGit(base);\n const diff = computeThreeWayDiff(gitBase, gitCurrent, gitBase);\n const changes: UnpushedChange[] = [];\n for (const entry of diff.entries) {\n if (entry.status !== 'local-only') continue;\n // Treat null and undefined alike as \"absent\" for kind classification.\n // The `releaseSelf` singleton extracts to `null` when no ledger\n // exists — without nullish-aware logic, the first publish (null →\n // ledger) gets labeled \"modified\" instead of \"added\", which the\n // strip then under-counts in its \"+N added\" badge.\n const baseAbsent = entry.base === undefined || entry.base === null;\n const localAbsent = entry.local === undefined || entry.local === null;\n let kind: UnpushedChange['kind'];\n if (baseAbsent && !localAbsent) kind = 'added';\n else if (!baseAbsent && localAbsent) kind = 'removed';\n else kind = 'modified';\n changes.push({\n bucket: entry.bucket,\n key: entry.key,\n label: entry.label,\n kind,\n base: entry.base,\n local: entry.local,\n });\n }\n return finalize(changes, now().toISOString());\n}\n\n/**\n * Cheap \"anything to push?\" check for the BranchCard badge. Avoids\n * recomputing the full preview list when the caller only needs a\n * boolean. Identity short-circuits on referential equality of `current`\n * and `base` — common when the store hasn't mutated since pull.\n */\nexport function hasUnpushedChanges(\n base: WorkspaceSynced | null,\n current: WorkspaceSynced,\n): boolean {\n if (current === base) return false;\n return summarizeUnpushedChanges(base, current).total > 0;\n}\n\nfunction summarizeAllAsAdded(synced: WorkspaceSynced, computedAt: string): UnpushedSummary {\n const changes: UnpushedChange[] = [];\n for (const [id, req] of Object.entries(synced.collections.requests)) {\n changes.push({\n bucket: 'request',\n key: id,\n label: req.name || id,\n kind: 'added',\n base: undefined,\n local: req,\n });\n }\n for (const [id, folder] of Object.entries(synced.collections.folders)) {\n changes.push({\n bucket: 'folder',\n key: id,\n label: folder.name || id,\n kind: 'added',\n base: undefined,\n local: folder,\n });\n }\n for (const [name, env] of Object.entries(synced.environments.items)) {\n changes.push({\n bucket: 'environment',\n key: name,\n label: name,\n kind: 'added',\n base: undefined,\n local: env,\n });\n }\n for (const [id, link] of Object.entries(synced.linkedWorkspaces)) {\n changes.push({\n bucket: 'linkedWorkspace',\n key: id,\n label: link.name || id,\n kind: 'added',\n base: undefined,\n local: link,\n });\n }\n for (const [id, server] of Object.entries(synced.mockServers)) {\n changes.push({\n bucket: 'mockServer',\n key: id,\n label: server.name || id,\n kind: 'added',\n base: undefined,\n local: server,\n });\n }\n // executionPlans is optional in the synced doc — pre-migration workspaces\n // may not have hydrated it yet. Treat absent as the empty dict (no plans\n // to report) rather than crashing on Object.entries(undefined).\n for (const [id, plan] of Object.entries(synced.executionPlans ?? {})) {\n changes.push({\n bucket: 'executionPlan',\n key: id,\n label: plan.name || id,\n kind: 'added',\n base: undefined,\n local: plan,\n });\n }\n // secretKeys is also optional pre-migration; same treatment as plans.\n for (const [id, meta] of Object.entries(synced.secretKeys ?? {})) {\n changes.push({\n bucket: 'secretKey',\n key: id,\n label: meta.label || id,\n kind: 'added',\n base: undefined,\n local: meta,\n });\n }\n for (const [id, schema] of Object.entries(synced.globalAssets.schemas)) {\n changes.push({\n bucket: 'globalSchema',\n key: id,\n label: schema.name || id,\n kind: 'added',\n base: undefined,\n local: schema,\n });\n }\n for (const [id, gql] of Object.entries(synced.globalAssets.graphql)) {\n changes.push({\n bucket: 'globalGraphql',\n key: id,\n label: gql.name || id,\n kind: 'added',\n base: undefined,\n local: gql,\n });\n }\n for (const [id, file] of Object.entries(synced.globalAssets.files ?? {})) {\n changes.push({\n bucket: 'globalFile',\n key: id,\n label: file.name || file.filename || id,\n kind: 'added',\n base: undefined,\n local: file,\n });\n }\n for (const [key, override] of Object.entries(synced.linkedOverrides.requests)) {\n changes.push({\n bucket: 'linkedRequestOverride',\n key,\n label: `linked request override (${key})`,\n kind: 'added',\n base: undefined,\n local: override,\n });\n }\n for (const [key, override] of Object.entries(synced.linkedOverrides.environmentVars)) {\n changes.push({\n bucket: 'linkedEnvOverride',\n key,\n label: `linked env var override (${key})`,\n kind: 'added',\n base: undefined,\n local: override,\n });\n }\n for (const [linkId, ledger] of Object.entries(synced.releases.perLink)) {\n changes.push({\n bucket: 'releasePerLink',\n key: linkId,\n label: `linked release ledger (${linkId})`,\n kind: 'added',\n base: undefined,\n local: ledger,\n });\n }\n // Singletons that only count when they're non-default. We only report\n // the tree when it's non-empty — otherwise every fresh workspace would\n // claim a singleton \"add\".\n if (synced.collections.tree.children.length > 0) {\n changes.push({\n bucket: 'tree',\n key: '',\n label: 'Folder tree',\n kind: 'added',\n base: undefined,\n local: synced.collections.tree,\n });\n }\n if (synced.releases.self) {\n changes.push({\n bucket: 'releaseSelf',\n key: '',\n label: 'Release ledger',\n kind: 'added',\n base: undefined,\n local: synced.releases.self,\n });\n }\n // Workspace passphrase: only counts when actually set. A null/absent\n // value is the no-passphrase default — don't claim a singleton \"add\"\n // for every fresh workspace.\n if (synced.secretCrypto) {\n changes.push({\n bucket: 'secretCrypto',\n key: '',\n label: 'Workspace passphrase',\n kind: 'added',\n base: undefined,\n local: synced.secretCrypto,\n });\n }\n return finalize(changes, computedAt);\n}\n\nfunction finalize(changes: UnpushedChange[], computedAt: string): UnpushedSummary {\n changes.sort((a, b) => {\n const ba = BUCKET_ORDER.indexOf(a.bucket);\n const bb = BUCKET_ORDER.indexOf(b.bucket);\n if (ba !== bb) return ba - bb;\n return a.label.localeCompare(b.label, undefined, { sensitivity: 'base' });\n });\n let added = 0;\n let modified = 0;\n let removed = 0;\n for (const c of changes) {\n if (c.kind === 'added') added += 1;\n else if (c.kind === 'modified') modified += 1;\n else removed += 1;\n }\n return { added, modified, removed, total: changes.length, changes, computedAt };\n}\n\n/** Stable empty value for callers that want to default-render an empty summary. */\nexport const EMPTY_UNPUSHED_SUMMARY = EMPTY_SUMMARY;\n","// Three-way merge for linked-workspace updates.\n//\n// When a consumer wants to bump their pinned version of a linked workspace\n// to a newer one, we classify every request / env-var / folder against\n// THREE inputs:\n//\n// • base — the consumer's currently-pinned snapshot of the source.\n// • target — the source's published snapshot at the new version.\n// • override — the consumer's local modifications (only requests +\n// env-vars carry overrides; folders are source-pinned).\n//\n// Each entity gets one status:\n//\n// unchanged base ≡ target AND no override → no-op\n// source-only base ≠ target AND no override → fast-forward\n// local-only base ≡ target AND override → keep mine\n// both-changed base ≠ target AND override → user picks\n// new-in-source base missing, target present → adopt new entity\n// removed-in-source base present, target missing → orphan\n//\n// \"both-changed\" intentionally lumps clean-merge and conflict together\n// for the first cut — letting the user explicitly accept-source or\n// keep-mine is loud and safe. Auto-merging non-overlapping field edits\n// is a follow-on slice (lands cleanly on top of this same data shape).\n\nimport type {\n EnvironmentVariable,\n EnvironmentVariableOverride,\n Folder,\n LinkedSnapshot,\n Request as ApiRequest,\n RequestOverride,\n} from '@apicircle/shared';\n\nexport type LinkedUpdateStatus =\n | 'unchanged'\n | 'source-only'\n | 'local-only'\n | 'both-changed'\n | 'new-in-source'\n | 'removed-in-source';\n\nexport type LinkedUpdateBucket = 'request' | 'folder' | 'environment-var';\n\nexport interface LinkedUpdateEntry<TBase = unknown, TTarget = unknown, TOverride = unknown> {\n bucket: LinkedUpdateBucket;\n /** Identifier scoped to the bucket. For env-var, format `<envName>:<varKey>`. */\n key: string;\n label: string;\n status: LinkedUpdateStatus;\n base: TBase | null;\n target: TTarget | null;\n override: TOverride | null;\n /**\n * For `both-changed` entries only: `true` when the consumer's override touches\n * a DISJOINT set of fields from the ones the source changed — so keeping the\n * override is a clean field-level merge that needs no user decision. `false`\n * (or undefined) means override + source touched the same field → a real\n * conflict the user must resolve. Other statuses leave this undefined.\n */\n autoMergeable?: boolean;\n}\n\nexport interface LinkedUpdatePreview {\n fromVersion: string | null;\n toVersion: string;\n entries: LinkedUpdateEntry[];\n /** Quick counts for the modal summary line. */\n summary: Record<LinkedUpdateStatus, number>;\n}\n\nexport interface PreviewArgs {\n fromVersion: string | null;\n toVersion: string;\n base: LinkedSnapshot | null;\n target: LinkedSnapshot;\n /** All request overrides keyed by `${linkedWorkspaceId}:${itemId}` — caller pre-filters to one link. */\n requestOverrides: RequestOverride[];\n /** All env-var overrides for this link. */\n envVarOverrides: EnvironmentVariableOverride[];\n}\n\n/**\n * Pure function — returns a structured preview of every change between\n * `base` and `target`, classified by status and annotated with the\n * consumer's overrides where applicable. Caller renders the modal and\n * collects resolutions for `both-changed` entries.\n */\nexport function previewLinkedUpdate(args: PreviewArgs): LinkedUpdatePreview {\n const entries: LinkedUpdateEntry[] = [];\n\n // --- Requests ----------------------------------------------------------\n const baseRequests = args.base?.collections.requests ?? {};\n const targetRequests = args.target.collections.requests;\n const overrideByItem = new Map<string, RequestOverride>(\n args.requestOverrides.map((o) => [o.itemId, o]),\n );\n const allRequestIds = new Set([...Object.keys(baseRequests), ...Object.keys(targetRequests)]);\n for (const id of allRequestIds) {\n const base = baseRequests[id] ?? null;\n const target = targetRequests[id] ?? null;\n const override = overrideByItem.get(id) ?? null;\n const status = classifyRequest(base, target, override);\n if (status === 'unchanged') continue;\n entries.push({\n bucket: 'request',\n key: id,\n label: target?.name ?? base?.name ?? id,\n status,\n base,\n target,\n override,\n ...(status === 'both-changed' && base && target && override\n ? { autoMergeable: requestOverrideIsDisjoint(base, target, override) }\n : {}),\n });\n }\n\n // --- Folders -----------------------------------------------------------\n // Folders aren't overridable today — every change is either source-only\n // (consumer adopts) or removed-in-source (orphan). They always classify\n // cleanly without a user decision.\n const baseFolders = args.base?.collections.folders ?? {};\n const targetFolders = args.target.collections.folders;\n const allFolderIds = new Set([...Object.keys(baseFolders), ...Object.keys(targetFolders)]);\n for (const id of allFolderIds) {\n const base = baseFolders[id] ?? null;\n const target = targetFolders[id] ?? null;\n const status = classifyFolder(base, target);\n if (status === 'unchanged') continue;\n entries.push({\n bucket: 'folder',\n key: id,\n label: target?.name ?? base?.name ?? id,\n status,\n base,\n target,\n override: null,\n });\n }\n\n // --- Environment variables --------------------------------------------\n const baseEnvs = args.base?.environments.items ?? {};\n const targetEnvs = args.target.environments.items;\n const allEnvNames = new Set([...Object.keys(baseEnvs), ...Object.keys(targetEnvs)]);\n for (const envName of allEnvNames) {\n const baseVars = baseEnvs[envName]?.variables ?? [];\n const targetVars = targetEnvs[envName]?.variables ?? [];\n const overrides = args.envVarOverrides.filter((o) => o.envName === envName);\n const allKeys = new Set<string>([\n ...baseVars.map((v) => v.key),\n ...targetVars.map((v) => v.key),\n ...overrides.map((o) => o.varKey),\n ]);\n const baseByKey = new Map(baseVars.map((v) => [v.key, v]));\n const targetByKey = new Map(targetVars.map((v) => [v.key, v]));\n const overrideByKey = new Map(overrides.map((o) => [o.varKey, o]));\n for (const varKey of allKeys) {\n const base = baseByKey.get(varKey) ?? null;\n const target = targetByKey.get(varKey) ?? null;\n const override = overrideByKey.get(varKey) ?? null;\n const status = classifyEnvVar(base, target, override);\n if (status === 'unchanged') continue;\n entries.push({\n bucket: 'environment-var',\n key: `${envName}:${varKey}`,\n label: `${envName} → ${varKey}`,\n status,\n base,\n target,\n override,\n });\n }\n }\n\n const summary: Record<LinkedUpdateStatus, number> = {\n unchanged: 0,\n 'source-only': 0,\n 'local-only': 0,\n 'both-changed': 0,\n 'new-in-source': 0,\n 'removed-in-source': 0,\n };\n for (const e of entries) summary[e.status] += 1;\n\n return {\n fromVersion: args.fromVersion,\n toVersion: args.toVersion,\n entries,\n summary,\n };\n}\n\nfunction classifyRequest(\n base: ApiRequest | null,\n target: ApiRequest | null,\n override: RequestOverride | null,\n): LinkedUpdateStatus {\n if (!base && target) return 'new-in-source';\n if (base && !target) return 'removed-in-source';\n if (!base || !target) return 'unchanged';\n const sourceChanged = !structurallyEqual(base, target);\n const hasOverride = override !== null && Object.keys(override.patch).length > 0;\n if (!sourceChanged && !hasOverride) return 'unchanged';\n if (!sourceChanged && hasOverride) return 'local-only';\n if (sourceChanged && !hasOverride) return 'source-only';\n return 'both-changed';\n}\n\n// The request fields a consumer can override — must mirror\n// `RequestOverridePatch` in `@apicircle/shared`.\nconst OVERRIDABLE_REQUEST_FIELDS = [\n 'name',\n 'method',\n 'url',\n 'headers',\n 'query',\n 'pathParams',\n 'cookies',\n 'body',\n 'auth',\n 'contextVars',\n 'extractions',\n 'assertions',\n] as const;\n\n/**\n * True when the consumer's override touches a DISJOINT set of fields from the\n * ones the source changed base→target. In that case keeping the override is a\n * clean field-level merge (the override re-expresses as a delta vs the new\n * target on its own fields; the source's other changes flow through inherited).\n * False when any field appears in both sets — a genuine conflict.\n */\nfunction requestOverrideIsDisjoint(\n base: ApiRequest,\n target: ApiRequest,\n override: RequestOverride,\n): boolean {\n const baseRec: Record<string, unknown> = { ...base };\n const targetRec: Record<string, unknown> = { ...target };\n const overriddenFields = Object.keys(override.patch);\n for (const f of overriddenFields) {\n if (!OVERRIDABLE_REQUEST_FIELDS.includes(f as (typeof OVERRIDABLE_REQUEST_FIELDS)[number])) {\n continue;\n }\n if (!structurallyEqual(baseRec[f], targetRec[f])) {\n // The source changed a field the consumer also overrode → conflict.\n return false;\n }\n }\n return true;\n}\n\nfunction classifyFolder(base: Folder | null, target: Folder | null): LinkedUpdateStatus {\n if (!base && target) return 'new-in-source';\n if (base && !target) return 'removed-in-source';\n if (!base || !target) return 'unchanged';\n return structurallyEqual(base, target) ? 'unchanged' : 'source-only';\n}\n\nfunction classifyEnvVar(\n base: EnvironmentVariable | null,\n target: EnvironmentVariable | null,\n override: EnvironmentVariableOverride | null,\n): LinkedUpdateStatus {\n // Consumer-only addition (no source counterpart, override exists, not removed).\n if (!base && !target && override && !override.removed) return 'local-only';\n if (!base && target) return 'new-in-source';\n if (base && !target) return 'removed-in-source';\n if (!base || !target) return 'unchanged';\n const sourceChanged = !structurallyEqual(base, target);\n const hasOverride = override !== null;\n if (!sourceChanged && !hasOverride) return 'unchanged';\n if (!sourceChanged && hasOverride) return 'local-only';\n if (sourceChanged && !hasOverride) return 'source-only';\n return 'both-changed';\n}\n\n/**\n * Map status → 'mine' | 'theirs' for entries the user has resolved.\n * 'mine' = keep the override / orphan. 'theirs' = adopt source.\n *\n * `source-only`, `new-in-source`, and `local-only` don't need a\n * resolution (auto-applied), so this map is keyed only by entries that\n * are `both-changed` or `removed-in-source` (the latter optionally lets\n * the user keep their override as a consumer-only request — a rarer\n * choice).\n */\nexport type LinkedUpdateResolutionMap = Record<string, 'mine' | 'theirs'>;\n\nexport interface ApplyArgs {\n base: LinkedSnapshot | null;\n target: LinkedSnapshot;\n preview: LinkedUpdatePreview;\n resolutions: LinkedUpdateResolutionMap;\n /** All overrides for this link, BEFORE the apply. */\n requestOverrides: RequestOverride[];\n envVarOverrides: EnvironmentVariableOverride[];\n}\n\nexport interface ApplyResult {\n /** New canonical snapshot to cache (replaces base). */\n nextSnapshot: LinkedSnapshot;\n /** Override entries the consumer keeps after applying. */\n nextRequestOverrides: RequestOverride[];\n nextEnvVarOverrides: EnvironmentVariableOverride[];\n /** Per-entry record of what we did, surfaced to the toast / activity log. */\n log: Array<{ entryKey: string; bucket: LinkedUpdateBucket; action: string }>;\n}\n\n/**\n * Apply a fully-resolved preview. Pure — does not touch IDB or the store.\n *\n * Throws when any `both-changed` entry is missing a resolution.\n */\nexport function applyLinkedUpdate(args: ApplyArgs): ApplyResult {\n const log: ApplyResult['log'] = [];\n const requestOverridesByItem = new Map<string, RequestOverride>(\n args.requestOverrides.map((o) => [o.itemId, o]),\n );\n const envVarOverridesByKey = new Map<string, EnvironmentVariableOverride>(\n args.envVarOverrides.map((o) => [`${o.envName}:${o.varKey}`, o]),\n );\n\n for (const entry of args.preview.entries) {\n const id = `${entry.bucket}:${entry.key}`;\n if (entry.status === 'unchanged') continue;\n if (entry.status === 'source-only' || entry.status === 'new-in-source') {\n // Adopting target — nothing to do beyond replacing the snapshot.\n log.push({ entryKey: id, bucket: entry.bucket, action: 'adopt-source' });\n continue;\n }\n if (entry.status === 'local-only') {\n log.push({ entryKey: id, bucket: entry.bucket, action: 'keep-mine' });\n continue;\n }\n\n if (entry.status === 'removed-in-source') {\n // Default for orphans is to drop the override (nothing to override\n // if the source request is gone). Consumer can opt-in to keeping it\n // by supplying a 'mine' resolution explicitly.\n const choice = args.resolutions[id] ?? 'theirs';\n if (choice === 'theirs') {\n if (entry.bucket === 'request') requestOverridesByItem.delete(entry.key);\n else if (entry.bucket === 'environment-var') envVarOverridesByKey.delete(entry.key);\n log.push({ entryKey: id, bucket: entry.bucket, action: 'drop-orphan' });\n } else {\n log.push({ entryKey: id, bucket: entry.bucket, action: 'keep-orphan' });\n }\n continue;\n }\n\n if (entry.status === 'both-changed') {\n // Clean (disjoint-field) both-changed entries auto-merge: keeping the\n // override re-expresses it as a delta on the new target, with the\n // source's other field changes flowing through. No decision needed.\n const choice = args.resolutions[id] ?? (entry.autoMergeable ? 'mine' : undefined);\n if (!choice) {\n throw new Error(\n `applyLinkedUpdate: unresolved both-changed entry \"${entry.label}\" (${id})`,\n );\n }\n if (choice === 'theirs') {\n if (entry.bucket === 'request') requestOverridesByItem.delete(entry.key);\n else if (entry.bucket === 'environment-var') envVarOverridesByKey.delete(entry.key);\n log.push({ entryKey: id, bucket: entry.bucket, action: 'accept-source' });\n } else {\n const auto = entry.autoMergeable === true && !args.resolutions[id];\n log.push({ entryKey: id, bucket: entry.bucket, action: auto ? 'auto-merge' : 'keep-mine' });\n }\n }\n }\n\n return {\n nextSnapshot: args.target,\n nextRequestOverrides: [...requestOverridesByItem.values()],\n nextEnvVarOverrides: [...envVarOverridesByKey.values()],\n log,\n };\n}\n\n/**\n * Stable structural equality. JSON.stringify is good enough here because\n * every diffable field is a plain JSON value (no Dates, no class\n * instances, no functions). Object key ordering is preserved by V8's\n * insertion-order semantics for string keys.\n *\n * The `serializeWorkspace` canonical sort happens at push time, not at\n * diff time — this is intra-doc comparison, not byte equality with git.\n */\nfunction structurallyEqual(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n","import type {\n AssetGitRef,\n EnvPriorityRef,\n Folder,\n FolderNode,\n FormDataRow,\n EnvironmentVariableOverride,\n GlobalFileAsset,\n LinkedSnapshot,\n LinkedWorkspace,\n MockResponseBody,\n MockResponseConfig,\n RequestBody,\n Request as ApiRequest,\n RequestOverride,\n ReleaseHistory,\n ReleaseVersion,\n SecretCryptoMeta,\n WorkspaceLocal,\n WorkspaceSnapshot,\n WorkspaceSnapshotTrigger,\n WorkspaceSynced,\n} from '@apicircle/shared';\nimport { envPriorityKey, generateId } from '@apicircle/shared';\nimport type { WorkspacePatch, WorkspaceState } from './patches';\nimport {\n importApicircleFolderInto,\n type ImportApicircleFolderResult,\n} from './apicircleFolderImport';\nimport { appendReleaseEntry, deprecateRelease, yankRelease } from '../release/publishRelease';\nimport type { ParsedApicircleFolderExport } from '../import/apicircleFolder';\n\n// =============================================================================\n// applyMutation — single dispatch over every workspace patch.\n//\n// Pure: does not touch IDB, the network, or `Date.now` indirectly through\n// imports. The `now` parameter is injectable so tests can pin timestamps and\n// so the orchestrator stays deterministic when called multiple times in a\n// batch (e.g. an MCP tool handler applying several patches in sequence).\n//\n// `changedIds` carries the entity ids touched by the patch (request id,\n// folder id, environment name, plan id, mock id, etc). Callers use it to\n// invalidate caches, trigger autosave, or report results back to MCP\n// clients.\n// =============================================================================\n\nexport interface ApplyMutationOptions {\n /** ISO timestamp to stamp into `updatedAt`. Defaults to the current time. */\n now?: string;\n}\n\nexport interface ApplyMutationResult {\n next: WorkspaceState;\n changedIds: string[];\n}\n\nexport function applyMutation(\n state: WorkspaceState,\n patch: WorkspacePatch,\n options: ApplyMutationOptions = {},\n): ApplyMutationResult {\n const now = options.now ?? new Date().toISOString();\n switch (patch.kind) {\n case 'request.create':\n return applyRequestCreate(state, patch.request, now);\n case 'request.update':\n return applyRequestUpdate(state, patch.id, patch.patch, now);\n case 'request.delete':\n return applyRequestDelete(state, patch.id, now);\n case 'folder.create':\n return applyFolderCreate(state, patch.folder, now);\n case 'folder.delete':\n return applyFolderDelete(state, patch.id, now);\n case 'folder.move':\n return applyFolderMove(state, patch.id, patch.newParentId, now);\n case 'folder.update':\n return applyFolderUpdate(state, patch.id, patch.patch, now);\n case 'folder.import_apicircle':\n return applyFolderImportApicircle(state, patch.parsed, patch.parentFolderId, now);\n case 'environment.upsert':\n return applyEnvUpsert(state, patch.environment, now);\n case 'environment.delete':\n return applyEnvDelete(state, patch.name, now);\n case 'environment.setActive':\n return applyEnvSetActive(state, patch.name, now);\n case 'environment.setPriority':\n return applyEnvSetPriority(state, patch.order, now);\n case 'secretKey.upsert':\n return applySecretKeyUpsert(state, patch.meta, now);\n case 'secret.crypto.set':\n return applySecretCryptoSet(state, patch.crypto, now);\n case 'secret.crypto.clear':\n return applySecretCryptoClear(state, now);\n case 'assertion.upsert':\n return applyAssertionUpsert(state, patch.requestId, patch.assertion, now);\n case 'assertion.delete':\n return applyAssertionDelete(state, patch.requestId, patch.assertionId, now);\n case 'mock.upsert':\n return applyMockUpsert(state, patch.mock, now);\n case 'mock.delete':\n return applyMockDelete(state, patch.id, now);\n case 'release.publish':\n return applyReleasePublish(state, patch.entry, now);\n case 'release.deprecate':\n return applyReleaseDeprecate(state, patch.version, now);\n case 'release.yank':\n return applyReleaseYank(state, patch.version, now);\n case 'linkedWorkspace.upsert':\n return applyLinkedWorkspaceUpsert(state, patch.link, patch.ledger, patch.snapshot, now);\n case 'linkedWorkspace.remove':\n return applyLinkedWorkspaceRemove(state, patch.id, now);\n case 'linkedWorkspace.applyUpdate':\n return applyLinkedWorkspaceApplyUpdate(state, patch, now);\n case 'linkedOverride.setRequest':\n return applyLinkedOverrideSetRequest(state, patch.override, now);\n case 'linkedOverride.removeRequest':\n return applyLinkedOverrideRemoveRequest(state, patch.linkedWorkspaceId, patch.itemId, now);\n case 'linkedOverride.setEnvVar':\n return applyLinkedOverrideSetEnvVar(state, patch.override, now);\n case 'linkedOverride.removeEnvVar':\n return applyLinkedOverrideRemoveEnvVar(\n state,\n patch.linkedWorkspaceId,\n patch.envName,\n patch.varKey,\n now,\n );\n case 'linkedOverride.clearForLink':\n return applyLinkedOverrideClearForLink(state, patch.linkedWorkspaceId, now);\n case 'globalAsset.upsertFile':\n return applyGlobalAssetUpsertFile(state, patch.file, now);\n case 'globalAsset.removeFile':\n return applyGlobalAssetRemoveFile(state, patch.id, now);\n case 'globalAsset.markPushed':\n return applyGlobalAssetMarkPushed(state, patch.id, patch.ref, now);\n case 'globalAsset.markMerged':\n return applyGlobalAssetMarkMerged(state, patch.id, patch.ref, now);\n case 'globalAsset.cleanupWorkingRef':\n return applyGlobalAssetCleanupWorkingRef(state, patch.id, now);\n case 'globalAsset.invalidateRef':\n return applyGlobalAssetInvalidateRef(state, patch.id, patch.which, now);\n case 'plan.upsert':\n return applyPlanUpsert(state, patch.plan, now);\n case 'plan.delete':\n return applyPlanDelete(state, patch.id);\n case 'history.delete_run':\n return applyHistoryDeleteRun(state, patch.runId);\n case 'history.delete_plan_run':\n return applyHistoryDeletePlanRun(state, patch.planRunId);\n case 'history.purge':\n return applyHistoryPurge(state, patch.olderThanMs);\n case 'snapshot.capture':\n return applySnapshotCapture(state, patch, now);\n case 'snapshot.delete':\n return applySnapshotDelete(state, patch.id);\n case 'snapshot.restore':\n return applySnapshotRestore(state, patch.id, now);\n case 'snapshot.set_max_bytes':\n return applySnapshotSetMaxBytes(state, patch.maxBytes);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Request handlers\n// ---------------------------------------------------------------------------\n\nfunction applyRequestCreate(\n state: WorkspaceState,\n request: ApiRequest,\n now: string,\n): ApplyMutationResult {\n if (state.synced.collections.requests[request.id]) {\n return { next: state, changedIds: [] };\n }\n const tree = request.folderId\n ? state.synced.collections.tree\n : pushTreeChild(state.synced.collections.tree, { kind: 'request', id: request.id });\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n requests: { ...state.synced.collections.requests, [request.id]: request },\n tree,\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [request.id] };\n}\n\nfunction applyRequestUpdate(\n state: WorkspaceState,\n id: string,\n patch: Partial<Omit<ApiRequest, 'id' | 'createdAt'>>,\n now: string,\n): ApplyMutationResult {\n const existing = state.synced.collections.requests[id];\n if (!existing) {\n return { next: state, changedIds: [] };\n }\n const updated: ApiRequest = {\n ...existing,\n ...patch,\n id: existing.id,\n createdAt: existing.createdAt,\n updatedAt: now,\n };\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n requests: { ...state.synced.collections.requests, [id]: updated },\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [id] };\n}\n\nfunction applyRequestDelete(state: WorkspaceState, id: string, now: string): ApplyMutationResult {\n if (!state.synced.collections.requests[id]) {\n return { next: state, changedIds: [] };\n }\n const requests = { ...state.synced.collections.requests };\n delete requests[id];\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n requests,\n tree: removeTreeChild(state.synced.collections.tree, { kind: 'request', id }),\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n // Linked-request overrides live on `synced.linkedOverrides.requests`\n // and are keyed by the LINKED workspace's request id, not by an owned\n // request id. Deleting an owned request never touches them.\n return { next: { ...state, synced }, changedIds: [id] };\n}\n\n// ---------------------------------------------------------------------------\n// Folder handlers\n// ---------------------------------------------------------------------------\n\nfunction applyFolderCreate(\n state: WorkspaceState,\n folder: Folder,\n now: string,\n): ApplyMutationResult {\n if (state.synced.collections.folders[folder.id]) {\n return { next: state, changedIds: [] };\n }\n const tree = folder.parentId\n ? state.synced.collections.tree\n : pushTreeChild(state.synced.collections.tree, { kind: 'folder', id: folder.id });\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n folders: { ...state.synced.collections.folders, [folder.id]: folder },\n tree,\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [folder.id] };\n}\n\nfunction applyFolderDelete(state: WorkspaceState, id: string, now: string): ApplyMutationResult {\n if (!state.synced.collections.folders[id]) {\n return { next: state, changedIds: [] };\n }\n const folders = { ...state.synced.collections.folders };\n delete folders[id];\n // Reparent any direct children to the deleted folder's parent.\n const deleted = state.synced.collections.folders[id];\n const reparented: Record<string, Folder> = {};\n for (const [fid, f] of Object.entries(folders)) {\n if (f.parentId === id) {\n reparented[fid] = { ...f, parentId: deleted.parentId };\n } else {\n reparented[fid] = f;\n }\n }\n const requests = { ...state.synced.collections.requests };\n for (const [rid, r] of Object.entries(requests)) {\n if (r.folderId === id) {\n requests[rid] = { ...r, folderId: deleted.parentId };\n }\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n folders: reparented,\n requests,\n tree: removeTreeChild(state.synced.collections.tree, { kind: 'folder', id }),\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [id] };\n}\n\nfunction applyFolderMove(\n state: WorkspaceState,\n id: string,\n newParentId: string | null,\n now: string,\n): ApplyMutationResult {\n const folder = state.synced.collections.folders[id];\n if (!folder) {\n return { next: state, changedIds: [] };\n }\n if (folder.parentId === newParentId) {\n return { next: state, changedIds: [] };\n }\n // Reject self-parenting.\n if (newParentId === id) {\n return { next: state, changedIds: [] };\n }\n // Reject creating a cycle: walk up newParent's chain; if we hit `id`, abort.\n let cursor: string | null = newParentId;\n const folders = state.synced.collections.folders;\n while (cursor !== null) {\n if (cursor === id) return { next: state, changedIds: [] };\n cursor = folders[cursor]?.parentId ?? null;\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n folders: {\n ...state.synced.collections.folders,\n [id]: { ...folder, parentId: newParentId },\n },\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [id] };\n}\n\nfunction applyFolderUpdate(\n state: WorkspaceState,\n id: string,\n patch: Partial<Pick<Folder, 'name' | 'auth'>>,\n now: string,\n): ApplyMutationResult {\n const folder = state.synced.collections.folders[id];\n if (!folder) {\n return { next: state, changedIds: [] };\n }\n const nameChanging = 'name' in patch && patch.name !== undefined;\n const authChanging = 'auth' in patch;\n if (!nameChanging && !authChanging) {\n return { next: state, changedIds: [] };\n }\n let nextName = folder.name;\n if (nameChanging) {\n const trimmed = patch.name!.trim();\n if (!trimmed) {\n // Empty rename — preserve current. Reducer no-ops on invalid input\n // (matches request.update semantics: bad fields are dropped, the\n // patch as a whole still settles).\n } else if (trimmed === folder.name) {\n // No change to apply.\n } else if (!isFolderNameUnique(state, folder.parentId, trimmed, id)) {\n // Collision under the same parent — no-op rather than silently\n // accepting a duplicate. Headless writers should pre-uniquify (the\n // store helper `uniquifyName` does this already).\n return { next: state, changedIds: [] };\n } else {\n nextName = trimmed;\n }\n }\n const nextFolder: Folder = { ...folder, name: nextName };\n if (authChanging) {\n if (patch.auth === undefined) {\n delete nextFolder.auth;\n } else {\n nextFolder.auth = patch.auth;\n }\n }\n if (nextFolder.name === folder.name && nextFolder.auth === folder.auth) {\n return { next: state, changedIds: [] };\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: {\n ...state.synced.collections,\n folders: { ...state.synced.collections.folders, [id]: nextFolder },\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [id] };\n}\n\nfunction isFolderNameUnique(\n state: WorkspaceState,\n parentId: string | null,\n trimmedCandidate: string,\n ignoreId: string,\n): boolean {\n const target = trimmedCandidate.toLowerCase();\n for (const f of Object.values(state.synced.collections.folders)) {\n if (f.id === ignoreId) continue;\n if (f.parentId !== parentId) continue;\n if (f.name.trim().toLowerCase() === target) return false;\n }\n return true;\n}\n\n/**\n * Result-shape escape hatch for the `folder.import_apicircle` handler:\n * the underlying graft helper returns a richer object than the rest of\n * the reducers. We surface only the root + descendant ids through\n * `ApplyMutationResult.changedIds`. Clients that need the full counts\n * or re-attachment list should call `importApicircleFolderInto`\n * directly — the patch path is intentionally lossy so every reducer\n * has the same `{ next, changedIds }` shape.\n */\nfunction applyFolderImportApicircle(\n state: WorkspaceState,\n parsed: ParsedApicircleFolderExport,\n parentFolderId: string | null,\n now: string,\n): ApplyMutationResult {\n const result: ImportApicircleFolderResult = importApicircleFolderInto(\n state.synced,\n parsed,\n parentFolderId,\n );\n const synced: WorkspaceSynced = {\n ...result.synced,\n meta: { ...result.synced.meta, updatedAt: now },\n };\n const changedIds = [\n result.rootFolderId,\n ...parsed.subfolders.map((f) => f.id),\n ...parsed.requests.map((r) => r.id),\n ];\n return { next: { ...state, synced }, changedIds };\n}\n\n// ---------------------------------------------------------------------------\n// Environment handlers\n// ---------------------------------------------------------------------------\n\nfunction applyEnvUpsert(\n state: WorkspaceState,\n environment: {\n name: string;\n variables: Array<{ key: string; value: string; encrypted: boolean }>;\n },\n now: string,\n): ApplyMutationResult {\n const trimmed = environment.name.trim();\n if (!trimmed) {\n return { next: state, changedIds: [] };\n }\n const isNew = !state.synced.environments.items[trimmed];\n const synced: WorkspaceSynced = {\n ...state.synced,\n environments: {\n ...state.synced.environments,\n items: {\n ...state.synced.environments.items,\n [trimmed]: { ...environment, name: trimmed },\n },\n // Newly-created envs land at the end of the priority list so they're\n // always reachable. Existing envs keep their position.\n priorityOrder:\n isNew &&\n !state.synced.environments.priorityOrder.some(\n (r) => r.kind === 'local' && r.name === trimmed,\n )\n ? [...state.synced.environments.priorityOrder, { kind: 'local', name: trimmed }]\n : state.synced.environments.priorityOrder,\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [trimmed] };\n}\n\nfunction applyEnvDelete(state: WorkspaceState, name: string, now: string): ApplyMutationResult {\n if (!state.synced.environments.items[name]) {\n return { next: state, changedIds: [] };\n }\n const items = { ...state.synced.environments.items };\n delete items[name];\n const synced: WorkspaceSynced = {\n ...state.synced,\n environments: {\n ...state.synced.environments,\n items,\n activeName:\n state.synced.environments.activeName === name ? null : state.synced.environments.activeName,\n priorityOrder: state.synced.environments.priorityOrder.filter(\n (r) => !(r.kind === 'local' && r.name === name),\n ),\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [name] };\n}\n\nfunction applyEnvSetActive(\n state: WorkspaceState,\n name: string | null,\n now: string,\n): ApplyMutationResult {\n if (name !== null && !state.synced.environments.items[name]) {\n return { next: state, changedIds: [] };\n }\n if (state.synced.environments.activeName === name) {\n return { next: state, changedIds: [] };\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n environments: { ...state.synced.environments, activeName: name },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: name ? [name] : [] };\n}\n\nfunction applyEnvSetPriority(\n state: WorkspaceState,\n order: EnvPriorityRef[],\n now: string,\n): ApplyMutationResult {\n // Filter against:\n // - local envs: must be in `state.synced.environments.items`\n // - linked envs: pass through unconditionally — the snapshot lives in\n // `WorkspaceLocal.linkedCollections` which this reducer can't see.\n // Stale linked refs are dropped at resolve time (handled by\n // parseEnvPriorityKey returning null for unknown shapes).\n // Dedupe across both kinds via composite key.\n const knownLocal = new Set(Object.keys(state.synced.environments.items));\n const seen = new Set<string>();\n const filtered = order.filter((ref) => {\n const key = envPriorityKey(ref);\n if (seen.has(key)) return false;\n if (ref.kind === 'local' && !knownLocal.has(ref.name)) return false;\n seen.add(key);\n return true;\n });\n const synced: WorkspaceSynced = {\n ...state.synced,\n environments: { ...state.synced.environments, priorityOrder: filtered },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: filtered.map(envPriorityKey) };\n}\n\n// ---------------------------------------------------------------------------\n// Secret-vault slot handlers\n// ---------------------------------------------------------------------------\n\nfunction applySecretKeyUpsert(\n state: WorkspaceState,\n meta: { id: string; label: string; salt: string; createdAt: string },\n now: string,\n): ApplyMutationResult {\n // Defensive: an empty id or label would corrupt the slot map. Drop\n // silently so an MCP client batching multiple slot upserts doesn't\n // poison the workspace on a single malformed row.\n if (!meta.id || !meta.label.trim() || !meta.salt) {\n return { next: state, changedIds: [] };\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n secretKeys: {\n ...(state.synced.secretKeys ?? {}),\n [meta.id]: { ...meta, label: meta.label.trim() },\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [meta.id] };\n}\n\nfunction applySecretCryptoSet(\n state: WorkspaceState,\n crypto: SecretCryptoMeta,\n now: string,\n): ApplyMutationResult {\n // Defensive: refuse to persist a malformed blob. The verifier MUST be\n // populated — without it `unlockSecretCrypto` can't reject a wrong\n // passphrase and we'd hand back a wrong key to every downstream\n // decrypt. salt + iterations are equally non-negotiable.\n if (\n !crypto ||\n crypto.kdf !== 'pbkdf2-sha256-v1' ||\n !crypto.salt ||\n !crypto.verifier ||\n !(crypto.iterations >= 1)\n ) {\n return { next: state, changedIds: [] };\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n secretCrypto: { ...crypto },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: ['secret.crypto'] };\n}\n\nfunction applySecretCryptoClear(state: WorkspaceState, now: string): ApplyMutationResult {\n // No-op if already cleared. Keeps `updatedAt` stable so repeated calls\n // don't churn the synced doc.\n if (!state.synced.secretCrypto) {\n return { next: state, changedIds: [] };\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n secretCrypto: null,\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: ['secret.crypto'] };\n}\n\n// ---------------------------------------------------------------------------\n// Assertion handlers\n// ---------------------------------------------------------------------------\n\nfunction applyAssertionUpsert(\n state: WorkspaceState,\n requestId: string,\n assertion: { id: string; kind: string; op: string; expected: string | number; target?: string },\n now: string,\n): ApplyMutationResult {\n const request = state.synced.collections.requests[requestId];\n if (!request) {\n return { next: state, changedIds: [] };\n }\n const idx = request.assertions.findIndex((a) => a.id === assertion.id);\n const next = [...request.assertions];\n if (idx === -1) {\n next.push(assertion as ApiRequest['assertions'][number]);\n } else {\n next[idx] = assertion as ApiRequest['assertions'][number];\n }\n return applyRequestUpdate(state, requestId, { assertions: next }, now);\n}\n\nfunction applyAssertionDelete(\n state: WorkspaceState,\n requestId: string,\n assertionId: string,\n now: string,\n): ApplyMutationResult {\n const request = state.synced.collections.requests[requestId];\n if (!request) {\n return { next: state, changedIds: [] };\n }\n const next = request.assertions.filter((a) => a.id !== assertionId);\n if (next.length === request.assertions.length) {\n return { next: state, changedIds: [] };\n }\n return applyRequestUpdate(state, requestId, { assertions: next }, now);\n}\n\n// ---------------------------------------------------------------------------\n// Mock handlers\n// ---------------------------------------------------------------------------\n\nfunction applyMockUpsert(\n state: WorkspaceState,\n mock: { id: string },\n now: string,\n): ApplyMutationResult {\n const synced: WorkspaceSynced = {\n ...state.synced,\n mockServers: {\n ...state.synced.mockServers,\n [mock.id]: mock as WorkspaceSynced['mockServers'][string],\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [mock.id] };\n}\n\nfunction applyMockDelete(state: WorkspaceState, id: string, now: string): ApplyMutationResult {\n if (!state.synced.mockServers[id]) {\n return { next: state, changedIds: [] };\n }\n const mockServers = { ...state.synced.mockServers };\n delete mockServers[id];\n const synced: WorkspaceSynced = {\n ...state.synced,\n mockServers,\n meta: { ...state.synced.meta, updatedAt: now },\n };\n // Also clear runtime entry — a deleted definition can't have a live runtime.\n const local: WorkspaceLocal = state.local.mockRuntime.active[id]\n ? {\n ...state.local,\n mockRuntime: {\n active: Object.fromEntries(\n Object.entries(state.local.mockRuntime.active).filter(([k]) => k !== id),\n ),\n },\n }\n : state.local;\n return { next: { synced, local }, changedIds: [id] };\n}\n\n// ---------------------------------------------------------------------------\n// Release handlers (synced.releases.self)\n//\n// The workspace-self release ledger that linked consumers pin to. `publish`\n// appends a pre-built ReleaseVersion (snapshot already computed by the async\n// `buildReleaseEntry`); `deprecate` / `yank` flip the soft / hard signal\n// flags. These reducers delegate to the pure helpers in\n// `../release/publishRelease` and pass the injected `now` so batches stay\n// deterministic. They THROW (rather than no-op) on invalid semver, a\n// duplicate version, or an unknown version — see the patch-union comment.\n// ---------------------------------------------------------------------------\n\nfunction applyReleasePublish(\n state: WorkspaceState,\n entry: ReleaseVersion,\n now: string,\n): ApplyMutationResult {\n const synced = appendReleaseEntry(state.synced, entry, now);\n return { next: { ...state, synced }, changedIds: [entry.version] };\n}\n\nfunction applyReleaseDeprecate(\n state: WorkspaceState,\n version: string,\n now: string,\n): ApplyMutationResult {\n const synced = deprecateRelease(state.synced, version, now);\n return { next: { ...state, synced }, changedIds: [version] };\n}\n\nfunction applyReleaseYank(\n state: WorkspaceState,\n version: string,\n now: string,\n): ApplyMutationResult {\n const synced = yankRelease(state.synced, version, now);\n return { next: { ...state, synced }, changedIds: [version] };\n}\n\n// ---------------------------------------------------------------------------\n// Linked-workspace handlers (synced.linkedWorkspaces + releases.perLink +\n// linkedOverrides; local.linkedCollections + sessions.github.links)\n//\n// `upsert` writes the link record and OPTIONALLY the cached release ledger\n// (synced.releases.perLink) + collections/environments snapshot\n// (local.linkedCollections) produced by the network fetch in the host. The\n// snapshot lands in WorkspaceLocal so the consumer's pushed JSON never carries\n// the source's whole tree. `remove` cascades across every slice the link\n// touched. Both are pure + synchronous.\n// ---------------------------------------------------------------------------\n\nfunction applyLinkedWorkspaceUpsert(\n state: WorkspaceState,\n link: LinkedWorkspace,\n ledger: ReleaseHistory | undefined,\n snapshot: LinkedSnapshot | undefined,\n now: string,\n): ApplyMutationResult {\n const synced: WorkspaceSynced = {\n ...state.synced,\n linkedWorkspaces: { ...state.synced.linkedWorkspaces, [link.id]: link },\n releases: ledger\n ? {\n ...state.synced.releases,\n perLink: { ...state.synced.releases.perLink, [link.id]: ledger },\n }\n : state.synced.releases,\n meta: { ...state.synced.meta, updatedAt: now },\n };\n const local: WorkspaceLocal = snapshot\n ? {\n ...state.local,\n linkedCollections: { ...state.local.linkedCollections, [link.id]: snapshot },\n }\n : state.local;\n return { next: { synced, local }, changedIds: [link.id] };\n}\n\nfunction applyLinkedWorkspaceRemove(\n state: WorkspaceState,\n id: string,\n now: string,\n): ApplyMutationResult {\n if (!state.synced.linkedWorkspaces[id]) {\n return { next: state, changedIds: [] };\n }\n const linkedWorkspaces = { ...state.synced.linkedWorkspaces };\n delete linkedWorkspaces[id];\n const perLink = { ...state.synced.releases.perLink };\n delete perLink[id];\n // Override keys are `${linkedWorkspaceId}:…`; generateId() ids never contain\n // a colon, so the `${id}:` prefix is an unambiguous match.\n const prefix = `${id}:`;\n const dropPrefixed = <T>(map: Record<string, T>): Record<string, T> =>\n Object.fromEntries(Object.entries(map).filter(([k]) => !k.startsWith(prefix)));\n const synced: WorkspaceSynced = {\n ...state.synced,\n linkedWorkspaces,\n releases: { ...state.synced.releases, perLink },\n linkedOverrides: {\n requests: dropPrefixed(state.synced.linkedOverrides.requests),\n environmentVars: dropPrefixed(state.synced.linkedOverrides.environmentVars),\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n const linkedCollections = { ...state.local.linkedCollections };\n delete linkedCollections[id];\n const githubLinks = { ...state.local.sessions.github.links };\n delete githubLinks[id];\n const local: WorkspaceLocal = {\n ...state.local,\n linkedCollections,\n sessions: {\n ...state.local.sessions,\n github: { ...state.local.sessions.github, links: githubLinks },\n },\n };\n return { next: { synced, local }, changedIds: [id] };\n}\n\nfunction applyLinkedWorkspaceApplyUpdate(\n state: WorkspaceState,\n patch: {\n id: string;\n pinnedVersion: string | null;\n snapshot: LinkedSnapshot;\n ledger: ReleaseHistory;\n requestOverrides: RequestOverride[];\n envVarOverrides: EnvironmentVariableOverride[];\n },\n now: string,\n): ApplyMutationResult {\n const link = state.synced.linkedWorkspaces[patch.id];\n if (!link) {\n return { next: state, changedIds: [] };\n }\n const prefix = `${patch.id}:`;\n const otherRequests = Object.fromEntries(\n Object.entries(state.synced.linkedOverrides.requests).filter(([k]) => !k.startsWith(prefix)),\n );\n for (const o of patch.requestOverrides) {\n otherRequests[`${o.linkedWorkspaceId}:${o.itemId}`] = o;\n }\n const otherEnvVars = Object.fromEntries(\n Object.entries(state.synced.linkedOverrides.environmentVars).filter(\n ([k]) => !k.startsWith(prefix),\n ),\n );\n for (const o of patch.envVarOverrides) {\n otherEnvVars[`${o.linkedWorkspaceId}:${o.envName}:${o.varKey}`] = o;\n }\n const synced: WorkspaceSynced = {\n ...state.synced,\n linkedWorkspaces: {\n ...state.synced.linkedWorkspaces,\n [patch.id]: { ...link, pinnedVersion: patch.pinnedVersion },\n },\n releases: {\n ...state.synced.releases,\n perLink: { ...state.synced.releases.perLink, [patch.id]: patch.ledger },\n },\n linkedOverrides: { requests: otherRequests, environmentVars: otherEnvVars },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n const local: WorkspaceLocal = {\n ...state.local,\n linkedCollections: { ...state.local.linkedCollections, [patch.id]: patch.snapshot },\n };\n return { next: { synced, local }, changedIds: [patch.id] };\n}\n\n// ---------------------------------------------------------------------------\n// Linked-content override handlers (synced.linkedOverrides) — consumer edits to\n// a linked workspace's requests / env-vars, stored as field-level deltas.\n// ---------------------------------------------------------------------------\n\nfunction applyLinkedOverrideSetRequest(\n state: WorkspaceState,\n override: RequestOverride,\n now: string,\n): ApplyMutationResult {\n const key = `${override.linkedWorkspaceId}:${override.itemId}`;\n const synced: WorkspaceSynced = {\n ...state.synced,\n linkedOverrides: {\n ...state.synced.linkedOverrides,\n requests: {\n ...state.synced.linkedOverrides.requests,\n [key]: { ...override, updatedAt: now },\n },\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [key] };\n}\n\nfunction applyLinkedOverrideRemoveRequest(\n state: WorkspaceState,\n linkedWorkspaceId: string,\n itemId: string,\n now: string,\n): ApplyMutationResult {\n const key = `${linkedWorkspaceId}:${itemId}`;\n if (!state.synced.linkedOverrides.requests[key]) {\n return { next: state, changedIds: [] };\n }\n const requests = { ...state.synced.linkedOverrides.requests };\n delete requests[key];\n const synced: WorkspaceSynced = {\n ...state.synced,\n linkedOverrides: { ...state.synced.linkedOverrides, requests },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [key] };\n}\n\nfunction applyLinkedOverrideSetEnvVar(\n state: WorkspaceState,\n override: EnvironmentVariableOverride,\n now: string,\n): ApplyMutationResult {\n const key = `${override.linkedWorkspaceId}:${override.envName}:${override.varKey}`;\n const synced: WorkspaceSynced = {\n ...state.synced,\n linkedOverrides: {\n ...state.synced.linkedOverrides,\n environmentVars: {\n ...state.synced.linkedOverrides.environmentVars,\n [key]: { ...override, updatedAt: now },\n },\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [key] };\n}\n\nfunction applyLinkedOverrideRemoveEnvVar(\n state: WorkspaceState,\n linkedWorkspaceId: string,\n envName: string,\n varKey: string,\n now: string,\n): ApplyMutationResult {\n const key = `${linkedWorkspaceId}:${envName}:${varKey}`;\n if (!state.synced.linkedOverrides.environmentVars[key]) {\n return { next: state, changedIds: [] };\n }\n const environmentVars = { ...state.synced.linkedOverrides.environmentVars };\n delete environmentVars[key];\n const synced: WorkspaceSynced = {\n ...state.synced,\n linkedOverrides: { ...state.synced.linkedOverrides, environmentVars },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [key] };\n}\n\nfunction applyLinkedOverrideClearForLink(\n state: WorkspaceState,\n linkedWorkspaceId: string,\n now: string,\n): ApplyMutationResult {\n const prefix = `${linkedWorkspaceId}:`;\n const requestKeys = Object.keys(state.synced.linkedOverrides.requests).filter((k) =>\n k.startsWith(prefix),\n );\n const envKeys = Object.keys(state.synced.linkedOverrides.environmentVars).filter((k) =>\n k.startsWith(prefix),\n );\n if (requestKeys.length === 0 && envKeys.length === 0) {\n return { next: state, changedIds: [] };\n }\n const requests = Object.fromEntries(\n Object.entries(state.synced.linkedOverrides.requests).filter(([k]) => !k.startsWith(prefix)),\n );\n const environmentVars = Object.fromEntries(\n Object.entries(state.synced.linkedOverrides.environmentVars).filter(\n ([k]) => !k.startsWith(prefix),\n ),\n );\n const synced: WorkspaceSynced = {\n ...state.synced,\n linkedOverrides: { requests, environmentVars },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [...requestKeys, ...envKeys] };\n}\n\n// ---------------------------------------------------------------------------\n// Global file asset handlers (synced.globalAssets.files)\n//\n// `upsertFile` and `removeFile` are CRUD primitives. The four state-machine\n// transitions (`markPushed`, `markMerged`, `cleanupWorkingRef`,\n// `invalidateRef`) are driven by the push + refresh flows. Each preserves\n// the provenance fields the caller didn't touch — e.g. `markMerged` does\n// not clear `workingBranchRef`; that's the cleanup invariant's job.\n//\n// `removeFile` is the only one that cascades through other slices: every\n// request body + mock-response body that referenced the asset id gets\n// unbound. The helpers below mirror `clearGlobalFileAssetFromBody` and\n// friends from `globalAssetsActions.ts` — kept inline so the core layer\n// has no UI-store dependency.\n// ---------------------------------------------------------------------------\n\nfunction applyGlobalAssetUpsertFile(\n state: WorkspaceState,\n file: GlobalFileAsset,\n now: string,\n): ApplyMutationResult {\n const files = state.synced.globalAssets.files ?? {};\n const existing = files[file.id];\n // If the caller didn't carry the ref fields, preserve the existing ones.\n // Stops a generic `upsert` from accidentally erasing provenance the\n // push/refresh flows worked to establish.\n const next: GlobalFileAsset = {\n ...file,\n workingBranchRef:\n file.workingBranchRef !== undefined ? file.workingBranchRef : existing?.workingBranchRef,\n baseBranchRef: file.baseBranchRef !== undefined ? file.baseBranchRef : existing?.baseBranchRef,\n updatedAt: now,\n };\n const synced: WorkspaceSynced = {\n ...state.synced,\n globalAssets: {\n ...state.synced.globalAssets,\n files: { ...files, [file.id]: next },\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [file.id] };\n}\n\nfunction applyGlobalAssetRemoveFile(\n state: WorkspaceState,\n id: string,\n now: string,\n): ApplyMutationResult {\n const files = state.synced.globalAssets.files ?? {};\n if (!files[id]) {\n return { next: state, changedIds: [] };\n }\n const { [id]: _drop, ...rest } = files;\n void _drop;\n\n // Cascade — clear `globalFileAssetId` on every request body + mock\n // response body that referenced the asset.\n const requests = { ...state.synced.collections.requests };\n for (const [reqId, req] of Object.entries(requests)) {\n const body = clearAssetFromRequestBody(req.body, id);\n if (body !== req.body) requests[reqId] = { ...req, body, updatedAt: now };\n }\n\n const mockServers = { ...state.synced.mockServers };\n for (const [serverId, server] of Object.entries(mockServers)) {\n let touchedServer = false;\n const endpoints = server.endpoints.map((endpoint) => {\n let touched = false;\n const defaultResponse = clearAssetFromMockResponse(endpoint.defaultResponse, id);\n if (defaultResponse !== endpoint.defaultResponse) touched = true;\n const requestValidation = endpoint.requestValidation.map((rule) => {\n const failResponse = clearAssetFromMockResponse(rule.failResponse, id);\n if (failResponse === rule.failResponse) return rule;\n touched = true;\n return { ...rule, failResponse };\n });\n const responseRules = endpoint.responseRules.map((rule) => {\n const response = clearAssetFromMockResponse(rule.response, id);\n if (response === rule.response) return rule;\n touched = true;\n return { ...rule, response };\n });\n if (!touched) return endpoint;\n touchedServer = true;\n return { ...endpoint, defaultResponse, requestValidation, responseRules };\n });\n if (touchedServer) {\n // `source.kind === 'manual'` carries a parallel `endpoints` copy that\n // the manual-source editor reads from; mirror the same touch there.\n const source =\n server.source.kind === 'manual' ? { kind: 'manual' as const, endpoints } : server.source;\n mockServers[serverId] = { ...server, source, endpoints, updatedAt: now };\n }\n }\n\n // Drop the local-only buffers tied to this asset so reads don't return\n // stale \"Uploaded locally\" / \"Used by N\" entries after the delete.\n let local = state.local;\n if (local.pendingFileUploads && local.pendingFileUploads[id]) {\n const nextPending = { ...local.pendingFileUploads };\n delete nextPending[id];\n local = { ...local, pendingFileUploads: nextPending };\n }\n if (local.assetUsageIndex && local.assetUsageIndex[id]) {\n const nextUsage = { ...local.assetUsageIndex };\n delete nextUsage[id];\n local = { ...local, assetUsageIndex: nextUsage };\n }\n\n // Queue the attachment blob for deletion on the next push IF the asset\n // ever made it to a remote ref. Otherwise the bytes were only ever in\n // local IDB — there's no remote tree entry to delete, so we skip the\n // queue. The push flow emits `{path: '.apicircle/workspace-<id>/attachments/<slotId>',\n // sha: null}` over `base_tree` for every queued slot id, which GitHub\n // treats as a tree-entry deletion. The eventual PR merge then carries\n // the deletion through to the base branch.\n const existing = files[id];\n const hadRemoteRef = Boolean(existing.workingBranchRef || existing.baseBranchRef);\n if (hadRemoteRef && !(local.pendingAttachmentDeletes ?? []).includes(existing.slotId)) {\n local = {\n ...local,\n pendingAttachmentDeletes: [...(local.pendingAttachmentDeletes ?? []), existing.slotId],\n };\n }\n\n const synced: WorkspaceSynced = {\n ...state.synced,\n collections: { ...state.synced.collections, requests },\n mockServers,\n globalAssets: { ...state.synced.globalAssets, files: rest },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { synced, local }, changedIds: [id] };\n}\n\nfunction applyGlobalAssetMarkPushed(\n state: WorkspaceState,\n id: string,\n ref: AssetGitRef,\n now: string,\n): ApplyMutationResult {\n return mutateAssetRef(state, id, now, (asset) => ({ ...asset, workingBranchRef: ref }));\n}\n\nfunction applyGlobalAssetMarkMerged(\n state: WorkspaceState,\n id: string,\n ref: AssetGitRef,\n now: string,\n): ApplyMutationResult {\n return mutateAssetRef(state, id, now, (asset) => ({ ...asset, baseBranchRef: ref }));\n}\n\nfunction applyGlobalAssetCleanupWorkingRef(\n state: WorkspaceState,\n id: string,\n now: string,\n): ApplyMutationResult {\n return mutateAssetRef(state, id, now, (asset) => {\n if (!asset.workingBranchRef) return asset;\n return { ...asset, workingBranchRef: null };\n });\n}\n\nfunction applyGlobalAssetInvalidateRef(\n state: WorkspaceState,\n id: string,\n which: 'working' | 'base',\n now: string,\n): ApplyMutationResult {\n return mutateAssetRef(state, id, now, (asset) => {\n if (which === 'working') {\n if (!asset.workingBranchRef) return asset;\n return { ...asset, workingBranchRef: null };\n }\n if (!asset.baseBranchRef) return asset;\n return { ...asset, baseBranchRef: null };\n });\n}\n\nfunction mutateAssetRef(\n state: WorkspaceState,\n id: string,\n now: string,\n transform: (asset: GlobalFileAsset) => GlobalFileAsset,\n): ApplyMutationResult {\n const files = state.synced.globalAssets.files ?? {};\n const existing = files[id];\n if (!existing) return { next: state, changedIds: [] };\n const updated = transform(existing);\n if (updated === existing) return { next: state, changedIds: [] };\n const next: GlobalFileAsset = { ...updated, updatedAt: now };\n const synced: WorkspaceSynced = {\n ...state.synced,\n globalAssets: {\n ...state.synced.globalAssets,\n files: { ...files, [id]: next },\n },\n meta: { ...state.synced.meta, updatedAt: now },\n };\n return { next: { ...state, synced }, changedIds: [id] };\n}\n\nfunction clearAssetFromRequestBody(body: RequestBody, id: string): RequestBody {\n if (body.type === 'binary' && body.attachment?.globalFileAssetId === id) {\n return { type: 'binary', content: '' };\n }\n if (body.type !== 'form-data' || !body.formRows) return body;\n let touched = false;\n const formRows = body.formRows.map((row): FormDataRow => {\n if (row.kind !== 'file' || row.globalFileAssetId !== id) return row;\n touched = true;\n return { kind: 'file', key: row.key, enabled: row.enabled, slotId: null };\n });\n return touched ? { ...body, formRows } : body;\n}\n\nfunction clearAssetFromMockResponse(response: MockResponseConfig, id: string): MockResponseConfig {\n const body = clearAssetFromMockBody(response.body, id);\n return body === response.body ? response : { ...response, body };\n}\n\nfunction clearAssetFromMockBody(body: MockResponseBody, id: string): MockResponseBody {\n if (body.type === 'binary' && body.attachment?.globalFileAssetId === id) {\n return { type: 'binary', content: '' };\n }\n return body;\n}\n\n// ---------------------------------------------------------------------------\n// Plan handlers (WorkspaceLocal — never pushed to git)\n// ---------------------------------------------------------------------------\n\nfunction applyPlanUpsert(\n state: WorkspaceState,\n plan: { id: string },\n now: string,\n): ApplyMutationResult {\n const existing = state.local.executionPlans[plan.id];\n const merged = existing\n ? { ...existing, ...plan, id: existing.id, createdAt: existing.createdAt, updatedAt: now }\n : { ...plan, updatedAt: now };\n const local: WorkspaceLocal = {\n ...state.local,\n executionPlans: {\n ...state.local.executionPlans,\n [plan.id]: merged as WorkspaceLocal['executionPlans'][string],\n },\n };\n return { next: { ...state, local }, changedIds: [plan.id] };\n}\n\nfunction applyPlanDelete(state: WorkspaceState, id: string): ApplyMutationResult {\n if (!state.local.executionPlans[id]) {\n return { next: state, changedIds: [] };\n }\n const next = { ...state.local.executionPlans };\n delete next[id];\n // Drop history rows too — they'd dangle to a non-existent plan.\n const planRuns = state.local.history.planRuns.filter((r) => r.planId !== id);\n const local: WorkspaceLocal = {\n ...state.local,\n executionPlans: next,\n history: { ...state.local.history, planRuns },\n };\n return { next: { ...state, local }, changedIds: [id] };\n}\n\n// ---------------------------------------------------------------------------\n// Tree helpers\n// ---------------------------------------------------------------------------\n\nfunction pushTreeChild(\n tree: FolderNode,\n child: { kind: 'folder' | 'request'; id: string },\n): FolderNode {\n return { ...tree, children: [...tree.children, child] };\n}\n\nfunction removeTreeChild(\n tree: FolderNode,\n child: { kind: 'folder' | 'request'; id: string },\n): FolderNode {\n return {\n ...tree,\n children: tree.children.filter((c) => !(c.kind === child.kind && c.id === child.id)),\n };\n}\n\n// ---------------------------------------------------------------------------\n// History handlers (WorkspaceLocal — never pushed to git). Each is pure: drop\n// the matching row(s) and return the new state. The MCP host uses these to\n// expose \"delete a single run\" and \"purge older than N days\" so users can\n// keep their local IDB footprint bounded.\n// ---------------------------------------------------------------------------\n\nfunction applyHistoryDeleteRun(state: WorkspaceState, runId: string): ApplyMutationResult {\n const before = state.local.history.requestRuns;\n const after = before.filter((r) => r.id !== runId);\n if (after.length === before.length) {\n return { next: state, changedIds: [] };\n }\n const local: WorkspaceLocal = {\n ...state.local,\n history: { ...state.local.history, requestRuns: after },\n };\n return { next: { ...state, local }, changedIds: [runId] };\n}\n\nfunction applyHistoryDeletePlanRun(state: WorkspaceState, planRunId: string): ApplyMutationResult {\n const before = state.local.history.planRuns;\n const after = before.filter((r) => r.id !== planRunId);\n if (after.length === before.length) {\n return { next: state, changedIds: [] };\n }\n const local: WorkspaceLocal = {\n ...state.local,\n history: { ...state.local.history, planRuns: after },\n };\n return { next: { ...state, local }, changedIds: [planRunId] };\n}\n\n// ---------------------------------------------------------------------------\n// Snapshot handlers (WorkspaceLocal.snapshots — never pushed to git). Each\n// snapshot is a verbatim copy of `synced` plus metadata. Capture pushes a\n// new entry and evicts oldest until total size is under `maxBytes`. Restore\n// replaces `synced` with the snapshot's stored doc and clears\n// `local.sync.lastPulledSnapshot` so the next push surfaces the restore as\n// a logical re-fork rather than a no-op.\n// ---------------------------------------------------------------------------\n\nfunction approxJsonByteLength(value: unknown): number {\n // JSON.stringify is the closest proxy to what IDB will persist; encoding\n // costs are ~1 byte/char for ASCII payloads. Multi-byte chars under-count\n // slightly, which is fine — the cap is a soft eviction trigger, not a\n // hard quota.\n try {\n return JSON.stringify(value).length;\n } catch {\n return 0;\n }\n}\n\nfunction evictSnapshotsToCap(\n entries: WorkspaceSnapshot[],\n maxBytes: number,\n): { entries: WorkspaceSnapshot[]; evictedIds: string[] } {\n if (!Number.isFinite(maxBytes) || maxBytes <= 0) {\n return { entries, evictedIds: [] };\n }\n let total = entries.reduce((sum, e) => sum + e.sizeBytes, 0);\n if (total <= maxBytes) return { entries, evictedIds: [] };\n // Sort oldest-first so we drop the front of the list. We rebuild the\n // array rather than mutating it in place.\n const sorted = [...entries].sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n const evictedIds: string[] = [];\n while (total > maxBytes && sorted.length > 0) {\n const dropped = sorted.shift()!;\n evictedIds.push(dropped.id);\n total -= dropped.sizeBytes;\n }\n // Restore newest-first ordering so callers' \"first entry is most recent\"\n // assumption holds (the History panel renders in this order).\n return {\n entries: sorted.sort((a, b) => b.createdAt.localeCompare(a.createdAt)),\n evictedIds,\n };\n}\n\nfunction applySnapshotCapture(\n state: WorkspaceState,\n args: { trigger: WorkspaceSnapshotTrigger; note?: string; id?: string },\n now: string,\n): ApplyMutationResult {\n const id = args.id ?? generateId();\n const snapshot: WorkspaceSnapshot = {\n id,\n createdAt: now,\n triggeredBy: args.trigger,\n note: args.note,\n workspaceSyncedSnapshot: state.synced,\n sizeBytes: approxJsonByteLength(state.synced),\n };\n const ledger = state.local.snapshots;\n // Newest-first so the History panel can iterate without sorting.\n const merged = [snapshot, ...ledger.entries];\n const { entries, evictedIds } = evictSnapshotsToCap(merged, ledger.maxBytes);\n const local: WorkspaceLocal = {\n ...state.local,\n snapshots: { ...ledger, entries },\n };\n return { next: { ...state, local }, changedIds: [id, ...evictedIds] };\n}\n\nfunction applySnapshotDelete(state: WorkspaceState, id: string): ApplyMutationResult {\n const before = state.local.snapshots.entries;\n const after = before.filter((s) => s.id !== id);\n if (after.length === before.length) {\n return { next: state, changedIds: [] };\n }\n const local: WorkspaceLocal = {\n ...state.local,\n snapshots: { ...state.local.snapshots, entries: after },\n };\n return { next: { ...state, local }, changedIds: [id] };\n}\n\nfunction applySnapshotRestore(state: WorkspaceState, id: string, now: string): ApplyMutationResult {\n const target = state.local.snapshots.entries.find((s) => s.id === id);\n if (!target) {\n return { next: state, changedIds: [] };\n }\n // The synced doc replaces wholesale. The snapshot's own meta.updatedAt\n // is preserved so the user can see how stale the restored state was;\n // top-level workspace updatedAt re-stamps to `now` so downstream\n // consumers (the diff summary, last-pull tracker) see the change.\n const synced: WorkspaceSynced = {\n ...target.workspaceSyncedSnapshot,\n meta: { ...target.workspaceSyncedSnapshot.meta, updatedAt: now },\n };\n // Restore is logically a re-fork: anything in the upstream remote will\n // diverge from our restored state. Clear `lastPulledSnapshot` so the\n // diff summary surfaces every restored entry as \"new\" against remote.\n const local: WorkspaceLocal = {\n ...state.local,\n sync: {\n ...state.local.sync,\n lastPulledSnapshot: null,\n lastPulledSha: null,\n },\n };\n return { next: { synced, local }, changedIds: [id] };\n}\n\nfunction applySnapshotSetMaxBytes(state: WorkspaceState, maxBytes: number): ApplyMutationResult {\n if (maxBytes < 0) maxBytes = 0;\n const ledger = state.local.snapshots;\n const { entries, evictedIds } = evictSnapshotsToCap(ledger.entries, maxBytes);\n const local: WorkspaceLocal = {\n ...state.local,\n snapshots: { entries, maxBytes },\n };\n return { next: { ...state, local }, changedIds: evictedIds };\n}\n\nfunction applyHistoryPurge(state: WorkspaceState, olderThanMs: number): ApplyMutationResult {\n // `olderThanMs` is the cutoff age in milliseconds. Runs whose `startedAt`\n // is older than `now - olderThanMs` get dropped. Pass 0 to clear\n // everything; pass Number.POSITIVE_INFINITY to be a no-op.\n const cutoff = Date.now() - olderThanMs;\n const dropped: string[] = [];\n const requestRuns = state.local.history.requestRuns.filter((r) => {\n const t = Date.parse(r.startedAt);\n if (Number.isFinite(t) && t < cutoff) {\n dropped.push(r.id);\n return false;\n }\n return true;\n });\n const planRuns = state.local.history.planRuns.filter((r) => {\n const t = Date.parse(r.startedAt);\n if (Number.isFinite(t) && t < cutoff) {\n dropped.push(r.id);\n return false;\n }\n return true;\n });\n if (dropped.length === 0) {\n return { next: state, changedIds: [] };\n }\n const local: WorkspaceLocal = {\n ...state.local,\n history: { ...state.local.history, requestRuns, planRuns },\n };\n return { next: { ...state, local }, changedIds: dropped };\n}\n","// Pure workspace-graft logic for the `apicircle.folder/v1` envelope —\n// the bridge between `parseApicircleFolderExport` (which produces a\n// `ParsedApicircleFolderExport` with fresh ids + warnings) and the\n// destination `WorkspaceSynced` it lands in.\n//\n// Three things it does that the parser can't:\n//\n// 1. Uniquify the imported root folder name against the destination\n// parent (mirrors how `importPostmanCollection` wraps the imported\n// tree).\n// 2. Merge dependencies into `globalAssets`. Schemas + GraphQL\n// definitions reuse an existing entry when the name + content match\n// verbatim, so re-importing the same file does not pile up\n// duplicates; otherwise they're added with the parser-minted id.\n// 3. Rewrite cross-entity references (request.bodySchemaId,\n// request.graphqlSchemaId, body.attachment.globalFileAssetId,\n// form-row globalFileAssetId) onto the post-merge ids so the\n// workspace stays internally consistent.\n//\n// Pure — does not depend on IndexedDB, the React store, or any UI\n// helper. The MCP tool, CLI subcommand, and Zustand store all funnel\n// through this same function.\n\nimport type {\n Folder,\n GlobalFileAsset,\n GlobalGraphQL,\n GlobalSchema,\n Request as ApiRequest,\n WorkspaceSynced,\n} from '@apicircle/shared';\nimport type { ParsedApicircleFolderExport } from '../import/apicircleFolder';\n\nexport interface ImportApicircleFolderResult {\n synced: WorkspaceSynced;\n /** Id of the newly-created root folder in the destination workspace. */\n rootFolderId: string;\n /** Final display name (uniquified) of the imported root folder. */\n rootFolderName: string;\n counts: {\n folders: number; // includes the root\n requests: number;\n schemasAdded: number;\n schemasReused: number;\n graphqlAdded: number;\n graphqlReused: number;\n filesAdded: number;\n filesReused: number;\n };\n /**\n * File-asset ids whose metadata landed in `globalAssets.files`\n * without a backing slot (because the export envelope carries\n * metadata only — bytes stay in their Git LFS sidecar). UIs use this\n * to surface a \"re-attach these files\" cue after import.\n */\n filesRequiringReattachment: string[];\n}\n\n/**\n * Graft a parsed API Circle folder export into `synced` under\n * `parentFolderId` (root when `null`). Returns the patched workspace +\n * counts the UI / CLI / MCP can surface.\n */\nexport function importApicircleFolderInto(\n synced: WorkspaceSynced,\n parsed: ParsedApicircleFolderExport,\n parentFolderId: string | null,\n): ImportApicircleFolderResult {\n let cur = synced;\n\n // 1) Merge dependencies — build remap maps from parser-minted id to\n // final destination id. When a content match is found we reuse the\n // existing asset; otherwise we add a fresh entry with the parser's\n // id (which is already collision-free thanks to generateId()).\n const schemaRemap = new Map<string, string>();\n const graphqlRemap = new Map<string, string>();\n const fileRemap = new Map<string, string>();\n let schemasAdded = 0;\n let schemasReused = 0;\n let graphqlAdded = 0;\n let graphqlReused = 0;\n let filesAdded = 0;\n let filesReused = 0;\n const filesRequiringReattachment: string[] = [];\n\n const now = new Date().toISOString();\n\n for (const incoming of parsed.dependencies.schemas) {\n const existing = findMatchingSchema(cur, incoming);\n if (existing) {\n schemaRemap.set(incoming.id, existing.id);\n schemasReused += 1;\n continue;\n }\n cur = mergeGlobalSchema(cur, incoming, now);\n schemaRemap.set(incoming.id, incoming.id);\n schemasAdded += 1;\n }\n for (const incoming of parsed.dependencies.graphql) {\n const existing = findMatchingGraphQL(cur, incoming);\n if (existing) {\n graphqlRemap.set(incoming.id, existing.id);\n graphqlReused += 1;\n continue;\n }\n cur = mergeGlobalGraphQL(cur, incoming, now);\n graphqlRemap.set(incoming.id, incoming.id);\n graphqlAdded += 1;\n }\n for (const incoming of parsed.dependencies.files) {\n const existing = findMatchingFile(cur, incoming);\n if (existing) {\n fileRemap.set(incoming.id, existing.id);\n filesReused += 1;\n continue;\n }\n cur = mergeGlobalFile(cur, incoming, now);\n fileRemap.set(incoming.id, incoming.id);\n filesAdded += 1;\n filesRequiringReattachment.push(incoming.id);\n }\n\n // 2) Insert the root folder (with a uniquified name + the import's auth).\n const rootName = uniquifyFolderName(cur, parentFolderId, parsed.rootFolder.name);\n const root: Folder = {\n id: parsed.rootFolder.id,\n name: rootName,\n parentId: parentFolderId,\n auth: parsed.rootFolder.auth ? { ...parsed.rootFolder.auth } : undefined,\n };\n cur = insertFolder(cur, root, /* attachToTree */ parentFolderId === null);\n\n // 3) Insert subfolders. The parser pinned every parentId on a\n // destination id from the same export, so a single pass suffices.\n for (const f of parsed.subfolders) {\n cur = insertFolder(cur, f, /* attachToTree */ false);\n }\n\n // 4) Insert requests with dependency references rewritten through the\n // merge maps. Schema/GraphQL/file refs were already parser-mapped to\n // the \"incoming.id\"; this pass swaps in the reused-id where a\n // duplicate was detected.\n for (const r of parsed.requests) {\n const rewritten: ApiRequest = {\n ...r,\n bodySchemaId: rewriteRef(r.bodySchemaId, schemaRemap),\n graphqlSchemaId: rewriteRef(r.graphqlSchemaId, graphqlRemap),\n body: rewriteBodyFileRefs(r.body, fileRemap),\n };\n cur = insertRequest(cur, rewritten);\n }\n\n return {\n synced: { ...cur, meta: { ...cur.meta, updatedAt: now } },\n rootFolderId: root.id,\n rootFolderName: rootName,\n counts: {\n folders: parsed.subfolders.length + 1,\n requests: parsed.requests.length,\n schemasAdded,\n schemasReused,\n graphqlAdded,\n graphqlReused,\n filesAdded,\n filesReused,\n },\n filesRequiringReattachment,\n };\n}\n\n// -- internals --------------------------------------------------------------\n\n/**\n * Returns true when `name` is unused for that kind within `parentFolderId`\n * (case-insensitive, whitespace-trimmed). Matches the same check\n * `editorActions.isNameAvailableInFolder` performs — kept inline so this\n * module has no UI dependency.\n */\nfunction isFolderNameAvailable(\n synced: WorkspaceSynced,\n parentFolderId: string | null,\n name: string,\n): boolean {\n const trimmed = name.trim().toLowerCase();\n if (!trimmed) return false;\n for (const node of Object.values(synced.collections.folders)) {\n if (node.parentId !== parentFolderId) continue;\n if (node.name.trim().toLowerCase() === trimmed) return false;\n }\n return true;\n}\n\nfunction uniquifyFolderName(\n synced: WorkspaceSynced,\n parentFolderId: string | null,\n desired: string,\n): string {\n if (isFolderNameAvailable(synced, parentFolderId, desired)) return desired;\n let n = 2;\n while (!isFolderNameAvailable(synced, parentFolderId, `${desired} (${n})`)) {\n n += 1;\n if (n > 999) return `${desired} (${n})`;\n }\n return `${desired} (${n})`;\n}\n\nfunction insertFolder(\n synced: WorkspaceSynced,\n folder: Folder,\n attachToTree: boolean,\n): WorkspaceSynced {\n const folders = { ...synced.collections.folders, [folder.id]: folder };\n const tree = attachToTree\n ? {\n ...synced.collections.tree,\n children: [...synced.collections.tree.children, { kind: 'folder' as const, id: folder.id }],\n }\n : synced.collections.tree;\n return {\n ...synced,\n collections: { ...synced.collections, folders, tree },\n };\n}\n\nfunction insertRequest(synced: WorkspaceSynced, request: ApiRequest): WorkspaceSynced {\n return {\n ...synced,\n collections: {\n ...synced.collections,\n requests: { ...synced.collections.requests, [request.id]: request },\n },\n };\n}\n\nfunction withGlobalAssets(synced: WorkspaceSynced): WorkspaceSynced['globalAssets'] {\n return synced.globalAssets ?? { schemas: {}, graphql: {}, files: {} };\n}\n\nfunction findMatchingSchema(synced: WorkspaceSynced, candidate: GlobalSchema): GlobalSchema | null {\n const ga = withGlobalAssets(synced);\n for (const existing of Object.values(ga.schemas)) {\n if (existing.name === candidate.name && existing.schema === candidate.schema) {\n return existing;\n }\n }\n return null;\n}\n\nfunction findMatchingGraphQL(\n synced: WorkspaceSynced,\n candidate: GlobalGraphQL,\n): GlobalGraphQL | null {\n const ga = withGlobalAssets(synced);\n for (const existing of Object.values(ga.graphql)) {\n if (\n existing.name === candidate.name &&\n existing.kind === candidate.kind &&\n existing.source === candidate.source\n ) {\n return existing;\n }\n }\n return null;\n}\n\nfunction findMatchingFile(\n synced: WorkspaceSynced,\n candidate: GlobalFileAsset,\n): GlobalFileAsset | null {\n const ga = withGlobalAssets(synced);\n const files = ga.files ?? {};\n for (const existing of Object.values(files)) {\n if (\n existing.name === candidate.name &&\n existing.filename === candidate.filename &&\n existing.size === candidate.size\n ) {\n return existing;\n }\n }\n return null;\n}\n\nfunction mergeGlobalSchema(\n synced: WorkspaceSynced,\n schema: GlobalSchema,\n now: string,\n): WorkspaceSynced {\n const ga = withGlobalAssets(synced);\n return {\n ...synced,\n globalAssets: {\n ...ga,\n schemas: { ...ga.schemas, [schema.id]: { ...schema, updatedAt: now } },\n },\n };\n}\n\nfunction mergeGlobalGraphQL(\n synced: WorkspaceSynced,\n graphql: GlobalGraphQL,\n now: string,\n): WorkspaceSynced {\n const ga = withGlobalAssets(synced);\n return {\n ...synced,\n globalAssets: {\n ...ga,\n graphql: { ...ga.graphql, [graphql.id]: { ...graphql, updatedAt: now } },\n },\n };\n}\n\nfunction mergeGlobalFile(\n synced: WorkspaceSynced,\n file: GlobalFileAsset,\n now: string,\n): WorkspaceSynced {\n const ga = withGlobalAssets(synced);\n const files = ga.files ?? {};\n return {\n ...synced,\n globalAssets: {\n ...ga,\n files: { ...files, [file.id]: { ...file, updatedAt: now } },\n },\n };\n}\n\nfunction rewriteRef(\n value: string | null | undefined,\n remap: Map<string, string>,\n): string | null | undefined {\n if (value === null || value === undefined) return value;\n return remap.get(value) ?? value;\n}\n\nfunction rewriteBodyFileRefs(\n body: ApiRequest['body'],\n remap: Map<string, string>,\n): ApiRequest['body'] {\n if (body.type === 'binary') {\n if (!body.attachment) return body;\n const rewritten = rewriteRef(body.attachment.globalFileAssetId, remap);\n if (rewritten === body.attachment.globalFileAssetId) return body;\n return {\n ...body,\n attachment: { ...body.attachment, globalFileAssetId: rewritten },\n };\n }\n if (body.type === 'form-data' && body.formRows) {\n let mutated = false;\n const next = body.formRows.map((row) => {\n if (row.kind !== 'file') return row;\n const rewritten = rewriteRef(row.globalFileAssetId, remap);\n if (rewritten === row.globalFileAssetId) return row;\n mutated = true;\n return { ...row, globalFileAssetId: rewritten };\n });\n return mutated ? { ...body, formRows: next } : body;\n }\n return body;\n}\n","import type {\n Environment,\n EnvPriorityRef,\n ExecutionPlan,\n PlanRun,\n Request as ApiRequest,\n RequestAuth,\n RequestRun,\n WorkspaceLocal,\n WorkspaceSynced,\n} from '@apicircle/shared';\nimport { envPriorityKey, generateId, RUN_BODY_PREVIEW_LIMIT } from '@apicircle/shared';\nimport { mergeRequestOverride } from '../linked/requestOverride';\nimport { executeRequest, type ExecutionResult } from '../request/executeRequest';\nimport type { AttachmentResolver } from '../request/buildRequest';\nimport { runAssertions, type AssertionResult } from '../assertions/runAssertions';\nimport { extractContext } from '../environment/extractContext';\nimport { resolveInheritedAuth } from '../request/resolveInheritedAuth';\nimport { buildScope, resolveString } from '../environment/variableResolver';\nimport type { WorkspaceState } from './patches';\n\n// =============================================================================\n// runPlan — the headless execution-plan runner.\n//\n// The browser/desktop store has its own `runPlan` (workspaceStore.ts) wired to\n// IndexedDB secret crypto, AbortControllers, and live UI state. This one is the\n// runtime-agnostic engine: it takes a plain `WorkspaceState`, executes a plan's\n// steps with `executeRequest`, and returns the `PlanRun` plus the workspace\n// with history + refreshed tokens folded in. The CLI (`apicircle run`) drives\n// it; a hosted runtime or the MCP host could too.\n//\n// Secrets: encrypted env-var ciphertext is never decrypted here. Callers supply\n// plaintext keyed by `secretKeyId` (the CLI sources these from\n// `APICIRCLE_SECRET_<id>` / `--secrets`). An encrypted var with no supplied\n// value is omitted from scope, so `{{VAR}}` surfaces as an unresolved\n// placeholder rather than leaking ciphertext onto the wire.\n// =============================================================================\n\n// History buffer caps — mirror the store's circular-buffer behaviour so a CLI\n// that runs plans repeatedly doesn't grow workspace.local.json unbounded.\nconst MAX_REQUEST_RUNS = 500;\nconst MAX_PLAN_RUNS = 200;\n\n/**\n * Best-known identity of whoever launched a plan run. Recorded for display\n * and handed to the `authorize` hook. `unknown` is the headless default when\n * no GitHub session or OS user can be determined.\n */\nexport interface RunActor {\n kind: 'github' | 'os' | 'unknown';\n /** GitHub login, OS username, or 'unknown'. */\n name: string;\n}\n\nexport const ANONYMOUS_ACTOR: RunActor = { kind: 'unknown', name: 'unknown' };\n\n/**\n * Thrown by an `authorize` hook to deny a run. `runPlan` lets it propagate\n * untouched so callers (the CLI) can map it to a distinct exit code. Today no\n * built-in hook throws it — it exists for the per-user run restrictions that\n * are planned but not yet designed.\n */\nexport class PlanRunDeniedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PlanRunDeniedError';\n }\n}\n\n/** Context handed to the `authorize` hook before any HTTP request fires. */\nexport interface PlanRunAuthorizationContext {\n planId: string;\n plan: ExecutionPlan;\n actor: RunActor;\n state: WorkspaceState;\n}\n\nexport interface RunPlanOptions {\n /** Evaluate the per-request assertions. Defaults to `true`. */\n withAssertions?: boolean;\n /**\n * Halt the run after the first failed step — including missing / linked\n * steps — regardless of the plan's own `stopOnAssertionFailure`. This is\n * the `apicircle run --bail` behaviour. Defaults to `false`.\n */\n bail?: boolean;\n /**\n * Name of a local environment to layer on top of the run's env priority\n * order (highest precedence). Used by `apicircle run --env <name>`. A name\n * with no matching environment simply contributes nothing.\n */\n env?: string;\n /** Injected fetch — defaults to `globalThis.fetch`. Tests pass a stub. */\n fetchImpl?: typeof fetch;\n /** Aborts the run between steps and the in-flight request. */\n signal?: AbortSignal;\n /** Per-request hard timeout in ms. `null` disables. Defaults to executeRequest's 30s. */\n timeoutMs?: number | null;\n /** Resolver for local and linked attachment bytes used by file/binary bodies. */\n resolveAttachment?: AttachmentResolver;\n /** Plaintext secret values keyed by `secretKeyId`, for encrypted env vars. */\n secretsById?: Record<string, string>;\n /** Identity of whoever launched the run. Defaults to {@link ANONYMOUS_ACTOR}. */\n actor?: RunActor;\n /**\n * Authorization seam. Called once, before the first request, with the\n * resolved plan + actor. Throw (ideally {@link PlanRunDeniedError}) to deny\n * the run. Omit for an unrestricted run — the current default everywhere.\n */\n authorize?: (ctx: PlanRunAuthorizationContext) => void | Promise<void>;\n /** Invoked after each step settles — lets a CLI stream progress live. */\n onStep?: (step: PlanStepResult) => void;\n}\n\nexport interface PlanStepResult {\n /** Index into `plan.steps` — stable even when steps are skipped. */\n stepIndex: number;\n requestId: string;\n requestName: string;\n requestMethod: string;\n /** True when the step was skipped via `enabled: false`. */\n skipped: boolean;\n /** Execution result, or `null` for a skipped / unresolvable step. */\n result: ExecutionResult | null;\n assertionResults: AssertionResult[];\n /** `{{VAR}}` placeholders that didn't resolve in url / headers / query / body / auth. */\n missingVariables: string[];\n /** True when the request succeeded and (if enabled) every assertion passed. */\n passed: boolean;\n /** Set when the step couldn't run at all (missing / linked / unsupported). */\n error?: string;\n}\n\nexport interface RunPlanResult {\n planRun: PlanRun;\n /** One entry per step, including skipped ones (in `plan.steps` order). */\n steps: PlanStepResult[];\n /**\n * Workspace with the plan-run + request-runs appended to history and any\n * refreshed OAuth2 tokens persisted onto `synced`. Save this back to disk.\n */\n nextState: WorkspaceState;\n /** True when every executed (non-skipped) step passed. Vacuously true when none ran. */\n passed: boolean;\n}\n\nexport type ResolvePlanRefResult =\n | { ok: true; id: string; plan: ExecutionPlan }\n | { ok: false; error: string; available: string[] };\n\n/**\n * Resolve a user-supplied plan reference (a plan id, or a plan name) against a\n * workspace. Name matching is case-insensitive and trimmed; an ambiguous name\n * (two plans share it) is rejected so the caller can ask for an id instead.\n */\nexport function resolvePlanRef(synced: WorkspaceSynced, ref: string): ResolvePlanRefResult {\n const plans = synced.executionPlans ?? {};\n const entries = Object.entries(plans);\n const available = entries.map(([, p]) => p.name);\n if (entries.length === 0) {\n return { ok: false, error: 'This workspace has no execution plans.', available };\n }\n const direct = plans[ref];\n if (direct) return { ok: true, id: ref, plan: direct };\n\n const wanted = ref.trim().toLowerCase();\n const byName = entries.filter(([, p]) => p.name.trim().toLowerCase() === wanted);\n if (byName.length === 1) return { ok: true, id: byName[0][0], plan: byName[0][1] };\n if (byName.length > 1) {\n return {\n ok: false,\n error: `Plan name \"${ref}\" is ambiguous — ${byName.length} plans share it. Pass the plan id instead.`,\n available,\n };\n }\n return { ok: false, error: `No plan named \"${ref}\" in this workspace.`, available };\n}\n\nfunction lookupPlanStepRequest(\n step: { requestId: string; linkedWorkspaceId?: string },\n synced: WorkspaceSynced,\n local: WorkspaceLocal,\n): {\n request: ApiRequest | null;\n linkedEnvironments?: WorkspaceSynced['environments'];\n linkedFolders?: WorkspaceSynced['collections']['folders'];\n linkedGlobalAssets?: WorkspaceSynced['globalAssets'];\n error?: string;\n} {\n if (!step.linkedWorkspaceId) {\n const request = synced.collections.requests[step.requestId];\n return request\n ? { request }\n : { request: null, error: 'Request no longer exists in workspace.' };\n }\n\n const link = synced.linkedWorkspaces[step.linkedWorkspaceId];\n if (!link) return { request: null, error: 'Linked workspace was unlinked.' };\n\n const snapshot = local.linkedCollections[step.linkedWorkspaceId];\n if (!snapshot) {\n return {\n request: null,\n error: `No cached snapshot for \"${link.name}\". Refresh the link before running this plan.`,\n };\n }\n\n const baseRequest = snapshot.collections.requests[step.requestId];\n if (!baseRequest) {\n return {\n request: null,\n error: `Request not present in the cached snapshot of \"${link.name}\".`,\n };\n }\n\n const overrideKey = `${step.linkedWorkspaceId}:${step.requestId}`;\n const override = synced.linkedOverrides.requests[overrideKey];\n const request = override ? mergeRequestOverride(baseRequest, override.patch) : baseRequest;\n return {\n request,\n linkedEnvironments: applyEnvironmentOverrides(\n snapshot.environments,\n step.linkedWorkspaceId,\n synced,\n ),\n linkedFolders: snapshot.collections.folders,\n linkedGlobalAssets: snapshot.globalAssets,\n };\n}\n\nfunction applyEnvironmentOverrides(\n source: WorkspaceSynced['environments'],\n linkedWorkspaceId: string,\n synced: WorkspaceSynced,\n): WorkspaceSynced['environments'] {\n const overrides = Object.values(synced.linkedOverrides.environmentVars).filter(\n (override) => override.linkedWorkspaceId === linkedWorkspaceId,\n );\n if (overrides.length === 0) return source;\n\n const items: WorkspaceSynced['environments']['items'] = {};\n for (const [envName, env] of Object.entries(source.items)) {\n const envOverrides = overrides.filter((override) => override.envName === envName);\n if (envOverrides.length === 0) {\n items[envName] = env;\n continue;\n }\n\n const removed = new Set(\n envOverrides.filter((override) => override.removed).map((override) => override.varKey),\n );\n const replaceMap = new Map<string, (typeof envOverrides)[number]>();\n for (const override of envOverrides) {\n if (!override.removed) replaceMap.set(override.varKey, override);\n }\n const variables: Environment['variables'] = [];\n const seenKeys = new Set<string>();\n for (const variable of env.variables) {\n if (removed.has(variable.key)) continue;\n const override = replaceMap.get(variable.key);\n if (override) {\n variables.push({\n key: variable.key,\n value: override.value ?? variable.value,\n encrypted: override.encrypted ?? variable.encrypted,\n ...(override.secretKeyId !== undefined\n ? { secretKeyId: override.secretKeyId }\n : variable.secretKeyId !== undefined\n ? { secretKeyId: variable.secretKeyId }\n : {}),\n });\n } else {\n variables.push(variable);\n }\n seenKeys.add(variable.key);\n }\n\n for (const override of envOverrides) {\n if (override.removed || seenKeys.has(override.varKey)) continue;\n variables.push({\n key: override.varKey,\n value: override.value ?? '',\n encrypted: override.encrypted ?? false,\n ...(override.secretKeyId !== undefined ? { secretKeyId: override.secretKeyId } : {}),\n });\n }\n items[envName] = { ...env, variables };\n }\n return { ...source, items };\n}\n\n/**\n * Execute every enabled step of `planId` against the workspace. Never throws\n * for HTTP / assertion failures — those land in the returned step results.\n * Throws only for a missing plan or a denial from the `authorize` hook.\n */\nexport async function runPlan(\n state: WorkspaceState,\n planId: string,\n opts: RunPlanOptions = {},\n): Promise<RunPlanResult> {\n const plan = state.synced.executionPlans?.[planId];\n if (!plan) throw new Error(`Plan \"${planId}\" not found in workspace`);\n\n const actor = opts.actor ?? ANONYMOUS_ACTOR;\n if (opts.authorize) {\n await opts.authorize({ planId, plan, actor, state });\n }\n\n const withAssertions = opts.withAssertions ?? true;\n const bail = opts.bail ?? false;\n // The plan's own stop flag only halts on a *failed assertion*; --bail halts\n // on any failed step. Both feed the post-step break below.\n const stopOnAssertion = withAssertions && (plan.stopOnAssertionFailure ?? false);\n const secretsById = opts.secretsById ?? {};\n const flatEnvs = buildEnvMaps(state.synced, secretsById, state.local);\n const secretsByLabel = buildSecretsByLabel(state.synced, secretsById);\n\n // Env priority for this run: the plan's overlay (or the workspace order),\n // with an optional `--env` environment layered on top at highest precedence.\n const baseRefs =\n plan.envPriorityOrder.length > 0\n ? plan.envPriorityOrder\n : state.synced.environments.priorityOrder;\n const envRefs: readonly EnvPriorityRef[] = opts.env\n ? [{ kind: 'local', name: opts.env }, ...baseRefs]\n : baseRefs;\n\n const startedAt = new Date().toISOString();\n const planRunId = generateId();\n const t0 = Date.now();\n\n const stepRecords: PlanRun['steps'] = [];\n const newRequestRuns: RequestRun[] = [];\n const stepResults: PlanStepResult[] = [];\n\n // Rolling state across steps: extracted context vars feed the next step's\n // resolver; refreshed OAuth2 tokens replace the request's stored auth.\n let globalContext = { ...state.local.globalContext };\n let requests = state.synced.collections.requests;\n const tokenRefreshes = new Map<string, RequestAuth>();\n\n const record = (step: PlanStepResult): void => {\n stepResults.push(step);\n opts.onStep?.(step);\n };\n\n for (let i = 0; i < plan.steps.length; i++) {\n const step = plan.steps[i];\n\n // Disabled steps stay in the plan but contribute nothing to the run —\n // no request-run, no PlanRun.steps entry. Matches the store's runPlan.\n if (step.enabled === false) {\n const req = requests[step.requestId];\n record({\n stepIndex: i,\n requestId: step.requestId,\n requestName: req?.name ?? '(unknown request)',\n requestMethod: req?.method ?? '—',\n skipped: true,\n result: null,\n assertionResults: [],\n missingVariables: [],\n passed: true,\n });\n continue;\n }\n\n if (opts.signal?.aborted) break;\n\n const lookup = lookupPlanStepRequest(step, state.synced, state.local);\n const baseRequest = lookup.request;\n if (!baseRequest) {\n const runId = generateId();\n const error = lookup.error ?? 'Request no longer exists in workspace.';\n newRequestRuns.push(orphanRun(runId, step.requestId, error));\n stepRecords.push({ requestRunId: runId, passed: false });\n record({\n stepIndex: i,\n requestId: step.requestId,\n requestName: step.linkedWorkspaceId ? '(linked request)' : '(missing request)',\n requestMethod: '—',\n skipped: false,\n result: null,\n assertionResults: [],\n missingVariables: [],\n passed: false,\n error,\n });\n if (bail) break;\n continue;\n }\n\n const resolveSynced: WorkspaceSynced =\n step.linkedWorkspaceId && lookup.linkedEnvironments\n ? {\n ...state.synced,\n environments: lookup.linkedEnvironments,\n globalAssets: lookup.linkedGlobalAssets ?? state.synced.globalAssets,\n collections: {\n ...state.synced.collections,\n folders: lookup.linkedFolders ?? {},\n },\n }\n : state.synced;\n const stepEnvRefs =\n step.linkedWorkspaceId && plan.envPriorityOrder.length === 0\n ? (lookup.linkedEnvironments?.priorityOrder ?? envRefs)\n : envRefs;\n\n const { request: resolved, missing } = resolveRequest(\n baseRequest,\n resolveSynced,\n plan,\n stepEnvRefs,\n globalContext,\n step.linkedWorkspaceId ? buildEnvMaps(resolveSynced, secretsById, state.local) : flatEnvs,\n secretsByLabel,\n );\n\n const result = await executeRequest(resolved, {\n fetchImpl: opts.fetchImpl,\n signal: opts.signal,\n timeoutMs: opts.timeoutMs,\n resolveAttachment: opts.resolveAttachment,\n authOptions: {\n onTokenRefreshed: (refreshedAuth) => {\n if (!step.linkedWorkspaceId) tokenRefreshes.set(baseRequest.id, refreshedAuth);\n },\n },\n });\n\n const assertionResults = withAssertions ? runAssertions(baseRequest.assertions, result) : [];\n const passed = result.ok && (!withAssertions || assertionResults.every((a) => a.passed));\n const requestRun = buildRequestRun(resolved, result, assertionResults);\n newRequestRuns.push(requestRun);\n stepRecords.push({ requestRunId: requestRun.id, passed });\n record({\n stepIndex: i,\n requestId: baseRequest.id,\n requestName: baseRequest.name,\n requestMethod: baseRequest.method,\n skipped: false,\n result,\n assertionResults,\n missingVariables: missing,\n passed,\n });\n\n // Carry extracted context vars into the rolling scope for the next step.\n if (baseRequest.extractions.length > 0) {\n const { extracted } = extractContext(result, baseRequest.extractions);\n globalContext = { ...globalContext, ...extracted };\n }\n\n // Fold a refreshed token back into `requests` so a later step reusing the\n // same request sees the fresh access token instead of re-refreshing.\n const refreshed = step.linkedWorkspaceId ? undefined : tokenRefreshes.get(baseRequest.id);\n if (refreshed) {\n requests = {\n ...requests,\n [baseRequest.id]: { ...requests[baseRequest.id], auth: refreshed },\n };\n }\n\n if ((bail || stopOnAssertion) && !passed) break;\n }\n\n const planRun: PlanRun = {\n id: planRunId,\n planId,\n startedAt,\n durationMs: Date.now() - t0,\n withAssertions,\n steps: stepRecords,\n };\n\n // Newest-first history, same convention the store uses. Request-runs are\n // reversed so the last step to run sits at index 0.\n const requestRuns = [...newRequestRuns]\n .reverse()\n .concat(state.local.history.requestRuns)\n .slice(0, MAX_REQUEST_RUNS);\n const planRuns = [planRun, ...state.local.history.planRuns].slice(0, MAX_PLAN_RUNS);\n\n const nextState: WorkspaceState = {\n synced:\n tokenRefreshes.size > 0\n ? {\n ...state.synced,\n collections: { ...state.synced.collections, requests },\n meta: { ...state.synced.meta, updatedAt: new Date().toISOString() },\n }\n : state.synced,\n local: {\n ...state.local,\n globalContext,\n history: { ...state.local.history, requestRuns, planRuns },\n },\n };\n\n const executed = stepResults.filter((s) => !s.skipped);\n const passed = executed.every((s) => s.passed);\n\n return { planRun, steps: stepResults, nextState, passed };\n}\n\n// ---------------------------------------------------------------------------\n// variable resolution (headless — no IndexedDB / WebCrypto)\n// ---------------------------------------------------------------------------\n\n/**\n * Flatten the workspace's local environments into the `envPriorityKey`-keyed\n * map `buildScope` expects. Encrypted vars are substituted with the supplied\n * plaintext; an encrypted var with no supplied secret is omitted so the\n * `{{VAR}}` reference surfaces as unresolved instead of leaking ciphertext.\n */\nfunction buildEnvMaps(\n synced: WorkspaceSynced,\n secretsById: Record<string, string>,\n local?: WorkspaceLocal,\n): Record<string, Record<string, string>> {\n const flat: Record<string, Record<string, string>> = {};\n for (const [name, env] of Object.entries(synced.environments.items)) {\n const vars: Record<string, string> = {};\n for (const v of env.variables) {\n if (!v.key) continue;\n if (v.encrypted) {\n const supplied = v.secretKeyId ? secretsById[v.secretKeyId] : undefined;\n if (supplied === undefined) continue;\n vars[v.key] = supplied;\n } else {\n vars[v.key] = v.value;\n }\n }\n flat[envPriorityKey({ kind: 'local', name })] = vars;\n }\n if (local) {\n for (const [linkId, snapshot] of Object.entries(local.linkedCollections)) {\n const overridden = applyEnvironmentOverrides(snapshot.environments, linkId, synced);\n for (const [envName, env] of Object.entries(overridden.items)) {\n const vars: Record<string, string> = {};\n for (const variable of env.variables) {\n if (!variable.key) continue;\n if (variable.encrypted) {\n const supplied = variable.secretKeyId ? secretsById[variable.secretKeyId] : undefined;\n if (supplied === undefined) continue;\n vars[variable.key] = supplied;\n } else {\n vars[variable.key] = variable.value;\n }\n }\n flat[envPriorityKey({ kind: 'linked', linkedWorkspaceId: linkId, envName })] = vars;\n }\n }\n }\n return flat;\n}\n\n/** Project supplied secrets onto their human labels for direct `{{Label}}` refs. */\nfunction buildSecretsByLabel(\n synced: WorkspaceSynced,\n secretsById: Record<string, string>,\n): Record<string, string> {\n const meta = synced.secretKeys ?? {};\n const byLabel: Record<string, string> = {};\n for (const [id, value] of Object.entries(secretsById)) {\n const label = meta[id]?.label;\n if (label) byLabel[label] = value;\n }\n return byLabel;\n}\n\n/**\n * Interpolate `{{var}}` placeholders across a request's url, headers, query,\n * body, and auth fields. Resolver precedence (highest first): per-request\n * contextVars → plan variables → rolling globalContext → env priority list →\n * secret labels. Path params and cookies are left verbatim — same as the\n * store's `resolveRequest`.\n */\nfunction resolveRequest(\n request: ApiRequest,\n synced: WorkspaceSynced,\n plan: ExecutionPlan,\n envRefs: readonly EnvPriorityRef[],\n globalContext: Record<string, string>,\n flatEnvs: Record<string, Record<string, string>>,\n secretsByLabel: Record<string, string>,\n): { request: ApiRequest; missing: string[] } {\n // contextVars layering (low → high): globalContext, plan vars, request vars.\n const ctxMap: Record<string, string> = { ...globalContext };\n for (const v of plan.variables ?? []) {\n if (v.key) ctxMap[v.key] = v.value;\n }\n for (const v of request.contextVars) {\n if (v.key) ctxMap[v.key] = v.value;\n }\n\n const scope = buildScope({\n contextVars: Object.entries(ctxMap).map(([key, value]) => ({ key, value })),\n environments: flatEnvs,\n activeEnvName: null,\n priorityOrder: envRefs.map(envPriorityKey),\n secrets: secretsByLabel,\n });\n\n const missing = new Set<string>();\n const sub = (input: string): string => {\n const { value, missing: m } = resolveString(input, scope);\n for (const name of m) missing.add(name);\n return value;\n };\n\n const url = sub(request.url);\n const headers = request.headers.map((h) => ({\n ...h,\n key: sub(h.key),\n value: sub(h.value),\n }));\n const query = request.query.map((q) => ({\n ...q,\n key: sub(q.key),\n value: sub(q.value),\n }));\n\n let body = request.body;\n if (\n body.type === 'json' ||\n body.type === 'text' ||\n body.type === 'xml' ||\n body.type === 'graphql' ||\n body.type === 'urlencoded'\n ) {\n body = { ...body, content: sub(body.content) };\n } else if (body.type === 'form-data' && body.formRows) {\n body = {\n ...body,\n formRows: body.formRows.map((row) =>\n row.kind === 'text'\n ? { ...row, key: sub(row.key), value: sub(row.value) }\n : { ...row, key: sub(row.key) },\n ),\n };\n }\n\n const inheritedAuth = resolveInheritedAuth({\n requestAuth: request.auth ?? { type: 'none' },\n folderId: request.folderId,\n folders: synced.collections.folders,\n });\n const auth = resolveAuthVariables(inheritedAuth, sub);\n\n return { request: { ...request, url, headers, query, body, auth }, missing: [...missing] };\n}\n\n/** Interpolate `{{var}}` in every string-valued auth field; `type` is left verbatim. */\nfunction resolveAuthVariables(auth: RequestAuth, sub: (input: string) => string): RequestAuth {\n const resolved: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(auth)) {\n resolved[key] = key !== 'type' && typeof value === 'string' ? sub(value) : value;\n }\n return resolved as unknown as RequestAuth;\n}\n\n// ---------------------------------------------------------------------------\n// RequestRun construction\n// ---------------------------------------------------------------------------\n\nfunction orphanRun(id: string, requestId: string, error: string): RequestRun {\n return {\n id,\n requestId,\n startedAt: new Date().toISOString(),\n durationMs: 0,\n status: null,\n statusText: '',\n ok: false,\n error,\n url: '',\n method: '',\n requestHeaders: {},\n requestBodyPreview: null,\n responseHeaders: {},\n responseBodyPreview: '',\n responseBodyKind: 'empty',\n responseTruncated: false,\n assertions: [],\n };\n}\n\nfunction buildRequestRun(\n resolved: ApiRequest,\n result: ExecutionResult,\n assertions: RequestRun['assertions'],\n): RequestRun {\n const { preview, truncated } = clampPreview(result.body ?? '');\n return {\n id: generateId(),\n requestId: resolved.id,\n startedAt: result.startedAt,\n durationMs: result.durationMs,\n status: result.status,\n statusText: result.statusText,\n ok: result.ok,\n error: result.error,\n url: redactUrlCredentials(result.url),\n method: result.method,\n requestHeaders: composeWireHeaders(resolved.headers),\n requestBodyPreview: previewRequestBody(resolved),\n responseHeaders: result.headers,\n responseBodyPreview: preview,\n responseBodyKind: result.bodyKind,\n responseTruncated: truncated,\n assertions,\n };\n}\n\nfunction clampPreview(value: string): { preview: string; truncated: boolean } {\n if (value.length <= RUN_BODY_PREVIEW_LIMIT) return { preview: value, truncated: false };\n return { preview: value.slice(0, RUN_BODY_PREVIEW_LIMIT), truncated: true };\n}\n\n/** Strip `user:pass@` userinfo before a URL enters persisted history. */\nfunction redactUrlCredentials(url: string): string {\n try {\n const parsed = new URL(url);\n if (parsed.username || parsed.password) {\n parsed.username = '';\n parsed.password = '';\n return parsed.toString();\n }\n } catch {\n /* not a parseable URL — leave it alone */\n }\n return url;\n}\n\nfunction composeWireHeaders(\n rows: ReadonlyArray<{ key: string; value: string; enabled: boolean }>,\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const row of rows) {\n if (!row.enabled) continue;\n const k = row.key.trim();\n if (k) out[k] = row.value;\n }\n return out;\n}\n\nfunction previewRequestBody(req: ApiRequest): string | null {\n const body = req.body;\n if (\n body.type === 'json' ||\n body.type === 'text' ||\n body.type === 'xml' ||\n body.type === 'urlencoded'\n ) {\n return clampPreview(body.content ?? '').preview;\n }\n if (body.type === 'graphql') {\n const envelope = JSON.stringify(\n { query: body.content ?? '', variables: body.variables ?? '' },\n null,\n 2,\n );\n return clampPreview(envelope).preview;\n }\n return null;\n}\n","/**\n * Token Oriented Object Notation (TOON) encoder.\n *\n * Compact, indentation-based serialization that drops most of JSON's\n * structural noise (quotes around keys/values where unambiguous, braces,\n * commas, colons-with-spaces). Optimized for LLM token budgets and\n * eyeballing — typical JSON shrinks 25–50% when re-encoded.\n *\n * Two encoding shapes are produced:\n *\n * - **Tabular** for arrays of homogeneous flat objects (common API list\n * payloads). The header lists keys once, the rows list values once:\n *\n * users[2]{id,name,active}:\n * 1,Alice,true\n * 2,Bob,false\n *\n * - **Indented** for everything else:\n *\n * meta:\n * page: 1\n * items:\n * - id: 1\n * name: Alice\n *\n * Strings are quoted only when they contain characters that would otherwise\n * break the line shape (commas, colons, leading/trailing whitespace, etc.).\n * Output is intentionally lossless for round-tripping primitive types — but\n * a TOON decoder is out of scope for this module: the encoder exists so the\n * UI can show an \"X% smaller\" hint and an optional preview.\n */\n\ntype Json = string | number | boolean | null | Json[] | { [key: string]: Json };\n\nconst INDENT = ' ';\n\nfunction isFlatPrimitive(v: unknown): v is string | number | boolean | null {\n return v === null || ['string', 'number', 'boolean'].includes(typeof v);\n}\n\nfunction isFlatObject(v: unknown): v is Record<string, string | number | boolean | null> {\n if (v === null || typeof v !== 'object' || Array.isArray(v)) return false;\n return Object.values(v).every(isFlatPrimitive);\n}\n\n/**\n * An array is \"tabular\" if it has ≥ 2 entries, all entries are flat\n * objects, and they share the same key set. Single-row arrays fall back\n * to the indented form because the header overhead doesn't pay off.\n */\nfunction tabularKeys(arr: unknown[]): string[] | null {\n if (arr.length < 2) return null;\n if (!arr.every(isFlatObject)) return null;\n const keys = Object.keys(arr[0]);\n if (keys.length === 0) return null;\n for (let i = 1; i < arr.length; i++) {\n const rowKeys = Object.keys(arr[i]);\n if (rowKeys.length !== keys.length) return null;\n for (const k of keys) if (!(k in (arr[i] as object))) return null;\n }\n return keys;\n}\n\nconst SAFE_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;\nconst NEEDS_QUOTING = /[,:\\n\\r\"]|^\\s|\\s$/;\n\nfunction encodeKey(k: string): string {\n return SAFE_KEY.test(k) ? k : JSON.stringify(k);\n}\n\nfunction encodeScalar(v: string | number | boolean | null): string {\n if (v === null) return 'null';\n if (typeof v === 'boolean' || typeof v === 'number') return String(v);\n // Reserved word collisions — quote so re-decode is unambiguous.\n if (v === 'null' || v === 'true' || v === 'false' || v === '') return JSON.stringify(v);\n if (NEEDS_QUOTING.test(v)) return JSON.stringify(v);\n return v;\n}\n\nfunction encodeRowValue(v: string | number | boolean | null): string {\n // Tabular rows are comma-separated; quoting rules are stricter.\n return encodeScalar(v);\n}\n\nfunction encodeNode(value: Json, indent: string): string {\n if (isFlatPrimitive(value)) return encodeScalar(value);\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]';\n const keys = tabularKeys(value);\n if (keys) {\n const header = `[${value.length}]{${keys.map(encodeKey).join(',')}}:`;\n const rows = value.map(\n (row) =>\n indent +\n INDENT +\n keys.map((k) => encodeRowValue((row as Record<string, Json>)[k] as never)).join(','),\n );\n return `${header}\\n${rows.join('\\n')}`;\n }\n return value\n .map((item) => {\n if (isFlatPrimitive(item) || Array.isArray(item)) {\n return `${indent}- ${encodeNode(item, indent + INDENT)}`;\n }\n // Object child: first line goes after `- `, rest stays where the\n // recursive call put it (already at indent + INDENT, aligned under\n // the bullet). The first line carries an extra indent we need to\n // strip so `- ` itself stands in for those two columns.\n const encoded = encodeNode(item, indent + INDENT);\n const innerIndent = indent + INDENT;\n const lines = encoded.split('\\n');\n const [first, ...rest] = lines;\n const firstStripped = first.startsWith(innerIndent)\n ? first.slice(innerIndent.length)\n : first;\n return [`${indent}- ${firstStripped}`, ...rest].join('\\n');\n })\n .join('\\n');\n }\n // Object.\n const entries = Object.entries(value);\n if (entries.length === 0) return '{}';\n return entries\n .map(([k, v]) => {\n if (isFlatPrimitive(v)) return `${indent}${encodeKey(k)}: ${encodeScalar(v)}`;\n if (Array.isArray(v) && v.length === 0) return `${indent}${encodeKey(k)}: []`;\n if (!Array.isArray(v) && typeof v === 'object' && Object.keys(v).length === 0) {\n return `${indent}${encodeKey(k)}: {}`;\n }\n // Tabular array → header sits on the same line; rows below.\n if (Array.isArray(v)) {\n const keys = tabularKeys(v);\n if (keys) {\n const header = `${indent}${encodeKey(k)}[${v.length}]{${keys.map(encodeKey).join(',')}}:`;\n const rows = v.map(\n (row) =>\n indent +\n INDENT +\n keys\n .map((rk) => encodeRowValue((row as Record<string, Json>)[rk] as never))\n .join(','),\n );\n return `${header}\\n${rows.join('\\n')}`;\n }\n }\n const child = encodeNode(v, indent + INDENT);\n return `${indent}${encodeKey(k)}:\\n${child}`;\n })\n .join('\\n');\n}\n\nexport function toToon(value: Json): string {\n if (isFlatPrimitive(value)) return encodeScalar(value);\n if (Array.isArray(value) && value.length === 0) return '[]';\n if (!Array.isArray(value) && typeof value === 'object' && Object.keys(value).length === 0) {\n return '{}';\n }\n return encodeNode(value, '');\n}\n","/**\n * Minimal block-style YAML encoder. Sibling of `toon.ts` — same job\n * (compact, indentation-based representation of JSON-shaped data) but\n * sticks to standard YAML syntax instead of TOON's tabular shorthand,\n * so the user can compare the two.\n *\n * For arrays of homogeneous flat objects YAML still emits one list item\n * per row (unlike TOON's `name[count]{cols}: rows` table), so YAML is\n * usually slightly larger than TOON on tabular payloads but identical or\n * very close on nested ones. Keeping both gives the user the full picture\n * when deciding which format to feed downstream.\n */\n\ntype Json = string | number | boolean | null | Json[] | { [key: string]: Json };\n\nconst INDENT = ' ';\n\nconst SAFE_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;\n// YAML's plain scalar restrictions: leading/trailing whitespace, special\n// indicators (`,`, `[`, `]`, `{`, `}`, `&`, `*`, `!`, `|`, `>`, `'`, `\"`,\n// `#`, `%`, `@`, `\\``, `?`, `:` followed by space, leading `-`/space).\n// We use a permissive screen — anything ambiguous gets JSON-quoted, which\n// is valid YAML.\nconst NEEDS_QUOTING = /[:#,&*!|>'\"`%@\\n\\r\\t]|^[-?\\s]|\\s$|^$/;\n\nfunction isFlatPrimitive(v: unknown): v is string | number | boolean | null {\n return v === null || ['string', 'number', 'boolean'].includes(typeof v);\n}\n\nfunction encodeKey(k: string): string {\n return SAFE_KEY.test(k) ? k : JSON.stringify(k);\n}\n\nfunction encodeScalar(v: string | number | boolean | null): string {\n if (v === null) return 'null';\n if (typeof v === 'boolean' || typeof v === 'number') return String(v);\n // Reserved word collisions — YAML 1.1 treats these as booleans.\n if (/^(null|true|false|yes|no|on|off|~)$/i.test(v)) return JSON.stringify(v);\n if (NEEDS_QUOTING.test(v)) return JSON.stringify(v);\n // Numeric-looking strings need quoting so they don't deserialize as numbers.\n if (/^-?\\d+(\\.\\d+)?([eE][+-]?\\d+)?$/.test(v)) return JSON.stringify(v);\n return v;\n}\n\nfunction encodeNode(value: Json, indent: string): string {\n if (isFlatPrimitive(value)) return encodeScalar(value);\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]';\n return value\n .map((item) => {\n if (isFlatPrimitive(item)) return `${indent}- ${encodeScalar(item)}`;\n if (Array.isArray(item) && item.length === 0) return `${indent}- []`;\n if (\n !Array.isArray(item) &&\n typeof item === 'object' &&\n item !== null &&\n Object.keys(item).length === 0\n ) {\n return `${indent}- {}`;\n }\n const encoded = encodeNode(item, indent + INDENT);\n const innerIndent = indent + INDENT;\n const lines = encoded.split('\\n');\n const [first, ...rest] = lines;\n const firstStripped = first.startsWith(innerIndent)\n ? first.slice(innerIndent.length)\n : first;\n return [`${indent}- ${firstStripped}`, ...rest].join('\\n');\n })\n .join('\\n');\n }\n // Object.\n const entries = Object.entries(value);\n if (entries.length === 0) return '{}';\n return entries\n .map(([k, v]) => {\n if (isFlatPrimitive(v)) return `${indent}${encodeKey(k)}: ${encodeScalar(v)}`;\n if (Array.isArray(v) && v.length === 0) return `${indent}${encodeKey(k)}: []`;\n if (!Array.isArray(v) && typeof v === 'object' && Object.keys(v).length === 0) {\n return `${indent}${encodeKey(k)}: {}`;\n }\n const child = encodeNode(v, indent + INDENT);\n return `${indent}${encodeKey(k)}:\\n${child}`;\n })\n .join('\\n');\n}\n\nexport function toYaml(value: Json): string {\n if (isFlatPrimitive(value)) return encodeScalar(value);\n if (Array.isArray(value) && value.length === 0) return '[]';\n if (!Array.isArray(value) && typeof value === 'object' && Object.keys(value).length === 0) {\n return '{}';\n }\n return encodeNode(value, '');\n}\n","/**\n * Minimal RFC 4180-ish CSV encoder, used purely as a \"what if you sent\n * this as CSV\" savings preview. Returns null when the input isn't an\n * array of homogeneous flat objects — CSV only makes sense for tabular\n * data, and forcing it on nested JSON would either lose information or\n * inflate the payload, defeating the point of the savings hint.\n */\n\ntype Json = string | number | boolean | null | Json[] | { [key: string]: Json };\n\nfunction isFlat(v: unknown): v is string | number | boolean | null {\n return v === null || ['string', 'number', 'boolean'].includes(typeof v);\n}\n\nfunction isFlatRow(v: unknown): v is Record<string, string | number | boolean | null> {\n if (v === null || typeof v !== 'object' || Array.isArray(v)) return false;\n return Object.values(v).every(isFlat);\n}\n\nconst NEEDS_QUOTING = /[\",\\r\\n]/;\n\nfunction escapeCell(v: string | number | boolean | null): string {\n if (v === null) return '';\n const s = typeof v === 'string' ? v : String(v);\n return NEEDS_QUOTING.test(s) ? `\"${s.replace(/\"/g, '\"\"')}\"` : s;\n}\n\nexport function toCsv(value: Json): string | null {\n if (!Array.isArray(value) || value.length === 0) return null;\n if (!value.every(isFlatRow)) return null;\n\n const keys = Object.keys(value[0]);\n if (keys.length === 0) return null;\n for (let i = 1; i < value.length; i++) {\n const row = value[i] as Record<string, unknown>;\n if (Object.keys(row).length !== keys.length) return null;\n for (const k of keys) if (!(k in row)) return null;\n }\n\n const lines = [keys.map(escapeCell).join(',')];\n for (const row of value) {\n lines.push(keys.map((k) => escapeCell((row as Record<string, Json>)[k] as never)).join(','));\n }\n return lines.join('\\n');\n}\n","import { utf8ByteLength } from '@apicircle/shared';\nimport { toToon } from './toon';\nimport { toYaml } from './yaml';\nimport { toCsv } from './csv';\n\n/**\n * Output formats we measure savings for. Minification is NOT in this\n * list on purpose — stripping whitespace from pretty-printed JSON isn't\n * a \"transformation\", it's the wire-effective baseline most APIs already\n * send. Comparing TOON/YAML/CSV against pretty JSON would inflate the\n * apparent savings; we always normalize to minified JSON first.\n */\nexport type TransformFormat = 'toon' | 'yaml' | 'csv';\n\nexport interface TransformCandidate {\n format: TransformFormat;\n /** Encoded payload. Available so the UI can offer \"view\" / \"copy\". */\n preview: string;\n /** UTF-8 bytes of `preview`. */\n bytes: number;\n /**\n * Bytes saved vs `minifiedBytes` (the wire baseline), expressed as a\n * percentage with one decimal. Clamped at 0 — candidates that don't\n * beat the baseline are dropped from `candidates` entirely.\n */\n percentSaved: number;\n}\n\nexport interface TransformSavings {\n /** UTF-8 bytes of the body as received (may be pretty-printed). */\n originalBytes: number;\n /**\n * UTF-8 bytes of the same body re-emitted as compact JSON. This is\n * the honest wire-baseline — most APIs already send minified JSON,\n * and any \"transformation savings\" should be measured against that,\n * not against a verbose pretty-printed version. When `originalBytes ===\n * minifiedBytes`, the wire body was already compact; when they differ,\n * the UI can surface that delta separately as a \"minify only\" tip\n * without mixing it into transformation savings.\n */\n minifiedBytes: number;\n /** Sorted by percentSaved descending. Empty when nothing beats minified. */\n candidates: TransformCandidate[];\n}\n\n/**\n * Compute savings candidates for a response body. Only JSON-shaped\n * content is inspected — binary, plain text, and HTML return an empty\n * candidate list. Pure, no side effects.\n *\n * Baselines:\n * - `originalBytes` : received-as-is. What the editor is currently rendering.\n * - `minifiedBytes` : what the wire would have carried with whitespace stripped.\n * - `candidates[].percentSaved` : measured against `minifiedBytes`. So a\n * \"20% smaller as TOON\" claim means TOON beats compact JSON by 20%,\n * not that it beats pretty JSON by 20%.\n */\nexport function computeTransformSavings(body: string, contentType?: string): TransformSavings {\n const originalBytes = utf8ByteLength(body);\n if (!isJsonLike(body, contentType)) {\n return { originalBytes, minifiedBytes: originalBytes, candidates: [] };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n return { originalBytes, minifiedBytes: originalBytes, candidates: [] };\n }\n\n const minified = JSON.stringify(parsed);\n const minifiedBytes = utf8ByteLength(minified);\n\n const candidates: TransformCandidate[] = [];\n\n try {\n const toon = toToon(parsed as Parameters<typeof toToon>[0]);\n if (toon && toon !== minified) {\n candidates.push(makeCandidate('toon', toon, minifiedBytes));\n }\n } catch {\n // Encoder bug shouldn't break the response panel — silently skip.\n }\n\n try {\n const yaml = toYaml(parsed as Parameters<typeof toYaml>[0]);\n if (yaml && yaml !== minified) {\n candidates.push(makeCandidate('yaml', yaml, minifiedBytes));\n }\n } catch {\n // Same: don't crash the panel on an encoder hiccup.\n }\n\n const csv = toCsv(parsed as Parameters<typeof toCsv>[0]);\n if (csv) {\n candidates.push(makeCandidate('csv', csv, minifiedBytes));\n }\n\n return {\n originalBytes,\n minifiedBytes,\n candidates: candidates\n .filter((c) => c.bytes < minifiedBytes)\n .sort((a, b) => b.percentSaved - a.percentSaved),\n };\n}\n\nfunction makeCandidate(\n format: TransformFormat,\n preview: string,\n baselineBytes: number,\n): TransformCandidate {\n const bytes = utf8ByteLength(preview);\n const ratio = baselineBytes === 0 ? 0 : 1 - bytes / baselineBytes;\n return {\n format,\n preview,\n bytes,\n percentSaved: Math.max(0, Math.round(ratio * 1000) / 10),\n };\n}\n\nfunction isJsonLike(body: string, contentType?: string): boolean {\n if (contentType && /\\bjson\\b/i.test(contentType)) return true;\n // Best-effort sniff for missing/wrong content-type: strict trim, then\n // require an opening brace/bracket. Avoids accidentally trying to JSON\n // parse an HTML page.\n const trimmed = body.trim();\n if (!trimmed) return false;\n return trimmed.startsWith('{') || trimmed.startsWith('[');\n}\n\nexport const TRANSFORM_FORMAT_LABELS: Record<TransformFormat, string> = {\n toon: 'TOON',\n yaml: 'YAML',\n csv: 'CSV',\n};\n"],"mappings":"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,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;AACjD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE;AAClD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;AACnD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;AACjD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;AAClD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE;AAClD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;AACnD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;AACjD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;AACjD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE;AAClD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;AACnD,QAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;AACjD,QA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","names":["n","c","a","b","d","base64","out","base64","warnings","randomHex","base64UrlEncode","HTTP_METHODS","buildRequest","HTTP_METHODS","parseAuth","buildRequest","parseMethod","parseBody","PBKDF2_ITERATIONS","SALT_BYTES","base64Encode","base64Decode","randomHex","sha256Hex","typeName","sortedReplacer","structurallyEqual","envPriorityKey","generateId","envPriorityKey","crypto","snapshot","generateId","envPriorityKey","generateId","request","snapshot","generateId","lookup","passed","envPriorityKey","INDENT","INDENT","SAFE_KEY","NEEDS_QUOTING","isFlatPrimitive","encodeKey","encodeScalar","encodeNode","NEEDS_QUOTING"]}
|