Skip to content
nexsspPublic

About

Ultra-fast Go execution engine for resilient DAGs, typed actions, and hot-swappable workflows. Features constant-memory streaming and zero-allocation hot paths.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Nexss Kernel

CI Latest tag Go Reference License

Runnable examples are maintained in the central Nexss Ecosystem Examples repository.

Nexss Kernel is a lightweight, typed Go execution library for building reusable actions, resilient pipelines, and deterministic DAG workflows. It is independent of concrete transport protocols, persistence implementations, AI vendor SDKs, and specific identity providers.

The Kernel provides core execution semantics, typed generics, context-based security guards, and resilient middleware. Applications and sibling modules supply concrete network adapters, storage drivers, and domain logic.

Kernel does not expose a runtime Version function or constant. Go binaries built with module metadata can inspect runtime/debug.ReadBuildInfo for the linked module version.

Design goal: Predictable execution semantics, focused interfaces, zero-allocation hot paths, and idiomatic Go.

Development Commands

This repository uses Task for local workflows and CI. Install it once with:

go install github.com/go-task/task/v3/cmd/task@latest

Use task --list to view targets. Common commands:

task test                 # short test suite
task test -- ./action     # test one package or path
task test:race            # race-enabled tests
task bench                # benchmarks with memory statistics
task ci                   # the CI gate

Architecture

Application / Domain Package / Transport Adapters
        │
        ├── Domain builders (appaction pattern)
        ├── HTTP / CLI / Worker / NATS / gRPC adapters
        ├── AI, Tooling & Provider modules
        └── Database, Cache & Storage implementations
        │
        ▼
Nexss Kernel
  typed actions · Builder · middleware · hooks · retry
  cache/idempotency contracts · context guards (RBAC/perms)
  composition · DAG graphs · categorized errors (xerr)

The Kernel owns the lifecycle, concurrency safety, and execution semantics of an action. Extension modules implement backend drivers or add explicit middleware layers; they do not fork the builder or alter execution semantics.


Core Packages

Package Purpose
action Typed action builders, middleware, composition, retries, timeouts, circuit breakers, concurrency limits, caching, idempotency, durable journaling/resume, streaming, sagas, and resilience policies.
ai/dag Typed directed acyclic graphs with deterministic compilation, static and conditional routing, layered parallel execution, nested graphs, state snapshots, Mermaid rendering, and suspension/resume semantics.
stream Domain-neutral lazy stream operators, including Map, Filter, Take, Batch, BatchByTime, Window, Reduce, FlatMap, Distinct, Throttle, Debounce, and worker pools.
observe Optional vendor-neutral lifecycle events, bounded memory history, metrics aggregation, Prometheus, JSONL, and slog sinks.
xctx Typed request context values, pooled request scopes, request/execution/trace identity, correlation data, roles, permissions, features, progress, and deterministic controls.
xerr Categorized errors for validation, authorization, conflicts, not-found cases, transient failures, internal failures, and panic recovery.
xfile / xfs Typed file references and resolvers, plus confined and atomic filesystem helpers.
broadcast / ringbuf In-process topics and bounded ring buffers for event publication and telemetry.
timing / xsync Timing-wheel scheduling and generic pooling primitives.
xtest/ktest Allocation checks, polling/leak helpers, test contexts, action fakes, contract assertions, and fluent action test runs.

Ring buffer memory budgets

ringbuf.NewChecked(capacity) validates the rounded allocation against the default 64 MiB per-ring budget and returns an error before allocating. For an intentional per-ring override, use ringbuf.NewWithOptions(ringbuf.Options{Capacity: ..., MemoryBudgetBytes: ...}). The source-compatible ringbuf.New(capacity) also uses the safe default and returns nil when validation fails; over-limit requests are never silently clamped to a smaller ring.

The generic mutex-backed ringbuf.NewBuffer[T](capacity) uses the same default budget and returns nil on rejection. Use NewBufferChecked[T] to inspect an error or NewBufferWithOptions[T] to set an explicit per-buffer budget. The estimate includes the buffer header and backing array, but excludes allocator overhead and objects reachable through pointers in T. For zero-size T, no per-element bytes are counted, so the byte budget does not cap logical capacity. action.NewHistory and observe.NewMemorySink use the same budget; use action.NewHistoryChecked / action.NewHistoryWithOptions or observe.NewMemorySinkChecked / observe.NewMemorySinkWithOptions to inspect errors or select explicit budgets. Builder methods WithHistoryChecked / RecordHistoryChecked return allocation errors, while their WithOptions variants accept explicit limits. Legacy RecordHistory causes Do to return a configuration error rather than run without the requested history.


Basic Action Usage

Actions are typed generic functions wrapped with fluent middleware pipelines. Request and response types are inferred from the handler signature without reflection on the hot path:

package main

import (
    "context"
    "fmt"
    "time"

    "github.com/nexssp/kernel/action"
)

type UserRequest struct {
    ID string `json:"id"`
}

type User struct {
    ID   string `json:"id"`
    Name string `json:"name"`
}

func main() {
    lookupUser := action.New("user.lookup", func(ctx context.Context, req UserRequest) (User, error) {
        return User{ID: req.ID, Name: "Alice"}, nil
    }).
        Timeout(2 * time.Second).
        Retry(2, action.ExponentialBackoff(25*time.Millisecond, 2*time.Second)).
        Build()

    user, err := lookupUser.Do(context.Background(), UserRequest{ID: "usr-42"})
    if err != nil {
        panic(err)
    }

    fmt.Printf("User: %s (%s)\n", user.Name, user.ID)
}

Dynamic Dispatch and Reflection-Free Bridge

The Kernel supports type-erased and dynamic execution boundaries (such as AI tool-calling agents, plugin registries, and generic HTTP routers) without weakening typed internal handlers:

act := action.New("user.lookup", lookupHandler).Build()

// 1. Direct type-erased call: zero heap allocations when matching Req and Res are pointers.
//    A value-type Res may allocate when it is boxed into any.
result, err := act.DoAny(ctx, UserRequest{ID: "usr-42"})

// 2. Universal Invoker: automatically decodes and coerces dynamic payloads
result, err = action.InvokeAny(ctx, act, map[string]any{"id": "usr-42"})

// 3. Coerce: converts dynamic structures (JSON, maps, strings) into target types
req, err := action.Coerce[UserRequest](untypedInput)

// 4. Dynamic lifting: lifts AnyAction into *Builder[any, any] for composition
dynamicAct := action.Dynamic(act).Build()

Composition and Pipelines

  • Pipe[Req, Mid, Res] connects two actions sequentially (A → B).
  • PipeWith[Req, Mid1, Mid2, Res] connects two actions with an inline transformation function, avoiding intermediate adapter structs.
  • Chain[T] executes same-typed actions sequentially, piping output to input.
  • Branch and BranchAny route execution conditionally using a router function.
  • FirstSuccess runs fallback chains, returning the first non-error result.
  • Parallel executes typed actions concurrently over the same request (scatter-gather).
  • ParallelNamed and ParallelMap execute heterogeneous actions concurrently, collecting results into a map[string]any.
// Pipeline with zero-allocation inline field transform
pipeline := action.PipeWith("user.process",
    fetchUserAct,
    func(ctx context.Context, u User) (string, error) { return u.Email, nil },
    sendEmailAct,
).Build()

// Heterogeneous concurrent execution
reviewer := action.ParallelNamed[string]("review.suite", map[string]action.AnyAction{
    "security": checkSecurityAct,
    "linter":   runLinterAct,
}).Build()

results, err := reviewer.Do(ctx, "package main...")

Resilience, Concurrency, and Traffic Protection

Retries and Circuit Breaking

  • Retry retries only transient errors identified by xerr.IsTransient.
  • RetryIf evaluates an application-defined RetryPredicate(err error) bool.
  • RetryAll retries on any non-nil error (intended for idempotent batch jobs).
  • InferredResilient / SmartResilience configures an adaptive circuit breaker and exponential jitter retry driven automatically by xerr.Kind. It fast-fails 4xx errors (BadRequest, Unauthorized, Forbidden, NotFound, Validation) without consuming retries.
  • Adaptive applies a circuit breaker with dynamic timeout scaling and half-open state recovery.
  • Standalone and adaptive breakers count caller deadline expirations as failures; explicit caller cancellation is excluded. A handler that ignores its context can keep a half-open probe occupied until it returns.

Backoff Strategies

  • ExponentialBackoff(base, max) doubles wait duration per attempt.
  • ExponentialJitter(base, max) adds ±30% random jitter to mitigate thundering-herd spikes.
  • LinearBackoff(step) and ConstantBackoff(duration).

Concurrency and Traffic Shields

  • Dedup(keyFn) applies singleflight deduplication. Callers sharing a key block until active execution completes, receiving copies of the result. Context cancellation of a joined caller does not cancel the flight.
  • Coalesce(coalescer, keyFn) shares in-flight results across actions. A canceled waiter may exit without terminating the background execution for other callers.
  • ConcurrencyLimit(limit) enforces an in-process ceiling using atomic counters. Excess calls return ErrConcurrencyLimit.
  • RateLimit, RateLimitWithKey, and RateLimitDistributed provide token-bucket admission control.
  • AdaptiveLoadShedding evaluates system statistics (CPU percentage and goroutine count) against priority tiers (PriorityCritical, PriorityNormal, PriorityLow), dropping non-essential traffic when thresholds are exceeded.

Execution Primitives

  • FanOut(ctx, act, reqs, maxConcurrency) executes concurrent items while preserving input order in the returned slice. A non-positive concurrency limit uses DefaultAsyncMaxConcurrency (16), and the whole call is bounded by DefaultAsyncTimeout (2 minutes) unless the parent context ends sooner; use FanOutWithOptions to change either.
  • Race(ctx, act, reqs) returns the first successful result and cancels losing attempts. Handlers must cooperate with context cancellation.

Caching and Idempotency

Multi-Layer Read-Through Caching

Cache(ttl, keyFn, layers...) coordinates L1 (local memory) through LN (distributed) stores:

  • Cache hits return without invoking the underlying handler.
  • Cache misses execute the handler under singleflight protection to prevent cache stampedes.
  • Slower-layer hits automatically back-fill faster layers.
  • If no layers are passed, an internal thread-safe in-memory cache is instantiated. It evicts entries inline during Set and lazily during Get; it starts no janitor goroutine and requires no Close() call.
  • Once() memoizes the result or error of the first execution indefinitely for static configurations.

Idempotency Contracts

  • .Idempotent() and .IdempotentWithConfig(cfg) enable replay only when a caller supplies an explicit key. Transport adapters should read cfg.Header() (default Idempotency-Key) and bind it with xctx.WithIdempotencyKey(ctx, key). RequestID is correlation-only; neither it nor a payload hash is used as a fallback key. For typed requests, configure RequestKeyFunc; the older KeyFunc remains available for []byte requests.
  • Builder-created actions default Namespace to their final action name; direct IdempotencyMiddleware use requires an explicit namespace. Versioned v2 storage keys include the namespace and a fingerprint of tenant, user, and authorization scope, and do not store the raw client key. Because the persisted key format changed, old idempotency entries will not be replayed by this version; expire or migrate them as part of deployment.
  • MemoryIdempotencyStore provides in-memory reference coordination.
  • IdempotencyCoordinator defines atomic claim semantics (Claim, Complete, Release) with leased in-progress locks and request hash validation to detect duplicate payload conflicts.
  • Reusing a key for a different payload returns Conflict; corrupt responses or missing/corrupt saved request hashes fail closed instead of executing the handler again. Successful responses are replayed only until the configured TTL expires. Handler errors are not cached and may be retried; expired distributed claims may be taken over while the original handler is still running. Use downstream idempotency or fencing when repeating side effects is unsafe.
  • Same-process callers share one active execution. Shared work keeps the leader's context values but not its cancellation; coalescing and deduplication use DefaultSharedFlightTimeout (2 minutes), while idempotency uses IdempotencyConfig.FlightTimeout (default 2 minutes). Each caller can stop waiting on its own cancellation, but the synchronous leader call may remain blocked until the handler returns or the shared timeout expires. MaxConcurrentFlights bounds unique idempotency keys (default 256); no background handler goroutines are started.
  • This active-flight cap applies to Idempotency; Dedup and Coalesce do not expose a MaxConcurrentFlights limit. High-cardinality distinct keys can therefore grow their in-flight state without a configured bound under load; account for this when choosing those middleware for untrusted or bursty traffic.
  • Durable and idempotent results are persisted as JSON. For empty-interface result types, including named empty interfaces, the first successful call is normalized to the same standard values returned by JSON replay (numbers are float64, objects are map[string]any, arrays are []any, and typed nil pointers/maps/slices become nil). Concrete result types use normal encoding/json decoding into their declared Res type on replay. A non-empty interface generally cannot be reconstructed from JSON as its original concrete dynamic type, so use a concrete result type when replay must succeed; arbitrary dynamic Go types are not restored from persisted type names.
  • A Journal.RecordStep error or idempotency completion error can be ambiguous: the write may have committed before the error was returned. Durable journals do not guarantee exactly-once external side effects after an ambiguous write failure; use downstream idempotency/fencing or a storage protocol with definitive commit outcomes when repeats are unsafe.

Durable Execution Identity and Resume

  • DigestBytes and DigestString create fixed-size SHA-256 bindings without heap allocation on the comparison path.
  • ExecutionIdentity binds an execution to its execution namespace, source digest, input digest, and contract digest.
  • DurableWithResume extends Durable with journal-backed identity validation before replay.
  • A changed source or input returns an xerr.Conflict; callers may use ResumeOptions{Force: true, ForceReason: ...} to create an explicit successor generation.
  • ResumeJournal stores identity metadata alongside the existing Journal contract. Durable replay and singleflight remain owned by the shared Kernel runner.

Distributed Coordination and Sagas

Distributed Locks

  • Exclusive(mutex, ttl, keyFn) acquires an application-provided Mutex before execution and releases it upon completion. Contention returns ErrLocked.
  • LeaderOnly(mutex, ttl) runs the action under a fixed leader key.

Monotonic Fenced Coordination

  • ExclusiveFenced(fencedMutex, ttl, keyFn) and LeaderOnlyFenced acquire a LockLease containing a monotonically increasing fence counter.
  • An internal ticker renews the lease at ttl / 3. If lease renewal fails or the lease is lost, the action context is canceled immediately to abort in-flight work.
  • Handlers retrieve the lease via action.LeaseFromContext(ctx).

Contract Notice: Fencing is only effective if the downstream database or storage operation validates the token (e.g., UPDATE ... WHERE fence >= @fence). The Kernel coordinates lease lifecycle and cancellation; it cannot enforce fencing on storage engines that do not verify the token.

Sagas

action.NewSaga[Req, Res] coordinates distributed operations with compensating transactions:

  • AddStep(name, do, undo) registers forward work and its reverse compensation.
  • AddOptionalStep(name, do, undo) registers steps that may fail without triggering a saga abort.
  • If a mandatory step fails or panics, registered Undo functions execute in reverse order (LIFO) under an uncancelled context.
  • .AsAction() converts the compiled saga into an executable *BuiltAction[Req, SagaResult[Res]].

Streaming and State Machines

Pure O(1) Memory Streaming

action.NewStream wraps Go 1.23+ iter.Seq2 handlers under action lifecycle management. NewStreamOp composes typed stream actions, while StreamWorkerPool adds bounded per-item parallelism:

stream := action.NewStream("telemetry.stream", func(ctx context.Context, req Query) (iter.Seq2[Record, error], error) {
    return func(yield func(Record, error) bool) {
        for i := 0; i < req.Limit; i++ {
            if ctx.Err() != nil {
                yield(Record{}, ctx.Err())
                return
            }
            if !yield(Record{ID: i}, nil) {
                return // Consumer stopped early
            }
        }
    }, nil
})

seq, err := stream.Do(ctx, Query{Limit: 100})
for record, err := range seq {
    // Zero heap allocation streaming
}

CollectStream materializes an iterator into an in-memory slice when streaming is not required. The stream package also provides time-based grouping (BatchByTime), sliding windows, throttling, debouncing, distinct filtering, and context-aware operators. Use the supplied context; do not substitute context.Background() inside an operator.

State Machines

action.NewStateMachine guards entity lifecycle transitions:

  • Handlers implement StateEntity (GetState(), SetState()).
  • Allow(from, to...) registers permissible transitions.
  • Disallowed transitions are rejected with xerr.KindConflict before committing state changes.

Deterministic DAG Workflows (ai/dag)

The ai/dag package compiles directed acyclic graphs into deterministic, concurrent execution layers:

graph, err := dag.New("order.workflow").
    AddNode("validate", "val_out", validateAction).
    AddNode("reserve", "res_out", reserveAction).
    AddNode("charge", "chg_out", chargeAction).
    AddEdge("validate", "reserve").
    AddEdge("validate", "charge").
    Compile()
if err != nil {
    return err
}

initialState := dag.AcquireState()
defer initialState.Release()

finalState, err := graph.Execute(ctx, initialState)
if err != nil {
    return err
}
defer finalState.Release()

res, err := dag.GetNodeOutput[ReserveResult](finalState, "reserve")

DAG Characteristics

  • Cycle Detection: Compiles layers using Kahn's algorithm; circular dependencies return xerr.KindConflict.
  • Namespaced Outputs: Node outputs are stored under tasks.<node_id>.output to prevent key collisions during parallel execution.
  • Pooled State: State instances utilize sync.Pool. Read operations during layer execution are zero-lock. Callers must call state.Release() when finished.
  • Sub-graph Nesting: A compiled DAG can be converted into an action via .AsAction() and embedded directly as a node in a parent DAG.
  • Mermaid Export: graph.ToMermaid() exports deterministic, formatted Mermaid flowchart diagrams.

Checkpointing & Human-in-the-Loop (HIL) Resumption

Workflows that require asynchronous human intervention (approvals, manual reviews, external callbacks) are supported natively via dag.ErrSuspended:

// 1. Initial execution halts at approval step
state, err := graph.Execute(ctx, initialState)
if errors.Is(err, dag.ErrSuspended) {
    // Partial progress is preserved; persist state snapshot to storage
    db.SaveWorkflow(workflowID, state.Data())
    state.Release()
    return
}

// 2. Later: Resume after human approval
savedSnapshot := db.LoadWorkflow(workflowID)
resumeState := dag.AcquireState()
for k, v := range savedSnapshot { resumeState.Set(k, v) }
defer resumeState.Release()

// Completed node actions are skipped; routing is evaluated again from entry
finalState, err := graph.Execute(ctx, resumeState)
  • When a node returns dag.ErrSuspended, Execute returns (partialState, dag.ErrSuspended) without purging the state from memory.
  • A resumed dynamic DAG starts traversal again at its configured entry. Node actions whose output key (tasks.<nodeID>.output) is already present in State are skipped, but conditional-edge routers run again on each traversal.
  • A router must choose the same target for the same persisted state and stable graph configuration. Do not rely on time, randomness, or mutable external state when a resumed workflow must follow the same branch; a route may change intentionally when the persisted state or graph configuration changes.

Context, Security, and Categorized Errors

Request Scopes (xctx)

xctx manages request-scoped metadata without heap allocations on standard paths:

  • NewScope(parent) obtains a pooled *RequestScope. Call the returned cleanup() function upon request completion to return the scope to sync.Pool.
  • Context helpers provide typed accessors: WithUserID, WithTenantID, WithRoles, WithPermissions, WithFeatures, WithTraceID.
  • Request-scope setters, accessors, and authorization checks synchronize mutable metadata; direct field access through ScopeFrom remains the caller's synchronization responsibility.
  • Each accessor acquires a scope lock. For related multi-field reads, SnapshotFrom(ctx) takes one read lock and returns a detached identity/authorization snapshot; it clones role, permission, and feature slices (so it may allocate) and intentionally omits the separately locked trace-event ring. Use typed accessors for isolated reads; opt into a snapshot when a coherent multi-field view justifies the copy cost.
  • CloneForAsync(ctx) clones request metadata into a detached context, preserving tracing and identity while decoupling from the parent cancellation tree.

Atomic Filesystem Writes (xfs)

WriteFileAtomic syncs the parent directory after rename on POSIX and returns a sync error even though the rename may already have taken effect. Windows renames remain atomic but cannot be made crash-durable with directory fsync.

Security and Governance Guards

  • RequireAuth() rejects unauthenticated contexts (xerr.KindUnauthorized).
  • RequireTenant() requires a populated tenant ID.
  • RequireRole(role) and RequireAnyRole(roles...) enforce RBAC claims.
  • RequirePermission(perm) verifies granular permission strings (supports wildcard *).
  • RequireFeature(flags...) and RequireAnyFeature(flags...) evaluate feature toggles.
  • RequireCreationLimit(resource, checkFn) checks resource quotas on entity creation (ID == 0).
  • ImmutableWhen(guardFn, reason) aborts execution if an entity is in a locked/terminal state.
  • TrackPIIAccess(tracker, purpose) records personal data access reasons for regulatory compliance.
  • Audited(logger, category, detailsFn) records audit events upon successful action execution.
  • Transactional(runner) wraps execution inside an application-provided TxRunner.

Categorized Errors (xerr)

xerr provides structured error categories to drive consistent transport mapping and retry decisions:

// Categories: BadRequest, Unauthorized, Forbidden, NotFound, Conflict,
// Validation, TooManyRequests, Timeout, Unavailable, Internal, CircuitBreaker.
return xerr.NotFound("user not found")
return xerr.Unavailable("database connection dropped", originalErr)
  • xerr.IsTransient(err) checks whether an error is safe to retry.
  • xerr.From(err) converts arbitrary Go errors into structured *AppError types.
  • appErr.Public(requestID) returns a sanitized ErrorResponse suitable for API responses without leaking internal causes or stack traces.
  • Validation detail values are redacted; clients receive field names and validation rules without the submitted values.
  • xerr.Sprint(err) renders error trees with sanitized user stack traces in development (ENV=dev) and structured one-line outputs in production.

Observation and Lifecycle Telemetry

The optional observe package emits vendor-neutral lifecycle events. Sinks are concurrency-safe and receive structured observe.Event records with action Duration and complete Request/Response payload references for latency and token/cost attribution:

type fanoutSink struct{ sinks []observe.Sink }
func (f *fanoutSink) Emit(ctx context.Context, e observe.Event) {
    for _, s := range f.sinks { s.Emit(ctx, e) }
}

sink := &fanoutSink{sinks: []observe.Sink{
    observe.NewSlogSink(slog.Default()),
    observe.NewMetricsSink(),
    observe.NewPrometheusSink(),
    observe.NewMemorySink(100),
    observe.NewJSONLSink(os.Stdout, 4096),
}}

act := action.New("user.find", findUser).
    AnyHook(observe.Hook(sink)).
    Build()

Event Taxonomy

Kind Emitted When Relevant Event Fields
executed Action completes successfully Request, Response, Duration
error Action fails with an error Error, Duration
retry Retry middleware initiates another attempt Attempt, Error, Duration
cache_hit A cache layer serves the response Request, Response, Duration
cache_miss No cache layer contains the key Request, Duration
canceled Action observes caller context cancellation Request, Duration
panic Action recovers an unhandled panic Recovered, Request, Duration
deduplicated Concurrent duplicate waits on an existing flight Request, Duration
coalesced Concurrent caller receives a coalesced result Request, Duration

Every event includes Time, Duration, Kind, Action, and available correlation identifiers (ExecutionID, TraceID, SpanID).

  • Context cancellations emit canceled and are not duplicated as error events.
  • Recovered panics emit a panic event followed by an error event containing the resulting xerr.KindInternal error.
  • Nil hooks and no-op sinks evaluate with zero heap allocations on the hot path.

Built-in Sinks

  • MemorySink: Thread-safe circular ring buffer. Events() returns an isolated snapshot copy in oldest-to-newest order.
  • MetricsSink: Aggregates counters by action name and event kind. Snapshot() returns an isolated map.
  • PrometheusSink: Generates deterministic Prometheus exposition text with escaped labels.
  • JSONLSink: Synchronized structured JSON writer with serialized durations. Raw error and recovered panic text are replaced with [redacted].
  • SlogSink: Dispatches structured logs including duration through standard library log/slog.

Architectural Boundaries

The Kernel provides execution semantics and safety contracts; applications supply external integrations:

  • Storage & State: Cache backends, distributed locks, idempotency stores, and database transactions are supplied via interfaces. The Kernel does not bundle concrete database drivers.
  • Telemetry Ingestion: observe captures lifecycle events and execution duration locally. Forwarding events to OpenTelemetry collectors, Datadog, or external brokers belongs to application sinks.
  • Human-in-the-Loop & Workflows: The Kernel manages suspension (dag.ErrSuspended), partial state preservation, and memoized resumption. Applications supply the human interfaces (webhooks, email dispatch, approval dashboards) and durable persistence for state snapshots.
  • Durable Resume Binding: action.ExecutionIdentity binds replay to source, input, and contract digests. A mismatch is a conflict unless the caller explicitly requests a forced successor generation with a reason.
  • Security Decisions: Context guards inspect metadata attached to context.Context. Authentication (decoding JWTs, session lookups, certificate validation) is handled at transport boundaries.
  • Resource Ownership: Pooled objects (dag.State, xctx.RequestScope) must be explicitly released by the caller to prevent resource leaks.

Performance Model and Verification

The Kernel avoids reflection on execution paths, relies on immutable structures post-build, and compiles middleware chains at initialization time.

Streaming is O(1) in memory: StreamAction[Req, T] wraps Go 1.23 iter.Seq2[T, error] under action lifecycle management. The typed Do and DoStreamTyped paths do not allocate per item; the type-erased DoStreamAny boundary boxes each item into any and can allocate for non-pointer values. A constant per-call overhead is also paid (iterator closure, hook wrappers, panic recovery).

Benchmark and Quality Verification

Run the repository checks through Task, using the same targets as CI:

# Format
task fmt

# Lint and static analysis
task lint

# Run the race-enabled test gate
task test:race

# Benchmark core dispatch and allocation profiles
task bench

# Run the complete CI gate
task ci

Examples Reference

Complete, runnable examples are maintained in the central nexssp/examples repository. This repository keeps only examples/README.md as a pointer:


API Stability

v1.0.0-rc1 is a release candidate for 1.0. The exported API is considered feature-complete: until v1.0.0, only fixes for blocking defects are expected, and any API change will be called out in the CHANGELOG. Please try the candidate and report problems through GitHub issues.

From v1.0.0 the module follows Semantic Versioning: no breaking changes to exported APIs within v1.x. Symbols marked Deprecated: keep working for the lifetime of v1. Prior to 1.0 (v0.x), exported APIs could change between minor releases.

Pre-release versions are never selected automatically by go get; opt in explicitly:

go get github.com/nexssp/kernel@v1.0.0-rc1

Pin an explicit version rather than tracking main.

Contributing

Read CONTRIBUTING.md before opening a pull request. Changes must be typed, covered by tests, and include benchmarks for performance-critical paths.

Security

Report suspected vulnerabilities privately according to SECURITY.md.

License

Apache License 2.0. See LICENSE. Copyright © 2018–2026 Marcin Polak and Contributors.

About

Ultra-fast Go execution engine for resilient DAGs, typed actions, and hot-swappable workflows. Features constant-memory streaming and zero-allocation hot paths.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages