# Security and Privacy Statecraft may capture sensitive application screens. - No telemetry in v0.1. - No automatic upload of screenshots, reports, URLs, diagnostics, or source data. - No external assets in generated reports. - Do not persist authorization headers, cookies, tokens, or sensitive request bodies by default. - Sanitize request diagnostics. - Capture only failed-request URL, method, and error text; never inspect or retain request headers, response headers, cookies, or bodies. Remove URL credentials and fragments, replace every query value with `[REDACTED]`, redact authorization/cookie values and common token/secret assignments in free-form console and page-error text, pre-bound every value before sanitizing, and cap both diagnostic sizes and counts. Never attach an original unsanitized throwable as a public error cause. - Config/scenario modules are trusted local code running with user privileges; importing a config can execute arbitrary local code. Default config lookup checks names only inside the selected project directory, returns canonical paths (including symbolic-link targets), and refuses ambiguous files instead of silently executing one. An explicit config path may point elsewhere. - `statecraft init` never offers a force mode. It rejects existing generated targets and symbolic-link directory boundaries, creates files exclusively, publishes the config last, and never deletes paths during failure recovery because a concurrently changed path may no longer be owned by that invocation. - `statecraft scan` executes trusted config and scenario modules locally, writes runner-owned PNG and schema-v1 JSON output plus report-owned HTML beneath the invocation directory's `.statecraft/`, and prints report metadata rather than diagnostic payloads. Exact route validation completes before output creation. - Phase 5 HTML generation validates through the schema-v1 core parser, derives screenshot references only from validated artifact paths, HTML-escapes every report-controlled string, embeds no external asset, and sets a restrictive document Content Security Policy. Its constant filter/detail script contains no report values and is authorized only by its exact SHA-256; external scripts remain blocked. The runner stages HTML with JSON and screenshots under one owned project lock, rejects symbolic-link/non-file output targets, and restores the prior coherent output set when publication fails. Generated HTML and screenshots remain sensitive local artifacts. - Persistence canonicalizes the project root and revalidates real `.statecraft` path boundaries before publication. The owned lock coordinates Statecraft runs; as with other local developer tools, it does not defend against a hostile same-user process mutating the project directory while a scan is actively publishing. Run scans only in a project directory controlled by the current user. - `statecraft open` validates the fixed `.statecraft/report/index.html` target beneath the canonical invocation directory, rejects symbolic-link or non-regular path boundaries observed during validation, and passes the absolute path as one shell-free argument to an absolute system-launcher path so repository-local binaries cannot intercept the handoff. The operating-system handoff is pathname-based and cannot atomically pin the validated file, so the local project/report directory is trusted against concurrent same-user mutation during that handoff. The command does not generate, rewrite, upload, or parse report contents. - Recommend ignoring `.statecraft/` where reports may contain sensitive data. - GitHub Actions evidence upload is an explicit repository-owner choice, not automatic Statecraft behavior. The documented workflow uses `if: always()` so failed scans remain diagnosable and uploads the complete `.statecraft` bundle so report screenshots remain usable. Artifacts in a public repository must be treated as public; sensitive captures require a private repository with restricted read access or no upload. Statecraft's own release gate uploads only the deterministic fictional example evidence with short retention. - npm publication runs only from a non-prerelease GitHub Release workflow with read-only repository contents, job-scoped `id-token: write`, and a protected `npm-publish` Environment. The event commit, exact tag target, membership in `main`, package metadata, tarball contents, consumer installation, and registry integrity are checked before publication. npm trusted publishing now uses short-lived OIDC credentials. The completed first-publication bootstrap required a temporary `All Packages` write token with bypass-2FA authority because npm could not scope a token to unclaimed package names; that token and the protected Environment's `NPM_TOKEN` secret were deleted immediately after the trusted publishers were configured. Never recreate that credential for normal releases, and never commit npm credentials, packed tarballs, or generated reports. - Persist screenshots, JSON, and HTML with owner-only modes for new and existing runner directories/files where supported. Reject symbolic-link artifact/report targets, stage the complete output set inside `.statecraft/`, and serialize complete runs with a process-owned, phase-aware local lock that only auto-recovers abandoned capture-only state. Hide the old report files before artifact replacement, publish JSON and then HTML after the artifact tree, and preserve publishing/recovery data rather than deleting the last good copies when rollback is incomplete. - Prefer mature dependencies and minimize runtime dependency count. - The example application uses fictional, deterministic commerce data only. Its API fixtures must never contain copied customer records, credentials, tokens, or production endpoints; scenario interception stays local to the browser run. Customer fixture values live behind a Next.js `server-only` boundary, while client components import only the runtime contract. Production-browser regression coverage scans emitted static chunks to prevent restricted fixture fields from leaking into downloadable JavaScript.