@procedures/client 0.46.0 → 0.47.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +99 -68
- package/README.md +4 -4
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters/http/server/transport.d.ts +5 -0
- package/dist/adapters/http/server/transport.d.ts.map +1 -1
- package/dist/adapters/http/server/transport.js +7 -0
- package/dist/adapters/http/server/transport.js.map +1 -1
- package/dist/adapters/local/client/transport.d.ts.map +1 -1
- package/dist/adapters/local/client/transport.js +12 -1
- package/dist/adapters/local/client/transport.js.map +1 -1
- package/dist/adapters/websocket/client/node.d.ts.map +1 -1
- package/dist/adapters/websocket/client/node.js +9 -2
- package/dist/adapters/websocket/client/node.js.map +1 -1
- package/dist/adapters/websocket/server/transport.d.ts.map +1 -1
- package/dist/adapters/websocket/server/transport.js +14 -5
- package/dist/adapters/websocket/server/transport.js.map +1 -1
- package/dist/browser.d.ts +2 -2
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +7 -3
- package/dist/browser.js.map +1 -1
- package/dist/client/client.d.ts +10 -1
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +46 -5
- package/dist/client/client.js.map +1 -1
- package/dist/client/errors/known-codes.d.ts +16 -0
- package/dist/client/errors/known-codes.d.ts.map +1 -0
- package/dist/client/errors/known-codes.js +20 -0
- package/dist/client/errors/known-codes.js.map +1 -0
- package/dist/client/validation/index.d.ts +1 -1
- package/dist/client/validation/index.js +1 -1
- package/dist/events/publisher.js +1 -1
- package/dist/events/publisher.js.map +1 -1
- package/dist/procedures/caller.d.ts +1 -1
- package/dist/procedures/caller.js +1 -1
- package/dist/procedures/collection/admission.d.ts +1 -1
- package/dist/procedures/collection/admission.js +1 -1
- package/dist/procedures/core/array.js +1 -1
- package/dist/procedures/core/array.js.map +1 -1
- package/dist/procedures/core/comparison.js +1 -1
- package/dist/procedures/core/comparison.js.map +1 -1
- package/dist/procedures/core/index.d.ts.map +1 -1
- package/dist/procedures/core/index.js +4 -2
- package/dist/procedures/core/index.js.map +1 -1
- package/dist/procedures/core/math.js +1 -1
- package/dist/procedures/core/math.js.map +1 -1
- package/dist/procedures/core/meta.js +1 -1
- package/dist/procedures/core/meta.js.map +1 -1
- package/dist/procedures/core/object.js +1 -1
- package/dist/procedures/core/object.js.map +1 -1
- package/dist/procedures/core/operands.d.ts.map +1 -1
- package/dist/procedures/core/operands.js +7 -2
- package/dist/procedures/core/operands.js.map +1 -1
- package/dist/procedures/core/outputs.d.ts +1 -1
- package/dist/procedures/core/outputs.d.ts.map +1 -1
- package/dist/procedures/core/outputs.js +1 -1
- package/dist/procedures/core/outputs.js.map +1 -1
- package/dist/procedures/core/string.js +1 -1
- package/dist/procedures/core/string.js.map +1 -1
- package/dist/procedures/core/type.js +1 -1
- package/dist/procedures/core/type.js.map +1 -1
- package/dist/procedures/define-procedure.d.ts.map +1 -1
- package/dist/procedures/define-procedure.js +28 -12
- package/dist/procedures/define-procedure.js.map +1 -1
- package/dist/procedures/index.d.ts +6 -5
- package/dist/procedures/index.d.ts.map +1 -1
- package/dist/procedures/index.js +6 -4
- package/dist/procedures/index.js.map +1 -1
- package/dist/procedures/invoke.d.ts.map +1 -1
- package/dist/procedures/invoke.js +14 -1
- package/dist/procedures/invoke.js.map +1 -1
- package/dist/procedures/module.d.ts +34 -0
- package/dist/procedures/module.d.ts.map +1 -1
- package/dist/procedures/module.js +90 -0
- package/dist/procedures/module.js.map +1 -1
- package/dist/procedures/ref.d.ts +10 -1
- package/dist/procedures/ref.d.ts.map +1 -1
- package/dist/procedures/ref.js +64 -0
- package/dist/procedures/ref.js.map +1 -1
- package/dist/procedures/registry.d.ts +64 -0
- package/dist/procedures/registry.d.ts.map +1 -1
- package/dist/procedures/registry.js +60 -0
- package/dist/procedures/registry.js.map +1 -1
- package/dist/procedures/segments.d.ts.map +1 -1
- package/dist/procedures/segments.js +13 -3
- package/dist/procedures/segments.js.map +1 -1
- package/dist/procedures/types.d.ts +6 -0
- package/dist/procedures/types.d.ts.map +1 -1
- package/dist/procedures/types.js.map +1 -1
- package/dist/server/error-policy.d.ts.map +1 -1
- package/dist/server/error-policy.js +2 -1
- package/dist/server/error-policy.js.map +1 -1
- package/dist/server/face-rules.d.ts +1 -1
- package/dist/server/face-rules.js +1 -1
- package/dist/server/host-procedures.d.ts.map +1 -1
- package/dist/server/host-procedures.js +12 -8
- package/dist/server/host-procedures.js.map +1 -1
- package/dist/server/procedure-server.d.ts +18 -5
- package/dist/server/procedure-server.d.ts.map +1 -1
- package/dist/server/procedure-server.js +28 -8
- package/dist/server/procedure-server.js.map +1 -1
- package/dist/server/server.d.ts +5 -0
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +9 -1
- package/dist/server/server.js.map +1 -1
- package/dist/testing/transport-contract.d.ts +1 -1
- package/dist/testing/transport-contract.js +2 -2
- package/dist/testing/transport-contract.js.map +1 -1
- package/dist/tracing/traceparent.d.ts +6 -0
- package/dist/tracing/traceparent.d.ts.map +1 -1
- package/dist/tracing/traceparent.js +27 -6
- package/dist/tracing/traceparent.js.map +1 -1
- package/package.json +5 -4
- package/src/adapters/http/server/transport.ts +8 -0
- package/src/adapters/local/client/transport.ts +11 -1
- package/src/adapters/websocket/client/node.ts +11 -2
- package/src/adapters/websocket/server/transport.ts +17 -5
- package/src/browser.ts +11 -0
- package/src/client/client.ts +46 -4
- package/src/client/errors/known-codes.ts +22 -0
- package/src/client/validation/index.ts +1 -1
- package/src/events/publisher.ts +1 -1
- package/src/procedures/caller.ts +1 -1
- package/src/procedures/collection/admission.ts +1 -1
- package/src/procedures/core/array.ts +1 -1
- package/src/procedures/core/comparison.ts +1 -1
- package/src/procedures/core/index.ts +4 -1
- package/src/procedures/core/math.ts +1 -1
- package/src/procedures/core/meta.ts +1 -1
- package/src/procedures/core/object.ts +1 -1
- package/src/procedures/core/operands.ts +8 -1
- package/src/procedures/core/outputs.ts +1 -1
- package/src/procedures/core/string.ts +1 -1
- package/src/procedures/core/type.ts +1 -1
- package/src/procedures/define-procedure.ts +25 -10
- package/src/procedures/index.ts +7 -2
- package/src/procedures/invoke.ts +15 -1
- package/src/procedures/module.ts +113 -2
- package/src/procedures/ref.ts +58 -1
- package/src/procedures/registry.ts +99 -0
- package/src/procedures/segments.ts +12 -3
- package/src/procedures/types.ts +6 -0
- package/src/server/error-policy.ts +2 -1
- package/src/server/face-rules.ts +1 -1
- package/src/server/host-procedures.ts +12 -8
- package/src/server/procedure-server.ts +29 -8
- package/src/server/server.ts +10 -1
- package/src/testing/transport-contract.ts +2 -2
- package/src/tracing/traceparent.ts +28 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @procedures/client
|
|
2
2
|
|
|
3
|
+
## 0.47.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0650616: Security fix. `tokenMatches` accepted an empty presented token when the expected token was empty, so a server with `token: ""` admitted a request with an empty bearer. An empty expected token now matches nothing, so `token: ""` means "refuse each network request". The comparison now loops over the presented token, so its time depends only on what the caller sent, as its doc comment says. `MCP_HTTP_TOKEN` set and empty is now an error at the start of the HTTP face, because the server otherwise started with no token. PATCH: the change affects only a server that is open by mistake.
|
|
8
|
+
- ae1e3fd: Shorter doc comments.
|
|
9
|
+
- f1ece74: Neutral names in comments.
|
|
10
|
+
|
|
11
|
+
## 0.47.1
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- f845c6d: `segmentsToTopic()` builds its text in a loop and makes no array. `decodeSegment()` returns a segment without `%` at once. The keys of paths and topics stay the same.
|
|
16
|
+
|
|
17
|
+
## 0.47.0
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
- 2f0c7b0: The release train: the ranges of @mark1russell7/coeval change to a version outside the old range.
|
|
22
|
+
- ad70c38: The release train: the ranges of @mark1russell7/coeval change to a version outside the old range.
|
|
23
|
+
- 47819c6: The release train of 2026-11-02: the ranges of `@mark1russell7/coeval` change from `^0.15.0` to `^0.17.0`. In coeval 0.17.0, `conforms` has a new truth for `formula.if`, `formula.and` and `formula.or`.
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- c9125a8: `HttpServerTransport` has the new method `inFlight()`. It gives the number of requests in progress, open streams too, as `WebSocketServerTransport.inFlight()` does. The change is additive.
|
|
28
|
+
- 335728b: `encodeSegment()` returns a segment without `.` and `%` at once, without a replace with a callback. The keys of paths and topics stay the same.
|
|
29
|
+
- d987202: A call of `mark` loads only the packages of its path (roadmap O93). `ProcedureRegistry` gets an optional resolver, `resolve(path)` and `loadAll()`. `createLazyRegistry()` makes a registry that loads a package at the first lookup of one of its paths. A procedure that reads or writes the registry gets each package first. The manifest of `mark` (version 3) has the packages of each command. The packages `ws` and `cli-table3` load at their first use. The sync methods of the registry and the eager registries do not change.
|
|
30
|
+
- 45a737f: `newTraceId()` and `newSpanId()` take their random bytes from one pool of 4096 bytes, and use a table for the hex digits. Before, each id called `getRandomValues` for 8 or 16 bytes. The ids keep their form. Each random byte goes to one id only.
|
|
31
|
+
- d77e9e8: The entries `.`, `./browser` and `./procedures` export `mathProcedures`, the math procedures under `client` (roadmap O95). A bundle that registers only these gets no other core procedure. The error policy of a server reads the known codes from `ErrorCode` and `ERROR_CODES`, not from `ERROR_REGISTRY`, so a bundle of the server gets no copy of the error texts. A test makes sure that both sets of codes are equal. `isKnownErrorCode` does not change.
|
|
32
|
+
- e913014: Each module imports zod with `import * as z from "zod"`, not `import { z } from "zod"`. With the old form, an esbuild bundle got each locale of zod: 264 kB of minified code (esbuild metafile of the journey worker of the site). The Vite build of the site gives the same worker files with both forms. The procedure scaffolder writes the new form in `types.ts`. The API and the behavior stay the same.
|
|
33
|
+
|
|
3
34
|
## 0.46.0
|
|
4
35
|
|
|
5
36
|
### Minor Changes
|
|
@@ -90,9 +121,9 @@ No changes in this release.
|
|
|
90
121
|
- Each app: examine each retry rule that reads the `retryable` flag of an error. Such a rule sees the new flags of the tables. To retry a 500 of a proxy, give the retry middleware a `shouldRetry` function that matches the code `INTERNAL_ERROR`.
|
|
91
122
|
- Each app with `HybridStorage` over HTTP: to make a 500 of a proxy offline again, give an `isUnavailable` option that also matches the code `INTERNAL_ERROR`.
|
|
92
123
|
- The site (`packages/site`): no step. It does not match on the three old codes, and it has no retry rule for a status.
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
124
|
+
- An app: do the steps of each app in its dev host and in its client code. Then examine the retry rules of its HTTP requests to the procedures server.
|
|
125
|
+
- An app: do the steps of each app.
|
|
126
|
+
- An app: do the steps of each app in each client of `@procedures/client` that it has.
|
|
96
127
|
- e4cb0cf: The release train: the ranges of @mark1russell7/algebra, @mark1russell7/service change to a version outside the old range.
|
|
97
128
|
|
|
98
129
|
### Patch Changes
|
|
@@ -150,7 +181,7 @@ No changes in this release.
|
|
|
150
181
|
|
|
151
182
|
- A caller that reads the code of a 413 from the HTTP handler compares it with `PAYLOAD_TOO_LARGE`, not `INVALID_REQUEST`.
|
|
152
183
|
- A caller of `WebSocketTransport` that retries each failed call stops at `retryable: false`. A call above the limit of the server fails the same way each time.
|
|
153
|
-
-
|
|
184
|
+
- Apps: no step, unless one of them compares the code of a refused large request with `INVALID_REQUEST`.
|
|
154
185
|
|
|
155
186
|
## 0.38.0
|
|
156
187
|
|
|
@@ -176,7 +207,7 @@ No changes in this release.
|
|
|
176
207
|
|
|
177
208
|
- A caller of `cli-kit` with a `format` hook for a path with a dotted segment writes the key in the encoded form, for example `a.b%2Ec`.
|
|
178
209
|
- A reader of the ecosystem scan that splits a `key` on `.` uses `keyToPath(key)`.
|
|
179
|
-
-
|
|
210
|
+
- Apps: no step, if their procedure paths have no segment with `.` or `%`.
|
|
180
211
|
|
|
181
212
|
## 0.37.0
|
|
182
213
|
|
|
@@ -212,8 +243,8 @@ No changes in this release.
|
|
|
212
243
|
- A reader of `changes` with a rule of the rows: apply a full answer as a replacement of the copy. The sync of `@procedures/client-store` does this. A full answer comes after each delete, so give `admitsAll` to the principals with full rights.
|
|
213
244
|
- A host whose `allow` of `events.subscribe` refused a principal with a rule of the rows can admit it.
|
|
214
245
|
- A host with full rights for some principals: give `admission.admitsAll`. Without it, the publisher examines each row of each event for each subscriber. Also, each write reads its rows before the change while such a subscriber is open.
|
|
215
|
-
-
|
|
216
|
-
-
|
|
246
|
+
- An app: give `admitsAll` for the principals that read a whole partition. Then admit the principals with a `when` condition in `allow`.
|
|
247
|
+
- Other apps: no change, if their collections have no `admission.admit`. Then their events do not change.
|
|
217
248
|
|
|
218
249
|
## 0.35.1
|
|
219
250
|
|
|
@@ -285,8 +316,8 @@ No changes in this release.
|
|
|
285
316
|
- A host whose `expose`, policy or limit pattern names such a path in text uses the encoded form, for example `collections.e2e%2Etabs.*`.
|
|
286
317
|
- An `mcpExclude` entry, an `expose` deny entry or a limit entry in the old raw form, for example `collections.e2e.tabs.drop`, does not match. The check compares the encoded key, so the procedure becomes visible, or the limit does not apply. Write each such entry in the encoded form, for example `collections.e2e%2Etabs.drop`.
|
|
287
318
|
- A subscriber of a dotted collection uses `collectionChangeTopic(name)`. The raw topic `collections.a.b` is the topic of the partition `b` of `a`.
|
|
288
|
-
-
|
|
289
|
-
-
|
|
319
|
+
- An app: read the collection of a topic with `collectionTopicPartition(topic)`, not with a pattern, for example `/^collections\.([^.]+)\./`.
|
|
320
|
+
- Other apps: no change, if their collection names have no `.` and no `%`.
|
|
290
321
|
|
|
291
322
|
### Patch Changes
|
|
292
323
|
|
|
@@ -303,7 +334,7 @@ No changes in this release.
|
|
|
303
334
|
|
|
304
335
|
Migration:
|
|
305
336
|
|
|
306
|
-
-
|
|
337
|
+
- Apps: no change at this time. The deprecated names work until the next MINOR.
|
|
307
338
|
- Before the next MINOR, replace `zodAdapter<T>(schema)` with `schema`. To keep the check of a schema against a type, write `const schema: z.ZodType<T> = ...`.
|
|
308
339
|
- Before the next MINOR, replace `typedAnySchema<T>()` and `outputSchema<T>()` with `typed<T>()`.
|
|
309
340
|
- A parse-only object (`{ parse }`) in `zodAdapter` becomes a Standard Schema with a `~standard` property.
|
|
@@ -344,7 +375,7 @@ No changes in this release.
|
|
|
344
375
|
|
|
345
376
|
Now each repetition multiplies the ways of the part inside it. The guard refuses `((a|a){9}){9}` and `((a?){9}){9}`. A pattern with few ways still passes, for example `((?:a|b){3}){3}` and `(\d{1,3}\.){3}\d{1,3}`.
|
|
346
377
|
|
|
347
|
-
Migration: the
|
|
378
|
+
Migration: the apps do not turn `$regex` on, so they need no change.
|
|
348
379
|
- 21dc858: Fixes for the security findings of the second code audit (roadmap O55).
|
|
349
380
|
|
|
350
381
|
PATCH: bug fixes and additive options. Each fix refuses only an input that the documentation does not give. A caller that uses the documented behavior sees no change. A request to a loopback, private or link-local host still works, with a deprecation notice. Version 0.29.0 refuses it (decision D35).
|
|
@@ -376,7 +407,7 @@ No changes in this release.
|
|
|
376
407
|
|
|
377
408
|
A bounded repetition with at most 1000 ways to match passes, for example `(\d{1,3}\.){3}`. Alternatives that start with different characters pass, for example `(?:foo|bar)+` and `(?:[a-z]|-)+`.
|
|
378
409
|
|
|
379
|
-
Migration: the
|
|
410
|
+
Migration: the apps do not turn `$regex` on, so they need no change. A host that turns it on and gets the new `VALIDATION_ERROR` writes the pattern without the ambiguity. For example, write `(?:a|b)+` for `(a|ab|b)+`, and write the repetitions out, `\w+\s\w+\s` for `(\w+\s){2}`.
|
|
380
411
|
|
|
381
412
|
## 0.27.8
|
|
382
413
|
|
|
@@ -526,13 +557,13 @@ No changes in this release.
|
|
|
526
557
|
- A face of your own that gives `mcpFace()` a handler of its own: give the handler `admission: (credentials) => server.admission(credentials)`.
|
|
527
558
|
- An MCP client that a request hook refuses gets 401 at `initialize`. Give it valid credentials for each HTTP request.
|
|
528
559
|
- The site: no change. It has no MCP host, and it used no function of `peer/security.ts`.
|
|
529
|
-
-
|
|
530
|
-
-
|
|
531
|
-
-
|
|
532
|
-
-
|
|
533
|
-
-
|
|
534
|
-
-
|
|
535
|
-
-
|
|
560
|
+
- An app: no change. Its dev host has only the HTTP and WebSocket faces of `createProcedureHost()`. Each request of these faces had one check before.
|
|
561
|
+
- An app: its `mcpFace()` on the procedures host uses a session hook for each HTTP request. In the accounts mode, a request without a session gets `ANONYMOUS`. Thus an MCP client without a session gets no 401 at `initialize`.
|
|
562
|
+
- An app: in the mode `on` (`AUTH_MODE=on`), a request without a tenant token gets 401 at `initialize`. Before, the client opened a session and listed the tools, and each tool call got `UNAUTHORIZED`.
|
|
563
|
+
- An app: accounts that are not ready (the error `UNAVAILABLE` of the hook) give 401 at `initialize`, with `WWW-Authenticate: Bearer`. Before, `initialize` passed, and each tool call got `UNAUTHORIZED`. An MCP client can start its OAuth discovery on this 401.
|
|
564
|
+
- An app: outside the accounts mode, the policy has `allowedOrigins: "*"`. The MCP face takes it, as the HTTP face does. A request with a cookie still needs a named origin. With the default `ambientCredentials: "always"` of its request hook, `"*"` permits no other origin.
|
|
565
|
+
- An app: to keep only the own origin on the MCP face, give `mcpFace({ allowedOrigins: [] })`. Its MCP host over stdio has no change.
|
|
566
|
+
- An app: no change. Its procedures host has only the HTTP face, and its MCP host has only stdio and SDK faces.
|
|
536
567
|
- `mark mcp --http --token` and `@procedures/mcp-dev-tools`: no change for a client. The token is the token of the server, and the server checks each HTTP request one time.
|
|
537
568
|
|
|
538
569
|
## 0.26.2
|
|
@@ -620,9 +651,9 @@ No changes in this release.
|
|
|
620
651
|
- A test that expects `retryable: false` for such an end before the first item: expect the flag of the code.
|
|
621
652
|
- A custom `errorOf` of `writeNdjsonStream`: read its second parameter to give the same rule.
|
|
622
653
|
- The site: no change is necessary. The lab simulates its server with explicit flags. The streams of the journey do not fail.
|
|
623
|
-
-
|
|
624
|
-
-
|
|
625
|
-
-
|
|
654
|
+
- An app: no change is necessary. Its browser client has the retry middleware, but its procedures throw no `UNAVAILABLE`, `CONNECTION_CLOSED` or `RATE_LIMITED` without a flag.
|
|
655
|
+
- An app: no change is necessary. Its handlers give `UNAVAILABLE` with an explicit flag, and it serves no stream procedure of its own.
|
|
656
|
+
- An app: no change is necessary. The cuts of its host have their own flag, and it uses no retry middleware.
|
|
626
657
|
|
|
627
658
|
### Patch Changes
|
|
628
659
|
|
|
@@ -651,7 +682,7 @@ No changes in this release.
|
|
|
651
682
|
|
|
652
683
|
`WIRE-PROTOCOL.md` (section "Error codes") and the doc comments of `errorResponse`, `defaultNdjsonError`, `errorStatus` and `streamErrorMeta` have the deprecation notes.
|
|
653
684
|
|
|
654
|
-
|
|
685
|
+
Apps: no change in this release.
|
|
655
686
|
|
|
656
687
|
## 0.24.0
|
|
657
688
|
|
|
@@ -682,9 +713,9 @@ No changes in this release.
|
|
|
682
713
|
|
|
683
714
|
Migration:
|
|
684
715
|
|
|
685
|
-
- The site and
|
|
686
|
-
-
|
|
687
|
-
-
|
|
716
|
+
- The site and an app: no change. They have no MCP host.
|
|
717
|
+
- An app: no change. Its MCP hosts have no task store.
|
|
718
|
+
- An app: no change. Its MCP host has no tasks.
|
|
688
719
|
- polite-crawler-mcp: no change. Each request has the host token, so each session is one client. A session with 100 tasks gets fewer tasks only when ten or more sessions are near the limit. To keep the rule of CLI-51, give `new McpTaskStore({ reserve: 0 })`.
|
|
689
720
|
- A host whose clients each have many sessions under one principal: each client keeps at most `maxStored - reserve` tasks. To keep the rule of CLI-51, give `reserve: 0` in `tasks` of the host or in `new McpTaskStore()`.
|
|
690
721
|
- 71091a5: Added: the envelope form of a program (coeval, decisions D6, D9 and D10, roadmap item M7). A call is `{ "type": ["client", "add"], "value": input }`, and a reference is `{ "type": "ref", "value": ["names", "sum"] }`. The `$proc` form does not change.
|
|
@@ -714,9 +745,9 @@ No changes in this release.
|
|
|
714
745
|
|
|
715
746
|
- Does a subscriber of `a.b` get `FORBIDDEN` with the reason `partition-not-allowed`? Then make the resolver of `a.b` give a partition. Or rename `a.b` to a name without a dot, for example `a_b`.
|
|
716
747
|
- The site: no change is necessary. It serves no collection.
|
|
717
|
-
-
|
|
718
|
-
-
|
|
719
|
-
-
|
|
748
|
+
- An app: no change is necessary. Its server serves no collection.
|
|
749
|
+
- An app: no change is necessary. Its one served collection, `examples`, has no dot in its name.
|
|
750
|
+
- An app: no change is necessary. Its host serves no collection.
|
|
720
751
|
|
|
721
752
|
## 0.22.0
|
|
722
753
|
|
|
@@ -751,9 +782,9 @@ No changes in this release.
|
|
|
751
782
|
The migration steps of the known consumers:
|
|
752
783
|
|
|
753
784
|
- The site: no change. It imports none of these names. It names `HttpServerTransport` and `WebSocketServerTransport` only in the text of its journey.
|
|
754
|
-
-
|
|
755
|
-
-
|
|
756
|
-
-
|
|
785
|
+
- An app: no change. It imports none of these names, and its host uses `runProcedureHost`. Its `vite.config.ts` maps the root to `@procedures/client/browser`. The map can stay, because the root is also a browser entry.
|
|
786
|
+
- An app: no change. It imports none of these names.
|
|
787
|
+
- An app: no change. It imports none of these names.
|
|
757
788
|
- The procedures image of the harness of `systems` (`packages/harness/image/procedures/server-ws.mjs`) imports `WebSocketServerTransport` from the root. It pins `@procedures/client` 0.7.0. When it moves to this MINOR or a later version, import `WebSocketServerTransport` from `@procedures/client/node`.
|
|
758
789
|
- `headroom` (`packages/daemon/src/gateway.ts`) gives `checkBrowserRequest` of the root a request of `node:http`: no change.
|
|
759
790
|
|
|
@@ -782,9 +813,9 @@ No changes in this release.
|
|
|
782
813
|
- A custom transport or face that sends no credentials to a server with a token or a request hook now gets `UNAUTHORIZED`. Set the credentials of its request (`requestCredentials()`), or `LOCAL_CREDENTIALS` for a face in this process.
|
|
783
814
|
- Code that calls `server.handle()` of a server with a token or a request hook gives `credentials: LOCAL_CREDENTIALS`.
|
|
784
815
|
- The site: no change. Its servers have no token and no request hook, and its workers serve over `PortTransport`, which sets the marker.
|
|
785
|
-
-
|
|
786
|
-
-
|
|
787
|
-
-
|
|
816
|
+
- An app: no change. `scripts/dev.ts` starts a server without a token and without a request hook. Its HTTP and WebSocket faces set the credentials of each request.
|
|
817
|
+
- An app: no change. Its procedure host has a request hook and no token. All its faces send credentials: HTTP, WebSocket and MCP over Streamable HTTP (`mcpFace`). No code of the app calls `handle()` directly. Its MCP host operates over stdio, which is local.
|
|
818
|
+
- An app: no change. Its loopback server and its remote server have a request hook (`principalOf`), and the remote server has a token. `makeProcedureHandler` mounts `procedureHandler`, which sends the credentials of each request. A test that calls `handle()` of such a server gives `LOCAL_CREDENTIALS`, or credentials with the token.
|
|
788
819
|
|
|
789
820
|
## 0.18.1
|
|
790
821
|
|
|
@@ -804,9 +835,9 @@ No changes in this release.
|
|
|
804
835
|
|
|
805
836
|
- When a host fails with `CollectionTopicCollisionError`, rename the plain collection, for example `a.b` to `a_b`. A name without a dot has no topic of a partition.
|
|
806
837
|
- The site: no change is necessary. It serves no collection.
|
|
807
|
-
-
|
|
808
|
-
-
|
|
809
|
-
-
|
|
838
|
+
- An app: no change is necessary. Its server serves no collection.
|
|
839
|
+
- An app: no change is necessary. Its host gives partitions to each served collection (`examples`), and no collection has a plain storage.
|
|
840
|
+
- An app: no change is necessary. Its host serves no collection.
|
|
810
841
|
- 0379278: Docs and tests: the rule of the retryable flag of an in-band end (CLI-58). The behavior does not change, thus this change is a PATCH of the client group (decision D13).
|
|
811
842
|
|
|
812
843
|
- Before the stream starts, an error of a handler without a retryable flag gets the flag of its code in `ERROR_CODES` (CLI-48). Thus `UNAVAILABLE` without a flag is retryable, and the HTTP face answers 503.
|
|
@@ -817,7 +848,7 @@ No changes in this release.
|
|
|
817
848
|
- This rule agrees with the rule of a cut (CLI-48): the flag is false when the call can have had its effect.
|
|
818
849
|
- `WIRE-PROTOCOL.md` gives the rule in the section "Error codes". Tests pin it on the wire of HTTP and WebSocket, and on the HTTP, WebSocket and MCP faces of the procedures host.
|
|
819
850
|
|
|
820
|
-
|
|
851
|
+
Apps: no change.
|
|
821
852
|
|
|
822
853
|
## 0.18.0
|
|
823
854
|
|
|
@@ -859,9 +890,9 @@ No changes in this release.
|
|
|
859
890
|
- Code that matches the status 405 or 415 of a procedure server: match the status 403 and the reasons `method-not-allowed` and `media-type-not-allowed`.
|
|
860
891
|
- Code that reads `GuardResult.code` of `checkBrowserRequest()`: read `reason`.
|
|
861
892
|
- Code that matches the code `"500"` or the default code of `ServerError`: match `INTERNAL_ERROR`.
|
|
862
|
-
-
|
|
863
|
-
-
|
|
864
|
-
-
|
|
893
|
+
- Apps: no code of theirs matches a former code, so no change is necessary.
|
|
894
|
+
- An app: its dev server uses `HttpServerTransport`, and its answers change only as the table says.
|
|
895
|
+
- An app: its host uses `procedureHandler`, which gave the codes of wire v1 already.
|
|
865
896
|
|
|
866
897
|
## 0.17.4
|
|
867
898
|
|
|
@@ -922,9 +953,9 @@ No changes in this release.
|
|
|
922
953
|
- For each collection with partitions whose name has `%` or `.`, upgrade the publishers and the subscribers together.
|
|
923
954
|
- Build each topic rule of a collection with `collectionTopicRule()`. Do not join the parts yourself.
|
|
924
955
|
- The site: no change is necessary. It has no collection with partitions.
|
|
925
|
-
-
|
|
926
|
-
-
|
|
927
|
-
-
|
|
956
|
+
- An app: no change is necessary. It has no collection with partitions.
|
|
957
|
+
- An app: no change is necessary. The app has dotted names of collections, but no dotted name has partitions yet. When a dotted name gets partitions, build the rule of its host with `collectionTopicRule()`, not `collections.${c}.*`.
|
|
958
|
+
- An app: no change is necessary. It has no collection with partitions.
|
|
928
959
|
|
|
929
960
|
## 0.15.1
|
|
930
961
|
|
|
@@ -954,7 +985,7 @@ No changes in this release.
|
|
|
954
985
|
principalOf,
|
|
955
986
|
limits: [
|
|
956
987
|
{
|
|
957
|
-
name: "
|
|
988
|
+
name: "app.writes",
|
|
958
989
|
key: { claim: "tenant" },
|
|
959
990
|
covers: { writes: true },
|
|
960
991
|
policy: { type: "sliding-window", limit: { value: 120, unit: "count" }, window: { value: 1, unit: "min" } },
|
|
@@ -1014,9 +1045,9 @@ No changes in this release.
|
|
|
1014
1045
|
Migration:
|
|
1015
1046
|
|
|
1016
1047
|
- **Site.** No change. The site does not write collections.
|
|
1017
|
-
- **
|
|
1018
|
-
- **
|
|
1019
|
-
- **
|
|
1048
|
+
- **An app with `HybridStorage`.** No change for a storage or a `HybridStorage` without `versionOf`. A `HybridStorage` with `versionOf` over `ApiStorage` needs a server storage with the same `versionOf` (for example `new InMemoryStorage({ versionOf })`), or the option `sendBaseVersions: false`.
|
|
1049
|
+
- **An app with last-write-wins.** It gives no expected version, so nothing changes. Its own storage must refuse a write with an expected version until it tests one. Add the guard to its `set`, `delete` and `setBatch`, and run the contract suite: its first case tests the refusal. To adopt the version later, stamp a version field on the server, give the storage a `versionOf` that tests it in the write, and give the same `versionOf` to the `HybridStorage` of the client. Then add `createWithVersions` to the contract run.
|
|
1050
|
+
- **An app without versions.** No change: it gives no expected version. A storage of the app that implements `CollectionStorage` must refuse a write with an expected version, as above.
|
|
1020
1051
|
- **Other storages.** Each class that implements `CollectionStorage` reads the new options of `set`, `delete` and `setBatch`. It tests them in the write, or it rejects the write with `preconditionNotSupported()`. It never ignores them.
|
|
1021
1052
|
|
|
1022
1053
|
## 0.14.1
|
|
@@ -1050,9 +1081,9 @@ No changes in this release.
|
|
|
1050
1081
|
The migration steps of the known consumers:
|
|
1051
1082
|
|
|
1052
1083
|
- The site: no change. It imports none of these names.
|
|
1053
|
-
-
|
|
1054
|
-
-
|
|
1055
|
-
-
|
|
1084
|
+
- An app: no change. It imports none of these names. The server stub in `vite.config.ts` names `HttpServerTransport` and `WebSocketServerTransport`, and it can stay.
|
|
1085
|
+
- An app: no change. It imports none of these names.
|
|
1086
|
+
- An app: no change. It imports none of these names.
|
|
1056
1087
|
- The procedures image of the harness of `systems` (`packages/harness/image/procedures/server-ws.mjs`) imports `WebSocketServerTransport` from the root. It pins `@procedures/client` 0.7.0. When it moves to a version after the next MINOR, import `WebSocketServerTransport` from `@procedures/client/node`.
|
|
1057
1088
|
|
|
1058
1089
|
## 0.14.0
|
|
@@ -1085,16 +1116,16 @@ No changes in this release.
|
|
|
1085
1116
|
- A caller that finds a cut by the code `INTERNAL_ERROR`: look for `UNAVAILABLE` in its place. Do not retry the call when `retryable` is false.
|
|
1086
1117
|
- A handler that throws `UNAVAILABLE` with `retryable: false`: its HTTP status is 500 in place of 503. Without the flag, the error is retryable and gets 503. A retry middleware then sends the call again, so give `retryable: false` when the call can have had its effect.
|
|
1087
1118
|
- The site: no change is necessary. Its code does not read the code of a cut, or the HTTP status 503.
|
|
1088
|
-
-
|
|
1089
|
-
- The procedures host of
|
|
1090
|
-
-
|
|
1119
|
+
- An app: no change is necessary. Its code does not read `INTERNAL_ERROR`, `UNAVAILABLE` or the severity of an error.
|
|
1120
|
+
- The procedures host of an app (APP-11): no change is necessary. Its code does not read `INTERNAL_ERROR`. Its error "the server has no AGENT_TOKEN" is `UNAVAILABLE` with `retryable: false`, so its HTTP status is 500 in place of 503. No code of the app reads that status.
|
|
1121
|
+
- An app: no change is necessary. Its drain test already expects `UNAVAILABLE` with `retryable: false` for a cut procedure call (S6 A12). Its code reads only `NOT_FOUND` and `FORBIDDEN`.
|
|
1091
1122
|
- The `mark` CLI and `procedure-server`: no change is necessary. The lifecycle test of CI-2 expects `UNAVAILABLE` for the cut of `lifecycle.ticksOnce`.
|
|
1092
1123
|
|
|
1093
1124
|
## 0.13.2
|
|
1094
1125
|
|
|
1095
1126
|
### Patch Changes
|
|
1096
1127
|
|
|
1097
|
-
- 3a235b9: New: the patch operations `$remove` and `$insert
|
|
1128
|
+
- 3a235b9: New: the patch operations `$remove` and `$insert`. `$remove` takes an element out of an array, and the next elements move down by one, as the operation `remove` of JSON Patch (RFC 6902). For a field of an object, it is the same as `$unset`. `$insert` adds an element to an array at an index, as the operation `add` of JSON Patch. Each index of one patch refers to the item before the patch. A patch that removes and inserts elements of the same array is refused, and so is an `$insert` past the end of an array. `$unset` keeps the rule of MongoDB: an element of an array becomes `null`. The storage contract has a case for the two operations, so each storage gets them through `applyPatch`.
|
|
1098
1129
|
|
|
1099
1130
|
## 0.13.1
|
|
1100
1131
|
|
|
@@ -1125,10 +1156,10 @@ No changes in this release.
|
|
|
1125
1156
|
- A host with an `expose` rule must list the collection procedures that it serves, for example `collections.notes.*`. `host.*` and `events.subscribe` stay always on.
|
|
1126
1157
|
- An app that pins its own procedures with `registerProcedures()` on a server with an expose rule: list them in the rule. Give `{ alwaysOn: true }` only to a procedure of the host itself.
|
|
1127
1158
|
- The site: no change is necessary. Its servers have no expose rule.
|
|
1128
|
-
-
|
|
1159
|
+
- An app: no change is necessary. Its server has an expose rule, but it pins no procedure and serves no collection.
|
|
1129
1160
|
- The `mark` CLI and `procedure-server`: no change is necessary. They serve no collection, and `--expose` keeps `host.*` and `events.subscribe` on.
|
|
1130
|
-
-
|
|
1131
|
-
- The procedures host of
|
|
1161
|
+
- An app: no change is necessary. Its host has no expose rule.
|
|
1162
|
+
- The procedures host of an app (APP-11): no change is necessary. Its rule `["collections.*", "app.*"]` lists the collection procedures. To hide `clear`, an `exclude` of the policy now has an effect.
|
|
1132
1163
|
|
|
1133
1164
|
## 0.12.2
|
|
1134
1165
|
|
|
@@ -1177,9 +1208,9 @@ No changes in this release.
|
|
|
1177
1208
|
|
|
1178
1209
|
Migration steps:
|
|
1179
1210
|
|
|
1180
|
-
- The site and
|
|
1181
|
-
- The MCP host of
|
|
1182
|
-
-
|
|
1211
|
+
- The site and an app: no change is necessary, unless they read `/health` of a peer. Then call `host.info` with the token.
|
|
1212
|
+
- The MCP host of an app: no change is necessary. To share the port of its procedures host, mount `mcpFace()` on its listener.
|
|
1213
|
+
- Apps under `run()`: build the procedures with `createProcedureHost()`, and call `host.declare(svc)` in the service of the process. Give `listen` for a port of the host, or mount `host.handler` and `host.upgrade` on the listener of the app.
|
|
1183
1214
|
- A caller of `createPeer()` with a different token for each transport: give one token.
|
|
1184
1215
|
- A Docker `HEALTHCHECK` or a probe of Kubernetes that read `/health` of a peer: use the probes of the service. Give the service `probeServer({ port, server_retry_after })` on a port of its own, or mount `probeHandler(health, { prefix: "/health" })` on the port of the app. Both come from `@mark1russell7/service/http`, and they answer `/health/startup`, `/health/readiness` and `/health/liveness`. The lockfile check of a client calls `host.info` with the token of the lockfile.
|
|
1185
1216
|
- A test that read `/health` of a peer: call `host.info` with the token, or check the status 404.
|
|
@@ -1207,8 +1238,8 @@ No changes in this release.
|
|
|
1207
1238
|
|
|
1208
1239
|
Migration steps:
|
|
1209
1240
|
|
|
1210
|
-
- The site,
|
|
1211
|
-
-
|
|
1241
|
+
- The site, an app and the MCP host of another app: no change is necessary. `stop({ grace })` keeps its result. Change `server.callsInFlight` to `server.inFlight()`.
|
|
1242
|
+
- Apps under `run()`: declare the parts in the service of the process. Do not call `stop()`. Declare `svc.server("procedures", {}, server)`, and declare each handle of `server.storageHandles()` with `svc.dependency(handle.name, spec, handle)`. Give the server and `run()` the same clock, with the option `clock` of each.
|
|
1212
1243
|
- A test with a fake clock that calls `stop({ grace })` with calls in flight: advance the clock by the grace, or stop without a grace.
|
|
1213
1244
|
|
|
1214
1245
|
## 0.9.2
|
|
@@ -1321,14 +1352,14 @@ No changes in this release.
|
|
|
1321
1352
|
- The option `origin` of `HybridStorage` is the tag of the storage (a random `hybrid-…` tag by default). Each write of the storage to the local copy and to the remote has it. The write methods of `HybridStorage` and `ApiStorage` take `{ origin }`.
|
|
1322
1353
|
- `capture: "observe"`: the storage observes the local copy and queues each change with another origin. Thus an application can write to the local copy directly, for example with the synchronous writes of a SignalDB collection. In `write-through` and `remote-only` mode, the storage sends a captured change at once.
|
|
1323
1354
|
- The option `syncState` takes a `SyncStateStore`: `MemorySyncStateStore`, or `IndexedDbSyncStateStore` of `@procedures/store/indexeddb`. The store keeps the cursor and the base versions. A new storage with the same store and a durable local copy asks only for the changes since the cursor, and it finds the conflicts of the base versions. A failure of the store goes to the status (`operation: "store"`, `SyncStateError`), and the storage goes on.
|
|
1324
|
-
- The option `feed` takes a `RemoteChangeFeed`. A delta whose `since` is the cursor applies without a read of the remote. A gap, a lost event, a new subscription or another delta makes one pull. A delta that comes during a pull applies after the pull, so the pull does not erase it
|
|
1355
|
+
- The option `feed` takes a `RemoteChangeFeed`. A delta whose `since` is the cursor applies without a read of the remote. A gap, a lost event, a new subscription or another delta makes one pull. A delta that comes during a pull applies after the pull, so the pull does not erase it.
|
|
1325
1356
|
- In `write-through` mode, a pull or a delta does not write over an own write that waits for the remote, a set or a delete. The storage keeps the remote value of the id, and after the write it reads the id again: then the rules of a pull decide. A read of a missing id does not bring back an item whose own delete waits.
|
|
1326
|
-
- With `versionOf`, the storage keeps the versions of its own writes until their echoes come (option `echoWindow`, 30 seconds by default). The echo of an older own write does not write over a newer local write
|
|
1357
|
+
- With `versionOf`, the storage keeps the versions of its own writes until their echoes come (option `echoWindow`, 30 seconds by default). The echo of an older own write does not write over a newer local write.
|
|
1327
1358
|
- `EventsChangeFeed` of `@procedures/store` is the feed of the change events. Its source is a `Client`, a `WebSocketTransport` or another transport. It treats the events as hints: a gap of the numbers, a lost event, a hint and each confirmation of the subscription call `onGap()`.
|
|
1328
1359
|
- The core collection procedures publish `CollectionChangeEvent` `{ since, version, changed, deleted, origin }` on `ctx.bus`, under the topic `collections.<name>` (`collectionChangeTopic()`), while a subscriber listens. The changes come from `getChangesSince()` of the storage, and the events of one storage make a chain of versions. The option `changeEvents` of `createCollectionProcedures()` turns them off, or gives the topic of each call: the partition of CLI-17 goes there.
|
|
1329
1360
|
- A value reaches a subscriber only through the checks of a read. By default, an event has the ids and the versions only, and `EventsChangeFeed` gives it to `onHint()`: `HybridStorage` reads the values with `changes`, and a hint with only deletes applies without a read. With `changeEvents: { values: true }`, an event also has `values`: each row `{ id, value }` passes the output filter of the host (`admitItem`) for each subscriber, and a refused id goes in `withheld`, so the storage pulls it.
|
|
1330
1361
|
- `EventPublisher` refuses a topic whose reads the capability of the call does not permit (`FORBIDDEN`, `effects-exceeded`). Its new option `reads` gives the reads of a topic. The default, `collectionTopicReads()`, gives `collection:<name>` for `collections.<name>` and `collections.<name>.<partition>`. `ctx.admit` gives a procedure the output filter of its host for the data that it sends later.
|
|
1331
|
-
- The syncs of one `HybridStorage` run one at a time: the deltas and the hints of the feed, the pulls, the pushes, the reads after an own write and the mode switches. A remote delta and a full sync never run at the same time
|
|
1362
|
+
- The syncs of one `HybridStorage` run one at a time: the deltas and the hints of the feed, the pulls, the pushes, the reads after an own write and the mode switches. A remote delta and a full sync never run at the same time.
|
|
1332
1363
|
- The write inputs of the collection procedures take an optional `origin` (1 to 256 characters). The procedure gives it to the storage and to the event. A server before this change ignores the field.
|
|
1333
1364
|
- `Client.subscribe()` and `Client.events()` subscribe to the topics of the bus of the server through the middleware and the context of the client. A subscription has no deadline: the timeouts of the client do not apply to it, and only `metadata: { timeout }` in its options gives one.
|
|
1334
1365
|
- New exports: `collectionChangeTopic`, `CollectionChangeEvent` and `CollectionChangeEventsOptions` from `@procedures/client`, `./browser` and `./procedures`. `EventsChangeFeed`, `MemorySyncStateStore`, `SyncStateError` and the types `RemoteChangeFeed`, `RemoteChangeListener`, `RemoteChanges`, `EventSubscriber`, `ChangeEventSource`, `EventsChangeFeedOptions`, `SyncState`, `SyncStateChange` and `SyncStateStore` from `@procedures/store`. `IndexedDbSyncStateStore` and `MemorySyncStateStore` from `@procedures/store/indexeddb`.
|
|
@@ -1397,7 +1428,7 @@ No changes in this release.
|
|
|
1397
1428
|
|
|
1398
1429
|
### Patch Changes
|
|
1399
1430
|
|
|
1400
|
-
- 389b054: A token check no longer tells the length of the token through its time. The peer compares the SHA-256 digests of the two tokens with `timingSafeEqual`. The `tokenMatches` of the client, which runs in a browser too, compares each character of the expected token for each presented token. Before, a token of another length returned at once.
|
|
1431
|
+
- 389b054: A token check no longer tells the length of the token through its time. The peer compares the SHA-256 digests of the two tokens with `timingSafeEqual`. The `tokenMatches` of the client, which runs in a browser too, compares each character of the expected token for each presented token. Before, a token of another length returned at once. A re-audit found it.
|
|
1401
1432
|
|
|
1402
1433
|
## 0.6.0
|
|
1403
1434
|
|
package/README.md
CHANGED
|
@@ -167,7 +167,7 @@ for await (const event of client.stream({ service: "events", operation: "watch"
|
|
|
167
167
|
|
|
168
168
|
```typescript
|
|
169
169
|
import { defineProcedure, registerProcedures } from "client";
|
|
170
|
-
import
|
|
170
|
+
import * as z from "zod";
|
|
171
171
|
|
|
172
172
|
const getUserProcedure = defineProcedure({
|
|
173
173
|
path: ["users", "get"],
|
|
@@ -693,7 +693,7 @@ http.listen(4820);
|
|
|
693
693
|
- An `OPTIONS` request gets 204 and starts no procedure.
|
|
694
694
|
- `cors: { origin: ["https://app.example"], credentials: true }` lets a page of that origin call with its cookies. A list or a function of origins sends `Access-Control-Allow-Credentials: true` by default.
|
|
695
695
|
- An origin that the CORS does not permit gets no `Access-Control-*` header. With a list or a function of origins, each response gets `Vary: Origin`.
|
|
696
|
-
- `secretHeaders` names more headers that carry a secret, for example `X-
|
|
696
|
+
- `secretHeaders` names more headers that carry a secret, for example `X-App-Token`. `secretQuery` names the query parameters that carry a secret. Its default is `["token"]`. These values go into the credentials of the request, not into its metadata.
|
|
697
697
|
- `handler.middleware` mounts the handler in Connect or Express. A request outside `basePath` goes to `next`.
|
|
698
698
|
- The handler has the stop parts of a service transport: `start()`, `stopIntake()`, `drain(deadline, signal)`, `inFlight()` and `close()`. It does not make a server and does not listen.
|
|
699
699
|
|
|
@@ -743,9 +743,9 @@ const server = new ProcedureServer({
|
|
|
743
743
|
capability: { clearance: "intimate" },
|
|
744
744
|
principalOf: ({ cookies = {}, headers = {}, query = {} }) => ({
|
|
745
745
|
// The token of a cookie, of an application header or of the query
|
|
746
|
-
bearer: cookies["
|
|
746
|
+
bearer: cookies["app_token"] ?? headers["x-app-token"] ?? query["token"],
|
|
747
747
|
// A guest switch can only make the capability narrower
|
|
748
|
-
...(cookies["
|
|
748
|
+
...(cookies["app_audience"] ? { narrowing: { clearance: cookies["app_audience"] } } : {}),
|
|
749
749
|
}),
|
|
750
750
|
});
|
|
751
751
|
```
|