Skip to content

On-device sensitive-detail detection + redaction (pre-send) - #32

Merged
adilei merged 2 commits into
release/0.4.0from
adilei-local-sensitive-detail-highlighting
Aug 6, 2026
Merged

On-device sensitive-detail detection + redaction (pre-send)#32
adilei merged 2 commits into
release/0.4.0from
adilei-local-sensitive-detail-highlighting

Conversation

@adilei

@adilei adilei commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

⛔ DO NOT MERGE — work-in-progress checkpoint

Opened to capture in-progress work on on-device sensitive-detail detection + redaction so we can pick it up later. This branch does not typecheck and is not runnable as-is (see Current state). It is a design + partial-implementation snapshot, not a reviewable change.

Goal

Detect and auto-redact sensitive/problematic details (secrets, PII, names) on-device before Skill Recorder sends captured session data to GitHub Copilot on Analyze. Fully local, MIT-compatible, and non-blocking — Analyze never stops; flagged values are redacted in the outgoing text and reported as "Redacted N details".

Design (locked)

Three detection layers → one non-blocking redactor:

  1. secretlint (@secretlint/core + preset-recommend + pattern rule) — provider secrets, always on. AWS ID scan enabled (enableIDScanRule: true); JWTs via a custom pattern rule.
  2. In-repo regex (common/sensitive.ts) — structured PII: email, credit-card (Luhn), SSN, phone. Always on, renderer-safe.
  3. Xenova/bert-base-NER (transformers.js, dtype q8model_quantized.onnx) — person/location/org. Opt-in "Advanced protection" toggle that downloads the model; never blocks Analyze (getPipelineForScan() returns null until cached).

Overlapping matches collapse via resolveOverlaps by rank (secrets 90 > structured-PII 40–55 > NER 30). UI report masks values (maskValue, 2+2 reveal); outgoing text is redacted with non-revealing ••••.

🚧 Why this is paused — architectural gap

get_frames sends screen JPEGs inline to the model, and the LLM extracts data directly from those images — we have no OCR. So text-only redaction can't touch a secret that's visible on screen: we'd mask the text while shipping a screenshot of the same secret. Text redaction still uniquely covers voice narration, clipboard, and unsampled/off-screen text, but the feature is incomplete for on-screen secrets.

Decision needed before resuming (any of):

  • Add frame redaction: OCR each served frame (e.g. tesseract.js, Apache-2.0, offline) → run the same detectors → blur matched boxes with sharp (already a dep). ~1–3 s/frame CPU + one dep.
  • Or scope the feature honestly to text channels only and strengthen the screenshot warning.
  • Or drop it.

Current state

  • common/sensitive.tsrewritten to v2 core (types + masking + structured-PII + generalized resolveOverlaps). Detectors verified by hand.
  • ✅ secretlint API fully grounded (config shape, message→category mapping, dummy-key allowlist, AWS ID-scan gating).
  • ✅ NER model grounded (q8, enableCpuMemArena:false required under Electron).
  • ⚠️ Downstream still v1electron/sensitive/scanner.ts, common/sensitive.test.ts, electron/sensitive/scanner.test.ts, src/SensitiveReview.tsx, and the IPC/UI wiring reference removed v1 symbols (scanText, shannonEntropy, high-entropy). 6 known tsc errors.
  • Test fixtures were rewritten to runtime-constructed tokens (no literal secrets) to satisfy push protection.

Remaining work (bottom-up)

  1. electron/sensitive/: secretlint-config.ts, secrets.ts, ner-model.ts, ner.ts, model-manager.ts (mirror electron/narration/{whisper,manager}.ts).
  2. Rework scanner.ts → async scanSession(id, nerPipeline?) → { report, values[] } merging all 3 layers.
  3. Thread a redact seam through describer/{describer,tools}.ts (wrap get_timeline/get_events/get_narration); remove the blocking gate in common/ipc.ts + electron/ipc.ts; wire SensitiveModelManager + sensitive IPC channels in main.ts/preload.cjs.
  4. UI: non-blocking "Redacted N details" banner + "Advanced protection" opt-in toggle + status HUD (SensitiveReview.tsx, Library.tsx, App.css).
  5. Evals (requested): evals/sensitive/{corpus,score,run}.ts — LLM-free detection precision/recall + redaction leak-check; NER cases gated on cache.
  6. Compliance: npm run compliance:prepare for new MIT deps + THIRD-PARTY notices; attribute bert-base-NER. Review the secretlint transitive npm audit findings.
  7. Resolve the frames/OCR decision above.

How to resume

common/sensitive.ts is the source of truth for the v2 core. Implement the electron/sensitive/* modules, then flip the scanner + tests + UI off the v1 symbols until npm run typecheck and npm test pass. Detailed design notes and grounded API facts live in the session's plan doc.

Co-authored-by: Copilot

@adilei
adilei changed the base branch from main to release/0.3.0 August 5, 2026 10:06
@adilei adilei changed the title [DO NOT MERGE] WIP: on-device sensitive-detail detection + redaction On-device sensitive-detail detection + redaction (pre-send) Aug 5, 2026
…ction

Scan captured text and screen frames on-device before Analyze sends anything
to GitHub Copilot, and redact whatever looks sensitive.

- Text: secretlint (secrets) + checksum-validated structured-PII regex (email,
  credit-card+Luhn, SSN, phone) run inside the Analyze IPC handler and mask
  every outgoing describer tool field (get_timeline/get_events/get_narration)
  through a longest-first literal redactor. Non-blocking: Analyze always
  proceeds and returns a masked SensitiveReport for review.
- Frames (Advanced protection, on by default): Tesseract.js OCR locates
  on-screen secrets/PII, plus entropy/credential-assignment heuristics and
  cross-feed of known text values; sharp blurs the matched boxes before any
  JPEG leaves the machine. Fail-closed: frames are withheld while OCR is
  provisioning or errored. OCR model pinned to an immutable commit and verified
  by SHA-256 before use.
- The report persists next to the session (masked values + counts only, never
  raw) so it survives reopening an analyzed session.
- Evals: evals/sensitive/* (hermetic run + real-image OCR + degraded-frame
  realistic gates). Adds @secretlint/* and tesseract.js(+core); the tesseract.js
  install script is reviewed and denied (opencollective banner, not needed).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 75a0080c-95f1-499f-b3b5-48d5a1ee29cb
@adilei
adilei force-pushed the adilei-local-sensitive-detail-highlighting branch from 45651b2 to b009002 Compare August 6, 2026 08:18
Pin OCR and Artistic dependency notices and source materials in the fail-closed release compliance bundle.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@adilei
adilei marked this pull request as ready for review August 6, 2026 10:27
@adilei
adilei merged commit e8a2531 into release/0.4.0 Aug 6, 2026
5 checks passed
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.

2 participants