@cullet/erp-core 1.0.5 → 1.0.7

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 (143) hide show
  1. package/dist/gate-engine-registry.js.map +1 -1
  2. package/dist/gate-types.d.ts +1 -1
  3. package/dist/gate-v1-payload.schema.js +43 -0
  4. package/dist/gate-v1-payload.schema.js.map +1 -1
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.js +9 -3
  7. package/dist/index.js.map +1 -1
  8. package/dist/outcome.js.map +1 -1
  9. package/dist/policies/engines/v1/gate/index.d.ts +4 -0
  10. package/dist/policies/engines/v1/gate/index.js.map +1 -1
  11. package/dist/policy-service.js +14 -11
  12. package/dist/policy-service.js.map +1 -1
  13. package/dist/validation-code.js +43 -9
  14. package/dist/validation-code.js.map +1 -1
  15. package/dist/validation-error.d.ts +15 -1
  16. package/dist/validation-error.js.map +1 -1
  17. package/meta.json +2 -2
  18. package/package.json +1 -1
  19. package/src/core/application/commands/command.ts +4 -4
  20. package/src/core/application/commands/index.ts +2 -2
  21. package/src/core/application/commands/requested-by.ts +3 -3
  22. package/src/core/application/index.ts +8 -8
  23. package/src/core/application/policy-error-mapper.ts +2 -2
  24. package/src/core/application/ports/index.ts +10 -6
  25. package/src/core/application/ports/policy-port.ts +6 -3
  26. package/src/core/application/ports/temporal-repository.port.ts +2 -2
  27. package/src/core/application/queries/index.ts +2 -2
  28. package/src/core/application/queries/query.ts +4 -4
  29. package/src/core/application/temporal/index.ts +2 -2
  30. package/src/core/application/temporal/temporal-context.ts +2 -2
  31. package/src/core/application/temporal/temporal-use-case.ts +4 -4
  32. package/src/core/application/use-case.ts +3 -3
  33. package/src/core/config/core-config.instance.ts +2 -2
  34. package/src/core/config/core-config.ts +3 -3
  35. package/src/core/config/index.ts +8 -5
  36. package/src/core/config/policy-reporter.ts +3 -3
  37. package/src/core/config/silent-policy-reporter.ts +1 -1
  38. package/src/core/domain/entity.ts +11 -5
  39. package/src/core/domain/rulesets/entity-ruleset.contracts.ts +2 -2
  40. package/src/core/domain/rulesets/ruleset-registry.ts +2 -2
  41. package/src/core/domain/rulesets/value-object-ruleset.contracts.ts +2 -2
  42. package/src/core/domain/temporal/index.ts +4 -4
  43. package/src/core/domain/temporal/temporal-range.ts +2 -2
  44. package/src/core/domain/temporal/temporal-snapshot.ts +3 -3
  45. package/src/core/domain/temporal/transaction-time.ts +3 -3
  46. package/src/core/domain/temporal/valid-time.ts +3 -3
  47. package/src/core/domain/value-object.ts +3 -3
  48. package/src/core/errors/app-error.ts +6 -2
  49. package/src/core/errors/authentication-error.ts +3 -3
  50. package/src/core/errors/authorization-error.ts +3 -3
  51. package/src/core/errors/business-rule-violation-error.ts +3 -3
  52. package/src/core/errors/conflict-error.ts +3 -3
  53. package/src/core/errors/idempotency-error.ts +3 -3
  54. package/src/core/errors/index.ts +23 -23
  55. package/src/core/errors/integration-error.ts +3 -3
  56. package/src/core/errors/legacy-incompatible-error.ts +3 -3
  57. package/src/core/errors/not-found-error.ts +3 -3
  58. package/src/core/errors/serialization-error.ts +3 -3
  59. package/src/core/errors/temporal-error.ts +3 -3
  60. package/src/core/errors/unexpected-error.ts +3 -3
  61. package/src/core/errors/utils/index.ts +2 -1
  62. package/src/core/errors/utils/json-safe.ts +25 -7
  63. package/src/core/errors/validation-error.ts +5 -5
  64. package/src/core/exceptions/business-rule-violation-exception.ts +1 -1
  65. package/src/core/exceptions/entity-not-found-exception.ts +1 -1
  66. package/src/core/exceptions/invalid-state-transition-exception.ts +1 -1
  67. package/src/core/exceptions/invariant-violation-exception.ts +1 -1
  68. package/src/core/exceptions/validation-exception.ts +3 -3
  69. package/src/core/index.ts +7 -7
  70. package/src/core/policies/asof/asof.ts +4 -4
  71. package/src/core/policies/asof/index.ts +2 -2
  72. package/src/core/policies/catalog/catalog.instance.ts +3 -3
  73. package/src/core/policies/catalog/index.ts +6 -6
  74. package/src/core/policies/catalog/policy-catalog-entry.ts +3 -3
  75. package/src/core/policies/catalog/policy-catalog.ts +3 -3
  76. package/src/core/policies/catalog/policy-key.ts +1 -1
  77. package/src/core/policies/context/context-builder.ts +5 -5
  78. package/src/core/policies/context/context-registry.instance.ts +3 -3
  79. package/src/core/policies/context/context-registry.ts +2 -2
  80. package/src/core/policies/context/context-resolver.ts +2 -2
  81. package/src/core/policies/context/context-seed.ts +2 -2
  82. package/src/core/policies/context/index.ts +9 -9
  83. package/src/core/policies/context/path.ts +1 -1
  84. package/src/core/policies/defs/in-memory-policy-definition-repo.ts +3 -3
  85. package/src/core/policies/defs/index.ts +8 -8
  86. package/src/core/policies/defs/policy-definition-repository.ts +1 -1
  87. package/src/core/policies/defs/policy-definition.ts +6 -6
  88. package/src/core/policies/defs/policy-payload.contracts.ts +1 -1
  89. package/src/core/policies/defs/policy-scope.ts +2 -2
  90. package/src/core/policies/defs/policy-semver.ts +12 -5
  91. package/src/core/policies/engines/compute-engine-registry.ts +9 -6
  92. package/src/core/policies/engines/compute-evaluator-registry.ts +1 -1
  93. package/src/core/policies/engines/compute-payload.ts +1 -1
  94. package/src/core/policies/engines/compute-registry.ts +7 -7
  95. package/src/core/policies/engines/compute-types.ts +4 -4
  96. package/src/core/policies/engines/condition-evaluator-reporter.ts +2 -0
  97. package/src/core/policies/engines/gate-engine-registry.ts +3 -3
  98. package/src/core/policies/engines/gate-payload.ts +1 -1
  99. package/src/core/policies/engines/gate-types.ts +3 -3
  100. package/src/core/policies/engines/index.ts +14 -14
  101. package/src/core/policies/engines/parse-compute-payload.ts +4 -4
  102. package/src/core/policies/engines/parse-gate-payload.ts +4 -4
  103. package/src/core/policies/engines/v1/compute/compute-engine-v1.ts +6 -6
  104. package/src/core/policies/engines/v1/compute/compute-payload.schema.ts +3 -3
  105. package/src/core/policies/engines/v1/compute/index.ts +4 -4
  106. package/src/core/policies/engines/v1/compute/resolve-decision-table-v1.ts +4 -4
  107. package/src/core/policies/engines/v1/condition-evaluator.ts +90 -6
  108. package/src/core/policies/engines/v1/condition-schema.ts +1 -1
  109. package/src/core/policies/engines/v1/gate/gate-engine-v1.ts +7 -7
  110. package/src/core/policies/engines/v1/gate/gate-types-v1.ts +1 -1
  111. package/src/core/policies/engines/v1/gate/gate-v1-payload.schema.ts +3 -3
  112. package/src/core/policies/engines/v1/gate/index.ts +4 -4
  113. package/src/core/policies/engines/v1/index.ts +3 -3
  114. package/src/core/policies/index.ts +30 -23
  115. package/src/core/policies/package/policy-package.ts +3 -3
  116. package/src/core/policies/policy-ids.ts +3 -3
  117. package/src/core/policies/resolver/index.ts +1 -1
  118. package/src/core/policies/resolver/policy-resolver.ts +4 -4
  119. package/src/core/policies/service/index.ts +3 -3
  120. package/src/core/policies/service/policy-evaluation-error.ts +1 -1
  121. package/src/core/policies/service/policy-service.ts +21 -14
  122. package/src/core/policies/utils/date.ts +1 -1
  123. package/src/core/policies/utils/hash.ts +23 -11
  124. package/src/core/policies/utils/index.ts +3 -3
  125. package/src/core/policies/utils/result.ts +1 -1
  126. package/src/core/result/outcome.ts +1 -1
  127. package/src/core/shared/aggregate-version.ts +1 -1
  128. package/src/core/shared/hashing.ts +33 -4
  129. package/src/core/shared/immutable.ts +13 -2
  130. package/src/core/shared/temporal-guards.ts +1 -1
  131. package/src/core/versioning/domain-event-contracts.ts +5 -5
  132. package/src/examples/rulesets/entity/order-creation-rules-v1.ts +2 -2
  133. package/src/examples/rulesets/entity/order-invariants-v1.ts +2 -2
  134. package/src/examples/rulesets/entity/order-invariants-v2.ts +3 -3
  135. package/src/examples/rulesets/entity/order.ts +1 -1
  136. package/src/examples/rulesets/value-object/cpf-rules-v1.ts +1 -1
  137. package/src/examples/rulesets/value-object/cpf-rules-v2.ts +2 -2
  138. package/src/examples/rulesets/value-object/cpf.ts +1 -1
  139. package/src/examples/rulesets/value-object/customer.ts +3 -3
  140. package/src/examples/rulesets/value-object/person-name-rules-v1.ts +1 -1
  141. package/src/examples/rulesets/value-object/person-name-rules-v2.ts +2 -2
  142. package/src/examples/rulesets/value-object/person-name.ts +1 -1
  143. package/src/version.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"outcome.js","names":[],"sources":["../src/core/result/outcome.ts"],"sourcesContent":["// core/domain/outcome.ts\n\nimport { InvariantViolationException } from \"../exceptions/invariant-violation-exception\";\n\n/**\n * Outcome — Business decision abstraction.\n *\n * Represents the semantic result of a domain decision, policy evaluation,\n * or business rule. NOT for technical success/failure — use Result for that.\n *\n * Mental model:\n * \"What was the business decision?\"\n * NOT \"Did the operation succeed?\"\n *\n * The status axis represents valid business outcomes (APPROVED, REJECTED,\n * ALLOW, DENY, NO_OP, etc.), never technical Ok/Err.\n *\n * @typeParam S - Union of valid status literals for this outcome\n * @typeParam D - Shape of the decision data carried by this outcome\n */\nexport class Outcome<S extends string, D = undefined> {\n readonly status: S;\n readonly data: D;\n readonly reason: string | undefined;\n readonly metadata: Readonly<Record<string, unknown>>;\n\n private constructor(\n status: S,\n data: D,\n reason: string | undefined,\n metadata: Readonly<Record<string, unknown>>,\n ) {\n this.status = status;\n this.data = data;\n this.reason = reason;\n this.metadata = metadata;\n Object.freeze(this);\n }\n\n // ─── Generic factory ────────────────────────────────────────────────\n\n static of<S extends string, D = undefined>(\n status: S,\n data: D,\n reason?: string,\n metadata?: Record<string, unknown>,\n ): Outcome<S, D> {\n return new Outcome(\n status,\n data,\n reason,\n Object.freeze({ ...metadata }),\n );\n }\n\n // ─── Convenience factories for common business statuses ─────────────\n\n static approved<D = undefined>(\n data: D,\n reason?: string,\n ): Outcome<\"APPROVED\", D> {\n return new Outcome(\"APPROVED\", data, reason, Object.freeze({}));\n }\n\n static rejected<D = undefined>(\n data: D,\n reason: string,\n ): Outcome<\"REJECTED\", D> {\n return new Outcome(\"REJECTED\", data, reason, Object.freeze({}));\n }\n\n static noOp<D = undefined>(data: D, reason?: string): Outcome<\"NO_OP\", D> {\n return new Outcome(\"NO_OP\", data, reason, Object.freeze({}));\n }\n\n static deferred<D = undefined>(\n data: D,\n reason: string,\n ): Outcome<\"DEFERRED\", D> {\n return new Outcome(\"DEFERRED\", data, reason, Object.freeze({}));\n }\n\n static requiresReview<D = undefined>(\n data: D,\n reason: string,\n ): Outcome<\"REQUIRES_REVIEW\", D> {\n return new Outcome(\"REQUIRES_REVIEW\", data, reason, Object.freeze({}));\n }\n\n // ─── Type narrowing ────────────────────────────────────────────────\n\n /**\n * Narrows this Outcome to a specific status.\n *\n * @example\n * if (outcome.is('DENY')) {\n * outcome.data.violations // TS knows status is 'DENY'\n * }\n */\n is<T extends S>(status: T): this is Outcome<T, D> {\n return (this.status as string) === status;\n }\n\n // ─── Exhaustive match ──────────────────────────────────────────────\n\n /**\n * Exhaustive pattern match over all possible statuses.\n * TypeScript enforces that every status has a handler.\n *\n * @example\n * outcome.match({\n * ALLOW: (o) => handleAllow(o.data),\n * DENY: (o) => handleDeny(o.data.violations),\n * })\n */\n match<THandlers extends { [K in S]: (outcome: Outcome<K, D>) => unknown }>(\n handlers: THandlers,\n ): ReturnType<THandlers[S]> {\n const handler = (\n handlers as Partial<Record<string, (o: unknown) => unknown>>\n )[this.status];\n\n if (typeof handler !== \"function\") {\n const availableStatuses = Object.keys(handlers);\n throw new InvariantViolationException(\n `Outcome.match is missing a handler for runtime status \"${this.status}\". Available handlers: ${availableStatuses.join(\", \") || \"(none)\"}`,\n );\n }\n\n return handler(this) as ReturnType<THandlers[S]>;\n }\n\n // ─── Derived copies ────────────────────────────────────────────────\n\n withMetadata(extra: Record<string, unknown>): Outcome<S, D> {\n return new Outcome(\n this.status,\n this.data,\n this.reason,\n Object.freeze({ ...this.metadata, ...extra }),\n );\n }\n\n withReason(reason: string): Outcome<S, D> {\n return new Outcome(this.status, this.data, reason, this.metadata);\n }\n\n // ─── Debug ─────────────────────────────────────────────────────────\n\n toString(): string {\n const parts: string[] = [this.status];\n if (this.reason) parts.push(`reason=\"${this.reason}\"`);\n return `Outcome(${parts.join(\", \")})`;\n }\n}\n\n/** Common business outcome statuses. Extend per domain as needed. */\nexport type CommonOutcomeStatus =\n | \"APPROVED\"\n | \"REJECTED\"\n | \"NO_OP\"\n | \"DEFERRED\"\n | \"REQUIRES_REVIEW\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,IAAa,UAAb,MAAa,QAAyC;CAMlD,YACI,QACA,MACA,QACA,UACF;EACE,KAAK,SAAS;EACd,KAAK,OAAO;EACZ,KAAK,SAAS;EACd,KAAK,WAAW;EAChB,OAAO,OAAO,IAAI;CACtB;CAIA,OAAO,GACH,QACA,MACA,QACA,UACa;EACb,OAAO,IAAI,QACP,QACA,MACA,QACA,OAAO,OAAO,EAAE,GAAG,SAAS,CAAC,CACjC;CACJ;CAIA,OAAO,SACH,MACA,QACsB;EACtB,OAAO,IAAI,QAAQ,YAAY,MAAM,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CAClE;CAEA,OAAO,SACH,MACA,QACsB;EACtB,OAAO,IAAI,QAAQ,YAAY,MAAM,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CAClE;CAEA,OAAO,KAAoB,MAAS,QAAsC;EACtE,OAAO,IAAI,QAAQ,SAAS,MAAM,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CAC/D;CAEA,OAAO,SACH,MACA,QACsB;EACtB,OAAO,IAAI,QAAQ,YAAY,MAAM,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CAClE;CAEA,OAAO,eACH,MACA,QAC6B;EAC7B,OAAO,IAAI,QAAQ,mBAAmB,MAAM,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CACzE;;;;;;;;;CAYA,GAAgB,QAAkC;EAC9C,OAAQ,KAAK,WAAsB;CACvC;;;;;;;;;;;CAcA,MACI,UACwB;EACxB,MAAM,UACF,SACF,KAAK;EAEP,IAAI,OAAO,YAAY,YAAY;GAC/B,MAAM,oBAAoB,OAAO,KAAK,QAAQ;GAC9C,MAAM,IAAI,4BACN,0DAA0D,KAAK,OAAO,yBAAyB,kBAAkB,KAAK,IAAI,KAAK,UACnI;EACJ;EAEA,OAAO,QAAQ,IAAI;CACvB;CAIA,aAAa,OAA+C;EACxD,OAAO,IAAI,QACP,KAAK,QACL,KAAK,MACL,KAAK,QACL,OAAO,OAAO;GAAE,GAAG,KAAK;GAAU,GAAG;EAAM,CAAC,CAChD;CACJ;CAEA,WAAW,QAA+B;EACtC,OAAO,IAAI,QAAQ,KAAK,QAAQ,KAAK,MAAM,QAAQ,KAAK,QAAQ;CACpE;CAIA,WAAmB;EACf,MAAM,QAAkB,CAAC,KAAK,MAAM;EACpC,IAAI,KAAK,QAAQ,MAAM,KAAK,WAAW,KAAK,OAAO,EAAE;EACrD,OAAO,WAAW,MAAM,KAAK,IAAI,EAAE;CACvC;AACJ"}
1
+ {"version":3,"file":"outcome.js","names":[],"sources":["../src/core/result/outcome.ts"],"sourcesContent":["// core/domain/outcome.ts\n\nimport { InvariantViolationException } from \"../exceptions/invariant-violation-exception.js\";\n\n/**\n * Outcome — Business decision abstraction.\n *\n * Represents the semantic result of a domain decision, policy evaluation,\n * or business rule. NOT for technical success/failure — use Result for that.\n *\n * Mental model:\n * \"What was the business decision?\"\n * NOT \"Did the operation succeed?\"\n *\n * The status axis represents valid business outcomes (APPROVED, REJECTED,\n * ALLOW, DENY, NO_OP, etc.), never technical Ok/Err.\n *\n * @typeParam S - Union of valid status literals for this outcome\n * @typeParam D - Shape of the decision data carried by this outcome\n */\nexport class Outcome<S extends string, D = undefined> {\n readonly status: S;\n readonly data: D;\n readonly reason: string | undefined;\n readonly metadata: Readonly<Record<string, unknown>>;\n\n private constructor(\n status: S,\n data: D,\n reason: string | undefined,\n metadata: Readonly<Record<string, unknown>>,\n ) {\n this.status = status;\n this.data = data;\n this.reason = reason;\n this.metadata = metadata;\n Object.freeze(this);\n }\n\n // ─── Generic factory ────────────────────────────────────────────────\n\n static of<S extends string, D = undefined>(\n status: S,\n data: D,\n reason?: string,\n metadata?: Record<string, unknown>,\n ): Outcome<S, D> {\n return new Outcome(\n status,\n data,\n reason,\n Object.freeze({ ...metadata }),\n );\n }\n\n // ─── Convenience factories for common business statuses ─────────────\n\n static approved<D = undefined>(\n data: D,\n reason?: string,\n ): Outcome<\"APPROVED\", D> {\n return new Outcome(\"APPROVED\", data, reason, Object.freeze({}));\n }\n\n static rejected<D = undefined>(\n data: D,\n reason: string,\n ): Outcome<\"REJECTED\", D> {\n return new Outcome(\"REJECTED\", data, reason, Object.freeze({}));\n }\n\n static noOp<D = undefined>(data: D, reason?: string): Outcome<\"NO_OP\", D> {\n return new Outcome(\"NO_OP\", data, reason, Object.freeze({}));\n }\n\n static deferred<D = undefined>(\n data: D,\n reason: string,\n ): Outcome<\"DEFERRED\", D> {\n return new Outcome(\"DEFERRED\", data, reason, Object.freeze({}));\n }\n\n static requiresReview<D = undefined>(\n data: D,\n reason: string,\n ): Outcome<\"REQUIRES_REVIEW\", D> {\n return new Outcome(\"REQUIRES_REVIEW\", data, reason, Object.freeze({}));\n }\n\n // ─── Type narrowing ────────────────────────────────────────────────\n\n /**\n * Narrows this Outcome to a specific status.\n *\n * @example\n * if (outcome.is('DENY')) {\n * outcome.data.violations // TS knows status is 'DENY'\n * }\n */\n is<T extends S>(status: T): this is Outcome<T, D> {\n return (this.status as string) === status;\n }\n\n // ─── Exhaustive match ──────────────────────────────────────────────\n\n /**\n * Exhaustive pattern match over all possible statuses.\n * TypeScript enforces that every status has a handler.\n *\n * @example\n * outcome.match({\n * ALLOW: (o) => handleAllow(o.data),\n * DENY: (o) => handleDeny(o.data.violations),\n * })\n */\n match<THandlers extends { [K in S]: (outcome: Outcome<K, D>) => unknown }>(\n handlers: THandlers,\n ): ReturnType<THandlers[S]> {\n const handler = (\n handlers as Partial<Record<string, (o: unknown) => unknown>>\n )[this.status];\n\n if (typeof handler !== \"function\") {\n const availableStatuses = Object.keys(handlers);\n throw new InvariantViolationException(\n `Outcome.match is missing a handler for runtime status \"${this.status}\". Available handlers: ${availableStatuses.join(\", \") || \"(none)\"}`,\n );\n }\n\n return handler(this) as ReturnType<THandlers[S]>;\n }\n\n // ─── Derived copies ────────────────────────────────────────────────\n\n withMetadata(extra: Record<string, unknown>): Outcome<S, D> {\n return new Outcome(\n this.status,\n this.data,\n this.reason,\n Object.freeze({ ...this.metadata, ...extra }),\n );\n }\n\n withReason(reason: string): Outcome<S, D> {\n return new Outcome(this.status, this.data, reason, this.metadata);\n }\n\n // ─── Debug ─────────────────────────────────────────────────────────\n\n toString(): string {\n const parts: string[] = [this.status];\n if (this.reason) parts.push(`reason=\"${this.reason}\"`);\n return `Outcome(${parts.join(\", \")})`;\n }\n}\n\n/** Common business outcome statuses. Extend per domain as needed. */\nexport type CommonOutcomeStatus =\n | \"APPROVED\"\n | \"REJECTED\"\n | \"NO_OP\"\n | \"DEFERRED\"\n | \"REQUIRES_REVIEW\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,IAAa,UAAb,MAAa,QAAyC;CAMlD,YACI,QACA,MACA,QACA,UACF;EACE,KAAK,SAAS;EACd,KAAK,OAAO;EACZ,KAAK,SAAS;EACd,KAAK,WAAW;EAChB,OAAO,OAAO,IAAI;CACtB;CAIA,OAAO,GACH,QACA,MACA,QACA,UACa;EACb,OAAO,IAAI,QACP,QACA,MACA,QACA,OAAO,OAAO,EAAE,GAAG,SAAS,CAAC,CACjC;CACJ;CAIA,OAAO,SACH,MACA,QACsB;EACtB,OAAO,IAAI,QAAQ,YAAY,MAAM,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CAClE;CAEA,OAAO,SACH,MACA,QACsB;EACtB,OAAO,IAAI,QAAQ,YAAY,MAAM,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CAClE;CAEA,OAAO,KAAoB,MAAS,QAAsC;EACtE,OAAO,IAAI,QAAQ,SAAS,MAAM,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CAC/D;CAEA,OAAO,SACH,MACA,QACsB;EACtB,OAAO,IAAI,QAAQ,YAAY,MAAM,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CAClE;CAEA,OAAO,eACH,MACA,QAC6B;EAC7B,OAAO,IAAI,QAAQ,mBAAmB,MAAM,QAAQ,OAAO,OAAO,CAAC,CAAC,CAAC;CACzE;;;;;;;;;CAYA,GAAgB,QAAkC;EAC9C,OAAQ,KAAK,WAAsB;CACvC;;;;;;;;;;;CAcA,MACI,UACwB;EACxB,MAAM,UACF,SACF,KAAK;EAEP,IAAI,OAAO,YAAY,YAAY;GAC/B,MAAM,oBAAoB,OAAO,KAAK,QAAQ;GAC9C,MAAM,IAAI,4BACN,0DAA0D,KAAK,OAAO,yBAAyB,kBAAkB,KAAK,IAAI,KAAK,UACnI;EACJ;EAEA,OAAO,QAAQ,IAAI;CACvB;CAIA,aAAa,OAA+C;EACxD,OAAO,IAAI,QACP,KAAK,QACL,KAAK,MACL,KAAK,QACL,OAAO,OAAO;GAAE,GAAG,KAAK;GAAU,GAAG;EAAM,CAAC,CAChD;CACJ;CAEA,WAAW,QAA+B;EACtC,OAAO,IAAI,QAAQ,KAAK,QAAQ,KAAK,MAAM,QAAQ,KAAK,QAAQ;CACpE;CAIA,WAAmB;EACf,MAAM,QAAkB,CAAC,KAAK,MAAM;EACpC,IAAI,KAAK,QAAQ,MAAM,KAAK,WAAW,KAAK,OAAO,EAAE;EACrD,OAAO,WAAW,MAAM,KAAK,IAAI,EAAE;CACvC;AACJ"}
@@ -26,6 +26,8 @@ declare class ConditionEvaluatorV1 {
26
26
  private static buildNullishNumericOperandMessage;
27
27
  private static buildNullishDateOperandMessage;
28
28
  private static buildInvalidDateOperandMessage;
29
+ private static buildInvalidNumericOperandMessage;
30
+ private static buildInvalidSetOperandMessage;
29
31
  private static buildEmptyOrConditionMessage;
30
32
  private static buildEmptyAndConditionMessage;
31
33
  private static parseComparableDate;
@@ -33,6 +35,8 @@ declare class ConditionEvaluatorV1 {
33
35
  private buildReport;
34
36
  private conditionEvalErr;
35
37
  private reportDateOperandError;
38
+ private reportInvalidNumericOperand;
39
+ private reportInvalidSetOperand;
36
40
  private evaluateDateRelationalNode;
37
41
  private evaluateOperator;
38
42
  private evaluateNumericRelationalNode;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/core/policies/engines/v1/gate/gate-engine-v1.ts"],"sourcesContent":["import { type CoreConfig, coreConfig } from \"../../../../config\";\nimport { Outcome } from \"../../../../result/outcome\";\nimport { Result } from \"../../../../result/result\";\n\nimport {\n ConditionEvaluatorV1,\n type TracedConditionEvaluation,\n} from \"../condition-evaluator\";\nimport type { ConditionLeafNode, ConditionNode } from \"../condition-types\";\nimport type { GatePayload } from \"../../gate-payload\";\nimport type {\n GateOutcome,\n GateStatus,\n GateTraceLeafSnapshot,\n GateTraceNodeSnapshot,\n PolicyContext,\n PolicyViolation,\n VersionedGateEngine,\n} from \"../../gate-types\";\n\n// ─── Gate engine v1 ─────────────────────────────────────────────────────────\n\nexport class GateEngineV1 implements VersionedGateEngine {\n public readonly version = 1;\n private readonly coreConfig: CoreConfig;\n\n constructor(params: { readonly coreConfig?: CoreConfig } = {}) {\n this.coreConfig = params.coreConfig ?? coreConfig;\n }\n\n private allow(): Result<GateOutcome, string> {\n return Result.ok(Outcome.of(\"ALLOW\", { violations: [] }));\n }\n\n private deny(violation: PolicyViolation): Result<GateOutcome, string> {\n return Result.ok(\n Outcome.of(\"DENY\", {\n violations: [violation],\n }),\n );\n }\n\n private outcomeFromStatus(\n status: GateStatus,\n violation: PolicyViolation,\n ): Result<GateOutcome, string> {\n return status === \"ALLOW\" ? this.allow() : this.deny(violation);\n }\n\n private isLeafNode(node: ConditionNode): node is ConditionLeafNode {\n return \"field\" in node && \"op\" in node;\n }\n\n private toLeafSnapshot(node: ConditionLeafNode): GateTraceLeafSnapshot {\n return {\n kind: \"LEAF\",\n field: node.field,\n op: node.op,\n ...(node.allowNull === true ? { allowNull: true } : {}),\n };\n }\n\n private toNodeSnapshot(node: ConditionNode): GateTraceNodeSnapshot {\n if (this.isLeafNode(node)) {\n return this.toLeafSnapshot(node);\n }\n\n if (\"and\" in node) {\n return {\n kind: \"AND\",\n childCount: node.and.length,\n };\n }\n\n if (\"or\" in node) {\n return {\n kind: \"OR\",\n childCount: node.or.length,\n };\n }\n\n return {\n kind: \"NOT\",\n };\n }\n\n private buildDenyViolation(\n conditionResult: TracedConditionEvaluation,\n ): PolicyViolation {\n return {\n code: \"DENY_CONDITION_MET\",\n message: `Gate denied at ${conditionResult.trace.conditionPath}`,\n trace: {\n conditionPath: conditionResult.trace.conditionPath,\n decisiveNode: this.toNodeSnapshot(\n conditionResult.trace.decisiveNode,\n ),\n lastEvaluatedLeaf: this.toLeafSnapshot(\n conditionResult.trace.lastEvaluatedLeaf,\n ),\n lastEvaluatedLeafPath:\n conditionResult.trace.lastEvaluatedLeafPath,\n lastEvaluatedLeafResult:\n conditionResult.trace.lastEvaluatedLeafResult,\n field: conditionResult.trace.lastEvaluatedLeaf.field,\n op: conditionResult.trace.lastEvaluatedLeaf.op,\n },\n };\n }\n\n private normalizePayload(payload: GatePayload): {\n readonly allowIf: ConditionNode;\n readonly defaultOutcome: \"ALLOW\" | \"DENY\";\n } {\n if (\"condition\" in payload) {\n return {\n allowIf: payload.condition,\n defaultOutcome: \"DENY\",\n };\n }\n\n return payload;\n }\n\n /**\n * Evaluates a GATE payload against a context object.\n * Pure function — no side effects.\n *\n * Receives an already-parsed `GatePayload`; the registry is responsible\n * for parsing from raw `unknown` before calling this method.\n * Returns Result for technical failures (condition evaluation errors).\n * The Outcome inside carries the business decision (ALLOW/DENY).\n */\n evaluate(\n payload: GatePayload,\n context: PolicyContext,\n ): Result<GateOutcome, string> {\n const gatePayload = this.normalizePayload(payload);\n const conditionEvaluator = new ConditionEvaluatorV1(\n context,\n this.coreConfig.getConditionEvaluationOptions(this.version),\n );\n\n const isAllowedResult = conditionEvaluator.evaluateWithTrace(\n gatePayload.allowIf,\n );\n if (isAllowedResult.isErr()) {\n return Result.err(isAllowedResult.errorOrNull()!);\n }\n\n const isAllowed = isAllowedResult.getOrNull()!;\n if (isAllowed.matched) {\n return this.allow();\n }\n\n return this.outcomeFromStatus(\n gatePayload.defaultOutcome,\n this.buildDenyViolation(isAllowed),\n );\n }\n}\n"],"mappings":";;;AAsBA,IAAa,eAAb,MAAyD;CAIrD,YAAY,SAA+C,CAAC,GAAG;iBAHrC;EAItB,KAAK,aAAa,OAAO,cAAc;CAC3C;CAEA,QAA6C;EACzC,OAAO,OAAO,GAAG,QAAQ,GAAG,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;CAC5D;CAEA,KAAa,WAAyD;EAClE,OAAO,OAAO,GACV,QAAQ,GAAG,QAAQ,EACf,YAAY,CAAC,SAAS,EAC1B,CAAC,CACL;CACJ;CAEA,kBACI,QACA,WAC2B;EAC3B,OAAO,WAAW,UAAU,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS;CAClE;CAEA,WAAmB,MAAgD;EAC/D,OAAO,WAAW,QAAQ,QAAQ;CACtC;CAEA,eAAuB,MAAgD;EACnE,OAAO;GACH,MAAM;GACN,OAAO,KAAK;GACZ,IAAI,KAAK;GACT,GAAI,KAAK,cAAc,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;EACzD;CACJ;CAEA,eAAuB,MAA4C;EAC/D,IAAI,KAAK,WAAW,IAAI,GACpB,OAAO,KAAK,eAAe,IAAI;EAGnC,IAAI,SAAS,MACT,OAAO;GACH,MAAM;GACN,YAAY,KAAK,IAAI;EACzB;EAGJ,IAAI,QAAQ,MACR,OAAO;GACH,MAAM;GACN,YAAY,KAAK,GAAG;EACxB;EAGJ,OAAO,EACH,MAAM,MACV;CACJ;CAEA,mBACI,iBACe;EACf,OAAO;GACH,MAAM;GACN,SAAS,kBAAkB,gBAAgB,MAAM;GACjD,OAAO;IACH,eAAe,gBAAgB,MAAM;IACrC,cAAc,KAAK,eACf,gBAAgB,MAAM,YAC1B;IACA,mBAAmB,KAAK,eACpB,gBAAgB,MAAM,iBAC1B;IACA,uBACI,gBAAgB,MAAM;IAC1B,yBACI,gBAAgB,MAAM;IAC1B,OAAO,gBAAgB,MAAM,kBAAkB;IAC/C,IAAI,gBAAgB,MAAM,kBAAkB;GAChD;EACJ;CACJ;CAEA,iBAAyB,SAGvB;EACE,IAAI,eAAe,SACf,OAAO;GACH,SAAS,QAAQ;GACjB,gBAAgB;EACpB;EAGJ,OAAO;CACX;;;;;;;;;;CAWA,SACI,SACA,SAC2B;EAC3B,MAAM,cAAc,KAAK,iBAAiB,OAAO;EAMjD,MAAM,kBAAkB,IALO,qBAC3B,SACA,KAAK,WAAW,8BAA8B,KAAK,OAAO,CAGrB,EAAE,kBACvC,YAAY,OAChB;EACA,IAAI,gBAAgB,MAAM,GACtB,OAAO,OAAO,IAAI,gBAAgB,YAAY,CAAE;EAGpD,MAAM,YAAY,gBAAgB,UAAU;EAC5C,IAAI,UAAU,SACV,OAAO,KAAK,MAAM;EAGtB,OAAO,KAAK,kBACR,YAAY,gBACZ,KAAK,mBAAmB,SAAS,CACrC;CACJ;AACJ"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/core/policies/engines/v1/gate/gate-engine-v1.ts"],"sourcesContent":["import { type CoreConfig, coreConfig } from \"../../../../config/index.js\";\nimport { Outcome } from \"../../../../result/outcome.js\";\nimport { Result } from \"../../../../result/result.js\";\n\nimport {\n ConditionEvaluatorV1,\n type TracedConditionEvaluation,\n} from \"../condition-evaluator.js\";\nimport type { ConditionLeafNode, ConditionNode } from \"../condition-types.js\";\nimport type { GatePayload } from \"../../gate-payload.js\";\nimport type {\n GateOutcome,\n GateStatus,\n GateTraceLeafSnapshot,\n GateTraceNodeSnapshot,\n PolicyContext,\n PolicyViolation,\n VersionedGateEngine,\n} from \"../../gate-types.js\";\n\n// ─── Gate engine v1 ─────────────────────────────────────────────────────────\n\nexport class GateEngineV1 implements VersionedGateEngine {\n public readonly version = 1;\n private readonly coreConfig: CoreConfig;\n\n constructor(params: { readonly coreConfig?: CoreConfig } = {}) {\n this.coreConfig = params.coreConfig ?? coreConfig;\n }\n\n private allow(): Result<GateOutcome, string> {\n return Result.ok(Outcome.of(\"ALLOW\", { violations: [] }));\n }\n\n private deny(violation: PolicyViolation): Result<GateOutcome, string> {\n return Result.ok(\n Outcome.of(\"DENY\", {\n violations: [violation],\n }),\n );\n }\n\n private outcomeFromStatus(\n status: GateStatus,\n violation: PolicyViolation,\n ): Result<GateOutcome, string> {\n return status === \"ALLOW\" ? this.allow() : this.deny(violation);\n }\n\n private isLeafNode(node: ConditionNode): node is ConditionLeafNode {\n return \"field\" in node && \"op\" in node;\n }\n\n private toLeafSnapshot(node: ConditionLeafNode): GateTraceLeafSnapshot {\n return {\n kind: \"LEAF\",\n field: node.field,\n op: node.op,\n ...(node.allowNull === true ? { allowNull: true } : {}),\n };\n }\n\n private toNodeSnapshot(node: ConditionNode): GateTraceNodeSnapshot {\n if (this.isLeafNode(node)) {\n return this.toLeafSnapshot(node);\n }\n\n if (\"and\" in node) {\n return {\n kind: \"AND\",\n childCount: node.and.length,\n };\n }\n\n if (\"or\" in node) {\n return {\n kind: \"OR\",\n childCount: node.or.length,\n };\n }\n\n return {\n kind: \"NOT\",\n };\n }\n\n private buildDenyViolation(\n conditionResult: TracedConditionEvaluation,\n ): PolicyViolation {\n return {\n code: \"DENY_CONDITION_MET\",\n message: `Gate denied at ${conditionResult.trace.conditionPath}`,\n trace: {\n conditionPath: conditionResult.trace.conditionPath,\n decisiveNode: this.toNodeSnapshot(\n conditionResult.trace.decisiveNode,\n ),\n lastEvaluatedLeaf: this.toLeafSnapshot(\n conditionResult.trace.lastEvaluatedLeaf,\n ),\n lastEvaluatedLeafPath:\n conditionResult.trace.lastEvaluatedLeafPath,\n lastEvaluatedLeafResult:\n conditionResult.trace.lastEvaluatedLeafResult,\n field: conditionResult.trace.lastEvaluatedLeaf.field,\n op: conditionResult.trace.lastEvaluatedLeaf.op,\n },\n };\n }\n\n private normalizePayload(payload: GatePayload): {\n readonly allowIf: ConditionNode;\n readonly defaultOutcome: \"ALLOW\" | \"DENY\";\n } {\n if (\"condition\" in payload) {\n return {\n allowIf: payload.condition,\n defaultOutcome: \"DENY\",\n };\n }\n\n return payload;\n }\n\n /**\n * Evaluates a GATE payload against a context object.\n * Pure function — no side effects.\n *\n * Receives an already-parsed `GatePayload`; the registry is responsible\n * for parsing from raw `unknown` before calling this method.\n * Returns Result for technical failures (condition evaluation errors).\n * The Outcome inside carries the business decision (ALLOW/DENY).\n */\n evaluate(\n payload: GatePayload,\n context: PolicyContext,\n ): Result<GateOutcome, string> {\n const gatePayload = this.normalizePayload(payload);\n const conditionEvaluator = new ConditionEvaluatorV1(\n context,\n this.coreConfig.getConditionEvaluationOptions(this.version),\n );\n\n const isAllowedResult = conditionEvaluator.evaluateWithTrace(\n gatePayload.allowIf,\n );\n if (isAllowedResult.isErr()) {\n return Result.err(isAllowedResult.errorOrNull()!);\n }\n\n const isAllowed = isAllowedResult.getOrNull()!;\n if (isAllowed.matched) {\n return this.allow();\n }\n\n return this.outcomeFromStatus(\n gatePayload.defaultOutcome,\n this.buildDenyViolation(isAllowed),\n );\n }\n}\n"],"mappings":";;;AAsBA,IAAa,eAAb,MAAyD;CAIrD,YAAY,SAA+C,CAAC,GAAG;iBAHrC;EAItB,KAAK,aAAa,OAAO,cAAc;CAC3C;CAEA,QAA6C;EACzC,OAAO,OAAO,GAAG,QAAQ,GAAG,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;CAC5D;CAEA,KAAa,WAAyD;EAClE,OAAO,OAAO,GACV,QAAQ,GAAG,QAAQ,EACf,YAAY,CAAC,SAAS,EAC1B,CAAC,CACL;CACJ;CAEA,kBACI,QACA,WAC2B;EAC3B,OAAO,WAAW,UAAU,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS;CAClE;CAEA,WAAmB,MAAgD;EAC/D,OAAO,WAAW,QAAQ,QAAQ;CACtC;CAEA,eAAuB,MAAgD;EACnE,OAAO;GACH,MAAM;GACN,OAAO,KAAK;GACZ,IAAI,KAAK;GACT,GAAI,KAAK,cAAc,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;EACzD;CACJ;CAEA,eAAuB,MAA4C;EAC/D,IAAI,KAAK,WAAW,IAAI,GACpB,OAAO,KAAK,eAAe,IAAI;EAGnC,IAAI,SAAS,MACT,OAAO;GACH,MAAM;GACN,YAAY,KAAK,IAAI;EACzB;EAGJ,IAAI,QAAQ,MACR,OAAO;GACH,MAAM;GACN,YAAY,KAAK,GAAG;EACxB;EAGJ,OAAO,EACH,MAAM,MACV;CACJ;CAEA,mBACI,iBACe;EACf,OAAO;GACH,MAAM;GACN,SAAS,kBAAkB,gBAAgB,MAAM;GACjD,OAAO;IACH,eAAe,gBAAgB,MAAM;IACrC,cAAc,KAAK,eACf,gBAAgB,MAAM,YAC1B;IACA,mBAAmB,KAAK,eACpB,gBAAgB,MAAM,iBAC1B;IACA,uBACI,gBAAgB,MAAM;IAC1B,yBACI,gBAAgB,MAAM;IAC1B,OAAO,gBAAgB,MAAM,kBAAkB;IAC/C,IAAI,gBAAgB,MAAM,kBAAkB;GAChD;EACJ;CACJ;CAEA,iBAAyB,SAGvB;EACE,IAAI,eAAe,SACf,OAAO;GACH,SAAS,QAAQ;GACjB,gBAAgB;EACpB;EAGJ,OAAO;CACX;;;;;;;;;;CAWA,SACI,SACA,SAC2B;EAC3B,MAAM,cAAc,KAAK,iBAAiB,OAAO;EAMjD,MAAM,kBAAkB,IALO,qBAC3B,SACA,KAAK,WAAW,8BAA8B,KAAK,OAAO,CAGrB,EAAE,kBACvC,YAAY,OAChB;EACA,IAAI,gBAAgB,MAAM,GACtB,OAAO,OAAO,IAAI,gBAAgB,YAAY,CAAE;EAGpD,MAAM,YAAY,gBAAgB,UAAU;EAC5C,IAAI,UAAU,SACV,OAAO,KAAK,MAAM;EAGtB,OAAO,KAAK,kBACR,YAAY,gBACZ,KAAK,mBAAmB,SAAS,CACrC;CACJ;AACJ"}
@@ -16,7 +16,7 @@ var PolicyHashing = class PolicyHashing {
16
16
  static sha256(input) {
17
17
  return sha256Hex(input);
18
18
  }
19
- static assertHashable(value, path) {
19
+ static assertHashable(value, path, seen) {
20
20
  if (value === null) return;
21
21
  const type = typeof value;
22
22
  if (type === "undefined") throw new TypeError(`canonicalJson does not accept undefined values (at ${path})`);
@@ -27,16 +27,16 @@ var PolicyHashing = class PolicyHashing {
27
27
  if (!isValidDate(value)) throw new TypeError(`canonicalJson does not accept Invalid Date (at ${path})`);
28
28
  return;
29
29
  }
30
- if (Array.isArray(value)) {
31
- value.forEach((item, index) => {
32
- PolicyHashing.assertHashable(item, `${path}[${index}]`);
33
- });
34
- return;
35
- }
36
- for (const [key, nested] of Object.entries(value)) PolicyHashing.assertHashable(nested, `${path}.${key}`);
30
+ if (seen.has(value)) throw new TypeError(`canonicalJson does not accept circular references (at ${path})`);
31
+ seen.add(value);
32
+ if (Array.isArray(value)) value.forEach((item, index) => {
33
+ PolicyHashing.assertHashable(item, `${path}[${index}]`, seen);
34
+ });
35
+ else for (const [key, nested] of Object.entries(value)) PolicyHashing.assertHashable(nested, `${path}.${key}`, seen);
36
+ seen.delete(value);
37
37
  }
38
38
  static canonicalJson(value) {
39
- PolicyHashing.assertHashable(value, "$");
39
+ PolicyHashing.assertHashable(value, "$", /* @__PURE__ */ new WeakSet());
40
40
  return stableStringify(value);
41
41
  }
42
42
  static computePayloadHash(payload, policyKey, policyVersion) {
@@ -345,13 +345,16 @@ var InMemoryPolicyDefinitionRepository = class {
345
345
  //#region src/core/policies/defs/policy-semver.ts
346
346
  const POLICY_SEMVER_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
347
347
  function parseSemver(version) {
348
- const [core, preRelease = null] = version.split("+")[0].split("-");
348
+ const withoutBuild = version.split("+")[0];
349
+ const dashIndex = withoutBuild.indexOf("-");
350
+ const core = dashIndex === -1 ? withoutBuild : withoutBuild.slice(0, dashIndex);
351
+ const preRelease = dashIndex === -1 ? null : withoutBuild.slice(dashIndex + 1);
349
352
  const [major, minor, patch] = core.split(".").map(Number);
350
353
  return {
351
354
  major,
352
355
  minor,
353
356
  patch,
354
- preRelease: preRelease ?? null
357
+ preRelease
355
358
  };
356
359
  }
357
360
  function comparePreRelease(a, b) {