zoobzio January 24, 2026 Edit this page

Types Reference

Complete documentation for slush's public types.

Core Types

Key

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

Capability token that authorizes service registration and enumeration. Returned by Start().

Obtaining a Key:

  • Call Start() at application startup
  • Start() can only be called once

Operations requiring a Key:

  • Register[T](key, impl) — Register a service
  • Freeze(key) — Lock the registry
  • Services(key) — Enumerate services

Security:

  • The inner pointer is unexported, preventing forgery via struct literal
  • Only code with access to the key can modify the registry
  • Keys are invalidated by Reset() (testing only)

Example:

func main() {
    key := slush.Start()

    // Pass key to initialization code
    initDatabase(key)
    initServices(key)

    // Optionally lock the registry
    slush.Freeze(key)

    // Key not needed for Use
    db, _ := slush.Use[Database](ctx)
}

func initDatabase(key slush.Key) {
    slush.Register[Database](key, newPostgresDB())
}

See also: Start, Freeze


Guard

type Guard func(ctx context.Context) error

A function that validates context before service access.

Contract:

  • Return nil to allow access
  • Return an error to deny access

Behavior when returned error is non-nil:

  • Use[T] returns ErrAccessDenied wrapping your error
  • Guard chain stops (subsequent guards don't run)
  • SignalDenied event emitted with error message

Example:

// Simple guard
func requireAuth(ctx context.Context) error {
    if auth.UserFromContext(ctx) == nil {
        return errors.New("unauthenticated")
    }
    return nil
}

// Parameterized guard
func requirePermission(perm string) slush.Guard {
    return func(ctx context.Context) error {
        if !hasPermission(ctx, perm) {
            return fmt.Errorf("missing permission: %s", perm)
        }
        return nil
    }
}

See also: Guards Guide, Handle.Guard


Handle

type Handle[T any] struct {
    // contains filtered or unexported fields
}

Configuration handle for a registered service. Returned by Register[T].

Methods:

MethodDescription
Guard(g Guard) *Handle[T]Add access control check (chainable)

Example:

handle := slush.Register[Database](key, db)
handle.Guard(requireAuth)
handle.Guard(requireRole("admin"))

// Or chained
slush.Register[Database](key, db).
    Guard(requireAuth).
    Guard(requireRole("admin"))

Internals:

Handle wraps a generic *handle[T] that stores:

  • The service implementation (impl T)
  • Guard slice ([]Guard)
  • Pre-computed FQDNs for interface and implementation

See also: Register, Architecture


ServiceInfo

type ServiceInfo struct {
    Interface  string            // Interface FQDN (the lookup key)
    Impl       string            // Implementation FQDN
    Metadata   sentinel.Metadata // Sentinel metadata from cache
    GuardCount int               // Number of guards configured
}

Describes a registered service. Returned by Services().

Fields:

FieldTypeDescription
InterfacestringFully qualified name of the interface type (e.g., "github.com/app.Database")
ImplstringFully qualified name of the implementation type (e.g., "github.com/app.postgresDB")
Metadatasentinel.MetadataType metadata from sentinel's cache (may be empty if not scanned)
GuardCountintNumber of guards attached to this service

Example:

svcs, err := slush.Services(key)
if err != nil {
    log.Fatal(err)
}
for _, svc := range svcs {
    fmt.Printf("Service: %s\n", svc.Interface)
    fmt.Printf("  Impl: %s\n", svc.Impl)
    fmt.Printf("  Guards: %d\n", svc.GuardCount)

    if len(svc.Metadata.Fields) > 0 {
        fmt.Printf("  Fields:\n")
        for _, f := range svc.Metadata.Fields {
            fmt.Printf("    - %s: %s\n", f.Name, f.Type)
        }
    }
}

See also: Services, sentinel Integration


Errors

ErrNotFound

var ErrNotFound = errors.New("slush: service not registered")

Returned by Use[T] when no service is registered for type T.

Example:

db, err := slush.Use[Database](ctx)
if errors.Is(err, slush.ErrNotFound) {
    // Handle missing service
    log.Println("Database service not configured")
}

ErrAccessDenied

var ErrAccessDenied = errors.New("slush: access denied")

Returned by Use[T] when a guard returns an error. The guard's error is joined.

Example:

db, err := slush.Use[Database](ctx)
if errors.Is(err, slush.ErrAccessDenied) {
    // Guard rejected - full error includes reason
    log.Println(err)  // "slush: access denied\nmissing permission: db:write"

    // Can also check the guard's specific error
    var permErr *PermissionError
    if errors.As(err, &permErr) {
        log.Printf("Missing: %s", permErr.Permission)
    }
}

ErrInvalidKey

var ErrInvalidKey = errors.New("slush: invalid key")

Returned by Services() when an invalid key is provided.

Example:

svcs, err := slush.Services(key)
if errors.Is(err, slush.ErrInvalidKey) {
    log.Println("Invalid registry key")
}

See also: Key, Services


Internal Types

These types are not exported but understanding them helps with debugging.

service (interface)

type service interface {
    fqdns() (iface, impl string)
    guards() []Guard
    guardCount() int
}

Internal interface that handle[T] satisfies. Enables heterogeneous storage in the registry map.

handleT (generic struct)

type handle[T any] struct {
    g             []Guard
    interfaceFQDN string
    implFQDN      string
    impl          T
}

Internal generic struct that stores a service with full type safety. Satisfies the service interface for storage while preserving T for type-safe retrieval.


sentinel Types

These types come from the sentinel package and appear in ServiceInfo.Metadata.

sentinel.Metadata

type Metadata struct {
    FQDN          string
    TypeName      string
    PackageName   string
    Fields        []FieldMetadata
    Relationships []TypeRelationship
}

Type metadata extracted by sentinel. May be empty if the implementation wasn't scanned.

sentinel.FieldMetadata

type FieldMetadata struct {
    Name  string
    Type  string
    Kind  FieldKind
    Tags  map[string]string
    Index []int
}

Field-level metadata including struct tags.

See also: sentinel Integration, sentinel Documentation


capitan Types

These types come from the capitan package and are used for event handling.

capitan.Signal

Represents an event type. slush exports four signals:

  • SignalRegistered
  • SignalAccessed
  • SignalDenied
  • SignalNotFound

capitan.StringKey

Typed key for string event fields. slush exports:

  • KeyInterface
  • KeyImpl
  • KeyError

See also: capitan Integration, capitan Documentation


Next Steps