@aventara/core 1.0.0-rc.0 → 1.0.0-rc.2
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 +1434 -0
- package/ERRORS.md +142 -0
- package/README.md +247 -57
- 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 +25 -11
- package/dist/adapters/adapter-identifier.d.ts +6 -6
- 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 +3 -3
- package/dist/adapters/adapter-resource.d.ts +18 -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 +7 -7
- 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 +18 -18
- package/dist/compiler/contract.compiler.js +637 -442
- 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/config/any-framework-config.d.ts +19 -12
- package/dist/config/computed-fields.d.ts +62 -0
- package/dist/config/computed-fields.js +80 -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 +74 -31
- package/dist/config/config.resolver.js +108 -44
- package/dist/config/config.validator.d.ts +7 -7
- package/dist/config/config.validator.js +581 -72
- package/dist/config/define-resource.d.ts +57 -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 +1 -1
- package/dist/config/exact-framework-config.d.ts +308 -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 +111 -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 +122 -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/capability.d.ts +21 -12
- package/dist/contracts/capability.js +2 -0
- package/dist/contracts/client-contract-structure.validator.d.ts +388 -63
- package/dist/contracts/client-contract-structure.validator.js +156 -10
- package/dist/contracts/contract-canonicalizer.d.ts +26 -3
- package/dist/contracts/contract-canonicalizer.js +156 -29
- package/dist/contracts/contract-hash.d.ts +12 -7
- package/dist/contracts/contract-hash.js +3 -2
- 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 +24 -16
- 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 +81 -42
- package/dist/contracts/identifier.d.ts +4 -4
- 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 +15 -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/contract-view.d.ts +213 -147
- package/dist/framework/framework-construction.error.d.ts +19 -10
- package/dist/framework/framework-construction.error.js +7 -3
- package/dist/framework/framework.d.ts +47 -23
- package/dist/framework/framework.factory.d.ts +8 -6
- package/dist/framework/framework.factory.js +49 -22
- package/dist/framework/operation-facade.d.ts +123 -52
- package/dist/framework/operation-facade.js +9 -1
- package/dist/index.d.ts +57 -50
- package/dist/index.js +7 -6
- package/dist/internal.d.ts +17 -10
- package/dist/internal.js +4 -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 +343 -207
- package/dist/operations/operation-call.d.ts +27 -28
- package/dist/operations/operation-identity.d.ts +10 -10
- package/dist/operations/operation-result.d.ts +21 -21
- package/dist/operations/operation-validator-core.d.ts +6 -6
- package/dist/operations/operation-validator-core.js +99 -6
- package/dist/operations/operation-validator.d.ts +9 -9
- package/dist/operations/projection-scope.resolver.d.ts +6 -6
- package/dist/operations/structural-limits.walker.d.ts +6 -6
- 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/protocol/absent-route.responder.d.ts +13 -12
- package/dist/protocol/absent-route.responder.js +19 -19
- package/dist/protocol/contract-document.responder.d.ts +3 -3
- package/dist/protocol/contract-document.responder.js +2 -2
- package/dist/protocol/http-request.decoder.d.ts +17 -13
- package/dist/protocol/http-request.decoder.js +10 -10
- package/dist/protocol/http-request.reader.d.ts +3 -3
- 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-surface.d.ts +4 -4
- package/dist/protocol/protocol.binder.d.ts +50 -27
- package/dist/protocol/protocol.binder.js +12 -9
- package/dist/protocol/protocol.handler.d.ts +22 -13
- package/dist/protocol/protocol.handler.js +91 -17
- 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 -5
- package/dist/runtime/caller-data.copier.js +31 -14
- package/dist/runtime/caller-data.door.d.ts +17 -11
- package/dist/runtime/caller-data.door.js +6 -4
- package/dist/runtime/computed-read-runtime.d.ts +7 -6
- package/dist/runtime/computed-read-runtime.js +76 -50
- 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 +59 -0
- package/dist/runtime/context-executor.runtime.js +275 -0
- package/dist/runtime/create-requirement.d.ts +44 -79
- package/dist/runtime/create-requirement.js +213 -73
- package/dist/runtime/decimal.d.ts +2 -2
- package/dist/runtime/decimal.js +1 -1
- package/dist/runtime/diagnostics-reporter.d.ts +54 -27
- package/dist/runtime/diagnostics-reporter.js +24 -0
- package/dist/runtime/error-boundary.d.ts +65 -8
- package/dist/runtime/error-boundary.js +49 -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 +10 -2
- package/dist/runtime/field-check.evaluator.d.ts +29 -0
- package/dist/runtime/field-check.evaluator.js +521 -0
- package/dist/runtime/field-compute.d.ts +64 -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 +19 -0
- package/dist/runtime/field-validator.runtime.js +92 -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 +23 -2
- 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 +25 -0
- package/dist/runtime/level-lifecycle.runtime.js +39 -0
- package/dist/runtime/misuse-reporter.d.ts +12 -12
- package/dist/runtime/mutation-planner.d.ts +19 -10
- 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 +33 -6
- package/dist/runtime/operation-response.d.ts +17 -17
- package/dist/runtime/operation-runtime.d.ts +127 -25
- package/dist/runtime/operation-runtime.js +441 -78
- package/dist/runtime/outcome-mapper.d.ts +16 -5
- package/dist/runtime/outcome-mapper.js +23 -6
- package/dist/runtime/output-validator.d.ts +10 -10
- 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 +223 -34
- package/dist/runtime/readonly-value.d.ts +43 -0
- package/dist/runtime/readonly-value.js +150 -0
- 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 +35 -16
- package/dist/runtime/scalar-runtime.js +102 -34
- 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 +2 -2
- 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 +4 -4
- package/dist/transactions/transaction-integrity-error.d.ts +6 -6
- package/dist/transactions/transaction-integrity-error.js +5 -2
- package/dist/transactions/transaction-plan-assembler.d.ts +21 -11
- package/dist/transactions/transaction-plan-assembler.js +169 -32
- package/dist/transactions/transaction-plan-validator.d.ts +45 -20
- 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 +19 -2
- package/dist/transactions/transaction-reference-resolver.js +26 -14
- package/dist/transactions/transaction-reference-validator.d.ts +76 -4
- package/dist/transactions/transaction-reference-validator.js +129 -71
- package/dist/transactions/transaction-reference.d.ts +13 -13
- package/dist/transactions/transaction-reference.js +5 -0
- package/dist/transactions/transaction-request.d.ts +18 -5
- package/dist/transactions/transaction-response.d.ts +6 -6
- package/dist/transactions/transaction-runtime.d.ts +8 -7
- package/dist/transactions/transaction-runtime.js +191 -50
- package/dist/transactions/transaction-settlement.runtime.d.ts +51 -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 +2 -2
- package/dist/transactions/transaction-slot-writer.js +2 -2
- package/dist/transactions/transaction-stage.runtime.d.ts +82 -0
- package/dist/transactions/transaction-stage.runtime.js +126 -0
- package/package.json +9 -7
- 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,15 +1,16 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
1
|
+
import type { AvContracts } from "../compiler/contract.compiler.js";
|
|
2
|
+
import type { RemoteRequestOrigin } from "../config/config-layer.js";
|
|
3
|
+
import type { RemoteOperationRequest } from "../runtime/operation-request.js";
|
|
4
|
+
import type { AgentTransactionRequest, ClientTransactionRequest } from "../transactions/transaction-request.js";
|
|
4
5
|
import type { AvProtocolResponse } from "./http-response.encoder.js";
|
|
5
6
|
/** One HTTP request as a host hands it to the protocol. */
|
|
6
7
|
export type AvProtocolRequest = {
|
|
7
8
|
/** The HTTP method as received. Anything but `POST` on a framework route is `A2012`. */
|
|
8
9
|
readonly method: string;
|
|
9
10
|
/**
|
|
10
|
-
* The request path
|
|
11
|
-
* URL-decoded): `/_resources/users/find/many`, `/_transactions`, `/_contract
|
|
12
|
-
* the
|
|
11
|
+
* The request path relative to the configured `api` mount path, as received (not yet
|
|
12
|
+
* URL-decoded): `/_resources/users/find/many`, `/_transactions`, `/_contract`,
|
|
13
|
+
* in the same form as the paths `protocol.surface()` returns.
|
|
13
14
|
*/
|
|
14
15
|
readonly path: string;
|
|
15
16
|
/**
|
|
@@ -19,8 +20,8 @@ export type AvProtocolRequest = {
|
|
|
19
20
|
*/
|
|
20
21
|
readonly headers: Readonly<Record<string, string | readonly string[] | undefined>>;
|
|
21
22
|
/**
|
|
22
|
-
* The body, in one of two explicitly named arms
|
|
23
|
-
* one it was given:
|
|
23
|
+
* The body, in one of two explicitly named arms, so the decoder never guesses
|
|
24
|
+
* which one it was given:
|
|
24
25
|
*/
|
|
25
26
|
readonly body: {
|
|
26
27
|
readonly kind: "raw";
|
|
@@ -45,19 +46,22 @@ type Decoded<Request> = {
|
|
|
45
46
|
readonly response: AvProtocolResponse;
|
|
46
47
|
readonly requestId: string;
|
|
47
48
|
};
|
|
48
|
-
/**
|
|
49
|
-
|
|
49
|
+
/**
|
|
50
|
+
* What `protocol.decodeOperation` answers: a client-origin request, or an
|
|
51
|
+
* agent-origin one from a binding made with `{ origin: "agent" }`.
|
|
52
|
+
*/
|
|
53
|
+
export type DecodedOperation = Decoded<RemoteOperationRequest>;
|
|
50
54
|
/** `protocol.decodeOperation`'s success value: the request `framework.execute` takes. */
|
|
51
55
|
export type DecodedOperationRequest = Extract<DecodedOperation, {
|
|
52
56
|
ok: true;
|
|
53
57
|
}>;
|
|
54
58
|
/** What `protocol.decodeTransaction` answers. */
|
|
55
|
-
export type DecodedTransaction = Decoded<ClientTransactionRequest>;
|
|
59
|
+
export type DecodedTransaction = Decoded<ClientTransactionRequest | AgentTransactionRequest>;
|
|
56
60
|
/**
|
|
57
61
|
* `protocol.decodeOperation(request)` — one operation route's HTTP request as
|
|
58
62
|
* the client-origin request `framework.execute` takes, or its answer.
|
|
59
63
|
*/
|
|
60
|
-
export declare function decodeOperationRequest(contracts:
|
|
64
|
+
export declare function decodeOperationRequest(contracts: AvContracts, received: AvProtocolRequest, origin?: RemoteRequestOrigin): DecodedOperation;
|
|
61
65
|
/**
|
|
62
66
|
* `protocol.decodeTransaction(request)` — the `/_transactions` request as the client-
|
|
63
67
|
* origin plan request `framework.executeTransaction` takes, or its answer. The same
|
|
@@ -66,7 +70,7 @@ export declare function decodeOperationRequest(contracts: FrameworkContracts, re
|
|
|
66
70
|
* the plan then runs under ClientContract rules: the plan is client origin and cannot
|
|
67
71
|
* say otherwise. The body is the plan verbatim.
|
|
68
72
|
*/
|
|
69
|
-
export declare function decodeTransactionRequest(contracts:
|
|
73
|
+
export declare function decodeTransactionRequest(contracts: AvContracts, received: AvProtocolRequest, origin?: RemoteRequestOrigin): DecodedTransaction;
|
|
70
74
|
/**
|
|
71
75
|
* Whether `value` is a body this decoder parsed from raw content. Only the protocol's
|
|
72
76
|
* own shortcuts ask, about a request they have just decoded, before any host code
|
|
@@ -2,21 +2,21 @@ import { checkOperationRoute, checkTransactionsRoute, } from "./absent-route.res
|
|
|
2
2
|
import { readRequest } from "./http-request.reader.js";
|
|
3
3
|
import { transportFailure, } from "./protocol-failure.js";
|
|
4
4
|
import { headerValue } from "./protocol-headers.js";
|
|
5
|
-
export function decodeOperationRequest(contracts, received) {
|
|
5
|
+
export function decodeOperationRequest(contracts, received, origin = "client") {
|
|
6
6
|
const read = readRequest(received);
|
|
7
7
|
if (!read.ok) {
|
|
8
8
|
return read;
|
|
9
9
|
}
|
|
10
|
-
const route = checkOperationRoute(contracts, read);
|
|
10
|
+
const route = checkOperationRoute(contracts, read, origin);
|
|
11
11
|
if (!route.ok) {
|
|
12
12
|
return refused(route.response, read.requestId);
|
|
13
13
|
}
|
|
14
|
-
const body = readBody(read, contracts);
|
|
14
|
+
const body = readBody(read, contracts, origin);
|
|
15
15
|
return body.ok
|
|
16
16
|
? {
|
|
17
17
|
ok: true,
|
|
18
18
|
request: {
|
|
19
|
-
origin
|
|
19
|
+
origin,
|
|
20
20
|
requestId: read.requestId,
|
|
21
21
|
resource: route.resource,
|
|
22
22
|
...route.operation,
|
|
@@ -28,21 +28,21 @@ export function decodeOperationRequest(contracts, received) {
|
|
|
28
28
|
}
|
|
29
29
|
: refused(body.response, read.requestId);
|
|
30
30
|
}
|
|
31
|
-
export function decodeTransactionRequest(contracts, received) {
|
|
31
|
+
export function decodeTransactionRequest(contracts, received, origin = "client") {
|
|
32
32
|
const read = readRequest(received);
|
|
33
33
|
if (!read.ok) {
|
|
34
34
|
return read;
|
|
35
35
|
}
|
|
36
|
-
const route = checkTransactionsRoute(contracts, read);
|
|
36
|
+
const route = checkTransactionsRoute(contracts, read, origin);
|
|
37
37
|
if (!route.ok) {
|
|
38
38
|
return refused(route.response, read.requestId);
|
|
39
39
|
}
|
|
40
|
-
const body = readBody(read, contracts);
|
|
40
|
+
const body = readBody(read, contracts, origin);
|
|
41
41
|
return body.ok
|
|
42
42
|
? {
|
|
43
43
|
ok: true,
|
|
44
44
|
request: {
|
|
45
|
-
origin
|
|
45
|
+
origin,
|
|
46
46
|
requestId: read.requestId,
|
|
47
47
|
protocol: route.protocol,
|
|
48
48
|
transport: transportOf(read),
|
|
@@ -58,8 +58,8 @@ function refused(response, requestId) {
|
|
|
58
58
|
function transportOf(read) {
|
|
59
59
|
return { method: "POST", headers: read.headers };
|
|
60
60
|
}
|
|
61
|
-
function readBody(read, contracts) {
|
|
62
|
-
const code = bodyValue(read.request.body, headerValue(read.headers, "content-type"), contracts.
|
|
61
|
+
function readBody(read, contracts, origin) {
|
|
62
|
+
const code = bodyValue(read.request.body, headerValue(read.headers, "content-type"), contracts[origin].limits.maxRequestBytes);
|
|
63
63
|
return typeof code === "string"
|
|
64
64
|
? { ok: false, response: transportFailure(code, read.requestId) }
|
|
65
65
|
: { ok: true, value: code.value };
|
|
@@ -2,9 +2,9 @@ import type { ClientProtocolIdentity } from "../runtime/operation-request.js";
|
|
|
2
2
|
import type { OperationRouteSegments } from "./absent-route.responder.js";
|
|
3
3
|
import type { AvProtocolRequest } from "./http-request.decoder.js";
|
|
4
4
|
import type { AvProtocolResponse } from "./http-response.encoder.js";
|
|
5
|
-
/** `POST <
|
|
5
|
+
/** `POST <api>/_transactions`. */
|
|
6
6
|
export declare const TRANSACTIONS_ROUTE = "/_transactions";
|
|
7
|
-
/** `GET <
|
|
7
|
+
/** `GET <api>/_contract`. */
|
|
8
8
|
export declare const CONTRACT_ROUTE = "/_contract";
|
|
9
9
|
/** The methods an operation or `/_transactions` route accepts: `POST`, only. */
|
|
10
10
|
export declare const POST_ONLY: readonly string[];
|
|
@@ -12,7 +12,7 @@ export declare const POST_ONLY: readonly string[];
|
|
|
12
12
|
export declare const GET_ONLY: readonly string[];
|
|
13
13
|
/**
|
|
14
14
|
* Whether a path lies in the protocol's namespace: underscore-prefixed paths beneath
|
|
15
|
-
* the
|
|
15
|
+
* the `api` mount path are reserved for framework facilities; every other path is the
|
|
16
16
|
* host's.
|
|
17
17
|
*/
|
|
18
18
|
export declare function isProtocolPath(path: string): boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import type {
|
|
1
|
+
import { type AvOperationResponse } from "../runtime/operation-response.js";
|
|
2
|
+
import type { AvTransactionResponse } from "../transactions/transaction-response.js";
|
|
3
3
|
/**
|
|
4
4
|
* One HTTP response as the protocol hands it to a host: what the encoders
|
|
5
5
|
* (`protocol.encodeOperation` / `encodeTransaction`) and `protocol.failure`
|
|
@@ -28,7 +28,7 @@ export type UnencodableReport = (error: unknown, operation?: number) => void;
|
|
|
28
28
|
* `requestId` is echoed as `Aventara-Request-Id` — pass the id the request ran under,
|
|
29
29
|
* which the decoder supplies.
|
|
30
30
|
*/
|
|
31
|
-
export declare function encodeOperationResponse(response:
|
|
31
|
+
export declare function encodeOperationResponse(response: AvOperationResponse, requestId: string, report?: UnencodableReport): AvProtocolResponse;
|
|
32
32
|
/**
|
|
33
33
|
* `protocol.encodeTransaction(response, requestId)`: the same for a plan's response. A
|
|
34
34
|
* committed plan is `200 A1009` — even when it created something — with each
|
|
@@ -37,4 +37,4 @@ export declare function encodeOperationResponse(response: OperationResponse, req
|
|
|
37
37
|
* status. A step whose result cannot be encoded answers `A3003` → 500 naming that step
|
|
38
38
|
* as `cause.operation`, as every internal failure inside a plan does.
|
|
39
39
|
*/
|
|
40
|
-
export declare function encodeTransactionResponse(response:
|
|
40
|
+
export declare function encodeTransactionResponse(response: AvTransactionResponse, requestId: string, report?: UnencodableReport): AvProtocolResponse;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { encodeBase64, WIRE_SCALAR_PATTERNS, } from "../contracts/wire-scalar-format.js";
|
|
2
|
-
import {
|
|
2
|
+
import { AvDecimal } from "../runtime/decimal.js";
|
|
3
3
|
import { SERIALIZATION_FAILURE_MESSAGE } from "../runtime/error-boundary.js";
|
|
4
4
|
import { operationFailure, } from "../runtime/operation-response.js";
|
|
5
5
|
import { httpStatus } from "./http-status.table.js";
|
|
6
6
|
import { headers } from "./protocol-headers.js";
|
|
7
7
|
export function encodeOperationResponse(response, requestId, report) {
|
|
8
8
|
try {
|
|
9
|
-
return written(response,
|
|
9
|
+
return written(response, toWireText(response.data), requestId);
|
|
10
10
|
}
|
|
11
11
|
catch (error) {
|
|
12
12
|
report?.(error);
|
|
13
|
-
return written(serializationFailure(), null, requestId);
|
|
13
|
+
return written(serializationFailure(), "null", requestId);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
export function encodeTransactionResponse(response, requestId, report) {
|
|
@@ -25,13 +25,16 @@ export function encodeTransactionResponse(response, requestId, report) {
|
|
|
25
25
|
}
|
|
26
26
|
const steps = [];
|
|
27
27
|
for (step = 0; step < data.length; step += 1) {
|
|
28
|
-
|
|
28
|
+
if (!Object.hasOwn(data, step)) {
|
|
29
|
+
throw unencodable(data);
|
|
30
|
+
}
|
|
31
|
+
steps.push(toWireText(data[step]));
|
|
29
32
|
}
|
|
30
|
-
return written(response, steps, requestId);
|
|
33
|
+
return written(response, `[${steps.join(",")}]`, requestId);
|
|
31
34
|
}
|
|
32
35
|
catch (error) {
|
|
33
36
|
report?.(error, step);
|
|
34
|
-
return written(serializationFailure(step), null, requestId);
|
|
37
|
+
return written(serializationFailure(step), "null", requestId);
|
|
35
38
|
}
|
|
36
39
|
}
|
|
37
40
|
function serializationFailure(operation) {
|
|
@@ -51,82 +54,118 @@ function written(response, wireData, requestId) {
|
|
|
51
54
|
"Content-Type": "application/json",
|
|
52
55
|
[headers.requestId]: requestId,
|
|
53
56
|
},
|
|
54
|
-
body: JSON.stringify({
|
|
57
|
+
body: `{"data":${wireData},${JSON.stringify({ code, cause }).slice(1)}`,
|
|
55
58
|
};
|
|
56
59
|
}
|
|
57
60
|
function unencodable(value) {
|
|
58
61
|
return new TypeError("A result value has no wire form.", { cause: value });
|
|
59
62
|
}
|
|
60
|
-
function
|
|
63
|
+
function toWireText(value) {
|
|
64
|
+
const output = [];
|
|
65
|
+
const ancestors = new Set();
|
|
66
|
+
const stack = [{ kind: "value", value }];
|
|
67
|
+
while (stack.length > 0) {
|
|
68
|
+
const task = stack.pop();
|
|
69
|
+
if (task.kind === "text") {
|
|
70
|
+
output.push(task.text);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (task.kind === "leave") {
|
|
74
|
+
ancestors.delete(task.container);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const current = task.value;
|
|
78
|
+
const scalar = scalarWireText(current);
|
|
79
|
+
if (scalar !== undefined) {
|
|
80
|
+
output.push(scalar);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const container = current;
|
|
84
|
+
if (ancestors.has(container)) {
|
|
85
|
+
throw unencodable(container);
|
|
86
|
+
}
|
|
87
|
+
ancestors.add(container);
|
|
88
|
+
stack.push({ kind: "leave", container });
|
|
89
|
+
if (Array.isArray(container)) {
|
|
90
|
+
pushList(stack, container);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
pushRecord(stack, container);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return output.join("");
|
|
97
|
+
}
|
|
98
|
+
function pushList(stack, list) {
|
|
99
|
+
const tasks = [{ kind: "text", text: "[" }];
|
|
100
|
+
for (let index = 0; index < list.length; index += 1) {
|
|
101
|
+
if (!Object.hasOwn(list, index)) {
|
|
102
|
+
throw unencodable(list);
|
|
103
|
+
}
|
|
104
|
+
if (index > 0) {
|
|
105
|
+
tasks.push({ kind: "text", text: "," });
|
|
106
|
+
}
|
|
107
|
+
tasks.push({ kind: "value", value: list[index] });
|
|
108
|
+
}
|
|
109
|
+
tasks.push({ kind: "text", text: "]" });
|
|
110
|
+
pushReversed(stack, tasks);
|
|
111
|
+
}
|
|
112
|
+
function pushRecord(stack, record) {
|
|
113
|
+
const prototype = Object.getPrototypeOf(record);
|
|
114
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
115
|
+
throw unencodable(record);
|
|
116
|
+
}
|
|
117
|
+
const tasks = [{ kind: "text", text: "{" }];
|
|
118
|
+
for (const key of Object.keys(record)) {
|
|
119
|
+
const member = record[key];
|
|
120
|
+
if (member === undefined) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
tasks.push({
|
|
124
|
+
kind: "text",
|
|
125
|
+
text: `${tasks.length > 1 ? "," : ""}${JSON.stringify(key)}:`,
|
|
126
|
+
});
|
|
127
|
+
tasks.push({ kind: "value", value: member });
|
|
128
|
+
}
|
|
129
|
+
tasks.push({ kind: "text", text: "}" });
|
|
130
|
+
pushReversed(stack, tasks);
|
|
131
|
+
}
|
|
132
|
+
function pushReversed(stack, tasks) {
|
|
133
|
+
for (let index = tasks.length - 1; index >= 0; index -= 1) {
|
|
134
|
+
stack.push(tasks[index]);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function scalarWireText(value) {
|
|
61
138
|
switch (typeof value) {
|
|
62
139
|
case "string":
|
|
63
140
|
case "boolean":
|
|
64
|
-
return value;
|
|
141
|
+
return JSON.stringify(value);
|
|
65
142
|
case "number":
|
|
66
143
|
if (Number.isFinite(value)) {
|
|
67
|
-
return value;
|
|
144
|
+
return JSON.stringify(value);
|
|
68
145
|
}
|
|
69
146
|
throw unencodable(value);
|
|
70
147
|
case "bigint":
|
|
71
|
-
return value.toString(10);
|
|
148
|
+
return JSON.stringify(value.toString(10));
|
|
72
149
|
case "object":
|
|
73
150
|
break;
|
|
74
151
|
default:
|
|
75
152
|
throw unencodable(value);
|
|
76
153
|
}
|
|
77
154
|
if (value === null) {
|
|
78
|
-
return null;
|
|
155
|
+
return "null";
|
|
79
156
|
}
|
|
80
157
|
if (value instanceof Date) {
|
|
81
158
|
const wire = Number.isNaN(value.getTime()) ? "" : value.toISOString();
|
|
82
159
|
if (!WIRE_SCALAR_PATTERNS.datetime.test(wire)) {
|
|
83
160
|
throw unencodable(value);
|
|
84
161
|
}
|
|
85
|
-
return wire;
|
|
162
|
+
return JSON.stringify(wire);
|
|
86
163
|
}
|
|
87
|
-
if (value instanceof
|
|
88
|
-
return value.toString();
|
|
164
|
+
if (value instanceof AvDecimal) {
|
|
165
|
+
return JSON.stringify(value.toString());
|
|
89
166
|
}
|
|
90
167
|
if (value instanceof Uint8Array) {
|
|
91
|
-
return encodeBase64(value);
|
|
92
|
-
}
|
|
93
|
-
if (ancestors.has(value)) {
|
|
94
|
-
throw unencodable(value);
|
|
95
|
-
}
|
|
96
|
-
ancestors.add(value);
|
|
97
|
-
try {
|
|
98
|
-
return Array.isArray(value)
|
|
99
|
-
? toWireList(value, ancestors)
|
|
100
|
-
: toWireRecord(value, ancestors);
|
|
101
|
-
}
|
|
102
|
-
finally {
|
|
103
|
-
ancestors.delete(value);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
function toWireList(list, ancestors) {
|
|
107
|
-
const wire = [];
|
|
108
|
-
for (let index = 0; index < list.length; index += 1) {
|
|
109
|
-
wire.push(toWireElement(list, index, ancestors));
|
|
110
|
-
}
|
|
111
|
-
return wire;
|
|
112
|
-
}
|
|
113
|
-
function toWireElement(list, index, ancestors) {
|
|
114
|
-
if (!Object.hasOwn(list, index)) {
|
|
115
|
-
throw unencodable(list);
|
|
116
|
-
}
|
|
117
|
-
return toWire(list[index], ancestors);
|
|
118
|
-
}
|
|
119
|
-
function toWireRecord(record, ancestors) {
|
|
120
|
-
const prototype = Object.getPrototypeOf(record);
|
|
121
|
-
if (prototype !== Object.prototype && prototype !== null) {
|
|
122
|
-
throw unencodable(record);
|
|
123
|
-
}
|
|
124
|
-
const members = [];
|
|
125
|
-
for (const key of Object.keys(record)) {
|
|
126
|
-
const member = record[key];
|
|
127
|
-
if (member !== undefined) {
|
|
128
|
-
members.push([key, toWire(member, ancestors)]);
|
|
129
|
-
}
|
|
168
|
+
return JSON.stringify(encodeBase64(value));
|
|
130
169
|
}
|
|
131
|
-
return
|
|
170
|
+
return undefined;
|
|
132
171
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AvOperationCode } from "../runtime/operation-response.js";
|
|
2
2
|
/**
|
|
3
3
|
* `AvProtocol.httpStatus` — the HTTP status each A-code carries, as passive data.
|
|
4
4
|
*/
|
|
5
5
|
export declare const httpStatus: {
|
|
6
|
-
readonly [C in
|
|
6
|
+
readonly [C in AvOperationCode]: number;
|
|
7
7
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type AvOperationResponse } from "../runtime/operation-response.js";
|
|
2
2
|
/**
|
|
3
3
|
* The HTTP status plays no part — a code is read even at an unexpected status.
|
|
4
4
|
*/
|
|
5
|
-
export declare function isOperationResponse(value: unknown): value is
|
|
5
|
+
export declare function isOperationResponse(value: unknown): value is AvOperationResponse;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { type
|
|
1
|
+
import type { AvContractClient } from "../contracts/contract.js";
|
|
2
|
+
import { type AvOperationIdentity } from "../operations/operation-identity.js";
|
|
3
3
|
/**
|
|
4
4
|
* One route of the protocol surface: a route a host mounts for the bound
|
|
5
5
|
* ClientContract, tagged by `kind`.
|
|
@@ -9,7 +9,7 @@ export type SurfaceRoute = ({
|
|
|
9
9
|
readonly method: "POST";
|
|
10
10
|
readonly path: `/_resources/${string}`;
|
|
11
11
|
readonly resource: string;
|
|
12
|
-
} &
|
|
12
|
+
} & AvOperationIdentity) | {
|
|
13
13
|
readonly kind: "contract";
|
|
14
14
|
readonly method: "GET";
|
|
15
15
|
readonly path: "/_contract";
|
|
@@ -24,4 +24,4 @@ export type SurfaceRoute = ({
|
|
|
24
24
|
* order, then `GET /_contract`, then `POST /_transactions` when, and only when,
|
|
25
25
|
* `transactions === "interactive"`.
|
|
26
26
|
*/
|
|
27
|
-
export declare function surfaceOf(client:
|
|
27
|
+
export declare function surfaceOf(client: AvContractClient): readonly SurfaceRoute[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
1
|
+
import type { AvFramework } from "../framework/framework.js";
|
|
2
|
+
import type { AvOperationResponse } from "../runtime/operation-response.js";
|
|
3
|
+
import type { AvState } from "../runtime/request-state.js";
|
|
4
|
+
import type { AvTransactionResponse } from "../transactions/transaction-response.js";
|
|
4
5
|
import { type AvProtocolRequest, type DecodedOperation, type DecodedOperationRequest, type DecodedTransaction } from "./http-request.decoder.js";
|
|
5
6
|
import { type AvProtocolResponse } from "./http-response.encoder.js";
|
|
6
7
|
import { transportFailure } from "./protocol-failure.js";
|
|
@@ -11,49 +12,51 @@ import { type SurfaceRoute } from "./protocol-surface.js";
|
|
|
11
12
|
*/
|
|
12
13
|
export type AvProtocolBinding = {
|
|
13
14
|
/**
|
|
14
|
-
* Every route a host mounts for the bound
|
|
15
|
+
* Every route a host mounts for the bound Contract (the Client Contract, or the
|
|
16
|
+
* Agent Contract under `{ origin: "agent" }`), from one list, each
|
|
15
17
|
* tagged by `kind`: one `POST` `operation` route per `(resource, family, variant)`
|
|
16
|
-
* it advertises
|
|
18
|
+
* it advertises and no other, then the `contract` route `GET /_contract`
|
|
17
19
|
* (always), then the `transactions` route `POST /_transactions` exactly when its
|
|
18
20
|
* `transactions` is `"interactive"`. Each path is relative to
|
|
19
|
-
* `framework.
|
|
21
|
+
* `framework.api`. Read once at bind time: every call answers the same
|
|
20
22
|
* deep-frozen list, which is passive data a host may serialize.
|
|
21
23
|
*/
|
|
22
24
|
readonly surface: () => readonly SurfaceRoute[];
|
|
23
25
|
/**
|
|
24
|
-
* An operation route's HTTP request → the client-origin
|
|
26
|
+
* An operation route's HTTP request → the client-origin (or the binding's
|
|
27
|
+
* agent-origin) request
|
|
25
28
|
* `framework.execute` takes, or the framework response that answers it instead,
|
|
26
29
|
* with the request id either way. Answers absence for an unadvertised triple
|
|
27
30
|
* without executing it, so a catch-all host is safe. Raw body: size, content type,
|
|
28
|
-
* JSON and shape enforced; parsed body: shape only
|
|
29
|
-
* parser's.
|
|
31
|
+
* JSON and shape enforced; parsed body: shape only, since the rest was the
|
|
32
|
+
* host's parser's job.
|
|
30
33
|
*/
|
|
31
34
|
readonly decodeOperation: (request: AvProtocolRequest) => DecodedOperation;
|
|
32
35
|
/**
|
|
33
|
-
* The same for `/_transactions` → the
|
|
34
|
-
* `framework.executeTransaction` takes; absent unless the
|
|
36
|
+
* The same for `/_transactions` → the binding's origin's plan request
|
|
37
|
+
* `framework.executeTransaction` takes; absent unless the bound Contract's
|
|
35
38
|
* transactions are `"interactive"`.
|
|
36
39
|
*/
|
|
37
40
|
readonly decodeTransaction: (request: AvProtocolRequest) => DecodedTransaction;
|
|
38
41
|
/**
|
|
39
|
-
* One operation's framework response
|
|
42
|
+
* One operation's framework response (what `framework.execute` answered) as the
|
|
40
43
|
* HTTP response a host writes: the code's status, `data` in wire forms, `Aventara-
|
|
41
44
|
* Request-Id` echoed. A result with no wire form answers `A3003` → 500. A
|
|
42
45
|
* diagnostic of one operation names it (`resource`, `family`, `variant`), so the
|
|
43
|
-
* `A3003` reaches the diagnostics sink only when the host passes `decoded`
|
|
44
|
-
* `decodeOperation`'s success value
|
|
46
|
+
* `A3003` reaches the diagnostics sink only when the host passes `decoded`
|
|
47
|
+
* (`decodeOperation`'s success value), as `handleOperation` does; without it the
|
|
45
48
|
* answer is the same and nothing is reported.
|
|
46
49
|
*/
|
|
47
|
-
readonly encodeOperation: (response:
|
|
50
|
+
readonly encodeOperation: (response: AvOperationResponse, requestId: string, decoded?: DecodedOperationRequest) => AvProtocolResponse;
|
|
48
51
|
/**
|
|
49
|
-
* The same for `/_transactions
|
|
52
|
+
* The same for `/_transactions`: what `framework.executeTransaction` answered. An
|
|
50
53
|
* `A3003` is reported to the Framework's diagnostics sink as a `"transaction"`
|
|
51
|
-
* diagnostic
|
|
54
|
+
* diagnostic (client origin, this `requestId`, the step it blames as `operation`)
|
|
52
55
|
* with the value that had no wire form (or what its getter threw) as `error`.
|
|
53
56
|
*/
|
|
54
|
-
readonly encodeTransaction: (response:
|
|
57
|
+
readonly encodeTransaction: (response: AvTransactionResponse, requestId: string) => AvProtocolResponse;
|
|
55
58
|
/**
|
|
56
|
-
* A transport code
|
|
59
|
+
* A transport code (`A2000`, `A2010`, `A2011` or `A2012`) as the complete
|
|
57
60
|
* framework response. For a host that parses the body itself and must answer
|
|
58
61
|
* its parser's failure. `A2012` requires the methods its route allows, so
|
|
59
62
|
* every 405 carries `Allow`.
|
|
@@ -67,20 +70,30 @@ export type AvProtocolBinding = {
|
|
|
67
70
|
* host hands it: one that is not an `AvProtocolRequest` answers `400 A2000`; it
|
|
68
71
|
* never rejects.
|
|
69
72
|
*/
|
|
70
|
-
readonly handleOperation: (request: AvProtocolRequest
|
|
73
|
+
readonly handleOperation: (request: AvProtocolRequest, options?: {
|
|
74
|
+
/**
|
|
75
|
+
* Seeds the request's `ctx.$state` (a host reads its platform request
|
|
76
|
+
* here, Passport's `req.user`, say). Called once, after decoding; a
|
|
77
|
+
* throw is answered like any developer failure. Omitted, the state is `{}`.
|
|
78
|
+
*/
|
|
79
|
+
readonly state?: () => AvState | Promise<AvState>;
|
|
80
|
+
}) => Promise<AvProtocolResponse>;
|
|
71
81
|
/**
|
|
72
82
|
* The same for `/_transactions`: `decodeTransaction` →
|
|
73
83
|
* `framework.executeTransaction` → `encodeTransaction`. Every step runs under
|
|
74
84
|
* ClientContract rules; a committed plan is `200 A1009`, a rolled-back one its
|
|
75
85
|
* failing step's own status.
|
|
76
86
|
*/
|
|
77
|
-
readonly handleTransaction: (request: AvProtocolRequest
|
|
87
|
+
readonly handleTransaction: (request: AvProtocolRequest, options?: {
|
|
88
|
+
/** Seeds the plan's one `ctx.$state`, as for `handleOperation`. */
|
|
89
|
+
readonly state?: () => AvState | Promise<AvState>;
|
|
90
|
+
}) => Promise<AvProtocolResponse>;
|
|
78
91
|
/**
|
|
79
92
|
* The `GET /_contract` responder: the bound ClientContract's JCS-canonical bytes,
|
|
80
93
|
* `ETag` its quoted hash, `Cache-Control: no-cache`, and `304` with no body when
|
|
81
94
|
* `If-None-Match` matches (weak comparison, a list, `*`). Requires no identity
|
|
82
|
-
* header; any other method is `405 A2012` with `Allow: GET`. The bytes are
|
|
83
|
-
* once, at
|
|
95
|
+
* header; any other method is `405 A2012` with `Allow: GET`. The bytes are the ones
|
|
96
|
+
* the Contract's hash was taken over, written once, at construction.
|
|
84
97
|
*/
|
|
85
98
|
readonly encodeContract: (request: AvProtocolRequest) => AvProtocolResponse;
|
|
86
99
|
/**
|
|
@@ -91,12 +104,22 @@ export type AvProtocolBinding = {
|
|
|
91
104
|
* `undefined` for a path outside the protocol's namespace, which the host
|
|
92
105
|
* answers itself. An operation or `/_transactions` route answered `500 A3000`
|
|
93
106
|
* is also reported once to the Framework's diagnostics sink, as an
|
|
94
|
-
* `
|
|
107
|
+
* `AvUnmountedRouteError` naming the route the host did not mount.
|
|
95
108
|
*/
|
|
96
109
|
readonly answerAbsent: (request: AvProtocolRequest) => AvProtocolResponse | undefined;
|
|
97
110
|
};
|
|
98
111
|
/**
|
|
99
|
-
* `AvProtocol.bind(framework)`: reads the instance's compiled
|
|
100
|
-
*
|
|
112
|
+
* `AvProtocol.bind(framework, options?)`: reads the instance's compiled Client
|
|
113
|
+
* Contract (or, with `{ origin: "agent" }`, its Agent Contract) once and returns
|
|
114
|
+
* the bound members, frozen. Every request decoded through it runs under that
|
|
115
|
+
* origin.
|
|
101
116
|
*/
|
|
102
|
-
export declare function bind(framework:
|
|
117
|
+
export declare function bind(framework: AvFramework, options?: {
|
|
118
|
+
/**
|
|
119
|
+
* The origin every request through this binding runs under: `"client"`
|
|
120
|
+
* (the default: the Client Contract, `/_contract`'s document) or `"agent"`
|
|
121
|
+
* (the Agent Contract, its hash and its layer's pipelines), for a host
|
|
122
|
+
* that serves an AI agent — an MCP server.
|
|
123
|
+
*/
|
|
124
|
+
readonly origin?: "client" | "agent";
|
|
125
|
+
}): AvProtocolBinding;
|
|
@@ -7,13 +7,16 @@ import { encodeOperationResponse, encodeTransactionResponse, } from "./http-resp
|
|
|
7
7
|
import { handleOperationRequest, handleTransactionRequest, operationUnencodableReport, planUnencodableReport, } from "./protocol.handler.js";
|
|
8
8
|
import { transportFailure } from "./protocol-failure.js";
|
|
9
9
|
import { surfaceOf } from "./protocol-surface.js";
|
|
10
|
-
export function bind(framework) {
|
|
10
|
+
export function bind(framework, options) {
|
|
11
11
|
const { contracts } = framework;
|
|
12
|
-
const
|
|
13
|
-
const
|
|
12
|
+
const origin = options?.origin === "agent" ? "agent" : "client";
|
|
13
|
+
const contract = contracts[origin];
|
|
14
|
+
const surface = surfaceOf(contract);
|
|
15
|
+
const document = contractDocumentOf(contract);
|
|
14
16
|
const sink = diagnosticsSinkOf(framework);
|
|
15
17
|
const handler = {
|
|
16
18
|
contracts,
|
|
19
|
+
origin,
|
|
17
20
|
execute: (request) => framework.execute(request),
|
|
18
21
|
executeTransaction: (request) => framework.executeTransaction(request),
|
|
19
22
|
owned: ownedExecutionOf(framework),
|
|
@@ -21,16 +24,16 @@ export function bind(framework) {
|
|
|
21
24
|
};
|
|
22
25
|
return Object.freeze({
|
|
23
26
|
surface: () => surface,
|
|
24
|
-
decodeOperation: (request) => decodeOperationRequest(contracts, request),
|
|
25
|
-
decodeTransaction: (request) => decodeTransactionRequest(contracts, request),
|
|
27
|
+
decodeOperation: (request) => decodeOperationRequest(contracts, request, origin),
|
|
28
|
+
decodeTransaction: (request) => decodeTransactionRequest(contracts, request, origin),
|
|
26
29
|
encodeOperation: (response, requestId, decoded) => encodeOperationResponse(response, requestId, decoded === undefined
|
|
27
30
|
? undefined
|
|
28
31
|
: operationUnencodableReport(sink, decoded.request)),
|
|
29
|
-
encodeTransaction: (response, requestId) => encodeTransactionResponse(response, requestId, planUnencodableReport(sink, requestId)),
|
|
32
|
+
encodeTransaction: (response, requestId) => encodeTransactionResponse(response, requestId, planUnencodableReport(sink, requestId, origin)),
|
|
30
33
|
failure: transportFailure,
|
|
31
|
-
handleOperation: (request) => handleOperationRequest(handler, request),
|
|
32
|
-
handleTransaction: (request) => handleTransactionRequest(handler, request),
|
|
34
|
+
handleOperation: (request, options) => handleOperationRequest(handler, request, options),
|
|
35
|
+
handleTransaction: (request, options) => handleTransactionRequest(handler, request, options),
|
|
33
36
|
encodeContract: (request) => encodeContractRequest(document, request),
|
|
34
|
-
answerAbsent: (request) => answerAbsentRequest(contracts, request, sink),
|
|
37
|
+
answerAbsent: (request) => answerAbsentRequest(contracts, request, sink, origin),
|
|
35
38
|
});
|
|
36
39
|
}
|