Commit graph

19 commits

Author SHA1 Message Date
Snider
68ba956587 feat: add WithGzip response compression middleware
Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:20:46 +00:00
Snider
6521b90d26 feat: add WithTimeout per-request timeout middleware
Wraps gin-contrib/timeout to enforce per-request deadlines. When a
handler exceeds the configured duration, the client receives a 504
Gateway Timeout with the standard Fail("timeout", ...) error envelope.

Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:18:24 +00:00
Snider
0cce70082b fix: correct misleading IsDevelopment comments in WithSecure
Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 23:15:29 +00:00
Snider
f5ce02d661 feat: add WithSlog structured request logging middleware
Adds WithSlog(logger) option wrapping gin-contrib/slog for structured
request logging via Go's standard log/slog package. Logs method, path,
status code, latency, and client IP for every request. Falls back to
slog.Default() when nil is passed.

Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:14:15 +00:00
Snider
6bb7195cca feat: add WithSecure security headers middleware
Wraps gin-contrib/secure to set HSTS (1 year, includeSubdomains),
X-Frame-Options DENY, X-Content-Type-Options nosniff, and
Referrer-Policy strict-origin-when-cross-origin on all responses.

Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:10:52 +00:00
Snider
8f3e496173 test: add live Authentik integration tests
Validates go-api Authentik middleware against the production OIDC
provider at auth.lthn.io. Tests client_credentials token acquisition,
JWT validation via JWKS, forward-auth header extraction, RequireAuth/
RequireGroup enforcement, and permissive fail-open behaviour.

Gated behind AUTHENTIK_INTEGRATION=1 env var so normal CI is unaffected.
Also fixes README issuer URL to use auth.lthn.io.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 19:29:20 +00:00
Snider
0d424903e6 docs: add Authentik integration guide to CLAUDE.md and README
Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 16:45:26 +00:00
Snider
d279343491 feat(authentik): add RequireAuth and RequireGroup middleware
Add two route-level middleware helpers for enforcing authentication and
group membership. RequireAuth returns 401 when no user is in context.
RequireGroup returns 401 for unauthenticated requests and 403 when the
user lacks the specified group. Both use UK English error codes
("unauthorised", "forbidden") consistent with existing bearer auth.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 16:43:55 +00:00
Snider
5cba2f2cd4 feat(authentik): add OIDC JWT validation middleware
Add JWT validation as a second authentication block in the Authentik
middleware. Direct API clients can now send Authorization: Bearer <jwt>
tokens validated via OIDC discovery (coreos/go-oidc). Forward-auth
headers take priority; JWT is only attempted when no user was extracted
from headers. Validation is permissive — failures continue without a
user context. OIDC providers are cached per issuer to avoid repeated
discovery.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 16:42:23 +00:00
Snider
d760e77e49 feat(authentik): add header extraction middleware and WithAuthentik option
Add permissive forward-auth middleware that extracts user identity from
X-authentik-* headers when TrustedProxy is enabled. Headers are ignored
when TrustedProxy is false to prevent spoofing from untrusted sources.

- GetUser(c) helper retrieves AuthentikUser from Gin context
- authentikMiddleware splits groups/entitlements on pipe delimiter
- /health and /swagger bypass header extraction
- WithAuthentik option wires middleware into the Engine

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 16:38:13 +00:00
Snider
6cd3b7e7e0 feat(authentik): add AuthentikUser and AuthentikConfig types
Introduce core types for the Authentik forward-auth integration:
- AuthentikConfig with Issuer, ClientID, TrustedProxy, PublicPaths
- AuthentikUser with Username, Email, Name, UID, Groups, Entitlements, JWT
- HasGroup helper for group membership checks

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 16:36:38 +00:00
Snider
17ae94530d docs: add CLAUDE.md and README.md
Agent instructions and quick start guide with RouteGroup example.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 15:57:44 +00:00
Snider
095c38a8c4 feat: add Swagger UI endpoint with runtime spec serving
Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 15:56:29 +00:00
Snider
22f8a6915c feat: add WebSocket endpoint and channel listing from StreamGroups
Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 15:53:10 +00:00
Snider
d21734d8d9 feat: add bearer auth, request ID, and CORS middleware
Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 15:49:35 +00:00
Snider
db75c88d58 feat: add Engine with Register, Handler, Serve, and graceful shutdown
Engine manages route groups and builds a Gin-based HTTP handler.
New() accepts functional options (WithAddr). Handler() builds a fresh
Gin engine with Recovery middleware and /health endpoint. Serve()
starts the server and performs graceful shutdown on context cancellation.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 15:46:11 +00:00
Snider
6f5fb69944 feat: add RouteGroup and StreamGroup interfaces
RouteGroup declares Name, BasePath, and RegisterRoutes for subsystems
to mount their endpoints onto a Gin router group. StreamGroup optionally
declares WebSocket channel names. Gin v1.11.0 added as dependency.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 15:44:58 +00:00
Snider
7835837e38 feat: add response envelope with OK, Fail, Paginated helpers
Generic Response[T] envelope with Success, Data, Error, and Meta fields.
Includes OK, Fail, FailWithDetails, and Paginated constructor functions.
JSON marshalling correctly omits empty fields via omitempty tags.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 15:44:17 +00:00
Snider
889391a3a7 chore: scaffold go-api module
EUPL-1.2 licence, module path forge.lthn.ai/core/go-api.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 15:42:16 +00:00