Skip to content

fix: address full code-review findings (correctness, security, CI)#3

Merged
riglar merged 5 commits into
devfrom
fix/code-review-findings
Jun 12, 2026
Merged

fix: address full code-review findings (correctness, security, CI)#3
riglar merged 5 commits into
devfrom
fix/code-review-findings

Conversation

@riglar

@riglar riglar commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the findings from a full code review of the repo: correctness and security fixes across the command/service/gateway layers, test-harness reliability fixes, and CI/install hardening. Four commits, reviewable independently: core src/ fixes, test harness, CI/install scripts, cleanup/docs.

Highest-impact fixes

  • CI exit-code integrity: polling now reports PASSED only when every test passed — unknown/cancelled statuses or an empty result set previously exited 0. cloud no longer skips its finally via process.exit, so --json output prints on failed runs and temp files are cleaned.
  • Credential exposure: telemetry redacts --api-key/--env/--app-url values from argv before shipping to Axiom, and flushSync passes auth headers to curl via a 0600 config file instead of world-visible process arguments.
  • Hang/truncation class: artifact, report, and moropo downloads use pipeline() instead of .pipe() + finished(), so mid-download network errors fail fast instead of hanging forever or leaving truncated zips.
  • Error handling for all commands: index.ts replaces citty's error-swallowing runMain with a replica that records failure telemetry, honors CliError.exitCode, and prints one clean error line (previously: stack trace + duplicated message, no telemetry).
  • Concurrent-refresh safety: session refresh is serialized behind a lockfile with re-read-and-merge, so CI matrices can't revoke the session family via Supabase refresh-token rotation.
  • Test suite trustworthiness: the integration suite now runs against an isolated DCD_CONFIG_DIR (it previously read — and could refresh — the developer's real session, making five tests depend on local login state), polls mock-API readiness instead of sleeping 3s, and fails loudly when the mock API dies.

The first commit's message has the full per-area breakdown (~35 fixes).

Deliberately deferred (follow-up PRs)

  • strict: true burn-down (tsconfig currently strict: false)
  • Streaming uploads (binaries are currently held in memory up to 3×)
  • live.ts raw-fetch → ApiGateway refactor
  • Tightening the catch-and-accept integration-test assertions

Test plan

  • pnpm build clean, pnpm lint 0 errors (28 warnings, down from 36 on dev)
  • pnpm test: 121/121 passing against the mock API
  • Manual smoke tests: --help/--version exit 0; unknown command shows usage + single error line; unauthenticated command exits 1 with actionable message; verifyAppZip validated against the real wikipedia.zip fixture (including __MACOSX entries)

🤖 Generated with Claude Code

riglar and others added 5 commits June 12, 2026 17:57
- telemetry: redact --api-key/--env/--app-url values from argv before
  shipping events; pass auth headers to curl via 0600 config file
  instead of process arguments
- polling: report PASSED only when every test passed (unknown/cancelled
  statuses and empty result sets no longer exit 0 in CI); retry on
  empty results; stop spinner on fatal polling errors; follow retry_of
  chains when grouping retries; fix off-by-one in failure limit
- cloud: defer process.exit until after finally so --json output prints
  on failed runs and temp files are cleaned; ship failure telemetry on
  RUN_FAILED; re-emit non-punycode warnings; guard failure-path
  artifact downloads from masking the run-failed exit code
- index: replace citty runMain with a replica that records failure
  telemetry, honors CliError.exitCode, and prints clean errors for all
  commands instead of stack traces
- gateways: stream downloads via pipeline() so mid-download network
  errors fail fast instead of hanging or truncating silently; typed
  ApiError with HTTP status; parse JSON responses inside error
  handling with operation context; auth-mode-neutral 401 message
- auth: serialize session refresh behind a lockfile and re-read/merge
  config to survive concurrent invocations (CI matrices); sessionOnly
  option so switch-org works with DEVICE_CLOUD_API_KEY exported;
  switch-org defaults to the logged-in env's API URL instead of prod
- paths: segment-aware common-root computation and anchored prefix
  stripping shared via src/utils/paths.ts (replaceAll corrupted paths
  when the root substring recurred or collapsed to '')
- methods: abort before upload on 401/403 from SHA dedup check; accept
  zips without explicit directory entries (ignoring __MACOSX/.DS_Store)
  and close zip handles on all paths; remove dead code
- execution-plan: apply --exclude-flows to workspace config globs; fix
  double directory join for string runFlow/runScript deps; parse YAML
  docs beyond the second separator; dedupe sequential flows
- cloud/upload: positional flow file works with --app-file/--app-url;
  '.apk' extension check no longer matches 'myapk'; moropo temp dirs
  cleaned up after runs and on download errors
- metadata-extractor: route sync throws in zip ready handler to reject
  instead of crashing; close handles on all paths; dedupe parseInfoPlist
- misc: corrupt config warns instead of silently logging out; version
  compare handles prereleases; pagination hint uses actual page size;
  parseIntFlag rejects negatives/garbage; abort timer cleanup in
  connectivity checks; no retries on 4xx for Expo URL downloads;
  env-aware console URLs; correct --json/--json-file exit-code docs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rtion

- test-runner: run the suite with an isolated DCD_CONFIG_DIR so the CLI
  under test can never read or refresh the developer's real session
  (five auth tests previously depended on local login state)
- test-runner: replace the fixed 3s sleep with readiness polling
  against the mock API (30s deadline, fails loudly), forward mock API
  output with a prefix instead of leaving pipes unread, fail the run if
  the server dies mid-suite, kill the server's whole process group on
  POSIX, and treat signal-killed mocha as failure instead of exit 0
- metadata-extractor test: the expect.fail call was caught by its own
  catch block (AssertionError instanceof Error), so the test could
  never fail; assert via a threw flag instead

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- cli-ci: drop --ignore-registry-errors so a failed audit can't pass
  silently; scope the workflow token to contents: read
- npm-publish: refuse prod-tag publishes from any ref other than the
  production branch (workflow_dispatch could previously publish any
  non-beta version to npm latest, bypassing release-please)
- install.sh: wrap the body in main() so a truncated curl | sh
  download executes nothing
- install.ps1: pin TLS 1.2 on Windows PowerShell 5.x; read the raw
  unexpanded User PATH and write it back as ExpandString (previously
  froze %VAR% entries); append instead of prepend and skip when
  already present

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- src/types/schema.types.ts was a byte-identical, hand-maintained copy
  of the generated file with no importers; delete it and its eslint
  ignore entry
- CLAUDE.md described the abandoned loopback-server login flow; it now
  documents the implemented PKCE + claim-polling flow, and the
  telemetry section reflects the new index.ts runner

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The self-hosted runner's git upgrade made cone-mode sparse-checkout
hard-error on file patterns ("'api/swagger.json' is not a directory"),
breaking every CI run since June 10 with no repo change. Switch the
dcd checkout to non-cone patterns, which support file paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant