-
Notifications
You must be signed in to change notification settings - Fork 0
Refactor for security, resilience, and clean design #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
baditaflorin
merged 1 commit into
main
from
claude/security-resilience-refactor-01TvN8XGRwqyE1ZdPt9zvgyp
Nov 18, 2025
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # Git | ||
| .git | ||
| .gitignore | ||
| .github | ||
|
|
||
| # Build artifacts | ||
| bin/ | ||
| *.db | ||
| *.out | ||
| coverage.html | ||
|
|
||
| # IDE | ||
| .vscode | ||
| .idea | ||
| *.swp | ||
| *.swo | ||
| *~ | ||
|
|
||
| # OS | ||
| .DS_Store | ||
| Thumbs.db | ||
|
|
||
| # Documentation | ||
| *.md | ||
| !README.md | ||
| docs/ | ||
|
|
||
| # Docker | ||
| Dockerfile* | ||
| docker-compose*.yml | ||
| .dockerignore | ||
|
|
||
| # CI/CD | ||
| .travis.yml | ||
| .gitlab-ci.yml | ||
|
|
||
| # Test files | ||
| *_test.go | ||
| testdata/ | ||
|
|
||
| # Temporary files | ||
| tmp/ | ||
| temp/ | ||
| *.tmp |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # Server Configuration | ||
| SERVER_HOST=localhost | ||
| SERVER_PORT=8080 | ||
| SERVER_READ_TIMEOUT=15s | ||
| SERVER_WRITE_TIMEOUT=15s | ||
| SERVER_IDLE_TIMEOUT=60s | ||
|
|
||
| # Database Configuration | ||
| DB_PATH=./useragent.db | ||
| DB_MAX_OPEN_CONNS=25 | ||
| DB_MAX_IDLE_CONNS=5 | ||
| DB_CONN_MAX_LIFETIME=5m | ||
|
|
||
| # Application Configuration | ||
| APP_ENV=development # Options: development, staging, production | ||
| LOG_LEVEL=info # Options: debug, info, warn, error | ||
| MAX_REQUESTS_PER_MINUTE=100 | ||
|
|
||
| # Production Example (uncomment and modify for production): | ||
| # APP_ENV=production | ||
| # LOG_LEVEL=warn | ||
| # SERVER_HOST=0.0.0.0 | ||
| # DB_PATH=/data/useragent.db | ||
| # MAX_REQUESTS_PER_MINUTE=50 |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| # Multi-stage build for security and size optimization | ||
| FROM golang:1.22-alpine AS builder | ||
|
|
||
| # Install build dependencies | ||
| RUN apk add --no-cache git ca-certificates tzdata | ||
|
|
||
| # Create appuser for running the application | ||
| RUN adduser -D -g '' appuser | ||
|
|
||
| WORKDIR /build | ||
|
|
||
| # Copy go mod files first for better caching | ||
| COPY go.mod go.sum* ./ | ||
|
|
||
| # Download dependencies | ||
| RUN go mod download | ||
| RUN go mod verify | ||
|
|
||
| # Copy source code | ||
| COPY . . | ||
|
|
||
| # Build the application with security flags | ||
| RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build \ | ||
| -ldflags='-w -s -extldflags "-static"' \ | ||
| -a -installsuffix cgo \ | ||
| -o /app/useragent-demo \ | ||
| ./cmd/demo | ||
|
|
||
| # Final stage - minimal runtime image | ||
| FROM alpine:latest | ||
|
|
||
| # Install runtime dependencies and security updates | ||
| RUN apk --no-cache add ca-certificates tzdata && \ | ||
| apk --no-cache upgrade | ||
|
|
||
| # Create non-root user | ||
| RUN adduser -D -g '' appuser | ||
|
|
||
| # Create directory for database with proper permissions | ||
| RUN mkdir -p /data && chown appuser:appuser /data | ||
|
|
||
| # Copy timezone data and certificates | ||
| COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo | ||
| COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ | ||
|
|
||
| # Copy the binary from builder | ||
| COPY --from=builder /app/useragent-demo /app/useragent-demo | ||
|
|
||
| # Set ownership | ||
| RUN chown -R appuser:appuser /app | ||
|
|
||
| # Switch to non-root user | ||
| USER appuser | ||
|
|
||
| # Set working directory | ||
| WORKDIR /app | ||
|
|
||
| # Environment variables | ||
| ENV SERVER_HOST=0.0.0.0 \ | ||
| SERVER_PORT=8080 \ | ||
| DB_PATH=/data/useragent.db \ | ||
| APP_ENV=production \ | ||
| LOG_LEVEL=info | ||
|
|
||
| # Expose port | ||
| EXPOSE 8080 | ||
|
|
||
| # Health check | ||
| HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ | ||
| CMD wget --no-verbose --tries=1 --spider http://localhost:8080/api/health || exit 1 | ||
|
Comment on lines
+69
to
+70
|
||
|
|
||
| # Volume for persistent data | ||
| VOLUME ["/data"] | ||
|
|
||
| # Run the application | ||
| ENTRYPOINT ["/app/useragent-demo"] | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| .PHONY: help build test test-coverage test-race clean run run-demo docker-build docker-run lint security-scan fmt vet install-tools | ||
|
|
||
| # Variables | ||
| APP_NAME=useragent-demo | ||
| BINARY_NAME=useragent-demo | ||
| GO=go | ||
| GOFLAGS=-v | ||
| LDFLAGS=-ldflags "-w -s" | ||
| COVERAGE_FILE=coverage.out | ||
| DOCKER_IMAGE=commonuseragent:latest | ||
|
|
||
| # Colors for output | ||
| GREEN := $(shell tput -Txterm setaf 2) | ||
| YELLOW := $(shell tput -Txterm setaf 3) | ||
| RESET := $(shell tput -Txterm sgr0) | ||
|
|
||
| help: ## Show this help message | ||
| @echo '$(GREEN)Available targets:$(RESET)' | ||
| @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " $(YELLOW)%-20s$(RESET) %s\n", $$1, $$2}' | ||
|
|
||
| install-tools: ## Install development tools | ||
| @echo '$(GREEN)Installing development tools...$(RESET)' | ||
| @which golangci-lint > /dev/null || (echo 'Installing golangci-lint...' && go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest) | ||
| @which gosec > /dev/null || (echo 'Installing gosec...' && go install github.com/securego/gosec/v2/cmd/gosec@latest) | ||
| @which staticcheck > /dev/null || (echo 'Installing staticcheck...' && go install honnef.co/go/tools/cmd/staticcheck@latest) | ||
|
|
||
| build: ## Build the library | ||
| @echo '$(GREEN)Building library...$(RESET)' | ||
| $(GO) build $(GOFLAGS) ./... | ||
|
|
||
| build-demo: ## Build the demo application | ||
| @echo '$(GREEN)Building demo application...$(RESET)' | ||
| $(GO) build $(GOFLAGS) $(LDFLAGS) -o bin/$(BINARY_NAME) ./cmd/demo | ||
|
|
||
| test: ## Run tests | ||
| @echo '$(GREEN)Running tests...$(RESET)' | ||
| $(GO) test $(GOFLAGS) -timeout 30s ./... | ||
|
|
||
| test-coverage: ## Run tests with coverage | ||
| @echo '$(GREEN)Running tests with coverage...$(RESET)' | ||
| $(GO) test -v -race -coverprofile=$(COVERAGE_FILE) -covermode=atomic ./... | ||
| $(GO) tool cover -html=$(COVERAGE_FILE) -o coverage.html | ||
| @echo '$(GREEN)Coverage report generated: coverage.html$(RESET)' | ||
|
|
||
| test-race: ## Run tests with race detector | ||
| @echo '$(GREEN)Running tests with race detector...$(RESET)' | ||
| $(GO) test -v -race -timeout 60s ./... | ||
|
|
||
| bench: ## Run benchmarks | ||
| @echo '$(GREEN)Running benchmarks...$(RESET)' | ||
| $(GO) test -bench=. -benchmem ./... | ||
|
|
||
| fmt: ## Format Go code | ||
| @echo '$(GREEN)Formatting code...$(RESET)' | ||
| $(GO) fmt ./... | ||
|
|
||
| vet: ## Run go vet | ||
| @echo '$(GREEN)Running go vet...$(RESET)' | ||
| $(GO) vet ./... | ||
|
|
||
| lint: install-tools ## Run linter | ||
| @echo '$(GREEN)Running linter...$(RESET)' | ||
| golangci-lint run ./... | ||
|
|
||
| security-scan: install-tools ## Run security scanner | ||
| @echo '$(GREEN)Running security scanner...$(RESET)' | ||
| gosec -exclude-generated ./... | ||
|
|
||
| staticcheck: install-tools ## Run staticcheck | ||
| @echo '$(GREEN)Running staticcheck...$(RESET)' | ||
| staticcheck ./... | ||
|
|
||
| check: fmt vet lint staticcheck security-scan ## Run all checks (fmt, vet, lint, staticcheck, security) | ||
| @echo '$(GREEN)All checks passed!$(RESET)' | ||
|
|
||
| run-demo: build-demo ## Run the demo application | ||
| @echo '$(GREEN)Starting demo application...$(RESET)' | ||
| ./bin/$(BINARY_NAME) | ||
|
|
||
| run-demo-dev: ## Run the demo application in development mode | ||
| @echo '$(GREEN)Starting demo application (development mode)...$(RESET)' | ||
| APP_ENV=development LOG_LEVEL=debug $(GO) run ./cmd/demo | ||
|
|
||
| clean: ## Clean build artifacts | ||
| @echo '$(GREEN)Cleaning build artifacts...$(RESET)' | ||
| rm -rf bin/ | ||
| rm -f $(COVERAGE_FILE) coverage.html | ||
| rm -f *.db | ||
| $(GO) clean -cache -testcache | ||
|
|
||
| docker-build: ## Build Docker image | ||
| @echo '$(GREEN)Building Docker image...$(RESET)' | ||
| docker build -t $(DOCKER_IMAGE) . | ||
|
|
||
| docker-run: ## Run Docker container | ||
| @echo '$(GREEN)Running Docker container...$(RESET)' | ||
| docker run -p 8080:8080 --rm $(DOCKER_IMAGE) | ||
|
|
||
| docker-compose-up: ## Start services with docker-compose | ||
| @echo '$(GREEN)Starting services with docker-compose...$(RESET)' | ||
| docker-compose up -d | ||
|
|
||
| docker-compose-down: ## Stop services with docker-compose | ||
| @echo '$(GREEN)Stopping services with docker-compose...$(RESET)' | ||
| docker-compose down | ||
|
|
||
| docker-compose-logs: ## View docker-compose logs | ||
| docker-compose logs -f | ||
|
|
||
| mod-download: ## Download dependencies | ||
| @echo '$(GREEN)Downloading dependencies...$(RESET)' | ||
| $(GO) mod download | ||
|
|
||
| mod-tidy: ## Tidy dependencies | ||
| @echo '$(GREEN)Tidying dependencies...$(RESET)' | ||
| $(GO) mod tidy | ||
|
|
||
| mod-verify: ## Verify dependencies | ||
| @echo '$(GREEN)Verifying dependencies...$(RESET)' | ||
| $(GO) mod verify | ||
|
|
||
| deps: mod-download mod-tidy mod-verify ## Manage dependencies (download, tidy, verify) | ||
|
|
||
| all: clean deps check test build build-demo ## Run all checks, tests, and build everything | ||
| @echo '$(GREEN)All tasks completed successfully!$(RESET)' | ||
|
|
||
| ci: deps check test-coverage ## Run CI pipeline | ||
| @echo '$(GREEN)CI pipeline completed!$(RESET)' | ||
|
|
||
| .DEFAULT_GOAL := help |
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Dockerfile copies
go.sum*with a wildcard (line 13), which will silently succeed even if go.sum doesn't exist. Since go.sum is critical for dependency verification and reproducible builds, consider removing the wildcard to ensure the build fails if go.sum is missing:COPY go.mod go.sum ./