go-modules

module
v0.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 21, 2026 License: MIT

README

go-modules

Shared platform library for Go services. Capability-based packages — not a layered application: each package is one platform concern with its contract and implementation together.

Package Concern
apperror Application error type mapped to HTTP statuses
authentication, authentication/iam, authentication/dummy Authentication: bearer token → identity
authorization Actor security context + scope/permission policy
clock, logger, random, validator Core contracts + implementations
config Layered JSON config loading with env overrides
echo Echo HTTP stack: error handler, server, middlewares, guards
event Domain events + in-process sync bus
nats NATS JetStream connection, routing, subscribers, DLQ
outbox Transactional outbox storage + NATS relay
pagination Cursor pagination types
persistence DB connector, migrator, unit of work
queue Work-queue contract + outbox-backed implementation
sentry Sentry init with shutdown flush
storage, storage/s3 File storage contract + S3 backend
testutil Test helpers

config, echo, nats, and sentry wrap a same-named third-party package (labstack echo, nats.go, sentry-go, config loading) that services also import in the same files. Where both appear in one file, alias the upstream import (labecho, natslib); the wrapper keeps the clean name.

Service architecture docs

docs/ holds the reference architecture for every data intensive service built on this library — shared so it lives in one place instead of being copied into each repo:

Each service keeps only its own docs/DOMAIN.md and docs/SERVICE.md (flows, endpoints, deviations).

Auth architecture

Authentication (authentication) answers who is calling; authorization (authorization) answers may they do this. They meet in authorization.Actor.

HTTP request with "Authorization: Bearer <token>"
    │
    ▼
echo.AuthMiddleware ───────────────── marks admin routes for role hydration,
    │                                 continues anonymously on bad tokens
    ▼
authentication.Authenticator[U].Authenticate    U = the service's user entity
    │
    ├─ iam driver (production):       validate JWT against JWKS (RS256,
    │                                 issuer, expiry; refetch rate-limited)
    │                                   ├─ service-account token → service Actor, no user
    │                                   └─ user token → UserResolver[U] (service-owned
    │                                      find-or-provision) → user Actor + *U
    │
    └─ dummy driver (tests/local):    token is base64 JSON Actor
    │
    ▼
Actor + user stored in request context
    │
    ▼
echo.RequireUser / RequireAdmin / RequireService   (route guards)
    │
    ▼
use case calls authorization.Authorizer.Authorize(actor, permissions...)
                                      (scope + permission policy: exact,
                                       admin-prefixed, or service wildcard)
What a service implements

Only its user resolver — everything else is shared:

// 1. The resolver: validated claims → the service's user entity.
type userResolver struct{ /* repo, clock, ... */ }

func (r *userResolver) Resolve(ctx context.Context, c *iam.Claims) (*myservice.User, error) {
    // find-or-provision; this is where per-service rules live
}

// 2. Wiring: one call.
authn, err := authentication.New(
    authentication.Config{Driver: cfg.Auth.Driver, IAM: iam.Config{
        Issuer: cfg.Auth.Issuer, JwksURL: cfg.Auth.JwksURL, ServiceName: "MyService",
    }},
    newUserResolver(...),
    repo.FindByID, // dummy-driver lookup
)

// 3. HTTP middleware: one struct.
echo.AuthMiddleware(echo.AuthConfig[myservice.User]{
    Authenticate:    authn.Authenticate,
    WithUser:        myservice.ContextWithUser,
    AdminPathPrefix: "/myservice/v1/admin",
})
Extending
  • Custom driver (API keys, another IdP): implement the one-method authentication.Authenticator[U] interface — or wrap a closure in authentication.Func[U] — and skip authentication.New. The middleware and guards only see the interface.
  • Function-only resolver: iam.UserResolverFunc[U] adapts a closure.
  • Test wiring: iam.WithHTTPClient injects an in-process round-tripper; iam.WithJWKSCooldown tunes (or disables) the JWKS refetch rate limit.
  • Permissions: fully qualified "<service>:<resource>.<action>" (e.g. "assets:assets.write"). The shared TokenAuthorizer matches the exact form, the admin:-prefixed form, and service wildcards (assets:*, admin:assets:*).

Consumption pattern

Services keep thin facade packages re-exporting shared contracts via type aliases (internal/domain/common, internal/application/port, …) so domain and application code never imports go-modules directly, plus one bootstrap/modules.go mapping service config to the narrow shared config types (logger.Config, nats.Config, persistence/config.Config, …).

Until the GitHub repo exists, services use replace github.com/tupicapp/go-modules => ../go-modules.

License

Released under the MIT License.

Directories

Path Synopsis
concrete
app
Package app provides shared application lifecycle logic and bootstrap helpers.
Package app provides shared application lifecycle logic and bootstrap helpers.
config
Package config loads layered JSON configuration files with environment variable overrides into a service-defined config struct.
Package config loads layered JSON configuration files with environment variable overrides into a service-defined config struct.
echo
Package echo provides the shared Echo HTTP stack: instance assembly, apperror-aware error handling, request logging, Sentry integration, the HTTP server lifecycle, and actor guard middlewares.
Package echo provides the shared Echo HTTP stack: instance assembly, apperror-aware error handling, request logging, Sentry integration, the HTTP server lifecycle, and actor guard middlewares.
iam
Package iam authenticates requests using IAM (Keycloak) service JWTs.
Package iam authenticates requests using IAM (Keycloak) service JWTs.
messaging_router
Package messaging_router provides the default in-memory subject→handler router implementing messaging.MessageHandlerRegisterer.
Package messaging_router provides the default in-memory subject→handler router implementing messaging.MessageHandlerRegisterer.
nats
Package nats provides the NATS JetStream connection, subject routing, and event/queue subscribers shared by all Tupic services.
Package nats provides the NATS JetStream connection, subject routing, and event/queue subscribers shared by all Tupic services.
objectstorage_router
Package objectstorage_router provides the default in-memory event router implementing objectstorage.EventHandlerRegisterer; "<Category>:*" matches every subtype within the category, with exact matches taking precedence.
Package objectstorage_router provides the default in-memory event router implementing objectstorage.EventHandlerRegisterer; "<Category>:*" matches every subtype within the category, with exact matches taking precedence.
outbox_queue
Package outbox_queue implements the queue.Queue contract on top of the outbox: each task is stored as an integration event whose subject carries the channel, so the relay ships it to the work-queue stream.
Package outbox_queue implements the queue.Queue contract on top of the outbox: each task is stored as an integration event whose subject carries the channel, so the relay ships it to the work-queue stream.
persistence
Package persistence wires the database connector, migrator, and unit of work shared by all platform services.
Package persistence wires the database connector, migrator, and unit of work shared by all platform services.
persistence/config
Package config holds the persistence configuration types in a leaf package so the connector and migrator can import them without cycles.
Package config holds the persistence configuration types in a leaf package so the connector and migrator can import them without cycles.
persistence/connector
Package connector opens and supervises the SQL connection pool and its GORM handle.
Package connector opens and supervises the SQL connection pool and its GORM handle.
persistence/migrator
Package migrator selects the migration driver from configuration.
Package migrator selects the migration driver from configuration.
persistence/migrator/contract
Package contract defines the migration driver contract.
Package contract defines the migration driver contract.
persistence/migrator/postgres
Package postgres implements the migration contract with golang-migrate.
Package postgres implements the migration contract with golang-migrate.
persistence/uow
Package uow provides the GORM implementation of the UnitOfWork contract, plus the context plumbing repositories use to join an ambient transaction.
Package uow provides the GORM implementation of the UnitOfWork contract, plus the context plumbing repositories use to join an ambient transaction.
random
Package random provides a crypto/rand-backed implementation of the random.Random contract.
Package random provides a crypto/rand-backed implementation of the random.Random contract.
s3
Package s3 implements the storage contract with AWS S3 (or a compatible API such as LocalStack/MinIO).
Package s3 implements the storage contract with AWS S3 (or a compatible API such as LocalStack/MinIO).
sentry
Package sentry initializes the Sentry SDK with a shutdown flush hook.
Package sentry initializes the Sentry SDK with a shutdown flush hook.
sqs
Package sqs is the SQS adapter for object-storage events: it polls an SQS queue fed by S3 bucket notifications, parses each message into an objectstorage.Event, and dispatches it through an objectstorage.Router.
Package sqs is the SQS adapter for object-storage events: it polls an SQS queue fed by S3 bucket notifications, parses each message into an objectstorage.Event, and dispatches it through an objectstorage.Router.
zap
contract
clock
Package clock provides the Clock contract to provide time with testability.
Package clock provides the Clock contract to provide time with testability.
event
Package event defines the domain-event contract and the in-process synchronous event bus shared by all platform services.
Package event defines the domain-event contract and the in-process synchronous event bus shared by all platform services.
logger
Package logger provides the Logger contract.
Package logger provides the Logger contract.
messaging
Package messaging defines the transport-agnostic inbound message contract and router shared by subscription adapters (NATS, SQS, …).
Package messaging defines the transport-agnostic inbound message contract and router shared by subscription adapters (NATS, SQS, …).
objectstorage
Package objectstorage defines the transport-agnostic object-storage event contract shared by storage-event adapters (SQS, SNS, EventBridge, …).
Package objectstorage defines the transport-agnostic object-storage event contract shared by storage-event adapters (SQS, SNS, EventBridge, …).
outbox
Package outbox implements the Transactional Outbox pattern: events are stored in the caller's DB transaction and a relay ships them to NATS asynchronously.
Package outbox implements the Transactional Outbox pattern: events are stored in the caller's DB transaction and a relay ships them to NATS asynchronously.
persistence
Package uow provides the UnitOfWork contract.
Package uow provides the UnitOfWork contract.
queue
Package queue defines the task queue contract.
Package queue defines the task queue contract.
random
Package random defines the contract for generating random values.
Package random defines the contract for generating random values.
storage
Package storage defines the platform file-storage contract.
Package storage defines the platform file-storage contract.
validator
Package validator defines the Validator contract.
Package validator defines the Validator contract.
worker
Package worker defines the port a service's interface layer uses to declare named worker subscriptions.
Package worker defines the port a service's interface layer uses to declare named worker subscriptions.
shared
apperror
Package apperror defines the platform-wide application error type used to map domain and application failures to transport-level responses.
Package apperror defines the platform-wide application error type used to map domain and application failures to transport-level responses.
pagination
Package pagination defines shared cursor-pagination types.
Package pagination defines shared cursor-pagination types.
testkit
authenticationtest
Package authenticationtest provides a test-double authenticator that skips real IAM: it decodes the actor from the bearer token and resolves the user through a caller-supplied lookup, so the double carries no persistence dependency.
Package authenticationtest provides a test-double authenticator that skips real IAM: it decodes the actor from the bearer token and resolves the user through a caller-supplied lookup, so the double carries no persistence dependency.
migratortest
Package migratortest provides recording test doubles for the migrator contract.
Package migratortest provides recording test doubles for the migrator contract.
Package utility provides general-purpose helper functions shared across Tupic services.
Package utility provides general-purpose helper functions shared across Tupic services.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL