Skip to content

Commit ad5c05f

Browse files
committed
26.2.4
v26.2.4: Major platform update — security hardening, TLS everywhere, 12 new services, 78 new tests Infrastructure: - PostgreSQL TLS enabled by default (ECDSA P-256 self-signed, sslmode=require) - Redis TLS enabled by default (rediss://, auto-generated certs) - HTTP-to-HTTPS redirect with health endpoint exceptions - Trivy scanner pinned to v0.69.1 for reproducible builds - Docker CLI upgraded to 29.2.0 (API 1.53) Security hardening: - JWT tokens rejected from query parameters (header + cookie only) - CORS restricted to same-origin by default (was allow-all) - CSRF constant-time comparison + auto-regeneration - Return URL validation against open redirects - Bearer prefix enforcement per RFC 6750 - WebSocket origin validation on all upgrade requests - WebSocket rate limiting (20 concurrent per IP) - TOTP replay attack protection via Redis - Admin self-role-change prevention - 10 MB max request body on all authenticated routes - Webhook tokens hashed with SHA-256 before storage - Per-route CSP (strict global, relaxed for Monaco) - getRealIP uses rightmost non-private X-Forwarded-For New services (12): - Calendar (events, tasks, checklists, notes) - Change events feed (immutable audit trail with full-text search) - Cost/resource optimization (usage tracking, recommendations) - Custom dashboards (per-user widget layouts) - Drift detection (config snapshots, env/port/volume/image diff) - Session recording & replay (asciicast v2, gzip, retention policies) - Registry browsing (Docker Hub, GHCR, Harbor, OCI v2) - Compliance evaluator (CIS Docker Benchmark scoring) - Compliance PDF report generator (pure Go, no dependencies) - Proxy backend abstraction layer (SyncBackend interface) - About page (version, runtime, DB version, health) New scheduler workers: - Auto-deploy (GitOps image tag detection) - Runbook execution (multi-step with approval gates) - SLA breach detection (vulnerability deadline monitoring) - Webhook dispatch (HMAC-SHA256 signed, with retry) New developer tools (15 browser-based): - Base64/URL/hex encoders, JSON/YAML formatters, UUID/password generators - Hash calculator, CIDR calculator, regex tester, JWT decoder - Text diff viewer, crypto key generator, TOTP generator App catalog expanded (6 → 20 apps, 7 categories): - Nextcloud, Traefik v3, WireGuard Easy, Mattermost - Passbolt, Vaultwarden, Authentik, Uptime Kuma - Grafana + Prometheus, Woodpecker CI, PostgreSQL + pgAdmin New database migrations (036–044): - Agent events, git sync full-name, CVE remediation tracking - Change events, drift detection, resource optimization - Session recording, runbook approvals, calendar Application bootstrap: - Monolithic app.go (2554 lines) split into 8 init files - API errors standardized (machine-readable codes, consistent JSON) - Auth provider adapter layer (decoupled LDAP/OAuth types) Config changes: - JWT secret and encryption key auto-generated on first run - Default admin password now random (printed to stderr) - cookie_secure defaults to true - Configurable rate limits, paths, storage dirs Frontend: - 23 new template page directories - Self-hosted vendor libs: asciinema-player, bcrypt.js, js-yaml, marked Testing: - 78 new test files (54 → 132 total) - Shared testutil package with fixtures and helpers - Coverage across agent, services, repositories, handlers, middleware CI/CD: - GitHub Actions pipeline (lint, test, security scan, build) - GoReleaser config (multi-arch linux/darwin amd64/arm64) - Pre-commit hooks (govulncheck, migration verify, go mod tidy) Bug fixes: - Containers not appearing after restart (host stuck offline) - Host never recovering from offline status - Shortcuts form multiple submission (disabled inactive inputs) - Ansible inventory routes were commented out (404) - Node metrics "No Data Available" (type constant mismatch) - NATS "Disconnected" on About page (readiness check) - Stack deploy log not streaming (buffered output) - Server readiness race (poll loop replaces sleep) - Forward reference compile error in app.go - NATS client Connect() never called - Audit service nil in standalone mode - Orphan contexts in goroutines (Trivy, scheduler) - Proxy host ID resolution (hashUUIDToInt)
1 parent 6f6f89f commit ad5c05f

587 files changed

Lines changed: 103973 additions & 7751 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.goreleaser.yml

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
# usulnet - GoReleaser Configuration
3+
# https://goreleaser.com
4+
5+
version: 2
6+
7+
before:
8+
hooks:
9+
- go mod tidy
10+
- go install github.com/a-h/templ/cmd/templ@v0.3.977
11+
- templ generate
12+
13+
builds:
14+
- id: usulnet
15+
main: ./cmd/usulnet
16+
binary: usulnet
17+
env:
18+
- CGO_ENABLED=0
19+
goos:
20+
- linux
21+
- darwin
22+
goarch:
23+
- amd64
24+
- arm64
25+
ldflags:
26+
- -s -w
27+
- -X github.com/fr4nsys/usulnet/internal/app.Version={{.Version}}
28+
- -X github.com/fr4nsys/usulnet/internal/app.Commit={{.Commit}}
29+
- -X github.com/fr4nsys/usulnet/internal/app.BuildTime={{.Date}}
30+
flags:
31+
- -trimpath
32+
33+
- id: usulnet-agent
34+
main: ./cmd/usulnet-agent
35+
binary: usulnet-agent
36+
env:
37+
- CGO_ENABLED=0
38+
goos:
39+
- linux
40+
- darwin
41+
goarch:
42+
- amd64
43+
- arm64
44+
ldflags:
45+
- -s -w
46+
- -X github.com/fr4nsys/usulnet/internal/app.Version={{.Version}}
47+
- -X github.com/fr4nsys/usulnet/internal/app.Commit={{.Commit}}
48+
- -X github.com/fr4nsys/usulnet/internal/app.BuildTime={{.Date}}
49+
flags:
50+
- -trimpath
51+
52+
archives:
53+
- id: default
54+
formats:
55+
- tar.gz
56+
name_template: >-
57+
{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}
58+
files:
59+
- LICENSE
60+
- README.md
61+
- config.yaml
62+
- deploy/**/*
63+
64+
checksum:
65+
name_template: "checksums.txt"
66+
algorithm: sha256
67+
68+
changelog:
69+
sort: asc
70+
filters:
71+
exclude:
72+
- "^docs:"
73+
- "^test:"
74+
- "^ci:"
75+
- "^chore:"
76+
- "^style:"
77+
groups:
78+
- title: "Security"
79+
regexp: '^.*?sec(urity)?(\(.+\))?\!?:.+$'
80+
order: 0
81+
- title: "Features"
82+
regexp: '^.*?feat(\(.+\))?\!?:.+$'
83+
order: 1
84+
- title: "Bug Fixes"
85+
regexp: '^.*?fix(\(.+\))?\!?:.+$'
86+
order: 2
87+
- title: "Performance"
88+
regexp: '^.*?perf(\(.+\))?\!?:.+$'
89+
order: 3
90+
- title: "Other"
91+
order: 999
92+
93+
dockers:
94+
- image_templates:
95+
- "ghcr.io/fr4nsys/usulnet:{{ .Version }}-amd64"
96+
- "ghcr.io/fr4nsys/usulnet:latest-amd64"
97+
use: buildx
98+
dockerfile: Dockerfile
99+
build_flag_templates:
100+
- "--platform=linux/amd64"
101+
- "--build-arg=VERSION={{.Version}}"
102+
- "--build-arg=COMMIT={{.Commit}}"
103+
- "--build-arg=BUILD_TIME={{.Date}}"
104+
- "--label=org.opencontainers.image.version={{.Version}}"
105+
- "--label=org.opencontainers.image.revision={{.Commit}}"
106+
- "--label=org.opencontainers.image.created={{.Date}}"
107+
ids:
108+
- usulnet
109+
110+
- image_templates:
111+
- "ghcr.io/fr4nsys/usulnet:{{ .Version }}-arm64"
112+
- "ghcr.io/fr4nsys/usulnet:latest-arm64"
113+
use: buildx
114+
dockerfile: Dockerfile
115+
build_flag_templates:
116+
- "--platform=linux/arm64"
117+
- "--build-arg=VERSION={{.Version}}"
118+
- "--build-arg=COMMIT={{.Commit}}"
119+
- "--build-arg=BUILD_TIME={{.Date}}"
120+
- "--label=org.opencontainers.image.version={{.Version}}"
121+
- "--label=org.opencontainers.image.revision={{.Commit}}"
122+
- "--label=org.opencontainers.image.created={{.Date}}"
123+
ids:
124+
- usulnet
125+
goarch: arm64
126+
127+
docker_manifests:
128+
- name_template: "ghcr.io/fr4nsys/usulnet:{{ .Version }}"
129+
image_templates:
130+
- "ghcr.io/fr4nsys/usulnet:{{ .Version }}-amd64"
131+
- "ghcr.io/fr4nsys/usulnet:{{ .Version }}-arm64"
132+
- name_template: "ghcr.io/fr4nsys/usulnet:latest"
133+
image_templates:
134+
- "ghcr.io/fr4nsys/usulnet:latest-amd64"
135+
- "ghcr.io/fr4nsys/usulnet:latest-arm64"
136+
137+
release:
138+
github:
139+
owner: fr4nsys
140+
name: usulnet
141+
prerelease: auto
142+
name_template: "v{{.Version}}"
143+
header: |
144+
## usulnet v{{.Version}}
145+
146+
Docker Management Platform — self-hosted alternative to Portainer.
147+
footer: |
148+
## Docker
149+
150+
```bash
151+
docker pull ghcr.io/fr4nsys/usulnet:{{.Version}}
152+
```
153+
154+
**Full Changelog**: https://github.com/fr4nsys/usulnet/compare/{{ .PreviousTag }}...{{ .Tag }}

Dockerfile

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,16 +93,17 @@ LABEL org.opencontainers.image.title="usulnet" \
9393
org.opencontainers.image.vendor="usulnet" \
9494
org.opencontainers.image.licenses="AGPL-3.0"
9595

96-
# All runtime packages in a single layer (includes nvim editor deps)
97-
# Minimized apk cache by combining all installs
96+
# Runtime packages (includes nvim editor deps)
9897
RUN apk add --no-cache \
9998
ca-certificates tzdata curl su-exec util-linux \
10099
docker-cli docker-cli-compose \
101100
neovim git ripgrep fd \
102101
musl-locales musl-locales-lang && \
103-
# Install Trivy vulnerability scanner
104-
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin && \
105-
# Clean up curl caches
102+
update-ca-certificates
103+
104+
# Install Trivy vulnerability scanner (pinned version for reproducibility)
105+
ARG TRIVY_VERSION=0.69.1
106+
RUN curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v${TRIVY_VERSION} && \
106107
rm -rf /tmp/* /var/cache/apk/*
107108

108109
# Overwrite Alpine's docker-cli (27.x, API 1.47) with Docker 29.2.0 (API 1.53)

Makefile

Lines changed: 103 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: all build build-agent run test test-coverage test-check-coverage test-benchmark test-e2e clean dev-up dev-down migrate lint lint-fix fmt vet templ css install-hooks
1+
.PHONY: all build build-agent run test test-coverage test-check-coverage test-benchmark test-e2e clean dev-certs dev-up dev-down migrate lint lint-fix fmt vet templ css install-hooks help release-check release-snapshot verify-migrations security-scan docker-push
22

33
# Variables
44
BINARY_NAME=usulnet
@@ -76,7 +76,7 @@ test-coverage:
7676

7777
test-check-coverage:
7878
@echo "Running coverage threshold check..."
79-
@bash scripts/check-coverage.sh 40
79+
@bash scripts/check-coverage.sh 15
8080

8181
test-benchmark:
8282
@echo "Running benchmarks..."
@@ -92,11 +92,21 @@ clean:
9292
@rm -f coverage.out coverage.html
9393

9494
# Development environment
95-
dev-up:
95+
dev-certs: ## Generate TLS certificates for dev environment (PostgreSQL, HTTPS, NATS)
96+
@if [ ! -f dev-certs/ca.crt ]; then \
97+
echo "Generating dev TLS certificates..."; \
98+
$(GORUN) $(MAIN_PATH) pki init --data-dir ./dev-certs; \
99+
chmod 755 dev-certs; \
100+
chmod 644 dev-certs/*.crt; \
101+
else \
102+
echo "Dev certificates already exist (dev-certs/ca.crt)"; \
103+
fi
104+
105+
dev-up: dev-certs
96106
docker compose -f docker-compose.dev.yml up -d
97107
@echo "Waiting for services to be ready..."
98108
@sleep 5
99-
@echo "Development environment is ready"
109+
@echo "Development environment is ready (PostgreSQL TLS: verify-full)"
100110

101111
dev-down:
102112
docker compose -f docker-compose.dev.yml down
@@ -163,5 +173,93 @@ install-hooks:
163173
@echo "Pre-commit hook installed"
164174

165175
# Quality gate — run all quality checks
166-
quality: lint vet test-check-coverage
176+
quality: lint vet test test-check-coverage
167177
@echo "All quality checks passed!"
178+
179+
# Release engineering
180+
release-check:
181+
@echo "Checking release prerequisites..."
182+
@test -n "$$(git describe --exact-match --tags HEAD 2>/dev/null)" || (echo "ERROR: HEAD is not tagged. Tag with: git tag -a vX.Y.Z -m 'Release vX.Y.Z'" && exit 1)
183+
@test -z "$$(git status --porcelain)" || (echo "ERROR: Working tree is dirty. Commit or stash changes." && exit 1)
184+
@which goreleaser > /dev/null 2>&1 || (echo "ERROR: goreleaser not found. Install: go install github.com/goreleaser/goreleaser/v2@latest" && exit 1)
185+
@echo "All release prerequisites met."
186+
187+
release-snapshot:
188+
@echo "Building release snapshot (no publish)..."
189+
@which goreleaser > /dev/null 2>&1 || (echo "Installing goreleaser..." && go install github.com/goreleaser/goreleaser/v2@latest)
190+
goreleaser release --snapshot --clean
191+
192+
verify-migrations:
193+
@echo "Verifying migration integrity..."
194+
@bash scripts/verify-migrations.sh
195+
196+
security-scan:
197+
@echo "Running security scans..."
198+
@which govulncheck > /dev/null 2>&1 || (echo "Installing govulncheck..." && go install golang.org/x/vuln/cmd/govulncheck@latest)
199+
govulncheck ./...
200+
@if which golangci-lint > /dev/null 2>&1; then \
201+
echo "Running gosec via golangci-lint..."; \
202+
golangci-lint run --enable gosec ./...; \
203+
else \
204+
echo "SKIP: golangci-lint not installed"; \
205+
fi
206+
207+
docker-push:
208+
@echo "Pushing Docker images..."
209+
@test -n "$(DOCKER_REGISTRY)" || (echo "ERROR: DOCKER_REGISTRY not set" && exit 1)
210+
docker tag usulnet:latest $(DOCKER_REGISTRY)/usulnet:latest
211+
docker tag usulnet:latest $(DOCKER_REGISTRY)/usulnet:$(shell git describe --tags --always)
212+
docker push $(DOCKER_REGISTRY)/usulnet:latest
213+
docker push $(DOCKER_REGISTRY)/usulnet:$(shell git describe --tags --always)
214+
215+
# Help
216+
help:
217+
@echo "usulnet — Docker Management Platform"
218+
@echo ""
219+
@echo "Build:"
220+
@echo " make build Full build (templ + CSS + Go binary)"
221+
@echo " make build-agent Build agent binary only"
222+
@echo " make build-all Build both binaries"
223+
@echo " make frontend Generate templates + compile CSS"
224+
@echo ""
225+
@echo "Run:"
226+
@echo " make run Run the server (go run)"
227+
@echo " make dev-certs Generate TLS certificates for dev environment"
228+
@echo " make dev-up Start dev services (PostgreSQL, Redis, NATS) with TLS"
229+
@echo " make dev-down Stop dev services"
230+
@echo " make dev-up-agent Start dev services with agent profile"
231+
@echo ""
232+
@echo "Test:"
233+
@echo " make test Run tests with race detection and coverage"
234+
@echo " make test-coverage Generate HTML coverage report"
235+
@echo " make test-check-coverage Check coverage threshold"
236+
@echo " make test-benchmark Run benchmark tests"
237+
@echo " make test-e2e Run E2E tests (requires running services)"
238+
@echo ""
239+
@echo "Code Quality:"
240+
@echo " make lint Run golangci-lint"
241+
@echo " make lint-fix Run golangci-lint with auto-fix"
242+
@echo " make fmt Format Go source files"
243+
@echo " make vet Run go vet"
244+
@echo " make quality Full quality gate (lint + vet + test + coverage)"
245+
@echo " make security-scan Run govulncheck + gosec"
246+
@echo " make verify-migrations Check migration file integrity"
247+
@echo ""
248+
@echo "Database:"
249+
@echo " make migrate Run migrations up"
250+
@echo " make migrate-down Roll back migrations"
251+
@echo " make migrate-status Show migration status"
252+
@echo ""
253+
@echo "Docker:"
254+
@echo " make docker-build Build production Docker image"
255+
@echo " make docker-build-agent Build agent Docker image"
256+
@echo ""
257+
@echo "Release:"
258+
@echo " make release-check Verify release prerequisites (clean tree, tag, goreleaser)"
259+
@echo " make release-snapshot Build release locally without publishing"
260+
@echo " make docker-push Push Docker images (requires DOCKER_REGISTRY)"
261+
@echo ""
262+
@echo "Other:"
263+
@echo " make deps Download and tidy Go modules"
264+
@echo " make install-hooks Install git pre-commit hook"
265+
@echo " make clean Remove build artifacts"

0 commit comments

Comments
 (0)