Skip to content

stablekernel/crucible

Crucible

Go Reference Go Report Card Go Version Docs

PRs welcome Contributor Covenant 2.1 OpenSSF Scorecard License: Apache 2.0

The Crucible sky-squid mascot

Forge event-driven services in Go.

Crucible is a multi-module Go toolkit for building event-driven services. Its design philosophy is thin seams, no-op defaults, no forced dependencies: every cross-cutting concern (logging, tracing, metrics, IDs, time) is a small, consumer-providable interface with a do-nothing default. You bring your logger, your tracer, your clock. Crucible never makes you adopt its choices, and never leaks a third-party type into a public signature.

The state engine is the extreme end of this: stdlib-only, with no injected IO at all. The IO modules carry the heavier seams via injection, but follow the same rule. Defaults are no-ops, nothing third-party is forced on the consumer.

Documentation

Guides, concepts, the food-delivery example, and the generated API reference live in the documentation site:

Modules

Each module is independently versioned (per-module SemVer) and carries its own stability label.

Module What it is Status
state Full-featured, domain-agnostic statechart engine. Stdlib-only, no IO. experimental
state/analysis Static model-checking and path enumeration over a machine's IR. experimental
state/evolution Diffs two machine definitions and classifies the SemVer bump. experimental
state/conformance Reusable harness for driving golden scenarios against a machine. experimental
state/expr Rich expression tier: CEL-backed guards type-checked against the context schema. experimental
telemetry Vendor-neutral tracing/metrics interface for the IO modules. Stdlib-only. experimental
telemetry/slog log/slog adapter for the telemetry interface. experimental
telemetry/otel OpenTelemetry adapter for the telemetry interface. experimental
telemetry/datadog Datadog adapter for the telemetry interface. experimental
broker Message broker seam: publish/subscribe transport with injected adapters. planned
sink Egress seam: fan emitted effects out to many destinations, fire-and-forget. experimental
source Ingress seam: consume streams and drive statecharts; ack on durable transition. experimental
source/kafka Kafka/RedPanda Inlet over franz-go: group consumer, mark-commit-after-process. experimental
source/jetstream NATS JetStream Inlet over nats.go: pull consumer, ack/nak/term, MaxAckPending. experimental
source/redis Redis Streams Inlet over go-redis: consumer group, XACK/pending-claim, DLQ. experimental
source/cloudevents CloudEvents codec with structured and binary content modes. experimental
source/cdc Change-data-capture codec: decode Debezium/OpenCDC change events, drive by key. experimental
source/statemachine Bridge: an inbound message drives a transition, ack tied to the durable commit. experimental

source also ships composable reliability middleware as its own opt-in modules (source/retry, source/dlq, source/idempotency, source/schema) and an in-memory source/memsource test source, each experimental.

Status

Early and evolving. state is a complete, embeddable statechart engine, covering hierarchical, parallel, and final states, history, guard combinators, delayed transitions, invoked services, an actor model, snapshots, and JSON (de)serialization, backed by its analysis, evolution, and conformance packages. telemetry, sink, and source (with all their adapters, codecs, and middleware) are released and documented; broker is planned. Treat every API as experimental until it reaches v1.

Roadmap

Two kinds of seam frame the work ahead, and both build on the engine without reaching into the kernel: the IO edges where effects leave and events arrive, and the serializable IR as a first-class artifact anything can read or write.

The kernel emits effects as pure data; a small family of bring-your-own-adapter IO seams moves events to and from the outside world, each defaulting to a no-op and forcing nothing third-party on the consumer:

  • broker (planned): pub/sub transport. Publish emitted events and subscribe machines to external streams.
  • sink: egress fan-out. Dispatch emitted effects to many outlets (SQL, Dynamo, StatsD, and more), fire-and-forget. Docs.
  • source: ingress. Subscribe external streams and drive machines, with the ack tied to a durable transition; the symmetric counterpart to sink. Docs. The source/cdc codec decodes Debezium/OpenCDC change-event topics into typed change events; a native database write-ahead-log connector (logical replication slot, binlog) remains future work.

A small set of tools works the IR directly:

  • Visual editor (planned): a browser workbench over the IR. Author, simulate, and inspect machines, with reachability and version-diff overlays from the existing analysis and evolution packages.
  • IR CLI (exploring): headless IR tooling for CI. Lint reachability and nondeterminism, render diagrams, and classify version diffs straight from a machine's IR.

Durable state and event persistence is tracked separately with the durable runtime, not here.

Contributing

Contributions are welcome. See CONTRIBUTING.md for dev setup, the Mage targets, conventional commits, and the DCO sign-off requirement. By participating you agree to the Code of Conduct.

License

Licensed under the Apache License, Version 2.0. See NOTICE for attribution.

About

Forge event-driven services in Go

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Contributors

Languages