• v1.0.0 098a2098f8

    Rene Nochebuena released this 2026-05-29 09:43:45 -06:00 | 0 commits to main since this release

    v1.0.0

    code.nochebuena.dev/einherjar/contracts

    Overview

    contracts v1.0.0 is the foundation of the Einherjar framework. It defines the
    interfaces and minimal types that every starter depends on — and nothing else. Zero
    external dependencies. Zero Einherjar dependencies. Nothing is above it in the
    dependency graph.

    Its interfaces are permanent. Adding a method to a published interface is a breaking
    change in Go, and breaking changes require a major version bump with coordinated
    updates across all implementing starters. This is not a limitation — it is the design.

    Architecture Decisions Resolved

    Decision Resolution
    Flat package vs sub-packages Sub-packages — one per domain (lifecycle, observability, logging, errs, security). Consumers import only what they need.
    xerrors codes in contracts No — error codes and typed error constructors live in core.
    health.Checkable in web or contracts contracts/observability — data starters implement Checkable without importing the HTTP layer.
    Identifiable in web or contracts contracts/observability — all starters implement Identifiable without importing each other.
    Duck-typed logz/xerrors bridge Replaced — errs.CodedError and errs.ContextualError are proper contracts.
    One file per type Enforced structurally and by the compliance test (AST-based, CT-6).
    Identity as pointer or value Value type — prevents nil-check burden and accidental mutation across concurrent middleware.
    Request-scoped security context SecurityBag — carries Identity + typed attributes; immutable; replaces bare Identity propagation.

    Full API

    lifecycle

    type Component interface {
        OnInit() error
        OnStart() error
        OnStop() error
    }
    

    observability

    type Level int
    
    const (
        LevelCritical Level = iota // zero value — safe default
        LevelDegraded
    )
    
    type Checkable interface {
        HealthCheck(ctx context.Context) error
        Name() string
        Priority() Level
    }
    
    // Identifiable is implemented by all starters that register with the launcher.
    // The launcher type-asserts registered components to collect module identity
    // and print the loaded-module list after the startup banner.
    // Function-only modules (auth, auth-jwt, telemetry, httpclient) expose a
    // package-level Module variable instead.
    type Identifiable interface {
        ModulePath() string    // e.g. "code.nochebuena.dev/einherjar/web"
        ModuleVersion() string // e.g. "v1.0.0"; "(devel)" in local workspaces
    }
    

    logging

    type Logger interface {
        Debug(msg string, args ...any)
        Info(msg string, args ...any)
        Warn(msg string, args ...any)
        Error(msg string, err error, args ...any)
        With(args ...any) Logger
        WithContext(ctx context.Context) Logger
    }
    

    errs

    type CodedError interface {
        ErrorCode() string
    }
    
    type ContextualError interface {
        ErrorContext() map[string]any
    }
    

    security

    type Identity struct {
        UID         string
        TenantID    string
        DisplayName string
        Email       string
    }
    
    func NewIdentity(uid, displayName, email string) Identity
    func (i Identity) WithTenant(id string) Identity
    
    type Permission int64
    const MaxPermission Permission = 62
    
    type PermissionMask int64
    func (m PermissionMask) Has(p Permission) bool
    func (m PermissionMask) Grant(p Permission) PermissionMask
    
    type PermissionProvider interface {
        ResolveMask(ctx context.Context, uid, resource string) (PermissionMask, error)
    }
    
    // SecurityBag — immutable request-scoped security context
    type SecurityBag struct { /* unexported fields */ }
    
    func NewSecurityBag(id Identity) SecurityBag
    func (b SecurityBag) Identity() Identity
    func (b SecurityBag) WithIdentity(id Identity) SecurityBag
    func (b SecurityBag) Get(key string) (any, bool)
    func (b SecurityBag) With(key string, value any) SecurityBag
    
    func SetBagInContext(ctx context.Context, bag SecurityBag) context.Context
    func BagFromContext(ctx context.Context) (SecurityBag, bool)
    
    // SetInContext/FromContext — backed by SecurityBag; all four cross-function
    // combinations are valid and return consistent results.
    func SetInContext(ctx context.Context, id Identity) context.Context
    func FromContext(ctx context.Context) (Identity, bool)
    

    Installation

    go get code.nochebuena.dev/einherjar/contracts@v1.0.0
    
    Downloads