zoobzio January 24, 2026 Edit this page

API Reference

Complete documentation for slush's public functions.

Initialization

Start

func Start() Key

Initializes the service registry and returns a capability key for registration.

Returns:

  • Key — Capability token required for Register, Freeze, and Services

Panics:

  • If called more than once

Behavior:

  • Must be called before any registration
  • Returns a Key that authorizes registration operations
  • Can only be called once per process

Example:

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

    slush.Register[Database](key, db)
    slush.Register[Logger](key, logger)

    slush.Freeze(key)  // Optional: prevent further registration

    startServer()
}

See also: Key, Freeze, Register


Freeze

func Freeze(key Key)

Prevents further service registration.

Parameters:

  • key — The key returned by Start()

Panics:

  • If key is invalid

Behavior:

  • After calling, any attempt to Register will panic
  • Use and Services continue to work normally
  • Cannot be undone (except via Reset in tests)

Example:

key := slush.Start()
slush.Register[Database](key, db)
slush.Freeze(key)

// This would panic:
// slush.Register[Logger](key, logger)

See also: Start, Register


Registration

Register

func Register[T any](key Key, impl T) *Handle[T]

Stores a service implementation keyed by interface type T.

Parameters:

  • key — The key returned by Start()
  • impl — The service implementation to store

Returns:

  • *Handle[T] — Configuration handle for adding guards

Panics:

  • If Start() has not been called
  • If key is invalid
  • If registry is frozen

Behavior:

  • Creates a new registry entry for type T
  • Subsequent calls with the same T overwrite the previous registration
  • Emits SignalRegistered via capitan
  • Pre-computes FQDNs for interface and implementation

Example:

key := slush.Start()
slush.Register[Database](key, postgresDB)
slush.Register[Mailer](key, sendgridMailer).
    Guard(requireAuth)

See also: Start, Handle.Guard, Types Reference


Retrieval

Use

func Use[T any](ctx context.Context) (T, error)

Retrieves a service by interface type, running all guards first.

Parameters:

  • ctx — Context passed to guard functions

Returns:

  • T — The service implementation (zero value on error)
  • errornil on success, ErrNotFound or ErrAccessDenied on failure

Errors:

  • ErrNotFound — No service registered for type T
  • ErrAccessDenied — A guard returned an error (wrapped with guard's error)

Behavior:

  • Looks up service by reflect.TypeFor[T]()
  • Runs guards in registration order; stops on first error
  • Emits SignalAccessed, SignalDenied, or SignalNotFound via capitan

Example:

db, err := slush.Use[Database](ctx)
if errors.Is(err, slush.ErrNotFound) {
    // Service not registered
}
if errors.Is(err, slush.ErrAccessDenied) {
    // Guard rejected - unwrap for details
    log.Println(err)  // "slush: access denied: missing permission"
}

See also: MustUse, Guard


MustUse

func MustUse[T any](ctx context.Context) T

Retrieves a service, panicking on error. For bootstrap code only.

Parameters:

  • ctx — Context passed to guard functions

Returns:

  • T — The service implementation

Panics:

  • If service not found
  • If any guard returns an error

Example:

func main() {
    initServices()

    // OK to panic during bootstrap
    logger := slush.MustUse[Logger](context.Background())
    db := slush.MustUse[Database](context.Background())

    startServer(logger, db)
}

See also: Use


Enumeration

Services

func Services(key Key) ([]ServiceInfo, error)

Returns information about all registered services.

Parameters:

  • key — The key returned by Start()

Returns:

  • []ServiceInfo — Slice of service metadata (see ServiceInfo)
  • errornil on success, ErrInvalidKey if key is invalid

Errors:

  • ErrInvalidKey — The provided key is invalid

Behavior:

  • Iterates all registry entries
  • Looks up sentinel metadata for each implementation FQDN
  • Thread-safe (holds read lock during iteration)

Example:

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

See also: ServiceInfo, sentinel Integration


Testing Utilities

Note: These functions are only available in test builds (-tags=testing or -tags=integration). They do not exist in production binaries.

Unregister

func Unregister[T any]()

Removes a service by type. For testing only.

Build tag: testing or integration

Behavior:

  • Deletes registry entry for type T
  • No-op if type not registered
  • Thread-safe

Example:

func TestServiceReplacement(t *testing.T) {
    slush.Reset()
    key := slush.Start()
    slush.Register[Database](key, mockDB{})

    // Replace with different mock
    slush.Unregister[Database]()
    slush.Register[Database](key, otherMockDB{})
}

See also: Reset


Reset

func Reset()

Clears all registered services and resets initialization state. For testing only.

Build tag: testing or integration

Behavior:

  • Clears all registered services
  • Resets started and frozen state
  • Invalidates the current key
  • Allows Start() to be called again

Example:

func TestIsolated(t *testing.T) {
    slush.Reset()
    defer slush.Reset()

    key := slush.Start()
    slush.Register[Database](key, mockDB{})
    // Test...
}

See also: Unregister, Testing Guide


Handle Methods

Handle.Guard

func (h *Handle[T]) Guard(g Guard) *Handle[T]

Adds an access control check to the service. Chainable.

Parameters:

  • g — Guard function to add

Returns:

  • *Handle[T] — Same handle for chaining

Behavior:

  • Appends guard to service's guard list
  • Guards run in order during Use[T]
  • Thread-safe (acquires write lock)

Example:

slush.Register[Database](key, db).
    Guard(requireAuth).
    Guard(requireRole("admin")).
    Guard(rateLimit(100))

See also: Guard, Guards Guide


Signals

SignalRegistered

var SignalRegistered = capitan.NewSignal("slush.registered", "Service registered")

Emitted when a service is registered. Severity: Info.

Fields:

  • KeyInterface — Interface FQDN
  • KeyImpl — Implementation FQDN

SignalAccessed

var SignalAccessed = capitan.NewSignal("slush.accessed", "Service accessed")

Emitted when a service is successfully retrieved. Severity: Debug.

Fields:

  • KeyInterface — Interface FQDN
  • KeyImpl — Implementation FQDN

SignalDenied

var SignalDenied = capitan.NewSignal("slush.denied", "Service access denied")

Emitted when a guard rejects access. Severity: Warn.

Fields:

  • KeyInterface — Interface FQDN
  • KeyImpl — Implementation FQDN
  • KeyError — Guard error message

SignalNotFound

var SignalNotFound = capitan.NewSignal("slush.not_found", "Service not found")

Emitted when a requested service isn't registered. Severity: Warn.

Fields:

  • KeyInterface — Interface FQDN

Field Keys

KeyInterface

var KeyInterface = capitan.NewStringKey("interface")

Event field for interface FQDN.

KeyImpl

var KeyImpl = capitan.NewStringKey("impl")

Event field for implementation FQDN.

KeyError

var KeyError = capitan.NewStringKey("error")

Event field for error messages.


Next Steps