@aventara/core 1.0.0-rc.3 → 1.0.0-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +130 -1
  2. package/ERRORS.md +6 -6
  3. package/README.md +72 -12
  4. package/dist/adapters/adapter-operation.d.ts +7 -0
  5. package/dist/compiler/contract.compiler.d.ts +6 -0
  6. package/dist/compiler/contract.compiler.js +73 -12
  7. package/dist/config/computed-fields.js +2 -9
  8. package/dist/config/config-diagnostic.guidance.js +3 -3
  9. package/dist/config/config.resolver.d.ts +14 -0
  10. package/dist/config/config.resolver.js +31 -0
  11. package/dist/config/config.validator.js +82 -0
  12. package/dist/config/exact-framework-config.d.ts +5 -0
  13. package/dist/config/framework-config.d.ts +26 -1
  14. package/dist/contracts/client-contract-structure.validator.d.ts +8 -0
  15. package/dist/contracts/client-contract-structure.validator.js +6 -1
  16. package/dist/contracts/field.d.ts +11 -0
  17. package/dist/framework/contract-view.d.ts +41 -10
  18. package/dist/framework/framework.factory.js +39 -11
  19. package/dist/framework/operation-facade.d.ts +24 -5
  20. package/dist/framework/operation-facade.js +2 -1
  21. package/dist/index.d.ts +4 -1
  22. package/dist/internal.d.ts +1 -0
  23. package/dist/internal.js +1 -0
  24. package/dist/operations/operation-arguments.d.ts +1 -1
  25. package/dist/operations/operation-call.d.ts +9 -5
  26. package/dist/operations/operation-result.d.ts +5 -3
  27. package/dist/operations/operation-validator-core.js +6 -0
  28. package/dist/policy/policy-admission.d.ts +22 -0
  29. package/dist/policy/policy-admission.js +400 -0
  30. package/dist/policy/policy-after-update.runtime.d.ts +29 -0
  31. package/dist/policy/policy-after-update.runtime.js +131 -0
  32. package/dist/policy/policy-condition.d.ts +15 -0
  33. package/dist/policy/policy-condition.js +36 -0
  34. package/dist/policy/policy-engine.d.ts +111 -0
  35. package/dist/policy/policy-engine.js +1 -0
  36. package/dist/policy/policy-nested-write.runtime.d.ts +38 -0
  37. package/dist/policy/policy-nested-write.runtime.js +449 -0
  38. package/dist/policy/policy-read.runtime.d.ts +83 -0
  39. package/dist/policy/policy-read.runtime.js +494 -0
  40. package/dist/policy/policy-request.d.ts +37 -0
  41. package/dist/policy/policy-request.js +52 -0
  42. package/dist/policy/policy-session.d.ts +83 -0
  43. package/dist/policy/policy-session.js +234 -0
  44. package/dist/policy/policy-startup.validator.d.ts +8 -0
  45. package/dist/policy/policy-startup.validator.js +106 -0
  46. package/dist/policy/policy-write.runtime.d.ts +30 -0
  47. package/dist/policy/policy-write.runtime.js +394 -0
  48. package/dist/prebuilt/core-version.generated.d.ts +2 -0
  49. package/dist/prebuilt/core-version.generated.js +1 -0
  50. package/dist/prebuilt/prebuilt-contracts.d.ts +40 -0
  51. package/dist/prebuilt/prebuilt-contracts.emitter.d.ts +16 -0
  52. package/dist/prebuilt/prebuilt-contracts.emitter.js +50 -0
  53. package/dist/prebuilt/prebuilt-contracts.js +1 -0
  54. package/dist/prebuilt/prebuilt-contracts.loader.d.ts +21 -0
  55. package/dist/prebuilt/prebuilt-contracts.loader.js +122 -0
  56. package/dist/prebuilt/prebuilt-inputs.fingerprint.d.ts +16 -0
  57. package/dist/prebuilt/prebuilt-inputs.fingerprint.js +192 -0
  58. package/dist/runtime/computed-read-runtime.d.ts +6 -1
  59. package/dist/runtime/computed-read-runtime.js +224 -45
  60. package/dist/runtime/context-executor.runtime.js +4 -2
  61. package/dist/runtime/execution-options.d.ts +8 -0
  62. package/dist/runtime/framework-warning.emitter.d.ts +6 -0
  63. package/dist/runtime/framework-warning.emitter.js +8 -0
  64. package/dist/runtime/level-lifecycle.runtime.js +3 -2
  65. package/dist/runtime/operation-code.guidance.js +3 -3
  66. package/dist/runtime/operation-request.d.ts +7 -0
  67. package/dist/runtime/operation-runtime.d.ts +9 -1
  68. package/dist/runtime/operation-runtime.js +114 -10
  69. package/dist/runtime/readonly-value.d.ts +5 -1
  70. package/dist/runtime/readonly-value.js +67 -28
  71. package/dist/transactions/transaction-runtime.d.ts +4 -1
  72. package/dist/transactions/transaction-runtime.js +27 -5
  73. package/package.json +2 -2
@@ -5,6 +5,8 @@ const ROOT_ONLY_PROPERTIES = new Set([
5
5
  "api",
6
6
  "mcp",
7
7
  "adapter",
8
+ "prebuilt",
9
+ "policy",
8
10
  "diagnostics",
9
11
  "misuse",
10
12
  "application",
@@ -618,6 +620,14 @@ export function validateFrameworkConfig(value) {
618
620
  else {
619
621
  validateAdapter(value.adapter, diagnostics);
620
622
  }
623
+ if (Object.hasOwn(value, "prebuilt") &&
624
+ value.prebuilt !== undefined &&
625
+ (value.prebuilt === null || typeof value.prebuilt !== "object")) {
626
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "prebuilt", "prebuilt must be the generated prebuilt Contracts object when provided"));
627
+ }
628
+ if (Object.hasOwn(value, "policy") && value.policy !== undefined) {
629
+ validatePolicy(value.policy, diagnostics);
630
+ }
621
631
  if (Object.hasOwn(value, "diagnostics") &&
622
632
  value.diagnostics !== undefined &&
623
633
  typeof value.diagnostics !== "function") {
@@ -639,6 +649,78 @@ export function validateFrameworkConfig(value) {
639
649
  }
640
650
  return diagnostics;
641
651
  }
652
+ const POLICY_PROPERTIES = new Set(["engine", "principal"]);
653
+ function validatePolicy(value, diagnostics) {
654
+ if (!isPlainRecord(value)) {
655
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "policy", "policy must be { engine, principal }"));
656
+ return;
657
+ }
658
+ for (const key of Object.keys(value)) {
659
+ if (!POLICY_PROPERTIES.has(key)) {
660
+ diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", `policy.${key}`, `unknown policy property: ${key}`));
661
+ }
662
+ }
663
+ if (!Object.hasOwn(value, "principal")) {
664
+ diagnostics.push(diagnostic("CONFIG_REQUIRED", "policy.principal", "policy.principal is required"));
665
+ }
666
+ else if (typeof value.principal !== "function") {
667
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "policy.principal", "policy.principal must be a function"));
668
+ }
669
+ if (!Object.hasOwn(value, "engine")) {
670
+ diagnostics.push(diagnostic("CONFIG_REQUIRED", "policy.engine", "policy.engine is required"));
671
+ return;
672
+ }
673
+ const engine = value.engine;
674
+ if (engine === null || typeof engine !== "object") {
675
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "policy.engine", "policy.engine must be an object"));
676
+ return;
677
+ }
678
+ const members = engine;
679
+ for (const question of ["can", "scopeOf", "fieldsOf"]) {
680
+ if (typeof members[question] !== "function") {
681
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `policy.engine.${question}`, `policy.engine.${question} must be a function`));
682
+ }
683
+ }
684
+ validatePolicyLists(members.governed, "governed", { all: "string lists", one: "a list of strings" }, isStringList, diagnostics);
685
+ validatePolicyLists(members.paths, "paths", {
686
+ all: "path lists",
687
+ one: "a list of paths, each a list of strings",
688
+ }, (paths) => Array.isArray(paths) && paths.every(isStringList), diagnostics);
689
+ validatePolicyLists(members.afterChecks, "afterChecks", { all: "action lists", one: "a list of actions" }, isStringList, diagnostics);
690
+ validateAfterCheckActions(members.afterChecks, diagnostics);
691
+ }
692
+ function validateAfterCheckActions(lists, diagnostics) {
693
+ if (!isPlainRecord(lists)) {
694
+ return;
695
+ }
696
+ for (const [resource, actions] of Object.entries(lists)) {
697
+ if (!isStringList(actions)) {
698
+ continue;
699
+ }
700
+ for (const action of actions) {
701
+ if (action !== "update") {
702
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", `policy.engine.afterChecks.${resource}`, `policy.engine.afterChecks.${resource}: "${action}" is no action an after check runs on; only "update" is`));
703
+ }
704
+ }
705
+ }
706
+ }
707
+ function isStringList(value) {
708
+ return (Array.isArray(value) && value.every((name) => typeof name === "string"));
709
+ }
710
+ function validatePolicyLists(lists, list, entry, isEntry, diagnostics) {
711
+ if (lists === undefined) {
712
+ return;
713
+ }
714
+ if (!isPlainRecord(lists)) {
715
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `policy.engine.${list}`, `policy.engine.${list} must be an object of ${entry.all} when provided`));
716
+ return;
717
+ }
718
+ for (const [key, value] of Object.entries(lists)) {
719
+ if (!isEntry(value)) {
720
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `policy.engine.${list}.${key}`, `policy.engine.${list}.${key} must be ${entry.one}`));
721
+ }
722
+ }
723
+ }
642
724
  function validateMcp(value, api, diagnostics) {
643
725
  if (typeof value === "string") {
644
726
  validateMcpPath(value, "mcp", api, diagnostics);
@@ -238,6 +238,11 @@ type RootSchema<M extends AvAdapterModel, Cfg> = LayerKeysSchema & {
238
238
  readonly api: Leaf;
239
239
  readonly mcp: McpSchema;
240
240
  readonly adapter: Leaf;
241
+ readonly prebuilt: Leaf;
242
+ readonly policy: {
243
+ readonly engine: Leaf;
244
+ readonly principal: Leaf;
245
+ };
241
246
  readonly diagnostics: Leaf;
242
247
  readonly misuse: Leaf;
243
248
  readonly resources: RootResourcesSchema<M>;
@@ -2,10 +2,13 @@ import type { AvAdapter } from "../adapters/adapter.interface.js";
2
2
  import type { AvAdapterModel } from "../adapters/adapter-model.js";
3
3
  import type { AvContractLimits } from "../contracts/contract-limits.js";
4
4
  import type { AvTransactionCapability } from "../contracts/transaction-capability.js";
5
+ import type { AvPolicyEngine } from "../policy/policy-engine.js";
6
+ import type { AvPrebuiltContracts } from "../prebuilt/prebuilt-contracts.js";
5
7
  import type { AvDiagnosticsSink } from "../runtime/diagnostics-reporter.js";
6
8
  import type { AvMisuseSink } from "../runtime/misuse-reporter.js";
9
+ import type { AvState } from "../runtime/request-state.js";
7
10
  import type { AvConfigAny } from "./any-framework-config.js";
8
- import type { AvConfigLayerName } from "./config-layer.js";
11
+ import type { AvConfigLayerName, AvRequestOrigin } from "./config-layer.js";
9
12
  import type { AvConfigExemptions } from "./framework-exemptions-config.js";
10
13
  import type { AvConfigLayerKind, AvConfigResources, LayerOfKind } from "./framework-resources-config.js";
11
14
  import type { AvPipeline } from "./pipeline-config.js";
@@ -71,6 +74,28 @@ export type AvConfig<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAn
71
74
  */
72
75
  readonly mcp?: AvConfigMcp;
73
76
  readonly adapter: AvAdapter<M>;
77
+ /**
78
+ * Contracts compiled ahead of time (the generated `aventaraContracts`), for a
79
+ * fast cold start on serverless and edge platforms. Used only when they were
80
+ * compiled from this configuration and the adapter's model by this core;
81
+ * otherwise the Contracts are compiled at startup, as without it, and a
82
+ * `AVENTARA_PREBUILT_STALE` warning says why.
83
+ */
84
+ readonly prebuilt?: AvPrebuiltContracts;
85
+ /**
86
+ * The policy engine every client and agent request is checked against, and
87
+ * how a request's principal is derived from its `ctx.$state`. Application
88
+ * calls bypass it unless they name a principal (`{ as }`); calls a stage
89
+ * makes through `ctx` always do.
90
+ */
91
+ readonly policy?: {
92
+ readonly engine: AvPolicyEngine;
93
+ /** The request's principal, from its `ctx.$state` and its layer; `null` for an anonymous caller. */
94
+ readonly principal: (facts: {
95
+ readonly $state: AvState;
96
+ readonly $origin: AvRequestOrigin;
97
+ }) => unknown;
98
+ };
74
99
  readonly diagnostics?: AvDiagnosticsSink;
75
100
  /** Told about every caller value refused as unreadable or not plain data. */
76
101
  readonly misuse?: AvMisuseSink;
@@ -498,6 +498,10 @@ export declare const CLIENT_CONTRACT_STRUCTURE: {
498
498
  readonly minimum: 0;
499
499
  readonly unique: false;
500
500
  };
501
+ readonly governed: {
502
+ readonly is: "literal";
503
+ readonly values: readonly [true];
504
+ };
501
505
  };
502
506
  };
503
507
  readonly relation: {
@@ -694,6 +698,10 @@ export declare const CLIENT_CONTRACT_STRUCTURE: {
694
698
  readonly minimum: 1;
695
699
  readonly unique: false;
696
700
  };
701
+ readonly governed: {
702
+ readonly is: "literal";
703
+ readonly values: readonly [true];
704
+ };
697
705
  };
698
706
  };
699
707
  };
@@ -237,6 +237,7 @@ const SCALAR_FIELD = object({
237
237
  format: STRING,
238
238
  json: { is: "jsonSchema" },
239
239
  validators: list(FIELD_CHECK),
240
+ governed: literal([true]),
240
241
  });
241
242
  const RELATION_FIELD = object({
242
243
  kind: literal(["relation"]),
@@ -257,7 +258,11 @@ const RELATION_FIELD = object({
257
258
  update: RELATION_MUTATION,
258
259
  nestedWriteFilter: literal(["scalar"]),
259
260
  }),
260
- }, { inverse: STRING, referenceFields: nonEmptyList(STRING) });
261
+ }, {
262
+ inverse: STRING,
263
+ referenceFields: nonEmptyList(STRING),
264
+ governed: literal([true]),
265
+ });
261
266
  const OPERATION_AVAILABILITY = union(literal([true]), object({ projection: literal(PROJECTION_SCOPES) }, { write: literal(WRITE_SCOPES) }), object({ write: literal(WRITE_SCOPES) }, { projection: literal(PROJECTION_SCOPES) }));
262
267
  const RESOURCE = object({
263
268
  fields: registry({
@@ -138,6 +138,12 @@ export type AvScalarField<C extends AvContract> = {
138
138
  * `list: true` length check, which applies to the list.
139
139
  */
140
140
  readonly validators?: readonly AvFieldCheck[];
141
+ /**
142
+ * `true` when the policy governs the field: it is left out of every default
143
+ * projection, and a caller that wants it names it (`select: ["$defaults",
144
+ * "email"]`).
145
+ */
146
+ readonly governed?: true;
141
147
  };
142
148
  /** A relation field; the `target` Resource describes the related row. */
143
149
  export type AvRelationField<C extends AvContract> = {
@@ -162,6 +168,11 @@ export type AvRelationField<C extends AvContract> = {
162
168
  * holds no reference, and where the layer shows none of them.
163
169
  */
164
170
  readonly referenceFields?: readonly [string, ...string[]];
171
+ /**
172
+ * `true` when the policy engine's `governed` set names the relation: including
173
+ * it on rows the caller may not read it on refuses the request.
174
+ */
175
+ readonly governed?: true;
165
176
  };
166
177
  /** One field of a Resource: a scalar or a relation. */
167
178
  export type AvField<C extends AvContract> = AvScalarField<C> | AvRelationField<C>;
@@ -17,6 +17,14 @@ type RootBlock<Cfg, Key extends PropertyKey> = LiteralRecord<(Cfg & {
17
17
  })[Key]>;
18
18
  /** The root's `resources` block, its stages erased. */
19
19
  type ResourcesBlock<Cfg> = ErasedResources<RootBlock<Cfg, "resources">>;
20
+ /** A `resources` block reduced to the `fields` entries the view reads. */
21
+ type ViewBlock<Block> = [Block] extends [never] ? never : {
22
+ readonly [R in keyof Block as "fields" extends keyof NonNullable<Block[R]> ? R : never]: {
23
+ readonly fields: (NonNullable<Block[R]> & {
24
+ readonly fields?: unknown;
25
+ })["fields"];
26
+ };
27
+ };
20
28
  /** An overlay's `resources` block, its stages erased (see {@link ResourcesBlock}). */
21
29
  type OverlayResourcesBlock<Cfg, Layer extends AvRequestOrigin> = ErasedResources<LiteralRecord<(LiteralRecord<OverlayOf<Cfg, Layer>> & {
22
30
  readonly resources?: unknown;
@@ -90,12 +98,33 @@ type DefinitionOf<FieldEntry> = EntryOf<FieldEntry, "definition">;
90
98
  type LayeredFields<ModelFields, ResourceConfig> = {
91
99
  readonly [F in keyof ModelFields | AddedFieldKey<ModelFields, ResourceConfig>]: F extends keyof ModelFields ? LayeredModelField<ModelFields[F], DefinitionOf<EntryOf<ResourceConfig, F>>> : AddedField<DefinitionOf<EntryOf<ResourceConfig, F>>>;
92
100
  };
101
+ /** The configuration's `policy.engine`, read by indexed access (see {@link RootBlock}). */
102
+ type PolicyEngineOf<Cfg> = (NonNullable<(Cfg & {
103
+ readonly policy?: unknown;
104
+ })["policy"]> & {
105
+ readonly engine?: unknown;
106
+ })["engine"];
107
+ /** The configuration's policy engine's `governed` set, when its type states one. */
108
+ type GovernedBlock<Cfg> = LiteralRecord<(NonNullable<PolicyEngineOf<Cfg>> & {
109
+ readonly governed?: unknown;
110
+ })["governed"]>;
111
+ /** The names `Governed` lists for Resource `R`, or `never`. */
112
+ type GovernedNames<Governed, R> = [Governed] extends [never] ? never : R extends keyof Governed ? Governed[R] extends readonly (infer Name)[] ? Name : never : never;
113
+ /** The `governed: true` mark, added to a field: a key the field does not have. */
114
+ type GovernedMark = {
115
+ readonly governed: true;
116
+ };
117
+ /** A Resource's fields with each governed one marked. */
118
+ type GovernedFields<Fields, Governed> = [Governed] extends [never] ? Fields : {
119
+ readonly [F in keyof Fields]: F extends Governed ? Fields[F] & GovernedMark : Fields[F];
120
+ };
93
121
  /**
94
122
  * One Resource before exposure: the model's own, with its fields layered and
95
- * its create requirements less what the layers' compute stages fill.
123
+ * marked where governed, and its create requirements less what the layers'
124
+ * compute stages fill.
96
125
  */
97
- type LayeredResource<in out Resource, in out ResourceConfig, in out OverlayConfig> = {
98
- readonly [P in keyof Resource]: P extends "fields" ? LayeredFields<Resource[P], EntryOf<ResourceConfig, "fields">> : P extends "createRequirements" ? RequirementsLessComputed<Exclude<Resource[P], undefined>, ComputedOnCreateKey<EntryOf<ResourceConfig, "fields">> | ComputedOnCreateKey<EntryOf<OverlayConfig, "fields">>> : Resource[P];
126
+ type LayeredResource<in out Resource, in out ResourceConfig, in out OverlayConfig, in out Governed = never> = {
127
+ readonly [P in keyof Resource]: P extends "fields" ? GovernedFields<LayeredFields<Resource[P], EntryOf<ResourceConfig, "fields">>, Governed> : P extends "createRequirements" ? RequirementsLessComputed<Exclude<Resource[P], undefined>, ComputedOnCreateKey<EntryOf<ResourceConfig, "fields">> | ComputedOnCreateKey<EntryOf<OverlayConfig, "fields">>> : Resource[P];
99
128
  };
100
129
  /** The fields of a `fields` block with a `compute.create` stage. */
101
130
  type ComputedOnCreateKey<FieldsBlock> = [FieldsBlock] extends [never] ? never : {
@@ -132,8 +161,8 @@ type GroupsLessComputed<Groups, Computed> = Groups extends readonly [
132
161
  ...GroupsLessComputed<Rest, Computed>
133
162
  ] : GroupsLessComputed<Rest, Computed> : readonly [];
134
163
  /** The Resources before exposure: the model, with the root's definitions applied. */
135
- type LayeredResources<Resources, Block, OverlayBlock> = {
136
- readonly [R in keyof Resources]: LayeredResource<Resources[R], EntryOf<Block, R>, EntryOf<OverlayBlock, R>>;
164
+ type LayeredResources<Resources, Block, OverlayBlock, Governed = never> = {
165
+ readonly [R in keyof Resources]: LayeredResource<Resources[R], EntryOf<Block, R>, EntryOf<OverlayBlock, R>, GovernedNames<Governed, R>>;
137
166
  };
138
167
  /**
139
168
  * The style a layer's `exposed` sets: `false` picks, `true` or absent omits, a
@@ -289,13 +318,15 @@ export type RootViewResources<M extends AvAdapterModel, Cfg> = ExposedResources<
289
318
  /** The Resources of an overlay's final view: the root's view, narrowed by it. */
290
319
  export type OverlayViewResources<M extends AvAdapterModel, Cfg, Layer extends "application" | "client"> = ExposedResources<ExposedResources<LayeredResources<M["resources"], ResourcesBlock<Cfg>, OverlayResourcesBlock<Cfg, Layer>>, ExposureStyleOf<ExposedOf<Cfg>>, ExemptionsOf<Cfg>>, ExposureStyleOf<ExposedOf<OverlayOf<Cfg, Layer>>>, ExemptionsOf<OverlayOf<Cfg, Layer>>>;
291
320
  /**
292
- * One derived Contract's type: the model, with the root's `resources` block
321
+ * One derived Contract's type: the model, with the root's `fields` entries
293
322
  * applied, then the root's exposure, then the overlay's over the root's view.
323
+ * `framework.application`, `client`, `appTx` and `clientTx` are typed over it,
324
+ * and a declaration file names it when it writes one of their nodes.
294
325
  */
295
- type DerivedContractView<M extends AvAdapterModel, FieldsBlock, RootStyle, RootExemptions, OverlayStyle, OverlayExemptions, OverlayBlock> = {
326
+ export type AvContractView<M extends AvAdapterModel, RootFields, RootStyle, RootExemptions, OverlayStyle, OverlayExemptions, OverlayFields, Governed = never> = {
296
327
  readonly scalars: M["scalars"];
297
328
  readonly enums: M["enums"];
298
- readonly resources: ExposedResources<ExposedResources<LayeredResources<M["resources"], FieldsBlock, OverlayBlock>, RootStyle, RootExemptions>, OverlayStyle, OverlayExemptions>;
329
+ readonly resources: ExposedResources<ExposedResources<LayeredResources<M["resources"], RootFields, OverlayFields, Governed>, RootStyle, RootExemptions>, OverlayStyle, OverlayExemptions>;
299
330
  readonly limits: AvContractLimits;
300
331
  readonly transactions: M["transactions"];
301
332
  };
@@ -303,7 +334,7 @@ type DerivedContractView<M extends AvAdapterModel, FieldsBlock, RootStyle, RootE
303
334
  * The Application Contract's type, derived from the adapter model and the
304
335
  * configuration.
305
336
  */
306
- export type AvContractApplicationView<M extends AvAdapterModel, Cfg = AvConfigAny> = [Cfg] extends [unknown] ? DerivedContractView<M, ResourcesBlock<Cfg>, ExposureStyleOf<ExposedOf<Cfg>>, ExemptionsOf<Cfg>, ExposureStyleOf<ExposedOf<OverlayOf<Cfg, "application">>>, ExemptionsOf<OverlayOf<Cfg, "application">>, OverlayResourcesBlock<Cfg, "application">> : never;
337
+ export type AvContractApplicationView<M extends AvAdapterModel, Cfg = AvConfigAny> = [Cfg] extends [unknown] ? AvContractView<M, ViewBlock<ResourcesBlock<Cfg>>, ExposureStyleOf<ExposedOf<Cfg>>, ExemptionsOf<Cfg>, ExposureStyleOf<ExposedOf<OverlayOf<Cfg, "application">>>, ExemptionsOf<OverlayOf<Cfg, "application">>, ViewBlock<OverlayResourcesBlock<Cfg, "application">>, GovernedBlock<Cfg>> : never;
307
338
  /**
308
339
  * The Client Contract's type, derived from the adapter model and the
309
340
  * configuration: what the client layer hides is absent. It types
@@ -311,5 +342,5 @@ export type AvContractApplicationView<M extends AvAdapterModel, Cfg = AvConfigAn
311
342
  */
312
343
  export type ClientContractView<M extends AvAdapterModel, Cfg = AvConfigAny> = [
313
344
  Cfg
314
- ] extends [unknown] ? DerivedContractView<M, ResourcesBlock<Cfg>, ExposureStyleOf<ExposedOf<Cfg>>, ExemptionsOf<Cfg>, ExposureStyleOf<ExposedOf<OverlayOf<Cfg, "client">>>, ExemptionsOf<OverlayOf<Cfg, "client">>, OverlayResourcesBlock<Cfg, "client">> : never;
345
+ ] extends [unknown] ? AvContractView<M, ViewBlock<ResourcesBlock<Cfg>>, ExposureStyleOf<ExposedOf<Cfg>>, ExemptionsOf<Cfg>, ExposureStyleOf<ExposedOf<OverlayOf<Cfg, "client">>>, ExemptionsOf<OverlayOf<Cfg, "client">>, ViewBlock<OverlayResourcesBlock<Cfg, "client">>, GovernedBlock<Cfg>> : never;
315
346
  export {};
@@ -1,9 +1,12 @@
1
- import { compileContracts } from "../compiler/contract.compiler.js";
1
+ import { compileContracts, } from "../compiler/contract.compiler.js";
2
2
  import { computedFieldsOf, warnOnStaleComputedFields, } from "../config/computed-fields.js";
3
- import { resolveFrameworkConfig } from "../config/config.resolver.js";
3
+ import { resolveFrameworkConfig, } from "../config/config.resolver.js";
4
4
  import { validateFrameworkConfig } from "../config/config.validator.js";
5
5
  import { validateForcedOperations } from "../config/forced-operation.validator.js";
6
6
  import { AVENTARA_PROTOCOL_VERSION } from "../contracts/contract-protocol.js";
7
+ import { callerOf } from "../policy/policy-request.js";
8
+ import { policyStartupDiagnostics } from "../policy/policy-startup.validator.js";
9
+ import { loadPrebuiltContracts, warnStalePrebuilt, } from "../prebuilt/prebuilt-contracts.loader.js";
7
10
  import { copyEnvelopeAtDoor, refuseCallerData, } from "../runtime/caller-data.door.js";
8
11
  import { createDiagnosticsReporter, createTransactionDiagnosticsChannel, recordDiagnosticsSink, } from "../runtime/diagnostics-reporter.js";
9
12
  import { createMisuseReporter, } from "../runtime/misuse-reporter.js";
@@ -39,7 +42,9 @@ export async function createFramework(config) {
39
42
  trees: resolvedConfig.trees,
40
43
  agentExtends: resolvedConfig.agent.parent,
41
44
  }));
42
- const compilation = await compileContracts(model, resolvedConfig);
45
+ const compilation = (config.prebuilt === undefined
46
+ ? undefined
47
+ : await prebuiltCompilation(config.prebuilt, model, config, resolvedConfig)) ?? (await compileContracts(model, resolvedConfig));
43
48
  if (!compilation.ok) {
44
49
  throw new AvConstructionError("contract-compilation", compilation.diagnostics);
45
50
  }
@@ -47,6 +52,12 @@ export async function createFramework(config) {
47
52
  if (forcing.length > 0) {
48
53
  throw new AvConstructionError("configuration", forcing);
49
54
  }
55
+ if (resolvedConfig.policy !== undefined) {
56
+ const policy = policyStartupDiagnostics(compilation.contracts.core, resolvedConfig.policy);
57
+ if (policy.length > 0) {
58
+ throw new AvConstructionError("configuration", policy);
59
+ }
60
+ }
50
61
  const runtimeDependencies = {
51
62
  adapter: config.adapter,
52
63
  contracts: compilation.contracts,
@@ -56,7 +67,7 @@ export async function createFramework(config) {
56
67
  const execute = createOperationRuntime(runtimeDependencies, pipelineDependencies);
57
68
  const executeTransaction = createTransactionRuntime(runtimeDependencies, pipelineDependencies);
58
69
  const misuse = createMisuseReporter(resolvedConfig.misuse);
59
- const executeOperation = (request) => executeTotally(execute, request, resolvedConfig.diagnostics, "caller");
70
+ const executeOperation = (request, caller) => executeTotally(execute, request, resolvedConfig.diagnostics, "caller", caller);
60
71
  const protocol = {
61
72
  version: AVENTARA_PROTOCOL_VERSION,
62
73
  hash: compilation.contracts.client.protocol.hash,
@@ -90,7 +101,7 @@ export async function createFramework(config) {
90
101
  clientTx: createOperationTree(model, (resource, identity) => (args) => assembler.defer("client", resource, identity, args === undefined ? {} : args)),
91
102
  execute: (request) => executeRequestTotally(execute, request, resolvedConfig.diagnostics, misuse),
92
103
  executeTransaction: (request) => executeTransactionRequestTotally(executeTransaction, request, resolvedConfig.diagnostics, misuse),
93
- transaction: (async (operations, options) => settleOperation(await runTransactionTotally(executeTransaction, assembler, operations, requestIdOf(options), stateOptionOf(options), resolvedConfig.diagnostics))),
104
+ transaction: (async (operations, options) => settleOperation(await runTransactionTotally(executeTransaction, assembler, operations, requestIdOf(options), stateOptionOf(options), resolvedConfig.diagnostics, callerOf(options)))),
94
105
  };
95
106
  recordDiagnosticsSink(framework, resolvedConfig.diagnostics);
96
107
  recordOwnedExecution(framework, {
@@ -101,10 +112,27 @@ export async function createFramework(config) {
101
112
  });
102
113
  return framework;
103
114
  }
104
- async function executeTotally(execute, request, diagnostics, source) {
115
+ async function prebuiltCompilation(prebuilt, model, config, resolved) {
116
+ let loaded;
117
+ try {
118
+ loaded = await loadPrebuiltContracts(prebuilt, model, config, resolved);
119
+ }
120
+ catch (error) {
121
+ loaded = {
122
+ ok: false,
123
+ reason: `it could not be read (${error instanceof Error ? error.message : String(error)})`,
124
+ };
125
+ }
126
+ if (!loaded.ok) {
127
+ warnStalePrebuilt(loaded.reason);
128
+ return undefined;
129
+ }
130
+ return { ok: true, contracts: loaded.contracts };
131
+ }
132
+ async function executeTotally(execute, request, diagnostics, source, caller) {
105
133
  const report = createDiagnosticsReporter(diagnostics, request);
106
134
  try {
107
- return await execute(request, report, source);
135
+ return await execute(request, report, source, caller);
108
136
  }
109
137
  catch (error) {
110
138
  report(error, "A3000");
@@ -145,18 +173,18 @@ function executeTransactionRequestTotally(execute, request, diagnostics, misuse)
145
173
  }
146
174
  return executeTransactionTotally(execute, envelope.value, diagnostics, undefined, { source: "caller" });
147
175
  }
148
- async function executeTransactionTotally(execute, request, diagnostics, origins, planArguments) {
176
+ async function executeTransactionTotally(execute, request, diagnostics, origins, planArguments, caller) {
149
177
  const channel = createTransactionDiagnosticsChannel(diagnostics, request);
150
178
  const report = channel.transaction();
151
179
  try {
152
- return await execute(request, channel, origins, planArguments);
180
+ return await execute(request, channel, origins, planArguments, caller);
153
181
  }
154
182
  catch (error) {
155
183
  report(error, "A3000");
156
184
  return internalFailure();
157
185
  }
158
186
  }
159
- async function runTransactionTotally(execute, assembler, operations, requestId, state, diagnostics) {
187
+ async function runTransactionTotally(execute, assembler, operations, requestId, state, diagnostics, caller) {
160
188
  let assembled;
161
189
  try {
162
190
  assembled = await assembler.assemble(operations);
@@ -181,5 +209,5 @@ async function runTransactionTotally(execute, assembler, operations, requestId,
181
209
  source: "owned",
182
210
  refused: assembled.refused,
183
211
  statements: assembled.statements,
184
- });
212
+ }, caller);
185
213
  }
@@ -1,9 +1,10 @@
1
1
  import type { AvAdapterModel } from "../adapters/adapter-model.js";
2
2
  import type { AvContract } from "../contracts/contract.js";
3
3
  import type { AvApplicationScalarForms, AvWireScalarForms } from "../contracts/scalar-value-type.js";
4
- import type { AvResourceKey } from "../operations/operation-arguments.js";
5
- import type { AvDeferredOperationCall, AvOperationCall, AvOperationGrammar } from "../operations/operation-call.js";
4
+ import type { AvOperationArgumentsFor, AvResourceKey } from "../operations/operation-arguments.js";
5
+ import type { AvOperationCall, AvOperationGrammar, DeferredArguments, DeferredPlainCall, DeferredProjectingCall, PlainCall, ProjectingCall } from "../operations/operation-call.js";
6
6
  import type { AvOperationIdentity } from "../operations/operation-identity.js";
7
+ import { type PolicyCaller } from "../policy/policy-request.js";
7
8
  import type { AvExecutionOptions } from "../runtime/execution-options.js";
8
9
  import type { FrameworkOperationRequest } from "../runtime/operation-request.js";
9
10
  import type { AvOperationResponse } from "../runtime/operation-response.js";
@@ -21,11 +22,29 @@ type OpaqueSurface = {
21
22
  };
22
23
  /** The four typed surfaces of an `AvFramework`, named by the member that holds each. */
23
24
  type FacadeSurface = "application" | "client" | "appTx" | "clientTx";
25
+ /** `framework.application.<Resource>.<family>.<variant>` when the variant takes a `select` or `include`. */
26
+ export type AvApplicationProjectingCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = ProjectingCall<C, R, I, AvOperationArgumentsFor<C, R, I, AvApplicationScalarForms>, AvApplicationScalarForms, AvExecutionOptions>;
27
+ /** `framework.application.<Resource>.<family>.<variant>` when it does not (the `count` variants). */
28
+ export type AvApplicationPlainCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = PlainCall<C, R, I, AvOperationArgumentsFor<C, R, I, AvApplicationScalarForms>, AvApplicationScalarForms, AvExecutionOptions>;
29
+ /** `framework.client.<Resource>.<family>.<variant>` when the variant takes a `select` or `include`: wire forms in. */
30
+ export type AvClientProjectingCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = ProjectingCall<C, R, I, AvOperationArgumentsFor<C, R, I, AvWireScalarForms>, AvApplicationScalarForms, AvExecutionOptions>;
31
+ /** `framework.client.<Resource>.<family>.<variant>` when it does not. */
32
+ export type AvClientPlainCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = PlainCall<C, R, I, AvOperationArgumentsFor<C, R, I, AvWireScalarForms>, AvApplicationScalarForms, AvExecutionOptions>;
33
+ /** `framework.appTx.<Resource>.<family>.<variant>` when the variant takes a `select` or `include`. */
34
+ export type AvAppTxProjectingCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = DeferredProjectingCall<C, R, I, DeferredArguments<C, R, I, AvApplicationScalarForms, AvApplicationScalarForms>, AvApplicationScalarForms, "application">;
35
+ /** `framework.appTx.<Resource>.<family>.<variant>` when it does not. */
36
+ export type AvAppTxPlainCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = DeferredPlainCall<C, R, I, DeferredArguments<C, R, I, AvApplicationScalarForms, AvApplicationScalarForms>, AvApplicationScalarForms, "application">;
37
+ /** `framework.clientTx.<Resource>.<family>.<variant>` when the variant takes a `select` or `include`: wire forms in. */
38
+ export type AvClientTxProjectingCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = DeferredProjectingCall<C, R, I, DeferredArguments<C, R, I, AvWireScalarForms, AvApplicationScalarForms>, AvApplicationScalarForms, "client">;
39
+ /** `framework.clientTx.<Resource>.<family>.<variant>` when it does not. */
40
+ export type AvClientTxPlainCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = DeferredPlainCall<C, R, I, DeferredArguments<C, R, I, AvWireScalarForms, AvApplicationScalarForms>, AvApplicationScalarForms, "client">;
24
41
  /**
25
42
  * One variant on a surface: a direct call (application or wire forms), or a
26
- * deferred one for a transaction (`appTx`, `clientTx`).
43
+ * deferred one for a transaction (`appTx`, `clientTx`), projecting when its
44
+ * arguments carry a `select` (as `AvOperationCall` and `AvDeferredOperationCall`
45
+ * decide it).
27
46
  */
28
- type SurfaceCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, S extends FacadeSurface> = S extends "application" ? AvOperationCall<C, R, I, AvApplicationScalarForms, AvApplicationScalarForms, AvExecutionOptions> : S extends "client" ? AvOperationCall<C, R, I, AvWireScalarForms, AvApplicationScalarForms, AvExecutionOptions> : S extends "appTx" ? AvDeferredOperationCall<C, R, I, AvApplicationScalarForms, AvApplicationScalarForms, "application"> : AvDeferredOperationCall<C, R, I, AvWireScalarForms, AvApplicationScalarForms, "client">;
47
+ type SurfaceCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, S extends FacadeSurface> = S extends "application" ? "select" extends keyof AvOperationArgumentsFor<C, R, I, AvApplicationScalarForms> ? AvApplicationProjectingCall<C, R, I> : AvApplicationPlainCall<C, R, I> : S extends "client" ? "select" extends keyof AvOperationArgumentsFor<C, R, I, AvWireScalarForms> ? AvClientProjectingCall<C, R, I> : AvClientPlainCall<C, R, I> : S extends "appTx" ? "select" extends keyof DeferredArguments<C, R, I, AvApplicationScalarForms, AvApplicationScalarForms> ? AvAppTxProjectingCall<C, R, I> : AvAppTxPlainCall<C, R, I> : "select" extends keyof DeferredArguments<C, R, I, AvWireScalarForms, AvApplicationScalarForms> ? AvClientTxProjectingCall<C, R, I> : AvClientTxPlainCall<C, R, I>;
29
48
  /** The families view `C` advertises on Resource `R`. */
30
49
  type FamilyKey<C extends AvContract, R extends AvResourceKey<C>> = keyof AvOperationGrammar<C>[R];
31
50
  /** One family node of surface `S`; the public names below are its four instances. */
@@ -131,7 +150,7 @@ type ComputeReadFacade<C> = C extends AvContract ? string extends AvResourceKey<
131
150
  } : never;
132
151
  /** Builds the request one façade call hands to `execute`, under its request id and state. */
133
152
  export type FacadeRequest = (resource: string, identity: AvOperationIdentity, args: unknown, requestId: string, state: AvState | undefined) => FrameworkOperationRequest;
134
- type FacadeExecutor = (request: FrameworkOperationRequest) => Promise<AvOperationResponse>;
153
+ type FacadeExecutor = (request: FrameworkOperationRequest, caller: PolicyCaller | undefined) => Promise<AvOperationResponse>;
135
154
  /**
136
155
  * Builds a façade over `model`, the same object its types are read from, so a
137
156
  * call that type-checks always reaches `execute`: a Resource, variant or field
@@ -1,10 +1,11 @@
1
1
  import { isOperationVariantAvailable } from "../contracts/resource-operations.js";
2
2
  import { parseOperationIdentity } from "../operations/operation-identity.js";
3
+ import { callerOf } from "../policy/policy-request.js";
3
4
  import { thrownFailure } from "../runtime/framework-error.factory.js";
4
5
  import { requestIdOf } from "../runtime/request-id.js";
5
6
  import { stateOptionOf } from "../runtime/request-state.resolver.js";
6
7
  export function createOperationFacade(model, request, execute) {
7
- return createOperationTree(model, (resource, identity) => async (args, options) => settleOperation(await execute(request(resource, identity, args === undefined ? {} : args, requestIdOf(options), stateOptionOf(options)))));
8
+ return createOperationTree(model, (resource, identity) => async (args, options) => settleOperation(await execute(request(resource, identity, args === undefined ? {} : args, requestIdOf(options), stateOptionOf(options)), callerOf(options))));
8
9
  }
9
10
  export function settleOperation(response) {
10
11
  if (response.cause !== null) {
package/dist/index.d.ts CHANGED
@@ -27,16 +27,19 @@ export type { AvOperationAvailability, AvOperationVariantScopes, AvResourceOpera
27
27
  export type { AvBuiltInScalar, AvScalarDefinition, AvScalarRegistry, } from "./contracts/scalar.js";
28
28
  export type { AvApplicationScalarForms, AvScalarValueType, AvWireScalarForms, } from "./contracts/scalar-value-type.js";
29
29
  export type { AvTransactionCapability } from "./contracts/transaction-capability.js";
30
+ export type { AvContractView } from "./framework/contract-view.js";
30
31
  export { createFramework } from "./framework/framework.factory.js";
31
32
  export type { AvFramework } from "./framework/framework.js";
32
33
  export type { AvConstructionDiagnostic, AvConstructionStage, } from "./framework/framework-construction.error.js";
33
34
  export { AvConstructionError } from "./framework/framework-construction.error.js";
34
- export type { AvApplicationFacade, AvApplicationFamilyFacade, AvApplicationResourceFacade, AvAppTxFacade, AvAppTxFamilyFacade, AvAppTxResourceFacade, AvClientFacade, AvClientFamilyFacade, AvClientResourceFacade, AvClientTxFacade, AvClientTxFamilyFacade, AvClientTxResourceFacade, } from "./framework/operation-facade.js";
35
+ export type { AvApplicationFacade, AvApplicationFamilyFacade, AvApplicationPlainCall, AvApplicationProjectingCall, AvApplicationResourceFacade, AvAppTxFacade, AvAppTxFamilyFacade, AvAppTxPlainCall, AvAppTxProjectingCall, AvAppTxResourceFacade, AvClientFacade, AvClientFamilyFacade, AvClientPlainCall, AvClientProjectingCall, AvClientResourceFacade, AvClientTxFacade, AvClientTxFamilyFacade, AvClientTxPlainCall, AvClientTxProjectingCall, AvClientTxResourceFacade, } from "./framework/operation-facade.js";
35
36
  export type { AvCreateDataInput, AvCursorInput, AvFieldKey, AvIncludeInput, AvNullsOrder, AvOperationArgumentMap, AvOperationArgumentsFor, AvOrderByEntry, AvOrderByInput, AvProjectionEntry, AvRelationProjectionInput, AvResourceKey, AvScalarOrderInput, AvSelectInput, AvSortDirection, AvUniqueWhereInput, AvUpdateDataInput, AvWhereInput, } from "./operations/operation-arguments.js";
36
37
  export type { AvDeferredOperationCall, AvOperationCall, AvOperationGrammar, AvOperationSlot, } from "./operations/operation-call.js";
37
38
  export type { AvOperationFamily, AvOperationIdentity, AvOperationVariant, } from "./operations/operation-identity.js";
38
39
  export type { AvOperationResultFor } from "./operations/operation-result.js";
39
40
  export type { AvValidationCode, AvValidationIssue, } from "./operations/validation-code.js";
41
+ export type { AvPolicyEngine, AvPolicyWhere, } from "./policy/policy-engine.js";
42
+ export type { AvPrebuiltContracts } from "./prebuilt/prebuilt-contracts.js";
40
43
  export { AvDecimal } from "./runtime/decimal.js";
41
44
  export type { AvDiagnostic, AvDiagnosticsSink, AvMcpDiagnostic, AvOperationDiagnostic, AvTransactionDiagnostic, } from "./runtime/diagnostics-reporter.js";
42
45
  export { AvErrorCatalog, type AvErrorCatalogCode, type AvErrorCatalogEntry, type AvErrorKind, } from "./runtime/error.catalog.js";
@@ -32,6 +32,7 @@ export type { AvDatabaseRefusal } from "./operations/database-refusal.js";
32
32
  export { DATABASE_REFUSALS } from "./operations/database-refusal.js";
33
33
  export type { SemanticOperationArguments } from "./operations/operation-validator.js";
34
34
  export { VALIDATION_CODES } from "./operations/validation-code.js";
35
+ export { emitPrebuiltContracts, prebuiltContractsOf, } from "./prebuilt/prebuilt-contracts.emitter.js";
35
36
  export { mcpFailureReporterOf } from "./runtime/diagnostics-reporter.js";
36
37
  export type { AvErrorClassName } from "./runtime/framework-error-class.table.js";
37
38
  export { FRAMEWORK_ERROR_CLASS_OF } from "./runtime/framework-error-class.table.js";
package/dist/internal.js CHANGED
@@ -13,6 +13,7 @@ export { BUILT_IN_SCALARS } from "./contracts/scalar.js";
13
13
  export { TRANSACTION_CAPABILITIES } from "./contracts/transaction-capability.js";
14
14
  export { DATABASE_REFUSALS } from "./operations/database-refusal.js";
15
15
  export { VALIDATION_CODES } from "./operations/validation-code.js";
16
+ export { emitPrebuiltContracts, prebuiltContractsOf, } from "./prebuilt/prebuilt-contracts.emitter.js";
16
17
  export { mcpFailureReporterOf } from "./runtime/diagnostics-reporter.js";
17
18
  export { FRAMEWORK_ERROR_CLASS_OF } from "./runtime/framework-error-class.table.js";
18
19
  export { OPERATION_CODES } from "./runtime/operation-response.js";
@@ -335,7 +335,7 @@ type IncludeRelationProjectionEntry<C extends AvContract, K extends AvResourceKe
335
335
  * One entry of a `select` argument, at one projection position. The default is
336
336
  * the unrestricted position.
337
337
  */
338
- export type AvProjectionEntry<C extends AvContract, K extends AvResourceKey<C>, Scope extends AvProjectionScope = UnrestrictedProjection, AllowCount extends boolean = false, Forms extends ScalarForms = UnstatedForms> = SelectableScalarKey<C, K, Scope> | SelectableRelationKey<C, K, Scope> | SelectRelationProjectionEntry<C, K, Scope, Forms> | (AllowCount extends true ? "$count" : never);
338
+ export type AvProjectionEntry<C extends AvContract, K extends AvResourceKey<C>, Scope extends AvProjectionScope = UnrestrictedProjection, AllowCount extends boolean = false, Forms extends ScalarForms = UnstatedForms> = SelectableScalarKey<C, K, Scope> | SelectableRelationKey<C, K, Scope> | SelectRelationProjectionEntry<C, K, Scope, Forms> | "$defaults" | (AllowCount extends true ? "$count" : never);
339
339
  /** A `select` argument: the fields to return. */
340
340
  export type AvSelectInput<C extends AvContract, K extends AvResourceKey<C>, Scope extends AvProjectionScope = UnrestrictedProjection, AllowCount extends boolean = false, Forms extends ScalarForms = UnstatedForms> = readonly AvProjectionEntry<C, K, Scope, AllowCount, Forms>[];
341
341
  /** An `include` argument: the relations to return with each row. */
@@ -55,8 +55,10 @@ export type AvOperationGrammar<C extends AvContract> = {
55
55
  export type AvOperationSlot<I extends AvOperationIdentity, Result> = I["variant"] extends "first" ? Result | null : Result;
56
56
  /** What a direct call resolves: the slot, every failure thrown. */
57
57
  type Settled<I extends AvOperationIdentity, Result> = AvOperationSlot<I, Result>;
58
- type ProjectingCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Options> = <const Select extends SelectOf<Args> = never, const Include extends IncludeOf<Args> = never>(...args: CallArgumentList<Omit<Args, ProjectionKey>, Omit<Args, ProjectionKey> & ProjectionArgument<Select, Include>, Options>) => Promise<Settled<I, AdmittedOperationResult<C, R, I, InferredProjection<Select, Include>, ResultForms>>>;
59
- type PlainCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Options> = (...args: CallArgumentList<Args, Args, Options>) => Promise<Settled<I, AdmittedOperationResult<C, R, I, unknown, ResultForms>>>;
58
+ /** A direct call that projects: generic in its `select`/`include` literal. */
59
+ export type ProjectingCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Options> = <const Select extends SelectOf<Args> = never, const Include extends IncludeOf<Args> = never>(...args: CallArgumentList<Omit<Args, ProjectionKey>, Omit<Args, ProjectionKey> & ProjectionArgument<Select, Include>, Options>) => Promise<Settled<I, AdmittedOperationResult<C, R, I, InferredProjection<Select, Include>, ResultForms>>>;
60
+ /** A direct call that does not project. */
61
+ export type PlainCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Options> = (...args: CallArgumentList<Args, Args, Options>) => Promise<Settled<I, AdmittedOperationResult<C, R, I, unknown, ResultForms>>>;
60
62
  /**
61
63
  * One direct call: its arguments in `Forms`, its result in `ResultForms`,
62
64
  * resolving the slot and throwing every failure, taking `Options` per call. It is generic in its
@@ -68,9 +70,11 @@ export type AvOperationCall<C extends AvContract, R extends AvResourceKey<C>, I
68
70
  * `$ref` typed in `ResultForms` — the forms the source's final data is read in, so a
69
71
  * reference carries what its source resolves.
70
72
  */
71
- type DeferredArguments<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Forms extends ScalarForms, ResultForms extends ScalarForms> = ReferenceableArgumentsFor<C, R, I, Forms, ResultForms>;
72
- type DeferredProjectingCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Origin extends HandleOrigin> = <const Select extends SelectOf<Args> = never, const Include extends IncludeOf<Args> = never>(...args: ArgumentList<Omit<Args, ProjectionKey>, Omit<Args, ProjectionKey> & ProjectionArgument<Select, Include>>) => AvOperation<AvOperationSlot<I, AdmittedOperationResult<C, R, I, InferredProjection<Select, Include>, ResultForms>>, Origin>;
73
- type DeferredPlainCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Origin extends HandleOrigin> = (...args: ArgumentList<Args, Args>) => AvOperation<AvOperationSlot<I, AdmittedOperationResult<C, R, I, unknown, ResultForms>>, Origin>;
73
+ export type DeferredArguments<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Forms extends ScalarForms, ResultForms extends ScalarForms> = ReferenceableArgumentsFor<C, R, I, Forms, ResultForms>;
74
+ /** A deferred operation that projects: generic in its `select`/`include` literal. */
75
+ export type DeferredProjectingCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Origin extends HandleOrigin> = <const Select extends SelectOf<Args> = never, const Include extends IncludeOf<Args> = never>(...args: ArgumentList<Omit<Args, ProjectionKey>, Omit<Args, ProjectionKey> & ProjectionArgument<Select, Include>>) => AvOperation<AvOperationSlot<I, AdmittedOperationResult<C, R, I, InferredProjection<Select, Include>, ResultForms>>, Origin>;
76
+ /** A deferred operation that does not project. */
77
+ export type DeferredPlainCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, Args, ResultForms extends ScalarForms, Origin extends HandleOrigin> = (...args: ArgumentList<Args, Args>) => AvOperation<AvOperationSlot<I, AdmittedOperationResult<C, R, I, unknown, ResultForms>>, Origin>;
74
78
  /**
75
79
  * One deferred operation: a handle typed `AvOperation<AvOperationSlot<…>, Origin>`,
76
80
  * with `$ref` present exactly where the result is one row. A handle is not a