fix: CLI setup-command/color UX and harden save-deliverable path handling#373
Closed
jeypzz wants to merge 3 commits into
Closed
fix: CLI setup-command/color UX and harden save-deliverable path handling#373jeypzz wants to merge 3 commits into
jeypzz wants to merge 3 commits into
Conversation
The invalid-config error path told users to run 'shn setup', but the published binary is 'shannon' (see apps/cli/package.json `bin`) — there is no 'shn' command. Match the sibling parse-error message in the same file, which already uses 'npx @keygraph/shannon setup'.
displaySplash always emitted raw ANSI color codes, so the escape sequences leaked into piped/redirected output and ignored the NO_COLOR convention (https://no-color.org). Gate the color codes behind a shouldUseColor() check: NO_COLOR disables color, FORCE_COLOR forces it, otherwise color is only emitted to an interactive TTY. The box-drawing glyphs are unaffected, so the logo still renders in monochrome.
Two related path-handling issues in the save-deliverable script:
1. Traversal guard: the check used `resolved.startsWith(`${cwd}/`)` with
a hardcoded '/' separator and a brittle string-prefix match. On
Windows resolve() returns backslash paths, so every legitimate path
was rejected as a traversal attempt; the prefix match could also
false-trigger on sibling directories. Replace it with a
path.relative() based check (separator-correct, no prefix aliasing).
2. Deduplicate: the deliverables directory was rebuilt inline with the
same `subdir.split('/')` logic — and hardcoded default string — that
already lives in deliverablesDir()/DEFAULT_DELIVERABLES_SUBDIR in
paths.ts (used by every other call site). Reuse the shared helper,
which also removes the confusing local variable that shadowed it.
Collaborator
|
Hi @jeypzz, thanks for reporting these. Both CLI/UX fixes have since been resolved independently:
On Closing this out, appreciate the work. |
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
A small batch of correctness/UX fixes found while reading through the CLI and worker code.
CLI / UX
Invalid command in config error — the invalid-config error path told users to run
shn setup, but the published binary isshannon(seeapps/cli/package.jsonbin); there is noshncommand. It now matches the sibling parse-error message in the same file (npx @keygraph/shannon setup).Splash ignored
NO_COLOR/ non-TTY —displaySplashalways emitted raw ANSI color codes, so escape sequences leaked into piped/redirected output and theNO_COLORconvention was ignored. Color is now gated behind ashouldUseColor()check (NO_COLORdisables,FORCE_COLORforces, otherwise TTY-only). The box-drawing glyphs are unaffected, so the logo still renders in monochrome.Worker
Broken path-traversal guard in
save-deliverable— the check usedresolved.startsWith(${cwd}/)with a hardcoded/separator and a brittle string-prefix match. On Windowsresolve()returns backslash paths, so legitimate paths were rejected as traversal attempts, and the prefix match could false-trigger on sibling directories. Replaced with apath.relative()-based check (separator-correct, no prefix aliasing).Duplicated path logic — the same script rebuilt the deliverables directory inline with the same
subdir.split('/')logic and a hardcoded default string that already lives indeliverablesDir()/DEFAULT_DELIVERABLES_SUBDIRinpaths.ts(used by every other call site). It now reuses the shared helper, which also removes a local variable that shadowed it.Testing
tsc --noEmitpasses for both packages (turbo run check).biome lintis clean on all changed files.