@procedures/client 0.15.0 → 0.15.1
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 +60 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters/http/server/handler.d.ts.map +1 -1
- package/dist/adapters/http/server/handler.js +5 -3
- package/dist/adapters/http/server/handler.js.map +1 -1
- package/dist/browser.d.ts +2 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js.map +1 -1
- package/dist/client/errors/registry.d.ts.map +1 -1
- package/dist/client/errors/registry.js +12 -0
- package/dist/client/errors/registry.js.map +1 -1
- package/dist/client/middleware/rate-limit.d.ts +17 -0
- package/dist/client/middleware/rate-limit.d.ts.map +1 -1
- package/dist/client/middleware/rate-limit.js +94 -39
- package/dist/client/middleware/rate-limit.js.map +1 -1
- package/dist/events/index.d.ts +1 -0
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js.map +1 -1
- package/dist/events/publisher.d.ts +46 -1
- package/dist/events/publisher.d.ts.map +1 -1
- package/dist/events/publisher.js +95 -5
- package/dist/events/publisher.js.map +1 -1
- package/dist/events/recheck.d.ts +84 -0
- package/dist/events/recheck.d.ts.map +1 -0
- package/dist/events/recheck.js +135 -0
- package/dist/events/recheck.js.map +1 -0
- package/dist/protocol.d.ts +1 -1
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +1 -0
- package/dist/protocol.js.map +1 -1
- package/dist/server/host-policy.d.ts +17 -0
- package/dist/server/host-policy.d.ts.map +1 -1
- package/dist/server/host-policy.js +7 -0
- package/dist/server/host-policy.js.map +1 -1
- package/dist/server/limits.d.ts +122 -0
- package/dist/server/limits.d.ts.map +1 -0
- package/dist/server/limits.js +153 -0
- package/dist/server/limits.js.map +1 -0
- package/dist/server/procedure-server.d.ts +31 -1
- package/dist/server/procedure-server.d.ts.map +1 -1
- package/dist/server/procedure-server.js +38 -2
- package/dist/server/procedure-server.js.map +1 -1
- package/dist/server/request-auth.d.ts +5 -1
- package/dist/server/request-auth.d.ts.map +1 -1
- package/dist/server/request-auth.js +19 -2
- package/dist/server/request-auth.js.map +1 -1
- package/package.json +3 -3
- package/src/adapters/http/server/handler.ts +5 -3
- package/src/browser.ts +4 -0
- package/src/client/errors/registry.ts +13 -0
- package/src/client/middleware/rate-limit.ts +116 -41
- package/src/events/index.ts +1 -0
- package/src/events/publisher.ts +116 -6
- package/src/events/recheck.ts +182 -0
- package/src/protocol.ts +3 -1
- package/src/server/host-policy.ts +22 -0
- package/src/server/limits.ts +254 -0
- package/src/server/procedure-server.ts +55 -3
- package/src/server/request-auth.ts +19 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
# @procedures/client
|
|
2
2
|
|
|
3
|
+
## 0.15.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c78da2d: The procedures server can limit the calls of each principal, tenant or route (server stack CLI-40). This change is additive. Without the new option, nothing changes. Thus it is a PATCH of the client group (decision D13).
|
|
8
|
+
|
|
9
|
+
The new behavior:
|
|
10
|
+
|
|
11
|
+
- `hostPolicy()` and `ProcedureServer` of `@procedures/client` have the new option `limits`. Each limit has a name, a key over the call, the calls that it covers, a limit policy, a store and a bound on its keys.
|
|
12
|
+
- The key is the principal, a claim of the principal (`{ claim: "tenant" }`), the route, a list of these, or a function of the call. A call without a value of its key is outside the limit.
|
|
13
|
+
- The option `covers` takes `{ writes: true }` for only the calls that can change data, `{ routes: [...] }` for some procedures, or a function of the call.
|
|
14
|
+
- Each limit is a keyed limiter of `@mark1russell7/service/limiter` (SYS-28) on the clock of the server. The option `limitStores` gives the stores that the replicas share.
|
|
15
|
+
- The server takes one unit of each limit that covers a call, after the authentication and before the run. This is one step for each face: HTTP, WebSocket, MCP and the calls in the process.
|
|
16
|
+
- A call above a limit gets the new error code `RATE_LIMITED` (retryable). Its metadata has the wait in `retry-after` (milliseconds) and the cause in `reason` (`limit`, `cap` or `store`). The call does not run.
|
|
17
|
+
- HTTP gives 429 with `Retry-After` in whole seconds. WebSocket gives the same code and metadata. MCP gives the code, `reason` and `retryAfterMs` in `_meta`.
|
|
18
|
+
- A circuit breaker does not count `RATE_LIMITED`, because the server is healthy.
|
|
19
|
+
- `createProcedureHost()` of `@procedures/peer` declares each limiter on its service with `svc.limiter()`. Thus `describe()` and `lint()` see it. `host.limiters` gives the limiters, and `ProcedureServer.limiters()` gives them too.
|
|
20
|
+
- The rate limit middleware of the client (`createRateLimitMiddleware`) uses the same keyed limiter. Its bucket, its queue and its statistics do not change. The new option `clock` gives the clock of the bucket and of the queue. The default is `Date.now()` and `setTimeout`, as before.
|
|
21
|
+
- The `Retry-After` header of the HTTP face rounds the wait up to whole seconds with the rule of `@mark1russell7/service`. A wait above a whole second only by an error of floating point does not add a second.
|
|
22
|
+
- The client packages use `@mark1russell7/service` 0.5.3 and `@mark1russell7/algebra` 0.7.2.
|
|
23
|
+
|
|
24
|
+
An example for the writes of each tenant:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
hostPolicy({
|
|
28
|
+
principalOf,
|
|
29
|
+
limits: [
|
|
30
|
+
{
|
|
31
|
+
name: "graph.writes",
|
|
32
|
+
key: { claim: "tenant" },
|
|
33
|
+
covers: { writes: true },
|
|
34
|
+
policy: { type: "sliding-window", limit: { value: 120, unit: "count" }, window: { value: 1, unit: "min" } },
|
|
35
|
+
store: { kind: "local" },
|
|
36
|
+
evict: { maxKeys: { value: 10000, unit: "count" } },
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
- d99b2d5: New: an open subscription can get the checks of its admission again (roadmap CLI-44). Before, `EventPublisher` examined the rights of a subscriber only at the start of `events.subscribe`. A subscription of a collection change feed thus continued after the app revoked a right.
|
|
42
|
+
|
|
43
|
+
`rightsChanged(change)` of `EventPublisher` starts a check of each open subscription that the change touches. The change is the id of a principal, a test of the principal, or no value for each subscription. The new option `recheck` of `EventPublisherOptions` has `maxAge`, a check after a time on the clock of the publisher. It also has `rightsChanges`, a source of the changes of the app.
|
|
44
|
+
|
|
45
|
+
The check is the same function as at the start: the topic rule, the reads, `allow` and the partition. While it operates, the events of the subscription wait. A refusal ends the subscription with its error, for example `FORBIDDEN`. The events that waited do not reach the subscriber. The new option `clock` of `EventPublisherOptions` is the clock of `maxAge`, and a `ProcedureServer` gives its own clock. Without a call of `rightsChanged()` and without the option `recheck`, nothing changes.
|
|
46
|
+
- 534e4ea: Fixed: `bearerOf` also reads the scheme of an `Authorization` header in another case (CLI-60). RFC 7235 makes the scheme case-insensitive, with one or more spaces (`1*SP`) before the token. Before, `bearerOf` read only a header that starts with `Bearer ` and one space, so a correct `bearer <token>` got 401.
|
|
47
|
+
|
|
48
|
+
Each header that `bearerOf` read before gives the same token. A correct header in another case passes too, also with more spaces before the token.
|
|
49
|
+
|
|
50
|
+
- A header that starts with `Bearer ` gives the rest of the header, as before.
|
|
51
|
+
- A header with the scheme in another case, for example `bearer` or `BEARER`, gives the token after one or more spaces. Spaces or tabs can come after the token. The token has no whitespace (`token68`).
|
|
52
|
+
- A tab between the scheme and the token is not `1*SP`, so it gives no token.
|
|
53
|
+
- `Basic x`, `Bearer` with no space and an empty header give no token, as before.
|
|
54
|
+
- The token comparison (`tokenMatches`) does not change.
|
|
55
|
+
|
|
56
|
+
Each user of `bearerOf` gets the change. These users are `credentialsOf`, `requestCredentials`, `procedureHandler` and the WebSocket server. The WebSocket admission of `createProcedureHost()`, `guardMcpRequest` and the credentials of the MCP face also get it.
|
|
57
|
+
- 44fdd60: `@types/ws` is a dependency of `@procedures/client`, not a development dependency (CLI-61). The published declarations of the WebSocket transports name the types of `ws`, which is a dependency. Before, a project that checks the declarations of its libraries (`skipLibCheck: false`) and had no `@types/ws` failed to compile. Now each install gets the types with `ws`.
|
|
58
|
+
|
|
59
|
+
The types of `express` stay an optional part, as `express` is an optional peer dependency. A project that checks library declarations and imports the root of the client needs `@types/express` until the next breaking release of the server stack (CLI-6 step 2), which takes the Express types out of the root.
|
|
60
|
+
|
|
61
|
+
PATCH: a dependency of the package changes, and no API changes.
|
|
62
|
+
|
|
3
63
|
## 0.15.0
|
|
4
64
|
|
|
5
65
|
### Minor Changes
|