@constructive-io/graphql-server 5.20.7 → 5.21.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/diagnostics/debug-memory-snapshot.d.ts +3 -0
- package/diagnostics/debug-memory-snapshot.js +2 -0
- package/errors/graphql-response.d.ts +17 -3
- package/errors/graphql-response.js +7 -4
- package/esm/diagnostics/debug-memory-snapshot.js +2 -0
- package/esm/errors/graphql-response.js +7 -4
- package/esm/middleware/admission-control.js +132 -0
- package/esm/middleware/api.js +8 -3
- package/esm/middleware/graphile.js +15 -0
- package/esm/middleware/request-protection.js +2 -0
- package/esm/middleware/routing.js +32 -3
- package/esm/plugins/request-protection-plugin.js +26 -1
- package/esm/refusals/recorder.js +136 -0
- package/esm/server.js +20 -0
- package/middleware/admission-control.d.ts +20 -0
- package/middleware/admission-control.js +136 -0
- package/middleware/api.js +7 -2
- package/middleware/graphile.js +15 -0
- package/middleware/request-protection.js +2 -0
- package/middleware/routing.d.ts +6 -0
- package/middleware/routing.js +34 -4
- package/package.json +15 -15
- package/plugins/request-protection-plugin.d.ts +3 -0
- package/plugins/request-protection-plugin.js +28 -2
- package/refusals/recorder.d.ts +78 -0
- package/refusals/recorder.js +147 -0
- package/server.d.ts +1 -0
- package/server.js +20 -0
package/server.js
CHANGED
|
@@ -20,6 +20,7 @@ const agentic_1 = require("./agentic");
|
|
|
20
20
|
const debug_db_snapshot_1 = require("./diagnostics/debug-db-snapshot");
|
|
21
21
|
const debug_sampler_1 = require("./diagnostics/debug-sampler");
|
|
22
22
|
const observability_1 = require("./diagnostics/observability");
|
|
23
|
+
const admission_control_1 = require("./middleware/admission-control");
|
|
23
24
|
const api_1 = require("./middleware/api");
|
|
24
25
|
const auth_1 = require("./middleware/auth");
|
|
25
26
|
// Auth cookie handling is done via AuthCookiePlugin in grafserv
|
|
@@ -38,6 +39,7 @@ const guard_1 = require("./middleware/observability/guard");
|
|
|
38
39
|
const request_logger_1 = require("./middleware/observability/request-logger");
|
|
39
40
|
const request_protection_1 = require("./middleware/request-protection");
|
|
40
41
|
const routing_1 = require("./middleware/routing");
|
|
42
|
+
const recorder_1 = require("./refusals/recorder");
|
|
41
43
|
const log = new logger_1.Logger('server');
|
|
42
44
|
/**
|
|
43
45
|
* Creates and starts a GraphQL server instance
|
|
@@ -76,6 +78,7 @@ class Server {
|
|
|
76
78
|
closed = false;
|
|
77
79
|
httpServer = null;
|
|
78
80
|
debugSampler = null;
|
|
81
|
+
refusalRecorder = null;
|
|
79
82
|
constructor(opts) {
|
|
80
83
|
this.opts = (0, graphql_env_1.getEnvOptions)(opts);
|
|
81
84
|
const effectiveOpts = this.opts;
|
|
@@ -153,6 +156,13 @@ class Server {
|
|
|
153
156
|
// Resolve the tenant's protection bounds before anything can spend budget
|
|
154
157
|
// on the request (and before the GraphQL handler reads them for pgSettings).
|
|
155
158
|
app.use((0, request_protection_1.createRequestProtectionMiddleware)());
|
|
159
|
+
// Spend the width and rate bounds the line above resolved, before a
|
|
160
|
+
// request can take a pool connection. Scoped to /graphql rather than
|
|
161
|
+
// mounted globally because a concurrency slot is held for as long as the
|
|
162
|
+
// handler runs: the SSE routes below are long-lived by design and would
|
|
163
|
+
// sit in the budget for the life of the stream. The other lanes need
|
|
164
|
+
// their own bound sized for streaming, not this one.
|
|
165
|
+
app.use('/graphql', (0, admission_control_1.createAdmissionControlMiddleware)());
|
|
156
166
|
app.use((0, captcha_1.createCaptchaMiddleware)());
|
|
157
167
|
// CSRF protection for cookie-authenticated requests
|
|
158
168
|
// Skip CSRF for Bearer token auth (not vulnerable to CSRF) and anonymous requests
|
|
@@ -194,6 +204,11 @@ class Server {
|
|
|
194
204
|
app.use(error_handler_1.errorHandler); // Catches all thrown errors
|
|
195
205
|
this.app = app;
|
|
196
206
|
this.debugSampler = observabilityEnabled ? (0, debug_sampler_1.startDebugSampler)(effectiveOpts) : null;
|
|
207
|
+
// Refusals are counted in memory by the middleware above and flushed to
|
|
208
|
+
// the platform table on a timer; the request path never touches the pool.
|
|
209
|
+
this.refusalRecorder = (0, recorder_1.createPlatformRefusalRecorder)(effectiveOpts);
|
|
210
|
+
(0, recorder_1.installRefusalRecorder)(this.refusalRecorder);
|
|
211
|
+
this.refusalRecorder.start();
|
|
197
212
|
}
|
|
198
213
|
listen() {
|
|
199
214
|
const { server } = this.opts;
|
|
@@ -298,6 +313,11 @@ class Server {
|
|
|
298
313
|
this.closed = true;
|
|
299
314
|
this.shuttingDown = true;
|
|
300
315
|
await this.removeEventListener();
|
|
316
|
+
if (this.refusalRecorder) {
|
|
317
|
+
(0, recorder_1.installRefusalRecorder)(null);
|
|
318
|
+
await this.refusalRecorder.stop();
|
|
319
|
+
this.refusalRecorder = null;
|
|
320
|
+
}
|
|
301
321
|
if (this.debugSampler) {
|
|
302
322
|
await this.debugSampler.stop();
|
|
303
323
|
this.debugSampler = null;
|