@lovrozagar/oat 0.7.7 → 0.8.0

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 (68) hide show
  1. package/README.md +90 -27
  2. package/dist/cli.js +4 -0
  3. package/dist/config/define-config.d.ts +39 -7
  4. package/dist/config/define-config.d.ts.map +1 -1
  5. package/dist/config/define-config.js.map +1 -1
  6. package/dist/index.d.ts +1 -1
  7. package/dist/reference/defects.d.ts +7 -0
  8. package/dist/reference/defects.d.ts.map +1 -1
  9. package/dist/reference/defects.js +7 -0
  10. package/dist/reference/defects.js.map +1 -1
  11. package/dist/reference/http.d.ts.map +1 -1
  12. package/dist/reference/http.js +37 -0
  13. package/dist/reference/http.js.map +1 -1
  14. package/dist/reference/model.d.ts +2 -0
  15. package/dist/reference/model.d.ts.map +1 -1
  16. package/dist/reference/model.js +1 -0
  17. package/dist/reference/model.js.map +1 -1
  18. package/dist/reference/spec.d.ts.map +1 -1
  19. package/dist/reference/spec.js +4 -2
  20. package/dist/reference/spec.js.map +1 -1
  21. package/dist/report/console.d.ts.map +1 -1
  22. package/dist/report/console.js +58 -0
  23. package/dist/report/console.js.map +1 -1
  24. package/dist/runtime/auth.d.ts +4 -0
  25. package/dist/runtime/auth.d.ts.map +1 -1
  26. package/dist/runtime/auth.js +43 -12
  27. package/dist/runtime/auth.js.map +1 -1
  28. package/dist/runtime/checks.d.ts +8 -0
  29. package/dist/runtime/checks.d.ts.map +1 -1
  30. package/dist/runtime/checks.js +220 -13
  31. package/dist/runtime/checks.js.map +1 -1
  32. package/dist/runtime/client.d.ts +15 -0
  33. package/dist/runtime/client.d.ts.map +1 -1
  34. package/dist/runtime/client.js +55 -6
  35. package/dist/runtime/client.js.map +1 -1
  36. package/dist/runtime/cookies.d.ts +58 -0
  37. package/dist/runtime/cookies.d.ts.map +1 -0
  38. package/dist/runtime/cookies.js +191 -0
  39. package/dist/runtime/cookies.js.map +1 -0
  40. package/dist/runtime/exchanges.d.ts.map +1 -1
  41. package/dist/runtime/exchanges.js +14 -0
  42. package/dist/runtime/exchanges.js.map +1 -1
  43. package/dist/runtime/fixture.d.ts +10 -0
  44. package/dist/runtime/fixture.d.ts.map +1 -1
  45. package/dist/runtime/fixture.js +107 -0
  46. package/dist/runtime/fixture.js.map +1 -1
  47. package/dist/runtime/run.d.ts.map +1 -1
  48. package/dist/runtime/run.js +49 -2
  49. package/dist/runtime/run.js.map +1 -1
  50. package/dist/runtime/unique.d.ts +47 -0
  51. package/dist/runtime/unique.d.ts.map +1 -0
  52. package/dist/runtime/unique.js +185 -0
  53. package/dist/runtime/unique.js.map +1 -0
  54. package/dist/runtime/world.d.ts +8 -0
  55. package/dist/runtime/world.d.ts.map +1 -1
  56. package/dist/runtime/world.js +53 -8
  57. package/dist/runtime/world.js.map +1 -1
  58. package/dist/spec/extensions.d.ts +21 -0
  59. package/dist/spec/extensions.d.ts.map +1 -1
  60. package/dist/spec/extensions.js +64 -0
  61. package/dist/spec/extensions.js.map +1 -1
  62. package/dist/spec/graph.d.ts +8 -0
  63. package/dist/spec/graph.d.ts.map +1 -1
  64. package/dist/spec/graph.js +7 -1
  65. package/dist/spec/graph.js.map +1 -1
  66. package/labs/annotated-openapi.yaml +25 -0
  67. package/labs/oob-auth.config.ts +56 -20
  68. package/package.json +1 -1
package/README.md CHANGED
@@ -103,7 +103,7 @@ The first principal is the writer. Isolation needs a second principal with diffe
103
103
 
104
104
  oat never needs ground truth about your data. A filter and its negation must partition the set; a page walk must cover the collection; a record read four ways must read the same.
105
105
 
106
- oat does **not** use OpenAPI `security` / `securitySchemes`, `servers[]`, cookies, webhooks, callbacks, or `links`. Auth is the config. The primary origin is `baseUrl`. Extra hosts go in `origins[]`, each with its own spec — do not merge them into the primary document. Request bodies follow the document: JSON, `multipart/form-data` (scalars + dummy / pool / `each` / `resolveUpload` files), or `application/x-www-form-urlencoded`. `hooks.resolveInput` can replace a generated JSON field (a Stripe test `pm_…`); `hooks.resolveHeaders` can attach a one-shot header (Turnstile) per request.
106
+ oat does **not** use OpenAPI `security` / `securitySchemes`, `servers[]`, webhooks, callbacks, or `links`. Auth is the config. The primary origin is `baseUrl`. Extra hosts go in `origins[]`, each with its own spec — do not merge them into the primary document. A RequestStep whose `path` is an absolute `http(s)` URL is a recorded hop on that URL (a mailed consume page) — that is not an `origins[]` entry and does not need a spec. Request bodies follow the document: JSON, `multipart/form-data` (scalars + dummy / pool / `each` / `resolveUpload` files), or `application/x-www-form-urlencoded`. `hooks.resolveInput` can replace a generated JSON field (a Stripe test `pm_…`); `hooks.resolveHeaders` can attach a one-shot header (Turnstile) per request.
107
107
 
108
108
  ## Quick start
109
109
 
@@ -611,7 +611,7 @@ Each step is one of:
611
611
  }
612
612
  ```
613
613
 
614
- **Request step** (when the document has no auth operations):
614
+ **Request step** (when the document has no auth operations, or the hop is not in the spec):
615
615
 
616
616
  ```ts
617
617
  {
@@ -622,25 +622,37 @@ Each step is one of:
622
622
  }
623
623
  ```
624
624
 
625
+ `path` is joined to this origin's `baseUrl`, unless it is an absolute `http://` or `https://` URL — then oat dispatches to that URL as a recorded exchange (method, URL, status, redirects, response headers). That is how a consume page on the app origin is an auth step when `baseUrl` is the API. Unknown host is allowed. `redirect` defaults to `"follow"` with a per-request cookie jar, so a 303 that sets `Set-Cookie` still leaves that cookie visible to `saveAs`. `redirect: "manual"` stops at the first 3xx (`expect: [303]` then bind from that response).
626
+
625
627
  **Out-of-band step** (email link, OTP — oat cannot collect this itself):
626
628
 
627
629
  ```ts
628
- { outOfBand: { address: "{address}", kind: "email-verify", as: "verifyToken" } }
630
+ { outOfBand: { address: "{address}", kind: "email-verify", as: "verifyLink" } }
629
631
  ```
630
632
 
631
- Later steps interpolate `{name}` from the flow scope. `saveAs` paths are `$.foo.bar` / `$.orgs.0.id` (dot + numeric index only; no JSON Pointer, no filters). Bind `saveAs.refreshToken` from `$.refresh_token` so `{refreshToken}` interpolates in `auth.refresh`. `saveClaimsFrom` reads a JWT's _claims_ (signature is not verified — oat is reading its own credential). `rootsFromFlow` maps path parameter names to those bound keys.
633
+ The hook returns a string. If that string is a URL, a later RequestStep must GET it — a hook-side `fetch` is not a recorded exchange.
634
+
635
+ Later steps interpolate `{name}` from the flow scope. `saveAs` addresses:
636
+
637
+ - `$.foo.bar` / `$.orgs.0.id` — JSON body (dot + numeric index only; no JSON Pointer, no filters)
638
+ - `cookie:<name>` — that cookie on `Set-Cookie` for this hop, including followed hops
639
+ - `header:<name>` — a non-set-cookie response header, case-insensitive
640
+
641
+ Missing cookie / header / JSON path fails the auth step closed. Bind `saveAs.refreshToken` from `$.refresh_token` or `cookie:refresh` so `{refreshToken}` interpolates in `auth.refresh`. `saveClaimsFrom.token` is a JSON path into the response body (`$.access_token`) or a scope key already bound by `saveAs` (`credential`). Signature is not verified — oat is reading its own credential. `rootsFromFlow` maps path parameter names to those bound keys.
632
642
 
633
- `bind` on a step runs **before** the request. `saveAs` / `saveClaimsFrom` run **after**. `credentialFrom` is read from the last HTTP response unless a step already saved `credential`.
643
+ `bind` on a step runs **before** the request. `saveAs` then `saveClaimsFrom` run **after**. `credentialFrom` is read from the last HTTP response unless a step already saved `credential`. `outOfBand.as = "credential"` still wins over `credentialFrom`.
634
644
 
635
645
  If a step's status is not acceptable, auth fails the run (not a finding): `oat: principal "alpha" failed at auth step 2 (POST /v1/…)`.
636
646
 
637
- A complete register → verify → use-claims example:
647
+ A complete register → mailed GET → cookie session example:
638
648
 
639
649
  ```ts
640
650
  function signUp(email: string): AuthFlow {
641
651
  return {
642
652
  credentialFrom: "$.access_token",
643
653
  expiresInFrom: "$.access_token_expires_in",
654
+ header: "cookie",
655
+ template: "session={credential}",
644
656
  refresh: {
645
657
  steps: [
646
658
  {
@@ -657,22 +669,41 @@ function signUp(email: string): AuthFlow {
657
669
  body: { email, password: "…" },
658
670
  method: "POST",
659
671
  path: "/v1/auth/register/email",
672
+ saveAs: { credential: "$.access_token", refreshToken: "$.refresh_token" },
660
673
  },
661
- { outOfBand: { address: email, as: "verifyToken", kind: "email-verify" } },
674
+ { outOfBand: { address: email, as: "verifyLink", kind: "email-verify" } },
662
675
  {
663
- body: { token: "{verifyToken}" },
664
- method: "POST",
665
- path: "/v1/auth/email/verify",
666
- saveAs: { credential: "$.access_token", refreshToken: "$.refresh_token" },
676
+ method: "GET",
677
+ path: "{verifyLink}", // absolute URL; not joined to baseUrl
678
+ expect: [200, 303],
679
+ saveAs: {
680
+ credential: "cookie:session",
681
+ refreshToken: "cookie:refresh",
682
+ },
667
683
  saveClaimsFrom: {
668
- token: "$.access_token",
684
+ token: "credential",
669
685
  bind: { orgId: "orgs.0.oid", projectId: "orgs.0.pids.0" },
670
686
  },
671
687
  },
672
688
  ],
673
689
  }
674
690
  }
691
+ ```
692
+
693
+ When the user path **is** POST-token, keep that chain — it is still valid:
675
694
 
695
+ ```ts
696
+ { outOfBand: { address: email, as: "verifyToken", kind: "email-verify" } },
697
+ {
698
+ body: { token: "{verifyToken}" },
699
+ method: "POST",
700
+ path: "/v1/auth/email/verify",
701
+ saveAs: { credential: "$.access_token", refreshToken: "$.refresh_token" },
702
+ saveClaimsFrom: { token: "$.access_token", bind: { orgId: "orgs.0.oid" } },
703
+ }
704
+ ```
705
+
706
+ ```ts
676
707
  principals: [
677
708
  {
678
709
  id: "alpha",
@@ -733,13 +764,14 @@ The CLI writes `principals.json` into each run folder (and `.oat/runs/latest/pri
733
764
  ```ts
734
765
  hooks: {
735
766
  // Return null to retry (attempt is 1-based). oat backs off until a value arrives.
736
- resolveOutOfBand: async ({ address, kind, attempt }) => {
737
- const token = await readMailCatcher(address, kind)
738
- return token // or null
767
+ // `scope` is the flow at this step; `headers` are the live principal credential headers.
768
+ resolveOutOfBand: async ({ address, kind, attempt, scope, headers }) => {
769
+ const link = await readMailCatcher(address, kind)
770
+ return link // URL or token string, or null
739
771
  },
740
- // Remove a principal this run provisioned (and everything it created).
741
- teardownPrincipal: async (address) => {
742
- await fetch(`https://api.example.com/test/cleanup?email=${address}`, { method: "DELETE" })
772
+ // Remove a principal this run provisioned. `ctx` is the last live credential.
773
+ teardownPrincipal: async (address, { credential, headers }) => {
774
+ await fetch(`https://api.example.com/v1/auth/account`, { method: "DELETE", headers })
743
775
  },
744
776
  // Return a file to send, `{ fields }` to replace the whole request, or null to fall through.
745
777
  resolveUpload: async ({ operationId, field, contentMediaType }) => {
@@ -785,7 +817,7 @@ hooks: {
785
817
  }
786
818
  ```
787
819
 
788
- Without `resolveOutOfBand`, an `outOfBand` step cannot complete. oat polls the hook; the hook must not sleep. Returning `""` is treated like `null`.
820
+ Without `resolveOutOfBand`, an `outOfBand` step cannot complete. oat polls the hook; the hook must not sleep. Returning `""` is treated like `null`. The hook is not a recorded hop: if the human GETs a mailed URL, a later RequestStep must GET that URL so it appears in `exchanges.jsonl` and can `expect` / `saveAs`.
789
821
 
790
822
  Default schedule (0.6.2, unchanged unless `outOfBand` is set): **6** attempts, first sleep **200** ms, doubling, cap **3000** ms. oat sleeps after every miss, including the last, so the worst-case wait is
791
823
 
@@ -800,7 +832,7 @@ outOfBand: { attempts: 20, initialMs: 1000, maxMs: 8000 }
800
832
 
801
833
  Worst-case wait is `sum_{i=0}^{attempts-1} min(initialMs × 2^i, maxMs)`. `worstCaseWaitMs()` from the package computes it. Existing configs that omit `outOfBand` do not slow down.
802
834
 
803
- Without `teardownPrincipal`, provisioned accounts are reported as leftover rather than cascade-deleted. Per-record DELETE still runs for seeded rows when a delete (or `x-cleanup`) exists.
835
+ Without `teardownPrincipal`, provisioned accounts are reported as leftover rather than cascade-deleted. Per-record DELETE still runs for seeded rows when a delete (or `x-cleanup`) exists. The hook is called with the last live credential (`ctx.credential` / `ctx.headers`), not an already-cleared one, so authenticated delete-account is expressible without a tester-key god route. One-argument JavaScript callbacks still run.
804
836
 
805
837
  `resolveHeaders` is called on every dispatch (including the 401 retry). Merge order: `globalHeaders` → hook → per-request headers → principal credential. Use `ctx.operationId` / `ctx.method` / `ctx.url` to attach a one-shot captcha only on captcha ops. oat does not speak Turnstile.
806
838
 
@@ -998,6 +1030,8 @@ A 402 / plan-limit (`payment_required`, `*_plan_limit`) on create is not a backe
998
1030
 
999
1031
  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).
1000
1032
 
1033
+ When create is tagged `x-unique`, a first-variant seed **409** with a nonempty same-tenant list **adopts** that row (`world.seed` `COVERAGE_GAP` naming `x-unique` — the create could not insert). Unique-conflict checks still run against that row. Write-path oracles that need a body oat submitted stay skipped. 409 with an empty list stays `BLOCKED` (`could not seed`). A 409 without the tag is still today's seed failure. The seed 409 itself is not `create.unique-conflict-rejected` passing — that check is the explicit second POST. See [`x-unique`](#x-unique). Later variants that 409 only shorten the cohort. Generated values for unique body columns differ across variants (a suffix) without weakening `maxLength` / `pattern`; if the document cannot express two distinct values, oat records a gap and skips extra variants.
1034
+
1001
1035
  `--seed` / `seed` makes the bodies identical across runs. It does not make server-assigned ids identical.
1002
1036
 
1003
1037
  Teardown DELETEs created rows (or the `x-cleanup` route) newest-first. Failures and missing delete routes are printed as leftovers, not as check findings. `keepFixtures: true` skips this.
@@ -1119,6 +1153,7 @@ What each tag **unlocks** (otherwise the check cannot run):
1119
1153
  | `x-soft-delete` | `softdelete.absent-from-default-list` |
1120
1154
  | `x-invite` | `auth.invite-grants-then-revokes` |
1121
1155
  | `x-wait` | `effects.side-effect-arrives` |
1156
+ | `x-unique` | `create.unique-conflict-rejected`, `update.unique-conflict-rejected` |
1122
1157
 
1123
1158
  What each tag **sharpens** (the check already runs, but the verdict changes):
1124
1159
 
@@ -1168,13 +1203,16 @@ x-invite:
1168
1203
  grantPointer: $.grant_id
1169
1204
  tokenFrom: response # or outOfBand
1170
1205
  tokenKind: org-invite # only when tokenFrom is outOfBand; default `${entity}-invite`
1206
+ acceptFrom: token # default. `link` = GET the OOB URL instead of POSTing accept JSON
1171
1207
  ```
1172
1208
 
1173
- Put this on the invite operation. Config must give the invitee `inviteAs`. Defaults if omitted: `granteeField: key`, `tokenPointer: $.token`, `grantPointer: $.grant_id`, `tokenFrom: response`. All three of `invite` / `accept` / `revoke` (operationIds) are required or the tag is ignored.
1209
+ Put this on the invite operation. Config must give the invitee `inviteAs`. Defaults if omitted: `granteeField: key`, `tokenPointer: $.token`, `grantPointer: $.grant_id`, `tokenFrom: response`, `acceptFrom: token`. All three of `invite` / `accept` / `revoke` (operationIds) are required or the tag is ignored. `oat doctor` / `oat plan` print the accept mode.
1174
1210
 
1175
1211
  `tokenFrom: response` (default) reads the accept token from the invite HTTP body at `tokenPointer`. Keep this for backends that still put the token in JSON.
1176
1212
 
1177
- `tokenFrom: outOfBand` ignores the response token and calls `resolveOutOfBand({ address: inviteAs, kind })` after the invite POST. `kind` is `tokenKind` or `${entity}-invite` (`org` → `org-invite`, `project` → `project-invite`). Use this when the live profile must accept only the mailed token.
1213
+ `tokenFrom: outOfBand` ignores the response token and calls `resolveOutOfBand({ address: inviteAs, kind, scope, headers })` after the invite POST. `kind` is `tokenKind` or `${entity}-invite` (`org` → `org-invite`, `project` → `project-invite`). Use this when the live profile must accept only the mailed token.
1214
+
1215
+ `acceptFrom: token` (default) stuffs that string into the documented accept JSON / path as today. `acceptFrom: link` requires the string to be an absolute `http(s)` URL: oat GETs it (recorded, cookie-jar follow). The `accept` operationId is unused for that hop; `revoke` still uses the documented revoke operation. 2xx/3xx that leaves the grant readable continues the timeline; 4xx, 404, or an unreadable grant is a finding. A config that still POSTs `{ token }` with `tokenFrom: outOfBand` and no `acceptFrom` does not change meaning.
1178
1216
 
1179
1217
  An invite operation is **not** the entity's fixture create, even when it is `POST` on the collection. oat will not seed it with a generated email. The invite check (and only that check) creates the grant, using `inviteAs` as `granteeField`. The check still runs when there is no non-invite create, as long as an item or list route exists.
1180
1218
 
@@ -1409,6 +1447,28 @@ Every 403 is not a feature gate. No tag, or a tag that disagrees with `vars.feat
1409
1447
 
1410
1448
  **Fallback:** none. Without the tag, a 403 is a failed create.
1411
1449
 
1450
+ ### `x-unique`
1451
+
1452
+ ```yaml
1453
+ x-unique:
1454
+ - [email]
1455
+ - [workspace_id, slug]
1456
+ # or: { columns: [email] }
1457
+ # or a single string[] meaning one set: [email]
1458
+ ```
1459
+
1460
+ Column sets that must stay unique. Honey/apps emit this as route meta → OpenAPI. `doctor` / `plan` show the effective sets per entity the way they show `x-feature-gate`.
1461
+
1462
+ Accepted shapes: a list of column sets, `{ columns: [...] }` objects, and a single `string[]` meaning one set. Each set is a non-empty list of column names; empty sets are dropped. Malformed / non-array → treat as absent (`null`), unique checks do not run, `doctor` records an `x-unique` gap. `[]` after filtering → explicit none, checks do not run. No tag → unique checks do not run, `doctor` says so.
1463
+
1464
+ Do not infer uniqueness from 409s, unique-looking names, or JSON Schema `uniqueItems`. Index names and product `error_key` / `vars.type` are not required; HTTP **409** is the unique-conflict class.
1465
+
1466
+ `create.unique-conflict-rejected` — after a known row (seeded or adopted), a second create with the same unique-set values is 409, list cardinality does not grow, and a documented 409 body still matches the 409 schema. **2xx is `BACKEND_BUG`** (evidence: both exchanges, unique columns, list before/after when list resolved; tear down a returned id). Probe each probeable set separately (one 2xx fails the check; do not collide every set in one request). Probeable = at least one column on the create JSON or form body; path/tenant/`x-generated` columns may fill set identity from scope, but a set with no body columns is skipped, not failed. Do not reuse `Idempotency-Key` / `Idempotence-Key` / `X-Idempotency-Key` (omit, or send a fresh key if the document requires it). 402 / documented feature-gate 403 on the probe is `COVERAGE_GAP`, not a unique pass. Other 4xx / 5xx is not a unique pass. Verdict is never `SECURITY`. Leftover/extra rows do not skip the check.
1467
+
1468
+ `update.unique-conflict-rejected` — PATCH a **different** row onto another row's unique-set values is 409 (same scoring). PATCH of a row's own unique values unchanged is not this check. Skip update sets whose columns are all `x-immutable`.
1469
+
1470
+ **Fallback:** none. Without the tag, unique checks do not run, and a seed 409 is a failed create.
1471
+
1412
1472
  ### `--profile` — cost gating
1413
1473
 
1414
1474
  ```bash
@@ -1467,7 +1527,7 @@ export default defineConfig({
1467
1527
 
1468
1528
  ## Checks
1469
1529
 
1470
- 94 checks. A check that cannot run says so (`did not apply` + `needs`). A check that depends on a broken primitive is `BLOCKED`. A check that ran and stopped is inconclusive, not a pass.
1530
+ 96 checks. A check that cannot run says so (`did not apply` + `needs`). A check that depends on a broken primitive is `BLOCKED`. A check that ran and stopped is inconclusive, not a pass.
1471
1531
 
1472
1532
  Order is fixed (foundations first) so cascade suppression has a cause to point at. Mutating checks run alone; read-only checks may share in-flight requests under `maxInFlight`.
1473
1533
 
@@ -1553,6 +1613,8 @@ Order is fixed (foundations first) so cascade suppression has a cause to point a
1553
1613
  | `tenant.filter-does-not-bypass-scope` | `filter=id.eq.<other tenant>` does not return that row | second principal, a filter, and a tagged or inferred tenant | `query.filter-selects-from-whole-set` |
1554
1614
  | `auth.rank-is-monotonic` | a lower rank cannot do what a higher rank is denied | two same-tenant principals at different `rank` | `list.read-after-write` |
1555
1615
  | `auth.invite-grants-then-revokes` | invite → accept grants; revoke takes it back | `x-invite` + peer with `inviteAs` | list, cross-tenant |
1616
+ | `create.unique-conflict-rejected` | a second create colliding a documented unique set is 409, not 2xx; the list does not grow | `x-unique` with a probeable create body column and a known row | — |
1617
+ | `update.unique-conflict-rejected` | PATCHing a **different** row onto another row's unique-set values is 409, not 2xx | `x-unique`, update, two known rows; skip all-`x-immutable` sets | — |
1556
1618
  | `patch.immutable-field-rejected` | PATCHing an `x-immutable` field is rejected or ignored | `x-immutable` | — |
1557
1619
  | `softdelete.absent-from-default-list` | a soft-deleted row is gone from the default list | `x-soft-delete` | `list.read-after-write` |
1558
1620
  | `invalidation.declared-route-changes` | after a write, the other entity's listed route actually changes | `x-invalidate` naming another entity | list, persist |
@@ -1867,7 +1929,7 @@ const { doc: resolved, externalRefs } = dereference(doc)
1867
1929
  const model = buildModel(resolved)
1868
1930
  ```
1869
1931
 
1870
- Types exported: `OatConfig`, `Principal`, `AuthFlow`, `AuthRefresh`, `AuthStep`, `HookAuth`, `Hooks`, `Uploads`, `UploadRequest`, `UploadFile`, `HeaderRequest`, `InputRequest`, `OriginSpec`, `OutOfBandConfig`, `RunOptions`, `RunResult`, `Finding`, `Verdict`, `Actor`, `SpecModel`, `EntityModel`, `OperationModel`, `OpenApiDocument`, `AuthRefreshRequiredError`, `loadPersistedPrincipals`, `worstCaseWaitMs`, `allocateRunDir`, `DEFAULT_RUNS_ROOT`, matrix types.
1932
+ Types exported: `OatConfig`, `Principal`, `AuthFlow`, `AuthRefresh`, `AuthStep`, `HookAuth`, `Hooks`, `Uploads`, `UploadRequest`, `UploadFile`, `HeaderRequest`, `InputRequest`, `OriginSpec`, `OutOfBandConfig`, `OutOfBandRequest`, `TeardownPrincipalContext`, `RunOptions`, `RunResult`, `Finding`, `Verdict`, `Actor`, `SpecModel`, `EntityModel`, `OperationModel`, `OpenApiDocument`, `AuthRefreshRequiredError`, `loadPersistedPrincipals`, `worstCaseWaitMs`, `allocateRunDir`, `DEFAULT_RUNS_ROOT`, matrix types.
1871
1933
 
1872
1934
  ## CI
1873
1935
 
@@ -1956,6 +2018,7 @@ Comma-separated. Each is one named lie the demo API can tell. Primary check is w
1956
2018
  | `ASYNC_RECEIPT_MISSING_ID` | `async.receipt-identifies-the-job` | receipt has no id |
1957
2019
  | `PATCH_REPLACES` | `patch.minimality` | PATCH is implemented as replace |
1958
2020
  | `IDEMPOTENCY_IGNORED` | `idempotency.replay-does-not-duplicate` | Idempotency-Key is ignored |
2021
+ | `UNIQUE_NOT_ENFORCED` | `create.unique-conflict-rejected` | a duplicate unique-set write is 2xx instead of 409 |
1959
2022
  | `DELETE_MISSING_OK` | `delete.absent-record-returns-404` | DELETE missing returns 200 |
1960
2023
  | `CONCURRENT_WRITE_LOST` | `concurrency.no-lost-update` | full-row write clobbers a parallel PATCH |
1961
2024
  | `ENUM_NOT_VALIDATED` | `validation.enum-enforced` | enum is not enforced |
@@ -1980,10 +2043,10 @@ These are deliberate. An agent should not invent a flag for them.
1980
2043
  - **No request timeout by default.** `fetch` waits until the server answers unless `network.requestTimeoutMs` is set. Watch `status=in_flight` and `idle_ms` on that request.
1981
2044
  - **No retry on 5xx.** 429 is retried (up to 5, honouring `Retry-After`). One 401 → force refresh + single retry. A second 401 is evidence.
1982
2045
  - **Network throws are not HTTP.** Offline / DNS / reset / timeout: 4 retries, then one wait (default 60s) for the link. If it does not come back, `net.unreachable` is recorded, remaining work stands down, the report is still written, exit `1`. Progress `status=network`. Failed attempts are journaled as `status: 0` with `{ error: "network", kind }`.
1983
- - **No OpenAPI `security`.** Put credentials in `principals`. Cookie auth is a `headers: { cookie: "…" }` (or a flow that sets that header).
1984
- - **No `servers[]`.** Always set `baseUrl`. Extra hosts are `origins[]`, each with its own `spec`.
2046
+ - **No OpenAPI `security`.** Put credentials in `principals`. Cookie auth is a `headers: { cookie: "…" }` (or a flow that sets that header / `saveAs: { credential: "cookie:session" }`). oat does not grow OpenAPI cookie `securitySchemes`.
2047
+ - **No `servers[]`.** Always set `baseUrl`. Extra hosts are `origins[]`, each with its own `spec`. An app origin that is HTML + `Set-Cookie` is a RequestStep with an absolute URL, not a dummy spec in `origins[]`.
1985
2048
  - **No OCR.** Multipart and file parts are sent as dummy / pool / `each` / `resolveUpload` bytes. oat checks HTTP status and JSON responses, not whether a PDF is a real invoice.
1986
- - **No webhook / callback / link-object following.**
2049
+ - **No webhook / callback / link-object following**, except the explicit auth / invite GET of a URL `resolveOutOfBand` returned. A hook-side `fetch` of that URL is not a recorded exchange.
1987
2050
  - **External `$ref`s are not fetched.** In-document `$ref`s are.
1988
2051
  - **`x-idempotent` is not the idempotency check.** The check keys off a documented `Idempotency-Key` header.
1989
2052
  - **Rate-limit pacing only covers requests oat itself sends.** It cannot see traffic from anything else hitting the backend at the same time, so a shared budget can still trip even when oat's own share was within the declared rate.
package/dist/cli.js CHANGED
@@ -258,6 +258,7 @@ export async function main() {
258
258
  const { postgresAvailable, renderParserSuite, renderSuite, runExampleSpecSuite, runTagUnlockSuite, runParserSuite, runPayloadCatalogSuite, runCoverageReportSuite, runSeedContractSuite, runEffectsSuite, runTenantScopeSuite, runSuite, sqliteAvailable, d1Available, } = await import("./conformance/suite.js");
259
259
  const { runFeatureGateSuite } = await import("./conformance/feature-gate.js");
260
260
  const { runRateLimitSuite } = await import("./conformance/rate-limit.js");
261
+ const { runUniqueSuite } = await import("./conformance/unique.js");
261
262
  const parser = renderParserSuite(runParserSuite());
262
263
  process.stdout.write(parser.text);
263
264
  /* The documented example is checked in the same breath: it is the only place a reader
@@ -281,6 +282,9 @@ export async function main() {
281
282
  const rateLimit = renderParserSuite(await runRateLimitSuite());
282
283
  process.stdout.write(rateLimit.text);
283
284
  parser.failures += rateLimit.failures;
285
+ const unique = renderParserSuite(await runUniqueSuite());
286
+ process.stdout.write(unique.text);
287
+ parser.failures += unique.failures;
284
288
  const seedContract = renderParserSuite(await runSeedContractSuite());
285
289
  process.stdout.write(seedContract.text);
286
290
  parser.failures += seedContract.failures;
@@ -10,14 +10,22 @@ export type { FieldType, FilterOp, FilterableField, FilterableFrom, QueryCapabil
10
10
  interface StepBase {
11
11
  /**
12
12
  * Binds parts of the response into the flow's scope. Later steps interpolate them as
13
- * `{name}`, and `rootsFromFlow` can promote them to path parameters. Values are addressed by
14
- * path: `$.access_token`, `$.orgs.0.id`.
13
+ * `{name}`, and `rootsFromFlow` can promote them to path parameters.
14
+ *
15
+ * Address forms:
16
+ * - `$.access_token` / `$.orgs.0.id` — JSON body (dot + numeric index only)
17
+ * - `cookie:<name>` — that cookie on `Set-Cookie` for this hop (and followed hops)
18
+ * - `header:<name>` — a non-set-cookie response header, case-insensitive
19
+ *
20
+ * Missing cookie / header / JSON path fails the auth step closed.
15
21
  */
16
22
  saveAs?: Record<string, string>;
17
23
  /**
18
24
  * Binds values out of a JWT's claims. Tenancy commonly rides in the token rather than the
19
25
  * response body, and a principal that can name its own tenant needs no roots configured. The
20
26
  * signature is not verified — oat is reading its own credential, not trusting a third party.
27
+ * `token` is a JSON path into the response body (`$.access_token`) or a scope key already
28
+ * bound by `saveAs` (`credential`).
21
29
  */
22
30
  saveClaimsFrom?: {
23
31
  token: string;
@@ -40,19 +48,31 @@ export interface OperationStep extends StepBase {
40
48
  /** Calls a raw path, for endpoints the document does not describe. */
41
49
  export interface RequestStep extends StepBase {
42
50
  method: string;
51
+ /**
52
+ * Path relative to this origin's `baseUrl`, or an absolute `http://` / `https://` URL.
53
+ * Absolute URLs are not joined to `baseUrl` — that is how a consume page on the app origin
54
+ * is a recorded hop when the spec origin is the API.
55
+ */
43
56
  path: string;
44
57
  body?: unknown;
45
58
  headers?: Record<string, string>;
46
59
  query?: Record<string, string>;
47
- /** Named `origins[]` entry. Omit to hit the primary `baseUrl`. */
60
+ /** Named `origins[]` entry. Omit to hit the primary `baseUrl`. Ignored for absolute URLs. */
48
61
  origin?: string;
62
+ /**
63
+ * Redirect policy for this hop. Default `follow` uses a per-request cookie jar so a 303
64
+ * that sets `Set-Cookie` still leaves that cookie visible to `saveAs`. `manual` stops at
65
+ * the first 3xx (`expect: [303]` then reads cookies from that response).
66
+ */
67
+ redirect?: "follow" | "manual";
49
68
  }
50
69
  /**
51
70
  * A value that never travels over HTTP — an emailed verification token, an OTP, a magic link.
52
71
  *
53
72
  * oat declares the need and calls `hooks.resolveOutOfBand` to satisfy it, polling with backoff
54
73
  * because such stores are usually eventually consistent. That hook is the entire coupling
55
- * surface between oat and one specific backend.
74
+ * surface between oat and one specific backend. The hook returns a string (a token, or the
75
+ * mailed URL); oat records the consume hop only when a later RequestStep GETs that URL.
56
76
  */
57
77
  export interface OutOfBandStep {
58
78
  outOfBand: {
@@ -147,6 +167,16 @@ export interface OutOfBandRequest {
147
167
  kind: string;
148
168
  /** 1-based; oat retries with backoff until a value arrives or the attempts run out. */
149
169
  attempt: number;
170
+ /** Flow scope at this step (interpolated binds + prior `saveAs`). */
171
+ scope: Record<string, string>;
172
+ /** Principal credential headers as they would be sent now (Authorization or Cookie). */
173
+ headers: Record<string, string>;
174
+ }
175
+ export interface TeardownPrincipalContext {
176
+ /** Live credential string — the last issued one, not a cleared snapshot. */
177
+ credential: string;
178
+ /** Live principal header map (Authorization or Cookie, whatever the flow uses). */
179
+ headers: Record<string, string>;
150
180
  }
151
181
  /**
152
182
  * Poll schedule for `resolveOutOfBand` and `resolvePrincipalAuth`.
@@ -236,10 +266,12 @@ export interface Hooks {
236
266
  resolveOutOfBand?: (request: OutOfBandRequest) => Promise<string | null>;
237
267
  /**
238
268
  * Removes a principal the run provisioned, and everything that principal created with it.
239
- * Usually the only handle that works: per-record deletes are typically owner-scoped, and the
240
- * credential dies with the run.
269
+ * `ctx.headers` is the live principal header map so authenticated delete-account is
270
+ * expressible without a tester-key god route. Address stays — some backends still key
271
+ * teardown on it. One-argument JavaScript callbacks still run (the second argument is
272
+ * extra); TypeScript configs should take `ctx`.
241
273
  */
242
- teardownPrincipal?: (address: string) => Promise<void>;
274
+ teardownPrincipal?: (address: string, ctx: TeardownPrincipalContext) => Promise<void>;
243
275
  /**
244
276
  * Exact file or whole request. Return `null` to fall through to `uploads.each`, then pool, then a dummy.
245
277
  * `UploadFile` replaces that field. `{ fields }` with a file replaces the whole request.
@@ -1 +1 @@
1
- {"version":3,"file":"define-config.d.ts","sourceRoot":"","sources":["../../src/config/define-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"define-config.d.ts","sourceRoot":"","sources":["../../src/config/define-config.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"define-config.js","sourceRoot":"","sources":["../../src/config/define-config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAoHH,MAAM,UAAU,UAAU,CAAC,IAAmB;IAC7C,OAAO,UAAU,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,CAAA;AACrF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAmB;IAC7C,OAAO,OAAO,IAAI,IAAI,CAAA;AACvB,CAAC;AA4UD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,MAAiB;IAC7C,OAAO,MAAM,CAAA;AACd,CAAC"}
1
+ {"version":3,"file":"define-config.js","sourceRoot":"","sources":["../../src/config/define-config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwIH,MAAM,UAAU,UAAU,CAAC,IAAmB;IAC7C,OAAO,UAAU,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,CAAA;AACrF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAmB;IAC7C,OAAO,OAAO,IAAI,IAAI,CAAA;AACvB,CAAC;AAyVD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,MAAiB;IAC7C,OAAO,MAAM,CAAA;AACd,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { defineConfig, isAuthFlow, isHookAuth } from "./config/define-config.ts";
2
- export type { AuthFlow, AuthRefresh, AuthStep, EntityConfig, FieldType, FilterOp, FilterableField, FilterableFrom, HeaderRequest, HookAuth, Hooks, InputRequest, OatConfig, OperationStep, OriginSpec, OutOfBandConfig, OutOfBandRequest, OutOfBandStep, Principal, PrincipalAuth, PrincipalAuthResult, ProfileSpec, QueryCapabilities, QueryCapabilitiesRequest, RateLimitSpec, RequestStep, SideEffectRequest, UploadFile, UploadRequest, UploadResolution, Uploads, } from "./config/define-config.ts";
2
+ export type { AuthFlow, AuthRefresh, AuthStep, EntityConfig, FieldType, FilterOp, FilterableField, FilterableFrom, HeaderRequest, HookAuth, Hooks, InputRequest, OatConfig, OperationStep, OriginSpec, OutOfBandConfig, OutOfBandRequest, OutOfBandStep, Principal, PrincipalAuth, PrincipalAuthResult, ProfileSpec, QueryCapabilities, QueryCapabilitiesRequest, RateLimitSpec, RequestStep, SideEffectRequest, TeardownPrincipalContext, UploadFile, UploadRequest, UploadResolution, Uploads, } from "./config/define-config.ts";
3
3
  export { loadConfig } from "./config/load.ts";
4
4
  export { loadPersistedPrincipals, parsePersistedPrincipals } from "./runtime/principals.ts";
5
5
  export type { PersistedPrincipal } from "./runtime/principals.ts";
@@ -31,6 +31,13 @@ export declare const DEFECTS: {
31
31
  * enumerating other tenants' identifiers.
32
32
  */
33
33
  readonly EXISTENCE_LEAK_VIA_STATUS: "cross-tenant denial uses 403, revealing that the record exists";
34
+ /**
35
+ * Accepts a second create (or a colliding PATCH) of a documented unique column set.
36
+ *
37
+ * The document said these columns are unique. Returning 2xx instead of 409 is the backend
38
+ * ignoring that constraint — the unique-conflict checks exist to name that lie.
39
+ */
40
+ readonly UNIQUE_NOT_ENFORCED: "a duplicate unique-set write is accepted instead of 409";
34
41
  /**
35
42
  * Accepts an Idempotency-Key and creates a second record anyway.
36
43
  *
@@ -1 +1 @@
1
- {"version":3,"file":"defects.d.ts","sourceRoot":"","sources":["../../src/reference/defects.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,OAAO;IACnB,iFAAiF;;IAEjF,qFAAqF;;IAErF,kEAAkE;;IAElE,iFAAiF;;IAEjF,wEAAwE;;IAExE,6CAA6C;;IAE7C,mFAAmF;;IAEnF;;;;;;OAMG;;IAEH;;;;;;OAMG;;IAEH;;;;;;;OAOG;;IAEH;;;;;;;OAOG;;IAEH;;;;;;OAMG;;IAEH;;;;;;;OAOG;;IAEH;;;;;;;OAOG;;IAEH;;;;;;OAMG;;IAGH;;;;OAIG;;IAGH;;;OAGG;;IAGH;;;;;;;;OAQG;;IAEH;;;;;;;OAOG;;IAEH,gDAAgD;;IAEhD,iCAAiC;;IAEjC,oDAAoD;;IAEpD,mCAAmC;;IAEnC,6EAA6E;;IAE7E,qCAAqC;;IAErC,4CAA4C;;IAE5C,+DAA+D;;IAE/D;;;;;;OAMG;;IAEH;;;;;;;;OAQG;;IAEH;;;;;OAKG;;IAEH,wDAAwD;;IAExD,gDAAgD;;IAEhD,iDAAiD;;IAEjD,yDAAyD;;IAEzD,sDAAsD;;IAEtD,6DAA6D;;IAE7D,yDAAyD;;IAEzD,iDAAiD;;IAEjD,gDAAgD;;IAEhD,uDAAuD;;IAEvD,iEAAiE;;IAEjE,2EAA2E;;IAE3E,kDAAkD;;IAElD,oDAAoD;;IAEpD,4DAA4D;;IAE5D;;;;;OAKG;;IAEH;;;;;OAKG;;IAEH,6DAA6D;;IAE7D,gDAAgD;;IAEhD,kDAAkD;;IAElD,8DAA8D;;IAE9D,6DAA6D;;IAE7D,+DAA+D;;IAE/D,8DAA8D;;IAE9D,+DAA+D;;IAE/D,yFAAyF;;IAEzF,uFAAuF;;IAEvF,mEAAmE;;IAEnE,+EAA+E;;IAE/E,mDAAmD;;IAEnD,2EAA2E;;IAE3E;;;;;;;OAOG;;IAEH;;;OAGG;;IAEH;;;OAGG;;IAEH;;;;OAIG;;IAEH;;;;;;OAMG;;IAEH,4EAA4E;;IAE5E,6DAA6D;;CAEpD,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,OAAO,CAAA;AAE7C,qBAAa,SAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,KAAK,GAAE,SAAS,MAAM,EAAO;IAIzC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAUpD,GAAG,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO;IAI9B,IAAI,IAAI,UAAU,EAAE;CAGpB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,UAAU,CAE/D"}
1
+ {"version":3,"file":"defects.d.ts","sourceRoot":"","sources":["../../src/reference/defects.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,OAAO;IACnB,iFAAiF;;IAEjF,qFAAqF;;IAErF,kEAAkE;;IAElE,iFAAiF;;IAEjF,wEAAwE;;IAExE,6CAA6C;;IAE7C,mFAAmF;;IAEnF;;;;;;OAMG;;IAEH;;;;;OAKG;;IAEH;;;;;;OAMG;;IAEH;;;;;;;OAOG;;IAEH;;;;;;;OAOG;;IAEH;;;;;;OAMG;;IAEH;;;;;;;OAOG;;IAEH;;;;;;;OAOG;;IAEH;;;;;;OAMG;;IAGH;;;;OAIG;;IAGH;;;OAGG;;IAGH;;;;;;;;OAQG;;IAEH;;;;;;;OAOG;;IAEH,gDAAgD;;IAEhD,iCAAiC;;IAEjC,oDAAoD;;IAEpD,mCAAmC;;IAEnC,6EAA6E;;IAE7E,qCAAqC;;IAErC,4CAA4C;;IAE5C,+DAA+D;;IAE/D;;;;;;OAMG;;IAEH;;;;;;;;OAQG;;IAEH;;;;;OAKG;;IAEH,wDAAwD;;IAExD,gDAAgD;;IAEhD,iDAAiD;;IAEjD,yDAAyD;;IAEzD,sDAAsD;;IAEtD,6DAA6D;;IAE7D,yDAAyD;;IAEzD,iDAAiD;;IAEjD,gDAAgD;;IAEhD,uDAAuD;;IAEvD,iEAAiE;;IAEjE,2EAA2E;;IAE3E,kDAAkD;;IAElD,oDAAoD;;IAEpD,4DAA4D;;IAE5D;;;;;OAKG;;IAEH;;;;;OAKG;;IAEH,6DAA6D;;IAE7D,gDAAgD;;IAEhD,kDAAkD;;IAElD,8DAA8D;;IAE9D,6DAA6D;;IAE7D,+DAA+D;;IAE/D,8DAA8D;;IAE9D,+DAA+D;;IAE/D,yFAAyF;;IAEzF,uFAAuF;;IAEvF,mEAAmE;;IAEnE,+EAA+E;;IAE/E,mDAAmD;;IAEnD,2EAA2E;;IAE3E;;;;;;;OAOG;;IAEH;;;OAGG;;IAEH;;;OAGG;;IAEH;;;;OAIG;;IAEH;;;;;;OAMG;;IAEH,4EAA4E;;IAE5E,6DAA6D;;CAEpD,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,OAAO,CAAA;AAE7C,qBAAa,SAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,KAAK,GAAE,SAAS,MAAM,EAAO;IAIzC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAUpD,GAAG,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO;IAI9B,IAAI,IAAI,UAAU,EAAE;CAGpB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,UAAU,CAE/D"}
@@ -31,6 +31,13 @@ export const DEFECTS = {
31
31
  * enumerating other tenants' identifiers.
32
32
  */
33
33
  EXISTENCE_LEAK_VIA_STATUS: "cross-tenant denial uses 403, revealing that the record exists",
34
+ /**
35
+ * Accepts a second create (or a colliding PATCH) of a documented unique column set.
36
+ *
37
+ * The document said these columns are unique. Returning 2xx instead of 409 is the backend
38
+ * ignoring that constraint — the unique-conflict checks exist to name that lie.
39
+ */
40
+ UNIQUE_NOT_ENFORCED: "a duplicate unique-set write is accepted instead of 409",
34
41
  /**
35
42
  * Accepts an Idempotency-Key and creates a second record anyway.
36
43
  *
@@ -1 +1 @@
1
- {"version":3,"file":"defects.js","sourceRoot":"","sources":["../../src/reference/defects.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"defects.js","sourceRoot":"","sources":["../../src/reference/defects.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/reference/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAA;AAEhG,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAInE,OAAO,EAAsB,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE/D,UAAU,SAAS;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAA;CACZ;AA0ID,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,SAAS,CAAA;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,UAAU,EAAE,SAAS,EAAE,CAAA;CACvB;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EAIrE,WAAW,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,OAAO,CAAC,KAAK,CAAC,GACjD,OAAO,CAAC,eAAe,CAAC,CAykB1B;AAsKD,uFAAuF;AACvF,wBAAsB,kBAAkB,CACvC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACxE,OAAO,CAAC,eAAe,CAAC,CAG1B;AAED,oEAAoE;AACpE,wBAAsB,kBAAkB,CACvC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACxE,OAAO,CAAC,eAAe,CAAC,CAI1B;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CACnC,OAAO,GAAE;IACR,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACZ,GACJ,OAAO,CAAC,eAAe,CAAC,CA2B1B;AAED,gGAAgG;AAChG,wBAAsB,oBAAoB,CACzC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACxE,OAAO,CAAC,eAAe,CAAC,CAG1B"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/reference/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAA;AAEhG,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAInE,OAAO,EAAsB,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE/D,UAAU,SAAS;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAA;CACZ;AA0ID,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,SAAS,CAAA;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,UAAU,EAAE,SAAS,EAAE,CAAA;CACvB;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EAIrE,WAAW,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,OAAO,CAAC,KAAK,CAAC,GACjD,OAAO,CAAC,eAAe,CAAC,CAknB1B;AAsKD,uFAAuF;AACvF,wBAAsB,kBAAkB,CACvC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACxE,OAAO,CAAC,eAAe,CAAC,CAG1B;AAED,oEAAoE;AACpE,wBAAsB,kBAAkB,CACvC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACxE,OAAO,CAAC,eAAe,CAAC,CAI1B;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CACnC,OAAO,GAAE;IACR,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACZ,GACJ,OAAO,CAAC,eAAe,CAAC,CA2B1B;AAED,gGAAgG;AAChG,wBAAsB,oBAAoB,CACzC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACxE,OAAO,CAAC,eAAe,CAAC,CAG1B"}
@@ -231,6 +231,41 @@ createStore) {
231
231
  return record;
232
232
  return { ...record, _internal_revision: 7, _shard: "shard-a" };
233
233
  }
234
+ async function assertUnique(entity, record, exceptId, defects) {
235
+ if (defects.has("UNIQUE_NOT_ENFORCED"))
236
+ return;
237
+ const sets = entity.unique ?? [];
238
+ if (sets.length === 0)
239
+ return;
240
+ const scope = {};
241
+ for (const parent of entity.parents) {
242
+ const value = record[parent];
243
+ if (typeof value === "string")
244
+ scope[parent] = value;
245
+ }
246
+ const tenant = record[TENANT_FIELD];
247
+ if (typeof tenant === "string")
248
+ scope[TENANT_FIELD] = tenant;
249
+ const pageSize = Math.max(entity.maxLimit, 100);
250
+ const items = [];
251
+ for (let page = 1; page <= 200; page++) {
252
+ const chunk = await store.query(entity, scope, { limit: pageSize, page }, {
253
+ softDeleteField: entity.softDeleteField,
254
+ });
255
+ items.push(...chunk.items);
256
+ if (chunk.items.length < pageSize)
257
+ break;
258
+ }
259
+ for (const set of sets) {
260
+ const collides = items.some((row) => {
261
+ if (exceptId !== undefined && String(row[entity.identity]) === exceptId)
262
+ return false;
263
+ return set.every((col) => JSON.stringify(row[col]) === JSON.stringify(record[col]));
264
+ });
265
+ if (collides)
266
+ throw new HttpError(409, "conflict", `unique constraint violated (${set.join(", ")})`);
267
+ }
268
+ }
234
269
  function withDefaults(entity, input, scope) {
235
270
  const record = { ...input };
236
271
  record[entity.identity] = store.nextId(entity.name);
@@ -550,6 +585,7 @@ createStore) {
550
585
  if (defects.has("CREATE_DROPS_FIELD"))
551
586
  delete input.description;
552
587
  const record = withDefaults(entity, input, { ...scope, project_id: principal.projectId });
588
+ await assertUnique(entity, record, undefined, defects);
553
589
  const created = await store.insert(entity, record);
554
590
  /* Progress starts on POST .../jobs/start, not on create. A seeded job that
555
591
  * ticks for 60ms looks like a PATCH side effect once x-generated is stripped. */
@@ -595,6 +631,7 @@ createStore) {
595
631
  for (const parent of entity.parents)
596
632
  delete changes[parent];
597
633
  }
634
+ await assertUnique(entity, { ...existing, ...changes }, itemId, defects);
598
635
  const updated = await store.update(entity, itemId, changes);
599
636
  return send(res, defects.has("RESPONSE_STATUS_UNDECLARED") ? 201 : 200, decorate(updated ?? { ...existing, ...changes }));
600
637
  }