@zapier/policy-schema 0.15.0 → 0.18.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.mjs CHANGED
@@ -2,9 +2,14 @@ import { z } from 'zod';
2
2
 
3
3
  // src/schema.ts
4
4
  var RUBBERDUCK_POLICY_VERSION = "rc-rubberduck";
5
- var VALID_VERSIONS = [1, 2, RUBBERDUCK_POLICY_VERSION];
5
+ var VALID_VERSIONS = [1, 2, 3, RUBBERDUCK_POLICY_VERSION];
6
+ var ID_BASED_VERSIONS = /* @__PURE__ */ new Set([
7
+ 3,
8
+ RUBBERDUCK_POLICY_VERSION
9
+ ]);
6
10
  var VALID_EFFECTS = ["allow", "ask", "deny"];
7
11
  var VALID_OPERATOR_LIST = [
12
+ "all",
8
13
  "equals",
9
14
  "exists",
10
15
  "in",
@@ -13,37 +18,47 @@ var VALID_OPERATOR_LIST = [
13
18
  "matches_host",
14
19
  "matches_path",
15
20
  "matches_url",
21
+ "none",
16
22
  "range",
17
23
  "size",
24
+ "some",
18
25
  "values_in"
19
26
  ];
20
27
  var ScalarSchema = z.union([z.string(), z.number(), z.boolean()]);
21
- var PathSchema = z.array(z.union([z.string(), z.number()])).min(1);
28
+ var PathSegmentSchema = z.union([z.string(), z.number().int()]);
29
+ var PathSchema = z.array(PathSegmentSchema).min(1);
30
+ var RelativePathSchema = z.array(PathSegmentSchema);
31
+ var NegateField = { negate: z.boolean().optional() };
22
32
  var ConditionValueSchema = z.json();
23
33
  var EqualsConditionSchema = z.object({
24
34
  path: PathSchema,
25
35
  operator: z.literal("equals"),
26
- value: ConditionValueSchema
36
+ value: ConditionValueSchema,
37
+ ...NegateField
27
38
  }).strict();
28
39
  var InConditionSchema = z.object({
29
40
  path: PathSchema,
30
41
  operator: z.literal("in"),
31
- value: z.array(ScalarSchema).min(1)
42
+ value: z.array(ScalarSchema).min(1),
43
+ ...NegateField
32
44
  }).strict();
33
45
  var MatchesConditionSchema = z.object({
34
46
  path: PathSchema,
35
47
  operator: z.literal("matches"),
36
- value: z.string()
48
+ value: z.string(),
49
+ ...NegateField
37
50
  }).strict();
38
51
  var MatchesHostConditionSchema = z.object({
39
52
  path: PathSchema,
40
53
  operator: z.literal("matches_host"),
41
- value: z.string()
54
+ value: z.string(),
55
+ ...NegateField
42
56
  }).strict();
43
57
  var MatchesPathConditionSchema = z.object({
44
58
  path: PathSchema,
45
59
  operator: z.literal("matches_path"),
46
- value: z.string()
60
+ value: z.string(),
61
+ ...NegateField
47
62
  }).strict();
48
63
  var RangeValueSchema = z.object({
49
64
  min: z.number().finite().optional(),
@@ -54,26 +69,31 @@ var RangeValueSchema = z.object({
54
69
  var RangeConditionSchema = z.object({
55
70
  path: PathSchema,
56
71
  operator: z.literal("range"),
57
- value: RangeValueSchema
72
+ value: RangeValueSchema,
73
+ ...NegateField
58
74
  }).strict();
59
75
  var MatchesUrlConditionSchema = z.object({
60
76
  path: PathSchema,
61
77
  operator: z.literal("matches_url"),
62
- value: z.string()
78
+ value: z.string(),
79
+ ...NegateField
63
80
  }).strict();
64
81
  var ValuesInConditionSchema = z.object({
65
82
  path: PathSchema,
66
83
  operator: z.literal("values_in"),
67
- value: z.array(ScalarSchema).min(1)
84
+ value: z.array(ScalarSchema).min(1),
85
+ ...NegateField
68
86
  }).strict();
69
87
  var ExistsConditionSchema = z.object({
70
88
  path: PathSchema,
71
- operator: z.literal("exists")
89
+ operator: z.literal("exists"),
90
+ ...NegateField
72
91
  }).strict();
73
92
  var KeysInConditionSchema = z.object({
74
93
  path: PathSchema,
75
94
  operator: z.literal("keys_in"),
76
- value: z.array(z.string())
95
+ value: z.array(z.string()),
96
+ ...NegateField
77
97
  }).strict();
78
98
  var SizeValueSchema = z.union([
79
99
  z.number().int().nonnegative(),
@@ -82,7 +102,26 @@ var SizeValueSchema = z.union([
82
102
  var SizeConditionSchema = z.object({
83
103
  path: PathSchema,
84
104
  operator: z.literal("size"),
85
- value: SizeValueSchema
105
+ value: SizeValueSchema,
106
+ ...NegateField
107
+ }).strict();
108
+ var RelativeConditionSchema = z.union([
109
+ EqualsConditionSchema.extend({ path: RelativePathSchema }),
110
+ InConditionSchema.extend({ path: RelativePathSchema }),
111
+ MatchesConditionSchema.extend({ path: RelativePathSchema }),
112
+ MatchesHostConditionSchema.extend({ path: RelativePathSchema }),
113
+ MatchesPathConditionSchema.extend({ path: RelativePathSchema }),
114
+ RangeConditionSchema.extend({ path: RelativePathSchema }),
115
+ MatchesUrlConditionSchema.extend({ path: RelativePathSchema }),
116
+ ValuesInConditionSchema.extend({ path: RelativePathSchema }),
117
+ ExistsConditionSchema.extend({ path: RelativePathSchema }),
118
+ KeysInConditionSchema.extend({ path: RelativePathSchema }),
119
+ SizeConditionSchema.extend({ path: RelativePathSchema })
120
+ ]);
121
+ var QuantifierConditionSchema = z.object({
122
+ path: PathSchema,
123
+ operator: z.enum(["some", "all", "none"]),
124
+ where: z.array(RelativeConditionSchema).min(1)
86
125
  }).strict();
87
126
  var ConditionSchema = z.union([
88
127
  // Scalar operators
@@ -99,7 +138,8 @@ var ConditionSchema = z.union([
99
138
  // Other operators
100
139
  ExistsConditionSchema,
101
140
  KeysInConditionSchema,
102
- SizeConditionSchema
141
+ SizeConditionSchema,
142
+ QuantifierConditionSchema
103
143
  ]);
104
144
  var ScalarOperatorSchema = z.enum([
105
145
  "equals",
@@ -109,7 +149,7 @@ var ScalarOperatorSchema = z.enum([
109
149
  "matches_path",
110
150
  "range"
111
151
  ]);
112
- var ArrayOperatorSchema = z.enum(["values_in"]);
152
+ var ArrayOperatorSchema = z.enum(["values_in", "some", "all", "none"]);
113
153
  var UrlOperatorSchema = z.enum(["matches_url"]);
114
154
  var OtherOperatorSchema = z.enum(["exists", "keys_in", "size"]);
115
155
  var OperatorSchema = z.enum([
@@ -124,6 +164,9 @@ var OperatorSchema = z.enum([
124
164
  "matches_url",
125
165
  // Array
126
166
  "values_in",
167
+ "some",
168
+ "all",
169
+ "none",
127
170
  // Other
128
171
  "exists",
129
172
  "keys_in",
@@ -168,9 +211,24 @@ var RcRubberduckPolicySchema = z.object({
168
211
  defaultEffect: DefaultEffectSchema,
169
212
  statements: z.array(RcRubberduckStatementSchema)
170
213
  }).strict();
214
+ var V3_MAX_TIERS = 3;
215
+ var V3StatementSchema = z.object({
216
+ id: StatementIdSchema,
217
+ effect: z.enum(["allow", "ask", "deny"]),
218
+ permissions: z.array(z.string()).min(1),
219
+ resources: z.array(z.string()).min(1),
220
+ conditions: z.array(ConditionSchema).optional()
221
+ }).strict();
222
+ var V3PolicySchema = z.object({
223
+ version: z.literal(3),
224
+ // Ordered tiers, in priority order. 1..V3_MAX_TIERS tiers; a tier may be
225
+ // empty (e.g. `[[]]` denies everything).
226
+ statements: z.array(z.array(V3StatementSchema)).min(1).max(V3_MAX_TIERS)
227
+ }).strict();
171
228
  var PolicySchema = z.union([
172
229
  V1PolicySchema,
173
230
  V2PolicySchema,
231
+ V3PolicySchema,
174
232
  RcRubberduckPolicySchema
175
233
  ]);
176
234
  var CanonicalHashSchema = z.custom(
@@ -235,76 +293,87 @@ var OverrideSchema = z.union([
235
293
  }).strict()
236
294
  ]);
237
295
  function getOpenApiSchema() {
238
- return {
296
+ const statementItems = {
239
297
  type: "object",
240
- required: ["version", "statements"],
298
+ required: ["effect", "permissions", "resources"],
241
299
  properties: {
242
- version: {
243
- anyOf: [
244
- { type: "integer", enum: [1, 2] },
245
- { type: "string", enum: [RUBBERDUCK_POLICY_VERSION] }
246
- ],
247
- description: "Policy schema version. Stable versions are 1 and 2; supported release candidates are rc-rubberduck."
248
- },
249
300
  id: {
250
301
  type: "string",
251
- description: "Policy id (required for rc-rubberduck policies). Must use the p_ prefix and contain no whitespace."
302
+ description: "Statement identifier. Required for v3 and rc-rubberduck policies; must use the s_ prefix with no whitespace. Optional on v1/v2 for debugging and provenance."
252
303
  },
253
- defaultEffect: {
304
+ effect: {
254
305
  type: "string",
255
- enum: [...DefaultEffectSchema.options],
256
- description: "Effect applied when no statement matches. Required on rc-rubberduck policies; deny equals implicit deny."
306
+ enum: [...VALID_EFFECTS].sort(),
307
+ description: "Whether to allow, ask, or deny the specified permissions. The 'ask' effect is valid in version 2, version 3, and rc-rubberduck policies."
257
308
  },
258
- statements: {
309
+ permissions: {
310
+ type: "array",
311
+ minItems: 1,
312
+ items: { type: "string" },
313
+ description: "List of permission identifiers."
314
+ },
315
+ resources: {
259
316
  type: "array",
260
- description: "List of policy statements defining permissions.",
317
+ minItems: 1,
318
+ items: { type: "string" },
319
+ description: "List of resource identifiers the statement applies to."
320
+ },
321
+ conditions: {
322
+ type: "array",
323
+ description: "Optional conditions that must be met for the statement to apply.",
261
324
  items: {
262
325
  type: "object",
263
- required: ["effect", "permissions", "resources"],
326
+ required: ["path", "operator"],
264
327
  properties: {
265
- id: {
266
- type: "string",
267
- description: "Statement identifier. Required for rc-rubberduck policies; must use the s_ prefix with no whitespace. Optional on v1/v2 for debugging and provenance."
328
+ path: {
329
+ type: "array",
330
+ minItems: 1,
331
+ description: "Path to the value to evaluate in the request context.",
332
+ items: {
333
+ anyOf: [{ type: "string" }, { type: "integer" }]
334
+ }
268
335
  },
269
- effect: {
336
+ operator: {
270
337
  type: "string",
271
- enum: [...VALID_EFFECTS].sort(),
272
- description: "Whether to allow, ask, or deny the specified permissions. The 'ask' effect is valid in version 2 and rc-rubberduck policies."
338
+ enum: [...VALID_OPERATOR_LIST],
339
+ description: "Comparison operator used to evaluate the condition."
273
340
  },
274
- permissions: {
275
- type: "array",
276
- minItems: 1,
277
- items: { type: "string" },
278
- description: "List of permission identifiers."
341
+ value: {
342
+ description: "Value to compare against using the operator."
279
343
  },
280
- resources: {
281
- type: "array",
282
- minItems: 1,
283
- items: { type: "string" },
284
- description: "List of resource identifiers the statement applies to."
344
+ negate: {
345
+ type: "boolean",
346
+ description: "When true, the condition passes only if the operator would have failed. Not permitted on the some, all, and none quantifiers."
285
347
  },
286
- conditions: {
348
+ where: {
287
349
  type: "array",
288
- description: "Optional conditions that must be met for the statement to apply.",
350
+ minItems: 1,
351
+ description: "Conditions evaluated relative to each collection element for some, all, and none.",
289
352
  items: {
290
353
  type: "object",
291
354
  required: ["path", "operator"],
292
355
  properties: {
293
356
  path: {
294
357
  type: "array",
295
- minItems: 1,
296
- description: "Path to the value to evaluate in the request context.",
358
+ minItems: 0,
359
+ description: "Path relative to the collection element; an empty path selects the element itself.",
297
360
  items: {
298
361
  anyOf: [{ type: "string" }, { type: "integer" }]
299
362
  }
300
363
  },
301
364
  operator: {
302
365
  type: "string",
303
- enum: [...VALID_OPERATOR_LIST],
304
- description: "Comparison operator used to evaluate the condition."
366
+ enum: [...VALID_OPERATOR_LIST].filter(
367
+ (operator) => operator !== "some" && operator !== "all" && operator !== "none"
368
+ ),
369
+ description: "Non-quantifier operator evaluated against the collection element."
305
370
  },
306
371
  value: {
307
372
  description: "Value to compare against using the operator."
373
+ },
374
+ negate: {
375
+ type: "boolean",
376
+ description: "When true, the relative condition passes only if the operator would have failed."
308
377
  }
309
378
  }
310
379
  }
@@ -314,6 +383,42 @@ function getOpenApiSchema() {
314
383
  }
315
384
  }
316
385
  };
386
+ return {
387
+ type: "object",
388
+ required: ["version", "statements"],
389
+ properties: {
390
+ version: {
391
+ anyOf: [
392
+ { type: "integer", enum: [1, 2, 3] },
393
+ { type: "string", enum: [RUBBERDUCK_POLICY_VERSION] }
394
+ ],
395
+ description: "Policy schema version. Stable versions are 1, 2, and 3; supported release candidates are rc-rubberduck."
396
+ },
397
+ id: {
398
+ type: "string",
399
+ description: "Policy id (required for rc-rubberduck policies; not permitted on any other version). Must use the p_ prefix and contain no whitespace."
400
+ },
401
+ defaultEffect: {
402
+ type: "string",
403
+ enum: [...DefaultEffectSchema.options],
404
+ description: "Effect applied when no statement matches. Required on rc-rubberduck policies (deny equals implicit deny); not permitted on any other version."
405
+ },
406
+ statements: {
407
+ type: "array",
408
+ description: "Policy statements. For v1/v2/rc-rubberduck each entry is a statement. For v3 each entry is a tier (a list of statements); tiers are in priority order and evaluated first-to-last (the first tier with a match decides), so `statements` is a list of lists.",
409
+ items: {
410
+ anyOf: [
411
+ statementItems,
412
+ {
413
+ type: "array",
414
+ description: "A v3 tier: statements evaluated together with deny > ask > allow precedence.",
415
+ items: statementItems
416
+ }
417
+ ]
418
+ }
419
+ }
420
+ }
421
+ };
317
422
  }
318
423
 
319
- export { ArrayOperatorSchema, CanonicalHashSchema, ConditionSchema, ConditionValueSchema, DefaultEffectSchema, OperatorSchema, OtherOperatorSchema, OverrideSchema, PolicyIdSchema, PolicySchema, RUBBERDUCK_POLICY_VERSION, RangeValueSchema, ScalarOperatorSchema, SizeValueSchema, StatementIdSchema, StatementSchema, UrlOperatorSchema, VALID_EFFECTS, VALID_OPERATOR_LIST, VALID_VERSIONS, getOpenApiSchema };
424
+ export { ArrayOperatorSchema, CanonicalHashSchema, ConditionSchema, ConditionValueSchema, DefaultEffectSchema, ID_BASED_VERSIONS, OperatorSchema, OtherOperatorSchema, OverrideSchema, PolicyIdSchema, PolicySchema, RUBBERDUCK_POLICY_VERSION, RangeValueSchema, ScalarOperatorSchema, SizeValueSchema, StatementIdSchema, StatementSchema, UrlOperatorSchema, V3_MAX_TIERS, VALID_EFFECTS, VALID_OPERATOR_LIST, VALID_VERSIONS, getOpenApiSchema };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zapier/policy-schema",
3
- "version": "0.15.0",
3
+ "version": "0.18.0",
4
4
  "description": "Zod schemas and TypeScript types for the Zapier policy engine",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",