@zapier/policy-context 1.0.0 → 1.1.1
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 +33 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -15
- package/dist/index.d.ts +43 -15
- package/dist/index.js +32 -30
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AccessLevelSchema: () => AccessLevelSchema,
|
|
24
|
+
ActionRunContextInputSchema: () => ActionRunContextInputSchema,
|
|
24
25
|
ActionRunContextSchema: () => ActionRunContextSchema,
|
|
25
26
|
ActionTypeSchema: () => ActionTypeSchema,
|
|
26
27
|
BuildActionRunContextOptionsSchema: () => BuildActionRunContextOptionsSchema,
|
|
@@ -28,7 +29,6 @@ __export(index_exports, {
|
|
|
28
29
|
DEFAULT_PORTS: () => DEFAULT_PORTS,
|
|
29
30
|
HttpRequestContextSchema: () => HttpRequestContextSchema,
|
|
30
31
|
IGNORED_HEADERS: () => IGNORED_HEADERS,
|
|
31
|
-
JsonValueSchema: () => import_policy_schema.JsonValueSchema,
|
|
32
32
|
ParsedUrlSchema: () => ParsedUrlSchema,
|
|
33
33
|
READ_ACTION_TYPES: () => READ_ACTION_TYPES,
|
|
34
34
|
READ_HTTP_METHODS: () => READ_HTTP_METHODS,
|
|
@@ -52,7 +52,6 @@ module.exports = __toCommonJS(index_exports);
|
|
|
52
52
|
// src/types.ts
|
|
53
53
|
var import_zod = require("zod");
|
|
54
54
|
var import_zod_to_openapi = require("@asteasolutions/zod-to-openapi");
|
|
55
|
-
var import_policy_schema = require("@zapier/policy-schema");
|
|
56
55
|
(0, import_zod_to_openapi.extendZodWithOpenApi)(import_zod.z);
|
|
57
56
|
var ParsedUrlSchema = import_zod.z.object({
|
|
58
57
|
scheme: import_zod.z.string().openapi({ description: 'URL scheme, e.g. "https"' }),
|
|
@@ -64,7 +63,9 @@ var ParsedUrlSchema = import_zod.z.object({
|
|
|
64
63
|
query: import_zod.z.record(import_zod.z.string(), import_zod.z.array(import_zod.z.string())).openapi({
|
|
65
64
|
description: "Query parameters as key to string array mapping"
|
|
66
65
|
})
|
|
67
|
-
}).openapi("ParsedUrl"
|
|
66
|
+
}).openapi("ParsedUrl", {
|
|
67
|
+
description: "Parsed URL components for policy condition matching"
|
|
68
|
+
});
|
|
68
69
|
var DEFAULT_PORTS = {
|
|
69
70
|
http: 80,
|
|
70
71
|
https: 443
|
|
@@ -98,8 +99,8 @@ function buildUrlString(parsed) {
|
|
|
98
99
|
return `${scheme}://${host}${portString}${path}${queryString ? "?" + queryString : ""}`;
|
|
99
100
|
}
|
|
100
101
|
var HttpRequestContextSchema = import_zod.z.object({
|
|
101
|
-
request_type: import_zod.z.literal("http_request"),
|
|
102
|
-
method: import_zod.z.string().max(10).transform((m) => m.toUpperCase()),
|
|
102
|
+
request_type: import_zod.z.literal("http_request").openapi({ description: "Context type discriminator" }),
|
|
103
|
+
method: import_zod.z.string().max(10).transform((m) => m.toUpperCase()).openapi({ description: "HTTP method" }),
|
|
103
104
|
/** Parsed URL components for policy condition matching */
|
|
104
105
|
url: ParsedUrlSchema,
|
|
105
106
|
/** Filtered headers (IGNORED_HEADERS excluded, keys lowercased) */
|
|
@@ -107,16 +108,15 @@ var HttpRequestContextSchema = import_zod.z.object({
|
|
|
107
108
|
description: "Filtered headers (IGNORED_HEADERS excluded, keys lowercased)"
|
|
108
109
|
}),
|
|
109
110
|
/** Raw body string */
|
|
110
|
-
body: import_zod.z.string().max(65536).nullable(),
|
|
111
|
-
/**
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}),
|
|
111
|
+
body: import_zod.z.string().max(65536).nullable().openapi({ description: "Raw body string" }),
|
|
112
|
+
/**
|
|
113
|
+
* Parsed JSON body. Authored as `z.unknown().pipe(z.json())` so
|
|
114
|
+
* zod-to-openapi sees the outer `z.unknown()` and emits a permissive
|
|
115
|
+
* field (no recursive `$ref`, no type), while the inner `z.json()`
|
|
116
|
+
* still rejects non-JSON values (`Date`, `undefined`, functions) at
|
|
117
|
+
* parse time. Same inferred `JsonValue` type either way.
|
|
118
|
+
*/
|
|
119
|
+
body_json: import_zod.z.unknown().pipe(import_zod.z.json()).nullable().describe("Parsed JSON body (if applicable)"),
|
|
120
120
|
/** Zapier connection ID used for this request */
|
|
121
121
|
connection_id: import_zod.z.string().max(255).optional().openapi({ description: "Zapier connection ID used for this request" }),
|
|
122
122
|
/** Optional human-readable reason for the request */
|
|
@@ -133,6 +133,7 @@ var ActionTypeSchema = import_zod.z.enum([
|
|
|
133
133
|
"write"
|
|
134
134
|
]).openapi("action_type", { description: "Canonical Zapier action type." });
|
|
135
135
|
var ACTION_RESOURCE_SEGMENT_PATTERN = /^[A-Za-z0-9._+-]+(?:@[A-Za-z0-9._+-]+)?$/;
|
|
136
|
+
var ACTION_KEY_SEGMENT_PATTERN = /^[A-Za-z0-9._+:-]+(?:@[A-Za-z0-9._+:-]+)?$/;
|
|
136
137
|
function parseActionResource(resource) {
|
|
137
138
|
const segments = resource.split("/");
|
|
138
139
|
if (segments.length !== 4 || segments[0] !== "action") {
|
|
@@ -155,7 +156,7 @@ function parseActionResource(resource) {
|
|
|
155
156
|
`action resource has invalid selected_api segment "${selectedApi}": ${resource}`
|
|
156
157
|
);
|
|
157
158
|
}
|
|
158
|
-
if (!
|
|
159
|
+
if (!ACTION_KEY_SEGMENT_PATTERN.test(actionKey)) {
|
|
159
160
|
throw new Error(
|
|
160
161
|
`action resource has invalid action_key segment "${actionKey}": ${resource}`
|
|
161
162
|
);
|
|
@@ -167,7 +168,7 @@ function parseActionResource(resource) {
|
|
|
167
168
|
};
|
|
168
169
|
}
|
|
169
170
|
var ActionRunContextInputSchema = import_zod.z.object({
|
|
170
|
-
request_type: import_zod.z.literal("action_run"),
|
|
171
|
+
request_type: import_zod.z.literal("action_run").openapi({ description: "Context type discriminator" }),
|
|
171
172
|
resource: import_zod.z.string().max(1024).optional().openapi({
|
|
172
173
|
description: "Canonical action resource, e.g. action/Slack@1.0.0/write/send_message"
|
|
173
174
|
}),
|
|
@@ -184,14 +185,8 @@ var ActionRunContextInputSchema = import_zod.z.object({
|
|
|
184
185
|
description: "Legacy: action key, e.g. send_message. Prefer `resource`."
|
|
185
186
|
}),
|
|
186
187
|
connection_id: import_zod.z.string().max(255).optional().openapi({ description: "Zapier connection ID used for this request" }),
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
// introspection of the recursive JsonValueSchema (z.lazy). The
|
|
190
|
-
// generator script strips this `type` after emit so the produced
|
|
191
|
-
// schema matches the original "any inputs" shape.
|
|
192
|
-
type: "object",
|
|
193
|
-
description: "Action input parameters"
|
|
194
|
-
}),
|
|
188
|
+
/** Action input parameters. See body_json above for the pipe rationale. */
|
|
189
|
+
inputs: import_zod.z.unknown().pipe(import_zod.z.json()).optional().describe("Action input parameters"),
|
|
195
190
|
reason: import_zod.z.string().max(1024).optional().openapi({ description: "Optional human-readable reason for the request" })
|
|
196
191
|
}).openapi("ActionRunContext", {
|
|
197
192
|
description: "Action run context. The canonical shape carries the action identity in a single `resource` field of the form `action/{selected_api}/{action_type}/{action_key}`. The legacy `{selected_api, action_type, action_key}` shape is also accepted on input during the migration window \u2014 approvalsapi normalizes it to the canonical form before storage."
|
|
@@ -227,7 +222,14 @@ var ActionRunContextSchema = ActionRunContextInputSchema.transform(
|
|
|
227
222
|
}
|
|
228
223
|
);
|
|
229
224
|
var RequestContextSchema = import_zod.z.union([HttpRequestContextSchema, ActionRunContextSchema]).openapi("RequestContext", {
|
|
230
|
-
description: "
|
|
225
|
+
description: "Union of request context shapes, keyed on `request_type`.",
|
|
226
|
+
discriminator: {
|
|
227
|
+
propertyName: "request_type",
|
|
228
|
+
mapping: {
|
|
229
|
+
http_request: "#/components/schemas/HttpRequestContext",
|
|
230
|
+
action_run: "#/components/schemas/ActionRunContext"
|
|
231
|
+
}
|
|
232
|
+
}
|
|
231
233
|
});
|
|
232
234
|
|
|
233
235
|
// src/constants.ts
|
|
@@ -348,7 +350,7 @@ var BuildHttpRequestContextOptionsSchema = import_zod2.z.object({
|
|
|
348
350
|
/** Raw body string */
|
|
349
351
|
body: import_zod2.z.string().nullable().optional(),
|
|
350
352
|
/** Pre-parsed JSON body (e.g. from Fastify's automatic JSON parsing) */
|
|
351
|
-
body_json:
|
|
353
|
+
body_json: import_zod2.z.json().optional(),
|
|
352
354
|
/** Connection ID associated with this request */
|
|
353
355
|
connection_id: import_zod2.z.string().optional()
|
|
354
356
|
});
|
|
@@ -393,11 +395,11 @@ var BuildActionRunContextOptionsSchema = import_zod2.z.object({
|
|
|
393
395
|
message: "selected_api must contain only [A-Za-z0-9._@+-] (no globs, slashes, or whitespace)"
|
|
394
396
|
}),
|
|
395
397
|
action_type: ActionTypeSchema,
|
|
396
|
-
action_key: import_zod2.z.string().regex(
|
|
397
|
-
message: "action_key must contain only [A-Za-z0-9._
|
|
398
|
+
action_key: import_zod2.z.string().regex(ACTION_KEY_SEGMENT_PATTERN, {
|
|
399
|
+
message: "action_key must contain only [A-Za-z0-9._@:+-] (no globs, slashes, or whitespace)"
|
|
398
400
|
}),
|
|
399
401
|
connection_id: import_zod2.z.string().optional(),
|
|
400
|
-
inputs:
|
|
402
|
+
inputs: import_zod2.z.json().optional(),
|
|
401
403
|
reason: import_zod2.z.string().optional()
|
|
402
404
|
});
|
|
403
405
|
function buildActionRunContext(options) {
|
|
@@ -530,6 +532,7 @@ function buildConnectionPolicy(options) {
|
|
|
530
532
|
// Annotate the CommonJS export names for ESM import in node:
|
|
531
533
|
0 && (module.exports = {
|
|
532
534
|
AccessLevelSchema,
|
|
535
|
+
ActionRunContextInputSchema,
|
|
533
536
|
ActionRunContextSchema,
|
|
534
537
|
ActionTypeSchema,
|
|
535
538
|
BuildActionRunContextOptionsSchema,
|
|
@@ -537,7 +540,6 @@ function buildConnectionPolicy(options) {
|
|
|
537
540
|
DEFAULT_PORTS,
|
|
538
541
|
HttpRequestContextSchema,
|
|
539
542
|
IGNORED_HEADERS,
|
|
540
|
-
JsonValueSchema,
|
|
541
543
|
ParsedUrlSchema,
|
|
542
544
|
READ_ACTION_TYPES,
|
|
543
545
|
READ_HTTP_METHODS,
|
package/dist/index.cjs.map
CHANGED
|
@@ -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 ActionTypeSchema,\n RequestContextSchema,\n JsonValueSchema,\n ParsedUrlSchema,\n DEFAULT_PORTS,\n parseUrl,\n buildUrlString,\n parseActionResource,\n type HttpRequestContext,\n type ActionRunContext,\n type ActionType,\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 isWriteRequest,\n AccessLevelSchema,\n READ_ACTION_TYPES,\n READ_HTTP_METHODS,\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 { extendZodWithOpenApi } from \"@asteasolutions/zod-to-openapi\";\nimport { JsonValueSchema } from \"@zapier/policy-schema\";\n\nextendZodWithOpenApi(z);\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\n .object({\n scheme: z.string().openapi({ description: 'URL scheme, e.g. \"https\"' }),\n host: z.string().openapi({ description: 'Hostname, e.g. \"api.example.com\"' }),\n port: z\n .number()\n .int()\n .openapi({\n description: \"Port number (defaults to 443 for https, 80 for http)\",\n }),\n path: z.string().openapi({ description: 'URL path, e.g. \"/v1/foo\"' }),\n query: z\n .record(z.string(), z.array(z.string()))\n .openapi({\n description: \"Query parameters as key to string array mapping\",\n }),\n })\n .openapi(\"ParsedUrl\");\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\n .object({\n request_type: z.literal(\"http_request\"),\n method: z\n .string()\n .max(10)\n .transform((m) => m.toUpperCase()),\n /** Parsed URL components for policy condition matching */\n url: ParsedUrlSchema,\n /** Filtered headers (IGNORED_HEADERS excluded, keys lowercased) */\n headers: z\n .record(z.string(), z.string())\n .openapi({\n description: \"Filtered headers (IGNORED_HEADERS excluded, keys lowercased)\",\n }),\n /** Raw body string */\n body: z.string().max(65536).nullable(),\n /** Parsed JSON body */\n body_json: JsonValueSchema.nullable().openapi({\n // `type: 'object'` is a placeholder so zod-to-openapi short-circuits\n // introspection of the recursive JsonValueSchema (z.lazy). The\n // generator script strips this `type` after emit so the produced\n // schema matches the original \"any JSON value\" shape.\n type: \"object\",\n description: \"Parsed JSON body (if applicable)\",\n }),\n /** Zapier connection ID used for this request */\n connection_id: z\n .string()\n .max(255)\n .optional()\n .openapi({ description: \"Zapier connection ID used for this request\" }),\n /** Optional human-readable reason for the request */\n reason: z\n .string()\n .max(1024)\n .optional()\n .openapi({ description: \"Optional human-readable reason for the request\" }),\n })\n .openapi(\"HttpRequestContext\");\nexport type HttpRequestContext = z.infer<typeof HttpRequestContextSchema>;\n\n/**\n * Canonical Zapier action types.\n *\n * Mirrors the `action_type` enum in sdkapi's OpenAPI spec\n * (`packages/openapi-spec/openapi.d.ts` `action_type`). Single source of\n * truth for any code that branches on or filters by action_type — keeps\n * `ActionRunContextSchema`, `BuildActionRunContextOptionsSchema`, and the\n * `READ_ACTION_TYPES` allowlist in `connection-policy.ts` aligned.\n */\nexport const ActionTypeSchema = z\n .enum([\n \"filter\",\n \"read\",\n \"read_bulk\",\n \"run\",\n \"search\",\n \"search_and_write\",\n \"search_or_write\",\n \"write\",\n ])\n .openapi(\"action_type\", { description: \"Canonical Zapier action type.\" });\nexport type ActionType = z.infer<typeof ActionTypeSchema>;\n\n/**\n * Allowed character set for `selected_api` and `action_key` segments of\n * an action resource. Blocks `*`, `/`, whitespace, and other glob/path\n * metacharacters that would otherwise widen policy scope. Permits at\n * most one `@`, which `globSelectedApiVersion` treats as the\n * version separator.\n */\nexport const ACTION_RESOURCE_SEGMENT_PATTERN =\n /^[A-Za-z0-9._+-]+(?:@[A-Za-z0-9._+-]+)?$/;\n\n/**\n * Parse an action resource string of the form\n * `action/{selected_api}/{action_type}/{action_key}` into its parts.\n * Throws if the string doesn't match the canonical 4-segment shape or\n * if its `action_type` segment isn't one of the canonical 8 — every\n * action_run context that has been through `ActionRunContextSchema` is\n * guaranteed to parse cleanly, so a thrown error here means upstream\n * validation was bypassed.\n */\nexport function parseActionResource(resource: string): {\n selected_api: string;\n action_type: ActionType;\n action_key: string;\n} {\n const segments = resource.split(\"/\");\n if (segments.length !== 4 || segments[0] !== \"action\") {\n throw new Error(\n `action resource must be action/{selected_api}/{action_type}/{action_key}: got ${resource}`,\n );\n }\n const [, selectedApi, actionTypeRaw, actionKey] = segments;\n if (!selectedApi || !actionTypeRaw || !actionKey) {\n throw new Error(`action resource has empty segment: ${resource}`);\n }\n const actionType = ActionTypeSchema.safeParse(actionTypeRaw);\n if (!actionType.success) {\n throw new Error(\n `action resource has unknown action_type \"${actionTypeRaw}\": ${resource}`,\n );\n }\n if (!ACTION_RESOURCE_SEGMENT_PATTERN.test(selectedApi)) {\n throw new Error(\n `action resource has invalid selected_api segment \"${selectedApi}\": ${resource}`,\n );\n }\n if (!ACTION_RESOURCE_SEGMENT_PATTERN.test(actionKey)) {\n throw new Error(\n `action resource has invalid action_key segment \"${actionKey}\": ${resource}`,\n );\n }\n return {\n selected_api: selectedApi,\n action_type: actionType.data,\n action_key: actionKey,\n };\n}\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 *\n * Carries the action identity in a single canonical `resource` field of\n * the form `action/{selected_api}/{action_type}/{action_key}`, which is\n * also what the policy engine matches against. Use `parseActionResource`\n * to extract the individual parts when needed for display.\n *\n * Accepts either the canonical `resource` field or the legacy\n * `{selected_api, action_type, action_key}` triple on input — the\n * transform composes a canonical resource from the legacy fields when\n * needed, so downstream code only ever sees a single `resource`. Lets\n * sdkapi keep sending the old shape during the migration window.\n */\n/**\n * Raw input shape for `ActionRunContextSchema`, before the transform that\n * canonicalizes legacy fields into `resource`. Exposed for the OpenAPI\n * schema generator (which can't represent transforms) — runtime callers\n * should keep using `ActionRunContextSchema`.\n */\nexport const ActionRunContextInputSchema = z\n .object({\n request_type: z.literal(\"action_run\"),\n resource: z\n .string()\n .max(1024)\n .optional()\n .openapi({\n description:\n \"Canonical action resource, e.g. action/Slack@1.0.0/write/send_message\",\n }),\n selected_api: z\n .string()\n .max(255)\n .optional()\n .openapi({\n deprecated: true,\n description:\n \"Legacy: app identifier, e.g. Slack@1.0.0. Prefer `resource`.\",\n }),\n action_type: ActionTypeSchema.optional().openapi({\n deprecated: true,\n description: \"Legacy: canonical Zapier action type. Prefer `resource`.\",\n }),\n action_key: z\n .string()\n .max(255)\n .optional()\n .openapi({\n deprecated: true,\n description:\n \"Legacy: action key, e.g. send_message. Prefer `resource`.\",\n }),\n connection_id: z\n .string()\n .max(255)\n .optional()\n .openapi({ description: \"Zapier connection ID used for this request\" }),\n inputs: JsonValueSchema.optional().openapi({\n // `type: 'object'` is a placeholder so zod-to-openapi short-circuits\n // introspection of the recursive JsonValueSchema (z.lazy). The\n // generator script strips this `type` after emit so the produced\n // schema matches the original \"any inputs\" shape.\n type: \"object\",\n description: \"Action input parameters\",\n }),\n reason: z\n .string()\n .max(1024)\n .optional()\n .openapi({ description: \"Optional human-readable reason for the request\" }),\n })\n .openapi(\"ActionRunContext\", {\n description:\n \"Action run context. The canonical shape carries the action identity in a single `resource` field of the form `action/{selected_api}/{action_type}/{action_key}`. The legacy `{selected_api, action_type, action_key}` shape is also accepted on input during the migration window — approvalsapi normalizes it to the canonical form before storage.\",\n });\n\nexport const ActionRunContextSchema = ActionRunContextInputSchema.transform(\n (input, ctx) => {\n const resource =\n input.resource ??\n (input.selected_api && input.action_type && input.action_key\n ? `action/${input.selected_api}/${input.action_type}/${input.action_key}`\n : undefined);\n if (resource === undefined) {\n ctx.addIssue({\n code: \"custom\",\n message:\n \"action_run context requires either `resource` or all of `selected_api`/`action_type`/`action_key`\",\n });\n return z.NEVER;\n }\n try {\n parseActionResource(resource);\n } catch (err) {\n ctx.addIssue({\n code: \"custom\",\n message: err instanceof Error ? err.message : String(err),\n });\n return z.NEVER;\n }\n return {\n request_type: \"action_run\" as const,\n resource,\n ...(input.connection_id !== undefined && {\n connection_id: input.connection_id,\n }),\n ...(input.inputs !== undefined && { inputs: input.inputs }),\n ...(input.reason !== undefined && { reason: input.reason }),\n };\n },\n);\nexport type ActionRunContext = z.infer<typeof ActionRunContextSchema>;\n\n/**\n * Union of all request context types, keyed on `request_type`.\n *\n * Plain `z.union` (not `z.discriminatedUnion`) because\n * `ActionRunContextSchema` carries a `.transform` and discriminated\n * unions can't accept a `ZodEffects` member.\n */\nexport const RequestContextSchema = z\n .union([HttpRequestContextSchema, ActionRunContextSchema])\n .openapi(\"RequestContext\", {\n description: \"Discriminated union over request_type.\",\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 ActionTypeSchema,\n JsonValueSchema,\n parseUrl,\n ACTION_RESOURCE_SEGMENT_PATTERN,\n type HttpRequestContext,\n type ActionRunContext,\n} from \"./types.ts\";\nimport { buildActionResource } from \"./conditions.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 // Validate options up-front so downstream string ops (e.g. method.toUpperCase)\n // see well-typed values. Mirrors the pattern in buildActionRunContext.\n const parsed = BuildHttpRequestContextOptionsSchema.parse(options);\n\n // Normalize URL — SDK CLI strips the protocol\n const rawUrl = parsed.url.includes(\"://\")\n ? parsed.url\n : `https://${parsed.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 (parsed.headers) {\n for (const [key, value] of Object.entries(parsed.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 (parsed.body_json !== undefined) {\n body_json = parsed.body_json;\n } else if (parsed.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(parsed.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: parsed.method.toUpperCase(),\n url,\n headers,\n body: parsed.body ?? null,\n body_json,\n connection_id: parsed.connection_id,\n });\n}\n\nexport const BuildActionRunContextOptionsSchema = z.object({\n selected_api: z.string().regex(ACTION_RESOURCE_SEGMENT_PATTERN, {\n message:\n \"selected_api must contain only [A-Za-z0-9._@+-] (no globs, slashes, or whitespace)\",\n }),\n action_type: ActionTypeSchema,\n action_key: z.string().regex(ACTION_RESOURCE_SEGMENT_PATTERN, {\n message:\n \"action_key must contain only [A-Za-z0-9._@+-] (no globs, slashes, or whitespace)\",\n }),\n connection_id: z.string().optional(),\n inputs: JsonValueSchema.optional(),\n reason: z.string().optional(),\n});\nexport type BuildActionRunContextOptions = z.infer<\n typeof BuildActionRunContextOptionsSchema\n>;\n\n/**\n * Build a canonical ActionRunContext from raw action parts.\n *\n * Callers pass the three identity fields separately for readability;\n * this validates them and collapses them into the canonical `resource`\n * string the schema stores.\n */\nexport function buildActionRunContext(\n options: BuildActionRunContextOptions,\n): ActionRunContext {\n const parsed = BuildActionRunContextOptionsSchema.parse(options);\n return ActionRunContextSchema.parse({\n request_type: \"action_run\",\n resource: buildActionResource({\n selected_api: parsed.selected_api,\n action_type: parsed.action_type,\n action_key: parsed.action_key,\n }),\n connection_id: parsed.connection_id,\n inputs: parsed.inputs,\n reason: parsed.reason,\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 {\n HttpRequestContext,\n ActionRunContext,\n ActionType,\n} 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 } else if (context.body !== null) {\n // Non-JSON body (text/plain, XML, form-encoded): pin the raw body so\n // exact-match policies actually match the originating request.\n conditions.push({\n path: [\"body\"],\n operator: \"equals\",\n value: context.body,\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 (context.inputs !== undefined && context.inputs !== null) {\n conditions.push({\n path: [\"inputs\"],\n operator: \"equals\",\n value: context.inputs,\n });\n }\n\n return conditions;\n}\n\n/**\n * The three identity fields that compose an action resource string.\n */\nexport interface ActionResourceParts {\n selected_api: string;\n action_type: ActionType;\n action_key: string;\n}\n\n/**\n * Build the resource string for an action.\n * Format: action/{selected_api}/{action_type}/{action_key}\n */\nexport function buildActionResource(parts: ActionResourceParts): string {\n return `action/${parts.selected_api}/${parts.action_type}/${parts.action_key}`;\n}\n\n/**\n * Build a broad action resource that matches all actions of the same type\n * for an app (e.g. all reads, all writes). Scopes on `action_type` to\n * avoid silently granting cross-type access.\n *\n * Format: action/{selected_api}/{action_type}/{wildcard}\n */\nexport function buildBroadActionResource(\n parts: Pick<ActionResourceParts, \"selected_api\" | \"action_type\">,\n): string {\n return `action/${parts.selected_api}/${parts.action_type}/*`;\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} 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: [context.resource],\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\";\nimport {\n parseActionResource,\n type ActionType,\n type RequestContext,\n} from \"./types.ts\";\n\n/**\n * Replace the implementation-version suffix of a `selected_api` with a `@*`\n * wildcard so connection-level policies stay valid across version bumps. A\n * runtime request with `selected_api: \"App@2.7.3\"` matches a policy resource\n * scoped to `App@*` while still being distinguishable from a different app\n * (e.g. `App2@1.0.0`).\n *\n * No-op when the input has no `@` — assumed to be already version-less.\n */\nfunction globSelectedApiVersion(selectedApi: string): string {\n const at = selectedApi.indexOf(\"@\");\n return at === -1 ? selectedApi : selectedApi.slice(0, at) + \"@*\";\n}\n\nexport const AccessLevelSchema = z.enum([\"read\", \"read_write\"]);\nexport type AccessLevel = z.infer<typeof AccessLevelSchema>;\n\n/** HTTP methods that count as side-effect-free reads for connection-level policies. */\nexport const READ_HTTP_METHODS = [\"GET\", \"HEAD\", \"OPTIONS\"] as const;\n\n/**\n * Action types that count as side-effect-free reads for connection-level\n * policies. `read_bulk` is the paginated/bulk variant of `read` — same\n * external API semantics, no mutations. Widely used by major apps (Slack,\n * Gmail, Jira, Salesforce, etc.) via the public `bulkReads` schema key.\n * `filter` and `run` are excluded: neither has a runtime executor for\n * external apps, and `filter` actions don't carry a connection_id anyway,\n * so this allowlist has no effect on them.\n */\nexport const READ_ACTION_TYPES = [\n \"read\",\n \"read_bulk\",\n \"search\",\n] as const satisfies readonly ActionType[];\n\nconst READ_HTTP_METHOD_SET: ReadonlySet<string> = new Set(READ_HTTP_METHODS);\nconst READ_ACTION_TYPE_SET: ReadonlySet<ActionType> = new Set(\n READ_ACTION_TYPES,\n);\n\n/**\n * Returns true when the request needs write access (i.e. it is NOT a\n * side-effect-free read). Mirrors the logic encoded in `buildConnectionPolicy`\n * so UI surfaces that gate the read-vs-read_write choice stay consistent\n * with the policies they generate.\n */\nexport function isWriteRequest(context: RequestContext): boolean {\n if (context.request_type === \"http_request\") {\n // Method is uppercase by construction (buildHttpRequestContext canonicalizes\n // it on the way in), so no normalization is needed here.\n return !READ_HTTP_METHOD_SET.has(context.method);\n }\n const { action_type } = parseActionResource(context.resource);\n return !READ_ACTION_TYPE_SET.has(action_type);\n}\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}/{action_type}/*` per allowed type,\n * scoped by connection_id. For read access, the resource list expands to\n * one entry per read action_type so the engine matches via the resource\n * string rather than a separate `path: [\"action_type\"]` condition.\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 apiPattern = globSelectedApiVersion(selectedApi);\n const actionResources =\n accessLevel === \"read\"\n ? READ_ACTION_TYPES.map((t) => `action/${apiPattern}/${t}/*`)\n : [`action/${apiPattern}/*/*`];\n\n const actionStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: actionResources,\n conditions: [connectionCondition],\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 ActionRunContextInputSchema,\n ActionTypeSchema,\n RequestContextSchema,\n ParsedUrlSchema,\n DEFAULT_PORTS,\n parseUrl,\n buildUrlString,\n parseActionResource,\n type HttpRequestContext,\n type ActionRunContext,\n type ActionType,\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 isWriteRequest,\n AccessLevelSchema,\n READ_ACTION_TYPES,\n READ_HTTP_METHODS,\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 { extendZodWithOpenApi } from \"@asteasolutions/zod-to-openapi\";\n\nextendZodWithOpenApi(z);\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\n .object({\n scheme: z.string().openapi({ description: 'URL scheme, e.g. \"https\"' }),\n host: z.string().openapi({ description: 'Hostname, e.g. \"api.example.com\"' }),\n port: z\n .number()\n .int()\n .openapi({\n description: \"Port number (defaults to 443 for https, 80 for http)\",\n }),\n path: z.string().openapi({ description: 'URL path, e.g. \"/v1/foo\"' }),\n query: z\n .record(z.string(), z.array(z.string()))\n .openapi({\n description: \"Query parameters as key to string array mapping\",\n }),\n })\n .openapi(\"ParsedUrl\", {\n description: \"Parsed URL components for policy condition matching\",\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\n .object({\n request_type: z\n .literal(\"http_request\")\n .openapi({ description: \"Context type discriminator\" }),\n method: z\n .string()\n .max(10)\n .transform((m) => m.toUpperCase())\n .openapi({ description: \"HTTP method\" }),\n /** Parsed URL components for policy condition matching */\n url: ParsedUrlSchema,\n /** Filtered headers (IGNORED_HEADERS excluded, keys lowercased) */\n headers: z\n .record(z.string(), z.string())\n .openapi({\n description: \"Filtered headers (IGNORED_HEADERS excluded, keys lowercased)\",\n }),\n /** Raw body string */\n body: z\n .string()\n .max(65536)\n .nullable()\n .openapi({ description: \"Raw body string\" }),\n /**\n * Parsed JSON body. Authored as `z.unknown().pipe(z.json())` so\n * zod-to-openapi sees the outer `z.unknown()` and emits a permissive\n * field (no recursive `$ref`, no type), while the inner `z.json()`\n * still rejects non-JSON values (`Date`, `undefined`, functions) at\n * parse time. Same inferred `JsonValue` type either way.\n */\n body_json: z\n .unknown()\n .pipe(z.json())\n .nullable()\n .describe(\"Parsed JSON body (if applicable)\"),\n /** Zapier connection ID used for this request */\n connection_id: z\n .string()\n .max(255)\n .optional()\n .openapi({ description: \"Zapier connection ID used for this request\" }),\n /** Optional human-readable reason for the request */\n reason: z\n .string()\n .max(1024)\n .optional()\n .openapi({ description: \"Optional human-readable reason for the request\" }),\n })\n .openapi(\"HttpRequestContext\");\nexport type HttpRequestContext = z.infer<typeof HttpRequestContextSchema>;\n\n/**\n * Canonical Zapier action types.\n *\n * Mirrors the `action_type` enum in sdkapi's OpenAPI spec\n * (`packages/openapi-spec/openapi.d.ts` `action_type`). Single source of\n * truth for any code that branches on or filters by action_type — keeps\n * `ActionRunContextSchema`, `BuildActionRunContextOptionsSchema`, and the\n * `READ_ACTION_TYPES` allowlist in `connection-policy.ts` aligned.\n */\nexport const ActionTypeSchema = z\n .enum([\n \"filter\",\n \"read\",\n \"read_bulk\",\n \"run\",\n \"search\",\n \"search_and_write\",\n \"search_or_write\",\n \"write\",\n ])\n .openapi(\"action_type\", { description: \"Canonical Zapier action type.\" });\nexport type ActionType = z.infer<typeof ActionTypeSchema>;\n\n/**\n * Allowed character set for the `selected_api` segment of an action\n * resource. Blocks `*`, `/`, `:`, whitespace, and other glob/path\n * metacharacters that would otherwise widen policy scope. Permits at\n * most one `@`, which `globSelectedApiVersion` treats as the\n * version separator.\n */\nexport const ACTION_RESOURCE_SEGMENT_PATTERN =\n /^[A-Za-z0-9._+-]+(?:@[A-Za-z0-9._+-]+)?$/;\n\n/**\n * Allowed character set for the `action_key` segment of an action\n * resource. More permissive than `ACTION_RESOURCE_SEGMENT_PATTERN`\n * because sdkapi emits keys like `ae:358405` and `core:123abc` that\n * carry a namespace prefix separated by `:`. Still blocks `*`, `/`,\n * whitespace, and other glob/path metacharacters.\n */\nexport const ACTION_KEY_SEGMENT_PATTERN =\n /^[A-Za-z0-9._+:-]+(?:@[A-Za-z0-9._+:-]+)?$/;\n\n/**\n * Parse an action resource string of the form\n * `action/{selected_api}/{action_type}/{action_key}` into its parts.\n * Throws if the string doesn't match the canonical 4-segment shape or\n * if its `action_type` segment isn't one of the canonical 8 — every\n * action_run context that has been through `ActionRunContextSchema` is\n * guaranteed to parse cleanly, so a thrown error here means upstream\n * validation was bypassed.\n */\nexport function parseActionResource(resource: string): {\n selected_api: string;\n action_type: ActionType;\n action_key: string;\n} {\n const segments = resource.split(\"/\");\n if (segments.length !== 4 || segments[0] !== \"action\") {\n throw new Error(\n `action resource must be action/{selected_api}/{action_type}/{action_key}: got ${resource}`,\n );\n }\n const [, selectedApi, actionTypeRaw, actionKey] = segments;\n if (!selectedApi || !actionTypeRaw || !actionKey) {\n throw new Error(`action resource has empty segment: ${resource}`);\n }\n const actionType = ActionTypeSchema.safeParse(actionTypeRaw);\n if (!actionType.success) {\n throw new Error(\n `action resource has unknown action_type \"${actionTypeRaw}\": ${resource}`,\n );\n }\n if (!ACTION_RESOURCE_SEGMENT_PATTERN.test(selectedApi)) {\n throw new Error(\n `action resource has invalid selected_api segment \"${selectedApi}\": ${resource}`,\n );\n }\n if (!ACTION_KEY_SEGMENT_PATTERN.test(actionKey)) {\n throw new Error(\n `action resource has invalid action_key segment \"${actionKey}\": ${resource}`,\n );\n }\n return {\n selected_api: selectedApi,\n action_type: actionType.data,\n action_key: actionKey,\n };\n}\n\n/**\n * Raw input shape for `ActionRunContextSchema`, before the transform that\n * canonicalizes legacy fields into `resource`. Exposed for the OpenAPI\n * schema generator (which can't represent transforms) — runtime callers\n * should use `ActionRunContextSchema`, which accepts either the canonical\n * `resource` field or the legacy `{selected_api, action_type, action_key}`\n * triple on input.\n */\nexport const ActionRunContextInputSchema = z\n .object({\n request_type: z\n .literal(\"action_run\")\n .openapi({ description: \"Context type discriminator\" }),\n resource: z\n .string()\n .max(1024)\n .optional()\n .openapi({\n description:\n \"Canonical action resource, e.g. action/Slack@1.0.0/write/send_message\",\n }),\n selected_api: z\n .string()\n .max(255)\n .optional()\n .openapi({\n deprecated: true,\n description:\n \"Legacy: app identifier, e.g. Slack@1.0.0. Prefer `resource`.\",\n }),\n action_type: ActionTypeSchema.optional().openapi({\n deprecated: true,\n description: \"Legacy: canonical Zapier action type. Prefer `resource`.\",\n }),\n action_key: z\n .string()\n .max(255)\n .optional()\n .openapi({\n deprecated: true,\n description:\n \"Legacy: action key, e.g. send_message. Prefer `resource`.\",\n }),\n connection_id: z\n .string()\n .max(255)\n .optional()\n .openapi({ description: \"Zapier connection ID used for this request\" }),\n /** Action input parameters. See body_json above for the pipe rationale. */\n inputs: z\n .unknown()\n .pipe(z.json())\n .optional()\n .describe(\"Action input parameters\"),\n reason: z\n .string()\n .max(1024)\n .optional()\n .openapi({ description: \"Optional human-readable reason for the request\" }),\n })\n .openapi(\"ActionRunContext\", {\n description:\n \"Action run context. The canonical shape carries the action identity in a single `resource` field of the form `action/{selected_api}/{action_type}/{action_key}`. The legacy `{selected_api, action_type, action_key}` shape is also accepted on input during the migration window — approvalsapi normalizes it to the canonical form before storage.\",\n });\n\nexport const ActionRunContextSchema = ActionRunContextInputSchema.transform(\n (input, ctx) => {\n const resource =\n input.resource ??\n (input.selected_api && input.action_type && input.action_key\n ? `action/${input.selected_api}/${input.action_type}/${input.action_key}`\n : undefined);\n if (resource === undefined) {\n ctx.addIssue({\n code: \"custom\",\n message:\n \"action_run context requires either `resource` or all of `selected_api`/`action_type`/`action_key`\",\n });\n return z.NEVER;\n }\n try {\n parseActionResource(resource);\n } catch (err) {\n ctx.addIssue({\n code: \"custom\",\n message: err instanceof Error ? err.message : String(err),\n });\n return z.NEVER;\n }\n return {\n request_type: \"action_run\" as const,\n resource,\n ...(input.connection_id !== undefined && {\n connection_id: input.connection_id,\n }),\n ...(input.inputs !== undefined && { inputs: input.inputs }),\n ...(input.reason !== undefined && { reason: input.reason }),\n };\n },\n);\nexport type ActionRunContext = z.infer<typeof ActionRunContextSchema>;\n\n/**\n * Union of all request context types, keyed on `request_type`.\n *\n * Plain `z.union` (not `z.discriminatedUnion`) because\n * `ActionRunContextSchema` carries a `.transform` and discriminated\n * unions can't accept a `ZodEffects` member. The discriminator metadata\n * below tells OpenAPI consumers how to narrow the union — zod-to-openapi\n * emits this as `anyOf` + discriminator, which openapi-typescript and\n * other codegen targets render as a properly narrowed TS union.\n */\nexport const RequestContextSchema = z\n .union([HttpRequestContextSchema, ActionRunContextSchema])\n .openapi(\"RequestContext\", {\n description: \"Union of request context shapes, keyed on `request_type`.\",\n discriminator: {\n propertyName: \"request_type\",\n mapping: {\n http_request: \"#/components/schemas/HttpRequestContext\",\n action_run: \"#/components/schemas/ActionRunContext\",\n },\n },\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 ActionTypeSchema,\n parseUrl,\n ACTION_RESOURCE_SEGMENT_PATTERN,\n ACTION_KEY_SEGMENT_PATTERN,\n type HttpRequestContext,\n type ActionRunContext,\n} from \"./types.ts\";\nimport { buildActionResource } from \"./conditions.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: z.json().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 // Validate options up-front so downstream string ops (e.g. method.toUpperCase)\n // see well-typed values. Mirrors the pattern in buildActionRunContext.\n const parsed = BuildHttpRequestContextOptionsSchema.parse(options);\n\n // Normalize URL — SDK CLI strips the protocol\n const rawUrl = parsed.url.includes(\"://\")\n ? parsed.url\n : `https://${parsed.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 (parsed.headers) {\n for (const [key, value] of Object.entries(parsed.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 (parsed.body_json !== undefined) {\n body_json = parsed.body_json;\n } else if (parsed.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(parsed.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: parsed.method.toUpperCase(),\n url,\n headers,\n body: parsed.body ?? null,\n body_json,\n connection_id: parsed.connection_id,\n });\n}\n\nexport const BuildActionRunContextOptionsSchema = z.object({\n selected_api: z.string().regex(ACTION_RESOURCE_SEGMENT_PATTERN, {\n message:\n \"selected_api must contain only [A-Za-z0-9._@+-] (no globs, slashes, or whitespace)\",\n }),\n action_type: ActionTypeSchema,\n action_key: z.string().regex(ACTION_KEY_SEGMENT_PATTERN, {\n message:\n \"action_key must contain only [A-Za-z0-9._@:+-] (no globs, slashes, or whitespace)\",\n }),\n connection_id: z.string().optional(),\n inputs: z.json().optional(),\n reason: z.string().optional(),\n});\nexport type BuildActionRunContextOptions = z.infer<\n typeof BuildActionRunContextOptionsSchema\n>;\n\n/**\n * Build a canonical ActionRunContext from raw action parts.\n *\n * Callers pass the three identity fields separately for readability;\n * this validates them and collapses them into the canonical `resource`\n * string the schema stores.\n */\nexport function buildActionRunContext(\n options: BuildActionRunContextOptions,\n): ActionRunContext {\n const parsed = BuildActionRunContextOptionsSchema.parse(options);\n return ActionRunContextSchema.parse({\n request_type: \"action_run\",\n resource: buildActionResource({\n selected_api: parsed.selected_api,\n action_type: parsed.action_type,\n action_key: parsed.action_key,\n }),\n connection_id: parsed.connection_id,\n inputs: parsed.inputs,\n reason: parsed.reason,\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 {\n HttpRequestContext,\n ActionRunContext,\n ActionType,\n} 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 } else if (context.body !== null) {\n // Non-JSON body (text/plain, XML, form-encoded): pin the raw body so\n // exact-match policies actually match the originating request.\n conditions.push({\n path: [\"body\"],\n operator: \"equals\",\n value: context.body,\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 (context.inputs !== undefined && context.inputs !== null) {\n conditions.push({\n path: [\"inputs\"],\n operator: \"equals\",\n value: context.inputs,\n });\n }\n\n return conditions;\n}\n\n/**\n * The three identity fields that compose an action resource string.\n */\nexport interface ActionResourceParts {\n selected_api: string;\n action_type: ActionType;\n action_key: string;\n}\n\n/**\n * Build the resource string for an action.\n * Format: action/{selected_api}/{action_type}/{action_key}\n */\nexport function buildActionResource(parts: ActionResourceParts): string {\n return `action/${parts.selected_api}/${parts.action_type}/${parts.action_key}`;\n}\n\n/**\n * Build a broad action resource that matches all actions of the same type\n * for an app (e.g. all reads, all writes). Scopes on `action_type` to\n * avoid silently granting cross-type access.\n *\n * Format: action/{selected_api}/{action_type}/{wildcard}\n */\nexport function buildBroadActionResource(\n parts: Pick<ActionResourceParts, \"selected_api\" | \"action_type\">,\n): string {\n return `action/${parts.selected_api}/${parts.action_type}/*`;\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} 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: [context.resource],\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\";\nimport {\n parseActionResource,\n type ActionType,\n type RequestContext,\n} from \"./types.ts\";\n\n/**\n * Replace the implementation-version suffix of a `selected_api` with a `@*`\n * wildcard so connection-level policies stay valid across version bumps. A\n * runtime request with `selected_api: \"App@2.7.3\"` matches a policy resource\n * scoped to `App@*` while still being distinguishable from a different app\n * (e.g. `App2@1.0.0`).\n *\n * No-op when the input has no `@` — assumed to be already version-less.\n */\nfunction globSelectedApiVersion(selectedApi: string): string {\n const at = selectedApi.indexOf(\"@\");\n return at === -1 ? selectedApi : selectedApi.slice(0, at) + \"@*\";\n}\n\nexport const AccessLevelSchema = z.enum([\"read\", \"read_write\"]);\nexport type AccessLevel = z.infer<typeof AccessLevelSchema>;\n\n/** HTTP methods that count as side-effect-free reads for connection-level policies. */\nexport const READ_HTTP_METHODS = [\"GET\", \"HEAD\", \"OPTIONS\"] as const;\n\n/**\n * Action types that count as side-effect-free reads for connection-level\n * policies. `read_bulk` is the paginated/bulk variant of `read` — same\n * external API semantics, no mutations. Widely used by major apps (Slack,\n * Gmail, Jira, Salesforce, etc.) via the public `bulkReads` schema key.\n * `filter` and `run` are excluded: neither has a runtime executor for\n * external apps, and `filter` actions don't carry a connection_id anyway,\n * so this allowlist has no effect on them.\n */\nexport const READ_ACTION_TYPES = [\n \"read\",\n \"read_bulk\",\n \"search\",\n] as const satisfies readonly ActionType[];\n\nconst READ_HTTP_METHOD_SET: ReadonlySet<string> = new Set(READ_HTTP_METHODS);\nconst READ_ACTION_TYPE_SET: ReadonlySet<ActionType> = new Set(\n READ_ACTION_TYPES,\n);\n\n/**\n * Returns true when the request needs write access (i.e. it is NOT a\n * side-effect-free read). Mirrors the logic encoded in `buildConnectionPolicy`\n * so UI surfaces that gate the read-vs-read_write choice stay consistent\n * with the policies they generate.\n */\nexport function isWriteRequest(context: RequestContext): boolean {\n if (context.request_type === \"http_request\") {\n // Method is uppercase by construction (buildHttpRequestContext canonicalizes\n // it on the way in), so no normalization is needed here.\n return !READ_HTTP_METHOD_SET.has(context.method);\n }\n const { action_type } = parseActionResource(context.resource);\n return !READ_ACTION_TYPE_SET.has(action_type);\n}\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}/{action_type}/*` per allowed type,\n * scoped by connection_id. For read access, the resource list expands to\n * one entry per read action_type so the engine matches via the resource\n * string rather than a separate `path: [\"action_type\"]` condition.\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 apiPattern = globSelectedApiVersion(selectedApi);\n const actionResources =\n accessLevel === \"read\"\n ? READ_ACTION_TYPES.map((t) => `action/${apiPattern}/${t}/*`)\n : [`action/${apiPattern}/*/*`];\n\n const actionStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: actionResources,\n conditions: [connectionCondition],\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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import * as _zapier_policy_schema from '@zapier/policy-schema';
|
|
2
|
-
import { Condition, Policy } from '@zapier/policy-schema';
|
|
3
|
-
export { JsonValueSchema } from '@zapier/policy-schema';
|
|
4
1
|
import { z } from 'zod';
|
|
2
|
+
import { Condition, Policy } from '@zapier/policy-schema';
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* Parsed URL components for policy evaluation.
|
|
@@ -48,7 +46,7 @@ declare const HttpRequestContextSchema: z.ZodObject<{
|
|
|
48
46
|
}, z.core.$strip>;
|
|
49
47
|
headers: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
50
48
|
body: z.ZodNullable<z.ZodString>;
|
|
51
|
-
body_json: z.ZodNullable<z.
|
|
49
|
+
body_json: z.ZodNullable<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
|
|
52
50
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
53
51
|
reason: z.ZodOptional<z.ZodString>;
|
|
54
52
|
}, z.core.$strip>;
|
|
@@ -87,6 +85,33 @@ declare function parseActionResource(resource: string): {
|
|
|
87
85
|
action_type: ActionType;
|
|
88
86
|
action_key: string;
|
|
89
87
|
};
|
|
88
|
+
/**
|
|
89
|
+
* Raw input shape for `ActionRunContextSchema`, before the transform that
|
|
90
|
+
* canonicalizes legacy fields into `resource`. Exposed for the OpenAPI
|
|
91
|
+
* schema generator (which can't represent transforms) — runtime callers
|
|
92
|
+
* should use `ActionRunContextSchema`, which accepts either the canonical
|
|
93
|
+
* `resource` field or the legacy `{selected_api, action_type, action_key}`
|
|
94
|
+
* triple on input.
|
|
95
|
+
*/
|
|
96
|
+
declare const ActionRunContextInputSchema: z.ZodObject<{
|
|
97
|
+
request_type: z.ZodLiteral<"action_run">;
|
|
98
|
+
resource: z.ZodOptional<z.ZodString>;
|
|
99
|
+
selected_api: z.ZodOptional<z.ZodString>;
|
|
100
|
+
action_type: z.ZodOptional<z.ZodEnum<{
|
|
101
|
+
filter: "filter";
|
|
102
|
+
read: "read";
|
|
103
|
+
read_bulk: "read_bulk";
|
|
104
|
+
run: "run";
|
|
105
|
+
search: "search";
|
|
106
|
+
search_and_write: "search_and_write";
|
|
107
|
+
search_or_write: "search_or_write";
|
|
108
|
+
write: "write";
|
|
109
|
+
}>>;
|
|
110
|
+
action_key: z.ZodOptional<z.ZodString>;
|
|
111
|
+
connection_id: z.ZodOptional<z.ZodString>;
|
|
112
|
+
inputs: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
|
|
113
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
114
|
+
}, z.core.$strip>;
|
|
90
115
|
declare const ActionRunContextSchema: z.ZodPipe<z.ZodObject<{
|
|
91
116
|
request_type: z.ZodLiteral<"action_run">;
|
|
92
117
|
resource: z.ZodOptional<z.ZodString>;
|
|
@@ -103,11 +128,11 @@ declare const ActionRunContextSchema: z.ZodPipe<z.ZodObject<{
|
|
|
103
128
|
}>>;
|
|
104
129
|
action_key: z.ZodOptional<z.ZodString>;
|
|
105
130
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
106
|
-
inputs: z.ZodOptional<z.
|
|
131
|
+
inputs: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
|
|
107
132
|
reason: z.ZodOptional<z.ZodString>;
|
|
108
133
|
}, z.core.$strip>, z.ZodTransform<{
|
|
109
134
|
reason?: string | undefined;
|
|
110
|
-
inputs?:
|
|
135
|
+
inputs?: z.core.util.JSONType | undefined;
|
|
111
136
|
connection_id?: string | undefined;
|
|
112
137
|
request_type: "action_run";
|
|
113
138
|
resource: string;
|
|
@@ -118,7 +143,7 @@ declare const ActionRunContextSchema: z.ZodPipe<z.ZodObject<{
|
|
|
118
143
|
action_type?: "filter" | "read" | "read_bulk" | "run" | "search" | "search_and_write" | "search_or_write" | "write" | undefined;
|
|
119
144
|
action_key?: string | undefined;
|
|
120
145
|
connection_id?: string | undefined;
|
|
121
|
-
inputs?:
|
|
146
|
+
inputs?: z.core.util.JSONType | undefined;
|
|
122
147
|
reason?: string | undefined;
|
|
123
148
|
}>>;
|
|
124
149
|
type ActionRunContext = z.infer<typeof ActionRunContextSchema>;
|
|
@@ -127,7 +152,10 @@ type ActionRunContext = z.infer<typeof ActionRunContextSchema>;
|
|
|
127
152
|
*
|
|
128
153
|
* Plain `z.union` (not `z.discriminatedUnion`) because
|
|
129
154
|
* `ActionRunContextSchema` carries a `.transform` and discriminated
|
|
130
|
-
* unions can't accept a `ZodEffects` member.
|
|
155
|
+
* unions can't accept a `ZodEffects` member. The discriminator metadata
|
|
156
|
+
* below tells OpenAPI consumers how to narrow the union — zod-to-openapi
|
|
157
|
+
* emits this as `anyOf` + discriminator, which openapi-typescript and
|
|
158
|
+
* other codegen targets render as a properly narrowed TS union.
|
|
131
159
|
*/
|
|
132
160
|
declare const RequestContextSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
133
161
|
request_type: z.ZodLiteral<"http_request">;
|
|
@@ -141,7 +169,7 @@ declare const RequestContextSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
141
169
|
}, z.core.$strip>;
|
|
142
170
|
headers: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
143
171
|
body: z.ZodNullable<z.ZodString>;
|
|
144
|
-
body_json: z.ZodNullable<z.
|
|
172
|
+
body_json: z.ZodNullable<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
|
|
145
173
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
146
174
|
reason: z.ZodOptional<z.ZodString>;
|
|
147
175
|
}, z.core.$strip>, z.ZodPipe<z.ZodObject<{
|
|
@@ -160,11 +188,11 @@ declare const RequestContextSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
160
188
|
}>>;
|
|
161
189
|
action_key: z.ZodOptional<z.ZodString>;
|
|
162
190
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
163
|
-
inputs: z.ZodOptional<z.
|
|
191
|
+
inputs: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
|
|
164
192
|
reason: z.ZodOptional<z.ZodString>;
|
|
165
193
|
}, z.core.$strip>, z.ZodTransform<{
|
|
166
194
|
reason?: string | undefined;
|
|
167
|
-
inputs?:
|
|
195
|
+
inputs?: z.core.util.JSONType | undefined;
|
|
168
196
|
connection_id?: string | undefined;
|
|
169
197
|
request_type: "action_run";
|
|
170
198
|
resource: string;
|
|
@@ -175,7 +203,7 @@ declare const RequestContextSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
175
203
|
action_type?: "filter" | "read" | "read_bulk" | "run" | "search" | "search_and_write" | "search_or_write" | "write" | undefined;
|
|
176
204
|
action_key?: string | undefined;
|
|
177
205
|
connection_id?: string | undefined;
|
|
178
|
-
inputs?:
|
|
206
|
+
inputs?: z.core.util.JSONType | undefined;
|
|
179
207
|
reason?: string | undefined;
|
|
180
208
|
}>>]>;
|
|
181
209
|
type RequestContext = z.infer<typeof RequestContextSchema>;
|
|
@@ -194,7 +222,7 @@ declare const BuildHttpRequestContextOptionsSchema: z.ZodObject<{
|
|
|
194
222
|
url: z.ZodString;
|
|
195
223
|
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodUndefined]>>>;
|
|
196
224
|
body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
197
|
-
body_json: z.ZodOptional<z.
|
|
225
|
+
body_json: z.ZodOptional<z.ZodJSONSchema>;
|
|
198
226
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
199
227
|
}, z.core.$strip>;
|
|
200
228
|
type BuildHttpRequestContextOptions = z.infer<typeof BuildHttpRequestContextOptionsSchema>;
|
|
@@ -228,7 +256,7 @@ declare const BuildActionRunContextOptionsSchema: z.ZodObject<{
|
|
|
228
256
|
}>;
|
|
229
257
|
action_key: z.ZodString;
|
|
230
258
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
231
|
-
inputs: z.ZodOptional<z.
|
|
259
|
+
inputs: z.ZodOptional<z.ZodJSONSchema>;
|
|
232
260
|
reason: z.ZodOptional<z.ZodString>;
|
|
233
261
|
}, z.core.$strip>;
|
|
234
262
|
type BuildActionRunContextOptions = z.infer<typeof BuildActionRunContextOptionsSchema>;
|
|
@@ -335,4 +363,4 @@ declare function buildConnectionPolicy(options: {
|
|
|
335
363
|
accessLevel: AccessLevel;
|
|
336
364
|
}): Policy;
|
|
337
365
|
|
|
338
|
-
export { type AccessLevel, AccessLevelSchema, type ActionRunContext, ActionRunContextSchema, type ActionType, ActionTypeSchema, type BuildActionRunContextOptions, BuildActionRunContextOptionsSchema, type BuildHttpRequestContextOptions, BuildHttpRequestContextOptionsSchema, DEFAULT_PORTS, type HttpRequestContext, HttpRequestContextSchema, IGNORED_HEADERS, type ParsedUrl, ParsedUrlSchema, READ_ACTION_TYPES, READ_HTTP_METHODS, type RequestContext, RequestContextSchema, buildActionResource, buildActionRunContext, buildBroadActionResource, buildConnectionPolicy, buildDomainHttpConditions, buildExactActionConditions, buildExactHttpConditions, buildHttpRequestContext, buildUrlString, isWriteRequest, parseActionResource, parseUrl, toExactPolicy };
|
|
366
|
+
export { type AccessLevel, AccessLevelSchema, type ActionRunContext, ActionRunContextInputSchema, ActionRunContextSchema, type ActionType, ActionTypeSchema, type BuildActionRunContextOptions, BuildActionRunContextOptionsSchema, type BuildHttpRequestContextOptions, BuildHttpRequestContextOptionsSchema, DEFAULT_PORTS, type HttpRequestContext, HttpRequestContextSchema, IGNORED_HEADERS, type ParsedUrl, ParsedUrlSchema, READ_ACTION_TYPES, READ_HTTP_METHODS, type RequestContext, RequestContextSchema, buildActionResource, buildActionRunContext, buildBroadActionResource, buildConnectionPolicy, buildDomainHttpConditions, buildExactActionConditions, buildExactHttpConditions, buildHttpRequestContext, buildUrlString, isWriteRequest, parseActionResource, parseUrl, toExactPolicy };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import * as _zapier_policy_schema from '@zapier/policy-schema';
|
|
2
|
-
import { Condition, Policy } from '@zapier/policy-schema';
|
|
3
|
-
export { JsonValueSchema } from '@zapier/policy-schema';
|
|
4
1
|
import { z } from 'zod';
|
|
2
|
+
import { Condition, Policy } from '@zapier/policy-schema';
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* Parsed URL components for policy evaluation.
|
|
@@ -48,7 +46,7 @@ declare const HttpRequestContextSchema: z.ZodObject<{
|
|
|
48
46
|
}, z.core.$strip>;
|
|
49
47
|
headers: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
50
48
|
body: z.ZodNullable<z.ZodString>;
|
|
51
|
-
body_json: z.ZodNullable<z.
|
|
49
|
+
body_json: z.ZodNullable<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
|
|
52
50
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
53
51
|
reason: z.ZodOptional<z.ZodString>;
|
|
54
52
|
}, z.core.$strip>;
|
|
@@ -87,6 +85,33 @@ declare function parseActionResource(resource: string): {
|
|
|
87
85
|
action_type: ActionType;
|
|
88
86
|
action_key: string;
|
|
89
87
|
};
|
|
88
|
+
/**
|
|
89
|
+
* Raw input shape for `ActionRunContextSchema`, before the transform that
|
|
90
|
+
* canonicalizes legacy fields into `resource`. Exposed for the OpenAPI
|
|
91
|
+
* schema generator (which can't represent transforms) — runtime callers
|
|
92
|
+
* should use `ActionRunContextSchema`, which accepts either the canonical
|
|
93
|
+
* `resource` field or the legacy `{selected_api, action_type, action_key}`
|
|
94
|
+
* triple on input.
|
|
95
|
+
*/
|
|
96
|
+
declare const ActionRunContextInputSchema: z.ZodObject<{
|
|
97
|
+
request_type: z.ZodLiteral<"action_run">;
|
|
98
|
+
resource: z.ZodOptional<z.ZodString>;
|
|
99
|
+
selected_api: z.ZodOptional<z.ZodString>;
|
|
100
|
+
action_type: z.ZodOptional<z.ZodEnum<{
|
|
101
|
+
filter: "filter";
|
|
102
|
+
read: "read";
|
|
103
|
+
read_bulk: "read_bulk";
|
|
104
|
+
run: "run";
|
|
105
|
+
search: "search";
|
|
106
|
+
search_and_write: "search_and_write";
|
|
107
|
+
search_or_write: "search_or_write";
|
|
108
|
+
write: "write";
|
|
109
|
+
}>>;
|
|
110
|
+
action_key: z.ZodOptional<z.ZodString>;
|
|
111
|
+
connection_id: z.ZodOptional<z.ZodString>;
|
|
112
|
+
inputs: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
|
|
113
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
114
|
+
}, z.core.$strip>;
|
|
90
115
|
declare const ActionRunContextSchema: z.ZodPipe<z.ZodObject<{
|
|
91
116
|
request_type: z.ZodLiteral<"action_run">;
|
|
92
117
|
resource: z.ZodOptional<z.ZodString>;
|
|
@@ -103,11 +128,11 @@ declare const ActionRunContextSchema: z.ZodPipe<z.ZodObject<{
|
|
|
103
128
|
}>>;
|
|
104
129
|
action_key: z.ZodOptional<z.ZodString>;
|
|
105
130
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
106
|
-
inputs: z.ZodOptional<z.
|
|
131
|
+
inputs: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
|
|
107
132
|
reason: z.ZodOptional<z.ZodString>;
|
|
108
133
|
}, z.core.$strip>, z.ZodTransform<{
|
|
109
134
|
reason?: string | undefined;
|
|
110
|
-
inputs?:
|
|
135
|
+
inputs?: z.core.util.JSONType | undefined;
|
|
111
136
|
connection_id?: string | undefined;
|
|
112
137
|
request_type: "action_run";
|
|
113
138
|
resource: string;
|
|
@@ -118,7 +143,7 @@ declare const ActionRunContextSchema: z.ZodPipe<z.ZodObject<{
|
|
|
118
143
|
action_type?: "filter" | "read" | "read_bulk" | "run" | "search" | "search_and_write" | "search_or_write" | "write" | undefined;
|
|
119
144
|
action_key?: string | undefined;
|
|
120
145
|
connection_id?: string | undefined;
|
|
121
|
-
inputs?:
|
|
146
|
+
inputs?: z.core.util.JSONType | undefined;
|
|
122
147
|
reason?: string | undefined;
|
|
123
148
|
}>>;
|
|
124
149
|
type ActionRunContext = z.infer<typeof ActionRunContextSchema>;
|
|
@@ -127,7 +152,10 @@ type ActionRunContext = z.infer<typeof ActionRunContextSchema>;
|
|
|
127
152
|
*
|
|
128
153
|
* Plain `z.union` (not `z.discriminatedUnion`) because
|
|
129
154
|
* `ActionRunContextSchema` carries a `.transform` and discriminated
|
|
130
|
-
* unions can't accept a `ZodEffects` member.
|
|
155
|
+
* unions can't accept a `ZodEffects` member. The discriminator metadata
|
|
156
|
+
* below tells OpenAPI consumers how to narrow the union — zod-to-openapi
|
|
157
|
+
* emits this as `anyOf` + discriminator, which openapi-typescript and
|
|
158
|
+
* other codegen targets render as a properly narrowed TS union.
|
|
131
159
|
*/
|
|
132
160
|
declare const RequestContextSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
133
161
|
request_type: z.ZodLiteral<"http_request">;
|
|
@@ -141,7 +169,7 @@ declare const RequestContextSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
141
169
|
}, z.core.$strip>;
|
|
142
170
|
headers: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
143
171
|
body: z.ZodNullable<z.ZodString>;
|
|
144
|
-
body_json: z.ZodNullable<z.
|
|
172
|
+
body_json: z.ZodNullable<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
|
|
145
173
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
146
174
|
reason: z.ZodOptional<z.ZodString>;
|
|
147
175
|
}, z.core.$strip>, z.ZodPipe<z.ZodObject<{
|
|
@@ -160,11 +188,11 @@ declare const RequestContextSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
160
188
|
}>>;
|
|
161
189
|
action_key: z.ZodOptional<z.ZodString>;
|
|
162
190
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
163
|
-
inputs: z.ZodOptional<z.
|
|
191
|
+
inputs: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
|
|
164
192
|
reason: z.ZodOptional<z.ZodString>;
|
|
165
193
|
}, z.core.$strip>, z.ZodTransform<{
|
|
166
194
|
reason?: string | undefined;
|
|
167
|
-
inputs?:
|
|
195
|
+
inputs?: z.core.util.JSONType | undefined;
|
|
168
196
|
connection_id?: string | undefined;
|
|
169
197
|
request_type: "action_run";
|
|
170
198
|
resource: string;
|
|
@@ -175,7 +203,7 @@ declare const RequestContextSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
175
203
|
action_type?: "filter" | "read" | "read_bulk" | "run" | "search" | "search_and_write" | "search_or_write" | "write" | undefined;
|
|
176
204
|
action_key?: string | undefined;
|
|
177
205
|
connection_id?: string | undefined;
|
|
178
|
-
inputs?:
|
|
206
|
+
inputs?: z.core.util.JSONType | undefined;
|
|
179
207
|
reason?: string | undefined;
|
|
180
208
|
}>>]>;
|
|
181
209
|
type RequestContext = z.infer<typeof RequestContextSchema>;
|
|
@@ -194,7 +222,7 @@ declare const BuildHttpRequestContextOptionsSchema: z.ZodObject<{
|
|
|
194
222
|
url: z.ZodString;
|
|
195
223
|
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodUndefined]>>>;
|
|
196
224
|
body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
197
|
-
body_json: z.ZodOptional<z.
|
|
225
|
+
body_json: z.ZodOptional<z.ZodJSONSchema>;
|
|
198
226
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
199
227
|
}, z.core.$strip>;
|
|
200
228
|
type BuildHttpRequestContextOptions = z.infer<typeof BuildHttpRequestContextOptionsSchema>;
|
|
@@ -228,7 +256,7 @@ declare const BuildActionRunContextOptionsSchema: z.ZodObject<{
|
|
|
228
256
|
}>;
|
|
229
257
|
action_key: z.ZodString;
|
|
230
258
|
connection_id: z.ZodOptional<z.ZodString>;
|
|
231
|
-
inputs: z.ZodOptional<z.
|
|
259
|
+
inputs: z.ZodOptional<z.ZodJSONSchema>;
|
|
232
260
|
reason: z.ZodOptional<z.ZodString>;
|
|
233
261
|
}, z.core.$strip>;
|
|
234
262
|
type BuildActionRunContextOptions = z.infer<typeof BuildActionRunContextOptionsSchema>;
|
|
@@ -335,4 +363,4 @@ declare function buildConnectionPolicy(options: {
|
|
|
335
363
|
accessLevel: AccessLevel;
|
|
336
364
|
}): Policy;
|
|
337
365
|
|
|
338
|
-
export { type AccessLevel, AccessLevelSchema, type ActionRunContext, ActionRunContextSchema, type ActionType, ActionTypeSchema, type BuildActionRunContextOptions, BuildActionRunContextOptionsSchema, type BuildHttpRequestContextOptions, BuildHttpRequestContextOptionsSchema, DEFAULT_PORTS, type HttpRequestContext, HttpRequestContextSchema, IGNORED_HEADERS, type ParsedUrl, ParsedUrlSchema, READ_ACTION_TYPES, READ_HTTP_METHODS, type RequestContext, RequestContextSchema, buildActionResource, buildActionRunContext, buildBroadActionResource, buildConnectionPolicy, buildDomainHttpConditions, buildExactActionConditions, buildExactHttpConditions, buildHttpRequestContext, buildUrlString, isWriteRequest, parseActionResource, parseUrl, toExactPolicy };
|
|
366
|
+
export { type AccessLevel, AccessLevelSchema, type ActionRunContext, ActionRunContextInputSchema, ActionRunContextSchema, type ActionType, ActionTypeSchema, type BuildActionRunContextOptions, BuildActionRunContextOptionsSchema, type BuildHttpRequestContextOptions, BuildHttpRequestContextOptionsSchema, DEFAULT_PORTS, type HttpRequestContext, HttpRequestContextSchema, IGNORED_HEADERS, type ParsedUrl, ParsedUrlSchema, READ_ACTION_TYPES, READ_HTTP_METHODS, type RequestContext, RequestContextSchema, buildActionResource, buildActionRunContext, buildBroadActionResource, buildConnectionPolicy, buildDomainHttpConditions, buildExactActionConditions, buildExactHttpConditions, buildHttpRequestContext, buildUrlString, isWriteRequest, parseActionResource, parseUrl, toExactPolicy };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// src/types.ts
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi";
|
|
4
|
-
import { JsonValueSchema } from "@zapier/policy-schema";
|
|
5
4
|
extendZodWithOpenApi(z);
|
|
6
5
|
var ParsedUrlSchema = z.object({
|
|
7
6
|
scheme: z.string().openapi({ description: 'URL scheme, e.g. "https"' }),
|
|
@@ -13,7 +12,9 @@ var ParsedUrlSchema = z.object({
|
|
|
13
12
|
query: z.record(z.string(), z.array(z.string())).openapi({
|
|
14
13
|
description: "Query parameters as key to string array mapping"
|
|
15
14
|
})
|
|
16
|
-
}).openapi("ParsedUrl"
|
|
15
|
+
}).openapi("ParsedUrl", {
|
|
16
|
+
description: "Parsed URL components for policy condition matching"
|
|
17
|
+
});
|
|
17
18
|
var DEFAULT_PORTS = {
|
|
18
19
|
http: 80,
|
|
19
20
|
https: 443
|
|
@@ -47,8 +48,8 @@ function buildUrlString(parsed) {
|
|
|
47
48
|
return `${scheme}://${host}${portString}${path}${queryString ? "?" + queryString : ""}`;
|
|
48
49
|
}
|
|
49
50
|
var HttpRequestContextSchema = z.object({
|
|
50
|
-
request_type: z.literal("http_request"),
|
|
51
|
-
method: z.string().max(10).transform((m) => m.toUpperCase()),
|
|
51
|
+
request_type: z.literal("http_request").openapi({ description: "Context type discriminator" }),
|
|
52
|
+
method: z.string().max(10).transform((m) => m.toUpperCase()).openapi({ description: "HTTP method" }),
|
|
52
53
|
/** Parsed URL components for policy condition matching */
|
|
53
54
|
url: ParsedUrlSchema,
|
|
54
55
|
/** Filtered headers (IGNORED_HEADERS excluded, keys lowercased) */
|
|
@@ -56,16 +57,15 @@ var HttpRequestContextSchema = z.object({
|
|
|
56
57
|
description: "Filtered headers (IGNORED_HEADERS excluded, keys lowercased)"
|
|
57
58
|
}),
|
|
58
59
|
/** Raw body string */
|
|
59
|
-
body: z.string().max(65536).nullable(),
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}),
|
|
60
|
+
body: z.string().max(65536).nullable().openapi({ description: "Raw body string" }),
|
|
61
|
+
/**
|
|
62
|
+
* Parsed JSON body. Authored as `z.unknown().pipe(z.json())` so
|
|
63
|
+
* zod-to-openapi sees the outer `z.unknown()` and emits a permissive
|
|
64
|
+
* field (no recursive `$ref`, no type), while the inner `z.json()`
|
|
65
|
+
* still rejects non-JSON values (`Date`, `undefined`, functions) at
|
|
66
|
+
* parse time. Same inferred `JsonValue` type either way.
|
|
67
|
+
*/
|
|
68
|
+
body_json: z.unknown().pipe(z.json()).nullable().describe("Parsed JSON body (if applicable)"),
|
|
69
69
|
/** Zapier connection ID used for this request */
|
|
70
70
|
connection_id: z.string().max(255).optional().openapi({ description: "Zapier connection ID used for this request" }),
|
|
71
71
|
/** Optional human-readable reason for the request */
|
|
@@ -82,6 +82,7 @@ var ActionTypeSchema = z.enum([
|
|
|
82
82
|
"write"
|
|
83
83
|
]).openapi("action_type", { description: "Canonical Zapier action type." });
|
|
84
84
|
var ACTION_RESOURCE_SEGMENT_PATTERN = /^[A-Za-z0-9._+-]+(?:@[A-Za-z0-9._+-]+)?$/;
|
|
85
|
+
var ACTION_KEY_SEGMENT_PATTERN = /^[A-Za-z0-9._+:-]+(?:@[A-Za-z0-9._+:-]+)?$/;
|
|
85
86
|
function parseActionResource(resource) {
|
|
86
87
|
const segments = resource.split("/");
|
|
87
88
|
if (segments.length !== 4 || segments[0] !== "action") {
|
|
@@ -104,7 +105,7 @@ function parseActionResource(resource) {
|
|
|
104
105
|
`action resource has invalid selected_api segment "${selectedApi}": ${resource}`
|
|
105
106
|
);
|
|
106
107
|
}
|
|
107
|
-
if (!
|
|
108
|
+
if (!ACTION_KEY_SEGMENT_PATTERN.test(actionKey)) {
|
|
108
109
|
throw new Error(
|
|
109
110
|
`action resource has invalid action_key segment "${actionKey}": ${resource}`
|
|
110
111
|
);
|
|
@@ -116,7 +117,7 @@ function parseActionResource(resource) {
|
|
|
116
117
|
};
|
|
117
118
|
}
|
|
118
119
|
var ActionRunContextInputSchema = z.object({
|
|
119
|
-
request_type: z.literal("action_run"),
|
|
120
|
+
request_type: z.literal("action_run").openapi({ description: "Context type discriminator" }),
|
|
120
121
|
resource: z.string().max(1024).optional().openapi({
|
|
121
122
|
description: "Canonical action resource, e.g. action/Slack@1.0.0/write/send_message"
|
|
122
123
|
}),
|
|
@@ -133,14 +134,8 @@ var ActionRunContextInputSchema = z.object({
|
|
|
133
134
|
description: "Legacy: action key, e.g. send_message. Prefer `resource`."
|
|
134
135
|
}),
|
|
135
136
|
connection_id: z.string().max(255).optional().openapi({ description: "Zapier connection ID used for this request" }),
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
// introspection of the recursive JsonValueSchema (z.lazy). The
|
|
139
|
-
// generator script strips this `type` after emit so the produced
|
|
140
|
-
// schema matches the original "any inputs" shape.
|
|
141
|
-
type: "object",
|
|
142
|
-
description: "Action input parameters"
|
|
143
|
-
}),
|
|
137
|
+
/** Action input parameters. See body_json above for the pipe rationale. */
|
|
138
|
+
inputs: z.unknown().pipe(z.json()).optional().describe("Action input parameters"),
|
|
144
139
|
reason: z.string().max(1024).optional().openapi({ description: "Optional human-readable reason for the request" })
|
|
145
140
|
}).openapi("ActionRunContext", {
|
|
146
141
|
description: "Action run context. The canonical shape carries the action identity in a single `resource` field of the form `action/{selected_api}/{action_type}/{action_key}`. The legacy `{selected_api, action_type, action_key}` shape is also accepted on input during the migration window \u2014 approvalsapi normalizes it to the canonical form before storage."
|
|
@@ -176,7 +171,14 @@ var ActionRunContextSchema = ActionRunContextInputSchema.transform(
|
|
|
176
171
|
}
|
|
177
172
|
);
|
|
178
173
|
var RequestContextSchema = z.union([HttpRequestContextSchema, ActionRunContextSchema]).openapi("RequestContext", {
|
|
179
|
-
description: "
|
|
174
|
+
description: "Union of request context shapes, keyed on `request_type`.",
|
|
175
|
+
discriminator: {
|
|
176
|
+
propertyName: "request_type",
|
|
177
|
+
mapping: {
|
|
178
|
+
http_request: "#/components/schemas/HttpRequestContext",
|
|
179
|
+
action_run: "#/components/schemas/ActionRunContext"
|
|
180
|
+
}
|
|
181
|
+
}
|
|
180
182
|
});
|
|
181
183
|
|
|
182
184
|
// src/constants.ts
|
|
@@ -297,7 +299,7 @@ var BuildHttpRequestContextOptionsSchema = z2.object({
|
|
|
297
299
|
/** Raw body string */
|
|
298
300
|
body: z2.string().nullable().optional(),
|
|
299
301
|
/** Pre-parsed JSON body (e.g. from Fastify's automatic JSON parsing) */
|
|
300
|
-
body_json:
|
|
302
|
+
body_json: z2.json().optional(),
|
|
301
303
|
/** Connection ID associated with this request */
|
|
302
304
|
connection_id: z2.string().optional()
|
|
303
305
|
});
|
|
@@ -342,11 +344,11 @@ var BuildActionRunContextOptionsSchema = z2.object({
|
|
|
342
344
|
message: "selected_api must contain only [A-Za-z0-9._@+-] (no globs, slashes, or whitespace)"
|
|
343
345
|
}),
|
|
344
346
|
action_type: ActionTypeSchema,
|
|
345
|
-
action_key: z2.string().regex(
|
|
346
|
-
message: "action_key must contain only [A-Za-z0-9._
|
|
347
|
+
action_key: z2.string().regex(ACTION_KEY_SEGMENT_PATTERN, {
|
|
348
|
+
message: "action_key must contain only [A-Za-z0-9._@:+-] (no globs, slashes, or whitespace)"
|
|
347
349
|
}),
|
|
348
350
|
connection_id: z2.string().optional(),
|
|
349
|
-
inputs:
|
|
351
|
+
inputs: z2.json().optional(),
|
|
350
352
|
reason: z2.string().optional()
|
|
351
353
|
});
|
|
352
354
|
function buildActionRunContext(options) {
|
|
@@ -478,6 +480,7 @@ function buildConnectionPolicy(options) {
|
|
|
478
480
|
}
|
|
479
481
|
export {
|
|
480
482
|
AccessLevelSchema,
|
|
483
|
+
ActionRunContextInputSchema,
|
|
481
484
|
ActionRunContextSchema,
|
|
482
485
|
ActionTypeSchema,
|
|
483
486
|
BuildActionRunContextOptionsSchema,
|
|
@@ -485,7 +488,6 @@ export {
|
|
|
485
488
|
DEFAULT_PORTS,
|
|
486
489
|
HttpRequestContextSchema,
|
|
487
490
|
IGNORED_HEADERS,
|
|
488
|
-
JsonValueSchema,
|
|
489
491
|
ParsedUrlSchema,
|
|
490
492
|
READ_ACTION_TYPES,
|
|
491
493
|
READ_HTTP_METHODS,
|
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 { extendZodWithOpenApi } from \"@asteasolutions/zod-to-openapi\";\nimport { JsonValueSchema } from \"@zapier/policy-schema\";\n\nextendZodWithOpenApi(z);\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\n .object({\n scheme: z.string().openapi({ description: 'URL scheme, e.g. \"https\"' }),\n host: z.string().openapi({ description: 'Hostname, e.g. \"api.example.com\"' }),\n port: z\n .number()\n .int()\n .openapi({\n description: \"Port number (defaults to 443 for https, 80 for http)\",\n }),\n path: z.string().openapi({ description: 'URL path, e.g. \"/v1/foo\"' }),\n query: z\n .record(z.string(), z.array(z.string()))\n .openapi({\n description: \"Query parameters as key to string array mapping\",\n }),\n })\n .openapi(\"ParsedUrl\");\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\n .object({\n request_type: z.literal(\"http_request\"),\n method: z\n .string()\n .max(10)\n .transform((m) => m.toUpperCase()),\n /** Parsed URL components for policy condition matching */\n url: ParsedUrlSchema,\n /** Filtered headers (IGNORED_HEADERS excluded, keys lowercased) */\n headers: z\n .record(z.string(), z.string())\n .openapi({\n description: \"Filtered headers (IGNORED_HEADERS excluded, keys lowercased)\",\n }),\n /** Raw body string */\n body: z.string().max(65536).nullable(),\n /** Parsed JSON body */\n body_json: JsonValueSchema.nullable().openapi({\n // `type: 'object'` is a placeholder so zod-to-openapi short-circuits\n // introspection of the recursive JsonValueSchema (z.lazy). The\n // generator script strips this `type` after emit so the produced\n // schema matches the original \"any JSON value\" shape.\n type: \"object\",\n description: \"Parsed JSON body (if applicable)\",\n }),\n /** Zapier connection ID used for this request */\n connection_id: z\n .string()\n .max(255)\n .optional()\n .openapi({ description: \"Zapier connection ID used for this request\" }),\n /** Optional human-readable reason for the request */\n reason: z\n .string()\n .max(1024)\n .optional()\n .openapi({ description: \"Optional human-readable reason for the request\" }),\n })\n .openapi(\"HttpRequestContext\");\nexport type HttpRequestContext = z.infer<typeof HttpRequestContextSchema>;\n\n/**\n * Canonical Zapier action types.\n *\n * Mirrors the `action_type` enum in sdkapi's OpenAPI spec\n * (`packages/openapi-spec/openapi.d.ts` `action_type`). Single source of\n * truth for any code that branches on or filters by action_type — keeps\n * `ActionRunContextSchema`, `BuildActionRunContextOptionsSchema`, and the\n * `READ_ACTION_TYPES` allowlist in `connection-policy.ts` aligned.\n */\nexport const ActionTypeSchema = z\n .enum([\n \"filter\",\n \"read\",\n \"read_bulk\",\n \"run\",\n \"search\",\n \"search_and_write\",\n \"search_or_write\",\n \"write\",\n ])\n .openapi(\"action_type\", { description: \"Canonical Zapier action type.\" });\nexport type ActionType = z.infer<typeof ActionTypeSchema>;\n\n/**\n * Allowed character set for `selected_api` and `action_key` segments of\n * an action resource. Blocks `*`, `/`, whitespace, and other glob/path\n * metacharacters that would otherwise widen policy scope. Permits at\n * most one `@`, which `globSelectedApiVersion` treats as the\n * version separator.\n */\nexport const ACTION_RESOURCE_SEGMENT_PATTERN =\n /^[A-Za-z0-9._+-]+(?:@[A-Za-z0-9._+-]+)?$/;\n\n/**\n * Parse an action resource string of the form\n * `action/{selected_api}/{action_type}/{action_key}` into its parts.\n * Throws if the string doesn't match the canonical 4-segment shape or\n * if its `action_type` segment isn't one of the canonical 8 — every\n * action_run context that has been through `ActionRunContextSchema` is\n * guaranteed to parse cleanly, so a thrown error here means upstream\n * validation was bypassed.\n */\nexport function parseActionResource(resource: string): {\n selected_api: string;\n action_type: ActionType;\n action_key: string;\n} {\n const segments = resource.split(\"/\");\n if (segments.length !== 4 || segments[0] !== \"action\") {\n throw new Error(\n `action resource must be action/{selected_api}/{action_type}/{action_key}: got ${resource}`,\n );\n }\n const [, selectedApi, actionTypeRaw, actionKey] = segments;\n if (!selectedApi || !actionTypeRaw || !actionKey) {\n throw new Error(`action resource has empty segment: ${resource}`);\n }\n const actionType = ActionTypeSchema.safeParse(actionTypeRaw);\n if (!actionType.success) {\n throw new Error(\n `action resource has unknown action_type \"${actionTypeRaw}\": ${resource}`,\n );\n }\n if (!ACTION_RESOURCE_SEGMENT_PATTERN.test(selectedApi)) {\n throw new Error(\n `action resource has invalid selected_api segment \"${selectedApi}\": ${resource}`,\n );\n }\n if (!ACTION_RESOURCE_SEGMENT_PATTERN.test(actionKey)) {\n throw new Error(\n `action resource has invalid action_key segment \"${actionKey}\": ${resource}`,\n );\n }\n return {\n selected_api: selectedApi,\n action_type: actionType.data,\n action_key: actionKey,\n };\n}\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 *\n * Carries the action identity in a single canonical `resource` field of\n * the form `action/{selected_api}/{action_type}/{action_key}`, which is\n * also what the policy engine matches against. Use `parseActionResource`\n * to extract the individual parts when needed for display.\n *\n * Accepts either the canonical `resource` field or the legacy\n * `{selected_api, action_type, action_key}` triple on input — the\n * transform composes a canonical resource from the legacy fields when\n * needed, so downstream code only ever sees a single `resource`. Lets\n * sdkapi keep sending the old shape during the migration window.\n */\n/**\n * Raw input shape for `ActionRunContextSchema`, before the transform that\n * canonicalizes legacy fields into `resource`. Exposed for the OpenAPI\n * schema generator (which can't represent transforms) — runtime callers\n * should keep using `ActionRunContextSchema`.\n */\nexport const ActionRunContextInputSchema = z\n .object({\n request_type: z.literal(\"action_run\"),\n resource: z\n .string()\n .max(1024)\n .optional()\n .openapi({\n description:\n \"Canonical action resource, e.g. action/Slack@1.0.0/write/send_message\",\n }),\n selected_api: z\n .string()\n .max(255)\n .optional()\n .openapi({\n deprecated: true,\n description:\n \"Legacy: app identifier, e.g. Slack@1.0.0. Prefer `resource`.\",\n }),\n action_type: ActionTypeSchema.optional().openapi({\n deprecated: true,\n description: \"Legacy: canonical Zapier action type. Prefer `resource`.\",\n }),\n action_key: z\n .string()\n .max(255)\n .optional()\n .openapi({\n deprecated: true,\n description:\n \"Legacy: action key, e.g. send_message. Prefer `resource`.\",\n }),\n connection_id: z\n .string()\n .max(255)\n .optional()\n .openapi({ description: \"Zapier connection ID used for this request\" }),\n inputs: JsonValueSchema.optional().openapi({\n // `type: 'object'` is a placeholder so zod-to-openapi short-circuits\n // introspection of the recursive JsonValueSchema (z.lazy). The\n // generator script strips this `type` after emit so the produced\n // schema matches the original \"any inputs\" shape.\n type: \"object\",\n description: \"Action input parameters\",\n }),\n reason: z\n .string()\n .max(1024)\n .optional()\n .openapi({ description: \"Optional human-readable reason for the request\" }),\n })\n .openapi(\"ActionRunContext\", {\n description:\n \"Action run context. The canonical shape carries the action identity in a single `resource` field of the form `action/{selected_api}/{action_type}/{action_key}`. The legacy `{selected_api, action_type, action_key}` shape is also accepted on input during the migration window — approvalsapi normalizes it to the canonical form before storage.\",\n });\n\nexport const ActionRunContextSchema = ActionRunContextInputSchema.transform(\n (input, ctx) => {\n const resource =\n input.resource ??\n (input.selected_api && input.action_type && input.action_key\n ? `action/${input.selected_api}/${input.action_type}/${input.action_key}`\n : undefined);\n if (resource === undefined) {\n ctx.addIssue({\n code: \"custom\",\n message:\n \"action_run context requires either `resource` or all of `selected_api`/`action_type`/`action_key`\",\n });\n return z.NEVER;\n }\n try {\n parseActionResource(resource);\n } catch (err) {\n ctx.addIssue({\n code: \"custom\",\n message: err instanceof Error ? err.message : String(err),\n });\n return z.NEVER;\n }\n return {\n request_type: \"action_run\" as const,\n resource,\n ...(input.connection_id !== undefined && {\n connection_id: input.connection_id,\n }),\n ...(input.inputs !== undefined && { inputs: input.inputs }),\n ...(input.reason !== undefined && { reason: input.reason }),\n };\n },\n);\nexport type ActionRunContext = z.infer<typeof ActionRunContextSchema>;\n\n/**\n * Union of all request context types, keyed on `request_type`.\n *\n * Plain `z.union` (not `z.discriminatedUnion`) because\n * `ActionRunContextSchema` carries a `.transform` and discriminated\n * unions can't accept a `ZodEffects` member.\n */\nexport const RequestContextSchema = z\n .union([HttpRequestContextSchema, ActionRunContextSchema])\n .openapi(\"RequestContext\", {\n description: \"Discriminated union over request_type.\",\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 ActionTypeSchema,\n JsonValueSchema,\n parseUrl,\n ACTION_RESOURCE_SEGMENT_PATTERN,\n type HttpRequestContext,\n type ActionRunContext,\n} from \"./types.ts\";\nimport { buildActionResource } from \"./conditions.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 // Validate options up-front so downstream string ops (e.g. method.toUpperCase)\n // see well-typed values. Mirrors the pattern in buildActionRunContext.\n const parsed = BuildHttpRequestContextOptionsSchema.parse(options);\n\n // Normalize URL — SDK CLI strips the protocol\n const rawUrl = parsed.url.includes(\"://\")\n ? parsed.url\n : `https://${parsed.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 (parsed.headers) {\n for (const [key, value] of Object.entries(parsed.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 (parsed.body_json !== undefined) {\n body_json = parsed.body_json;\n } else if (parsed.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(parsed.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: parsed.method.toUpperCase(),\n url,\n headers,\n body: parsed.body ?? null,\n body_json,\n connection_id: parsed.connection_id,\n });\n}\n\nexport const BuildActionRunContextOptionsSchema = z.object({\n selected_api: z.string().regex(ACTION_RESOURCE_SEGMENT_PATTERN, {\n message:\n \"selected_api must contain only [A-Za-z0-9._@+-] (no globs, slashes, or whitespace)\",\n }),\n action_type: ActionTypeSchema,\n action_key: z.string().regex(ACTION_RESOURCE_SEGMENT_PATTERN, {\n message:\n \"action_key must contain only [A-Za-z0-9._@+-] (no globs, slashes, or whitespace)\",\n }),\n connection_id: z.string().optional(),\n inputs: JsonValueSchema.optional(),\n reason: z.string().optional(),\n});\nexport type BuildActionRunContextOptions = z.infer<\n typeof BuildActionRunContextOptionsSchema\n>;\n\n/**\n * Build a canonical ActionRunContext from raw action parts.\n *\n * Callers pass the three identity fields separately for readability;\n * this validates them and collapses them into the canonical `resource`\n * string the schema stores.\n */\nexport function buildActionRunContext(\n options: BuildActionRunContextOptions,\n): ActionRunContext {\n const parsed = BuildActionRunContextOptionsSchema.parse(options);\n return ActionRunContextSchema.parse({\n request_type: \"action_run\",\n resource: buildActionResource({\n selected_api: parsed.selected_api,\n action_type: parsed.action_type,\n action_key: parsed.action_key,\n }),\n connection_id: parsed.connection_id,\n inputs: parsed.inputs,\n reason: parsed.reason,\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 {\n HttpRequestContext,\n ActionRunContext,\n ActionType,\n} 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 } else if (context.body !== null) {\n // Non-JSON body (text/plain, XML, form-encoded): pin the raw body so\n // exact-match policies actually match the originating request.\n conditions.push({\n path: [\"body\"],\n operator: \"equals\",\n value: context.body,\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 (context.inputs !== undefined && context.inputs !== null) {\n conditions.push({\n path: [\"inputs\"],\n operator: \"equals\",\n value: context.inputs,\n });\n }\n\n return conditions;\n}\n\n/**\n * The three identity fields that compose an action resource string.\n */\nexport interface ActionResourceParts {\n selected_api: string;\n action_type: ActionType;\n action_key: string;\n}\n\n/**\n * Build the resource string for an action.\n * Format: action/{selected_api}/{action_type}/{action_key}\n */\nexport function buildActionResource(parts: ActionResourceParts): string {\n return `action/${parts.selected_api}/${parts.action_type}/${parts.action_key}`;\n}\n\n/**\n * Build a broad action resource that matches all actions of the same type\n * for an app (e.g. all reads, all writes). Scopes on `action_type` to\n * avoid silently granting cross-type access.\n *\n * Format: action/{selected_api}/{action_type}/{wildcard}\n */\nexport function buildBroadActionResource(\n parts: Pick<ActionResourceParts, \"selected_api\" | \"action_type\">,\n): string {\n return `action/${parts.selected_api}/${parts.action_type}/*`;\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} 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: [context.resource],\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\";\nimport {\n parseActionResource,\n type ActionType,\n type RequestContext,\n} from \"./types.ts\";\n\n/**\n * Replace the implementation-version suffix of a `selected_api` with a `@*`\n * wildcard so connection-level policies stay valid across version bumps. A\n * runtime request with `selected_api: \"App@2.7.3\"` matches a policy resource\n * scoped to `App@*` while still being distinguishable from a different app\n * (e.g. `App2@1.0.0`).\n *\n * No-op when the input has no `@` — assumed to be already version-less.\n */\nfunction globSelectedApiVersion(selectedApi: string): string {\n const at = selectedApi.indexOf(\"@\");\n return at === -1 ? selectedApi : selectedApi.slice(0, at) + \"@*\";\n}\n\nexport const AccessLevelSchema = z.enum([\"read\", \"read_write\"]);\nexport type AccessLevel = z.infer<typeof AccessLevelSchema>;\n\n/** HTTP methods that count as side-effect-free reads for connection-level policies. */\nexport const READ_HTTP_METHODS = [\"GET\", \"HEAD\", \"OPTIONS\"] as const;\n\n/**\n * Action types that count as side-effect-free reads for connection-level\n * policies. `read_bulk` is the paginated/bulk variant of `read` — same\n * external API semantics, no mutations. Widely used by major apps (Slack,\n * Gmail, Jira, Salesforce, etc.) via the public `bulkReads` schema key.\n * `filter` and `run` are excluded: neither has a runtime executor for\n * external apps, and `filter` actions don't carry a connection_id anyway,\n * so this allowlist has no effect on them.\n */\nexport const READ_ACTION_TYPES = [\n \"read\",\n \"read_bulk\",\n \"search\",\n] as const satisfies readonly ActionType[];\n\nconst READ_HTTP_METHOD_SET: ReadonlySet<string> = new Set(READ_HTTP_METHODS);\nconst READ_ACTION_TYPE_SET: ReadonlySet<ActionType> = new Set(\n READ_ACTION_TYPES,\n);\n\n/**\n * Returns true when the request needs write access (i.e. it is NOT a\n * side-effect-free read). Mirrors the logic encoded in `buildConnectionPolicy`\n * so UI surfaces that gate the read-vs-read_write choice stay consistent\n * with the policies they generate.\n */\nexport function isWriteRequest(context: RequestContext): boolean {\n if (context.request_type === \"http_request\") {\n // Method is uppercase by construction (buildHttpRequestContext canonicalizes\n // it on the way in), so no normalization is needed here.\n return !READ_HTTP_METHOD_SET.has(context.method);\n }\n const { action_type } = parseActionResource(context.resource);\n return !READ_ACTION_TYPE_SET.has(action_type);\n}\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}/{action_type}/*` per allowed type,\n * scoped by connection_id. For read access, the resource list expands to\n * one entry per read action_type so the engine matches via the resource\n * string rather than a separate `path: [\"action_type\"]` condition.\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 apiPattern = globSelectedApiVersion(selectedApi);\n const actionResources =\n accessLevel === \"read\"\n ? READ_ACTION_TYPES.map((t) => `action/${apiPattern}/${t}/*`)\n : [`action/${apiPattern}/*/*`];\n\n const actionStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: actionResources,\n conditions: [connectionCondition],\n };\n\n return {\n version: 2,\n statements: [authStatement, httpStatement, actionStatement],\n };\n}\n"],"mappings":"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","names":["z","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 { extendZodWithOpenApi } from \"@asteasolutions/zod-to-openapi\";\n\nextendZodWithOpenApi(z);\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\n .object({\n scheme: z.string().openapi({ description: 'URL scheme, e.g. \"https\"' }),\n host: z.string().openapi({ description: 'Hostname, e.g. \"api.example.com\"' }),\n port: z\n .number()\n .int()\n .openapi({\n description: \"Port number (defaults to 443 for https, 80 for http)\",\n }),\n path: z.string().openapi({ description: 'URL path, e.g. \"/v1/foo\"' }),\n query: z\n .record(z.string(), z.array(z.string()))\n .openapi({\n description: \"Query parameters as key to string array mapping\",\n }),\n })\n .openapi(\"ParsedUrl\", {\n description: \"Parsed URL components for policy condition matching\",\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\n .object({\n request_type: z\n .literal(\"http_request\")\n .openapi({ description: \"Context type discriminator\" }),\n method: z\n .string()\n .max(10)\n .transform((m) => m.toUpperCase())\n .openapi({ description: \"HTTP method\" }),\n /** Parsed URL components for policy condition matching */\n url: ParsedUrlSchema,\n /** Filtered headers (IGNORED_HEADERS excluded, keys lowercased) */\n headers: z\n .record(z.string(), z.string())\n .openapi({\n description: \"Filtered headers (IGNORED_HEADERS excluded, keys lowercased)\",\n }),\n /** Raw body string */\n body: z\n .string()\n .max(65536)\n .nullable()\n .openapi({ description: \"Raw body string\" }),\n /**\n * Parsed JSON body. Authored as `z.unknown().pipe(z.json())` so\n * zod-to-openapi sees the outer `z.unknown()` and emits a permissive\n * field (no recursive `$ref`, no type), while the inner `z.json()`\n * still rejects non-JSON values (`Date`, `undefined`, functions) at\n * parse time. Same inferred `JsonValue` type either way.\n */\n body_json: z\n .unknown()\n .pipe(z.json())\n .nullable()\n .describe(\"Parsed JSON body (if applicable)\"),\n /** Zapier connection ID used for this request */\n connection_id: z\n .string()\n .max(255)\n .optional()\n .openapi({ description: \"Zapier connection ID used for this request\" }),\n /** Optional human-readable reason for the request */\n reason: z\n .string()\n .max(1024)\n .optional()\n .openapi({ description: \"Optional human-readable reason for the request\" }),\n })\n .openapi(\"HttpRequestContext\");\nexport type HttpRequestContext = z.infer<typeof HttpRequestContextSchema>;\n\n/**\n * Canonical Zapier action types.\n *\n * Mirrors the `action_type` enum in sdkapi's OpenAPI spec\n * (`packages/openapi-spec/openapi.d.ts` `action_type`). Single source of\n * truth for any code that branches on or filters by action_type — keeps\n * `ActionRunContextSchema`, `BuildActionRunContextOptionsSchema`, and the\n * `READ_ACTION_TYPES` allowlist in `connection-policy.ts` aligned.\n */\nexport const ActionTypeSchema = z\n .enum([\n \"filter\",\n \"read\",\n \"read_bulk\",\n \"run\",\n \"search\",\n \"search_and_write\",\n \"search_or_write\",\n \"write\",\n ])\n .openapi(\"action_type\", { description: \"Canonical Zapier action type.\" });\nexport type ActionType = z.infer<typeof ActionTypeSchema>;\n\n/**\n * Allowed character set for the `selected_api` segment of an action\n * resource. Blocks `*`, `/`, `:`, whitespace, and other glob/path\n * metacharacters that would otherwise widen policy scope. Permits at\n * most one `@`, which `globSelectedApiVersion` treats as the\n * version separator.\n */\nexport const ACTION_RESOURCE_SEGMENT_PATTERN =\n /^[A-Za-z0-9._+-]+(?:@[A-Za-z0-9._+-]+)?$/;\n\n/**\n * Allowed character set for the `action_key` segment of an action\n * resource. More permissive than `ACTION_RESOURCE_SEGMENT_PATTERN`\n * because sdkapi emits keys like `ae:358405` and `core:123abc` that\n * carry a namespace prefix separated by `:`. Still blocks `*`, `/`,\n * whitespace, and other glob/path metacharacters.\n */\nexport const ACTION_KEY_SEGMENT_PATTERN =\n /^[A-Za-z0-9._+:-]+(?:@[A-Za-z0-9._+:-]+)?$/;\n\n/**\n * Parse an action resource string of the form\n * `action/{selected_api}/{action_type}/{action_key}` into its parts.\n * Throws if the string doesn't match the canonical 4-segment shape or\n * if its `action_type` segment isn't one of the canonical 8 — every\n * action_run context that has been through `ActionRunContextSchema` is\n * guaranteed to parse cleanly, so a thrown error here means upstream\n * validation was bypassed.\n */\nexport function parseActionResource(resource: string): {\n selected_api: string;\n action_type: ActionType;\n action_key: string;\n} {\n const segments = resource.split(\"/\");\n if (segments.length !== 4 || segments[0] !== \"action\") {\n throw new Error(\n `action resource must be action/{selected_api}/{action_type}/{action_key}: got ${resource}`,\n );\n }\n const [, selectedApi, actionTypeRaw, actionKey] = segments;\n if (!selectedApi || !actionTypeRaw || !actionKey) {\n throw new Error(`action resource has empty segment: ${resource}`);\n }\n const actionType = ActionTypeSchema.safeParse(actionTypeRaw);\n if (!actionType.success) {\n throw new Error(\n `action resource has unknown action_type \"${actionTypeRaw}\": ${resource}`,\n );\n }\n if (!ACTION_RESOURCE_SEGMENT_PATTERN.test(selectedApi)) {\n throw new Error(\n `action resource has invalid selected_api segment \"${selectedApi}\": ${resource}`,\n );\n }\n if (!ACTION_KEY_SEGMENT_PATTERN.test(actionKey)) {\n throw new Error(\n `action resource has invalid action_key segment \"${actionKey}\": ${resource}`,\n );\n }\n return {\n selected_api: selectedApi,\n action_type: actionType.data,\n action_key: actionKey,\n };\n}\n\n/**\n * Raw input shape for `ActionRunContextSchema`, before the transform that\n * canonicalizes legacy fields into `resource`. Exposed for the OpenAPI\n * schema generator (which can't represent transforms) — runtime callers\n * should use `ActionRunContextSchema`, which accepts either the canonical\n * `resource` field or the legacy `{selected_api, action_type, action_key}`\n * triple on input.\n */\nexport const ActionRunContextInputSchema = z\n .object({\n request_type: z\n .literal(\"action_run\")\n .openapi({ description: \"Context type discriminator\" }),\n resource: z\n .string()\n .max(1024)\n .optional()\n .openapi({\n description:\n \"Canonical action resource, e.g. action/Slack@1.0.0/write/send_message\",\n }),\n selected_api: z\n .string()\n .max(255)\n .optional()\n .openapi({\n deprecated: true,\n description:\n \"Legacy: app identifier, e.g. Slack@1.0.0. Prefer `resource`.\",\n }),\n action_type: ActionTypeSchema.optional().openapi({\n deprecated: true,\n description: \"Legacy: canonical Zapier action type. Prefer `resource`.\",\n }),\n action_key: z\n .string()\n .max(255)\n .optional()\n .openapi({\n deprecated: true,\n description:\n \"Legacy: action key, e.g. send_message. Prefer `resource`.\",\n }),\n connection_id: z\n .string()\n .max(255)\n .optional()\n .openapi({ description: \"Zapier connection ID used for this request\" }),\n /** Action input parameters. See body_json above for the pipe rationale. */\n inputs: z\n .unknown()\n .pipe(z.json())\n .optional()\n .describe(\"Action input parameters\"),\n reason: z\n .string()\n .max(1024)\n .optional()\n .openapi({ description: \"Optional human-readable reason for the request\" }),\n })\n .openapi(\"ActionRunContext\", {\n description:\n \"Action run context. The canonical shape carries the action identity in a single `resource` field of the form `action/{selected_api}/{action_type}/{action_key}`. The legacy `{selected_api, action_type, action_key}` shape is also accepted on input during the migration window — approvalsapi normalizes it to the canonical form before storage.\",\n });\n\nexport const ActionRunContextSchema = ActionRunContextInputSchema.transform(\n (input, ctx) => {\n const resource =\n input.resource ??\n (input.selected_api && input.action_type && input.action_key\n ? `action/${input.selected_api}/${input.action_type}/${input.action_key}`\n : undefined);\n if (resource === undefined) {\n ctx.addIssue({\n code: \"custom\",\n message:\n \"action_run context requires either `resource` or all of `selected_api`/`action_type`/`action_key`\",\n });\n return z.NEVER;\n }\n try {\n parseActionResource(resource);\n } catch (err) {\n ctx.addIssue({\n code: \"custom\",\n message: err instanceof Error ? err.message : String(err),\n });\n return z.NEVER;\n }\n return {\n request_type: \"action_run\" as const,\n resource,\n ...(input.connection_id !== undefined && {\n connection_id: input.connection_id,\n }),\n ...(input.inputs !== undefined && { inputs: input.inputs }),\n ...(input.reason !== undefined && { reason: input.reason }),\n };\n },\n);\nexport type ActionRunContext = z.infer<typeof ActionRunContextSchema>;\n\n/**\n * Union of all request context types, keyed on `request_type`.\n *\n * Plain `z.union` (not `z.discriminatedUnion`) because\n * `ActionRunContextSchema` carries a `.transform` and discriminated\n * unions can't accept a `ZodEffects` member. The discriminator metadata\n * below tells OpenAPI consumers how to narrow the union — zod-to-openapi\n * emits this as `anyOf` + discriminator, which openapi-typescript and\n * other codegen targets render as a properly narrowed TS union.\n */\nexport const RequestContextSchema = z\n .union([HttpRequestContextSchema, ActionRunContextSchema])\n .openapi(\"RequestContext\", {\n description: \"Union of request context shapes, keyed on `request_type`.\",\n discriminator: {\n propertyName: \"request_type\",\n mapping: {\n http_request: \"#/components/schemas/HttpRequestContext\",\n action_run: \"#/components/schemas/ActionRunContext\",\n },\n },\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 ActionTypeSchema,\n parseUrl,\n ACTION_RESOURCE_SEGMENT_PATTERN,\n ACTION_KEY_SEGMENT_PATTERN,\n type HttpRequestContext,\n type ActionRunContext,\n} from \"./types.ts\";\nimport { buildActionResource } from \"./conditions.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: z.json().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 // Validate options up-front so downstream string ops (e.g. method.toUpperCase)\n // see well-typed values. Mirrors the pattern in buildActionRunContext.\n const parsed = BuildHttpRequestContextOptionsSchema.parse(options);\n\n // Normalize URL — SDK CLI strips the protocol\n const rawUrl = parsed.url.includes(\"://\")\n ? parsed.url\n : `https://${parsed.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 (parsed.headers) {\n for (const [key, value] of Object.entries(parsed.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 (parsed.body_json !== undefined) {\n body_json = parsed.body_json;\n } else if (parsed.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(parsed.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: parsed.method.toUpperCase(),\n url,\n headers,\n body: parsed.body ?? null,\n body_json,\n connection_id: parsed.connection_id,\n });\n}\n\nexport const BuildActionRunContextOptionsSchema = z.object({\n selected_api: z.string().regex(ACTION_RESOURCE_SEGMENT_PATTERN, {\n message:\n \"selected_api must contain only [A-Za-z0-9._@+-] (no globs, slashes, or whitespace)\",\n }),\n action_type: ActionTypeSchema,\n action_key: z.string().regex(ACTION_KEY_SEGMENT_PATTERN, {\n message:\n \"action_key must contain only [A-Za-z0-9._@:+-] (no globs, slashes, or whitespace)\",\n }),\n connection_id: z.string().optional(),\n inputs: z.json().optional(),\n reason: z.string().optional(),\n});\nexport type BuildActionRunContextOptions = z.infer<\n typeof BuildActionRunContextOptionsSchema\n>;\n\n/**\n * Build a canonical ActionRunContext from raw action parts.\n *\n * Callers pass the three identity fields separately for readability;\n * this validates them and collapses them into the canonical `resource`\n * string the schema stores.\n */\nexport function buildActionRunContext(\n options: BuildActionRunContextOptions,\n): ActionRunContext {\n const parsed = BuildActionRunContextOptionsSchema.parse(options);\n return ActionRunContextSchema.parse({\n request_type: \"action_run\",\n resource: buildActionResource({\n selected_api: parsed.selected_api,\n action_type: parsed.action_type,\n action_key: parsed.action_key,\n }),\n connection_id: parsed.connection_id,\n inputs: parsed.inputs,\n reason: parsed.reason,\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 {\n HttpRequestContext,\n ActionRunContext,\n ActionType,\n} 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 } else if (context.body !== null) {\n // Non-JSON body (text/plain, XML, form-encoded): pin the raw body so\n // exact-match policies actually match the originating request.\n conditions.push({\n path: [\"body\"],\n operator: \"equals\",\n value: context.body,\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 (context.inputs !== undefined && context.inputs !== null) {\n conditions.push({\n path: [\"inputs\"],\n operator: \"equals\",\n value: context.inputs,\n });\n }\n\n return conditions;\n}\n\n/**\n * The three identity fields that compose an action resource string.\n */\nexport interface ActionResourceParts {\n selected_api: string;\n action_type: ActionType;\n action_key: string;\n}\n\n/**\n * Build the resource string for an action.\n * Format: action/{selected_api}/{action_type}/{action_key}\n */\nexport function buildActionResource(parts: ActionResourceParts): string {\n return `action/${parts.selected_api}/${parts.action_type}/${parts.action_key}`;\n}\n\n/**\n * Build a broad action resource that matches all actions of the same type\n * for an app (e.g. all reads, all writes). Scopes on `action_type` to\n * avoid silently granting cross-type access.\n *\n * Format: action/{selected_api}/{action_type}/{wildcard}\n */\nexport function buildBroadActionResource(\n parts: Pick<ActionResourceParts, \"selected_api\" | \"action_type\">,\n): string {\n return `action/${parts.selected_api}/${parts.action_type}/*`;\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} 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: [context.resource],\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\";\nimport {\n parseActionResource,\n type ActionType,\n type RequestContext,\n} from \"./types.ts\";\n\n/**\n * Replace the implementation-version suffix of a `selected_api` with a `@*`\n * wildcard so connection-level policies stay valid across version bumps. A\n * runtime request with `selected_api: \"App@2.7.3\"` matches a policy resource\n * scoped to `App@*` while still being distinguishable from a different app\n * (e.g. `App2@1.0.0`).\n *\n * No-op when the input has no `@` — assumed to be already version-less.\n */\nfunction globSelectedApiVersion(selectedApi: string): string {\n const at = selectedApi.indexOf(\"@\");\n return at === -1 ? selectedApi : selectedApi.slice(0, at) + \"@*\";\n}\n\nexport const AccessLevelSchema = z.enum([\"read\", \"read_write\"]);\nexport type AccessLevel = z.infer<typeof AccessLevelSchema>;\n\n/** HTTP methods that count as side-effect-free reads for connection-level policies. */\nexport const READ_HTTP_METHODS = [\"GET\", \"HEAD\", \"OPTIONS\"] as const;\n\n/**\n * Action types that count as side-effect-free reads for connection-level\n * policies. `read_bulk` is the paginated/bulk variant of `read` — same\n * external API semantics, no mutations. Widely used by major apps (Slack,\n * Gmail, Jira, Salesforce, etc.) via the public `bulkReads` schema key.\n * `filter` and `run` are excluded: neither has a runtime executor for\n * external apps, and `filter` actions don't carry a connection_id anyway,\n * so this allowlist has no effect on them.\n */\nexport const READ_ACTION_TYPES = [\n \"read\",\n \"read_bulk\",\n \"search\",\n] as const satisfies readonly ActionType[];\n\nconst READ_HTTP_METHOD_SET: ReadonlySet<string> = new Set(READ_HTTP_METHODS);\nconst READ_ACTION_TYPE_SET: ReadonlySet<ActionType> = new Set(\n READ_ACTION_TYPES,\n);\n\n/**\n * Returns true when the request needs write access (i.e. it is NOT a\n * side-effect-free read). Mirrors the logic encoded in `buildConnectionPolicy`\n * so UI surfaces that gate the read-vs-read_write choice stay consistent\n * with the policies they generate.\n */\nexport function isWriteRequest(context: RequestContext): boolean {\n if (context.request_type === \"http_request\") {\n // Method is uppercase by construction (buildHttpRequestContext canonicalizes\n // it on the way in), so no normalization is needed here.\n return !READ_HTTP_METHOD_SET.has(context.method);\n }\n const { action_type } = parseActionResource(context.resource);\n return !READ_ACTION_TYPE_SET.has(action_type);\n}\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}/{action_type}/*` per allowed type,\n * scoped by connection_id. For read access, the resource list expands to\n * one entry per read action_type so the engine matches via the resource\n * string rather than a separate `path: [\"action_type\"]` condition.\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 apiPattern = globSelectedApiVersion(selectedApi);\n const actionResources =\n accessLevel === \"read\"\n ? READ_ACTION_TYPES.map((t) => `action/${apiPattern}/${t}/*`)\n : [`action/${apiPattern}/*/*`];\n\n const actionStatement: Statement = {\n effect: \"allow\",\n permissions: [\"can_execute\"],\n resources: actionResources,\n conditions: [connectionCondition],\n };\n\n return {\n version: 2,\n statements: [authStatement, httpStatement, actionStatement],\n };\n}\n"],"mappings":"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","names":["z","z","z","z"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zapier/policy-context",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Shared request context types, builders, and policy condition generators for sdkapi and approvalsapi",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@asteasolutions/zod-to-openapi": "^8.5.0",
|
|
31
|
-
"@zapier/policy-schema": "0.
|
|
31
|
+
"@zapier/policy-schema": "0.12.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"zod": "^4.0.0"
|