@substrat-run/contracts 0.137.0 → 0.139.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.
- package/dist/control-plane.d.ts +122 -0
- package/dist/control-plane.d.ts.map +1 -1
- package/dist/control-plane.js +95 -0
- package/dist/control-plane.js.map +1 -1
- package/dist/deploy.d.ts +12 -0
- package/dist/deploy.d.ts.map +1 -1
- package/dist/entity-state.d.ts +95 -0
- package/dist/entity-state.d.ts.map +1 -0
- package/dist/entity-state.js +79 -0
- package/dist/entity-state.js.map +1 -0
- package/dist/errors.d.ts +24 -5
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +23 -5
- package/dist/errors.js.map +1 -1
- package/dist/findings.d.ts +208 -0
- package/dist/findings.d.ts.map +1 -0
- package/dist/findings.js +116 -0
- package/dist/findings.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/kernel-events.d.ts.map +1 -1
- package/dist/kernel-events.js +5 -0
- package/dist/kernel-events.js.map +1 -1
- package/dist/lifecycle-flow.d.ts +2 -0
- package/dist/lifecycle-flow.d.ts.map +1 -1
- package/dist/lifecycle-flow.js +4 -4
- package/dist/lifecycle-flow.js.map +1 -1
- package/dist/manifest.d.ts +7 -0
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +7 -0
- package/dist/manifest.js.map +1 -1
- package/dist/model.d.ts +52 -0
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +39 -0
- package/dist/model.js.map +1 -1
- package/dist/openapi.d.ts.map +1 -1
- package/dist/openapi.js +24 -0
- package/dist/openapi.js.map +1 -1
- package/dist/operation-series.d.ts +88 -0
- package/dist/operation-series.d.ts.map +1 -0
- package/dist/operation-series.js +95 -0
- package/dist/operation-series.js.map +1 -0
- package/dist/peer.d.ts +2 -0
- package/dist/peer.d.ts.map +1 -1
- package/dist/peer.js +4 -0
- package/dist/peer.js.map +1 -1
- package/dist/permission.d.ts +23 -5
- package/dist/permission.d.ts.map +1 -1
- package/dist/permission.js +24 -4
- package/dist/permission.js.map +1 -1
- package/dist/rate-limit.d.ts +147 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +248 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/sql-tokens.d.ts +9 -1
- package/dist/sql-tokens.d.ts.map +1 -1
- package/dist/sql-tokens.js +4 -1
- package/dist/sql-tokens.js.map +1 -1
- package/package.json +1 -1
package/dist/permission.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission.js","sourceRoot":"","sources":["../src/permission.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"permission.js","sourceRoot":"","sources":["../src/permission.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request rate limiting on the request path (#130).
|
|
3
|
+
*
|
|
4
|
+
* A tenant must be protected from another tenant, and from its own AI-built frontend with
|
|
5
|
+
* a polling bug. The limit is enforced where a request first meets the platform: the router
|
|
6
|
+
* on the hosted path, `@substrat-run/vertical-host`'s `rateLimit()` middleware on a node
|
|
7
|
+
* host with no router in front. Never in a scope host and never in the kernel: a limiter in
|
|
8
|
+
* a scope DO serialises behind that scope's write queue, and cannot see one token's
|
|
9
|
+
* traffic across scopes.
|
|
10
|
+
*
|
|
11
|
+
* ## Why the policy lives here
|
|
12
|
+
*
|
|
13
|
+
* Both of those choke points derive the same keys, speak the same headers and refuse with
|
|
14
|
+
* the same problem — through one call, {@link evaluateRateLimits}. This file is that grammar
|
|
15
|
+
* and nothing else: which counter remembers a key is the caller's ({@link RateLimiter}), so
|
|
16
|
+
* the router binds Cloudflare's native rate-limit binding and a node host binds
|
|
17
|
+
* vertical-host's `memoryRateLimiter`, and the two cannot disagree about what a key or a 429
|
|
18
|
+
* looks like.
|
|
19
|
+
*
|
|
20
|
+
* ## The keys
|
|
21
|
+
*
|
|
22
|
+
* Every key begins `<tenant>:<scope>:<bucket>:`, so one tenant's traffic can never spend
|
|
23
|
+
* another tenant's budget. That is a property of the key, not of a configuration.
|
|
24
|
+
*
|
|
25
|
+
* - **credential**: one budget per caller. A bearer token when the request carries one, else
|
|
26
|
+
* the session cookie a signed-in browser carries, else the client address. A credential is
|
|
27
|
+
* only ever represented by a truncated SHA-256 digest: the raw token or cookie is never
|
|
28
|
+
* part of a key, so it reaches no counter and no log line.
|
|
29
|
+
* - **ip**: one budget per client address, set well above the credential budget. The router
|
|
30
|
+
* cannot verify a bearer, so without it a caller minting a fresh fake token per request
|
|
31
|
+
* would get a fresh credential budget per request too.
|
|
32
|
+
*
|
|
33
|
+
* ## The fail mode
|
|
34
|
+
*
|
|
35
|
+
* Open. A limiter that throws lets the request through, and the caller logs it. The limiter
|
|
36
|
+
* protects capacity; it is not an authorization boundary — every request still meets the
|
|
37
|
+
* vertical's authentication and permission checks — and failing closed would turn an outage
|
|
38
|
+
* of the counter into an outage of every tenant behind it.
|
|
39
|
+
*/
|
|
40
|
+
import { type Problem } from './errors.js';
|
|
41
|
+
/** RFC 9110 §10.2.3: seconds a client should wait before trying again. */
|
|
42
|
+
export declare const RETRY_AFTER_HEADER = "Retry-After";
|
|
43
|
+
/** The policies a response was judged against (draft-ietf-httpapi-ratelimit-headers). */
|
|
44
|
+
export declare const RATE_LIMIT_POLICY_HEADER = "RateLimit-Policy";
|
|
45
|
+
/** The state of the policy that refused (same draft): nothing remaining, and when it resets. */
|
|
46
|
+
export declare const RATE_LIMIT_HEADER = "RateLimit";
|
|
47
|
+
/**
|
|
48
|
+
* Exposed to a cross-origin browser client — the same trap `IDEMPOTENCY_EXPOSED_HEADERS`
|
|
49
|
+
* documents. An unexposed `Retry-After` is the one that matters: a frontend that cannot
|
|
50
|
+
* read it cannot back off by it.
|
|
51
|
+
*/
|
|
52
|
+
export declare const RATE_LIMIT_EXPOSED_HEADERS: readonly ["Retry-After", "RateLimit", "RateLimit-Policy"];
|
|
53
|
+
/**
|
|
54
|
+
* The counter seam. Exactly the shape of Cloudflare's rate-limit binding, so the binding IS
|
|
55
|
+
* a `RateLimiter` and needs no wrapper. `success: false` means the key is over its limit.
|
|
56
|
+
*/
|
|
57
|
+
export interface RateLimiter {
|
|
58
|
+
limit(options: {
|
|
59
|
+
key: string;
|
|
60
|
+
}): Promise<{
|
|
61
|
+
success: boolean;
|
|
62
|
+
}>;
|
|
63
|
+
}
|
|
64
|
+
/** The two buckets every request is counted in. */
|
|
65
|
+
export declare const RATE_LIMIT_BUCKETS: readonly ['credential', 'ip'];
|
|
66
|
+
export type RateLimitBucket = (typeof RATE_LIMIT_BUCKETS)[number];
|
|
67
|
+
/** One bucket's budget: `limit` requests per `period` seconds. */
|
|
68
|
+
export interface RateLimitPolicy {
|
|
69
|
+
readonly limit: number;
|
|
70
|
+
readonly period: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The defaults: conservative, so a normal client never meets them. 1200 a minute per
|
|
74
|
+
* credential is twenty requests a second sustained; the address budget is five times that,
|
|
75
|
+
* so an office behind one NAT, every person on their own session, stays well clear of it.
|
|
76
|
+
* A deployment sets its own (the router's `wrangler.jsonc`, a node host's options).
|
|
77
|
+
*/
|
|
78
|
+
export declare const DEFAULT_RATE_LIMITS: Readonly<Record<RateLimitBucket, RateLimitPolicy>>;
|
|
79
|
+
/**
|
|
80
|
+
* Read a deployment's configured limits, or `undefined` when they are not a complete,
|
|
81
|
+
* well-formed set. Strict on purpose: a typo in a limit must be loud (the caller logs and
|
|
82
|
+
* fails open), never a silently different budget.
|
|
83
|
+
*/
|
|
84
|
+
export declare function parseRateLimits(value: unknown): Record<RateLimitBucket, RateLimitPolicy> | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* The cookies that ARE a signed-in browser's credential: the platform session (oidc-rp's
|
|
87
|
+
* `sb_session`), a capability session (`sb_capability`, one cookie per link since #1686), and
|
|
88
|
+
* Better Auth's session token on an instance using that provider. Any other cookie — a
|
|
89
|
+
* preference, an analytics id — says nothing about who is calling and is ignored.
|
|
90
|
+
*/
|
|
91
|
+
export declare function isSessionCookie(name: string): boolean;
|
|
92
|
+
/** What a request offers to be counted by. Header values are read, never kept. */
|
|
93
|
+
export interface RateLimitSubject {
|
|
94
|
+
readonly tenantId: string;
|
|
95
|
+
readonly scopeId: string;
|
|
96
|
+
readonly headers: Headers;
|
|
97
|
+
/** The client address, when the host knows one. Absent ⇒ one shared anonymous budget. */
|
|
98
|
+
readonly clientIp?: string | null | undefined;
|
|
99
|
+
/** The request method. An `OPTIONS` preflight is never counted (see {@link evaluateRateLimits}). */
|
|
100
|
+
readonly method?: string;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The key one request is counted under in one bucket. Async because a credential is hashed
|
|
104
|
+
* (Web Crypto) before it goes anywhere — and only when the credential bucket is counted.
|
|
105
|
+
*/
|
|
106
|
+
export declare function rateLimitKey(bucket: RateLimitBucket, subject: RateLimitSubject): Promise<string>;
|
|
107
|
+
/** A 429, as the parts a host's own `Response` is built from. */
|
|
108
|
+
export interface RateLimitedRefusal {
|
|
109
|
+
readonly status: 429;
|
|
110
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
111
|
+
readonly body: Problem;
|
|
112
|
+
}
|
|
113
|
+
/** What one request's count decided, for the host to answer and log. */
|
|
114
|
+
export interface RateLimitEvaluation {
|
|
115
|
+
/** The 429 to answer instead of serving the request, when a bucket refused it. */
|
|
116
|
+
readonly refusal?: RateLimitedRefusal;
|
|
117
|
+
/** `RateLimit-Policy` for the response the request goes on to get; null when nothing counted it. */
|
|
118
|
+
readonly policyHeader: string | null;
|
|
119
|
+
/**
|
|
120
|
+
* Set when a counter threw and the request was let through anyway (fail open): the fields of
|
|
121
|
+
* the host's `rate-limit-unavailable` log line. Never a key — even a digest has no business
|
|
122
|
+
* in a log line.
|
|
123
|
+
*/
|
|
124
|
+
readonly unavailable?: {
|
|
125
|
+
readonly reason: string;
|
|
126
|
+
readonly buckets: RateLimitBucket[];
|
|
127
|
+
readonly error: string[];
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Count one request in the buckets that have a counter — the whole decision both hosts make.
|
|
132
|
+
*
|
|
133
|
+
* The ADDRESS is counted first, and a request it refuses is never counted against a
|
|
134
|
+
* credential. A credential key is minted from whatever the request sends, so a caller
|
|
135
|
+
* rotating made-up tokens from one address would otherwise create a fresh credential counter
|
|
136
|
+
* with every request it was already refused for — unbounded state in a counter that keeps
|
|
137
|
+
* its keys (the node host's), and spent budget on keys nobody holds. Once the address is
|
|
138
|
+
* over, the credential bucket is not asked.
|
|
139
|
+
*/
|
|
140
|
+
export declare function evaluateRateLimits(input: {
|
|
141
|
+
readonly subject: RateLimitSubject;
|
|
142
|
+
readonly policies: Readonly<Record<RateLimitBucket, RateLimitPolicy>>;
|
|
143
|
+
readonly limiters: Readonly<Partial<Record<RateLimitBucket, RateLimiter>>>;
|
|
144
|
+
/** The request path, for the problem's `instance`. */
|
|
145
|
+
readonly instance?: string;
|
|
146
|
+
}): Promise<RateLimitEvaluation>;
|
|
147
|
+
//# sourceMappingURL=rate-limit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request rate limiting on the request path (#130).
|
|
3
|
+
*
|
|
4
|
+
* A tenant must be protected from another tenant, and from its own AI-built frontend with
|
|
5
|
+
* a polling bug. The limit is enforced where a request first meets the platform: the router
|
|
6
|
+
* on the hosted path, `@substrat-run/vertical-host`'s `rateLimit()` middleware on a node
|
|
7
|
+
* host with no router in front. Never in a scope host and never in the kernel: a limiter in
|
|
8
|
+
* a scope DO serialises behind that scope's write queue, and cannot see one token's
|
|
9
|
+
* traffic across scopes.
|
|
10
|
+
*
|
|
11
|
+
* ## Why the policy lives here
|
|
12
|
+
*
|
|
13
|
+
* Both of those choke points derive the same keys, speak the same headers and refuse with
|
|
14
|
+
* the same problem — through one call, {@link evaluateRateLimits}. This file is that grammar
|
|
15
|
+
* and nothing else: which counter remembers a key is the caller's ({@link RateLimiter}), so
|
|
16
|
+
* the router binds Cloudflare's native rate-limit binding and a node host binds
|
|
17
|
+
* vertical-host's `memoryRateLimiter`, and the two cannot disagree about what a key or a 429
|
|
18
|
+
* looks like.
|
|
19
|
+
*
|
|
20
|
+
* ## The keys
|
|
21
|
+
*
|
|
22
|
+
* Every key begins `<tenant>:<scope>:<bucket>:`, so one tenant's traffic can never spend
|
|
23
|
+
* another tenant's budget. That is a property of the key, not of a configuration.
|
|
24
|
+
*
|
|
25
|
+
* - **credential**: one budget per caller. A bearer token when the request carries one, else
|
|
26
|
+
* the session cookie a signed-in browser carries, else the client address. A credential is
|
|
27
|
+
* only ever represented by a truncated SHA-256 digest: the raw token or cookie is never
|
|
28
|
+
* part of a key, so it reaches no counter and no log line.
|
|
29
|
+
* - **ip**: one budget per client address, set well above the credential budget. The router
|
|
30
|
+
* cannot verify a bearer, so without it a caller minting a fresh fake token per request
|
|
31
|
+
* would get a fresh credential budget per request too.
|
|
32
|
+
*
|
|
33
|
+
* ## The fail mode
|
|
34
|
+
*
|
|
35
|
+
* Open. A limiter that throws lets the request through, and the caller logs it. The limiter
|
|
36
|
+
* protects capacity; it is not an authorization boundary — every request still meets the
|
|
37
|
+
* vertical's authentication and permission checks — and failing closed would turn an outage
|
|
38
|
+
* of the counter into an outage of every tenant behind it.
|
|
39
|
+
*/
|
|
40
|
+
import { substratError, toProblem, PROBLEM_CONTENT_TYPE } from './errors.js';
|
|
41
|
+
/** RFC 9110 §10.2.3: seconds a client should wait before trying again. */
|
|
42
|
+
export const RETRY_AFTER_HEADER = 'Retry-After';
|
|
43
|
+
/** The policies a response was judged against (draft-ietf-httpapi-ratelimit-headers). */
|
|
44
|
+
export const RATE_LIMIT_POLICY_HEADER = 'RateLimit-Policy';
|
|
45
|
+
/** The state of the policy that refused (same draft): nothing remaining, and when it resets. */
|
|
46
|
+
export const RATE_LIMIT_HEADER = 'RateLimit';
|
|
47
|
+
/**
|
|
48
|
+
* Exposed to a cross-origin browser client — the same trap `IDEMPOTENCY_EXPOSED_HEADERS`
|
|
49
|
+
* documents. An unexposed `Retry-After` is the one that matters: a frontend that cannot
|
|
50
|
+
* read it cannot back off by it.
|
|
51
|
+
*/
|
|
52
|
+
export const RATE_LIMIT_EXPOSED_HEADERS = [RETRY_AFTER_HEADER, RATE_LIMIT_HEADER, RATE_LIMIT_POLICY_HEADER];
|
|
53
|
+
/** The two buckets every request is counted in. */
|
|
54
|
+
export const RATE_LIMIT_BUCKETS = ['credential', 'ip'];
|
|
55
|
+
/**
|
|
56
|
+
* The defaults: conservative, so a normal client never meets them. 1200 a minute per
|
|
57
|
+
* credential is twenty requests a second sustained; the address budget is five times that,
|
|
58
|
+
* so an office behind one NAT, every person on their own session, stays well clear of it.
|
|
59
|
+
* A deployment sets its own (the router's `wrangler.jsonc`, a node host's options).
|
|
60
|
+
*/
|
|
61
|
+
export const DEFAULT_RATE_LIMITS = {
|
|
62
|
+
credential: { limit: 1200, period: 60 },
|
|
63
|
+
ip: { limit: 6000, period: 60 },
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Read a deployment's configured limits, or `undefined` when they are not a complete,
|
|
67
|
+
* well-formed set. Strict on purpose: a typo in a limit must be loud (the caller logs and
|
|
68
|
+
* fails open), never a silently different budget.
|
|
69
|
+
*/
|
|
70
|
+
export function parseRateLimits(value) {
|
|
71
|
+
if (typeof value !== 'object' || value === null)
|
|
72
|
+
return undefined;
|
|
73
|
+
const out = {};
|
|
74
|
+
for (const bucket of RATE_LIMIT_BUCKETS) {
|
|
75
|
+
const policy = value[bucket];
|
|
76
|
+
if (!isPositiveInt(policy?.limit) || !isPositiveInt(policy?.period))
|
|
77
|
+
return undefined;
|
|
78
|
+
out[bucket] = { limit: policy.limit, period: policy.period };
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
const isPositiveInt = (n) => Number.isInteger(n) && n > 0;
|
|
83
|
+
/**
|
|
84
|
+
* The cookies that ARE a signed-in browser's credential: the platform session (oidc-rp's
|
|
85
|
+
* `sb_session`), a capability session (`sb_capability`, one cookie per link since #1686), and
|
|
86
|
+
* Better Auth's session token on an instance using that provider. Any other cookie — a
|
|
87
|
+
* preference, an analytics id — says nothing about who is calling and is ignored.
|
|
88
|
+
*/
|
|
89
|
+
export function isSessionCookie(name) {
|
|
90
|
+
return (name === 'sb_session' ||
|
|
91
|
+
name.startsWith('sb_capability') ||
|
|
92
|
+
name === 'better-auth.session_token' ||
|
|
93
|
+
name === '__Secure-better-auth.session_token');
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The key one request is counted under in one bucket. Async because a credential is hashed
|
|
97
|
+
* (Web Crypto) before it goes anywhere — and only when the credential bucket is counted.
|
|
98
|
+
*/
|
|
99
|
+
export async function rateLimitKey(bucket, subject) {
|
|
100
|
+
const address = subject.clientIp ? `ip:${subject.clientIp}` : 'anon';
|
|
101
|
+
const caller = bucket === 'credential' ? ((await credentialOf(subject.headers)) ?? address) : address;
|
|
102
|
+
return `${subject.tenantId}:${subject.scopeId}:${bucket}:${caller}`;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The caller's credential as a digest: `b:` for a bearer, `s:` for a session cookie set.
|
|
106
|
+
* Every session cookie the request carries is hashed together, sorted, so a browser holding
|
|
107
|
+
* a stale host-only `sb_session` beside its domain one is still one caller.
|
|
108
|
+
*/
|
|
109
|
+
async function credentialOf(headers) {
|
|
110
|
+
const authorization = headers.get('authorization');
|
|
111
|
+
if (authorization)
|
|
112
|
+
return `b:${await digest(authorization)}`;
|
|
113
|
+
const session = sessionCookiesOf(headers.get('cookie'));
|
|
114
|
+
if (session.length > 0)
|
|
115
|
+
return `s:${await digest(session.join('\n'))}`;
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
function sessionCookiesOf(header) {
|
|
119
|
+
if (!header)
|
|
120
|
+
return [];
|
|
121
|
+
const out = [];
|
|
122
|
+
for (const part of header.split(';')) {
|
|
123
|
+
const eq = part.indexOf('=');
|
|
124
|
+
if (eq === -1)
|
|
125
|
+
continue;
|
|
126
|
+
const name = part.slice(0, eq).trim();
|
|
127
|
+
if (isSessionCookie(name))
|
|
128
|
+
out.push(`${name}=${part.slice(eq + 1).trim()}`);
|
|
129
|
+
}
|
|
130
|
+
return out.sort();
|
|
131
|
+
}
|
|
132
|
+
/** 128 bits of SHA-256, hex: unguessable, and short enough to be a counter key. */
|
|
133
|
+
async function digest(text) {
|
|
134
|
+
const bytes = new Uint8Array(await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(text)));
|
|
135
|
+
let hex = '';
|
|
136
|
+
for (const b of bytes.subarray(0, 16))
|
|
137
|
+
hex += b.toString(16).padStart(2, '0');
|
|
138
|
+
return hex;
|
|
139
|
+
}
|
|
140
|
+
/** The order buckets are counted in: the address first (see {@link evaluateRateLimits}). */
|
|
141
|
+
const COUNTING_ORDER = ['ip', 'credential'];
|
|
142
|
+
/**
|
|
143
|
+
* Count one request in the buckets that have a counter — the whole decision both hosts make.
|
|
144
|
+
*
|
|
145
|
+
* The ADDRESS is counted first, and a request it refuses is never counted against a
|
|
146
|
+
* credential. A credential key is minted from whatever the request sends, so a caller
|
|
147
|
+
* rotating made-up tokens from one address would otherwise create a fresh credential counter
|
|
148
|
+
* with every request it was already refused for — unbounded state in a counter that keeps
|
|
149
|
+
* its keys (the node host's), and spent budget on keys nobody holds. Once the address is
|
|
150
|
+
* over, the credential bucket is not asked.
|
|
151
|
+
*/
|
|
152
|
+
export async function evaluateRateLimits(input) {
|
|
153
|
+
// A CORS preflight is never counted, so never refused: a refused preflight is opaque to the
|
|
154
|
+
// page whatever headers it carries, so the page could not read the 429 its real request
|
|
155
|
+
// would have met. It reaches the vertical's own preflight handler instead.
|
|
156
|
+
if (input.subject.method === 'OPTIONS')
|
|
157
|
+
return { policyHeader: null };
|
|
158
|
+
const buckets = RATE_LIMIT_BUCKETS.filter((bucket) => input.limiters[bucket]);
|
|
159
|
+
if (buckets.length === 0)
|
|
160
|
+
return { policyHeader: null };
|
|
161
|
+
const results = [];
|
|
162
|
+
for (const bucket of COUNTING_ORDER) {
|
|
163
|
+
const limiter = input.limiters[bucket];
|
|
164
|
+
if (!limiter)
|
|
165
|
+
continue;
|
|
166
|
+
try {
|
|
167
|
+
const key = await rateLimitKey(bucket, input.subject);
|
|
168
|
+
results.push({ bucket, success: (await limiter.limit({ key })).success });
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
results.push({ bucket, success: true, error: error instanceof Error ? error.message : String(error) });
|
|
172
|
+
}
|
|
173
|
+
if (!results.at(-1).success)
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
const policyHeader = buckets
|
|
177
|
+
.map((bucket) => `"${bucket}";q=${input.policies[bucket].limit};w=${input.policies[bucket].period}`)
|
|
178
|
+
.join(', ');
|
|
179
|
+
const failed = results.filter((r) => r.error !== undefined);
|
|
180
|
+
const unavailable = failed.length > 0
|
|
181
|
+
? {
|
|
182
|
+
reason: 'the rate limiter threw; the request was let through',
|
|
183
|
+
buckets: failed.map((r) => r.bucket),
|
|
184
|
+
error: failed.map((r) => r.error),
|
|
185
|
+
}
|
|
186
|
+
: undefined;
|
|
187
|
+
const refused = results.find((r) => !r.success)?.bucket;
|
|
188
|
+
return {
|
|
189
|
+
policyHeader,
|
|
190
|
+
...(unavailable ? { unavailable } : {}),
|
|
191
|
+
...(refused
|
|
192
|
+
? {
|
|
193
|
+
refusal: refusalFor(refused, input.policies[refused], policyHeader, {
|
|
194
|
+
instance: input.instance,
|
|
195
|
+
origin: input.subject.headers.get('origin'),
|
|
196
|
+
}),
|
|
197
|
+
}
|
|
198
|
+
: {}),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* The refusal: 429 `application/problem+json` with code `rate_limited`, and the headers a
|
|
203
|
+
* client backs off by. Parts rather than a `Response`, as the rest of this package hands out
|
|
204
|
+
* data: each host builds its own.
|
|
205
|
+
*
|
|
206
|
+
* `Retry-After` is the bucket's whole period. A counter that cannot say where in its window
|
|
207
|
+
* a key sits (Cloudflare's binding cannot) makes the period the only bound that is never
|
|
208
|
+
* too short, and a retry that is too early is just another 429.
|
|
209
|
+
*/
|
|
210
|
+
function refusalFor(bucket, policy, policyHeader, { instance, origin }) {
|
|
211
|
+
const retryAfter = policy.period;
|
|
212
|
+
const body = toProblem(substratError('rate_limited', `Too many requests for this ${bucket === 'ip' ? 'client address' : 'credential'}: ` +
|
|
213
|
+
`at most ${policy.limit} every ${policy.period} seconds. Retry after ${retryAfter} seconds.`, { retryAfter }), instance);
|
|
214
|
+
return {
|
|
215
|
+
status: 429,
|
|
216
|
+
headers: {
|
|
217
|
+
'content-type': PROBLEM_CONTENT_TYPE,
|
|
218
|
+
[RETRY_AFTER_HEADER]: String(retryAfter),
|
|
219
|
+
[RATE_LIMIT_POLICY_HEADER]: policyHeader,
|
|
220
|
+
[RATE_LIMIT_HEADER]: `"${bucket}";r=0;t=${retryAfter}`,
|
|
221
|
+
...(origin ? refusalCors(origin) : {}),
|
|
222
|
+
},
|
|
223
|
+
body,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* CORS for the refusal, and only for it.
|
|
228
|
+
*
|
|
229
|
+
* A refusal is answered before the vertical runs, so the vertical's own CORS policy never
|
|
230
|
+
* sees it. Without these headers a cross-origin page reads a network error rather than a
|
|
231
|
+
* 429, and cannot back off by `Retry-After` — the polling loop this exists to stop keeps
|
|
232
|
+
* polling. The route names no origin allowlist to follow, so the refusal reflects whichever
|
|
233
|
+
* origin asked, credentials included.
|
|
234
|
+
*
|
|
235
|
+
* That is safe for THIS response and would not be for any other: the body and headers are
|
|
236
|
+
* the requester's own rate state — the budget that refused and when to retry — and no vertical
|
|
237
|
+
* data, which is why the policy is built here and never applied to a response the vertical
|
|
238
|
+
* gave.
|
|
239
|
+
*/
|
|
240
|
+
function refusalCors(origin) {
|
|
241
|
+
return {
|
|
242
|
+
'access-control-allow-origin': origin,
|
|
243
|
+
'access-control-allow-credentials': 'true',
|
|
244
|
+
'access-control-expose-headers': RATE_LIMIT_EXPOSED_HEADERS.join(', '),
|
|
245
|
+
vary: 'Origin',
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=rate-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"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"}
|
package/dist/sql-tokens.d.ts
CHANGED
|
@@ -22,9 +22,17 @@ export interface SqlToken {
|
|
|
22
22
|
readonly text: string;
|
|
23
23
|
/** A quoted identifier or string literal — never read as a keyword. */
|
|
24
24
|
readonly quoted: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* One of `( ) , = ;`, present only when asked for (`{ punctuation: true }`). A reader that
|
|
27
|
+
* has to know WHERE in a statement a name sits — an assignment target, a column list — needs
|
|
28
|
+
* these; one that only looks for table names does not, and gets the same tokens it always did.
|
|
29
|
+
*/
|
|
30
|
+
readonly punct?: true;
|
|
25
31
|
}
|
|
26
32
|
/** The statement text as identifier and keyword tokens, comments and whitespace dropped. */
|
|
27
|
-
export declare function tokenizeSql(sql: string
|
|
33
|
+
export declare function tokenizeSql(sql: string, options?: {
|
|
34
|
+
readonly punctuation?: boolean;
|
|
35
|
+
}): SqlToken[];
|
|
28
36
|
/** True when any part of a (possibly dotted, possibly quoted) name is a spine table. */
|
|
29
37
|
export declare function namesSpineTable(name: string): boolean;
|
|
30
38
|
/**
|
package/dist/sql-tokens.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-tokens.d.ts","sourceRoot":"","sources":["../src/sql-tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,YAAY,cAAc,CAAC;AAExC,MAAM,WAAW,QAAQ;IACvB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"sql-tokens.d.ts","sourceRoot":"","sources":["../src/sql-tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,YAAY,cAAc,CAAC;AAExC,MAAM,WAAW,QAAQ;IACvB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC;CACvB;AAID,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,QAAQ,EAAE,CAsGjG;AAED,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAEtD;AAED,gGAAgG;AAChG,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,EAAE,CAOxE"}
|
package/dist/sql-tokens.js
CHANGED
|
@@ -17,8 +17,9 @@
|
|
|
17
17
|
* `_SUBSTRAT_TUPLES` is the tuples table.
|
|
18
18
|
*/
|
|
19
19
|
export const SPINE_PREFIX = '_substrat';
|
|
20
|
+
const PUNCTUATION = new Set(['(', ')', ',', '=', ';']);
|
|
20
21
|
/** The statement text as identifier and keyword tokens, comments and whitespace dropped. */
|
|
21
|
-
export function tokenizeSql(sql) {
|
|
22
|
+
export function tokenizeSql(sql, options) {
|
|
22
23
|
const tokens = [];
|
|
23
24
|
const n = sql.length;
|
|
24
25
|
let i = 0;
|
|
@@ -122,6 +123,8 @@ export function tokenizeSql(sql) {
|
|
|
122
123
|
// Whitespace does not break a dotted name (`main . tbl` is one); anything else does.
|
|
123
124
|
if (!/\s/.test(c))
|
|
124
125
|
continues = false;
|
|
126
|
+
if (options?.punctuation && PUNCTUATION.has(c))
|
|
127
|
+
tokens.push({ text: c, quoted: false, punct: true });
|
|
125
128
|
i += 1;
|
|
126
129
|
}
|
|
127
130
|
return tokens;
|
package/dist/sql-tokens.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-tokens.js","sourceRoot":"","sources":["../src/sql-tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"sql-tokens.js","sourceRoot":"","sources":["../src/sql-tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC;AAexC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAEvD,4FAA4F;AAC5F,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,OAA4C;IACnF,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC;IACrB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,mFAAmF;IACnF,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,MAAe,EAAQ,EAAE;QACnD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACvC,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;YACtB,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;QAC9F,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAChC,CAAC;QACD,gFAAgF;QAChF,+EAA+E;QAC/E,kFAAkF;QAClF,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,SAAS,CAAC;YACR,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;gBAChC,CAAC,IAAI,CAAC,CAAC;gBACP,SAAS;YACX,CAAC;YACD,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACzC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI;oBAAE,CAAC,IAAI,CAAC,CAAC;gBACxC,SAAS;YACX,CAAC;YACD,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACzC,CAAC,IAAI,CAAC,CAAC;gBACP,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC;oBAAE,CAAC,IAAI,CAAC,CAAC;gBAChE,CAAC,IAAI,CAAC,CAAC;gBACP,SAAS;YACX,CAAC;YACD,MAAM;QACR,CAAC;QACD,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACnB,SAAS,GAAG,IAAI,CAAC;YACjB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACb,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAE,CAAC;QAClB,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI;gBAAE,CAAC,IAAI,CAAC,CAAC;YACxC,SAAS;QACX,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAC5B,CAAC,IAAI,CAAC,CAAC;YACP,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC;gBAAE,CAAC,IAAI,CAAC,CAAC;YAChE,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACxC,4EAA4E;YAC5E,mEAAmE;YACnE,CAAC,IAAI,CAAC,CAAC;YACP,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBACb,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;oBACjB,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;wBACrB,IAAI,IAAI,CAAC,CAAC;wBACV,CAAC,IAAI,CAAC,CAAC;wBACP,SAAS;oBACX,CAAC;oBACD,CAAC,IAAI,CAAC,CAAC;oBACP,MAAM;gBACR,CAAC;gBACD,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;gBACf,CAAC,IAAI,CAAC,CAAC;YACT,CAAC;YACD,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjB,SAAS;QACX,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,CAAC,IAAI,CAAC,CAAC;YACP,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC/B,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;gBACf,CAAC,IAAI,CAAC,CAAC;YACT,CAAC;YACD,CAAC,IAAI,CAAC,CAAC;YACP,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjB,SAAS;QACX,CAAC;QACD,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC;gBAAE,CAAC,IAAI,CAAC,CAAC;YACtD,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC7B,CAAC,GAAG,CAAC,CAAC;YACN,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAClB,SAAS;QACX,CAAC;QACD,qFAAqF;QACrF,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,SAAS,GAAG,KAAK,CAAC;QACrC,IAAI,OAAO,EAAE,WAAW,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrG,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;AACrF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,kBAAkB,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,kBAAkB,CAAC,MAA2B;IAC5D,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,YAAY;YAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@substrat-run/contracts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.139.0",
|
|
4
4
|
"description": "Substrat kernel contract schemas — Zod is the source of truth (master plan D-22); OAS/JSON Schema are emitted artifacts",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|