Skip to content

Feature/pin and redaction preview#163

Open
DevSars24 wants to merge 2 commits into
DebugProbe:mainfrom
DevSars24:feature/pin-and-redaction-preview
Open

Feature/pin and redaction preview#163
DevSars24 wants to merge 2 commits into
DebugProbe:mainfrom
DevSars24:feature/pin-and-redaction-preview

Conversation

@DevSars24

@DevSars24 DevSars24 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds two independent Phase 2 features, shipped as two separate commits so either can be reviewed or reverted on its own:

  1. Pin/Favorite a Trace
  2. Redaction Preview Toggle

Both stay within the existing in-memory DebugEntryStore — no new database, no external storage, no persistence added.


Feature 1: Pin/Favorite a Trace

Lets you pin an important trace from the dashboard so it survives eviction once the store fills up and starts trimming old entries.

  • Added IsPinned on DebugEntry
  • New endpoint POST /debug/pin/{id} toggles pin state
  • Pinned entries live in a separate collection, excluded from normal FIFO eviction
  • Capped at 5 pinned entries — pinning a 6th returns 409 Conflict instead of silently bumping another one
  • Clear() resets pinned entries too, so there's no leftover state after a full reset
  • No persistence — pinned state resets on app restart, same as everything else in this library
Dashboard showing Pinned Traces section

Feature 2: Redaction Preview Toggle

Lets a developer temporarily view the original value of a redacted header/field (e.g. an API key) on the trace detail page. Local debugging only — not intended for production.

  • New config option: AllowRedactionPreview (default false)

  • When true, the middleware stores both the redacted and original values

  • When false (default), the original value is never stored anywhere — not even in memory

  • The banner and original values only render when both are true:

    1. AllowRedactionPreview = true
    2. App is running in a local/Development environment

    This is enforced server-side before the HTML is generated — not hidden with CSS. The original value is never sent to the browser unless both conditions hold.

  • Setting AllowRedactionPreview = true together with AllowUiInProduction = true throws at startup, to prevent this from accidentally shipping open in production.

  • RedactionUtils.cs — the actual redaction logic — is untouched. This feature is purely an additional layer on top of it.

On the sample app config: DebugProbe.SampleApi/Program.cs ships with AllowRedactionPreview = false, matching the library default. This doesn't mean the feature only works in this one file — any consumer of the library can set it to true in their own Program.cs and it behaves exactly as shown below. Keeping the sample off by default just avoids anyone copy-pasting a security-preview feature into production already turned on.

The screenshot below was captured with the option set to true locally, purely to demonstrate the feature end-to-end.

Trace detail page showing Redaction Preview banner with original header value revealed

Testing

All 119 tests pass.

Pin feature — 13 new tests: toggle on/off, 5-entry cap enforcement (409), pinned entries surviving eviction, Clear() behavior, dashboard section rendering.

Redaction preview — 11 new tests: startup validation on misconfiguration, values not persisted when disabled, values persisted correctly when enabled, banner rendering gated on both config and environment.

Manually verified end-to-end via curl and browser:

  • Pinned trace stays visible after generating additional requests
  • With AllowRedactionPreview=false, the secret never appears — not in the JSON response, not in the page source
  • With AllowRedactionPreview=true + Development environment, banner and original value render correctly (see screenshot above)

Files changed

  • Models/DebugEntry.cs — Added IsPinned and original-value fields
  • Storage/DebugEntryStore.cs — Pin storage, eviction logic, cap enforcement
  • Options/DebugProbeOptions.cs — Added AllowRedactionPreview
  • Options/DebugProbeOptionsValidator.cs — Blocks unsafe config combination at startup
  • Middleware/DebugProbeMiddleware.cs — Captures original values when preview is enabled
  • Extensions/DebugProbeExtensions.cs — New pin endpoint
  • Internal/Rendering/HtmlRenderer.cs — Pinned section + redaction preview banner
  • DebugProbe.SampleApi/Program.cs — Added X-Api-Key to redacted headers, AllowRedactionPreview set to false
  • DebugProbe.AspNetCore.Tests/ — 24 new tests across both features

Storage (Option B): separate ConcurrentDictionary for pinned entries,
protected from FIFO eviction. MaxPinnedEntries=5 constant cap.
TryPin() toggles; Clear() flushes all (full session reset).
POST /debug/pin/{id} endpoint returns 409 when cap exceeded.
Dashboard: Pinned Traces section, pin/unpin buttons per row.
CSS, JS, HTML template updates. 13 new tests.
- DebugProbeOptions: AllowRedactionPreview (default false)
- DebugProbeOptionsValidator: fail fast if AllowRedactionPreview=true && AllowUiInProduction=true
- DebugEntry: OriginalRequestHeaders, OriginalRequestBody, OriginalResponseBody, OriginalQuery
- DebugProbeMiddleware: capture pre-redaction raw values into OriginalXxx when AllowRedactionPreview=true
- HtmlRenderer: server-side two-gate check (AllowRedactionPreview=true AND Development env); render collapsible preview banner with original values
- CSS: redaction-preview-toggle, redaction-original-value styles
- Tests: 7 new tests (options validation, middleware capture, renderer two-gate check)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant