Files
TylerandClaude Fable 5 ccbb9b03dc
Template tests / tests (pull_request) Failing after 34s
Enforce a truthful local-first AI/privacy contract
Phase 1 of the improvement plan (PR 3 of the sequence). The docs claimed
"fully offline"/"never talks to the network," but text-intel makes HTTP
requests to a configurable Ollama host that could be remote, with no timeout,
no cancellation, and no size limit; the Windows hook logged raw keystrokes
into capture metadata that could then be sent to that host.

Privacy — raw keystroke capture:
- New capture.captureTypedText setting, default false. With it off, printable
  characters are never buffered in JS and the Windows keyboard hook never even
  emits them across the process boundary (the flag is threaded into the C#).
  Shortcut/navigation detection (Ctrl+T, Enter, …) is unaffected.

AI network hardening (app/text-intel.js):
- Every Ollama call goes through fetchJson with an AbortController deadline
  (ai.timeoutMs, default 60s): a dead endpoint fails fast instead of leaving
  UI actions pending forever.
- Cancellation: in-flight requests are tracked and cancelInflight(guideId)
  aborts them; new ai:cancel IPC + api.ai.cancel are called when the editor
  closes, and shutdown cancels everything.
- Bounded concurrency (2) for AI network work.
- Screenshots are only attached when allowed (ai.attachScreenshots), the model
  is vision-capable, and the image is within ai.maxImageBytes — no more
  unbounded base64-expanded 4K bodies.

Local-first host policy (core/text-intel.js):
- New isLoopbackHost + validateOllamaHost. By default only a loopback Ollama
  endpoint is contacted; a remote host is refused with a clear message unless
  ai.allowRemoteHost is explicitly enabled. Blocked hosts are never contacted.

Honest documentation:
- README, package.json, and the welcome screen drop "fully offline"/"never
  talks to the network"/"Electron is the only dependency" for an accurate
  local-first contract that discloses the optional AI path and the bundled
  Tesseract OCR dependency.
- New docs/PRIVACY.md details exactly what is collected locally and the one
  outbound (opt-in, loopback-by-default) AI feature.

Tests: loopback/remote host matrix, remote-blocked-without-opt-in (and never
contacted), remote-allowed-with-opt-in, request timeout, explicit cancel vs
timeout, typed-text off-by-default vs opted-in, shortcut detection still works,
and a source guard that the C# CHAR emission stays behind the opt-in. 224 unit
tests pass; startup smoke and workflow E2E pass.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-03 11:36:01 -07:00

2.9 KiB

StepForge privacy and network contract

StepForge is local-first. Guides, screenshots, and settings live on your machine and are never uploaded on their own. This document describes exactly what data StepForge collects locally and the one situation in which data leaves your device.

What never happens

  • No telemetry or analytics.
  • No update checks, license checks, or "phone home".
  • No cloud storage or sync.
  • No dependency downloads at runtime (dependencies are installed only by you, via npm ci).

Data StepForge collects locally

When you capture a step, StepForge may record, stored only on disk in your data directory, capture context to help title and describe the step:

  • The screenshot image.
  • OCR text read from the region around your click (via the bundled Tesseract engine — this runs locally, it is not a network call).
  • The foreground window title and application name.
  • The accessibility label/role/value of the clicked UI element (Windows).
  • Keyboard shortcuts you pressed (for example Ctrl+T).

Raw typed text is OFF by default

StepForge can additionally record the raw printable characters you type between captures. Because this can capture passwords or other secrets, it is disabled by default. It is only recorded when you explicitly enable capture.captureTypedText, and even then the characters are used only to title the current step and are not retained beyond it. With the setting off, raw characters are never read or stored (on Windows they never even leave the keyboard-hook process).

The one outbound feature: optional AI

StepForge has an optional AI integration that generates step titles and descriptions with a local large-language-model runtime (Ollama). It is off by default. When you turn it on and configure an endpoint:

  • StepForge sends the step screenshot (only to vision-capable models, only when "Attach screenshots" is on, and only if within the size limit) and the step text/capture context to the configured Ollama endpoint.
  • By default the endpoint must be a local (loopback) address — for example http://127.0.0.1:11434. StepForge refuses to send data to a non-loopback host unless you explicitly enable "Allow remote AI host". Enabling that option means your screenshots and text are sent to the remote host you configured; StepForge cannot control what that host does with them.
  • Every AI request has a timeout, can be cancelled (closing the guide cancels in-flight requests), and runs under a bounded concurrency limit.

Bundled dependencies

Beyond the Electron desktop shell, StepForge bundles the Tesseract OCR engine and its English language data as production dependencies. All OCR runs locally.

Where your data lives

  • Windows: %APPDATA%\stepforge
  • Linux: ~/.local/share/stepforge (or $XDG_DATA_HOME/stepforge)
  • Override with the STEPFORGE_DATA_DIR environment variable.