@zapier/policy-context 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,12 +1,8 @@
1
- import { z } from 'zod';
2
1
  import * as _zapier_policy_schema from '@zapier/policy-schema';
3
- import { JsonValue, Condition, Policy } from '@zapier/policy-schema';
2
+ import { Condition, Policy } from '@zapier/policy-schema';
3
+ export { JsonValueSchema } from '@zapier/policy-schema';
4
+ import { z } from 'zod';
4
5
 
5
- /**
6
- * Zod schema for arbitrary JSON values. Used across context schemas for
7
- * unstructured fields like `body_json` and `inputs`.
8
- */
9
- declare const JsonValueSchema: z.ZodCustom<JsonValue, JsonValue>;
10
6
  /**
11
7
  * Parsed URL components for policy evaluation.
12
8
  * Matches the ParsedUrl shape from @zapier/policy-schema so that
@@ -42,7 +38,7 @@ declare function buildUrlString(parsed: ParsedUrl): string;
42
38
  */
43
39
  declare const HttpRequestContextSchema: z.ZodObject<{
44
40
  request_type: z.ZodLiteral<"http_request">;
45
- method: z.ZodString;
41
+ method: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
46
42
  url: z.ZodObject<{
47
43
  scheme: z.ZodString;
48
44
  host: z.ZodString;
@@ -52,32 +48,90 @@ declare const HttpRequestContextSchema: z.ZodObject<{
52
48
  }, z.core.$strip>;
53
49
  headers: z.ZodRecord<z.ZodString, z.ZodString>;
54
50
  body: z.ZodNullable<z.ZodString>;
55
- body_json: z.ZodNullable<z.ZodCustom<JsonValue, JsonValue>>;
51
+ body_json: z.ZodNullable<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
56
52
  connection_id: z.ZodOptional<z.ZodString>;
57
53
  reason: z.ZodOptional<z.ZodString>;
58
54
  }, z.core.$strip>;
59
55
  type HttpRequestContext = z.infer<typeof HttpRequestContextSchema>;
60
56
  /**
61
- * Action run context for approval/policy flows.
62
- * Sent by sdkapi when an action run is denied, stored by approvalsapi,
63
- * and used to build policy conditions.
57
+ * Canonical Zapier action types.
58
+ *
59
+ * Mirrors the `action_type` enum in sdkapi's OpenAPI spec
60
+ * (`packages/openapi-spec/openapi.d.ts` `action_type`). Single source of
61
+ * truth for any code that branches on or filters by action_type — keeps
62
+ * `ActionRunContextSchema`, `BuildActionRunContextOptionsSchema`, and the
63
+ * `READ_ACTION_TYPES` allowlist in `connection-policy.ts` aligned.
64
64
  */
65
- declare const ActionRunContextSchema: z.ZodObject<{
65
+ declare const ActionTypeSchema: z.ZodEnum<{
66
+ filter: "filter";
67
+ read: "read";
68
+ read_bulk: "read_bulk";
69
+ run: "run";
70
+ search: "search";
71
+ search_and_write: "search_and_write";
72
+ search_or_write: "search_or_write";
73
+ write: "write";
74
+ }>;
75
+ type ActionType = z.infer<typeof ActionTypeSchema>;
76
+ /**
77
+ * Parse an action resource string of the form
78
+ * `action/{selected_api}/{action_type}/{action_key}` into its parts.
79
+ * Throws if the string doesn't match the canonical 4-segment shape or
80
+ * if its `action_type` segment isn't one of the canonical 8 — every
81
+ * action_run context that has been through `ActionRunContextSchema` is
82
+ * guaranteed to parse cleanly, so a thrown error here means upstream
83
+ * validation was bypassed.
84
+ */
85
+ declare function parseActionResource(resource: string): {
86
+ selected_api: string;
87
+ action_type: ActionType;
88
+ action_key: string;
89
+ };
90
+ declare const ActionRunContextSchema: z.ZodPipe<z.ZodObject<{
66
91
  request_type: z.ZodLiteral<"action_run">;
67
- selected_api: z.ZodString;
68
- action_type: z.ZodString;
69
- action_key: z.ZodString;
92
+ resource: z.ZodOptional<z.ZodString>;
93
+ selected_api: z.ZodOptional<z.ZodString>;
94
+ action_type: z.ZodOptional<z.ZodEnum<{
95
+ filter: "filter";
96
+ read: "read";
97
+ read_bulk: "read_bulk";
98
+ run: "run";
99
+ search: "search";
100
+ search_and_write: "search_and_write";
101
+ search_or_write: "search_or_write";
102
+ write: "write";
103
+ }>>;
104
+ action_key: z.ZodOptional<z.ZodString>;
70
105
  connection_id: z.ZodOptional<z.ZodString>;
71
- inputs: z.ZodOptional<z.ZodCustom<JsonValue, JsonValue>>;
106
+ inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
72
107
  reason: z.ZodOptional<z.ZodString>;
73
- }, z.core.$strip>;
108
+ }, z.core.$strip>, z.ZodTransform<{
109
+ reason?: string | undefined;
110
+ inputs?: _zapier_policy_schema.JsonValue | undefined;
111
+ connection_id?: string | undefined;
112
+ request_type: "action_run";
113
+ resource: string;
114
+ }, {
115
+ request_type: "action_run";
116
+ resource?: string | undefined;
117
+ selected_api?: string | undefined;
118
+ action_type?: "filter" | "read" | "read_bulk" | "run" | "search" | "search_and_write" | "search_or_write" | "write" | undefined;
119
+ action_key?: string | undefined;
120
+ connection_id?: string | undefined;
121
+ inputs?: _zapier_policy_schema.JsonValue | undefined;
122
+ reason?: string | undefined;
123
+ }>>;
74
124
  type ActionRunContext = z.infer<typeof ActionRunContextSchema>;
75
125
  /**
76
- * Discriminated union of all request context types.
126
+ * Union of all request context types, keyed on `request_type`.
127
+ *
128
+ * Plain `z.union` (not `z.discriminatedUnion`) because
129
+ * `ActionRunContextSchema` carries a `.transform` and discriminated
130
+ * unions can't accept a `ZodEffects` member.
77
131
  */
78
- declare const RequestContextSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
132
+ declare const RequestContextSchema: z.ZodUnion<readonly [z.ZodObject<{
79
133
  request_type: z.ZodLiteral<"http_request">;
80
- method: z.ZodString;
134
+ method: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
81
135
  url: z.ZodObject<{
82
136
  scheme: z.ZodString;
83
137
  host: z.ZodString;
@@ -87,18 +141,43 @@ declare const RequestContextSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
87
141
  }, z.core.$strip>;
88
142
  headers: z.ZodRecord<z.ZodString, z.ZodString>;
89
143
  body: z.ZodNullable<z.ZodString>;
90
- body_json: z.ZodNullable<z.ZodCustom<JsonValue, JsonValue>>;
144
+ body_json: z.ZodNullable<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
91
145
  connection_id: z.ZodOptional<z.ZodString>;
92
146
  reason: z.ZodOptional<z.ZodString>;
93
- }, z.core.$strip>, z.ZodObject<{
147
+ }, z.core.$strip>, z.ZodPipe<z.ZodObject<{
94
148
  request_type: z.ZodLiteral<"action_run">;
95
- selected_api: z.ZodString;
96
- action_type: z.ZodString;
97
- action_key: z.ZodString;
149
+ resource: z.ZodOptional<z.ZodString>;
150
+ selected_api: z.ZodOptional<z.ZodString>;
151
+ action_type: z.ZodOptional<z.ZodEnum<{
152
+ filter: "filter";
153
+ read: "read";
154
+ read_bulk: "read_bulk";
155
+ run: "run";
156
+ search: "search";
157
+ search_and_write: "search_and_write";
158
+ search_or_write: "search_or_write";
159
+ write: "write";
160
+ }>>;
161
+ action_key: z.ZodOptional<z.ZodString>;
98
162
  connection_id: z.ZodOptional<z.ZodString>;
99
- inputs: z.ZodOptional<z.ZodCustom<JsonValue, JsonValue>>;
163
+ inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
100
164
  reason: z.ZodOptional<z.ZodString>;
101
- }, z.core.$strip>], "request_type">;
165
+ }, z.core.$strip>, z.ZodTransform<{
166
+ reason?: string | undefined;
167
+ inputs?: _zapier_policy_schema.JsonValue | undefined;
168
+ connection_id?: string | undefined;
169
+ request_type: "action_run";
170
+ resource: string;
171
+ }, {
172
+ request_type: "action_run";
173
+ resource?: string | undefined;
174
+ selected_api?: string | undefined;
175
+ action_type?: "filter" | "read" | "read_bulk" | "run" | "search" | "search_and_write" | "search_or_write" | "write" | undefined;
176
+ action_key?: string | undefined;
177
+ connection_id?: string | undefined;
178
+ inputs?: _zapier_policy_schema.JsonValue | undefined;
179
+ reason?: string | undefined;
180
+ }>>]>;
102
181
  type RequestContext = z.infer<typeof RequestContextSchema>;
103
182
 
104
183
  /**
@@ -115,7 +194,7 @@ declare const BuildHttpRequestContextOptionsSchema: z.ZodObject<{
115
194
  url: z.ZodString;
116
195
  headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodUndefined]>>>;
117
196
  body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
118
- body_json: z.ZodOptional<z.ZodCustom<_zapier_policy_schema.JsonValue, _zapier_policy_schema.JsonValue>>;
197
+ body_json: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
119
198
  connection_id: z.ZodOptional<z.ZodString>;
120
199
  }, z.core.$strip>;
121
200
  type BuildHttpRequestContextOptions = z.infer<typeof BuildHttpRequestContextOptionsSchema>;
@@ -137,14 +216,28 @@ type BuildHttpRequestContextOptions = z.infer<typeof BuildHttpRequestContextOpti
137
216
  declare function buildHttpRequestContext(options: BuildHttpRequestContextOptions): HttpRequestContext;
138
217
  declare const BuildActionRunContextOptionsSchema: z.ZodObject<{
139
218
  selected_api: z.ZodString;
140
- action_type: z.ZodString;
219
+ action_type: z.ZodEnum<{
220
+ filter: "filter";
221
+ read: "read";
222
+ read_bulk: "read_bulk";
223
+ run: "run";
224
+ search: "search";
225
+ search_and_write: "search_and_write";
226
+ search_or_write: "search_or_write";
227
+ write: "write";
228
+ }>;
141
229
  action_key: z.ZodString;
142
230
  connection_id: z.ZodOptional<z.ZodString>;
143
- inputs: z.ZodOptional<z.ZodCustom<_zapier_policy_schema.JsonValue, _zapier_policy_schema.JsonValue>>;
231
+ inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
232
+ reason: z.ZodOptional<z.ZodString>;
144
233
  }, z.core.$strip>;
145
234
  type BuildActionRunContextOptions = z.infer<typeof BuildActionRunContextOptionsSchema>;
146
235
  /**
147
236
  * Build a canonical ActionRunContext from raw action parts.
237
+ *
238
+ * Callers pass the three identity fields separately for readability;
239
+ * this validates them and collapses them into the canonical `resource`
240
+ * string the schema stores.
148
241
  */
149
242
  declare function buildActionRunContext(options: BuildActionRunContextOptions): ActionRunContext;
150
243
 
@@ -171,16 +264,27 @@ declare function buildDomainHttpConditions(context: HttpRequestContext): Conditi
171
264
  * @returns Condition[] for an action permission statement
172
265
  */
173
266
  declare function buildExactActionConditions(context: ActionRunContext): Condition[];
267
+ /**
268
+ * The three identity fields that compose an action resource string.
269
+ */
270
+ interface ActionResourceParts {
271
+ selected_api: string;
272
+ action_type: ActionType;
273
+ action_key: string;
274
+ }
174
275
  /**
175
276
  * Build the resource string for an action.
176
277
  * Format: action/{selected_api}/{action_type}/{action_key}
177
278
  */
178
- declare function buildActionResource(context: ActionRunContext): string;
279
+ declare function buildActionResource(parts: ActionResourceParts): string;
179
280
  /**
180
- * Build a broad action resource that matches all actions for an app.
181
- * Format: action/{selected_api}/{wildcard}/{wildcard}
281
+ * Build a broad action resource that matches all actions of the same type
282
+ * for an app (e.g. all reads, all writes). Scopes on `action_type` to
283
+ * avoid silently granting cross-type access.
284
+ *
285
+ * Format: action/{selected_api}/{action_type}/{wildcard}
182
286
  */
183
- declare function buildBroadActionResource(context: ActionRunContext): string;
287
+ declare function buildBroadActionResource(parts: Pick<ActionResourceParts, "selected_api" | "action_type">): string;
184
288
 
185
289
  /**
186
290
  * Build an exact-match policy from any supported request context.
@@ -195,13 +299,35 @@ declare const AccessLevelSchema: z.ZodEnum<{
195
299
  read_write: "read_write";
196
300
  }>;
197
301
  type AccessLevel = z.infer<typeof AccessLevelSchema>;
302
+ /** HTTP methods that count as side-effect-free reads for connection-level policies. */
303
+ declare const READ_HTTP_METHODS: readonly ["GET", "HEAD", "OPTIONS"];
304
+ /**
305
+ * Action types that count as side-effect-free reads for connection-level
306
+ * policies. `read_bulk` is the paginated/bulk variant of `read` — same
307
+ * external API semantics, no mutations. Widely used by major apps (Slack,
308
+ * Gmail, Jira, Salesforce, etc.) via the public `bulkReads` schema key.
309
+ * `filter` and `run` are excluded: neither has a runtime executor for
310
+ * external apps, and `filter` actions don't carry a connection_id anyway,
311
+ * so this allowlist has no effect on them.
312
+ */
313
+ declare const READ_ACTION_TYPES: readonly ["read", "read_bulk", "search"];
314
+ /**
315
+ * Returns true when the request needs write access (i.e. it is NOT a
316
+ * side-effect-free read). Mirrors the logic encoded in `buildConnectionPolicy`
317
+ * so UI surfaces that gate the read-vs-read_write choice stay consistent
318
+ * with the policies they generate.
319
+ */
320
+ declare function isWriteRequest(context: RequestContext): boolean;
198
321
  /**
199
322
  * Build a connection-level policy that covers both HTTP and action access.
200
323
  *
201
324
  * Always produces three statements:
202
325
  * 1. `can_use` for the authentication
203
326
  * 2. `can_execute` on `http` scoped by connection_id (+ method filter for read)
204
- * 3. `can_execute` on `action/{selectedApi}/**` scoped by connection_id (+ action_type filter for read)
327
+ * 3. `can_execute` on `action/{selectedApi}/{action_type}/*` per allowed type,
328
+ * scoped by connection_id. For read access, the resource list expands to
329
+ * one entry per read action_type so the engine matches via the resource
330
+ * string rather than a separate `path: ["action_type"]` condition.
205
331
  */
206
332
  declare function buildConnectionPolicy(options: {
207
333
  connectionId: string;
@@ -209,4 +335,4 @@ declare function buildConnectionPolicy(options: {
209
335
  accessLevel: AccessLevel;
210
336
  }): Policy;
211
337
 
212
- export { type AccessLevel, AccessLevelSchema, type ActionRunContext, ActionRunContextSchema, type BuildActionRunContextOptions, BuildActionRunContextOptionsSchema, type BuildHttpRequestContextOptions, BuildHttpRequestContextOptionsSchema, DEFAULT_PORTS, type HttpRequestContext, HttpRequestContextSchema, IGNORED_HEADERS, JsonValueSchema, type ParsedUrl, ParsedUrlSchema, type RequestContext, RequestContextSchema, buildActionResource, buildActionRunContext, buildBroadActionResource, buildConnectionPolicy, buildDomainHttpConditions, buildExactActionConditions, buildExactHttpConditions, buildHttpRequestContext, buildUrlString, parseUrl, toExactPolicy };
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 };