Configuration
Devtools work with no configuration in development. Everything below is for changing where they mount, how much they keep and who is allowed in.
Options
import { defineConfig, withPluginOptions } from '@vercube/core';
import { DevtoolsPlugin } from '@vercube/devtools';
export default defineConfig({
plugins: [
withPluginOptions(DevtoolsPlugin, {
path: '/__inspect',
token: process.env.DEVTOOLS_TOKEN,
maxRequests: 500,
redactHeaders: ['x-internal-signature'],
}),
],
});
| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | config.dev | Master switch. Off in production unless explicitly enabled. |
path | string | '/_devtools' | Where the UI and its API are mounted. |
token | string | null | null | Access token. Required in production. Read from x-devtools-token or the vercube_devtools_token cookie; ?token= is honoured on the UI page only. |
maxRequests | number | 250 | Size of the in-memory request ring buffer. |
trackRequests | boolean | true | Record per-request timelines. |
captureHeaders | boolean | true | Capture request and response headers. |
redactHeaders | string[] | [] | Extra header names to redact on top of the built-in list. |
captureBodies | boolean | true | Capture request and response bodies for the inspector. |
maxBodyBytes | number | 65536 | Largest body kept per message. |
captureLogs | boolean | true | Capture lines written through the Logger service. |
maxLogs | number | 500 | Size of the in-memory log ring buffer. |
When devtools are active
Unless you set enabled explicitly, devtools run when config.dev is true and config.production is not. A production build therefore installs none of the hooks at all, and turning devtools on anywhere else takes an explicit enabled: true. With production: true the plugin refuses to mount without a token and logs an error instead of exposing the inspector.
Access tokens
Set a token whenever the application is reachable by anyone but you:
withPluginOptions(DevtoolsPlugin, {
enabled: true,
token: process.env.DEVTOOLS_TOKEN,
});
Open the UI once with ?token=…. The inspector moves the token into a SameSite=Strict cookie and removes it from the URL, so it is not repeated on every API call, in Referer headers or in browser history. Later requests authenticate with that cookie or an x-devtools-token header, and the query parameter is rejected on API paths, so it can never end up in a proxy log. Tokens are compared in constant time.
What is redacted
Credential-bearing headers such as authorization, cookie or x-api-key are always replaced with <redacted>, and redactHeaders adds your own. The same name-based rule applies to query parameters, configuration values and storage keys, in camelCase, snake_case and SCREAMING_CASE spellings.
token so nobody else can read the inspector, or turn captureBodies off.Devtools routes and your middlewares
Devtools endpoints are ordinary @Controller routes, and the plugin detaches your application's global middlewares from the devtools mount so an auth or rate-limit middleware cannot lock you out of your own inspector. The mount is matched on whole path segments, so a route that merely shares the prefix, such as /_devtools-admin, keeps its global middlewares.
token option for access control. Do not assume your application's auth protects the devtools mount, because it deliberately does not.Memory
Everything devtools keep is in memory and bounded: maxRequests and maxLogs cap the ring buffers, maxBodyBytes caps each captured body, and process metrics keep only the most recent samples. On a chatty application raise maxRequests so a reproduction is not pushed out of the buffer before you read it; on a memory-tight container lower it or turn body capture off.