@cullet/erp-core 1.5.0 → 2.0.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 (306) hide show
  1. package/KIT_CONTEXT.md +2 -2
  2. package/dist/abac/index.d.cts +2 -2
  3. package/dist/abac/index.d.ts +2 -2
  4. package/dist/aggregate-version.cjs +14 -0
  5. package/dist/aggregate-version.cjs.map +1 -0
  6. package/dist/aggregate-version.js +9 -0
  7. package/dist/aggregate-version.js.map +1 -0
  8. package/dist/app-error.cjs +8 -1
  9. package/dist/app-error.cjs.map +1 -1
  10. package/dist/app-error.js +8 -1
  11. package/dist/app-error.js.map +1 -1
  12. package/dist/application/index.cjs +8 -4
  13. package/dist/application/index.d.cts +2 -2
  14. package/dist/application/index.d.ts +2 -2
  15. package/dist/application/index.js +1 -2
  16. package/dist/authorization-error.cjs +67 -17
  17. package/dist/authorization-error.cjs.map +1 -1
  18. package/dist/authorization-error.d.cts +6 -2
  19. package/dist/authorization-error.d.ts +6 -2
  20. package/dist/authorization-error.js +50 -18
  21. package/dist/authorization-error.js.map +1 -1
  22. package/dist/authorizer.port.d.cts +18 -3
  23. package/dist/authorizer.port.d.ts +18 -3
  24. package/dist/composite-authorizer.d.cts +63 -10
  25. package/dist/composite-authorizer.d.ts +63 -10
  26. package/dist/condition-evaluator.cjs +115 -184
  27. package/dist/condition-evaluator.cjs.map +1 -1
  28. package/dist/condition-evaluator.js +116 -179
  29. package/dist/condition-evaluator.js.map +1 -1
  30. package/dist/core-config.d.cts +53 -6
  31. package/dist/core-config.d.ts +53 -6
  32. package/dist/decorate.cjs +14 -0
  33. package/dist/decorate.js +9 -0
  34. package/dist/domain/index.cjs +107 -2
  35. package/dist/domain/index.cjs.map +1 -0
  36. package/dist/domain/index.d.cts +25 -1
  37. package/dist/domain/index.d.ts +25 -1
  38. package/dist/domain/index.js +99 -3
  39. package/dist/domain/index.js.map +1 -0
  40. package/dist/domain-event-contracts.cjs +12 -8
  41. package/dist/domain-event-contracts.cjs.map +1 -1
  42. package/dist/domain-event-contracts.d.cts +29 -4
  43. package/dist/domain-event-contracts.d.ts +29 -4
  44. package/dist/domain-event-contracts.js +11 -7
  45. package/dist/domain-event-contracts.js.map +1 -1
  46. package/dist/domain-exception.cjs +2 -1
  47. package/dist/domain-exception.cjs.map +1 -1
  48. package/dist/domain-exception.js +2 -1
  49. package/dist/domain-exception.js.map +1 -1
  50. package/dist/errors/index.cjs +1 -1
  51. package/dist/errors/index.d.cts +1 -1
  52. package/dist/errors/index.d.ts +1 -1
  53. package/dist/errors/index.js +2 -2
  54. package/dist/exceptions/index.cjs +2 -2
  55. package/dist/exceptions/index.d.cts +1 -2
  56. package/dist/exceptions/index.d.ts +1 -2
  57. package/dist/exceptions/index.js +2 -2
  58. package/dist/gate-engine-registry.cjs.map +1 -1
  59. package/dist/gate-engine-registry.d.cts +1 -1
  60. package/dist/gate-engine-registry.d.ts +1 -1
  61. package/dist/gate-engine-registry.js.map +1 -1
  62. package/dist/gate-v1-payload.schema.cjs +11 -6
  63. package/dist/gate-v1-payload.schema.cjs.map +1 -1
  64. package/dist/gate-v1-payload.schema.js +11 -6
  65. package/dist/gate-v1-payload.schema.js.map +1 -1
  66. package/dist/hashing.cjs +1 -1
  67. package/dist/hashing.cjs.map +1 -1
  68. package/dist/hashing.js +2 -2
  69. package/dist/hashing.js.map +1 -1
  70. package/dist/immutable.cjs +25 -12
  71. package/dist/immutable.cjs.map +1 -1
  72. package/dist/immutable.js +24 -11
  73. package/dist/immutable.js.map +1 -1
  74. package/dist/index.cjs +13 -10
  75. package/dist/index.cjs.map +1 -1
  76. package/dist/index.d.cts +9 -10
  77. package/dist/index.d.ts +9 -10
  78. package/dist/index.js +7 -9
  79. package/dist/index.js.map +1 -1
  80. package/dist/invalid-state-transition-exception.cjs +6 -6
  81. package/dist/invalid-state-transition-exception.cjs.map +1 -1
  82. package/dist/invalid-state-transition-exception.js +6 -6
  83. package/dist/invalid-state-transition-exception.js.map +1 -1
  84. package/dist/invariant-violation-exception.cjs +2 -2
  85. package/dist/invariant-violation-exception.cjs.map +1 -1
  86. package/dist/invariant-violation-exception.js +2 -2
  87. package/dist/invariant-violation-exception.js.map +1 -1
  88. package/dist/not-found-error.cjs +6 -4
  89. package/dist/not-found-error.cjs.map +1 -1
  90. package/dist/not-found-error.js +6 -4
  91. package/dist/not-found-error.js.map +1 -1
  92. package/dist/outcome.cjs +5 -5
  93. package/dist/outcome.cjs.map +1 -1
  94. package/dist/outcome.js +5 -5
  95. package/dist/outcome.js.map +1 -1
  96. package/dist/parse-gate-payload.d.cts +1 -1
  97. package/dist/parse-gate-payload.d.ts +1 -1
  98. package/dist/path.d.cts +2 -2
  99. package/dist/path.d.ts +2 -2
  100. package/dist/plugin.cjs +23 -13
  101. package/dist/plugin.cjs.map +1 -1
  102. package/dist/plugin.d.cts +22 -8
  103. package/dist/plugin.d.ts +22 -8
  104. package/dist/plugin.js +23 -13
  105. package/dist/plugin.js.map +1 -1
  106. package/dist/policies/engines/index.d.cts +1 -1
  107. package/dist/policies/engines/index.d.ts +1 -1
  108. package/dist/policies/engines/v1/gate/index.d.cts +3 -15
  109. package/dist/policies/engines/v1/gate/index.d.ts +3 -15
  110. package/dist/policies/index.d.cts +1 -1
  111. package/dist/policies/index.d.ts +1 -1
  112. package/dist/policy-bridge.cjs +30 -2
  113. package/dist/policy-bridge.cjs.map +1 -1
  114. package/dist/policy-bridge.d.cts +18 -0
  115. package/dist/policy-bridge.d.ts +18 -0
  116. package/dist/policy-bridge.js +30 -2
  117. package/dist/policy-bridge.js.map +1 -1
  118. package/dist/policy-service.cjs +40 -46
  119. package/dist/policy-service.cjs.map +1 -1
  120. package/dist/policy-service.d.cts +72 -9
  121. package/dist/policy-service.d.ts +72 -9
  122. package/dist/policy-service.js +42 -48
  123. package/dist/policy-service.js.map +1 -1
  124. package/dist/requested-by.cjs +1 -1
  125. package/dist/requested-by.cjs.map +1 -1
  126. package/dist/requested-by.js +1 -1
  127. package/dist/requested-by.js.map +1 -1
  128. package/dist/result.cjs +29 -1
  129. package/dist/result.cjs.map +1 -1
  130. package/dist/result.d.cts +12 -0
  131. package/dist/result.d.ts +12 -0
  132. package/dist/result.js +29 -1
  133. package/dist/result.js.map +1 -1
  134. package/dist/rule.cjs +94 -24
  135. package/dist/rule.cjs.map +1 -1
  136. package/dist/rule.js +94 -24
  137. package/dist/rule.js.map +1 -1
  138. package/dist/ruleset-registry.cjs +19 -0
  139. package/dist/ruleset-registry.cjs.map +1 -1
  140. package/dist/ruleset-registry.js +19 -0
  141. package/dist/ruleset-registry.js.map +1 -1
  142. package/dist/stable-stringify.cjs +43 -3
  143. package/dist/stable-stringify.cjs.map +1 -1
  144. package/dist/stable-stringify.js +38 -4
  145. package/dist/stable-stringify.js.map +1 -1
  146. package/dist/temporal-snapshot.d.cts +87 -0
  147. package/dist/temporal-snapshot.d.ts +87 -0
  148. package/dist/temporal-use-case.cjs +169 -16
  149. package/dist/temporal-use-case.cjs.map +1 -1
  150. package/dist/temporal-use-case.d.cts +76 -43
  151. package/dist/temporal-use-case.d.ts +76 -43
  152. package/dist/temporal-use-case.js +162 -15
  153. package/dist/temporal-use-case.js.map +1 -1
  154. package/dist/unexpected-error.cjs +4 -2
  155. package/dist/unexpected-error.cjs.map +1 -1
  156. package/dist/unexpected-error.js +4 -2
  157. package/dist/unexpected-error.js.map +1 -1
  158. package/dist/uuid-identifier.cjs +140 -2
  159. package/dist/uuid-identifier.cjs.map +1 -1
  160. package/dist/uuid-identifier.d.cts +26 -7
  161. package/dist/uuid-identifier.d.ts +26 -7
  162. package/dist/uuid-identifier.js +135 -3
  163. package/dist/uuid-identifier.js.map +1 -1
  164. package/dist/uuid.cjs +11 -6
  165. package/dist/uuid.cjs.map +1 -1
  166. package/dist/uuid.js +11 -6
  167. package/dist/uuid.js.map +1 -1
  168. package/dist/validation-code.cjs +9 -0
  169. package/dist/validation-code.cjs.map +1 -1
  170. package/dist/validation-code.d.cts +3 -0
  171. package/dist/validation-code.d.ts +3 -0
  172. package/dist/validation-code.js +9 -0
  173. package/dist/validation-code.js.map +1 -1
  174. package/dist/validation-error.cjs +42 -67
  175. package/dist/validation-error.cjs.map +1 -1
  176. package/dist/validation-error.d.cts +24 -8
  177. package/dist/validation-error.d.ts +24 -8
  178. package/dist/validation-error.js +41 -66
  179. package/dist/validation-error.js.map +1 -1
  180. package/dist/validation-exception.cjs +17 -6
  181. package/dist/validation-exception.cjs.map +1 -1
  182. package/dist/validation-exception.d.cts +33 -9
  183. package/dist/validation-exception.d.ts +33 -9
  184. package/dist/validation-exception.js +17 -6
  185. package/dist/validation-exception.js.map +1 -1
  186. package/dist/validation-field.cjs +3 -0
  187. package/dist/validation-field.cjs.map +1 -1
  188. package/dist/validation-field.d.cts +1 -0
  189. package/dist/validation-field.d.ts +1 -0
  190. package/dist/validation-field.js +3 -0
  191. package/dist/validation-field.js.map +1 -1
  192. package/dist/value-object-ruleset.contracts.d.cts +10 -0
  193. package/dist/value-object-ruleset.contracts.d.ts +10 -0
  194. package/dist/value-object.cjs +12 -2
  195. package/dist/value-object.cjs.map +1 -1
  196. package/dist/value-object.d.cts +16 -0
  197. package/dist/value-object.d.ts +16 -0
  198. package/dist/value-object.js +13 -3
  199. package/dist/value-object.js.map +1 -1
  200. package/dist/version.d.cts +27 -0
  201. package/dist/version.d.ts +27 -0
  202. package/dist/versioning/index.d.cts +2 -2
  203. package/dist/versioning/index.d.ts +2 -2
  204. package/meta.json +3 -2
  205. package/package.json +1 -1
  206. package/src/core/abac/authorizer.ts +60 -10
  207. package/src/core/abac/domain/policy-set.ts +52 -5
  208. package/src/core/abac/domain/rule.ts +28 -16
  209. package/src/core/abac/index.ts +7 -1
  210. package/src/core/application/commands/command.ts +14 -1
  211. package/src/core/application/commands/requested-by.ts +12 -3
  212. package/src/core/application/index.ts +2 -1
  213. package/src/core/application/policy-error-mapper.ts +6 -0
  214. package/src/core/application/ports/index.ts +7 -0
  215. package/src/core/application/ports/temporal-repository.port.ts +35 -2
  216. package/src/core/application/queries/index.ts +1 -1
  217. package/src/core/application/queries/query.ts +19 -2
  218. package/src/core/application/temporal/temporal-use-case.ts +31 -4
  219. package/src/core/application/use-case.ts +44 -7
  220. package/src/core/config/core-config.ts +46 -25
  221. package/src/core/config/index.ts +1 -0
  222. package/src/core/config/policy-reporter.ts +32 -1
  223. package/src/core/domain/entity.ts +50 -7
  224. package/src/core/domain/rulesets/entity-ruleset.contracts.ts +0 -2
  225. package/src/core/domain/rulesets/ruleset-registry.ts +24 -0
  226. package/src/core/domain/rulesets/value-object-ruleset.contracts.ts +1 -7
  227. package/src/core/domain/temporal/half-open-interval.ts +34 -0
  228. package/src/core/domain/temporal/temporal-snapshot.ts +13 -2
  229. package/src/core/domain/temporal/transaction-time.ts +19 -15
  230. package/src/core/domain/temporal/valid-time.ts +20 -15
  231. package/src/core/domain/uuid-identifier.ts +5 -3
  232. package/src/core/domain/value-object.ts +17 -0
  233. package/src/core/errors/authentication-error.ts +5 -31
  234. package/src/core/errors/authorization-error.ts +12 -20
  235. package/src/core/errors/business-rule-violation-error.ts +4 -1
  236. package/src/core/errors/idempotency-error.ts +5 -2
  237. package/src/core/errors/index.ts +4 -0
  238. package/src/core/errors/integration-error.ts +4 -24
  239. package/src/core/errors/legacy-incompatible-error.ts +1 -0
  240. package/src/core/errors/not-found-error.ts +4 -1
  241. package/src/core/errors/temporal-error.ts +22 -20
  242. package/src/core/errors/unexpected-error.ts +5 -1
  243. package/src/core/errors/utils/factory-helpers.ts +70 -0
  244. package/src/core/errors/utils/index.ts +5 -0
  245. package/src/core/errors/utils/json-safe.ts +15 -1
  246. package/src/core/errors/validation-error.ts +4 -1
  247. package/src/core/exceptions/business-rule-violation-exception.ts +2 -1
  248. package/src/core/exceptions/domain-exception.ts +9 -1
  249. package/src/core/exceptions/entity-not-found-exception.ts +5 -1
  250. package/src/core/exceptions/invalid-state-transition-exception.ts +5 -2
  251. package/src/core/exceptions/invariant-violation-exception.ts +2 -2
  252. package/src/core/exceptions/validation-code.ts +14 -0
  253. package/src/core/exceptions/validation-exception.ts +44 -5
  254. package/src/core/exceptions/validation-field.ts +11 -1
  255. package/src/core/plugins/plugin.ts +25 -15
  256. package/src/core/plugins/types.ts +4 -2
  257. package/src/core/policies/asof/asof.ts +12 -0
  258. package/src/core/policies/catalog/policy-catalog-entry.ts +3 -1
  259. package/src/core/policies/catalog/policy-catalog.ts +5 -1
  260. package/src/core/policies/context/context-builder.ts +20 -0
  261. package/src/core/policies/context/context-resolver.ts +5 -0
  262. package/src/core/policies/context/context-seed.ts +11 -0
  263. package/src/core/policies/defs/in-memory-policy-definition-repo.ts +0 -2
  264. package/src/core/policies/engines/parse-gate-payload.ts +9 -0
  265. package/src/core/policies/engines/v1/condition-date-operands.ts +112 -0
  266. package/src/core/policies/engines/v1/condition-evaluator.ts +99 -325
  267. package/src/core/policies/engines/v1/condition-schema.ts +23 -19
  268. package/src/core/policies/engines/v1/condition-types.ts +18 -11
  269. package/src/core/policies/index.ts +4 -6
  270. package/src/core/policies/service/policy-service.ts +46 -35
  271. package/src/core/policies/utils/hash.ts +5 -69
  272. package/src/core/policies/utils/result.ts +1 -1
  273. package/src/core/rbac/access-request.ts +12 -2
  274. package/src/core/rbac/authorizer.ts +8 -1
  275. package/src/core/rbac/domain/role.ts +20 -0
  276. package/src/core/rbac/domain/scope.ts +6 -1
  277. package/src/core/result/index.ts +5 -0
  278. package/src/core/result/outcome.ts +5 -7
  279. package/src/core/result/result.ts +34 -1
  280. package/src/core/shared/hashing.ts +6 -3
  281. package/src/core/shared/immutable.ts +22 -4
  282. package/src/core/shared/stable-stringify.ts +91 -4
  283. package/src/core/shared/uuid.ts +11 -6
  284. package/src/core/versioning/domain-event-contracts.ts +43 -15
  285. package/src/core/versioning/index.ts +1 -0
  286. package/src/core/versioning/version.ts +30 -1
  287. package/src/domain/index.ts +5 -0
  288. package/src/examples/rulesets/entity/order-creation-rules-v1.ts +1 -1
  289. package/src/examples/rulesets/entity/order-invariants-v1.ts +2 -4
  290. package/src/examples/rulesets/entity/order-invariants-v2.ts +2 -4
  291. package/src/examples/rulesets/value-object/cpf-rules-v1.ts +2 -4
  292. package/src/examples/rulesets/value-object/cpf-rules-v2.ts +2 -4
  293. package/src/examples/rulesets/value-object/person-name-rules-v1.ts +2 -4
  294. package/src/examples/rulesets/value-object/person-name-rules-v2.ts +2 -4
  295. package/src/result/index.ts +7 -2
  296. package/src/version.ts +1 -1
  297. package/dist/domain-exception.d.cts +0 -7
  298. package/dist/domain-exception.d.ts +0 -7
  299. package/dist/entity.cjs +0 -122
  300. package/dist/entity.cjs.map +0 -1
  301. package/dist/entity.js +0 -111
  302. package/dist/entity.js.map +0 -1
  303. package/dist/use-case.cjs +0 -92
  304. package/dist/use-case.cjs.map +0 -1
  305. package/dist/use-case.js +0 -87
  306. package/dist/use-case.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"condition-evaluator.js","names":["#initialReporter","#currentReporter","#bridgeToConditionReporter"],"sources":["../src/core/config/silent-policy-reporter.ts","../src/core/config/core-config.ts","../src/core/config/core-config.instance.ts","../src/core/policies/context/path.ts","../src/core/policies/utils/date.ts","../src/core/policies/engines/v1/condition-evaluator.ts"],"sourcesContent":["import type { PolicyReporter } from \"./policy-reporter.js\";\n\nexport class SilentPolicyReporter implements PolicyReporter {\n report(_event: Parameters<PolicyReporter[\"report\"]>[0]): void {}\n}\n","import type {\n ConditionEvaluationOptions,\n ConditionEvaluatorReporter,\n} from \"../policies/engines/condition-evaluator-reporter.js\";\nimport type { PolicyEvent, PolicyReporter } from \"./policy-reporter.js\";\nimport { SilentPolicyReporter } from \"./silent-policy-reporter.js\";\n\nexport interface CoreObservabilityConfig {\n readonly reporter?: PolicyReporter;\n}\n\nexport interface CoreConfigOptions {\n readonly observability?: CoreObservabilityConfig;\n}\n\nfunction reportSafely(\n policyReporter: PolicyReporter,\n event: PolicyEvent,\n): void {\n try {\n policyReporter.report(event);\n } catch {\n // Falhas de telemetria nao podem interromper o fluxo de dominio.\n }\n}\n\n/**\n * Centraliza a configuracao pura do core sem depender de implementacoes\n * concretas de logging, tracing ou report.\n */\nexport class CoreConfig {\n readonly #initialReporter: PolicyReporter;\n #currentReporter: PolicyReporter;\n\n constructor(options: CoreConfigOptions = {}) {\n const reporter =\n options.observability?.reporter ?? new SilentPolicyReporter();\n this.#initialReporter = reporter;\n this.#currentReporter = reporter;\n }\n\n configure(options: CoreConfigOptions): this {\n const reporter = options.observability?.reporter;\n if (reporter) {\n this.#currentReporter = reporter;\n }\n return this;\n }\n\n // Restores the reporter captured at construction time.\n reset(): this {\n this.#currentReporter = this.#initialReporter;\n return this;\n }\n\n getPolicyReporter(): PolicyReporter {\n return this.#currentReporter;\n }\n\n getConditionEvaluationOptions(\n engineVersion: number,\n ): ConditionEvaluationOptions {\n return {\n reporter: this.#bridgeToConditionReporter(this.#currentReporter),\n engineVersion,\n };\n }\n\n #bridgeToConditionReporter(\n policyReporter: PolicyReporter,\n ): ConditionEvaluatorReporter {\n return {\n warn(report) {\n reportSafely(policyReporter, {\n kind: \"condition-eval\",\n ...report,\n } satisfies PolicyEvent);\n },\n error(report) {\n reportSafely(policyReporter, {\n kind: \"condition-eval\",\n ...report,\n } satisfies PolicyEvent);\n },\n };\n }\n}\n","import { CoreConfig } from \"./core-config.js\";\nimport { SilentPolicyReporter } from \"./silent-policy-reporter.js\";\n\n/**\n * Shared instance for the application composition root.\n * Use `new CoreConfig()` for isolated runtimes, tests, or multi-tenant hosts.\n *\n * The default reporter is silent so the core has no runtime logging dependency.\n * Hosts can swap in their own `PolicyReporter` via\n * `coreConfig.configure({ observability: { reporter } })`.\n */\nexport const coreConfig = new CoreConfig({\n observability: { reporter: new SilentPolicyReporter() },\n});\n","/**\n * Utilities for reading/writing values at dot-separated paths\n * in plain objects, e.g. \"installment.dueDate\".\n */\n\nimport { Result } from \"../../result/result.js\";\n\nexport class PolicyContextPath {\n private static readonly FORBIDDEN_SEGMENTS = new Set([\n \"__proto__\",\n \"prototype\",\n \"constructor\",\n ]);\n\n private static resolve(\n obj: Record<string, unknown>,\n path: string,\n ): Result<\n {\n readonly found: boolean;\n readonly value: unknown;\n },\n string\n > {\n const segmentsResult = PolicyContextPath.parseSegments(path);\n if (segmentsResult.isErr()) {\n return Result.err(segmentsResult.errorOrNull()!);\n }\n\n const segments = segmentsResult.getOrNull()!;\n let current: unknown = obj;\n\n for (const segment of segments) {\n if (\n current === null ||\n current === undefined ||\n typeof current !== \"object\"\n ) {\n return Result.ok({ found: false, value: undefined });\n }\n\n const record = current as Record<string, unknown>;\n if (!Object.prototype.hasOwnProperty.call(record, segment)) {\n return Result.ok({ found: false, value: undefined });\n }\n\n current = record[segment];\n }\n\n return Result.ok({ found: true, value: current });\n }\n\n private static parseSegments(\n path: string,\n ): Result<readonly string[], string> {\n if (path.trim().length === 0) {\n return Result.err(\"Path cannot be empty\");\n }\n\n const segments = path.split(\".\");\n if (segments.some((segment) => segment.length === 0)) {\n return Result.err(`Path \"${path}\" contains an empty segment`);\n }\n\n const forbiddenSegment = segments.find((segment) =>\n PolicyContextPath.FORBIDDEN_SEGMENTS.has(segment),\n );\n if (forbiddenSegment !== undefined) {\n return Result.err(\n `Path \"${path}\" contains forbidden segment \"${forbiddenSegment}\"`,\n );\n }\n\n return Result.ok(segments);\n }\n\n private static isPlainRecord(\n value: unknown,\n ): value is Record<string, unknown> {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n }\n\n static getOrAbsent(\n obj: Record<string, unknown>,\n path: string,\n ): Result<unknown, \"absent\"> {\n const resolvedPath = PolicyContextPath.resolve(obj, path);\n if (resolvedPath.isErr()) {\n return Result.err(\"absent\");\n }\n\n const { found, value } = resolvedPath.getOrNull()!;\n if (!found) {\n return Result.err(\"absent\");\n }\n\n return Result.ok(value);\n }\n\n static has(obj: Record<string, unknown>, path: string): boolean {\n const resolvedPath = PolicyContextPath.resolve(obj, path);\n if (resolvedPath.isErr()) {\n return false;\n }\n\n return resolvedPath.getOrNull()!.found;\n }\n\n static set(\n obj: Record<string, unknown>,\n path: string,\n value: unknown,\n ): Result<void, string> {\n const segmentsResult = PolicyContextPath.parseSegments(path);\n if (segmentsResult.isErr()) {\n return Result.err(segmentsResult.errorOrNull()!);\n }\n\n const segments = segmentsResult.getOrNull()!;\n let current: Record<string, unknown> = obj;\n\n for (let i = 0; i < segments.length - 1; i++) {\n const seg = segments[i];\n const next = current[seg];\n\n if (next === undefined) {\n const container = Object.create(null) as Record<\n string,\n unknown\n >;\n current[seg] = container;\n current = container;\n continue;\n }\n\n if (!PolicyContextPath.isPlainRecord(next)) {\n return Result.err(\n `Cannot create nested path \"${path}\" because \"${segments\n .slice(0, i + 1)\n .join(\".\")}\" already contains a non-plain object`,\n );\n }\n\n current = next;\n }\n\n current[segments[segments.length - 1]] = value;\n return Result.ok(undefined);\n }\n}\n","import { isValidDate } from \"../../shared/temporal-guards.js\";\n\nexport class PolicyDateUtils {\n static isValid(value: Date): boolean {\n return isValidDate(value);\n }\n}\n","import { PolicyContextPath } from \"../../context/index.js\";\n// Import the date util directly (not the utils barrel): the barrel re-exports\n// PolicyHashing, whose node:crypto import would needlessly drag a Node-only\n// API into the zod-free ./abac subpath.\nimport { PolicyDateUtils } from \"../../utils/date.js\";\nimport { Result } from \"../../../result/result.js\";\n\nimport type {\n ConditionAndNode,\n ConditionLeafNode,\n ConditionNode,\n ConditionNotNode,\n ConditionOp,\n ConditionOrNode,\n} from \"./condition-types.js\";\nimport type {\n ConditionEvaluationOptions,\n ConditionEvaluationReport,\n} from \"../condition-evaluator-reporter.js\";\nimport type { PolicyContext } from \"../gate-types.js\";\n\nconst CONDITION_EVAL_THROWN_TAG = \"CONDITION_EVAL_THREW\";\nconst NULLISH_NUMERIC_OPERAND_NOT_ALLOWED_TAG =\n \"NULLISH_NUMERIC_OPERAND_NOT_ALLOWED\";\nconst NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG = \"NULLISH_DATE_OPERAND_NOT_ALLOWED\";\nconst INVALID_DATE_OPERAND_TAG = \"INVALID_DATE_OPERAND\";\nconst INVALID_NUMERIC_OPERAND_TAG = \"INVALID_NUMERIC_OPERAND\";\nconst INVALID_SET_OPERAND_TAG = \"INVALID_SET_OPERAND\";\nconst EMPTY_OR_CONDITION_TAG = \"EMPTY_OR_CONDITION\";\nconst EMPTY_AND_CONDITION_TAG = \"EMPTY_AND_CONDITION\";\nconst ISO_8601_UTC_DATE_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/;\n\nexport interface ConditionEvaluationTrace {\n readonly conditionPath: string;\n readonly decisiveNode: ConditionNode;\n readonly lastEvaluatedLeaf: ConditionLeafNode;\n readonly lastEvaluatedLeafPath: string;\n readonly lastEvaluatedLeafResult: boolean;\n}\n\nexport interface TracedConditionEvaluation {\n readonly matched: boolean;\n readonly trace: ConditionEvaluationTrace;\n}\n\ntype RelationalOperator = Extract<ConditionOp, \"gt\" | \"gte\" | \"lt\" | \"lte\">;\n\nexport class ConditionEvaluatorV1 {\n constructor(\n private readonly context: PolicyContext,\n private readonly options: ConditionEvaluationOptions,\n ) {}\n\n private static isLeafNode(node: ConditionNode): node is ConditionLeafNode {\n return \"field\" in node && \"op\" in node;\n }\n\n private static isAndNode(node: ConditionNode): node is ConditionAndNode {\n return \"and\" in node;\n }\n\n private static isOrNode(node: ConditionNode): node is ConditionOrNode {\n return \"or\" in node;\n }\n\n private static isNotNode(node: ConditionNode): node is ConditionNotNode {\n return \"not\" in node;\n }\n\n private static isRelationalOperator(\n op: ConditionOp,\n ): op is RelationalOperator {\n return op === \"gt\" || op === \"gte\" || op === \"lt\" || op === \"lte\";\n }\n\n private static describeError(error: unknown): {\n name: string;\n message: string;\n } {\n if (error instanceof Error) {\n return {\n name: error.name,\n message: error.message,\n };\n }\n\n return {\n name: \"NonErrorThrown\",\n message: String(error),\n };\n }\n\n private static buildNullishNumericOperandMessage(\n node: ConditionLeafNode,\n actual: null | undefined,\n ): string {\n const resolvedValue = actual === null ? \"null\" : \"undefined\";\n\n return `${NULLISH_NUMERIC_OPERAND_NOT_ALLOWED_TAG}: \"${node.field}\" resolved to ${resolvedValue} for numeric operator \"${node.op}\"`;\n }\n\n private static buildNullishDateOperandMessage(\n node: ConditionLeafNode,\n actual: null | undefined,\n ): string {\n const resolvedValue = actual === null ? \"null\" : \"undefined\";\n\n return `${NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG}: \"${node.field}\" resolved to ${resolvedValue} for date comparison operator \"${node.op}\"`;\n }\n\n private static buildInvalidDateOperandMessage(\n node: ConditionLeafNode,\n ): string {\n return `${INVALID_DATE_OPERAND_TAG}: \"${node.field}\" with operator \"${node.op}\" requires Date or ISO 8601 UTC string operands`;\n }\n\n private static buildInvalidNumericOperandMessage(\n node: ConditionLeafNode,\n ): string {\n return `${INVALID_NUMERIC_OPERAND_TAG}: \"${node.field}\" with operator \"${node.op}\" requires numeric operands`;\n }\n\n private static buildInvalidSetOperandMessage(\n node: ConditionLeafNode,\n ): string {\n return `${INVALID_SET_OPERAND_TAG}: \"${node.field}\" with operator \"${node.op}\" requires an array operand`;\n }\n\n private static buildEmptyOrConditionMessage(): string {\n return `${EMPTY_OR_CONDITION_TAG}: OR nodes must contain at least one child condition`;\n }\n\n private static buildEmptyAndConditionMessage(): string {\n return `${EMPTY_AND_CONDITION_TAG}: AND nodes must contain at least one child condition`;\n }\n\n private static parseComparableDate(\n value: unknown,\n ): Result<Date, string> | null {\n if (value instanceof Date) {\n if (!PolicyDateUtils.isValid(value)) {\n return Result.err(\"Invalid Date instance\");\n }\n\n return Result.ok(value);\n }\n\n if (\n typeof value !== \"string\" ||\n !ISO_8601_UTC_DATE_PATTERN.test(value)\n ) {\n return null;\n }\n\n const parsed = new Date(value);\n if (\n !PolicyDateUtils.isValid(parsed) ||\n parsed.toISOString() !== value\n ) {\n return Result.err(\"Invalid ISO 8601 UTC date string\");\n }\n\n return Result.ok(parsed);\n }\n\n private static evaluateRelationalNumbers(\n actual: number,\n op: RelationalOperator,\n expected: number,\n ): boolean {\n switch (op) {\n case \"gt\":\n return actual > expected;\n case \"gte\":\n return actual >= expected;\n case \"lt\":\n return actual < expected;\n case \"lte\":\n return actual <= expected;\n }\n }\n\n private buildReport(params: {\n readonly level: ConditionEvaluationReport[\"level\"];\n readonly tag: ConditionEvaluationReport[\"tag\"];\n readonly message: string;\n readonly details: Readonly<Record<string, unknown>>;\n }): ConditionEvaluationReport {\n return {\n occurredAt: new Date(),\n level: params.level,\n tag: params.tag,\n message: params.message,\n engineVersion: this.options.engineVersion,\n details: params.details,\n };\n }\n\n private conditionEvalErr<TValue>(\n node: ConditionNode,\n error: unknown,\n ): Result<TValue, string> {\n const cause = ConditionEvaluatorV1.describeError(error);\n const message = `${CONDITION_EVAL_THROWN_TAG}: ${cause.name}: ${cause.message}`;\n\n this.options.reporter.error(\n this.buildReport({\n level: \"error\",\n tag: CONDITION_EVAL_THROWN_TAG,\n message,\n details: { node, cause },\n }),\n );\n\n return Result.err(message);\n }\n\n private static containsInvalidDate(value: unknown): boolean {\n if (value instanceof Date) {\n return !PolicyDateUtils.isValid(value);\n }\n if (Array.isArray(value)) {\n return value.some((item) =>\n ConditionEvaluatorV1.containsInvalidDate(item),\n );\n }\n return false;\n }\n\n // Valid Dates become their ISO string so equality/set operators compare\n // instants instead of references; every other value passes through.\n private static normalizeDateOperand(value: unknown): unknown {\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (Array.isArray(value)) {\n return value.map((item) =>\n ConditionEvaluatorV1.normalizeDateOperand(item),\n );\n }\n return value;\n }\n\n private reportDateOperandError(\n node: ConditionLeafNode,\n actual: unknown,\n ): Result<boolean, string> {\n const message =\n ConditionEvaluatorV1.buildInvalidDateOperandMessage(node);\n\n this.options.reporter.error(\n this.buildReport({\n level: \"error\",\n tag: INVALID_DATE_OPERAND_TAG,\n message,\n details: {\n field: node.field,\n op: node.op,\n actual,\n expected: node.value,\n node,\n },\n }),\n );\n\n return Result.err(message);\n }\n\n private reportInvalidNumericOperand(\n node: ConditionLeafNode,\n actual: unknown,\n ): Result<boolean, string> {\n const message =\n ConditionEvaluatorV1.buildInvalidNumericOperandMessage(node);\n\n this.options.reporter.error(\n this.buildReport({\n level: \"error\",\n tag: INVALID_NUMERIC_OPERAND_TAG,\n message,\n details: {\n field: node.field,\n op: node.op,\n actual,\n expected: node.value,\n node,\n },\n }),\n );\n\n return Result.err(message);\n }\n\n private reportInvalidSetOperand(\n node: ConditionLeafNode,\n actual: unknown,\n ): Result<boolean, string> {\n const message =\n ConditionEvaluatorV1.buildInvalidSetOperandMessage(node);\n\n this.options.reporter.error(\n this.buildReport({\n level: \"error\",\n tag: INVALID_SET_OPERAND_TAG,\n message,\n details: {\n field: node.field,\n op: node.op,\n actual,\n expected: node.value,\n node,\n },\n }),\n );\n\n return Result.err(message);\n }\n\n private evaluateDateRelationalNode(\n node: ConditionLeafNode,\n actual: unknown,\n ): Result<boolean, string> | null {\n if (!ConditionEvaluatorV1.isRelationalOperator(node.op)) {\n return null;\n }\n\n const actualDateResult =\n ConditionEvaluatorV1.parseComparableDate(actual);\n const expectedDateResult = ConditionEvaluatorV1.parseComparableDate(\n node.value,\n );\n\n if (actualDateResult === null && expectedDateResult === null) {\n return null;\n }\n\n const allowsNull = node.allowNull === true;\n\n if (actual === null) {\n if (allowsNull) {\n return Result.ok(false);\n }\n\n const message = ConditionEvaluatorV1.buildNullishDateOperandMessage(\n node,\n actual,\n );\n this.options.reporter.error(\n this.buildReport({\n level: \"error\",\n tag: NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG,\n message,\n details: {\n field: node.field,\n op: node.op,\n actual,\n expected: node.value,\n allowNull: allowsNull,\n node,\n },\n }),\n );\n\n return Result.err(message);\n }\n\n if (actual === undefined) {\n const message = ConditionEvaluatorV1.buildNullishDateOperandMessage(\n node,\n actual,\n );\n this.options.reporter.error(\n this.buildReport({\n level: \"error\",\n tag: NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG,\n message,\n details: {\n field: node.field,\n op: node.op,\n actual,\n expected: node.value,\n allowNull: allowsNull,\n node,\n },\n }),\n );\n\n return Result.err(message);\n }\n\n if (\n actualDateResult === null ||\n actualDateResult.isErr() ||\n expectedDateResult === null ||\n expectedDateResult.isErr()\n ) {\n return this.reportDateOperandError(node, actual);\n }\n\n return Result.ok(\n ConditionEvaluatorV1.evaluateRelationalNumbers(\n actualDateResult.getOrNull()!.getTime(),\n node.op,\n expectedDateResult.getOrNull()!.getTime(),\n ),\n );\n }\n\n private evaluateOperator(\n actual: unknown,\n op: ConditionOp,\n expected: unknown,\n ): boolean {\n switch (op) {\n case \"eq\":\n return actual === expected;\n case \"neq\":\n return actual !== expected;\n case \"gt\":\n return (\n typeof actual === \"number\" &&\n typeof expected === \"number\" &&\n ConditionEvaluatorV1.evaluateRelationalNumbers(\n actual,\n op,\n expected,\n )\n );\n case \"gte\":\n return (\n typeof actual === \"number\" &&\n typeof expected === \"number\" &&\n ConditionEvaluatorV1.evaluateRelationalNumbers(\n actual,\n op,\n expected,\n )\n );\n case \"lt\":\n return (\n typeof actual === \"number\" &&\n typeof expected === \"number\" &&\n ConditionEvaluatorV1.evaluateRelationalNumbers(\n actual,\n op,\n expected,\n )\n );\n case \"lte\":\n return (\n typeof actual === \"number\" &&\n typeof expected === \"number\" &&\n ConditionEvaluatorV1.evaluateRelationalNumbers(\n actual,\n op,\n expected,\n )\n );\n case \"in\":\n return Array.isArray(expected) && expected.includes(actual);\n case \"notIn\":\n return Array.isArray(expected) && !expected.includes(actual);\n case \"isNull\":\n return actual === null;\n case \"isNotNull\":\n return actual !== null && actual !== undefined;\n }\n }\n\n private evaluateNumericRelationalNode(\n node: ConditionLeafNode,\n actual: unknown,\n ): Result<boolean, string> {\n const allowsNull = node.allowNull === true;\n if (actual === undefined || (actual === null && !allowsNull)) {\n const message =\n ConditionEvaluatorV1.buildNullishNumericOperandMessage(\n node,\n actual as null | undefined,\n );\n\n this.options.reporter.error(\n this.buildReport({\n level: \"error\",\n tag: NULLISH_NUMERIC_OPERAND_NOT_ALLOWED_TAG,\n message,\n details: {\n field: node.field,\n op: node.op,\n actual,\n expected: node.value,\n allowNull: allowsNull,\n node,\n },\n }),\n );\n\n return Result.err(message);\n }\n\n // null + allowNull: a relational comparison against a missing value\n // never matches.\n if (actual === null) {\n return Result.ok(false);\n }\n\n // Both operands must be numbers. A present but wrong-typed operand is a\n // context/configuration error, surfaced like the date path instead of\n // silently collapsing to \"no match\".\n if (typeof actual !== \"number\" || typeof node.value !== \"number\") {\n return this.reportInvalidNumericOperand(node, actual);\n }\n\n return Result.ok(this.evaluateOperator(actual, node.op, node.value));\n }\n\n private evaluateLeafNode(node: ConditionLeafNode): Result<boolean, string> {\n const actualResult = PolicyContextPath.getOrAbsent(\n this.context,\n node.field,\n );\n if (actualResult.isErr()) {\n this.options.reporter.warn(\n this.buildReport({\n level: \"warn\",\n tag: \"MISSING_CONTEXT_FIELD\",\n message: `MISSING_CONTEXT_FIELD: \"${node.field}\" not found in context`,\n details: { field: node.field, node },\n }),\n );\n\n return Result.err(\n `MISSING_CONTEXT_FIELD: \"${node.field}\" not found in context`,\n );\n }\n\n try {\n const actual = actualResult.getOrThrow();\n if (ConditionEvaluatorV1.isRelationalOperator(node.op)) {\n const dateResult = this.evaluateDateRelationalNode(\n node,\n actual,\n );\n if (dateResult !== null) {\n return dateResult;\n }\n\n return this.evaluateNumericRelationalNode(node, actual);\n }\n\n if (\n (node.op === \"in\" || node.op === \"notIn\") &&\n !Array.isArray(node.value)\n ) {\n return this.reportInvalidSetOperand(node, actual);\n }\n\n if (\n node.op === \"eq\" ||\n node.op === \"neq\" ||\n node.op === \"in\" ||\n node.op === \"notIn\"\n ) {\n // A Date operand would otherwise compare by reference and\n // silently never match. Normalize valid Dates (either side,\n // including set items) to their ISO string; an invalid Date is\n // a context/configuration error, like the relational path.\n if (\n ConditionEvaluatorV1.containsInvalidDate(actual) ||\n ConditionEvaluatorV1.containsInvalidDate(node.value)\n ) {\n return this.reportDateOperandError(node, actual);\n }\n\n return Result.ok(\n this.evaluateOperator(\n ConditionEvaluatorV1.normalizeDateOperand(actual),\n node.op,\n ConditionEvaluatorV1.normalizeDateOperand(node.value),\n ),\n );\n }\n\n return Result.ok(\n this.evaluateOperator(actual, node.op, node.value),\n );\n } catch (error) {\n return this.conditionEvalErr(node, error);\n }\n }\n\n private buildTrace(params: {\n readonly conditionPath: string;\n readonly decisiveNode: ConditionNode;\n readonly lastEvaluatedLeaf: ConditionLeafNode;\n readonly lastEvaluatedLeafPath: string;\n readonly lastEvaluatedLeafResult: boolean;\n }): ConditionEvaluationTrace {\n return {\n conditionPath: params.conditionPath,\n decisiveNode: params.decisiveNode,\n lastEvaluatedLeaf: params.lastEvaluatedLeaf,\n lastEvaluatedLeafPath: params.lastEvaluatedLeafPath,\n lastEvaluatedLeafResult: params.lastEvaluatedLeafResult,\n };\n }\n\n private evaluateWithTraceInternal(\n node: ConditionNode,\n path: string,\n ): Result<TracedConditionEvaluation, string> {\n if (ConditionEvaluatorV1.isLeafNode(node)) {\n const leafResult = this.evaluateLeafNode(node);\n if (leafResult.isErr()) {\n return Result.err(leafResult.errorOrNull()!);\n }\n\n const matched = leafResult.getOrNull()!;\n return Result.ok({\n matched,\n trace: this.buildTrace({\n conditionPath: path,\n decisiveNode: node,\n lastEvaluatedLeaf: node,\n lastEvaluatedLeafPath: path,\n lastEvaluatedLeafResult: matched,\n }),\n });\n }\n\n if (ConditionEvaluatorV1.isAndNode(node)) {\n if (node.and.length === 0) {\n return Result.err(\n ConditionEvaluatorV1.buildEmptyAndConditionMessage(),\n );\n }\n\n let lastTracedChild: TracedConditionEvaluation | null = null;\n\n for (const [index, child] of node.and.entries()) {\n const childPath = `${path}.and[${index}]`;\n const childResult = this.evaluateWithTraceInternal(\n child,\n childPath,\n );\n if (childResult.isErr()) {\n return Result.err(childResult.errorOrNull()!);\n }\n\n const tracedChild = childResult.getOrNull()!;\n lastTracedChild = tracedChild;\n if (!tracedChild.matched) {\n return Result.ok({\n matched: false,\n trace: this.buildTrace({\n conditionPath: childPath,\n decisiveNode: child,\n lastEvaluatedLeaf:\n tracedChild.trace.lastEvaluatedLeaf,\n lastEvaluatedLeafPath:\n tracedChild.trace.lastEvaluatedLeafPath,\n lastEvaluatedLeafResult:\n tracedChild.trace.lastEvaluatedLeafResult,\n }),\n });\n }\n }\n\n return Result.ok({\n matched: true,\n trace: lastTracedChild!.trace,\n });\n }\n\n if (ConditionEvaluatorV1.isOrNode(node)) {\n let lastTrace: ConditionEvaluationTrace | null = null;\n\n for (const [index, child] of node.or.entries()) {\n const childResult = this.evaluateWithTraceInternal(\n child,\n `${path}.or[${index}]`,\n );\n if (childResult.isErr()) {\n return Result.err(childResult.errorOrNull()!);\n }\n\n const tracedChild = childResult.getOrNull()!;\n lastTrace = tracedChild.trace;\n if (tracedChild.matched) {\n return Result.ok({\n matched: true,\n trace: tracedChild.trace,\n });\n }\n }\n\n if (lastTrace === null) {\n return Result.err(\n ConditionEvaluatorV1.buildEmptyOrConditionMessage(),\n );\n }\n\n return Result.ok({ matched: false, trace: lastTrace! });\n }\n\n if (ConditionEvaluatorV1.isNotNode(node)) {\n const childPath = `${path}.not`;\n const childResult = this.evaluateWithTraceInternal(\n node.not,\n childPath,\n );\n if (childResult.isErr()) {\n return Result.err(childResult.errorOrNull()!);\n }\n\n const tracedChild = childResult.getOrNull()!;\n return Result.ok({\n matched: !tracedChild.matched,\n trace: this.buildTrace({\n conditionPath: path,\n decisiveNode: node,\n lastEvaluatedLeaf: tracedChild.trace.lastEvaluatedLeaf,\n lastEvaluatedLeafPath:\n tracedChild.trace.lastEvaluatedLeafPath,\n lastEvaluatedLeafResult:\n tracedChild.trace.lastEvaluatedLeafResult,\n }),\n });\n }\n\n return this.conditionEvalErr(\n node,\n new TypeError(\"Invalid condition node shape\"),\n );\n }\n\n evaluate(node: ConditionNode): Result<boolean, string> {\n try {\n const result = this.evaluateWithTraceInternal(node, \"$\");\n if (result.isErr()) {\n return Result.err(result.errorOrNull()!);\n }\n\n return Result.ok(result.getOrNull()!.matched);\n } catch (error) {\n return this.conditionEvalErr(node, error);\n }\n }\n\n evaluateWithTrace(\n node: ConditionNode,\n ): Result<TracedConditionEvaluation, string> {\n try {\n return this.evaluateWithTraceInternal(node, \"$\");\n } catch (error) {\n return this.conditionEvalErr(node, error);\n }\n }\n\n static extractFields(node: ConditionNode): string[] {\n if (ConditionEvaluatorV1.isLeafNode(node)) {\n return [node.field];\n }\n\n if (ConditionEvaluatorV1.isAndNode(node)) {\n return node.and.flatMap((child) =>\n ConditionEvaluatorV1.extractFields(child),\n );\n }\n\n if (ConditionEvaluatorV1.isOrNode(node)) {\n return node.or.flatMap((child) =>\n ConditionEvaluatorV1.extractFields(child),\n );\n }\n\n if (ConditionEvaluatorV1.isNotNode(node)) {\n return ConditionEvaluatorV1.extractFields(node.not);\n }\n\n return [];\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"condition-evaluator.js","names":["#initialReporter","#currentReporter","#bridgeToConditionReporter"],"sources":["../src/core/config/silent-policy-reporter.ts","../src/core/config/core-config.ts","../src/core/config/core-config.instance.ts","../src/core/policies/context/path.ts","../src/core/policies/utils/date.ts","../src/core/policies/engines/v1/condition-date-operands.ts","../src/core/policies/engines/v1/condition-evaluator.ts"],"sourcesContent":["import type { PolicyReporter } from \"./policy-reporter.js\";\n\nexport class SilentPolicyReporter implements PolicyReporter {\n report(_event: Parameters<PolicyReporter[\"report\"]>[0]): void {}\n}\n","import type {\n ConditionEvaluationOptions,\n ConditionEvaluationReport,\n ConditionEvaluationReportLevel,\n ConditionEvaluatorReporter,\n} from \"../policies/engines/condition-evaluator-reporter.js\";\nimport type { PolicyEvent, PolicyReporter } from \"./policy-reporter.js\";\nimport { SilentPolicyReporter } from \"./silent-policy-reporter.js\";\n\nexport interface CoreObservabilityConfig {\n readonly reporter?: PolicyReporter;\n}\n\nexport interface CoreConfigOptions {\n // `observability` is today's only section. Future core config (settings,\n // feature flags) joins here as sibling keys — that umbrella is why the\n // reporter is nested under `observability` instead of living at the root.\n readonly observability?: CoreObservabilityConfig;\n}\n\n/** Reports an event without letting a throwing reporter abort the caller. */\nfunction safeReport(policyReporter: PolicyReporter, event: PolicyEvent): void {\n try {\n policyReporter.report(event);\n } catch {\n // Telemetry failures must never interrupt the domain flow.\n }\n}\n\n/**\n * The core's config namespace. Today it holds a single section —\n * `observability` — whose whole job is to decide *where policy telemetry goes*\n * while guaranteeing telemetry is best-effort (a throwing reporter can never\n * abort a domain flow). App config (env, settings, feature flags) is\n * deliberately absent for now: when the core needs it, it joins here as a\n * sibling section rather than a new module — which is why this is `config`,\n * not `observability`. It holds the active {@link PolicyReporter} (silent by\n * default, so the core carries no logging dependency), bridges it to the\n * engines' {@link ConditionEvaluatorReporter}, and offers `reportSafely` as\n * the single guarded emit path shared with {@link PolicyService}.\n */\nexport class CoreConfig {\n readonly #initialReporter: PolicyReporter;\n #currentReporter: PolicyReporter;\n\n constructor(options: CoreConfigOptions = {}) {\n const reporter =\n options.observability?.reporter ?? new SilentPolicyReporter();\n this.#initialReporter = reporter;\n this.#currentReporter = reporter;\n }\n\n /**\n * Swaps the active reporter. Pass `observability.reporter` to enable\n * telemetry, or set it explicitly to `undefined` to go silent again.\n * Omitting `observability` (or its `reporter` key) is a no-op.\n */\n configure(options: CoreConfigOptions): this {\n const observability = options.observability;\n if (observability && \"reporter\" in observability) {\n this.#currentReporter =\n observability.reporter ?? new SilentPolicyReporter();\n }\n return this;\n }\n\n // Restores the reporter captured at construction time — which is silent\n // only if this instance was built without one.\n reset(): this {\n this.#currentReporter = this.#initialReporter;\n return this;\n }\n\n /** Emits a policy event through the active reporter, best-effort. */\n reportSafely(event: PolicyEvent): void {\n safeReport(this.#currentReporter, event);\n }\n\n getConditionEvaluationOptions(\n engineVersion: number,\n ): ConditionEvaluationOptions {\n return {\n reporter: this.#bridgeToConditionReporter(this.#currentReporter),\n engineVersion,\n };\n }\n\n #bridgeToConditionReporter(\n policyReporter: PolicyReporter,\n ): ConditionEvaluatorReporter {\n // Capture the reporter now so a mid-evaluation reconfigure never splits\n // a single evaluation's reports across two reporters (intentional).\n const emit = (\n level: ConditionEvaluationReportLevel,\n report: ConditionEvaluationReport,\n ): void => {\n safeReport(policyReporter, {\n kind: \"condition-eval\",\n ...report,\n level,\n });\n };\n return {\n warn: (report) => emit(\"warn\", report),\n error: (report) => emit(\"error\", report),\n };\n }\n}\n","import { CoreConfig } from \"./core-config.js\";\nimport { SilentPolicyReporter } from \"./silent-policy-reporter.js\";\n\n/**\n * Shared instance for the application composition root.\n * Use `new CoreConfig()` for isolated runtimes, tests, or multi-tenant hosts.\n *\n * The default reporter is silent so the core has no runtime logging dependency.\n * Hosts can swap in their own `PolicyReporter` via\n * `coreConfig.configure({ observability: { reporter } })`.\n */\nexport const coreConfig = new CoreConfig({\n observability: { reporter: new SilentPolicyReporter() },\n});\n","/**\n * Utilities for reading/writing values at dot-separated paths\n * in plain objects, e.g. \"installment.dueDate\".\n */\n\nimport { Result } from \"../../result/result.js\";\n\nexport class PolicyContextPath {\n private static readonly FORBIDDEN_SEGMENTS = new Set([\n \"__proto__\",\n \"prototype\",\n \"constructor\",\n ]);\n\n private static resolve(\n obj: Record<string, unknown>,\n path: string,\n ): Result<\n {\n readonly found: boolean;\n readonly value: unknown;\n },\n string\n > {\n const segmentsResult = PolicyContextPath.parseSegments(path);\n if (segmentsResult.isErr()) {\n return Result.err(segmentsResult.errorOrNull()!);\n }\n\n const segments = segmentsResult.getOrNull()!;\n let current: unknown = obj;\n\n for (const segment of segments) {\n if (\n current === null ||\n current === undefined ||\n typeof current !== \"object\"\n ) {\n return Result.ok({ found: false, value: undefined });\n }\n\n const record = current as Record<string, unknown>;\n if (!Object.prototype.hasOwnProperty.call(record, segment)) {\n return Result.ok({ found: false, value: undefined });\n }\n\n current = record[segment];\n }\n\n return Result.ok({ found: true, value: current });\n }\n\n private static parseSegments(\n path: string,\n ): Result<readonly string[], string> {\n if (path.trim().length === 0) {\n return Result.err(\"Path cannot be empty\");\n }\n\n const segments = path.split(\".\");\n if (segments.some((segment) => segment.length === 0)) {\n return Result.err(`Path \"${path}\" contains an empty segment`);\n }\n\n const forbiddenSegment = segments.find((segment) =>\n PolicyContextPath.FORBIDDEN_SEGMENTS.has(segment),\n );\n if (forbiddenSegment !== undefined) {\n return Result.err(\n `Path \"${path}\" contains forbidden segment \"${forbiddenSegment}\"`,\n );\n }\n\n return Result.ok(segments);\n }\n\n private static isPlainRecord(\n value: unknown,\n ): value is Record<string, unknown> {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n }\n\n static getOrAbsent(\n obj: Record<string, unknown>,\n path: string,\n ): Result<unknown, \"absent\"> {\n const resolvedPath = PolicyContextPath.resolve(obj, path);\n if (resolvedPath.isErr()) {\n return Result.err(\"absent\");\n }\n\n const { found, value } = resolvedPath.getOrNull()!;\n if (!found) {\n return Result.err(\"absent\");\n }\n\n return Result.ok(value);\n }\n\n static has(obj: Record<string, unknown>, path: string): boolean {\n const resolvedPath = PolicyContextPath.resolve(obj, path);\n if (resolvedPath.isErr()) {\n return false;\n }\n\n return resolvedPath.getOrNull()!.found;\n }\n\n static set(\n obj: Record<string, unknown>,\n path: string,\n value: unknown,\n ): Result<void, string> {\n const segmentsResult = PolicyContextPath.parseSegments(path);\n if (segmentsResult.isErr()) {\n return Result.err(segmentsResult.errorOrNull()!);\n }\n\n const segments = segmentsResult.getOrNull()!;\n let current: Record<string, unknown> = obj;\n\n for (let i = 0; i < segments.length - 1; i++) {\n const seg = segments[i];\n const next = current[seg];\n\n if (next === undefined) {\n const container = Object.create(null) as Record<\n string,\n unknown\n >;\n current[seg] = container;\n current = container;\n continue;\n }\n\n if (!PolicyContextPath.isPlainRecord(next)) {\n return Result.err(\n `Cannot create nested path \"${path}\" because \"${segments\n .slice(0, i + 1)\n .join(\".\")}\" already contains a non-plain object`,\n );\n }\n\n current = next;\n }\n\n current[segments[segments.length - 1]] = value;\n return Result.ok(undefined);\n }\n}\n","import { isValidDate } from \"../../shared/temporal-guards.js\";\n\nexport class PolicyDateUtils {\n static isValid(value: Date): boolean {\n return isValidDate(value);\n }\n}\n","// Pure helpers for treating condition operands as instants. Extracted from\n// condition-evaluator.ts to keep that file under the kit's size limit and to\n// isolate the (zod-free) date logic the ./abac subpath re-uses. Import the date\n// util directly (not the utils barrel): the barrel re-exports PolicyHashing,\n// whose node:crypto import would needlessly drag a Node-only API into the\n// zod-free ./abac subpath.\nimport { PolicyDateUtils } from \"../../utils/date.js\";\nimport { Result } from \"../../../result/result.js\";\n\nimport type { ConditionOp } from \"./condition-types.js\";\n\nexport type RelationalOperator = Extract<\n ConditionOp,\n \"gt\" | \"gte\" | \"lt\" | \"lte\"\n>;\n\n/**\n * The one instant format condition date operands may use. Strict on purpose\n * (UTC, milliseconds) so comparisons are unambiguous across time zones — and\n * so a malformed operand fails loudly instead of comparing wrong.\n */\nexport const CANONICAL_UTC_DATE_FORMAT = \"YYYY-MM-DDTHH:mm:ss.SSSZ\";\n\nconst ISO_8601_UTC_DATE_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/;\n// A value that is clearly meant to be a date-time but isn't canonical UTC\n// (missing milliseconds, a non-UTC offset, a space separator…). Lets the\n// caller report a \"malformed date\" error instead of a misleading \"not a\n// number\" one.\nconst ISO_8601_DATE_LIKE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}/;\n\n/**\n * Parses a value used as a date operand:\n * - `Result.ok(Date)` for a valid Date or a canonical ISO-8601 UTC string;\n * - `Result.err` when it is date-shaped but malformed (invalid Date, or a\n * date-like string that isn't canonical UTC) — a configuration error worth\n * surfacing rather than silently treating as \"not a date\";\n * - `null` when the value isn't date-shaped at all, so the caller can fall\n * through to a numeric comparison.\n */\nexport function parseComparableDate(\n value: unknown,\n): Result<Date, string> | null {\n if (value instanceof Date) {\n return PolicyDateUtils.isValid(value)\n ? Result.ok(value)\n : Result.err(\"Invalid Date instance\");\n }\n\n if (typeof value !== \"string\") {\n return null;\n }\n\n if (ISO_8601_UTC_DATE_PATTERN.test(value)) {\n const parsed = new Date(value);\n if (\n !PolicyDateUtils.isValid(parsed) ||\n parsed.toISOString() !== value\n ) {\n return Result.err(\"Invalid ISO 8601 UTC date string\");\n }\n\n return Result.ok(parsed);\n }\n\n if (ISO_8601_DATE_LIKE_PATTERN.test(value)) {\n return Result.err(\n `date operand must be canonical ISO 8601 UTC (${CANONICAL_UTC_DATE_FORMAT})`,\n );\n }\n\n return null;\n}\n\nexport function evaluateRelationalNumbers(\n actual: number,\n op: RelationalOperator,\n expected: number,\n): boolean {\n switch (op) {\n case \"gt\":\n return actual > expected;\n case \"gte\":\n return actual >= expected;\n case \"lt\":\n return actual < expected;\n case \"lte\":\n return actual <= expected;\n }\n}\n\nexport function containsInvalidDate(value: unknown): boolean {\n if (value instanceof Date) {\n return !PolicyDateUtils.isValid(value);\n }\n if (Array.isArray(value)) {\n return value.some((item) => containsInvalidDate(item));\n }\n return false;\n}\n\n// Valid Dates become their ISO string so equality/set operators compare\n// instants instead of references; every other value passes through.\nexport function normalizeDateOperand(value: unknown): unknown {\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (Array.isArray(value)) {\n return value.map((item) => normalizeDateOperand(item));\n }\n return value;\n}\n","import { PolicyContextPath } from \"../../context/index.js\";\nimport { Result } from \"../../../result/result.js\";\n\nimport {\n CANONICAL_UTC_DATE_FORMAT,\n containsInvalidDate,\n evaluateRelationalNumbers,\n normalizeDateOperand,\n parseComparableDate,\n type RelationalOperator,\n} from \"./condition-date-operands.js\";\nimport type {\n ConditionAndNode,\n ConditionLeafNode,\n ConditionNode,\n ConditionNotNode,\n ConditionOp,\n ConditionOrNode,\n} from \"./condition-types.js\";\nimport type {\n ConditionEvaluationOptions,\n ConditionEvaluationReport,\n} from \"../condition-evaluator-reporter.js\";\nimport type { PolicyContext } from \"../gate-types.js\";\n\nconst CONDITION_EVAL_THROWN_TAG = \"CONDITION_EVAL_THREW\";\nconst NULLISH_NUMERIC_OPERAND_NOT_ALLOWED_TAG =\n \"NULLISH_NUMERIC_OPERAND_NOT_ALLOWED\";\nconst NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG = \"NULLISH_DATE_OPERAND_NOT_ALLOWED\";\nconst INVALID_DATE_OPERAND_TAG = \"INVALID_DATE_OPERAND\";\nconst INVALID_NUMERIC_OPERAND_TAG = \"INVALID_NUMERIC_OPERAND\";\nconst INVALID_SET_OPERAND_TAG = \"INVALID_SET_OPERAND\";\nconst EMPTY_OR_CONDITION_TAG = \"EMPTY_OR_CONDITION\";\nconst EMPTY_AND_CONDITION_TAG = \"EMPTY_AND_CONDITION\";\n\nexport interface ConditionEvaluationTrace {\n readonly conditionPath: string;\n readonly decisiveNode: ConditionNode;\n readonly lastEvaluatedLeaf: ConditionLeafNode;\n readonly lastEvaluatedLeafPath: string;\n readonly lastEvaluatedLeafResult: boolean;\n}\n\nexport interface TracedConditionEvaluation {\n readonly matched: boolean;\n readonly trace: ConditionEvaluationTrace;\n}\n\nexport class ConditionEvaluatorV1 {\n constructor(\n private readonly context: PolicyContext,\n private readonly options: ConditionEvaluationOptions,\n ) {}\n\n private static isLeafNode(node: ConditionNode): node is ConditionLeafNode {\n return \"field\" in node && \"op\" in node;\n }\n\n private static isAndNode(node: ConditionNode): node is ConditionAndNode {\n return \"and\" in node;\n }\n\n private static isOrNode(node: ConditionNode): node is ConditionOrNode {\n return \"or\" in node;\n }\n\n private static isNotNode(node: ConditionNode): node is ConditionNotNode {\n return \"not\" in node;\n }\n\n private static isRelationalOperator(\n op: ConditionOp,\n ): op is RelationalOperator {\n return op === \"gt\" || op === \"gte\" || op === \"lt\" || op === \"lte\";\n }\n\n private static describeError(error: unknown): {\n name: string;\n message: string;\n } {\n if (error instanceof Error) {\n return { name: error.name, message: error.message };\n }\n\n return { name: \"NonErrorThrown\", message: String(error) };\n }\n\n private static invalidDateOperandMessage(node: ConditionLeafNode): string {\n return `${INVALID_DATE_OPERAND_TAG}: \"${node.field}\" with operator \"${node.op}\" requires Date or ISO 8601 UTC (${CANONICAL_UTC_DATE_FORMAT}) string operands`;\n }\n\n private buildReport(params: {\n readonly level: ConditionEvaluationReport[\"level\"];\n readonly tag: ConditionEvaluationReport[\"tag\"];\n readonly message: string;\n readonly details: Readonly<Record<string, unknown>>;\n }): ConditionEvaluationReport {\n return {\n occurredAt: new Date(),\n level: params.level,\n tag: params.tag,\n message: params.message,\n engineVersion: this.options.engineVersion,\n details: params.details,\n };\n }\n\n // Single reporting seam for every leaf-level operand error. Collapses the\n // formerly per-tag report methods, whose only real difference was the tag,\n // message, and (for the nullish cases) an `allowNull` detail.\n private reportLeafError(\n tag: ConditionEvaluationReport[\"tag\"],\n message: string,\n node: ConditionLeafNode,\n actual: unknown,\n extra?: Readonly<Record<string, unknown>>,\n ): Result<boolean, string> {\n this.options.reporter.error(\n this.buildReport({\n level: \"error\",\n tag,\n message,\n details: {\n field: node.field,\n op: node.op,\n actual,\n expected: node.value,\n ...extra,\n node,\n },\n }),\n );\n\n return Result.err(message);\n }\n\n private conditionEvalErr<TValue>(\n node: ConditionNode,\n error: unknown,\n ): Result<TValue, string> {\n const cause = ConditionEvaluatorV1.describeError(error);\n const message = `${CONDITION_EVAL_THROWN_TAG}: ${cause.name}: ${cause.message}`;\n\n this.options.reporter.error(\n this.buildReport({\n level: \"error\",\n tag: CONDITION_EVAL_THROWN_TAG,\n message,\n details: { node, cause },\n }),\n );\n\n return Result.err(message);\n }\n\n private evaluateDateRelationalNode(\n node: ConditionLeafNode,\n actual: unknown,\n ): Result<boolean, string> | null {\n if (!ConditionEvaluatorV1.isRelationalOperator(node.op)) {\n return null;\n }\n\n const actualDate = parseComparableDate(actual);\n const expectedDate = parseComparableDate(node.value);\n\n // Neither operand is date-shaped: let the numeric path handle it.\n if (actualDate === null && expectedDate === null) {\n return null;\n }\n\n const allowsNull = node.allowNull === true;\n if (actual === null && allowsNull) {\n return Result.ok(false);\n }\n\n if (actual === null || actual === undefined) {\n const resolved = actual === null ? \"null\" : \"undefined\";\n return this.reportLeafError(\n NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG,\n `${NULLISH_DATE_OPERAND_NOT_ALLOWED_TAG}: \"${node.field}\" resolved to ${resolved} for date comparison operator \"${node.op}\"`,\n node,\n actual,\n { allowNull: allowsNull },\n );\n }\n\n if (\n actualDate === null ||\n actualDate.isErr() ||\n expectedDate === null ||\n expectedDate.isErr()\n ) {\n return this.reportLeafError(\n INVALID_DATE_OPERAND_TAG,\n ConditionEvaluatorV1.invalidDateOperandMessage(node),\n node,\n actual,\n );\n }\n\n return Result.ok(\n evaluateRelationalNumbers(\n actualDate.getOrNull()!.getTime(),\n node.op,\n expectedDate.getOrNull()!.getTime(),\n ),\n );\n }\n\n private evaluateOperator(\n actual: unknown,\n op: ConditionOp,\n expected: unknown,\n ): boolean {\n switch (op) {\n case \"eq\":\n return actual === expected;\n case \"neq\":\n return actual !== expected;\n case \"gt\":\n case \"gte\":\n case \"lt\":\n case \"lte\":\n return (\n typeof actual === \"number\" &&\n typeof expected === \"number\" &&\n evaluateRelationalNumbers(actual, op, expected)\n );\n case \"in\":\n return Array.isArray(expected) && expected.includes(actual);\n case \"notIn\":\n return Array.isArray(expected) && !expected.includes(actual);\n case \"isNull\":\n return actual === null || actual === undefined;\n case \"isNotNull\":\n return actual !== null && actual !== undefined;\n }\n }\n\n private evaluateNumericRelationalNode(\n node: ConditionLeafNode,\n actual: unknown,\n ): Result<boolean, string> {\n const allowsNull = node.allowNull === true;\n if (actual === undefined || (actual === null && !allowsNull)) {\n const resolved = actual === null ? \"null\" : \"undefined\";\n return this.reportLeafError(\n NULLISH_NUMERIC_OPERAND_NOT_ALLOWED_TAG,\n `${NULLISH_NUMERIC_OPERAND_NOT_ALLOWED_TAG}: \"${node.field}\" resolved to ${resolved} for numeric operator \"${node.op}\"`,\n node,\n actual,\n { allowNull: allowsNull },\n );\n }\n\n // null + allowNull: a relational comparison against a missing value\n // never matches.\n if (actual === null) {\n return Result.ok(false);\n }\n\n // Both operands must be finite numbers. A present but wrong-typed or\n // NaN operand is a context/configuration error, surfaced like the date\n // path instead of silently collapsing to \"no match\".\n if (\n typeof actual !== \"number\" ||\n Number.isNaN(actual) ||\n typeof node.value !== \"number\" ||\n Number.isNaN(node.value)\n ) {\n return this.reportLeafError(\n INVALID_NUMERIC_OPERAND_TAG,\n `${INVALID_NUMERIC_OPERAND_TAG}: \"${node.field}\" with operator \"${node.op}\" requires numeric operands`,\n node,\n actual,\n );\n }\n\n return Result.ok(this.evaluateOperator(actual, node.op, node.value));\n }\n\n private evaluateLeafNode(node: ConditionLeafNode): Result<boolean, string> {\n const actualResult = PolicyContextPath.getOrAbsent(\n this.context,\n node.field,\n );\n if (actualResult.isErr()) {\n const message = `MISSING_CONTEXT_FIELD: \"${node.field}\" not found in context`;\n this.options.reporter.warn(\n this.buildReport({\n level: \"warn\",\n tag: \"MISSING_CONTEXT_FIELD\",\n message,\n details: { field: node.field, node },\n }),\n );\n\n return Result.err(message);\n }\n\n try {\n const actual = actualResult.getOrThrow();\n if (ConditionEvaluatorV1.isRelationalOperator(node.op)) {\n const dateResult = this.evaluateDateRelationalNode(\n node,\n actual,\n );\n if (dateResult !== null) {\n return dateResult;\n }\n\n return this.evaluateNumericRelationalNode(node, actual);\n }\n\n if (\n (node.op === \"in\" || node.op === \"notIn\") &&\n !Array.isArray(node.value)\n ) {\n return this.reportLeafError(\n INVALID_SET_OPERAND_TAG,\n `${INVALID_SET_OPERAND_TAG}: \"${node.field}\" with operator \"${node.op}\" requires an array operand`,\n node,\n actual,\n );\n }\n\n if (\n node.op === \"eq\" ||\n node.op === \"neq\" ||\n node.op === \"in\" ||\n node.op === \"notIn\"\n ) {\n // A Date operand would otherwise compare by reference and\n // silently never match. Normalize valid Dates (either side,\n // including set items) to their ISO string; an invalid Date is\n // a context/configuration error, like the relational path.\n if (\n containsInvalidDate(actual) ||\n containsInvalidDate(node.value)\n ) {\n return this.reportLeafError(\n INVALID_DATE_OPERAND_TAG,\n ConditionEvaluatorV1.invalidDateOperandMessage(node),\n node,\n actual,\n );\n }\n\n return Result.ok(\n this.evaluateOperator(\n normalizeDateOperand(actual),\n node.op,\n normalizeDateOperand(node.value),\n ),\n );\n }\n\n return Result.ok(\n this.evaluateOperator(actual, node.op, node.value),\n );\n } catch (error) {\n return this.conditionEvalErr(node, error);\n }\n }\n\n private buildTrace(params: {\n readonly conditionPath: string;\n readonly decisiveNode: ConditionNode;\n readonly lastEvaluatedLeaf: ConditionLeafNode;\n readonly lastEvaluatedLeafPath: string;\n readonly lastEvaluatedLeafResult: boolean;\n }): ConditionEvaluationTrace {\n return {\n conditionPath: params.conditionPath,\n decisiveNode: params.decisiveNode,\n lastEvaluatedLeaf: params.lastEvaluatedLeaf,\n lastEvaluatedLeafPath: params.lastEvaluatedLeafPath,\n lastEvaluatedLeafResult: params.lastEvaluatedLeafResult,\n };\n }\n\n private evaluateWithTraceInternal(\n node: ConditionNode,\n path: string,\n ): Result<TracedConditionEvaluation, string> {\n if (ConditionEvaluatorV1.isLeafNode(node)) {\n const leafResult = this.evaluateLeafNode(node);\n if (leafResult.isErr()) {\n return Result.err(leafResult.errorOrNull()!);\n }\n\n const matched = leafResult.getOrNull()!;\n return Result.ok({\n matched,\n trace: this.buildTrace({\n conditionPath: path,\n decisiveNode: node,\n lastEvaluatedLeaf: node,\n lastEvaluatedLeafPath: path,\n lastEvaluatedLeafResult: matched,\n }),\n });\n }\n\n if (ConditionEvaluatorV1.isAndNode(node)) {\n if (node.and.length === 0) {\n return Result.err(\n `${EMPTY_AND_CONDITION_TAG}: AND nodes must contain at least one child condition`,\n );\n }\n\n let lastTracedChild: TracedConditionEvaluation | null = null;\n\n for (const [index, child] of node.and.entries()) {\n const childPath = `${path}.and[${index}]`;\n const childResult = this.evaluateWithTraceInternal(\n child,\n childPath,\n );\n if (childResult.isErr()) {\n return Result.err(childResult.errorOrNull()!);\n }\n\n const tracedChild = childResult.getOrNull()!;\n lastTracedChild = tracedChild;\n if (!tracedChild.matched) {\n return Result.ok({\n matched: false,\n trace: this.buildTrace({\n conditionPath: childPath,\n decisiveNode: child,\n lastEvaluatedLeaf:\n tracedChild.trace.lastEvaluatedLeaf,\n lastEvaluatedLeafPath:\n tracedChild.trace.lastEvaluatedLeafPath,\n lastEvaluatedLeafResult:\n tracedChild.trace.lastEvaluatedLeafResult,\n }),\n });\n }\n }\n\n return Result.ok({\n matched: true,\n trace: lastTracedChild!.trace,\n });\n }\n\n if (ConditionEvaluatorV1.isOrNode(node)) {\n let lastTrace: ConditionEvaluationTrace | null = null;\n\n for (const [index, child] of node.or.entries()) {\n const childResult = this.evaluateWithTraceInternal(\n child,\n `${path}.or[${index}]`,\n );\n if (childResult.isErr()) {\n return Result.err(childResult.errorOrNull()!);\n }\n\n const tracedChild = childResult.getOrNull()!;\n lastTrace = tracedChild.trace;\n if (tracedChild.matched) {\n return Result.ok({\n matched: true,\n trace: tracedChild.trace,\n });\n }\n }\n\n if (lastTrace === null) {\n return Result.err(\n `${EMPTY_OR_CONDITION_TAG}: OR nodes must contain at least one child condition`,\n );\n }\n\n return Result.ok({ matched: false, trace: lastTrace! });\n }\n\n if (ConditionEvaluatorV1.isNotNode(node)) {\n const childPath = `${path}.not`;\n const childResult = this.evaluateWithTraceInternal(\n node.not,\n childPath,\n );\n if (childResult.isErr()) {\n return Result.err(childResult.errorOrNull()!);\n }\n\n const tracedChild = childResult.getOrNull()!;\n return Result.ok({\n matched: !tracedChild.matched,\n trace: this.buildTrace({\n conditionPath: path,\n decisiveNode: node,\n lastEvaluatedLeaf: tracedChild.trace.lastEvaluatedLeaf,\n lastEvaluatedLeafPath:\n tracedChild.trace.lastEvaluatedLeafPath,\n lastEvaluatedLeafResult:\n tracedChild.trace.lastEvaluatedLeafResult,\n }),\n });\n }\n\n return this.conditionEvalErr(\n node,\n new TypeError(\"Invalid condition node shape\"),\n );\n }\n\n evaluate(node: ConditionNode): Result<boolean, string> {\n try {\n const result = this.evaluateWithTraceInternal(node, \"$\");\n if (result.isErr()) {\n return Result.err(result.errorOrNull()!);\n }\n\n return Result.ok(result.getOrNull()!.matched);\n } catch (error) {\n return this.conditionEvalErr(node, error);\n }\n }\n\n evaluateWithTrace(\n node: ConditionNode,\n ): Result<TracedConditionEvaluation, string> {\n try {\n return this.evaluateWithTraceInternal(node, \"$\");\n } catch (error) {\n return this.conditionEvalErr(node, error);\n }\n }\n\n static extractFields(node: ConditionNode): string[] {\n if (ConditionEvaluatorV1.isLeafNode(node)) {\n return [node.field];\n }\n\n if (ConditionEvaluatorV1.isAndNode(node)) {\n return node.and.flatMap((child) =>\n ConditionEvaluatorV1.extractFields(child),\n );\n }\n\n if (ConditionEvaluatorV1.isOrNode(node)) {\n return node.or.flatMap((child) =>\n ConditionEvaluatorV1.extractFields(child),\n );\n }\n\n if (ConditionEvaluatorV1.isNotNode(node)) {\n return ConditionEvaluatorV1.extractFields(node.not);\n }\n\n return [];\n }\n}\n"],"mappings":"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"}
@@ -2,7 +2,8 @@ import { r as Result } from "./result.cjs";
2
2
  import { n as Outcome } from "./outcome.cjs";
3
3
 
4
4
  //#region src/core/policies/engines/v1/condition-types.d.ts
5
- type ConditionOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "isNull" | "isNotNull";
5
+ declare const CONDITION_OPS: readonly ["eq", "neq", "gt", "gte", "lt", "lte", "in", "notIn", "isNull", "isNotNull"];
6
+ type ConditionOp = (typeof CONDITION_OPS)[number];
6
7
  interface ConditionLeafNode {
7
8
  readonly field: string;
8
9
  readonly op: ConditionOp;
@@ -143,7 +144,39 @@ interface PolicyEvaluationCompletedEvent {
143
144
  readonly engineKind: "GATE" | "COMPUTE";
144
145
  readonly occurredAt: Date;
145
146
  }
146
- type PolicyEvent = ConditionEvalEvent | PolicyResolutionEvent | PolicyEvaluationFailedEvent | PolicyEvaluationCompletedEvent;
147
+ /**
148
+ * A resolved ABAC decision (both PERMIT and DENY). Emitted best-effort by the
149
+ * `AbacAuthorizer` so a host can build an authorization audit trail without an
150
+ * adapter of its own; silent by default like every other event. Types are kept
151
+ * self-contained (no import from `core/abac`) to avoid a config→abac cycle.
152
+ */
153
+ interface AbacDecisionEvent {
154
+ readonly kind: "abac-decision";
155
+ readonly level: "info";
156
+ readonly action: string;
157
+ readonly resource?: {
158
+ readonly type: string;
159
+ readonly id?: string;
160
+ };
161
+ readonly actorId: string;
162
+ readonly effect: "PERMIT" | "DENY";
163
+ /** Deciding rule id, or `"<default>"` / `"<default-deny>"` when the set's default decided. */
164
+ readonly decidingRuleId: string;
165
+ readonly decidingRuleVersion?: number;
166
+ readonly algorithm: string;
167
+ readonly occurredAt: Date;
168
+ }
169
+ type PolicyEvent = ConditionEvalEvent | PolicyResolutionEvent | PolicyEvaluationFailedEvent | PolicyEvaluationCompletedEvent | AbacDecisionEvent;
170
+ /**
171
+ * Sink for policy telemetry. The core never logs on its own — it hands typed
172
+ * events here and a host implementation decides what to do with them.
173
+ *
174
+ * Redaction is the host's responsibility: a `condition-eval` event carries the
175
+ * evaluated field path and value in `details` (e.g. `student.flags.*`), so in
176
+ * an ERP those payloads can contain PII. Sanitize before persisting or shipping
177
+ * events off-box; the core deliberately keeps no redaction seam so it stays
178
+ * pure and unopinionated about your logging stack.
179
+ */
147
180
  interface PolicyReporter {
148
181
  report(event: PolicyEvent): void;
149
182
  }
@@ -156,17 +189,31 @@ interface CoreConfigOptions {
156
189
  readonly observability?: CoreObservabilityConfig;
157
190
  }
158
191
  /**
159
- * Centraliza a configuracao pura do core sem depender de implementacoes
160
- * concretas de logging, tracing ou report.
192
+ * The core's config namespace. Today it holds a single section —
193
+ * `observability` whose whole job is to decide *where policy telemetry goes*
194
+ * while guaranteeing telemetry is best-effort (a throwing reporter can never
195
+ * abort a domain flow). App config (env, settings, feature flags) is
196
+ * deliberately absent for now: when the core needs it, it joins here as a
197
+ * sibling section rather than a new module — which is why this is `config`,
198
+ * not `observability`. It holds the active {@link PolicyReporter} (silent by
199
+ * default, so the core carries no logging dependency), bridges it to the
200
+ * engines' {@link ConditionEvaluatorReporter}, and offers `reportSafely` as
201
+ * the single guarded emit path shared with {@link PolicyService}.
161
202
  */
162
203
  declare class CoreConfig {
163
204
  #private;
164
205
  constructor(options?: CoreConfigOptions);
206
+ /**
207
+ * Swaps the active reporter. Pass `observability.reporter` to enable
208
+ * telemetry, or set it explicitly to `undefined` to go silent again.
209
+ * Omitting `observability` (or its `reporter` key) is a no-op.
210
+ */
165
211
  configure(options: CoreConfigOptions): this;
166
212
  reset(): this;
167
- getPolicyReporter(): PolicyReporter;
213
+ /** Emits a policy event through the active reporter, best-effort. */
214
+ reportSafely(event: PolicyEvent): void;
168
215
  getConditionEvaluationOptions(engineVersion: number): ConditionEvaluationOptions;
169
216
  }
170
217
  //#endregion
171
- export { ConditionLeafNode as A, GateTraceNodeSnapshot as C, VersionedGateEngine as D, PolicyViolation as E, GatePayload as O, GateTraceLeafSnapshot as S, PolicyContext as T, ConditionEvaluationReportTag as _, PolicyDecisionId as a, GateOutcomeData as b, TenantId as c, asSchoolId as d, asTenantId as f, ConditionEvaluationReportLevel as g, ConditionEvaluationReport as h, PolicyReporter as i, ConditionNode as j, GatePayloadV1 as k, asPolicyDecisionId as l, ConditionEvaluationOptions as m, CoreConfigOptions as n, PolicyDefinitionId as o, ConditionEvaluationCause as p, CoreObservabilityConfig as r, SchoolId as s, CoreConfig as t, asPolicyDefinitionId as u, ConditionEvaluatorReporter as v, GateViolationTrace as w, GateStatus as x, GateOutcome as y };
218
+ export { ConditionNode as A, GateViolationTrace as C, GatePayload as D, VersionedGateEngine as E, GatePayloadV1 as O, GateTraceNodeSnapshot as S, PolicyViolation as T, ConditionEvaluatorReporter as _, PolicyDefinitionId as a, GateStatus as b, asPolicyDecisionId as c, asTenantId as d, ConditionEvaluationCause as f, ConditionEvaluationReportTag as g, ConditionEvaluationReportLevel as h, PolicyDecisionId as i, ConditionLeafNode as k, asPolicyDefinitionId as l, ConditionEvaluationReport as m, CoreConfigOptions as n, SchoolId as o, ConditionEvaluationOptions as p, CoreObservabilityConfig as r, TenantId as s, CoreConfig as t, asSchoolId as u, GateOutcome as v, PolicyContext as w, GateTraceLeafSnapshot as x, GateOutcomeData as y };
172
219
  //# sourceMappingURL=core-config.d.cts.map
@@ -2,7 +2,8 @@ import { r as Result } from "./result.js";
2
2
  import { n as Outcome } from "./outcome.js";
3
3
 
4
4
  //#region src/core/policies/engines/v1/condition-types.d.ts
5
- type ConditionOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "isNull" | "isNotNull";
5
+ declare const CONDITION_OPS: readonly ["eq", "neq", "gt", "gte", "lt", "lte", "in", "notIn", "isNull", "isNotNull"];
6
+ type ConditionOp = (typeof CONDITION_OPS)[number];
6
7
  interface ConditionLeafNode {
7
8
  readonly field: string;
8
9
  readonly op: ConditionOp;
@@ -143,7 +144,39 @@ interface PolicyEvaluationCompletedEvent {
143
144
  readonly engineKind: "GATE" | "COMPUTE";
144
145
  readonly occurredAt: Date;
145
146
  }
146
- type PolicyEvent = ConditionEvalEvent | PolicyResolutionEvent | PolicyEvaluationFailedEvent | PolicyEvaluationCompletedEvent;
147
+ /**
148
+ * A resolved ABAC decision (both PERMIT and DENY). Emitted best-effort by the
149
+ * `AbacAuthorizer` so a host can build an authorization audit trail without an
150
+ * adapter of its own; silent by default like every other event. Types are kept
151
+ * self-contained (no import from `core/abac`) to avoid a config→abac cycle.
152
+ */
153
+ interface AbacDecisionEvent {
154
+ readonly kind: "abac-decision";
155
+ readonly level: "info";
156
+ readonly action: string;
157
+ readonly resource?: {
158
+ readonly type: string;
159
+ readonly id?: string;
160
+ };
161
+ readonly actorId: string;
162
+ readonly effect: "PERMIT" | "DENY";
163
+ /** Deciding rule id, or `"<default>"` / `"<default-deny>"` when the set's default decided. */
164
+ readonly decidingRuleId: string;
165
+ readonly decidingRuleVersion?: number;
166
+ readonly algorithm: string;
167
+ readonly occurredAt: Date;
168
+ }
169
+ type PolicyEvent = ConditionEvalEvent | PolicyResolutionEvent | PolicyEvaluationFailedEvent | PolicyEvaluationCompletedEvent | AbacDecisionEvent;
170
+ /**
171
+ * Sink for policy telemetry. The core never logs on its own — it hands typed
172
+ * events here and a host implementation decides what to do with them.
173
+ *
174
+ * Redaction is the host's responsibility: a `condition-eval` event carries the
175
+ * evaluated field path and value in `details` (e.g. `student.flags.*`), so in
176
+ * an ERP those payloads can contain PII. Sanitize before persisting or shipping
177
+ * events off-box; the core deliberately keeps no redaction seam so it stays
178
+ * pure and unopinionated about your logging stack.
179
+ */
147
180
  interface PolicyReporter {
148
181
  report(event: PolicyEvent): void;
149
182
  }
@@ -156,17 +189,31 @@ interface CoreConfigOptions {
156
189
  readonly observability?: CoreObservabilityConfig;
157
190
  }
158
191
  /**
159
- * Centraliza a configuracao pura do core sem depender de implementacoes
160
- * concretas de logging, tracing ou report.
192
+ * The core's config namespace. Today it holds a single section —
193
+ * `observability` whose whole job is to decide *where policy telemetry goes*
194
+ * while guaranteeing telemetry is best-effort (a throwing reporter can never
195
+ * abort a domain flow). App config (env, settings, feature flags) is
196
+ * deliberately absent for now: when the core needs it, it joins here as a
197
+ * sibling section rather than a new module — which is why this is `config`,
198
+ * not `observability`. It holds the active {@link PolicyReporter} (silent by
199
+ * default, so the core carries no logging dependency), bridges it to the
200
+ * engines' {@link ConditionEvaluatorReporter}, and offers `reportSafely` as
201
+ * the single guarded emit path shared with {@link PolicyService}.
161
202
  */
162
203
  declare class CoreConfig {
163
204
  #private;
164
205
  constructor(options?: CoreConfigOptions);
206
+ /**
207
+ * Swaps the active reporter. Pass `observability.reporter` to enable
208
+ * telemetry, or set it explicitly to `undefined` to go silent again.
209
+ * Omitting `observability` (or its `reporter` key) is a no-op.
210
+ */
165
211
  configure(options: CoreConfigOptions): this;
166
212
  reset(): this;
167
- getPolicyReporter(): PolicyReporter;
213
+ /** Emits a policy event through the active reporter, best-effort. */
214
+ reportSafely(event: PolicyEvent): void;
168
215
  getConditionEvaluationOptions(engineVersion: number): ConditionEvaluationOptions;
169
216
  }
170
217
  //#endregion
171
- export { ConditionLeafNode as A, GateTraceNodeSnapshot as C, VersionedGateEngine as D, PolicyViolation as E, GatePayload as O, GateTraceLeafSnapshot as S, PolicyContext as T, ConditionEvaluationReportTag as _, PolicyDecisionId as a, GateOutcomeData as b, TenantId as c, asSchoolId as d, asTenantId as f, ConditionEvaluationReportLevel as g, ConditionEvaluationReport as h, PolicyReporter as i, ConditionNode as j, GatePayloadV1 as k, asPolicyDecisionId as l, ConditionEvaluationOptions as m, CoreConfigOptions as n, PolicyDefinitionId as o, ConditionEvaluationCause as p, CoreObservabilityConfig as r, SchoolId as s, CoreConfig as t, asPolicyDefinitionId as u, ConditionEvaluatorReporter as v, GateViolationTrace as w, GateStatus as x, GateOutcome as y };
218
+ export { ConditionNode as A, GateViolationTrace as C, GatePayload as D, VersionedGateEngine as E, GatePayloadV1 as O, GateTraceNodeSnapshot as S, PolicyViolation as T, ConditionEvaluatorReporter as _, PolicyDefinitionId as a, GateStatus as b, asPolicyDecisionId as c, asTenantId as d, ConditionEvaluationCause as f, ConditionEvaluationReportTag as g, ConditionEvaluationReportLevel as h, PolicyDecisionId as i, ConditionLeafNode as k, asPolicyDefinitionId as l, ConditionEvaluationReport as m, CoreConfigOptions as n, SchoolId as o, ConditionEvaluationOptions as p, CoreObservabilityConfig as r, TenantId as s, CoreConfig as t, asSchoolId as u, GateOutcome as v, PolicyContext as w, GateTraceLeafSnapshot as x, GateOutcomeData as y };
172
219
  //# sourceMappingURL=core-config.d.ts.map
@@ -0,0 +1,14 @@
1
+ //#region \0@oxc-project+runtime@0.132.0/helpers/decorate.js
2
+ function __decorate(decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ }
8
+ //#endregion
9
+ Object.defineProperty(exports, "__decorate", {
10
+ enumerable: true,
11
+ get: function() {
12
+ return __decorate;
13
+ }
14
+ });
@@ -0,0 +1,9 @@
1
+ //#region \0@oxc-project+runtime@0.132.0/helpers/decorate.js
2
+ function __decorate(decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ }
8
+ //#endregion
9
+ export { __decorate as t };
@@ -1,11 +1,105 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_entity = require("../entity.cjs");
2
+ const require_invariant_violation_exception = require("../invariant-violation-exception.cjs");
3
+ const require_temporal_guards = require("../temporal-guards.cjs");
4
+ const require_immutable = require("../immutable.cjs");
3
5
  const require_value_object = require("../value-object.cjs");
4
6
  const require_uuid_identifier = require("../uuid-identifier.cjs");
7
+ //#region src/core/domain/temporal/half-open-interval.ts
8
+ /**
9
+ * Shared core of the bitemporal primitives: a half-open interval
10
+ * `[start, end)` whose end, when present, must be strictly later than its
11
+ * start. `ValidTime` and `TransactionTime` are the same shape under different
12
+ * (deliberate) vocabularies — the invariant lives here once so the two files
13
+ * cannot drift apart.
14
+ *
15
+ * Internal to `domain/temporal`; not exported from the barrel.
16
+ */
17
+ function assertHalfOpenInterval(startLabel, start, endLabel, end) {
18
+ require_temporal_guards.assertValidDate(startLabel, start);
19
+ if (end === void 0) return;
20
+ require_temporal_guards.assertValidDate(endLabel, end);
21
+ if (end.getTime() <= start.getTime()) throw new require_invariant_violation_exception.InvariantViolationException(`${endLabel} must be later than ${startLabel}`);
22
+ }
23
+ //#endregion
24
+ //#region src/core/domain/temporal/transaction-time.ts
25
+ function assertTransactionTime(txTime, fieldName = "txTime") {
26
+ assertHalfOpenInterval(`${fieldName}.recordedAt`, txTime.recordedAt, `${fieldName}.supersededAt`, txTime.supersededAt);
27
+ }
28
+ function createTransactionTime(input) {
29
+ assertTransactionTime(input, "txTime");
30
+ if (input.supersededAt === void 0) return require_immutable.makeImmutable({ recordedAt: input.recordedAt });
31
+ return require_immutable.makeImmutable({
32
+ recordedAt: input.recordedAt,
33
+ supersededAt: input.supersededAt
34
+ });
35
+ }
36
+ //#endregion
37
+ //#region src/core/domain/temporal/valid-time.ts
38
+ function assertValidTime(validTime, fieldName = "validTime") {
39
+ assertHalfOpenInterval(`${fieldName}.from`, validTime.from, `${fieldName}.to`, validTime.to);
40
+ }
41
+ function createValidTime(input) {
42
+ assertValidTime(input, "validTime");
43
+ if (input.to === void 0) return require_immutable.makeImmutable({ from: input.from });
44
+ return require_immutable.makeImmutable({
45
+ from: input.from,
46
+ to: input.to
47
+ });
48
+ }
49
+ //#endregion
50
+ //#region src/core/domain/temporal/temporal-range.ts
51
+ /**
52
+ * Checks whether a temporal range is "open" (has no end date).
53
+ * Useful for identifying information that is still in effect / active.
54
+ */
55
+ function isOpen(range) {
56
+ assertValidTime(range, "range");
57
+ return range.to === void 0;
58
+ }
59
+ /**
60
+ * Checks whether a temporal range is "closed" (has a defined end date).
61
+ */
62
+ function isClosed(range) {
63
+ return !isOpen(range);
64
+ }
65
+ /**
66
+ * Checks whether a specific date is contained within the temporal range.
67
+ * The lower bound (`from`) is inclusive, while the upper bound (`to`) is exclusive.
68
+ */
69
+ function contains(range, date) {
70
+ assertValidTime(range, "range");
71
+ require_temporal_guards.assertValidDate("date", date);
72
+ const fromTime = range.from.getTime();
73
+ const toTime = range.to?.getTime() ?? Number.POSITIVE_INFINITY;
74
+ const targetTime = date.getTime();
75
+ return targetTime >= fromTime && targetTime < toTime;
76
+ }
77
+ /**
78
+ * Checks whether two temporal ranges overlap at any point.
79
+ * Useful for validating whether a new rule conflicts with an existing one.
80
+ */
81
+ function overlaps(left, right) {
82
+ assertValidTime(left, "left");
83
+ assertValidTime(right, "right");
84
+ const leftFrom = left.from.getTime();
85
+ const leftTo = left.to?.getTime() ?? Number.POSITIVE_INFINITY;
86
+ const rightFrom = right.from.getTime();
87
+ return leftFrom < (right.to?.getTime() ?? Number.POSITIVE_INFINITY) && rightFrom < leftTo;
88
+ }
89
+ //#endregion
90
+ //#region src/core/domain/temporal/temporal-snapshot.ts
91
+ function createTemporalSnapshot(input) {
92
+ return Object.freeze({
93
+ data: require_immutable.makeImmutable(input.data),
94
+ validTime: createValidTime(input.validTime),
95
+ txTime: createTransactionTime(input.txTime)
96
+ });
97
+ }
98
+ //#endregion
5
99
  Object.defineProperty(exports, "Entity", {
6
100
  enumerable: true,
7
101
  get: function() {
8
- return require_entity.Entity;
102
+ return require_uuid_identifier.Entity;
9
103
  }
10
104
  });
11
105
  exports.UuidIdentifier = require_uuid_identifier.UuidIdentifier;
@@ -15,3 +109,14 @@ Object.defineProperty(exports, "ValueObject", {
15
109
  return require_value_object.ValueObject;
16
110
  }
17
111
  });
112
+ exports.assertTransactionTime = assertTransactionTime;
113
+ exports.assertValidTime = assertValidTime;
114
+ exports.contains = contains;
115
+ exports.createTemporalSnapshot = createTemporalSnapshot;
116
+ exports.createTransactionTime = createTransactionTime;
117
+ exports.createValidTime = createValidTime;
118
+ exports.isClosed = isClosed;
119
+ exports.isOpen = isOpen;
120
+ exports.overlaps = overlaps;
121
+
122
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["InvariantViolationException","makeImmutable","makeImmutable","makeImmutable"],"sources":["../../src/core/domain/temporal/half-open-interval.ts","../../src/core/domain/temporal/transaction-time.ts","../../src/core/domain/temporal/valid-time.ts","../../src/core/domain/temporal/temporal-range.ts","../../src/core/domain/temporal/temporal-snapshot.ts"],"sourcesContent":["import { InvariantViolationException } from \"../../exceptions/invariant-violation-exception.js\";\nimport { assertValidDate } from \"../../shared/temporal-guards.js\";\n\n/**\n * Shared core of the bitemporal primitives: a half-open interval\n * `[start, end)` whose end, when present, must be strictly later than its\n * start. `ValidTime` and `TransactionTime` are the same shape under different\n * (deliberate) vocabularies — the invariant lives here once so the two files\n * cannot drift apart.\n *\n * Internal to `domain/temporal`; not exported from the barrel.\n */\nfunction assertHalfOpenInterval(\n startLabel: string,\n start: Date,\n endLabel: string,\n end: Date | undefined,\n): void {\n assertValidDate(startLabel, start);\n\n if (end === undefined) {\n return;\n }\n\n assertValidDate(endLabel, end);\n\n if (end.getTime() <= start.getTime()) {\n throw new InvariantViolationException(\n `${endLabel} must be later than ${startLabel}`,\n );\n }\n}\n\nexport { assertHalfOpenInterval };\n","import { makeImmutable } from \"../../shared/immutable.js\";\n\nimport { assertHalfOpenInterval } from \"./half-open-interval.js\";\n\n/**\n * Represents transaction time (Transaction Time).\n * Defines when the system learned about or recorded a piece of information.\n * Useful for auditing and reconstructing system state at a specific past moment.\n *\n * The window is half-open — `recordedAt` inclusive, `supersededAt` exclusive —\n * and strictly non-empty: `supersededAt` must be later than `recordedAt`, so a\n * record superseded in the same instant it was written is not representable.\n *\n * One caveat mirrors {@link ValueObject}: `createTransactionTime` clones the\n * input dates (no aliasing) but the inner `Date`s are NOT frozen —\n * `Object.freeze` cannot block `setTime`/`setFullYear`, so a caller can still\n * mutate `recordedAt` in place and corrupt the audit record after creation.\n * `readonly` only prevents reassignment. Treat the dates as read-only, or keep\n * instants as ISO/epoch in your own state when that guarantee matters.\n */\ninterface TransactionTime {\n /** When the information was first recorded in the system. */\n readonly recordedAt: Date;\n /** When this information was superseded or invalidated by a newer version. */\n readonly supersededAt?: Date;\n}\n\ntype CreateTransactionTimeInput = TransactionTime;\n\nfunction assertTransactionTime(\n txTime: TransactionTime,\n fieldName: string = \"txTime\",\n): void {\n assertHalfOpenInterval(\n `${fieldName}.recordedAt`,\n txTime.recordedAt,\n `${fieldName}.supersededAt`,\n txTime.supersededAt,\n );\n}\n\nfunction createTransactionTime(\n input: CreateTransactionTimeInput,\n): TransactionTime {\n assertTransactionTime(input, \"txTime\");\n\n if (input.supersededAt === undefined) {\n return makeImmutable({\n recordedAt: input.recordedAt,\n });\n }\n\n return makeImmutable({\n recordedAt: input.recordedAt,\n supersededAt: input.supersededAt,\n });\n}\n\nexport {\n assertTransactionTime,\n createTransactionTime,\n type CreateTransactionTimeInput,\n type TransactionTime,\n};\n","import { makeImmutable } from \"../../shared/immutable.js\";\n\nimport { assertHalfOpenInterval } from \"./half-open-interval.js\";\n\n/**\n * Represents business time (Valid Time).\n * Defines when a piece of information is considered true or in effect in the real world.\n *\n * The window is half-open — `from` inclusive, `to` exclusive — and strictly\n * non-empty: `to` must be later than `from`, so a zero-duration range `[t, t)`\n * is deliberately not representable. Model an instantaneous event as an open\n * range closed by the next fact, not as an empty window.\n *\n * One caveat mirrors {@link ValueObject}: `createValidTime` clones the input\n * dates (no aliasing) but the inner `Date`s are NOT frozen — `Object.freeze`\n * cannot block `setTime`/`setFullYear`, so a caller can still mutate `from`\n * in place and corrupt the range after creation. `readonly` only prevents\n * reassignment. Treat the dates as read-only, or keep instants as ISO/epoch in\n * your own state when that guarantee matters.\n */\ninterface ValidTime {\n /** Start of the validity window (inclusive). */\n readonly from: Date;\n /** End of the validity window (exclusive). When absent, the information is still in effect. */\n readonly to?: Date;\n}\n\ntype CreateValidTimeInput = ValidTime;\n\nfunction assertValidTime(\n validTime: ValidTime,\n fieldName: string = \"validTime\",\n): void {\n assertHalfOpenInterval(\n `${fieldName}.from`,\n validTime.from,\n `${fieldName}.to`,\n validTime.to,\n );\n}\n\nfunction createValidTime(input: CreateValidTimeInput): ValidTime {\n assertValidTime(input, \"validTime\");\n\n if (input.to === undefined) {\n return makeImmutable({\n from: input.from,\n });\n }\n\n return makeImmutable({\n from: input.from,\n to: input.to,\n });\n}\n\nexport {\n assertValidTime,\n createValidTime,\n type CreateValidTimeInput,\n type ValidTime,\n};\n","import { assertValidDate } from \"../../shared/temporal-guards.js\";\n\nimport { assertValidTime, type ValidTime } from \"./valid-time.js\";\n\n/**\n * Checks whether a temporal range is \"open\" (has no end date).\n * Useful for identifying information that is still in effect / active.\n */\nfunction isOpen(range: ValidTime): boolean {\n assertValidTime(range, \"range\");\n\n return range.to === undefined;\n}\n\n/**\n * Checks whether a temporal range is \"closed\" (has a defined end date).\n */\nfunction isClosed(range: ValidTime): boolean {\n return !isOpen(range);\n}\n\n/**\n * Checks whether a specific date is contained within the temporal range.\n * The lower bound (`from`) is inclusive, while the upper bound (`to`) is exclusive.\n */\nfunction contains(range: ValidTime, date: Date): boolean {\n assertValidTime(range, \"range\");\n assertValidDate(\"date\", date);\n\n const fromTime = range.from.getTime();\n const toTime = range.to?.getTime() ?? Number.POSITIVE_INFINITY;\n const targetTime = date.getTime();\n\n return targetTime >= fromTime && targetTime < toTime;\n}\n\n/**\n * Checks whether two temporal ranges overlap at any point.\n * Useful for validating whether a new rule conflicts with an existing one.\n */\nfunction overlaps(left: ValidTime, right: ValidTime): boolean {\n assertValidTime(left, \"left\");\n assertValidTime(right, \"right\");\n\n const leftFrom = left.from.getTime();\n const leftTo = left.to?.getTime() ?? Number.POSITIVE_INFINITY;\n const rightFrom = right.from.getTime();\n const rightTo = right.to?.getTime() ?? Number.POSITIVE_INFINITY;\n\n return leftFrom < rightTo && rightFrom < leftTo;\n}\n\nexport { contains, isClosed, isOpen, overlaps };\n","import { type DeepReadonly, makeImmutable } from \"../../shared/immutable.js\";\n\nimport {\n createTransactionTime,\n type CreateTransactionTimeInput,\n type TransactionTime,\n} from \"./transaction-time.js\";\nimport {\n createValidTime,\n type CreateValidTimeInput,\n type ValidTime,\n} from \"./valid-time.js\";\n\n/**\n * Pairs a domain datum with its time dimensions (Business and Transaction).\n * It is the representation of an entry in the append-only (historical) table.\n *\n * `data` must be plain, structured-cloneable state — the primitive shape of an\n * aggregate, not the aggregate itself. `createTemporalSnapshot` deep-clones it\n * via `structuredClone`: functions and symbols inside `data` throw an\n * `InvariantViolationException`, and class instances (a `ValueObject`, an\n * `Entity`) are NOT rejected — they are silently flattened to plain objects,\n * losing their prototype (and with it `equals`/`toPrimitive`). Project rich\n * objects down first, e.g. with `toPrimitive()`.\n */\ninterface TemporalSnapshot<T> {\n /** The data or state captured by the snapshot. */\n readonly data: DeepReadonly<T>;\n /** Period during which this datum was valid in the real world. */\n readonly validTime: ValidTime;\n /** Period during which this record was the state known to the system. */\n readonly txTime: TransactionTime;\n}\n\ninterface CreateTemporalSnapshotInput<T> {\n readonly data: T;\n readonly validTime: CreateValidTimeInput;\n readonly txTime: CreateTransactionTimeInput;\n}\n\nfunction createTemporalSnapshot<T>(\n input: CreateTemporalSnapshotInput<T>,\n): TemporalSnapshot<T> {\n // The time dimensions come out of their factories already cloned and\n // frozen; only `data` still needs the clone+freeze. Freezing the shell by\n // hand avoids a second structuredClone pass over the whole snapshot.\n return Object.freeze({\n data: makeImmutable(input.data),\n validTime: createValidTime(input.validTime),\n txTime: createTransactionTime(input.txTime),\n });\n}\n\nexport {\n createTemporalSnapshot,\n type CreateTemporalSnapshotInput,\n type TemporalSnapshot,\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAYA,SAAS,uBACL,YACA,OACA,UACA,KACI;CACJ,wBAAA,gBAAgB,YAAY,KAAK;CAEjC,IAAI,QAAQ,KAAA,GACR;CAGJ,wBAAA,gBAAgB,UAAU,GAAG;CAE7B,IAAI,IAAI,QAAQ,KAAK,MAAM,QAAQ,GAC/B,MAAM,IAAIA,sCAAAA,4BACN,GAAG,SAAS,sBAAsB,YACtC;AAER;;;ACFA,SAAS,sBACL,QACA,YAAoB,UAChB;CACJ,uBACI,GAAG,UAAU,cACb,OAAO,YACP,GAAG,UAAU,gBACb,OAAO,YACX;AACJ;AAEA,SAAS,sBACL,OACe;CACf,sBAAsB,OAAO,QAAQ;CAErC,IAAI,MAAM,iBAAiB,KAAA,GACvB,OAAOC,kBAAAA,cAAc,EACjB,YAAY,MAAM,WACtB,CAAC;CAGL,OAAOA,kBAAAA,cAAc;EACjB,YAAY,MAAM;EAClB,cAAc,MAAM;CACxB,CAAC;AACL;;;AC3BA,SAAS,gBACL,WACA,YAAoB,aAChB;CACJ,uBACI,GAAG,UAAU,QACb,UAAU,MACV,GAAG,UAAU,MACb,UAAU,EACd;AACJ;AAEA,SAAS,gBAAgB,OAAwC;CAC7D,gBAAgB,OAAO,WAAW;CAElC,IAAI,MAAM,OAAO,KAAA,GACb,OAAOC,kBAAAA,cAAc,EACjB,MAAM,MAAM,KAChB,CAAC;CAGL,OAAOA,kBAAAA,cAAc;EACjB,MAAM,MAAM;EACZ,IAAI,MAAM;CACd,CAAC;AACL;;;;;;;AC9CA,SAAS,OAAO,OAA2B;CACvC,gBAAgB,OAAO,OAAO;CAE9B,OAAO,MAAM,OAAO,KAAA;AACxB;;;;AAKA,SAAS,SAAS,OAA2B;CACzC,OAAO,CAAC,OAAO,KAAK;AACxB;;;;;AAMA,SAAS,SAAS,OAAkB,MAAqB;CACrD,gBAAgB,OAAO,OAAO;CAC9B,wBAAA,gBAAgB,QAAQ,IAAI;CAE5B,MAAM,WAAW,MAAM,KAAK,QAAQ;CACpC,MAAM,SAAS,MAAM,IAAI,QAAQ,KAAK,OAAO;CAC7C,MAAM,aAAa,KAAK,QAAQ;CAEhC,OAAO,cAAc,YAAY,aAAa;AAClD;;;;;AAMA,SAAS,SAAS,MAAiB,OAA2B;CAC1D,gBAAgB,MAAM,MAAM;CAC5B,gBAAgB,OAAO,OAAO;CAE9B,MAAM,WAAW,KAAK,KAAK,QAAQ;CACnC,MAAM,SAAS,KAAK,IAAI,QAAQ,KAAK,OAAO;CAC5C,MAAM,YAAY,MAAM,KAAK,QAAQ;CAGrC,OAAO,YAFS,MAAM,IAAI,QAAQ,KAAK,OAAO,sBAEjB,YAAY;AAC7C;;;ACVA,SAAS,uBACL,OACmB;CAInB,OAAO,OAAO,OAAO;EACjB,MAAMC,kBAAAA,cAAc,MAAM,IAAI;EAC9B,WAAW,gBAAgB,MAAM,SAAS;EAC1C,QAAQ,sBAAsB,MAAM,MAAM;CAC9C,CAAC;AACL"}
@@ -1,4 +1,28 @@
1
1
  import { t as DeepReadonly } from "../immutable.cjs";
2
2
  import { n as ValueObjectPluginContract, t as ValueObject } from "../value-object.cjs";
3
+ import { a as ValidTime, c as CreateTransactionTimeInput, d as createTransactionTime, i as CreateValidTimeInput, l as TransactionTime, n as TemporalSnapshot, o as assertValidTime, r as createTemporalSnapshot, s as createValidTime, t as CreateTemporalSnapshotInput, u as assertTransactionTime } from "../temporal-snapshot.cjs";
3
4
  import { n as Entity, r as EntityState, t as UuidIdentifier } from "../uuid-identifier.cjs";
4
- export { type DeepReadonly, Entity, type EntityState, UuidIdentifier, ValueObject, type ValueObjectPluginContract };
5
+
6
+ //#region src/core/domain/temporal/temporal-range.d.ts
7
+ /**
8
+ * Checks whether a temporal range is "open" (has no end date).
9
+ * Useful for identifying information that is still in effect / active.
10
+ */
11
+ declare function isOpen(range: ValidTime): boolean;
12
+ /**
13
+ * Checks whether a temporal range is "closed" (has a defined end date).
14
+ */
15
+ declare function isClosed(range: ValidTime): boolean;
16
+ /**
17
+ * Checks whether a specific date is contained within the temporal range.
18
+ * The lower bound (`from`) is inclusive, while the upper bound (`to`) is exclusive.
19
+ */
20
+ declare function contains(range: ValidTime, date: Date): boolean;
21
+ /**
22
+ * Checks whether two temporal ranges overlap at any point.
23
+ * Useful for validating whether a new rule conflicts with an existing one.
24
+ */
25
+ declare function overlaps(left: ValidTime, right: ValidTime): boolean;
26
+ //#endregion
27
+ export { CreateTemporalSnapshotInput, CreateTransactionTimeInput, CreateValidTimeInput, type DeepReadonly, Entity, type EntityState, TemporalSnapshot, TransactionTime, UuidIdentifier, ValidTime, ValueObject, type ValueObjectPluginContract, assertTransactionTime, assertValidTime, contains, createTemporalSnapshot, createTransactionTime, createValidTime, isClosed, isOpen, overlaps };
28
+ //# sourceMappingURL=index.d.cts.map