@zapier/policy-schema 0.17.0 → 0.19.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,10 @@ 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, 3, RUBBERDUCK_POLICY_VERSION];
5
+ var VALID_VERSIONS = [1, 2, 3, 4, RUBBERDUCK_POLICY_VERSION];
6
6
  var ID_BASED_VERSIONS = /* @__PURE__ */ new Set([
7
7
  3,
8
+ 4,
8
9
  RUBBERDUCK_POLICY_VERSION
9
10
  ]);
10
11
  var VALID_EFFECTS = ["allow", "ask", "deny"];
@@ -25,33 +26,40 @@ var VALID_OPERATOR_LIST = [
25
26
  "values_in"
26
27
  ];
27
28
  var ScalarSchema = z.union([z.string(), z.number(), z.boolean()]);
28
- var PathSchema = z.array(z.union([z.string(), z.number()])).min(1);
29
- var RelativePathSchema = z.array(z.union([z.string(), z.number()]));
29
+ var PathSegmentSchema = z.union([z.string(), z.number().int()]);
30
+ var PathSchema = z.array(PathSegmentSchema).min(1);
31
+ var RelativePathSchema = z.array(PathSegmentSchema);
32
+ var NegateField = { negate: z.boolean().optional() };
30
33
  var ConditionValueSchema = z.json();
31
34
  var EqualsConditionSchema = z.object({
32
35
  path: PathSchema,
33
36
  operator: z.literal("equals"),
34
- value: ConditionValueSchema
37
+ value: ConditionValueSchema,
38
+ ...NegateField
35
39
  }).strict();
36
40
  var InConditionSchema = z.object({
37
41
  path: PathSchema,
38
42
  operator: z.literal("in"),
39
- value: z.array(ScalarSchema).min(1)
43
+ value: z.array(ScalarSchema).min(1),
44
+ ...NegateField
40
45
  }).strict();
41
46
  var MatchesConditionSchema = z.object({
42
47
  path: PathSchema,
43
48
  operator: z.literal("matches"),
44
- value: z.string()
49
+ value: z.string(),
50
+ ...NegateField
45
51
  }).strict();
46
52
  var MatchesHostConditionSchema = z.object({
47
53
  path: PathSchema,
48
54
  operator: z.literal("matches_host"),
49
- value: z.string()
55
+ value: z.string(),
56
+ ...NegateField
50
57
  }).strict();
51
58
  var MatchesPathConditionSchema = z.object({
52
59
  path: PathSchema,
53
60
  operator: z.literal("matches_path"),
54
- value: z.string()
61
+ value: z.string(),
62
+ ...NegateField
55
63
  }).strict();
56
64
  var RangeValueSchema = z.object({
57
65
  min: z.number().finite().optional(),
@@ -62,26 +70,31 @@ var RangeValueSchema = z.object({
62
70
  var RangeConditionSchema = z.object({
63
71
  path: PathSchema,
64
72
  operator: z.literal("range"),
65
- value: RangeValueSchema
73
+ value: RangeValueSchema,
74
+ ...NegateField
66
75
  }).strict();
67
76
  var MatchesUrlConditionSchema = z.object({
68
77
  path: PathSchema,
69
78
  operator: z.literal("matches_url"),
70
- value: z.string()
79
+ value: z.string(),
80
+ ...NegateField
71
81
  }).strict();
72
82
  var ValuesInConditionSchema = z.object({
73
83
  path: PathSchema,
74
84
  operator: z.literal("values_in"),
75
- value: z.array(ScalarSchema).min(1)
85
+ value: z.array(ScalarSchema).min(1),
86
+ ...NegateField
76
87
  }).strict();
77
88
  var ExistsConditionSchema = z.object({
78
89
  path: PathSchema,
79
- operator: z.literal("exists")
90
+ operator: z.literal("exists"),
91
+ ...NegateField
80
92
  }).strict();
81
93
  var KeysInConditionSchema = z.object({
82
94
  path: PathSchema,
83
95
  operator: z.literal("keys_in"),
84
- value: z.array(z.string())
96
+ value: z.array(z.string()),
97
+ ...NegateField
85
98
  }).strict();
86
99
  var SizeValueSchema = z.union([
87
100
  z.number().int().nonnegative(),
@@ -90,7 +103,8 @@ var SizeValueSchema = z.union([
90
103
  var SizeConditionSchema = z.object({
91
104
  path: PathSchema,
92
105
  operator: z.literal("size"),
93
- value: SizeValueSchema
106
+ value: SizeValueSchema,
107
+ ...NegateField
94
108
  }).strict();
95
109
  var RelativeConditionSchema = z.union([
96
110
  EqualsConditionSchema.extend({ path: RelativePathSchema }),
@@ -176,6 +190,7 @@ var V2StatementSchema = z.object({
176
190
  var StatementSchema = V2StatementSchema;
177
191
  var StatementIdSchema = z.string().regex(/^s_\S+$/, { error: "Statement id must match ^s_\\S+$" }).max(512);
178
192
  var PolicyIdSchema = z.string().regex(/^p_\S+$/, { error: "Policy id must match ^p_\\S+$" }).max(512);
193
+ var RuleIdSchema = z.string().regex(/^r_\S+$/, { error: "Rule id must match ^r_\\S+$" }).max(512);
179
194
  var V1PolicySchema = z.object({
180
195
  version: z.literal(1),
181
196
  statements: z.array(V1StatementSchema)
@@ -212,10 +227,25 @@ var V3PolicySchema = z.object({
212
227
  // empty (e.g. `[[]]` denies everything).
213
228
  statements: z.array(z.array(V3StatementSchema)).min(1).max(V3_MAX_TIERS)
214
229
  }).strict();
230
+ var V4_MAX_TIERS = 3;
231
+ var V4RuleSchema = z.object({
232
+ id: RuleIdSchema,
233
+ effect: z.enum(["allow", "ask", "deny"]),
234
+ permissions: z.array(z.string()).min(1),
235
+ resources: z.array(z.string()).min(1),
236
+ conditions: z.array(ConditionSchema).optional()
237
+ }).strict();
238
+ var V4PolicySchema = z.object({
239
+ version: z.literal(4),
240
+ // Ordered tiers, in priority order. 1..V4_MAX_TIERS tiers; a tier may be
241
+ // empty (e.g. `[[]]` denies everything). Renamed from v3's `statements`.
242
+ rules: z.array(z.array(V4RuleSchema)).min(1).max(V4_MAX_TIERS)
243
+ }).strict();
215
244
  var PolicySchema = z.union([
216
245
  V1PolicySchema,
217
246
  V2PolicySchema,
218
247
  V3PolicySchema,
248
+ V4PolicySchema,
219
249
  RcRubberduckPolicySchema
220
250
  ]);
221
251
  var CanonicalHashSchema = z.custom(
@@ -250,6 +280,12 @@ var OverridePolicyIdBaseShape = {
250
280
  policyId: PolicyIdSchema,
251
281
  effect: z.literal("allow")
252
282
  };
283
+ var OverrideRuleIdBaseShape = {
284
+ id: z.string().optional(),
285
+ /** Targets a v4 rule by id (r_ prefix, non-null). */
286
+ ruleId: RuleIdSchema,
287
+ effect: z.literal("allow")
288
+ };
253
289
  var OverrideSchema = z.union([
254
290
  // statementHash × match
255
291
  z.object({ ...OverrideHashBaseShape, match: z.literal("any") }).strict(),
@@ -277,6 +313,15 @@ var OverrideSchema = z.union([
277
313
  z.object({
278
314
  ...OverridePolicyIdBaseShape,
279
315
  conditionals: z.array(ConditionSchema)
316
+ }).strict(),
317
+ // ruleId × match
318
+ z.object({ ...OverrideRuleIdBaseShape, match: z.literal("any") }).strict(),
319
+ // ruleId × contextHash
320
+ z.object({ ...OverrideRuleIdBaseShape, contextHash: CanonicalHashSchema }).strict(),
321
+ // ruleId × conditionals
322
+ z.object({
323
+ ...OverrideRuleIdBaseShape,
324
+ conditionals: z.array(ConditionSchema)
280
325
  }).strict()
281
326
  ]);
282
327
  function getOpenApiSchema() {
@@ -291,7 +336,7 @@ function getOpenApiSchema() {
291
336
  effect: {
292
337
  type: "string",
293
338
  enum: [...VALID_EFFECTS].sort(),
294
- description: "Whether to allow, ask, or deny the specified permissions. The 'ask' effect is valid in version 2, version 3, and rc-rubberduck policies."
339
+ description: "Whether to allow, ask, or deny the specified permissions. The 'ask' effect is valid in version 2, version 3, version 4, and rc-rubberduck policies."
295
340
  },
296
341
  permissions: {
297
342
  type: "array",
@@ -328,6 +373,10 @@ function getOpenApiSchema() {
328
373
  value: {
329
374
  description: "Value to compare against using the operator."
330
375
  },
376
+ negate: {
377
+ type: "boolean",
378
+ description: "When true, the condition passes only if the operator would have failed. Not permitted on the some, all, and none quantifiers."
379
+ },
331
380
  where: {
332
381
  type: "array",
333
382
  minItems: 1,
@@ -353,6 +402,10 @@ function getOpenApiSchema() {
353
402
  },
354
403
  value: {
355
404
  description: "Value to compare against using the operator."
405
+ },
406
+ negate: {
407
+ type: "boolean",
408
+ description: "When true, the relative condition passes only if the operator would have failed."
356
409
  }
357
410
  }
358
411
  }
@@ -362,42 +415,123 @@ function getOpenApiSchema() {
362
415
  }
363
416
  }
364
417
  };
365
- return {
366
- type: "object",
367
- required: ["version", "statements"],
418
+ const ruleItems = {
419
+ ...statementItems,
368
420
  properties: {
369
- version: {
370
- anyOf: [
371
- { type: "integer", enum: [1, 2, 3] },
372
- { type: "string", enum: [RUBBERDUCK_POLICY_VERSION] }
373
- ],
374
- description: "Policy schema version. Stable versions are 1, 2, and 3; supported release candidates are rc-rubberduck."
375
- },
421
+ ...statementItems.properties,
376
422
  id: {
377
423
  type: "string",
378
- description: "Policy id (required for rc-rubberduck policies; not permitted on any other version). Must use the p_ prefix and contain no whitespace."
424
+ description: "Rule identifier. Required for v4 policies; must use the r_ prefix with no whitespace."
379
425
  },
380
- defaultEffect: {
381
- type: "string",
382
- enum: [...DefaultEffectSchema.options],
383
- description: "Effect applied when no statement matches. Required on rc-rubberduck policies (deny equals implicit deny); not permitted on any other version."
426
+ resources: {
427
+ ...statementItems.properties.resources,
428
+ description: "List of resource identifiers the rule applies to."
384
429
  },
385
- statements: {
386
- type: "array",
387
- 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.",
388
- items: {
389
- anyOf: [
390
- statementItems,
391
- {
392
- type: "array",
393
- description: "A v3 tier: statements evaluated together with deny > ask > allow precedence.",
394
- items: statementItems
395
- }
396
- ]
397
- }
430
+ conditions: {
431
+ ...statementItems.properties.conditions,
432
+ description: "Optional conditions that must be met for the rule to apply."
398
433
  }
399
434
  }
400
435
  };
436
+ const versionDescription = "Policy schema version. Stable versions are 1, 2, 3, and 4; supported release candidates are rc-rubberduck.";
437
+ const flatStatements = {
438
+ type: "array",
439
+ description: "Policy statements; each entry is a statement.",
440
+ items: statementItems
441
+ };
442
+ const statementTiers = {
443
+ type: "array",
444
+ description: "v3 tiers in priority order; each entry is a tier (a list of statements) evaluated first-to-last (the first tier with a match decides), so `statements` is a list of lists.",
445
+ items: {
446
+ type: "array",
447
+ description: "A v3 tier: statements evaluated together with deny > ask > allow precedence.",
448
+ items: statementItems
449
+ }
450
+ };
451
+ const ruleTiers = {
452
+ type: "array",
453
+ description: "v4 rules in priority order; each entry is a tier (a list of rules) evaluated first-to-last (the first tier with a match decides), so `rules` is a list of lists.",
454
+ items: {
455
+ type: "array",
456
+ description: "A v4 tier: rules evaluated together with deny > ask > allow precedence.",
457
+ items: ruleItems
458
+ }
459
+ };
460
+ const idProperty = {
461
+ type: "string",
462
+ description: "Policy id (rc-rubberduck only). Must use the p_ prefix and contain no whitespace."
463
+ };
464
+ const defaultEffectProperty = {
465
+ type: "string",
466
+ enum: [...DefaultEffectSchema.options],
467
+ description: "Effect applied when no statement matches (rc-rubberduck only; deny equals implicit deny)."
468
+ };
469
+ return {
470
+ oneOf: [
471
+ {
472
+ type: "object",
473
+ required: ["version", "statements"],
474
+ properties: {
475
+ version: {
476
+ type: "integer",
477
+ const: 1,
478
+ description: versionDescription
479
+ },
480
+ statements: flatStatements
481
+ }
482
+ },
483
+ {
484
+ type: "object",
485
+ required: ["version", "statements"],
486
+ properties: {
487
+ version: {
488
+ type: "integer",
489
+ const: 2,
490
+ description: versionDescription
491
+ },
492
+ statements: flatStatements
493
+ }
494
+ },
495
+ {
496
+ type: "object",
497
+ required: ["version", "statements"],
498
+ properties: {
499
+ version: {
500
+ type: "integer",
501
+ const: 3,
502
+ description: versionDescription
503
+ },
504
+ statements: statementTiers
505
+ }
506
+ },
507
+ {
508
+ type: "object",
509
+ required: ["version", "rules"],
510
+ properties: {
511
+ version: {
512
+ type: "integer",
513
+ const: 4,
514
+ description: versionDescription
515
+ },
516
+ rules: ruleTiers
517
+ }
518
+ },
519
+ {
520
+ type: "object",
521
+ required: ["version", "id", "defaultEffect", "statements"],
522
+ properties: {
523
+ version: {
524
+ type: "string",
525
+ const: RUBBERDUCK_POLICY_VERSION,
526
+ description: versionDescription
527
+ },
528
+ id: idProperty,
529
+ defaultEffect: defaultEffectProperty,
530
+ statements: flatStatements
531
+ }
532
+ }
533
+ ]
534
+ };
401
535
  }
402
536
 
403
- 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 };
537
+ export { ArrayOperatorSchema, CanonicalHashSchema, ConditionSchema, ConditionValueSchema, DefaultEffectSchema, ID_BASED_VERSIONS, OperatorSchema, OtherOperatorSchema, OverrideSchema, PolicyIdSchema, PolicySchema, RUBBERDUCK_POLICY_VERSION, RangeValueSchema, RuleIdSchema, ScalarOperatorSchema, SizeValueSchema, StatementIdSchema, StatementSchema, UrlOperatorSchema, V3_MAX_TIERS, V4_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.17.0",
3
+ "version": "0.19.0",
4
4
  "description": "Zod schemas and TypeScript types for the Zapier policy engine",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",