Skip to main content
StackNext is designed around a strict local-first boundary. Telemetry is produced by your app, sent over loopback to the collector on this machine, and kept in memory. Explicit capture runs, baselines, comparisons and snapshots are redacted JSON records under the project’s .stacknext directory; they are never uploaded. There is no cloud service, account, analytics endpoint or outbound ingestion.

What StackNext collects

Redaction

Redaction happens twice: once in the application process before data is sent, and again in the collector before it enters the store. A bug in one layer does not automatically expose raw data through the other.
  • URLs: http://host/path?token=secret#fragment becomes http://host/path. Relative paths lose their query string too.
  • Sensitive keys: names containing authorization, cookie, password, secret, API key, access/refresh/private token, client secret, credential, connection string, database URL, DSN and similar terms become [redacted].
  • Headers: attribute maps with a header-shaped key are replaced wholesale.
  • Secret patterns: bearer tokens, JWTs, GitHub/Slack/Stripe-style keys, AWS access key IDs, credential-bearing connection strings and key=value password/token/secret patterns are replaced.
  • SQL: redaction patterns are applied to query text. Bind parameters are never included, so values passed as ?/$1 parameters cannot leak.
  • Errors: messages and stacks pass through the same text redaction. Query strings in stack URLs are removed. Next.js error context is bounded and redacted before storage.
  • Resource attributes: only a small allowlist is retained (service name, version, namespace, SDK metadata, runtime, Next.js version and environment).
Custom span, Server Action and framework attributes all pass through the same sanitizer before enqueueing, then through the collector pass before storage. Names are redacted and URL query strings are stripped too. NEXT_OTEL_VERBOSE=1 can add more Next.js spans and attributes to the sample. Those fields still pass through both redaction layers; verbose tracing does not enable body, header, cookie, query-value or SQL-parameter capture. It does increase stored span volume and can shorten the effective retention of older events when capacity is reached. Diagnostics are derived from the same redacted telemetry. Findings, /api/export and MCP responses are subject to the same local-only boundary. StackNext does not send telemetry or findings to an AI provider, hosted inference service or any other external endpoint. Redaction is pattern-based and intentionally conservative, not a formal secret scanner. If an application embeds an unrecognized secret as a literal in a SQL string, a URL path segment, a span attribute or an error message, it may still be stored. Keep credentials out of those places, and review an export before sharing it.

Verify redaction

Search the output for the values you expect to be absent. The repository’s tests assert that known example secrets do not appear in API, export, regression or snapshot output.

Local network boundary

  • The collector and dashboard share one HTTP server bound to 127.0.0.1 or localhost only. Startup rejects any other host.
  • Ingestion requires an Authorization: Bearer <token> header. The token is generated with 32 random bytes by stacknext dev and stored in .stacknext/run.json with mode 0600. Plain HTTP is used because traffic never leaves the loopback interface.
  • Read APIs and the SSE stream require either that bearer token or an HttpOnly, SameSite=Strict session cookie issued when the dashboard HTML is loaded. Sessions expire after 24 hours and are capped at 100.
  • Regression capture writes require the bearer token and are not available to the dashboard session cookie. Run, baseline and comparison reads use the same bearer-or-cookie boundary as other read APIs.
  • Snapshot writes accept the bearer token or the dashboard session cookie, but still require loopback Host and same-origin/Sec-Fetch-Site checks.
  • .stacknext is created with mode 0700, record files use mode 0600, and .stacknext/.gitignore ignores runtime state. The bearer token lives in .stacknext/run.json, not in run, baseline, comparison or snapshot records.
  • Requests with a non-loopback Host header are rejected. Cross-origin requests and Sec-Fetch-Site: cross-site requests are rejected.
  • The dashboard sends a restrictive CSP (default-src 'self'), nosniff, X-Frame-Options: DENY, Referrer-Policy: no-referrer and no CORS headers.
  • The MCP server’s API client refuses collector URLs that are not loopback.
  • stacknext export writes with mode 0600; the data is redacted, but it is still a full local trace dump.

Retention

Live telemetry

The store is in memory and bounded by:
  • collector.maxSpans — total span capacity (default 5,000). Error and query buffers are derived from it.
  • collector.retentionMs — how long received telemetry stays (default 600,000 ms, or 10 minutes).
When data ages out or capacity is reached, it is dropped and the drop counters increase. A finding can disappear because its evidence left the sample, not because the problem was fixed. The store is reset when the collector process exits. Use an explicit snapshot if you need evidence after a restart.

Regression records

Runs, baselines and comparisons are local files under .stacknext/{runs,baselines,comparisons}. They are immutable and never auto-deleted. Remove a baseline with stacknext baseline remove <baseline-id> --yes. To remove an individual run or comparison, delete its JSON file in .stacknext/runs or .stacknext/comparisons; there are no CLI removal commands for those records. Each record is capped at 16 MiB.

Snapshots

snapshots.autoKeep defaults to 10. snapshots.maxBytes defaults to 64 MiB; an oversized save fails instead of truncating. Snapshots are never replayed into the live store.

Bounds and backpressure

Instrumentation never blocks a request for telemetry network I/O. Events are queued and flushed asynchronously. When a buffer is full, the oldest events are dropped. Drops are counted and reported by /api/health, stacknext status and the dashboard settings page. The collector rejects malformed payloads, wrong content types, oversized bodies and unauthenticated requests.

What never leaves the machine

StackNext does not send telemetry to any external service. The only network calls the SDK makes are to the loopback collector URL supplied by stacknext dev. The Playwright fixture talks only to the loopback collector. Regression records and snapshots are written to local disk and are never uploaded by StackNext. The MCP client you connect may log or transmit tool results under its own policy. The Next.js application may also have its own monitoring or telemetry; StackNext does not disable or reconfigure it. If another OpenTelemetry provider is already registered, StackNext yields to it rather than replacing it.