@zapier/policy-schema 0.13.0 → 0.15.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.cjs CHANGED
@@ -3,7 +3,8 @@
3
3
  var zod = require('zod');
4
4
 
5
5
  // src/schema.ts
6
- var VALID_VERSIONS = [1, 2];
6
+ var RUBBERDUCK_POLICY_VERSION = "rc-rubberduck";
7
+ var VALID_VERSIONS = [1, 2, RUBBERDUCK_POLICY_VERSION];
7
8
  var VALID_EFFECTS = ["allow", "ask", "deny"];
8
9
  var VALID_OPERATOR_LIST = [
9
10
  "equals",
@@ -20,10 +21,11 @@ var VALID_OPERATOR_LIST = [
20
21
  ];
21
22
  var ScalarSchema = zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean()]);
22
23
  var PathSchema = zod.z.array(zod.z.union([zod.z.string(), zod.z.number()])).min(1);
24
+ var ConditionValueSchema = zod.z.json();
23
25
  var EqualsConditionSchema = zod.z.object({
24
26
  path: PathSchema,
25
27
  operator: zod.z.literal("equals"),
26
- value: zod.z.json()
28
+ value: ConditionValueSchema
27
29
  }).strict();
28
30
  var InConditionSchema = zod.z.object({
29
31
  path: PathSchema,
@@ -129,7 +131,6 @@ var OperatorSchema = zod.z.enum([
129
131
  "keys_in",
130
132
  "size"
131
133
  ]);
132
- var ConditionValueSchema = zod.z.json();
133
134
  var V1StatementSchema = zod.z.object({
134
135
  id: zod.z.string().optional(),
135
136
  effect: zod.z.enum(["allow", "deny"]),
@@ -145,32 +146,93 @@ var V2StatementSchema = zod.z.object({
145
146
  conditions: zod.z.array(ConditionSchema).optional()
146
147
  }).strict();
147
148
  var StatementSchema = V2StatementSchema;
149
+ var StatementIdSchema = zod.z.string().regex(/^s_\S+$/, { error: "Statement id must match ^s_\\S+$" }).max(512);
150
+ var PolicyIdSchema = zod.z.string().regex(/^p_\S+$/, { error: "Policy id must match ^p_\\S+$" }).max(512);
148
151
  var V1PolicySchema = zod.z.object({
149
152
  version: zod.z.literal(1),
150
153
  statements: zod.z.array(V1StatementSchema)
151
154
  }).strict();
155
+ var DefaultEffectSchema = zod.z.enum(["deny", "ask"]);
152
156
  var V2PolicySchema = zod.z.object({
153
157
  version: zod.z.literal(2),
154
158
  statements: zod.z.array(V2StatementSchema)
155
159
  }).strict();
156
- var PolicySchema = zod.z.union([V1PolicySchema, V2PolicySchema]);
160
+ var RcRubberduckStatementSchema = zod.z.object({
161
+ id: StatementIdSchema,
162
+ effect: zod.z.enum(["allow", "ask", "deny"]),
163
+ permissions: zod.z.array(zod.z.string()).min(1),
164
+ resources: zod.z.array(zod.z.string()).min(1),
165
+ conditions: zod.z.array(ConditionSchema).optional()
166
+ }).strict();
167
+ var RcRubberduckPolicySchema = zod.z.object({
168
+ version: zod.z.literal(RUBBERDUCK_POLICY_VERSION),
169
+ id: PolicyIdSchema,
170
+ defaultEffect: DefaultEffectSchema,
171
+ statements: zod.z.array(RcRubberduckStatementSchema)
172
+ }).strict();
173
+ var PolicySchema = zod.z.union([
174
+ V1PolicySchema,
175
+ V2PolicySchema,
176
+ RcRubberduckPolicySchema
177
+ ]);
157
178
  var CanonicalHashSchema = zod.z.custom(
158
179
  (value) => typeof value === "string" && /^[0-9a-f]{64}$/.test(value),
159
180
  { error: "Expected a 64-character lowercase hex SHA-256 digest" }
160
181
  );
161
- var OverrideBaseShape = {
182
+ var OverrideHashBaseShape = {
162
183
  id: zod.z.string().optional(),
184
+ /**
185
+ * The canonical hash of the targeted statement.
186
+ * Used for v1/v2 policies. Must be a valid SHA-256 hex digest (non-null).
187
+ */
163
188
  statementHash: CanonicalHashSchema,
164
189
  effect: zod.z.literal("allow")
165
190
  };
191
+ var OverrideIdBaseShape = {
192
+ id: zod.z.string().optional(),
193
+ /**
194
+ * The statement id of the targeted statement. Used for rc-rubberduck policies.
195
+ * Must be a valid statement id (non-null). To target the policy's default
196
+ * effect, use policyId instead.
197
+ */
198
+ statementId: StatementIdSchema,
199
+ effect: zod.z.literal("allow")
200
+ };
201
+ var OverridePolicyIdBaseShape = {
202
+ id: zod.z.string().optional(),
203
+ /**
204
+ * Targets the policy's default effect. Only applies when this policyId
205
+ * matches the evaluated policy's id. Used for rc-rubberduck policies.
206
+ */
207
+ policyId: PolicyIdSchema,
208
+ effect: zod.z.literal("allow")
209
+ };
166
210
  var OverrideSchema = zod.z.union([
167
- zod.z.object({ ...OverrideBaseShape, match: zod.z.literal("any") }).strict(),
168
- zod.z.object({ ...OverrideBaseShape, contextHash: CanonicalHashSchema }).strict(),
169
- // Empty conditionals is intentional (the "blank check"): the override
170
- // applies whenever the targeted ask statement fires, with no extra
171
- // conditions. Do not add .min(1) here.
211
+ // statementHash × match
212
+ zod.z.object({ ...OverrideHashBaseShape, match: zod.z.literal("any") }).strict(),
213
+ // statementHash × contextHash
214
+ zod.z.object({ ...OverrideHashBaseShape, contextHash: CanonicalHashSchema }).strict(),
215
+ // statementHash × conditionals
216
+ zod.z.object({
217
+ ...OverrideHashBaseShape,
218
+ conditionals: zod.z.array(ConditionSchema)
219
+ }).strict(),
220
+ // statementId × match
221
+ zod.z.object({ ...OverrideIdBaseShape, match: zod.z.literal("any") }).strict(),
222
+ // statementId × contextHash
223
+ zod.z.object({ ...OverrideIdBaseShape, contextHash: CanonicalHashSchema }).strict(),
224
+ // statementId × conditionals
225
+ zod.z.object({
226
+ ...OverrideIdBaseShape,
227
+ conditionals: zod.z.array(ConditionSchema)
228
+ }).strict(),
229
+ // policyId × match
230
+ zod.z.object({ ...OverridePolicyIdBaseShape, match: zod.z.literal("any") }).strict(),
231
+ // policyId × contextHash
232
+ zod.z.object({ ...OverridePolicyIdBaseShape, contextHash: CanonicalHashSchema }).strict(),
233
+ // policyId × conditionals
172
234
  zod.z.object({
173
- ...OverrideBaseShape,
235
+ ...OverridePolicyIdBaseShape,
174
236
  conditionals: zod.z.array(ConditionSchema)
175
237
  }).strict()
176
238
  ]);
@@ -180,9 +242,20 @@ function getOpenApiSchema() {
180
242
  required: ["version", "statements"],
181
243
  properties: {
182
244
  version: {
183
- type: "integer",
184
- enum: [...VALID_VERSIONS],
185
- description: `Policy schema version. Must be one of ${JSON.stringify([...VALID_VERSIONS])}.`
245
+ anyOf: [
246
+ { type: "integer", enum: [1, 2] },
247
+ { type: "string", enum: [RUBBERDUCK_POLICY_VERSION] }
248
+ ],
249
+ description: "Policy schema version. Stable versions are 1 and 2; supported release candidates are rc-rubberduck."
250
+ },
251
+ id: {
252
+ type: "string",
253
+ description: "Policy id (required for rc-rubberduck policies). Must use the p_ prefix and contain no whitespace."
254
+ },
255
+ defaultEffect: {
256
+ type: "string",
257
+ enum: [...DefaultEffectSchema.options],
258
+ description: "Effect applied when no statement matches. Required on rc-rubberduck policies; deny equals implicit deny."
186
259
  },
187
260
  statements: {
188
261
  type: "array",
@@ -193,12 +266,12 @@ function getOpenApiSchema() {
193
266
  properties: {
194
267
  id: {
195
268
  type: "string",
196
- description: "Optional identifier for debugging and provenance. Included in canonical hash."
269
+ description: "Statement identifier. Required for rc-rubberduck policies; must use the s_ prefix with no whitespace. Optional on v1/v2 for debugging and provenance."
197
270
  },
198
271
  effect: {
199
272
  type: "string",
200
273
  enum: [...VALID_EFFECTS].sort(),
201
- description: "Whether to allow, ask, or deny the specified permissions. The 'ask' effect is only valid in version 2 policies."
274
+ description: "Whether to allow, ask, or deny the specified permissions. The 'ask' effect is valid in version 2 and rc-rubberduck policies."
202
275
  },
203
276
  permissions: {
204
277
  type: "array",
@@ -249,13 +322,17 @@ exports.ArrayOperatorSchema = ArrayOperatorSchema;
249
322
  exports.CanonicalHashSchema = CanonicalHashSchema;
250
323
  exports.ConditionSchema = ConditionSchema;
251
324
  exports.ConditionValueSchema = ConditionValueSchema;
325
+ exports.DefaultEffectSchema = DefaultEffectSchema;
252
326
  exports.OperatorSchema = OperatorSchema;
253
327
  exports.OtherOperatorSchema = OtherOperatorSchema;
254
328
  exports.OverrideSchema = OverrideSchema;
329
+ exports.PolicyIdSchema = PolicyIdSchema;
255
330
  exports.PolicySchema = PolicySchema;
331
+ exports.RUBBERDUCK_POLICY_VERSION = RUBBERDUCK_POLICY_VERSION;
256
332
  exports.RangeValueSchema = RangeValueSchema;
257
333
  exports.ScalarOperatorSchema = ScalarOperatorSchema;
258
334
  exports.SizeValueSchema = SizeValueSchema;
335
+ exports.StatementIdSchema = StatementIdSchema;
259
336
  exports.StatementSchema = StatementSchema;
260
337
  exports.UrlOperatorSchema = UrlOperatorSchema;
261
338
  exports.VALID_EFFECTS = VALID_EFFECTS;
package/dist/index.d.cts CHANGED
@@ -1,13 +1,16 @@
1
1
  import { z } from 'zod';
2
2
 
3
- /** Current policy document version. */
4
- declare const VALID_VERSIONS: readonly [1, 2];
3
+ /** Release-candidate policy document version for the current experimental shape. */
4
+ declare const RUBBERDUCK_POLICY_VERSION: "rc-rubberduck";
5
+ /** Supported policy document versions. */
6
+ declare const VALID_VERSIONS: readonly [1, 2, "rc-rubberduck"];
5
7
  /** Valid policy effects. */
6
8
  declare const VALID_EFFECTS: readonly ["allow", "ask", "deny"];
7
9
  /** Derived from VALID_EFFECTS — the constant is the single source of truth. */
8
10
  type Effect = (typeof VALID_EFFECTS)[number];
9
11
  /** Valid condition operators. */
10
12
  declare const VALID_OPERATOR_LIST: readonly ["equals", "exists", "in", "keys_in", "matches", "matches_host", "matches_path", "matches_url", "range", "size", "values_in"];
13
+ declare const ConditionValueSchema: z.ZodJSONSchema;
11
14
  declare const RangeValueSchema: z.ZodObject<{
12
15
  min: z.ZodOptional<z.ZodNumber>;
13
16
  max: z.ZodOptional<z.ZodNumber>;
@@ -114,7 +117,6 @@ declare const OperatorSchema: z.ZodEnum<{
114
117
  }>;
115
118
  /** Derived from OperatorSchema — the schema is the single source of truth. */
116
119
  type Operator = z.infer<typeof OperatorSchema>;
117
- declare const ConditionValueSchema: z.ZodJSONSchema;
118
120
  /** Statement schema accepting the union of all effects (use PolicySchema for version-aware validation). */
119
121
  declare const StatementSchema: z.ZodObject<{
120
122
  id: z.ZodOptional<z.ZodString>;
@@ -178,6 +180,21 @@ declare const StatementSchema: z.ZodObject<{
178
180
  }, z.core.$strict>;
179
181
  /** Derived from StatementSchema — the schema is the single source of truth. */
180
182
  type Statement = z.infer<typeof StatementSchema>;
183
+ /** Statement identifier for rc-rubberduck policies. Must match ^s_\S+$ and be ≤512 chars. */
184
+ declare const StatementIdSchema: z.ZodString;
185
+ /** Derived from StatementIdSchema — the schema is the single source of truth. */
186
+ type StatementId = z.infer<typeof StatementIdSchema>;
187
+ /** Policy identifier for rc-rubberduck policies. Must match ^p_\S+$ and be ≤512 chars. */
188
+ declare const PolicyIdSchema: z.ZodString;
189
+ /** Derived from PolicyIdSchema — the schema is the single source of truth. */
190
+ type PolicyId = z.infer<typeof PolicyIdSchema>;
191
+ /** Effect applied when no statement matches (rc-rubberduck, required). deny == implicit deny. */
192
+ declare const DefaultEffectSchema: z.ZodEnum<{
193
+ ask: "ask";
194
+ deny: "deny";
195
+ }>;
196
+ /** Derived from DefaultEffectSchema — the schema is the single source of truth. */
197
+ type DefaultEffect = z.infer<typeof DefaultEffectSchema>;
181
198
  declare const PolicySchema: z.ZodUnion<readonly [z.ZodObject<{
182
199
  version: z.ZodLiteral<1>;
183
200
  statements: z.ZodArray<z.ZodObject<{
@@ -301,15 +318,93 @@ declare const PolicySchema: z.ZodUnion<readonly [z.ZodObject<{
301
318
  }, z.core.$strict>]>;
302
319
  }, z.core.$strict>]>>>;
303
320
  }, z.core.$strict>>;
321
+ }, z.core.$strict>, z.ZodObject<{
322
+ version: z.ZodLiteral<"rc-rubberduck">;
323
+ id: z.ZodString;
324
+ defaultEffect: z.ZodEnum<{
325
+ ask: "ask";
326
+ deny: "deny";
327
+ }>;
328
+ statements: z.ZodArray<z.ZodObject<{
329
+ id: z.ZodString;
330
+ effect: z.ZodEnum<{
331
+ allow: "allow";
332
+ ask: "ask";
333
+ deny: "deny";
334
+ }>;
335
+ permissions: z.ZodArray<z.ZodString>;
336
+ resources: z.ZodArray<z.ZodString>;
337
+ conditions: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
338
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
339
+ operator: z.ZodLiteral<"equals">;
340
+ value: z.ZodJSONSchema;
341
+ }, z.core.$strict>, z.ZodObject<{
342
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
343
+ operator: z.ZodLiteral<"in">;
344
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
345
+ }, z.core.$strict>, z.ZodObject<{
346
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
347
+ operator: z.ZodLiteral<"matches">;
348
+ value: z.ZodString;
349
+ }, z.core.$strict>, z.ZodObject<{
350
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
351
+ operator: z.ZodLiteral<"matches_host">;
352
+ value: z.ZodString;
353
+ }, z.core.$strict>, z.ZodObject<{
354
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
355
+ operator: z.ZodLiteral<"matches_path">;
356
+ value: z.ZodString;
357
+ }, z.core.$strict>, z.ZodObject<{
358
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
359
+ operator: z.ZodLiteral<"range">;
360
+ value: z.ZodObject<{
361
+ min: z.ZodOptional<z.ZodNumber>;
362
+ max: z.ZodOptional<z.ZodNumber>;
363
+ }, z.core.$strict>;
364
+ }, z.core.$strict>, z.ZodObject<{
365
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
366
+ operator: z.ZodLiteral<"matches_url">;
367
+ value: z.ZodString;
368
+ }, z.core.$strict>, z.ZodObject<{
369
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
370
+ operator: z.ZodLiteral<"values_in">;
371
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
372
+ }, z.core.$strict>, z.ZodObject<{
373
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
374
+ operator: z.ZodLiteral<"exists">;
375
+ }, z.core.$strict>, z.ZodObject<{
376
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
377
+ operator: z.ZodLiteral<"keys_in">;
378
+ value: z.ZodArray<z.ZodString>;
379
+ }, z.core.$strict>, z.ZodObject<{
380
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
381
+ operator: z.ZodLiteral<"size">;
382
+ value: z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
383
+ min: z.ZodOptional<z.ZodNumber>;
384
+ max: z.ZodOptional<z.ZodNumber>;
385
+ }, z.core.$strict>]>;
386
+ }, z.core.$strict>]>>>;
387
+ }, z.core.$strict>>;
304
388
  }, z.core.$strict>]>;
305
389
  /** Derived from PolicySchema — the schema is the single source of truth. */
306
390
  type Policy = z.infer<typeof PolicySchema>;
307
391
  /** SHA-256 hex digest of an RFC 8785 (JCS) canonicalized JSON value. */
308
392
  declare const CanonicalHashSchema: z.ZodCustom<CanonicalHash, CanonicalHash>;
309
393
  /**
310
- * Runtime schema for the Override type. `.strict()` keeps the variants
311
- * mutually exclusive (an object carrying two variant fields fails all
312
- * branches).
394
+ * Runtime schema for the Override type. Each variant has exactly one target
395
+ * field (statementHash for v1/v2, statementId or policyId for rc-rubberduck) and exactly
396
+ * one binding mode (match, contextHash, or conditionals). `.strict()` keeps
397
+ * the variants mutually exclusive (an object carrying fields from two variants
398
+ * fails all branches).
399
+ *
400
+ * Targets are all non-null:
401
+ * - statementHash: targets a v1/v2 statement by canonical hash
402
+ * - statementId: targets an rc-rubberduck statement by id
403
+ * - policyId: targets that policy's default effect (rc-rubberduck only)
404
+ *
405
+ * Empty conditionals is intentional (the "blank check"): the override applies
406
+ * whenever the targeted ask statement fires, with no extra conditions. Do not
407
+ * add .min(1) to conditionals.
313
408
  */
314
409
  declare const OverrideSchema: z.ZodUnion<readonly [z.ZodObject<{
315
410
  match: z.ZodLiteral<"any">;
@@ -375,6 +470,134 @@ declare const OverrideSchema: z.ZodUnion<readonly [z.ZodObject<{
375
470
  id: z.ZodOptional<z.ZodString>;
376
471
  statementHash: z.ZodCustom<CanonicalHash, CanonicalHash>;
377
472
  effect: z.ZodLiteral<"allow">;
473
+ }, z.core.$strict>, z.ZodObject<{
474
+ match: z.ZodLiteral<"any">;
475
+ id: z.ZodOptional<z.ZodString>;
476
+ statementId: z.ZodString;
477
+ effect: z.ZodLiteral<"allow">;
478
+ }, z.core.$strict>, z.ZodObject<{
479
+ contextHash: z.ZodCustom<CanonicalHash, CanonicalHash>;
480
+ id: z.ZodOptional<z.ZodString>;
481
+ statementId: z.ZodString;
482
+ effect: z.ZodLiteral<"allow">;
483
+ }, z.core.$strict>, z.ZodObject<{
484
+ conditionals: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
485
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
486
+ operator: z.ZodLiteral<"equals">;
487
+ value: z.ZodJSONSchema;
488
+ }, z.core.$strict>, z.ZodObject<{
489
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
490
+ operator: z.ZodLiteral<"in">;
491
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
492
+ }, z.core.$strict>, z.ZodObject<{
493
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
494
+ operator: z.ZodLiteral<"matches">;
495
+ value: z.ZodString;
496
+ }, z.core.$strict>, z.ZodObject<{
497
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
498
+ operator: z.ZodLiteral<"matches_host">;
499
+ value: z.ZodString;
500
+ }, z.core.$strict>, z.ZodObject<{
501
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
502
+ operator: z.ZodLiteral<"matches_path">;
503
+ value: z.ZodString;
504
+ }, z.core.$strict>, z.ZodObject<{
505
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
506
+ operator: z.ZodLiteral<"range">;
507
+ value: z.ZodObject<{
508
+ min: z.ZodOptional<z.ZodNumber>;
509
+ max: z.ZodOptional<z.ZodNumber>;
510
+ }, z.core.$strict>;
511
+ }, z.core.$strict>, z.ZodObject<{
512
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
513
+ operator: z.ZodLiteral<"matches_url">;
514
+ value: z.ZodString;
515
+ }, z.core.$strict>, z.ZodObject<{
516
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
517
+ operator: z.ZodLiteral<"values_in">;
518
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
519
+ }, z.core.$strict>, z.ZodObject<{
520
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
521
+ operator: z.ZodLiteral<"exists">;
522
+ }, z.core.$strict>, z.ZodObject<{
523
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
524
+ operator: z.ZodLiteral<"keys_in">;
525
+ value: z.ZodArray<z.ZodString>;
526
+ }, z.core.$strict>, z.ZodObject<{
527
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
528
+ operator: z.ZodLiteral<"size">;
529
+ value: z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
530
+ min: z.ZodOptional<z.ZodNumber>;
531
+ max: z.ZodOptional<z.ZodNumber>;
532
+ }, z.core.$strict>]>;
533
+ }, z.core.$strict>]>>;
534
+ id: z.ZodOptional<z.ZodString>;
535
+ statementId: z.ZodString;
536
+ effect: z.ZodLiteral<"allow">;
537
+ }, z.core.$strict>, z.ZodObject<{
538
+ match: z.ZodLiteral<"any">;
539
+ id: z.ZodOptional<z.ZodString>;
540
+ policyId: z.ZodString;
541
+ effect: z.ZodLiteral<"allow">;
542
+ }, z.core.$strict>, z.ZodObject<{
543
+ contextHash: z.ZodCustom<CanonicalHash, CanonicalHash>;
544
+ id: z.ZodOptional<z.ZodString>;
545
+ policyId: z.ZodString;
546
+ effect: z.ZodLiteral<"allow">;
547
+ }, z.core.$strict>, z.ZodObject<{
548
+ conditionals: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
549
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
550
+ operator: z.ZodLiteral<"equals">;
551
+ value: z.ZodJSONSchema;
552
+ }, z.core.$strict>, z.ZodObject<{
553
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
554
+ operator: z.ZodLiteral<"in">;
555
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
556
+ }, z.core.$strict>, z.ZodObject<{
557
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
558
+ operator: z.ZodLiteral<"matches">;
559
+ value: z.ZodString;
560
+ }, z.core.$strict>, z.ZodObject<{
561
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
562
+ operator: z.ZodLiteral<"matches_host">;
563
+ value: z.ZodString;
564
+ }, z.core.$strict>, z.ZodObject<{
565
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
566
+ operator: z.ZodLiteral<"matches_path">;
567
+ value: z.ZodString;
568
+ }, z.core.$strict>, z.ZodObject<{
569
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
570
+ operator: z.ZodLiteral<"range">;
571
+ value: z.ZodObject<{
572
+ min: z.ZodOptional<z.ZodNumber>;
573
+ max: z.ZodOptional<z.ZodNumber>;
574
+ }, z.core.$strict>;
575
+ }, z.core.$strict>, z.ZodObject<{
576
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
577
+ operator: z.ZodLiteral<"matches_url">;
578
+ value: z.ZodString;
579
+ }, z.core.$strict>, z.ZodObject<{
580
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
581
+ operator: z.ZodLiteral<"values_in">;
582
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
583
+ }, z.core.$strict>, z.ZodObject<{
584
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
585
+ operator: z.ZodLiteral<"exists">;
586
+ }, z.core.$strict>, z.ZodObject<{
587
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
588
+ operator: z.ZodLiteral<"keys_in">;
589
+ value: z.ZodArray<z.ZodString>;
590
+ }, z.core.$strict>, z.ZodObject<{
591
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
592
+ operator: z.ZodLiteral<"size">;
593
+ value: z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
594
+ min: z.ZodOptional<z.ZodNumber>;
595
+ max: z.ZodOptional<z.ZodNumber>;
596
+ }, z.core.$strict>]>;
597
+ }, z.core.$strict>]>>;
598
+ id: z.ZodOptional<z.ZodString>;
599
+ policyId: z.ZodString;
600
+ effect: z.ZodLiteral<"allow">;
378
601
  }, z.core.$strict>]>;
379
602
  /** Derived from OverrideSchema — the schema is the single source of truth. */
380
603
  type Override = z.infer<typeof OverrideSchema>;
@@ -409,6 +632,10 @@ interface OverrideTrace {
409
632
  matched: boolean;
410
633
  conditionResults?: ConditionTrace[];
411
634
  }
635
+ interface DefaultTrace {
636
+ defaultEffect: DefaultEffect;
637
+ overrides: OverrideTrace[];
638
+ }
412
639
  interface StatementTrace {
413
640
  statement: Statement;
414
641
  permissionMatched: boolean;
@@ -429,6 +656,8 @@ interface PolicyResult {
429
656
  explicit: boolean;
430
657
  reason: PolicyReason;
431
658
  statements: StatementTrace[];
659
+ /** Trace mode only. Present when no statement matched and an ask default was consulted (never attached for deny defaults). */
660
+ default?: DefaultTrace;
432
661
  }
433
662
  interface ParsedUrl {
434
663
  scheme: string;
@@ -465,4 +694,4 @@ interface OpenApiSchema {
465
694
  anyOf?: OpenApiSchema[];
466
695
  }
467
696
 
468
- export { type ArrayOperator, ArrayOperatorSchema, type CanonicalHash, CanonicalHashSchema, type Condition, ConditionSchema, type ConditionTrace, type ConditionValue, ConditionValueSchema, type Effect, type EvaluatePolicyOptions, type JsonValue, type OpenApiSchema, type Operator, OperatorSchema, type OtherOperator, OtherOperatorSchema, type Override, OverrideSchema, type OverrideTrace, type ParsedUrl, type Policy, type PolicyActionRequest, type PolicyHttpRequest, type PolicyReason, type PolicyRequest, type PolicyResult, PolicySchema, type RangeValue, RangeValueSchema, type ScalarOperator, ScalarOperatorSchema, type SizeValue, SizeValueSchema, type Statement, StatementSchema, type StatementTrace, type UrlOperator, UrlOperatorSchema, VALID_EFFECTS, VALID_OPERATOR_LIST, VALID_VERSIONS, getOpenApiSchema };
697
+ export { type ArrayOperator, ArrayOperatorSchema, type CanonicalHash, CanonicalHashSchema, type Condition, ConditionSchema, type ConditionTrace, type ConditionValue, ConditionValueSchema, type DefaultEffect, DefaultEffectSchema, type DefaultTrace, type Effect, type EvaluatePolicyOptions, type JsonValue, type OpenApiSchema, type Operator, OperatorSchema, type OtherOperator, OtherOperatorSchema, type Override, OverrideSchema, type OverrideTrace, type ParsedUrl, type Policy, type PolicyActionRequest, type PolicyHttpRequest, type PolicyId, PolicyIdSchema, type PolicyReason, type PolicyRequest, type PolicyResult, PolicySchema, RUBBERDUCK_POLICY_VERSION, type RangeValue, RangeValueSchema, type ScalarOperator, ScalarOperatorSchema, type SizeValue, SizeValueSchema, type Statement, type StatementId, StatementIdSchema, StatementSchema, type StatementTrace, type UrlOperator, UrlOperatorSchema, VALID_EFFECTS, VALID_OPERATOR_LIST, VALID_VERSIONS, getOpenApiSchema };
package/dist/index.d.ts CHANGED
@@ -1,13 +1,16 @@
1
1
  import { z } from 'zod';
2
2
 
3
- /** Current policy document version. */
4
- declare const VALID_VERSIONS: readonly [1, 2];
3
+ /** Release-candidate policy document version for the current experimental shape. */
4
+ declare const RUBBERDUCK_POLICY_VERSION: "rc-rubberduck";
5
+ /** Supported policy document versions. */
6
+ declare const VALID_VERSIONS: readonly [1, 2, "rc-rubberduck"];
5
7
  /** Valid policy effects. */
6
8
  declare const VALID_EFFECTS: readonly ["allow", "ask", "deny"];
7
9
  /** Derived from VALID_EFFECTS — the constant is the single source of truth. */
8
10
  type Effect = (typeof VALID_EFFECTS)[number];
9
11
  /** Valid condition operators. */
10
12
  declare const VALID_OPERATOR_LIST: readonly ["equals", "exists", "in", "keys_in", "matches", "matches_host", "matches_path", "matches_url", "range", "size", "values_in"];
13
+ declare const ConditionValueSchema: z.ZodJSONSchema;
11
14
  declare const RangeValueSchema: z.ZodObject<{
12
15
  min: z.ZodOptional<z.ZodNumber>;
13
16
  max: z.ZodOptional<z.ZodNumber>;
@@ -114,7 +117,6 @@ declare const OperatorSchema: z.ZodEnum<{
114
117
  }>;
115
118
  /** Derived from OperatorSchema — the schema is the single source of truth. */
116
119
  type Operator = z.infer<typeof OperatorSchema>;
117
- declare const ConditionValueSchema: z.ZodJSONSchema;
118
120
  /** Statement schema accepting the union of all effects (use PolicySchema for version-aware validation). */
119
121
  declare const StatementSchema: z.ZodObject<{
120
122
  id: z.ZodOptional<z.ZodString>;
@@ -178,6 +180,21 @@ declare const StatementSchema: z.ZodObject<{
178
180
  }, z.core.$strict>;
179
181
  /** Derived from StatementSchema — the schema is the single source of truth. */
180
182
  type Statement = z.infer<typeof StatementSchema>;
183
+ /** Statement identifier for rc-rubberduck policies. Must match ^s_\S+$ and be ≤512 chars. */
184
+ declare const StatementIdSchema: z.ZodString;
185
+ /** Derived from StatementIdSchema — the schema is the single source of truth. */
186
+ type StatementId = z.infer<typeof StatementIdSchema>;
187
+ /** Policy identifier for rc-rubberduck policies. Must match ^p_\S+$ and be ≤512 chars. */
188
+ declare const PolicyIdSchema: z.ZodString;
189
+ /** Derived from PolicyIdSchema — the schema is the single source of truth. */
190
+ type PolicyId = z.infer<typeof PolicyIdSchema>;
191
+ /** Effect applied when no statement matches (rc-rubberduck, required). deny == implicit deny. */
192
+ declare const DefaultEffectSchema: z.ZodEnum<{
193
+ ask: "ask";
194
+ deny: "deny";
195
+ }>;
196
+ /** Derived from DefaultEffectSchema — the schema is the single source of truth. */
197
+ type DefaultEffect = z.infer<typeof DefaultEffectSchema>;
181
198
  declare const PolicySchema: z.ZodUnion<readonly [z.ZodObject<{
182
199
  version: z.ZodLiteral<1>;
183
200
  statements: z.ZodArray<z.ZodObject<{
@@ -301,15 +318,93 @@ declare const PolicySchema: z.ZodUnion<readonly [z.ZodObject<{
301
318
  }, z.core.$strict>]>;
302
319
  }, z.core.$strict>]>>>;
303
320
  }, z.core.$strict>>;
321
+ }, z.core.$strict>, z.ZodObject<{
322
+ version: z.ZodLiteral<"rc-rubberduck">;
323
+ id: z.ZodString;
324
+ defaultEffect: z.ZodEnum<{
325
+ ask: "ask";
326
+ deny: "deny";
327
+ }>;
328
+ statements: z.ZodArray<z.ZodObject<{
329
+ id: z.ZodString;
330
+ effect: z.ZodEnum<{
331
+ allow: "allow";
332
+ ask: "ask";
333
+ deny: "deny";
334
+ }>;
335
+ permissions: z.ZodArray<z.ZodString>;
336
+ resources: z.ZodArray<z.ZodString>;
337
+ conditions: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
338
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
339
+ operator: z.ZodLiteral<"equals">;
340
+ value: z.ZodJSONSchema;
341
+ }, z.core.$strict>, z.ZodObject<{
342
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
343
+ operator: z.ZodLiteral<"in">;
344
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
345
+ }, z.core.$strict>, z.ZodObject<{
346
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
347
+ operator: z.ZodLiteral<"matches">;
348
+ value: z.ZodString;
349
+ }, z.core.$strict>, z.ZodObject<{
350
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
351
+ operator: z.ZodLiteral<"matches_host">;
352
+ value: z.ZodString;
353
+ }, z.core.$strict>, z.ZodObject<{
354
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
355
+ operator: z.ZodLiteral<"matches_path">;
356
+ value: z.ZodString;
357
+ }, z.core.$strict>, z.ZodObject<{
358
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
359
+ operator: z.ZodLiteral<"range">;
360
+ value: z.ZodObject<{
361
+ min: z.ZodOptional<z.ZodNumber>;
362
+ max: z.ZodOptional<z.ZodNumber>;
363
+ }, z.core.$strict>;
364
+ }, z.core.$strict>, z.ZodObject<{
365
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
366
+ operator: z.ZodLiteral<"matches_url">;
367
+ value: z.ZodString;
368
+ }, z.core.$strict>, z.ZodObject<{
369
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
370
+ operator: z.ZodLiteral<"values_in">;
371
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
372
+ }, z.core.$strict>, z.ZodObject<{
373
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
374
+ operator: z.ZodLiteral<"exists">;
375
+ }, z.core.$strict>, z.ZodObject<{
376
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
377
+ operator: z.ZodLiteral<"keys_in">;
378
+ value: z.ZodArray<z.ZodString>;
379
+ }, z.core.$strict>, z.ZodObject<{
380
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
381
+ operator: z.ZodLiteral<"size">;
382
+ value: z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
383
+ min: z.ZodOptional<z.ZodNumber>;
384
+ max: z.ZodOptional<z.ZodNumber>;
385
+ }, z.core.$strict>]>;
386
+ }, z.core.$strict>]>>>;
387
+ }, z.core.$strict>>;
304
388
  }, z.core.$strict>]>;
305
389
  /** Derived from PolicySchema — the schema is the single source of truth. */
306
390
  type Policy = z.infer<typeof PolicySchema>;
307
391
  /** SHA-256 hex digest of an RFC 8785 (JCS) canonicalized JSON value. */
308
392
  declare const CanonicalHashSchema: z.ZodCustom<CanonicalHash, CanonicalHash>;
309
393
  /**
310
- * Runtime schema for the Override type. `.strict()` keeps the variants
311
- * mutually exclusive (an object carrying two variant fields fails all
312
- * branches).
394
+ * Runtime schema for the Override type. Each variant has exactly one target
395
+ * field (statementHash for v1/v2, statementId or policyId for rc-rubberduck) and exactly
396
+ * one binding mode (match, contextHash, or conditionals). `.strict()` keeps
397
+ * the variants mutually exclusive (an object carrying fields from two variants
398
+ * fails all branches).
399
+ *
400
+ * Targets are all non-null:
401
+ * - statementHash: targets a v1/v2 statement by canonical hash
402
+ * - statementId: targets an rc-rubberduck statement by id
403
+ * - policyId: targets that policy's default effect (rc-rubberduck only)
404
+ *
405
+ * Empty conditionals is intentional (the "blank check"): the override applies
406
+ * whenever the targeted ask statement fires, with no extra conditions. Do not
407
+ * add .min(1) to conditionals.
313
408
  */
314
409
  declare const OverrideSchema: z.ZodUnion<readonly [z.ZodObject<{
315
410
  match: z.ZodLiteral<"any">;
@@ -375,6 +470,134 @@ declare const OverrideSchema: z.ZodUnion<readonly [z.ZodObject<{
375
470
  id: z.ZodOptional<z.ZodString>;
376
471
  statementHash: z.ZodCustom<CanonicalHash, CanonicalHash>;
377
472
  effect: z.ZodLiteral<"allow">;
473
+ }, z.core.$strict>, z.ZodObject<{
474
+ match: z.ZodLiteral<"any">;
475
+ id: z.ZodOptional<z.ZodString>;
476
+ statementId: z.ZodString;
477
+ effect: z.ZodLiteral<"allow">;
478
+ }, z.core.$strict>, z.ZodObject<{
479
+ contextHash: z.ZodCustom<CanonicalHash, CanonicalHash>;
480
+ id: z.ZodOptional<z.ZodString>;
481
+ statementId: z.ZodString;
482
+ effect: z.ZodLiteral<"allow">;
483
+ }, z.core.$strict>, z.ZodObject<{
484
+ conditionals: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
485
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
486
+ operator: z.ZodLiteral<"equals">;
487
+ value: z.ZodJSONSchema;
488
+ }, z.core.$strict>, z.ZodObject<{
489
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
490
+ operator: z.ZodLiteral<"in">;
491
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
492
+ }, z.core.$strict>, z.ZodObject<{
493
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
494
+ operator: z.ZodLiteral<"matches">;
495
+ value: z.ZodString;
496
+ }, z.core.$strict>, z.ZodObject<{
497
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
498
+ operator: z.ZodLiteral<"matches_host">;
499
+ value: z.ZodString;
500
+ }, z.core.$strict>, z.ZodObject<{
501
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
502
+ operator: z.ZodLiteral<"matches_path">;
503
+ value: z.ZodString;
504
+ }, z.core.$strict>, z.ZodObject<{
505
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
506
+ operator: z.ZodLiteral<"range">;
507
+ value: z.ZodObject<{
508
+ min: z.ZodOptional<z.ZodNumber>;
509
+ max: z.ZodOptional<z.ZodNumber>;
510
+ }, z.core.$strict>;
511
+ }, z.core.$strict>, z.ZodObject<{
512
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
513
+ operator: z.ZodLiteral<"matches_url">;
514
+ value: z.ZodString;
515
+ }, z.core.$strict>, z.ZodObject<{
516
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
517
+ operator: z.ZodLiteral<"values_in">;
518
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
519
+ }, z.core.$strict>, z.ZodObject<{
520
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
521
+ operator: z.ZodLiteral<"exists">;
522
+ }, z.core.$strict>, z.ZodObject<{
523
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
524
+ operator: z.ZodLiteral<"keys_in">;
525
+ value: z.ZodArray<z.ZodString>;
526
+ }, z.core.$strict>, z.ZodObject<{
527
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
528
+ operator: z.ZodLiteral<"size">;
529
+ value: z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
530
+ min: z.ZodOptional<z.ZodNumber>;
531
+ max: z.ZodOptional<z.ZodNumber>;
532
+ }, z.core.$strict>]>;
533
+ }, z.core.$strict>]>>;
534
+ id: z.ZodOptional<z.ZodString>;
535
+ statementId: z.ZodString;
536
+ effect: z.ZodLiteral<"allow">;
537
+ }, z.core.$strict>, z.ZodObject<{
538
+ match: z.ZodLiteral<"any">;
539
+ id: z.ZodOptional<z.ZodString>;
540
+ policyId: z.ZodString;
541
+ effect: z.ZodLiteral<"allow">;
542
+ }, z.core.$strict>, z.ZodObject<{
543
+ contextHash: z.ZodCustom<CanonicalHash, CanonicalHash>;
544
+ id: z.ZodOptional<z.ZodString>;
545
+ policyId: z.ZodString;
546
+ effect: z.ZodLiteral<"allow">;
547
+ }, z.core.$strict>, z.ZodObject<{
548
+ conditionals: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
549
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
550
+ operator: z.ZodLiteral<"equals">;
551
+ value: z.ZodJSONSchema;
552
+ }, z.core.$strict>, z.ZodObject<{
553
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
554
+ operator: z.ZodLiteral<"in">;
555
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
556
+ }, z.core.$strict>, z.ZodObject<{
557
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
558
+ operator: z.ZodLiteral<"matches">;
559
+ value: z.ZodString;
560
+ }, z.core.$strict>, z.ZodObject<{
561
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
562
+ operator: z.ZodLiteral<"matches_host">;
563
+ value: z.ZodString;
564
+ }, z.core.$strict>, z.ZodObject<{
565
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
566
+ operator: z.ZodLiteral<"matches_path">;
567
+ value: z.ZodString;
568
+ }, z.core.$strict>, z.ZodObject<{
569
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
570
+ operator: z.ZodLiteral<"range">;
571
+ value: z.ZodObject<{
572
+ min: z.ZodOptional<z.ZodNumber>;
573
+ max: z.ZodOptional<z.ZodNumber>;
574
+ }, z.core.$strict>;
575
+ }, z.core.$strict>, z.ZodObject<{
576
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
577
+ operator: z.ZodLiteral<"matches_url">;
578
+ value: z.ZodString;
579
+ }, z.core.$strict>, z.ZodObject<{
580
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
581
+ operator: z.ZodLiteral<"values_in">;
582
+ value: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
583
+ }, z.core.$strict>, z.ZodObject<{
584
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
585
+ operator: z.ZodLiteral<"exists">;
586
+ }, z.core.$strict>, z.ZodObject<{
587
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
588
+ operator: z.ZodLiteral<"keys_in">;
589
+ value: z.ZodArray<z.ZodString>;
590
+ }, z.core.$strict>, z.ZodObject<{
591
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
592
+ operator: z.ZodLiteral<"size">;
593
+ value: z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
594
+ min: z.ZodOptional<z.ZodNumber>;
595
+ max: z.ZodOptional<z.ZodNumber>;
596
+ }, z.core.$strict>]>;
597
+ }, z.core.$strict>]>>;
598
+ id: z.ZodOptional<z.ZodString>;
599
+ policyId: z.ZodString;
600
+ effect: z.ZodLiteral<"allow">;
378
601
  }, z.core.$strict>]>;
379
602
  /** Derived from OverrideSchema — the schema is the single source of truth. */
380
603
  type Override = z.infer<typeof OverrideSchema>;
@@ -409,6 +632,10 @@ interface OverrideTrace {
409
632
  matched: boolean;
410
633
  conditionResults?: ConditionTrace[];
411
634
  }
635
+ interface DefaultTrace {
636
+ defaultEffect: DefaultEffect;
637
+ overrides: OverrideTrace[];
638
+ }
412
639
  interface StatementTrace {
413
640
  statement: Statement;
414
641
  permissionMatched: boolean;
@@ -429,6 +656,8 @@ interface PolicyResult {
429
656
  explicit: boolean;
430
657
  reason: PolicyReason;
431
658
  statements: StatementTrace[];
659
+ /** Trace mode only. Present when no statement matched and an ask default was consulted (never attached for deny defaults). */
660
+ default?: DefaultTrace;
432
661
  }
433
662
  interface ParsedUrl {
434
663
  scheme: string;
@@ -465,4 +694,4 @@ interface OpenApiSchema {
465
694
  anyOf?: OpenApiSchema[];
466
695
  }
467
696
 
468
- export { type ArrayOperator, ArrayOperatorSchema, type CanonicalHash, CanonicalHashSchema, type Condition, ConditionSchema, type ConditionTrace, type ConditionValue, ConditionValueSchema, type Effect, type EvaluatePolicyOptions, type JsonValue, type OpenApiSchema, type Operator, OperatorSchema, type OtherOperator, OtherOperatorSchema, type Override, OverrideSchema, type OverrideTrace, type ParsedUrl, type Policy, type PolicyActionRequest, type PolicyHttpRequest, type PolicyReason, type PolicyRequest, type PolicyResult, PolicySchema, type RangeValue, RangeValueSchema, type ScalarOperator, ScalarOperatorSchema, type SizeValue, SizeValueSchema, type Statement, StatementSchema, type StatementTrace, type UrlOperator, UrlOperatorSchema, VALID_EFFECTS, VALID_OPERATOR_LIST, VALID_VERSIONS, getOpenApiSchema };
697
+ export { type ArrayOperator, ArrayOperatorSchema, type CanonicalHash, CanonicalHashSchema, type Condition, ConditionSchema, type ConditionTrace, type ConditionValue, ConditionValueSchema, type DefaultEffect, DefaultEffectSchema, type DefaultTrace, type Effect, type EvaluatePolicyOptions, type JsonValue, type OpenApiSchema, type Operator, OperatorSchema, type OtherOperator, OtherOperatorSchema, type Override, OverrideSchema, type OverrideTrace, type ParsedUrl, type Policy, type PolicyActionRequest, type PolicyHttpRequest, type PolicyId, PolicyIdSchema, type PolicyReason, type PolicyRequest, type PolicyResult, PolicySchema, RUBBERDUCK_POLICY_VERSION, type RangeValue, RangeValueSchema, type ScalarOperator, ScalarOperatorSchema, type SizeValue, SizeValueSchema, type Statement, type StatementId, StatementIdSchema, StatementSchema, type StatementTrace, type UrlOperator, UrlOperatorSchema, VALID_EFFECTS, VALID_OPERATOR_LIST, VALID_VERSIONS, getOpenApiSchema };
package/dist/index.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import { z } from 'zod';
2
2
 
3
3
  // src/schema.ts
4
- var VALID_VERSIONS = [1, 2];
4
+ var RUBBERDUCK_POLICY_VERSION = "rc-rubberduck";
5
+ var VALID_VERSIONS = [1, 2, RUBBERDUCK_POLICY_VERSION];
5
6
  var VALID_EFFECTS = ["allow", "ask", "deny"];
6
7
  var VALID_OPERATOR_LIST = [
7
8
  "equals",
@@ -18,10 +19,11 @@ var VALID_OPERATOR_LIST = [
18
19
  ];
19
20
  var ScalarSchema = z.union([z.string(), z.number(), z.boolean()]);
20
21
  var PathSchema = z.array(z.union([z.string(), z.number()])).min(1);
22
+ var ConditionValueSchema = z.json();
21
23
  var EqualsConditionSchema = z.object({
22
24
  path: PathSchema,
23
25
  operator: z.literal("equals"),
24
- value: z.json()
26
+ value: ConditionValueSchema
25
27
  }).strict();
26
28
  var InConditionSchema = z.object({
27
29
  path: PathSchema,
@@ -127,7 +129,6 @@ var OperatorSchema = z.enum([
127
129
  "keys_in",
128
130
  "size"
129
131
  ]);
130
- var ConditionValueSchema = z.json();
131
132
  var V1StatementSchema = z.object({
132
133
  id: z.string().optional(),
133
134
  effect: z.enum(["allow", "deny"]),
@@ -143,32 +144,93 @@ var V2StatementSchema = z.object({
143
144
  conditions: z.array(ConditionSchema).optional()
144
145
  }).strict();
145
146
  var StatementSchema = V2StatementSchema;
147
+ var StatementIdSchema = z.string().regex(/^s_\S+$/, { error: "Statement id must match ^s_\\S+$" }).max(512);
148
+ var PolicyIdSchema = z.string().regex(/^p_\S+$/, { error: "Policy id must match ^p_\\S+$" }).max(512);
146
149
  var V1PolicySchema = z.object({
147
150
  version: z.literal(1),
148
151
  statements: z.array(V1StatementSchema)
149
152
  }).strict();
153
+ var DefaultEffectSchema = z.enum(["deny", "ask"]);
150
154
  var V2PolicySchema = z.object({
151
155
  version: z.literal(2),
152
156
  statements: z.array(V2StatementSchema)
153
157
  }).strict();
154
- var PolicySchema = z.union([V1PolicySchema, V2PolicySchema]);
158
+ var RcRubberduckStatementSchema = z.object({
159
+ id: StatementIdSchema,
160
+ effect: z.enum(["allow", "ask", "deny"]),
161
+ permissions: z.array(z.string()).min(1),
162
+ resources: z.array(z.string()).min(1),
163
+ conditions: z.array(ConditionSchema).optional()
164
+ }).strict();
165
+ var RcRubberduckPolicySchema = z.object({
166
+ version: z.literal(RUBBERDUCK_POLICY_VERSION),
167
+ id: PolicyIdSchema,
168
+ defaultEffect: DefaultEffectSchema,
169
+ statements: z.array(RcRubberduckStatementSchema)
170
+ }).strict();
171
+ var PolicySchema = z.union([
172
+ V1PolicySchema,
173
+ V2PolicySchema,
174
+ RcRubberduckPolicySchema
175
+ ]);
155
176
  var CanonicalHashSchema = z.custom(
156
177
  (value) => typeof value === "string" && /^[0-9a-f]{64}$/.test(value),
157
178
  { error: "Expected a 64-character lowercase hex SHA-256 digest" }
158
179
  );
159
- var OverrideBaseShape = {
180
+ var OverrideHashBaseShape = {
160
181
  id: z.string().optional(),
182
+ /**
183
+ * The canonical hash of the targeted statement.
184
+ * Used for v1/v2 policies. Must be a valid SHA-256 hex digest (non-null).
185
+ */
161
186
  statementHash: CanonicalHashSchema,
162
187
  effect: z.literal("allow")
163
188
  };
189
+ var OverrideIdBaseShape = {
190
+ id: z.string().optional(),
191
+ /**
192
+ * The statement id of the targeted statement. Used for rc-rubberduck policies.
193
+ * Must be a valid statement id (non-null). To target the policy's default
194
+ * effect, use policyId instead.
195
+ */
196
+ statementId: StatementIdSchema,
197
+ effect: z.literal("allow")
198
+ };
199
+ var OverridePolicyIdBaseShape = {
200
+ id: z.string().optional(),
201
+ /**
202
+ * Targets the policy's default effect. Only applies when this policyId
203
+ * matches the evaluated policy's id. Used for rc-rubberduck policies.
204
+ */
205
+ policyId: PolicyIdSchema,
206
+ effect: z.literal("allow")
207
+ };
164
208
  var OverrideSchema = z.union([
165
- z.object({ ...OverrideBaseShape, match: z.literal("any") }).strict(),
166
- z.object({ ...OverrideBaseShape, contextHash: CanonicalHashSchema }).strict(),
167
- // Empty conditionals is intentional (the "blank check"): the override
168
- // applies whenever the targeted ask statement fires, with no extra
169
- // conditions. Do not add .min(1) here.
209
+ // statementHash × match
210
+ z.object({ ...OverrideHashBaseShape, match: z.literal("any") }).strict(),
211
+ // statementHash × contextHash
212
+ z.object({ ...OverrideHashBaseShape, contextHash: CanonicalHashSchema }).strict(),
213
+ // statementHash × conditionals
214
+ z.object({
215
+ ...OverrideHashBaseShape,
216
+ conditionals: z.array(ConditionSchema)
217
+ }).strict(),
218
+ // statementId × match
219
+ z.object({ ...OverrideIdBaseShape, match: z.literal("any") }).strict(),
220
+ // statementId × contextHash
221
+ z.object({ ...OverrideIdBaseShape, contextHash: CanonicalHashSchema }).strict(),
222
+ // statementId × conditionals
223
+ z.object({
224
+ ...OverrideIdBaseShape,
225
+ conditionals: z.array(ConditionSchema)
226
+ }).strict(),
227
+ // policyId × match
228
+ z.object({ ...OverridePolicyIdBaseShape, match: z.literal("any") }).strict(),
229
+ // policyId × contextHash
230
+ z.object({ ...OverridePolicyIdBaseShape, contextHash: CanonicalHashSchema }).strict(),
231
+ // policyId × conditionals
170
232
  z.object({
171
- ...OverrideBaseShape,
233
+ ...OverridePolicyIdBaseShape,
172
234
  conditionals: z.array(ConditionSchema)
173
235
  }).strict()
174
236
  ]);
@@ -178,9 +240,20 @@ function getOpenApiSchema() {
178
240
  required: ["version", "statements"],
179
241
  properties: {
180
242
  version: {
181
- type: "integer",
182
- enum: [...VALID_VERSIONS],
183
- description: `Policy schema version. Must be one of ${JSON.stringify([...VALID_VERSIONS])}.`
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
+ id: {
250
+ type: "string",
251
+ description: "Policy id (required for rc-rubberduck policies). Must use the p_ prefix and contain no whitespace."
252
+ },
253
+ defaultEffect: {
254
+ type: "string",
255
+ enum: [...DefaultEffectSchema.options],
256
+ description: "Effect applied when no statement matches. Required on rc-rubberduck policies; deny equals implicit deny."
184
257
  },
185
258
  statements: {
186
259
  type: "array",
@@ -191,12 +264,12 @@ function getOpenApiSchema() {
191
264
  properties: {
192
265
  id: {
193
266
  type: "string",
194
- description: "Optional identifier for debugging and provenance. Included in canonical hash."
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."
195
268
  },
196
269
  effect: {
197
270
  type: "string",
198
271
  enum: [...VALID_EFFECTS].sort(),
199
- description: "Whether to allow, ask, or deny the specified permissions. The 'ask' effect is only valid in version 2 policies."
272
+ description: "Whether to allow, ask, or deny the specified permissions. The 'ask' effect is valid in version 2 and rc-rubberduck policies."
200
273
  },
201
274
  permissions: {
202
275
  type: "array",
@@ -243,4 +316,4 @@ function getOpenApiSchema() {
243
316
  };
244
317
  }
245
318
 
246
- export { ArrayOperatorSchema, CanonicalHashSchema, ConditionSchema, ConditionValueSchema, OperatorSchema, OtherOperatorSchema, OverrideSchema, PolicySchema, RangeValueSchema, ScalarOperatorSchema, SizeValueSchema, StatementSchema, UrlOperatorSchema, VALID_EFFECTS, VALID_OPERATOR_LIST, VALID_VERSIONS, getOpenApiSchema };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zapier/policy-schema",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "Zod schemas and TypeScript types for the Zapier policy engine",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",