Skip to content

fix: comprehensive code-audit fixes (perf, concurrency, error-handling, security, tests, CI)#90

Merged
GeiserX merged 3 commits into
mainfrom
fix/review-code-wave1
Jul 10, 2026
Merged

fix: comprehensive code-audit fixes (perf, concurrency, error-handling, security, tests, CI)#90
GeiserX merged 3 commits into
mainfrom
fix/review-code-wave1

Conversation

@GeiserX

@GeiserX GeiserX commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Fixes from a full-codebase multi-perspective audit (/review-code! — 8 auditors). Delivered in 3 verified waves on this branch. Overall health went from a first-pass 7/10 toward closing every HIGH-severity actionable finding; the only items left are genuine architecture decisions / a preventive security refactor that warrant their own PRs (listed at the bottom).

Wave 1 — safe, high-value, mechanical

  • perf: add idx_earnings_platform_created (the fastest-growing table had zero indexes; every scan blocked the single SQLite conn). GetAppState fetches earnings/deployments once (was 3×/2×).
  • correctness: unify the two divergent memory parsers — native failed open (unbounded) on a bad/fractional MemLimit while Docker failed closed.
  • error-handling: RecordEvent/updatePID log their swallowed errors; 5 frontend try/catch gaps (silent dead tabs / empty forms / unhandled rejections) + consistent slug escapeHtml.
  • test: fix the flaky TestNativeSupervisorStopsAfterMaxRestarts (actively reddening CI — failed live during the audit).
  • CI/sec: pin go-version 1.26.5 (crypto/tls advisory); persist-credentials:false; fix the Windows-signing if: that never fired.

Wave 2 — concurrency perf (HIGH)

  • List now samples native-process stats concurrently (goroutine per entry, 8-slot semaphore, own slice index) — was O(N×200ms) blocking on every dashboard click; mirrors the Docker path.
  • collectAll is now a bounded worker pool (6) — was serial (a few slow providers stretched a cycle to minutes). Single-flight, per-service error isolation, post-loop ordering, ctx-cancel-safety all preserved.
  • facade: add the 3 missing bindings (StartService — called by main.ts — ListServices, GetService) to the hand-maintained wails.d.ts that had drifted from Go.

Wave 3 — nits, security warning, test gaps

  • collector error strings standardized to the user-facing house style; substitute is now a single-pass regexp (no re-expansion of ${...} inside a value); Fleet-Bind help now warns about the unauthenticated /metrics LAN exposure.
  • test: new resource_limits_windows_test.go (//go:build windows, runs on windows-latest at release) for the previously-untested Job-Object path; fixed the sibling flaky test.

Verification (all local, macOS)

go build ./... + GOOS=windows go build/vet (compiles the Windows test) + go vet ./... + go test -race ./... (all 10 packages) + frontend tsc && vite build — all green.

Deferred — with rationale, not dropped (need their own PR / your call)

  • Security (preventive): native state.json stores service creds in plaintext — defeats the AES-GCM at-rest design vs backups/sync. Fix crosses the deliberate runtimestore decoupling (inject a sealer / re-resolve from the encrypted store on relaunch) and touches the core relaunch flow, so it deserves a dedicated, well-tested PR (no credential-bearing native service ships today, so it is preventive).
  • CI cadence: add macOS/Windows to the per-PR test matrix (today the cross-OS suite only runs at release) — free on this public repo, but it slows PR feedback + needs a single-OS codecov upload, so flagging for your nod.
  • Architecture decisions (real tradeoffs): rename the Docker-shaped Provider/ContainerInfo to a runtime-neutral shape (churns the deployments schema + frontend); collector self-registration (retire the central dispatch map); extract computeEarningsSummaryinternal/summary (now param-testable after wave 1, so lower ROI). These change public contracts/schema and are best decided explicitly.

… CI (wave 1)

From a full-codebase multi-perspective audit. Wave 1 = the safe, high-value,
mechanical fixes (concurrency refactors + large refactors deferred).

Performance:
- store: add idx_earnings_platform_created on earnings(platform, created_at) —
  the fastest-growing table had zero indexes; ListDailyBalances/ListLatestEarnings/
  PurgeOldData full-scanned it under a single SQLite connection.
- app: GetAppState fetches ListLatestEarnings/ListDeployments once and threads
  them into computeEarningsSummary/notifications (was 3x/2x per call).

Error handling:
- store: RecordEvent no longer swallows its INSERT error (it sinks all health
  events; a silent failure masked crash-loops) — logs on failure.
- native: updatePID logs a registry-persist failure, like persistRunning.
- frontend: renderSettings/renderFleet/removeFleetDevice/hydrateWizardForm and
  clipboard copy now try/catch their awaited bound calls (were silent dead tabs
  / empty forms / unhandled rejections).

Consistency / correctness:
- runtime: unify the two divergent memory parsers into one canonical
  parseMemoryBytes (fractional + overflow-guarded); the native path now shares
  the Docker grammar, removing the fail-open-on-fractional divergence. Deletes
  the duplicate parseMemBytes + its test.
- frontend: escapeHtml all slug interpolations consistently.

Test:
- fix flaky TestNativeSupervisorStopsAfterMaxRestarts (5s deadline -> the repo's
  waitFor 15s poll; ~4s consumed by real fork/exec under -race intermittently
  reddened CI).

CI / security:
- pin go-version 1.26.5 in both workflows (closes crypto/tls GO-2026-5856,
  reachable via Docker Logs).
- desktop-release: add persist-credentials:false; fix the Windows-signing `if`
  (referenced step-level env, always false, so signing never ran).

Verified: go build ./... + GOOS=windows build + go vet ./... + go test -race
./... + frontend tsc && vite build all green.
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR pins Go tooling in CI and desktop releases, reuses fetched application data, hardens frontend actions, improves runtime memory parsing and persistence logging, updates supervisor timing tests, and adds store logging and an earnings index.

Changes

Delivery workflow updates

Layer / File(s) Summary
Pinned toolchains and release safeguards
.github/workflows/ci.yml, .github/workflows/desktop-release.yml
CI and release jobs pin Go to 1.26.5; Windows signing checks the secret directly, and publishing disables checkout credential persistence.

Application state and frontend resilience

Layer / File(s) Summary
Shared application data inputs
app.go, metrics.go, app_test.go
Earnings and deployment slices are passed into summaries and notifications, with updated metrics handling and tests.
Escaped UI actions and guarded requests
frontend/src/main.ts
Service identifiers are escaped in data attributes, and settings, fleet, clipboard, removal, and credential failures now produce scoped error toasts.

Runtime and store behavior

Layer / File(s) Summary
Canonical memory-limit parsing
internal/runtime/runtime.go, internal/runtime/resource_limits_*.go, internal/runtime/runtime_test.go
Native resource-limit paths use parseMemoryBytes, reject non-positive values and overflow, and expand parser coverage.
Supervisor persistence and shutdown validation
internal/runtime/native.go, internal/runtime/native_test.go
PID registry failures are logged, and supervisor shutdown tests use a longer polling timeout.
Store logging and earnings indexing
internal/store/store.go
Runtime event insertion failures are logged, corrupt service data handling is documented, and an earnings index is added.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the PR’s main audit-fix theme and covers the major areas changed, even if it is broad.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/review-code-wave1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.00000% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.70%. Comparing base (a3862db) to head (76b1e02).

Files with missing lines Patch % Lines
internal/collectors/collectors.go 50.00% 3 Missing ⚠️
internal/runtime/native.go 90.47% 2 Missing ⚠️
internal/store/store.go 33.33% 1 Missing and 1 partial ⚠️
internal/runtime/resource_limits_linux.go 0.00% 0 Missing and 1 partial ⚠️
internal/runtime/runtime.go 88.88% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #90      +/-   ##
==========================================
- Coverage   74.74%   74.70%   -0.05%     
==========================================
  Files          15       14       -1     
  Lines        3271     3261      -10     
==========================================
- Hits         2445     2436       -9     
+ Misses        652      651       -1     
  Partials      174      174              
Files with missing lines Coverage Δ
metrics.go 92.38% <100.00%> (+0.30%) ⬆️
internal/runtime/resource_limits_linux.go 75.00% <0.00%> (ø)
internal/runtime/runtime.go 56.67% <88.88%> (+0.52%) ⬆️
internal/runtime/native.go 82.14% <90.47%> (-0.01%) ⬇️
internal/store/store.go 81.29% <33.33%> (-0.36%) ⬇️
internal/collectors/collectors.go 60.20% <50.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
metrics.go (1)

73-78: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Duplicate ListLatestEarnings fetch in the metrics path.

renderMetrics fetches earnings at line 75 for computeEarningsSummary, then renderStoreMetrics (line 101) fetches the same data again. The PR objective is to avoid repeated fetches — thread the earnings slice into renderStoreMetrics to eliminate the second query.

♻️ Proposed refactor
 func (a *App) renderMetrics() string {
 	mw := &metricsWriter{}
 	// ...
 	var summary EarningsSummary
 	if a.store != nil {
-		summary = a.computeEarningsSummary(a.store.ListLatestEarnings())
+		earnings := a.store.ListLatestEarnings()
+		summary = a.computeEarningsSummary(earnings)
+		a.renderStoreMetrics(mw, earnings)
 	} else {
 		summary = a.computeEarningsSummary(nil)
 	}
 	// ...
-	if a.store != nil {
-		a.renderStoreMetrics(mw)
-	}
 	return mw.String()
 }

-func (a *App) renderStoreMetrics(mw *metricsWriter) {
+func (a *App) renderStoreMetrics(mw *metricsWriter, latest []store.EarningsRecord) {
 	// -- Per-platform latest balance / error --
-	latest := a.store.ListLatestEarnings()
 	mw.family("cashpilot_service_balance", ...)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@metrics.go` around lines 73 - 78, renderMetrics currently fetches earnings
separately from renderStoreMetrics, causing duplicate ListLatestEarnings
queries. Store the fetched earnings slice once in renderMetrics, pass it to
computeEarningsSummary and renderStoreMetrics, and update renderStoreMetrics’
signature and callers to use the provided slice instead of querying a.store
again.
frontend/src/main.ts (1)

1317-1317: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Raw slug in CSS attribute selector after escaping in HTML.

The data-form-slug attribute is set with escapeHtml(service.slug) (line 1242), but hydrateWizardForm uses the raw service.slug in the CSS selector string. For normal slugs this works because the DOM attribute value equals the raw slug after HTML parsing. If a slug ever contained a " character, the selector would break. Slugs are controlled identifiers so this is theoretical, but worth noting for consistency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/main.ts` at line 1317, Update hydrateWizardForm to safely handle
service.slug when constructing the data-form-slug CSS selector, using
appropriate CSS attribute-value escaping or a DOM lookup that avoids
interpolating the raw slug; keep it consistent with the escaped value assigned
by escapeHtml when rendering the attribute.
.github/workflows/desktop-release.yml (1)

29-29: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Consider cache-poisoning risk on setup-go cache.

zizmor flags setup-go with cache: true as potentially vulnerable to cache poisoning in public repos. If this repository is public, a attacker could submit a PR that poisons the Go module cache. Evaluate whether cache: true is acceptable given the repo's visibility, or consider cache: false with explicit go mod download if this is a concern.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/desktop-release.yml at line 29, Review the setup-go
configuration in the desktop release workflow and assess whether its enabled
module caching is safe for this repository’s visibility and PR model. If cache
poisoning is a concern, disable setup-go caching and add an explicit go mod
download step; otherwise document or retain the justified configuration.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Line 25: Update the Go version configuration used by the CI workflow and its
corresponding release configuration to use the documented auto-patching selector
“1.26.x” instead of the exact “1.26.5” pin, ensuring the values remain
consistent with docs/SECURITY-NOTES.md.

In @.github/workflows/desktop-release.yml:
- Line 63: Replace the secrets.WINDOWS_SIGN_CERT reference in the step’s if
condition with the corresponding env.WINDOWS_SIGN_CERT variable already defined
for the step, while preserving the Windows runner check.

In `@internal/runtime/runtime.go`:
- Around line 685-692: Update the overflow check in the unit-parsing conversion
logic to use a greater-than-or-equal comparison against math.MaxInt64, ensuring
the exact 2^63 boundary is rejected before int64 conversion. Locate the bytes
calculation and guard in the relevant parsing function and change the condition
from > to >=.

---

Nitpick comments:
In @.github/workflows/desktop-release.yml:
- Line 29: Review the setup-go configuration in the desktop release workflow and
assess whether its enabled module caching is safe for this repository’s
visibility and PR model. If cache poisoning is a concern, disable setup-go
caching and add an explicit go mod download step; otherwise document or retain
the justified configuration.

In `@frontend/src/main.ts`:
- Line 1317: Update hydrateWizardForm to safely handle service.slug when
constructing the data-form-slug CSS selector, using appropriate CSS
attribute-value escaping or a DOM lookup that avoids interpolating the raw slug;
keep it consistent with the escaped value assigned by escapeHtml when rendering
the attribute.

In `@metrics.go`:
- Around line 73-78: renderMetrics currently fetches earnings separately from
renderStoreMetrics, causing duplicate ListLatestEarnings queries. Store the
fetched earnings slice once in renderMetrics, pass it to computeEarningsSummary
and renderStoreMetrics, and update renderStoreMetrics’ signature and callers to
use the provided slice instead of querying a.store again.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d16c4f6e-8f55-4e1d-9c3e-132bc7753784

📥 Commits

Reviewing files that changed from the base of the PR and between a3862db and 187b1e1.

📒 Files selected for processing (15)
  • .github/workflows/ci.yml
  • .github/workflows/desktop-release.yml
  • app.go
  • app_test.go
  • frontend/src/main.ts
  • internal/runtime/native.go
  • internal/runtime/native_test.go
  • internal/runtime/resource_limits.go
  • internal/runtime/resource_limits_linux.go
  • internal/runtime/resource_limits_test.go
  • internal/runtime/resource_limits_windows.go
  • internal/runtime/runtime.go
  • internal/runtime/runtime_test.go
  • internal/store/store.go
  • metrics.go
💤 Files with no reviewable changes (2)
  • internal/runtime/resource_limits_test.go
  • internal/runtime/resource_limits.go

Comment thread .github/workflows/ci.yml
- uses: actions/setup-go@v6
with:
go-version: '1.26'
go-version: '1.26.5'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚖️ Poor tradeoff

Pinning to exact 1.26.5 contradicts the documented auto-patch strategy.

docs/SECURITY-NOTES.md:10-14 states CI/release builds use go-version: '1.26' / '1.26.x' to automatically pull each Go security patch. Pinning to the exact 1.26.5 means future patches (e.g., 1.26.6) won't be picked up without a manual workflow update, degrading the security posture the docs describe. Either update the docs to reflect the intentional pinning strategy, or use '1.26.x' to retain auto-patching.

Also applies to: 56-56

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml at line 25, Update the Go version configuration
used by the CI workflow and its corresponding release configuration to use the
documented auto-patching selector “1.26.x” instead of the exact “1.26.5” pin,
ensuring the values remain consistent with docs/SECURITY-NOTES.md.


- name: Sign Windows binaries
if: runner.os == 'Windows' && env.WINDOWS_SIGN_CERT != ''
if: runner.os == 'Windows' && secrets.WINDOWS_SIGN_CERT != ''

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

secrets context is not allowed in step if conditionals — this will fail.

actionlint confirms: the secrets context is unavailable in if expressions. GitHub Actions only allows env, github, inputs, job, matrix, needs, runner, steps, strategy, and vars in conditionals. The step already maps WINDOWS_SIGN_CERT into env at line 65 — reference that instead.

🔧 Fix: use env instead of secrets in the if condition
       - name: Sign Windows binaries
-        if: runner.os == 'Windows' && secrets.WINDOWS_SIGN_CERT != ''
+        if: runner.os == 'Windows' && env.WINDOWS_SIGN_CERT != ''
         env:
           WINDOWS_SIGN_CERT: ${{ secrets.WINDOWS_SIGN_CERT }}
           WINDOWS_SIGN_CERT_PASSWORD: ${{ secrets.WINDOWS_SIGN_CERT_PASSWORD }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if: runner.os == 'Windows' && secrets.WINDOWS_SIGN_CERT != ''
- name: Sign Windows binaries
if: runner.os == 'Windows' && env.WINDOWS_SIGN_CERT != ''
env:
WINDOWS_SIGN_CERT: ${{ secrets.WINDOWS_SIGN_CERT }}
WINDOWS_SIGN_CERT_PASSWORD: ${{ secrets.WINDOWS_SIGN_CERT_PASSWORD }}
🧰 Tools
🪛 actionlint (1.7.12)

[error] 63-63: context "secrets" is not allowed here. available contexts are "env", "github", "inputs", "job", "matrix", "needs", "runner", "steps", "strategy", "vars". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details

(expression)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/desktop-release.yml at line 63, Replace the
secrets.WINDOWS_SIGN_CERT reference in the step’s if condition with the
corresponding env.WINDOWS_SIGN_CERT variable already defined for the step, while
preserving the Windows runner check.

Source: Linters/SAST tools

Comment on lines +685 to +692
// Guard against overflowing a 64-bit byte count before the float->int64
// conversion, which would otherwise silently produce an unspecified/wrapped
// result for very large mantissas or unit multipliers (e.g. "1e300t").
bytes := value * float64(multiplier)
if bytes > math.MaxInt64 {
return 0, fmt.Errorf("%q overflows a 64-bit byte count", s)
}
return int64(bytes), nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify that float64(math.MaxInt64) == 2^63 and int64(2^63) overflows.
cat <<'EOF' | go run -
package main

import (
	"fmt"
	"math"
)

func main() {
	f := float64(math.MaxInt64)
	fmt.Printf("float64(MaxInt64) = %v\n", f)
	fmt.Printf("float64(MaxInt64) == 2^63: %v\n", f == float64(1<<63))
	i := int64(f)
	fmt.Printf("int64(float64(MaxInt64)) = %d (MinInt64=%d, overflow=%v)\n", i, math.MinInt64, i == math.MinInt64)

	// Simulate "8388608t"
	bytes := 8388608.0 * float64(int64(1)<<40)
	fmt.Printf("8388608t bytes = %v\n", bytes)
	fmt.Printf("bytes > math.MaxInt64: %v\n", bytes > math.MaxInt64)
	fmt.Printf("bytes >= math.MaxInt64: %v\n", bytes >= math.MaxInt64)
	fmt.Printf("int64(bytes) = %d\n", int64(bytes))
}
EOF

Repository: GeiserX/CashPilot-Desktop

Length of output: 186


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== source =="
sed -n '675,700p' internal/runtime/runtime.go

echo
echo "== go verifier =="
tmpdir="$(mktemp -d)"
cat >"$tmpdir/main.go" <<'EOF'
package main

import (
	"fmt"
	"math"
)

func main() {
	f := float64(math.MaxInt64)
	fmt.Printf("float64(MaxInt64)=%.0f\n", f)
	fmt.Printf("float64(MaxInt64)==2^63:%v\n", f == float64(uint64(1)<<63))
	fmt.Printf("float64(MaxInt64)>MaxInt64:%v\n", f > math.MaxInt64)
	fmt.Printf("float64(MaxInt64)>=MaxInt64:%v\n", f >= math.MaxInt64)
	fmt.Printf("int64(float64(MaxInt64))=%d\n", int64(f))

	bytes := 8388608.0 * float64(int64(1)<<40)
	fmt.Printf("8388608t bytes=%.0f\n", bytes)
	fmt.Printf("bytes>MaxInt64:%v\n", bytes > math.MaxInt64)
	fmt.Printf("bytes>=MaxInt64:%v\n", bytes >= math.MaxInt64)
	fmt.Printf("int64(bytes)=%d\n", int64(bytes))
}
EOF
go run "$tmpdir/main.go"
rm -rf "$tmpdir"

Repository: GeiserX/CashPilot-Desktop

Length of output: 1406


Handle the exact 2^63 boundary too. bytes > math.MaxInt64 still lets 8388608t through because math.MaxInt64 rounds to 2^63 as a float64; use >= so the boundary case is rejected.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/runtime/runtime.go` around lines 685 - 692, Update the overflow
check in the unit-parsing conversion logic to use a greater-than-or-equal
comparison against math.MaxInt64, ensuring the exact 2^63 boundary is rejected
before int64 conversion. Locate the bytes calculation and guard in the relevant
parsing function and change the condition from > to >=.

GeiserX added 2 commits July 10, 2026 15:04
…ts facade drift (wave 2)

- runtime: NativeProcessProvider.List samples each alive process's CPU/mem concurrently
  (goroutine per entry, own preallocated slice index, 8-slot semaphore, WaitGroup join)
  instead of sequentially at ~200ms each — mirrors DockerProvider.statsForContainers.
  Sort order + entryIsOurs liveness gate preserved.
- app: collectAll's per-service collect loop is now a bounded worker pool
  (collectConcurrency=6) — was strictly sequential. Single-flight guard, per-service
  emitError (never aborts batch), post-loop ordering (wg.Wait before sampleHealth/purge),
  and ctx-cancel-without-goroutine-leak all preserved. Store writes serialize on the
  single SQLite connection.
- app_test: TestCollectAllSingleFlight rewritten — asserted max-concurrent-collects==1,
  which measured the old SEQUENTIAL collect, not single-flight. Now asserts the real
  property: of 8 concurrent collectAll calls only one body runs (3 collects total, not
  8x3) and the run's parallelism stays within collectConcurrency.
- frontend: add the 3 missing bindings (StartService — called by main.ts — plus
  ListServices, GetService) to the hand-maintained wails.d.ts, which had drifted from Go.

Verified: build + GOOS=windows build + vet + go test -race ./... (root + runtime, no
data race) + frontend tsc && vite build.
…sibling

- collectors: standardize the 6 lowercase error-string outliers to the user-facing
  Product-Capitalized house style (these surface in earnings.error + toasts).
- runtime: substitute is now a single-pass regexp replacer (compiled once at package
  scope) instead of accumulating strings.ReplaceAll over random map order — a value
  containing a literal ${OTHER} is no longer re-expanded. Known/unknown/non-var
  semantics preserved.
- security: extend the Fleet Bind Address help to warn that a non-loopback bind also
  serves the UNAUTHENTICATED /metrics endpoint (earnings/health) to the LAN.
- test: add resource_limits_windows_test.go (//go:build windows) — the Windows Job
  Object path had zero coverage; runs on windows-latest at release. Invalid-pid error
  path + nil/no-Process guard, no risk to the test process.
- test: fix the sibling flaky test TestNativeSupervisorRecordsCrashAndRestartEvents
  (same 5s deadline the wave-1 fix left untouched) -> waitFor(15s) poll.

Verified: build + GOOS=windows build/vet (compiles the windows test) + go vet ./... +
go test -race ./internal/collectors/ ./internal/runtime/ . all green.
@GeiserX GeiserX changed the title fix: code-audit findings — perf, error-handling, consistency, CI (wave 1) fix: comprehensive code-audit fixes (perf, concurrency, error-handling, security, tests, CI) Jul 10, 2026
@GeiserX GeiserX merged commit 178fbf7 into main Jul 10, 2026
6 checks passed
@GeiserX GeiserX deleted the fix/review-code-wave1 branch July 10, 2026 16:40
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