Network hardening + CI: size limits, retries, client reuse, tests#2
Merged
itsdevcoffee merged 1 commit intomainfrom Dec 16, 2025
Merged
Network hardening + CI: size limits, retries, client reuse, tests#2itsdevcoffee merged 1 commit intomainfrom
itsdevcoffee merged 1 commit intomainfrom
Conversation
## What Harden network layer and add comprehensive CI pipeline: 1. HTTP response size limits (DoS protection) 2. Exponential backoff retries for transient failures 3. Singleton HTTP client for connection reuse 4. Concurrency limiting (max 5 parallel fetches) 5. Visible clipboard error feedback 6. CI workflow with tests, linting, vulnerability scanning ## Changes ### HTTP Safety - Limit response body to 10MB via io.LimitReader (github.go, registry.go) - Retry failed requests 3x with exponential backoff (1s, 2s, 4s) - Singleton HTTP client for connection pooling and reuse ### Concurrency Control - Semaphore pattern limits concurrent marketplace fetches to 5 - Prevents GitHub rate limiting and resource exhaustion - Applied to both discovery.go and discover_with_registry.go ### UX Improvements - Clipboard errors now visible to user (3s red flash) - Added Error color (#EF4444) to UI palette - Clear feedback instead of silent failures ### CI/CD - .github/workflows/ci.yml: 4 jobs (test, lint, vuln-check, build) - go test -race for race condition detection - golangci-lint with gosec for security analysis - govulncheck for known vulnerability scanning - gofmt validation ## Why - **Security**: Unbounded reads could DoS client via large responses - **Reliability**: Transient network failures should auto-retry - **Performance**: Connection reuse reduces latency/overhead - **UX**: Users need to know when clipboard fails - **Quality**: CI catches bugs before merge ## Testing \`\`\`bash go test -v -race ./... go build ./cmd/plum/ # All tests pass, no race conditions \`\`\` ## Manual Validation 1. Run plum, press Shift+U → observe retry behavior on network hiccup 2. Test clipboard copy (c key) → error should show if clipboard unavailable 3. Verify HTTP client reuse (singleton pattern) 4. Check concurrency limit (max 5 parallel requests)
6 tasks
itsdevcoffee
added a commit
that referenced
this pull request
Dec 16, 2025
Focused follow-up pass to close remaining edge cases after PRs #1 and #2: 1. Windows-safe atomic file replacement: - Add atomicRename helper with remove+retry fallback - Fixes os.Rename failures when destination exists on Windows - Applied to both cache.go and registry.go 2. Tightened retry policy: - Only retry transient failures (5xx, 429, network/timeout errors) - Skip retries for permanent failures (4xx except 429) - Add httpStatusError type for structured error handling - Add isRetryableError() helper with proper error type checking 3. HTTP tests made real: - Convert GitHubRawBase from const to package variable - Remove all t.Skip() scaffolding - Add asserting tests for: * Body size limit enforcement * Retry behavior on transient failures * Non-retry behavior on permanent failures (404) * Invalid JSON handling * Timeout handling (skipped in short mode) 4. CI polish: - Switch from hardcoded go-version to go-version-file: go.mod - Improves maintainability and version consistency All tests passing with race detector enabled.
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
Harden network layer against DoS/failures and establish CI quality gates.
Problems Fixed
1. Unbounded HTTP Reads (CRITICAL)
io.LimitReadercaps response at 10MBgithub.go:88,registry.go:1272. No Retry Logic (HIGH)
github.go:40-593. HTTP Client Churn (MEDIUM)
sync.Oncegithub.go:120-1314. Unbounded Concurrency (MEDIUM)
discovery.go:85,discover_with_registry.go:255. Silent Clipboard Errors (LOW)
cto copy, nothing happens → confusionupdate.go:315,view.go:5156. No CI Checks (HIGH)
.github/workflows/ci.ymlChanges Made
HTTP Layer (
internal/marketplace/github.go,registry.go)Body size limit:
io.LimitReader(resp.Body, MaxResponseBodySize)"response body exceeded 10485760 bytes"Retry with backoff:
FetchManifestFromGitHubnow callsfetchManifestAttemptin looptime.Duration(1<<uint(attempt)) * time.SecondSingleton client:
httpClient()usessync.Oncehttp.Clientinstance for all requestsTransport(10 idle, 5 per host)Concurrency Control (
discovery.go,discover_with_registry.go)UI Feedback (
internal/ui/)clipboardErrorFlash boolinModelclearClipboardErrorMsgwith 3s delayErrorcolor (#EF4444) added to paletteCI/CD Infrastructure
.github/workflows/ci.yml: 4 jobs run on every PR/pushgo test -v -race -coverprofile=coverage.out ./...golangci-lint+gofmtvalidationgovulncheck ./...go build -v ./cmd/plum/.golangci.yml: Linter configerrcheck,gosimple,govet,staticcheck,gosec,gofmt, etc.gosecenabled)Test Results
Unit Tests
```bash
$ go test -v -race ./...
ok github.com/itsdevcoffee/plum/internal/marketplace 1.040s
```
Build Verification
```bash
$ go build ./cmd/plum/
Success - binary created
```
Race Detector
```bash
$ go test -race ./...
No data races detected
```
How to Validate
Automated
```bash
Run full test suite
go test -v -race ./...
Build binary
go build ./cmd/plum/
Lint (requires golangci-lint)
golangci-lint run
Vulnerability scan (requires govulncheck)
govulncheck ./...
```
Manual Testing
1. Retry Behavior
plum, pressShift+U2. Clipboard Error Feedback
Enteron a plugin, then pressc3. HTTP Client Reuse
httpClient()sync.Onceensures only 1 client created4. Concurrency Limit
5. Body Size Limit
Checklist
go test -race ./...)Follow-up Work (Future PRs)
buildRawURLaccept base URL to enable full HTTP mockingNotes
github_test.gocontains skeleton tests marked as skippedbuildRawURLto be injectable (out of scope for this PR)