@lovrozagar/oat 0.6.0 → 0.6.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.
Files changed (40) hide show
  1. package/README.md +21 -7
  2. package/dist/cli.js +4 -0
  3. package/dist/runtime/async.d.ts +19 -4
  4. package/dist/runtime/async.d.ts.map +1 -1
  5. package/dist/runtime/async.js +55 -6
  6. package/dist/runtime/async.js.map +1 -1
  7. package/dist/runtime/checks.d.ts.map +1 -1
  8. package/dist/runtime/checks.js +90 -21
  9. package/dist/runtime/checks.js.map +1 -1
  10. package/dist/runtime/client.d.ts +2 -2
  11. package/dist/runtime/client.d.ts.map +1 -1
  12. package/dist/runtime/client.js +36 -14
  13. package/dist/runtime/client.js.map +1 -1
  14. package/dist/runtime/fixture.d.ts.map +1 -1
  15. package/dist/runtime/fixture.js +86 -21
  16. package/dist/runtime/fixture.js.map +1 -1
  17. package/dist/runtime/rate-limit.d.ts +40 -2
  18. package/dist/runtime/rate-limit.d.ts.map +1 -1
  19. package/dist/runtime/rate-limit.js +115 -4
  20. package/dist/runtime/rate-limit.js.map +1 -1
  21. package/dist/runtime/run.d.ts.map +1 -1
  22. package/dist/runtime/run.js +23 -18
  23. package/dist/runtime/run.js.map +1 -1
  24. package/dist/runtime/sse.d.ts +17 -0
  25. package/dist/runtime/sse.d.ts.map +1 -0
  26. package/dist/runtime/sse.js +62 -0
  27. package/dist/runtime/sse.js.map +1 -0
  28. package/dist/runtime/world.d.ts +16 -0
  29. package/dist/runtime/world.d.ts.map +1 -1
  30. package/dist/runtime/world.js +89 -0
  31. package/dist/runtime/world.js.map +1 -1
  32. package/dist/spec/collection.d.ts +2 -0
  33. package/dist/spec/collection.d.ts.map +1 -1
  34. package/dist/spec/collection.js +16 -0
  35. package/dist/spec/collection.js.map +1 -1
  36. package/dist/spec/graph.d.ts +2 -0
  37. package/dist/spec/graph.d.ts.map +1 -1
  38. package/dist/spec/graph.js +2 -1
  39. package/dist/spec/graph.js.map +1 -1
  40. package/package.json +1 -1
package/README.md CHANGED
@@ -807,7 +807,7 @@ Numbers use the ladder `1, 2, 5, 10, 20, 50, 100` so **lexical order ≠ numeric
807
807
 
808
808
  Empty schemas (`{}`, `true`, `additionalProperties: {}`) and cyclic `$ref`s after inlining stop the walk — they become a scalar or `{}`, never another object descent. A `RangeError` during generation is a `COVERAGE_GAP` on that entity naming the operationId and JSON pointer (`fixture generation overflow on table.create (/)`), not `blocked by unknown`.
809
809
 
810
- String fields honour `format` and `pattern`: `email` → `oat-{variant}-{index}@example.test`, `uri` / `url` → `https://example.test/...`, `uuid` → a fixed-shape UUID, `pattern` → a string that matches (or the field is omitted / the entity is a gap). `"Quarterly Report N"` is only used when the document does not constrain the string.
810
+ String fields honour `format`, `pattern`, and `minLength` together: `email` → `oat-{variant}-{index}@example.test`, `uri` / `url` → `https://example.test/...`, `uuid` → a fixed-shape UUID, `pattern` → a string that matches (or the field is omitted / the entity is a gap). A generated string is padded to `minLength` (repeat the last character) without breaking `pattern`. `"Quarterly Report N"` is only used when the document does not constrain the string. `minLength` greater than `maxLength` omits an optional field and records `missingRequired` on a required one.
811
811
 
812
812
  An operation with `x-invite` is not `entity.create`. oat does not POST a generated invitee. The invite check sends `granteeField` = the peer's `inviteAs`. Missing `inviteAs` is a coverage gap naming the tag.
813
813
 
@@ -817,6 +817,10 @@ Parent path parameters are created first (depth-first through the owning entity'
817
817
 
818
818
  A create that returns `>= 300` on the first variant fails the entity (downstream checks `BLOCKED`). Later variants that fail just shorten the cohort — a partial cohort is still used.
819
819
 
820
+ HTTP 429 is retried first — `Retry-After` or exponential backoff, up to five times — on seed, checks, and teardown, whether or not the operation declared `x-rate-limit`. The first 429 is never a seed failure. A leftover 429 after those retries is a gap, not a backend defect.
821
+
822
+ A 402 / plan-limit (`payment_required`, `*_plan_limit`) on create is not a backend defect when the same-tenant list already has a row — typically an earlier `x-effects` create that filled a free-plan quota. oat reuses that id so children (a `row` after extract created a `table`) can still seed. It does not invent records. Write-path checks on the adopted entity stand down.
823
+
820
824
  A documented feature-gate 403 is the exception: if create declares `x-feature-gate` and the body is `vars.type: feature_gate` (and `vars.feature` matches the tag when present), oat records a `COVERAGE_GAP` naming the tag rather than a seed defect. See [`x-feature-gate`](#x-feature-gate).
821
825
 
822
826
  `--seed` / `seed` makes the bodies identical across runs. It does not make server-assigned ids identical.
@@ -894,7 +898,7 @@ Collection shape is derived from the success JSON schema, not from hardcoded wra
894
898
  | page | `page`, `pageNumber`, `page_number`, `offset` |
895
899
  | limit | `limit`, `perPage`, `per_page`, `pageSize`, `page_size` |
896
900
 
897
- Success schema is the first JSON media type on responses `200`, `201`, `202`, `2XX`, or `default`. Request schema is taken from `requestBody` preferring `multipart/form-data`, then `application/x-www-form-urlencoded`, then JSON. A raw `text/event-stream` body is not treated as a JSON schema defect.
901
+ Success schema is the first JSON media type on responses `200`, `201`, `202`, `2XX`, or `default`. Request schema is taken from `requestBody` preferring `multipart/form-data`, then `application/x-www-form-urlencoded`, then JSON. A success response that lists `text/event-stream` is a stream: oat consumes it to the end and does not treat the raw body as a JSON schema defect. Media type is the stream tag — there is no `x-stream`.
898
902
 
899
903
  ## OpenAPI meta tags
900
904
 
@@ -973,6 +977,8 @@ An invite operation is **not** the entity's fixture create, even when it is `POS
973
977
 
974
978
  Timeline asserted: cannot read → invite → still cannot → accept → can → revoke → cannot.
975
979
 
980
+ Accept and revoke send the documented JSON request body when the operation declares one, filled from the invite token / grant id (and other known scope values). A path-only accept (`POST /invites/{token}` with no body) stays path-only — oat does not invent a body.
981
+
976
982
  **Fallback:** the check does not run.
977
983
 
978
984
  ### `x-query`
@@ -1007,11 +1013,17 @@ x-async:
1007
1013
  pollIntervalMs: 2000
1008
1014
  ```
1009
1015
 
1010
- The HTTP response is a receipt. oat polls until `until` matches, then treats that payload as the result. `poll` may be an operationId or `"GET /path/{id}"`. Defaults: `timeoutMs: 120000`, `pollIntervalMs: 2000`.
1016
+ `x-async` means **POST is a receipt, then poll**. It is not how you mark a stream. A stream is a success response that lists `text/event-stream`.
1017
+
1018
+ When the start response is JSON, oat polls `poll` until `until` matches, then treats that payload as the result. `poll` may be an operationId or `"GET /path/{id}"`. Defaults: `timeoutMs: 120000`, `pollIntervalMs: 2000`.
1019
+
1020
+ When the start response is `text/event-stream`, oat parses `event:` / `data:` frames. `data` is JSON when it starts with `{` / `[`. `idFrom` is resolved against **each event's JSON `data`**, first hit wins — `$.batch_id` on `event: batch` data `{ "batch_id": "…" }` works. A frame named `complete` / `error`, or one whose `data` matches `until`, is the terminal record; `successWhen` is applied to it and oat does **not** GET the poll route. Poll only if the stream ended without a terminal frame **and** `idFrom` resolved.
1021
+
1022
+ A spec may leave both `x-async` and `text/event-stream` on the same operation. The stream is still the result; `x-async` only supplies `idFrom` / `until` / the poll fallback.
1011
1023
 
1012
1024
  `until` / `successWhen` use the same `field.op.value` predicates as filters (`eq`, `in`, …).
1013
1025
 
1014
- **Fallback:** treated as synchronous; async checks are `COVERAGE_GAP`.
1026
+ **Fallback:** treated as synchronous; async checks are `COVERAGE_GAP`. A 2xx stream without `x-async` is consumed and recorded; async checks do not run.
1015
1027
 
1016
1028
  ### `x-effects`
1017
1029
 
@@ -1164,7 +1176,9 @@ x-rate-limit: { category: ai, rps: 3 }
1164
1176
 
1165
1177
  Groups operations sharing one throughput budget (`category`) and optionally the rate itself (`rps`). Without this, oat's matrix can hammer a `login` or paid-inference route past its real limit, collect 429s, and report them as backend defects — exactly the false-positive class that erodes trust fastest. With it, requests to that category are paced through a token bucket before they fire.
1166
1178
 
1167
- A 429 is only ever reported when the request that drew it was demonstrably under the _declared_ rate — oat's own bucket had a free token, so it did not have to wait for one. A 429 that arrived only after oat's bucket made the request wait means oat's own rate model was too generous, which is paced around, never reported.
1179
+ Tags are the **proactive** path. HTTP 429 is the **reactive** path and is honoured even when the operation has no `x-rate-limit` at all (untagged JWT writes, teardown DELETEs). oat reads `Retry-After` (delta-seconds or HTTP-date), otherwise backs off 1s, 2s, 4s… capped at 30s, and retries the same request up to five times. The wait is fed into the matching bucket, or into an implicit `untagged-write` bucket so the next call does not immediately re-trip.
1180
+
1181
+ A 429 is only ever reported when the request that drew it was demonstrably under the _declared_ rate — oat's own bucket had a free token, so it did not have to wait for one. A 429 that arrived only after oat's bucket made the request wait means oat's own rate model was too generous, which is paced around, never reported. A 429 against a config-supplied or implicit rate is never a finding.
1168
1182
 
1169
1183
  `config.rateLimits` is checked first and needs no tag at all — it is what keeps oat usable against a backend that has not adopted `x-rate-limit` yet, or against an environment (staging, usually) whose real limit differs from what the document claims for production. A 429 against a config-supplied rate is never a finding: it is the operator's own belief about the environment, not a claim the API made.
1170
1184
 
@@ -1235,8 +1249,8 @@ Order is fixed (foundations first) so cascade suppression has a cause to point a
1235
1249
  | `softdelete.absent-from-default-list` | a soft-deleted row is gone from the default list | `x-soft-delete` | `list.read-after-write` |
1236
1250
  | `invalidation.declared-route-changes` | after a write, the other entity's listed route actually changes | `x-invalidate` naming another entity | list, persist |
1237
1251
  | `effects.declared-effect-occurs` | `x-effects` cardinality delta is observed on the named list | `x-effects` | `list.read-after-write` |
1238
- | `async.reaches-terminal-state` | polling `x-async` reaches `until` before `timeoutMs` | `x-async` | — |
1239
- | `async.receipt-identifies-the-job` | `idFrom` on the receipt resolves to a pollable job | `x-async` + `idFrom` | — |
1252
+ | `async.reaches-terminal-state` | `x-async` reaches `until` (poll, or a terminal SSE frame) before `timeoutMs` | `x-async` | — |
1253
+ | `async.receipt-identifies-the-job` | `idFrom` on the receipt (JSON object or SSE event JSON) resolves to a pollable job | `x-async` + `idFrom` | — |
1240
1254
  | `patch.minimality` | PATCH `{ name }` does not clear other writable fields | update + item route | — |
1241
1255
  | `idempotency.replay-does-not-duplicate` | same Idempotency-Key + same body does not create a second row | create + documented Idempotency-Key header | list, persist |
1242
1256
  | `delete.absent-record-returns-404` | DELETE of a missing id is 404, not 200 | delete | — |
package/dist/cli.js CHANGED
@@ -236,6 +236,7 @@ export async function main() {
236
236
  if (command === "conformance") {
237
237
  const { postgresAvailable, renderParserSuite, renderSuite, runExampleSpecSuite, runTagUnlockSuite, runParserSuite, runPayloadCatalogSuite, runCoverageReportSuite, runSeedContractSuite, runTenantScopeSuite, runSuite, sqliteAvailable, d1Available, } = await import("./conformance/suite.js");
238
238
  const { runFeatureGateSuite } = await import("./conformance/feature-gate.js");
239
+ const { runRateLimitSuite } = await import("./conformance/rate-limit.js");
239
240
  const parser = renderParserSuite(runParserSuite());
240
241
  process.stdout.write(parser.text);
241
242
  /* The documented example is checked in the same breath: it is the only place a reader
@@ -256,6 +257,9 @@ export async function main() {
256
257
  const featureGate = renderParserSuite(await runFeatureGateSuite());
257
258
  process.stdout.write(featureGate.text);
258
259
  parser.failures += featureGate.failures;
260
+ const rateLimit = renderParserSuite(await runRateLimitSuite());
261
+ process.stdout.write(rateLimit.text);
262
+ parser.failures += rateLimit.failures;
259
263
  const seedContract = renderParserSuite(await runSeedContractSuite());
260
264
  process.stdout.write(seedContract.text);
261
265
  parser.failures += seedContract.failures;
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * Async operation support.
3
3
  *
4
- * For an operation declared with `x-async`, the HTTP response is a receipt, not an outcome. oat
5
- * drives the poll route to a terminal state and treats that payload as the real result — without
6
- * this, an extraction or batch API is testable only as "returned 202", which for such an API is
7
- * most of the surface.
4
+ * `x-async` means the HTTP response is a receipt, then oat polls. A `text/event-stream` body is
5
+ * the result itself — parse events, do not `JSON.parse` the raw string. Poll only when the
6
+ * stream ends without a terminal frame and `idFrom` resolved.
8
7
  */
9
8
  import type { AsyncSpec } from "../spec/extensions.ts";
10
9
  import type { Client, Exchange } from "./client.ts";
10
+ import { type SseEvent } from "./sse.ts";
11
11
  export interface AsyncOutcome {
12
12
  /** Terminal state reached, or null on timeout. */
13
13
  terminal: Record<string, unknown> | null;
@@ -23,6 +23,21 @@ export interface AsyncOutcome {
23
23
  * language as the filter grammar rather than inventing a second one.
24
24
  */
25
25
  export declare function matchesPredicate(record: Record<string, unknown>, expression: string): boolean;
26
+ export declare function readPath(body: unknown, path: string): unknown;
27
+ /**
28
+ * Resolve `idFrom` against a JSON receipt, or against each SSE event's JSON `data` (first hit).
29
+ */
30
+ export declare function resolveAsyncId(receipt: unknown, idFrom: string): unknown;
31
+ export interface StreamAsyncView {
32
+ id: unknown;
33
+ /** Event data that carried `idFrom`, for binding the poll path. */
34
+ idRecord: Record<string, unknown> | null;
35
+ /** `complete` / `error` frame, or a frame whose `data` matches `until`. */
36
+ terminal: Record<string, unknown> | null;
37
+ events: SseEvent[];
38
+ }
39
+ /** Read job id and terminal state from SSE frames. `null` when the body is not a stream. */
40
+ export declare function inspectStreamAsync(receipt: unknown, spec: AsyncSpec): StreamAsyncView | null;
26
41
  /**
27
42
  * Polls until `until` matches, the timeout expires, or the poll route stops responding.
28
43
  *
@@ -1 +1 @@
1
- {"version":3,"file":"async.d.ts","sourceRoot":"","sources":["../../src/runtime/async.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAGnD,MAAM,WAAW,YAAY;IAC5B,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACxC,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;IACjB,2FAA2F;IAC3F,SAAS,EAAE,OAAO,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CA0B7F;AAcD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,cAAc,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GACjD,OAAO,CAAC,YAAY,CAAC,CA4EvB"}
1
+ {"version":3,"file":"async.d.ts","sourceRoot":"","sources":["../../src/runtime/async.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,KAAK,QAAQ,EAAa,MAAM,UAAU,CAAA;AAGnD,MAAM,WAAW,YAAY;IAC5B,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACxC,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;IACjB,2FAA2F;IAC3F,SAAS,EAAE,OAAO,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CA0B7F;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAU7D;AAOD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAYxE;AAED,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,OAAO,CAAA;IACX,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACxC,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACxC,MAAM,EAAE,QAAQ,EAAE,CAAA;CAClB;AAED,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,GAAG,eAAe,GAAG,IAAI,CAsB5F;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,cAAc,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GACjD,OAAO,CAAC,YAAY,CAAC,CA4EvB"}
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Async operation support.
3
3
  *
4
- * For an operation declared with `x-async`, the HTTP response is a receipt, not an outcome. oat
5
- * drives the poll route to a terminal state and treats that payload as the real result — without
6
- * this, an extraction or batch API is testable only as "returned 202", which for such an API is
7
- * most of the surface.
4
+ * `x-async` means the HTTP response is a receipt, then oat polls. A `text/event-stream` body is
5
+ * the result itself — parse events, do not `JSON.parse` the raw string. Poll only when the
6
+ * stream ends without a terminal frame and `idFrom` resolved.
8
7
  */
8
+ import { sseEvents } from "./sse.js";
9
9
  import { fillPath } from "./world.js";
10
10
  /**
11
11
  * A single PostgREST-style predicate, reused here so `until`/`successWhen` speak the same
@@ -41,7 +41,7 @@ export function matchesPredicate(record, expression) {
41
41
  return false;
42
42
  }
43
43
  }
44
- function readPath(body, path) {
44
+ export function readPath(body, path) {
45
45
  let node = body;
46
46
  for (const segment of path
47
47
  .replace(/^\$\.?/, "")
@@ -53,6 +53,55 @@ function readPath(body, path) {
53
53
  }
54
54
  return node;
55
55
  }
56
+ function recordOf(data) {
57
+ if (data === null || typeof data !== "object" || Array.isArray(data))
58
+ return null;
59
+ return data;
60
+ }
61
+ /**
62
+ * Resolve `idFrom` against a JSON receipt, or against each SSE event's JSON `data` (first hit).
63
+ */
64
+ export function resolveAsyncId(receipt, idFrom) {
65
+ const events = sseEvents(receipt);
66
+ if (events !== null) {
67
+ for (const ev of events) {
68
+ const record = recordOf(ev.data);
69
+ if (record === null)
70
+ continue;
71
+ const found = readPath(record, idFrom);
72
+ if (found !== undefined && found !== null)
73
+ return found;
74
+ }
75
+ return undefined;
76
+ }
77
+ return readPath(receipt, idFrom);
78
+ }
79
+ /** Read job id and terminal state from SSE frames. `null` when the body is not a stream. */
80
+ export function inspectStreamAsync(receipt, spec) {
81
+ const events = sseEvents(receipt);
82
+ if (events === null)
83
+ return null;
84
+ let id;
85
+ let idRecord = null;
86
+ let terminal = null;
87
+ for (const ev of events) {
88
+ const record = recordOf(ev.data);
89
+ if (record === null)
90
+ continue;
91
+ if (id === undefined && spec.idFrom !== undefined) {
92
+ const found = readPath(record, spec.idFrom);
93
+ if (found !== undefined && found !== null) {
94
+ id = found;
95
+ idRecord = record;
96
+ }
97
+ }
98
+ const named = ev.event === "complete" || ev.event === "error";
99
+ const untilHit = spec.until !== undefined && matchesPredicate(record, spec.until);
100
+ if (named || untilHit)
101
+ terminal = record;
102
+ }
103
+ return { events, id, idRecord, terminal };
104
+ }
56
105
  /**
57
106
  * Polls until `until` matches, the timeout expires, or the poll route stops responding.
58
107
  *
@@ -65,7 +114,7 @@ export async function driveAsync(client, spec, receipt, scope, headers, refreshI
65
114
  const began = performance.now();
66
115
  const pollScope = { ...scope };
67
116
  if (spec.idFrom !== undefined) {
68
- const id = readPath(receipt, spec.idFrom);
117
+ const id = resolveAsyncId(receipt, spec.idFrom);
69
118
  if (id !== undefined && id !== null) {
70
119
  /* The receipt names the job; bind it to whichever poll-path parameter is unresolved. */
71
120
  const parameters = [...spec.poll.matchAll(/\{([^}]+)\}/g)].map((m) => m[1] ?? "");
@@ -1 +1 @@
1
- {"version":3,"file":"async.js","sourceRoot":"","sources":["../../src/runtime/async.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"async.js","sourceRoot":"","sources":["../../src/runtime/async.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/runtime/checks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAIjE,OAAO,KAAK,EAAE,MAAM,EAA4B,MAAM,aAAa,CAAA;AAGnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAGpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,KAAK,OAAO,EAAY,MAAM,YAAY,CAAA;AAEnD,kGAAkG;AAClG,MAAM,WAAW,KAAK;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IACxB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,iEAAiE;IACjE,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;CAC5B;AAED,MAAM,WAAW,YAAY;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,SAAS,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,MAAM,EAAE,cAAc,CAAA;IACtB,MAAM,EAAE,cAAc,GAAG,SAAS,CAAA;IAClC,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAA;IACpC,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAA;IACpC,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAA;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,OAAO,EAAE,OAAO,EAAE,CAAA;IAClB,KAAK,EAAE,eAAe,GAAG,IAAI,CAAA;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IACzB,IAAI,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,uFAAuF;IACvF,cAAc,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnD;;;OAGG;IACH,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,6FAA6F;IAC7F,OAAO,EAAE,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;IACnD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IAC5C,SAAS,EAAE,eAAe,GAAG,SAAS,CAAA;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,wDAAwD;IACxD,OAAO,EAAE,aAAa,CAAA;IACtB,8DAA8D;IAC9D,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,0DAA0D;IAC1D,SAAS,EAAE,cAAc,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,KAAK;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,8EAA8E;IAC9E,UAAU,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,OAAO,CAAA;IAC1C;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACzC;AAk/ID,eAAO,MAAM,MAAM,EAAE,SAAS,KAAK,EA8ElC,CAAA"}
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/runtime/checks.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,7 @@ import { pathTemplateMatches } from "../spec/load.js";
11
11
  import { encodeForOperation } from "./body.js";
12
12
  import { STRING_PAYLOADS, payloadFits } from "./payloads.js";
13
13
  import { describeFeatureGate, isDocumentedFeatureGateDenial, reportFeatureGateSchemaDrift } from "./feature-gate.js";
14
- import { driveAsync } from "./async.js";
14
+ import { driveAsync, inspectStreamAsync, matchesPredicate, resolveAsyncId } from "./async.js";
15
15
  import { buildCohort } from "./fixture.js";
16
16
  import { fillPath } from "./world.js";
17
17
  /* ------------------------------------------------------------------- helpers */
@@ -33,6 +33,16 @@ function standDownForFeatureGate(ctx, op, exchange, check) {
33
33
  "down rather than treat the documented 403 as a defect.");
34
34
  return true;
35
35
  }
36
+ /**
37
+ * A 429 that survived Client retries is the bucket, not the backend. The check that needed a
38
+ * 2xx stands down; it is not a defect and it is not a concurrency conclusion.
39
+ */
40
+ function standDownForRateLimit(ctx, exchange, check) {
41
+ if (exchange.status !== 429)
42
+ return false;
43
+ ctx.findings.unresolved(check, ctx.entityName, "the request was rate-limited (429) after retries, so this check could not complete");
44
+ return true;
45
+ }
36
46
  /** The list endpoint's derived conventions — parameter roles and envelope spellings. */
37
47
  function conv(ctx) {
38
48
  return ctx.listOp.conventions;
@@ -2607,8 +2617,14 @@ const inviteGrantsThenRevokes = {
2607
2617
  if (token === undefined) {
2608
2618
  return ctx.findings.unresolved(this.id, ctx.entityName, `invite response has no token at ${spec.tokenPointer}`);
2609
2619
  }
2610
- const accepted = await ctx.client.request(acceptOp.method, fillPath(acceptOp.path, { token }), {
2611
- headers: delegate.headers(),
2620
+ const acceptScope = { ...resource, token };
2621
+ const acceptBody = documentedJsonBody(ctx, acceptOp, acceptScope);
2622
+ const accepted = await ctx.client.request(acceptOp.method, fillPath(acceptOp.path, acceptScope), {
2623
+ ...(acceptBody === undefined ? {} : { body: acceptBody }),
2624
+ headers: {
2625
+ ...delegate.headers(),
2626
+ ...(acceptBody === undefined ? {} : { "content-type": "application/json" }),
2627
+ },
2612
2628
  });
2613
2629
  if (standDownForFeatureGate(ctx, acceptOp, accepted, this.id))
2614
2630
  return;
@@ -2623,7 +2639,15 @@ const inviteGrantsThenRevokes = {
2623
2639
  if (grantId === undefined) {
2624
2640
  return ctx.findings.unresolved(this.id, ctx.entityName, `invite response has no grant id at ${spec.grantPointer}, so revoke cannot be expressed`);
2625
2641
  }
2626
- const revoked = await ctx.client.request(revokeOp.method, fillPath(revokeOp.path, { ...resource, grant_id: grantId }), { headers: owner.headers() });
2642
+ const revokeScope = { ...resource, grant_id: grantId, token };
2643
+ const revokeBody = documentedJsonBody(ctx, revokeOp, revokeScope);
2644
+ const revoked = await ctx.client.request(revokeOp.method, fillPath(revokeOp.path, revokeScope), {
2645
+ ...(revokeBody === undefined ? {} : { body: revokeBody }),
2646
+ headers: {
2647
+ ...owner.headers(),
2648
+ ...(revokeBody === undefined ? {} : { "content-type": "application/json" }),
2649
+ },
2650
+ });
2627
2651
  if (standDownForFeatureGate(ctx, revokeOp, revoked, this.id))
2628
2652
  return;
2629
2653
  if (revoked.status >= 300) {
@@ -2978,7 +3002,7 @@ const successSchemaHonoured = {
2978
3002
  const exchange = createExchange(ctx);
2979
3003
  if (exchange === undefined)
2980
3004
  return;
2981
- if (isEventStream(exchange))
3005
+ if (isEventStream(exchange, createOp))
2982
3006
  return;
2983
3007
  if (!validator.documents(raw, exchange.status)) {
2984
3008
  return ctx.findings.unresolved(this.id, ctx.entityName, `create returned ${exchange.status}, which the document declares no schema for — ` +
@@ -3039,10 +3063,41 @@ function submittedFields(body) {
3039
3063
  return body;
3040
3064
  return {};
3041
3065
  }
3042
- function isEventStream(exchange) {
3066
+ /** Document first, then the live `Content-Type`. Media type is the stream tag — not `x-async`. */
3067
+ function isEventStream(exchange, op) {
3068
+ if (op?.eventStream === true)
3069
+ return true;
3043
3070
  const type = exchange.responseHeaders["content-type"] ?? "";
3044
3071
  return type.includes("text/event-stream");
3045
3072
  }
3073
+ /**
3074
+ * JSON request body declared on the operation, filled from known flow values.
3075
+ *
3076
+ * Path-only accept/revoke (`POST /invites/{token}` with no body) stay path-only.
3077
+ */
3078
+ function documentedJsonBody(ctx, op, fields) {
3079
+ const raw = ctx.model.rawOperations.get(op.operationId);
3080
+ const picked = raw === undefined ? null : requestContent(raw);
3081
+ if (picked === null || !picked.mediaType.includes("json"))
3082
+ return undefined;
3083
+ const properties = picked.schema.properties;
3084
+ if (properties !== null && typeof properties === "object") {
3085
+ const names = Object.keys(properties);
3086
+ if (names.length > 0) {
3087
+ const body = {};
3088
+ for (const name of names) {
3089
+ if (fields[name] !== undefined)
3090
+ body[name] = fields[name];
3091
+ }
3092
+ return body;
3093
+ }
3094
+ }
3095
+ if (fields.token !== undefined)
3096
+ return { token: fields.token };
3097
+ if (fields.grant_id !== undefined)
3098
+ return { grant_id: fields.grant_id };
3099
+ return { ...fields };
3100
+ }
3046
3101
  function findConstrained(schema, predicate) {
3047
3102
  const props = schema.properties;
3048
3103
  if (props === null || typeof props !== "object")
@@ -3201,6 +3256,10 @@ const noLostUpdate = {
3201
3256
  return;
3202
3257
  if (standDownForFeatureGate(ctx, ctx.updateOp, secondWrite, this.id))
3203
3258
  return;
3259
+ if (standDownForRateLimit(ctx, firstWrite, this.id))
3260
+ return;
3261
+ if (standDownForRateLimit(ctx, secondWrite, this.id))
3262
+ return;
3204
3263
  if (firstWrite.status >= 300 || secondWrite.status >= 300) {
3205
3264
  return ctx.findings.unresolved(this.id, ctx.entityName, `a concurrent PATCH was rejected (${firstWrite.status}, ${secondWrite.status}), so no ` +
3206
3265
  "race actually took place");
@@ -3298,6 +3357,8 @@ const declaredEffectsOccur = {
3298
3357
  });
3299
3358
  if (standDownForFeatureGate(ctx, op, invoked, this.id))
3300
3359
  continue;
3360
+ if (standDownForRateLimit(ctx, invoked, this.id))
3361
+ continue;
3301
3362
  if (invoked.status >= 400) {
3302
3363
  ctx.findings.gap(this.id, ctx.entityName, `${op.operationId} could not be invoked`, `returned ${invoked.status}; its declared effects are unverified`);
3303
3364
  continue;
@@ -3374,7 +3435,21 @@ const asyncReachesTerminalState = {
3374
3435
  ctx.findings.gap(this.id, ctx.entityName, `${op.operationId} could not be started`, `returned ${start.status}; the async lifecycle after it is untested`);
3375
3436
  continue;
3376
3437
  }
3377
- const outcome = await driveAsync(ctx.client, spec, start.responseBody, ctx.scope, ctx.auth, ctx.refreshIfStale);
3438
+ const streamed = isEventStream(start, op);
3439
+ const fromStream = streamed ? inspectStreamAsync(start.responseBody, spec) : null;
3440
+ if (fromStream?.terminal !== null && fromStream?.terminal !== undefined) {
3441
+ if (spec.successWhen !== undefined && !matchesPredicate(fromStream.terminal, spec.successWhen)) {
3442
+ ctx.findings.gap(this.id, ctx.entityName, `${op.operationId} reached a non-success terminal state`, `terminal state did not satisfy "${spec.successWhen}"; downstream effects of ` +
3443
+ "this operation are untested");
3444
+ }
3445
+ continue;
3446
+ }
3447
+ const receipt = fromStream?.idRecord !== null && fromStream?.idRecord !== undefined ? fromStream.idRecord : start.responseBody;
3448
+ if (streamed && fromStream !== null && (fromStream.id === undefined || fromStream.id === null)) {
3449
+ ctx.findings.backend(this.id, ctx.entityName, `${op.operationId} job disappeared before completing`, "the stream ended without a terminal frame and without a job id, so the poll route cannot be named.", [start]);
3450
+ continue;
3451
+ }
3452
+ const outcome = await driveAsync(ctx.client, spec, receipt, ctx.scope, ctx.auth, ctx.refreshIfStale);
3378
3453
  if (outcome.timedOut) {
3379
3454
  ctx.findings.backend(this.id, ctx.entityName, `${op.operationId} never reached a terminal state`, `polled ${spec.poll} ${outcome.polls} time(s) over ${Math.round(outcome.elapsedMs)}ms ` +
3380
3455
  `without satisfying "${spec.until ?? "any terminal state"}". A job that neither ` +
@@ -3414,19 +3489,7 @@ const asyncReceiptIsResolvable = {
3414
3489
  const started = ctx.client.transcript.find((e) => e.method === op.method && e.status < 300 && new URL(e.url).pathname === resolved);
3415
3490
  if (started === undefined)
3416
3491
  continue;
3417
- const body = started.responseBody;
3418
- const path = spec.idFrom
3419
- .replace(/^\$\.?/, "")
3420
- .split(".")
3421
- .filter(Boolean);
3422
- let node = body;
3423
- for (const segment of path) {
3424
- if (node === null || typeof node !== "object") {
3425
- node = undefined;
3426
- break;
3427
- }
3428
- node = node[segment];
3429
- }
3492
+ const node = resolveAsyncId(started.responseBody, spec.idFrom);
3430
3493
  if (node !== undefined && node !== null)
3431
3494
  continue;
3432
3495
  ctx.findings.spec(this.id, ctx.entityName, `${op.operationId} response does not carry the job identifier it declares`, `x-async names "${spec.idFrom}" as the job id, but the response has no such value. ` +
@@ -3543,6 +3606,8 @@ const stringPayloadSurvives = {
3543
3606
  const control = await writeField(ASCII_PAYLOAD_PROBE, id);
3544
3607
  if (standDownForFeatureGate(ctx, writeOp, control, this.id))
3545
3608
  return;
3609
+ if (standDownForRateLimit(ctx, control, this.id))
3610
+ return;
3546
3611
  if (control.status === 401 || control.status === 403) {
3547
3612
  return ctx.findings.unresolved(this.id, ctx.entityName, `the ASCII control write returned ${control.status}, so later refusals cannot be attributed to the payload`);
3548
3613
  }
@@ -3585,7 +3650,9 @@ const stringPayloadSurvives = {
3585
3650
  evidence.push(written);
3586
3651
  continue;
3587
3652
  }
3588
- if (written.status === 404 || written.status === 409 || written.status === 415 || written.status === 429) {
3653
+ if (standDownForRateLimit(ctx, written, this.id))
3654
+ return;
3655
+ if (written.status === 404 || written.status === 409 || written.status === 415) {
3589
3656
  continue;
3590
3657
  }
3591
3658
  if (written.status >= 400 && written.status < 500) {
@@ -3684,6 +3751,8 @@ const documentedStatusHonoured = {
3684
3751
  continue;
3685
3752
  if (isDocumentedFeatureGateDenial(op, exchange.status, exchange.responseBody))
3686
3753
  continue;
3754
+ if (exchange.status === 429)
3755
+ continue;
3687
3756
  const raw = ctx.model.rawOperations.get(op.operationId);
3688
3757
  if (!declaresConcreteStatuses(raw))
3689
3758
  continue;