@zapier/policy-context 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -27,7 +27,7 @@ __export(index_exports, {
27
27
  DEFAULT_PORTS: () => DEFAULT_PORTS,
28
28
  HttpRequestContextSchema: () => HttpRequestContextSchema,
29
29
  IGNORED_HEADERS: () => IGNORED_HEADERS,
30
- JsonValueSchema: () => JsonValueSchema,
30
+ JsonValueSchema: () => import_policy_schema.JsonValueSchema,
31
31
  ParsedUrlSchema: () => ParsedUrlSchema,
32
32
  RequestContextSchema: () => RequestContextSchema,
33
33
  buildActionResource: () => buildActionResource,
@@ -46,7 +46,7 @@ module.exports = __toCommonJS(index_exports);
46
46
 
47
47
  // src/types.ts
48
48
  var import_zod = require("zod");
49
- var JsonValueSchema = import_zod.z.custom();
49
+ var import_policy_schema = require("@zapier/policy-schema");
50
50
  var ParsedUrlSchema = import_zod.z.object({
51
51
  scheme: import_zod.z.string(),
52
52
  host: import_zod.z.string(),
@@ -96,7 +96,7 @@ var HttpRequestContextSchema = import_zod.z.object({
96
96
  /** Raw body string */
97
97
  body: import_zod.z.string().nullable(),
98
98
  /** Parsed JSON body */
99
- body_json: JsonValueSchema.nullable(),
99
+ body_json: import_policy_schema.JsonValueSchema.nullable(),
100
100
  /** Zapier connection ID used for this request */
101
101
  connection_id: import_zod.z.string().optional(),
102
102
  /** Optional human-readable reason for the request */
@@ -108,7 +108,7 @@ var ActionRunContextSchema = import_zod.z.object({
108
108
  action_type: import_zod.z.string(),
109
109
  action_key: import_zod.z.string(),
110
110
  connection_id: import_zod.z.string().optional(),
111
- inputs: JsonValueSchema.optional(),
111
+ inputs: import_policy_schema.JsonValueSchema.optional(),
112
112
  reason: import_zod.z.string().optional()
113
113
  });
114
114
  var RequestContextSchema = import_zod.z.discriminatedUnion("request_type", [
@@ -160,7 +160,7 @@ var BuildHttpRequestContextOptionsSchema = import_zod2.z.object({
160
160
  /** Raw body string */
161
161
  body: import_zod2.z.string().nullable().optional(),
162
162
  /** Pre-parsed JSON body (e.g. from Fastify's automatic JSON parsing) */
163
- body_json: JsonValueSchema.optional(),
163
+ body_json: import_policy_schema.JsonValueSchema.optional(),
164
164
  /** Connection ID associated with this request */
165
165
  connection_id: import_zod2.z.string().optional()
166
166
  });
@@ -204,7 +204,7 @@ var BuildActionRunContextOptionsSchema = import_zod2.z.object({
204
204
  action_type: import_zod2.z.string(),
205
205
  action_key: import_zod2.z.string(),
206
206
  connection_id: import_zod2.z.string().optional(),
207
- inputs: JsonValueSchema.optional()
207
+ inputs: import_policy_schema.JsonValueSchema.optional()
208
208
  });
209
209
  function buildActionRunContext(options) {
210
210
  return ActionRunContextSchema.parse({
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/constants.ts","../src/builders.ts","../src/conditions.ts","../src/policies.ts","../src/connection-policy.ts"],"sourcesContent":["// ABOUTME: Public API for @zapier/policy-context.\n// ABOUTME: Shared context types, builders, and condition generators for sdkapi + approvalsapi.\n\nexport {\n HttpRequestContextSchema,\n ActionRunContextSchema,\n RequestContextSchema,\n JsonValueSchema,\n ParsedUrlSchema,\n DEFAULT_PORTS,\n parseUrl,\n buildUrlString,\n type HttpRequestContext,\n type ActionRunContext,\n type RequestContext,\n type ParsedUrl,\n} from \"./types.ts\";\n\nexport { IGNORED_HEADERS } from \"./constants.ts\";\n\nexport {\n buildHttpRequestContext,\n buildActionRunContext,\n BuildHttpRequestContextOptionsSchema,\n BuildActionRunContextOptionsSchema,\n type BuildHttpRequestContextOptions,\n type BuildActionRunContextOptions,\n} from \"./builders.ts\";\n\nexport {\n buildExactHttpConditions,\n buildDomainHttpConditions,\n buildExactActionConditions,\n buildActionResource,\n buildBroadActionResource,\n} from \"./conditions.ts\";\n\nexport { toExactPolicy } from \"./policies.ts\";\n\nexport {\n buildConnectionPolicy,\n AccessLevelSchema,\n type AccessLevel,\n} from \"./connection-policy.ts\";\n","// ABOUTME: Canonical request context types shared between sdkapi and approvalsapi.\n// ABOUTME: These define the contract for how requests are described in approval flows and policy evaluation.\n\nimport { z } from \"zod\";\nimport type { JsonValue } from \"@zapier/policy-schema\";\n\n/**\n * Zod schema for arbitrary JSON values. Used across context schemas for\n * unstructured fields like `body_json` and `inputs`.\n */\nexport const JsonValueSchema = z.custom<JsonValue>();\n\n/**\n * Parsed URL components for policy evaluation.\n * Matches the ParsedUrl shape from @zapier/policy-schema so that\n * evaluatePolicy condition paths like [\"url\", \"host\"] resolve correctly.\n */\nexport const ParsedUrlSchema = z.object({\n scheme: z.string(),\n host: z.string(),\n port: z.number(),\n path: z.string(),\n query: z.record(z.string(), z.array(z.string())),\n});\nexport type ParsedUrl = z.infer<typeof ParsedUrlSchema>;\n\n/** Default ports by scheme, used when URL has no explicit port. */\nexport const DEFAULT_PORTS: Record<string, number> = {\n http: 80,\n https: 443,\n};\n\n/**\n * Parse a raw URL string into a ParsedUrl.\n * Same logic as parseUrlForPolicyContext in @zapier/policy.\n */\nexport function parseUrl(raw: string): ParsedUrl {\n const url = new URL(raw);\n const scheme = url.protocol.slice(0, -1).toLowerCase();\n const host = url.hostname.toLowerCase();\n const port = url.port ? parseInt(url.port, 10) : (DEFAULT_PORTS[scheme] ?? 0);\n const path = url.pathname || \"/\";\n const query: Record<string, string[]> = {};\n for (const [key, value] of url.searchParams) {\n if (!query[key]) {\n query[key] = [];\n }\n query[key].push(value);\n }\n return { scheme, host, port, path, query };\n}\n\n/**\n * Reconstruct a URL string from a ParsedUrl.\n * Same logic as buildUrl in @zapier/policy.\n */\nexport function buildUrlString(parsed: ParsedUrl): string {\n const { scheme, host, port, path, query } = parsed;\n const defaultPort = DEFAULT_PORTS[scheme];\n const portString = port !== defaultPort ? `:${String(port)}` : \"\";\n const params = new URLSearchParams();\n for (const [key, values] of Object.entries(query)) {\n for (const value of values) {\n params.append(key, value);\n }\n }\n const queryString = params.toString();\n return `${scheme}://${host}${portString}${path}${queryString ? \"?\" + queryString : \"\"}`;\n}\n\n/**\n * HTTP request context for approval/policy flows.\n * Sent by sdkapi when a relay request is denied, stored by approvalsapi,\n * and used for both policy evaluation and building policy conditions.\n *\n * The url field is a ParsedUrl object (matching @zapier/policy-schema's ParsedUrl)\n * so that evaluatePolicy conditions like [\"url\", \"host\"] resolve correctly.\n */\nexport const HttpRequestContextSchema = z.object({\n request_type: z.literal(\"http_request\"),\n method: z.string(),\n /** Parsed URL components for policy condition matching */\n url: ParsedUrlSchema,\n /** Filtered headers (IGNORED_HEADERS excluded, keys lowercased) */\n headers: z.record(z.string(), z.string()),\n /** Raw body string */\n body: z.string().nullable(),\n /** Parsed JSON body */\n body_json: JsonValueSchema.nullable(),\n /** Zapier connection ID used for this request */\n connection_id: z.string().optional(),\n /** Optional human-readable reason for the request */\n reason: z.string().optional(),\n});\nexport type HttpRequestContext = z.infer<typeof HttpRequestContextSchema>;\n\n/**\n * Action run context for approval/policy flows.\n * Sent by sdkapi when an action run is denied, stored by approvalsapi,\n * and used to build policy conditions.\n */\nexport const ActionRunContextSchema = z.object({\n request_type: z.literal(\"action_run\"),\n selected_api: z.string(),\n action_type: z.string(),\n action_key: z.string(),\n connection_id: z.string().optional(),\n inputs: JsonValueSchema.optional(),\n reason: z.string().optional(),\n});\nexport type ActionRunContext = z.infer<typeof ActionRunContextSchema>;\n\n/**\n * Discriminated union of all request context types.\n */\nexport const RequestContextSchema = z.discriminatedUnion(\"request_type\", [\n HttpRequestContextSchema,\n ActionRunContextSchema,\n]);\nexport type RequestContext = z.infer<typeof RequestContextSchema>;\n","// ABOUTME: Canonical set of headers to exclude when building request contexts.\n// ABOUTME: Shared between sdkapi (context creation) and approvalsapi (condition building).\n\n/**\n * Headers to exclude when building request contexts from raw HTTP requests.\n *\n * These are either sensitive (auth credentials), HTTP infrastructure headers\n * that vary per-request, or proxy-internal headers that are not meaningful\n * for policy decisions.\n */\nexport const IGNORED_HEADERS = new Set([\n // Auth / credentials — never include in contexts or policy conditions\n \"authorization\",\n \"x-relay-authorization\",\n \"x-relay-authentication-id\",\n \"x-api-key\",\n \"cookie\",\n \"set-cookie\",\n \"proxy-authorization\",\n\n // HTTP infrastructure — varies per-request, not policy-relevant\n \"host\",\n \"connection\",\n \"content-length\",\n \"transfer-encoding\",\n \"accept-encoding\",\n \"user-agent\",\n \"accept\",\n \"accept-language\",\n \"sec-fetch-mode\",\n\n // Proxy / forwarding — infrastructure, not meaningful for policy\n \"x-forwarded-for\",\n \"x-forwarded-host\",\n \"x-forwarded-proto\",\n \"x-real-ip\",\n\n // Proxy internal — sdkapi-specific headers\n \"x-is-interactive-session\",\n \"x-relay-callback-url\",\n]);\n","// ABOUTME: Canonical builders for creating request contexts from raw request parts.\n// ABOUTME: Used by sdkapi to build both approval contexts and policy eval contexts.\n\nimport { z } from \"zod\";\nimport {\n HttpRequestContextSchema,\n ActionRunContextSchema,\n JsonValueSchema,\n parseUrl,\n type HttpRequestContext,\n type ActionRunContext,\n} from \"./types.ts\";\nimport { IGNORED_HEADERS } from \"./constants.ts\";\n\nexport const BuildHttpRequestContextOptionsSchema = z.object({\n method: z.string(),\n /** Raw URL string. Will be normalized with https:// if no protocol present. */\n url: z.string(),\n /** Raw headers from the request. Will be filtered through IGNORED_HEADERS. */\n headers: z\n .record(\n z.string(),\n z.union([z.string(), z.array(z.string()), z.undefined()]),\n )\n .optional(),\n /** Raw body string */\n body: z.string().nullable().optional(),\n /** Pre-parsed JSON body (e.g. from Fastify's automatic JSON parsing) */\n body_json: JsonValueSchema.optional(),\n /** Connection ID associated with this request */\n connection_id: z.string().optional(),\n});\nexport type BuildHttpRequestContextOptions = z.infer<\n typeof BuildHttpRequestContextOptionsSchema\n>;\n\n/**\n * Build a canonical HttpRequestContext from raw request parts.\n *\n * This is the single source of truth for how HTTP request contexts are created.\n * Both sdkapi (for policy evaluation) and approvalsapi (for context storage)\n * should use this to ensure the context shape is consistent.\n *\n * Matches the behavior of createPolicyHttpRequest from @zapier/policy, with\n * the addition of header filtering through IGNORED_HEADERS.\n *\n * - Normalizes URL (adds https:// if missing) and parses into { scheme, host, port, path, query }\n * - Filters headers through IGNORED_HEADERS, lowercases keys, string values only\n * - Auto-parses body_json from body when content-type is JSON and body_json not provided\n * - body defaults to null (not undefined)\n */\nexport function buildHttpRequestContext(\n options: BuildHttpRequestContextOptions,\n): HttpRequestContext {\n // Normalize URL — SDK CLI strips the protocol\n const rawUrl = options.url.includes(\"://\")\n ? options.url\n : `https://${options.url}`;\n const url = parseUrl(rawUrl);\n\n // Filter headers: exclude ignored, lowercase keys, string values only\n const headers: Record<string, string> = {};\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n const lowerKey = key.toLowerCase();\n if (!IGNORED_HEADERS.has(lowerKey) && typeof value === \"string\") {\n headers[lowerKey] = value;\n }\n }\n }\n\n // Auto-parse body_json from body when content-type is JSON\n // (matches createPolicyHttpRequest behavior from @zapier/policy)\n let body_json: unknown = null;\n if (options.body_json !== undefined) {\n body_json = options.body_json;\n } else if (options.body) {\n const contentType = headers[\"content-type\"];\n const isJson =\n typeof contentType === \"string\" &&\n (contentType.includes(\"application/json\") ||\n (contentType.includes(\"application/\") &&\n contentType.includes(\"+json\")));\n if (isJson) {\n try {\n body_json = JSON.parse(options.body);\n } catch {\n // Invalid JSON body — leave body_json as null\n }\n }\n }\n\n return HttpRequestContextSchema.parse({\n request_type: \"http_request\",\n method: options.method,\n url,\n headers,\n body: options.body ?? null,\n body_json,\n connection_id: options.connection_id,\n });\n}\n\nexport const BuildActionRunContextOptionsSchema = z.object({\n selected_api: z.string(),\n action_type: z.string(),\n action_key: z.string(),\n connection_id: z.string().optional(),\n inputs: JsonValueSchema.optional(),\n});\nexport type BuildActionRunContextOptions = z.infer<\n typeof BuildActionRunContextOptionsSchema\n>;\n\n/**\n * Build a canonical ActionRunContext from raw action parts.\n */\nexport function buildActionRunContext(\n options: BuildActionRunContextOptions,\n): ActionRunContext {\n return ActionRunContextSchema.parse({\n request_type: \"action_run\",\n selected_api: options.selected_api,\n action_type: options.action_type,\n action_key: options.action_key,\n connection_id: options.connection_id,\n inputs: options.inputs,\n });\n}\n","// ABOUTME: Builds policy conditions from stored request contexts.\n// ABOUTME: Used by approvalsapi's \"allow exact request\" and \"allow domain\" instant policy flows.\n\nimport type { Condition } from \"@zapier/policy-schema\";\nimport type { HttpRequestContext, ActionRunContext } from \"./types.ts\";\nimport { IGNORED_HEADERS } from \"./constants.ts\";\n\n/**\n * Build conditions that match an exact HTTP request.\n *\n * Handles the matches_url / query param split correctly:\n * - `matches_url` only supports scheme+host+port+path (no query string per spec)\n * - Query parameters are added as separate decomposed conditions on `url.query.<key>`\n *\n * @returns Condition[] for an http permission statement\n */\nexport function buildExactHttpConditions(\n context: HttpRequestContext,\n): Condition[] {\n const conditions: Condition[] = [\n { path: [\"method\"], operator: \"equals\", value: context.method },\n ];\n\n const { url } = context;\n\n // matches_url condition uses URL without query string (per @zapier/policy spec)\n const defaultPort =\n url.scheme === \"https\" ? 443 : url.scheme === \"http\" ? 80 : 0;\n const portString = url.port !== defaultPort ? `:${String(url.port)}` : \"\";\n const urlWithoutQuery = `${url.scheme}://${url.host}${portString}${url.path}`;\n conditions.push({\n path: [\"url\"],\n operator: \"matches_url\",\n value: urlWithoutQuery,\n });\n\n // Add decomposed conditions for each query parameter.\n for (const [key, values] of Object.entries(url.query)) {\n conditions.push({\n path: [\"url\", \"query\", key],\n operator: \"equals\",\n value: values,\n });\n }\n\n // body_json condition\n if (context.body_json !== null) {\n conditions.push({\n path: [\"body_json\"],\n operator: \"equals\",\n value: context.body_json,\n });\n }\n\n // Header conditions (filtered through IGNORED_HEADERS again for safety)\n for (const [key, value] of Object.entries(context.headers)) {\n if (!IGNORED_HEADERS.has(key.toLowerCase()) && typeof value === \"string\") {\n conditions.push({\n path: [\"headers\", key.toLowerCase()],\n operator: \"equals\",\n value,\n });\n }\n }\n\n return conditions;\n}\n\n/**\n * Build conditions that match any request to a given domain.\n * Uses the host from the parsed URL.\n *\n * @returns Condition[] for an http permission statement\n */\nexport function buildDomainHttpConditions(\n context: HttpRequestContext,\n): Condition[] {\n return [\n {\n path: [\"url\", \"host\"],\n operator: \"matches_host\",\n value: context.url.host,\n },\n ];\n}\n\n/**\n * Build conditions that match an exact action run (with inputs).\n *\n * @returns Condition[] for an action permission statement\n */\nexport function buildExactActionConditions(\n context: ActionRunContext,\n): Condition[] {\n const conditions: Condition[] = [];\n\n if (\n context.inputs !== undefined &&\n context.inputs !== null &&\n typeof context.inputs === \"object\"\n ) {\n conditions.push({\n path: [\"inputs\"],\n operator: \"equals\",\n value: context.inputs,\n });\n }\n\n return conditions;\n}\n\n/**\n * Build the resource string for an action.\n * Format: action/{selected_api}/{action_type}/{action_key}\n */\nexport function buildActionResource(context: ActionRunContext): string {\n return `action/${context.selected_api}/${context.action_type}/${context.action_key}`;\n}\n\n/**\n * Build a broad action resource that matches all actions for an app.\n * Format: action/{selected_api}/{wildcard}/{wildcard}\n */\nexport function buildBroadActionResource(context: ActionRunContext): string {\n return `action/${context.selected_api}/*/*`;\n}\n","// ABOUTME: Assembles complete Policy objects from request contexts.\n// ABOUTME: Single source of truth for \"exact request\" instant policies used by web UI and API.\n\nimport type { Policy, Statement } from \"@zapier/policy-schema\";\nimport type {\n RequestContext,\n HttpRequestContext,\n ActionRunContext,\n} from \"./types.ts\";\nimport {\n buildExactHttpConditions,\n buildExactActionConditions,\n buildActionResource,\n} from \"./conditions.ts\";\n\n/**\n * Build a `can_use` authentication statement, if the context has a connection_id.\n */\nfunction buildAuthStatement(authenticationId: string): Statement {\n return {\n effect: \"allow\",\n permissions: [\"can_use\"],\n resources: [`connection/${authenticationId}`],\n conditions: [],\n };\n}\n\n/**\n * Build an exact-match policy from an HTTP request context.\n *\n * Produces a policy that allows only the specific request described by the context:\n * - `can_use` statement for the authentication (if present)\n * - `can_execute` statement for `http` with conditions from `buildExactHttpConditions`\n * plus a `keys_in` guard restricting allowed query parameter keys\n */\nfunction httpContextToPolicy(context: HttpRequestContext): Policy {\n const statements: Statement[] = [];\n\n if (context.connection_id) {\n statements.push(buildAuthStatement(context.connection_id));\n }\n\n const conditions = buildExactHttpConditions(context);\n\n // Add a keys_in guard so only the query param keys present in the original\n // request are allowed — blocks injection of extra query params.\n conditions.push({\n path: [\"url\", \"query\"],\n operator: \"keys_in\",\n value: Object.keys(context.url.query),\n });\n\n statements.push({\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [\"http\"],\n conditions,\n });\n\n return { version: 2, statements };\n}\n\n/**\n * Build an exact-match policy from an action run context.\n *\n * Produces a policy that allows only the specific action described by the context:\n * - `can_use` statement for the authentication (if present)\n * - `can_execute` statement for the action resource with input conditions\n */\nfunction actionContextToPolicy(context: ActionRunContext): Policy {\n const statements: Statement[] = [];\n\n if (context.connection_id) {\n statements.push(buildAuthStatement(context.connection_id));\n }\n\n statements.push({\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [buildActionResource(context)],\n conditions: buildExactActionConditions(context),\n });\n\n return { version: 2, statements };\n}\n\n/**\n * Build an exact-match policy from any supported request context.\n *\n * This is the single source of truth for \"allow this exact request\" instant policies.\n * Used by the web UI and anywhere else that needs to produce an exact policy from a context.\n */\nexport function toExactPolicy(context: RequestContext): Policy {\n if (context.request_type === \"http_request\") {\n return httpContextToPolicy(context);\n }\n return actionContextToPolicy(context);\n}\n","// ABOUTME: Builds connection-level policies for the basic approvals MVP.\n// ABOUTME: Generates deterministic policies that allow read or read+write access scoped to a specific connection.\n\nimport { z } from \"zod\";\nimport type { Policy, Statement, Condition } from \"@zapier/policy-schema\";\n\nexport const AccessLevelSchema = z.enum([\"read\", \"read_write\"]);\nexport type AccessLevel = z.infer<typeof AccessLevelSchema>;\n\nconst READ_HTTP_METHODS = [\"GET\", \"HEAD\", \"OPTIONS\"];\nconst READ_ACTION_TYPES = [\"read\", \"search\"];\n\n/**\n * Build a connection-level policy that covers both HTTP and action access.\n *\n * Always produces three statements:\n * 1. `can_use` for the authentication\n * 2. `can_execute` on `http` scoped by connection_id (+ method filter for read)\n * 3. `can_execute` on `action/{selectedApi}/**` scoped by connection_id (+ action_type filter for read)\n */\nexport function buildConnectionPolicy(options: {\n connectionId: string;\n selectedApi: string;\n accessLevel: AccessLevel;\n}): Policy {\n const { connectionId, selectedApi, accessLevel } = options;\n\n const authStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_use\"],\n resources: [`connection/${connectionId}`],\n conditions: [],\n };\n\n const connectionCondition: Condition = {\n path: [\"connection_id\"],\n operator: \"equals\",\n value: connectionId,\n };\n\n const httpConditions: Condition[] = [connectionCondition];\n if (accessLevel === \"read\") {\n httpConditions.push({\n path: [\"method\"],\n operator: \"in\",\n value: READ_HTTP_METHODS,\n });\n }\n\n const httpStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [\"http\"],\n conditions: httpConditions,\n };\n\n const actionConditions: Condition[] = [connectionCondition];\n if (accessLevel === \"read\") {\n actionConditions.push({\n path: [\"action_type\"],\n operator: \"in\",\n value: READ_ACTION_TYPES,\n });\n }\n\n const actionStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [`action/${selectedApi}/*/*`],\n conditions: actionConditions,\n };\n\n return {\n version: 2,\n statements: [authStatement, httpStatement, actionStatement],\n };\n}\n"],"mappings":"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","names":["import_zod","import_zod"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/constants.ts","../src/builders.ts","../src/conditions.ts","../src/policies.ts","../src/connection-policy.ts"],"sourcesContent":["// ABOUTME: Public API for @zapier/policy-context.\n// ABOUTME: Shared context types, builders, and condition generators for sdkapi + approvalsapi.\n\nexport {\n HttpRequestContextSchema,\n ActionRunContextSchema,\n RequestContextSchema,\n JsonValueSchema,\n ParsedUrlSchema,\n DEFAULT_PORTS,\n parseUrl,\n buildUrlString,\n type HttpRequestContext,\n type ActionRunContext,\n type RequestContext,\n type ParsedUrl,\n} from \"./types.ts\";\n\nexport { IGNORED_HEADERS } from \"./constants.ts\";\n\nexport {\n buildHttpRequestContext,\n buildActionRunContext,\n BuildHttpRequestContextOptionsSchema,\n BuildActionRunContextOptionsSchema,\n type BuildHttpRequestContextOptions,\n type BuildActionRunContextOptions,\n} from \"./builders.ts\";\n\nexport {\n buildExactHttpConditions,\n buildDomainHttpConditions,\n buildExactActionConditions,\n buildActionResource,\n buildBroadActionResource,\n} from \"./conditions.ts\";\n\nexport { toExactPolicy } from \"./policies.ts\";\n\nexport {\n buildConnectionPolicy,\n AccessLevelSchema,\n type AccessLevel,\n} from \"./connection-policy.ts\";\n","// ABOUTME: Canonical request context types shared between sdkapi and approvalsapi.\n// ABOUTME: These define the contract for how requests are described in approval flows and policy evaluation.\n\nimport { z } from \"zod\";\nimport { JsonValueSchema } from \"@zapier/policy-schema\";\n\nexport { JsonValueSchema };\n\n/**\n * Parsed URL components for policy evaluation.\n * Matches the ParsedUrl shape from @zapier/policy-schema so that\n * evaluatePolicy condition paths like [\"url\", \"host\"] resolve correctly.\n */\nexport const ParsedUrlSchema = z.object({\n scheme: z.string(),\n host: z.string(),\n port: z.number(),\n path: z.string(),\n query: z.record(z.string(), z.array(z.string())),\n});\nexport type ParsedUrl = z.infer<typeof ParsedUrlSchema>;\n\n/** Default ports by scheme, used when URL has no explicit port. */\nexport const DEFAULT_PORTS: Record<string, number> = {\n http: 80,\n https: 443,\n};\n\n/**\n * Parse a raw URL string into a ParsedUrl.\n * Same logic as parseUrlForPolicyContext in @zapier/policy.\n */\nexport function parseUrl(raw: string): ParsedUrl {\n const url = new URL(raw);\n const scheme = url.protocol.slice(0, -1).toLowerCase();\n const host = url.hostname.toLowerCase();\n const port = url.port ? parseInt(url.port, 10) : (DEFAULT_PORTS[scheme] ?? 0);\n const path = url.pathname || \"/\";\n const query: Record<string, string[]> = {};\n for (const [key, value] of url.searchParams) {\n if (!query[key]) {\n query[key] = [];\n }\n query[key].push(value);\n }\n return { scheme, host, port, path, query };\n}\n\n/**\n * Reconstruct a URL string from a ParsedUrl.\n * Same logic as buildUrl in @zapier/policy.\n */\nexport function buildUrlString(parsed: ParsedUrl): string {\n const { scheme, host, port, path, query } = parsed;\n const defaultPort = DEFAULT_PORTS[scheme];\n const portString = port !== defaultPort ? `:${String(port)}` : \"\";\n const params = new URLSearchParams();\n for (const [key, values] of Object.entries(query)) {\n for (const value of values) {\n params.append(key, value);\n }\n }\n const queryString = params.toString();\n return `${scheme}://${host}${portString}${path}${queryString ? \"?\" + queryString : \"\"}`;\n}\n\n/**\n * HTTP request context for approval/policy flows.\n * Sent by sdkapi when a relay request is denied, stored by approvalsapi,\n * and used for both policy evaluation and building policy conditions.\n *\n * The url field is a ParsedUrl object (matching @zapier/policy-schema's ParsedUrl)\n * so that evaluatePolicy conditions like [\"url\", \"host\"] resolve correctly.\n */\nexport const HttpRequestContextSchema = z.object({\n request_type: z.literal(\"http_request\"),\n method: z.string(),\n /** Parsed URL components for policy condition matching */\n url: ParsedUrlSchema,\n /** Filtered headers (IGNORED_HEADERS excluded, keys lowercased) */\n headers: z.record(z.string(), z.string()),\n /** Raw body string */\n body: z.string().nullable(),\n /** Parsed JSON body */\n body_json: JsonValueSchema.nullable(),\n /** Zapier connection ID used for this request */\n connection_id: z.string().optional(),\n /** Optional human-readable reason for the request */\n reason: z.string().optional(),\n});\nexport type HttpRequestContext = z.infer<typeof HttpRequestContextSchema>;\n\n/**\n * Action run context for approval/policy flows.\n * Sent by sdkapi when an action run is denied, stored by approvalsapi,\n * and used to build policy conditions.\n */\nexport const ActionRunContextSchema = z.object({\n request_type: z.literal(\"action_run\"),\n selected_api: z.string(),\n action_type: z.string(),\n action_key: z.string(),\n connection_id: z.string().optional(),\n inputs: JsonValueSchema.optional(),\n reason: z.string().optional(),\n});\nexport type ActionRunContext = z.infer<typeof ActionRunContextSchema>;\n\n/**\n * Discriminated union of all request context types.\n */\nexport const RequestContextSchema = z.discriminatedUnion(\"request_type\", [\n HttpRequestContextSchema,\n ActionRunContextSchema,\n]);\nexport type RequestContext = z.infer<typeof RequestContextSchema>;\n","// ABOUTME: Canonical set of headers to exclude when building request contexts.\n// ABOUTME: Shared between sdkapi (context creation) and approvalsapi (condition building).\n\n/**\n * Headers to exclude when building request contexts from raw HTTP requests.\n *\n * These are either sensitive (auth credentials), HTTP infrastructure headers\n * that vary per-request, or proxy-internal headers that are not meaningful\n * for policy decisions.\n */\nexport const IGNORED_HEADERS = new Set([\n // Auth / credentials — never include in contexts or policy conditions\n \"authorization\",\n \"x-relay-authorization\",\n \"x-relay-authentication-id\",\n \"x-api-key\",\n \"cookie\",\n \"set-cookie\",\n \"proxy-authorization\",\n\n // HTTP infrastructure — varies per-request, not policy-relevant\n \"host\",\n \"connection\",\n \"content-length\",\n \"transfer-encoding\",\n \"accept-encoding\",\n \"user-agent\",\n \"accept\",\n \"accept-language\",\n \"sec-fetch-mode\",\n\n // Proxy / forwarding — infrastructure, not meaningful for policy\n \"x-forwarded-for\",\n \"x-forwarded-host\",\n \"x-forwarded-proto\",\n \"x-real-ip\",\n\n // Proxy internal — sdkapi-specific headers\n \"x-is-interactive-session\",\n \"x-relay-callback-url\",\n]);\n","// ABOUTME: Canonical builders for creating request contexts from raw request parts.\n// ABOUTME: Used by sdkapi to build both approval contexts and policy eval contexts.\n\nimport { z } from \"zod\";\nimport {\n HttpRequestContextSchema,\n ActionRunContextSchema,\n JsonValueSchema,\n parseUrl,\n type HttpRequestContext,\n type ActionRunContext,\n} from \"./types.ts\";\nimport { IGNORED_HEADERS } from \"./constants.ts\";\n\nexport const BuildHttpRequestContextOptionsSchema = z.object({\n method: z.string(),\n /** Raw URL string. Will be normalized with https:// if no protocol present. */\n url: z.string(),\n /** Raw headers from the request. Will be filtered through IGNORED_HEADERS. */\n headers: z\n .record(\n z.string(),\n z.union([z.string(), z.array(z.string()), z.undefined()]),\n )\n .optional(),\n /** Raw body string */\n body: z.string().nullable().optional(),\n /** Pre-parsed JSON body (e.g. from Fastify's automatic JSON parsing) */\n body_json: JsonValueSchema.optional(),\n /** Connection ID associated with this request */\n connection_id: z.string().optional(),\n});\nexport type BuildHttpRequestContextOptions = z.infer<\n typeof BuildHttpRequestContextOptionsSchema\n>;\n\n/**\n * Build a canonical HttpRequestContext from raw request parts.\n *\n * This is the single source of truth for how HTTP request contexts are created.\n * Both sdkapi (for policy evaluation) and approvalsapi (for context storage)\n * should use this to ensure the context shape is consistent.\n *\n * Matches the behavior of createPolicyHttpRequest from @zapier/policy, with\n * the addition of header filtering through IGNORED_HEADERS.\n *\n * - Normalizes URL (adds https:// if missing) and parses into { scheme, host, port, path, query }\n * - Filters headers through IGNORED_HEADERS, lowercases keys, string values only\n * - Auto-parses body_json from body when content-type is JSON and body_json not provided\n * - body defaults to null (not undefined)\n */\nexport function buildHttpRequestContext(\n options: BuildHttpRequestContextOptions,\n): HttpRequestContext {\n // Normalize URL — SDK CLI strips the protocol\n const rawUrl = options.url.includes(\"://\")\n ? options.url\n : `https://${options.url}`;\n const url = parseUrl(rawUrl);\n\n // Filter headers: exclude ignored, lowercase keys, string values only\n const headers: Record<string, string> = {};\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n const lowerKey = key.toLowerCase();\n if (!IGNORED_HEADERS.has(lowerKey) && typeof value === \"string\") {\n headers[lowerKey] = value;\n }\n }\n }\n\n // Auto-parse body_json from body when content-type is JSON\n // (matches createPolicyHttpRequest behavior from @zapier/policy)\n let body_json: unknown = null;\n if (options.body_json !== undefined) {\n body_json = options.body_json;\n } else if (options.body) {\n const contentType = headers[\"content-type\"];\n const isJson =\n typeof contentType === \"string\" &&\n (contentType.includes(\"application/json\") ||\n (contentType.includes(\"application/\") &&\n contentType.includes(\"+json\")));\n if (isJson) {\n try {\n body_json = JSON.parse(options.body);\n } catch {\n // Invalid JSON body — leave body_json as null\n }\n }\n }\n\n return HttpRequestContextSchema.parse({\n request_type: \"http_request\",\n method: options.method,\n url,\n headers,\n body: options.body ?? null,\n body_json,\n connection_id: options.connection_id,\n });\n}\n\nexport const BuildActionRunContextOptionsSchema = z.object({\n selected_api: z.string(),\n action_type: z.string(),\n action_key: z.string(),\n connection_id: z.string().optional(),\n inputs: JsonValueSchema.optional(),\n});\nexport type BuildActionRunContextOptions = z.infer<\n typeof BuildActionRunContextOptionsSchema\n>;\n\n/**\n * Build a canonical ActionRunContext from raw action parts.\n */\nexport function buildActionRunContext(\n options: BuildActionRunContextOptions,\n): ActionRunContext {\n return ActionRunContextSchema.parse({\n request_type: \"action_run\",\n selected_api: options.selected_api,\n action_type: options.action_type,\n action_key: options.action_key,\n connection_id: options.connection_id,\n inputs: options.inputs,\n });\n}\n","// ABOUTME: Builds policy conditions from stored request contexts.\n// ABOUTME: Used by approvalsapi's \"allow exact request\" and \"allow domain\" instant policy flows.\n\nimport type { Condition } from \"@zapier/policy-schema\";\nimport type { HttpRequestContext, ActionRunContext } from \"./types.ts\";\nimport { IGNORED_HEADERS } from \"./constants.ts\";\n\n/**\n * Build conditions that match an exact HTTP request.\n *\n * Handles the matches_url / query param split correctly:\n * - `matches_url` only supports scheme+host+port+path (no query string per spec)\n * - Query parameters are added as separate decomposed conditions on `url.query.<key>`\n *\n * @returns Condition[] for an http permission statement\n */\nexport function buildExactHttpConditions(\n context: HttpRequestContext,\n): Condition[] {\n const conditions: Condition[] = [\n { path: [\"method\"], operator: \"equals\", value: context.method },\n ];\n\n const { url } = context;\n\n // matches_url condition uses URL without query string (per @zapier/policy spec)\n const defaultPort =\n url.scheme === \"https\" ? 443 : url.scheme === \"http\" ? 80 : 0;\n const portString = url.port !== defaultPort ? `:${String(url.port)}` : \"\";\n const urlWithoutQuery = `${url.scheme}://${url.host}${portString}${url.path}`;\n conditions.push({\n path: [\"url\"],\n operator: \"matches_url\",\n value: urlWithoutQuery,\n });\n\n // Add decomposed conditions for each query parameter.\n for (const [key, values] of Object.entries(url.query)) {\n conditions.push({\n path: [\"url\", \"query\", key],\n operator: \"equals\",\n value: values,\n });\n }\n\n // body_json condition\n if (context.body_json !== null) {\n conditions.push({\n path: [\"body_json\"],\n operator: \"equals\",\n value: context.body_json,\n });\n }\n\n // Header conditions (filtered through IGNORED_HEADERS again for safety)\n for (const [key, value] of Object.entries(context.headers)) {\n if (!IGNORED_HEADERS.has(key.toLowerCase()) && typeof value === \"string\") {\n conditions.push({\n path: [\"headers\", key.toLowerCase()],\n operator: \"equals\",\n value,\n });\n }\n }\n\n return conditions;\n}\n\n/**\n * Build conditions that match any request to a given domain.\n * Uses the host from the parsed URL.\n *\n * @returns Condition[] for an http permission statement\n */\nexport function buildDomainHttpConditions(\n context: HttpRequestContext,\n): Condition[] {\n return [\n {\n path: [\"url\", \"host\"],\n operator: \"matches_host\",\n value: context.url.host,\n },\n ];\n}\n\n/**\n * Build conditions that match an exact action run (with inputs).\n *\n * @returns Condition[] for an action permission statement\n */\nexport function buildExactActionConditions(\n context: ActionRunContext,\n): Condition[] {\n const conditions: Condition[] = [];\n\n if (\n context.inputs !== undefined &&\n context.inputs !== null &&\n typeof context.inputs === \"object\"\n ) {\n conditions.push({\n path: [\"inputs\"],\n operator: \"equals\",\n value: context.inputs,\n });\n }\n\n return conditions;\n}\n\n/**\n * Build the resource string for an action.\n * Format: action/{selected_api}/{action_type}/{action_key}\n */\nexport function buildActionResource(context: ActionRunContext): string {\n return `action/${context.selected_api}/${context.action_type}/${context.action_key}`;\n}\n\n/**\n * Build a broad action resource that matches all actions for an app.\n * Format: action/{selected_api}/{wildcard}/{wildcard}\n */\nexport function buildBroadActionResource(context: ActionRunContext): string {\n return `action/${context.selected_api}/*/*`;\n}\n","// ABOUTME: Assembles complete Policy objects from request contexts.\n// ABOUTME: Single source of truth for \"exact request\" instant policies used by web UI and API.\n\nimport type { Policy, Statement } from \"@zapier/policy-schema\";\nimport type {\n RequestContext,\n HttpRequestContext,\n ActionRunContext,\n} from \"./types.ts\";\nimport {\n buildExactHttpConditions,\n buildExactActionConditions,\n buildActionResource,\n} from \"./conditions.ts\";\n\n/**\n * Build a `can_use` authentication statement, if the context has a connection_id.\n */\nfunction buildAuthStatement(authenticationId: string): Statement {\n return {\n effect: \"allow\",\n permissions: [\"can_use\"],\n resources: [`connection/${authenticationId}`],\n conditions: [],\n };\n}\n\n/**\n * Build an exact-match policy from an HTTP request context.\n *\n * Produces a policy that allows only the specific request described by the context:\n * - `can_use` statement for the authentication (if present)\n * - `can_execute` statement for `http` with conditions from `buildExactHttpConditions`\n * plus a `keys_in` guard restricting allowed query parameter keys\n */\nfunction httpContextToPolicy(context: HttpRequestContext): Policy {\n const statements: Statement[] = [];\n\n if (context.connection_id) {\n statements.push(buildAuthStatement(context.connection_id));\n }\n\n const conditions = buildExactHttpConditions(context);\n\n // Add a keys_in guard so only the query param keys present in the original\n // request are allowed — blocks injection of extra query params.\n conditions.push({\n path: [\"url\", \"query\"],\n operator: \"keys_in\",\n value: Object.keys(context.url.query),\n });\n\n statements.push({\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [\"http\"],\n conditions,\n });\n\n return { version: 2, statements };\n}\n\n/**\n * Build an exact-match policy from an action run context.\n *\n * Produces a policy that allows only the specific action described by the context:\n * - `can_use` statement for the authentication (if present)\n * - `can_execute` statement for the action resource with input conditions\n */\nfunction actionContextToPolicy(context: ActionRunContext): Policy {\n const statements: Statement[] = [];\n\n if (context.connection_id) {\n statements.push(buildAuthStatement(context.connection_id));\n }\n\n statements.push({\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [buildActionResource(context)],\n conditions: buildExactActionConditions(context),\n });\n\n return { version: 2, statements };\n}\n\n/**\n * Build an exact-match policy from any supported request context.\n *\n * This is the single source of truth for \"allow this exact request\" instant policies.\n * Used by the web UI and anywhere else that needs to produce an exact policy from a context.\n */\nexport function toExactPolicy(context: RequestContext): Policy {\n if (context.request_type === \"http_request\") {\n return httpContextToPolicy(context);\n }\n return actionContextToPolicy(context);\n}\n","// ABOUTME: Builds connection-level policies for the basic approvals MVP.\n// ABOUTME: Generates deterministic policies that allow read or read+write access scoped to a specific connection.\n\nimport { z } from \"zod\";\nimport type { Policy, Statement, Condition } from \"@zapier/policy-schema\";\n\nexport const AccessLevelSchema = z.enum([\"read\", \"read_write\"]);\nexport type AccessLevel = z.infer<typeof AccessLevelSchema>;\n\nconst READ_HTTP_METHODS = [\"GET\", \"HEAD\", \"OPTIONS\"];\nconst READ_ACTION_TYPES = [\"read\", \"search\"];\n\n/**\n * Build a connection-level policy that covers both HTTP and action access.\n *\n * Always produces three statements:\n * 1. `can_use` for the authentication\n * 2. `can_execute` on `http` scoped by connection_id (+ method filter for read)\n * 3. `can_execute` on `action/{selectedApi}/**` scoped by connection_id (+ action_type filter for read)\n */\nexport function buildConnectionPolicy(options: {\n connectionId: string;\n selectedApi: string;\n accessLevel: AccessLevel;\n}): Policy {\n const { connectionId, selectedApi, accessLevel } = options;\n\n const authStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_use\"],\n resources: [`connection/${connectionId}`],\n conditions: [],\n };\n\n const connectionCondition: Condition = {\n path: [\"connection_id\"],\n operator: \"equals\",\n value: connectionId,\n };\n\n const httpConditions: Condition[] = [connectionCondition];\n if (accessLevel === \"read\") {\n httpConditions.push({\n path: [\"method\"],\n operator: \"in\",\n value: READ_HTTP_METHODS,\n });\n }\n\n const httpStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [\"http\"],\n conditions: httpConditions,\n };\n\n const actionConditions: Condition[] = [connectionCondition];\n if (accessLevel === \"read\") {\n actionConditions.push({\n path: [\"action_type\"],\n operator: \"in\",\n value: READ_ACTION_TYPES,\n });\n }\n\n const actionStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [`action/${selectedApi}/*/*`],\n conditions: actionConditions,\n };\n\n return {\n version: 2,\n statements: [authStatement, httpStatement, actionStatement],\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGA,iBAAkB;AAClB,2BAAgC;AASzB,IAAM,kBAAkB,aAAE,OAAO;AAAA,EACtC,QAAQ,aAAE,OAAO;AAAA,EACjB,MAAM,aAAE,OAAO;AAAA,EACf,MAAM,aAAE,OAAO;AAAA,EACf,MAAM,aAAE,OAAO;AAAA,EACf,OAAO,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,MAAM,aAAE,OAAO,CAAC,CAAC;AACjD,CAAC;AAIM,IAAM,gBAAwC;AAAA,EACnD,MAAM;AAAA,EACN,OAAO;AACT;AAMO,SAAS,SAAS,KAAwB;AAC/C,QAAM,MAAM,IAAI,IAAI,GAAG;AACvB,QAAM,SAAS,IAAI,SAAS,MAAM,GAAG,EAAE,EAAE,YAAY;AACrD,QAAM,OAAO,IAAI,SAAS,YAAY;AACtC,QAAM,OAAO,IAAI,OAAO,SAAS,IAAI,MAAM,EAAE,IAAK,cAAc,MAAM,KAAK;AAC3E,QAAM,OAAO,IAAI,YAAY;AAC7B,QAAM,QAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,KAAK,KAAK,IAAI,cAAc;AAC3C,QAAI,CAAC,MAAM,GAAG,GAAG;AACf,YAAM,GAAG,IAAI,CAAC;AAAA,IAChB;AACA,UAAM,GAAG,EAAE,KAAK,KAAK;AAAA,EACvB;AACA,SAAO,EAAE,QAAQ,MAAM,MAAM,MAAM,MAAM;AAC3C;AAMO,SAAS,eAAe,QAA2B;AACxD,QAAM,EAAE,QAAQ,MAAM,MAAM,MAAM,MAAM,IAAI;AAC5C,QAAM,cAAc,cAAc,MAAM;AACxC,QAAM,aAAa,SAAS,cAAc,IAAI,OAAO,IAAI,CAAC,KAAK;AAC/D,QAAM,SAAS,IAAI,gBAAgB;AACnC,aAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,eAAW,SAAS,QAAQ;AAC1B,aAAO,OAAO,KAAK,KAAK;AAAA,IAC1B;AAAA,EACF;AACA,QAAM,cAAc,OAAO,SAAS;AACpC,SAAO,GAAG,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG,IAAI,GAAG,cAAc,MAAM,cAAc,EAAE;AACvF;AAUO,IAAM,2BAA2B,aAAE,OAAO;AAAA,EAC/C,cAAc,aAAE,QAAQ,cAAc;AAAA,EACtC,QAAQ,aAAE,OAAO;AAAA;AAAA,EAEjB,KAAK;AAAA;AAAA,EAEL,SAAS,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,OAAO,CAAC;AAAA;AAAA,EAExC,MAAM,aAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE1B,WAAW,qCAAgB,SAAS;AAAA;AAAA,EAEpC,eAAe,aAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAEnC,QAAQ,aAAE,OAAO,EAAE,SAAS;AAC9B,CAAC;AAQM,IAAM,yBAAyB,aAAE,OAAO;AAAA,EAC7C,cAAc,aAAE,QAAQ,YAAY;AAAA,EACpC,cAAc,aAAE,OAAO;AAAA,EACvB,aAAa,aAAE,OAAO;AAAA,EACtB,YAAY,aAAE,OAAO;AAAA,EACrB,eAAe,aAAE,OAAO,EAAE,SAAS;AAAA,EACnC,QAAQ,qCAAgB,SAAS;AAAA,EACjC,QAAQ,aAAE,OAAO,EAAE,SAAS;AAC9B,CAAC;AAMM,IAAM,uBAAuB,aAAE,mBAAmB,gBAAgB;AAAA,EACvE;AAAA,EACA;AACF,CAAC;;;ACxGM,IAAM,kBAAkB,oBAAI,IAAI;AAAA;AAAA,EAErC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AACF,CAAC;;;ACrCD,IAAAA,cAAkB;AAWX,IAAM,uCAAuC,cAAE,OAAO;AAAA,EAC3D,QAAQ,cAAE,OAAO;AAAA;AAAA,EAEjB,KAAK,cAAE,OAAO;AAAA;AAAA,EAEd,SAAS,cACN;AAAA,IACC,cAAE,OAAO;AAAA,IACT,cAAE,MAAM,CAAC,cAAE,OAAO,GAAG,cAAE,MAAM,cAAE,OAAO,CAAC,GAAG,cAAE,UAAU,CAAC,CAAC;AAAA,EAC1D,EACC,SAAS;AAAA;AAAA,EAEZ,MAAM,cAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA;AAAA,EAErC,WAAW,qCAAgB,SAAS;AAAA;AAAA,EAEpC,eAAe,cAAE,OAAO,EAAE,SAAS;AACrC,CAAC;AAoBM,SAAS,wBACd,SACoB;AAEpB,QAAM,SAAS,QAAQ,IAAI,SAAS,KAAK,IACrC,QAAQ,MACR,WAAW,QAAQ,GAAG;AAC1B,QAAM,MAAM,SAAS,MAAM;AAG3B,QAAM,UAAkC,CAAC;AACzC,MAAI,QAAQ,SAAS;AACnB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,GAAG;AAC1D,YAAM,WAAW,IAAI,YAAY;AACjC,UAAI,CAAC,gBAAgB,IAAI,QAAQ,KAAK,OAAO,UAAU,UAAU;AAC/D,gBAAQ,QAAQ,IAAI;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAIA,MAAI,YAAqB;AACzB,MAAI,QAAQ,cAAc,QAAW;AACnC,gBAAY,QAAQ;AAAA,EACtB,WAAW,QAAQ,MAAM;AACvB,UAAM,cAAc,QAAQ,cAAc;AAC1C,UAAM,SACJ,OAAO,gBAAgB,aACtB,YAAY,SAAS,kBAAkB,KACrC,YAAY,SAAS,cAAc,KAClC,YAAY,SAAS,OAAO;AAClC,QAAI,QAAQ;AACV,UAAI;AACF,oBAAY,KAAK,MAAM,QAAQ,IAAI;AAAA,MACrC,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,SAAO,yBAAyB,MAAM;AAAA,IACpC,cAAc;AAAA,IACd,QAAQ,QAAQ;AAAA,IAChB;AAAA,IACA;AAAA,IACA,MAAM,QAAQ,QAAQ;AAAA,IACtB;AAAA,IACA,eAAe,QAAQ;AAAA,EACzB,CAAC;AACH;AAEO,IAAM,qCAAqC,cAAE,OAAO;AAAA,EACzD,cAAc,cAAE,OAAO;AAAA,EACvB,aAAa,cAAE,OAAO;AAAA,EACtB,YAAY,cAAE,OAAO;AAAA,EACrB,eAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,QAAQ,qCAAgB,SAAS;AACnC,CAAC;AAQM,SAAS,sBACd,SACkB;AAClB,SAAO,uBAAuB,MAAM;AAAA,IAClC,cAAc;AAAA,IACd,cAAc,QAAQ;AAAA,IACtB,aAAa,QAAQ;AAAA,IACrB,YAAY,QAAQ;AAAA,IACpB,eAAe,QAAQ;AAAA,IACvB,QAAQ,QAAQ;AAAA,EAClB,CAAC;AACH;;;AChHO,SAAS,yBACd,SACa;AACb,QAAM,aAA0B;AAAA,IAC9B,EAAE,MAAM,CAAC,QAAQ,GAAG,UAAU,UAAU,OAAO,QAAQ,OAAO;AAAA,EAChE;AAEA,QAAM,EAAE,IAAI,IAAI;AAGhB,QAAM,cACJ,IAAI,WAAW,UAAU,MAAM,IAAI,WAAW,SAAS,KAAK;AAC9D,QAAM,aAAa,IAAI,SAAS,cAAc,IAAI,OAAO,IAAI,IAAI,CAAC,KAAK;AACvE,QAAM,kBAAkB,GAAG,IAAI,MAAM,MAAM,IAAI,IAAI,GAAG,UAAU,GAAG,IAAI,IAAI;AAC3E,aAAW,KAAK;AAAA,IACd,MAAM,CAAC,KAAK;AAAA,IACZ,UAAU;AAAA,IACV,OAAO;AAAA,EACT,CAAC;AAGD,aAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,IAAI,KAAK,GAAG;AACrD,eAAW,KAAK;AAAA,MACd,MAAM,CAAC,OAAO,SAAS,GAAG;AAAA,MAC1B,UAAU;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAGA,MAAI,QAAQ,cAAc,MAAM;AAC9B,eAAW,KAAK;AAAA,MACd,MAAM,CAAC,WAAW;AAAA,MAClB,UAAU;AAAA,MACV,OAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,GAAG;AAC1D,QAAI,CAAC,gBAAgB,IAAI,IAAI,YAAY,CAAC,KAAK,OAAO,UAAU,UAAU;AACxE,iBAAW,KAAK;AAAA,QACd,MAAM,CAAC,WAAW,IAAI,YAAY,CAAC;AAAA,QACnC,UAAU;AAAA,QACV;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAQO,SAAS,0BACd,SACa;AACb,SAAO;AAAA,IACL;AAAA,MACE,MAAM,CAAC,OAAO,MAAM;AAAA,MACpB,UAAU;AAAA,MACV,OAAO,QAAQ,IAAI;AAAA,IACrB;AAAA,EACF;AACF;AAOO,SAAS,2BACd,SACa;AACb,QAAM,aAA0B,CAAC;AAEjC,MACE,QAAQ,WAAW,UACnB,QAAQ,WAAW,QACnB,OAAO,QAAQ,WAAW,UAC1B;AACA,eAAW,KAAK;AAAA,MACd,MAAM,CAAC,QAAQ;AAAA,MACf,UAAU;AAAA,MACV,OAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAMO,SAAS,oBAAoB,SAAmC;AACrE,SAAO,UAAU,QAAQ,YAAY,IAAI,QAAQ,WAAW,IAAI,QAAQ,UAAU;AACpF;AAMO,SAAS,yBAAyB,SAAmC;AAC1E,SAAO,UAAU,QAAQ,YAAY;AACvC;;;AC3GA,SAAS,mBAAmB,kBAAqC;AAC/D,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,aAAa,CAAC,SAAS;AAAA,IACvB,WAAW,CAAC,cAAc,gBAAgB,EAAE;AAAA,IAC5C,YAAY,CAAC;AAAA,EACf;AACF;AAUA,SAAS,oBAAoB,SAAqC;AAChE,QAAM,aAA0B,CAAC;AAEjC,MAAI,QAAQ,eAAe;AACzB,eAAW,KAAK,mBAAmB,QAAQ,aAAa,CAAC;AAAA,EAC3D;AAEA,QAAM,aAAa,yBAAyB,OAAO;AAInD,aAAW,KAAK;AAAA,IACd,MAAM,CAAC,OAAO,OAAO;AAAA,IACrB,UAAU;AAAA,IACV,OAAO,OAAO,KAAK,QAAQ,IAAI,KAAK;AAAA,EACtC,CAAC;AAED,aAAW,KAAK;AAAA,IACd,QAAQ;AAAA,IACR,aAAa,CAAC,aAAa;AAAA,IAC3B,WAAW,CAAC,MAAM;AAAA,IAClB;AAAA,EACF,CAAC;AAED,SAAO,EAAE,SAAS,GAAG,WAAW;AAClC;AASA,SAAS,sBAAsB,SAAmC;AAChE,QAAM,aAA0B,CAAC;AAEjC,MAAI,QAAQ,eAAe;AACzB,eAAW,KAAK,mBAAmB,QAAQ,aAAa,CAAC;AAAA,EAC3D;AAEA,aAAW,KAAK;AAAA,IACd,QAAQ;AAAA,IACR,aAAa,CAAC,aAAa;AAAA,IAC3B,WAAW,CAAC,oBAAoB,OAAO,CAAC;AAAA,IACxC,YAAY,2BAA2B,OAAO;AAAA,EAChD,CAAC;AAED,SAAO,EAAE,SAAS,GAAG,WAAW;AAClC;AAQO,SAAS,cAAc,SAAiC;AAC7D,MAAI,QAAQ,iBAAiB,gBAAgB;AAC3C,WAAO,oBAAoB,OAAO;AAAA,EACpC;AACA,SAAO,sBAAsB,OAAO;AACtC;;;AC9FA,IAAAC,cAAkB;AAGX,IAAM,oBAAoB,cAAE,KAAK,CAAC,QAAQ,YAAY,CAAC;AAG9D,IAAM,oBAAoB,CAAC,OAAO,QAAQ,SAAS;AACnD,IAAM,oBAAoB,CAAC,QAAQ,QAAQ;AAUpC,SAAS,sBAAsB,SAI3B;AACT,QAAM,EAAE,cAAc,aAAa,YAAY,IAAI;AAEnD,QAAM,gBAA2B;AAAA,IAC/B,QAAQ;AAAA,IACR,aAAa,CAAC,SAAS;AAAA,IACvB,WAAW,CAAC,cAAc,YAAY,EAAE;AAAA,IACxC,YAAY,CAAC;AAAA,EACf;AAEA,QAAM,sBAAiC;AAAA,IACrC,MAAM,CAAC,eAAe;AAAA,IACtB,UAAU;AAAA,IACV,OAAO;AAAA,EACT;AAEA,QAAM,iBAA8B,CAAC,mBAAmB;AACxD,MAAI,gBAAgB,QAAQ;AAC1B,mBAAe,KAAK;AAAA,MAClB,MAAM,CAAC,QAAQ;AAAA,MACf,UAAU;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,gBAA2B;AAAA,IAC/B,QAAQ;AAAA,IACR,aAAa,CAAC,aAAa;AAAA,IAC3B,WAAW,CAAC,MAAM;AAAA,IAClB,YAAY;AAAA,EACd;AAEA,QAAM,mBAAgC,CAAC,mBAAmB;AAC1D,MAAI,gBAAgB,QAAQ;AAC1B,qBAAiB,KAAK;AAAA,MACpB,MAAM,CAAC,aAAa;AAAA,MACpB,UAAU;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,kBAA6B;AAAA,IACjC,QAAQ;AAAA,IACR,aAAa,CAAC,aAAa;AAAA,IAC3B,WAAW,CAAC,UAAU,WAAW,MAAM;AAAA,IACvC,YAAY;AAAA,EACd;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,YAAY,CAAC,eAAe,eAAe,eAAe;AAAA,EAC5D;AACF;","names":["import_zod","import_zod"]}
package/dist/index.d.cts CHANGED
@@ -1,12 +1,8 @@
1
- import { z } from 'zod';
2
1
  import * as _zapier_policy_schema from '@zapier/policy-schema';
3
- import { JsonValue, Condition, Policy } from '@zapier/policy-schema';
2
+ import { Condition, Policy } from '@zapier/policy-schema';
3
+ export { JsonValueSchema } from '@zapier/policy-schema';
4
+ import { z } from 'zod';
4
5
 
5
- /**
6
- * Zod schema for arbitrary JSON values. Used across context schemas for
7
- * unstructured fields like `body_json` and `inputs`.
8
- */
9
- declare const JsonValueSchema: z.ZodCustom<JsonValue, JsonValue>;
10
6
  /**
11
7
  * Parsed URL components for policy evaluation.
12
8
  * Matches the ParsedUrl shape from @zapier/policy-schema so that
@@ -52,7 +48,7 @@ declare const HttpRequestContextSchema: z.ZodObject<{
52
48
  }, z.core.$strip>;
53
49
  headers: z.ZodRecord<z.ZodString, z.ZodString>;
54
50
  body: z.ZodNullable<z.ZodString>;
55
- body_json: z.ZodNullable<z.ZodCustom<JsonValue, JsonValue>>;
51
+ body_json: z.ZodNullable<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
56
52
  connection_id: z.ZodOptional<z.ZodString>;
57
53
  reason: z.ZodOptional<z.ZodString>;
58
54
  }, z.core.$strip>;
@@ -68,7 +64,7 @@ declare const ActionRunContextSchema: z.ZodObject<{
68
64
  action_type: z.ZodString;
69
65
  action_key: z.ZodString;
70
66
  connection_id: z.ZodOptional<z.ZodString>;
71
- inputs: z.ZodOptional<z.ZodCustom<JsonValue, JsonValue>>;
67
+ inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
72
68
  reason: z.ZodOptional<z.ZodString>;
73
69
  }, z.core.$strip>;
74
70
  type ActionRunContext = z.infer<typeof ActionRunContextSchema>;
@@ -87,7 +83,7 @@ declare const RequestContextSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
87
83
  }, z.core.$strip>;
88
84
  headers: z.ZodRecord<z.ZodString, z.ZodString>;
89
85
  body: z.ZodNullable<z.ZodString>;
90
- body_json: z.ZodNullable<z.ZodCustom<JsonValue, JsonValue>>;
86
+ body_json: z.ZodNullable<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
91
87
  connection_id: z.ZodOptional<z.ZodString>;
92
88
  reason: z.ZodOptional<z.ZodString>;
93
89
  }, z.core.$strip>, z.ZodObject<{
@@ -96,7 +92,7 @@ declare const RequestContextSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
96
92
  action_type: z.ZodString;
97
93
  action_key: z.ZodString;
98
94
  connection_id: z.ZodOptional<z.ZodString>;
99
- inputs: z.ZodOptional<z.ZodCustom<JsonValue, JsonValue>>;
95
+ inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
100
96
  reason: z.ZodOptional<z.ZodString>;
101
97
  }, z.core.$strip>], "request_type">;
102
98
  type RequestContext = z.infer<typeof RequestContextSchema>;
@@ -115,7 +111,7 @@ declare const BuildHttpRequestContextOptionsSchema: z.ZodObject<{
115
111
  url: z.ZodString;
116
112
  headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodUndefined]>>>;
117
113
  body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
118
- body_json: z.ZodOptional<z.ZodCustom<_zapier_policy_schema.JsonValue, _zapier_policy_schema.JsonValue>>;
114
+ body_json: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
119
115
  connection_id: z.ZodOptional<z.ZodString>;
120
116
  }, z.core.$strip>;
121
117
  type BuildHttpRequestContextOptions = z.infer<typeof BuildHttpRequestContextOptionsSchema>;
@@ -140,7 +136,7 @@ declare const BuildActionRunContextOptionsSchema: z.ZodObject<{
140
136
  action_type: z.ZodString;
141
137
  action_key: z.ZodString;
142
138
  connection_id: z.ZodOptional<z.ZodString>;
143
- inputs: z.ZodOptional<z.ZodCustom<_zapier_policy_schema.JsonValue, _zapier_policy_schema.JsonValue>>;
139
+ inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
144
140
  }, z.core.$strip>;
145
141
  type BuildActionRunContextOptions = z.infer<typeof BuildActionRunContextOptionsSchema>;
146
142
  /**
@@ -209,4 +205,4 @@ declare function buildConnectionPolicy(options: {
209
205
  accessLevel: AccessLevel;
210
206
  }): Policy;
211
207
 
212
- export { type AccessLevel, AccessLevelSchema, type ActionRunContext, ActionRunContextSchema, type BuildActionRunContextOptions, BuildActionRunContextOptionsSchema, type BuildHttpRequestContextOptions, BuildHttpRequestContextOptionsSchema, DEFAULT_PORTS, type HttpRequestContext, HttpRequestContextSchema, IGNORED_HEADERS, JsonValueSchema, type ParsedUrl, ParsedUrlSchema, type RequestContext, RequestContextSchema, buildActionResource, buildActionRunContext, buildBroadActionResource, buildConnectionPolicy, buildDomainHttpConditions, buildExactActionConditions, buildExactHttpConditions, buildHttpRequestContext, buildUrlString, parseUrl, toExactPolicy };
208
+ export { type AccessLevel, AccessLevelSchema, type ActionRunContext, ActionRunContextSchema, type BuildActionRunContextOptions, BuildActionRunContextOptionsSchema, type BuildHttpRequestContextOptions, BuildHttpRequestContextOptionsSchema, DEFAULT_PORTS, type HttpRequestContext, HttpRequestContextSchema, IGNORED_HEADERS, type ParsedUrl, ParsedUrlSchema, type RequestContext, RequestContextSchema, buildActionResource, buildActionRunContext, buildBroadActionResource, buildConnectionPolicy, buildDomainHttpConditions, buildExactActionConditions, buildExactHttpConditions, buildHttpRequestContext, buildUrlString, parseUrl, toExactPolicy };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,8 @@
1
- import { z } from 'zod';
2
1
  import * as _zapier_policy_schema from '@zapier/policy-schema';
3
- import { JsonValue, Condition, Policy } from '@zapier/policy-schema';
2
+ import { Condition, Policy } from '@zapier/policy-schema';
3
+ export { JsonValueSchema } from '@zapier/policy-schema';
4
+ import { z } from 'zod';
4
5
 
5
- /**
6
- * Zod schema for arbitrary JSON values. Used across context schemas for
7
- * unstructured fields like `body_json` and `inputs`.
8
- */
9
- declare const JsonValueSchema: z.ZodCustom<JsonValue, JsonValue>;
10
6
  /**
11
7
  * Parsed URL components for policy evaluation.
12
8
  * Matches the ParsedUrl shape from @zapier/policy-schema so that
@@ -52,7 +48,7 @@ declare const HttpRequestContextSchema: z.ZodObject<{
52
48
  }, z.core.$strip>;
53
49
  headers: z.ZodRecord<z.ZodString, z.ZodString>;
54
50
  body: z.ZodNullable<z.ZodString>;
55
- body_json: z.ZodNullable<z.ZodCustom<JsonValue, JsonValue>>;
51
+ body_json: z.ZodNullable<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
56
52
  connection_id: z.ZodOptional<z.ZodString>;
57
53
  reason: z.ZodOptional<z.ZodString>;
58
54
  }, z.core.$strip>;
@@ -68,7 +64,7 @@ declare const ActionRunContextSchema: z.ZodObject<{
68
64
  action_type: z.ZodString;
69
65
  action_key: z.ZodString;
70
66
  connection_id: z.ZodOptional<z.ZodString>;
71
- inputs: z.ZodOptional<z.ZodCustom<JsonValue, JsonValue>>;
67
+ inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
72
68
  reason: z.ZodOptional<z.ZodString>;
73
69
  }, z.core.$strip>;
74
70
  type ActionRunContext = z.infer<typeof ActionRunContextSchema>;
@@ -87,7 +83,7 @@ declare const RequestContextSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
87
83
  }, z.core.$strip>;
88
84
  headers: z.ZodRecord<z.ZodString, z.ZodString>;
89
85
  body: z.ZodNullable<z.ZodString>;
90
- body_json: z.ZodNullable<z.ZodCustom<JsonValue, JsonValue>>;
86
+ body_json: z.ZodNullable<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
91
87
  connection_id: z.ZodOptional<z.ZodString>;
92
88
  reason: z.ZodOptional<z.ZodString>;
93
89
  }, z.core.$strip>, z.ZodObject<{
@@ -96,7 +92,7 @@ declare const RequestContextSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
96
92
  action_type: z.ZodString;
97
93
  action_key: z.ZodString;
98
94
  connection_id: z.ZodOptional<z.ZodString>;
99
- inputs: z.ZodOptional<z.ZodCustom<JsonValue, JsonValue>>;
95
+ inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
100
96
  reason: z.ZodOptional<z.ZodString>;
101
97
  }, z.core.$strip>], "request_type">;
102
98
  type RequestContext = z.infer<typeof RequestContextSchema>;
@@ -115,7 +111,7 @@ declare const BuildHttpRequestContextOptionsSchema: z.ZodObject<{
115
111
  url: z.ZodString;
116
112
  headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodUndefined]>>>;
117
113
  body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
118
- body_json: z.ZodOptional<z.ZodCustom<_zapier_policy_schema.JsonValue, _zapier_policy_schema.JsonValue>>;
114
+ body_json: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
119
115
  connection_id: z.ZodOptional<z.ZodString>;
120
116
  }, z.core.$strip>;
121
117
  type BuildHttpRequestContextOptions = z.infer<typeof BuildHttpRequestContextOptionsSchema>;
@@ -140,7 +136,7 @@ declare const BuildActionRunContextOptionsSchema: z.ZodObject<{
140
136
  action_type: z.ZodString;
141
137
  action_key: z.ZodString;
142
138
  connection_id: z.ZodOptional<z.ZodString>;
143
- inputs: z.ZodOptional<z.ZodCustom<_zapier_policy_schema.JsonValue, _zapier_policy_schema.JsonValue>>;
139
+ inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
144
140
  }, z.core.$strip>;
145
141
  type BuildActionRunContextOptions = z.infer<typeof BuildActionRunContextOptionsSchema>;
146
142
  /**
@@ -209,4 +205,4 @@ declare function buildConnectionPolicy(options: {
209
205
  accessLevel: AccessLevel;
210
206
  }): Policy;
211
207
 
212
- export { type AccessLevel, AccessLevelSchema, type ActionRunContext, ActionRunContextSchema, type BuildActionRunContextOptions, BuildActionRunContextOptionsSchema, type BuildHttpRequestContextOptions, BuildHttpRequestContextOptionsSchema, DEFAULT_PORTS, type HttpRequestContext, HttpRequestContextSchema, IGNORED_HEADERS, JsonValueSchema, type ParsedUrl, ParsedUrlSchema, type RequestContext, RequestContextSchema, buildActionResource, buildActionRunContext, buildBroadActionResource, buildConnectionPolicy, buildDomainHttpConditions, buildExactActionConditions, buildExactHttpConditions, buildHttpRequestContext, buildUrlString, parseUrl, toExactPolicy };
208
+ export { type AccessLevel, AccessLevelSchema, type ActionRunContext, ActionRunContextSchema, type BuildActionRunContextOptions, BuildActionRunContextOptionsSchema, type BuildHttpRequestContextOptions, BuildHttpRequestContextOptionsSchema, DEFAULT_PORTS, type HttpRequestContext, HttpRequestContextSchema, IGNORED_HEADERS, type ParsedUrl, ParsedUrlSchema, type RequestContext, RequestContextSchema, buildActionResource, buildActionRunContext, buildBroadActionResource, buildConnectionPolicy, buildDomainHttpConditions, buildExactActionConditions, buildExactHttpConditions, buildHttpRequestContext, buildUrlString, parseUrl, toExactPolicy };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/types.ts
2
2
  import { z } from "zod";
3
- var JsonValueSchema = z.custom();
3
+ import { JsonValueSchema } from "@zapier/policy-schema";
4
4
  var ParsedUrlSchema = z.object({
5
5
  scheme: z.string(),
6
6
  host: z.string(),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/constants.ts","../src/builders.ts","../src/conditions.ts","../src/policies.ts","../src/connection-policy.ts"],"sourcesContent":["// ABOUTME: Canonical request context types shared between sdkapi and approvalsapi.\n// ABOUTME: These define the contract for how requests are described in approval flows and policy evaluation.\n\nimport { z } from \"zod\";\nimport type { JsonValue } from \"@zapier/policy-schema\";\n\n/**\n * Zod schema for arbitrary JSON values. Used across context schemas for\n * unstructured fields like `body_json` and `inputs`.\n */\nexport const JsonValueSchema = z.custom<JsonValue>();\n\n/**\n * Parsed URL components for policy evaluation.\n * Matches the ParsedUrl shape from @zapier/policy-schema so that\n * evaluatePolicy condition paths like [\"url\", \"host\"] resolve correctly.\n */\nexport const ParsedUrlSchema = z.object({\n scheme: z.string(),\n host: z.string(),\n port: z.number(),\n path: z.string(),\n query: z.record(z.string(), z.array(z.string())),\n});\nexport type ParsedUrl = z.infer<typeof ParsedUrlSchema>;\n\n/** Default ports by scheme, used when URL has no explicit port. */\nexport const DEFAULT_PORTS: Record<string, number> = {\n http: 80,\n https: 443,\n};\n\n/**\n * Parse a raw URL string into a ParsedUrl.\n * Same logic as parseUrlForPolicyContext in @zapier/policy.\n */\nexport function parseUrl(raw: string): ParsedUrl {\n const url = new URL(raw);\n const scheme = url.protocol.slice(0, -1).toLowerCase();\n const host = url.hostname.toLowerCase();\n const port = url.port ? parseInt(url.port, 10) : (DEFAULT_PORTS[scheme] ?? 0);\n const path = url.pathname || \"/\";\n const query: Record<string, string[]> = {};\n for (const [key, value] of url.searchParams) {\n if (!query[key]) {\n query[key] = [];\n }\n query[key].push(value);\n }\n return { scheme, host, port, path, query };\n}\n\n/**\n * Reconstruct a URL string from a ParsedUrl.\n * Same logic as buildUrl in @zapier/policy.\n */\nexport function buildUrlString(parsed: ParsedUrl): string {\n const { scheme, host, port, path, query } = parsed;\n const defaultPort = DEFAULT_PORTS[scheme];\n const portString = port !== defaultPort ? `:${String(port)}` : \"\";\n const params = new URLSearchParams();\n for (const [key, values] of Object.entries(query)) {\n for (const value of values) {\n params.append(key, value);\n }\n }\n const queryString = params.toString();\n return `${scheme}://${host}${portString}${path}${queryString ? \"?\" + queryString : \"\"}`;\n}\n\n/**\n * HTTP request context for approval/policy flows.\n * Sent by sdkapi when a relay request is denied, stored by approvalsapi,\n * and used for both policy evaluation and building policy conditions.\n *\n * The url field is a ParsedUrl object (matching @zapier/policy-schema's ParsedUrl)\n * so that evaluatePolicy conditions like [\"url\", \"host\"] resolve correctly.\n */\nexport const HttpRequestContextSchema = z.object({\n request_type: z.literal(\"http_request\"),\n method: z.string(),\n /** Parsed URL components for policy condition matching */\n url: ParsedUrlSchema,\n /** Filtered headers (IGNORED_HEADERS excluded, keys lowercased) */\n headers: z.record(z.string(), z.string()),\n /** Raw body string */\n body: z.string().nullable(),\n /** Parsed JSON body */\n body_json: JsonValueSchema.nullable(),\n /** Zapier connection ID used for this request */\n connection_id: z.string().optional(),\n /** Optional human-readable reason for the request */\n reason: z.string().optional(),\n});\nexport type HttpRequestContext = z.infer<typeof HttpRequestContextSchema>;\n\n/**\n * Action run context for approval/policy flows.\n * Sent by sdkapi when an action run is denied, stored by approvalsapi,\n * and used to build policy conditions.\n */\nexport const ActionRunContextSchema = z.object({\n request_type: z.literal(\"action_run\"),\n selected_api: z.string(),\n action_type: z.string(),\n action_key: z.string(),\n connection_id: z.string().optional(),\n inputs: JsonValueSchema.optional(),\n reason: z.string().optional(),\n});\nexport type ActionRunContext = z.infer<typeof ActionRunContextSchema>;\n\n/**\n * Discriminated union of all request context types.\n */\nexport const RequestContextSchema = z.discriminatedUnion(\"request_type\", [\n HttpRequestContextSchema,\n ActionRunContextSchema,\n]);\nexport type RequestContext = z.infer<typeof RequestContextSchema>;\n","// ABOUTME: Canonical set of headers to exclude when building request contexts.\n// ABOUTME: Shared between sdkapi (context creation) and approvalsapi (condition building).\n\n/**\n * Headers to exclude when building request contexts from raw HTTP requests.\n *\n * These are either sensitive (auth credentials), HTTP infrastructure headers\n * that vary per-request, or proxy-internal headers that are not meaningful\n * for policy decisions.\n */\nexport const IGNORED_HEADERS = new Set([\n // Auth / credentials — never include in contexts or policy conditions\n \"authorization\",\n \"x-relay-authorization\",\n \"x-relay-authentication-id\",\n \"x-api-key\",\n \"cookie\",\n \"set-cookie\",\n \"proxy-authorization\",\n\n // HTTP infrastructure — varies per-request, not policy-relevant\n \"host\",\n \"connection\",\n \"content-length\",\n \"transfer-encoding\",\n \"accept-encoding\",\n \"user-agent\",\n \"accept\",\n \"accept-language\",\n \"sec-fetch-mode\",\n\n // Proxy / forwarding — infrastructure, not meaningful for policy\n \"x-forwarded-for\",\n \"x-forwarded-host\",\n \"x-forwarded-proto\",\n \"x-real-ip\",\n\n // Proxy internal — sdkapi-specific headers\n \"x-is-interactive-session\",\n \"x-relay-callback-url\",\n]);\n","// ABOUTME: Canonical builders for creating request contexts from raw request parts.\n// ABOUTME: Used by sdkapi to build both approval contexts and policy eval contexts.\n\nimport { z } from \"zod\";\nimport {\n HttpRequestContextSchema,\n ActionRunContextSchema,\n JsonValueSchema,\n parseUrl,\n type HttpRequestContext,\n type ActionRunContext,\n} from \"./types.ts\";\nimport { IGNORED_HEADERS } from \"./constants.ts\";\n\nexport const BuildHttpRequestContextOptionsSchema = z.object({\n method: z.string(),\n /** Raw URL string. Will be normalized with https:// if no protocol present. */\n url: z.string(),\n /** Raw headers from the request. Will be filtered through IGNORED_HEADERS. */\n headers: z\n .record(\n z.string(),\n z.union([z.string(), z.array(z.string()), z.undefined()]),\n )\n .optional(),\n /** Raw body string */\n body: z.string().nullable().optional(),\n /** Pre-parsed JSON body (e.g. from Fastify's automatic JSON parsing) */\n body_json: JsonValueSchema.optional(),\n /** Connection ID associated with this request */\n connection_id: z.string().optional(),\n});\nexport type BuildHttpRequestContextOptions = z.infer<\n typeof BuildHttpRequestContextOptionsSchema\n>;\n\n/**\n * Build a canonical HttpRequestContext from raw request parts.\n *\n * This is the single source of truth for how HTTP request contexts are created.\n * Both sdkapi (for policy evaluation) and approvalsapi (for context storage)\n * should use this to ensure the context shape is consistent.\n *\n * Matches the behavior of createPolicyHttpRequest from @zapier/policy, with\n * the addition of header filtering through IGNORED_HEADERS.\n *\n * - Normalizes URL (adds https:// if missing) and parses into { scheme, host, port, path, query }\n * - Filters headers through IGNORED_HEADERS, lowercases keys, string values only\n * - Auto-parses body_json from body when content-type is JSON and body_json not provided\n * - body defaults to null (not undefined)\n */\nexport function buildHttpRequestContext(\n options: BuildHttpRequestContextOptions,\n): HttpRequestContext {\n // Normalize URL — SDK CLI strips the protocol\n const rawUrl = options.url.includes(\"://\")\n ? options.url\n : `https://${options.url}`;\n const url = parseUrl(rawUrl);\n\n // Filter headers: exclude ignored, lowercase keys, string values only\n const headers: Record<string, string> = {};\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n const lowerKey = key.toLowerCase();\n if (!IGNORED_HEADERS.has(lowerKey) && typeof value === \"string\") {\n headers[lowerKey] = value;\n }\n }\n }\n\n // Auto-parse body_json from body when content-type is JSON\n // (matches createPolicyHttpRequest behavior from @zapier/policy)\n let body_json: unknown = null;\n if (options.body_json !== undefined) {\n body_json = options.body_json;\n } else if (options.body) {\n const contentType = headers[\"content-type\"];\n const isJson =\n typeof contentType === \"string\" &&\n (contentType.includes(\"application/json\") ||\n (contentType.includes(\"application/\") &&\n contentType.includes(\"+json\")));\n if (isJson) {\n try {\n body_json = JSON.parse(options.body);\n } catch {\n // Invalid JSON body — leave body_json as null\n }\n }\n }\n\n return HttpRequestContextSchema.parse({\n request_type: \"http_request\",\n method: options.method,\n url,\n headers,\n body: options.body ?? null,\n body_json,\n connection_id: options.connection_id,\n });\n}\n\nexport const BuildActionRunContextOptionsSchema = z.object({\n selected_api: z.string(),\n action_type: z.string(),\n action_key: z.string(),\n connection_id: z.string().optional(),\n inputs: JsonValueSchema.optional(),\n});\nexport type BuildActionRunContextOptions = z.infer<\n typeof BuildActionRunContextOptionsSchema\n>;\n\n/**\n * Build a canonical ActionRunContext from raw action parts.\n */\nexport function buildActionRunContext(\n options: BuildActionRunContextOptions,\n): ActionRunContext {\n return ActionRunContextSchema.parse({\n request_type: \"action_run\",\n selected_api: options.selected_api,\n action_type: options.action_type,\n action_key: options.action_key,\n connection_id: options.connection_id,\n inputs: options.inputs,\n });\n}\n","// ABOUTME: Builds policy conditions from stored request contexts.\n// ABOUTME: Used by approvalsapi's \"allow exact request\" and \"allow domain\" instant policy flows.\n\nimport type { Condition } from \"@zapier/policy-schema\";\nimport type { HttpRequestContext, ActionRunContext } from \"./types.ts\";\nimport { IGNORED_HEADERS } from \"./constants.ts\";\n\n/**\n * Build conditions that match an exact HTTP request.\n *\n * Handles the matches_url / query param split correctly:\n * - `matches_url` only supports scheme+host+port+path (no query string per spec)\n * - Query parameters are added as separate decomposed conditions on `url.query.<key>`\n *\n * @returns Condition[] for an http permission statement\n */\nexport function buildExactHttpConditions(\n context: HttpRequestContext,\n): Condition[] {\n const conditions: Condition[] = [\n { path: [\"method\"], operator: \"equals\", value: context.method },\n ];\n\n const { url } = context;\n\n // matches_url condition uses URL without query string (per @zapier/policy spec)\n const defaultPort =\n url.scheme === \"https\" ? 443 : url.scheme === \"http\" ? 80 : 0;\n const portString = url.port !== defaultPort ? `:${String(url.port)}` : \"\";\n const urlWithoutQuery = `${url.scheme}://${url.host}${portString}${url.path}`;\n conditions.push({\n path: [\"url\"],\n operator: \"matches_url\",\n value: urlWithoutQuery,\n });\n\n // Add decomposed conditions for each query parameter.\n for (const [key, values] of Object.entries(url.query)) {\n conditions.push({\n path: [\"url\", \"query\", key],\n operator: \"equals\",\n value: values,\n });\n }\n\n // body_json condition\n if (context.body_json !== null) {\n conditions.push({\n path: [\"body_json\"],\n operator: \"equals\",\n value: context.body_json,\n });\n }\n\n // Header conditions (filtered through IGNORED_HEADERS again for safety)\n for (const [key, value] of Object.entries(context.headers)) {\n if (!IGNORED_HEADERS.has(key.toLowerCase()) && typeof value === \"string\") {\n conditions.push({\n path: [\"headers\", key.toLowerCase()],\n operator: \"equals\",\n value,\n });\n }\n }\n\n return conditions;\n}\n\n/**\n * Build conditions that match any request to a given domain.\n * Uses the host from the parsed URL.\n *\n * @returns Condition[] for an http permission statement\n */\nexport function buildDomainHttpConditions(\n context: HttpRequestContext,\n): Condition[] {\n return [\n {\n path: [\"url\", \"host\"],\n operator: \"matches_host\",\n value: context.url.host,\n },\n ];\n}\n\n/**\n * Build conditions that match an exact action run (with inputs).\n *\n * @returns Condition[] for an action permission statement\n */\nexport function buildExactActionConditions(\n context: ActionRunContext,\n): Condition[] {\n const conditions: Condition[] = [];\n\n if (\n context.inputs !== undefined &&\n context.inputs !== null &&\n typeof context.inputs === \"object\"\n ) {\n conditions.push({\n path: [\"inputs\"],\n operator: \"equals\",\n value: context.inputs,\n });\n }\n\n return conditions;\n}\n\n/**\n * Build the resource string for an action.\n * Format: action/{selected_api}/{action_type}/{action_key}\n */\nexport function buildActionResource(context: ActionRunContext): string {\n return `action/${context.selected_api}/${context.action_type}/${context.action_key}`;\n}\n\n/**\n * Build a broad action resource that matches all actions for an app.\n * Format: action/{selected_api}/{wildcard}/{wildcard}\n */\nexport function buildBroadActionResource(context: ActionRunContext): string {\n return `action/${context.selected_api}/*/*`;\n}\n","// ABOUTME: Assembles complete Policy objects from request contexts.\n// ABOUTME: Single source of truth for \"exact request\" instant policies used by web UI and API.\n\nimport type { Policy, Statement } from \"@zapier/policy-schema\";\nimport type {\n RequestContext,\n HttpRequestContext,\n ActionRunContext,\n} from \"./types.ts\";\nimport {\n buildExactHttpConditions,\n buildExactActionConditions,\n buildActionResource,\n} from \"./conditions.ts\";\n\n/**\n * Build a `can_use` authentication statement, if the context has a connection_id.\n */\nfunction buildAuthStatement(authenticationId: string): Statement {\n return {\n effect: \"allow\",\n permissions: [\"can_use\"],\n resources: [`connection/${authenticationId}`],\n conditions: [],\n };\n}\n\n/**\n * Build an exact-match policy from an HTTP request context.\n *\n * Produces a policy that allows only the specific request described by the context:\n * - `can_use` statement for the authentication (if present)\n * - `can_execute` statement for `http` with conditions from `buildExactHttpConditions`\n * plus a `keys_in` guard restricting allowed query parameter keys\n */\nfunction httpContextToPolicy(context: HttpRequestContext): Policy {\n const statements: Statement[] = [];\n\n if (context.connection_id) {\n statements.push(buildAuthStatement(context.connection_id));\n }\n\n const conditions = buildExactHttpConditions(context);\n\n // Add a keys_in guard so only the query param keys present in the original\n // request are allowed — blocks injection of extra query params.\n conditions.push({\n path: [\"url\", \"query\"],\n operator: \"keys_in\",\n value: Object.keys(context.url.query),\n });\n\n statements.push({\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [\"http\"],\n conditions,\n });\n\n return { version: 2, statements };\n}\n\n/**\n * Build an exact-match policy from an action run context.\n *\n * Produces a policy that allows only the specific action described by the context:\n * - `can_use` statement for the authentication (if present)\n * - `can_execute` statement for the action resource with input conditions\n */\nfunction actionContextToPolicy(context: ActionRunContext): Policy {\n const statements: Statement[] = [];\n\n if (context.connection_id) {\n statements.push(buildAuthStatement(context.connection_id));\n }\n\n statements.push({\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [buildActionResource(context)],\n conditions: buildExactActionConditions(context),\n });\n\n return { version: 2, statements };\n}\n\n/**\n * Build an exact-match policy from any supported request context.\n *\n * This is the single source of truth for \"allow this exact request\" instant policies.\n * Used by the web UI and anywhere else that needs to produce an exact policy from a context.\n */\nexport function toExactPolicy(context: RequestContext): Policy {\n if (context.request_type === \"http_request\") {\n return httpContextToPolicy(context);\n }\n return actionContextToPolicy(context);\n}\n","// ABOUTME: Builds connection-level policies for the basic approvals MVP.\n// ABOUTME: Generates deterministic policies that allow read or read+write access scoped to a specific connection.\n\nimport { z } from \"zod\";\nimport type { Policy, Statement, Condition } from \"@zapier/policy-schema\";\n\nexport const AccessLevelSchema = z.enum([\"read\", \"read_write\"]);\nexport type AccessLevel = z.infer<typeof AccessLevelSchema>;\n\nconst READ_HTTP_METHODS = [\"GET\", \"HEAD\", \"OPTIONS\"];\nconst READ_ACTION_TYPES = [\"read\", \"search\"];\n\n/**\n * Build a connection-level policy that covers both HTTP and action access.\n *\n * Always produces three statements:\n * 1. `can_use` for the authentication\n * 2. `can_execute` on `http` scoped by connection_id (+ method filter for read)\n * 3. `can_execute` on `action/{selectedApi}/**` scoped by connection_id (+ action_type filter for read)\n */\nexport function buildConnectionPolicy(options: {\n connectionId: string;\n selectedApi: string;\n accessLevel: AccessLevel;\n}): Policy {\n const { connectionId, selectedApi, accessLevel } = options;\n\n const authStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_use\"],\n resources: [`connection/${connectionId}`],\n conditions: [],\n };\n\n const connectionCondition: Condition = {\n path: [\"connection_id\"],\n operator: \"equals\",\n value: connectionId,\n };\n\n const httpConditions: Condition[] = [connectionCondition];\n if (accessLevel === \"read\") {\n httpConditions.push({\n path: [\"method\"],\n operator: \"in\",\n value: READ_HTTP_METHODS,\n });\n }\n\n const httpStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [\"http\"],\n conditions: httpConditions,\n };\n\n const actionConditions: Condition[] = [connectionCondition];\n if (accessLevel === \"read\") {\n actionConditions.push({\n path: [\"action_type\"],\n operator: \"in\",\n value: READ_ACTION_TYPES,\n });\n }\n\n const actionStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [`action/${selectedApi}/*/*`],\n conditions: actionConditions,\n };\n\n return {\n version: 2,\n statements: [authStatement, httpStatement, actionStatement],\n };\n}\n"],"mappings":"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","names":["z","z","z"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/constants.ts","../src/builders.ts","../src/conditions.ts","../src/policies.ts","../src/connection-policy.ts"],"sourcesContent":["// ABOUTME: Canonical request context types shared between sdkapi and approvalsapi.\n// ABOUTME: These define the contract for how requests are described in approval flows and policy evaluation.\n\nimport { z } from \"zod\";\nimport { JsonValueSchema } from \"@zapier/policy-schema\";\n\nexport { JsonValueSchema };\n\n/**\n * Parsed URL components for policy evaluation.\n * Matches the ParsedUrl shape from @zapier/policy-schema so that\n * evaluatePolicy condition paths like [\"url\", \"host\"] resolve correctly.\n */\nexport const ParsedUrlSchema = z.object({\n scheme: z.string(),\n host: z.string(),\n port: z.number(),\n path: z.string(),\n query: z.record(z.string(), z.array(z.string())),\n});\nexport type ParsedUrl = z.infer<typeof ParsedUrlSchema>;\n\n/** Default ports by scheme, used when URL has no explicit port. */\nexport const DEFAULT_PORTS: Record<string, number> = {\n http: 80,\n https: 443,\n};\n\n/**\n * Parse a raw URL string into a ParsedUrl.\n * Same logic as parseUrlForPolicyContext in @zapier/policy.\n */\nexport function parseUrl(raw: string): ParsedUrl {\n const url = new URL(raw);\n const scheme = url.protocol.slice(0, -1).toLowerCase();\n const host = url.hostname.toLowerCase();\n const port = url.port ? parseInt(url.port, 10) : (DEFAULT_PORTS[scheme] ?? 0);\n const path = url.pathname || \"/\";\n const query: Record<string, string[]> = {};\n for (const [key, value] of url.searchParams) {\n if (!query[key]) {\n query[key] = [];\n }\n query[key].push(value);\n }\n return { scheme, host, port, path, query };\n}\n\n/**\n * Reconstruct a URL string from a ParsedUrl.\n * Same logic as buildUrl in @zapier/policy.\n */\nexport function buildUrlString(parsed: ParsedUrl): string {\n const { scheme, host, port, path, query } = parsed;\n const defaultPort = DEFAULT_PORTS[scheme];\n const portString = port !== defaultPort ? `:${String(port)}` : \"\";\n const params = new URLSearchParams();\n for (const [key, values] of Object.entries(query)) {\n for (const value of values) {\n params.append(key, value);\n }\n }\n const queryString = params.toString();\n return `${scheme}://${host}${portString}${path}${queryString ? \"?\" + queryString : \"\"}`;\n}\n\n/**\n * HTTP request context for approval/policy flows.\n * Sent by sdkapi when a relay request is denied, stored by approvalsapi,\n * and used for both policy evaluation and building policy conditions.\n *\n * The url field is a ParsedUrl object (matching @zapier/policy-schema's ParsedUrl)\n * so that evaluatePolicy conditions like [\"url\", \"host\"] resolve correctly.\n */\nexport const HttpRequestContextSchema = z.object({\n request_type: z.literal(\"http_request\"),\n method: z.string(),\n /** Parsed URL components for policy condition matching */\n url: ParsedUrlSchema,\n /** Filtered headers (IGNORED_HEADERS excluded, keys lowercased) */\n headers: z.record(z.string(), z.string()),\n /** Raw body string */\n body: z.string().nullable(),\n /** Parsed JSON body */\n body_json: JsonValueSchema.nullable(),\n /** Zapier connection ID used for this request */\n connection_id: z.string().optional(),\n /** Optional human-readable reason for the request */\n reason: z.string().optional(),\n});\nexport type HttpRequestContext = z.infer<typeof HttpRequestContextSchema>;\n\n/**\n * Action run context for approval/policy flows.\n * Sent by sdkapi when an action run is denied, stored by approvalsapi,\n * and used to build policy conditions.\n */\nexport const ActionRunContextSchema = z.object({\n request_type: z.literal(\"action_run\"),\n selected_api: z.string(),\n action_type: z.string(),\n action_key: z.string(),\n connection_id: z.string().optional(),\n inputs: JsonValueSchema.optional(),\n reason: z.string().optional(),\n});\nexport type ActionRunContext = z.infer<typeof ActionRunContextSchema>;\n\n/**\n * Discriminated union of all request context types.\n */\nexport const RequestContextSchema = z.discriminatedUnion(\"request_type\", [\n HttpRequestContextSchema,\n ActionRunContextSchema,\n]);\nexport type RequestContext = z.infer<typeof RequestContextSchema>;\n","// ABOUTME: Canonical set of headers to exclude when building request contexts.\n// ABOUTME: Shared between sdkapi (context creation) and approvalsapi (condition building).\n\n/**\n * Headers to exclude when building request contexts from raw HTTP requests.\n *\n * These are either sensitive (auth credentials), HTTP infrastructure headers\n * that vary per-request, or proxy-internal headers that are not meaningful\n * for policy decisions.\n */\nexport const IGNORED_HEADERS = new Set([\n // Auth / credentials — never include in contexts or policy conditions\n \"authorization\",\n \"x-relay-authorization\",\n \"x-relay-authentication-id\",\n \"x-api-key\",\n \"cookie\",\n \"set-cookie\",\n \"proxy-authorization\",\n\n // HTTP infrastructure — varies per-request, not policy-relevant\n \"host\",\n \"connection\",\n \"content-length\",\n \"transfer-encoding\",\n \"accept-encoding\",\n \"user-agent\",\n \"accept\",\n \"accept-language\",\n \"sec-fetch-mode\",\n\n // Proxy / forwarding — infrastructure, not meaningful for policy\n \"x-forwarded-for\",\n \"x-forwarded-host\",\n \"x-forwarded-proto\",\n \"x-real-ip\",\n\n // Proxy internal — sdkapi-specific headers\n \"x-is-interactive-session\",\n \"x-relay-callback-url\",\n]);\n","// ABOUTME: Canonical builders for creating request contexts from raw request parts.\n// ABOUTME: Used by sdkapi to build both approval contexts and policy eval contexts.\n\nimport { z } from \"zod\";\nimport {\n HttpRequestContextSchema,\n ActionRunContextSchema,\n JsonValueSchema,\n parseUrl,\n type HttpRequestContext,\n type ActionRunContext,\n} from \"./types.ts\";\nimport { IGNORED_HEADERS } from \"./constants.ts\";\n\nexport const BuildHttpRequestContextOptionsSchema = z.object({\n method: z.string(),\n /** Raw URL string. Will be normalized with https:// if no protocol present. */\n url: z.string(),\n /** Raw headers from the request. Will be filtered through IGNORED_HEADERS. */\n headers: z\n .record(\n z.string(),\n z.union([z.string(), z.array(z.string()), z.undefined()]),\n )\n .optional(),\n /** Raw body string */\n body: z.string().nullable().optional(),\n /** Pre-parsed JSON body (e.g. from Fastify's automatic JSON parsing) */\n body_json: JsonValueSchema.optional(),\n /** Connection ID associated with this request */\n connection_id: z.string().optional(),\n});\nexport type BuildHttpRequestContextOptions = z.infer<\n typeof BuildHttpRequestContextOptionsSchema\n>;\n\n/**\n * Build a canonical HttpRequestContext from raw request parts.\n *\n * This is the single source of truth for how HTTP request contexts are created.\n * Both sdkapi (for policy evaluation) and approvalsapi (for context storage)\n * should use this to ensure the context shape is consistent.\n *\n * Matches the behavior of createPolicyHttpRequest from @zapier/policy, with\n * the addition of header filtering through IGNORED_HEADERS.\n *\n * - Normalizes URL (adds https:// if missing) and parses into { scheme, host, port, path, query }\n * - Filters headers through IGNORED_HEADERS, lowercases keys, string values only\n * - Auto-parses body_json from body when content-type is JSON and body_json not provided\n * - body defaults to null (not undefined)\n */\nexport function buildHttpRequestContext(\n options: BuildHttpRequestContextOptions,\n): HttpRequestContext {\n // Normalize URL — SDK CLI strips the protocol\n const rawUrl = options.url.includes(\"://\")\n ? options.url\n : `https://${options.url}`;\n const url = parseUrl(rawUrl);\n\n // Filter headers: exclude ignored, lowercase keys, string values only\n const headers: Record<string, string> = {};\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n const lowerKey = key.toLowerCase();\n if (!IGNORED_HEADERS.has(lowerKey) && typeof value === \"string\") {\n headers[lowerKey] = value;\n }\n }\n }\n\n // Auto-parse body_json from body when content-type is JSON\n // (matches createPolicyHttpRequest behavior from @zapier/policy)\n let body_json: unknown = null;\n if (options.body_json !== undefined) {\n body_json = options.body_json;\n } else if (options.body) {\n const contentType = headers[\"content-type\"];\n const isJson =\n typeof contentType === \"string\" &&\n (contentType.includes(\"application/json\") ||\n (contentType.includes(\"application/\") &&\n contentType.includes(\"+json\")));\n if (isJson) {\n try {\n body_json = JSON.parse(options.body);\n } catch {\n // Invalid JSON body — leave body_json as null\n }\n }\n }\n\n return HttpRequestContextSchema.parse({\n request_type: \"http_request\",\n method: options.method,\n url,\n headers,\n body: options.body ?? null,\n body_json,\n connection_id: options.connection_id,\n });\n}\n\nexport const BuildActionRunContextOptionsSchema = z.object({\n selected_api: z.string(),\n action_type: z.string(),\n action_key: z.string(),\n connection_id: z.string().optional(),\n inputs: JsonValueSchema.optional(),\n});\nexport type BuildActionRunContextOptions = z.infer<\n typeof BuildActionRunContextOptionsSchema\n>;\n\n/**\n * Build a canonical ActionRunContext from raw action parts.\n */\nexport function buildActionRunContext(\n options: BuildActionRunContextOptions,\n): ActionRunContext {\n return ActionRunContextSchema.parse({\n request_type: \"action_run\",\n selected_api: options.selected_api,\n action_type: options.action_type,\n action_key: options.action_key,\n connection_id: options.connection_id,\n inputs: options.inputs,\n });\n}\n","// ABOUTME: Builds policy conditions from stored request contexts.\n// ABOUTME: Used by approvalsapi's \"allow exact request\" and \"allow domain\" instant policy flows.\n\nimport type { Condition } from \"@zapier/policy-schema\";\nimport type { HttpRequestContext, ActionRunContext } from \"./types.ts\";\nimport { IGNORED_HEADERS } from \"./constants.ts\";\n\n/**\n * Build conditions that match an exact HTTP request.\n *\n * Handles the matches_url / query param split correctly:\n * - `matches_url` only supports scheme+host+port+path (no query string per spec)\n * - Query parameters are added as separate decomposed conditions on `url.query.<key>`\n *\n * @returns Condition[] for an http permission statement\n */\nexport function buildExactHttpConditions(\n context: HttpRequestContext,\n): Condition[] {\n const conditions: Condition[] = [\n { path: [\"method\"], operator: \"equals\", value: context.method },\n ];\n\n const { url } = context;\n\n // matches_url condition uses URL without query string (per @zapier/policy spec)\n const defaultPort =\n url.scheme === \"https\" ? 443 : url.scheme === \"http\" ? 80 : 0;\n const portString = url.port !== defaultPort ? `:${String(url.port)}` : \"\";\n const urlWithoutQuery = `${url.scheme}://${url.host}${portString}${url.path}`;\n conditions.push({\n path: [\"url\"],\n operator: \"matches_url\",\n value: urlWithoutQuery,\n });\n\n // Add decomposed conditions for each query parameter.\n for (const [key, values] of Object.entries(url.query)) {\n conditions.push({\n path: [\"url\", \"query\", key],\n operator: \"equals\",\n value: values,\n });\n }\n\n // body_json condition\n if (context.body_json !== null) {\n conditions.push({\n path: [\"body_json\"],\n operator: \"equals\",\n value: context.body_json,\n });\n }\n\n // Header conditions (filtered through IGNORED_HEADERS again for safety)\n for (const [key, value] of Object.entries(context.headers)) {\n if (!IGNORED_HEADERS.has(key.toLowerCase()) && typeof value === \"string\") {\n conditions.push({\n path: [\"headers\", key.toLowerCase()],\n operator: \"equals\",\n value,\n });\n }\n }\n\n return conditions;\n}\n\n/**\n * Build conditions that match any request to a given domain.\n * Uses the host from the parsed URL.\n *\n * @returns Condition[] for an http permission statement\n */\nexport function buildDomainHttpConditions(\n context: HttpRequestContext,\n): Condition[] {\n return [\n {\n path: [\"url\", \"host\"],\n operator: \"matches_host\",\n value: context.url.host,\n },\n ];\n}\n\n/**\n * Build conditions that match an exact action run (with inputs).\n *\n * @returns Condition[] for an action permission statement\n */\nexport function buildExactActionConditions(\n context: ActionRunContext,\n): Condition[] {\n const conditions: Condition[] = [];\n\n if (\n context.inputs !== undefined &&\n context.inputs !== null &&\n typeof context.inputs === \"object\"\n ) {\n conditions.push({\n path: [\"inputs\"],\n operator: \"equals\",\n value: context.inputs,\n });\n }\n\n return conditions;\n}\n\n/**\n * Build the resource string for an action.\n * Format: action/{selected_api}/{action_type}/{action_key}\n */\nexport function buildActionResource(context: ActionRunContext): string {\n return `action/${context.selected_api}/${context.action_type}/${context.action_key}`;\n}\n\n/**\n * Build a broad action resource that matches all actions for an app.\n * Format: action/{selected_api}/{wildcard}/{wildcard}\n */\nexport function buildBroadActionResource(context: ActionRunContext): string {\n return `action/${context.selected_api}/*/*`;\n}\n","// ABOUTME: Assembles complete Policy objects from request contexts.\n// ABOUTME: Single source of truth for \"exact request\" instant policies used by web UI and API.\n\nimport type { Policy, Statement } from \"@zapier/policy-schema\";\nimport type {\n RequestContext,\n HttpRequestContext,\n ActionRunContext,\n} from \"./types.ts\";\nimport {\n buildExactHttpConditions,\n buildExactActionConditions,\n buildActionResource,\n} from \"./conditions.ts\";\n\n/**\n * Build a `can_use` authentication statement, if the context has a connection_id.\n */\nfunction buildAuthStatement(authenticationId: string): Statement {\n return {\n effect: \"allow\",\n permissions: [\"can_use\"],\n resources: [`connection/${authenticationId}`],\n conditions: [],\n };\n}\n\n/**\n * Build an exact-match policy from an HTTP request context.\n *\n * Produces a policy that allows only the specific request described by the context:\n * - `can_use` statement for the authentication (if present)\n * - `can_execute` statement for `http` with conditions from `buildExactHttpConditions`\n * plus a `keys_in` guard restricting allowed query parameter keys\n */\nfunction httpContextToPolicy(context: HttpRequestContext): Policy {\n const statements: Statement[] = [];\n\n if (context.connection_id) {\n statements.push(buildAuthStatement(context.connection_id));\n }\n\n const conditions = buildExactHttpConditions(context);\n\n // Add a keys_in guard so only the query param keys present in the original\n // request are allowed — blocks injection of extra query params.\n conditions.push({\n path: [\"url\", \"query\"],\n operator: \"keys_in\",\n value: Object.keys(context.url.query),\n });\n\n statements.push({\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [\"http\"],\n conditions,\n });\n\n return { version: 2, statements };\n}\n\n/**\n * Build an exact-match policy from an action run context.\n *\n * Produces a policy that allows only the specific action described by the context:\n * - `can_use` statement for the authentication (if present)\n * - `can_execute` statement for the action resource with input conditions\n */\nfunction actionContextToPolicy(context: ActionRunContext): Policy {\n const statements: Statement[] = [];\n\n if (context.connection_id) {\n statements.push(buildAuthStatement(context.connection_id));\n }\n\n statements.push({\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [buildActionResource(context)],\n conditions: buildExactActionConditions(context),\n });\n\n return { version: 2, statements };\n}\n\n/**\n * Build an exact-match policy from any supported request context.\n *\n * This is the single source of truth for \"allow this exact request\" instant policies.\n * Used by the web UI and anywhere else that needs to produce an exact policy from a context.\n */\nexport function toExactPolicy(context: RequestContext): Policy {\n if (context.request_type === \"http_request\") {\n return httpContextToPolicy(context);\n }\n return actionContextToPolicy(context);\n}\n","// ABOUTME: Builds connection-level policies for the basic approvals MVP.\n// ABOUTME: Generates deterministic policies that allow read or read+write access scoped to a specific connection.\n\nimport { z } from \"zod\";\nimport type { Policy, Statement, Condition } from \"@zapier/policy-schema\";\n\nexport const AccessLevelSchema = z.enum([\"read\", \"read_write\"]);\nexport type AccessLevel = z.infer<typeof AccessLevelSchema>;\n\nconst READ_HTTP_METHODS = [\"GET\", \"HEAD\", \"OPTIONS\"];\nconst READ_ACTION_TYPES = [\"read\", \"search\"];\n\n/**\n * Build a connection-level policy that covers both HTTP and action access.\n *\n * Always produces three statements:\n * 1. `can_use` for the authentication\n * 2. `can_execute` on `http` scoped by connection_id (+ method filter for read)\n * 3. `can_execute` on `action/{selectedApi}/**` scoped by connection_id (+ action_type filter for read)\n */\nexport function buildConnectionPolicy(options: {\n connectionId: string;\n selectedApi: string;\n accessLevel: AccessLevel;\n}): Policy {\n const { connectionId, selectedApi, accessLevel } = options;\n\n const authStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_use\"],\n resources: [`connection/${connectionId}`],\n conditions: [],\n };\n\n const connectionCondition: Condition = {\n path: [\"connection_id\"],\n operator: \"equals\",\n value: connectionId,\n };\n\n const httpConditions: Condition[] = [connectionCondition];\n if (accessLevel === \"read\") {\n httpConditions.push({\n path: [\"method\"],\n operator: \"in\",\n value: READ_HTTP_METHODS,\n });\n }\n\n const httpStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [\"http\"],\n conditions: httpConditions,\n };\n\n const actionConditions: Condition[] = [connectionCondition];\n if (accessLevel === \"read\") {\n actionConditions.push({\n path: [\"action_type\"],\n operator: \"in\",\n value: READ_ACTION_TYPES,\n });\n }\n\n const actionStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: [`action/${selectedApi}/*/*`],\n conditions: actionConditions,\n };\n\n return {\n version: 2,\n statements: [authStatement, httpStatement, actionStatement],\n };\n}\n"],"mappings":"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","names":["z","z","z"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zapier/policy-context",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Shared request context types, builders, and policy condition generators for sdkapi and approvalsapi",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,7 +27,7 @@
27
27
  "access": "public"
28
28
  },
29
29
  "dependencies": {
30
- "@zapier/policy-schema": "0.11.0"
30
+ "@zapier/policy-schema": "0.11.1"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "zod": "^4.0.0"