Concepts
Glacier is 15 packages organized into three tiers. The tiers aren't a metaphor - they're a testable import constraint enforced by a layering test on every PR. Understanding the tiers tells you what you can depend on and what you can't.
The three tiers
The DAG has no cycles. Forbidden edges are testable invariants - a Lynx-owned test rejects any import that violates them on every PR.
Tier 0: Kernel
Universal packages. Every consumer of any Glacier package transitively depends on these five. They are small, allocation-light, and stable by design.
- option - The
Option[T]/OptionFunc[T]protocol that every package's constructor speaks. Zero deps on other Glacier packages. - errs - Error wrapping, joining, classification, stack traces, and the
Sentinelconstructor that enforces the library register format at construction time. - log -
log/slogconventions withTraceandNoticelevels, context-attribute attachment (log.With), TTY color, andRedact. - assert - Test assertions (
Equal[T],NoError,Match,Len) with smart deep-compare and therequire/halt-on-failure mirror. - term - Terminal capability detection, 24-bit ANSI styling, glyph registry, beauty-writer column layout, prompts, animation.
Tier 1: Mid
Mid-tier packages are independent of each other. Each depends only on the kernel. You can import any one of them without pulling in the other four.
- concur - Context-aware sync primitives:
Mutex.LockCtx,Groupwith panic recovery,Semaphore,Pool[T],Once[T]. - fluent - Lazy
iter.Seqpipeline operators:Map,Filter,Take,Window,GroupBy, joins, set ops. Generics-first; zero deps outside kernel. - conf - Layered configuration with atomic snapshots. Defaults, JSON file, env, flags.
Register[T]returns a typed accessor. - fixture - Test resources: golden files, typed snapshots, deterministic fake clocks, in-memory filesystems, goroutine and FD leak guards.
- obs - Opt-in OpenTelemetry via OTLP gRPC.
MeterProviderandTracerProviderwith hooks forhttpc,cli, andconf. Zero overhead when off.
Tier 2: Leaves
Leaf packages are large enough to justify isolation. They depend on kernel and mid-tier packages only and never import each other. A consumer who needs only httpmock for tests does not pull in cli.
- cli - CLI builder: struct tags for flags,
glaciergencodegen for wiring, banner via//go:embed, signal handling throughinternal/sigh. - mock - Interface mocks:
mock.Of[T]reflect-based or+glacier:mockcodegen typed wrappers. Fluent expectation builder, automaticVerifyon cleanup. - httpmock - Programmable
http.RoundTripperfor tests. Stub builder,JSON[T]response helpers, strict-by-default. - httpc - Typed HTTP client:
Get[T],Post[T],Put[T]auto-unmarshal. Retry with backoff, dry-run via context. - cache - Generic key-value cache:
New[V]in-memory,NewDisk[V]per-key JSON with flock,NewLayeredwrite-through.GetOrLoadsingleflights concurrent misses;obscounters when configured.
Cross-cutting conventions
Seven rules inherited by every package. They are the framework's coherence story.
Functional options. Every package configurable at construction uses
option.Option[T]. Unexportedconfigstruct,With<Knob>(value)constructors,option.Applyin the package constructor. Boolean knobs use the no-arg form (Strict(), notWithStrict(true)).Error contract. Library errors are lowercase, no trailing period, in the format
package: action: cause. Per-package sentinels areErr<Cause>viaerrs.Sentinel. Typed errors are<Cause>ErrorwithUnwrap. Multi-error returns useerrs.Join.errors.Is/errors.Asare the only composition operators - no string matching ofError()output.Context propagation.
ctx context.Contextis the first parameter of every function that performs I/O, takes time, or is observable from another goroutine. Synchronous constructors do not take ctx. Cancellation surfaces asctx.Err()wrapped in a package-specific sentinel.Lifecycle. Constructors are
New(opts ...option.Option[T]) (*T, error). Types with async resources addStart(ctx). Types with resources addClose() error.Closeis idempotent. Multi-resource types returnerrs.JoinfromClose.Logging. Loggers are injected via
WithLogger(*slog.Logger). The default isslog.Default(). Context carries attributes vialog.With(ctx, ...slog.Attr).log.From(ctx)reads the injected logger.Naming. Short lowercase package names, no stutter on exported types,
Err<Cause>sentinels,<Cause>Errortyped errors,<Verb>erfor single-method interfaces. Full reference in spec 0001.Path safety. Every file-touching package routes path operations through
internal/safefile:filepath.Clean, reject..components, reject absolute paths unless explicitly allowed, open-then-fstat (never stat-then-open). Every JSON decode passes throughinternal/safejson.Decode[T]for size cap, depth cap, and UTF-8 validation.