@o3co/auth.policy-verifier.builtins 0.12.0 → 0.13.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.
Files changed (54) hide show
  1. package/README.ja.md +24 -3
  2. package/README.md +41 -5
  3. package/dist/collectors/PayloadClaimAttributeCollector.d.mts.map +1 -1
  4. package/dist/collectors/PayloadScopeCollector.d.mts.map +1 -1
  5. package/dist/collectors/PayloadSubjectIdCollector.d.mts.map +1 -1
  6. package/dist/collectors/RequestContextAttributeCollector.d.mts.map +1 -1
  7. package/dist/collectors/StaticPermissionCollector.d.mts +15 -1
  8. package/dist/collectors/StaticPermissionCollector.d.mts.map +1 -1
  9. package/dist/collectors/StaticPermissionCollector.mjs +19 -1
  10. package/dist/collectors/StaticRoleCollector.d.mts +17 -1
  11. package/dist/collectors/StaticRoleCollector.d.mts.map +1 -1
  12. package/dist/collectors/StaticRoleCollector.mjs +40 -1
  13. package/dist/collectors/_attributeMapping.d.mts +10 -2
  14. package/dist/collectors/_attributeMapping.d.mts.map +1 -1
  15. package/dist/collectors/_attributeMapping.mjs +10 -2
  16. package/dist/collectors/_claims.d.mts.map +1 -1
  17. package/dist/collectors/_claims.mjs +7 -3
  18. package/dist/module.d.mts.map +1 -1
  19. package/dist/resource/DotNotationResourceParser.d.mts.map +1 -1
  20. package/dist/rules/AttrLiteralCompare.d.mts +11 -1
  21. package/dist/rules/AttrLiteralCompare.d.mts.map +1 -1
  22. package/dist/rules/AttrLiteralCompare.mjs +21 -9
  23. package/dist/rules/AttrLiteralEqual.d.mts +10 -1
  24. package/dist/rules/AttrLiteralEqual.d.mts.map +1 -1
  25. package/dist/rules/AttrLiteralEqual.mjs +19 -10
  26. package/dist/rules/AttrLiteralIn.d.mts +9 -1
  27. package/dist/rules/AttrLiteralIn.d.mts.map +1 -1
  28. package/dist/rules/AttrLiteralIn.mjs +14 -6
  29. package/dist/rules/AttrLiteralNotEqual.d.mts +12 -2
  30. package/dist/rules/AttrLiteralNotEqual.d.mts.map +1 -1
  31. package/dist/rules/AttrLiteralNotEqual.mjs +21 -11
  32. package/dist/rules/AttrLiteralNotIn.d.mts +11 -2
  33. package/dist/rules/AttrLiteralNotIn.d.mts.map +1 -1
  34. package/dist/rules/AttrLiteralNotIn.mjs +16 -7
  35. package/dist/rules/AttrMatchRule.d.mts +2 -1
  36. package/dist/rules/AttrMatchRule.d.mts.map +1 -1
  37. package/dist/rules/AttrMatchRule.mjs +6 -1
  38. package/dist/rules/AttrPairCompare.d.mts +11 -1
  39. package/dist/rules/AttrPairCompare.d.mts.map +1 -1
  40. package/dist/rules/AttrPairCompare.mjs +22 -10
  41. package/dist/rules/AttrPairEqual.d.mts +10 -1
  42. package/dist/rules/AttrPairEqual.d.mts.map +1 -1
  43. package/dist/rules/AttrPairEqual.mjs +18 -8
  44. package/dist/rules/AttrPairNotEqual.d.mts +10 -1
  45. package/dist/rules/AttrPairNotEqual.d.mts.map +1 -1
  46. package/dist/rules/AttrPairNotEqual.mjs +18 -8
  47. package/dist/rules/HasPermission.d.mts.map +1 -1
  48. package/dist/rules/HasScope.d.mts.map +1 -1
  49. package/dist/rules/collectors/ResourceActionPermissionRuleCollector.d.mts +1 -1
  50. package/dist/rules/collectors/ResourceActionPermissionRuleCollector.d.mts.map +1 -1
  51. package/dist/rules/collectors/ResourceActionPermissionRuleCollector.mjs +1 -1
  52. package/dist/rules/collectors/ResourceActionScopeRuleCollector.d.mts +5 -1
  53. package/dist/rules/collectors/ResourceActionScopeRuleCollector.d.mts.map +1 -1
  54. package/package.json +5 -5
@@ -21,25 +21,34 @@ import { requireAttrName, requireLiteralValue, requireOptionalGroup, } from "./_
21
21
  *
22
22
  * Pass a shared `group` string to two instances to opt into OR semantics
23
23
  * (e.g. "role is admin" OR "role is superuser" under one group).
24
+ *
25
+ * ## Configuration is copied at construction
26
+ *
27
+ * The constructor reads each field of `config` once, validates it, and keeps
28
+ * the validated value in a field of its own; the object is not retained (#255).
29
+ * A caller that mutates the config afterwards changes nothing: the rule answers
30
+ * from the values it validated, and `ruleType` and `message` keep describing
31
+ * them.
24
32
  */
25
33
  export class AttrLiteralEqual {
26
- config;
27
34
  ruleType;
28
35
  code = "attr_not_equal";
29
36
  message;
37
+ a;
38
+ v;
30
39
  constructor(config) {
31
- this.config = config;
32
- requireAttrName("AttrLiteralEqual", "a", config.a);
33
- requireLiteralValue("AttrLiteralEqual", "v", config.v);
40
+ const a = requireAttrName("AttrLiteralEqual", "a", config.a);
41
+ const v = requireLiteralValue("AttrLiteralEqual", "v", config.v);
34
42
  const group = requireOptionalGroup("AttrLiteralEqual", config.group);
35
- this.ruleType =
36
- group ?? `attr_literal_equal:${config.a}:${typeof config.v}:${String(config.v)}`;
37
- this.message = `Attribute constraint not satisfied: ${config.a} must equal ${String(config.v)}.`;
43
+ this.a = a;
44
+ this.v = v;
45
+ this.ruleType = group ?? `attr_literal_equal:${a}:${typeof v}:${String(v)}`;
46
+ this.message = `Attribute constraint not satisfied: ${a} must equal ${String(v)}.`;
38
47
  }
39
48
  verify(attrs) {
40
- const x = attrs.get(this.config.a);
41
- if (typeof x !== typeof this.config.v)
49
+ const x = attrs.get(this.a);
50
+ if (typeof x !== typeof this.v)
42
51
  return false;
43
- return x === this.config.v;
52
+ return x === this.v;
44
53
  }
45
54
  }
@@ -24,12 +24,20 @@ export interface AttrLiteralInConfig {
24
24
  * will share a ruleType and be OR-combined.
25
25
  *
26
26
  * Pass an explicit `group` string to override the default ruleType entirely.
27
+ *
28
+ * ## Configuration is copied at construction
29
+ *
30
+ * The constructor reads each field of `config` once, validates it, and keeps
31
+ * the validated value in a field of its own; the object is not retained (#255).
32
+ * A caller that mutates the config afterwards changes nothing: the rule answers
33
+ * from the values it validated, and `ruleType` and `message` keep describing
34
+ * them.
27
35
  */
28
36
  export declare class AttrLiteralIn implements Rule {
29
- private readonly config;
30
37
  readonly ruleType: string;
31
38
  readonly code = "attr_not_in_set";
32
39
  readonly message: string;
40
+ private readonly a;
33
41
  private readonly elementType;
34
42
  private readonly valuesSet;
35
43
  constructor(config: AttrLiteralInConfig);
@@ -1 +1 @@
1
- {"version":3,"file":"AttrLiteralIn.d.mts","sourceRoot":"","sources":["../../src/rules/AttrLiteralIn.mts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAEN,KAAK,YAAY,EAIjB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,mBAAmB;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,aAAc,YAAW,IAAI;IAQ7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,qBAAqB;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;gBAEjB,MAAM,EAAE,mBAAmB;IAaxD,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAK1C"}
1
+ {"version":3,"file":"AttrLiteralIn.d.mts","sourceRoot":"","sources":["../../src/rules/AttrLiteralIn.mts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAEN,KAAK,YAAY,EAIjB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,mBAAmB;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,aAAc,YAAW,IAAI;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,qBAAqB;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;gBAElC,MAAM,EAAE,mBAAmB;IAcvC,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAK1C"}
@@ -20,27 +20,35 @@ import { computeValuesKey, requireAttrName, requireHomogeneousLiteralArray, requ
20
20
  * will share a ruleType and be OR-combined.
21
21
  *
22
22
  * Pass an explicit `group` string to override the default ruleType entirely.
23
+ *
24
+ * ## Configuration is copied at construction
25
+ *
26
+ * The constructor reads each field of `config` once, validates it, and keeps
27
+ * the validated value in a field of its own; the object is not retained (#255).
28
+ * A caller that mutates the config afterwards changes nothing: the rule answers
29
+ * from the values it validated, and `ruleType` and `message` keep describing
30
+ * them.
23
31
  */
24
32
  export class AttrLiteralIn {
25
- config;
26
33
  ruleType;
27
34
  code = "attr_not_in_set";
28
35
  message;
36
+ a;
29
37
  elementType;
30
38
  valuesSet;
31
39
  constructor(config) {
32
- this.config = config;
33
- requireAttrName("AttrLiteralIn", "a", config.a);
40
+ const a = requireAttrName("AttrLiteralIn", "a", config.a);
34
41
  const values = requireHomogeneousLiteralArray("AttrLiteralIn", config.values);
35
42
  const group = requireOptionalGroup("AttrLiteralIn", config.group);
43
+ this.a = a;
36
44
  this.elementType = typeof values[0];
37
45
  this.valuesSet = new Set(values);
38
46
  const valuesKey = computeValuesKey(values);
39
- this.ruleType = group ?? `attr_literal_in:${config.a}:${valuesKey}`;
40
- this.message = `Attribute constraint not satisfied: ${config.a} must be one of [${values.map(String).join(", ")}].`;
47
+ this.ruleType = group ?? `attr_literal_in:${a}:${valuesKey}`;
48
+ this.message = `Attribute constraint not satisfied: ${a} must be one of [${values.map(String).join(", ")}].`;
41
49
  }
42
50
  verify(attrs) {
43
- const x = attrs.get(this.config.a);
51
+ const x = attrs.get(this.a);
44
52
  if (typeof x !== this.elementType)
45
53
  return false;
46
54
  return this.valuesSet.has(x);
@@ -9,7 +9,8 @@ export interface AttrLiteralNotEqualConfig {
9
9
  * Rule that passes when a named attribute is present, matches the type of the
10
10
  * configured literal value, and is strictly NOT equal to it. No type coercion
11
11
  * is performed. If the attribute is missing, null, or of the wrong type the
12
- * rule returns false (safe-deny).
12
+ * rule returns false (safe-deny). A `NaN` attribute against a number literal
13
+ * is an unequal number and passes; whether it should deny is #254.
13
14
  *
14
15
  * ## Grouping and the default ruleType
15
16
  *
@@ -24,12 +25,21 @@ export interface AttrLiteralNotEqualConfig {
24
25
  * of two independent constraints. See AttrLiteralEqual for the same rationale.
25
26
  *
26
27
  * Pass a shared `group` string to two instances to opt into OR semantics.
28
+ *
29
+ * ## Configuration is copied at construction
30
+ *
31
+ * The constructor reads each field of `config` once, validates it, and keeps
32
+ * the validated value in a field of its own; the object is not retained (#255).
33
+ * A caller that mutates the config afterwards changes nothing: the rule answers
34
+ * from the values it validated, and `ruleType` and `message` keep describing
35
+ * them.
27
36
  */
28
37
  export declare class AttrLiteralNotEqual implements Rule {
29
- private readonly config;
30
38
  readonly ruleType: string;
31
39
  readonly code = "attr_equal";
32
40
  readonly message: string;
41
+ private readonly a;
42
+ private readonly v;
33
43
  constructor(config: AttrLiteralNotEqualConfig);
34
44
  verify(attrs: ReadonlyAttributes): boolean;
35
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AttrLiteralNotEqual.d.mts","sourceRoot":"","sources":["../../src/rules/AttrLiteralNotEqual.mts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EACN,KAAK,YAAY,EAIjB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,yBAAyB;IACzC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,YAAY,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,mBAAoB,YAAW,IAAI;IAKnC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEI,MAAM,EAAE,yBAAyB;IAU9D,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAK1C"}
1
+ {"version":3,"file":"AttrLiteralNotEqual.d.mts","sourceRoot":"","sources":["../../src/rules/AttrLiteralNotEqual.mts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EACN,KAAK,YAAY,EAIjB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,yBAAyB;IACzC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,YAAY,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,mBAAoB,YAAW,IAAI;IAC/C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAe;gBAErB,MAAM,EAAE,yBAAyB;IAW7C,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAK1C"}
@@ -5,7 +5,8 @@ import { requireAttrName, requireLiteralValue, requireOptionalGroup, } from "./_
5
5
  * Rule that passes when a named attribute is present, matches the type of the
6
6
  * configured literal value, and is strictly NOT equal to it. No type coercion
7
7
  * is performed. If the attribute is missing, null, or of the wrong type the
8
- * rule returns false (safe-deny).
8
+ * rule returns false (safe-deny). A `NaN` attribute against a number literal
9
+ * is an unequal number and passes; whether it should deny is #254.
9
10
  *
10
11
  * ## Grouping and the default ruleType
11
12
  *
@@ -20,25 +21,34 @@ import { requireAttrName, requireLiteralValue, requireOptionalGroup, } from "./_
20
21
  * of two independent constraints. See AttrLiteralEqual for the same rationale.
21
22
  *
22
23
  * Pass a shared `group` string to two instances to opt into OR semantics.
24
+ *
25
+ * ## Configuration is copied at construction
26
+ *
27
+ * The constructor reads each field of `config` once, validates it, and keeps
28
+ * the validated value in a field of its own; the object is not retained (#255).
29
+ * A caller that mutates the config afterwards changes nothing: the rule answers
30
+ * from the values it validated, and `ruleType` and `message` keep describing
31
+ * them.
23
32
  */
24
33
  export class AttrLiteralNotEqual {
25
- config;
26
34
  ruleType;
27
35
  code = "attr_equal";
28
36
  message;
37
+ a;
38
+ v;
29
39
  constructor(config) {
30
- this.config = config;
31
- requireAttrName("AttrLiteralNotEqual", "a", config.a);
32
- requireLiteralValue("AttrLiteralNotEqual", "v", config.v);
40
+ const a = requireAttrName("AttrLiteralNotEqual", "a", config.a);
41
+ const v = requireLiteralValue("AttrLiteralNotEqual", "v", config.v);
33
42
  const group = requireOptionalGroup("AttrLiteralNotEqual", config.group);
34
- this.ruleType =
35
- group ?? `attr_literal_not_equal:${config.a}:${typeof config.v}:${String(config.v)}`;
36
- this.message = `Attribute constraint not satisfied: ${config.a} must not equal ${String(config.v)}.`;
43
+ this.a = a;
44
+ this.v = v;
45
+ this.ruleType = group ?? `attr_literal_not_equal:${a}:${typeof v}:${String(v)}`;
46
+ this.message = `Attribute constraint not satisfied: ${a} must not equal ${String(v)}.`;
37
47
  }
38
48
  verify(attrs) {
39
- const x = attrs.get(this.config.a);
40
- if (typeof x !== typeof this.config.v)
49
+ const x = attrs.get(this.a);
50
+ if (typeof x !== typeof this.v)
41
51
  return false;
42
- return x !== this.config.v;
52
+ return x !== this.v;
43
53
  }
44
54
  }
@@ -9,7 +9,8 @@ export interface AttrLiteralNotInConfig {
9
9
  * Rule that passes when a named attribute is present, matches the element type
10
10
  * of the configured values array, and is NOT included in that array. No type
11
11
  * coercion is performed. If the attribute is missing, null, or of the wrong
12
- * type the rule returns false (safe-deny).
12
+ * type the rule returns false (safe-deny). A `NaN` attribute against number
13
+ * values is in none of them and passes; whether it should deny is #254.
13
14
  *
14
15
  * ## Grouping and the default ruleType
15
16
  *
@@ -19,12 +20,20 @@ export interface AttrLiteralNotInConfig {
19
20
  * `attr_literal_not_in:{a}:{valuesKey}`
20
21
  *
21
22
  * Pass an explicit `group` string to override the default ruleType entirely.
23
+ *
24
+ * ## Configuration is copied at construction
25
+ *
26
+ * The constructor reads each field of `config` once, validates it, and keeps
27
+ * the validated value in a field of its own; the object is not retained (#255).
28
+ * A caller that mutates the config afterwards changes nothing: the rule answers
29
+ * from the values it validated, and `ruleType` and `message` keep describing
30
+ * them.
22
31
  */
23
32
  export declare class AttrLiteralNotIn implements Rule {
24
- private readonly config;
25
33
  readonly ruleType: string;
26
34
  readonly code = "attr_in_set";
27
35
  readonly message: string;
36
+ private readonly a;
28
37
  private readonly elementType;
29
38
  private readonly valuesSet;
30
39
  constructor(config: AttrLiteralNotInConfig);
@@ -1 +1 @@
1
- {"version":3,"file":"AttrLiteralNotIn.d.mts","sourceRoot":"","sources":["../../src/rules/AttrLiteralNotIn.mts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAEN,KAAK,YAAY,EAIjB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,sBAAsB;IACtC,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,gBAAiB,YAAW,IAAI;IAQhC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;gBAEjB,MAAM,EAAE,sBAAsB;IAa3D,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAK1C"}
1
+ {"version":3,"file":"AttrLiteralNotIn.d.mts","sourceRoot":"","sources":["../../src/rules/AttrLiteralNotIn.mts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAEN,KAAK,YAAY,EAIjB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,sBAAsB;IACtC,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,gBAAiB,YAAW,IAAI;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;gBAElC,MAAM,EAAE,sBAAsB;IAc1C,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAK1C"}
@@ -5,7 +5,8 @@ import { computeValuesKey, requireAttrName, requireHomogeneousLiteralArray, requ
5
5
  * Rule that passes when a named attribute is present, matches the element type
6
6
  * of the configured values array, and is NOT included in that array. No type
7
7
  * coercion is performed. If the attribute is missing, null, or of the wrong
8
- * type the rule returns false (safe-deny).
8
+ * type the rule returns false (safe-deny). A `NaN` attribute against number
9
+ * values is in none of them and passes; whether it should deny is #254.
9
10
  *
10
11
  * ## Grouping and the default ruleType
11
12
  *
@@ -15,27 +16,35 @@ import { computeValuesKey, requireAttrName, requireHomogeneousLiteralArray, requ
15
16
  * `attr_literal_not_in:{a}:{valuesKey}`
16
17
  *
17
18
  * Pass an explicit `group` string to override the default ruleType entirely.
19
+ *
20
+ * ## Configuration is copied at construction
21
+ *
22
+ * The constructor reads each field of `config` once, validates it, and keeps
23
+ * the validated value in a field of its own; the object is not retained (#255).
24
+ * A caller that mutates the config afterwards changes nothing: the rule answers
25
+ * from the values it validated, and `ruleType` and `message` keep describing
26
+ * them.
18
27
  */
19
28
  export class AttrLiteralNotIn {
20
- config;
21
29
  ruleType;
22
30
  code = "attr_in_set";
23
31
  message;
32
+ a;
24
33
  elementType;
25
34
  valuesSet;
26
35
  constructor(config) {
27
- this.config = config;
28
- requireAttrName("AttrLiteralNotIn", "a", config.a);
36
+ const a = requireAttrName("AttrLiteralNotIn", "a", config.a);
29
37
  const values = requireHomogeneousLiteralArray("AttrLiteralNotIn", config.values);
30
38
  const group = requireOptionalGroup("AttrLiteralNotIn", config.group);
39
+ this.a = a;
31
40
  this.elementType = typeof values[0];
32
41
  this.valuesSet = new Set(values);
33
42
  const valuesKey = computeValuesKey(values);
34
- this.ruleType = group ?? `attr_literal_not_in:${config.a}:${valuesKey}`;
35
- this.message = `Attribute constraint not satisfied: ${config.a} must not be one of [${values.map(String).join(", ")}].`;
43
+ this.ruleType = group ?? `attr_literal_not_in:${a}:${valuesKey}`;
44
+ this.message = `Attribute constraint not satisfied: ${a} must not be one of [${values.map(String).join(", ")}].`;
36
45
  }
37
46
  verify(attrs) {
38
- const x = attrs.get(this.config.a);
47
+ const x = attrs.get(this.a);
39
48
  if (typeof x !== this.elementType)
40
49
  return false;
41
50
  return !this.valuesSet.has(x);
@@ -1,11 +1,12 @@
1
1
  import { AttrPairEqual, type AttrPairEqualConfig } from "./AttrPairEqual.mjs";
2
2
  export type AttrMatchRuleConfig = AttrPairEqualConfig;
3
3
  /**
4
- * @deprecated Use {@link AttrPairEqual}. Scheduled for removal in a future major version.
4
+ * @deprecated since v0.3 — use {@link AttrPairEqual}.
5
5
  *
6
6
  * Kept as a thin wrapper that preserves the legacy `ruleType` (`attr_match:{a}:{b}`)
7
7
  * and legacy `message` wording. `verify()` semantics are inherited unchanged from
8
8
  * `AttrPairEqual`: both named attributes must be non-empty strings and equal.
9
+ * Its config is validated by `super`, so a refusal names `AttrPairEqual`.
9
10
  */
10
11
  export declare class AttrMatchRule extends AttrPairEqual {
11
12
  readonly ruleType: string;
@@ -1 +1 @@
1
- {"version":3,"file":"AttrMatchRule.d.mts","sourceRoot":"","sources":["../../src/rules/AttrMatchRule.mts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE9E,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEtD;;;;;;GAMG;AACH,qBAAa,aAAc,SAAQ,aAAa;IAC/C,SAAkB,QAAQ,EAAE,MAAM,CAAC;IACnC,SAAkB,OAAO,EAAE,MAAM,CAAC;gBAEtB,MAAM,EAAE,mBAAmB;CAKvC"}
1
+ {"version":3,"file":"AttrMatchRule.d.mts","sourceRoot":"","sources":["../../src/rules/AttrMatchRule.mts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE9E,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEtD;;;;;;;GAOG;AACH,qBAAa,aAAc,SAAQ,aAAa;IAC/C,SAAkB,QAAQ,EAAE,MAAM,CAAC;IACnC,SAAkB,OAAO,EAAE,MAAM,CAAC;gBAEtB,MAAM,EAAE,mBAAmB;CAKvC"}
@@ -1,12 +1,17 @@
1
1
  // SPDX-FileCopyrightText: 2026 1o1 Co. Ltd.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
+ /*
4
+ * The deprecated `AttrMatchRule`: `AttrPairEqual` under its legacy `ruleType`
5
+ * and message, kept for existing configurations.
6
+ */
3
7
  import { AttrPairEqual } from "./AttrPairEqual.mjs";
4
8
  /**
5
- * @deprecated Use {@link AttrPairEqual}. Scheduled for removal in a future major version.
9
+ * @deprecated since v0.3 — use {@link AttrPairEqual}.
6
10
  *
7
11
  * Kept as a thin wrapper that preserves the legacy `ruleType` (`attr_match:{a}:{b}`)
8
12
  * and legacy `message` wording. `verify()` semantics are inherited unchanged from
9
13
  * `AttrPairEqual`: both named attributes must be non-empty strings and equal.
14
+ * Its config is validated by `super`, so a refusal names `AttrPairEqual`.
10
15
  */
11
16
  export class AttrMatchRule extends AttrPairEqual {
12
17
  ruleType;
@@ -23,12 +23,22 @@ export interface AttrPairCompareConfig {
23
23
  * `attr_pair_compare:{a}:{op}:{b}`
24
24
  *
25
25
  * Pass an explicit `group` string to override the default ruleType entirely.
26
+ *
27
+ * ## Configuration is copied at construction
28
+ *
29
+ * The constructor reads each field of `config` once, validates it, and keeps
30
+ * the validated value in a field of its own; the object is not retained (#255).
31
+ * A caller that mutates the config afterwards changes nothing: the rule answers
32
+ * from the values it validated, and `ruleType` and `message` keep describing
33
+ * them.
26
34
  */
27
35
  export declare class AttrPairCompare implements Rule {
28
- private readonly config;
29
36
  readonly ruleType: string;
30
37
  readonly code = "attr_compare_violated";
31
38
  readonly message: string;
39
+ private readonly a;
40
+ private readonly op;
41
+ private readonly b;
32
42
  constructor(config: AttrPairCompareConfig);
33
43
  verify(attrs: ReadonlyAttributes): boolean;
34
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AttrPairCompare.d.mts","sourceRoot":"","sources":["../../src/rules/AttrPairCompare.mts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAEN,KAAK,SAAS,EAId,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,qBAAqB;IACrC,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,SAAS,CAAC;IACd,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,eAAgB,YAAW,IAAI;IAK/B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,2BAA2B;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEI,MAAM,EAAE,qBAAqB;IAU1D,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAO1C"}
1
+ {"version":3,"file":"AttrPairCompare.d.mts","sourceRoot":"","sources":["../../src/rules/AttrPairCompare.mts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAEN,KAAK,SAAS,EAId,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,qBAAqB;IACrC,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,SAAS,CAAC;IACd,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,eAAgB,YAAW,IAAI;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,2BAA2B;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAY;IAC/B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;gBAEf,MAAM,EAAE,qBAAqB;IAazC,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAO1C"}
@@ -18,28 +18,40 @@ import { applyCompare, requireAttrName, requireCompareOp, requireOptionalGroup,
18
18
  * `attr_pair_compare:{a}:{op}:{b}`
19
19
  *
20
20
  * Pass an explicit `group` string to override the default ruleType entirely.
21
+ *
22
+ * ## Configuration is copied at construction
23
+ *
24
+ * The constructor reads each field of `config` once, validates it, and keeps
25
+ * the validated value in a field of its own; the object is not retained (#255).
26
+ * A caller that mutates the config afterwards changes nothing: the rule answers
27
+ * from the values it validated, and `ruleType` and `message` keep describing
28
+ * them.
21
29
  */
22
30
  export class AttrPairCompare {
23
- config;
24
31
  ruleType;
25
32
  code = "attr_compare_violated";
26
33
  message;
34
+ a;
35
+ op;
36
+ b;
27
37
  constructor(config) {
28
- this.config = config;
29
- requireAttrName("AttrPairCompare", "a", config.a);
30
- requireAttrName("AttrPairCompare", "b", config.b);
31
- requireCompareOp("AttrPairCompare", config.op);
38
+ const a = requireAttrName("AttrPairCompare", "a", config.a);
39
+ const b = requireAttrName("AttrPairCompare", "b", config.b);
40
+ const op = requireCompareOp("AttrPairCompare", config.op);
32
41
  const group = requireOptionalGroup("AttrPairCompare", config.group);
33
- this.ruleType = group ?? `attr_pair_compare:${config.a}:${config.op}:${config.b}`;
34
- this.message = `Attribute constraint not satisfied: ${config.a} must be ${config.op} ${config.b}.`;
42
+ this.a = a;
43
+ this.op = op;
44
+ this.b = b;
45
+ this.ruleType = group ?? `attr_pair_compare:${a}:${op}:${b}`;
46
+ this.message = `Attribute constraint not satisfied: ${a} must be ${op} ${b}.`;
35
47
  }
36
48
  verify(attrs) {
37
- const a = attrs.get(this.config.a);
38
- const b = attrs.get(this.config.b);
49
+ const a = attrs.get(this.a);
50
+ const b = attrs.get(this.b);
39
51
  if (typeof a !== "number")
40
52
  return false;
41
53
  if (typeof b !== "number")
42
54
  return false;
43
- return applyCompare(this.config.op, a, b);
55
+ return applyCompare(this.op, a, b);
44
56
  }
45
57
  }
@@ -23,12 +23,21 @@ export interface AttrPairEqualConfig {
23
23
  * `attr_pair_equal:{a}:{b}`
24
24
  *
25
25
  * Pass a shared `group` string to two instances to opt into OR semantics.
26
+ *
27
+ * ## Configuration is copied at construction
28
+ *
29
+ * The constructor reads each field of `config` once, validates it, and keeps
30
+ * the validated value in a field of its own; the object is not retained (#255).
31
+ * A caller that mutates the config afterwards changes nothing: the rule answers
32
+ * from the values it validated, and `ruleType` and `message` keep describing
33
+ * them.
26
34
  */
27
35
  export declare class AttrPairEqual implements Rule {
28
- private readonly config;
29
36
  readonly ruleType: string;
30
37
  readonly code = "attr_mismatch";
31
38
  readonly message: string;
39
+ private readonly a;
40
+ private readonly b;
32
41
  constructor(config: AttrPairEqualConfig);
33
42
  verify(attrs: ReadonlyAttributes): boolean;
34
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AttrPairEqual.d.mts","sourceRoot":"","sources":["../../src/rules/AttrPairEqual.mts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAGhF,MAAM,WAAW,mBAAmB;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,aAAc,YAAW,IAAI;IAK7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEI,MAAM,EAAE,mBAAmB;IASxD,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAO1C"}
1
+ {"version":3,"file":"AttrPairEqual.d.mts","sourceRoot":"","sources":["../../src/rules/AttrPairEqual.mts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAGhF,MAAM,WAAW,mBAAmB;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,aAAc,YAAW,IAAI;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;gBAEf,MAAM,EAAE,mBAAmB;IAWvC,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAO1C"}
@@ -20,23 +20,33 @@ import { requireAttrName, requireOptionalGroup } from "./_sharedValidation.mjs";
20
20
  * `attr_pair_equal:{a}:{b}`
21
21
  *
22
22
  * Pass a shared `group` string to two instances to opt into OR semantics.
23
+ *
24
+ * ## Configuration is copied at construction
25
+ *
26
+ * The constructor reads each field of `config` once, validates it, and keeps
27
+ * the validated value in a field of its own; the object is not retained (#255).
28
+ * A caller that mutates the config afterwards changes nothing: the rule answers
29
+ * from the values it validated, and `ruleType` and `message` keep describing
30
+ * them.
23
31
  */
24
32
  export class AttrPairEqual {
25
- config;
26
33
  ruleType;
27
34
  code = "attr_mismatch";
28
35
  message;
36
+ a;
37
+ b;
29
38
  constructor(config) {
30
- this.config = config;
31
- requireAttrName("AttrPairEqual", "a", config.a);
32
- requireAttrName("AttrPairEqual", "b", config.b);
39
+ const a = requireAttrName("AttrPairEqual", "a", config.a);
40
+ const b = requireAttrName("AttrPairEqual", "b", config.b);
33
41
  const group = requireOptionalGroup("AttrPairEqual", config.group);
34
- this.ruleType = group ?? `attr_pair_equal:${config.a}:${config.b}`;
35
- this.message = `Attribute constraint not satisfied: ${config.a} must equal ${config.b}.`;
42
+ this.a = a;
43
+ this.b = b;
44
+ this.ruleType = group ?? `attr_pair_equal:${a}:${b}`;
45
+ this.message = `Attribute constraint not satisfied: ${a} must equal ${b}.`;
36
46
  }
37
47
  verify(attrs) {
38
- const a = attrs.get(this.config.a);
39
- const b = attrs.get(this.config.b);
48
+ const a = attrs.get(this.a);
49
+ const b = attrs.get(this.b);
40
50
  if (typeof a !== "string" || a.length === 0)
41
51
  return false;
42
52
  if (typeof b !== "string" || b.length === 0)
@@ -22,12 +22,21 @@ export interface AttrPairNotEqualConfig {
22
22
  * `attr_pair_not_equal:{a}:{b}`
23
23
  *
24
24
  * Pass a shared `group` string to two instances to opt into OR semantics.
25
+ *
26
+ * ## Configuration is copied at construction
27
+ *
28
+ * The constructor reads each field of `config` once, validates it, and keeps
29
+ * the validated value in a field of its own; the object is not retained (#255).
30
+ * A caller that mutates the config afterwards changes nothing: the rule answers
31
+ * from the values it validated, and `ruleType` and `message` keep describing
32
+ * them.
25
33
  */
26
34
  export declare class AttrPairNotEqual implements Rule {
27
- private readonly config;
28
35
  readonly ruleType: string;
29
36
  readonly code = "attr_match";
30
37
  readonly message: string;
38
+ private readonly a;
39
+ private readonly b;
31
40
  constructor(config: AttrPairNotEqualConfig);
32
41
  verify(attrs: ReadonlyAttributes): boolean;
33
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AttrPairNotEqual.d.mts","sourceRoot":"","sources":["../../src/rules/AttrPairNotEqual.mts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAGhF,MAAM,WAAW,sBAAsB;IACtC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,gBAAiB,YAAW,IAAI;IAKhC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEI,MAAM,EAAE,sBAAsB;IAS3D,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAO1C"}
1
+ {"version":3,"file":"AttrPairNotEqual.d.mts","sourceRoot":"","sources":["../../src/rules/AttrPairNotEqual.mts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAGhF,MAAM,WAAW,sBAAsB;IACtC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,gBAAiB,YAAW,IAAI;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;gBAEf,MAAM,EAAE,sBAAsB;IAW1C,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;CAO1C"}
@@ -19,23 +19,33 @@ import { requireAttrName, requireOptionalGroup } from "./_sharedValidation.mjs";
19
19
  * `attr_pair_not_equal:{a}:{b}`
20
20
  *
21
21
  * Pass a shared `group` string to two instances to opt into OR semantics.
22
+ *
23
+ * ## Configuration is copied at construction
24
+ *
25
+ * The constructor reads each field of `config` once, validates it, and keeps
26
+ * the validated value in a field of its own; the object is not retained (#255).
27
+ * A caller that mutates the config afterwards changes nothing: the rule answers
28
+ * from the values it validated, and `ruleType` and `message` keep describing
29
+ * them.
22
30
  */
23
31
  export class AttrPairNotEqual {
24
- config;
25
32
  ruleType;
26
33
  code = "attr_match";
27
34
  message;
35
+ a;
36
+ b;
28
37
  constructor(config) {
29
- this.config = config;
30
- requireAttrName("AttrPairNotEqual", "a", config.a);
31
- requireAttrName("AttrPairNotEqual", "b", config.b);
38
+ const a = requireAttrName("AttrPairNotEqual", "a", config.a);
39
+ const b = requireAttrName("AttrPairNotEqual", "b", config.b);
32
40
  const group = requireOptionalGroup("AttrPairNotEqual", config.group);
33
- this.ruleType = group ?? `attr_pair_not_equal:${config.a}:${config.b}`;
34
- this.message = `Attribute constraint not satisfied: ${config.a} must not equal ${config.b}.`;
41
+ this.a = a;
42
+ this.b = b;
43
+ this.ruleType = group ?? `attr_pair_not_equal:${a}:${b}`;
44
+ this.message = `Attribute constraint not satisfied: ${a} must not equal ${b}.`;
35
45
  }
36
46
  verify(attrs) {
37
- const a = attrs.get(this.config.a);
38
- const b = attrs.get(this.config.b);
47
+ const a = attrs.get(this.a);
48
+ const b = attrs.get(this.b);
39
49
  if (typeof a !== "string" || a.length === 0)
40
50
  return false;
41
51
  if (typeof b !== "string" || b.length === 0)
@@ -1 +1 @@
1
- {"version":3,"file":"HasPermission.d.mts","sourceRoot":"","sources":["../../src/rules/HasPermission.mts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAQ,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAGtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,aAAc,YAAW,IAAI;IAK7B,OAAO,CAAC,UAAU;IAJ9B,QAAQ,CAAC,QAAQ,gBAAgB;IACjC,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEL,UAAU,EAAE,MAAM;IAItC,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;IAoB1C,OAAO,CAAC,KAAK;CA0Bb"}
1
+ {"version":3,"file":"HasPermission.d.mts","sourceRoot":"","sources":["../../src/rules/HasPermission.mts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,kBAAkB,EAAQ,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAGtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,aAAc,YAAW,IAAI;IAK7B,OAAO,CAAC,UAAU;IAJ9B,QAAQ,CAAC,QAAQ,gBAAgB;IACjC,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEL,UAAU,EAAE,MAAM;IAItC,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;IAoB1C,OAAO,CAAC,KAAK;CA0Bb"}
@@ -1 +1 @@
1
- {"version":3,"file":"HasScope.d.mts","sourceRoot":"","sources":["../../src/rules/HasScope.mts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAGhF,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC/B;;;;;;;;OAQG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,QAAS,YAAW,IAAI;IAQnC,OAAO,CAAC,KAAK;IAPd,QAAQ,CAAC,QAAQ,WAAW;IAC5B,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAU;gBAGvC,KAAK,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,eAAe;IAM1B,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;IAM1C,OAAO,CAAC,UAAU;CAYlB"}
1
+ {"version":3,"file":"HasScope.d.mts","sourceRoot":"","sources":["../../src/rules/HasScope.mts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAGhF,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC/B;;;;;;;;OAQG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,QAAS,YAAW,IAAI;IAQnC,OAAO,CAAC,KAAK;IAPd,QAAQ,CAAC,QAAQ,WAAW;IAC5B,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAU;gBAGvC,KAAK,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,eAAe;IAM1B,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;IAM1C,OAAO,CAAC,UAAU;CAYlB"}
@@ -1,7 +1,7 @@
1
1
  import type { CollectorContext, Rule, RuleCollector } from "@o3co/auth.policy-verifier.core";
2
2
  /**
3
3
  * Rule collector that emits a single `HasPermission` rule for the
4
- * `{resource}.perm:{action}` permission string. Use when the effective
4
+ * `{resource.raw}.perm:{action}` permission string. Use when the effective
5
5
  * permission is encoded directly into the token's permission attribute rather
6
6
  * than derived from scopes.
7
7
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ResourceActionPermissionRuleCollector.d.mts","sourceRoot":"","sources":["../../../src/rules/collectors/ResourceActionPermissionRuleCollector.mts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAG7F;;;;;GAKG;AACH,qBAAa,qCAAsC,YAAW,aAAa;IACpE,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;CAIzD"}
1
+ {"version":3,"file":"ResourceActionPermissionRuleCollector.d.mts","sourceRoot":"","sources":["../../../src/rules/collectors/ResourceActionPermissionRuleCollector.mts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAG7F;;;;;GAKG;AACH,qBAAa,qCAAsC,YAAW,aAAa;IACpE,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;CAIzD"}
@@ -3,7 +3,7 @@
3
3
  import { HasPermission } from "../HasPermission.mjs";
4
4
  /**
5
5
  * Rule collector that emits a single `HasPermission` rule for the
6
- * `{resource}.perm:{action}` permission string. Use when the effective
6
+ * `{resource.raw}.perm:{action}` permission string. Use when the effective
7
7
  * permission is encoded directly into the token's permission attribute rather
8
8
  * than derived from scopes.
9
9
  */
@@ -18,7 +18,11 @@ export interface ResourceActionScopeRuleCollectorConfig {
18
18
  /**
19
19
  * The claim whose presence says the token asserted scopes (#219). Defaults
20
20
  * to `scope`; set it to what `PayloadScopeCollector` reads (`scp` for Okta)
21
- * so the two agree about which tokens are scopeless.
21
+ * so the two look at the same claim — each keeps its own option, and
22
+ * nothing checks that both were given the same name. Only presence is
23
+ * checked here: a claim holding no usable scope list (`""`, a number)
24
+ * yields no scopes from `PayloadScopeCollector` but still counts as scoped
25
+ * under `scopeless: "skip"`.
22
26
  */
23
27
  claim?: string;
24
28
  }