@aventara/testing 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.
@@ -1,5 +1,5 @@
1
- import type { Framework, PipelineContext } from "@aventara/core";
2
- import { Decimal } from "@aventara/core";
1
+ import type { AvContext, AvFramework } from "@aventara/core";
2
+ import { AvDecimal } from "@aventara/core";
3
3
  /**
4
4
  * The corpus's adapter model:
5
5
  *
@@ -7,7 +7,7 @@ import { Decimal } from "@aventara/core";
7
7
  * client scope;
8
8
  * - `books`: references `authors`, and deleting an author cascades into it
9
9
  * ({@link CORPUS_REFERENTIAL_ACTIONS}; a plan's `V1019`); the client scope
10
- * adds a computed `label` to it ({@link CORPUS_CLIENT_CONFIG});
10
+ * defines a computed `label` the client alone sees ({@link CORPUS_RESOURCES});
11
11
  * - `secrets`: its one operation restricted away at client scope;
12
12
  * - `hiddenRes`: hidden at client scope;
13
13
  * - `samples`: one field of each scalar whose wire form is not its runtime
@@ -283,9 +283,9 @@ export declare const CORPUS_REFERENTIAL_ACTIONS: {
283
283
  * The `where.id` a row sends to make the corpus Framework fail one way:
284
284
  *
285
285
  * - `A4000`, `A4001`, `A4002`, `A3000` — the client guard throws
286
- * `FrameworkError("A4000")`, denies (`false`), throws
287
- * `FrameworkError("A4002")`, or throws a plain `Error`;
288
- * - `A2008`, `A2013`, `A2014` — the Adapter throws `FrameworkError` with that
286
+ * `AvError("A4000")`, denies (`false`), throws
287
+ * `AvError("A4002")`, or throws a plain `Error`;
288
+ * - `A2008`, `A2013`, `A2014` — the Adapter throws `AvError` with that
289
289
  * conflict code; `A3001` — it throws a plain `Error`;
290
290
  * - `A3002` — a plan step carrying it runs, and the Adapter's transaction then
291
291
  * fails to commit;
@@ -307,65 +307,78 @@ export declare const CORPUS_TRIGGER: {
307
307
  readonly pipeOutputInvalid: "A3004";
308
308
  };
309
309
  /** The corpus's one client guard: it decides nothing unless a row names a trigger. */
310
- declare function corpusGuard(context: PipelineContext): boolean;
310
+ declare function corpusGuard(context: AvContext): boolean;
311
311
  /**
312
312
  * The corpus's one client pipe: it rewrites nothing unless a row names the
313
313
  * `A3004` trigger, and then adds a filter on a field the server does not have.
314
314
  */
315
315
  declare function corpusPipe(args: unknown): unknown;
316
316
  /**
317
- * The corpus's client-scope configuration: what the ClientContract hides or
318
- * restricts, and `books.label`, a VIRTUAL field added at client scope and
319
- * computed on read from `id`.
317
+ * The corpus's root `resources` tree: `books.label`, a VIRTUAL field computed on
318
+ * read from `id`.
320
319
  */
321
- export declare const CORPUS_CLIENT_CONFIG: {
322
- readonly fields: {
323
- readonly books: {
320
+ export declare const CORPUS_RESOURCES: {
321
+ readonly books: {
322
+ readonly fields: {
324
323
  readonly label: {
325
- readonly type: {
326
- readonly scalar: "string";
324
+ readonly definition: {
325
+ readonly type: {
326
+ readonly scalar: "string";
327
+ };
328
+ readonly nullable: false;
329
+ readonly list: false;
330
+ readonly lifecycle: readonly ["VIRTUAL"];
331
+ };
332
+ readonly pipelines: {
333
+ readonly compute: {
334
+ readonly read: {
335
+ readonly dependsOn: readonly ["id"];
336
+ readonly compute: ({ record, }: {
337
+ readonly record: Readonly<Record<string, unknown>>;
338
+ }) => string;
339
+ };
340
+ };
327
341
  };
328
- readonly nullable: false;
329
- readonly list: false;
330
- readonly lifecycle: readonly ["VIRTUAL"];
331
342
  };
332
343
  };
333
344
  };
334
- readonly behaviors: {
335
- readonly books: {
336
- readonly fields: {
337
- readonly label: {
338
- readonly read: {
339
- readonly dependsOn: readonly ["id"];
340
- readonly compute: ({ record, }: {
341
- readonly record: Readonly<Record<string, unknown>>;
342
- }) => string;
343
- };
345
+ };
346
+ /** The corpus's application layer: `books.label` is the client's only. */
347
+ export declare const CORPUS_APPLICATION_CONFIG: {
348
+ readonly exposed: true;
349
+ readonly exemptions: {
350
+ readonly resources: {
351
+ readonly books: {
352
+ readonly fields: {
353
+ readonly label: true;
344
354
  };
345
355
  };
346
356
  };
347
357
  };
358
+ };
359
+ /**
360
+ * The corpus's client layer: what the ClientContract hides or restricts, and
361
+ * the client's own guard and pipe.
362
+ */
363
+ export declare const CORPUS_CLIENT_CONFIG: {
348
364
  readonly pipelines: {
349
365
  readonly guards: readonly [typeof corpusGuard];
350
366
  readonly pipes: readonly [typeof corpusPipe];
351
367
  };
352
- readonly restrictions: {
353
- readonly authors: {
354
- readonly fields: {
355
- readonly secret: {
356
- readonly hidden: true;
368
+ readonly exposed: true;
369
+ readonly exemptions: {
370
+ readonly resources: {
371
+ readonly authors: {
372
+ readonly fields: {
373
+ readonly secret: true;
357
374
  };
358
375
  };
359
- };
360
- readonly secrets: {
361
- readonly operations: {
362
- readonly find: {
363
- readonly many: false;
376
+ readonly secrets: {
377
+ readonly operations: {
378
+ readonly find: readonly ["many"];
364
379
  };
365
380
  };
366
- };
367
- readonly hiddenRes: {
368
- readonly hidden: true;
381
+ readonly hiddenRes: true;
369
382
  };
370
383
  };
371
384
  };
@@ -375,20 +388,20 @@ export declare const CORPUS_ENTRYPOINT = "/api";
375
388
  * The corpus ClientContract's hash: what a generated client for it sends as
376
389
  * `Aventara-Contract-Hash`. A literal, as a generated client holds it.
377
390
  */
378
- export declare const CORPUS_CLIENT_CONTRACT_HASH = "sha256:07b1a75a6e8e88e30115ae81bcf7e3a12fa493bddce995a01867e2381bd158d0";
391
+ export declare const CORPUS_CLIENT_CONTRACT_HASH = "sha256:502530d5b918266c61f45e70035acd7d9637bbf7305c5572106185d5e63ec307";
379
392
  /**
380
393
  * The corpus ClientContract as `GET /_contract` serves it: its JCS-canonical
381
394
  * bytes, `protocol.hash` included. A literal, as a host must serve it byte for
382
395
  * byte.
383
396
  */
384
- export declare const CORPUS_CLIENT_CONTRACT_DOCUMENT = "{\"enums\":{},\"limits\":{\"maxBooleanNodes\":50,\"maxListLimit\":250,\"maxNestingDepth\":12,\"maxRequestBytes\":1048576,\"maxTransactionOperations\":20},\"protocol\":{\"hash\":\"sha256:07b1a75a6e8e88e30115ae81bcf7e3a12fa493bddce995a01867e2381bd158d0\",\"version\":1},\"resources\":{\"authors\":{\"fields\":{\"id\":{\"capabilities\":{\"filter\":[\"equals\"],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}},\"name\":{\"capabilities\":{\"create\":[],\"filter\":[\"equals\"],\"select\":true,\"update\":[]},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}}},\"identifiers\":[[\"id\"]],\"operations\":{\"create\":{\"count\":true,\"many\":true,\"one\":true},\"delete\":{\"count\":true,\"first\":true,\"many\":true,\"unique\":true},\"find\":{\"count\":true,\"first\":true,\"many\":true,\"unique\":true},\"update\":{\"count\":true,\"first\":true,\"many\":true,\"unique\":true},\"upsert\":{\"unique\":true}}},\"books\":{\"fields\":{\"authorId\":{\"capabilities\":{\"filter\":[\"equals\"],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}},\"id\":{\"capabilities\":{\"filter\":[\"equals\"],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}},\"label\":{\"capabilities\":{\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[\"COMPUTED_ON_READ\",\"VIRTUAL\"],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}}},\"identifiers\":[[\"id\"]],\"operations\":{\"find\":{\"many\":true}}},\"samples\":{\"fields\":{\"amount\":{\"capabilities\":{\"create\":[],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"decimal\"}},\"at\":{\"capabilities\":{\"create\":[],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"datetime\"}},\"blob\":{\"capabilities\":{\"create\":[],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"bytes\"}},\"count\":{\"capabilities\":{\"create\":[],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"bigint\"}},\"id\":{\"capabilities\":{\"filter\":[\"equals\"],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}}},\"identifiers\":[[\"id\"]],\"operations\":{\"create\":{\"one\":true},\"find\":{\"unique\":true}}},\"secrets\":{\"fields\":{\"id\":{\"capabilities\":{\"filter\":[\"equals\"],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}}},\"identifiers\":[[\"id\"]],\"operations\":{}}},\"scalars\":{\"bigint\":{\"builtin\":true},\"bytes\":{\"builtin\":true},\"datetime\":{\"builtin\":true},\"decimal\":{\"builtin\":true},\"string\":{\"builtin\":true}},\"transactions\":\"interactive\"}";
397
+ export declare const CORPUS_CLIENT_CONTRACT_DOCUMENT = "{\"enums\":{},\"limits\":{\"maxBooleanNodes\":50,\"maxJsonDepth\":64,\"maxListLimit\":250,\"maxNestingDepth\":12,\"maxRequestBytes\":1048576,\"maxTransactionOperations\":20},\"protocol\":{\"hash\":\"sha256:502530d5b918266c61f45e70035acd7d9637bbf7305c5572106185d5e63ec307\",\"version\":1},\"resources\":{\"authors\":{\"fields\":{\"id\":{\"capabilities\":{\"filter\":[\"equals\"],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}},\"name\":{\"capabilities\":{\"create\":[],\"filter\":[\"equals\"],\"select\":true,\"update\":[]},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}}},\"identifiers\":[[\"id\"]],\"operations\":{\"create\":{\"count\":true,\"many\":true,\"one\":true},\"delete\":{\"count\":true,\"first\":true,\"many\":true,\"unique\":true},\"find\":{\"count\":true,\"first\":true,\"many\":true,\"unique\":true},\"update\":{\"count\":true,\"first\":true,\"many\":true,\"unique\":true},\"upsert\":{\"unique\":true}}},\"books\":{\"fields\":{\"authorId\":{\"capabilities\":{\"filter\":[\"equals\"],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}},\"id\":{\"capabilities\":{\"filter\":[\"equals\"],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}},\"label\":{\"capabilities\":{\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[\"COMPUTED_ON_READ\",\"VIRTUAL\"],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}}},\"identifiers\":[[\"id\"]],\"operations\":{\"find\":{\"many\":true}}},\"samples\":{\"fields\":{\"amount\":{\"capabilities\":{\"create\":[],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"decimal\"}},\"at\":{\"capabilities\":{\"create\":[],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"datetime\"}},\"blob\":{\"capabilities\":{\"create\":[],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"bytes\"}},\"count\":{\"capabilities\":{\"create\":[],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"bigint\"}},\"id\":{\"capabilities\":{\"filter\":[\"equals\"],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}}},\"identifiers\":[[\"id\"]],\"operations\":{\"create\":{\"one\":true},\"find\":{\"unique\":true}}},\"secrets\":{\"fields\":{\"id\":{\"capabilities\":{\"filter\":[\"equals\"],\"select\":true},\"kind\":\"scalar\",\"lifecycle\":[],\"list\":false,\"nullable\":false,\"type\":{\"scalar\":\"string\"}}},\"identifiers\":[[\"id\"]],\"operations\":{}}},\"scalars\":{\"bigint\":{\"builtin\":true},\"bytes\":{\"builtin\":true},\"datetime\":{\"builtin\":true},\"decimal\":{\"builtin\":true},\"string\":{\"builtin\":true}},\"transactions\":\"interactive\"}";
385
398
  /**
386
399
  * The hash of the corpus's second ClientContract: the same model and
387
400
  * configuration with `transactions: "none"` (the `/_transactions` absence
388
401
  * rows). A row targets it by sending this hash, exactly as a client generated
389
402
  * against it would.
390
403
  */
391
- export declare const CORPUS_NONE_CLIENT_CONTRACT_HASH = "sha256:d333e8396b9bf9127e0859ed69b9874f230058a597e2129e6b9e9b380daef618";
404
+ export declare const CORPUS_NONE_CLIENT_CONTRACT_HASH = "sha256:5e99809294a2aae922b635e9a44b464b1b6e03359a54d30420292c62676a7ce5";
392
405
  /** The one record the corpus Adapter knows. */
393
406
  export declare const CORPUS_AUTHOR: {
394
407
  readonly id: "a1";
@@ -404,7 +417,7 @@ export declare const CORPUS_SAMPLE: {
404
417
  readonly id: "s1";
405
418
  readonly count: 9007199254740993n;
406
419
  readonly at: Date;
407
- readonly amount: Decimal;
420
+ readonly amount: AvDecimal;
408
421
  readonly blob: Uint8Array<ArrayBuffer>;
409
422
  };
410
423
  /**
@@ -415,7 +428,7 @@ export declare const CORPUS_SAMPLE: {
415
428
  * otherwise (a stale or absent hash included).
416
429
  */
417
430
  export declare function createCorpusFramework(contractHash?: string): Promise<{
418
- readonly framework: Framework;
431
+ readonly framework: AvFramework;
419
432
  readonly adapterCalls: () => number;
420
433
  }>;
421
434
  export {};
@@ -1,4 +1,4 @@
1
- import { createFramework, Decimal, FrameworkError } from "@aventara/core";
1
+ import { AvDecimal, AvError, createFramework } from "@aventara/core";
2
2
  import { createFakeAdapter } from "../adapters/fake-adapter.js";
3
3
  const identityString = {
4
4
  kind: "scalar",
@@ -113,13 +113,13 @@ function whereIdOf(args) {
113
113
  return typeof id === "string" ? id : undefined;
114
114
  }
115
115
  function corpusGuard(context) {
116
- switch (whereIdOf(context.args)) {
116
+ switch (whereIdOf(context.$args)) {
117
117
  case CORPUS_TRIGGER.unauthenticated:
118
- throw new FrameworkError("A4000", "Authentication is required.");
118
+ throw new AvError("A4000", "Authentication is required.");
119
119
  case CORPUS_TRIGGER.guardDenies:
120
120
  return false;
121
121
  case CORPUS_TRIGGER.policyDenies:
122
- throw new FrameworkError("A4002", "Denied by the corpus policy.");
122
+ throw new AvError("A4002", "Denied by the corpus policy.");
123
123
  case CORPUS_TRIGGER.guardThrows:
124
124
  throw new Error("the corpus guard failed");
125
125
  default:
@@ -133,47 +133,54 @@ function corpusPipe(args) {
133
133
  const record = args;
134
134
  return { ...record, where: { ...record.where, nope: "x" } };
135
135
  }
136
- export const CORPUS_CLIENT_CONFIG = {
137
- fields: {
138
- books: {
136
+ export const CORPUS_RESOURCES = {
137
+ books: {
138
+ fields: {
139
139
  label: {
140
- type: { scalar: "string" },
141
- nullable: false,
142
- list: false,
143
- lifecycle: ["VIRTUAL"],
144
- },
145
- },
146
- },
147
- behaviors: {
148
- books: {
149
- fields: {
150
- label: {
151
- read: {
152
- dependsOn: ["id"],
153
- compute: ({ record, }) => `book:${String(record.id)}`,
140
+ definition: {
141
+ type: { scalar: "string" },
142
+ nullable: false,
143
+ list: false,
144
+ lifecycle: ["VIRTUAL"],
145
+ },
146
+ pipelines: {
147
+ compute: {
148
+ read: {
149
+ dependsOn: ["id"],
150
+ compute: ({ record, }) => `book:${String(record.id)}`,
151
+ },
154
152
  },
155
153
  },
156
154
  },
157
155
  },
158
156
  },
157
+ };
158
+ export const CORPUS_APPLICATION_CONFIG = {
159
+ exposed: true,
160
+ exemptions: { resources: { books: { fields: { label: true } } } },
161
+ };
162
+ export const CORPUS_CLIENT_CONFIG = {
159
163
  pipelines: { guards: [corpusGuard], pipes: [corpusPipe] },
160
- restrictions: {
161
- authors: { fields: { secret: { hidden: true } } },
162
- secrets: { operations: { find: { many: false } } },
163
- hiddenRes: { hidden: true },
164
+ exposed: true,
165
+ exemptions: {
166
+ resources: {
167
+ authors: { fields: { secret: true } },
168
+ secrets: { operations: { find: ["many"] } },
169
+ hiddenRes: true,
170
+ },
164
171
  },
165
172
  };
166
173
  export const CORPUS_ENTRYPOINT = "/api";
167
- export const CORPUS_CLIENT_CONTRACT_HASH = "sha256:07b1a75a6e8e88e30115ae81bcf7e3a12fa493bddce995a01867e2381bd158d0";
168
- export const CORPUS_CLIENT_CONTRACT_DOCUMENT = '{"enums":{},"limits":{"maxBooleanNodes":50,"maxListLimit":250,"maxNestingDepth":12,"maxRequestBytes":1048576,"maxTransactionOperations":20},"protocol":{"hash":"sha256:07b1a75a6e8e88e30115ae81bcf7e3a12fa493bddce995a01867e2381bd158d0","version":1},"resources":{"authors":{"fields":{"id":{"capabilities":{"filter":["equals"],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}},"name":{"capabilities":{"create":[],"filter":["equals"],"select":true,"update":[]},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}}},"identifiers":[["id"]],"operations":{"create":{"count":true,"many":true,"one":true},"delete":{"count":true,"first":true,"many":true,"unique":true},"find":{"count":true,"first":true,"many":true,"unique":true},"update":{"count":true,"first":true,"many":true,"unique":true},"upsert":{"unique":true}}},"books":{"fields":{"authorId":{"capabilities":{"filter":["equals"],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}},"id":{"capabilities":{"filter":["equals"],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}},"label":{"capabilities":{"select":true},"kind":"scalar","lifecycle":["COMPUTED_ON_READ","VIRTUAL"],"list":false,"nullable":false,"type":{"scalar":"string"}}},"identifiers":[["id"]],"operations":{"find":{"many":true}}},"samples":{"fields":{"amount":{"capabilities":{"create":[],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"decimal"}},"at":{"capabilities":{"create":[],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"datetime"}},"blob":{"capabilities":{"create":[],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"bytes"}},"count":{"capabilities":{"create":[],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"bigint"}},"id":{"capabilities":{"filter":["equals"],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}}},"identifiers":[["id"]],"operations":{"create":{"one":true},"find":{"unique":true}}},"secrets":{"fields":{"id":{"capabilities":{"filter":["equals"],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}}},"identifiers":[["id"]],"operations":{}}},"scalars":{"bigint":{"builtin":true},"bytes":{"builtin":true},"datetime":{"builtin":true},"decimal":{"builtin":true},"string":{"builtin":true}},"transactions":"interactive"}';
169
- export const CORPUS_NONE_CLIENT_CONTRACT_HASH = "sha256:d333e8396b9bf9127e0859ed69b9874f230058a597e2129e6b9e9b380daef618";
174
+ export const CORPUS_CLIENT_CONTRACT_HASH = "sha256:502530d5b918266c61f45e70035acd7d9637bbf7305c5572106185d5e63ec307";
175
+ export const CORPUS_CLIENT_CONTRACT_DOCUMENT = '{"enums":{},"limits":{"maxBooleanNodes":50,"maxJsonDepth":64,"maxListLimit":250,"maxNestingDepth":12,"maxRequestBytes":1048576,"maxTransactionOperations":20},"protocol":{"hash":"sha256:502530d5b918266c61f45e70035acd7d9637bbf7305c5572106185d5e63ec307","version":1},"resources":{"authors":{"fields":{"id":{"capabilities":{"filter":["equals"],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}},"name":{"capabilities":{"create":[],"filter":["equals"],"select":true,"update":[]},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}}},"identifiers":[["id"]],"operations":{"create":{"count":true,"many":true,"one":true},"delete":{"count":true,"first":true,"many":true,"unique":true},"find":{"count":true,"first":true,"many":true,"unique":true},"update":{"count":true,"first":true,"many":true,"unique":true},"upsert":{"unique":true}}},"books":{"fields":{"authorId":{"capabilities":{"filter":["equals"],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}},"id":{"capabilities":{"filter":["equals"],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}},"label":{"capabilities":{"select":true},"kind":"scalar","lifecycle":["COMPUTED_ON_READ","VIRTUAL"],"list":false,"nullable":false,"type":{"scalar":"string"}}},"identifiers":[["id"]],"operations":{"find":{"many":true}}},"samples":{"fields":{"amount":{"capabilities":{"create":[],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"decimal"}},"at":{"capabilities":{"create":[],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"datetime"}},"blob":{"capabilities":{"create":[],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"bytes"}},"count":{"capabilities":{"create":[],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"bigint"}},"id":{"capabilities":{"filter":["equals"],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}}},"identifiers":[["id"]],"operations":{"create":{"one":true},"find":{"unique":true}}},"secrets":{"fields":{"id":{"capabilities":{"filter":["equals"],"select":true},"kind":"scalar","lifecycle":[],"list":false,"nullable":false,"type":{"scalar":"string"}}},"identifiers":[["id"]],"operations":{}}},"scalars":{"bigint":{"builtin":true},"bytes":{"builtin":true},"datetime":{"builtin":true},"decimal":{"builtin":true},"string":{"builtin":true}},"transactions":"interactive"}';
176
+ export const CORPUS_NONE_CLIENT_CONTRACT_HASH = "sha256:5e99809294a2aae922b635e9a44b464b1b6e03359a54d30420292c62676a7ce5";
170
177
  export const CORPUS_AUTHOR = { id: "a1", name: "Ada" };
171
178
  export const CORPUS_NOBODY = "nobody";
172
179
  export const CORPUS_SAMPLE = {
173
180
  id: "s1",
174
181
  count: 9007199254740993n,
175
182
  at: new Date("2026-10-05T12:34:56.789Z"),
176
- amount: new Decimal("12.50"),
183
+ amount: new AvDecimal("12.50"),
177
184
  blob: new Uint8Array([255, 0, 16]),
178
185
  };
179
186
  const CONFLICTS = {
@@ -190,7 +197,7 @@ function corpusAnswer(operation) {
190
197
  const id = whereIdOf(operation.arguments);
191
198
  const conflict = id === undefined ? undefined : CONFLICTS[id];
192
199
  if (conflict !== undefined) {
193
- throw new FrameworkError(conflict, `The corpus Adapter answered ${conflict}.`);
200
+ throw new AvError(conflict, `The corpus Adapter answered ${conflict}.`);
194
201
  }
195
202
  if (id === CORPUS_TRIGGER.adapterThrows) {
196
203
  throw new Error("the corpus Adapter failed");
@@ -245,8 +252,10 @@ export async function createCorpusFramework(contractHash) {
245
252
  : { transaction: failingCommit(fake.transaction) }),
246
253
  });
247
254
  const framework = await createFramework({
248
- entrypoint: CORPUS_ENTRYPOINT,
255
+ api: CORPUS_ENTRYPOINT,
249
256
  adapter,
257
+ resources: CORPUS_RESOURCES,
258
+ application: CORPUS_APPLICATION_CONFIG,
250
259
  client: CORPUS_CLIENT_CONFIG,
251
260
  });
252
261
  return { framework, adapterCalls: () => adapter.operations.length };
@@ -1,6 +1,6 @@
1
1
  import type { AvProtocolDriver } from "./protocol-driver.js";
2
2
  /**
3
- * `runAvProtocolConformance(driver)` — drives the protocol fixture corpus
3
+ * `runAvProtocolConformance(driver)` drives the protocol fixture corpus
4
4
  * through one host.
5
5
  *
6
6
  * Every row a host answers is driven; rows whose `client.outcome` is
@@ -12,17 +12,17 @@ import type { AvProtocolDriver } from "./protocol-driver.js";
12
12
  * held to the row's `server` block:
13
13
  *
14
14
  * - `status`, exactly;
15
- * - `code`: the body is a framework envelope carrying that code — or, for
15
+ * - `code`: the body is a framework envelope carrying that code or, for
16
16
  * `null`, is none;
17
17
  * - `causeKeys`: the exact sorted key set of `cause`;
18
18
  * - `issues`: each issue's `code` and `path`, in order;
19
19
  * - `adapterCalls`: the operations the corpus Adapter was handed, exactly;
20
20
  * - `responseHeaders`: each named header present (names matched without
21
- * regard to case) with exactly that value — a host may add its own;
21
+ * regard to case) with exactly that value; a host may add its own;
22
22
  * - `bodyBytes`: the body text, exactly.
23
23
  *
24
24
  * Resolves one result per driven row, in corpus order, each with the
25
- * mismatches found — none when the host conforms. A driver that throws is a
25
+ * mismatches found (none when the host conforms). A driver that throws is a
26
26
  * mismatch of its row, not a rejection of the run. Works with any test
27
27
  * runner: assert on the results with whatever runner you use.
28
28
  */
@@ -1,4 +1,4 @@
1
- import type { Framework } from "@aventara/core";
1
+ import type { AvFramework } from "@aventara/core";
2
2
  /**
3
3
  * The server side of the protocol fixture corpus (`AvProtocolFixtures`), for
4
4
  * a client or host author who serves it through their own stack: a Framework
@@ -19,11 +19,11 @@ export declare const AvProtocolCorpus: {
19
19
  * the corpus's `transactions: "none"` contract for that contract's hash (the
20
20
  * `/_transactions` absence rows send it), the main one for anything else.
21
21
  */
22
- readonly framework: (contractHash?: string) => Promise<Framework>;
22
+ readonly framework: (contractHash?: string) => Promise<AvFramework>;
23
23
  /** Where the corpus Framework is mounted; every row's `path` is relative to it. */
24
24
  readonly entrypoint: string;
25
25
  /**
26
- * The hash of the main corpus ClientContract — what a client generated against
26
+ * The hash of the main corpus ClientContract: what a client generated against
27
27
  * it sends as `Aventara-Contract-Hash`, and what `GET /_contract` names.
28
28
  */
29
29
  readonly clientContractHash: string;
@@ -1,4 +1,4 @@
1
- import type { Framework } from "@aventara/core";
1
+ import type { AvFramework } from "@aventara/core";
2
2
  import type { AvProtocolRequest, AvProtocolResponse } from "@aventara/core/protocol";
3
3
  /**
4
4
  * One host under test, as `runAvProtocolConformance` drives it: given the
@@ -7,7 +7,7 @@ import type { AvProtocolRequest, AvProtocolResponse } from "@aventara/core/proto
7
7
  * and body text, as an `AvProtocolResponse`). The run calls `close` once per
8
8
  * row, after its one request.
9
9
  */
10
- export type AvProtocolDriver = (framework: Framework) => Promise<{
10
+ export type AvProtocolDriver = (framework: AvFramework) => Promise<{
11
11
  readonly send: (request: AvProtocolRequest) => Promise<AvProtocolResponse>;
12
12
  readonly close: () => Promise<void>;
13
13
  }>;
@@ -1,4 +1,4 @@
1
- import type { OperationCode, ValidationCode } from "@aventara/core";
1
+ import type { AvOperationCode, AvValidationCode } from "@aventara/core";
2
2
  import type { AvProtocolRequest } from "@aventara/core/protocol";
3
3
  /**
4
4
  * One row of the protocol fixture corpus: the HTTP request a host receives
@@ -25,11 +25,11 @@ export type AvProtocolFixture = {
25
25
  */
26
26
  readonly status: number;
27
27
  /** `null`: the host produces no framework envelope at all. */
28
- readonly code: OperationCode | null;
28
+ readonly code: AvOperationCode | null;
29
29
  /** The exact, sorted key set of `cause`. */
30
30
  readonly causeKeys?: readonly string[];
31
31
  readonly issues?: readonly {
32
- readonly code: ValidationCode;
32
+ readonly code: AvValidationCode;
33
33
  readonly path?: readonly (string | number)[];
34
34
  }[];
35
35
  /** Always stated: `0` is an assertion, not a default. */
@@ -47,6 +47,6 @@ export type AvProtocolFixture = {
47
47
  */
48
48
  readonly outcome: "resolve" | "framework-error" | "transport-error";
49
49
  /** Present iff `outcome` is `"framework-error"`. */
50
- readonly code?: OperationCode;
50
+ readonly code?: AvOperationCode;
51
51
  };
52
52
  };
@@ -347,7 +347,8 @@ const TRANSACTIONS = [
347
347
  refused("method: GET on /_transactions → 405 A2012 with Allow: POST", planRequest("corpus-tx-get", [AUTHORS_FIND_MANY], { method: "GET" }), 405, "A2012", "The HTTP method is not allowed on this framework route.", { Allow: "POST" }),
348
348
  ];
349
349
  const STALE_HASH = `sha256:${"0".repeat(64)}`;
350
- const VALIDATION_FAILED = "Operation arguments failed framework validation.";
350
+ const RESOURCE_UNAVAILABLE = "The requested Resource is not available.";
351
+ const OPERATION_UNAVAILABLE = "The requested operation is not available on this Resource.";
351
352
  const absent = (label, request, status, code, cause) => ({
352
353
  label: `absent: ${label}`,
353
354
  request,
@@ -371,7 +372,7 @@ const absentRequest = (path, requestId, headers = {}, method = "POST") => {
371
372
  return { ...base, method, path, headers: { ...base.headers, ...headers } };
372
373
  };
373
374
  const unavailableOperation = (resource, operation, key) => ({
374
- message: VALIDATION_FAILED,
375
+ message: OPERATION_UNAVAILABLE,
375
376
  issues: [
376
377
  {
377
378
  path: [key],
@@ -381,7 +382,7 @@ const unavailableOperation = (resource, operation, key) => ({
381
382
  ],
382
383
  });
383
384
  const unavailableResource = (resource) => ({
384
- message: VALIDATION_FAILED,
385
+ message: RESOURCE_UNAVAILABLE,
385
386
  issues: [
386
387
  {
387
388
  code: "V1005",