@cullet/erp-core 1.0.2 → 1.0.4
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 +5 -0
- 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.d.ts +1 -0
- 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 -67
- 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 +557 -504
- 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
|
@@ -3,17 +3,17 @@ import { type PolicyCatalog, PolicyCatalogEntry, PolicyKey } from "../catalog";
|
|
|
3
3
|
import type { ContextSeed, PolicyContextBuilder } from "../context";
|
|
4
4
|
import { ContextSeedValidator } from "../context";
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
PolicyDefinition,
|
|
7
|
+
type PolicyDefinitionRepository,
|
|
8
|
+
type PolicyScope,
|
|
9
9
|
} from "../defs";
|
|
10
10
|
import type { PolicyDecisionId, PolicyDefinitionId } from "../policy-ids";
|
|
11
11
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
type ComputeOutcome,
|
|
13
|
+
ComputeRegistry,
|
|
14
|
+
GateEngineRegistry,
|
|
15
|
+
type GateOutcome,
|
|
16
|
+
type PolicyContext,
|
|
17
17
|
} from "../engines";
|
|
18
18
|
import { PolicyResolver } from "../resolver";
|
|
19
19
|
import { Result } from "../../result/result";
|
|
@@ -23,33 +23,33 @@ import type { PolicyEvent, PolicyReporter } from "../../config/policy-reporter";
|
|
|
23
23
|
import { SilentPolicyReporter } from "../../config/silent-policy-reporter";
|
|
24
24
|
|
|
25
25
|
import {
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
PolicyEvaluationErrors,
|
|
27
|
+
type PolicyEvaluationError,
|
|
28
28
|
} from "./policy-evaluation-error";
|
|
29
29
|
|
|
30
30
|
// ─── Input ──────────────────────────────────────────────────────────────────
|
|
31
31
|
|
|
32
32
|
export interface EvaluateInput {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
readonly decisionId: PolicyDecisionId;
|
|
34
|
+
readonly policyKey: string;
|
|
35
|
+
readonly scopeChain: readonly PolicyScope[];
|
|
36
|
+
readonly contextVersion: number;
|
|
37
|
+
readonly seed: ContextSeed;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export interface PolicyServiceOptions {
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
readonly asOf?: DeriveAsOfOptions;
|
|
42
|
+
readonly reporter?: PolicyReporter;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export interface PolicyServiceParams {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
readonly catalog: PolicyCatalog;
|
|
47
|
+
readonly contextBuilder: PolicyContextBuilder;
|
|
48
|
+
readonly defRepo: PolicyDefinitionRepository;
|
|
49
|
+
readonly resolver: PolicyResolver;
|
|
50
|
+
readonly gateEngines: GateEngineRegistry;
|
|
51
|
+
readonly computeRegistry: ComputeRegistry;
|
|
52
|
+
readonly options?: PolicyServiceOptions;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
// ─── Output ─────────────────────────────────────────────────────────────────
|
|
@@ -60,431 +60,444 @@ export type PolicyDecision = GateOutcome | ComputeOutcome;
|
|
|
60
60
|
export type { PolicyEvaluationError } from "./policy-evaluation-error";
|
|
61
61
|
|
|
62
62
|
export interface PolicyEvaluationResult {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
63
|
+
readonly decisionId: PolicyDecisionId;
|
|
64
|
+
readonly ref: {
|
|
65
|
+
readonly definitionId: PolicyDefinitionId;
|
|
66
|
+
readonly policyKey: string;
|
|
67
|
+
readonly policyVersion: string;
|
|
68
|
+
readonly payloadHash: string;
|
|
69
|
+
readonly gateEngineVersion?: number;
|
|
70
|
+
readonly computeEngineVersion?: number;
|
|
71
|
+
};
|
|
72
|
+
readonly kind: "GATE" | "COMPUTE";
|
|
73
|
+
readonly asOf: Date;
|
|
74
|
+
readonly evaluatedAt: Date;
|
|
75
|
+
readonly contextVersion: number;
|
|
76
|
+
/** Business decision expressed as an Outcome — not a technical Result. */
|
|
77
|
+
readonly decision: PolicyDecision;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
interface ResolvedPolicyCandidate {
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
readonly definition: PolicyDefinition;
|
|
82
|
+
readonly catalogEntry: PolicyCatalogEntry;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// ─── Service ────────────────────────────────────────────────────────────────
|
|
86
86
|
|
|
87
87
|
export class PolicyService {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
#reportSafely(event: PolicyEvent): void {
|
|
109
|
-
try {
|
|
110
|
-
this.#reporter.report(event);
|
|
111
|
-
} catch {
|
|
112
|
-
// Falhas de telemetria nao podem interromper a avaliacao de politicas.
|
|
88
|
+
readonly #reporter: PolicyReporter;
|
|
89
|
+
private readonly catalog: PolicyCatalog;
|
|
90
|
+
private readonly contextBuilder: PolicyContextBuilder;
|
|
91
|
+
private readonly defRepo: PolicyDefinitionRepository;
|
|
92
|
+
private readonly resolver: PolicyResolver;
|
|
93
|
+
private readonly gateEngines: GateEngineRegistry;
|
|
94
|
+
private readonly computeRegistry: ComputeRegistry;
|
|
95
|
+
private readonly options: PolicyServiceOptions;
|
|
96
|
+
|
|
97
|
+
constructor(params: PolicyServiceParams) {
|
|
98
|
+
this.catalog = params.catalog;
|
|
99
|
+
this.contextBuilder = params.contextBuilder;
|
|
100
|
+
this.defRepo = params.defRepo;
|
|
101
|
+
this.resolver = params.resolver;
|
|
102
|
+
this.gateEngines = params.gateEngines;
|
|
103
|
+
this.computeRegistry = params.computeRegistry;
|
|
104
|
+
this.options = params.options ?? {};
|
|
105
|
+
this.#reporter = this.options.reporter ?? new SilentPolicyReporter();
|
|
113
106
|
}
|
|
114
|
-
}
|
|
115
107
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
108
|
+
#reportSafely(event: PolicyEvent): void {
|
|
109
|
+
try {
|
|
110
|
+
this.#reporter.report(event);
|
|
111
|
+
} catch {
|
|
112
|
+
// Falhas de telemetria nao podem interromper a avaliacao de politicas.
|
|
113
|
+
}
|
|
121
114
|
}
|
|
122
115
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
116
|
+
private resolveEvaluationNow(seed: ContextSeed): Result<Date, string> {
|
|
117
|
+
const candidate = seed.fields["now"];
|
|
126
118
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
async evaluate(
|
|
131
|
-
input: EvaluateInput,
|
|
132
|
-
): Promise<Result<PolicyEvaluationResult, PolicyEvaluationError>> {
|
|
133
|
-
const result = await this.#evaluate(input);
|
|
134
|
-
if (result.isErr()) {
|
|
135
|
-
const error = result.errorOrNull()!;
|
|
136
|
-
this.#reportSafely({
|
|
137
|
-
kind: "policy-evaluation-failed",
|
|
138
|
-
level: "error",
|
|
139
|
-
policyKey: "policyKey" in error ? error.policyKey : undefined,
|
|
140
|
-
errorKind: error.kind,
|
|
141
|
-
message: error.message,
|
|
142
|
-
cause: error.cause,
|
|
143
|
-
occurredAt: new Date(),
|
|
144
|
-
});
|
|
145
|
-
} else {
|
|
146
|
-
const ok = result.getOrNull()!;
|
|
147
|
-
this.#reportSafely({
|
|
148
|
-
kind: "policy-evaluation-completed",
|
|
149
|
-
level: "info",
|
|
150
|
-
policyKey: ok.ref.policyKey,
|
|
151
|
-
decisionId: ok.decisionId,
|
|
152
|
-
engineKind: ok.kind,
|
|
153
|
-
occurredAt: ok.evaluatedAt,
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
return result;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
async #evaluate(
|
|
160
|
-
input: EvaluateInput,
|
|
161
|
-
): Promise<Result<PolicyEvaluationResult, PolicyEvaluationError>> {
|
|
162
|
-
const seedResult = ContextSeedValidator.validate(input.seed);
|
|
163
|
-
if (seedResult.isErr()) {
|
|
164
|
-
return Result.err(
|
|
165
|
-
PolicyEvaluationErrors.invalidContext(
|
|
166
|
-
"SEED_VALIDATION",
|
|
167
|
-
input.policyKey,
|
|
168
|
-
seedResult.errorOrNull()!,
|
|
169
|
-
),
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
const seed = seedResult.getOrNull()!;
|
|
119
|
+
if (candidate === undefined) {
|
|
120
|
+
return Result.ok(new Date());
|
|
121
|
+
}
|
|
173
122
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const familyEntry = family[0]!;
|
|
180
|
-
|
|
181
|
-
const nowResult = this.resolveEvaluationNow(seed);
|
|
182
|
-
if (nowResult.isErr()) {
|
|
183
|
-
return Result.err(
|
|
184
|
-
PolicyEvaluationErrors.invalidContext(
|
|
185
|
-
"AS_OF_DERIVATION",
|
|
186
|
-
policyKey,
|
|
187
|
-
nowResult.errorOrNull()!,
|
|
188
|
-
),
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
const now = nowResult.getOrNull()!;
|
|
192
|
-
|
|
193
|
-
const asOfResult = PolicyAsOfResolver.derive(
|
|
194
|
-
familyEntry.asOfSource,
|
|
195
|
-
seed,
|
|
196
|
-
now,
|
|
197
|
-
this.options.asOf,
|
|
198
|
-
);
|
|
199
|
-
if (asOfResult.isErr()) {
|
|
200
|
-
return Result.err(
|
|
201
|
-
PolicyEvaluationErrors.invalidContext(
|
|
202
|
-
"AS_OF_DERIVATION",
|
|
203
|
-
policyKey,
|
|
204
|
-
asOfResult.errorOrNull()!,
|
|
205
|
-
),
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
const asOf = asOfResult.getOrNull()!;
|
|
209
|
-
|
|
210
|
-
const definitionResult = this.#findCandidates(
|
|
211
|
-
policyKey,
|
|
212
|
-
familyEntry.kind,
|
|
213
|
-
asOf,
|
|
214
|
-
input,
|
|
215
|
-
);
|
|
216
|
-
if (definitionResult.isErr()) {
|
|
217
|
-
return Result.err(definitionResult.errorOrNull()!);
|
|
218
|
-
}
|
|
219
|
-
const {
|
|
220
|
-
definition: policyDefinition,
|
|
221
|
-
catalogEntry: versionedCatalogEntry,
|
|
222
|
-
} = definitionResult.getOrNull()!;
|
|
223
|
-
|
|
224
|
-
this.#reportSafely({
|
|
225
|
-
kind: "policy-resolution",
|
|
226
|
-
level: "info",
|
|
227
|
-
policyKey,
|
|
228
|
-
definitionId: policyDefinition.id,
|
|
229
|
-
policyVersion: policyDefinition.policyVersion,
|
|
230
|
-
engineKind: policyDefinition.isGate() ? "GATE" : "COMPUTE",
|
|
231
|
-
engineVersion: policyDefinition.isGate()
|
|
232
|
-
? policyDefinition.gateEngineVersion!
|
|
233
|
-
: policyDefinition.computeEngineVersion!,
|
|
234
|
-
occurredAt: now,
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
const ctxResult = await this.contextBuilder.build(
|
|
238
|
-
versionedCatalogEntry.contextRequirements,
|
|
239
|
-
seed,
|
|
240
|
-
);
|
|
241
|
-
if (ctxResult.isErr()) {
|
|
242
|
-
return Result.err(
|
|
243
|
-
PolicyEvaluationErrors.invalidContext(
|
|
244
|
-
"CONTEXT_BUILD",
|
|
245
|
-
policyKey,
|
|
246
|
-
ctxResult.errorOrNull()!,
|
|
247
|
-
),
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
const context = ctxResult.getOrNull()!;
|
|
251
|
-
|
|
252
|
-
const decisionResult = this.#executeEngine(
|
|
253
|
-
policyKey,
|
|
254
|
-
policyDefinition,
|
|
255
|
-
context,
|
|
256
|
-
);
|
|
257
|
-
if (decisionResult.isErr()) {
|
|
258
|
-
return Result.err(decisionResult.errorOrNull()!);
|
|
259
|
-
}
|
|
260
|
-
const decision = decisionResult.getOrNull()!;
|
|
261
|
-
|
|
262
|
-
const result: PolicyEvaluationResult = {
|
|
263
|
-
decisionId: input.decisionId,
|
|
264
|
-
ref: {
|
|
265
|
-
definitionId: policyDefinition.id,
|
|
266
|
-
policyKey: policyDefinition.policyKey,
|
|
267
|
-
policyVersion: policyDefinition.policyVersion,
|
|
268
|
-
payloadHash: policyDefinition.payloadHash,
|
|
269
|
-
...(policyDefinition.isGate()
|
|
270
|
-
? {
|
|
271
|
-
gateEngineVersion: policyDefinition.gateEngineVersion,
|
|
272
|
-
}
|
|
273
|
-
: {
|
|
274
|
-
computeEngineVersion: policyDefinition.computeEngineVersion,
|
|
275
|
-
}),
|
|
276
|
-
},
|
|
277
|
-
kind: policyDefinition.kind,
|
|
278
|
-
asOf,
|
|
279
|
-
evaluatedAt: now,
|
|
280
|
-
contextVersion: input.contextVersion,
|
|
281
|
-
decision,
|
|
282
|
-
};
|
|
123
|
+
if (!isValidDate(candidate)) {
|
|
124
|
+
return Result.err(
|
|
125
|
+
"seed.fields.now must be a valid Date when provided",
|
|
126
|
+
);
|
|
127
|
+
}
|
|
283
128
|
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
#resolveCatalogVariant(
|
|
288
|
-
definition: PolicyDefinition,
|
|
289
|
-
): Result<PolicyCatalogEntry, string> {
|
|
290
|
-
return this.catalog.getVersioned({
|
|
291
|
-
key: definition.policyKey,
|
|
292
|
-
kind: definition.kind,
|
|
293
|
-
...(definition.isGate()
|
|
294
|
-
? { gateEngineVersion: definition.gateEngineVersion }
|
|
295
|
-
: {
|
|
296
|
-
computeEngineVersion: definition.computeEngineVersion,
|
|
297
|
-
}),
|
|
298
|
-
payloadSchemaVersion: definition.payloadSchemaVersion,
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
#resolveCatalogFamily(
|
|
303
|
-
rawKey: string,
|
|
304
|
-
): Result<
|
|
305
|
-
{ key: string; family: readonly PolicyCatalogEntry[] },
|
|
306
|
-
PolicyEvaluationError
|
|
307
|
-
> {
|
|
308
|
-
const keyResult = PolicyKey.parse(rawKey);
|
|
309
|
-
if (keyResult.isErr()) {
|
|
310
|
-
return Result.err(
|
|
311
|
-
PolicyEvaluationErrors.invalidPolicyKey(
|
|
312
|
-
rawKey,
|
|
313
|
-
keyResult.errorOrNull()!,
|
|
314
|
-
),
|
|
315
|
-
);
|
|
129
|
+
return Result.ok(candidate);
|
|
316
130
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
131
|
+
|
|
132
|
+
async evaluate(
|
|
133
|
+
input: EvaluateInput,
|
|
134
|
+
): Promise<Result<PolicyEvaluationResult, PolicyEvaluationError>> {
|
|
135
|
+
const result = await this.#evaluate(input);
|
|
136
|
+
if (result.isErr()) {
|
|
137
|
+
const error = result.errorOrNull()!;
|
|
138
|
+
this.#reportSafely({
|
|
139
|
+
kind: "policy-evaluation-failed",
|
|
140
|
+
level: "error",
|
|
141
|
+
policyKey: "policyKey" in error ? error.policyKey : undefined,
|
|
142
|
+
errorKind: error.kind,
|
|
143
|
+
message: error.message,
|
|
144
|
+
cause: error.cause,
|
|
145
|
+
occurredAt: new Date(),
|
|
146
|
+
});
|
|
147
|
+
} else {
|
|
148
|
+
const ok = result.getOrNull()!;
|
|
149
|
+
this.#reportSafely({
|
|
150
|
+
kind: "policy-evaluation-completed",
|
|
151
|
+
level: "info",
|
|
152
|
+
policyKey: ok.ref.policyKey,
|
|
153
|
+
decisionId: ok.decisionId,
|
|
154
|
+
engineKind: ok.kind,
|
|
155
|
+
occurredAt: ok.evaluatedAt,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
return result;
|
|
327
159
|
}
|
|
328
160
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
161
|
+
async #evaluate(
|
|
162
|
+
input: EvaluateInput,
|
|
163
|
+
): Promise<Result<PolicyEvaluationResult, PolicyEvaluationError>> {
|
|
164
|
+
const seedResult = ContextSeedValidator.validate(input.seed);
|
|
165
|
+
if (seedResult.isErr()) {
|
|
166
|
+
return Result.err(
|
|
167
|
+
PolicyEvaluationErrors.invalidContext(
|
|
168
|
+
"SEED_VALIDATION",
|
|
169
|
+
input.policyKey,
|
|
170
|
+
seedResult.errorOrNull()!,
|
|
171
|
+
),
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
const seed = seedResult.getOrNull()!;
|
|
175
|
+
|
|
176
|
+
const catalogFamilyResult = this.#resolveCatalogFamily(input.policyKey);
|
|
177
|
+
if (catalogFamilyResult.isErr()) {
|
|
178
|
+
return Result.err(catalogFamilyResult.errorOrNull()!);
|
|
179
|
+
}
|
|
180
|
+
const { key: policyKey, family } = catalogFamilyResult.getOrNull()!;
|
|
181
|
+
const familyEntry = family[0]!;
|
|
182
|
+
|
|
183
|
+
const nowResult = this.resolveEvaluationNow(seed);
|
|
184
|
+
if (nowResult.isErr()) {
|
|
185
|
+
return Result.err(
|
|
186
|
+
PolicyEvaluationErrors.invalidContext(
|
|
187
|
+
"AS_OF_DERIVATION",
|
|
188
|
+
policyKey,
|
|
189
|
+
nowResult.errorOrNull()!,
|
|
190
|
+
),
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
const now = nowResult.getOrNull()!;
|
|
194
|
+
|
|
195
|
+
const asOfResult = PolicyAsOfResolver.derive(
|
|
196
|
+
familyEntry.asOfSource,
|
|
197
|
+
seed,
|
|
198
|
+
now,
|
|
199
|
+
this.options.asOf,
|
|
362
200
|
);
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
201
|
+
if (asOfResult.isErr()) {
|
|
202
|
+
return Result.err(
|
|
203
|
+
PolicyEvaluationErrors.invalidContext(
|
|
204
|
+
"AS_OF_DERIVATION",
|
|
205
|
+
policyKey,
|
|
206
|
+
asOfResult.errorOrNull()!,
|
|
207
|
+
),
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
const asOf = asOfResult.getOrNull()!;
|
|
211
|
+
|
|
212
|
+
const definitionResult = this.#findCandidates(
|
|
213
|
+
policyKey,
|
|
214
|
+
familyEntry.kind,
|
|
215
|
+
asOf,
|
|
216
|
+
input,
|
|
217
|
+
);
|
|
218
|
+
if (definitionResult.isErr()) {
|
|
219
|
+
return Result.err(definitionResult.errorOrNull()!);
|
|
220
|
+
}
|
|
221
|
+
const {
|
|
222
|
+
definition: policyDefinition,
|
|
223
|
+
catalogEntry: versionedCatalogEntry,
|
|
224
|
+
} = definitionResult.getOrNull()!;
|
|
225
|
+
|
|
226
|
+
this.#reportSafely({
|
|
227
|
+
kind: "policy-resolution",
|
|
228
|
+
level: "info",
|
|
229
|
+
policyKey,
|
|
230
|
+
definitionId: policyDefinition.id,
|
|
231
|
+
policyVersion: policyDefinition.policyVersion,
|
|
232
|
+
engineKind: policyDefinition.isGate() ? "GATE" : "COMPUTE",
|
|
233
|
+
engineVersion: policyDefinition.isGate()
|
|
234
|
+
? policyDefinition.gateEngineVersion!
|
|
235
|
+
: policyDefinition.computeEngineVersion!,
|
|
236
|
+
occurredAt: now,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
const ctxResult = await this.contextBuilder.build(
|
|
240
|
+
versionedCatalogEntry.contextRequirements,
|
|
241
|
+
seed,
|
|
242
|
+
);
|
|
243
|
+
if (ctxResult.isErr()) {
|
|
244
|
+
return Result.err(
|
|
245
|
+
PolicyEvaluationErrors.invalidContext(
|
|
246
|
+
"CONTEXT_BUILD",
|
|
247
|
+
policyKey,
|
|
248
|
+
ctxResult.errorOrNull()!,
|
|
249
|
+
),
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
const context = ctxResult.getOrNull()!;
|
|
253
|
+
|
|
254
|
+
const decisionResult = this.#executeEngine(
|
|
255
|
+
policyKey,
|
|
256
|
+
policyDefinition,
|
|
257
|
+
context,
|
|
258
|
+
);
|
|
259
|
+
if (decisionResult.isErr()) {
|
|
260
|
+
return Result.err(decisionResult.errorOrNull()!);
|
|
261
|
+
}
|
|
262
|
+
const decision = decisionResult.getOrNull()!;
|
|
263
|
+
|
|
264
|
+
const result: PolicyEvaluationResult = {
|
|
265
|
+
decisionId: input.decisionId,
|
|
266
|
+
ref: {
|
|
267
|
+
definitionId: policyDefinition.id,
|
|
268
|
+
policyKey: policyDefinition.policyKey,
|
|
269
|
+
policyVersion: policyDefinition.policyVersion,
|
|
270
|
+
payloadHash: policyDefinition.payloadHash,
|
|
271
|
+
...(policyDefinition.isGate()
|
|
272
|
+
? {
|
|
273
|
+
gateEngineVersion: policyDefinition.gateEngineVersion,
|
|
274
|
+
}
|
|
275
|
+
: {
|
|
276
|
+
computeEngineVersion:
|
|
277
|
+
policyDefinition.computeEngineVersion,
|
|
278
|
+
}),
|
|
279
|
+
},
|
|
280
|
+
kind: policyDefinition.kind,
|
|
281
|
+
asOf,
|
|
282
|
+
evaluatedAt: now,
|
|
283
|
+
contextVersion: input.contextVersion,
|
|
284
|
+
decision,
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
return Result.ok(result);
|
|
372
288
|
}
|
|
373
289
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
290
|
+
#resolveCatalogVariant(
|
|
291
|
+
definition: PolicyDefinition,
|
|
292
|
+
): Result<PolicyCatalogEntry, string> {
|
|
293
|
+
return this.catalog.getVersioned({
|
|
294
|
+
key: definition.policyKey,
|
|
295
|
+
kind: definition.kind,
|
|
296
|
+
...(definition.isGate()
|
|
297
|
+
? { gateEngineVersion: definition.gateEngineVersion }
|
|
298
|
+
: {
|
|
299
|
+
computeEngineVersion: definition.computeEngineVersion,
|
|
300
|
+
}),
|
|
301
|
+
payloadSchemaVersion: definition.payloadSchemaVersion,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
378
304
|
|
|
379
|
-
|
|
380
|
-
|
|
305
|
+
#resolveCatalogFamily(
|
|
306
|
+
rawKey: string,
|
|
307
|
+
): Result<
|
|
308
|
+
{ key: string; family: readonly PolicyCatalogEntry[] },
|
|
309
|
+
PolicyEvaluationError
|
|
310
|
+
> {
|
|
311
|
+
const keyResult = PolicyKey.parse(rawKey);
|
|
312
|
+
if (keyResult.isErr()) {
|
|
313
|
+
return Result.err(
|
|
314
|
+
PolicyEvaluationErrors.invalidPolicyKey(
|
|
315
|
+
rawKey,
|
|
316
|
+
keyResult.errorOrNull()!,
|
|
317
|
+
),
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
const policyKey = keyResult.getOrNull()!.toString();
|
|
321
|
+
|
|
322
|
+
const catalogFamilyResult = this.catalog.getFamily(policyKey);
|
|
323
|
+
if (catalogFamilyResult.isErr()) {
|
|
324
|
+
return Result.err(
|
|
325
|
+
PolicyEvaluationErrors.policyNotFound(
|
|
326
|
+
policyKey,
|
|
327
|
+
catalogFamilyResult.errorOrNull()!,
|
|
328
|
+
),
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return Result.ok({
|
|
333
|
+
key: policyKey,
|
|
334
|
+
family: catalogFamilyResult.getOrNull()!,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
#findCandidates(
|
|
339
|
+
policyKey: string,
|
|
340
|
+
policyKind: PolicyCatalogEntry["kind"],
|
|
341
|
+
asOf: Date,
|
|
342
|
+
input: EvaluateInput,
|
|
343
|
+
): Result<ResolvedPolicyCandidate, PolicyEvaluationError> {
|
|
344
|
+
const candidates = this.defRepo.findCandidates({
|
|
381
345
|
policyKey: policyKey,
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
346
|
+
kind: policyKind,
|
|
347
|
+
asOf,
|
|
348
|
+
contextVersion: input.contextVersion,
|
|
349
|
+
scopeChain: input.scopeChain,
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
const compatibleCandidates: ResolvedPolicyCandidate[] = [];
|
|
353
|
+
const compatibleCandidatesByDefinitionId = new Map<
|
|
354
|
+
string,
|
|
355
|
+
ResolvedPolicyCandidate
|
|
356
|
+
>();
|
|
357
|
+
const incompatibleVariantErrorsByDefinitionId = new Map<
|
|
358
|
+
string,
|
|
359
|
+
string
|
|
360
|
+
>();
|
|
361
|
+
|
|
362
|
+
for (const candidate of candidates) {
|
|
363
|
+
const compatibilityResult = this.#resolveCatalogVariant(candidate);
|
|
364
|
+
if (compatibilityResult.isErr()) {
|
|
365
|
+
incompatibleVariantErrorsByDefinitionId.set(
|
|
366
|
+
candidate.id,
|
|
367
|
+
compatibilityResult.errorOrNull()!,
|
|
368
|
+
);
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const resolvedCandidate: ResolvedPolicyCandidate = {
|
|
373
|
+
definition: candidate,
|
|
374
|
+
catalogEntry: compatibilityResult.getOrNull()!,
|
|
375
|
+
};
|
|
376
|
+
compatibleCandidates.push(resolvedCandidate);
|
|
377
|
+
compatibleCandidatesByDefinitionId.set(
|
|
378
|
+
candidate.id,
|
|
379
|
+
resolvedCandidate,
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (compatibleCandidates.length === 0 && candidates.length > 0) {
|
|
384
|
+
const selectedCandidateResult =
|
|
385
|
+
this.resolver.resolveBest(candidates);
|
|
386
|
+
if (selectedCandidateResult.isOk()) {
|
|
387
|
+
const selectedCandidate = selectedCandidateResult.getOrNull()!;
|
|
388
|
+
|
|
389
|
+
return Result.err(
|
|
390
|
+
PolicyEvaluationErrors.policyVariantNotFound({
|
|
391
|
+
policyKey: policyKey,
|
|
392
|
+
policyKind: selectedCandidate.kind,
|
|
393
|
+
payloadSchemaVersion:
|
|
394
|
+
selectedCandidate.payloadSchemaVersion,
|
|
395
|
+
...(selectedCandidate.isGate()
|
|
396
|
+
? {
|
|
397
|
+
gateEngineVersion:
|
|
398
|
+
selectedCandidate.gateEngineVersion,
|
|
399
|
+
}
|
|
400
|
+
: {
|
|
401
|
+
computeEngineVersion:
|
|
402
|
+
selectedCandidate.computeEngineVersion,
|
|
403
|
+
}),
|
|
404
|
+
cause:
|
|
405
|
+
incompatibleVariantErrorsByDefinitionId.get(
|
|
406
|
+
selectedCandidate.id,
|
|
407
|
+
) ??
|
|
408
|
+
"No compatible catalog variant matched the selected policy definition",
|
|
409
|
+
}),
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const bestResult = this.resolver.resolveBest(
|
|
415
|
+
compatibleCandidates.map((candidate) => candidate.definition),
|
|
416
|
+
);
|
|
417
|
+
if (bestResult.isErr()) {
|
|
418
|
+
return Result.err(
|
|
419
|
+
PolicyEvaluationErrors.policyDefinitionNotFound(
|
|
420
|
+
policyKey,
|
|
421
|
+
asOf,
|
|
422
|
+
input.contextVersion,
|
|
423
|
+
bestResult.errorOrNull()!,
|
|
424
|
+
),
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const bestDefinition = bestResult.getOrNull()!;
|
|
429
|
+
const resolvedCandidate = compatibleCandidatesByDefinitionId.get(
|
|
430
|
+
bestDefinition.id,
|
|
397
431
|
);
|
|
398
|
-
|
|
432
|
+
if (resolvedCandidate === undefined) {
|
|
433
|
+
return Result.err(
|
|
434
|
+
PolicyEvaluationErrors.policyDefinitionNotFound(
|
|
435
|
+
policyKey,
|
|
436
|
+
asOf,
|
|
437
|
+
input.contextVersion,
|
|
438
|
+
`Resolved definition "${bestDefinition.id}" is not present among compatible catalog variants`,
|
|
439
|
+
),
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return Result.ok(resolvedCandidate);
|
|
399
444
|
}
|
|
400
445
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
446
|
+
#executeEngine(
|
|
447
|
+
policyKey: string,
|
|
448
|
+
definition: PolicyDefinition,
|
|
449
|
+
context: PolicyContext,
|
|
450
|
+
): Result<PolicyDecision, PolicyEvaluationError> {
|
|
451
|
+
if (definition.isGate()) {
|
|
452
|
+
const gateResult = this.gateEngines.evaluate(
|
|
453
|
+
definition.gateEngineVersion,
|
|
454
|
+
definition.payloadJson,
|
|
455
|
+
context,
|
|
456
|
+
);
|
|
457
|
+
if (gateResult.isErr()) {
|
|
458
|
+
return Result.err(
|
|
459
|
+
PolicyEvaluationErrors.engineFailure(
|
|
460
|
+
policyKey,
|
|
461
|
+
"GATE",
|
|
462
|
+
definition.gateEngineVersion,
|
|
463
|
+
gateResult.errorOrNull()!,
|
|
464
|
+
),
|
|
465
|
+
);
|
|
466
|
+
}
|
|
414
467
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
}
|
|
468
|
+
return Result.ok(gateResult.getOrNull()!);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (!definition.isCompute()) {
|
|
472
|
+
return Result.err(
|
|
473
|
+
PolicyEvaluationErrors.policyVariantNotFound({
|
|
474
|
+
policyKey,
|
|
475
|
+
policyKind: definition.kind,
|
|
476
|
+
payloadSchemaVersion: definition.payloadSchemaVersion,
|
|
477
|
+
cause: `Unsupported policy kind "${definition.kind}"`,
|
|
478
|
+
}),
|
|
479
|
+
);
|
|
480
|
+
}
|
|
429
481
|
|
|
430
|
-
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
#executeEngine(
|
|
434
|
-
policyKey: string,
|
|
435
|
-
definition: PolicyDefinition,
|
|
436
|
-
context: PolicyContext,
|
|
437
|
-
): Result<PolicyDecision, PolicyEvaluationError> {
|
|
438
|
-
if (definition.isGate()) {
|
|
439
|
-
const gateResult = this.gateEngines.evaluate(
|
|
440
|
-
definition.gateEngineVersion,
|
|
441
|
-
definition.payloadJson,
|
|
442
|
-
context,
|
|
443
|
-
);
|
|
444
|
-
if (gateResult.isErr()) {
|
|
445
|
-
return Result.err(
|
|
446
|
-
PolicyEvaluationErrors.engineFailure(
|
|
482
|
+
const computeResult = this.computeRegistry.evaluate(
|
|
447
483
|
policyKey,
|
|
448
|
-
|
|
449
|
-
definition.
|
|
450
|
-
|
|
451
|
-
|
|
484
|
+
definition.computeEngineVersion,
|
|
485
|
+
definition.payloadSchemaVersion,
|
|
486
|
+
definition.payloadJson,
|
|
487
|
+
context,
|
|
452
488
|
);
|
|
453
|
-
}
|
|
454
489
|
|
|
455
|
-
|
|
490
|
+
if (computeResult.isErr()) {
|
|
491
|
+
return Result.err(
|
|
492
|
+
PolicyEvaluationErrors.engineFailure(
|
|
493
|
+
policyKey,
|
|
494
|
+
"COMPUTE",
|
|
495
|
+
definition.computeEngineVersion,
|
|
496
|
+
computeResult.errorOrNull()!,
|
|
497
|
+
),
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return Result.ok(computeResult.getOrNull()!);
|
|
456
502
|
}
|
|
457
|
-
|
|
458
|
-
if (!definition.isCompute()) {
|
|
459
|
-
return Result.err(
|
|
460
|
-
PolicyEvaluationErrors.policyVariantNotFound({
|
|
461
|
-
policyKey,
|
|
462
|
-
policyKind: definition.kind,
|
|
463
|
-
payloadSchemaVersion: definition.payloadSchemaVersion,
|
|
464
|
-
cause: `Unsupported policy kind "${definition.kind}"`,
|
|
465
|
-
}),
|
|
466
|
-
);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
const computeResult = this.computeRegistry.evaluate(
|
|
470
|
-
policyKey,
|
|
471
|
-
definition.computeEngineVersion,
|
|
472
|
-
definition.payloadSchemaVersion,
|
|
473
|
-
definition.payloadJson,
|
|
474
|
-
context,
|
|
475
|
-
);
|
|
476
|
-
|
|
477
|
-
if (computeResult.isErr()) {
|
|
478
|
-
return Result.err(
|
|
479
|
-
PolicyEvaluationErrors.engineFailure(
|
|
480
|
-
policyKey,
|
|
481
|
-
"COMPUTE",
|
|
482
|
-
definition.computeEngineVersion,
|
|
483
|
-
computeResult.errorOrNull()!,
|
|
484
|
-
),
|
|
485
|
-
);
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
return Result.ok(computeResult.getOrNull()!);
|
|
489
|
-
}
|
|
490
503
|
}
|