Skip to content

Runtime

Overview

The Runtime domain in comby serves as a meta-domain that provides introspection, control, and runtime-specific operations within the application framework. It enables the discovery and management of system capabilities such as permissions, commands, queries, events, aggregates, and event handlers. Additionally, the domain facilitates administrative tasks and monitoring through permissions and server-side events (SSE).

Concept

What is the Runtime Domain?

The Runtime domain is the meta-layer of Comby that allows applications to introspect themselves, manage permissions, and monitor system health. It provides APIs to discover what commands, queries, and events are available, control event handlers, and stream real-time system events.

Key Characteristics:

  • System Introspection: Discover available commands, queries, events, and handlers
  • Permission Management: Central permission registry and validation
  • Real-Time Monitoring: Metrics, event streaming (SSE), and system info
  • Store Access Control: Permissions for EventStore, CommandStore, DataStore, etc.
  • Schema Discovery: JSON schemas for all domain types
  • Event Handler Control: Start, stop, and restore event handler states
Runtime Domain (Meta-Layer)
├── Permission System (Registry & Validation)
├── Introspection (Commands, Queries, Events, Handlers)
├── Monitoring (Metrics, SSE, System Info)
├── Store Management (Access Control)
└── Schema Discovery (JSON Schemas)

Architecture

Hierarchy

Runtime Domain (System-Level)
├── Permissions
│   ├── Permission Registry
│   ├── Custom Permission Functions
│   └── Permission Validation
├── Runtime Information
│   ├── Commands (All registered commands)
│   ├── Queries (All registered queries)
│   ├── Events (All domain events)
│   ├── Command Handlers
│   ├── Query Handlers
│   └── Event Handlers (with metrics)
├── Monitoring
│   ├── Metrics (Event handler statistics)
│   ├── SSE (Real-time event streaming)
│   └── System Info (Tenant, version, etc.)
└── Store Access
    ├── EventStore Permissions
    ├── CommandStore Permissions
    ├── DataStore Permissions
    ├── CacheStore Permissions
    └── LogStore Permissions

Runtime domain interacts with:

  • All Domains: Registers their permissions, commands, queries, and events
  • Auth Domain: Provides permission validation functions
  • Facade: Central access point for runtime information
  • Event Handlers: Controls and monitors their execution
  • Stores: Manages access permissions

Permission System

Permission Hierarchy

The Runtime domain defines a 3-level permission hierarchy:

1. Anonymous

No authentication required, completely public access.

go
// Permission function
AnonymousCmdFn = func(ctx context.Context, cmd comby.Command) error {
    return nil  // Always allow
}

Use cases: Public endpoints, health checks, documentation

2. Authenticated

User is logged in (has account + session) but no active identity.

go
// Permission function
AuthenticatedCmdFn = func(ctx context.Context, cmd comby.Command) error {
    // Requires: SenderAccountUuid + SenderSessionUuid
    if hasValidAccountAndSession {
        return nil
    }
    return ErrPermissionDenied
}

Use cases: Profile management, account settings, identity selection

3. Authorized

User is logged in AND has selected an active identity with tenant context.

go
// Permission function
AuthorizedCmdFn = func(ctx context.Context, cmd comby.Command) error {
    // Requires: SenderAccountUuid + SenderSessionUuid + SenderIdentityUuid + SenderTenantUuid
    if hasCompleteContext {
        return nil
    }
    return ErrPermissionDenied
}

Use cases: Most domain operations, tenant-specific actions

Store Permissions

The Runtime domain defines permissions for all storage backends:

EventStore Permissions

StoreEvent.Info   - Retrieve EventStore information
StoreEvent.Read   - Read EventStore entries
StoreEvent.Update - Update EventStore entries
StoreEvent.Delete - Delete EventStore entries

CommandStore Permissions

StoreCommand.Info   - Retrieve CommandStore information
StoreCommand.Read   - Read CommandStore entries
StoreCommand.Update - Update CommandStore entries
StoreCommand.Delete - Delete CommandStore entries

DataStore Permissions

StoreData.Info   - Retrieve DataStore information
StoreData.Read   - Read DataStore entries
StoreData.Update - Update DataStore entries
StoreData.Delete - Delete DataStore entries

CacheStore Permissions

StoreCache.Info   - Retrieve CacheStore information
StoreCache.Read   - Read CacheStore entries
StoreCache.Update - Update CacheStore entries
StoreCache.Delete - Delete CacheStore entries

LogStore Permissions

StoreLog.Info   - Retrieve LogStore information
StoreLog.Read   - Read LogStore entries
StoreLog.Update - Update LogStore entries
StoreLog.Delete - Delete LogStore entries
go
// Debug: Show all available commands for a domain
func ShowDomainCommands(domain string, facade *comby.Facade) {
    handlers := runtime.CommandHandlerList(ctx, facade)

    for _, handler := range handlers {
        if handler.CommandHandlerDomain == domain {
            for _, cmd := range handler.DomainCommandHandlers {
                fmt.Printf("%s\n", cmd.DomainCmdName)
            }
        }
    }
}

Features

  • Complete system introspection
  • Permission management and validation
  • Custom permission functions
  • Real-time event streaming (SSE)
  • Event handler metrics and monitoring
  • Event handler state control
  • Store access permissions
  • JSON schema discovery
  • System information API
  • Three-level permission hierarchy (Anonymous, Authenticated, Authorized)

Best Practices

Permission Registration

  • Register permissions during domain initialization
  • Use descriptive permission names
  • Provide clear permission descriptions
  • Use custom functions only when RBAC is insufficient

Monitoring

  • Monitor event handler metrics regularly
  • Alert on failed events
  • Track event processing latency
  • Use SSE for real-time monitoring

Store Access

  • Restrict store access to admin users only
  • Use separate permissions for read vs write
  • Audit all store modifications
  • Never expose store endpoints publicly

Security Considerations

Permission Validation

  • Always validate permissions before execution
  • Use the three-level hierarchy appropriately
  • Custom functions should fail securely (deny by default)
  • Never skip permission checks in production

Store Access

  • Store permissions are highly privileged
  • Only system administrators should have store access
  • Audit all store operations
  • Implement rate limiting for store endpoints

SSE Streaming

  • Require authentication for SSE connections
  • Limit data exposed in SSE streams
  • Implement connection limits
  • Monitor for abuse

Runtime Information

  • Runtime endpoints can reveal system architecture
  • Restrict access to authorized users only
  • Don't expose sensitive configuration
  • Use HTTPS for all runtime endpoints

Troubleshooting

Permission denied for custom function

Cause: Custom permission function returned error.

Debug:

go
perm := findPermission(domain, permissionType)
if perm.FuncSet && perm.CmdFunc != nil {
    err := perm.CmdFunc(ctx, cmd)
    if err != nil {
        fmt.Printf("Custom function denied: %v\n", err)
    }
}

Event handler metrics not updating

Check:

  1. Is the event handler a StateRestorer?
  2. Does it implement EventHandlerMetricProvider?
  3. Are events being processed?

Solution: Ensure event handler implements required interfaces:

go
type MyReadmodel struct {
    *comby.BaseReadmodel  // Provides metrics
}

SSE connection failing

Check:

  1. Is authentication valid?
  2. Are required permissions granted?
  3. Is the SSE producer running?

Debug: Check SSE producer status in logs.

Store permissions not working

Cause: Store permissions not registered.

Solution:

go
runtime.RegisterStore(ctx, facade)

Integration with Other Domains

All Domains

Every domain automatically:

  • Registers commands and queries
  • Creates runtime permissions
  • Exposes schemas

Auth Domain

  • Consumes permission definitions
  • Validates permissions during authorization
  • Uses permission functions for custom logic

Custom Domains

go
// Custom domain registers its permissions
func Register(ctx context.Context, fc *comby.Facade) {
    // Commands and queries are auto-registered

    // Optional: Register custom permission functions
    runtime.RegisterPermission(
        runtime.NewPermissionCmdFunc(
            "MyDomain",
            "MyCommand",
            myCustomPermissionFn,
        ),
    )
}

Advanced Features

Event Handler Control

Restore event handler state:

go
// Via API
POST /api/tenants/{tenantUuid}/runtime/event-handler-list
{
    "action": "restore",
    "eventHandlerName": "CustomerReadmodel",
    "restoreFromZero": true
}

Schema Introspection

Get JSON schema for any command:

go
POST /api/tenants/{tenantUuid}/runtime/schema
{
    "domain": "Customer",
    "type": "CustomerCommandCreate"
}

Response:
{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "properties": {
        "customerUuid": {"type": "string"},
        "name": {"type": "string"},
        "email": {"type": "string", "format": "email"}
    }
}