Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ linters:
- gocritic
- revive
path: examples/.*
- linters:
- staticcheck
text: "SA1019:.*(PublicKey)\\.(X|Y)"
paths:
- third_party$
- builtin$
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.2] - 2026-10-01

### Added
- **`async`**: Concurrency orchestration package with panic-safe `Go`, context-aware `GoCtx`, fan-out `Parallel` with first-error cancellation, and bounded `ParallelLimit` using semaphores for worker quota protection.
- **`fsm`**: Declarative in-memory Finite State Machine with $O(1)$ compiled transition table lookups, `CanTransition`, and structured `ValidateTransition` errors.
- **`uuidutil`**: Centralized RFC 4122 UUID manipulation helpers (`New`, `NewString`, `ParsePtr`, `MustParse`, `IsValid`, `IsNil`).
- **`pagination`**: Added `PaginateSlice[T any]` and `PageMeta` in `slice.go` for bounds-safe generic slice slicing preventing out-of-bounds slice indexing.
- **`jwks`**: Thread-safe in-memory cached ECDSA P-256 JWKS public key resolver with 2-hour TTL and network-interruption stale fallback.
- **`ginmw`**:
- `RequireTenant` middleware with flexible source extraction (Gin context, claims, `x-tenant-id` header, or query parameters) and role-based bypass (`WithBypassRoles`).
- Standardized JSON response helpers (`RespondSuccess`, `RespondCreated`, `RespondError`, `RespondErrorWithDetail`) implementing JSend-compatible `Envelope[T any]`.
- Lock-free, low-latency RED metrics middleware (`REDMetrics`) and Prometheus text/JSON `/metrics` endpoint handler (`MetricsEndpoint`).

## [0.3.1] - 2026-09-24

### Security & Hardening
Expand Down
35 changes: 24 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# go-libs · latest published v0.3.1
# go-libs · latest published v0.3.2

Production Go microservices frequently reimplement identical operational plumbing—circuit breakers, rate limiters, singleflight caching, worker pools, structured error hierarchies, and graceful shutdown—leading to inconsistent behavior and dependency sprawl across services. `go-libs` provides a unified suite of 31 packages and Gin middleware with verified statement coverage under a single module BOM. Each package is independently importable with zero business domain logic, delivering hardened operational primitives without framework lock-in.
Production Go microservices frequently reimplement identical operational plumbing—circuit breakers, rate limiters, singleflight caching, worker pools, structured error hierarchies, and graceful shutdown—leading to inconsistent behavior and dependency sprawl across services. `go-libs` provides a unified suite of 35 packages and Gin middleware with verified statement coverage under a single module BOM. Each package is independently importable with zero business domain logic, delivering hardened operational primitives without framework lock-in.

[![Go Reference](https://pkg.go.dev/badge/github.com/umesh0492/go-libs.svg)](https://pkg.go.dev/github.com/umesh0492/go-libs)
[![Code Quality: golangci-lint](https://img.shields.io/badge/code%20quality-golangci--lint-brightgreen?logo=go)](https://golangci-lint.run/)
Expand All @@ -14,7 +14,7 @@ Shared, zero-business-logic Go libraries and middleware for cloud-native microse
> 📖 **Engineering Documentation & Architecture Blueprint**
> Complete subsystem guides, module selection flowcharts, architectural rationales, and execution topologies:
> - 🏛️ **[System Architecture & Blueprint](docs/ARCHITECTURE.md)** (Topology, Layering Boundaries, Middleware Order)
> - 📜 **[Changelog & Release Record](CHANGELOG.md)** (latest published v0.3.1 release ledger, API errata, and evolution)
> - 📜 **[Changelog & Release Record](CHANGELOG.md)** (latest published v0.3.2 release ledger, API errata, and evolution)
> - 🏷️ **[Versioning & Stability Matrix](docs/VERSIONING.md)** (Semantic versioning contracts and package tiers)
> - ⚡ **[Performance Benchmarks](BENCHMARKS.md)**
> - 📝 **[Decisions & Architecture Records](docs/adr/0001-domain-decoupling-and-audit-sink.md)**
Expand All @@ -26,7 +26,7 @@ Each package is independently importable, fully tested with verified statement c
This repository uses a **Single Module Monorepo** pattern. There is only *one* `go.mod` file at the root of `go-libs`.

**Why is this the best "BOM" (Bill of Materials) way?**
By having a single `github.com/umesh0492/go-libs@v0.3.1` import, you guarantee that all internal packages (`db`, `recovery`, `ratelimit`, `cache`, `workerpool`, `metrics`, `retry`, `telemetry`) are perfectly synced to the same tested release threshold across all your microservices. It prevents version drifting between interconnected middleware packages natively.
By having a single `github.com/umesh0492/go-libs@v0.3.2` import, you guarantee that all internal packages (`db`, `recovery`, `ratelimit`, `cache`, `workerpool`, `metrics`, `retry`, `telemetry`) are perfectly synced to the same tested release threshold across all your microservices. It prevents version drifting between interconnected middleware packages natively.

### Minimal-Footprint Imports

Expand Down Expand Up @@ -56,7 +56,7 @@ func main() {
EOF

# 3. Resolve dependencies
go get github.com/umesh0492/go-libs@v0.3.1
go get github.com/umesh0492/go-libs@v0.3.2
go mod tidy

# 4. Prove no heavy frameworks exist in go.sum (exits 0 with zero output if clean)
Expand All @@ -70,7 +70,7 @@ grep -E 'gin-gonic|jackc/pgx|opentelemetry' go.sum || echo "VERIFIED: Zero heavy
## Installation

```bash
go get github.com/umesh0492/go-libs@v0.3.1
go get github.com/umesh0492/go-libs@v0.3.2
```

Requirements:
Expand Down Expand Up @@ -257,6 +257,8 @@ helm upgrade --install microservice ./deploy/helm/microservice
| `workerpool` | `/workerpool` | `New(workers, queueSize, opts...)`, `Submit(task) error`, `SubmitContext(ctx, task) error`, `WithMetrics`, `WithPanicHandler` |
| `cache` | `/cache` | `NewTypedCache[T](opts...)`, `GetOrFetch`, `WithMetrics`, `WithEvictionInterval` — generic singleflight stampede-protected cache |
| `shutdown` | `/shutdown` | `New(timeout)`, `.Register(name, fn)`, `.Execute(ctx)`, `.Wait()` — concurrent graceful teardown manager |
| `async` | `/async` | `Go`, `GoCtx`, `Parallel`, `ParallelLimit` — panic-safe goroutines and bounded concurrency orchestration |
| `fsm` | `/fsm` | `NewMachine`, `ValidateTransition`, `CanTransition` — declarative in-memory finite state machine with O(1) transitions |

---

Expand All @@ -272,6 +274,7 @@ helm upgrade --install microservice ./deploy/helm/microservice
| `stringutil` | `/stringutil` | `OrDefault`, `MaskEmail`, `MaskPhone`, `TrimAndLower`, `Truncate`, `RandomStringFromReader` — safe string operations |
| `timeutil` | `/timeutil` | `NowIn(loc)`, `FormatIn`, `StartOfDay`, `EndOfDay`, `AddBusinessDays` — parametric time helpers |
| `cryptoutil` | `/cryptoutil` | `GenerateTempPassword(n)`, `HashPassword(pwd)`, `ComparePassword(hash, pwd)` — secure credential helpers backed by `crypto/rand` (CSPRNG) and `golang.org/x/crypto/bcrypt` (OWASP cost factor 12) |
| `uuidutil` | `/uuidutil` | `New`, `NewString`, `Parse`, `ParsePtr`, `MustParse`, `IsValid`, `IsNil` — centralized RFC 4122 UUID operations |

---

Expand All @@ -288,7 +291,7 @@ Compatible with standard library `http.Handler`, Chi, Echo, or any Go HTTP frame
| `requestid` | `/requestid` | `Middleware`, `FromContext(ctx)`, `Header` constant — W3C correlation ID propagation |
| `recovery` | `/recovery` | `Middleware(opts...)` — JSON panic recovery with structured `slog` output |
| `httputil` | `/httputil` | `OK`, `Created`, `NoContent`, `Error`, `ErrorFromDomain`, `ValidationError` — standardized responses |
| `pagination` | `/pagination` | `Parse(r)`, `NewResponse`, `NewTypedResponse[T]` — generic query parsing and response formatting |
| `pagination` | `/pagination` | `Parse(r)`, `NewResponse`, `NewTypedResponse[T]`, `PaginateSlice[T]` — query parsing, response formatting, and generic slice pagination |
| `health` | `/health` | `New(checks...)`, `LivenessHandler`, `ReadinessHandler`, `.Handler` — parallel HTTP probe service |
| `idempotency` | `/idempotency` | `NewMemoryStore()`, `NewPGStore(db.DBTX, opts...)`, `Store` — two-phase request deduplication with in-memory or PostgreSQL storage |
| `validation` | `/validation` | `FormatErrors(err)` — human-readable validator/v10 struct validation error formatting |
Expand All @@ -303,6 +306,7 @@ Compatible with standard library `http.Handler`, Chi, Echo, or any Go HTTP frame
| `rbac` | `/rbac` | `NewEngine()`, `Engine.Match(pattern, action)` — role-based access control engine |
| `rbaccontext` | `/rbaccontext` | `WithPermissions(ctx, perms)`, `Can(ctx, perm)`, `CanAny(ctx, perms...)` — permission helpers |
| `telemetry` | `/telemetry` | `NewTracerProvider(opts...)`, `InitProvider(tp)`, `StartSpan(ctx, tracer, span)` — OpenTelemetry distributed tracing |
| `jwks` | `/jwks` | `GetECPublicKey`, `NewResolver` — thread-safe cached ECDSA P-256 JWKS public key resolver with stale fallback |

> [!NOTE]
> **Domain & Application Accelerators**:
Expand All @@ -316,7 +320,7 @@ All Gin-specific middleware wrappers live in `ginmw` for uniform imports.

| Package | Import suffix | Key exports & Description |
|---|---|---|
| `ginmw` | `/ginmw` | `AuthMiddleware`, `GenerateToken`, `GetClaims`, `RateLimit`, `Recovery`, `RequestID`, `SecurityHeaders`, `Idempotency`, `Logger` — unified Gin web framework middleware suite |
| `ginmw` | `/ginmw` | `AuthMiddleware`, `GenerateToken`, `GetClaims`, `RateLimit`, `Recovery`, `RequestID`, `SecurityHeaders`, `Idempotency`, `Logger`, `RequireTenant`, `RespondSuccess`, `RespondError`, `REDMetrics` — unified Gin web framework middleware suite |

| Function | Purpose |
|---|---|
Expand All @@ -337,12 +341,17 @@ All Gin-specific middleware wrappers live in `ginmw` for uniform imports.
| `ginmw.Logger()` | Structured access log (method, path, status, latency) |
| `ginmw.Telemetry(service)` | OpenTelemetry W3C trace context extraction and span lifecycle |
| `ginmw.Idempotency(store)` | Two-phase HTTP request deduplication and response caching |
| `ginmw.RequireTenant(opts...)` | Enforces tenant presence from context, claims, or headers with optional role bypass |
| `ginmw.RespondSuccess(c, data)` | Unified JSend-compatible 200 JSON response envelope |
| `ginmw.RespondError(c, status, code, msg)` | Unified JSend-compatible structured error response envelope |
| `ginmw.REDMetrics()` | Thread-safe lock-free Rate, Errors, Duration metrics middleware |
| `ginmw.MetricsEndpoint()` | Prometheus text/JSON `/metrics` exposition handler |

---

## 📊 Verified Statement Coverage Status

Coverage across all 31 packages in `go-libs` is measured using Go's official statement-level coverage tool (`go test -short -coverprofile=coverage.out ./...`):
Coverage across all 35 packages in `go-libs` is measured using Go's official statement-level coverage tool (`go test -short -coverprofile=coverage.out ./...`):

> **Overall Repository Statement Coverage: 96.0%** (Zero data races across `-race`)
> **Core Middleware Gate (`ginmw`): 100.0%**
Expand All @@ -351,22 +360,25 @@ Coverage across all 31 packages in `go-libs` is measured using Go's official sta
| Package | Purpose | Statement Coverage |
|---|---|---|
| `apperror` | Canonical structured application error codes and helpers | **100.0%** |
| `async` | Panic-safe goroutines and bounded concurrency orchestration | **95.7%** |
| `bodylimit` | Gin middleware to cap HTTP request body sizes | **100.0%** |
| `cache` | Generic singleflight stampede-protected multi-policy cache (SampledLRU, LRU, LFU, FIFO, TTL) | **87.5%** |
| `circuitbreaker` | Outbound resilience 3-state machine (Consecutive & Failure Ratio algorithms) | **93.3%** |
| `clock` | Deterministic mockable time abstraction with RealClock and advanceable FakeClock | **95.2%** |
| `cryptoutil` | Secure password hashing (`golang.org/x/crypto/bcrypt`) and CSPRNG password generation (`crypto/rand`) | **100.0%** |
| `db` | Database Pool & Querier | **100.0%** |
| `env` | Zero-dependency typed environment variable parsers | **100.0%** |
| `fsm` | Declarative in-memory finite state machine with O(1) state transitions | **100.0%** |
| `ginmw` | Unified Gin HTTP middleware chain & helper | **100.0%** |
| `health` | Parallel dependency health check and Kubernetes probe handler | **100.0%** |
| `httpclient` | Resilient composed HTTP client (RateLimit -> CircuitBreaker -> Retry -> Timeout -> Transport) | **92.9%** |
| `httputil` | Standardized JSON response and error handlers | **100.0%** |
| `idempotency` | Two-phase HTTP request deduplication | **98.8%** |
| `jwks` | Thread-safe cached ECDSA P-256 JWKS public key resolver | **89.7%** |
| `logger` | Request-context aware structured logging with `slog`, sampling, and sensitive data redaction | **96.0%** |
| `maputil` | Generic type-safe map operations | **100.0%** |
| `metrics` | Framework-agnostic Counter, Gauge, Histogram interfaces | *N/A (Pure Interfaces)* |
| `pagination` | Offset-based request query parser and generic response | **100.0%** |
| `pagination` | Offset-based request query parser and generic slice pagination | **97.6%** |
| `ratelimit` | IP rate limiters (TokenBucket, SlidingWindow) with CIDR proxy parsing | **100.0%** |
| `rbac` | Role-Based Access Control logic engine | **100.0%** |
| `rbaccontext` | Context-based permission lookup helpers | **100.0%** |
Expand All @@ -379,6 +391,7 @@ Coverage across all 31 packages in `go-libs` is measured using Go's official sta
| `stringutil` | Sensitive info masking and text helpers | **100.0%** |
| `telemetry` | OpenTelemetry distributed tracing wrapper | **100.0%** |
| `timeutil` | Parametric time arithmetic, RFC parsing, business days, and timezone utilities | **100.0%** |
| `uuidutil` | Centralized RFC 4122 UUID operations and validation | **92.3%** |
| `validation` | Declarative validation error formatter | **100.0%** |
| `workerpool` | Bounded panic-safe concurrent worker pool with metrics & options | **100.0%** |
| **Total Statement Coverage** | **Cumulative across all packages** | **96.0%** |
Expand Down Expand Up @@ -437,7 +450,7 @@ Please see [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines, [SECU

### 📦 Repository Provenance & Release Record

`go-libs` is available from the Go module proxy at the latest verified published version, `v0.3.1`. The current `origin/main` checkout is a separate baseline history; see [Release Baseline](docs/RELEASE_BASELINE.md) before selecting a release or publishing a reconciliation. For the complete version-by-version delivery record and historical commit errata, see **[CHANGELOG.md](CHANGELOG.md)**. Full semantic versioning contracts and package stability tiers are detailed in **[docs/VERSIONING.md](docs/VERSIONING.md)**.
`go-libs` is available from the Go module proxy at the latest verified published version, `v0.3.2`. The current `origin/main` checkout is a separate baseline history; see [Release Baseline](docs/RELEASE_BASELINE.md) before selecting a release or publishing a reconciliation. For the complete version-by-version delivery record and historical commit errata, see **[CHANGELOG.md](CHANGELOG.md)**. Full semantic versioning contracts and package stability tiers are detailed in **[docs/VERSIONING.md](docs/VERSIONING.md)**.

---

Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Supported Versions

`go-libs` provides security updates for the current release series (currently v0.3.1):
`go-libs` provides security updates for the current release series (currently v0.3.2):

| Version Series | Status | Security Updates |
| -------------- | ------------------ | ---------------- |
Expand Down
28 changes: 28 additions & 0 deletions async/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# async

Package `async` provides panic-safe concurrency primitives, asynchronous goroutine runners, and bounded parallel task executors with context cancellation.

## Features

- **`Go` and `GoCtx`**: Fire-and-forget goroutines with automatic panic recovery and structured stack trace logging.
- **`Parallel`**: Unbounded fan-out concurrency with context cancellation, first-error capture, and panic isolation.
- **`ParallelLimit`**: Bounded semaphore concurrency control to safeguard database connection pools and external API rate limits during bulk execution.

## Usage

```go
import "github.com/umesh0492/go-libs/async"

// Fan-out concurrent queries
err := async.Parallel(ctx,
func(c context.Context) error {
return fetchUsers(c)
},
func(c context.Context) error {
return fetchSettings(c)
},
)

// Bounded worker batch execution
err := async.ParallelLimit(ctx, 5, tasks...)
```
41 changes: 41 additions & 0 deletions async/async.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: MIT

package async

import (
"context"
"log/slog"
"runtime/debug"
)

// Go executes the given function in a new goroutine, recovering from any panics
// and logging the panic details with stack trace.
func Go(fn func()) {
go func() {
defer func() {
if r := recover(); r != nil {
slog.Error("async goroutine panic recovered",
"panic", r,
"stack", string(debug.Stack()),
)
}
}()
fn()
}()
}

// GoCtx executes the given function in a new goroutine passing the provided context,
// recovering from any panics and logging the panic details with stack trace.
func GoCtx(ctx context.Context, fn func(ctx context.Context)) {
go func() {
defer func() {
if r := recover(); r != nil {
slog.Error("async goroutine panic recovered",
"panic", r,
"stack", string(debug.Stack()),
)
}
}()
fn(ctx)
}()
}
5 changes: 5 additions & 0 deletions async/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// SPDX-License-Identifier: MIT

// Package async provides panic-safe concurrency primitives, asynchronous goroutine
// runners, and bounded parallel task executors with context cancellation.
package async
Loading
Loading