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 forRegister,Freeze, andServices
Panics:
- If called more than once
Behavior:
- Must be called before any registration
- Returns a
Keythat 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 byStart()
Panics:
- If key is invalid
Behavior:
- After calling, any attempt to
Registerwill panic UseandServicescontinue to work normally- Cannot be undone (except via
Resetin tests)
Example:
key := slush.Start()
slush.Register[Database](key, db)
slush.Freeze(key)
// This would panic:
// slush.Register[Logger](key, logger)
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 byStart()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
Toverwrite the previous registration - Emits
SignalRegisteredvia 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)error—nilon success,ErrNotFoundorErrAccessDeniedon failure
Errors:
ErrNotFound— No service registered for typeTErrAccessDenied— 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, orSignalNotFoundvia 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"
}
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 byStart()
Returns:
[]ServiceInfo— Slice of service metadata (see ServiceInfo)error—nilon success,ErrInvalidKeyif 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=testingor-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
startedandfrozenstate - 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 FQDNKeyImpl— Implementation FQDN
SignalAccessed
var SignalAccessed = capitan.NewSignal("slush.accessed", "Service accessed")
Emitted when a service is successfully retrieved. Severity: Debug.
Fields:
KeyInterface— Interface FQDNKeyImpl— Implementation FQDN
SignalDenied
var SignalDenied = capitan.NewSignal("slush.denied", "Service access denied")
Emitted when a guard rejects access. Severity: Warn.
Fields:
KeyInterface— Interface FQDNKeyImpl— Implementation FQDNKeyError— 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
- Types Reference — Type documentation
- Guards Guide — Writing guards
- capitan Integration — Event handling