@aventara/core 1.0.0-rc.0 → 1.0.0-rc.10
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 +2068 -1
- package/ERRORS.md +142 -0
- package/README.md +485 -60
- package/dist/adapters/adapter-discovery-diagnostic.d.ts +4 -4
- 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 +33 -11
- package/dist/adapters/adapter-identifier.d.ts +15 -6
- package/dist/adapters/adapter-identifier.js +6 -1
- package/dist/adapters/adapter-model.d.ts +18 -9
- package/dist/adapters/adapter-operation-executor.interface.d.ts +4 -4
- package/dist/adapters/adapter-operation.d.ts +21 -6
- package/dist/adapters/adapter-resource.d.ts +23 -9
- package/dist/adapters/adapter-sql-statement.d.ts +19 -0
- package/dist/adapters/adapter-transaction-executor.interface.d.ts +19 -0
- package/dist/adapters/adapter.interface.d.ts +59 -29
- package/dist/avz/avz-check.factory.d.ts +83 -0
- package/dist/avz/avz-check.factory.js +116 -0
- package/dist/avz/avz-check.registry.d.ts +35 -0
- package/dist/avz/avz-check.registry.js +9 -0
- package/dist/avz/avz.d.ts +203 -0
- package/dist/{json → avz}/avz.js +150 -8
- package/dist/{json → avz}/index.d.ts +2 -1
- package/dist/{json → avz}/json-shape.registry.d.ts +9 -8
- package/dist/{json → avz}/zod-issue.translator.d.ts +8 -2
- package/dist/{json → avz}/zod-issue.translator.js +7 -0
- package/dist/compiler/contract-compiler-diagnostic.d.ts +31 -5
- 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 +23 -17
- package/dist/compiler/contract.compiler.js +753 -443
- package/dist/compiler/create-requirements.projector.d.ts +49 -0
- package/dist/compiler/create-requirements.projector.js +423 -0
- package/dist/compiler/field-validator.compiler.d.ts +47 -0
- package/dist/compiler/field-validator.compiler.js +238 -0
- 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/any-framework-config.d.ts +19 -12
- package/dist/config/computed-fields.d.ts +62 -0
- package/dist/config/computed-fields.js +73 -0
- package/dist/config/config-diagnostic.d.ts +11 -4
- package/dist/config/config-diagnostic.guidance.d.ts +6 -0
- package/dist/config/config-diagnostic.guidance.js +32 -0
- package/dist/config/config-layer.d.ts +15 -6
- package/dist/config/config.resolver.d.ts +98 -31
- package/dist/config/config.resolver.js +173 -44
- package/dist/config/config.validator.d.ts +7 -7
- package/dist/config/config.validator.js +792 -69
- package/dist/config/define-resource.d.ts +53 -0
- package/dist/config/define-resource.js +14 -0
- package/dist/config/effective-fields.d.ts +19 -23
- package/dist/config/entrypoint.normalizer.d.ts +4 -3
- package/dist/config/exact-framework-config.d.ts +325 -0
- package/dist/config/field-compute.resolver.d.ts +21 -0
- package/dist/config/field-compute.resolver.js +123 -0
- package/dist/config/field-pipeline-config.d.ts +47 -0
- package/dist/config/forced-operation.validator.d.ts +10 -0
- package/dist/config/forced-operation.validator.js +66 -0
- package/dist/config/framework-config.d.ts +148 -39
- package/dist/config/framework-exemptions-config.d.ts +91 -0
- package/dist/config/framework-exemptions-config.js +1 -0
- package/dist/config/framework-field-definition.d.ts +78 -0
- package/dist/config/framework-field-definition.js +28 -0
- package/dist/config/framework-resources-config.d.ts +127 -0
- package/dist/config/framework-resources-config.js +1 -0
- package/dist/config/pipeline-config.d.ts +56 -20
- package/dist/config/pipeline-tree.resolver.d.ts +79 -0
- package/dist/config/pipeline-tree.resolver.js +220 -0
- package/dist/config/stage-type.eraser.d.ts +65 -0
- package/dist/config/stage-type.eraser.js +1 -0
- package/dist/contracts/access-route.rules.d.ts +10 -0
- package/dist/contracts/access-route.rules.js +45 -0
- package/dist/contracts/capability.d.ts +37 -12
- package/dist/contracts/capability.js +20 -0
- package/dist/contracts/client-contract-structure.validator.d.ts +621 -114
- package/dist/contracts/client-contract-structure.validator.js +189 -10
- package/dist/contracts/contract-access.d.ts +29 -0
- package/dist/contracts/contract-access.js +1 -0
- package/dist/contracts/contract-canonicalizer.d.ts +27 -3
- package/dist/contracts/contract-canonicalizer.js +168 -29
- package/dist/contracts/contract-hash.d.ts +11 -7
- package/dist/contracts/contract-hash.js +4 -3
- package/dist/contracts/contract-limits.d.ts +4 -1
- package/dist/contracts/contract-limits.js +1 -0
- package/dist/contracts/contract-lookup.d.ts +5 -5
- package/dist/contracts/contract-protocol.d.ts +4 -4
- package/dist/contracts/contract.d.ts +51 -17
- package/dist/contracts/create-requirements.d.ts +35 -0
- package/dist/contracts/create-requirements.js +1 -0
- package/dist/contracts/enum-definition.d.ts +1 -1
- package/dist/contracts/field-check.d.ts +101 -0
- package/dist/contracts/field-check.js +1 -0
- package/dist/contracts/field.d.ts +109 -42
- package/dist/contracts/identifier.d.ts +4 -4
- package/dist/contracts/json-schema.projector.d.ts +11 -0
- package/dist/contracts/json-schema.projector.js +78 -0
- package/dist/contracts/json-shape.d.ts +12 -1
- package/dist/contracts/lifecycle-trait.d.ts +2 -2
- package/dist/contracts/resource-operations.d.ts +28 -28
- package/dist/contracts/resource.d.ts +15 -9
- package/dist/contracts/scalar-value-type.d.ts +17 -15
- package/dist/contracts/scalar.d.ts +3 -3
- package/dist/contracts/transaction-capability.d.ts +1 -1
- package/dist/contracts/wire-scalar-format.d.ts +4 -4
- package/dist/framework/access-facade.d.ts +116 -0
- package/dist/framework/access-facade.js +120 -0
- package/dist/framework/contract-view.d.ts +315 -145
- package/dist/framework/framework-construction.error.d.ts +21 -11
- package/dist/framework/framework-construction.error.js +20 -4
- package/dist/framework/framework.d.ts +71 -26
- package/dist/framework/framework.factory.d.ts +8 -6
- package/dist/framework/framework.factory.js +150 -38
- package/dist/framework/operation-facade.d.ts +192 -54
- package/dist/framework/operation-facade.js +10 -1
- package/dist/index.d.ts +67 -50
- package/dist/index.js +7 -6
- package/dist/internal.d.ts +20 -10
- package/dist/internal.js +9 -1
- package/dist/operations/database-refusal.d.ts +51 -0
- package/dist/operations/database-refusal.js +45 -0
- package/dist/operations/operation-arguments.d.ts +381 -228
- package/dist/operations/operation-call.d.ts +31 -28
- package/dist/operations/operation-identity.d.ts +10 -10
- package/dist/operations/operation-result.d.ts +25 -23
- package/dist/operations/operation-validator-core.d.ts +6 -6
- package/dist/operations/operation-validator-core.js +172 -38
- package/dist/operations/operation-validator.d.ts +10 -10
- package/dist/operations/projection-scope.resolver.d.ts +6 -6
- package/dist/operations/structural-limits.walker.d.ts +7 -7
- package/dist/operations/structural-limits.walker.js +145 -0
- package/dist/operations/validation-code.d.ts +11 -6
- package/dist/operations/validation-code.guidance.d.ts +6 -0
- package/dist/operations/validation-code.guidance.js +90 -0
- package/dist/operations/validation-code.js +4 -0
- package/dist/operations/write-scope.resolver.d.ts +10 -6
- 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 +297 -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 +409 -0
- package/dist/policy/policy-after-update.runtime.d.ts +79 -0
- package/dist/policy/policy-after-update.runtime.js +208 -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 +545 -0
- package/dist/policy/policy-read.runtime.d.ts +81 -0
- package/dist/policy/policy-read.runtime.js +503 -0
- package/dist/policy/policy-reference-write.runtime.d.ts +51 -0
- package/dist/policy/policy-reference-write.runtime.js +345 -0
- package/dist/policy/policy-request.d.ts +41 -0
- package/dist/policy/policy-request.js +63 -0
- package/dist/policy/policy-session.d.ts +106 -0
- package/dist/policy/policy-session.js +295 -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 +532 -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 +65 -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 +77 -0
- package/dist/prebuilt/prebuilt-inputs.fingerprint.d.ts +16 -0
- package/dist/prebuilt/prebuilt-inputs.fingerprint.js +229 -0
- package/dist/protocol/absent-route.responder.d.ts +17 -34
- package/dist/protocol/absent-route.responder.js +53 -20
- package/dist/protocol/contract-document.responder.d.ts +5 -4
- package/dist/protocol/contract-document.responder.js +2 -2
- package/dist/protocol/http-request.decoder.d.ts +33 -13
- package/dist/protocol/http-request.decoder.js +34 -11
- package/dist/protocol/http-request.reader.d.ts +9 -6
- package/dist/protocol/http-request.reader.js +1 -0
- package/dist/protocol/http-response.encoder.d.ts +4 -4
- package/dist/protocol/http-response.encoder.js +94 -55
- package/dist/protocol/http-status.table.d.ts +2 -2
- package/dist/protocol/operation-response.guard.d.ts +2 -2
- package/dist/protocol/protocol-headers.d.ts +3 -3
- package/dist/protocol/protocol-surface.d.ts +10 -5
- package/dist/protocol/protocol-surface.js +7 -0
- package/dist/protocol/protocol.binder.d.ts +66 -28
- package/dist/protocol/protocol.binder.js +16 -10
- package/dist/protocol/protocol.handler.d.ts +34 -14
- package/dist/protocol/protocol.handler.js +122 -18
- package/dist/protocol/unmounted-route.error.d.ts +4 -4
- package/dist/protocol/unmounted-route.error.js +2 -2
- package/dist/runtime/caller-data.copier.d.ts +22 -7
- package/dist/runtime/caller-data.copier.js +30 -17
- package/dist/runtime/caller-data.door.d.ts +18 -11
- package/dist/runtime/caller-data.door.js +6 -4
- package/dist/runtime/computed-read-runtime.d.ts +12 -6
- package/dist/runtime/computed-read-runtime.js +271 -71
- package/dist/runtime/computed-value.error.d.ts +7 -6
- package/dist/runtime/computed-value.error.js +5 -4
- package/dist/runtime/context-executor.runtime.d.ts +60 -0
- package/dist/runtime/context-executor.runtime.js +277 -0
- 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 +34 -79
- package/dist/runtime/create-requirement.js +205 -74
- package/dist/runtime/decimal.d.ts +16 -2
- package/dist/runtime/decimal.js +22 -1
- package/dist/runtime/diagnostics-reporter.d.ts +91 -30
- package/dist/runtime/diagnostics-reporter.js +37 -1
- package/dist/runtime/error-boundary.d.ts +73 -9
- package/dist/runtime/error-boundary.js +57 -19
- 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 +18 -2
- package/dist/runtime/field-check.evaluator.d.ts +27 -0
- package/dist/runtime/field-check.evaluator.js +521 -0
- package/dist/runtime/field-compute.d.ts +65 -0
- package/dist/runtime/field-compute.js +1 -0
- package/dist/runtime/field-stage.plan.d.ts +15 -0
- package/dist/runtime/field-stage.plan.js +27 -0
- package/dist/runtime/field-stage.runtime.d.ts +37 -0
- package/dist/runtime/field-stage.runtime.js +147 -0
- package/dist/runtime/field-validator.runtime.d.ts +29 -0
- package/dist/runtime/field-validator.runtime.js +126 -0
- package/dist/runtime/framework-error-class.table.d.ts +33 -0
- package/dist/runtime/framework-error-class.table.js +25 -0
- package/dist/runtime/framework-error.d.ts +68 -8
- package/dist/runtime/framework-error.factory.d.ts +4 -0
- package/dist/runtime/framework-error.factory.js +15 -0
- package/dist/runtime/framework-error.js +32 -2
- package/dist/runtime/framework-warning.emitter.d.ts +6 -0
- package/dist/runtime/framework-warning.emitter.js +8 -0
- package/dist/runtime/interceptor-next.error.d.ts +5 -0
- package/dist/runtime/interceptor-next.error.js +6 -0
- package/dist/runtime/json-value.d.ts +11 -6
- package/dist/runtime/level-lifecycle.runtime.d.ts +26 -0
- package/dist/runtime/level-lifecycle.runtime.js +40 -0
- package/dist/runtime/misuse-reporter.d.ts +12 -12
- package/dist/runtime/mutation-planner.d.ts +20 -16
- package/dist/runtime/mutation-planner.js +48 -35
- package/dist/runtime/nested-write.walker.d.ts +32 -0
- package/dist/runtime/nested-write.walker.js +73 -0
- 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 +45 -11
- package/dist/runtime/operation-response.d.ts +17 -17
- package/dist/runtime/operation-runtime.d.ts +133 -27
- package/dist/runtime/operation-runtime.js +576 -84
- package/dist/runtime/outcome-mapper.d.ts +17 -5
- package/dist/runtime/outcome-mapper.js +23 -6
- package/dist/runtime/output-validator.d.ts +11 -11
- package/dist/runtime/output-validator.js +3 -3
- package/dist/runtime/owned-execution.registry.d.ts +16 -6
- package/dist/runtime/pipe-output.validator.d.ts +43 -18
- package/dist/runtime/pipe-output.validator.js +15 -13
- package/dist/runtime/pipeline.d.ts +221 -34
- package/dist/runtime/readonly-value.d.ts +47 -0
- package/dist/runtime/readonly-value.js +189 -0
- package/dist/runtime/referential-action.d.ts +1 -1
- package/dist/runtime/request-envelope.validator.d.ts +3 -3
- package/dist/runtime/request-envelope.validator.js +12 -7
- package/dist/runtime/request-id.d.ts +1 -1
- package/dist/runtime/request-state.d.ts +14 -0
- package/dist/runtime/request-state.js +1 -0
- package/dist/runtime/request-state.resolver.d.ts +12 -0
- package/dist/runtime/request-state.resolver.js +20 -0
- package/dist/runtime/scalar-runtime.d.ts +33 -25
- package/dist/runtime/scalar-runtime.js +105 -38
- package/dist/runtime/unsent-value.normalizer.d.ts +15 -0
- package/dist/runtime/unsent-value.normalizer.js +128 -0
- package/dist/transactions/deferred-operation.d.ts +35 -20
- package/dist/transactions/operation-arguments-encoder.d.ts +3 -3
- package/dist/transactions/operation-arguments-encoder.js +8 -3
- package/dist/transactions/operation-fingerprint.js +2 -2
- package/dist/transactions/sql-statement.d.ts +85 -0
- package/dist/transactions/sql-statement.js +47 -0
- package/dist/transactions/sql-statement.validator.d.ts +44 -0
- package/dist/transactions/sql-statement.validator.js +167 -0
- package/dist/transactions/transaction-envelope.d.ts +9 -8
- package/dist/transactions/transaction-integrity-error.d.ts +6 -6
- package/dist/transactions/transaction-integrity-error.js +7 -2
- package/dist/transactions/transaction-plan-assembler.d.ts +30 -13
- package/dist/transactions/transaction-plan-assembler.js +184 -32
- package/dist/transactions/transaction-plan-validator.d.ts +50 -25
- package/dist/transactions/transaction-plan-validator.js +96 -38
- package/dist/transactions/transaction-reference-collector.d.ts +5 -5
- package/dist/transactions/transaction-reference-resolver.d.ts +21 -3
- package/dist/transactions/transaction-reference-resolver.js +26 -14
- package/dist/transactions/transaction-reference-validator.d.ts +74 -4
- package/dist/transactions/transaction-reference-validator.js +129 -71
- package/dist/transactions/transaction-reference.d.ts +14 -14
- package/dist/transactions/transaction-reference.js +5 -0
- package/dist/transactions/transaction-request.d.ts +22 -9
- package/dist/transactions/transaction-response.d.ts +6 -6
- package/dist/transactions/transaction-runtime.d.ts +12 -8
- package/dist/transactions/transaction-runtime.js +218 -50
- package/dist/transactions/transaction-settlement.runtime.d.ts +52 -0
- package/dist/transactions/transaction-settlement.runtime.js +120 -0
- package/dist/transactions/transaction-slot-path-error.d.ts +4 -4
- package/dist/transactions/transaction-slot-path-error.js +4 -2
- package/dist/transactions/transaction-slot-writer.js +2 -2
- package/dist/transactions/transaction-stage.runtime.d.ts +83 -0
- package/dist/transactions/transaction-stage.runtime.js +126 -0
- package/package.json +11 -9
- package/src/runtime/field-check.evaluator.ts +720 -0
- package/dist/config/define-fields.d.ts +0 -42
- package/dist/config/define-fields.js +0 -3
- package/dist/config/framework-behaviors-config.d.ts +0 -30
- package/dist/config/framework-fields-config.d.ts +0 -42
- package/dist/config/framework-restrictions-config.d.ts +0 -142
- package/dist/json/avz.d.ts +0 -96
- package/dist/runtime/field-behavior.d.ts +0 -48
- /package/dist/{config/framework-behaviors-config.js → adapters/adapter-sql-statement.js} +0 -0
- /package/dist/{config/framework-fields-config.js → adapters/adapter-transaction-executor.interface.js} +0 -0
- /package/dist/{json → avz}/index.js +0 -0
- /package/dist/{json → avz}/json-shape.registry.js +0 -0
- /package/dist/config/{framework-restrictions-config.js → exact-framework-config.js} +0 -0
- /package/dist/{runtime/field-behavior.js → config/field-pipeline-config.js} +0 -0
|
@@ -1,38 +1,173 @@
|
|
|
1
|
+
import { hasFieldValidators } from "../compiler/field-validator.compiler.js";
|
|
2
|
+
import { createComputedFields } from "../config/field-compute.resolver.js";
|
|
3
|
+
import { fieldStagesOf, isForcedOperation, nestedTargetLevels, operationLevels, rawPipelineTree, transactionLevelsOf, } from "../config/pipeline-tree.resolver.js";
|
|
1
4
|
import { AVENTARA_PROTOCOL_VERSION } from "../contracts/contract-protocol.js";
|
|
2
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";
|
|
9
|
+
import { transactionInfrastructureFailure } from "../transactions/transaction-response.js";
|
|
10
|
+
import { settleTransaction } from "../transactions/transaction-settlement.runtime.js";
|
|
11
|
+
import { TRANSACTION_PIPES, transactionFacts, } from "../transactions/transaction-stage.runtime.js";
|
|
3
12
|
import { copyAtDoor, misuseIdentityOf, refuseCallerData, } from "./caller-data.door.js";
|
|
4
13
|
import { materializeReadOperation, planReadOperation, } from "./computed-read-runtime.js";
|
|
5
|
-
import {
|
|
14
|
+
import { AvComputedValueError } from "./computed-value.error.js";
|
|
15
|
+
import { createContextExecutor, } from "./context-executor.runtime.js";
|
|
16
|
+
import { computedRequirementGapsOf, createRequirementIssues, recordWriteFactsOf, } from "./create-requirement.js";
|
|
17
|
+
import { createDiagnosticsReporter, } from "./diagnostics-reporter.js";
|
|
6
18
|
import { AdapterBoundary, OPERATION_ARGUMENTS_PATH, resolveOperationFailure, sanitizeOperationFailure, } from "./error-boundary.js";
|
|
19
|
+
import { planFieldStages } from "./field-stage.plan.js";
|
|
20
|
+
import { guardSentFields, pipeSentFields, valueAt, writeRecordPathsOf, } from "./field-stage.runtime.js";
|
|
21
|
+
import { fieldValidatorIssues, hiddenFieldRefusal, } from "./field-validator.runtime.js";
|
|
22
|
+
import { thrownFailure } from "./framework-error.factory.js";
|
|
23
|
+
import { AvInterceptorNextError } from "./interceptor-next.error.js";
|
|
24
|
+
import { runLevelLifecycle, } from "./level-lifecycle.runtime.js";
|
|
7
25
|
import { createMisuseReporter, } from "./misuse-reporter.js";
|
|
8
|
-
import {
|
|
26
|
+
import { applyNestedWriteCompute, applyWriteCompute, stripVirtualMutationInput, } from "./mutation-planner.js";
|
|
27
|
+
import { nestedWriteTargetsOf, } from "./nested-write.walker.js";
|
|
9
28
|
import { internalFailure, operationFailure } from "./operation-response.js";
|
|
10
|
-
import { mapOperationOutcome, mapValidationOutcome } from "./outcome-mapper.js";
|
|
11
|
-
import {
|
|
12
|
-
import { refusePipeOutput } from "./pipe-output.validator.js";
|
|
29
|
+
import { mapOperationOutcome, mapValidationOutcome, uniqueMissFailure, } from "./outcome-mapper.js";
|
|
30
|
+
import { AvOutputValidationError, validateOperationOutput, } from "./output-validator.js";
|
|
31
|
+
import { AvPipeOutputError, PIPE_OUTPUT_FAILURE_MESSAGE, refusePipeOutput, refuseStageOutput, } from "./pipe-output.validator.js";
|
|
32
|
+
import { deepFreeze, frozenCopy } from "./readonly-value.js";
|
|
33
|
+
import { requestStateOf } from "./request-state.resolver.js";
|
|
13
34
|
import { normalizeOperationScalarValues, } from "./scalar-runtime.js";
|
|
35
|
+
import { withoutUnsentWriteValues } from "./unsent-value.normalizer.js";
|
|
36
|
+
function scopeOf(request, binding) {
|
|
37
|
+
return {
|
|
38
|
+
requestId: request.requestId,
|
|
39
|
+
transaction: binding?.kind === "transaction" ? binding.executor : undefined,
|
|
40
|
+
state: request.state,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export function withRequestState(request) {
|
|
44
|
+
return { ...request, state: requestStateOf(request.state) };
|
|
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
|
+
}
|
|
62
|
+
export function createPipelineDependencies(dependencies, model) {
|
|
63
|
+
const misuse = createMisuseReporter(dependencies.config.misuse);
|
|
64
|
+
const recordWrites = recordWriteFactsOf({
|
|
65
|
+
...(dependencies.adapter.referentialActions === undefined
|
|
66
|
+
? {}
|
|
67
|
+
: { referentialActions: dependencies.adapter.referentialActions }),
|
|
68
|
+
model,
|
|
69
|
+
});
|
|
70
|
+
const contexts = createContextExecutor({
|
|
71
|
+
model,
|
|
72
|
+
adapter: dependencies.adapter,
|
|
73
|
+
application: dependencies.contracts.application,
|
|
74
|
+
diagnostics: dependencies.config.diagnostics,
|
|
75
|
+
misuse,
|
|
76
|
+
run: (request, transaction) => executeContextCall(raw, dependencies, request, transaction, misuse),
|
|
77
|
+
});
|
|
78
|
+
const { contracts, config } = dependencies;
|
|
79
|
+
const pipeline = {
|
|
80
|
+
contracts,
|
|
81
|
+
config,
|
|
82
|
+
recordWrites,
|
|
83
|
+
contexts,
|
|
84
|
+
fieldStages: {
|
|
85
|
+
application: planFieldStages(config.application.pipelines, contracts.application),
|
|
86
|
+
client: planFieldStages(config.client.pipelines, contracts.client),
|
|
87
|
+
agent: planFieldStages(config.agent.pipelines, contracts.agent),
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
const rawTree = rawPipelineTree(config.application.pipelines);
|
|
91
|
+
const raw = {
|
|
92
|
+
...pipeline,
|
|
93
|
+
config: {
|
|
94
|
+
...config,
|
|
95
|
+
application: { ...config.application, pipelines: rawTree },
|
|
96
|
+
},
|
|
97
|
+
fieldStages: {
|
|
98
|
+
...pipeline.fieldStages,
|
|
99
|
+
application: planFieldStages(rawTree, contracts.application),
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
return pipeline;
|
|
103
|
+
}
|
|
104
|
+
async function executeContextCall(raw, dependencies, request, transaction, misuse) {
|
|
105
|
+
const report = createDiagnosticsReporter(dependencies.config.diagnostics, request);
|
|
106
|
+
try {
|
|
107
|
+
let validated;
|
|
108
|
+
try {
|
|
109
|
+
validated = validateOperation(dependencies, request, "caller", misuse);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
return sanitizeOperationFailure(error, "runtime", report, {
|
|
113
|
+
path: OPERATION_ARGUMENTS_PATH,
|
|
114
|
+
arguments: request.arguments,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
if (!validated.ok) {
|
|
118
|
+
return validated.response;
|
|
119
|
+
}
|
|
120
|
+
const stateful = withRequestState(request);
|
|
121
|
+
const admitted = await admitOperation(raw, stateful, validated.contract, validated.arguments, OPERATION_ARGUMENTS_PATH, report, {
|
|
122
|
+
requestId: request.requestId,
|
|
123
|
+
transaction,
|
|
124
|
+
state: stateful.state,
|
|
125
|
+
});
|
|
126
|
+
if (!admitted.ok) {
|
|
127
|
+
return admitted.response;
|
|
128
|
+
}
|
|
129
|
+
return await executeAdmittedOperation(raw, stateful, validated.contract, admitted.args, OPERATION_ARGUMENTS_PATH, transaction === undefined
|
|
130
|
+
? { kind: "standalone", executor: dependencies.adapter }
|
|
131
|
+
: { kind: "transaction", executor: transaction }, report);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
report(error, "A3000");
|
|
135
|
+
return internalFailure();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
14
138
|
export function activeContract(contracts, request) {
|
|
15
|
-
return request.origin
|
|
16
|
-
? contracts.application
|
|
17
|
-
: contracts.client;
|
|
139
|
+
return contracts[request.origin];
|
|
18
140
|
}
|
|
19
141
|
function activeScopeConfig(config, request) {
|
|
20
|
-
return request.origin
|
|
142
|
+
return config[request.origin];
|
|
21
143
|
}
|
|
22
|
-
function
|
|
144
|
+
function operationFacts(contract, request, args) {
|
|
23
145
|
return {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
args,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
146
|
+
$operation: {
|
|
147
|
+
resource: request.resource,
|
|
148
|
+
family: request.family,
|
|
149
|
+
variant: request.variant,
|
|
150
|
+
},
|
|
151
|
+
$args: frozenCopy(args),
|
|
152
|
+
$origin: request.origin,
|
|
153
|
+
$requestId: request.requestId,
|
|
154
|
+
$contract: contract,
|
|
155
|
+
...(request.origin !== "application" && request.transport !== undefined
|
|
156
|
+
? { $transport: request.transport }
|
|
33
157
|
: {}),
|
|
34
158
|
};
|
|
35
159
|
}
|
|
160
|
+
function nestedFacts(contract, request, target, payload) {
|
|
161
|
+
return {
|
|
162
|
+
...operationFacts(contract, request, payload),
|
|
163
|
+
$operation: {
|
|
164
|
+
resource: target.resource,
|
|
165
|
+
family: target.family,
|
|
166
|
+
variant: "one",
|
|
167
|
+
nested: true,
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
36
171
|
function forbidden() {
|
|
37
172
|
return operationFailure("A4001", {
|
|
38
173
|
message: "Operation denied by a framework guard.",
|
|
@@ -48,18 +183,13 @@ function outputAccepted(contract, request, projection, data, report) {
|
|
|
48
183
|
return false;
|
|
49
184
|
}
|
|
50
185
|
if (!validation.ok) {
|
|
51
|
-
report(new
|
|
186
|
+
report(new AvOutputValidationError(request, validation.issues), "A3000");
|
|
52
187
|
}
|
|
53
188
|
return validation.ok;
|
|
54
189
|
}
|
|
55
|
-
export function createOperationRuntime(dependencies) {
|
|
56
|
-
const pipelineDependencies = {
|
|
57
|
-
contracts: dependencies.contracts,
|
|
58
|
-
config: dependencies.config,
|
|
59
|
-
recordWrites: recordWriteFactsOf(dependencies.adapter),
|
|
60
|
-
};
|
|
190
|
+
export function createOperationRuntime(dependencies, pipelineDependencies) {
|
|
61
191
|
const misuse = createMisuseReporter(dependencies.config.misuse);
|
|
62
|
-
return async (request, report, source) => {
|
|
192
|
+
return async (request, report, source, caller) => {
|
|
63
193
|
let validated;
|
|
64
194
|
try {
|
|
65
195
|
validated = validateOperation(dependencies, request, source, misuse);
|
|
@@ -73,7 +203,36 @@ export function createOperationRuntime(dependencies) {
|
|
|
73
203
|
if (!validated.ok) {
|
|
74
204
|
return validated.response;
|
|
75
205
|
}
|
|
76
|
-
|
|
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);
|
|
212
|
+
const admitted = await admitOperation(pipelineDependencies, stateful, validated.contract, validated.arguments, OPERATION_ARGUMENTS_PATH, report, {
|
|
213
|
+
requestId: request.requestId,
|
|
214
|
+
transaction: undefined,
|
|
215
|
+
state: stateful.state,
|
|
216
|
+
}, forced ? FORCED_CALL : SINGLE_CALL);
|
|
217
|
+
if (!admitted.ok) {
|
|
218
|
+
return admitted.response;
|
|
219
|
+
}
|
|
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);
|
|
234
|
+
}
|
|
235
|
+
return executeAdmittedOperation(pipelineDependencies, stateful, validated.contract, admitted.args, OPERATION_ARGUMENTS_PATH, { kind: "standalone", executor: dependencies.adapter }, report);
|
|
77
236
|
};
|
|
78
237
|
}
|
|
79
238
|
function validateOperation(dependencies, request, source, misuse) {
|
|
@@ -83,9 +242,11 @@ function validateOperation(dependencies, request, source, misuse) {
|
|
|
83
242
|
}
|
|
84
243
|
const contract = activeContract(dependencies.contracts, request);
|
|
85
244
|
let owned = request;
|
|
86
|
-
if (source
|
|
245
|
+
if (source !== "owned" &&
|
|
87
246
|
findOperationAvailabilityIssue(contract, request) === undefined) {
|
|
88
|
-
const copy =
|
|
247
|
+
const copy = source === "caller"
|
|
248
|
+
? copyAtDoor(request.arguments)
|
|
249
|
+
: { ok: false, error: source.refused };
|
|
89
250
|
if (!copy.ok) {
|
|
90
251
|
return rejected(mapValidationOutcome([
|
|
91
252
|
refuseCallerData(copy.error, OPERATION_ARGUMENTS_PATH, misuseIdentityOf(request), misuse),
|
|
@@ -100,24 +261,32 @@ function validateOperation(dependencies, request, source, misuse) {
|
|
|
100
261
|
return { ok: true, contract, arguments: validation.arguments };
|
|
101
262
|
}
|
|
102
263
|
export function validateProtocolIdentity(contracts, request) {
|
|
103
|
-
return request.origin === "
|
|
104
|
-
?
|
|
105
|
-
:
|
|
264
|
+
return request.origin === "application"
|
|
265
|
+
? undefined
|
|
266
|
+
: protocolIdentityFailure(contracts, request.protocol, request.origin);
|
|
106
267
|
}
|
|
107
|
-
export function protocolIdentityFailure(contracts, protocol) {
|
|
268
|
+
export function protocolIdentityFailure(contracts, protocol, origin) {
|
|
108
269
|
if (protocol.version !== AVENTARA_PROTOCOL_VERSION) {
|
|
109
270
|
return operationFailure("A2006", {
|
|
110
271
|
message: "Aventara protocol version does not match the server.",
|
|
111
272
|
});
|
|
112
273
|
}
|
|
113
|
-
if (protocol.hash !== contracts.
|
|
274
|
+
if (protocol.hash !== contracts[origin].protocol.hash) {
|
|
114
275
|
return operationFailure("A2005", {
|
|
115
|
-
message:
|
|
276
|
+
message: origin === "client"
|
|
277
|
+
? "Generated client contract does not match the server. Regenerate the client."
|
|
278
|
+
: "Agent contract does not match the server. Rebuild the agent's tools from the current Agent Contract.",
|
|
116
279
|
});
|
|
117
280
|
}
|
|
118
281
|
return undefined;
|
|
119
282
|
}
|
|
120
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
|
+
}
|
|
121
290
|
const validation = validateOperationArguments(contract, request, options);
|
|
122
291
|
if (!validation.ok) {
|
|
123
292
|
return { ok: false, response: mapValidationOutcome(validation.issues) };
|
|
@@ -133,75 +302,398 @@ export function validateOperationRequest(contract, request, options, write = "co
|
|
|
133
302
|
function rejected(response) {
|
|
134
303
|
return { ok: false, response };
|
|
135
304
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
305
|
+
const FIELD_PIPES = "Field pipes";
|
|
306
|
+
export const STEP_PIPES = "Pipes";
|
|
307
|
+
export const EVERY_FIELD = () => true;
|
|
308
|
+
function filtersOf(levels) {
|
|
309
|
+
return levels.flatMap((level) => level.filters);
|
|
310
|
+
}
|
|
311
|
+
const SINGLE_CALL = { select: EVERY_FIELD };
|
|
312
|
+
const FORCED_CALL = { select: EVERY_FIELD, beforeBegin: true };
|
|
313
|
+
export async function admitOperation(dependencies, request, contract, args, argumentsPath, report, scope, admission = SINGLE_CALL) {
|
|
314
|
+
const contexts = dependencies.contexts;
|
|
315
|
+
const tree = activeScopeConfig(dependencies.config, request).pipelines;
|
|
316
|
+
const levels = operationLevels(tree, request);
|
|
317
|
+
const planned = dependencies.fieldStages[request.origin];
|
|
318
|
+
const guarded = planned.guarded(request.resource);
|
|
319
|
+
const contracts = { core: dependencies.contracts.core, active: contract };
|
|
320
|
+
let current = deepFreeze(args);
|
|
321
|
+
const context = () => contexts.operation(scope, operationFacts(contract, request, current));
|
|
322
|
+
const admit = async () => {
|
|
323
|
+
for (const level of levels) {
|
|
324
|
+
for (const guard of level.guards) {
|
|
325
|
+
if ((await guard(context())) === false) {
|
|
326
|
+
return { ok: false, response: forbidden() };
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
if (guarded.length > 0 &&
|
|
331
|
+
!(await guardSentFields(fieldStagesOf(tree, request.resource), guarded, writeRecordPathsOf(request.family, current), current, context))) {
|
|
332
|
+
return { ok: false, response: forbidden() };
|
|
333
|
+
}
|
|
334
|
+
for (const target of planned.nestedGuards
|
|
335
|
+
? nestedWriteTargetsOf(contract, dependencies.recordWrites.references, request, current)
|
|
336
|
+
: []) {
|
|
337
|
+
const told = () => contexts.operation(scope, nestedFacts(contract, request, target, valueAt(current, target.path)));
|
|
338
|
+
for (const level of nestedTargetLevels(tree, target.resource, target.family)) {
|
|
339
|
+
for (const guard of level.guards) {
|
|
340
|
+
if ((await guard(told())) === false) {
|
|
341
|
+
return { ok: false, response: forbidden() };
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
const targetGuarded = planned.guarded(target.resource);
|
|
346
|
+
if (targetGuarded.length > 0 &&
|
|
347
|
+
!(await guardSentFields(fieldStagesOf(tree, target.resource), targetGuarded, target.records.map((site) => site.path), current, told))) {
|
|
348
|
+
return { ok: false, response: forbidden() };
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
let piped = false;
|
|
352
|
+
let pipeIndex = 0;
|
|
353
|
+
for (const level of levels) {
|
|
354
|
+
for (const pipe of level.pipes) {
|
|
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);
|
|
359
|
+
const refused = refusePipeOutput(contracts, request, returned, pipe, pipeIndex, admission.validation);
|
|
360
|
+
if (refused !== undefined) {
|
|
361
|
+
report(refused.error, "A3004");
|
|
362
|
+
return { ok: false, response: refused.response };
|
|
363
|
+
}
|
|
364
|
+
current = deepFreeze(returned);
|
|
365
|
+
piped = true;
|
|
366
|
+
}
|
|
367
|
+
pipeIndex += 1;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
const fields = await runFieldInputStages(dependencies, request, contract, current, argumentsPath, report, admission);
|
|
371
|
+
if (!fields.ok) {
|
|
372
|
+
return fields;
|
|
373
|
+
}
|
|
374
|
+
return {
|
|
375
|
+
ok: true,
|
|
376
|
+
args: deepFreeze(fields.args),
|
|
377
|
+
piped: piped || fields.piped,
|
|
378
|
+
};
|
|
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
|
+
}
|
|
141
390
|
try {
|
|
142
|
-
return await
|
|
391
|
+
return await admit();
|
|
143
392
|
}
|
|
144
393
|
catch (error) {
|
|
145
|
-
return
|
|
394
|
+
return {
|
|
395
|
+
ok: false,
|
|
396
|
+
response: await resolveOperationFailure(error, filtersOf(levels), context(), new AdapterBoundary(), report, { path: argumentsPath, arguments: current }),
|
|
397
|
+
};
|
|
146
398
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
399
|
+
}
|
|
400
|
+
async function runFieldInputStages(dependencies, request, contract, args, argumentsPath, report, admission) {
|
|
401
|
+
const scopeConfig = activeScopeConfig(dependencies.config, request);
|
|
402
|
+
const tree = scopeConfig.pipelines;
|
|
403
|
+
const planned = dependencies.fieldStages[request.origin];
|
|
404
|
+
const pipes = planned.anyPipes;
|
|
405
|
+
const judge = admission.beforeBegin === true && hasFieldValidators(contract);
|
|
406
|
+
if (!pipes && !judge) {
|
|
407
|
+
return { ok: true, args, piped: false };
|
|
408
|
+
}
|
|
409
|
+
let current = args;
|
|
410
|
+
let changed = false;
|
|
411
|
+
if (pipes) {
|
|
412
|
+
const pipedFields = planned.piped(request.resource);
|
|
413
|
+
let piped = pipedFields.length === 0
|
|
414
|
+
? { args: current, changed: false }
|
|
415
|
+
: await pipeSentFields(fieldStagesOf(tree, request.resource), pipedFields, writeRecordPathsOf(request.family, current), current, admission.select);
|
|
416
|
+
changed = piped.changed;
|
|
417
|
+
for (const target of nestedWriteTargetsOf(contract, dependencies.recordWrites.references, request, piped.args)) {
|
|
418
|
+
const targetPiped = planned.piped(target.resource);
|
|
419
|
+
if (targetPiped.length === 0) {
|
|
420
|
+
continue;
|
|
152
421
|
}
|
|
422
|
+
piped = await pipeSentFields(fieldStagesOf(tree, target.resource), targetPiped, target.records.map((site) => site.path), piped.args, admission.select);
|
|
423
|
+
changed ||= piped.changed;
|
|
153
424
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
425
|
+
current = piped.args;
|
|
426
|
+
if (changed) {
|
|
427
|
+
const refused = refuseStageOutput({ core: dependencies.contracts.core, active: contract }, request, current, FIELD_PIPES, admission.validation);
|
|
428
|
+
if (refused !== undefined) {
|
|
429
|
+
report(refused.error, "A3004");
|
|
430
|
+
return { ok: false, response: refused.response };
|
|
158
431
|
}
|
|
159
|
-
|
|
432
|
+
}
|
|
433
|
+
}
|
|
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
|
+
}
|
|
448
|
+
}
|
|
449
|
+
return { ok: true, args: current, piped: changed };
|
|
450
|
+
}
|
|
451
|
+
export async function prepareStep(dependencies, request, contract, args, argumentsPath, report, executor, changes, outer) {
|
|
452
|
+
let current = deepFreeze(withoutUnsentWriteValues(dependencies.contracts.core, request, args));
|
|
453
|
+
const scope = {
|
|
454
|
+
requestId: request.requestId,
|
|
455
|
+
transaction: executor,
|
|
456
|
+
state: request.state,
|
|
457
|
+
};
|
|
458
|
+
try {
|
|
459
|
+
const resolved = await runFieldInputStages(dependencies, request, contract, current, argumentsPath, report, { select: changes.written });
|
|
460
|
+
if (!resolved.ok) {
|
|
461
|
+
return resolved;
|
|
462
|
+
}
|
|
463
|
+
current = resolved.args;
|
|
464
|
+
const subject = changes.transactionPiped
|
|
465
|
+
? TRANSACTION_PIPES
|
|
466
|
+
: changes.pipedAroundReferences
|
|
467
|
+
? STEP_PIPES
|
|
468
|
+
: undefined;
|
|
469
|
+
if (subject !== undefined) {
|
|
470
|
+
const refused = refuseStageOutput({ core: dependencies.contracts.core, active: contract }, request, current, subject);
|
|
160
471
|
if (refused !== undefined) {
|
|
161
472
|
report(refused.error, "A3004");
|
|
162
|
-
return refused.response;
|
|
473
|
+
return { ok: false, response: refused.response };
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
return { ok: true, args: deepFreeze(current), piped: resolved.piped };
|
|
477
|
+
}
|
|
478
|
+
catch (error) {
|
|
479
|
+
return {
|
|
480
|
+
ok: false,
|
|
481
|
+
response: await resolveOperationFailure(error, filtersOf(operationLevels(activeScopeConfig(dependencies.config, request).pipelines, request)), dependencies.contexts.operation(scope, operationFacts(contract, request, current)), new AdapterBoundary(), report, { path: argumentsPath, arguments: current }, outer),
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
async function executeForcedOperation(dependencies, adapter, request, contract, args, report, forced) {
|
|
486
|
+
const plan = [
|
|
487
|
+
{
|
|
488
|
+
resource: request.resource,
|
|
489
|
+
family: request.family,
|
|
490
|
+
variant: request.variant,
|
|
491
|
+
args,
|
|
492
|
+
},
|
|
493
|
+
];
|
|
494
|
+
const settled = await settleTransaction({
|
|
495
|
+
adapter,
|
|
496
|
+
levels: forced
|
|
497
|
+
? transactionLevelsOf(activeScopeConfig(dependencies.config, request).pipelines, request.resource)
|
|
498
|
+
: [],
|
|
499
|
+
plan,
|
|
500
|
+
contextOf: (current, executor) => dependencies.contexts.transaction({
|
|
501
|
+
requestId: request.requestId,
|
|
502
|
+
transaction: executor,
|
|
503
|
+
state: request.state,
|
|
504
|
+
}, transactionFacts(contract, request, current)),
|
|
505
|
+
failureView: { path: OPERATION_ARGUMENTS_PATH, arguments: args },
|
|
506
|
+
report,
|
|
507
|
+
runStep: async (_index, step, piped, executor, _results, outer) => {
|
|
508
|
+
let stepArguments = step.args;
|
|
509
|
+
if (piped) {
|
|
510
|
+
const prepared = await prepareStep(dependencies, request, contract, stepArguments, OPERATION_ARGUMENTS_PATH, report, executor, {
|
|
511
|
+
written: () => false,
|
|
512
|
+
transactionPiped: true,
|
|
513
|
+
pipedAroundReferences: false,
|
|
514
|
+
}, outer);
|
|
515
|
+
if (!prepared.ok) {
|
|
516
|
+
return prepared.response;
|
|
517
|
+
}
|
|
518
|
+
stepArguments = prepared.args;
|
|
519
|
+
}
|
|
520
|
+
return executeAdmittedOperation(dependencies, request, contract, stepArguments, OPERATION_ARGUMENTS_PATH, { kind: "transaction", executor, outer }, report);
|
|
521
|
+
},
|
|
522
|
+
});
|
|
523
|
+
switch (settled.kind) {
|
|
524
|
+
case "committed":
|
|
525
|
+
return settled.responses[0] ?? internalFailure();
|
|
526
|
+
case "rolled-back":
|
|
527
|
+
return settled.response;
|
|
528
|
+
case "broken":
|
|
529
|
+
report(settled.error, "A3002");
|
|
530
|
+
return transactionInfrastructureFailure();
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
export async function executeAdmittedOperation(dependencies, request, contract, admittedArguments, argumentsPath, binding, report) {
|
|
534
|
+
const { executor } = binding;
|
|
535
|
+
const scope = scopeOf(request, binding);
|
|
536
|
+
const contexts = dependencies.contexts;
|
|
537
|
+
const scopeConfig = activeScopeConfig(dependencies.config, request);
|
|
538
|
+
const levels = operationLevels(scopeConfig.pipelines, request);
|
|
539
|
+
const adapterBoundary = new AdapterBoundary();
|
|
540
|
+
const contracts = { core: dependencies.contracts.core, active: contract };
|
|
541
|
+
let args = deepFreeze(admittedArguments);
|
|
542
|
+
const context = () => contexts.operation(scope, operationFacts(contract, request, args));
|
|
543
|
+
const computeContext = () => contexts.compute(scope, operationFacts(contract, request, args));
|
|
544
|
+
const reuse = { refusal: undefined };
|
|
545
|
+
const refusedReuse = (refusal) => {
|
|
546
|
+
report(refusal, "A3000");
|
|
547
|
+
return internalFailure();
|
|
548
|
+
};
|
|
549
|
+
let response;
|
|
550
|
+
try {
|
|
551
|
+
response = await runLifecycle();
|
|
552
|
+
}
|
|
553
|
+
catch (error) {
|
|
554
|
+
if (reuse.refusal !== undefined) {
|
|
555
|
+
return refusedReuse(reuse.refusal);
|
|
556
|
+
}
|
|
557
|
+
return resolveOperationFailure(error, filtersOf(levels), context(), adapterBoundary, report, { path: argumentsPath, arguments: args }, binding.kind === "transaction" ? binding.outer : undefined);
|
|
558
|
+
}
|
|
559
|
+
return reuse.refusal === undefined ? response : refusedReuse(reuse.refusal);
|
|
560
|
+
async function runLifecycle() {
|
|
561
|
+
let computed = await applyWriteCompute(contracts, scopeConfig.compute, request, args, computeContext);
|
|
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)));
|
|
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);
|
|
163
583
|
}
|
|
164
584
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
return mapValidationOutcome(missing);
|
|
585
|
+
const hiddenRefusal = hiddenFieldRefusal({ core: dependencies.contracts.core, active: contract }, dependencies.recordWrites.references, request, computed, argumentsPath);
|
|
586
|
+
if (hiddenRefusal !== undefined) {
|
|
587
|
+
throw hiddenRefusal;
|
|
169
588
|
}
|
|
170
|
-
|
|
171
|
-
|
|
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
|
+
}
|
|
172
603
|
}
|
|
604
|
+
let policyFailure;
|
|
605
|
+
const refuseWrite = (response) => {
|
|
606
|
+
policyFailure = response;
|
|
607
|
+
throw thrownFailure(response);
|
|
608
|
+
};
|
|
173
609
|
let readMaterialized = false;
|
|
174
610
|
let executedReadPlan;
|
|
175
611
|
const materialize = async (data, plan) => {
|
|
176
612
|
readMaterialized = true;
|
|
177
613
|
executedReadPlan = plan;
|
|
178
|
-
return materializeReadOperation(contract, scopeConfig.
|
|
614
|
+
return materializeReadOperation(contract, scopeConfig.compute, request, plan, data, computeContext);
|
|
179
615
|
};
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
616
|
+
const invoke = async () => {
|
|
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
|
+
}
|
|
675
|
+
const miss = uniqueMissFailure(request, adapterData);
|
|
676
|
+
if (miss !== undefined) {
|
|
677
|
+
throw thrownFailure(miss);
|
|
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
|
+
}
|
|
189
689
|
return materialize(adapterData, readPlan);
|
|
190
690
|
};
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
invoke = () => interceptor(pipelineContext(contract, request, args), next);
|
|
198
|
-
}
|
|
199
|
-
let data = await invoke();
|
|
200
|
-
if (!readMaterialized) {
|
|
201
|
-
data = await materialize(data, planReadOperation(dependencies.contracts.core, contract, scopeConfig.behaviors, request, args));
|
|
202
|
-
}
|
|
203
|
-
for (const hook of pipelines.hooks.after) {
|
|
204
|
-
await hook(data, pipelineContext(contract, request, args));
|
|
691
|
+
const materialized = async (data) => readMaterialized
|
|
692
|
+
? data
|
|
693
|
+
: materialize(data, planReadOperation(dependencies.contracts.core, dependencies.config.adapter.model, contract, scopeConfig.compute, request, args));
|
|
694
|
+
const data = await materialized(await runLevelLifecycle(levels, context, invoke, materialized, reuse, () => new AvInterceptorNextError()));
|
|
695
|
+
if (policyFailure !== undefined) {
|
|
696
|
+
return policyFailure;
|
|
205
697
|
}
|
|
206
698
|
if (!outputAccepted(contract, request, executedReadPlan?.projection, data, report)) {
|
|
207
699
|
return internalFailure();
|