refactor(main): extract pure path/id/mime helpers into paths.ts with unit tests#55
Merged
Conversation
…unit tests First, safe slice of the main-process decomposition: the pure, security- sensitive helpers move to app/src/main/paths.ts (no electron imports), so the containment logic is unit-testable without booting Electron — safePath, assertSlug, isSafeExternalUrl, assetKindFor, slugify, mimeFor, writeFileAtomic, and the extension sets. index.ts imports them; the slug/root-keyed wrappers (safeProjectPath/safeStylePath) stay since they close over PROJECTS_DIR/STYLES_DIR. Adds paths.test.ts covering the traversal / sibling-prefix / absolute- segment cases for safePath, the assertSlug allow/deny set, the https-only external-URL guard, and mime/kind/slugify. The remaining domain split (projects/media/watcher/albums/styles/voices/ scripts/ipc) is deliberately deferred: those close over startup-ordered module state (envLocked capture vs loadLocalEnv vs APP_HOME resolution) where a careless move would change boot behavior — worth doing as its own verifiable step. No behavior change here (typecheck + build + 114 tests green). Co-authored-by: Cursor <cursoragent@cursor.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
Audit roadmap Phase 6 (main-process decomposition) — the first, safe slice. The audit proposed splitting the 1,800-line
index.tsinto ~12 modules; this lands the highest-value, zero-risk piece and makes the security-critical logic testable.app/src/main/paths.ts(no electron imports) holds the pure helpers:safePath,assertSlug,isSafeExternalUrl,assetKindFor+ the extension sets,slugify,mimeFor, andwriteFileAtomic.index.tsimports them; the root-keyed wrapperssafeProjectPath/safeStylePathstay inindex.tsbecause they close overPROJECTS_DIR/STYLES_DIR.paths.test.ts(14 assertions across 10 cases):safePathtraversal + sibling-prefix (<root>-evil) + absolute-segment containment, theassertSlugallow/deny set, the https-only external-URL guard, andassetKindFor/mimeFor/slugify.safePathandassertSlughad no coverage before despite being the path-traversal boundary.Deliberately deferred (called out for a follow-up): the domain split (projects / media / watcher / albums / styles / voices / scripts / ipc) closes over startup-ordered module state —
envLockedmust be captured afterloadLocalEnv()but beforeapplyAgentEnv, andAPP_HOME/PROJECTS_DIRresolve fromreadSettings().homeDirat a precise point. Moving those carelessly would change boot behavior, so they deserve their own verifiable step rather than being rushed in here.Pure extraction — no behavior change. Main-process file moved, so restart
npm run dev.Test plan
paths.test.tsgreen; 114 tests totalMade with Cursor