@cullet/erp-core 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -24
- package/dist/gate-engine-registry.js.map +1 -1
- package/dist/gate-v1-payload.schema.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/outcome.js.map +1 -1
- package/dist/policies/engines/v1/gate/index.js.map +1 -1
- package/dist/policy-service.js.map +1 -1
- package/dist/validation-code.js.map +1 -1
- package/dist/validation-error.js.map +1 -1
- package/dist/validation-field.js.map +1 -1
- package/meta.json +67 -62
- package/package.json +56 -56
- package/src/core/application/commands/command.ts +3 -3
- package/src/core/application/commands/requested-by.ts +60 -60
- package/src/core/application/index.ts +21 -21
- package/src/core/application/policy-error-mapper.ts +54 -54
- package/src/core/application/ports/index.ts +6 -6
- package/src/core/application/ports/logger.port.ts +4 -4
- package/src/core/application/ports/metrics.port.ts +3 -3
- package/src/core/application/ports/policy-port.ts +7 -7
- package/src/core/application/ports/repository.port.ts +3 -3
- package/src/core/application/ports/temporal-repository.port.ts +4 -4
- package/src/core/application/ports/tracer.port.ts +7 -7
- package/src/core/application/queries/query.ts +13 -13
- package/src/core/application/temporal/index.ts +7 -7
- package/src/core/application/temporal/temporal-context.ts +20 -20
- package/src/core/application/temporal/temporal-use-case.ts +22 -22
- package/src/core/application/use-case.ts +10 -10
- package/src/core/config/core-config.instance.ts +1 -1
- package/src/core/config/core-config.ts +59 -59
- package/src/core/config/index.ts +6 -6
- package/src/core/config/policy-reporter.ts +31 -31
- package/src/core/config/silent-policy-reporter.ts +1 -1
- package/src/core/domain/entity.ts +44 -44
- package/src/core/domain/rulesets/entity-ruleset.contracts.ts +6 -6
- package/src/core/domain/rulesets/ruleset-registry.ts +49 -49
- package/src/core/domain/rulesets/ruleset.contracts.ts +6 -6
- package/src/core/domain/rulesets/value-object-ruleset.contracts.ts +5 -5
- package/src/core/domain/temporal/index.ts +11 -11
- package/src/core/domain/temporal/temporal-range.ts +16 -16
- package/src/core/domain/temporal/temporal-snapshot.ts +24 -24
- package/src/core/domain/temporal/transaction-time.ts +30 -30
- package/src/core/domain/temporal/valid-time.ts +29 -29
- package/src/core/domain/value-object.ts +16 -16
- package/src/core/errors/app-error.ts +64 -64
- package/src/core/errors/authentication-error.ts +134 -134
- package/src/core/errors/authorization-error.ts +154 -154
- package/src/core/errors/business-rule-violation-error.ts +15 -15
- package/src/core/errors/conflict-error.ts +202 -201
- package/src/core/errors/error-codes.ts +48 -48
- package/src/core/errors/idempotency-error.ts +324 -320
- package/src/core/errors/index.ts +50 -50
- package/src/core/errors/integration-error.ts +120 -120
- package/src/core/errors/legacy-incompatible-error.ts +13 -13
- package/src/core/errors/not-found-error.ts +14 -14
- package/src/core/errors/serialization-error.ts +167 -167
- package/src/core/errors/temporal-error.ts +109 -107
- package/src/core/errors/types.ts +35 -35
- package/src/core/errors/unexpected-error.ts +10 -10
- package/src/core/errors/utils/index.ts +2 -2
- package/src/core/errors/utils/json-safe.ts +53 -53
- package/src/core/errors/validation-error.ts +18 -18
- package/src/core/exceptions/business-rule-violation-exception.ts +6 -6
- package/src/core/exceptions/domain-exception.ts +5 -5
- package/src/core/exceptions/entity-not-found-exception.ts +6 -6
- package/src/core/exceptions/invalid-state-transition-exception.ts +8 -8
- package/src/core/exceptions/invariant-violation-exception.ts +3 -3
- package/src/core/exceptions/validation-code.ts +35 -29
- package/src/core/exceptions/validation-exception.ts +19 -19
- package/src/core/exceptions/validation-field.ts +20 -19
- package/src/core/index.ts +7 -7
- package/src/core/policies/asof/asof.ts +47 -47
- package/src/core/policies/catalog/catalog.instance.ts +8 -6
- package/src/core/policies/catalog/index.ts +4 -4
- package/src/core/policies/catalog/policy-catalog-entry.ts +199 -197
- package/src/core/policies/catalog/policy-catalog.ts +101 -101
- package/src/core/policies/catalog/policy-key.ts +51 -51
- package/src/core/policies/context/context-builder.ts +335 -313
- package/src/core/policies/context/context-registry.instance.ts +9 -9
- package/src/core/policies/context/context-registry.ts +61 -61
- package/src/core/policies/context/context-resolver.ts +12 -12
- package/src/core/policies/context/context-seed.ts +19 -15
- package/src/core/policies/context/index.ts +9 -9
- package/src/core/policies/context/path.ts +135 -128
- package/src/core/policies/defs/in-memory-policy-definition-repo.ts +56 -55
- package/src/core/policies/defs/index.ts +10 -10
- package/src/core/policies/defs/policy-definition-repository.ts +3 -3
- package/src/core/policies/defs/policy-definition.ts +143 -142
- package/src/core/policies/defs/policy-scope.ts +21 -19
- package/src/core/policies/defs/policy-semver.ts +51 -51
- package/src/core/policies/engines/compute-engine-registry.ts +43 -43
- package/src/core/policies/engines/compute-evaluator-registry.ts +20 -20
- package/src/core/policies/engines/compute-registry.ts +45 -45
- package/src/core/policies/engines/compute-types.ts +15 -15
- package/src/core/policies/engines/condition-evaluator-reporter.ts +17 -17
- package/src/core/policies/engines/gate-engine-registry.ts +27 -25
- package/src/core/policies/engines/gate-types.ts +28 -28
- package/src/core/policies/engines/index.ts +28 -28
- package/src/core/policies/engines/parse-compute-payload.ts +51 -45
- package/src/core/policies/engines/parse-gate-payload.ts +42 -42
- package/src/core/policies/engines/v1/compute/compute-engine-v1.ts +39 -37
- package/src/core/policies/engines/v1/compute/compute-payload.schema.ts +43 -41
- package/src/core/policies/engines/v1/compute/index.ts +6 -6
- package/src/core/policies/engines/v1/compute/resolve-decision-table-v1.ts +41 -39
- package/src/core/policies/engines/v1/condition-evaluator.ts +547 -505
- package/src/core/policies/engines/v1/condition-schema.ts +35 -35
- package/src/core/policies/engines/v1/condition-types.ts +21 -21
- package/src/core/policies/engines/v1/gate/gate-engine-v1.ts +134 -130
- package/src/core/policies/engines/v1/gate/gate-types-v1.ts +5 -5
- package/src/core/policies/engines/v1/gate/gate-v1-payload.schema.ts +32 -30
- package/src/core/policies/engines/v1/gate/index.ts +4 -4
- package/src/core/policies/engines/v1/index.ts +8 -8
- package/src/core/policies/index.ts +72 -72
- package/src/core/policies/package/policy-package.ts +3 -3
- package/src/core/policies/policy-ids.ts +25 -25
- package/src/core/policies/resolver/policy-resolver.ts +34 -34
- package/src/core/policies/service/index.ts +6 -6
- package/src/core/policies/service/policy-evaluation-error.ts +141 -133
- package/src/core/policies/service/policy-service.ts +432 -419
- package/src/core/policies/utils/date.ts +3 -3
- package/src/core/policies/utils/hash.ts +61 -61
- package/src/core/result/outcome.ts +131 -126
- package/src/core/result/result.ts +130 -127
- package/src/core/shared/aggregate-version.ts +5 -5
- package/src/core/shared/hashing.ts +18 -18
- package/src/core/shared/immutable.ts +29 -29
- package/src/core/shared/temporal-guards.ts +9 -9
- package/src/core/versioning/domain-event-contracts.ts +40 -40
- package/src/core/versioning/version.ts +19 -19
- package/src/examples/rulesets/entity/order-creation-rules-v1.ts +18 -18
- package/src/examples/rulesets/entity/order-invariants-v1.ts +31 -29
- package/src/examples/rulesets/entity/order-invariants-v2.ts +12 -12
- package/src/examples/rulesets/entity/order.ts +127 -127
- package/src/examples/rulesets/value-object/cpf-rules-v1.ts +41 -39
- package/src/examples/rulesets/value-object/cpf-rules-v2.ts +14 -12
- package/src/examples/rulesets/value-object/cpf.ts +24 -24
- package/src/examples/rulesets/value-object/customer.ts +42 -39
- package/src/examples/rulesets/value-object/person-name-rules-v1.ts +27 -27
- package/src/examples/rulesets/value-object/person-name-rules-v2.ts +13 -13
- package/src/examples/rulesets/value-object/person-name.ts +29 -26
- package/src/index.ts +2 -2
- package/src/version.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../../src/core/policies/engines/v1/gate/gate-engine-v1.ts"],"sourcesContent":["import { type CoreConfig, coreConfig } from \"../../../../config\";\nimport { Outcome } from \"../../../../result/outcome\";\nimport { Result } from \"../../../../result/result\";\n\nimport {\n
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../../src/core/policies/engines/v1/gate/gate-engine-v1.ts"],"sourcesContent":["import { type CoreConfig, coreConfig } from \"../../../../config\";\nimport { Outcome } from \"../../../../result/outcome\";\nimport { Result } from \"../../../../result/result\";\n\nimport {\n ConditionEvaluatorV1,\n type TracedConditionEvaluation,\n} from \"../condition-evaluator\";\nimport type { ConditionLeafNode, ConditionNode } from \"../condition-types\";\nimport type { GatePayload } from \"../../gate-payload\";\nimport type {\n GateOutcome,\n GateStatus,\n GateTraceLeafSnapshot,\n GateTraceNodeSnapshot,\n PolicyContext,\n PolicyViolation,\n VersionedGateEngine,\n} from \"../../gate-types\";\n\n// ─── Gate engine v1 ─────────────────────────────────────────────────────────\n\nexport class GateEngineV1 implements VersionedGateEngine {\n public readonly version = 1;\n private readonly coreConfig: CoreConfig;\n\n constructor(params: { readonly coreConfig?: CoreConfig } = {}) {\n this.coreConfig = params.coreConfig ?? coreConfig;\n }\n\n private allow(): Result<GateOutcome, string> {\n return Result.ok(Outcome.of(\"ALLOW\", { violations: [] }));\n }\n\n private deny(violation: PolicyViolation): Result<GateOutcome, string> {\n return Result.ok(\n Outcome.of(\"DENY\", {\n violations: [violation],\n }),\n );\n }\n\n private outcomeFromStatus(\n status: GateStatus,\n violation: PolicyViolation,\n ): Result<GateOutcome, string> {\n return status === \"ALLOW\" ? this.allow() : this.deny(violation);\n }\n\n private isLeafNode(node: ConditionNode): node is ConditionLeafNode {\n return \"field\" in node && \"op\" in node;\n }\n\n private toLeafSnapshot(node: ConditionLeafNode): GateTraceLeafSnapshot {\n return {\n kind: \"LEAF\",\n field: node.field,\n op: node.op,\n ...(node.allowNull === true ? { allowNull: true } : {}),\n };\n }\n\n private toNodeSnapshot(node: ConditionNode): GateTraceNodeSnapshot {\n if (this.isLeafNode(node)) {\n return this.toLeafSnapshot(node);\n }\n\n if (\"and\" in node) {\n return {\n kind: \"AND\",\n childCount: node.and.length,\n };\n }\n\n if (\"or\" in node) {\n return {\n kind: \"OR\",\n childCount: node.or.length,\n };\n }\n\n return {\n kind: \"NOT\",\n };\n }\n\n private buildDenyViolation(\n conditionResult: TracedConditionEvaluation,\n ): PolicyViolation {\n return {\n code: \"DENY_CONDITION_MET\",\n message: `Gate denied at ${conditionResult.trace.conditionPath}`,\n trace: {\n conditionPath: conditionResult.trace.conditionPath,\n decisiveNode: this.toNodeSnapshot(\n conditionResult.trace.decisiveNode,\n ),\n lastEvaluatedLeaf: this.toLeafSnapshot(\n conditionResult.trace.lastEvaluatedLeaf,\n ),\n lastEvaluatedLeafPath:\n conditionResult.trace.lastEvaluatedLeafPath,\n lastEvaluatedLeafResult:\n conditionResult.trace.lastEvaluatedLeafResult,\n field: conditionResult.trace.lastEvaluatedLeaf.field,\n op: conditionResult.trace.lastEvaluatedLeaf.op,\n },\n };\n }\n\n private normalizePayload(payload: GatePayload): {\n readonly allowIf: ConditionNode;\n readonly defaultOutcome: \"ALLOW\" | \"DENY\";\n } {\n if (\"condition\" in payload) {\n return {\n allowIf: payload.condition,\n defaultOutcome: \"DENY\",\n };\n }\n\n return payload;\n }\n\n /**\n * Evaluates a GATE payload against a context object.\n * Pure function — no side effects.\n *\n * Receives an already-parsed `GatePayload`; the registry is responsible\n * for parsing from raw `unknown` before calling this method.\n * Returns Result for technical failures (condition evaluation errors).\n * The Outcome inside carries the business decision (ALLOW/DENY).\n */\n evaluate(\n payload: GatePayload,\n context: PolicyContext,\n ): Result<GateOutcome, string> {\n const gatePayload = this.normalizePayload(payload);\n const conditionEvaluator = new ConditionEvaluatorV1(\n context,\n this.coreConfig.getConditionEvaluationOptions(this.version),\n );\n\n const isAllowedResult = conditionEvaluator.evaluateWithTrace(\n gatePayload.allowIf,\n );\n if (isAllowedResult.isErr()) {\n return Result.err(isAllowedResult.errorOrNull()!);\n }\n\n const isAllowed = isAllowedResult.getOrNull()!;\n if (isAllowed.matched) {\n return this.allow();\n }\n\n return this.outcomeFromStatus(\n gatePayload.defaultOutcome,\n this.buildDenyViolation(isAllowed),\n );\n }\n}\n"],"mappings":";;;AAsBA,IAAa,eAAb,MAAyD;CAIrD,YAAY,SAA+C,CAAC,GAAG;iBAHrC;EAItB,KAAK,aAAa,OAAO,cAAc;CAC3C;CAEA,QAA6C;EACzC,OAAO,OAAO,GAAG,QAAQ,GAAG,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;CAC5D;CAEA,KAAa,WAAyD;EAClE,OAAO,OAAO,GACV,QAAQ,GAAG,QAAQ,EACf,YAAY,CAAC,SAAS,EAC1B,CAAC,CACL;CACJ;CAEA,kBACI,QACA,WAC2B;EAC3B,OAAO,WAAW,UAAU,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS;CAClE;CAEA,WAAmB,MAAgD;EAC/D,OAAO,WAAW,QAAQ,QAAQ;CACtC;CAEA,eAAuB,MAAgD;EACnE,OAAO;GACH,MAAM;GACN,OAAO,KAAK;GACZ,IAAI,KAAK;GACT,GAAI,KAAK,cAAc,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;EACzD;CACJ;CAEA,eAAuB,MAA4C;EAC/D,IAAI,KAAK,WAAW,IAAI,GACpB,OAAO,KAAK,eAAe,IAAI;EAGnC,IAAI,SAAS,MACT,OAAO;GACH,MAAM;GACN,YAAY,KAAK,IAAI;EACzB;EAGJ,IAAI,QAAQ,MACR,OAAO;GACH,MAAM;GACN,YAAY,KAAK,GAAG;EACxB;EAGJ,OAAO,EACH,MAAM,MACV;CACJ;CAEA,mBACI,iBACe;EACf,OAAO;GACH,MAAM;GACN,SAAS,kBAAkB,gBAAgB,MAAM;GACjD,OAAO;IACH,eAAe,gBAAgB,MAAM;IACrC,cAAc,KAAK,eACf,gBAAgB,MAAM,YAC1B;IACA,mBAAmB,KAAK,eACpB,gBAAgB,MAAM,iBAC1B;IACA,uBACI,gBAAgB,MAAM;IAC1B,yBACI,gBAAgB,MAAM;IAC1B,OAAO,gBAAgB,MAAM,kBAAkB;IAC/C,IAAI,gBAAgB,MAAM,kBAAkB;GAChD;EACJ;CACJ;CAEA,iBAAyB,SAGvB;EACE,IAAI,eAAe,SACf,OAAO;GACH,SAAS,QAAQ;GACjB,gBAAgB;EACpB;EAGJ,OAAO;CACX;;;;;;;;;;CAWA,SACI,SACA,SAC2B;EAC3B,MAAM,cAAc,KAAK,iBAAiB,OAAO;EAMjD,MAAM,kBAAkB,IALO,qBAC3B,SACA,KAAK,WAAW,8BAA8B,KAAK,OAAO,CAGrB,EAAE,kBACvC,YAAY,OAChB;EACA,IAAI,gBAAgB,MAAM,GACtB,OAAO,OAAO,IAAI,gBAAgB,YAAY,CAAE;EAGpD,MAAM,YAAY,gBAAgB,UAAU;EAC5C,IAAI,UAAU,SACV,OAAO,KAAK,MAAM;EAGtB,OAAO,KAAK,kBACR,YAAY,gBACZ,KAAK,mBAAmB,SAAS,CACrC;CACJ;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy-service.js","names":["#reporter","#evaluate","#reportSafely","#resolveCatalogFamily","#findCandidates","#executeEngine","#resolveCatalogVariant"],"sources":["../src/core/policies/utils/hash.ts","../src/core/exceptions/validation-exception.ts","../src/core/policies/policy-ids.ts","../src/core/policies/catalog/policy-catalog-entry.ts","../src/core/policies/catalog/policy-catalog.ts","../src/core/policies/catalog/catalog.instance.ts","../src/core/policies/catalog/policy-key.ts","../src/core/policies/defs/policy-scope.ts","../src/core/policies/defs/in-memory-policy-definition-repo.ts","../src/core/policies/defs/policy-semver.ts","../src/core/policies/defs/policy-definition.ts","../src/core/policies/context/context-builder.ts","../src/core/policies/context/context-registry.ts","../src/core/policies/context/context-registry.instance.ts","../src/core/policies/context/context-seed.ts","../src/core/policies/asof/asof.ts","../src/core/policies/resolver/policy-resolver.ts","../src/core/policies/service/policy-evaluation-error.ts","../src/core/policies/service/policy-service.ts"],"sourcesContent":["import { sha256Hex, stableStringify } from \"../../shared/hashing\";\nimport { isValidDate } from \"../../shared/temporal-guards\";\n\n/**\n * Produces a deterministic SHA-256 hex digest of a canonical JSON representation.\n * Object keys are sorted recursively so key order does not affect the hash.\n * Array item order is preserved on purpose; callers that treat arrays as sets\n * must normalize or sort them before hashing.\n *\n * Values that JSON.stringify would silently drop or coerce (undefined,\n * non-finite numbers, functions, symbols, bigint) are rejected up-front to\n * prevent semantically different payloads from collapsing to the same hash.\n */\nexport class PolicyHashing {\n static sha256(input: string): string {\n return sha256Hex(input);\n }\n\n private static assertHashable(value: unknown, path: string): void {\n if (value === null) {\n return;\n }\n\n const type = typeof value;\n\n if (type === \"undefined\") {\n throw new TypeError(\n `canonicalJson does not accept undefined values (at ${path})`,\n );\n }\n\n if (type === \"number\" && !Number.isFinite(value)) {\n throw new TypeError(\n `canonicalJson does not accept non-finite numbers (at ${path}, value: ${String(value)})`,\n );\n }\n\n if (type === \"bigint\" || type === \"function\" || type === \"symbol\") {\n throw new TypeError(\n `canonicalJson does not accept ${type} values (at ${path})`,\n );\n }\n\n if (type !== \"object\") {\n return;\n }\n\n if (value instanceof Date) {\n if (!isValidDate(value)) {\n throw new TypeError(\n `canonicalJson does not accept Invalid Date (at ${path})`,\n );\n }\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n PolicyHashing.assertHashable(item, `${path}[${index}]`);\n });\n return;\n }\n\n for (const [key, nested] of Object.entries(\n value as Record<string, unknown>,\n )) {\n PolicyHashing.assertHashable(nested, `${path}.${key}`);\n }\n }\n\n static canonicalJson(value: unknown): string {\n PolicyHashing.assertHashable(value, \"$\");\n\n return stableStringify(value);\n }\n\n static computePayloadHash(\n payload: unknown,\n policyKey: string,\n policyVersion: string,\n ): string {\n const canonical = PolicyHashing.canonicalJson({\n policyKey,\n policyVersion,\n payload,\n });\n\n return PolicyHashing.sha256(canonical);\n }\n}\n","import { DomainException } from \"./domain-exception\";\nimport { ValidationCode } from \"./validation-code\";\nimport { ValidationField } from \"./validation-field\";\n\nexport interface ValidationViolation {\n readonly field: ValidationField;\n readonly code: ValidationCode;\n readonly message: string;\n}\n\nclass ValidationException extends DomainException {\n constructor(\n public readonly field: ValidationField,\n public readonly code: ValidationCode,\n message: string,\n ) {\n super(message);\n }\n}\n\n// Carries multiple validation violations from a single operation (e.g. bulk validation).\n// Use when you need to report all field errors at once rather than failing on the first.\nclass MultipleValidationException extends DomainException {\n constructor(public readonly violations: readonly ValidationViolation[]) {\n super(violations.map((v) => v.message).join(\"; \"));\n }\n}\n\nclass InvalidValueException extends ValidationException {\n constructor(field: ValidationField, code: ValidationCode, message: string) {\n super(field, code, message);\n }\n}\n\nexport {\n InvalidValueException,\n MultipleValidationException,\n ValidationException,\n};\n","import { ValidationCode } from \"../exceptions/validation-code\";\nimport { InvalidValueException } from \"../exceptions/validation-exception\";\nimport { ValidationField } from \"../exceptions/validation-field\";\n\ntype Brand<TValue, TBrand extends string> = TValue & {\n readonly __brand: TBrand;\n};\n\nexport type PolicyDefinitionId = Brand<string, \"PolicyDefinitionId\">;\nexport type PolicyDecisionId = Brand<string, \"PolicyDecisionId\">;\nexport type TenantId = Brand<string, \"TenantId\">;\nexport type SchoolId = Brand<string, \"SchoolId\">;\n\nconst POLICY_DEFINITION_ID_FIELD = ValidationField.of(\"policyDefinitionId\");\nconst POLICY_DECISION_ID_FIELD = ValidationField.of(\"policyDecisionId\");\nconst TENANT_ID_FIELD = ValidationField.of(\"tenantId\");\nconst SCHOOL_ID_FIELD = ValidationField.of(\"schoolId\");\n\nfunction assertIdString(value: unknown, field: ValidationField): string {\n if (typeof value !== \"string\") {\n throw new InvalidValueException(\n field,\n ValidationCode.INVALID_FORMAT,\n `${field.value} must be a string, got ${typeof value}`,\n );\n }\n\n if (value.trim().length === 0) {\n throw new InvalidValueException(\n field,\n ValidationCode.BLANK,\n `${field.value} must be a non-empty string`,\n );\n }\n\n return value;\n}\n\nfunction brandId<TBrand extends string>(\n value: unknown,\n field: ValidationField,\n): Brand<string, TBrand> {\n return assertIdString(value, field) as Brand<string, TBrand>;\n}\n\nexport function asPolicyDefinitionId(value: string): PolicyDefinitionId {\n return brandId<\"PolicyDefinitionId\">(value, POLICY_DEFINITION_ID_FIELD);\n}\n\nexport function asPolicyDecisionId(value: string): PolicyDecisionId {\n return brandId<\"PolicyDecisionId\">(value, POLICY_DECISION_ID_FIELD);\n}\n\nexport function asTenantId(value: string): TenantId {\n return brandId<\"TenantId\">(value, TENANT_ID_FIELD);\n}\n\nexport function asSchoolId(value: string): SchoolId {\n return brandId<\"SchoolId\">(value, SCHOOL_ID_FIELD);\n}\n","import { UnexpectedError } from \"../../errors\";\n\nimport type {\n AsOfSource,\n PolicyKind,\n PolicyOwner,\n PolicyScopeLevel,\n} from \"./catalog-types\";\nimport type { PolicyKey } from \"./policy-key\";\n\n/**\n * Properties for creating a PolicyCatalogEntry.\n */\nexport interface PolicyCatalogEntryProps {\n readonly key: PolicyKey;\n readonly kind: PolicyKind;\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n readonly payloadSchemaVersion?: number;\n readonly owner: PolicyOwner;\n readonly allowedScopes: readonly PolicyScopeLevel[];\n readonly asOfSource: AsOfSource;\n /** Paths the context must contain for this policy to be evaluable. */\n readonly contextRequirements: readonly string[];\n readonly tags?: readonly string[];\n readonly description: string;\n}\n\n/**\n * Represents a single entry in the Policy Catalog.\n * Encapsulates metadata and validation logic for a policy.\n */\nexport class PolicyCatalogEntry {\n public readonly key: PolicyKey;\n public readonly kind: PolicyKind;\n\n public readonly gateEngineVersion?: number;\n public readonly computeEngineVersion?: number;\n public readonly payloadSchemaVersion?: number;\n\n public readonly owner: PolicyOwner;\n public readonly allowedScopes: readonly PolicyScopeLevel[];\n public readonly asOfSource: AsOfSource;\n public readonly contextRequirements: readonly string[];\n public readonly tags: readonly string[];\n public readonly description: string;\n\n constructor(props: PolicyCatalogEntryProps) {\n this.key = props.key;\n this.kind = props.kind;\n this.gateEngineVersion = props.gateEngineVersion;\n this.computeEngineVersion = props.computeEngineVersion;\n this.payloadSchemaVersion = props.payloadSchemaVersion;\n this.owner = props.owner;\n this.allowedScopes = [...props.allowedScopes];\n this.asOfSource = props.asOfSource;\n this.contextRequirements = [...props.contextRequirements];\n this.tags = [...(props.tags ?? [])];\n this.description = props.description;\n }\n\n static assertFamilyConsistency(entries: readonly PolicyCatalogEntry[]): void {\n if (entries.length === 0) {\n throw new UnexpectedError(\n \"Cannot validate an empty PolicyCatalogEntry family\",\n );\n }\n\n const [first, ...rest] = entries;\n for (const entry of rest) {\n if (!first.key.equals(entry.key)) {\n throw new UnexpectedError(\n \"Cannot merge PolicyCatalog entries with different keys\",\n );\n }\n\n if (first.kind !== entry.kind) {\n throw new UnexpectedError(\n `PolicyCatalog entries for key \"${first.key.toString()}\" must share the same kind`,\n );\n }\n\n if (first.owner !== entry.owner) {\n throw new UnexpectedError(\n `PolicyCatalog entries for key \"${first.key.toString()}\" must share the same owner`,\n );\n }\n\n if (first.asOfSource !== entry.asOfSource) {\n throw new UnexpectedError(\n `PolicyCatalog entries for key \"${first.key.toString()}\" must share the same asOfSource`,\n );\n }\n\n if (first.description !== entry.description) {\n throw new UnexpectedError(\n `PolicyCatalog entries for key \"${first.key.toString()}\" must share the same description`,\n );\n }\n }\n }\n\n static from(\n entry: PolicyCatalogEntry | PolicyCatalogEntryProps,\n ): PolicyCatalogEntry {\n return entry instanceof PolicyCatalogEntry\n ? entry\n : new PolicyCatalogEntry(entry);\n }\n\n isGate(): boolean {\n return this.kind === \"GATE\";\n }\n\n isCompute(): boolean {\n return this.kind === \"COMPUTE\";\n }\n\n allowsScope(scope: PolicyScopeLevel): boolean {\n return this.allowedScopes.includes(scope);\n }\n\n hasExplicitVersionSelector(): boolean {\n return (\n this.gateEngineVersion !== undefined ||\n this.computeEngineVersion !== undefined ||\n this.payloadSchemaVersion !== undefined\n );\n }\n\n matchesVersion(params: {\n readonly kind: PolicyKind;\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n readonly payloadSchemaVersion?: number;\n }): boolean {\n if (this.kind !== params.kind) {\n return false;\n }\n\n if (\n this.gateEngineVersion !== undefined &&\n this.gateEngineVersion !== params.gateEngineVersion\n ) {\n return false;\n }\n\n if (\n this.computeEngineVersion !== undefined &&\n this.computeEngineVersion !== params.computeEngineVersion\n ) {\n return false;\n }\n\n if (\n this.payloadSchemaVersion !== undefined &&\n this.payloadSchemaVersion !== params.payloadSchemaVersion\n ) {\n return false;\n }\n\n return true;\n }\n\n toVariantKey(): string {\n return [\n this.key.toString(),\n this.kind,\n this.gateEngineVersion ?? \"gate:any\",\n this.computeEngineVersion ?? \"compute:any\",\n this.payloadSchemaVersion ?? \"schema:any\",\n ].join(\"::\");\n }\n\n usesNowAsOf(): boolean {\n return this.asOfSource === \"NOW\";\n }\n\n usesCallerProvidedAsOf(): boolean {\n return this.asOfSource === \"CALLER_PROVIDED\";\n }\n\n requiresContext(path: string): boolean {\n return this.contextRequirements.includes(path);\n }\n\n requiresAllContexts(paths: readonly string[]): boolean {\n return paths.every((path) => this.requiresContext(path));\n }\n\n hasTag(tag: string): boolean {\n return this.tags.includes(tag);\n }\n\n equals(other: PolicyCatalogEntry): boolean {\n return this.key.equals(other.key);\n }\n\n toJSON(): PolicyCatalogEntryProps {\n return {\n key: this.key,\n kind: this.kind,\n ...(this.gateEngineVersion !== undefined\n ? { gateEngineVersion: this.gateEngineVersion }\n : {}),\n ...(this.computeEngineVersion !== undefined\n ? { computeEngineVersion: this.computeEngineVersion }\n : {}),\n ...(this.payloadSchemaVersion !== undefined\n ? { payloadSchemaVersion: this.payloadSchemaVersion }\n : {}),\n owner: this.owner,\n allowedScopes: [...this.allowedScopes],\n asOfSource: this.asOfSource,\n contextRequirements: [...this.contextRequirements],\n tags: this.tags.length > 0 ? [...this.tags] : undefined,\n description: this.description,\n };\n }\n}\n","import { UnexpectedError } from \"../../errors\";\nimport { Result } from \"../../result/result\";\n\nimport { PolicyCatalogEntry } from \"./policy-catalog-entry\";\n\n/**\n * In-code catalog of all known policies.\n * The catalog defines the universe of policies; the database cannot invent new ones.\n */\nexport class PolicyCatalog {\n private readonly versionedEntries: ReadonlyMap<string, PolicyCatalogEntry>;\n private readonly entriesByKey: ReadonlyMap<\n string,\n readonly PolicyCatalogEntry[]\n >;\n\n constructor(entries: readonly PolicyCatalogEntry[]) {\n const families = new Map<string, PolicyCatalogEntry[]>();\n const versionedMap = new Map<string, PolicyCatalogEntry>();\n\n for (const rawEntry of entries) {\n const entry = PolicyCatalogEntry.from(rawEntry);\n const key = entry.key.toString();\n const variantKey = entry.toVariantKey();\n\n if (versionedMap.has(variantKey)) {\n throw new UnexpectedError(\n `Duplicate PolicyCatalog entry for key \"${key}\" and variant \"${variantKey}\"`,\n );\n }\n\n const family = families.get(key) ?? [];\n family.push(entry);\n families.set(key, family);\n versionedMap.set(variantKey, entry);\n }\n\n for (const family of families.values()) {\n PolicyCatalogEntry.assertFamilyConsistency(family);\n }\n\n this.versionedEntries = versionedMap;\n this.entriesByKey = families;\n }\n\n get(key: string): Result<PolicyCatalogEntry, string> {\n const familyResult = this.getFamily(key);\n if (familyResult.isErr()) {\n return Result.err(familyResult.errorOrNull()!);\n }\n\n const family = familyResult.getOrNull()!;\n if (family.length > 1) {\n return Result.err(\n `Policy key \"${key}\" has multiple catalog variants; use getVersioned(...) or getFamily(...)`,\n );\n }\n\n const [entry] = family;\n if (!entry) {\n return Result.err(`Policy not found in catalog: \"${key}\"`);\n }\n\n return Result.ok(entry);\n }\n\n getFamily(key: string): Result<readonly PolicyCatalogEntry[], string> {\n const family = this.entriesByKey.get(key);\n if (!family) {\n return Result.err(`Policy not found in catalog: \"${key}\"`);\n }\n\n return Result.ok(family);\n }\n\n getVersioned(params: {\n readonly key: string;\n readonly kind: \"GATE\" | \"COMPUTE\";\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n readonly payloadSchemaVersion?: number;\n }): Result<PolicyCatalogEntry, string> {\n const family = this.entriesByKey.get(params.key);\n if (!family || family.length === 0) {\n return Result.err(`Policy not found in catalog: \"${params.key}\"`);\n }\n\n const exactMatch = family.find((entry) => entry.matchesVersion(params));\n if (exactMatch) {\n return Result.ok(exactMatch);\n }\n\n if (family.length === 1 && !family[0].hasExplicitVersionSelector()) {\n return Result.ok(family[0]);\n }\n\n const versionDetails = [\n params.kind,\n params.gateEngineVersion !== undefined\n ? `gateEngineVersion=${params.gateEngineVersion}`\n : null,\n params.computeEngineVersion !== undefined\n ? `computeEngineVersion=${params.computeEngineVersion}`\n : null,\n params.payloadSchemaVersion !== undefined\n ? `payloadSchemaVersion=${params.payloadSchemaVersion}`\n : null,\n ]\n .filter((part): part is string => part !== null)\n .join(\", \");\n\n return Result.err(\n `Policy variant not found in catalog: \"${params.key}\" (${versionDetails})`,\n );\n }\n\n list(): readonly PolicyCatalogEntry[] {\n return Array.from(this.versionedEntries.values());\n }\n\n has(key: string): boolean {\n return this.entriesByKey.has(key);\n }\n}\n","import type { PolicyPackage } from \"../package/policy-package\";\n\nimport { PolicyCatalog } from \"./policy-catalog\";\nimport { PolicyCatalogEntry } from \"./policy-catalog-entry\";\n\n// ─── Factory ────────────────────────────────────────────────────────────────\n\n/**\n * Aggregates catalog entries contributed by each module package into a single\n * PolicyCatalog. The core knows nothing about concrete modules — callers\n * are responsible for passing all relevant packages at composition time.\n */\nexport class PolicyCatalogFactory {\n static build(packages: readonly PolicyPackage[]): PolicyCatalog {\n const entries = packages.flatMap((policyPackage) =>\n Array.from(policyPackage.catalogEntries).map(PolicyCatalogEntry.from),\n );\n\n return new PolicyCatalog(entries);\n }\n}\n","import { Result } from \"../../result/result\";\n\n/**\n * PolicyKey value object.\n *\n * Format: `module.area.policy_name` (exactly 3 dot-separated segments).\n * - module: structural segment (lowercase alphanumeric + underscore, starting with a letter)\n * - area: structural segment (lowercase alphanumeric + underscore, starting with a letter)\n * - name: specific policy identifier (lowercase alphanumeric + underscore, starting with a letter)\n */\n\nconst SEGMENT_PATTERN = /^[a-z][a-z0-9_]*$/;\nconst MAX_POLICY_KEY_LENGTH = 255;\n\nexport class PolicyKey {\n public readonly module: string;\n public readonly area: string;\n public readonly name: string;\n\n private constructor(module: string, area: string, name: string) {\n this.module = module;\n this.area = area;\n this.name = name;\n Object.freeze(this);\n }\n\n static parse(raw: string): Result<PolicyKey, string> {\n if (!raw || typeof raw !== \"string\") {\n return Result.err(\"PolicyKey cannot be empty\");\n }\n\n if (raw.length > MAX_POLICY_KEY_LENGTH) {\n return Result.err(\n `PolicyKey cannot exceed ${MAX_POLICY_KEY_LENGTH} characters, got ${raw.length}`,\n );\n }\n\n const segments = raw.split(\".\");\n if (segments.length !== 3) {\n return Result.err(\n `PolicyKey must have exactly 3 segments (module.area.name), got ${segments.length}: \"${raw}\"`,\n );\n }\n\n const [rawModule, rawArea, name] = segments;\n\n if (!SEGMENT_PATTERN.test(rawModule)) {\n return Result.err(\n `PolicyKey segment \"module\" is invalid: \"${rawModule}\". ` +\n \"Must start with a lowercase letter and contain only [a-z0-9_].\",\n );\n }\n\n if (!SEGMENT_PATTERN.test(rawArea)) {\n return Result.err(\n `PolicyKey segment \"area\" is invalid: \"${rawArea}\". ` +\n \"Must start with a lowercase letter and contain only [a-z0-9_].\",\n );\n }\n\n if (!SEGMENT_PATTERN.test(name)) {\n return Result.err(\n `PolicyKey segment \"name\" is invalid: \"${name}\". ` +\n \"Must start with a lowercase letter and contain only [a-z0-9_].\",\n );\n }\n\n return Result.ok(new PolicyKey(rawModule, rawArea, name));\n }\n\n toString(): string {\n return `${this.module}.${this.area}.${this.name}`;\n }\n\n equals(other: PolicyKey): boolean {\n return this.toString() === other.toString();\n }\n}\n","import type { PolicyScopeLevel } from \"../catalog\";\nimport type { SchoolId, TenantId } from \"../policy-ids\";\n\n/**\n * Scope attached to a PolicyDefinition — defines where it applies.\n */\nexport interface PolicyScope {\n readonly level: PolicyScopeLevel;\n readonly tenantId: TenantId | null;\n readonly schoolId: SchoolId | null;\n}\n\n/**\n * Ordered list of scopes from most-specific to least-specific.\n * Used by the resolver to match definitions.\n *\n * Example:\n * ```\n * [\n * { level: 'SCHOOL', tenantId: 't1', schoolId: 's1' },\n * { level: 'TENANT', tenantId: 't1', schoolId: null },\n * { level: 'GLOBAL', tenantId: null, schoolId: null },\n * ]\n * ```\n */\nexport type ScopeChain = readonly PolicyScope[];\n\n/**\n * Numeric weight for scope specificity (higher = more specific).\n */\nconst SCOPE_WEIGHT: Record<PolicyScopeLevel, number> = {\n SCHOOL: 3,\n TENANT: 2,\n GLOBAL: 1,\n};\n\nexport class PolicyScopeMatcher {\n static weight(level: PolicyScopeLevel): number {\n return SCOPE_WEIGHT[level];\n }\n\n static matchesChain(defScope: PolicyScope, chain: ScopeChain): boolean {\n return chain.some((scope) => PolicyScopeMatcher.equals(defScope, scope));\n }\n\n static equals(a: PolicyScope, b: PolicyScope): boolean {\n return (\n a.level === b.level &&\n a.tenantId === b.tenantId &&\n a.schoolId === b.schoolId\n );\n }\n}\n","import type {\n FindCandidatesParams,\n PolicyDefinition,\n} from \"./policy-definition\";\nimport type { PolicyDefinitionRepository } from \"./policy-definition-repository\";\nimport { PolicyScopeMatcher } from \"./policy-scope\";\n\nexport class InMemoryPolicyDefinitionRepository implements PolicyDefinitionRepository {\n private readonly definitions: readonly PolicyDefinition[];\n private readonly definitionsByPolicyKey: ReadonlyMap<\n string,\n readonly PolicyDefinition[]\n >;\n\n constructor(definitions: readonly PolicyDefinition[]) {\n this.definitions = definitions;\n this.definitionsByPolicyKey = definitions.reduce<\n Map<string, PolicyDefinition[]>\n >((index, definition) => {\n const existingDefinitions = index.get(definition.policyKey) ?? [];\n existingDefinitions.push(definition);\n index.set(definition.policyKey, existingDefinitions);\n return index;\n }, new Map<string, PolicyDefinition[]>());\n }\n\n findCandidates(params: FindCandidatesParams): PolicyDefinition[] {\n const {\n policyKey,\n kind,\n payloadSchemaVersion,\n asOf,\n contextVersion,\n scopeChain,\n } = params;\n\n const candidatesForPolicyKey =\n this.definitionsByPolicyKey.get(policyKey) ?? [];\n\n const candidates = candidatesForPolicyKey.filter((def) => {\n // Match kind\n if (def.kind !== kind) return false;\n if (\n payloadSchemaVersion !== undefined &&\n def.payloadSchemaVersion !== payloadSchemaVersion\n ) {\n return false;\n }\n\n if (!def.enabled) return false;\n\n // Only PUBLISHED\n if (def.status !== \"PUBLISHED\") return false;\n\n // Effective date range (effectiveFrom <= asOf, and effectiveTo is null or > asOf)\n if (def.effectiveFrom > asOf) return false;\n if (def.effectiveTo !== null && def.effectiveTo <= asOf) return false;\n\n // Context version compatibility\n if (contextVersion < def.contextVersionMin) return false;\n if (contextVersion > def.contextVersionMax) return false;\n\n // Scope must match one of the chain entries\n if (!PolicyScopeMatcher.matchesChain(def.scope, scopeChain)) {\n return false;\n }\n\n return true;\n });\n\n return candidates;\n }\n}\n","// Semver without build metadata: comparisons are defined only over\n// major.minor.patch and optional pre-release identifiers (semver §11).\nexport const POLICY_SEMVER_PATTERN =\n /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\\+([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?$/;\n\ninterface ParsedSemver {\n major: number;\n minor: number;\n patch: number;\n preRelease: string | null;\n}\n\nfunction parseSemver(version: string): ParsedSemver {\n const withoutBuild = version.split(\"+\")[0];\n const [core, preRelease = null] = withoutBuild.split(\"-\") as [\n string,\n string | undefined,\n ];\n const [major, minor, patch] = core.split(\".\").map(Number) as [\n number,\n number,\n number,\n ];\n return { major, minor, patch, preRelease: preRelease ?? null };\n}\n\nfunction comparePreRelease(a: string, b: string): number {\n const aIds = a.split(\".\");\n const bIds = b.split(\".\");\n const len = Math.max(aIds.length, bIds.length);\n\n for (let i = 0; i < len; i++) {\n const ai = aIds[i];\n const bi = bIds[i];\n\n // Shorter pre-release has lower precedence when prefix matches (semver §11.4.4)\n if (ai === undefined) return -1;\n if (bi === undefined) return 1;\n\n const aNum = Number(ai);\n const bNum = Number(bi);\n const aIsNum = !Number.isNaN(aNum);\n const bIsNum = !Number.isNaN(bNum);\n\n // Numeric identifiers always have lower precedence than alphanumeric (semver §11.4.1)\n if (aIsNum && !bIsNum) return -1;\n if (!aIsNum && bIsNum) return 1;\n\n if (aIsNum && bIsNum) {\n if (aNum !== bNum) return aNum - bNum;\n } else {\n if (ai < bi) return -1;\n if (ai > bi) return 1;\n }\n }\n\n return 0;\n}\n\n/**\n * Compares two valid semver strings.\n * Returns a negative number if a < b, 0 if a === b, positive if a > b.\n *\n * Callers are expected to pass only strings that already passed\n * `POLICY_SEMVER_PATTERN` validation (i.e. values stored in PolicyDefinition).\n */\nexport function comparePolicySemver(a: string, b: string): number {\n const av = parseSemver(a);\n const bv = parseSemver(b);\n\n if (av.major !== bv.major) return av.major - bv.major;\n if (av.minor !== bv.minor) return av.minor - bv.minor;\n if (av.patch !== bv.patch) return av.patch - bv.patch;\n\n // Release > pre-release (semver §11.3)\n if (av.preRelease === null && bv.preRelease !== null) return 1;\n if (av.preRelease !== null && bv.preRelease === null) return -1;\n if (av.preRelease !== null && bv.preRelease !== null) {\n return comparePreRelease(av.preRelease, bv.preRelease);\n }\n\n return 0;\n}\n","import { InvariantViolationException } from \"../../exceptions/invariant-violation-exception\";\nimport type { PolicyKind } from \"../catalog\";\nimport type { PolicyDefinitionId } from \"../policy-ids\";\n\nimport type { AnyPolicyPayload } from \"./policy-payload.contracts\";\nimport type { PolicyScope } from \"./policy-scope\";\nimport { POLICY_SEMVER_PATTERN } from \"./policy-semver\";\n\n// ─── Status ────────────────────────────────────────────────────────────────\n\nexport type PolicyDefinitionStatus = \"DRAFT\" | \"PUBLISHED\" | \"RETIRED\";\n\n// ─── Definition props ───────────────────────────────────────────────────────\n\nexport interface BasePolicyDefinitionProps<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> {\n readonly id: PolicyDefinitionId;\n readonly policyKey: K;\n readonly policyVersion: string; // semver\n readonly payloadSchemaVersion: number;\n readonly contextVersionMin: number;\n readonly contextVersionMax: number;\n readonly enabled: boolean;\n readonly status: PolicyDefinitionStatus;\n readonly scope: PolicyScope;\n readonly effectiveFrom: Date;\n readonly effectiveTo: Date | null;\n readonly priority: number;\n readonly payloadJson: P;\n readonly payloadHash: string;\n readonly createdAt: Date;\n readonly publishedAt: Date | null;\n}\n\nexport interface GatePolicyDefinitionProps<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> extends BasePolicyDefinitionProps<K, P> {\n readonly kind: \"GATE\";\n readonly gateEngineVersion: number;\n}\n\nexport interface ComputePolicyDefinitionProps<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> extends BasePolicyDefinitionProps<K, P> {\n readonly kind: \"COMPUTE\";\n readonly computeEngineVersion: number;\n}\n\nexport type GatePolicyDefinitionInput<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> = Omit<GatePolicyDefinitionProps<K, P>, \"kind\" | \"enabled\"> & {\n readonly enabled?: boolean;\n};\n\nexport type ComputePolicyDefinitionInput<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> = Omit<ComputePolicyDefinitionProps<K, P>, \"kind\" | \"enabled\"> & {\n readonly enabled?: boolean;\n};\n\nexport type PolicyDefinitionProps<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> = GatePolicyDefinitionProps<K, P> | ComputePolicyDefinitionProps<K, P>;\n\n// ─── Definition row (as if loaded from database) ────────────────────────────\n\nexport class PolicyDefinition<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> {\n private static assertPolicyVersionIsSemver(policyVersion: string): void {\n if (!POLICY_SEMVER_PATTERN.test(policyVersion)) {\n throw new InvariantViolationException(\n `PolicyDefinition.policyVersion must be a valid semver. Received: \"${policyVersion}\"`,\n );\n }\n }\n\n public readonly id: PolicyDefinitionId;\n public readonly policyKey: K;\n\n public readonly policyVersion: string;\n public readonly payloadSchemaVersion: number;\n public readonly contextVersionMin: number;\n public readonly contextVersionMax: number;\n public readonly gateEngineVersion?: number;\n public readonly computeEngineVersion?: number;\n\n public readonly enabled: boolean;\n public readonly status: PolicyDefinitionStatus;\n public readonly scope: PolicyScope;\n public readonly effectiveFrom: Date;\n public readonly effectiveTo: Date | null;\n public readonly priority: number;\n public readonly payloadJson: P;\n public readonly payloadHash: string;\n public readonly createdAt: Date;\n public readonly publishedAt: Date | null;\n public readonly kind: PolicyKind;\n\n private constructor(props: PolicyDefinitionProps<K, P>) {\n // The static factories are the supported API. This guard stays here because\n // TypeScript privacy does not protect runtime-only construction paths.\n this.id = props.id;\n this.policyKey = props.policyKey;\n PolicyDefinition.assertPolicyVersionIsSemver(props.policyVersion);\n this.policyVersion = props.policyVersion;\n this.payloadSchemaVersion = props.payloadSchemaVersion;\n this.contextVersionMin = props.contextVersionMin;\n this.contextVersionMax = props.contextVersionMax;\n this.enabled = props.enabled;\n this.status = props.status;\n this.scope = props.scope;\n this.effectiveFrom = props.effectiveFrom;\n this.effectiveTo = props.effectiveTo;\n this.priority = props.priority;\n this.payloadJson = props.payloadJson;\n this.payloadHash = props.payloadHash;\n this.createdAt = props.createdAt;\n this.publishedAt = props.publishedAt;\n this.kind = props.kind;\n\n if (props.kind === \"GATE\") {\n if (props.gateEngineVersion === undefined) {\n throw new InvariantViolationException(\n `PolicyDefinition of kind 'GATE' must have a 'gateEngineVersion'. Policy key: ${props.policyKey}`,\n );\n }\n this.gateEngineVersion = props.gateEngineVersion;\n } else {\n if (props.computeEngineVersion === undefined) {\n throw new InvariantViolationException(\n `PolicyDefinition of kind 'COMPUTE' must have a 'computeEngineVersion'. Policy key: ${props.policyKey}`,\n );\n }\n this.computeEngineVersion = props.computeEngineVersion;\n }\n }\n\n static gate<K extends string, P extends AnyPolicyPayload = AnyPolicyPayload>(\n props: GatePolicyDefinitionInput<K, P>,\n ): PolicyDefinition<K, P> {\n return new PolicyDefinition<K, P>({\n ...props,\n enabled: props.enabled ?? true,\n kind: \"GATE\",\n });\n }\n\n static compute<\n K extends string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n >(props: ComputePolicyDefinitionInput<K, P>): PolicyDefinition<K, P> {\n return new PolicyDefinition<K, P>({\n ...props,\n enabled: props.enabled ?? true,\n kind: \"COMPUTE\",\n });\n }\n\n isGate(): this is PolicyDefinition<K, P> & {\n readonly kind: \"GATE\";\n readonly gateEngineVersion: number;\n } {\n return this.kind === \"GATE\";\n }\n\n isCompute(): this is PolicyDefinition<K, P> & {\n readonly kind: \"COMPUTE\";\n readonly computeEngineVersion: number;\n } {\n return this.kind === \"COMPUTE\";\n }\n}\n\n// ─── Query parameters ───────────────────────────────────────────────────────\n\nexport interface FindCandidatesParams {\n readonly policyKey: string;\n readonly kind: PolicyKind;\n readonly payloadSchemaVersion?: number;\n readonly asOf: Date;\n readonly contextVersion: number;\n readonly scopeChain: readonly PolicyScope[];\n}\n","import { Result } from \"../../result/result\";\n\nimport type { ContextResolverRegistry } from \"./context-registry\";\nimport type {\n ContextResolverResilienceOptions,\n ContextResolverRetryOptions,\n ContextValueResolver,\n} from \"./context-resolver\";\nimport type { ContextSeed } from \"./context-seed\";\nimport { PolicyContextPath } from \"./path\";\n\ninterface NormalizedContextResolverRetryOptions {\n readonly maxAttempts: number;\n readonly initialDelayMs: number;\n readonly maxDelayMs: number;\n readonly backoffMultiplier: number;\n}\n\ninterface NormalizedContextResolverCircuitBreakerOptions {\n readonly failureThreshold: number;\n readonly cooldownMs: number;\n}\n\ninterface NormalizedContextResolverResilienceOptions {\n readonly timeoutMs: number | null;\n readonly retry: NormalizedContextResolverRetryOptions;\n readonly circuitBreaker: NormalizedContextResolverCircuitBreakerOptions | null;\n}\n\ninterface ContextResolverCircuitState {\n readonly failureCount: number;\n readonly openUntilMs: number | null;\n}\n\nexport interface PolicyContextBuilderOptions {\n readonly defaultResolverResilience?: ContextResolverResilienceOptions;\n readonly now?: () => number;\n readonly sleep?: (delayMs: number) => Promise<void>;\n}\n\nconst DEFAULT_RESOLVER_RETRY_OPTIONS: NormalizedContextResolverRetryOptions = {\n maxAttempts: 1,\n initialDelayMs: 25,\n maxDelayMs: 1_000,\n backoffMultiplier: 2,\n};\n\n/**\n * Builds a context object by resolving required paths from a seed.\n */\nexport class PolicyContextBuilder {\n private readonly circuitStates = new Map<\n string,\n ContextResolverCircuitState\n >();\n private readonly defaultResolverResilience?: ContextResolverResilienceOptions;\n private readonly now: () => number;\n private readonly sleep: (delayMs: number) => Promise<void>;\n\n constructor(\n private readonly registry: ContextResolverRegistry,\n options: PolicyContextBuilderOptions = {},\n ) {\n this.defaultResolverResilience = options.defaultResolverResilience;\n this.now = options.now ?? Date.now;\n this.sleep =\n options.sleep ??\n (async (delayMs) => {\n if (delayMs <= 0) {\n return;\n }\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, delayMs);\n });\n });\n }\n\n private static clampPositiveInteger(\n value: number | undefined,\n fallback: number,\n ): number {\n if (value === undefined || !Number.isFinite(value)) {\n return fallback;\n }\n\n return Math.max(1, Math.trunc(value));\n }\n\n private static clampNonNegativeInteger(\n value: number | undefined,\n fallback: number,\n ): number {\n if (value === undefined || !Number.isFinite(value)) {\n return fallback;\n }\n\n return Math.max(0, Math.trunc(value));\n }\n\n private static normalizeTimeoutMs(value: number | undefined): number | null {\n if (value === undefined || !Number.isFinite(value) || value <= 0) {\n return null;\n }\n\n return Math.trunc(value);\n }\n\n private static mergeRetryOptions(\n defaults: ContextResolverRetryOptions | false | undefined,\n overrides: ContextResolverRetryOptions | false | undefined,\n ): ContextResolverRetryOptions | false | undefined {\n if (overrides === false) {\n return false;\n }\n\n if (overrides !== undefined) {\n return {\n ...(defaults === false || defaults === undefined ? {} : defaults),\n ...overrides,\n };\n }\n\n return defaults;\n }\n\n private static mergeCircuitBreakerOptions(\n defaults: ContextResolverResilienceOptions[\"circuitBreaker\"] | undefined,\n overrides: ContextResolverResilienceOptions[\"circuitBreaker\"] | undefined,\n ): ContextResolverResilienceOptions[\"circuitBreaker\"] | undefined {\n if (overrides === false) {\n return false;\n }\n\n if (overrides !== undefined) {\n return {\n ...(defaults === false || defaults === undefined ? {} : defaults),\n ...overrides,\n };\n }\n\n return defaults;\n }\n\n private resolveResilienceOptions(\n resolver: ContextValueResolver,\n ): NormalizedContextResolverResilienceOptions {\n const defaults = this.defaultResolverResilience;\n const override = resolver.resilience;\n const retry = PolicyContextBuilder.mergeRetryOptions(\n defaults?.retry,\n override?.retry,\n );\n const circuitBreaker = PolicyContextBuilder.mergeCircuitBreakerOptions(\n defaults?.circuitBreaker,\n override?.circuitBreaker,\n );\n const retryOptions = retry === false ? undefined : retry;\n const circuitBreakerOptions =\n circuitBreaker === false ? undefined : circuitBreaker;\n\n return {\n timeoutMs: PolicyContextBuilder.normalizeTimeoutMs(\n override?.timeoutMs ?? defaults?.timeoutMs,\n ),\n retry: {\n maxAttempts: PolicyContextBuilder.clampPositiveInteger(\n retryOptions?.maxAttempts,\n DEFAULT_RESOLVER_RETRY_OPTIONS.maxAttempts,\n ),\n initialDelayMs: PolicyContextBuilder.clampNonNegativeInteger(\n retryOptions?.initialDelayMs,\n DEFAULT_RESOLVER_RETRY_OPTIONS.initialDelayMs,\n ),\n maxDelayMs: PolicyContextBuilder.clampNonNegativeInteger(\n retryOptions?.maxDelayMs,\n DEFAULT_RESOLVER_RETRY_OPTIONS.maxDelayMs,\n ),\n backoffMultiplier: PolicyContextBuilder.clampPositiveInteger(\n retryOptions?.backoffMultiplier,\n DEFAULT_RESOLVER_RETRY_OPTIONS.backoffMultiplier,\n ),\n },\n circuitBreaker:\n circuitBreakerOptions === undefined\n ? null\n : {\n failureThreshold: PolicyContextBuilder.clampPositiveInteger(\n circuitBreakerOptions.failureThreshold,\n 5,\n ),\n cooldownMs: PolicyContextBuilder.clampPositiveInteger(\n circuitBreakerOptions.cooldownMs,\n 30_000,\n ),\n },\n };\n }\n\n private getRetryDelayMs(\n attempt: number,\n retry: NormalizedContextResolverRetryOptions,\n ): number {\n return Math.min(\n retry.initialDelayMs * retry.backoffMultiplier ** (attempt - 1),\n retry.maxDelayMs,\n );\n }\n\n private resetCircuit(path: string): void {\n this.circuitStates.delete(path);\n }\n\n private isCircuitOpen(\n path: string,\n circuitBreaker: NormalizedContextResolverCircuitBreakerOptions | null,\n ): boolean {\n if (circuitBreaker === null) {\n return false;\n }\n\n const state = this.circuitStates.get(path);\n if (state === undefined || state.openUntilMs === null) {\n return false;\n }\n\n if (state.openUntilMs <= this.now()) {\n this.resetCircuit(path);\n return false;\n }\n\n return true;\n }\n\n private recordResolverFailure(\n path: string,\n circuitBreaker: NormalizedContextResolverCircuitBreakerOptions | null,\n ): void {\n if (circuitBreaker === null) {\n return;\n }\n\n const currentFailureCount = this.circuitStates.get(path)?.failureCount ?? 0;\n const nextFailureCount = currentFailureCount + 1;\n\n if (nextFailureCount >= circuitBreaker.failureThreshold) {\n this.circuitStates.set(path, {\n failureCount: 0,\n openUntilMs: this.now() + circuitBreaker.cooldownMs,\n });\n return;\n }\n\n this.circuitStates.set(path, {\n failureCount: nextFailureCount,\n openUntilMs: null,\n });\n }\n\n private static describeThrownResolverError(error: unknown): string {\n if (error instanceof Error) {\n return `threw ${error.name}: ${error.message}`;\n }\n\n return `threw ${String(error)}`;\n }\n\n private async resolveOnce(\n resolver: ContextValueResolver,\n seed: ContextSeed,\n timeoutMs: number | null,\n ): Promise<Result<unknown, string>> {\n const execute = async (): Promise<Result<unknown, string>> => {\n try {\n return await resolver.resolve(seed);\n } catch (error) {\n return Result.err(\n PolicyContextBuilder.describeThrownResolverError(error),\n );\n }\n };\n\n if (timeoutMs === null) {\n return execute();\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n try {\n return await Promise.race([\n execute(),\n new Promise<Result<unknown, string>>((resolve) => {\n timeoutId = setTimeout(() => {\n resolve(Result.err(`timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n private async resolveWithResilience(\n path: string,\n resolver: ContextValueResolver,\n seed: ContextSeed,\n ): Promise<Result<unknown, string>> {\n const resilience = this.resolveResilienceOptions(resolver);\n\n if (this.isCircuitOpen(path, resilience.circuitBreaker)) {\n return Result.err(\"circuit breaker is open\");\n }\n\n let lastError = \"resolver failed\";\n\n for (let attempt = 1; attempt <= resilience.retry.maxAttempts; attempt++) {\n const result = await this.resolveOnce(\n resolver,\n seed,\n resilience.timeoutMs,\n );\n\n if (result.isOk()) {\n this.resetCircuit(path);\n return result;\n }\n\n lastError = result.errorOrNull() ?? lastError;\n\n if (attempt < resilience.retry.maxAttempts) {\n await this.sleep(this.getRetryDelayMs(attempt, resilience.retry));\n }\n }\n\n this.recordResolverFailure(path, resilience.circuitBreaker);\n return Result.err(lastError);\n }\n\n /**\n * Resolves all required context paths and returns a flat context object.\n * If any required path cannot be resolved, returns an error.\n */\n async build(\n requirements: readonly string[],\n seed: ContextSeed,\n ): Promise<Result<Record<string, unknown>, string>> {\n const context: Record<string, unknown> = {};\n\n for (const path of requirements) {\n const resolver = this.registry.get(path);\n if (!resolver) {\n return Result.err(`Missing resolver for path \"${path}\"`);\n }\n\n const result = await this.resolveWithResilience(path, resolver, seed);\n if (result.isErr()) {\n return Result.err(\n `Resolver error for path \"${path}\": ${result.errorOrNull()}`,\n );\n }\n\n const setPathResult = PolicyContextPath.set(\n context,\n path,\n result.getOrNull(),\n );\n if (setPathResult.isErr()) {\n return Result.err(setPathResult.errorOrNull()!);\n }\n }\n\n // Final validation: ensure every required path resolved to a defined value.\n // `undefined` is rejected explicitly because resolvers that \"succeed\" with\n // undefined indicate an unresolved field, not a present-but-empty one.\n const missing = requirements.filter((path) => {\n const result = PolicyContextPath.getOrAbsent(context, path);\n return result.isErr() || result.getOrNull() === undefined;\n });\n if (missing.length > 0) {\n return Result.err(\n `Context missing required paths after resolution: ${missing.join(\n \", \",\n )}`,\n );\n }\n\n return Result.ok(context);\n }\n}\n","import { Result } from \"../../result/result\";\n\nimport type { ContextValueResolver } from \"./context-resolver\";\n\nexport interface ContextResolverRegistrationOptions {\n readonly namespace?: string;\n}\n\ninterface RegisteredContextResolver {\n readonly namespace: string;\n readonly resolver: ContextValueResolver;\n}\n\nconst DEFAULT_CONTEXT_RESOLVER_NAMESPACE = \"default\";\n\nfunction normalizeNamespace(namespace?: string): string {\n const normalized = namespace?.trim();\n\n if (normalized === undefined || normalized.length === 0) {\n return DEFAULT_CONTEXT_RESOLVER_NAMESPACE;\n }\n\n return normalized;\n}\n\n/**\n * Registry of context value resolvers, keyed by path.\n */\nexport class ContextResolverRegistry {\n private readonly resolvers = new Map<string, RegisteredContextResolver>();\n\n register(\n resolver: ContextValueResolver,\n options: ContextResolverRegistrationOptions = {},\n ): Result<void, string> {\n const namespace = normalizeNamespace(options.namespace);\n const existing = this.resolvers.get(resolver.path);\n\n if (existing !== undefined && existing.namespace !== namespace) {\n return Result.err(\n `Resolver path \"${resolver.path}\" is already registered by namespace \"${existing.namespace}\" and cannot be replaced by \"${namespace}\".`,\n );\n }\n\n this.resolvers.set(resolver.path, {\n namespace,\n resolver,\n });\n\n return Result.ok(undefined);\n }\n\n registerAll(\n resolvers: readonly ContextValueResolver[],\n options: ContextResolverRegistrationOptions = {},\n ): Result<void, string> {\n for (const r of resolvers) {\n const registrationResult = this.register(r, options);\n if (registrationResult.isErr()) {\n return registrationResult;\n }\n }\n\n return Result.ok(undefined);\n }\n\n get(path: string): ContextValueResolver | undefined {\n return this.resolvers.get(path)?.resolver;\n }\n\n has(path: string): boolean {\n return this.resolvers.has(path);\n }\n\n getNamespace(path: string): string | undefined {\n return this.resolvers.get(path)?.namespace;\n }\n}\n\nexport function registerNamespacedContextResolversIn(\n registry: ContextResolverRegistry,\n namespace: string,\n resolvers: readonly ContextValueResolver[],\n): Result<ContextResolverRegistry, string> {\n const registrationResult = registry.registerAll(resolvers, {\n namespace,\n });\n if (registrationResult.isErr()) {\n return Result.err(registrationResult.errorOrNull()!);\n }\n\n return Result.ok(registry);\n}\n\nexport { DEFAULT_CONTEXT_RESOLVER_NAMESPACE };\n","import { Result } from \"../../result/result\";\n\nimport {\n ContextResolverRegistry,\n registerNamespacedContextResolversIn,\n} from \"./context-registry\";\n\nimport type { ContextValueResolver } from \"./context-resolver\";\n\n/**\n * Official instance of the ContextResolverRegistry.\n * Use `new ContextResolverRegistry()` plus `registerNamespacedContextResolversIn`\n * when each runtime/composition root needs its own isolated resolver graph.\n */\nexport const contextResolverRegistry = new ContextResolverRegistry();\n\nexport function registerNamespacedContextResolvers(\n namespace: string,\n resolvers: readonly ContextValueResolver[],\n): Result<ContextResolverRegistry, string> {\n return registerNamespacedContextResolversIn(\n contextResolverRegistry,\n namespace,\n resolvers,\n );\n}\n","import { Result } from \"../../result/result\";\n\nimport type { SchoolId, TenantId } from \"../policy-ids\";\n\n/**\n * Seed data provided by the use case / caller.\n * Contains raw IDs and inputs that the context system will resolve into paths.\n * Each resolver is responsible for validating and extracting what it needs from fields.\n */\nexport interface ContextSeed {\n readonly tenantId: TenantId;\n readonly schoolId: SchoolId;\n readonly fields: Record<string, unknown>;\n}\n\nexport class ContextSeedValidator {\n private static isBlankSeedId(value: string): boolean {\n return value.trim().length === 0;\n }\n\n static validate(seed: ContextSeed): Result<ContextSeed, string> {\n if (ContextSeedValidator.isBlankSeedId(seed.tenantId)) {\n return Result.err(\"ContextSeed tenantId must be a non-empty string\");\n }\n\n if (ContextSeedValidator.isBlankSeedId(seed.schoolId)) {\n return Result.err(\"ContextSeed schoolId must be a non-empty string\");\n }\n\n return Result.ok(seed);\n }\n}\n","import type { AsOfSource } from \"../catalog\";\nimport type { ContextSeed } from \"../context\";\nimport { Result } from \"../../result/result\";\nimport { isValidDate } from \"../../shared/temporal-guards\";\n\nconst DEFAULT_MAX_AS_OF_FUTURE_YEARS = 10;\n\nexport interface DeriveAsOfOptions {\n readonly maxFutureYears?: number;\n}\n\nexport class PolicyAsOfResolver {\n private static resolveMaxFutureYears(\n options: DeriveAsOfOptions,\n ): Result<number, string> {\n const maxFutureYears =\n options.maxFutureYears ?? DEFAULT_MAX_AS_OF_FUTURE_YEARS;\n\n if (!Number.isInteger(maxFutureYears) || maxFutureYears < 0) {\n return Result.err(\n `deriveAsOf maxFutureYears must be a non-negative integer. Received: ${maxFutureYears}`,\n );\n }\n\n return Result.ok(maxFutureYears);\n }\n\n static derive(\n source: AsOfSource,\n seed: ContextSeed,\n now: Date,\n options: DeriveAsOfOptions = {},\n ): Result<Date, string> {\n const maxFutureYearsResult =\n PolicyAsOfResolver.resolveMaxFutureYears(options);\n if (maxFutureYearsResult.isErr()) {\n return Result.err(maxFutureYearsResult.errorOrNull()!);\n }\n const maxFutureYears = maxFutureYearsResult.getOrNull()!;\n\n switch (source) {\n case \"NOW\":\n return Result.ok(now);\n\n case \"CALLER_PROVIDED\": {\n const asOf = seed.fields[\"asOf\"];\n if (!isValidDate(asOf)) {\n return Result.err(\n 'asOfSource \"CALLER_PROVIDED\" requires seed.fields.asOf to be a Date',\n );\n }\n\n const maxFuture = new Date(now);\n maxFuture.setFullYear(maxFuture.getFullYear() + maxFutureYears);\n if (asOf > maxFuture) {\n return Result.err(\n `asOf date is more than ${maxFutureYears} years in the future (received ${asOf.toISOString()})`,\n );\n }\n\n return Result.ok(asOf);\n }\n\n default:\n return Result.err(`Unknown asOfSource: \"${source}\"`);\n }\n }\n}\n","import type { PolicyDefinition } from \"../defs\";\nimport { PolicyScopeMatcher } from \"../defs\";\nimport { comparePolicySemver } from \"../defs/policy-semver\";\nimport { Result } from \"../../result/result\";\n\n/**\n * Selects the best policy definition from a list of already-filtered candidates.\n *\n * Ordering criteria (highest priority first):\n * 1. Scope specificity: SCHOOL (3) > TENANT (2) > GLOBAL (1)\n * 2. Priority: higher number wins\n * 3. publishedAt descending (fallback to createdAt)\n * 4. Engine version descending (prefer-latest-engine-version — deterministic tiebreaker)\n * 5. policyVersion descending (semver — final deterministic tiebreaker)\n */\nexport class PolicyResolver {\n resolveBest(\n candidates: readonly PolicyDefinition[],\n ): Result<PolicyDefinition, string> {\n if (candidates.length === 0) {\n return Result.err(\n \"No matching policy definition found (candidates list is empty)\",\n );\n }\n\n const sorted = [...candidates].sort((a, b) => {\n // 1) Scope specificity (higher weight = more specific)\n const scopeDiff =\n PolicyScopeMatcher.weight(b.scope.level) -\n PolicyScopeMatcher.weight(a.scope.level);\n if (scopeDiff !== 0) return scopeDiff;\n\n // 2) Priority DESC\n const priorityDiff = b.priority - a.priority;\n if (priorityDiff !== 0) return priorityDiff;\n\n // 3) publishedAt DESC (fallback createdAt)\n const aDate = a.publishedAt ?? a.createdAt;\n const bDate = b.publishedAt ?? b.createdAt;\n const dateDiff = bDate.getTime() - aDate.getTime();\n if (dateDiff !== 0) return dateDiff;\n\n // 4) Engine version DESC — prefers the definition running on the most\n // capable engine when scope/priority/date are identical.\n const aEngine = a.gateEngineVersion ?? a.computeEngineVersion ?? 0;\n const bEngine = b.gateEngineVersion ?? b.computeEngineVersion ?? 0;\n const engineDiff = bEngine - aEngine;\n if (engineDiff !== 0) return engineDiff;\n\n // 5) policyVersion DESC (semver) — final deterministic tiebreaker so\n // the winner never depends on repository return order.\n return comparePolicySemver(b.policyVersion, a.policyVersion);\n });\n\n return Result.ok(sorted[0]);\n }\n}\n","import type { PolicyKind } from \"../catalog\";\n\n// ─── Error Union ─────────────────────────────────────────────────────────────\n\nexport type PolicyEvaluationError =\n | {\n readonly kind: \"INVALID_CONTEXT\";\n readonly stage: \"SEED_VALIDATION\" | \"AS_OF_DERIVATION\" | \"CONTEXT_BUILD\";\n readonly policyKey: string;\n readonly message: string;\n readonly cause: string;\n }\n | {\n readonly kind: \"INVALID_POLICY_KEY\";\n readonly rawPolicyKey: string;\n readonly message: string;\n readonly cause: string;\n }\n | {\n readonly kind: \"POLICY_NOT_FOUND\";\n readonly policyKey: string;\n readonly message: string;\n readonly cause: string;\n }\n | {\n readonly kind: \"POLICY_DEFINITION_NOT_FOUND\";\n readonly policyKey: string;\n readonly contextVersion: number;\n readonly asOf: Date;\n readonly message: string;\n readonly cause: string;\n }\n | {\n readonly kind: \"POLICY_VARIANT_NOT_FOUND\";\n readonly policyKey: string;\n readonly policyKind: PolicyKind;\n readonly payloadSchemaVersion: number;\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n readonly message: string;\n readonly cause: string;\n }\n | {\n readonly kind: \"ENGINE_FAILURE\";\n readonly policyKey: string;\n readonly engine: PolicyKind;\n readonly engineVersion: number;\n readonly message: string;\n readonly cause: string;\n };\n\n// ─── Factory object ─────────────────────────────────────────────────────────\n\nexport class PolicyEvaluationErrors {\n static invalidContext(\n stage: Extract<PolicyEvaluationError, { kind: \"INVALID_CONTEXT\" }>[\"stage\"],\n policyKey: string,\n cause: string,\n ): PolicyEvaluationError {\n return {\n kind: \"INVALID_CONTEXT\",\n stage,\n policyKey,\n message: \"Policy evaluation context is invalid\",\n cause,\n };\n }\n\n static invalidPolicyKey(\n rawPolicyKey: string,\n cause: string,\n ): PolicyEvaluationError {\n return {\n kind: \"INVALID_POLICY_KEY\",\n rawPolicyKey,\n message: \"Policy key is invalid\",\n cause,\n };\n }\n\n static policyNotFound(\n policyKey: string,\n cause: string,\n ): PolicyEvaluationError {\n return {\n kind: \"POLICY_NOT_FOUND\",\n policyKey,\n message: \"Policy is not registered in the catalog\",\n cause,\n };\n }\n\n static policyDefinitionNotFound(\n policyKey: string,\n asOf: Date,\n contextVersion: number,\n cause: string,\n ): PolicyEvaluationError {\n return {\n kind: \"POLICY_DEFINITION_NOT_FOUND\",\n policyKey,\n contextVersion,\n asOf,\n message: \"No published policy definition matched the evaluation inputs\",\n cause,\n };\n }\n\n static policyVariantNotFound(params: {\n readonly policyKey: string;\n readonly policyKind: PolicyKind;\n readonly payloadSchemaVersion: number;\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n readonly cause: string;\n }): PolicyEvaluationError {\n return {\n kind: \"POLICY_VARIANT_NOT_FOUND\",\n policyKey: params.policyKey,\n policyKind: params.policyKind,\n payloadSchemaVersion: params.payloadSchemaVersion,\n ...(params.gateEngineVersion !== undefined\n ? { gateEngineVersion: params.gateEngineVersion }\n : {}),\n ...(params.computeEngineVersion !== undefined\n ? { computeEngineVersion: params.computeEngineVersion }\n : {}),\n message: \"No catalog variant matched the selected policy definition\",\n cause: params.cause,\n };\n }\n\n static engineFailure(\n policyKey: string,\n engine: PolicyKind,\n engineVersion: number,\n cause: string,\n ): PolicyEvaluationError {\n return {\n kind: \"ENGINE_FAILURE\",\n policyKey,\n engine,\n engineVersion,\n message: \"Policy engine evaluation failed\",\n cause,\n };\n }\n}\n","import { PolicyAsOfResolver, type DeriveAsOfOptions } from \"../asof\";\nimport { type PolicyCatalog, PolicyCatalogEntry, PolicyKey } from \"../catalog\";\nimport type { ContextSeed, PolicyContextBuilder } from \"../context\";\nimport { ContextSeedValidator } from \"../context\";\nimport {\n PolicyDefinition,\n type PolicyDefinitionRepository,\n type PolicyScope,\n} from \"../defs\";\nimport type { PolicyDecisionId, PolicyDefinitionId } from \"../policy-ids\";\nimport {\n type ComputeOutcome,\n ComputeRegistry,\n GateEngineRegistry,\n type GateOutcome,\n type PolicyContext,\n} from \"../engines\";\nimport { PolicyResolver } from \"../resolver\";\nimport { Result } from \"../../result/result\";\nimport { isValidDate } from \"../../shared/temporal-guards\";\n\nimport type { PolicyEvent, PolicyReporter } from \"../../config/policy-reporter\";\nimport { SilentPolicyReporter } from \"../../config/silent-policy-reporter\";\n\nimport {\n PolicyEvaluationErrors,\n type PolicyEvaluationError,\n} from \"./policy-evaluation-error\";\n\n// ─── Input ──────────────────────────────────────────────────────────────────\n\nexport interface EvaluateInput {\n readonly decisionId: PolicyDecisionId;\n readonly policyKey: string;\n readonly scopeChain: readonly PolicyScope[];\n readonly contextVersion: number;\n readonly seed: ContextSeed;\n}\n\nexport interface PolicyServiceOptions {\n readonly asOf?: DeriveAsOfOptions;\n readonly reporter?: PolicyReporter;\n}\n\nexport interface PolicyServiceParams {\n readonly catalog: PolicyCatalog;\n readonly contextBuilder: PolicyContextBuilder;\n readonly defRepo: PolicyDefinitionRepository;\n readonly resolver: PolicyResolver;\n readonly gateEngines: GateEngineRegistry;\n readonly computeRegistry: ComputeRegistry;\n readonly options?: PolicyServiceOptions;\n}\n\n// ─── Output ─────────────────────────────────────────────────────────────────\n\n/** Union of all possible policy decision Outcomes. */\nexport type PolicyDecision = GateOutcome | ComputeOutcome;\n\nexport type { PolicyEvaluationError } from \"./policy-evaluation-error\";\n\nexport interface PolicyEvaluationResult {\n readonly decisionId: PolicyDecisionId;\n readonly ref: {\n readonly definitionId: PolicyDefinitionId;\n readonly policyKey: string;\n readonly policyVersion: string;\n readonly payloadHash: string;\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n };\n readonly kind: \"GATE\" | \"COMPUTE\";\n readonly asOf: Date;\n readonly evaluatedAt: Date;\n readonly contextVersion: number;\n /** Business decision expressed as an Outcome — not a technical Result. */\n readonly decision: PolicyDecision;\n}\n\ninterface ResolvedPolicyCandidate {\n readonly definition: PolicyDefinition;\n readonly catalogEntry: PolicyCatalogEntry;\n}\n\n// ─── Service ────────────────────────────────────────────────────────────────\n\nexport class PolicyService {\n readonly #reporter: PolicyReporter;\n private readonly catalog: PolicyCatalog;\n private readonly contextBuilder: PolicyContextBuilder;\n private readonly defRepo: PolicyDefinitionRepository;\n private readonly resolver: PolicyResolver;\n private readonly gateEngines: GateEngineRegistry;\n private readonly computeRegistry: ComputeRegistry;\n private readonly options: PolicyServiceOptions;\n\n constructor(params: PolicyServiceParams) {\n this.catalog = params.catalog;\n this.contextBuilder = params.contextBuilder;\n this.defRepo = params.defRepo;\n this.resolver = params.resolver;\n this.gateEngines = params.gateEngines;\n this.computeRegistry = params.computeRegistry;\n this.options = params.options ?? {};\n this.#reporter = this.options.reporter ?? new SilentPolicyReporter();\n }\n\n #reportSafely(event: PolicyEvent): void {\n try {\n this.#reporter.report(event);\n } catch {\n // Falhas de telemetria nao podem interromper a avaliacao de politicas.\n }\n }\n\n private resolveEvaluationNow(seed: ContextSeed): Result<Date, string> {\n const candidate = seed.fields[\"now\"];\n\n if (candidate === undefined) {\n return Result.ok(new Date());\n }\n\n if (!isValidDate(candidate)) {\n return Result.err(\"seed.fields.now must be a valid Date when provided\");\n }\n\n return Result.ok(candidate);\n }\n\n async evaluate(\n input: EvaluateInput,\n ): Promise<Result<PolicyEvaluationResult, PolicyEvaluationError>> {\n const result = await this.#evaluate(input);\n if (result.isErr()) {\n const error = result.errorOrNull()!;\n this.#reportSafely({\n kind: \"policy-evaluation-failed\",\n level: \"error\",\n policyKey: \"policyKey\" in error ? error.policyKey : undefined,\n errorKind: error.kind,\n message: error.message,\n cause: error.cause,\n occurredAt: new Date(),\n });\n } else {\n const ok = result.getOrNull()!;\n this.#reportSafely({\n kind: \"policy-evaluation-completed\",\n level: \"info\",\n policyKey: ok.ref.policyKey,\n decisionId: ok.decisionId,\n engineKind: ok.kind,\n occurredAt: ok.evaluatedAt,\n });\n }\n return result;\n }\n\n async #evaluate(\n input: EvaluateInput,\n ): Promise<Result<PolicyEvaluationResult, PolicyEvaluationError>> {\n const seedResult = ContextSeedValidator.validate(input.seed);\n if (seedResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.invalidContext(\n \"SEED_VALIDATION\",\n input.policyKey,\n seedResult.errorOrNull()!,\n ),\n );\n }\n const seed = seedResult.getOrNull()!;\n\n const catalogFamilyResult = this.#resolveCatalogFamily(input.policyKey);\n if (catalogFamilyResult.isErr()) {\n return Result.err(catalogFamilyResult.errorOrNull()!);\n }\n const { key: policyKey, family } = catalogFamilyResult.getOrNull()!;\n const familyEntry = family[0]!;\n\n const nowResult = this.resolveEvaluationNow(seed);\n if (nowResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.invalidContext(\n \"AS_OF_DERIVATION\",\n policyKey,\n nowResult.errorOrNull()!,\n ),\n );\n }\n const now = nowResult.getOrNull()!;\n\n const asOfResult = PolicyAsOfResolver.derive(\n familyEntry.asOfSource,\n seed,\n now,\n this.options.asOf,\n );\n if (asOfResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.invalidContext(\n \"AS_OF_DERIVATION\",\n policyKey,\n asOfResult.errorOrNull()!,\n ),\n );\n }\n const asOf = asOfResult.getOrNull()!;\n\n const definitionResult = this.#findCandidates(\n policyKey,\n familyEntry.kind,\n asOf,\n input,\n );\n if (definitionResult.isErr()) {\n return Result.err(definitionResult.errorOrNull()!);\n }\n const {\n definition: policyDefinition,\n catalogEntry: versionedCatalogEntry,\n } = definitionResult.getOrNull()!;\n\n this.#reportSafely({\n kind: \"policy-resolution\",\n level: \"info\",\n policyKey,\n definitionId: policyDefinition.id,\n policyVersion: policyDefinition.policyVersion,\n engineKind: policyDefinition.isGate() ? \"GATE\" : \"COMPUTE\",\n engineVersion: policyDefinition.isGate()\n ? policyDefinition.gateEngineVersion!\n : policyDefinition.computeEngineVersion!,\n occurredAt: now,\n });\n\n const ctxResult = await this.contextBuilder.build(\n versionedCatalogEntry.contextRequirements,\n seed,\n );\n if (ctxResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.invalidContext(\n \"CONTEXT_BUILD\",\n policyKey,\n ctxResult.errorOrNull()!,\n ),\n );\n }\n const context = ctxResult.getOrNull()!;\n\n const decisionResult = this.#executeEngine(\n policyKey,\n policyDefinition,\n context,\n );\n if (decisionResult.isErr()) {\n return Result.err(decisionResult.errorOrNull()!);\n }\n const decision = decisionResult.getOrNull()!;\n\n const result: PolicyEvaluationResult = {\n decisionId: input.decisionId,\n ref: {\n definitionId: policyDefinition.id,\n policyKey: policyDefinition.policyKey,\n policyVersion: policyDefinition.policyVersion,\n payloadHash: policyDefinition.payloadHash,\n ...(policyDefinition.isGate()\n ? {\n gateEngineVersion: policyDefinition.gateEngineVersion,\n }\n : {\n computeEngineVersion: policyDefinition.computeEngineVersion,\n }),\n },\n kind: policyDefinition.kind,\n asOf,\n evaluatedAt: now,\n contextVersion: input.contextVersion,\n decision,\n };\n\n return Result.ok(result);\n }\n\n #resolveCatalogVariant(\n definition: PolicyDefinition,\n ): Result<PolicyCatalogEntry, string> {\n return this.catalog.getVersioned({\n key: definition.policyKey,\n kind: definition.kind,\n ...(definition.isGate()\n ? { gateEngineVersion: definition.gateEngineVersion }\n : {\n computeEngineVersion: definition.computeEngineVersion,\n }),\n payloadSchemaVersion: definition.payloadSchemaVersion,\n });\n }\n\n #resolveCatalogFamily(\n rawKey: string,\n ): Result<\n { key: string; family: readonly PolicyCatalogEntry[] },\n PolicyEvaluationError\n > {\n const keyResult = PolicyKey.parse(rawKey);\n if (keyResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.invalidPolicyKey(\n rawKey,\n keyResult.errorOrNull()!,\n ),\n );\n }\n const policyKey = keyResult.getOrNull()!.toString();\n\n const catalogFamilyResult = this.catalog.getFamily(policyKey);\n if (catalogFamilyResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.policyNotFound(\n policyKey,\n catalogFamilyResult.errorOrNull()!,\n ),\n );\n }\n\n return Result.ok({\n key: policyKey,\n family: catalogFamilyResult.getOrNull()!,\n });\n }\n\n #findCandidates(\n policyKey: string,\n policyKind: PolicyCatalogEntry[\"kind\"],\n asOf: Date,\n input: EvaluateInput,\n ): Result<ResolvedPolicyCandidate, PolicyEvaluationError> {\n const candidates = this.defRepo.findCandidates({\n policyKey: policyKey,\n kind: policyKind,\n asOf,\n contextVersion: input.contextVersion,\n scopeChain: input.scopeChain,\n });\n\n const compatibleCandidates: ResolvedPolicyCandidate[] = [];\n const compatibleCandidatesByDefinitionId = new Map<\n string,\n ResolvedPolicyCandidate\n >();\n const incompatibleVariantErrorsByDefinitionId = new Map<string, string>();\n\n for (const candidate of candidates) {\n const compatibilityResult = this.#resolveCatalogVariant(candidate);\n if (compatibilityResult.isErr()) {\n incompatibleVariantErrorsByDefinitionId.set(\n candidate.id,\n compatibilityResult.errorOrNull()!,\n );\n continue;\n }\n\n const resolvedCandidate: ResolvedPolicyCandidate = {\n definition: candidate,\n catalogEntry: compatibilityResult.getOrNull()!,\n };\n compatibleCandidates.push(resolvedCandidate);\n compatibleCandidatesByDefinitionId.set(candidate.id, resolvedCandidate);\n }\n\n if (compatibleCandidates.length === 0 && candidates.length > 0) {\n const selectedCandidateResult = this.resolver.resolveBest(candidates);\n if (selectedCandidateResult.isOk()) {\n const selectedCandidate = selectedCandidateResult.getOrNull()!;\n\n return Result.err(\n PolicyEvaluationErrors.policyVariantNotFound({\n policyKey: policyKey,\n policyKind: selectedCandidate.kind,\n payloadSchemaVersion: selectedCandidate.payloadSchemaVersion,\n ...(selectedCandidate.isGate()\n ? {\n gateEngineVersion: selectedCandidate.gateEngineVersion,\n }\n : {\n computeEngineVersion: selectedCandidate.computeEngineVersion,\n }),\n cause:\n incompatibleVariantErrorsByDefinitionId.get(\n selectedCandidate.id,\n ) ??\n \"No compatible catalog variant matched the selected policy definition\",\n }),\n );\n }\n }\n\n const bestResult = this.resolver.resolveBest(\n compatibleCandidates.map((candidate) => candidate.definition),\n );\n if (bestResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.policyDefinitionNotFound(\n policyKey,\n asOf,\n input.contextVersion,\n bestResult.errorOrNull()!,\n ),\n );\n }\n\n const bestDefinition = bestResult.getOrNull()!;\n const resolvedCandidate = compatibleCandidatesByDefinitionId.get(\n bestDefinition.id,\n );\n if (resolvedCandidate === undefined) {\n return Result.err(\n PolicyEvaluationErrors.policyDefinitionNotFound(\n policyKey,\n asOf,\n input.contextVersion,\n `Resolved definition \"${bestDefinition.id}\" is not present among compatible catalog variants`,\n ),\n );\n }\n\n return Result.ok(resolvedCandidate);\n }\n\n #executeEngine(\n policyKey: string,\n definition: PolicyDefinition,\n context: PolicyContext,\n ): Result<PolicyDecision, PolicyEvaluationError> {\n if (definition.isGate()) {\n const gateResult = this.gateEngines.evaluate(\n definition.gateEngineVersion,\n definition.payloadJson,\n context,\n );\n if (gateResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.engineFailure(\n policyKey,\n \"GATE\",\n definition.gateEngineVersion,\n gateResult.errorOrNull()!,\n ),\n );\n }\n\n return Result.ok(gateResult.getOrNull()!);\n }\n\n if (!definition.isCompute()) {\n return Result.err(\n PolicyEvaluationErrors.policyVariantNotFound({\n policyKey,\n policyKind: definition.kind,\n payloadSchemaVersion: definition.payloadSchemaVersion,\n cause: `Unsupported policy kind \"${definition.kind}\"`,\n }),\n );\n }\n\n const computeResult = this.computeRegistry.evaluate(\n policyKey,\n definition.computeEngineVersion,\n definition.payloadSchemaVersion,\n definition.payloadJson,\n context,\n );\n\n if (computeResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.engineFailure(\n policyKey,\n \"COMPUTE\",\n definition.computeEngineVersion,\n computeResult.errorOrNull()!,\n ),\n );\n }\n\n return Result.ok(computeResult.getOrNull()!);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"policy-service.js","names":["#reporter","#evaluate","#reportSafely","#resolveCatalogFamily","#findCandidates","#executeEngine","#resolveCatalogVariant"],"sources":["../src/core/policies/utils/hash.ts","../src/core/exceptions/validation-exception.ts","../src/core/policies/policy-ids.ts","../src/core/policies/catalog/policy-catalog-entry.ts","../src/core/policies/catalog/policy-catalog.ts","../src/core/policies/catalog/catalog.instance.ts","../src/core/policies/catalog/policy-key.ts","../src/core/policies/defs/policy-scope.ts","../src/core/policies/defs/in-memory-policy-definition-repo.ts","../src/core/policies/defs/policy-semver.ts","../src/core/policies/defs/policy-definition.ts","../src/core/policies/context/context-builder.ts","../src/core/policies/context/context-registry.ts","../src/core/policies/context/context-registry.instance.ts","../src/core/policies/context/context-seed.ts","../src/core/policies/asof/asof.ts","../src/core/policies/resolver/policy-resolver.ts","../src/core/policies/service/policy-evaluation-error.ts","../src/core/policies/service/policy-service.ts"],"sourcesContent":["import { sha256Hex, stableStringify } from \"../../shared/hashing\";\nimport { isValidDate } from \"../../shared/temporal-guards\";\n\n/**\n * Produces a deterministic SHA-256 hex digest of a canonical JSON representation.\n * Object keys are sorted recursively so key order does not affect the hash.\n * Array item order is preserved on purpose; callers that treat arrays as sets\n * must normalize or sort them before hashing.\n *\n * Values that JSON.stringify would silently drop or coerce (undefined,\n * non-finite numbers, functions, symbols, bigint) are rejected up-front to\n * prevent semantically different payloads from collapsing to the same hash.\n */\nexport class PolicyHashing {\n static sha256(input: string): string {\n return sha256Hex(input);\n }\n\n private static assertHashable(value: unknown, path: string): void {\n if (value === null) {\n return;\n }\n\n const type = typeof value;\n\n if (type === \"undefined\") {\n throw new TypeError(\n `canonicalJson does not accept undefined values (at ${path})`,\n );\n }\n\n if (type === \"number\" && !Number.isFinite(value)) {\n throw new TypeError(\n `canonicalJson does not accept non-finite numbers (at ${path}, value: ${String(value)})`,\n );\n }\n\n if (type === \"bigint\" || type === \"function\" || type === \"symbol\") {\n throw new TypeError(\n `canonicalJson does not accept ${type} values (at ${path})`,\n );\n }\n\n if (type !== \"object\") {\n return;\n }\n\n if (value instanceof Date) {\n if (!isValidDate(value)) {\n throw new TypeError(\n `canonicalJson does not accept Invalid Date (at ${path})`,\n );\n }\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n PolicyHashing.assertHashable(item, `${path}[${index}]`);\n });\n return;\n }\n\n for (const [key, nested] of Object.entries(\n value as Record<string, unknown>,\n )) {\n PolicyHashing.assertHashable(nested, `${path}.${key}`);\n }\n }\n\n static canonicalJson(value: unknown): string {\n PolicyHashing.assertHashable(value, \"$\");\n\n return stableStringify(value);\n }\n\n static computePayloadHash(\n payload: unknown,\n policyKey: string,\n policyVersion: string,\n ): string {\n const canonical = PolicyHashing.canonicalJson({\n policyKey,\n policyVersion,\n payload,\n });\n\n return PolicyHashing.sha256(canonical);\n }\n}\n","import { DomainException } from \"./domain-exception\";\nimport { ValidationCode } from \"./validation-code\";\nimport { ValidationField } from \"./validation-field\";\n\nexport interface ValidationViolation {\n readonly field: ValidationField;\n readonly code: ValidationCode;\n readonly message: string;\n}\n\nclass ValidationException extends DomainException {\n constructor(\n public readonly field: ValidationField,\n public readonly code: ValidationCode,\n message: string,\n ) {\n super(message);\n }\n}\n\n// Carries multiple validation violations from a single operation (e.g. bulk validation).\n// Use when you need to report all field errors at once rather than failing on the first.\nclass MultipleValidationException extends DomainException {\n constructor(public readonly violations: readonly ValidationViolation[]) {\n super(violations.map((v) => v.message).join(\"; \"));\n }\n}\n\nclass InvalidValueException extends ValidationException {\n constructor(field: ValidationField, code: ValidationCode, message: string) {\n super(field, code, message);\n }\n}\n\nexport {\n InvalidValueException,\n MultipleValidationException,\n ValidationException,\n};\n","import { ValidationCode } from \"../exceptions/validation-code\";\nimport { InvalidValueException } from \"../exceptions/validation-exception\";\nimport { ValidationField } from \"../exceptions/validation-field\";\n\ntype Brand<TValue, TBrand extends string> = TValue & {\n readonly __brand: TBrand;\n};\n\nexport type PolicyDefinitionId = Brand<string, \"PolicyDefinitionId\">;\nexport type PolicyDecisionId = Brand<string, \"PolicyDecisionId\">;\nexport type TenantId = Brand<string, \"TenantId\">;\nexport type SchoolId = Brand<string, \"SchoolId\">;\n\nconst POLICY_DEFINITION_ID_FIELD = ValidationField.of(\"policyDefinitionId\");\nconst POLICY_DECISION_ID_FIELD = ValidationField.of(\"policyDecisionId\");\nconst TENANT_ID_FIELD = ValidationField.of(\"tenantId\");\nconst SCHOOL_ID_FIELD = ValidationField.of(\"schoolId\");\n\nfunction assertIdString(value: unknown, field: ValidationField): string {\n if (typeof value !== \"string\") {\n throw new InvalidValueException(\n field,\n ValidationCode.INVALID_FORMAT,\n `${field.value} must be a string, got ${typeof value}`,\n );\n }\n\n if (value.trim().length === 0) {\n throw new InvalidValueException(\n field,\n ValidationCode.BLANK,\n `${field.value} must be a non-empty string`,\n );\n }\n\n return value;\n}\n\nfunction brandId<TBrand extends string>(\n value: unknown,\n field: ValidationField,\n): Brand<string, TBrand> {\n return assertIdString(value, field) as Brand<string, TBrand>;\n}\n\nexport function asPolicyDefinitionId(value: string): PolicyDefinitionId {\n return brandId<\"PolicyDefinitionId\">(value, POLICY_DEFINITION_ID_FIELD);\n}\n\nexport function asPolicyDecisionId(value: string): PolicyDecisionId {\n return brandId<\"PolicyDecisionId\">(value, POLICY_DECISION_ID_FIELD);\n}\n\nexport function asTenantId(value: string): TenantId {\n return brandId<\"TenantId\">(value, TENANT_ID_FIELD);\n}\n\nexport function asSchoolId(value: string): SchoolId {\n return brandId<\"SchoolId\">(value, SCHOOL_ID_FIELD);\n}\n","import { UnexpectedError } from \"../../errors\";\n\nimport type {\n AsOfSource,\n PolicyKind,\n PolicyOwner,\n PolicyScopeLevel,\n} from \"./catalog-types\";\nimport type { PolicyKey } from \"./policy-key\";\n\n/**\n * Properties for creating a PolicyCatalogEntry.\n */\nexport interface PolicyCatalogEntryProps {\n readonly key: PolicyKey;\n readonly kind: PolicyKind;\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n readonly payloadSchemaVersion?: number;\n readonly owner: PolicyOwner;\n readonly allowedScopes: readonly PolicyScopeLevel[];\n readonly asOfSource: AsOfSource;\n /** Paths the context must contain for this policy to be evaluable. */\n readonly contextRequirements: readonly string[];\n readonly tags?: readonly string[];\n readonly description: string;\n}\n\n/**\n * Represents a single entry in the Policy Catalog.\n * Encapsulates metadata and validation logic for a policy.\n */\nexport class PolicyCatalogEntry {\n public readonly key: PolicyKey;\n public readonly kind: PolicyKind;\n\n public readonly gateEngineVersion?: number;\n public readonly computeEngineVersion?: number;\n public readonly payloadSchemaVersion?: number;\n\n public readonly owner: PolicyOwner;\n public readonly allowedScopes: readonly PolicyScopeLevel[];\n public readonly asOfSource: AsOfSource;\n public readonly contextRequirements: readonly string[];\n public readonly tags: readonly string[];\n public readonly description: string;\n\n constructor(props: PolicyCatalogEntryProps) {\n this.key = props.key;\n this.kind = props.kind;\n this.gateEngineVersion = props.gateEngineVersion;\n this.computeEngineVersion = props.computeEngineVersion;\n this.payloadSchemaVersion = props.payloadSchemaVersion;\n this.owner = props.owner;\n this.allowedScopes = [...props.allowedScopes];\n this.asOfSource = props.asOfSource;\n this.contextRequirements = [...props.contextRequirements];\n this.tags = [...(props.tags ?? [])];\n this.description = props.description;\n }\n\n static assertFamilyConsistency(\n entries: readonly PolicyCatalogEntry[],\n ): void {\n if (entries.length === 0) {\n throw new UnexpectedError(\n \"Cannot validate an empty PolicyCatalogEntry family\",\n );\n }\n\n const [first, ...rest] = entries;\n for (const entry of rest) {\n if (!first.key.equals(entry.key)) {\n throw new UnexpectedError(\n \"Cannot merge PolicyCatalog entries with different keys\",\n );\n }\n\n if (first.kind !== entry.kind) {\n throw new UnexpectedError(\n `PolicyCatalog entries for key \"${first.key.toString()}\" must share the same kind`,\n );\n }\n\n if (first.owner !== entry.owner) {\n throw new UnexpectedError(\n `PolicyCatalog entries for key \"${first.key.toString()}\" must share the same owner`,\n );\n }\n\n if (first.asOfSource !== entry.asOfSource) {\n throw new UnexpectedError(\n `PolicyCatalog entries for key \"${first.key.toString()}\" must share the same asOfSource`,\n );\n }\n\n if (first.description !== entry.description) {\n throw new UnexpectedError(\n `PolicyCatalog entries for key \"${first.key.toString()}\" must share the same description`,\n );\n }\n }\n }\n\n static from(\n entry: PolicyCatalogEntry | PolicyCatalogEntryProps,\n ): PolicyCatalogEntry {\n return entry instanceof PolicyCatalogEntry\n ? entry\n : new PolicyCatalogEntry(entry);\n }\n\n isGate(): boolean {\n return this.kind === \"GATE\";\n }\n\n isCompute(): boolean {\n return this.kind === \"COMPUTE\";\n }\n\n allowsScope(scope: PolicyScopeLevel): boolean {\n return this.allowedScopes.includes(scope);\n }\n\n hasExplicitVersionSelector(): boolean {\n return (\n this.gateEngineVersion !== undefined ||\n this.computeEngineVersion !== undefined ||\n this.payloadSchemaVersion !== undefined\n );\n }\n\n matchesVersion(params: {\n readonly kind: PolicyKind;\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n readonly payloadSchemaVersion?: number;\n }): boolean {\n if (this.kind !== params.kind) {\n return false;\n }\n\n if (\n this.gateEngineVersion !== undefined &&\n this.gateEngineVersion !== params.gateEngineVersion\n ) {\n return false;\n }\n\n if (\n this.computeEngineVersion !== undefined &&\n this.computeEngineVersion !== params.computeEngineVersion\n ) {\n return false;\n }\n\n if (\n this.payloadSchemaVersion !== undefined &&\n this.payloadSchemaVersion !== params.payloadSchemaVersion\n ) {\n return false;\n }\n\n return true;\n }\n\n toVariantKey(): string {\n return [\n this.key.toString(),\n this.kind,\n this.gateEngineVersion ?? \"gate:any\",\n this.computeEngineVersion ?? \"compute:any\",\n this.payloadSchemaVersion ?? \"schema:any\",\n ].join(\"::\");\n }\n\n usesNowAsOf(): boolean {\n return this.asOfSource === \"NOW\";\n }\n\n usesCallerProvidedAsOf(): boolean {\n return this.asOfSource === \"CALLER_PROVIDED\";\n }\n\n requiresContext(path: string): boolean {\n return this.contextRequirements.includes(path);\n }\n\n requiresAllContexts(paths: readonly string[]): boolean {\n return paths.every((path) => this.requiresContext(path));\n }\n\n hasTag(tag: string): boolean {\n return this.tags.includes(tag);\n }\n\n equals(other: PolicyCatalogEntry): boolean {\n return this.key.equals(other.key);\n }\n\n toJSON(): PolicyCatalogEntryProps {\n return {\n key: this.key,\n kind: this.kind,\n ...(this.gateEngineVersion !== undefined\n ? { gateEngineVersion: this.gateEngineVersion }\n : {}),\n ...(this.computeEngineVersion !== undefined\n ? { computeEngineVersion: this.computeEngineVersion }\n : {}),\n ...(this.payloadSchemaVersion !== undefined\n ? { payloadSchemaVersion: this.payloadSchemaVersion }\n : {}),\n owner: this.owner,\n allowedScopes: [...this.allowedScopes],\n asOfSource: this.asOfSource,\n contextRequirements: [...this.contextRequirements],\n tags: this.tags.length > 0 ? [...this.tags] : undefined,\n description: this.description,\n };\n }\n}\n","import { UnexpectedError } from \"../../errors\";\nimport { Result } from \"../../result/result\";\n\nimport { PolicyCatalogEntry } from \"./policy-catalog-entry\";\n\n/**\n * In-code catalog of all known policies.\n * The catalog defines the universe of policies; the database cannot invent new ones.\n */\nexport class PolicyCatalog {\n private readonly versionedEntries: ReadonlyMap<string, PolicyCatalogEntry>;\n private readonly entriesByKey: ReadonlyMap<\n string,\n readonly PolicyCatalogEntry[]\n >;\n\n constructor(entries: readonly PolicyCatalogEntry[]) {\n const families = new Map<string, PolicyCatalogEntry[]>();\n const versionedMap = new Map<string, PolicyCatalogEntry>();\n\n for (const rawEntry of entries) {\n const entry = PolicyCatalogEntry.from(rawEntry);\n const key = entry.key.toString();\n const variantKey = entry.toVariantKey();\n\n if (versionedMap.has(variantKey)) {\n throw new UnexpectedError(\n `Duplicate PolicyCatalog entry for key \"${key}\" and variant \"${variantKey}\"`,\n );\n }\n\n const family = families.get(key) ?? [];\n family.push(entry);\n families.set(key, family);\n versionedMap.set(variantKey, entry);\n }\n\n for (const family of families.values()) {\n PolicyCatalogEntry.assertFamilyConsistency(family);\n }\n\n this.versionedEntries = versionedMap;\n this.entriesByKey = families;\n }\n\n get(key: string): Result<PolicyCatalogEntry, string> {\n const familyResult = this.getFamily(key);\n if (familyResult.isErr()) {\n return Result.err(familyResult.errorOrNull()!);\n }\n\n const family = familyResult.getOrNull()!;\n if (family.length > 1) {\n return Result.err(\n `Policy key \"${key}\" has multiple catalog variants; use getVersioned(...) or getFamily(...)`,\n );\n }\n\n const [entry] = family;\n if (!entry) {\n return Result.err(`Policy not found in catalog: \"${key}\"`);\n }\n\n return Result.ok(entry);\n }\n\n getFamily(key: string): Result<readonly PolicyCatalogEntry[], string> {\n const family = this.entriesByKey.get(key);\n if (!family) {\n return Result.err(`Policy not found in catalog: \"${key}\"`);\n }\n\n return Result.ok(family);\n }\n\n getVersioned(params: {\n readonly key: string;\n readonly kind: \"GATE\" | \"COMPUTE\";\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n readonly payloadSchemaVersion?: number;\n }): Result<PolicyCatalogEntry, string> {\n const family = this.entriesByKey.get(params.key);\n if (!family || family.length === 0) {\n return Result.err(`Policy not found in catalog: \"${params.key}\"`);\n }\n\n const exactMatch = family.find((entry) => entry.matchesVersion(params));\n if (exactMatch) {\n return Result.ok(exactMatch);\n }\n\n if (family.length === 1 && !family[0].hasExplicitVersionSelector()) {\n return Result.ok(family[0]);\n }\n\n const versionDetails = [\n params.kind,\n params.gateEngineVersion !== undefined\n ? `gateEngineVersion=${params.gateEngineVersion}`\n : null,\n params.computeEngineVersion !== undefined\n ? `computeEngineVersion=${params.computeEngineVersion}`\n : null,\n params.payloadSchemaVersion !== undefined\n ? `payloadSchemaVersion=${params.payloadSchemaVersion}`\n : null,\n ]\n .filter((part): part is string => part !== null)\n .join(\", \");\n\n return Result.err(\n `Policy variant not found in catalog: \"${params.key}\" (${versionDetails})`,\n );\n }\n\n list(): readonly PolicyCatalogEntry[] {\n return Array.from(this.versionedEntries.values());\n }\n\n has(key: string): boolean {\n return this.entriesByKey.has(key);\n }\n}\n","import type { PolicyPackage } from \"../package/policy-package\";\n\nimport { PolicyCatalog } from \"./policy-catalog\";\nimport { PolicyCatalogEntry } from \"./policy-catalog-entry\";\n\n// ─── Factory ────────────────────────────────────────────────────────────────\n\n/**\n * Aggregates catalog entries contributed by each module package into a single\n * PolicyCatalog. The core knows nothing about concrete modules — callers\n * are responsible for passing all relevant packages at composition time.\n */\nexport class PolicyCatalogFactory {\n static build(packages: readonly PolicyPackage[]): PolicyCatalog {\n const entries = packages.flatMap((policyPackage) =>\n Array.from(policyPackage.catalogEntries).map(\n PolicyCatalogEntry.from,\n ),\n );\n\n return new PolicyCatalog(entries);\n }\n}\n","import { Result } from \"../../result/result\";\n\n/**\n * PolicyKey value object.\n *\n * Format: `module.area.policy_name` (exactly 3 dot-separated segments).\n * - module: structural segment (lowercase alphanumeric + underscore, starting with a letter)\n * - area: structural segment (lowercase alphanumeric + underscore, starting with a letter)\n * - name: specific policy identifier (lowercase alphanumeric + underscore, starting with a letter)\n */\n\nconst SEGMENT_PATTERN = /^[a-z][a-z0-9_]*$/;\nconst MAX_POLICY_KEY_LENGTH = 255;\n\nexport class PolicyKey {\n public readonly module: string;\n public readonly area: string;\n public readonly name: string;\n\n private constructor(module: string, area: string, name: string) {\n this.module = module;\n this.area = area;\n this.name = name;\n Object.freeze(this);\n }\n\n static parse(raw: string): Result<PolicyKey, string> {\n if (!raw || typeof raw !== \"string\") {\n return Result.err(\"PolicyKey cannot be empty\");\n }\n\n if (raw.length > MAX_POLICY_KEY_LENGTH) {\n return Result.err(\n `PolicyKey cannot exceed ${MAX_POLICY_KEY_LENGTH} characters, got ${raw.length}`,\n );\n }\n\n const segments = raw.split(\".\");\n if (segments.length !== 3) {\n return Result.err(\n `PolicyKey must have exactly 3 segments (module.area.name), got ${segments.length}: \"${raw}\"`,\n );\n }\n\n const [rawModule, rawArea, name] = segments;\n\n if (!SEGMENT_PATTERN.test(rawModule)) {\n return Result.err(\n `PolicyKey segment \"module\" is invalid: \"${rawModule}\". ` +\n \"Must start with a lowercase letter and contain only [a-z0-9_].\",\n );\n }\n\n if (!SEGMENT_PATTERN.test(rawArea)) {\n return Result.err(\n `PolicyKey segment \"area\" is invalid: \"${rawArea}\". ` +\n \"Must start with a lowercase letter and contain only [a-z0-9_].\",\n );\n }\n\n if (!SEGMENT_PATTERN.test(name)) {\n return Result.err(\n `PolicyKey segment \"name\" is invalid: \"${name}\". ` +\n \"Must start with a lowercase letter and contain only [a-z0-9_].\",\n );\n }\n\n return Result.ok(new PolicyKey(rawModule, rawArea, name));\n }\n\n toString(): string {\n return `${this.module}.${this.area}.${this.name}`;\n }\n\n equals(other: PolicyKey): boolean {\n return this.toString() === other.toString();\n }\n}\n","import type { PolicyScopeLevel } from \"../catalog\";\nimport type { SchoolId, TenantId } from \"../policy-ids\";\n\n/**\n * Scope attached to a PolicyDefinition — defines where it applies.\n */\nexport interface PolicyScope {\n readonly level: PolicyScopeLevel;\n readonly tenantId: TenantId | null;\n readonly schoolId: SchoolId | null;\n}\n\n/**\n * Ordered list of scopes from most-specific to least-specific.\n * Used by the resolver to match definitions.\n *\n * Example:\n * ```\n * [\n * { level: 'SCHOOL', tenantId: 't1', schoolId: 's1' },\n * { level: 'TENANT', tenantId: 't1', schoolId: null },\n * { level: 'GLOBAL', tenantId: null, schoolId: null },\n * ]\n * ```\n */\nexport type ScopeChain = readonly PolicyScope[];\n\n/**\n * Numeric weight for scope specificity (higher = more specific).\n */\nconst SCOPE_WEIGHT: Record<PolicyScopeLevel, number> = {\n SCHOOL: 3,\n TENANT: 2,\n GLOBAL: 1,\n};\n\nexport class PolicyScopeMatcher {\n static weight(level: PolicyScopeLevel): number {\n return SCOPE_WEIGHT[level];\n }\n\n static matchesChain(defScope: PolicyScope, chain: ScopeChain): boolean {\n return chain.some((scope) =>\n PolicyScopeMatcher.equals(defScope, scope),\n );\n }\n\n static equals(a: PolicyScope, b: PolicyScope): boolean {\n return (\n a.level === b.level &&\n a.tenantId === b.tenantId &&\n a.schoolId === b.schoolId\n );\n }\n}\n","import type {\n FindCandidatesParams,\n PolicyDefinition,\n} from \"./policy-definition\";\nimport type { PolicyDefinitionRepository } from \"./policy-definition-repository\";\nimport { PolicyScopeMatcher } from \"./policy-scope\";\n\nexport class InMemoryPolicyDefinitionRepository implements PolicyDefinitionRepository {\n private readonly definitions: readonly PolicyDefinition[];\n private readonly definitionsByPolicyKey: ReadonlyMap<\n string,\n readonly PolicyDefinition[]\n >;\n\n constructor(definitions: readonly PolicyDefinition[]) {\n this.definitions = definitions;\n this.definitionsByPolicyKey = definitions.reduce<\n Map<string, PolicyDefinition[]>\n >((index, definition) => {\n const existingDefinitions = index.get(definition.policyKey) ?? [];\n existingDefinitions.push(definition);\n index.set(definition.policyKey, existingDefinitions);\n return index;\n }, new Map<string, PolicyDefinition[]>());\n }\n\n findCandidates(params: FindCandidatesParams): PolicyDefinition[] {\n const {\n policyKey,\n kind,\n payloadSchemaVersion,\n asOf,\n contextVersion,\n scopeChain,\n } = params;\n\n const candidatesForPolicyKey =\n this.definitionsByPolicyKey.get(policyKey) ?? [];\n\n const candidates = candidatesForPolicyKey.filter((def) => {\n // Match kind\n if (def.kind !== kind) return false;\n if (\n payloadSchemaVersion !== undefined &&\n def.payloadSchemaVersion !== payloadSchemaVersion\n ) {\n return false;\n }\n\n if (!def.enabled) return false;\n\n // Only PUBLISHED\n if (def.status !== \"PUBLISHED\") return false;\n\n // Effective date range (effectiveFrom <= asOf, and effectiveTo is null or > asOf)\n if (def.effectiveFrom > asOf) return false;\n if (def.effectiveTo !== null && def.effectiveTo <= asOf)\n return false;\n\n // Context version compatibility\n if (contextVersion < def.contextVersionMin) return false;\n if (contextVersion > def.contextVersionMax) return false;\n\n // Scope must match one of the chain entries\n if (!PolicyScopeMatcher.matchesChain(def.scope, scopeChain)) {\n return false;\n }\n\n return true;\n });\n\n return candidates;\n }\n}\n","// Semver without build metadata: comparisons are defined only over\n// major.minor.patch and optional pre-release identifiers (semver §11).\nexport const POLICY_SEMVER_PATTERN =\n /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\\+([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?$/;\n\ninterface ParsedSemver {\n major: number;\n minor: number;\n patch: number;\n preRelease: string | null;\n}\n\nfunction parseSemver(version: string): ParsedSemver {\n const withoutBuild = version.split(\"+\")[0];\n const [core, preRelease = null] = withoutBuild.split(\"-\") as [\n string,\n string | undefined,\n ];\n const [major, minor, patch] = core.split(\".\").map(Number) as [\n number,\n number,\n number,\n ];\n return { major, minor, patch, preRelease: preRelease ?? null };\n}\n\nfunction comparePreRelease(a: string, b: string): number {\n const aIds = a.split(\".\");\n const bIds = b.split(\".\");\n const len = Math.max(aIds.length, bIds.length);\n\n for (let i = 0; i < len; i++) {\n const ai = aIds[i];\n const bi = bIds[i];\n\n // Shorter pre-release has lower precedence when prefix matches (semver §11.4.4)\n if (ai === undefined) return -1;\n if (bi === undefined) return 1;\n\n const aNum = Number(ai);\n const bNum = Number(bi);\n const aIsNum = !Number.isNaN(aNum);\n const bIsNum = !Number.isNaN(bNum);\n\n // Numeric identifiers always have lower precedence than alphanumeric (semver §11.4.1)\n if (aIsNum && !bIsNum) return -1;\n if (!aIsNum && bIsNum) return 1;\n\n if (aIsNum && bIsNum) {\n if (aNum !== bNum) return aNum - bNum;\n } else {\n if (ai < bi) return -1;\n if (ai > bi) return 1;\n }\n }\n\n return 0;\n}\n\n/**\n * Compares two valid semver strings.\n * Returns a negative number if a < b, 0 if a === b, positive if a > b.\n *\n * Callers are expected to pass only strings that already passed\n * `POLICY_SEMVER_PATTERN` validation (i.e. values stored in PolicyDefinition).\n */\nexport function comparePolicySemver(a: string, b: string): number {\n const av = parseSemver(a);\n const bv = parseSemver(b);\n\n if (av.major !== bv.major) return av.major - bv.major;\n if (av.minor !== bv.minor) return av.minor - bv.minor;\n if (av.patch !== bv.patch) return av.patch - bv.patch;\n\n // Release > pre-release (semver §11.3)\n if (av.preRelease === null && bv.preRelease !== null) return 1;\n if (av.preRelease !== null && bv.preRelease === null) return -1;\n if (av.preRelease !== null && bv.preRelease !== null) {\n return comparePreRelease(av.preRelease, bv.preRelease);\n }\n\n return 0;\n}\n","import { InvariantViolationException } from \"../../exceptions/invariant-violation-exception\";\nimport type { PolicyKind } from \"../catalog\";\nimport type { PolicyDefinitionId } from \"../policy-ids\";\n\nimport type { AnyPolicyPayload } from \"./policy-payload.contracts\";\nimport type { PolicyScope } from \"./policy-scope\";\nimport { POLICY_SEMVER_PATTERN } from \"./policy-semver\";\n\n// ─── Status ────────────────────────────────────────────────────────────────\n\nexport type PolicyDefinitionStatus = \"DRAFT\" | \"PUBLISHED\" | \"RETIRED\";\n\n// ─── Definition props ───────────────────────────────────────────────────────\n\nexport interface BasePolicyDefinitionProps<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> {\n readonly id: PolicyDefinitionId;\n readonly policyKey: K;\n readonly policyVersion: string; // semver\n readonly payloadSchemaVersion: number;\n readonly contextVersionMin: number;\n readonly contextVersionMax: number;\n readonly enabled: boolean;\n readonly status: PolicyDefinitionStatus;\n readonly scope: PolicyScope;\n readonly effectiveFrom: Date;\n readonly effectiveTo: Date | null;\n readonly priority: number;\n readonly payloadJson: P;\n readonly payloadHash: string;\n readonly createdAt: Date;\n readonly publishedAt: Date | null;\n}\n\nexport interface GatePolicyDefinitionProps<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> extends BasePolicyDefinitionProps<K, P> {\n readonly kind: \"GATE\";\n readonly gateEngineVersion: number;\n}\n\nexport interface ComputePolicyDefinitionProps<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> extends BasePolicyDefinitionProps<K, P> {\n readonly kind: \"COMPUTE\";\n readonly computeEngineVersion: number;\n}\n\nexport type GatePolicyDefinitionInput<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> = Omit<GatePolicyDefinitionProps<K, P>, \"kind\" | \"enabled\"> & {\n readonly enabled?: boolean;\n};\n\nexport type ComputePolicyDefinitionInput<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> = Omit<ComputePolicyDefinitionProps<K, P>, \"kind\" | \"enabled\"> & {\n readonly enabled?: boolean;\n};\n\nexport type PolicyDefinitionProps<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> = GatePolicyDefinitionProps<K, P> | ComputePolicyDefinitionProps<K, P>;\n\n// ─── Definition row (as if loaded from database) ────────────────────────────\n\nexport class PolicyDefinition<\n K extends string = string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n> {\n private static assertPolicyVersionIsSemver(policyVersion: string): void {\n if (!POLICY_SEMVER_PATTERN.test(policyVersion)) {\n throw new InvariantViolationException(\n `PolicyDefinition.policyVersion must be a valid semver. Received: \"${policyVersion}\"`,\n );\n }\n }\n\n public readonly id: PolicyDefinitionId;\n public readonly policyKey: K;\n\n public readonly policyVersion: string;\n public readonly payloadSchemaVersion: number;\n public readonly contextVersionMin: number;\n public readonly contextVersionMax: number;\n public readonly gateEngineVersion?: number;\n public readonly computeEngineVersion?: number;\n\n public readonly enabled: boolean;\n public readonly status: PolicyDefinitionStatus;\n public readonly scope: PolicyScope;\n public readonly effectiveFrom: Date;\n public readonly effectiveTo: Date | null;\n public readonly priority: number;\n public readonly payloadJson: P;\n public readonly payloadHash: string;\n public readonly createdAt: Date;\n public readonly publishedAt: Date | null;\n public readonly kind: PolicyKind;\n\n private constructor(props: PolicyDefinitionProps<K, P>) {\n // The static factories are the supported API. This guard stays here because\n // TypeScript privacy does not protect runtime-only construction paths.\n this.id = props.id;\n this.policyKey = props.policyKey;\n PolicyDefinition.assertPolicyVersionIsSemver(props.policyVersion);\n this.policyVersion = props.policyVersion;\n this.payloadSchemaVersion = props.payloadSchemaVersion;\n this.contextVersionMin = props.contextVersionMin;\n this.contextVersionMax = props.contextVersionMax;\n this.enabled = props.enabled;\n this.status = props.status;\n this.scope = props.scope;\n this.effectiveFrom = props.effectiveFrom;\n this.effectiveTo = props.effectiveTo;\n this.priority = props.priority;\n this.payloadJson = props.payloadJson;\n this.payloadHash = props.payloadHash;\n this.createdAt = props.createdAt;\n this.publishedAt = props.publishedAt;\n this.kind = props.kind;\n\n if (props.kind === \"GATE\") {\n if (props.gateEngineVersion === undefined) {\n throw new InvariantViolationException(\n `PolicyDefinition of kind 'GATE' must have a 'gateEngineVersion'. Policy key: ${props.policyKey}`,\n );\n }\n this.gateEngineVersion = props.gateEngineVersion;\n } else {\n if (props.computeEngineVersion === undefined) {\n throw new InvariantViolationException(\n `PolicyDefinition of kind 'COMPUTE' must have a 'computeEngineVersion'. Policy key: ${props.policyKey}`,\n );\n }\n this.computeEngineVersion = props.computeEngineVersion;\n }\n }\n\n static gate<\n K extends string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n >(props: GatePolicyDefinitionInput<K, P>): PolicyDefinition<K, P> {\n return new PolicyDefinition<K, P>({\n ...props,\n enabled: props.enabled ?? true,\n kind: \"GATE\",\n });\n }\n\n static compute<\n K extends string,\n P extends AnyPolicyPayload = AnyPolicyPayload,\n >(props: ComputePolicyDefinitionInput<K, P>): PolicyDefinition<K, P> {\n return new PolicyDefinition<K, P>({\n ...props,\n enabled: props.enabled ?? true,\n kind: \"COMPUTE\",\n });\n }\n\n isGate(): this is PolicyDefinition<K, P> & {\n readonly kind: \"GATE\";\n readonly gateEngineVersion: number;\n } {\n return this.kind === \"GATE\";\n }\n\n isCompute(): this is PolicyDefinition<K, P> & {\n readonly kind: \"COMPUTE\";\n readonly computeEngineVersion: number;\n } {\n return this.kind === \"COMPUTE\";\n }\n}\n\n// ─── Query parameters ───────────────────────────────────────────────────────\n\nexport interface FindCandidatesParams {\n readonly policyKey: string;\n readonly kind: PolicyKind;\n readonly payloadSchemaVersion?: number;\n readonly asOf: Date;\n readonly contextVersion: number;\n readonly scopeChain: readonly PolicyScope[];\n}\n","import { Result } from \"../../result/result\";\n\nimport type { ContextResolverRegistry } from \"./context-registry\";\nimport type {\n ContextResolverResilienceOptions,\n ContextResolverRetryOptions,\n ContextValueResolver,\n} from \"./context-resolver\";\nimport type { ContextSeed } from \"./context-seed\";\nimport { PolicyContextPath } from \"./path\";\n\ninterface NormalizedContextResolverRetryOptions {\n readonly maxAttempts: number;\n readonly initialDelayMs: number;\n readonly maxDelayMs: number;\n readonly backoffMultiplier: number;\n}\n\ninterface NormalizedContextResolverCircuitBreakerOptions {\n readonly failureThreshold: number;\n readonly cooldownMs: number;\n}\n\ninterface NormalizedContextResolverResilienceOptions {\n readonly timeoutMs: number | null;\n readonly retry: NormalizedContextResolverRetryOptions;\n readonly circuitBreaker: NormalizedContextResolverCircuitBreakerOptions | null;\n}\n\ninterface ContextResolverCircuitState {\n readonly failureCount: number;\n readonly openUntilMs: number | null;\n}\n\nexport interface PolicyContextBuilderOptions {\n readonly defaultResolverResilience?: ContextResolverResilienceOptions;\n readonly now?: () => number;\n readonly sleep?: (delayMs: number) => Promise<void>;\n}\n\nconst DEFAULT_RESOLVER_RETRY_OPTIONS: NormalizedContextResolverRetryOptions = {\n maxAttempts: 1,\n initialDelayMs: 25,\n maxDelayMs: 1_000,\n backoffMultiplier: 2,\n};\n\n/**\n * Builds a context object by resolving required paths from a seed.\n */\nexport class PolicyContextBuilder {\n private readonly circuitStates = new Map<\n string,\n ContextResolverCircuitState\n >();\n private readonly defaultResolverResilience?: ContextResolverResilienceOptions;\n private readonly now: () => number;\n private readonly sleep: (delayMs: number) => Promise<void>;\n\n constructor(\n private readonly registry: ContextResolverRegistry,\n options: PolicyContextBuilderOptions = {},\n ) {\n this.defaultResolverResilience = options.defaultResolverResilience;\n this.now = options.now ?? Date.now;\n this.sleep =\n options.sleep ??\n (async (delayMs) => {\n if (delayMs <= 0) {\n return;\n }\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, delayMs);\n });\n });\n }\n\n private static clampPositiveInteger(\n value: number | undefined,\n fallback: number,\n ): number {\n if (value === undefined || !Number.isFinite(value)) {\n return fallback;\n }\n\n return Math.max(1, Math.trunc(value));\n }\n\n private static clampNonNegativeInteger(\n value: number | undefined,\n fallback: number,\n ): number {\n if (value === undefined || !Number.isFinite(value)) {\n return fallback;\n }\n\n return Math.max(0, Math.trunc(value));\n }\n\n private static normalizeTimeoutMs(\n value: number | undefined,\n ): number | null {\n if (value === undefined || !Number.isFinite(value) || value <= 0) {\n return null;\n }\n\n return Math.trunc(value);\n }\n\n private static mergeRetryOptions(\n defaults: ContextResolverRetryOptions | false | undefined,\n overrides: ContextResolverRetryOptions | false | undefined,\n ): ContextResolverRetryOptions | false | undefined {\n if (overrides === false) {\n return false;\n }\n\n if (overrides !== undefined) {\n return {\n ...(defaults === false || defaults === undefined\n ? {}\n : defaults),\n ...overrides,\n };\n }\n\n return defaults;\n }\n\n private static mergeCircuitBreakerOptions(\n defaults:\n | ContextResolverResilienceOptions[\"circuitBreaker\"]\n | undefined,\n overrides:\n | ContextResolverResilienceOptions[\"circuitBreaker\"]\n | undefined,\n ): ContextResolverResilienceOptions[\"circuitBreaker\"] | undefined {\n if (overrides === false) {\n return false;\n }\n\n if (overrides !== undefined) {\n return {\n ...(defaults === false || defaults === undefined\n ? {}\n : defaults),\n ...overrides,\n };\n }\n\n return defaults;\n }\n\n private resolveResilienceOptions(\n resolver: ContextValueResolver,\n ): NormalizedContextResolverResilienceOptions {\n const defaults = this.defaultResolverResilience;\n const override = resolver.resilience;\n const retry = PolicyContextBuilder.mergeRetryOptions(\n defaults?.retry,\n override?.retry,\n );\n const circuitBreaker = PolicyContextBuilder.mergeCircuitBreakerOptions(\n defaults?.circuitBreaker,\n override?.circuitBreaker,\n );\n const retryOptions = retry === false ? undefined : retry;\n const circuitBreakerOptions =\n circuitBreaker === false ? undefined : circuitBreaker;\n\n return {\n timeoutMs: PolicyContextBuilder.normalizeTimeoutMs(\n override?.timeoutMs ?? defaults?.timeoutMs,\n ),\n retry: {\n maxAttempts: PolicyContextBuilder.clampPositiveInteger(\n retryOptions?.maxAttempts,\n DEFAULT_RESOLVER_RETRY_OPTIONS.maxAttempts,\n ),\n initialDelayMs: PolicyContextBuilder.clampNonNegativeInteger(\n retryOptions?.initialDelayMs,\n DEFAULT_RESOLVER_RETRY_OPTIONS.initialDelayMs,\n ),\n maxDelayMs: PolicyContextBuilder.clampNonNegativeInteger(\n retryOptions?.maxDelayMs,\n DEFAULT_RESOLVER_RETRY_OPTIONS.maxDelayMs,\n ),\n backoffMultiplier: PolicyContextBuilder.clampPositiveInteger(\n retryOptions?.backoffMultiplier,\n DEFAULT_RESOLVER_RETRY_OPTIONS.backoffMultiplier,\n ),\n },\n circuitBreaker:\n circuitBreakerOptions === undefined\n ? null\n : {\n failureThreshold:\n PolicyContextBuilder.clampPositiveInteger(\n circuitBreakerOptions.failureThreshold,\n 5,\n ),\n cooldownMs: PolicyContextBuilder.clampPositiveInteger(\n circuitBreakerOptions.cooldownMs,\n 30_000,\n ),\n },\n };\n }\n\n private getRetryDelayMs(\n attempt: number,\n retry: NormalizedContextResolverRetryOptions,\n ): number {\n return Math.min(\n retry.initialDelayMs * retry.backoffMultiplier ** (attempt - 1),\n retry.maxDelayMs,\n );\n }\n\n private resetCircuit(path: string): void {\n this.circuitStates.delete(path);\n }\n\n private isCircuitOpen(\n path: string,\n circuitBreaker: NormalizedContextResolverCircuitBreakerOptions | null,\n ): boolean {\n if (circuitBreaker === null) {\n return false;\n }\n\n const state = this.circuitStates.get(path);\n if (state === undefined || state.openUntilMs === null) {\n return false;\n }\n\n if (state.openUntilMs <= this.now()) {\n this.resetCircuit(path);\n return false;\n }\n\n return true;\n }\n\n private recordResolverFailure(\n path: string,\n circuitBreaker: NormalizedContextResolverCircuitBreakerOptions | null,\n ): void {\n if (circuitBreaker === null) {\n return;\n }\n\n const currentFailureCount =\n this.circuitStates.get(path)?.failureCount ?? 0;\n const nextFailureCount = currentFailureCount + 1;\n\n if (nextFailureCount >= circuitBreaker.failureThreshold) {\n this.circuitStates.set(path, {\n failureCount: 0,\n openUntilMs: this.now() + circuitBreaker.cooldownMs,\n });\n return;\n }\n\n this.circuitStates.set(path, {\n failureCount: nextFailureCount,\n openUntilMs: null,\n });\n }\n\n private static describeThrownResolverError(error: unknown): string {\n if (error instanceof Error) {\n return `threw ${error.name}: ${error.message}`;\n }\n\n return `threw ${String(error)}`;\n }\n\n private async resolveOnce(\n resolver: ContextValueResolver,\n seed: ContextSeed,\n timeoutMs: number | null,\n ): Promise<Result<unknown, string>> {\n const execute = async (): Promise<Result<unknown, string>> => {\n try {\n return await resolver.resolve(seed);\n } catch (error) {\n return Result.err(\n PolicyContextBuilder.describeThrownResolverError(error),\n );\n }\n };\n\n if (timeoutMs === null) {\n return execute();\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n try {\n return await Promise.race([\n execute(),\n new Promise<Result<unknown, string>>((resolve) => {\n timeoutId = setTimeout(() => {\n resolve(Result.err(`timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n private async resolveWithResilience(\n path: string,\n resolver: ContextValueResolver,\n seed: ContextSeed,\n ): Promise<Result<unknown, string>> {\n const resilience = this.resolveResilienceOptions(resolver);\n\n if (this.isCircuitOpen(path, resilience.circuitBreaker)) {\n return Result.err(\"circuit breaker is open\");\n }\n\n let lastError = \"resolver failed\";\n\n for (\n let attempt = 1;\n attempt <= resilience.retry.maxAttempts;\n attempt++\n ) {\n const result = await this.resolveOnce(\n resolver,\n seed,\n resilience.timeoutMs,\n );\n\n if (result.isOk()) {\n this.resetCircuit(path);\n return result;\n }\n\n lastError = result.errorOrNull() ?? lastError;\n\n if (attempt < resilience.retry.maxAttempts) {\n await this.sleep(\n this.getRetryDelayMs(attempt, resilience.retry),\n );\n }\n }\n\n this.recordResolverFailure(path, resilience.circuitBreaker);\n return Result.err(lastError);\n }\n\n /**\n * Resolves all required context paths and returns a flat context object.\n * If any required path cannot be resolved, returns an error.\n */\n async build(\n requirements: readonly string[],\n seed: ContextSeed,\n ): Promise<Result<Record<string, unknown>, string>> {\n const context: Record<string, unknown> = {};\n\n for (const path of requirements) {\n const resolver = this.registry.get(path);\n if (!resolver) {\n return Result.err(`Missing resolver for path \"${path}\"`);\n }\n\n const result = await this.resolveWithResilience(\n path,\n resolver,\n seed,\n );\n if (result.isErr()) {\n return Result.err(\n `Resolver error for path \"${path}\": ${result.errorOrNull()}`,\n );\n }\n\n const setPathResult = PolicyContextPath.set(\n context,\n path,\n result.getOrNull(),\n );\n if (setPathResult.isErr()) {\n return Result.err(setPathResult.errorOrNull()!);\n }\n }\n\n // Final validation: ensure every required path resolved to a defined value.\n // `undefined` is rejected explicitly because resolvers that \"succeed\" with\n // undefined indicate an unresolved field, not a present-but-empty one.\n const missing = requirements.filter((path) => {\n const result = PolicyContextPath.getOrAbsent(context, path);\n return result.isErr() || result.getOrNull() === undefined;\n });\n if (missing.length > 0) {\n return Result.err(\n `Context missing required paths after resolution: ${missing.join(\n \", \",\n )}`,\n );\n }\n\n return Result.ok(context);\n }\n}\n","import { Result } from \"../../result/result\";\n\nimport type { ContextValueResolver } from \"./context-resolver\";\n\nexport interface ContextResolverRegistrationOptions {\n readonly namespace?: string;\n}\n\ninterface RegisteredContextResolver {\n readonly namespace: string;\n readonly resolver: ContextValueResolver;\n}\n\nconst DEFAULT_CONTEXT_RESOLVER_NAMESPACE = \"default\";\n\nfunction normalizeNamespace(namespace?: string): string {\n const normalized = namespace?.trim();\n\n if (normalized === undefined || normalized.length === 0) {\n return DEFAULT_CONTEXT_RESOLVER_NAMESPACE;\n }\n\n return normalized;\n}\n\n/**\n * Registry of context value resolvers, keyed by path.\n */\nexport class ContextResolverRegistry {\n private readonly resolvers = new Map<string, RegisteredContextResolver>();\n\n register(\n resolver: ContextValueResolver,\n options: ContextResolverRegistrationOptions = {},\n ): Result<void, string> {\n const namespace = normalizeNamespace(options.namespace);\n const existing = this.resolvers.get(resolver.path);\n\n if (existing !== undefined && existing.namespace !== namespace) {\n return Result.err(\n `Resolver path \"${resolver.path}\" is already registered by namespace \"${existing.namespace}\" and cannot be replaced by \"${namespace}\".`,\n );\n }\n\n this.resolvers.set(resolver.path, {\n namespace,\n resolver,\n });\n\n return Result.ok(undefined);\n }\n\n registerAll(\n resolvers: readonly ContextValueResolver[],\n options: ContextResolverRegistrationOptions = {},\n ): Result<void, string> {\n for (const r of resolvers) {\n const registrationResult = this.register(r, options);\n if (registrationResult.isErr()) {\n return registrationResult;\n }\n }\n\n return Result.ok(undefined);\n }\n\n get(path: string): ContextValueResolver | undefined {\n return this.resolvers.get(path)?.resolver;\n }\n\n has(path: string): boolean {\n return this.resolvers.has(path);\n }\n\n getNamespace(path: string): string | undefined {\n return this.resolvers.get(path)?.namespace;\n }\n}\n\nexport function registerNamespacedContextResolversIn(\n registry: ContextResolverRegistry,\n namespace: string,\n resolvers: readonly ContextValueResolver[],\n): Result<ContextResolverRegistry, string> {\n const registrationResult = registry.registerAll(resolvers, {\n namespace,\n });\n if (registrationResult.isErr()) {\n return Result.err(registrationResult.errorOrNull()!);\n }\n\n return Result.ok(registry);\n}\n\nexport { DEFAULT_CONTEXT_RESOLVER_NAMESPACE };\n","import { Result } from \"../../result/result\";\n\nimport {\n ContextResolverRegistry,\n registerNamespacedContextResolversIn,\n} from \"./context-registry\";\n\nimport type { ContextValueResolver } from \"./context-resolver\";\n\n/**\n * Official instance of the ContextResolverRegistry.\n * Use `new ContextResolverRegistry()` plus `registerNamespacedContextResolversIn`\n * when each runtime/composition root needs its own isolated resolver graph.\n */\nexport const contextResolverRegistry = new ContextResolverRegistry();\n\nexport function registerNamespacedContextResolvers(\n namespace: string,\n resolvers: readonly ContextValueResolver[],\n): Result<ContextResolverRegistry, string> {\n return registerNamespacedContextResolversIn(\n contextResolverRegistry,\n namespace,\n resolvers,\n );\n}\n","import { Result } from \"../../result/result\";\n\nimport type { SchoolId, TenantId } from \"../policy-ids\";\n\n/**\n * Seed data provided by the use case / caller.\n * Contains raw IDs and inputs that the context system will resolve into paths.\n * Each resolver is responsible for validating and extracting what it needs from fields.\n */\nexport interface ContextSeed {\n readonly tenantId: TenantId;\n readonly schoolId: SchoolId;\n readonly fields: Record<string, unknown>;\n}\n\nexport class ContextSeedValidator {\n private static isBlankSeedId(value: string): boolean {\n return value.trim().length === 0;\n }\n\n static validate(seed: ContextSeed): Result<ContextSeed, string> {\n if (ContextSeedValidator.isBlankSeedId(seed.tenantId)) {\n return Result.err(\n \"ContextSeed tenantId must be a non-empty string\",\n );\n }\n\n if (ContextSeedValidator.isBlankSeedId(seed.schoolId)) {\n return Result.err(\n \"ContextSeed schoolId must be a non-empty string\",\n );\n }\n\n return Result.ok(seed);\n }\n}\n","import type { AsOfSource } from \"../catalog\";\nimport type { ContextSeed } from \"../context\";\nimport { Result } from \"../../result/result\";\nimport { isValidDate } from \"../../shared/temporal-guards\";\n\nconst DEFAULT_MAX_AS_OF_FUTURE_YEARS = 10;\n\nexport interface DeriveAsOfOptions {\n readonly maxFutureYears?: number;\n}\n\nexport class PolicyAsOfResolver {\n private static resolveMaxFutureYears(\n options: DeriveAsOfOptions,\n ): Result<number, string> {\n const maxFutureYears =\n options.maxFutureYears ?? DEFAULT_MAX_AS_OF_FUTURE_YEARS;\n\n if (!Number.isInteger(maxFutureYears) || maxFutureYears < 0) {\n return Result.err(\n `deriveAsOf maxFutureYears must be a non-negative integer. Received: ${maxFutureYears}`,\n );\n }\n\n return Result.ok(maxFutureYears);\n }\n\n static derive(\n source: AsOfSource,\n seed: ContextSeed,\n now: Date,\n options: DeriveAsOfOptions = {},\n ): Result<Date, string> {\n const maxFutureYearsResult =\n PolicyAsOfResolver.resolveMaxFutureYears(options);\n if (maxFutureYearsResult.isErr()) {\n return Result.err(maxFutureYearsResult.errorOrNull()!);\n }\n const maxFutureYears = maxFutureYearsResult.getOrNull()!;\n\n switch (source) {\n case \"NOW\":\n return Result.ok(now);\n\n case \"CALLER_PROVIDED\": {\n const asOf = seed.fields[\"asOf\"];\n if (!isValidDate(asOf)) {\n return Result.err(\n 'asOfSource \"CALLER_PROVIDED\" requires seed.fields.asOf to be a Date',\n );\n }\n\n const maxFuture = new Date(now);\n maxFuture.setFullYear(maxFuture.getFullYear() + maxFutureYears);\n if (asOf > maxFuture) {\n return Result.err(\n `asOf date is more than ${maxFutureYears} years in the future (received ${asOf.toISOString()})`,\n );\n }\n\n return Result.ok(asOf);\n }\n\n default:\n return Result.err(`Unknown asOfSource: \"${source}\"`);\n }\n }\n}\n","import type { PolicyDefinition } from \"../defs\";\nimport { PolicyScopeMatcher } from \"../defs\";\nimport { comparePolicySemver } from \"../defs/policy-semver\";\nimport { Result } from \"../../result/result\";\n\n/**\n * Selects the best policy definition from a list of already-filtered candidates.\n *\n * Ordering criteria (highest priority first):\n * 1. Scope specificity: SCHOOL (3) > TENANT (2) > GLOBAL (1)\n * 2. Priority: higher number wins\n * 3. publishedAt descending (fallback to createdAt)\n * 4. Engine version descending (prefer-latest-engine-version — deterministic tiebreaker)\n * 5. policyVersion descending (semver — final deterministic tiebreaker)\n */\nexport class PolicyResolver {\n resolveBest(\n candidates: readonly PolicyDefinition[],\n ): Result<PolicyDefinition, string> {\n if (candidates.length === 0) {\n return Result.err(\n \"No matching policy definition found (candidates list is empty)\",\n );\n }\n\n const sorted = [...candidates].sort((a, b) => {\n // 1) Scope specificity (higher weight = more specific)\n const scopeDiff =\n PolicyScopeMatcher.weight(b.scope.level) -\n PolicyScopeMatcher.weight(a.scope.level);\n if (scopeDiff !== 0) return scopeDiff;\n\n // 2) Priority DESC\n const priorityDiff = b.priority - a.priority;\n if (priorityDiff !== 0) return priorityDiff;\n\n // 3) publishedAt DESC (fallback createdAt)\n const aDate = a.publishedAt ?? a.createdAt;\n const bDate = b.publishedAt ?? b.createdAt;\n const dateDiff = bDate.getTime() - aDate.getTime();\n if (dateDiff !== 0) return dateDiff;\n\n // 4) Engine version DESC — prefers the definition running on the most\n // capable engine when scope/priority/date are identical.\n const aEngine = a.gateEngineVersion ?? a.computeEngineVersion ?? 0;\n const bEngine = b.gateEngineVersion ?? b.computeEngineVersion ?? 0;\n const engineDiff = bEngine - aEngine;\n if (engineDiff !== 0) return engineDiff;\n\n // 5) policyVersion DESC (semver) — final deterministic tiebreaker so\n // the winner never depends on repository return order.\n return comparePolicySemver(b.policyVersion, a.policyVersion);\n });\n\n return Result.ok(sorted[0]);\n }\n}\n","import type { PolicyKind } from \"../catalog\";\n\n// ─── Error Union ─────────────────────────────────────────────────────────────\n\nexport type PolicyEvaluationError =\n | {\n readonly kind: \"INVALID_CONTEXT\";\n readonly stage:\n | \"SEED_VALIDATION\"\n | \"AS_OF_DERIVATION\"\n | \"CONTEXT_BUILD\";\n readonly policyKey: string;\n readonly message: string;\n readonly cause: string;\n }\n | {\n readonly kind: \"INVALID_POLICY_KEY\";\n readonly rawPolicyKey: string;\n readonly message: string;\n readonly cause: string;\n }\n | {\n readonly kind: \"POLICY_NOT_FOUND\";\n readonly policyKey: string;\n readonly message: string;\n readonly cause: string;\n }\n | {\n readonly kind: \"POLICY_DEFINITION_NOT_FOUND\";\n readonly policyKey: string;\n readonly contextVersion: number;\n readonly asOf: Date;\n readonly message: string;\n readonly cause: string;\n }\n | {\n readonly kind: \"POLICY_VARIANT_NOT_FOUND\";\n readonly policyKey: string;\n readonly policyKind: PolicyKind;\n readonly payloadSchemaVersion: number;\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n readonly message: string;\n readonly cause: string;\n }\n | {\n readonly kind: \"ENGINE_FAILURE\";\n readonly policyKey: string;\n readonly engine: PolicyKind;\n readonly engineVersion: number;\n readonly message: string;\n readonly cause: string;\n };\n\n// ─── Factory object ─────────────────────────────────────────────────────────\n\nexport class PolicyEvaluationErrors {\n static invalidContext(\n stage: Extract<\n PolicyEvaluationError,\n { kind: \"INVALID_CONTEXT\" }\n >[\"stage\"],\n policyKey: string,\n cause: string,\n ): PolicyEvaluationError {\n return {\n kind: \"INVALID_CONTEXT\",\n stage,\n policyKey,\n message: \"Policy evaluation context is invalid\",\n cause,\n };\n }\n\n static invalidPolicyKey(\n rawPolicyKey: string,\n cause: string,\n ): PolicyEvaluationError {\n return {\n kind: \"INVALID_POLICY_KEY\",\n rawPolicyKey,\n message: \"Policy key is invalid\",\n cause,\n };\n }\n\n static policyNotFound(\n policyKey: string,\n cause: string,\n ): PolicyEvaluationError {\n return {\n kind: \"POLICY_NOT_FOUND\",\n policyKey,\n message: \"Policy is not registered in the catalog\",\n cause,\n };\n }\n\n static policyDefinitionNotFound(\n policyKey: string,\n asOf: Date,\n contextVersion: number,\n cause: string,\n ): PolicyEvaluationError {\n return {\n kind: \"POLICY_DEFINITION_NOT_FOUND\",\n policyKey,\n contextVersion,\n asOf,\n message:\n \"No published policy definition matched the evaluation inputs\",\n cause,\n };\n }\n\n static policyVariantNotFound(params: {\n readonly policyKey: string;\n readonly policyKind: PolicyKind;\n readonly payloadSchemaVersion: number;\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n readonly cause: string;\n }): PolicyEvaluationError {\n return {\n kind: \"POLICY_VARIANT_NOT_FOUND\",\n policyKey: params.policyKey,\n policyKind: params.policyKind,\n payloadSchemaVersion: params.payloadSchemaVersion,\n ...(params.gateEngineVersion !== undefined\n ? { gateEngineVersion: params.gateEngineVersion }\n : {}),\n ...(params.computeEngineVersion !== undefined\n ? { computeEngineVersion: params.computeEngineVersion }\n : {}),\n message:\n \"No catalog variant matched the selected policy definition\",\n cause: params.cause,\n };\n }\n\n static engineFailure(\n policyKey: string,\n engine: PolicyKind,\n engineVersion: number,\n cause: string,\n ): PolicyEvaluationError {\n return {\n kind: \"ENGINE_FAILURE\",\n policyKey,\n engine,\n engineVersion,\n message: \"Policy engine evaluation failed\",\n cause,\n };\n }\n}\n","import { PolicyAsOfResolver, type DeriveAsOfOptions } from \"../asof\";\nimport { type PolicyCatalog, PolicyCatalogEntry, PolicyKey } from \"../catalog\";\nimport type { ContextSeed, PolicyContextBuilder } from \"../context\";\nimport { ContextSeedValidator } from \"../context\";\nimport {\n PolicyDefinition,\n type PolicyDefinitionRepository,\n type PolicyScope,\n} from \"../defs\";\nimport type { PolicyDecisionId, PolicyDefinitionId } from \"../policy-ids\";\nimport {\n type ComputeOutcome,\n ComputeRegistry,\n GateEngineRegistry,\n type GateOutcome,\n type PolicyContext,\n} from \"../engines\";\nimport { PolicyResolver } from \"../resolver\";\nimport { Result } from \"../../result/result\";\nimport { isValidDate } from \"../../shared/temporal-guards\";\n\nimport type { PolicyEvent, PolicyReporter } from \"../../config/policy-reporter\";\nimport { SilentPolicyReporter } from \"../../config/silent-policy-reporter\";\n\nimport {\n PolicyEvaluationErrors,\n type PolicyEvaluationError,\n} from \"./policy-evaluation-error\";\n\n// ─── Input ──────────────────────────────────────────────────────────────────\n\nexport interface EvaluateInput {\n readonly decisionId: PolicyDecisionId;\n readonly policyKey: string;\n readonly scopeChain: readonly PolicyScope[];\n readonly contextVersion: number;\n readonly seed: ContextSeed;\n}\n\nexport interface PolicyServiceOptions {\n readonly asOf?: DeriveAsOfOptions;\n readonly reporter?: PolicyReporter;\n}\n\nexport interface PolicyServiceParams {\n readonly catalog: PolicyCatalog;\n readonly contextBuilder: PolicyContextBuilder;\n readonly defRepo: PolicyDefinitionRepository;\n readonly resolver: PolicyResolver;\n readonly gateEngines: GateEngineRegistry;\n readonly computeRegistry: ComputeRegistry;\n readonly options?: PolicyServiceOptions;\n}\n\n// ─── Output ─────────────────────────────────────────────────────────────────\n\n/** Union of all possible policy decision Outcomes. */\nexport type PolicyDecision = GateOutcome | ComputeOutcome;\n\nexport type { PolicyEvaluationError } from \"./policy-evaluation-error\";\n\nexport interface PolicyEvaluationResult {\n readonly decisionId: PolicyDecisionId;\n readonly ref: {\n readonly definitionId: PolicyDefinitionId;\n readonly policyKey: string;\n readonly policyVersion: string;\n readonly payloadHash: string;\n readonly gateEngineVersion?: number;\n readonly computeEngineVersion?: number;\n };\n readonly kind: \"GATE\" | \"COMPUTE\";\n readonly asOf: Date;\n readonly evaluatedAt: Date;\n readonly contextVersion: number;\n /** Business decision expressed as an Outcome — not a technical Result. */\n readonly decision: PolicyDecision;\n}\n\ninterface ResolvedPolicyCandidate {\n readonly definition: PolicyDefinition;\n readonly catalogEntry: PolicyCatalogEntry;\n}\n\n// ─── Service ────────────────────────────────────────────────────────────────\n\nexport class PolicyService {\n readonly #reporter: PolicyReporter;\n private readonly catalog: PolicyCatalog;\n private readonly contextBuilder: PolicyContextBuilder;\n private readonly defRepo: PolicyDefinitionRepository;\n private readonly resolver: PolicyResolver;\n private readonly gateEngines: GateEngineRegistry;\n private readonly computeRegistry: ComputeRegistry;\n private readonly options: PolicyServiceOptions;\n\n constructor(params: PolicyServiceParams) {\n this.catalog = params.catalog;\n this.contextBuilder = params.contextBuilder;\n this.defRepo = params.defRepo;\n this.resolver = params.resolver;\n this.gateEngines = params.gateEngines;\n this.computeRegistry = params.computeRegistry;\n this.options = params.options ?? {};\n this.#reporter = this.options.reporter ?? new SilentPolicyReporter();\n }\n\n #reportSafely(event: PolicyEvent): void {\n try {\n this.#reporter.report(event);\n } catch {\n // Falhas de telemetria nao podem interromper a avaliacao de politicas.\n }\n }\n\n private resolveEvaluationNow(seed: ContextSeed): Result<Date, string> {\n const candidate = seed.fields[\"now\"];\n\n if (candidate === undefined) {\n return Result.ok(new Date());\n }\n\n if (!isValidDate(candidate)) {\n return Result.err(\n \"seed.fields.now must be a valid Date when provided\",\n );\n }\n\n return Result.ok(candidate);\n }\n\n async evaluate(\n input: EvaluateInput,\n ): Promise<Result<PolicyEvaluationResult, PolicyEvaluationError>> {\n const result = await this.#evaluate(input);\n if (result.isErr()) {\n const error = result.errorOrNull()!;\n this.#reportSafely({\n kind: \"policy-evaluation-failed\",\n level: \"error\",\n policyKey: \"policyKey\" in error ? error.policyKey : undefined,\n errorKind: error.kind,\n message: error.message,\n cause: error.cause,\n occurredAt: new Date(),\n });\n } else {\n const ok = result.getOrNull()!;\n this.#reportSafely({\n kind: \"policy-evaluation-completed\",\n level: \"info\",\n policyKey: ok.ref.policyKey,\n decisionId: ok.decisionId,\n engineKind: ok.kind,\n occurredAt: ok.evaluatedAt,\n });\n }\n return result;\n }\n\n async #evaluate(\n input: EvaluateInput,\n ): Promise<Result<PolicyEvaluationResult, PolicyEvaluationError>> {\n const seedResult = ContextSeedValidator.validate(input.seed);\n if (seedResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.invalidContext(\n \"SEED_VALIDATION\",\n input.policyKey,\n seedResult.errorOrNull()!,\n ),\n );\n }\n const seed = seedResult.getOrNull()!;\n\n const catalogFamilyResult = this.#resolveCatalogFamily(input.policyKey);\n if (catalogFamilyResult.isErr()) {\n return Result.err(catalogFamilyResult.errorOrNull()!);\n }\n const { key: policyKey, family } = catalogFamilyResult.getOrNull()!;\n const familyEntry = family[0]!;\n\n const nowResult = this.resolveEvaluationNow(seed);\n if (nowResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.invalidContext(\n \"AS_OF_DERIVATION\",\n policyKey,\n nowResult.errorOrNull()!,\n ),\n );\n }\n const now = nowResult.getOrNull()!;\n\n const asOfResult = PolicyAsOfResolver.derive(\n familyEntry.asOfSource,\n seed,\n now,\n this.options.asOf,\n );\n if (asOfResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.invalidContext(\n \"AS_OF_DERIVATION\",\n policyKey,\n asOfResult.errorOrNull()!,\n ),\n );\n }\n const asOf = asOfResult.getOrNull()!;\n\n const definitionResult = this.#findCandidates(\n policyKey,\n familyEntry.kind,\n asOf,\n input,\n );\n if (definitionResult.isErr()) {\n return Result.err(definitionResult.errorOrNull()!);\n }\n const {\n definition: policyDefinition,\n catalogEntry: versionedCatalogEntry,\n } = definitionResult.getOrNull()!;\n\n this.#reportSafely({\n kind: \"policy-resolution\",\n level: \"info\",\n policyKey,\n definitionId: policyDefinition.id,\n policyVersion: policyDefinition.policyVersion,\n engineKind: policyDefinition.isGate() ? \"GATE\" : \"COMPUTE\",\n engineVersion: policyDefinition.isGate()\n ? policyDefinition.gateEngineVersion!\n : policyDefinition.computeEngineVersion!,\n occurredAt: now,\n });\n\n const ctxResult = await this.contextBuilder.build(\n versionedCatalogEntry.contextRequirements,\n seed,\n );\n if (ctxResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.invalidContext(\n \"CONTEXT_BUILD\",\n policyKey,\n ctxResult.errorOrNull()!,\n ),\n );\n }\n const context = ctxResult.getOrNull()!;\n\n const decisionResult = this.#executeEngine(\n policyKey,\n policyDefinition,\n context,\n );\n if (decisionResult.isErr()) {\n return Result.err(decisionResult.errorOrNull()!);\n }\n const decision = decisionResult.getOrNull()!;\n\n const result: PolicyEvaluationResult = {\n decisionId: input.decisionId,\n ref: {\n definitionId: policyDefinition.id,\n policyKey: policyDefinition.policyKey,\n policyVersion: policyDefinition.policyVersion,\n payloadHash: policyDefinition.payloadHash,\n ...(policyDefinition.isGate()\n ? {\n gateEngineVersion: policyDefinition.gateEngineVersion,\n }\n : {\n computeEngineVersion:\n policyDefinition.computeEngineVersion,\n }),\n },\n kind: policyDefinition.kind,\n asOf,\n evaluatedAt: now,\n contextVersion: input.contextVersion,\n decision,\n };\n\n return Result.ok(result);\n }\n\n #resolveCatalogVariant(\n definition: PolicyDefinition,\n ): Result<PolicyCatalogEntry, string> {\n return this.catalog.getVersioned({\n key: definition.policyKey,\n kind: definition.kind,\n ...(definition.isGate()\n ? { gateEngineVersion: definition.gateEngineVersion }\n : {\n computeEngineVersion: definition.computeEngineVersion,\n }),\n payloadSchemaVersion: definition.payloadSchemaVersion,\n });\n }\n\n #resolveCatalogFamily(\n rawKey: string,\n ): Result<\n { key: string; family: readonly PolicyCatalogEntry[] },\n PolicyEvaluationError\n > {\n const keyResult = PolicyKey.parse(rawKey);\n if (keyResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.invalidPolicyKey(\n rawKey,\n keyResult.errorOrNull()!,\n ),\n );\n }\n const policyKey = keyResult.getOrNull()!.toString();\n\n const catalogFamilyResult = this.catalog.getFamily(policyKey);\n if (catalogFamilyResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.policyNotFound(\n policyKey,\n catalogFamilyResult.errorOrNull()!,\n ),\n );\n }\n\n return Result.ok({\n key: policyKey,\n family: catalogFamilyResult.getOrNull()!,\n });\n }\n\n #findCandidates(\n policyKey: string,\n policyKind: PolicyCatalogEntry[\"kind\"],\n asOf: Date,\n input: EvaluateInput,\n ): Result<ResolvedPolicyCandidate, PolicyEvaluationError> {\n const candidates = this.defRepo.findCandidates({\n policyKey: policyKey,\n kind: policyKind,\n asOf,\n contextVersion: input.contextVersion,\n scopeChain: input.scopeChain,\n });\n\n const compatibleCandidates: ResolvedPolicyCandidate[] = [];\n const compatibleCandidatesByDefinitionId = new Map<\n string,\n ResolvedPolicyCandidate\n >();\n const incompatibleVariantErrorsByDefinitionId = new Map<\n string,\n string\n >();\n\n for (const candidate of candidates) {\n const compatibilityResult = this.#resolveCatalogVariant(candidate);\n if (compatibilityResult.isErr()) {\n incompatibleVariantErrorsByDefinitionId.set(\n candidate.id,\n compatibilityResult.errorOrNull()!,\n );\n continue;\n }\n\n const resolvedCandidate: ResolvedPolicyCandidate = {\n definition: candidate,\n catalogEntry: compatibilityResult.getOrNull()!,\n };\n compatibleCandidates.push(resolvedCandidate);\n compatibleCandidatesByDefinitionId.set(\n candidate.id,\n resolvedCandidate,\n );\n }\n\n if (compatibleCandidates.length === 0 && candidates.length > 0) {\n const selectedCandidateResult =\n this.resolver.resolveBest(candidates);\n if (selectedCandidateResult.isOk()) {\n const selectedCandidate = selectedCandidateResult.getOrNull()!;\n\n return Result.err(\n PolicyEvaluationErrors.policyVariantNotFound({\n policyKey: policyKey,\n policyKind: selectedCandidate.kind,\n payloadSchemaVersion:\n selectedCandidate.payloadSchemaVersion,\n ...(selectedCandidate.isGate()\n ? {\n gateEngineVersion:\n selectedCandidate.gateEngineVersion,\n }\n : {\n computeEngineVersion:\n selectedCandidate.computeEngineVersion,\n }),\n cause:\n incompatibleVariantErrorsByDefinitionId.get(\n selectedCandidate.id,\n ) ??\n \"No compatible catalog variant matched the selected policy definition\",\n }),\n );\n }\n }\n\n const bestResult = this.resolver.resolveBest(\n compatibleCandidates.map((candidate) => candidate.definition),\n );\n if (bestResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.policyDefinitionNotFound(\n policyKey,\n asOf,\n input.contextVersion,\n bestResult.errorOrNull()!,\n ),\n );\n }\n\n const bestDefinition = bestResult.getOrNull()!;\n const resolvedCandidate = compatibleCandidatesByDefinitionId.get(\n bestDefinition.id,\n );\n if (resolvedCandidate === undefined) {\n return Result.err(\n PolicyEvaluationErrors.policyDefinitionNotFound(\n policyKey,\n asOf,\n input.contextVersion,\n `Resolved definition \"${bestDefinition.id}\" is not present among compatible catalog variants`,\n ),\n );\n }\n\n return Result.ok(resolvedCandidate);\n }\n\n #executeEngine(\n policyKey: string,\n definition: PolicyDefinition,\n context: PolicyContext,\n ): Result<PolicyDecision, PolicyEvaluationError> {\n if (definition.isGate()) {\n const gateResult = this.gateEngines.evaluate(\n definition.gateEngineVersion,\n definition.payloadJson,\n context,\n );\n if (gateResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.engineFailure(\n policyKey,\n \"GATE\",\n definition.gateEngineVersion,\n gateResult.errorOrNull()!,\n ),\n );\n }\n\n return Result.ok(gateResult.getOrNull()!);\n }\n\n if (!definition.isCompute()) {\n return Result.err(\n PolicyEvaluationErrors.policyVariantNotFound({\n policyKey,\n policyKind: definition.kind,\n payloadSchemaVersion: definition.payloadSchemaVersion,\n cause: `Unsupported policy kind \"${definition.kind}\"`,\n }),\n );\n }\n\n const computeResult = this.computeRegistry.evaluate(\n policyKey,\n definition.computeEngineVersion,\n definition.payloadSchemaVersion,\n definition.payloadJson,\n context,\n );\n\n if (computeResult.isErr()) {\n return Result.err(\n PolicyEvaluationErrors.engineFailure(\n policyKey,\n \"COMPUTE\",\n definition.computeEngineVersion,\n computeResult.errorOrNull()!,\n ),\n );\n }\n\n return Result.ok(computeResult.getOrNull()!);\n }\n}\n"],"mappings":"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"}
|