warren

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

README

Warren

A DDD-first application framework and CLI for Go backends.

⚠️ Pre-release, v0.1 in progress. Most of the framework is importable and works today — use cases, errors, domain, config, DI, lifecycle, the module system, boot step 5, the consumer chain, the transactional outbox, the persistence and transport ports, health, validation, the CLI, and transport/http, which serves a real HTTP service over net/http.ServeMux and adds nothing to your go.mod but itself, and persistence/postgres, whose unit of work commits aggregate state and the outbox rows for that aggregate's events in one transaction. What is not in v0.1: openapi, auth (the JWT/OIDC verifier — the identity type and the policies ship in app), transport/grpc, broker/rabbitmq, broker/nats, and the Mongo/Redis/MySQL drivers — each deferred to v0.2 with the reason recorded in its own spec, not left as an open question. The short version: openapi's architecture is now ruled and its spec approved — it is a pure add-on over a route table frozen in v0.1, so go get gets it in v0.2 with no migration — auth needs two dependency audits that have not been run, and a third broker driver answers nothing that broker/memory plus the shared contract suite does not. Two planned modules are not on that list at all any more. resilience was dropped — retry and timeout are core-ring and ship, while a breaker guards an outbound call Warren does not make. jobs was dropped too: a scheduler is an ordinary lifecycle.Hook, which starts after its dependencies and is joined before them by construction, and outbox.Elector already gives leader-only — by NAME. One Elector is one advisory lock, so a field test that wired a scheduler and the outbox relay to the same one starved whichever of them lost the race, silently, for the life of the process. A scheduler mints its own instead: el, err := electors.Elector("ticket/sla-sweeper"). Different names lead at the same time; the relay's own name is reserved, so asking for it fails the boot rather than competing. The repository is being rebuilt spec-first: every package gets an approved SPEC.md before its first line of Go, retired once the package is implemented and reviewed. warren.md is the design; AGENT.md is the rules.

New here? Start with GETTING_STARTED.md — a complete service, from nothing to a running HTTP API, in one page.


What Warren is

Four claims define it — everything in this repository exists to protect one of them:

  1. Transport-agnostic use cases. One app.Handler[Req, Res]; HTTP, gRPC, and message consumers are thin adapters over it. A handler imports no transport and no driver — no net/http, no pgx, no kgo. That is the entire point. Two rules with two different remedies — move the routing to the controller; declare the port in the domain — and warren lint arch checks both, directly and through a helper package.
  2. Real module encapsulation. A provider is private to its module unless exported, and imports are explicit — not one global container where everything sees everything.
  3. DDD as real types, not folder naming conventions — aggregates, events, and the transactional outbox as compiler-checked constructs.
  4. Architecture enforced in CI. warren lint arch fails the build when domain/ imports infrastructure/ — for your project and for Warren's own repository, same command.

Warren is not a web framework, an ORM, or a deployment platform. It composes existing routers and drivers behind stable ports, and its dependency budget is defensible: the kernel is standard library + dig, permanently.

TOOLING     warren/cli — templates · AST editor · analyzer     build-time only
ADAPTERS    transport/http · transport/grpc · broker/kafka     separate modules,
            persistence/postgres · observability · …           never import each other
CONTRACTS   app.Handler · broker.Publisher · Registrar · …     ports & shared types
KERNEL      warren · di · lifecycle · config · log · errors    stdlib + dig only

One handler serves three protocols. Every error the framework can detect surfaces at boot — never on request 1.

Swapping a driver is one line of platform, not of main.go, and how many other lines depends on the driver's shape: a driver whose ports platform can re-export (the in-process broker) is invisible to every feature module, while one that must be its own module (platform.Broker() for Kafka, platform.Postgres()) is imported by each feature that consumes it — because a module may export only what its own providers return. This line used to claim main.go and one edit; a field test diffed two scaffolds and found N+1 files, none of them main.go.


Install

go install github.com/MerseniBilel/warren/cli/cmd/warren@latest
warren new myapp --module github.com/you/myapp
cd myapp && go mod tidy && go run ./cmd/myapp

That is the whole setup. The generated go.mod requires the published framework — core plus transport/http, and persistence/postgres or broker/kafka when you ask for them — so go mod tidy resolves it from the module proxy and there is no replace anywhere. It serves POST /users, /healthz and /readyz on :8080.

To use the framework without the CLI, go get github.com/MerseniBilel/warren and its adapters directly; GETTING_STARTED.md writes a service by hand that way, one file at a time.

Working on Warren itself is the one case that needs more. Build the CLI from your checkout and scaffold against it, so a change to the framework is exercised by a real service before it is tagged:

cd cli && go build -o ~/.local/bin/warren ./cmd/warren
warren new myapp --module github.com/you/myapp --framework /path/to/warren

--framework writes replace directives into the new project's go.mod, pinning it to your filesystem. That is why it is not the default, and it is not a committed replace in this repository either (invariant 8).


Status & roadmap

Progress is spec-first: ☑ means done and verified, not started.

Phase 0 — foundation
  • Package manifest written (warren.md) and repository reset to it
  • Rules rewritten (AGENT.md, CLAUDE.md)
  • All 32 packages scaffolded with a SPEC.md each
  • Every spec audited against the manifest — no invented API survived
  • Design contradictions found and catalogued (25 specs blocked on them)
  • Core decisions taken: config Source split, auth-code DLQ rows, Root[K] constraint, concrete registrars on Go 1.27
  • Remaining decisions folded into their specs and re-approved (every spec decided 2026-08-02: 12 approved and implemented, 10 deferred to v0.2 with the reason recorded in each, zero drafts left)
  • Tooling rebuilt: Makefile, CI workflow, golangci config, module-rules check (scripts/invariants.sh)
  • Dependency audits run (dig first) — no library enters a go.mod without one (dated audits in the warren.md §9 ledger: dig v1.19.0, cobra v1.10.2, franz-go v1.21.5, playground v10.30.3, and the rejections — dave/dst, robfig/cron, x/tools — with their reasons)
Phase 1 — kernel (buildable on Go 1.26, in dependency order)

All seven implemented packages were adversarially reviewed on 2026-08-01 (31 reproduced findings across two review rounds, all fixed with regression tests) and their specs retired — the code, tests, golden files, and warren.md entries are the contract now.

  • errors — the semantic vocabulary; load-bearing for everything (implemented; spec retired)
  • domainEntity, Root[K], AggregateRoot, Event; the §3.1 example compiles as a test (implemented; spec retired)
  • log — context-carried logger, Vendor mode, exported seeding surface (implemented; spec retired)
  • di — the container wrap; the golden diagnostic reproduces byte for byte; dig v1.19.0 audited (implemented; spec retired)
  • lifecycle — ordered start/stop, Ready() readiness gate (implemented; spec retired)
  • config (core) — Source-split loading: Load, Source, env, flags (implemented; spec retired — Module[T] lands with the root package)
  • config/yaml — the first file Source (v0.2; needs its own spec + YAML library audit before the module exists)
  • validate/playground — the full tag vocabulary (email, min, oneof, …) as its own module, with every tag checked AT BOOT so a typo is a diagnostic rather than a production panic (implemented. Core refuses those tags by design and its diagnostic told users to install this — a promise in shipped runtime output that CI was asserting on)
  • warren (root) — module system, boot sequence, run loop (implemented with config.Module[T]; adversarially reviewed — 8 findings fixed — spec retired)
  • app core — Handler/HandlerFunc/Middleware/Chain (implemented; a five-middleware chain adds 0 allocs; §10 handler compiles verbatim)
  • app built-in middleware — Retrying/Traced/Metered/Authorized (implemented over the app-owned ports: RetryPolicy, AuthorizationPolicy, context-carried Telemetry)
  • app.Transactional — over the one-method app.UnitOfWork port (implemented; the app spec is retired)
  • broker port + consumer chain — envelope, Pipeline (Recover/Drain/ TraceExtract/Deduplicate/DeadLetter/Retry/ConcurrencyLimit), options (implemented; §2.6 disposition table one test per code)
  • inbox — dedupe-store port + stdlib memory store (implemented)
Phase 2 — transport
  • transport (port) — sealed Registrar, generic free functions, route table of pre-built closures (implemented on Go 1.26 — the "Fix A" shape; the 1.27 method form is a mechanical call-site rewrite)
  • Bump toolchain to Go 1.27; verify generic methods compile as designed (and that inference works — explicit type arguments are needed today)
  • warren g repository --driver postgres — plain SQL over postgres.DB carrying the three rules no compiler enforces, plus the table's migration and a cmd/migrate binary (CI compiles the generated repository; the migrate path was run against a real Postgres)
  • warren new scaffolds a service that serves: a controller registering POST /users, whttp.Server wired in main.go, health probes, and log.Handler installed so every record carries the correlation ID (the scaffold's own compile test builds and runs it)
  • transport/http — the HTTP error column, health probes, the edge ring, drain-before-stop (implemented on net/http.ServeMux, not chi: the sealed Registrar already discards everything a router is bought for, and chi measured worst of five candidates on this project's own first priority. Zero third-party dependencies; 17 allocations per request, asserted by a test)
  • transport/grpcdeferred to v0.2, and the reasons are decided rather than open: a handler's Req must stay a plain Go struct or the HTTP adapter mis-encodes the same handler, so the wire needs generated proto messages and a generated shim between them — which needs warren g proto, the harder of the two artifacts. A proto codec over plain structs was prototyped, measured (faster than JSON) and rejected: no reflection descriptor, and field numbers in Go struct tags. The round found zero required changes to core transport
  • Fallback if 1.27 slips: generic free functions (compiles on 1.26; call sites change shape) (this is not a contingency any more — it is what SHIPPED. transport.Get[Req, Res](r, pattern, h) is a generic free function running on 1.26 today, and warren.md §3.5 fixes the names and argument order the 1.27 methods will take, so the bump above is a refactor of call sites rather than of the design)
Phase 3 — messaging
  • Outbox/inbox ownership decisions (writer split, leader election, module map) (Store.Append is the writer and runs in the caller's transaction; leadership is outbox.Elector plus outbox.Electors for named ones; outbox and inbox are OPTIONS on the persistence module rather than siblings, because they need its pool)
  • broker/memory — in-process driver, default in tests (implemented; passes the exported broker/brokertest contract suite)
  • outbox — writer port, relay, elector, memory store (implemented; the SQL store and advisory-lock elector land with postgres)
  • inbox — dedupe store, on by default (port + memory store shipped with the broker chain)
  • broker/kafka — franz-go driver: one client, one group, in-process fan-out, mark-the-prefix offsets, and publish errors carrying the code the outbox relay switches on (implemented; at-least-once plus inbox dedupe, not exactly-once — §5.1 claimed otherwise and §5.5 was right. 4 third-party modules, the smallest adapter footprint after transport/http's zero)
  • broker/rabbitmq, broker/nats — after their manifest entries are written
Phase 4 — persistence
  • persistence (port) — Repository, UnitOfWork, the Track/Collect enlistment seam, in-process driver + contract suite (implemented)
  • persistence/postgres — the UnitOfWork, postgres.DB, the outbox store with LISTEN/NOTIFY, an advisory-lock elector, a durable inbox, and plain-SQL migrations (implemented; passes persistence.RunContract unmodified against a real Postgres. Never migrates at boot — that races every replica of a rolling deploy. One third-party dependency: pgx; goose rejected)
  • persistence/mongo, persistence/redis — after their manifest entries are written (mysql: deferred — exists only in a heading)
Phase 5 — cross-cutting
  • Core policy ports decided: RetryPolicy/AuthorizationPolicy/ Telemetry live in app, telemetry rides the context
  • observability — OTel wiring: handlers, HTTP and broker propagation instrumented by one import, composed at BOOT so the request path decides nothing (implemented; DB spans need one explicit postgres.Configure line. 24 third-party modules, confined here by an invariant — a service that does not import it pays nothing)
  • validate — port in core, implementation in a submodule (the port is validate/validate.go; validate/playground implements it, and core refuses the tags it cannot check rather than ignoring them)
  • health — check registry, liveness/readiness verdicts, root-scope binding (implemented; the routes land with the transport adapters)
  • warren/testing (warrentest) — boot a module with fakes, Invoke by type, AssertPublished, Golden (implemented; stdlib + core only)
  • app.Identity — the identity seam, policies and the 401/403 split (v0.1)
  • app.Timeout + the resilience ruling: module DROPPED, not deferred (v0.1)
  • auth (verifier), openapi
Phase 6 — the CLI *(the discovery engine: scaffolding real apps is how
weaknesses get found)*
  • warren new — a scaffold that compiles and tests against today's framework, with the CI gate that builds it (the anti-rot mechanism)
  • warren version; core and all six submodules tagged v0.2.0, so a scaffold's go.mod resolves without a replace. v0.1.0 tagged core alone — a scaffold also requires transport/http, so it never resolved, and --framework <path> was the only working route
  • warren g module|entity|command|repository|consumer — golden-file tested, idempotent, stdlib AST editing (no dst: it has published no releases and sat untouched through Go 1.19–1.27), and everything the five write compiles, vets and passes its own tests in a real project on every CI run
  • warren lint arch — four rules read from the import graph: layer, cross-module, handler/transport and handler/driver, each checked directly and through a helper package; works on a project that does not compile; runs in Warren's own CI over Warren, same binary. The report discloses which rules did not run — a project outside internal/modules/ is told the cross-module rule compared nothing, rather than passing silently (--rules=rings next)
  • v0.2+: doctor, graph, explain di, templates eject
  • v0.3+: extract module, add <adapter>, migrate layout

Repository map

Where What
warren.md The package manifest — one entry per package, source of truth
AGENT.md Invariants, conventions, and process — canonical for humans and agents
<package>/SPEC.md The contract of a package not yet implemented; approved before any code, retired once the package ships
docs/assets/ Usage-flow diagrams for the approved specs

Contributing

Read AGENT.md first — the spec-first process, the dependency-audit rule, and the invariants apply to every change. No feature is implemented before its spec is approved, and no dependency is adopted without a written audit.

License

Apache-2.0 — see LICENSE.

Documentation

Overview

Package warren owns application bootstrap, the module system, and the run loop.

A module declaration is a value, not a side effect: NewModule returns an inert data structure and registers nothing. The bootstrapper walks the whole graph first, then materialises one DI scope per module, copies in only what each module's imports export, validates the whole graph, and only then instantiates anything — every error the framework can detect surfaces at boot, never on request 1.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type App

type App struct {
	// contains filtered or unexported fields
}

App is a bootstrapped application: the flattened module graph, its scoped containers, and its run loop.

func New

func New(modules ...Module) *App

New builds an App from the given module declarations. It does no fallible work — it collects the inert values and allocates the lifecycle; the boot sequence runs in Run or Start.

func (*App) Invoke

func (a *App) Invoke(module string, fn any) error

Invoke resolves fn's parameters from the named module's scope and calls fn — the seam tests and pre-transport mains reach the components the boot built, without constructing second instances. Module encapsulation holds: fn sees exactly what the module's own constructors see, own bindings and imported exports, nothing else. It is boot-time machinery (invariant 7 is about the request path); a transport adapter, once one exists, is the production caller of your handlers.

func (*App) Run

func (a *App) Run() error

Run boots the application and blocks until SIGINT or SIGTERM, then runs the shutdown sequence and returns. It returns the boot error if boot fails, otherwise whatever Stop returns. A second signal during shutdown cancels the drain — the force-exit short-circuit.

func (*App) Start

func (a *App) Start(ctx context.Context) error

Start runs boot steps 0–7 — flatten, scope, copy exports, validate, instantiate, hook up, open readiness — and returns once the application is serving. It exists so tests can drive boot without signals. Failure at any step is a startup failure; nothing is left half-started.

func (*App) Stop

func (a *App) Stop(ctx context.Context) error

Stop runs the shutdown sequence: readiness closes first, then hooks stop in reverse order, bounded by the force-exit deadline.

func (*App) Substitute

func (a *App) Substitute(subs ...Substitution) error

Substitute applies substitutions before boot: Substitute[T] replaces every provider of T, Bind[T] adds one in the root scope. It must be called before Start.

func (*App) Telemetry added in v0.2.0

func (a *App) Telemetry(t app.Telemetry) error

Telemetry sets the instrumentation compiled into every route at boot: with one bound, boot step 5 wraps app.Traced and app.Metered around every handler once, and the request path decides nothing.

It is the non-DI path — a test, or a main that constructs its own. A service that lists observability.Module needs none of it: the bootstrapper resolves an exported app.Telemetry from the graph and uses that. It must be called before Start.

func (*App) Validator added in v0.2.0

func (a *App) Validator(v validate.Validator) error

Validator sets the validator whose rules are compiled into every route closure at boot step 5. The default is validate.Required(). It must be called before Start.

It is the reachable form of the fix transport's own diagnostic promises: "transport.WithValidator(validate.None())" names a Builder that, until this existed, only the bootstrapper held.

type Module

type Module struct {
	// contains filtered or unexported fields
}

Module is an inert declaration of one module: its name, its imports, its providers, controllers, consumers, exports, and its lifecycle hooks. Constructing a Module registers nothing and performs no work.

Because Imports carries Module VALUES rather than names, a cycle between modules cannot reach the bootstrapper: closing one is recursion in the user's own declarations, before New is ever called. Go rejects both shapes it can take, at COMPILE time — verified, not assumed:

modules in different packages   → import cycle not allowed
modules in one package          → initialization cycle for A

So the failure is a build error naming both sides, which is a better diagnostic than Warren could produce anyway. What Warren does NOT catch is an arrangement that defeats both checks — an indirection through a function variable, say — and that fails as recursion or a deadlock in package init, with a Go stack and no mention of modules. Cycles between PROVIDERS are a different thing entirely and are detected by warren/di, which reports them as a Warren diagnostic naming the loop.

func NewModule

func NewModule(name string, opts ...ModuleOption) Module

NewModule returns an inert Module value named name, configured by opts. Nothing is registered and no container is touched. The call site is recorded: it is the "declared in module.go:14" line of the missing-provider diagnostic.

Declare each module ONCE. Modules are deduplicated by identity, so the natural `func Module() warren.Module` factory produces two distinct modules the moment two features import it, and two modules sharing a name is a boot error. The idiom that reads like a function and yields one identity:

var Module = sync.OnceValue(func() warren.Module {
    return warren.NewModule("platform", ...)
})

func (Module) Name

func (m Module) Name() string

Name reports the module's name — the scope App.Invoke addresses and the name diagnostics print.

type ModuleOption

type ModuleOption func(*Module)

ModuleOption configures a Module during NewModule.

func Consumers

func Consumers(consumers ...any) ModuleOption

Consumers declares the constructors of this module's message consumers. They are instantiated at boot; broker adapters register them at boot step 5. Like controllers, a consumer's constructor is also a provider — list it in one place only.

func Controllers

func Controllers(controllers ...any) ModuleOption

Controllers declares the constructors of this module's controllers. They are instantiated at boot; transport adapters register their routes at boot step 5. A controller's constructor is also a provider — list it here only, not in Providers too, or the duplicate registers as an ambiguous binding.

func Eager

func Eager[T any]() ModuleOption

Eager declares that T is materialised at boot even when nothing in the graph consumes it — for modules whose provider's construction IS the point. config.Module uses it so a bad config fails the boot even if no constructor injects the struct; without it, an unconsumed provider is simply never built.

func Exports

func Exports[T any]() ModuleOption

Exports makes T resolvable by modules that import this module. Anything not exported stays private. T must be a declared return type of one of the module's providers, controllers, or consumers — exporting anything else is a boot error, and a constructor returning a concrete type does not match an exported interface: declare the constructor's return type as the interface.

func Imports

func Imports(modules ...Module) ModuleOption

Imports declares the modules this module depends on. Only the imported modules' exported bindings become visible to it.

func OnStart

func OnStart(fn func(context.Context) error) ModuleOption

OnStart registers a startup hook for this module, run in dependency order at boot step 6. The hook is a plain closure fixed at declaration time and resolves nothing from the container; a hook that needs something built at boot — a consumer pipeline's drain func, a connection opened by a constructor — is registered the other way: the constructor injects lifecycle.Lifecycle (provided in the root scope) and appends its own lifecycle.Hook.

func OnStop

func OnStop(fn func(context.Context) error) ModuleOption

OnStop registers a shutdown hook for this module, run in reverse order at shutdown step 10. See OnStart for the boot-time-created alternative — the injected-Lifecycle pattern is how a consumer registers its drain.

func Optional added in v0.2.0

func Optional[T any]() ModuleOption

Optional declares that a nil T from one of this module's providers is MEANT, and must not fail the boot the way an undeclared nil does.

A provider returning nil is normally a boot error: warren.md §1.3's rule is that every detectable error surfaces at boot, and a nil interface otherwise booted clean and became a 500 on the first request to touch it. But some capabilities are legitimately absent. warren/observability returns a nil app.Telemetry when no collector is configured, and app.WithTelemetry drops a nil so the uninstrumented request path stays a pass-through — a no-op value instead would ride every request context and cost real work per request, which is the property the nil exists to preserve.

Optional is per TYPE, not per module: declaring one absence does not disarm the check for anything else the module provides. Consumers of an optional binding must handle the nil — that is the contract they are opting into.

func Providers

func Providers(constructors ...any) ModuleOption

Providers declares constructors owned by this module. A provider is private to its module unless its result type is also named in Exports.

Constructors wire; OnStart acquires. A constructor that opens a connection or starts a goroutine owns a resource the boot sequence cannot release if a later module fails to build — put acquisition in an OnStart hook, whose rollback the lifecycle guarantees.

type Substitution

type Substitution struct {
	// contains filtered or unexported fields
}

Substitution replaces or adds a binding before boot. It is the seam test harnesses use to inject fakes, and main can use it to provide a value it computed itself.

func Bind

func Bind[T any](v T) Substitution

Bind provides v as T in the root scope, where every module can see it.

If the graph already provides T, Bind REPLACES that provider rather than colliding with it: a harness binding a fake broker into an application whose platform module provides a real one is the normal case, and an ambiguous-binding failure there would be useless. Use Substitute when the replacement is required — it fails the boot if nothing matched.

func Substitute

func Substitute[T any](v T) Substitution

Substitute replaces every provider of T with v. An unmatched substitution is a boot error naming T — a typo'd fake is never silently ignored, which is the failure mode that makes test doubles untrustworthy.

Directories

Path Synopsis
app
Package app defines Warren's central abstraction: a transport-agnostic use case, and the core-ring middleware shape that decorates it.
Package app defines Warren's central abstraction: a transport-agnostic use case, and the core-ring middleware shape that decorates it.
internal/exampledomain
Package domain is the user-side domain of the §10 example, so the app tests can compile warren.md's handler verbatim.
Package domain is the user-side domain of the §10 example, so the app tests can compile warren.md's handler verbatim.
Package broker defines Warren's messaging ports: one driver-neutral message envelope, a publisher, a subscriber, and a message handler.
Package broker defines Warren's messaging ports: one driver-neutral message envelope, a publisher, a subscriber, and a message handler.
brokertest
Package brokertest is the contract suite every broker driver must pass: the in-process one, Kafka, RabbitMQ, NATS.
Package brokertest is the contract suite every broker driver must pass: the in-process one, Kafka, RabbitMQ, NATS.
memory
Package memory is the in-process broker: the default in tests, and the driver a modular monolith runs in production before its modules are extracted into services.
Package memory is the in-process broker: the default in tests, and the driver a modular monolith runs in production before its modules are extracted into services.
kafka module
cli module
Package config owns layered configuration resolution: struct defaults, then file sources, then environment variables, then command-line flags — later layers win, and the merged result is checked before boot continues.
Package config owns layered configuration resolution: struct defaults, then file sources, then environment variables, then command-line flags — later layers win, and the merged result is checked before boot continues.
di
Package di owns Warren's dependency-injection container: scoping, graph validation, and diagnostics.
Package di owns Warren's dependency-injection container: scoping, graph validation, and diagnostics.
internal/fixture/domain
Package domain is the contracts side of the §1.2 fixture graph the di tests run against.
Package domain is the contracts side of the §1.2 fixture graph the di tests run against.
internal/fixture/postgres
Package postgres is the providing module of the §1.2 fixture graph.
Package postgres is the providing module of the §1.2 fixture graph.
internal/fixture/user
Package user is the consuming module of the §1.2 fixture graph.
Package user is the consuming module of the §1.2 fixture graph.
Package domain provides the DDD building blocks Warren's other contracts are expressed in terms of: identity, aggregates, events, and specifications.
Package domain provides the DDD building blocks Warren's other contracts are expressed in terms of: identity, aggregates, events, and specifications.
Package errors defines Warren's semantic error vocabulary: a closed set of codes that describe what went wrong in terms a domain expert would use, with no reference to any transport.
Package errors defines Warren's semantic error vocabulary: a closed set of codes that describe what went wrong in terms a domain expert would use, with no reference to any transport.
Package health holds the registry of checks a service can be asked about and renders the two probe verdicts.
Package health holds the registry of checks a service can be asked about and renders the two probe verdicts.
Package inbox defines the dedupe-store port the consumer chain's Deduplicate stage records processed Message.IDs in, and ships the stdlib-only memory store that makes dedupe-by-default cost neither Docker nor a database.
Package inbox defines the dedupe-store port the consumer chain's Deduplicate stage records processed Message.IDs in, and ships the stdlib-only memory store that makes dedupe-by-default cost neither Docker nor a database.
inboxtest
Package inboxtest is the contract suite every inbox.Store must pass: the in-process one, and the durable stores that arrive with the persistence adapters.
Package inboxtest is the contract suite every inbox.Store must pass: the in-process one, and the durable stores that arrive with the persistence adapters.
internal
panics
Package panics contains one recovered panic and renders it as a Warren diagnostic.
Package panics contains one recovered panic and renders it as a Warren diagnostic.
Package lifecycle owns ordered startup and shutdown, readiness gating, and drain.
Package lifecycle owns ordered startup and shutdown, readiness gating, and drain.
Package log carries a *slog.Logger on the context and propagates the correlation ID that ties one request's records together.
Package log carries a *slog.Logger on the context and propagates the correlation ID that ties one request's records together.
Package outbox implements the transactional outbox: the pattern that makes a state change and the events announcing it atomic without a distributed transaction.
Package outbox implements the transactional outbox: the pattern that makes a state change and the events announcing it atomic without a distributed transaction.
Package persistence is the port repositories and units of work are written against: load and store aggregates by identity, and make the state a handler wrote and the events its aggregates raised commit together or not at all.
Package persistence is the port repositories and units of work are written against: load and store aggregates by identity, and make the state a handler wrote and the events its aggregates raised commit together or not at all.
postgres module
Package warrentest boots a Warren module for a test with dependencies substituted, invokes handlers by request and response type, and asserts on what was published.
Package warrentest boots a Warren module for a test with dependencies substituted, invokes handlers by request and response type, and asserts on what was published.
Package transport is the port through which a controller exposes a use case over HTTP, gRPC, and events.
Package transport is the port through which a controller exposes a use case over HTTP, gRPC, and events.
http module
Package validate is the port transport adapters validate decoded requests through, plus the standard-library implementation of validate:"required".
Package validate is the port transport adapters validate decoded requests through, plus the standard-library implementation of validate:"required".
playground module

Jump to

Keyboard shortcuts

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