@aventara/core 1.0.0-rc.1 → 1.0.0-rc.11
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/CHANGELOG.md +1022 -16
- package/ERRORS.md +142 -0
- package/README.md +330 -16
- package/dist/adapters/adapter-discovery-diagnostic.guidance.d.ts +6 -0
- package/dist/adapters/adapter-discovery-diagnostic.guidance.js +7 -0
- package/dist/adapters/adapter-field.d.ts +22 -0
- package/dist/adapters/adapter-identifier.d.ts +9 -0
- package/dist/adapters/adapter-identifier.js +6 -1
- package/dist/adapters/adapter-model.d.ts +9 -0
- package/dist/adapters/adapter-operation.d.ts +18 -3
- package/dist/adapters/adapter-resource.d.ts +5 -0
- package/dist/adapters/adapter.interface.d.ts +10 -0
- package/dist/avz/avz.d.ts +1 -1
- package/dist/avz/json-shape.registry.d.ts +2 -1
- package/dist/compiler/contract-compiler-diagnostic.guidance.d.ts +6 -0
- package/dist/compiler/contract-compiler-diagnostic.guidance.js +97 -0
- package/dist/compiler/contract.compiler.d.ts +6 -0
- package/dist/compiler/contract.compiler.js +281 -31
- package/dist/compiler/create-requirements.projector.js +1 -3
- package/dist/compiler/field-validator.compiler.js +1 -3
- package/dist/compiler/managed-elsewhere.projector.d.ts +52 -0
- package/dist/compiler/managed-elsewhere.projector.js +179 -0
- package/dist/compiler/managed-elsewhere.validator.d.ts +9 -0
- package/dist/compiler/managed-elsewhere.validator.js +74 -0
- package/dist/config/cache-stage.factory.d.ts +24 -0
- package/dist/config/cache-stage.factory.js +3 -0
- package/dist/config/computed-fields.d.ts +62 -0
- package/dist/config/computed-fields.js +73 -0
- package/dist/config/config-diagnostic.guidance.d.ts +6 -0
- package/dist/config/config-diagnostic.guidance.js +32 -0
- package/dist/config/config.resolver.d.ts +24 -0
- package/dist/config/config.resolver.js +66 -7
- package/dist/config/config.validator.js +283 -21
- package/dist/config/define-resource.d.ts +1 -5
- package/dist/config/entrypoint.normalizer.d.ts +3 -2
- package/dist/config/exact-framework-config.d.ts +73 -22
- package/dist/config/field-compute.resolver.d.ts +2 -0
- package/dist/config/field-compute.resolver.js +9 -3
- package/dist/config/framework-config.d.ts +53 -15
- package/dist/config/framework-resources-config.d.ts +25 -14
- package/dist/config/pipeline-config.d.ts +20 -4
- package/dist/config/pipeline-tree.resolver.d.ts +2 -2
- package/dist/config/pipeline-tree.resolver.js +2 -3
- package/dist/contracts/access-route.rules.d.ts +10 -0
- package/dist/contracts/access-route.rules.js +45 -0
- package/dist/contracts/canonical-json.writer.d.ts +7 -0
- package/dist/contracts/canonical-json.writer.js +55 -0
- package/dist/contracts/capability.d.ts +26 -1
- package/dist/contracts/capability.js +20 -0
- package/dist/contracts/client-contract-structure.validator.d.ts +365 -89
- package/dist/contracts/client-contract-structure.validator.js +49 -2
- package/dist/contracts/contract-access.d.ts +29 -0
- package/dist/contracts/contract-access.js +1 -0
- package/dist/contracts/contract-canonicalizer.d.ts +9 -1
- package/dist/contracts/contract-canonicalizer.js +35 -4
- package/dist/contracts/contract-hash.d.ts +0 -1
- package/dist/contracts/contract-hash.js +1 -1
- package/dist/contracts/contract-limits.d.ts +6 -0
- package/dist/contracts/contract-limits.js +2 -0
- package/dist/contracts/contract.d.ts +42 -1
- package/dist/contracts/field.d.ts +58 -1
- package/dist/contracts/json-schema.projector.d.ts +11 -0
- package/dist/contracts/json-schema.projector.js +76 -0
- package/dist/contracts/scalar-value-type.d.ts +3 -1
- package/dist/framework/access-facade.d.ts +116 -0
- package/dist/framework/access-facade.js +118 -0
- package/dist/framework/contract-view.d.ts +120 -16
- package/dist/framework/framework-construction.error.d.ts +14 -4
- package/dist/framework/framework-construction.error.js +18 -2
- package/dist/framework/framework.d.ts +26 -5
- package/dist/framework/framework.factory.d.ts +1 -1
- package/dist/framework/framework.factory.js +145 -24
- package/dist/framework/operation-facade.d.ts +141 -13
- package/dist/framework/operation-facade.js +9 -1
- package/dist/framework/operation-set.runner.d.ts +47 -0
- package/dist/framework/operation-set.runner.js +168 -0
- package/dist/index.d.ts +19 -5
- package/dist/index.js +3 -0
- package/dist/internal.d.ts +9 -2
- package/dist/internal.js +8 -0
- package/dist/operations/database-refusal.d.ts +51 -0
- package/dist/operations/database-refusal.js +45 -0
- package/dist/operations/operation-arguments.d.ts +148 -60
- package/dist/operations/operation-call.d.ts +9 -5
- package/dist/operations/operation-result.d.ts +6 -4
- package/dist/operations/operation-validator-core.js +160 -39
- package/dist/operations/operation-validator.d.ts +1 -1
- package/dist/operations/structural-limits.walker.d.ts +1 -1
- package/dist/operations/structural-limits.walker.js +1 -3
- package/dist/operations/validation-code.guidance.d.ts +6 -0
- package/dist/operations/validation-code.guidance.js +90 -0
- package/dist/operations/write-scope.resolver.d.ts +4 -0
- package/dist/operations/write-scope.resolver.js +2 -0
- package/dist/policy/access-provider.interface.d.ts +91 -0
- package/dist/policy/access-provider.interface.js +1 -0
- package/dist/policy/access-provider.registry.d.ts +17 -0
- package/dist/policy/access-provider.registry.js +15 -0
- package/dist/policy/access-question.d.ts +20 -0
- package/dist/policy/access-question.js +1 -0
- package/dist/policy/access-question.registry.d.ts +5 -0
- package/dist/policy/access-question.registry.js +19 -0
- package/dist/policy/access-question.runtime.d.ts +36 -0
- package/dist/policy/access-question.runtime.js +295 -0
- package/dist/policy/access-verb.table.d.ts +56 -0
- package/dist/policy/access-verb.table.js +21 -0
- package/dist/policy/access-verbs.d.ts +46 -0
- package/dist/policy/access-verbs.js +1 -0
- package/dist/policy/policy-admission.d.ts +20 -0
- package/dist/policy/policy-admission.js +407 -0
- package/dist/policy/policy-after-update.runtime.d.ts +79 -0
- package/dist/policy/policy-after-update.runtime.js +206 -0
- package/dist/policy/policy-condition.d.ts +15 -0
- package/dist/policy/policy-condition.js +36 -0
- package/dist/policy/policy-engine.d.ts +205 -0
- package/dist/policy/policy-engine.js +1 -0
- package/dist/policy/policy-named-rows.d.ts +18 -0
- package/dist/policy/policy-named-rows.js +51 -0
- package/dist/policy/policy-nested-write.runtime.d.ts +44 -0
- package/dist/policy/policy-nested-write.runtime.js +536 -0
- package/dist/policy/policy-read.runtime.d.ts +81 -0
- package/dist/policy/policy-read.runtime.js +501 -0
- package/dist/policy/policy-reference-write.runtime.d.ts +51 -0
- package/dist/policy/policy-reference-write.runtime.js +336 -0
- package/dist/policy/policy-request.d.ts +72 -0
- package/dist/policy/policy-request.js +115 -0
- package/dist/policy/policy-session.d.ts +106 -0
- package/dist/policy/policy-session.js +293 -0
- package/dist/policy/policy-startup.validator.d.ts +10 -0
- package/dist/policy/policy-startup.validator.js +112 -0
- package/dist/policy/policy-write.runtime.d.ts +39 -0
- package/dist/policy/policy-write.runtime.js +530 -0
- package/dist/prebuilt/core-version.generated.d.ts +2 -0
- package/dist/prebuilt/core-version.generated.js +1 -0
- package/dist/prebuilt/prebuilt-changes.d.ts +29 -0
- package/dist/prebuilt/prebuilt-changes.js +63 -0
- package/dist/prebuilt/prebuilt-contracts.d.ts +40 -0
- package/dist/prebuilt/prebuilt-contracts.emitter.d.ts +16 -0
- package/dist/prebuilt/prebuilt-contracts.emitter.js +50 -0
- package/dist/prebuilt/prebuilt-contracts.js +1 -0
- package/dist/prebuilt/prebuilt-contracts.loader.d.ts +19 -0
- package/dist/prebuilt/prebuilt-contracts.loader.js +75 -0
- package/dist/prebuilt/prebuilt-inputs.fingerprint.d.ts +16 -0
- package/dist/prebuilt/prebuilt-inputs.fingerprint.js +227 -0
- package/dist/protocol/absent-route.responder.d.ts +49 -14
- package/dist/protocol/absent-route.responder.js +92 -15
- package/dist/protocol/contract-document.responder.d.ts +9 -1
- package/dist/protocol/contract-document.responder.js +3 -2
- package/dist/protocol/http-request.decoder.d.ts +52 -3
- package/dist/protocol/http-request.decoder.js +45 -6
- package/dist/protocol/http-request.reader.d.ts +10 -3
- package/dist/protocol/http-request.reader.js +12 -2
- package/dist/protocol/http-response.encoder.d.ts +12 -0
- package/dist/protocol/http-response.encoder.js +17 -3
- package/dist/protocol/operation-response.guard.js +1 -3
- package/dist/protocol/operation-set.decoder.d.ts +48 -0
- package/dist/protocol/operation-set.decoder.js +185 -0
- package/dist/protocol/operation-set.handler.d.ts +27 -0
- package/dist/protocol/operation-set.handler.js +179 -0
- package/dist/protocol/protocol-headers.d.ts +12 -3
- package/dist/protocol/protocol-headers.js +12 -5
- package/dist/protocol/protocol-surface.d.ts +16 -3
- package/dist/protocol/protocol-surface.js +41 -1
- package/dist/protocol/protocol.binder.d.ts +52 -1
- package/dist/protocol/protocol.binder.js +6 -1
- package/dist/protocol/protocol.handler.d.ts +45 -1
- package/dist/protocol/protocol.handler.js +164 -19
- package/dist/protocol/read-cache.responder.d.ts +26 -0
- package/dist/protocol/read-cache.responder.js +47 -0
- package/dist/protocol/read-query.codec.d.ts +34 -0
- package/dist/protocol/read-query.codec.js +125 -0
- package/dist/runtime/caller-data.copier.d.ts +18 -3
- package/dist/runtime/caller-data.copier.js +21 -8
- package/dist/runtime/caller-data.door.d.ts +13 -6
- package/dist/runtime/computed-read-runtime.d.ts +6 -1
- package/dist/runtime/computed-read-runtime.js +229 -48
- package/dist/runtime/computed-value.error.d.ts +3 -2
- package/dist/runtime/computed-value.error.js +3 -2
- package/dist/runtime/context-executor.runtime.d.ts +4 -3
- package/dist/runtime/context-executor.runtime.js +4 -2
- package/dist/runtime/core-class.brand.d.ts +10 -0
- package/dist/runtime/core-class.brand.js +21 -0
- package/dist/runtime/create-requirement.d.ts +31 -5
- package/dist/runtime/create-requirement.js +130 -24
- package/dist/runtime/decimal.d.ts +14 -0
- package/dist/runtime/decimal.js +21 -0
- package/dist/runtime/diagnostics-reporter.d.ts +49 -9
- package/dist/runtime/diagnostics-reporter.js +16 -9
- package/dist/runtime/error-boundary.d.ts +9 -2
- package/dist/runtime/error-boundary.js +12 -0
- package/dist/runtime/error-guidance.d.ts +12 -0
- package/dist/runtime/error-guidance.js +1 -0
- package/dist/runtime/error.catalog.d.ts +49 -0
- package/dist/runtime/error.catalog.js +49 -0
- package/dist/runtime/execution-options.d.ts +8 -0
- package/dist/runtime/field-check.evaluator.d.ts +0 -2
- package/dist/runtime/field-check.evaluator.js +1 -1
- package/dist/runtime/field-compute.d.ts +11 -10
- package/dist/runtime/field-stage.runtime.d.ts +3 -3
- package/dist/runtime/field-stage.runtime.js +9 -11
- package/dist/runtime/field-validator.runtime.d.ts +19 -1
- package/dist/runtime/field-validator.runtime.js +49 -9
- package/dist/runtime/framework-error.js +9 -0
- package/dist/runtime/framework-warning.emitter.d.ts +6 -0
- package/dist/runtime/framework-warning.emitter.js +8 -0
- package/dist/runtime/json-value.d.ts +10 -5
- package/dist/runtime/level-lifecycle.runtime.d.ts +4 -3
- package/dist/runtime/level-lifecycle.runtime.js +3 -5
- package/dist/runtime/mutation-planner.d.ts +1 -6
- package/dist/runtime/mutation-planner.js +4 -17
- package/dist/runtime/nested-write.walker.js +2 -1
- package/dist/runtime/operation-code.guidance.d.ts +6 -0
- package/dist/runtime/operation-code.guidance.js +167 -0
- package/dist/runtime/operation-request.d.ts +16 -9
- package/dist/runtime/operation-runtime.d.ts +35 -17
- package/dist/runtime/operation-runtime.js +220 -49
- package/dist/runtime/outcome-mapper.d.ts +2 -1
- package/dist/runtime/output-validator.d.ts +1 -1
- package/dist/runtime/output-validator.js +1 -3
- package/dist/runtime/owned-execution.registry.d.ts +34 -4
- package/dist/runtime/pipe-output.validator.d.ts +10 -0
- package/dist/runtime/pipe-output.validator.js +4 -2
- package/dist/runtime/pipeline.d.ts +52 -23
- package/dist/runtime/readonly-value.d.ts +20 -5
- package/dist/runtime/readonly-value.js +74 -26
- package/dist/runtime/record.guard.d.ts +14 -0
- package/dist/runtime/record.guard.js +10 -0
- package/dist/runtime/referential-action.d.ts +1 -1
- package/dist/runtime/request-envelope.validator.js +13 -10
- package/dist/runtime/scalar-runtime.d.ts +4 -21
- package/dist/runtime/scalar-runtime.js +91 -31
- package/dist/runtime/thenable.guard.d.ts +7 -0
- package/dist/runtime/thenable.guard.js +5 -0
- package/dist/runtime/unsent-value.normalizer.d.ts +15 -0
- package/dist/runtime/unsent-value.normalizer.js +129 -0
- package/dist/transactions/operation-arguments-encoder.js +9 -10
- package/dist/transactions/operation-fingerprint.js +2 -2
- package/dist/transactions/sql-statement.d.ts +10 -2
- package/dist/transactions/sql-statement.validator.d.ts +2 -2
- package/dist/transactions/sql-statement.validator.js +40 -6
- package/dist/transactions/transaction-envelope.d.ts +5 -4
- package/dist/transactions/transaction-integrity-error.js +2 -0
- package/dist/transactions/transaction-plan-assembler.d.ts +12 -5
- package/dist/transactions/transaction-plan-assembler.js +49 -17
- package/dist/transactions/transaction-plan-validator.d.ts +23 -7
- package/dist/transactions/transaction-plan-validator.js +31 -7
- package/dist/transactions/transaction-reference-collector.js +8 -10
- package/dist/transactions/transaction-reference-resolver.d.ts +3 -2
- package/dist/transactions/transaction-reference-resolver.js +1 -3
- package/dist/transactions/transaction-reference-validator.d.ts +43 -3
- package/dist/transactions/transaction-reference-validator.js +83 -57
- package/dist/transactions/transaction-reference.d.ts +1 -1
- package/dist/transactions/transaction-reference.js +5 -0
- package/dist/transactions/transaction-request.d.ts +8 -8
- package/dist/transactions/transaction-runtime.d.ts +5 -2
- package/dist/transactions/transaction-runtime.js +108 -27
- package/dist/transactions/transaction-settlement.runtime.d.ts +4 -3
- package/dist/transactions/transaction-slot-path-error.js +2 -0
- package/dist/transactions/transaction-stage.runtime.d.ts +5 -3
- package/dist/transactions/transaction-stage.runtime.js +8 -7
- package/package.json +6 -5
- package/src/runtime/field-check.evaluator.ts +1 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { AvOperationIdentity } from "../operations/operation-identity.js";
|
|
2
|
+
import type { PolicySession } from "../policy/policy-session.js";
|
|
2
3
|
import type { AvTransportContext } from "./pipeline.js";
|
|
3
4
|
import type { AvState } from "./request-state.js";
|
|
4
5
|
/**
|
|
5
6
|
* The protocol version and Contract hash a remote caller says it was built for:
|
|
6
7
|
* the Client Contract's for a client, the Agent Contract's for an agent.
|
|
7
8
|
*/
|
|
8
|
-
export type
|
|
9
|
+
export type AvRequestProtocol = {
|
|
9
10
|
readonly version: number;
|
|
10
11
|
readonly hash: string;
|
|
11
12
|
};
|
|
@@ -20,7 +21,7 @@ type RuntimeOperationBase = AvOperationIdentity & {
|
|
|
20
21
|
readonly state?: AvState;
|
|
21
22
|
};
|
|
22
23
|
/** An in-process request, run under the Application Contract. */
|
|
23
|
-
export type
|
|
24
|
+
export type AvApplicationOperationRequest = RuntimeOperationBase & {
|
|
24
25
|
readonly origin: "application";
|
|
25
26
|
readonly protocol?: never;
|
|
26
27
|
readonly transport?: never;
|
|
@@ -29,24 +30,24 @@ export type ApplicationOperationRequest = RuntimeOperationBase & {
|
|
|
29
30
|
* A remote request, run under the Client Contract; `protocol` is the identity
|
|
30
31
|
* the client sent.
|
|
31
32
|
*/
|
|
32
|
-
export type
|
|
33
|
+
export type AvClientOperationRequest = RuntimeOperationBase & {
|
|
33
34
|
readonly origin: "client";
|
|
34
|
-
readonly protocol:
|
|
35
|
+
readonly protocol: AvRequestProtocol;
|
|
35
36
|
readonly transport?: AvTransportContext;
|
|
36
37
|
};
|
|
37
38
|
/**
|
|
38
39
|
* An AI agent's request, run under the Agent Contract; `protocol` is the
|
|
39
40
|
* identity of the Agent Contract the caller (an MCP server) was built from.
|
|
40
41
|
*/
|
|
41
|
-
export type
|
|
42
|
+
export type AvAgentOperationRequest = RuntimeOperationBase & {
|
|
42
43
|
readonly origin: "agent";
|
|
43
|
-
readonly protocol:
|
|
44
|
+
readonly protocol: AvRequestProtocol;
|
|
44
45
|
readonly transport?: AvTransportContext;
|
|
45
46
|
};
|
|
46
47
|
/** A request from outside the server: a client's or an agent's. */
|
|
47
|
-
export type RemoteOperationRequest =
|
|
48
|
+
export type RemoteOperationRequest = AvClientOperationRequest | AvAgentOperationRequest;
|
|
48
49
|
/** One operation request, as `framework.execute` takes it. */
|
|
49
|
-
export type
|
|
50
|
+
export type AvOperationRequest = AvApplicationOperationRequest | AvClientOperationRequest | AvAgentOperationRequest;
|
|
50
51
|
type WithoutArguments<Request> = Request extends unknown ? Omit<Request, "arguments"> : never;
|
|
51
52
|
/**
|
|
52
53
|
* A request as every stage after the Framework Validation Layer sees it:
|
|
@@ -56,12 +57,18 @@ type WithoutArguments<Request> = Request extends unknown ? Omit<Request, "argume
|
|
|
56
57
|
* unreachable by type. Distributive, so the origin and family/variant
|
|
57
58
|
* correlations survive the omission.
|
|
58
59
|
*/
|
|
59
|
-
export type OperationExecutionRequest = WithoutArguments<
|
|
60
|
+
export type OperationExecutionRequest = WithoutArguments<AvOperationRequest>;
|
|
60
61
|
/**
|
|
61
62
|
* A request whose stages run: its `state` settled once, the seed or the `{}`
|
|
62
63
|
* the runtime made for it, so every stage is told the same object.
|
|
63
64
|
*/
|
|
64
65
|
export type StatefulOperationRequest = OperationExecutionRequest & {
|
|
65
66
|
readonly state: AvState;
|
|
67
|
+
/**
|
|
68
|
+
* The request's policy session, when the policy checks it: a client's or an
|
|
69
|
+
* agent's request, or an application call made `as` a principal. Absent, nothing
|
|
70
|
+
* is checked: an application call, or a call a stage made through `ctx`.
|
|
71
|
+
*/
|
|
72
|
+
readonly policy?: PolicySession;
|
|
66
73
|
};
|
|
67
74
|
export {};
|
|
@@ -7,14 +7,15 @@ import type { ResolvedFrameworkConfig } from "../config/config.resolver.js";
|
|
|
7
7
|
import type { AvRequestOrigin, RemoteRequestOrigin } from "../config/config-layer.js";
|
|
8
8
|
import type { AvContract } from "../contracts/contract.js";
|
|
9
9
|
import type { OperationValidationOptions, SemanticOperationArguments } from "../operations/operation-validator.js";
|
|
10
|
-
import type
|
|
10
|
+
import { type PolicyCaller } from "../policy/policy-request.js";
|
|
11
|
+
import type { AvTransactionRequest } from "../transactions/transaction-request.js";
|
|
11
12
|
import { type ArgumentsSource } from "./caller-data.door.js";
|
|
12
13
|
import { type ContextExecutor, type ExecutorScope } from "./context-executor.runtime.js";
|
|
13
14
|
import { type RecordWriteFacts } from "./create-requirement.js";
|
|
14
15
|
import { type DiagnosticsReporter } from "./diagnostics-reporter.js";
|
|
15
16
|
import { type OuterFailureLayer } from "./error-boundary.js";
|
|
16
17
|
import { type FieldStagePlan } from "./field-stage.plan.js";
|
|
17
|
-
import type {
|
|
18
|
+
import type { AvOperationRequest, AvRequestProtocol, StatefulOperationRequest } from "./operation-request.js";
|
|
18
19
|
import type { AvOperationFailureResponse, AvOperationResponse } from "./operation-response.js";
|
|
19
20
|
import type { AvState } from "./request-state.js";
|
|
20
21
|
import { type NormalizationWrite } from "./scalar-runtime.js";
|
|
@@ -45,7 +46,7 @@ export type OperationPipelineDependencies<M extends AvAdapterModel> = Omit<Opera
|
|
|
45
46
|
* Where one operation's Adapter call runs: standalone, through the Adapter, or
|
|
46
47
|
* inside an open transaction, through its executor.
|
|
47
48
|
*/
|
|
48
|
-
|
|
49
|
+
type OperationBinding<M extends AvAdapterModel> = {
|
|
49
50
|
readonly kind: "standalone";
|
|
50
51
|
readonly executor: AvAdapterOperationExecutor<M>;
|
|
51
52
|
} | {
|
|
@@ -79,13 +80,15 @@ export declare function createPipelineDependencies<M extends AvAdapterModel>(dep
|
|
|
79
80
|
* request's arguments are the caller's own objects, copied at the door, or data
|
|
80
81
|
* no caller holds (see {@link ArgumentsSource}).
|
|
81
82
|
*/
|
|
82
|
-
export type FrameworkOperationExecutor = (request:
|
|
83
|
+
export type FrameworkOperationExecutor = (request: AvOperationRequest, report: DiagnosticsReporter, source: ArgumentsSource,
|
|
84
|
+
/** The principal an application call runs as (`{ as }`), when it names one. */
|
|
85
|
+
caller?: PolicyCaller) => Promise<AvOperationResponse>;
|
|
83
86
|
/** Selects the Contract of the request's origin. */
|
|
84
|
-
export declare function activeContract(contracts: AvContracts, request:
|
|
87
|
+
export declare function activeContract(contracts: AvContracts, request: AvOperationRequest | AvTransactionRequest): AvContract;
|
|
85
88
|
/** Creates the transport-independent operation executor owned by core. */
|
|
86
89
|
export declare function createOperationRuntime<M extends AvAdapterModel>(dependencies: OperationRuntimeDependencies<M>, pipelineDependencies: OperationPipelineDependencies<M>): FrameworkOperationExecutor;
|
|
87
90
|
/** Validates the request-level protocol identity. */
|
|
88
|
-
export declare function validateProtocolIdentity(contracts: AvContracts, request:
|
|
91
|
+
export declare function validateProtocolIdentity(contracts: AvContracts, request: AvOperationRequest | AvTransactionRequest): AvOperationFailureResponse | undefined;
|
|
89
92
|
/**
|
|
90
93
|
* The stale-client check on one remote protocol identity: the protocol version first
|
|
91
94
|
* (`A2006`), then the hash of the origin's Contract (`A2005`): the ClientContract's
|
|
@@ -94,8 +97,8 @@ export declare function validateProtocolIdentity(contracts: AvContracts, request
|
|
|
94
97
|
* (`@aventara/core/protocol`) call it too, so a stale client hears the same envelope
|
|
95
98
|
* whichever layer answers.
|
|
96
99
|
*/
|
|
97
|
-
export declare function protocolIdentityFailure(contracts: AvContracts, protocol:
|
|
98
|
-
|
|
100
|
+
export declare function protocolIdentityFailure(contracts: AvContracts, protocol: AvRequestProtocol, origin: RemoteRequestOrigin): AvOperationFailureResponse | undefined;
|
|
101
|
+
type ValidatedOperationArguments = {
|
|
99
102
|
readonly ok: true;
|
|
100
103
|
readonly arguments: SemanticOperationArguments;
|
|
101
104
|
} | {
|
|
@@ -103,8 +106,14 @@ export type ValidatedOperationArguments = {
|
|
|
103
106
|
readonly response: AvOperationFailureResponse;
|
|
104
107
|
};
|
|
105
108
|
/** Validates one operation's arguments through the Framework Validation Layer. */
|
|
106
|
-
export declare function validateOperationRequest(contract: AvContract, request:
|
|
107
|
-
/**
|
|
109
|
+
export declare function validateOperationRequest(contract: AvContract, request: AvOperationRequest, options?: OperationValidationOptions, write?: NormalizationWrite): ValidatedOperationArguments;
|
|
110
|
+
/** The subject a refused output of an operation's pipes is reported under at a plan step. */
|
|
111
|
+
export declare const STEP_PIPES = "Pipes";
|
|
112
|
+
/**
|
|
113
|
+
* Every sent field's path. A `$ref` is an object of `$`-keys, which no field
|
|
114
|
+
* pipe or validator takes, so a plan step's literal values before BEGIN are
|
|
115
|
+
* every field too, wherever a pipe left a reference or a literal.
|
|
116
|
+
*/
|
|
108
117
|
export declare const EVERY_FIELD: () => boolean;
|
|
109
118
|
/**
|
|
110
119
|
* What admission leaves: the deep-frozen arguments every later stage reads, and
|
|
@@ -120,23 +129,31 @@ export type AdmittedOperation = {
|
|
|
120
129
|
readonly response: AvOperationFailureResponse;
|
|
121
130
|
};
|
|
122
131
|
/** Which sent values an operation's field stages and validators take, and how its pipe output is checked. */
|
|
123
|
-
|
|
132
|
+
type AdmissionScope = {
|
|
124
133
|
/**
|
|
125
134
|
* The sent values the field pipes and validators take: every one for a single
|
|
126
|
-
* call
|
|
127
|
-
* at the step.
|
|
135
|
+
* call and for a plan step before BEGIN (an unresolved `$ref` is an object of
|
|
136
|
+
* `$`-keys, which they never take), its resolved `$ref` values at the step.
|
|
128
137
|
*/
|
|
129
138
|
readonly select: (path: readonly (string | number)[]) => boolean;
|
|
130
139
|
/** Before BEGIN a plan step's `$ref` slots are unresolved: these admit them. */
|
|
131
140
|
readonly validation?: OperationValidationOptions;
|
|
141
|
+
/**
|
|
142
|
+
* A plan step or a forced call, admitted before BEGIN: the validators judge
|
|
143
|
+
* there the sent values no later stage can change (a field with no write
|
|
144
|
+
* compute stage of its record's phase), so a caller's refusal opens no
|
|
145
|
+
* transaction. Everything is judged again after write compute.
|
|
146
|
+
*/
|
|
147
|
+
readonly beforeBegin?: boolean;
|
|
132
148
|
};
|
|
133
149
|
/**
|
|
134
|
-
* Runs an operation's admission — its guards
|
|
135
|
-
* the
|
|
150
|
+
* Runs an operation's admission — its guards and pipes, and before BEGIN the
|
|
151
|
+
* validators of the values nothing after it changes — and answers the
|
|
152
|
+
* deep-frozen arguments the rest of the operation reads, or the refusal.
|
|
136
153
|
*/
|
|
137
154
|
export declare function admitOperation<M extends AvAdapterModel>(dependencies: OperationPipelineDependencies<M>, request: StatefulOperationRequest, contract: AvContract, args: unknown, argumentsPath: readonly (string | number)[], report: DiagnosticsReporter, scope: ExecutorScope<M>, admission?: AdmissionScope): Promise<AdmittedOperation>;
|
|
138
155
|
/** How a plan step's arguments were changed between their admission and the step. */
|
|
139
|
-
|
|
156
|
+
type StepChanges = {
|
|
140
157
|
/** The sent `$ref` values written at this step: their field stages run now. */
|
|
141
158
|
readonly written: (path: readonly (string | number)[]) => boolean;
|
|
142
159
|
/** A transaction pipe changed the step: every value is judged again. */
|
|
@@ -146,7 +163,7 @@ export type StepChanges = {
|
|
|
146
163
|
};
|
|
147
164
|
/**
|
|
148
165
|
* A plan step's (or a forced call's) arguments at the step: resolved values
|
|
149
|
-
* through their field
|
|
166
|
+
* through their field pipes, and re-checked when a stage changed them.
|
|
150
167
|
*/
|
|
151
168
|
export declare function prepareStep<M extends AvAdapterModel>(dependencies: OperationPipelineDependencies<M>, request: StatefulOperationRequest, contract: AvContract, args: unknown, argumentsPath: readonly (string | number)[], report: DiagnosticsReporter, executor: AvAdapterTransactionExecutor<M>, changes: StepChanges, outer: OuterFailureLayer): Promise<AdmittedOperation>;
|
|
152
169
|
/**
|
|
@@ -155,3 +172,4 @@ export declare function prepareStep<M extends AvAdapterModel>(dependencies: Oper
|
|
|
155
172
|
* failures never reach this function, so developer filters never see them.
|
|
156
173
|
*/
|
|
157
174
|
export declare function executeAdmittedOperation<M extends AvAdapterModel>(dependencies: OperationPipelineDependencies<M>, request: StatefulOperationRequest, contract: AvContract, admittedArguments: unknown, argumentsPath: readonly (string | number)[], binding: OperationBinding<M>, report: DiagnosticsReporter): Promise<AvOperationResponse>;
|
|
175
|
+
export {};
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import { hasFieldValidators } from "../compiler/field-validator.compiler.js";
|
|
2
|
+
import { createComputedFields } from "../config/field-compute.resolver.js";
|
|
2
3
|
import { fieldStagesOf, isForcedOperation, nestedTargetLevels, operationLevels, rawPipelineTree, transactionLevelsOf, } from "../config/pipeline-tree.resolver.js";
|
|
3
4
|
import { AVENTARA_PROTOCOL_VERSION } from "../contracts/contract-protocol.js";
|
|
4
5
|
import { findOperationAvailabilityIssue, validateOperationArguments, } from "../operations/operation-validator.js";
|
|
6
|
+
import { enforceReadPolicy, } from "../policy/policy-read.runtime.js";
|
|
7
|
+
import { admitRequestPolicy, openRequestPolicy, } from "../policy/policy-request.js";
|
|
8
|
+
import { enforceWritePolicy, writeNeedsTransaction, } from "../policy/policy-write.runtime.js";
|
|
5
9
|
import { transactionInfrastructureFailure } from "../transactions/transaction-response.js";
|
|
6
10
|
import { settleTransaction } from "../transactions/transaction-settlement.runtime.js";
|
|
7
11
|
import { TRANSACTION_PIPES, transactionFacts, } from "../transactions/transaction-stage.runtime.js";
|
|
8
12
|
import { copyAtDoor, misuseIdentityOf, refuseCallerData, } from "./caller-data.door.js";
|
|
9
13
|
import { materializeReadOperation, planReadOperation, } from "./computed-read-runtime.js";
|
|
14
|
+
import { AvComputedValueError } from "./computed-value.error.js";
|
|
10
15
|
import { createContextExecutor, } from "./context-executor.runtime.js";
|
|
11
|
-
import { createRequirementIssues, recordWriteFactsOf, } from "./create-requirement.js";
|
|
16
|
+
import { computedRequirementGapsOf, createRequirementIssues, recordWriteFactsOf, } from "./create-requirement.js";
|
|
12
17
|
import { createDiagnosticsReporter, } from "./diagnostics-reporter.js";
|
|
13
18
|
import { AdapterBoundary, OPERATION_ARGUMENTS_PATH, resolveOperationFailure, sanitizeOperationFailure, } from "./error-boundary.js";
|
|
14
19
|
import { planFieldStages } from "./field-stage.plan.js";
|
|
15
20
|
import { guardSentFields, pipeSentFields, valueAt, writeRecordPathsOf, } from "./field-stage.runtime.js";
|
|
16
|
-
import { fieldValidatorIssues } from "./field-validator.runtime.js";
|
|
21
|
+
import { fieldValidatorIssues, hiddenFieldRefusal, } from "./field-validator.runtime.js";
|
|
17
22
|
import { thrownFailure } from "./framework-error.factory.js";
|
|
18
23
|
import { AvInterceptorNextError } from "./interceptor-next.error.js";
|
|
19
24
|
import { runLevelLifecycle, } from "./level-lifecycle.runtime.js";
|
|
@@ -23,10 +28,11 @@ import { nestedWriteTargetsOf, } from "./nested-write.walker.js";
|
|
|
23
28
|
import { internalFailure, operationFailure } from "./operation-response.js";
|
|
24
29
|
import { mapOperationOutcome, mapValidationOutcome, uniqueMissFailure, } from "./outcome-mapper.js";
|
|
25
30
|
import { AvOutputValidationError, validateOperationOutput, } from "./output-validator.js";
|
|
26
|
-
import { refusePipeOutput, refuseStageOutput, } from "./pipe-output.validator.js";
|
|
31
|
+
import { AvPipeOutputError, PIPE_OUTPUT_FAILURE_MESSAGE, refusePipeOutput, refuseStageOutput, } from "./pipe-output.validator.js";
|
|
27
32
|
import { deepFreeze, frozenCopy } from "./readonly-value.js";
|
|
28
33
|
import { requestStateOf } from "./request-state.resolver.js";
|
|
29
34
|
import { normalizeOperationScalarValues, } from "./scalar-runtime.js";
|
|
35
|
+
import { withoutUnsentWriteValues } from "./unsent-value.normalizer.js";
|
|
30
36
|
function scopeOf(request, binding) {
|
|
31
37
|
return {
|
|
32
38
|
requestId: request.requestId,
|
|
@@ -37,9 +43,30 @@ function scopeOf(request, binding) {
|
|
|
37
43
|
export function withRequestState(request) {
|
|
38
44
|
return { ...request, state: requestStateOf(request.state) };
|
|
39
45
|
}
|
|
46
|
+
function withRequestPolicy(dependencies, request, caller, report) {
|
|
47
|
+
const failed = (error) => {
|
|
48
|
+
report(error, "A3000");
|
|
49
|
+
return internalFailure();
|
|
50
|
+
};
|
|
51
|
+
const withPolicy = (policy) => policy === undefined ? request : { ...request, policy };
|
|
52
|
+
try {
|
|
53
|
+
const policy = openRequestPolicy(dependencies.config.policy, dependencies.contracts.core, request, caller, dependencies.adapter);
|
|
54
|
+
return policy instanceof Promise
|
|
55
|
+
? policy.then(withPolicy, failed)
|
|
56
|
+
: withPolicy(policy);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
return failed(error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
40
62
|
export function createPipelineDependencies(dependencies, model) {
|
|
41
63
|
const misuse = createMisuseReporter(dependencies.config.misuse);
|
|
42
|
-
const recordWrites = recordWriteFactsOf(
|
|
64
|
+
const recordWrites = recordWriteFactsOf({
|
|
65
|
+
...(dependencies.adapter.referentialActions === undefined
|
|
66
|
+
? {}
|
|
67
|
+
: { referentialActions: dependencies.adapter.referentialActions }),
|
|
68
|
+
model,
|
|
69
|
+
});
|
|
43
70
|
const contexts = createContextExecutor({
|
|
44
71
|
model,
|
|
45
72
|
adapter: dependencies.adapter,
|
|
@@ -121,7 +148,7 @@ function operationFacts(contract, request, args) {
|
|
|
121
148
|
family: request.family,
|
|
122
149
|
variant: request.variant,
|
|
123
150
|
},
|
|
124
|
-
$args: args,
|
|
151
|
+
$args: frozenCopy(args),
|
|
125
152
|
$origin: request.origin,
|
|
126
153
|
$requestId: request.requestId,
|
|
127
154
|
$contract: contract,
|
|
@@ -162,7 +189,7 @@ function outputAccepted(contract, request, projection, data, report) {
|
|
|
162
189
|
}
|
|
163
190
|
export function createOperationRuntime(dependencies, pipelineDependencies) {
|
|
164
191
|
const misuse = createMisuseReporter(dependencies.config.misuse);
|
|
165
|
-
return async (request, report, source) => {
|
|
192
|
+
return async (request, report, source, caller) => {
|
|
166
193
|
let validated;
|
|
167
194
|
try {
|
|
168
195
|
validated = validateOperation(dependencies, request, source, misuse);
|
|
@@ -176,17 +203,34 @@ export function createOperationRuntime(dependencies, pipelineDependencies) {
|
|
|
176
203
|
if (!validated.ok) {
|
|
177
204
|
return validated.response;
|
|
178
205
|
}
|
|
179
|
-
const
|
|
206
|
+
const opened = withRequestPolicy(dependencies, withRequestState(request), caller, report);
|
|
207
|
+
const stateful = opened instanceof Promise ? await opened : opened;
|
|
208
|
+
if (!("state" in stateful)) {
|
|
209
|
+
return stateful;
|
|
210
|
+
}
|
|
211
|
+
const forced = isForcedOperation(activeScopeConfig(dependencies.config, request).pipelines, request);
|
|
180
212
|
const admitted = await admitOperation(pipelineDependencies, stateful, validated.contract, validated.arguments, OPERATION_ARGUMENTS_PATH, report, {
|
|
181
213
|
requestId: request.requestId,
|
|
182
214
|
transaction: undefined,
|
|
183
215
|
state: stateful.state,
|
|
184
|
-
});
|
|
216
|
+
}, forced ? FORCED_CALL : SINGLE_CALL);
|
|
185
217
|
if (!admitted.ok) {
|
|
186
218
|
return admitted.response;
|
|
187
219
|
}
|
|
188
|
-
|
|
189
|
-
|
|
220
|
+
let checkedWrite = false;
|
|
221
|
+
if (stateful.policy !== undefined &&
|
|
222
|
+
request.family !== "find" &&
|
|
223
|
+
validated.contract.transactions === "interactive" &&
|
|
224
|
+
!forced) {
|
|
225
|
+
try {
|
|
226
|
+
checkedWrite = await writeNeedsTransaction(stateful.policy, dependencies.contracts.core, stateful, () => planReadOperation(dependencies.contracts.core, dependencies.config.adapter.model, validated.contract, activeScopeConfig(dependencies.config, request).compute, stateful, admitted.args), admitted.args);
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
return sanitizeOperationFailure(error, stateful.policy.execution.boundary.originOf(error), report, { path: OPERATION_ARGUMENTS_PATH, arguments: admitted.args });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (forced || checkedWrite) {
|
|
233
|
+
return executeForcedOperation(pipelineDependencies, dependencies.adapter, stateful, validated.contract, admitted.args, report, forced);
|
|
190
234
|
}
|
|
191
235
|
return executeAdmittedOperation(pipelineDependencies, stateful, validated.contract, admitted.args, OPERATION_ARGUMENTS_PATH, { kind: "standalone", executor: dependencies.adapter }, report);
|
|
192
236
|
};
|
|
@@ -198,9 +242,11 @@ function validateOperation(dependencies, request, source, misuse) {
|
|
|
198
242
|
}
|
|
199
243
|
const contract = activeContract(dependencies.contracts, request);
|
|
200
244
|
let owned = request;
|
|
201
|
-
if (source
|
|
245
|
+
if (source !== "owned" &&
|
|
202
246
|
findOperationAvailabilityIssue(contract, request) === undefined) {
|
|
203
|
-
const copy =
|
|
247
|
+
const copy = source === "caller"
|
|
248
|
+
? copyAtDoor(request.arguments)
|
|
249
|
+
: { ok: false, error: source.refused };
|
|
204
250
|
if (!copy.ok) {
|
|
205
251
|
return rejected(mapValidationOutcome([
|
|
206
252
|
refuseCallerData(copy.error, OPERATION_ARGUMENTS_PATH, misuseIdentityOf(request), misuse),
|
|
@@ -235,6 +281,12 @@ export function protocolIdentityFailure(contracts, protocol, origin) {
|
|
|
235
281
|
return undefined;
|
|
236
282
|
}
|
|
237
283
|
export function validateOperationRequest(contract, request, options, write = "copy") {
|
|
284
|
+
if (findOperationAvailabilityIssue(contract, request) === undefined) {
|
|
285
|
+
const sent = withoutUnsentWriteValues(contract, request, request.arguments);
|
|
286
|
+
if (sent !== request.arguments) {
|
|
287
|
+
request = { ...request, arguments: sent };
|
|
288
|
+
}
|
|
289
|
+
}
|
|
238
290
|
const validation = validateOperationArguments(contract, request, options);
|
|
239
291
|
if (!validation.ok) {
|
|
240
292
|
return { ok: false, response: mapValidationOutcome(validation.issues) };
|
|
@@ -251,12 +303,13 @@ function rejected(response) {
|
|
|
251
303
|
return { ok: false, response };
|
|
252
304
|
}
|
|
253
305
|
const FIELD_PIPES = "Field pipes";
|
|
254
|
-
const STEP_PIPES = "Pipes";
|
|
306
|
+
export const STEP_PIPES = "Pipes";
|
|
255
307
|
export const EVERY_FIELD = () => true;
|
|
256
308
|
function filtersOf(levels) {
|
|
257
309
|
return levels.flatMap((level) => level.filters);
|
|
258
310
|
}
|
|
259
311
|
const SINGLE_CALL = { select: EVERY_FIELD };
|
|
312
|
+
const FORCED_CALL = { select: EVERY_FIELD, beforeBegin: true };
|
|
260
313
|
export async function admitOperation(dependencies, request, contract, args, argumentsPath, report, scope, admission = SINGLE_CALL) {
|
|
261
314
|
const contexts = dependencies.contexts;
|
|
262
315
|
const tree = activeScopeConfig(dependencies.config, request).pipelines;
|
|
@@ -299,8 +352,10 @@ export async function admitOperation(dependencies, request, contract, args, argu
|
|
|
299
352
|
let pipeIndex = 0;
|
|
300
353
|
for (const level of levels) {
|
|
301
354
|
for (const pipe of level.pipes) {
|
|
302
|
-
const
|
|
303
|
-
|
|
355
|
+
const told = frozenCopy(current);
|
|
356
|
+
const output = await pipe(told, context());
|
|
357
|
+
if (output !== undefined && output !== told && output !== current) {
|
|
358
|
+
const returned = withoutUnsentWriteValues(dependencies.contracts.core, request, output);
|
|
304
359
|
const refused = refusePipeOutput(contracts, request, returned, pipe, pipeIndex, admission.validation);
|
|
305
360
|
if (refused !== undefined) {
|
|
306
361
|
report(refused.error, "A3004");
|
|
@@ -322,6 +377,16 @@ export async function admitOperation(dependencies, request, contract, args, argu
|
|
|
322
377
|
piped: piped || fields.piped,
|
|
323
378
|
};
|
|
324
379
|
};
|
|
380
|
+
const absent = createRequirementIssues(contract, dependencies.recordWrites, request, current, argumentsPath);
|
|
381
|
+
if (absent.length > 0) {
|
|
382
|
+
return { ok: false, response: mapValidationOutcome(absent) };
|
|
383
|
+
}
|
|
384
|
+
if (request.policy !== undefined) {
|
|
385
|
+
const refused = await admitRequestPolicy(request.policy, dependencies.contracts.core, contract, request, current, report, { path: argumentsPath, arguments: current });
|
|
386
|
+
if (refused !== undefined) {
|
|
387
|
+
return { ok: false, response: refused };
|
|
388
|
+
}
|
|
389
|
+
}
|
|
325
390
|
try {
|
|
326
391
|
return await admit();
|
|
327
392
|
}
|
|
@@ -333,10 +398,12 @@ export async function admitOperation(dependencies, request, contract, args, argu
|
|
|
333
398
|
}
|
|
334
399
|
}
|
|
335
400
|
async function runFieldInputStages(dependencies, request, contract, args, argumentsPath, report, admission) {
|
|
336
|
-
const
|
|
401
|
+
const scopeConfig = activeScopeConfig(dependencies.config, request);
|
|
402
|
+
const tree = scopeConfig.pipelines;
|
|
337
403
|
const planned = dependencies.fieldStages[request.origin];
|
|
338
404
|
const pipes = planned.anyPipes;
|
|
339
|
-
|
|
405
|
+
const judge = admission.beforeBegin === true && hasFieldValidators(contract);
|
|
406
|
+
if (!pipes && !judge) {
|
|
340
407
|
return { ok: true, args, piped: false };
|
|
341
408
|
}
|
|
342
409
|
let current = args;
|
|
@@ -364,14 +431,25 @@ async function runFieldInputStages(dependencies, request, contract, args, argume
|
|
|
364
431
|
}
|
|
365
432
|
}
|
|
366
433
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
434
|
+
if (judge) {
|
|
435
|
+
const compute = scopeConfig.compute;
|
|
436
|
+
const broken = fieldValidatorIssues(contract, dependencies.recordWrites.references, request, current, argumentsPath, admission.select, (resource, stage, field) => {
|
|
437
|
+
const fields = compute !== undefined && Object.hasOwn(compute, resource)
|
|
438
|
+
? compute[resource]
|
|
439
|
+
: undefined;
|
|
440
|
+
const phases = fields !== undefined && Object.hasOwn(fields, field)
|
|
441
|
+
? fields[field]
|
|
442
|
+
: undefined;
|
|
443
|
+
return phases?.[stage] !== undefined;
|
|
444
|
+
});
|
|
445
|
+
if (broken.length > 0) {
|
|
446
|
+
return { ok: false, response: mapValidationOutcome(broken) };
|
|
447
|
+
}
|
|
370
448
|
}
|
|
371
449
|
return { ok: true, args: current, piped: changed };
|
|
372
450
|
}
|
|
373
451
|
export async function prepareStep(dependencies, request, contract, args, argumentsPath, report, executor, changes, outer) {
|
|
374
|
-
let current = deepFreeze(args);
|
|
452
|
+
let current = deepFreeze(withoutUnsentWriteValues(dependencies.contracts.core, request, args));
|
|
375
453
|
const scope = {
|
|
376
454
|
requestId: request.requestId,
|
|
377
455
|
transaction: executor,
|
|
@@ -395,12 +473,6 @@ export async function prepareStep(dependencies, request, contract, args, argumen
|
|
|
395
473
|
return { ok: false, response: refused.response };
|
|
396
474
|
}
|
|
397
475
|
}
|
|
398
|
-
if (changes.transactionPiped) {
|
|
399
|
-
const broken = fieldValidatorIssues(contract, dependencies.recordWrites.references, request, current, argumentsPath, EVERY_FIELD);
|
|
400
|
-
if (broken.length > 0) {
|
|
401
|
-
return { ok: false, response: mapValidationOutcome(broken) };
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
476
|
return { ok: true, args: deepFreeze(current), piped: resolved.piped };
|
|
405
477
|
}
|
|
406
478
|
catch (error) {
|
|
@@ -410,7 +482,7 @@ export async function prepareStep(dependencies, request, contract, args, argumen
|
|
|
410
482
|
};
|
|
411
483
|
}
|
|
412
484
|
}
|
|
413
|
-
async function executeForcedOperation(dependencies, adapter, request, contract, args, report) {
|
|
485
|
+
async function executeForcedOperation(dependencies, adapter, request, contract, args, report, forced) {
|
|
414
486
|
const plan = [
|
|
415
487
|
{
|
|
416
488
|
resource: request.resource,
|
|
@@ -421,7 +493,9 @@ async function executeForcedOperation(dependencies, adapter, request, contract,
|
|
|
421
493
|
];
|
|
422
494
|
const settled = await settleTransaction({
|
|
423
495
|
adapter,
|
|
424
|
-
levels:
|
|
496
|
+
levels: forced
|
|
497
|
+
? transactionLevelsOf(activeScopeConfig(dependencies.config, request).pipelines, request.resource)
|
|
498
|
+
: [],
|
|
425
499
|
plan,
|
|
426
500
|
contextOf: (current, executor) => dependencies.contexts.transaction({
|
|
427
501
|
requestId: request.requestId,
|
|
@@ -465,15 +539,8 @@ export async function executeAdmittedOperation(dependencies, request, contract,
|
|
|
465
539
|
const adapterBoundary = new AdapterBoundary();
|
|
466
540
|
const contracts = { core: dependencies.contracts.core, active: contract };
|
|
467
541
|
let args = deepFreeze(admittedArguments);
|
|
468
|
-
|
|
469
|
-
const
|
|
470
|
-
if (told === undefined || told.of !== args) {
|
|
471
|
-
told = { of: args, view: frozenCopy(args) };
|
|
472
|
-
}
|
|
473
|
-
return told.view;
|
|
474
|
-
};
|
|
475
|
-
const context = () => contexts.operation(scope, operationFacts(contract, request, view()));
|
|
476
|
-
const computeContext = () => contexts.compute(scope, operationFacts(contract, request, view()));
|
|
542
|
+
const context = () => contexts.operation(scope, operationFacts(contract, request, args));
|
|
543
|
+
const computeContext = () => contexts.compute(scope, operationFacts(contract, request, args));
|
|
477
544
|
const reuse = { refusal: undefined };
|
|
478
545
|
const refusedReuse = (refusal) => {
|
|
479
546
|
report(refusal, "A3000");
|
|
@@ -493,11 +560,52 @@ export async function executeAdmittedOperation(dependencies, request, contract,
|
|
|
493
560
|
async function runLifecycle() {
|
|
494
561
|
let computed = await applyWriteCompute(contracts, scopeConfig.compute, request, args, computeContext);
|
|
495
562
|
computed = await applyNestedWriteCompute(contracts, scopeConfig.compute, computed, nestedWriteTargetsOf(contract, dependencies.recordWrites.references, request, computed), (target, payload) => contexts.compute(scope, nestedFacts(contract, request, target, payload)));
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
|
|
563
|
+
const broken = createRequirementIssues(contract, dependencies.recordWrites, request, computed, argumentsPath);
|
|
564
|
+
const [firstBroken] = broken;
|
|
565
|
+
if (firstBroken !== undefined) {
|
|
566
|
+
const what = firstBroken.code === "V1000"
|
|
567
|
+
? "dropped a required field"
|
|
568
|
+
: "wrote a reference twice";
|
|
569
|
+
report(new AvPipeOutputError(`Pipes or write compute ${what} of ${request.resource}.${request.family}.${request.variant} at "${(firstBroken.path ?? []).join(".")}" (${firstBroken.code}: ${firstBroken.message})`, broken), "A3004");
|
|
570
|
+
return operationFailure("A3004", {
|
|
571
|
+
message: PIPE_OUTPUT_FAILURE_MESSAGE,
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
const unfilled = computedRequirementGapsOf(contract, dependencies.recordWrites, request, computed, argumentsPath, (resource) => createComputedFields(scopeConfig.compute, resource));
|
|
575
|
+
const [firstUnfilled] = unfilled;
|
|
576
|
+
if (firstUnfilled !== undefined) {
|
|
577
|
+
throw new AvComputedValueError(firstUnfilled.resource, firstUnfilled.field, "create", unfilled.map((gap) => gap.issue), `compute.create on ${firstUnfilled.resource}.${firstUnfilled.field} returned undefined for a required field`);
|
|
578
|
+
}
|
|
579
|
+
if (hasFieldValidators(contract)) {
|
|
580
|
+
const refused = fieldValidatorIssues(contract, dependencies.recordWrites.references, request, computed, argumentsPath, EVERY_FIELD);
|
|
581
|
+
if (refused.length > 0) {
|
|
582
|
+
return mapValidationOutcome(refused);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
const hiddenRefusal = hiddenFieldRefusal({ core: dependencies.contracts.core, active: contract }, dependencies.recordWrites.references, request, computed, argumentsPath);
|
|
586
|
+
if (hiddenRefusal !== undefined) {
|
|
587
|
+
throw hiddenRefusal;
|
|
499
588
|
}
|
|
500
589
|
args = deepFreeze(computed);
|
|
590
|
+
let policyWrite;
|
|
591
|
+
if (request.policy !== undefined && request.family !== "find") {
|
|
592
|
+
const planned = planReadOperation(dependencies.contracts.core, dependencies.config.adapter.model, contract, scopeConfig.compute, request, args);
|
|
593
|
+
const plannedArguments = await stripVirtualMutationInput(contracts, request, planned.arguments);
|
|
594
|
+
try {
|
|
595
|
+
policyWrite = await enforceWritePolicy(request.policy.on({ executor, boundary: adapterBoundary }), dependencies.contracts.core, dependencies.config.adapter.model, request, planned, plannedArguments, binding.kind === "transaction");
|
|
596
|
+
}
|
|
597
|
+
catch (error) {
|
|
598
|
+
return sanitizeOperationFailure(error, adapterBoundary.originOf(error), report, { path: argumentsPath, arguments: args });
|
|
599
|
+
}
|
|
600
|
+
if (policyWrite.kind === "refused") {
|
|
601
|
+
return policyWrite.response;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
let policyFailure;
|
|
605
|
+
const refuseWrite = (response) => {
|
|
606
|
+
policyFailure = response;
|
|
607
|
+
throw thrownFailure(response);
|
|
608
|
+
};
|
|
501
609
|
let readMaterialized = false;
|
|
502
610
|
let executedReadPlan;
|
|
503
611
|
const materialize = async (data, plan) => {
|
|
@@ -506,24 +614,87 @@ export async function executeAdmittedOperation(dependencies, request, contract,
|
|
|
506
614
|
return materializeReadOperation(contract, scopeConfig.compute, request, plan, data, computeContext);
|
|
507
615
|
};
|
|
508
616
|
const invoke = async () => {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
617
|
+
let readPlan = planReadOperation(dependencies.contracts.core, dependencies.config.adapter.model, contract, scopeConfig.compute, request, args);
|
|
618
|
+
let adapterArguments = await stripVirtualMutationInput(contracts, request, readPlan.arguments);
|
|
619
|
+
let operation = request;
|
|
620
|
+
let settle;
|
|
621
|
+
let writeMiss;
|
|
622
|
+
let failedWrite;
|
|
623
|
+
if (policyWrite !== undefined && policyWrite.kind !== "refused") {
|
|
624
|
+
writeMiss = policyWrite.miss;
|
|
625
|
+
failedWrite = policyWrite.failed;
|
|
626
|
+
if (policyWrite.kind === "empty") {
|
|
627
|
+
if (writeMiss !== undefined && policyWrite.data === null) {
|
|
628
|
+
refuseWrite(await writeMiss());
|
|
629
|
+
}
|
|
630
|
+
return materialize(policyWrite.data, readPlan);
|
|
631
|
+
}
|
|
632
|
+
operation = policyWrite.identity;
|
|
633
|
+
adapterArguments = policyWrite.arguments;
|
|
634
|
+
readPlan = policyWrite.plan;
|
|
635
|
+
settle = policyWrite.settle;
|
|
636
|
+
}
|
|
637
|
+
else if (request.policy !== undefined && request.family === "find") {
|
|
638
|
+
const read = await enforceReadPolicy(request.policy.on({ executor, boundary: adapterBoundary }), dependencies.contracts.core, dependencies.config.adapter.model, request, readPlan, adapterArguments);
|
|
639
|
+
if (read.kind === "refused") {
|
|
640
|
+
throw thrownFailure(read.response);
|
|
641
|
+
}
|
|
642
|
+
if (read.kind === "empty") {
|
|
643
|
+
const miss = uniqueMissFailure(request, read.data);
|
|
644
|
+
if (miss !== undefined) {
|
|
645
|
+
throw thrownFailure(miss);
|
|
646
|
+
}
|
|
647
|
+
return materialize(read.data, readPlan);
|
|
648
|
+
}
|
|
649
|
+
operation = read.identity;
|
|
650
|
+
adapterArguments = read.arguments;
|
|
651
|
+
readPlan = read.plan;
|
|
652
|
+
settle = read.settle;
|
|
653
|
+
}
|
|
654
|
+
const { policy: _session, ...identity } = operation;
|
|
655
|
+
let adapterData;
|
|
656
|
+
try {
|
|
657
|
+
adapterData = await adapterBoundary.execute(() => executor.execute({
|
|
658
|
+
...identity,
|
|
659
|
+
resource: request.resource,
|
|
660
|
+
arguments: adapterArguments,
|
|
661
|
+
}));
|
|
662
|
+
}
|
|
663
|
+
catch (error) {
|
|
664
|
+
const missed = failedWrite === undefined
|
|
665
|
+
? undefined
|
|
666
|
+
: await failedWrite(error).catch(() => undefined);
|
|
667
|
+
if (missed !== undefined) {
|
|
668
|
+
refuseWrite(missed);
|
|
669
|
+
}
|
|
670
|
+
throw error;
|
|
671
|
+
}
|
|
672
|
+
if (writeMiss !== undefined && adapterData === null) {
|
|
673
|
+
refuseWrite(await writeMiss());
|
|
674
|
+
}
|
|
517
675
|
const miss = uniqueMissFailure(request, adapterData);
|
|
518
676
|
if (miss !== undefined) {
|
|
519
677
|
throw thrownFailure(miss);
|
|
520
678
|
}
|
|
679
|
+
if (settle !== undefined) {
|
|
680
|
+
const settled = await settle(adapterData);
|
|
681
|
+
if (!settled.ok) {
|
|
682
|
+
if (policyWrite !== undefined) {
|
|
683
|
+
refuseWrite(settled.response);
|
|
684
|
+
}
|
|
685
|
+
throw thrownFailure(settled.response);
|
|
686
|
+
}
|
|
687
|
+
adapterData = settled.data;
|
|
688
|
+
}
|
|
521
689
|
return materialize(adapterData, readPlan);
|
|
522
690
|
};
|
|
523
691
|
const materialized = async (data) => readMaterialized
|
|
524
692
|
? data
|
|
525
693
|
: materialize(data, planReadOperation(dependencies.contracts.core, dependencies.config.adapter.model, contract, scopeConfig.compute, request, args));
|
|
526
694
|
const data = await materialized(await runLevelLifecycle(levels, context, invoke, materialized, reuse, () => new AvInterceptorNextError()));
|
|
695
|
+
if (policyFailure !== undefined) {
|
|
696
|
+
return policyFailure;
|
|
697
|
+
}
|
|
527
698
|
if (!outputAccepted(contract, request, executedReadPlan?.projection, data, report)) {
|
|
528
699
|
return internalFailure();
|
|
529
700
|
}
|