@zapier/policy-context 0.10.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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.
@@ -38,7 +36,7 @@ declare function buildUrlString(parsed: ParsedUrl): string;
38
36
  */
39
37
  declare const HttpRequestContextSchema: z.ZodObject<{
40
38
  request_type: z.ZodLiteral<"http_request">;
41
- method: z.ZodString;
39
+ method: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
42
40
  url: z.ZodObject<{
43
41
  scheme: z.ZodString;
44
42
  host: z.ZodString;
@@ -48,32 +46,120 @@ 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.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
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>;
55
53
  type HttpRequestContext = z.infer<typeof HttpRequestContextSchema>;
56
54
  /**
57
- * Action run context for approval/policy flows.
58
- * Sent by sdkapi when an action run is denied, stored by approvalsapi,
59
- * and used to build policy conditions.
55
+ * Canonical Zapier action types.
56
+ *
57
+ * Mirrors the `action_type` enum in sdkapi's OpenAPI spec
58
+ * (`packages/openapi-spec/openapi.d.ts` `action_type`). Single source of
59
+ * truth for any code that branches on or filters by action_type — keeps
60
+ * `ActionRunContextSchema`, `BuildActionRunContextOptionsSchema`, and the
61
+ * `READ_ACTION_TYPES` allowlist in `connection-policy.ts` aligned.
62
+ */
63
+ declare const ActionTypeSchema: z.ZodEnum<{
64
+ filter: "filter";
65
+ read: "read";
66
+ read_bulk: "read_bulk";
67
+ run: "run";
68
+ search: "search";
69
+ search_and_write: "search_and_write";
70
+ search_or_write: "search_or_write";
71
+ write: "write";
72
+ }>;
73
+ type ActionType = z.infer<typeof ActionTypeSchema>;
74
+ /**
75
+ * Parse an action resource string of the form
76
+ * `action/{selected_api}/{action_type}/{action_key}` into its parts.
77
+ * Throws if the string doesn't match the canonical 4-segment shape or
78
+ * if its `action_type` segment isn't one of the canonical 8 — every
79
+ * action_run context that has been through `ActionRunContextSchema` is
80
+ * guaranteed to parse cleanly, so a thrown error here means upstream
81
+ * validation was bypassed.
82
+ */
83
+ declare function parseActionResource(resource: string): {
84
+ selected_api: string;
85
+ action_type: ActionType;
86
+ action_key: string;
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.
60
95
  */
61
- declare const ActionRunContextSchema: z.ZodObject<{
96
+ declare const ActionRunContextInputSchema: z.ZodObject<{
62
97
  request_type: z.ZodLiteral<"action_run">;
63
- selected_api: z.ZodString;
64
- action_type: z.ZodString;
65
- action_key: z.ZodString;
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>;
66
111
  connection_id: z.ZodOptional<z.ZodString>;
67
- inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
112
+ inputs: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
68
113
  reason: z.ZodOptional<z.ZodString>;
69
114
  }, z.core.$strip>;
115
+ declare const ActionRunContextSchema: z.ZodPipe<z.ZodObject<{
116
+ request_type: z.ZodLiteral<"action_run">;
117
+ resource: z.ZodOptional<z.ZodString>;
118
+ selected_api: z.ZodOptional<z.ZodString>;
119
+ action_type: z.ZodOptional<z.ZodEnum<{
120
+ filter: "filter";
121
+ read: "read";
122
+ read_bulk: "read_bulk";
123
+ run: "run";
124
+ search: "search";
125
+ search_and_write: "search_and_write";
126
+ search_or_write: "search_or_write";
127
+ write: "write";
128
+ }>>;
129
+ action_key: z.ZodOptional<z.ZodString>;
130
+ connection_id: z.ZodOptional<z.ZodString>;
131
+ inputs: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
132
+ reason: z.ZodOptional<z.ZodString>;
133
+ }, z.core.$strip>, z.ZodTransform<{
134
+ reason?: string | undefined;
135
+ inputs?: z.core.util.JSONType | undefined;
136
+ connection_id?: string | undefined;
137
+ request_type: "action_run";
138
+ resource: string;
139
+ }, {
140
+ request_type: "action_run";
141
+ resource?: string | undefined;
142
+ selected_api?: string | undefined;
143
+ action_type?: "filter" | "read" | "read_bulk" | "run" | "search" | "search_and_write" | "search_or_write" | "write" | undefined;
144
+ action_key?: string | undefined;
145
+ connection_id?: string | undefined;
146
+ inputs?: z.core.util.JSONType | undefined;
147
+ reason?: string | undefined;
148
+ }>>;
70
149
  type ActionRunContext = z.infer<typeof ActionRunContextSchema>;
71
150
  /**
72
- * Discriminated union of all request context types.
151
+ * Union of all request context types, keyed on `request_type`.
152
+ *
153
+ * Plain `z.union` (not `z.discriminatedUnion`) because
154
+ * `ActionRunContextSchema` carries a `.transform` and discriminated
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.
73
159
  */
74
- declare const RequestContextSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
160
+ declare const RequestContextSchema: z.ZodUnion<readonly [z.ZodObject<{
75
161
  request_type: z.ZodLiteral<"http_request">;
76
- method: z.ZodString;
162
+ method: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
77
163
  url: z.ZodObject<{
78
164
  scheme: z.ZodString;
79
165
  host: z.ZodString;
@@ -83,18 +169,43 @@ declare const RequestContextSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
83
169
  }, z.core.$strip>;
84
170
  headers: z.ZodRecord<z.ZodString, z.ZodString>;
85
171
  body: z.ZodNullable<z.ZodString>;
86
- body_json: z.ZodNullable<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
172
+ body_json: z.ZodNullable<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
87
173
  connection_id: z.ZodOptional<z.ZodString>;
88
174
  reason: z.ZodOptional<z.ZodString>;
89
- }, z.core.$strip>, z.ZodObject<{
175
+ }, z.core.$strip>, z.ZodPipe<z.ZodObject<{
90
176
  request_type: z.ZodLiteral<"action_run">;
91
- selected_api: z.ZodString;
92
- action_type: z.ZodString;
93
- action_key: z.ZodString;
177
+ resource: z.ZodOptional<z.ZodString>;
178
+ selected_api: z.ZodOptional<z.ZodString>;
179
+ action_type: z.ZodOptional<z.ZodEnum<{
180
+ filter: "filter";
181
+ read: "read";
182
+ read_bulk: "read_bulk";
183
+ run: "run";
184
+ search: "search";
185
+ search_and_write: "search_and_write";
186
+ search_or_write: "search_or_write";
187
+ write: "write";
188
+ }>>;
189
+ action_key: z.ZodOptional<z.ZodString>;
94
190
  connection_id: z.ZodOptional<z.ZodString>;
95
- inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
191
+ inputs: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodJSONSchema>>;
96
192
  reason: z.ZodOptional<z.ZodString>;
97
- }, z.core.$strip>], "request_type">;
193
+ }, z.core.$strip>, z.ZodTransform<{
194
+ reason?: string | undefined;
195
+ inputs?: z.core.util.JSONType | undefined;
196
+ connection_id?: string | undefined;
197
+ request_type: "action_run";
198
+ resource: string;
199
+ }, {
200
+ request_type: "action_run";
201
+ resource?: string | undefined;
202
+ selected_api?: string | undefined;
203
+ action_type?: "filter" | "read" | "read_bulk" | "run" | "search" | "search_and_write" | "search_or_write" | "write" | undefined;
204
+ action_key?: string | undefined;
205
+ connection_id?: string | undefined;
206
+ inputs?: z.core.util.JSONType | undefined;
207
+ reason?: string | undefined;
208
+ }>>]>;
98
209
  type RequestContext = z.infer<typeof RequestContextSchema>;
99
210
 
100
211
  /**
@@ -111,7 +222,7 @@ declare const BuildHttpRequestContextOptionsSchema: z.ZodObject<{
111
222
  url: z.ZodString;
112
223
  headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodUndefined]>>>;
113
224
  body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
114
- body_json: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
225
+ body_json: z.ZodOptional<z.ZodJSONSchema>;
115
226
  connection_id: z.ZodOptional<z.ZodString>;
116
227
  }, z.core.$strip>;
117
228
  type BuildHttpRequestContextOptions = z.infer<typeof BuildHttpRequestContextOptionsSchema>;
@@ -133,14 +244,28 @@ type BuildHttpRequestContextOptions = z.infer<typeof BuildHttpRequestContextOpti
133
244
  declare function buildHttpRequestContext(options: BuildHttpRequestContextOptions): HttpRequestContext;
134
245
  declare const BuildActionRunContextOptionsSchema: z.ZodObject<{
135
246
  selected_api: z.ZodString;
136
- action_type: z.ZodString;
247
+ action_type: z.ZodEnum<{
248
+ filter: "filter";
249
+ read: "read";
250
+ read_bulk: "read_bulk";
251
+ run: "run";
252
+ search: "search";
253
+ search_and_write: "search_and_write";
254
+ search_or_write: "search_or_write";
255
+ write: "write";
256
+ }>;
137
257
  action_key: z.ZodString;
138
258
  connection_id: z.ZodOptional<z.ZodString>;
139
- inputs: z.ZodOptional<z.ZodType<_zapier_policy_schema.JsonValue, unknown, z.core.$ZodTypeInternals<_zapier_policy_schema.JsonValue, unknown>>>;
259
+ inputs: z.ZodOptional<z.ZodJSONSchema>;
260
+ reason: z.ZodOptional<z.ZodString>;
140
261
  }, z.core.$strip>;
141
262
  type BuildActionRunContextOptions = z.infer<typeof BuildActionRunContextOptionsSchema>;
142
263
  /**
143
264
  * Build a canonical ActionRunContext from raw action parts.
265
+ *
266
+ * Callers pass the three identity fields separately for readability;
267
+ * this validates them and collapses them into the canonical `resource`
268
+ * string the schema stores.
144
269
  */
145
270
  declare function buildActionRunContext(options: BuildActionRunContextOptions): ActionRunContext;
146
271
 
@@ -167,16 +292,27 @@ declare function buildDomainHttpConditions(context: HttpRequestContext): Conditi
167
292
  * @returns Condition[] for an action permission statement
168
293
  */
169
294
  declare function buildExactActionConditions(context: ActionRunContext): Condition[];
295
+ /**
296
+ * The three identity fields that compose an action resource string.
297
+ */
298
+ interface ActionResourceParts {
299
+ selected_api: string;
300
+ action_type: ActionType;
301
+ action_key: string;
302
+ }
170
303
  /**
171
304
  * Build the resource string for an action.
172
305
  * Format: action/{selected_api}/{action_type}/{action_key}
173
306
  */
174
- declare function buildActionResource(context: ActionRunContext): string;
307
+ declare function buildActionResource(parts: ActionResourceParts): string;
175
308
  /**
176
- * Build a broad action resource that matches all actions for an app.
177
- * Format: action/{selected_api}/{wildcard}/{wildcard}
309
+ * Build a broad action resource that matches all actions of the same type
310
+ * for an app (e.g. all reads, all writes). Scopes on `action_type` to
311
+ * avoid silently granting cross-type access.
312
+ *
313
+ * Format: action/{selected_api}/{action_type}/{wildcard}
178
314
  */
179
- declare function buildBroadActionResource(context: ActionRunContext): string;
315
+ declare function buildBroadActionResource(parts: Pick<ActionResourceParts, "selected_api" | "action_type">): string;
180
316
 
181
317
  /**
182
318
  * Build an exact-match policy from any supported request context.
@@ -191,13 +327,35 @@ declare const AccessLevelSchema: z.ZodEnum<{
191
327
  read_write: "read_write";
192
328
  }>;
193
329
  type AccessLevel = z.infer<typeof AccessLevelSchema>;
330
+ /** HTTP methods that count as side-effect-free reads for connection-level policies. */
331
+ declare const READ_HTTP_METHODS: readonly ["GET", "HEAD", "OPTIONS"];
332
+ /**
333
+ * Action types that count as side-effect-free reads for connection-level
334
+ * policies. `read_bulk` is the paginated/bulk variant of `read` — same
335
+ * external API semantics, no mutations. Widely used by major apps (Slack,
336
+ * Gmail, Jira, Salesforce, etc.) via the public `bulkReads` schema key.
337
+ * `filter` and `run` are excluded: neither has a runtime executor for
338
+ * external apps, and `filter` actions don't carry a connection_id anyway,
339
+ * so this allowlist has no effect on them.
340
+ */
341
+ declare const READ_ACTION_TYPES: readonly ["read", "read_bulk", "search"];
342
+ /**
343
+ * Returns true when the request needs write access (i.e. it is NOT a
344
+ * side-effect-free read). Mirrors the logic encoded in `buildConnectionPolicy`
345
+ * so UI surfaces that gate the read-vs-read_write choice stay consistent
346
+ * with the policies they generate.
347
+ */
348
+ declare function isWriteRequest(context: RequestContext): boolean;
194
349
  /**
195
350
  * Build a connection-level policy that covers both HTTP and action access.
196
351
  *
197
352
  * Always produces three statements:
198
353
  * 1. `can_use` for the authentication
199
354
  * 2. `can_execute` on `http` scoped by connection_id (+ method filter for read)
200
- * 3. `can_execute` on `action/{selectedApi}/**` scoped by connection_id (+ action_type filter for read)
355
+ * 3. `can_execute` on `action/{selectedApi}/{action_type}/*` per allowed type,
356
+ * scoped by connection_id. For read access, the resource list expands to
357
+ * one entry per read action_type so the engine matches via the resource
358
+ * string rather than a separate `path: ["action_type"]` condition.
201
359
  */
202
360
  declare function buildConnectionPolicy(options: {
203
361
  connectionId: string;
@@ -205,4 +363,4 @@ declare function buildConnectionPolicy(options: {
205
363
  accessLevel: AccessLevel;
206
364
  }): Policy;
207
365
 
208
- export { type AccessLevel, AccessLevelSchema, type ActionRunContext, ActionRunContextSchema, type BuildActionRunContextOptions, BuildActionRunContextOptionsSchema, type BuildHttpRequestContextOptions, BuildHttpRequestContextOptionsSchema, DEFAULT_PORTS, type HttpRequestContext, HttpRequestContextSchema, IGNORED_HEADERS, type ParsedUrl, ParsedUrlSchema, type RequestContext, RequestContextSchema, buildActionResource, buildActionRunContext, buildBroadActionResource, buildConnectionPolicy, buildDomainHttpConditions, buildExactActionConditions, buildExactHttpConditions, buildHttpRequestContext, buildUrlString, parseUrl, toExactPolicy };
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 };