feat: production-grade hardening for v0.38.0#2
Merged
Conversation
run_shell previously gated only on a metacharacter denylist, so any allowlisted-metachar-free command could be invoked through the agent. Add SHELL_ALLOWLIST (pio, git, npm family, cargo family, python, make, cmake, ninja, plus a handful of read-only utilities) and reject anything else with a clear error. extract_program normalizes the program name (strips path prefix and Windows .exe/.cmd/.bat/.ps1 suffix) before the allowlist check. Every successful invocation is logged via log::info! so the user can audit what the AI ran. Covered by 8 new unit tests in filesystem.rs (allowlist accept/reject, metachar rejection, empty-input rejection, program extraction with paths and Windows extensions). Adds 6 more tests for the surrounding validators (leaf name traversal, lexical normalization, validate_path containment). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plan-mode phase transitions used bare substring matches — content
.includes('approve') for 'ready' and .includes('?') for 'clarify' —
which produced false positives on any plan body that mentioned
approval or contained a question mark anywhere.
Extract detectPlanPhase() to module scope and have it prefer an
explicit machine-readable marker emitted by the plan-mode prompt:
[[phase: explore|design|review|clarify|ready]]. Fall back to anchored
phrase matches restricted to the last 400 chars of the message body
(e.g. "plan ready for approval", "awaiting clarification"), which is
where the AI naturally puts the call to action. Both the plan-mode
and agent-mode useEffect hooks now share the same detector.
Update src/lib/prompts/modes/plan.md to document the marker contract
so plan-mode responses emit one marker per response.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
settingsStore previously had no version field on its zustand persist config, so any future field reshape would silently corrupt persisted state for existing users. Declare version: 1 (baseline) and a migrate callback that is a pass-through today; future schema bumps should branch on _fromVersion and reshape `persisted` into the new schema. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add .github/workflows/ci.yml gating push and pull_request on: - npm ci + npm run build (tsc strict + Vite) - cargo fmt --check - cargo clippy --all-targets -- -D warnings - cargo test --all-targets Pinned to windows-latest since Embedist is Windows-only (NSIS bundle, winreg dep, ConPTY). Caches ~/.cargo and src-tauri/target keyed on Cargo.lock to keep wall-clock under ~15 minutes on warm runs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Commit the project-level CLAUDE.md that was sitting untracked in the working tree (AGENTS.md already references it as the sibling doc). - Reconcile TODO-fix.md against current source: of the 9 items previously marked open, 6 had already shipped in prior releases (defaultImplementationMode toggle, PlanPhaseIndicator, token-usage display, SerialConfig dead code, bottom-panel resize, keyboard-shortcuts modal). Remaining items (3.8, 7.3, 8.5) are now resolved by this branch and annotated FIXED (v0.38.0). - Add docs/superpowers/specs/2026-05-28-production-grade-design.md capturing the scope, goals, non-goals, and verification criteria for the production-grade work. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Synchronize package.json, src-tauri/Cargo.toml, src-tauri/tauri.conf.json (plus the resulting Cargo.lock update) and add the v0.38.0 CHANGELOG entry summarizing the production-grade hardening landed on this branch: - Security: run_shell command allowlist + audit logging - Fixed: anchored plan-phase detection with explicit [[phase: x]] markers - Added: cargo test suite (14 tests), GitHub Actions CI, persist schema versioning - Documentation: reconciled TODO-fix, design spec under docs/superpowers/ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
run_shellnow enforces a command allowlist (pio,git,npm/npx/pnpm/yarn,cargo/rustc/rustup,python/python3,node,make/cmake/ninja, plus a handful of read-only utilities) on top of the existing metacharacter denylist. Every invocation is logged vialog::info!.approveor a stray?. Uses explicit[[phase: ready]]/[[phase: clarify]]markers (emitted byplan.md) with a tightened phrase fallback anchored to the last 400 chars.filesystem.rscovering the shell allowlist, program-name extraction, leaf-name traversal blocking, lexical normalization, andvalidate_pathcontainment. New.github/workflows/ci.ymlgates push/PR ontsc + vite build,cargo fmt --check,cargo clippy --all-targets -- -D warnings, andcargo test --all-targetsonwindows-latest.settingsStorenow declaresversion: 1+ a pass-throughmigratefor non-breaking future bumps.TODO-fix.mdreconciled — 6 of the 9 previously-open items had already shipped; the remaining 3 are closed by this PR. Design spec atdocs/superpowers/specs/2026-05-28-production-grade-design.md.0.38.0acrosspackage.json,Cargo.toml,tauri.conf.json;CHANGELOG.mdupdated.Test plan
npm run buildexits 0cargo clippy --all-targets -- -D warningsexits 0cargo test --all-targetsexits 0 (14/14 passing)npm run tauri buildproducesembedist.exeand NSIS installer (running locally; will attach on green CI)run_shellfrom agent mode with both an allowlisted (pio --version) and a non-allowlisted (curl ...) command and confirm the latter is refused with a clear error🤖 Generated with Claude Code