Documentation
¶
Overview ¶
Package contracts defines the stable interfaces between MuxCore and its modules. These interfaces form the v1 contract boundary.
STABILITY GUARANTEE (v1)
All exported types, interfaces, constants, and functions in this package are frozen for the v1 lifetime. Breaking changes — including but not limited to adding or removing interface methods, changing struct fields, or modifying constant values — require a v2 major version.
The following are NOT covered by this guarantee:
- Types explicitly marked "RESERVED" or "Experimental" in their doc comment
- The `eventschema.go` file (reserved for future schema-evolution support)
IMPLEMENTING CONTRACTS ¶
Modules implement these interfaces and register with core via gRPC. Each contract has a corresponding capability string for runtime discovery (see capabilities.go). Modules do not import core binary — they only import this contracts package and the proto-generated Go types.
IMPORT PATH ¶
This package is released as a standalone Go module so that module authors can depend on it without pulling in the full core dependency tree:
require github.com/Muxcore-Media/core/pkg/contracts v1.0.0
All feedback: https://github.com/Muxcore-Media/core/issues
Index ¶
- Constants
- Variables
- func ReplyEventType(eventType string) string
- func SensitiveLogFieldNames() []string
- type Action
- type AtomicMovable
- type AuditEntry
- type AuditFilter
- type AuditLogger
- type AuthProvider
- type Authorizer
- type BackupInfo
- type BackupProvider
- type Backupable
- type CacheLayer
- type CacheProvider
- type CallPolicyProvider
- type ChainVerificationResult
- type CircuitBreaker
- type CircuitState
- type Cluster
- type ClusterEvent
- type ClusterEventType
- type ConfigWatcher
- type ContractDeclaration
- type Counter
- type CredentialType
- type Credentials
- type DataRedactionProvider
- type DatabaseParams
- type DatabaseProvider
- type DeadLetterEntry
- type DeadLetterProvider
- type DistributedLockHandle
- type DistributedLockProvider
- type EncryptionProvider
- type Event
- type EventBus
- type EventHandler
- type EventStore
- type EventStoreEntry
- type Executor
- type FeatureFlagProvider
- type Gauge
- type Hardlinkable
- type HealthMonitor
- type Histogram
- type IdempotencyProvider
- type Identity
- type IdentityProvider
- type InputValidator
- type LBStrategy
- type LeaderChangedPayload
- type LockHandle
- type LogLevel
- type MeshHandler
- type MetricsProvider
- type Migration
- type Module
- type ModuleDegradedPayload
- type ModuleEntry
- type ModuleInfo
- type ModuleKind
- type ModuleMeshClient
- type ModuleRegisteredPayload
- type ModuleState
- type ModuleUnregisteredPayload
- type NodeInfo
- type NodeJoinedPayload
- type NodeLeftPayload
- type ObjectInfo
- type Permission
- type PublishPolicyProvider
- type RateLimiterProvider
- type RedactingLogger
- type Registry
- type ResourceAuthorizer
- type ResourceDescriptor
- type ResourcePublishPolicyProvider
- type RetryPolicy
- type RetryProvider
- type Rows
- type Scheduler
- type SchedulerTask
- type SchedulerTaskFilter
- type SchedulerTaskStatus
- type SecretsProvider
- type Seekable
- type SerializationProvider
- type Session
- type SettingDef
- type SettingType
- type SettingsProvider
- type Span
- type SpanStatusCode
- type SpoolResolver
- type StepCompletedPayload
- type StepFailedPayload
- type StepHandler
- type StepHandlerKind
- type StepResult
- type StepStartedPayload
- type StorageEvent
- type StorageEventType
- type StorageOrchestrator
- type StorageProvider
- type StorageTier
- type Streamable
- type StructuredLogger
- type TagDefinition
- type TagModule
- type TapestryCompletedPayload
- type TapestryDefinition
- type TapestryFailedPayload
- type TapestryRun
- type TapestryRunFilter
- type TapestryStartedPayload
- type TapestryStatus
- type TapestryStep
- type TierTransitionPayload
- type TieredProvider
- type TracingProvider
- type Tx
- type ValidationResult
- type Watchable
- type WorkerPool
- type WorkerTask
- type WorkerTaskFilter
- type WorkerTaskStatus
- type WorkflowEngine
Constants ¶
const ( CapabilitySecrets = "secrets" CapabilityDatabase = "database" CapabilityCache = "cache" CapabilityCacheLocal = "cache.local" CapabilityMetrics = "metrics" CapabilityTracing = "tracing" CapabilityCircuitBreaker = "circuitbreaker" CapabilityConfigWatcher = "config.watcher" CapabilityDeadLetter = "deadletter" CapabilityCallPolicy = "call.policy" CapabilityPublishPolicy = "publish.policy" CapabilityIdentity = "identity" CapabilityLogging = "logging" CapabilityRetry = "retry" CapabilityIdempotency = "idempotency" CapabilityFeatureFlags = "feature.flags" CapabilitySerialization = "serialization" CapabilityEncryption = "encryption" CapabilityDistributedLock = "distributed.lock" CapabilityDataRedaction = "data.redaction" CapabilityEventStore = "event.store" CapabilityInputValidate = "input.validate" CapabilityWorkflowEngine = "workflow.engine" CapabilitySpoolResolver = "spool.resolver" CapabilityScheduler = "scheduler" CapabilityHealthMonitor = "health.monitor" CapabilityBackup = "backup" // Worker pool capabilities. CapabilityWorkerPool = "worker.pool" // CapabilityExecutorPrefix is the prefix for executor discovery. // Modules handling task type "download" advertise "executor.download". CapabilityExecutorPrefix = "executor." // Auth/security capabilities. CapabilityAuth = "auth" CapabilityAuthorizer = "authorizer" CapabilityRateLimiter = "ratelimit" )
Capability strings for all discoverable services. Use these constants with Registry.FindByCapability and in ModuleInfo.Capabilities to avoid silent typo failures.
const ( EventClusterNodeJoined = "cluster.node.joined" EventClusterNodeLeft = "cluster.node.left" EventClusterNodeDegraded = "cluster.node.degraded" EventClusterLeaderChanged = "cluster.leader.changed" )
Cluster event types for the event bus.
const ( EventModuleRegistered = "module.registered" EventModuleUnregistered = "module.unregistered" EventModuleDegraded = "module.degraded" EventConfigReloaded = "config.reloaded" )
Module-lifecycle event types — the only domain event types core knows about. Cluster events are in cluster.go. All other event types are in contract repos.
const ( SafeContentTypeJSON = "application/json" SafeContentTypeProtobuf = "application/x-protobuf" SafeContentTypeMsgpack = "application/msgpack" )
SafeSerializationTypes enumerates content types that are considered safe for deserialization. These formats do not support code-execution gadgets or type-confusion attacks in their standard Go implementations.
Formats NOT in this list (e.g., "application/yaml", "application/gob", "application/x-java-serialized-object") MUST NOT be supported by SerializationProvider implementations unless explicit sandboxing is applied and documented.
const ( EventTapestryStarted = "tapestry.started" EventTapestryCompleted = "tapestry.completed" EventTapestryFailed = "tapestry.failed" EventTapestryCancelled = "tapestry.cancelled" EventTapestryPaused = "tapestry.paused" EventTapestryResumed = "tapestry.resumed" EventStepStarted = "tapestry.step.started" EventStepCompleted = "tapestry.step.completed" EventStepFailed = "tapestry.step.failed" )
Tapestry lifecycle event types — defined here so both core and modules can reference them without a separate contract repo for workflow.
const EventSchemaVersion = "v1"
EventSchemaVersion is the schema version for event payloads. Defined for future typed-payload support. Currently the event bus uses raw []byte Payload and this constant is not consumed at runtime.
const EventStorageTierTransition = "storage.tier.transition"
EventStorageTierTransition is emitted when an object moves between tiers.
Variables ¶
var ErrCallDenied = errors.New("call policy: access denied")
ErrCallDenied is returned when a call policy provider denies access. This is distinct from ErrCallNoPolicy which means no provider is registered.
var ErrCallNoPolicy = errors.New("call policy: no provider registered — calls are denied by default")
ErrCallNoPolicy is returned when no CallPolicyProvider is registered. In production, the mesh MUST reject cross-module calls when no provider is present rather than defaulting to open mode. This error signals that the deployment is missing a required security component.
var ErrCircuitOpen = errors.New("circuit breaker is open")
ErrCircuitOpen is returned by CircuitBreaker.Execute when the circuit is open and the call is rejected without execution.
var ErrDatabaseCredentialExposure = errors.New("database: credential passed as raw string — use DatabaseParams instead")
ErrDatabaseCredentialExposure is a sentinel error that DatabaseProvider implementations SHOULD return if they detect that credentials were passed as a raw connection string. This enables CI lint rules to detect unsafe database initialization.
var ErrLockHeld = errors.New("distributed lock: key is already held")
ErrLockHeld is returned by DistributedLockProvider.Acquire when the requested key is already locked by another client.
var ErrMigrationTargetNotFound = errors.New("database: target migration version not found")
ErrMigrationTargetNotFound is returned by DatabaseProvider.Rollback when the targetVersion does not exist in the provider's migration list.
var ErrNoCandidates = errors.New("load balancing: no candidate nodes available")
ErrNoCandidates is returned by LBStrategy.Pick when the candidate list is empty.
var ErrNotFound = errors.New("object not found")
ErrNotFound is returned by storage providers when a key does not exist. Use errors.Is(err, contracts.ErrNotFound) to check.
var ErrRollbackNotSupported = errors.New("database: rollback not supported by this provider")
ErrRollbackNotSupported is returned by DatabaseProvider.Rollback when the provider does not implement rollback functionality.
Functions ¶
func ReplyEventType ¶
ReplyEventType returns the event type that Request/reply handlers listen on. Responders publish a reply event with this type; Request waits for it.
bus.Subscribe(ctx, contracts.ReplyEventType("media.requested"), handler)
func SensitiveLogFieldNames ¶
func SensitiveLogFieldNames() []string
SensitiveLogFieldNames returns a copy of the curated list of field name prefixes that commonly carry credentials, tokens, or PII. Redaction providers and logging implementations SHOULD use this list as a default deny-set.
This list is not exhaustive — implementations may extend it based on their domain. The convention is lowercase field names as they appear in structured log fields.
Types ¶
type Action ¶
type Action string
Action represents an operation a caller wants to perform. Standard verbs: "create", "read", "update", "delete", "list", "execute".
type AtomicMovable ¶
type AuditEntry ¶
type AuditEntry struct {
ID string
Timestamp time.Time
Actor string // user ID, "system", or module ID
Action string // e.g., "http.request", "module.registered", "media.requested"
Resource string // e.g., "/api/movies", "admin-ui", "Inception"
ResourceID string // UUID of the affected resource, if applicable
Details map[string]string // arbitrary context — MUST NOT contain credentials or PII
TraceID string
NodeID string
// PrevEntryHash is the SHA-256 hash of the chronologically previous audit entry.
// This forms a tamper-evident hash chain. Zero value for the first entry in a log.
PrevEntryHash string
// Signature is an optional HMAC-SHA256 over the entry fields using a root key.
// Enables verification that the entry was produced by an authorized audit logger.
// Empty if the audit logger does not support cryptographic signing.
Signature string
}
AuditEntry is a single audit log record.
type AuditFilter ¶
type AuditFilter struct {
Actor string
Action string
Resource string
From time.Time
To time.Time
TraceID string
// VerifyChain, when true, instructs Query to validate the hash chain
// of returned entries and exclude or flag entries with broken links.
VerifyChain bool
}
AuditFilter narrows audit queries.
type AuditLogger ¶
type AuditLogger interface {
// Log records an audit entry.
//
// SECURITY: Details MUST NOT contain credentials, tokens, or PII.
// The caller is responsible for redacting sensitive data before
// calling Log. Use DataRedactionProvider if the details map is
// built from untrusted input.
Log(ctx context.Context, entry AuditEntry) error
// Query returns entries matching the filter.
Query(ctx context.Context, filter AuditFilter) ([]AuditEntry, error)
// Export writes all entries in the given format (json, csv).
Export(ctx context.Context, format string) (io.ReadCloser, error)
// VerifyChainIntegrity performs a standalone integrity check on the
// audit log hash chain in the given time range. Unlike Query with
// VerifyChain=true, this method does not return entry data — it only
// returns the verification result. This enables independent integrity
// audits without exposing audit content to the verifier.
//
// If the provider does not support hash chains, this method returns
// a result with Valid=true and TotalEntries=0 (no chain to verify).
VerifyChainIntegrity(ctx context.Context, from, to time.Time) (ChainVerificationResult, error)
// VerifyAll performs a full integrity check across all surviving
// rotated audit log files and the current active file, verifying
// the hash chain and HMAC signatures across file boundaries.
//
// Entries in the deleted oldest rotated file (if any) are reported
// in UnverifiableCount. The active file is snapshotted at call time;
// entries written concurrently are not included.
VerifyAll(ctx context.Context) (ChainVerificationResult, error)
}
AuditLogger records and queries audit entries.
type AuthProvider ¶
type AuthProvider interface {
// Authenticate verifies credentials and returns a session if valid.
// The returned Session.Token is the bearer token for subsequent
// Validate calls.
Authenticate(ctx context.Context, credentials Credentials) (Session, error)
// Validate checks whether a token is still valid and returns the
// associated session. Returns an error if the token is expired,
// revoked, or malformed.
//
// SECURITY: The token parameter MUST NOT be logged. Use a
// cryptographically safe prefix (first 8 chars of SHA-256) for
// audit trail references.
Validate(ctx context.Context, token string) (Session, error)
// Revoke invalidates a token so it can no longer be used for
// Validate calls. Already-established sessions are not affected
// until their next Validate.
Revoke(ctx context.Context, token string) error
}
AuthProvider authenticates callers and validates existing sessions.
SECURITY: Implementations MUST NOT log tokens. The token parameter on Validate and the Token field on Session are sensitive material. If you need to log authentication events, use AuditLogger with redacted token references (e.g., a SHA-256 prefix of the token).
type Authorizer ¶
type Authorizer interface {
// Can performs a permission check using a flat (action, resource) pair.
//
// SECURITY: The session parameter contains a raw token. Authorizer
// implementations MUST NOT log or store the full Session struct.
// Use session.Safe() if identity information is needed for audit.
Can(ctx context.Context, session Session, action string, resource string) (bool, error)
}
Authorizer checks whether a session is permitted to perform an action on a resource.
For resource-level checks with ABAC support, implement the optional ResourceAuthorizer interface alongside Authorizer. Callers that need resource-level authorization type-assert to ResourceAuthorizer and fall back to Authorizer.Can if it's not supported.
type BackupInfo ¶
type BackupInfo struct {
ID string
Timestamp time.Time
Size int64
Modules []string // module IDs included in the backup
}
BackupInfo describes a completed backup.
type BackupProvider ¶
type BackupProvider interface {
// CreateBackup captures state from all registered Backupable modules.
CreateBackup(ctx context.Context) (BackupInfo, error)
// Restore restores state from a previous backup.
Restore(ctx context.Context, backupID string) error
// ListBackups returns all available backups.
ListBackups(ctx context.Context) ([]BackupInfo, error)
// DeleteBackup removes a stored backup.
DeleteBackup(ctx context.Context, backupID string) error
}
BackupProvider is implemented by backup modules (backup-local, backup-s3, etc.)
type Backupable ¶
type Backupable interface {
// ExportState returns serialized state for backup.
ExportState(ctx context.Context) ([]byte, error)
// ImportState restores state from a backup.
ImportState(ctx context.Context, data []byte) error
}
Backupable is implemented by modules that have state to back up.
type CacheLayer ¶
type CacheLayer interface {
// Get returns cached data for the given key. The bool indicates a cache hit.
Get(ctx context.Context, key string) ([]byte, bool)
// Set caches data for the given key.
Set(ctx context.Context, key string, data []byte) error
// Invalidate removes all cached entries whose key has the given prefix.
Invalidate(ctx context.Context, prefix string) error
}
CacheLayer is an optional read-through cache for the storage orchestrator. Unlike CacheProvider (distributed caches for application state), CacheLayer provides local caching for storage objects. Implemented by cache-memory and similar modules. Core discovers a CacheLayer at bootstrap; if none is found, the orchestrator operates without a cache.
type CacheProvider ¶
type CacheProvider interface {
// Get retrieves a value by key. Returns nil, nil if the key does not exist.
Get(ctx context.Context, key string) ([]byte, error)
// Set stores a value with an optional TTL. Zero TTL means no expiration.
Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
// Delete removes one or more keys.
Delete(ctx context.Context, keys ...string) error
// Exists checks whether a key exists.
Exists(ctx context.Context, key string) (bool, error)
// Incr atomically increments an integer key by delta and returns the new value.
Incr(ctx context.Context, key string, delta int64) (int64, error)
// CompareAndSwap atomically replaces oldValue with newValue at key.
// Returns true if the swap succeeded (key held oldValue), false otherwise.
// A nil oldValue matches a non-existent key.
CompareAndSwap(ctx context.Context, key string, oldValue, newValue []byte) (bool, error)
// Lock acquires a distributed lock on a key. Returns a Lock handle.
// If the key is already locked, returns an error immediately (non-blocking).
Lock(ctx context.Context, key string, ttl time.Duration) (LockHandle, error)
// Publish sends a message on a pub/sub channel.
Publish(ctx context.Context, channel string, msg []byte) error
// Subscribe returns a channel that receives messages published on the given channel.
Subscribe(ctx context.Context, channel string) (<-chan []byte, error)
}
CacheProvider is implemented by cache modules (cache-redis, cache-valkey, etc.) to provide ephemeral state, distributed locks, and pub/sub. Core defines the contract; modules provide the driver.
type CallPolicyProvider ¶
type CallPolicyProvider interface {
// AllowCall returns (true, nil) if caller is permitted to invoke method on target.
// Returns (false, nil) if access is denied, or (false, error) if the policy engine
// encountered an error (transient failure, configuration issue, etc.).
AllowCall(ctx context.Context, callerModuleID, targetModuleID, method string) (bool, error)
}
CallPolicyProvider determines whether one module is allowed to call another. Implemented by modules that define inter-module access control. The mesh client consults this before dispatching calls.
SECURITY: When no CallPolicyProvider is registered, the mesh MUST deny all cross-module calls and return ErrCallNoPolicy. This is a change from the previous behavior where the default was open mode. Deployments that want open mode must register an explicit permissive policy provider.
Discovered via FindByCapability(CapabilityCallPolicy). Only one policy provider is consulted — if multiple register, the first found wins.
type ChainVerificationResult ¶
type ChainVerificationResult struct {
// Valid is true if the entire chain is intact with no broken links.
Valid bool
// TotalEntries is the number of entries in the verified range.
TotalEntries int
// UnverifiableCount is the number of entries that existed in the oldest
// rotated file which was deleted before verification. These entries
// cannot be verified and are not counted in TotalEntries.
UnverifiableCount int
// BrokenLinks is the list of entry IDs where the PrevEntryHash does
// not match the computed hash of the previous entry.
BrokenLinks []string
// FirstBrokenAt is the timestamp of the first detected break, or
// the zero time if no breaks were found.
FirstBrokenAt time.Time
}
ChainVerificationResult reports the outcome of a hash-chain integrity check.
type CircuitBreaker ¶
type CircuitBreaker interface {
// Execute runs fn within the circuit identified by key.
// If the circuit is open, returns ErrCircuitOpen immediately.
// If fn returns an error, the failure is recorded against the circuit.
Execute(ctx context.Context, key string, fn func(context.Context) error) error
// State returns the current state of the circuit identified by key.
State(key string) CircuitState
}
CircuitBreaker protects downstream calls from cascading failures. When a downstream module degrades, the circuit opens and calls fail fast instead of waiting for timeouts. After a configurable cooldown (module-defined), the circuit transitions to half-open to test recovery.
Modules that call other modules via Mesh.Call() wrap those calls in Execute() to gain circuit breaking without implementing it themselves.
type CircuitState ¶
type CircuitState string
CircuitState represents the current state of a circuit breaker.
const ( // CircuitClosed — normal operation, requests flow through. CircuitClosed CircuitState = "closed" // CircuitOpen — failing, requests are rejected immediately with ErrCircuitOpen. CircuitOpen CircuitState = "open" // CircuitHalfOpen — testing if the downstream has recovered. // A single success transitions back to closed; a failure re-opens. CircuitHalfOpen CircuitState = "half_open" )
type Cluster ¶
type Cluster interface {
// Start joins or forms a cluster. If no seed nodes are reachable,
// the node starts a new single-node cluster.
Start(ctx context.Context) error
// Stop gracefully leaves the cluster.
Stop(ctx context.Context) error
// Members returns all current cluster members.
Members() []NodeInfo
// Leader returns the current leader, or nil if unknown.
Leader() *NodeInfo
// LocalNode returns information about this node.
LocalNode() NodeInfo
// Events returns a channel that emits cluster membership changes.
Events() <-chan ClusterEvent
// Health checks whether the cluster is operational.
Health(ctx context.Context) error
// FindNodesByLabel returns all nodes with the given label value.
FindNodesByLabel(ctx context.Context, label, value string) []NodeInfo
// FindNodesByModule returns all nodes running the given module.
FindNodesByModule(ctx context.Context, moduleID string) []NodeInfo
}
Cluster manages node membership, leader election, and peer discovery.
type ClusterEvent ¶
type ClusterEvent struct {
Type ClusterEventType
Node NodeInfo
LeaderID string
}
ClusterEvent is emitted when cluster membership changes.
type ClusterEventType ¶
type ClusterEventType string
ClusterEventType describes the kind of membership change.
const ( ClusterNodeJoined ClusterEventType = "node.joined" ClusterNodeLeft ClusterEventType = "node.left" ClusterNodeDegraded ClusterEventType = "node.degraded" ClusterLeaderChanged ClusterEventType = "leader.changed" )
type ConfigWatcher ¶
type ConfigWatcher interface {
// OnChange registers a handler that fires when modules matching the
// given capability string are added or removed. Returns a cancel
// function to stop watching. The handler receives no arguments —
// the module is expected to re-query the registry for current state.
OnChange(ctx context.Context, capability string, handler func()) (cancel func())
}
ConfigWatcher notifies modules when infrastructure services change at runtime. Modules subscribe by capability string; when a new module registers or an existing one disappears, registered handlers fire.
Modules use this instead of polling the registry. Example:
watcher.OnChange(ctx, "secrets", func() {
entries := reg.FindByCapability("secrets")
if len(entries) > 0 {
secrets = entries[0].Module.(contracts.SecretsProvider)
}
})
ConfigWatcher is discovered via FindByCapability("config.watcher"). If no module implements it, modules fall back to polling or subscribe to module.registered/module.unregistered events directly.
type ContractDeclaration ¶
type ContractDeclaration struct {
Repo string // Go module path of the contract package
Version string // semantic version tag (e.g. "v1.0.0")
Interface string // Go interface name the module implements (e.g. "Downloader")
}
ContractDeclaration describes a typed contract that a module implements. Modules declare these in their Info() so consumers can verify compatibility before attempting type assertions. The marketplace uses these to detect incompatibilities between installed modules and prospective modules.
type Counter ¶
type Counter interface {
Inc()
Add(delta float64)
}
Counter is a monotonically increasing metric.
type CredentialType ¶
type CredentialType string
CredentialType enumerates well-known authentication schemes. Implementations MUST validate the type against this set to prevent credential-type confusion attacks (e.g., an attacker sending a password in a "token"-typed credential).
const ( CredentialTypePassword CredentialType = "password" CredentialTypeToken CredentialType = "token" CredentialTypeCert CredentialType = "cert" CredentialTypeAPIKey CredentialType = "api-key" )
type Credentials ¶
Credentials carries authentication material to the AuthProvider. Type identifies the credential scheme and Data holds the opaque credential payload.
SECURITY: Implementations MUST NOT log the Data field. Callers MUST NOT include credentials in structured log fields, audit entries, or event payloads. Use the SecretsProvider contract to store and retrieve credentials instead of passing them through application code.
Backward-compat: Credentials.Type remains string (not CredentialType) so existing providers that use custom type strings continue to work. New implementations SHOULD validate against the CredentialType constants.
type DataRedactionProvider ¶
type DataRedactionProvider interface {
// Redact returns a new map with sensitive values replaced according
// to the given rules. The input map is not modified. Rules are
// provider-specific identifiers; the provider silently ignores
// rules it doesn't recognize.
Redact(ctx context.Context, data map[string]any, rules []string) (map[string]any, error)
}
DataRedactionProvider redacts sensitive data from structured payloads before they are logged, audited, or stored. This contract exists so modules never write PII (emails, IP addresses, tokens, personal data) to plaintext logs or audit trails.
Modules call Redact on any map[string]any before passing it to StructuredLogger, AuditLogger, or any persistent storage. The provider applies configured rules to replace sensitive values with redacted placeholders.
The rules parameter is an opaque list of rule identifiers that the provider interprets. Common patterns: field-name matching ("email", "password"), path expressions ("user.address.street"), regex patterns ("/\\d{3}-\\d{2}-\\d{4}/"), or category tags ("pii", "phi"). The provider documents which rule syntax it supports.
This contract is provider-agnostic: a module that calls Redact works identically whether the backend uses regex, field-name allowlists, an external DLP service, or a future redaction engine.
If no DataRedactionProvider is registered, Redact returns the input unchanged — modules degrade without nil checks but SHOULD document that redaction is inactive.
type DatabaseParams ¶
type DatabaseParams struct {
// Driver is the database driver name (e.g., "postgres", "sqlite3").
Driver string
// Host is the database server address (host:port or socket path).
Host string
// Database is the database name.
Database string
// User is the database username.
User string
// Password is the database password. Leave empty for passwordless auth.
//
// SECURITY: Never log this field. Fetch the password from
// SecretsProvider at connection time rather than storing it in
// application state.
Password string
// Extra carries driver-specific connection parameters (e.g., sslmode,
// connect_timeout). These are appended to the DSN after the core params.
// Keys and values in Extra must not contain credentials.
Extra map[string]string
}
DatabaseParams separates connection parameters from credentials. Use this struct with DatabaseProvider.Open instead of passing a raw connection string. This prevents accidental credential exposure in logs, stack traces, and configuration serialization.
SECURITY: The Password field is a plain string — implementations MUST NOT log DatabaseParams or any field within it. If the database driver supports credential-free authentication (IAM, workload identity, certificate-based auth), prefer those methods and leave Password empty.
type DatabaseProvider ¶
type DatabaseProvider interface {
// Open initializes the database connection using separated connection
// parameters. This isolates credentials from connection metadata,
// reducing the risk of accidental credential exposure.
//
// Implementations SHOULD return ErrDatabaseCredentialExposure if
// the caller attempts to embed credentials in Extra.
Open(ctx context.Context, params DatabaseParams) error
// Close gracefully shuts down the database connection.
Close(ctx context.Context) error
// Health checks whether the database is reachable.
Health(ctx context.Context) error
// Exec runs a statement that modifies data (INSERT, UPDATE, DELETE, DDL).
//
// SECURITY: Callers MUST use parameterized queries. Never concatenate
// user input into the query string. The args ...any parameter supports
// standard SQL placeholders ($1, ?, :name). Consider using
// InputValidator with "sql:<param-count>" schema for additional
// injection protection.
Exec(ctx context.Context, query string, args ...any) (int64, error)
// Query runs a read query and returns a row iterator.
//
// SECURITY: Same parameterization requirement as Exec. All user
// input MUST be passed via args, never interpolated into query.
Query(ctx context.Context, query string, args ...any) (Rows, error)
// Transaction runs fn inside a database transaction, committing on success and rolling back on error.
Transaction(ctx context.Context, fn func(Tx) error) error
// Migrate applies ordered schema migrations. Implementations track which migrations
// have already been applied and skip those.
//
// SECURITY: Migration SQL (Up/Down strings) is trusted schema code.
// Implementations SHOULD verify migration content against a known
// checksum or signature before execution when operating in production.
Migrate(ctx context.Context, migrations []Migration) error
// Rollback reverts schema migrations down to the given target version
// by applying Down SQL in reverse version order. targetVersion of 0
// rolls back all migrations (empty schema). Returns nil if no rollback
// is needed (current version <= targetVersion). Returns
// ErrMigrationTargetNotFound if targetVersion does not exist in the
// migrations list. Returns ErrRollbackNotSupported if the provider
// does not implement rollback.
//
// Implementations MUST apply Down SQL within transactions and track
// the current schema version in their migrations tracking table.
// They MUST reject rollback past version 0 (dropping below baseline).
Rollback(ctx context.Context, targetVersion int) error
}
DatabaseProvider is implemented by database modules (database-postgres, database-sqlite, etc.) to provide persistent storage for modules. Core defines the contract; modules provide the driver.
Discovered via FindByCapability(CapabilityDatabase).
type DeadLetterEntry ¶
type DeadLetterEntry struct {
Event Event
HandlerName string
Error string
FailedAt time.Time
RetryCount int
}
DeadLetterEntry stores a failed event with its error context.
type DeadLetterProvider ¶
type DeadLetterProvider interface {
// Store records a failed event delivery. Called by the event bus
// or by modules that want explicit dead-letter handling.
Store(ctx context.Context, event Event, handlerName string, err error) error
// Replay returns failed events for the given handler since the given time.
// Sorted by FailedAt ascending.
Replay(ctx context.Context, handlerName string, since time.Time) ([]DeadLetterEntry, error)
// Discard removes a failed event from the dead letter store after
// the issue has been resolved.
Discard(ctx context.Context, eventID string) error
}
DeadLetterProvider stores events that failed to process so they can be inspected, replayed, or discarded. Modules that handle critical events (workflow steps, downloads, imports) can configure a dead letter provider to prevent silent data loss when a handler transiently fails.
DeadLetterProvider is discovered via FindByCapability("deadletter"). If no module implements it, failed events are logged and dropped.
type DistributedLockHandle ¶
type DistributedLockHandle interface {
// Unlock releases the lock. Safe to call multiple times.
Unlock(ctx context.Context) error
// Renew extends the lock's TTL without releasing and re-acquiring.
// Useful for long-running operations where the initial TTL would expire
// before completion. Returns ErrLockHeld if the lock was lost (e.g.,
// network partition caused the backend to expire it).
Renew(ctx context.Context, ttl time.Duration) error
}
DistributedLockHandle represents an acquired distributed lock. Callers must call Unlock when done, or Renew to extend the lease for long-running operations.
type DistributedLockProvider ¶
type DistributedLockProvider interface {
// Acquire attempts to acquire a lock for the given key with a TTL.
// Returns (nil, ErrLockHeld) if the key is already locked.
// Returns (nil, ctx.Err()) if the context is cancelled before acquisition.
// The returned handle must be Unlock()ed when the critical section completes.
Acquire(ctx context.Context, key string, ttl time.Duration) (DistributedLockHandle, error)
}
DistributedLockProvider provides standalone distributed locking. This is distinct from CacheProvider.Lock which ties locking to a cache instance. Modules that need coordination (leader election, singleton workers, migration gating, split-brain fencing) use this contract without needing to stand up a cache.
This contract is provider-agnostic: a module that calls Acquire works identically whether the backend is Redis, etcd, Consul, Postgres advisory locks, or a future coordination service.
Acquire is non-blocking by design. If the lock is held, it returns ErrLockHeld immediately. Callers that want blocking behavior compose this with RetryProvider.Execute.
If no DistributedLockProvider is registered, Acquire always succeeds (single-node mode) — modules degrade gracefully without nil checks.
type EncryptionProvider ¶
type EncryptionProvider interface {
// Encrypt encrypts plaintext and returns self-describing ciphertext.
// The returned bytes include key version metadata so Decrypt can
// identify the correct key even after rotation.
Encrypt(ctx context.Context, plaintext []byte) ([]byte, error)
// Decrypt decrypts ciphertext that was produced by Encrypt.
// The provider reads key metadata from the ciphertext to select
// the correct decryption key, including keys from previous rotations.
Decrypt(ctx context.Context, ciphertext []byte) ([]byte, error)
// RotateKey initiates key rotation. After rotation, new Encrypt calls
// use the new key. Old keys remain available for Decrypt indefinitely —
// previously encrypted data does not need re-encryption.
//
// SECURITY: Implementations that do NOT support rotation (static-key
// implementations) MUST return an error from this method. Production
// deployments SHOULD use a provider that supports rotation.
RotateKey(ctx context.Context) error
// Available reports whether encryption is configured and operational.
// Returns false if no provider is registered or the provider is in a
// degraded state. The fabric SHOULD use this to enforce encryption
// requirements at startup.
Available() bool
}
EncryptionProvider handles envelope encryption for sensitive data at rest. Modules call Encrypt before storing sensitive data and Decrypt after retrieving it. The provider manages key material, rotation, and versioning internally — modules never touch raw keys.
The ciphertext produced by Encrypt is self-describing: it carries key metadata so Decrypt can identify which key was used, even after rotation.
This contract is provider-agnostic: a module that calls Encrypt/Decrypt works identically whether the backend uses AES-GCM with local keys, a cloud KMS (AWS KMS, GCP KMS), HashiCorp Vault transit engine, or a future encryption service. The security posture is determined by the provider implementation, not by module code.
SECURITY: Production deployments MUST register an EncryptionProvider. If no EncryptionProvider is registered, the fabric SHOULD refuse to start in production mode. Development and CI environments may operate without encryption. Use the Available() method to check at runtime.
type Event ¶
type Event struct {
ID string
Type string
Source string
TraceID string
Payload []byte
Metadata map[string]string
Timestamp time.Time
}
Event is the envelope for all inter-module communication. Type is a dotted string like "module.registered" or "media.requested". Event type constants and payload schemas are defined by contract repos, not by core. Core only defines the module-lifecycle event types (below). Cluster-lifecycle events are defined in cluster.go.
Payload is opaque bytes. Producers and consumers agree on the encoding (typically JSON) for a given event type. The EventSchemaVersion constant is reserved for future typed-payload support; for v1, callers marshal and unmarshal Payload themselves.
Timestamp is set by the publisher. Consumers should treat it as advisory.
type EventBus ¶
type EventBus interface {
Publish(ctx context.Context, event Event) error
// Subscribe registers a handler for the given event type.
// Use "*" to subscribe to all events.
// Returns a cancel function that removes the subscription when called.
// The cancel function is safe to call multiple times.
Subscribe(ctx context.Context, eventType string, handler EventHandler) (cancel func(), err error)
// Request publishes an event and waits for a reply on ReplyEventType(event.Type).
Request(ctx context.Context, event Event, timeout time.Duration) (Event, error)
// SubscribeModule registers a handler tagged with a module identifier.
// Returns a cancel function that removes this subscription when called.
// Use UnsubscribeAll for bulk removal of all subscriptions owned by a module.
SubscribeModule(ctx context.Context, moduleID, eventType string, handler EventHandler) (cancel func(), err error)
// UnsubscribeAll removes all subscriptions tagged with the given module ID.
// If moduleID is empty, this is a no-op. Used by module lifecycle management
// during shutdown to prevent handlers from receiving events after the
// module has stopped.
UnsubscribeAll(ctx context.Context, moduleID string) error
}
EventBus is the core message bus. All module communication flows through it.
type EventHandler ¶
EventHandler is a callback invoked when a matching event is published.
type EventStore ¶
type EventStore interface {
// Append writes events to a stream and returns their assigned sequence
// numbers. Events in a single Append call are atomic — either all
// are written or none are. Returns the starting sequence number for
// the batch and an error if the write fails.
//
// The first event in a new stream gets sequence 1.
Append(ctx context.Context, stream string, events []Event) (firstSequence int64, err error)
// Read returns events from a stream starting at fromSequence (inclusive).
// limit caps the number of events returned. Pass 0 for no limit
// (provider default). Returns events in ascending sequence order.
// Returns an empty slice if fromSequence is beyond the stream end.
Read(ctx context.Context, stream string, fromSequence int64, limit int) ([]EventStoreEntry, error)
// Subscribe returns a channel that receives new events appended to
// the stream starting from fromSequence. The channel closes when ctx
// is cancelled. Events are delivered in sequence order.
//
// To catch up on existing events before live ones, call Read first
// to get historical events, then Subscribe from the last sequence + 1.
Subscribe(ctx context.Context, stream string, fromSequence int64) (<-chan EventStoreEntry, error)
// Streams returns the names of all known streams.
Streams(ctx context.Context) ([]string, error)
}
EventStore provides a durable, append-only event log. This is distinct from EventBus which handles fire-and-forget pub/sub. EventStore is for event sourcing: state is reconstructed by replaying all events in a stream from the beginning.
Streams are logical partitions — typically one per aggregate or entity type ("user-abc123", "order-456", "module.metrics"). Append guarantees that events within a stream are ordered by sequence number.
This contract is provider-agnostic: a module that calls Append/Read works identically whether the backend is PostgreSQL, Kafka, NATS JetStream, an in-memory log, or a future event store.
If no EventStore is registered, Append is a no-op (returns nil sequence) and Read/Subscribe return empty — modules that only need pub/sub use EventBus; modules that need event sourcing require an EventStore.
type EventStoreEntry ¶
type EventStoreEntry struct {
// Stream is the logical partition this event belongs to.
Stream string
// Sequence is the monotonically increasing position within the stream.
// The first event in a stream has sequence 1.
Sequence int64
// Event is the stored event with type, source, payload, and metadata.
Event Event
// StoredAt is when the event was appended to the store.
StoredAt time.Time
// Extra carries provider-specific extensions (e.g., partition info,
// checksum, storage tier).
Extra map[string]any
}
EventStoreEntry is a persisted event with its stream position.
type Executor ¶
type Executor interface {
CanHandle(taskType string) bool
Execute(ctx context.Context, task WorkerTask) (result []byte, err error)
}
Executor is implemented by modules that can run tasks of a given type.
type FeatureFlagProvider ¶
type FeatureFlagProvider interface {
// IsEnabled checks whether a feature flag is enabled for the caller
// in the given context. The context carries identity for percentage-based
// rollouts and targeting rules. defaultValue is returned when no provider
// is registered or the flag is not defined.
IsEnabled(ctx context.Context, flag string, defaultValue bool) bool
// GetVariant returns the assigned variant for a multivariate flag.
// Useful for A/B testing where a flag has more than two states.
// defaultValue is returned when no provider is registered or the
// flag is not defined.
GetVariant(ctx context.Context, flag string, defaultValue string) string
}
FeatureFlagProvider evaluates feature flags for gradual rollouts, kill switches, and A/B testing. Modules call IsEnabled before activating new code paths; the provider evaluates the flag against the caller's identity (via context) and any configured rules.
This contract is provider-agnostic: a module that calls IsEnabled works identically whether the backend is a config file, LaunchDarkly, a database table, or a future feature flag service.
If no FeatureFlagProvider is registered, IsEnabled returns defaultValue and GetVariant returns defaultValue — modules degrade gracefully without nil checks.
type Hardlinkable ¶
type HealthMonitor ¶
type HealthMonitor interface {
// StartMonitoring begins periodic health checking. The monitor calls Health()
// on every registered module at the configured interval and publishes
// events on the bus for any degraded modules.
StartMonitoring(ctx context.Context, reg Registry, bus EventBus) error
// Stop gracefully stops the health monitor.
Stop(ctx context.Context) error
}
HealthMonitor runs periodic health checks on all registered modules and publishes module.degraded events for unhealthy modules. Core starts the HealthMonitor at bootstrap if one is discovered from the registry. If no module implements this contract, periodic health monitoring is skipped (modules still report via /health endpoint).
type Histogram ¶
type Histogram interface {
Observe(value float64)
}
Histogram observes values and tracks distribution.
type IdempotencyProvider ¶
type IdempotencyProvider interface {
// Store records that a key has been processed and caches the result.
// Returns (true, nil) if the key was new — this is the first occurrence.
// Returns (false, nil) if the key was already stored — this is a duplicate.
// The result is cached for ttl; after expiry the key may be evicted.
Store(ctx context.Context, key string, result []byte, ttl time.Duration) (bool, error)
// Exists checks whether a key has been previously stored and not yet expired.
// Returns true if the key exists, false otherwise.
Exists(ctx context.Context, key string) (bool, error)
// Result retrieves the cached result for a previously stored key.
// Returns (nil, nil) if the key does not exist or has expired.
// This allows a duplicate request to receive the same response
// as the original without re-executing the operation.
Result(ctx context.Context, key string) ([]byte, error)
}
IdempotencyProvider prevents duplicate processing of requests. When a module receives a request that must not be processed more than once (e.g., payment capture, order creation), it generates an idempotency key and checks this provider before acting.
This contract is provider-agnostic: a module that calls Store/Exists works identically whether the backend is in-memory, Redis, a database table, or a future storage mechanism.
If no IdempotencyProvider is registered, Store always returns true (treated as first occurrence) and Exists always returns false — modules degrade gracefully without needing nil checks.
This contract pairs with RetryProvider. Retries may deliver the same logical request multiple times; IdempotencyProvider ensures the side effects only happen once.
type Identity ¶
type Identity struct {
// ID is the unique identifier for this caller (user ID, service account ID).
ID string
// Kind describes the type of identity (e.g., "user", "service", "api-key").
Kind string
// Roles are the authorization roles assigned to this identity.
Roles []string
// Claims carries provider-specific claims extracted from the auth token.
// For JWT this is the decoded payload. For API keys this may be scopes.
//
// SECURITY: May contain sensitive data. Redact before logging.
Claims map[string]any
// Extra carries provider-specific extensions that consumers can interpret.
//
// SECURITY: May contain sensitive data. Redact before logging.
Extra map[string]any
}
Identity represents the caller extracted from an authentication context. Fields are intentionally broad — the identity provider populates whatever it can determine, and downstream consumers interpret what they understand.
SECURITY: Claims and Extra carry provider-specific data that may include sensitive information from auth tokens (JWT payloads, API key metadata). These fields MUST be treated as potentially sensitive:
- NEVER serialize a full Identity to logs without redaction.
- NEVER include Identity in event payloads unless the event is explicitly an auth/identity event with access controls.
- Use SafeInfo() when passing identity data to subsystems that do not need provider-specific claims.
The SafeInfo method strips Claims and Extra, retaining only the typed fields that Authorizer needs for permission checks.
type IdentityProvider ¶
type IdentityProvider interface {
// ExtractIdentity extracts the caller identity from the given context.
// Returns (nil, nil) if no identity is present (unauthenticated request).
// Returns an error only if identity extraction itself fails (e.g., invalid
// token format), not if the request is simply unauthenticated.
ExtractIdentity(ctx context.Context) (*Identity, error)
}
IdentityProvider extracts caller identity from context. Modules call this to determine who is making a request before passing that identity to the Authorizer for permission checks.
This contract is provider-agnostic: a module that calls ExtractIdentity works identically whether the backend is JWT validation, API key lookup, mTLS certificate extraction, or a future protocol.
SECURITY: When no IdentityProvider is registered, the system MUST apply a deny-by-default access policy. Anonymous access (no identity) should only be permitted for explicitly public endpoints. The fabric should refuse to start in production mode without an IdentityProvider — see EnforcedIdentityProvider.
Discovered via FindByCapability("identity"). If no module implements this contract, the fabric treats all requests as unauthenticated (nil identity). Modules MUST check for nil identity and apply their own access policy. The recommended safe default is to deny access when identity is nil unless the endpoint is explicitly marked as public.
type InputValidator ¶
type InputValidator interface {
// Validate checks the given data against the named schema and returns
// a result indicating pass/fail plus any sanitized output.
//
// The schema parameter follows the conventions above. If the schema is
// not recognised, implementations should return a ValidationResult with
// Valid=false and an error entry explaining the unknown schema, rather
// than returning an error — this allows callers to fall back gracefully.
//
// SECURITY: The schema string MUST be validated before use (see type docs).
Validate(ctx context.Context, data []byte, schema string) (ValidationResult, error)
// SupportedSchemas returns the list of schema identifiers this validator
// can handle. Used for capability discovery so callers can determine at
// registration time whether a validator meets their needs.
SupportedSchemas() []string
}
InputValidator performs centralized input validation for the MuxCore fabric. Modules implement this contract to provide schema-aware validation that other modules can delegate to, rather than duplicating validation logic.
Schema conventions:
"json:<schema-name>" — JSON Schema validation (e.g., "json:user-create") "regex:<pattern>" — Regex-based validation (e.g., "regex:^[a-z]+$") "sql:<param-count>" — SQL injection-safe parameter binding (e.g., "sql:3")
SECURITY: The schema parameter is caller-controlled. Implementations MUST:
- Validate the schema string format before interpretation.
- Reject schemas with path-traversal characters (../, /, etc.) to prevent access to unintended schema files or namespaces.
- Apply a limit on schema name length to prevent resource exhaustion.
- Never treat the schema string as a file path without sanitization.
Schema names should match the pattern: ^[a-z][a-z0-9_.:-]{0,127}$
Modules discover registered validators via the registry and call SupportedSchemas() to check which schemas are available before calling Validate. If no InputValidator is registered, modules handle validation themselves (degrade gracefully).
Discovered via FindByCapability("input.validate"). If multiple validators register, the first found is consulted. Validators may internally delegate to other validators for schemas they do not support.
type LBStrategy ¶
type LBStrategy interface {
// Pick returns the index of the selected candidate from candidates.
// candidates is guaranteed to have at least one entry.
// Returns ErrNoCandidates if candidates is empty.
Pick(ctx context.Context, candidates []NodeInfo) (int, error)
}
LBStrategy selects a target node from a set of candidates for load-balanced cross-node module routing. Implementations must be safe for concurrent use.
type LeaderChangedPayload ¶
type LeaderChangedPayload struct {
PreviousLeader string `json:"previous_leader"`
NewLeader string `json:"new_leader"`
}
LeaderChangedPayload is the payload for cluster.leader.changed events.
type LockHandle ¶
LockHandle represents an acquired distributed lock.
type MeshHandler ¶
type MeshHandler interface {
// HandleCall processes a cross-module method invocation.
// method is an arbitrary string the caller and handler agree on.
// payload is the JSON-encoded request body.
// Returns the JSON-encoded response or an error.
HandleCall(ctx context.Context, method string, payload []byte) ([]byte, error)
}
MeshHandler is implemented by modules that want to receive cross-module gRPC calls. The mesh server routes incoming Call(targetModule, method, payload) requests to the target module's HandleCall method.
Modules register themselves as handlers during Start():
deps.Mesh.RegisterHandler("my-module", myHandler)
type MetricsProvider ¶
type MetricsProvider interface {
// Counter creates or returns a counter with the given name and labels.
Counter(name string, labels map[string]string) Counter
// Gauge creates or returns a gauge with the given name and labels.
Gauge(name string, labels map[string]string) Gauge
// Histogram creates or returns a histogram with the given name, labels, and buckets.
Histogram(name string, labels map[string]string, buckets []float64) Histogram
}
MetricsProvider exposes application metrics. Modules implement this to provide Prometheus, Datadog, or other metrics backends. Modules that want to expose metrics call these methods to register and update metrics. If no MetricsProvider is registered, metric calls are no-ops.
type Migration ¶
type Migration struct {
Version int
Name string
Up string // SQL to apply
// Down is SQL to revert the migration. Used by Rollback to undo
// schema changes in reverse version order.
Down string
}
Migration represents a versioned schema migration.
type ModuleDegradedPayload ¶
type ModuleDegradedPayload struct {
ModuleID string `json:"module_id"`
Error string `json:"error"`
}
ModuleDegradedPayload is the payload for module.degraded events.
type ModuleEntry ¶
type ModuleEntry struct {
Info ModuleInfo
State ModuleState
Module Module
}
type ModuleInfo ¶
type ModuleInfo struct {
ID string
Name string
Version string
Roles []string // module-defined role strings; core imposes no taxonomy
Description string
Author string
Capabilities []string // granular capability strings for routing/discovery
Contracts []ContractDeclaration // typed contracts this module implements
DependsOn []string // module IDs that must be initialized before this module starts. Cycles detected by Registry.StartupOrder().
// MinCoreVersion is the minimum core version required by this module.
// Uses SemVer (e.g., "1.2.0"). Empty means compatible with any version.
// Core rejects modules whose MinCoreVersion is greater than the running
// core version or targets a different major version.
MinCoreVersion string
// HTTPAddr is the address where this module serves HTTP, if any.
// Example: ":8085" or "0.0.0.0:9200". Leave empty if the module does not
// expose HTTP. Other modules discover this via ModuleEntry.Info.HTTPAddr
// after a successful FindByCapability or Resolve call.
HTTPAddr string
}
type ModuleKind ¶
type ModuleKind string
ModuleKind is a user-defined string that categorizes a module's role. Core has no opinion about what kinds exist — modules and consumers define them. Common conventions (defined in contract repos, not here): "auth", "downloader", "indexer", "media_manager", "playback", "storage", "workflow", "transcoder". The WorkflowEngine is discovered via "workflow.engine".
type ModuleMeshClient ¶
type ModuleMeshClient interface {
// Call invokes a method on the target module. If the target is registered
// locally, the call is dispatched in-process with zero network overhead.
// If the target is on a remote node, the call goes over gRPC.
Call(ctx context.Context, targetModule, method string, payload []byte) ([]byte, error)
// RegisterHandler registers a local module to receive incoming Call requests.
// Only call this during module Start(). Modules that don't receive calls
// don't need to register.
RegisterHandler(moduleID string, handler MeshHandler)
}
ModuleMeshClient is the interface modules use to call other modules. It abstracts whether the target is local (in-process) or remote (gRPC network call). Modules dial core's gRPC ModuleMesh service to obtain a client.
type ModuleRegisteredPayload ¶
type ModuleRegisteredPayload struct {
ModuleID string `json:"module_id"`
Version string `json:"version"`
}
ModuleRegisteredPayload is the payload for module.registered events.
type ModuleState ¶
type ModuleState string
const ( ModuleStateRegistered ModuleState = "registered" ModuleStateStarting ModuleState = "starting" ModuleStateRunning ModuleState = "running" ModuleStateDegraded ModuleState = "degraded" ModuleStateStopping ModuleState = "stopping" ModuleStateStopped ModuleState = "stopped" )
type ModuleUnregisteredPayload ¶
type ModuleUnregisteredPayload struct {
ModuleID string `json:"module_id"`
}
ModuleUnregisteredPayload is the payload for module.unregistered events.
type NodeInfo ¶
type NodeInfo struct {
ID string
GRPCAddr string
HTTPAddr string
Labels map[string]string
ModuleIDs []string
// ModuleHealth maps module ID to health status.
// Empty string means healthy. Non-empty is the last health check error.
ModuleHealth map[string]string
}
NodeInfo describes a node in the cluster.
type NodeJoinedPayload ¶
type NodeJoinedPayload struct {
NodeID string `json:"node_id"`
GRPCAddr string `json:"grpc_addr"`
HTTPAddr string `json:"http_addr"`
}
NodeJoinedPayload is the payload for cluster.node.joined events.
type NodeLeftPayload ¶
type NodeLeftPayload struct {
NodeID string `json:"node_id"`
}
NodeLeftPayload is the payload for cluster.node.left events.
type ObjectInfo ¶
type Permission ¶
type Permission string
Permission represents a named permission in the authorization system. The string format is "<domain>.<verb>" or "<domain>.<resource>.<verb>", e.g. "storage.read", "media.movies.delete", "admin.*".
Wildcard support:
- "*" matches all permissions (superuser)
- "domain.*" matches all permissions within a domain
- "domain.resource.*" matches all permissions on a specific resource
type PublishPolicyProvider ¶
type PublishPolicyProvider interface {
// CanPublish returns (true, nil) if the caller is permitted to publish
// events of the given type. Returns (false, nil) if publishing is denied.
CanPublish(ctx context.Context, callerID, eventType string) (bool, error)
}
PublishPolicyProvider determines whether a caller is authorized to publish events of a given type. Implemented by modules that define event-level access control. The event bus consults this before dispatching.
SECURITY: When no PublishPolicyProvider is registered, the event bus MUST deny all event publication. This is a change from the previous behavior where the default was open mode. Deployments that want open mode must register an explicit permissive policy provider.
Discovered via FindByCapability(CapabilityPublishPolicy).
For resource-level event authorization, implement the optional ResourcePublishPolicyProvider interface. The event bus will type-assert and use the richer interface when available.
type RateLimiterProvider ¶
type RateLimiterProvider interface {
// Allow checks whether a request from the given key (typically IP) is allowed.
// Returns true if the request should proceed, false if it should be rate-limited.
Allow(ctx context.Context, key string) bool
// Enabled returns whether rate limiting is active.
Enabled() bool
}
RateLimiterProvider is implemented by rate limiter modules (ratelimit-tokenbucket, etc.) to provide request rate limiting to the API server middleware chain. Core discovers a RateLimiterProvider at bootstrap and injects it into the middleware. If no module implements this contract, rate limiting is disabled (open mode).
type RedactingLogger ¶
type RedactingLogger interface {
StructuredLogger
// IsRedacting reports whether this logger automatically applies
// redaction to all fields before writing to sinks.
IsRedacting() bool
}
RedactingLogger is an optional extension that guarantees all log output is redacted. Implementations that embed automatic redaction can declare this interface so that callers can skip manual redaction.
Modules MAY type-assert their StructuredLogger to RedactingLogger to determine if manual redaction is necessary.
type Registry ¶
type Registry interface {
FindByRole(role string) []ModuleEntry
FindByCapability(cap string) []ModuleEntry
SupportsCapability(moduleID, cap string) bool
Resolve(id string) (ModuleEntry, error)
ListAll() []ModuleEntry
// StartupOrder returns module IDs in dependency-respecting order.
// Modules listed in DependsOn appear before the module that depends on them.
// Returns an error if a dependency cycle is detected.
StartupOrder() ([]string, error)
// DependencyGraph returns modules that list the given ID in their DependsOn.
// Useful for understanding the impact of stopping or removing a module.
DependencyGraph(id string) ([]string, error)
}
Registry provides runtime discovery of registered modules.
type ResourceAuthorizer ¶
type ResourceAuthorizer interface {
Authorizer
// CanWithResource performs a permission check with resource context.
// The resource descriptor enables hierarchical checks, ABAC policies,
// and resource-ownership gating. When ResourceDescriptor.ID is empty,
// the check is scoped to the resource type.
CanWithResource(ctx context.Context, session Session, action Action, resource ResourceDescriptor) (bool, error)
}
ResourceAuthorizer is an optional extension to Authorizer that enables resource-level permission checks with ABAC support. Implement this alongside Authorizer when your policy engine supports hierarchical resource permissions.
Callers that need resource-level authorization type-assert to this interface and fall back to Authorizer.Can() if not supported.
type ResourceDescriptor ¶
type ResourceDescriptor struct {
// Type is the resource kind, e.g. "media", "storage", "module".
Type string
// ID is the resource identifier, e.g. a UUID or key path.
// Empty means the check is at the resource-type level.
ID string
// Attributes carries additional resource properties that
// policy engines can use for ABAC decisions (owner, labels, tier).
// MUST NOT contain credentials or PII.
Attributes map[string]string
}
ResourceDescriptor carries the resource identifier and optional attributes for attribute-based access decisions.
type ResourcePublishPolicyProvider ¶
type ResourcePublishPolicyProvider interface {
PublishPolicyProvider
// CanPublishEvent performs event-level authorization with access to
// the full event payload. This enables resource-level checks beyond
// the type-level check in CanPublish.
CanPublishEvent(ctx context.Context, callerID string, event Event) (bool, error)
}
ResourcePublishPolicyProvider is an optional extension that enables resource-level event authorization with access to the full event payload. Implement this alongside PublishPolicyProvider to enable checks like "can this caller publish media.updated events for media item X?".
When a provider implements this interface, the event bus calls CanPublishEvent before CanPublish, giving the provider full event context.
type RetryPolicy ¶
type RetryPolicy struct {
// MaxAttempts is the maximum number of attempts, including the first.
// A value of 0 means the provider's default (typically 3).
MaxAttempts int
// InitialDelay is the delay before the first retry.
// A value of 0 means the provider's default (typically 100ms).
InitialDelay time.Duration
// MaxDelay is the maximum delay between retries. The backoff caps at this.
// A value of 0 means no cap (provider default).
MaxDelay time.Duration
// BackoffFactor is multiplied against the delay on each retry.
// Typical values: 2.0 (exponential), 1.0 (fixed delay).
// A value of 0 means the provider's default (typically 2.0).
BackoffFactor float64
// Jitter, when true, adds random jitter to the delay to avoid thundering herd.
Jitter bool
// Extra carries provider-specific extensions.
Extra map[string]any
}
RetryPolicy configures how a RetryProvider retries failed operations. Zero values mean "use the provider's default."
type RetryProvider ¶
type RetryProvider interface {
// Execute runs fn with retry semantics based on the given policy.
// Returns nil if fn succeeds on any attempt. Returns the last error
// if all attempts are exhausted. The context is passed to each attempt;
// if ctx is cancelled, retries stop immediately.
Execute(ctx context.Context, policy RetryPolicy, fn func(ctx context.Context) error) error
}
RetryProvider executes operations with configurable retry semantics. This contract is provider-agnostic: a module that wraps a call in RetryProvider.Execute works identically whether the backend uses simple backoff, exponential backoff with jitter, or a future retry strategy.
RetryProvider is complementary to CircuitBreaker. CircuitBreaker prevents cascading failures by opening the circuit when errors exceed a threshold. RetryProvider handles transient failures (network blips, temporary unavailability) by retrying individual calls with backoff. A robust module uses both.
If no RetryProvider is registered, Execute runs fn exactly once with no retries — modules don't need nil checks.
type Scheduler ¶
type Scheduler interface {
Schedule(ctx context.Context, task SchedulerTask) (string, error)
Cancel(ctx context.Context, taskID string) error
Status(ctx context.Context, taskID string) (SchedulerTaskStatus, error)
// List returns all scheduled tasks matching the filter. Pass nil to list all.
List(ctx context.Context, filter *SchedulerTaskFilter) ([]SchedulerTask, error)
}
Scheduler is implemented by scheduler modules (scheduler-cron, etc.) to provide task scheduling. Core defines the contract; modules provide the driver.
Discovered via FindByCapability(CapabilityScheduler).
type SchedulerTask ¶
type SchedulerTask struct {
ID string
Name string
CronExpr string
Payload []byte
Timeout time.Duration
Meta map[string]any
}
SchedulerTask is a unit of scheduled work. Payload carries the task data. Meta carries scheduler-specific or task-type-specific context that the scheduler module can interpret.
type SchedulerTaskFilter ¶
type SchedulerTaskFilter struct {
Status SchedulerTaskStatus
Name string // substring match on task name; empty matches all
}
SchedulerTaskFilter narrows List queries.
type SchedulerTaskStatus ¶
type SchedulerTaskStatus string
SchedulerTaskStatus represents the lifecycle of a scheduled task.
const ( SchedulerTaskScheduled SchedulerTaskStatus = "scheduled" SchedulerTaskRunning SchedulerTaskStatus = "running" SchedulerTaskCompleted SchedulerTaskStatus = "completed" SchedulerTaskFailed SchedulerTaskStatus = "failed" SchedulerTaskCancelled SchedulerTaskStatus = "cancelled" )
type SecretsProvider ¶
type SecretsProvider interface {
// Get retrieves a secret by key. Returns an error if not found.
Get(ctx context.Context, key string) (string, error)
// Set stores a secret. Implementations may be read-only (e.g., env-backed)
// and return an error for Set calls.
Set(ctx context.Context, key, value string) error
// Delete removes a secret. May not be supported by all backends.
Delete(ctx context.Context, key string) error
// List returns all known keys. Values are NOT included — only key names.
List(ctx context.Context) ([]string, error)
}
SecretsProvider manages sensitive configuration values (API keys, tokens, passwords). Modules implement this to back secrets from environment variables, HashiCorp Vault, encrypted files, or external secret managers.
This contract exists so modules never read raw env vars for credentials. A module that needs a Jackett API key calls deps.Secrets.Get("jackett_api_key") instead of os.Getenv("JACKETT_API_KEY"). This enables audit logging, rotation, and centralized secret management without changing module code.
type SerializationProvider ¶
type SerializationProvider interface {
// Marshal serializes v to bytes using the specified content type.
// Common content types: "application/json", "application/x-protobuf",
// "application/msgpack".
Marshal(contentType string, v any) ([]byte, error)
// Unmarshal deserializes data into v using the specified content type.
// v must be a pointer to a concrete target type.
//
// SECURITY: The content type and data originate from untrusted sources
// (the wire or another module). Implementations MUST validate the
// content type against a safelist before deserializing.
Unmarshal(contentType string, data []byte, v any) error
// SupportedTypes returns the content types this provider can handle.
// Callers can negotiate format by intersecting their needs with this list.
//
// SECURITY: The returned list MUST only include types that have been
// vetted for safe deserialization. See SafeSerializationTypes above.
SupportedTypes() []string
}
SerializationProvider handles marshaling and unmarshaling of data with content-type negotiation. Modules use this to serialize/deserialize payloads without knowing which format the other side expects.
A module producing protobuf can call Marshal("application/json", v) and the provider handles the conversion. A module consuming JSON can call Unmarshal(contentType, data, v) regardless of the wire format.
This contract is provider-agnostic: a module that calls Marshal/Unmarshal works identically whether the backend uses encoding/json + protobuf, msgpack, or a future serialization format.
SECURITY: Unmarshal deserializes untrusted data into an arbitrary target type. Implementations MUST:
- Reject content types that support code execution (YAML v1, gob, etc.) unless sandboxed with strict decoding modes.
- Enforce type safety — the target 'v' must be a concrete Go type, and the implementation must not instantiate types based on the serialized payload's type hints (no polymorphic deserialization).
- Reject payloads that exceed a reasonable size limit to prevent memory-exhaustion DoS. A minimum of 10 MB per payload is recommended.
If no SerializationProvider is registered, modules handle serialization themselves — this is acceptable for simple deployments where all modules agree on a single format.
type Session ¶
type Session struct {
UserID string
Username string
Roles []string
Permissions []string
Token string // SECURITY: zero before logging or serializing
}
Session represents an authenticated session.
SECURITY WARNING: The Token field carries the raw bearer token. Session structs flow through the authorization path (Authorizer.Can), and can be inadvertently serialized in logs, audit entries, or event payloads. Consumers that pass Session to loggers or serializers MUST zero the Token field first. Use the Safe() method when passing session identity to non-security subsystems.
type SettingDef ¶
type SettingDef struct {
Key string // env var or config key, e.g. "MUXCORE_JACKETT_URL"
Label string // human-readable label, e.g. "Jackett Server URL"
Type SettingType
Default string // default value as a string
Description string // help text
Required bool
Options []string // for SettingTypeSelect: allowed values
Group string // settings group, e.g. "Connection", "Downloads"
}
SettingDef describes one configuration setting that a module exposes.
type SettingType ¶
type SettingType string
SettingType enumerates the supported setting types.
const ( SettingTypeString SettingType = "string" SettingTypeInt SettingType = "int" SettingTypeBool SettingType = "bool" SettingTypeSelect SettingType = "select" SettingTypeSecret SettingType = "secret" // masked in UI, redacted in logs )
type SettingsProvider ¶
type SettingsProvider interface {
Settings() []SettingDef
}
SettingsProvider is an optional interface modules implement to expose their configuration to the admin UI. The admin UI discovers all modules that implement this interface and renders their settings automatically.
type Span ¶
type Span interface {
// SetAttribute records a key-value pair on the span. Attributes appear
// in trace visualizations and can be searched.
SetAttribute(key string, value string)
// SetStatus records the outcome of the span. Call before End().
SetStatus(code SpanStatusCode, description string)
// End marks the span as complete and sends it to the tracing backend.
End()
}
Span represents a single unit of work in a distributed trace.
type SpanStatusCode ¶
type SpanStatusCode int
SpanStatusCode indicates success or failure of a span.
const ( SpanStatusOK SpanStatusCode = 0 SpanStatusError SpanStatusCode = 1 )
type SpoolResolver ¶
type SpoolResolver interface {
// ResolveTag fetches and parses a tag definition from the given spool URL.
// The context carries deadlines and cancellation for the network request.
ResolveTag(ctx context.Context, spoolURL, tagName string) (*TagDefinition, error)
}
SpoolResolver resolves a tag name into a list of module definitions from a spool URL. Implementations may support different spool formats (GitHub, self-hosted, IPFS, etc.).
Discovered via FindByCapability(CapabilitySpoolResolver). If no resolver is registered, core falls back to a generic HTTPS JSON fetcher.
type StepCompletedPayload ¶
type StepFailedPayload ¶
type StepHandler ¶
type StepHandler struct {
// Kind determines how Ref is interpreted.
Kind StepHandlerKind
// Ref is a module ID (Kind=StepHandlerModule) or capability string
// (Kind=StepHandlerCapability).
Ref string
}
StepHandler specifies which module handles a tapestry step. Exactly one of Kind+Ref must be set.
type StepHandlerKind ¶
type StepHandlerKind string
StepHandlerKind identifies how a TapestryStep.Handler is resolved.
const ( // StepHandlerModule routes the step to a specific module by ID. // Handler.Ref must be a module ID (e.g. "transcoder-ffmpeg"). StepHandlerModule StepHandlerKind = "module" // StepHandlerCapability routes the step to any module advertising // the given capability. Handler.Ref must be a capability string // (e.g. "transcoder"). The workflow engine picks an available module. StepHandlerCapability StepHandlerKind = "capability" )
type StepResult ¶
type StepResult struct {
StepName string
Status string // "success", "failed", "skipped"
StartedAt time.Time
EndedAt time.Time
Attempt int
MaxRetries int
Output map[string]any // step output data passed to subsequent steps
Error string
}
StepResult captures the outcome of one tapestry step.
type StepStartedPayload ¶
type StorageEvent ¶
type StorageEvent struct {
Type StorageEventType
Key string
}
type StorageEventType ¶
type StorageEventType string
const ( StorageEventCreated StorageEventType = "created" StorageEventDeleted StorageEventType = "deleted" StorageEventModified StorageEventType = "modified" )
type StorageOrchestrator ¶
type StorageOrchestrator interface {
Get(ctx context.Context, key string) (io.ReadCloser, error)
Put(ctx context.Context, key string, data io.Reader, size int64) error
Delete(ctx context.Context, key string) error
Move(ctx context.Context, src, dst string) error
Exists(ctx context.Context, key string) (bool, error)
Stat(ctx context.Context, key string) (ObjectInfo, error)
List(ctx context.Context, prefix string) ([]ObjectInfo, error)
// Stream reads a byte range from a storage object. Uses provider-side
// streaming when the routed provider implements Streamable; otherwise
// falls back to a full Get with client-side slicing.
Stream(ctx context.Context, key string, offset, length int64) (io.ReadCloser, error)
// CapabilityCheck returns which capability interfaces the routed provider
// supports for the given key (streamable, seekable, watchable, etc.).
// Modules use this to negotiate behavior at runtime.
CapabilityCheck(ctx context.Context, key string) ([]string, error)
}
StorageOrchestrator is the high-level storage interface exposed to modules. It handles provider routing, caching, and capability negotiation internally.
type StorageProvider ¶
type StorageProvider interface {
Put(ctx context.Context, key string, data io.Reader, size int64) error
Get(ctx context.Context, key string) (io.ReadCloser, error)
Delete(ctx context.Context, key string) error
Move(ctx context.Context, src, dst string) error
Exists(ctx context.Context, key string) (bool, error)
Stat(ctx context.Context, key string) (ObjectInfo, error)
List(ctx context.Context, prefix string) ([]ObjectInfo, error)
}
Core blob storage interface — all storage providers implement this.
type StorageTier ¶
type StorageTier string
StorageTier represents the performance/cost tier of a storage backend.
const ( StorageTierHot StorageTier = "hot" StorageTierWarm StorageTier = "warm" StorageTierCold StorageTier = "cold" StorageTierArchive StorageTier = "archive" )
type Streamable ¶
type StructuredLogger ¶
type StructuredLogger interface {
// Debug logs at debug level with structured fields.
// SECURITY: fields may contain sensitive data — redact before calling.
Debug(ctx context.Context, msg string, fields map[string]any)
// Info logs at info level with structured fields.
// SECURITY: fields may contain sensitive data — redact before calling.
Info(ctx context.Context, msg string, fields map[string]any)
// Warn logs at warning level with structured fields.
// SECURITY: fields may contain sensitive data — redact before calling.
Warn(ctx context.Context, msg string, fields map[string]any)
// Error logs at error level with structured fields.
// SECURITY: fields may contain sensitive data — redact before calling.
Error(ctx context.Context, msg string, fields map[string]any)
// Level returns the configured minimum log level. Messages below this
// level are silently dropped by the provider.
Level() LogLevel
}
StructuredLogger provides leveled, structured logging for modules. This is the general-purpose logger — distinct from AuditLogger which handles security-relevant audit events specifically.
Modules call StructuredLogger instead of importing a specific logging library. This makes the logging backend swappable (slog, zap, zerolog, or a future standard) without changing module code.
SECURITY: All log methods accept fields as map[string]any. This map can inadvertently contain credentials, tokens, PII, or other sensitive data. Callers MUST:
- Apply DataRedactionProvider.Redact() to the fields map before passing it to any log method if the map contains untrusted data.
- Never log full Identity structs — use Identity.SafeInfo().
- Never log Session structs — use Session.Safe().
- Avoid logging raw request bodies, query parameters, or headers.
Implementations SHOULD apply automatic field-name-based redaction for keys matching SensitiveLogFieldNames before writing to any sink.
If no StructuredLogger is registered, log calls are no-ops — modules do not need nil checks.
type TagDefinition ¶
type TagDefinition struct {
Name string `json:"name"`
Description string `json:"description"`
Version string `json:"version"`
Modules []TagModule `json:"modules"`
}
TagDefinition is a curated module preset fetched from a spool.
type TagModule ¶
type TagModule struct {
Repo string `json:"repo"`
Version string `json:"version"`
Required bool `json:"required"`
Checksum string `json:"checksum,omitempty"`
// InstanceID differentiates multiple copies of the same module on one
// node. When set, the derived module ID becomes "{baseID}-{instanceID}"
// instead of just "{baseID}". Allows running two identical modules
// with different config (e.g. two torrent downloaders on different ports).
InstanceID string `json:"instance_id,omitempty"`
// Config is instance-specific configuration passed as environment
// variables to the module binary. Each key is prefixed with MUXCORE_CFG_
// and set as an env var during spawn.
Config map[string]string `json:"config,omitempty"`
}
TagModule is a single module entry in a spool tag definition.
type TapestryDefinition ¶
type TapestryDefinition struct {
ID string
Name string
Description string
Steps []TapestryStep
Version string
Meta map[string]any
}
TapestryDefinition is a registered, reusable workflow template.
type TapestryFailedPayload ¶
type TapestryRun ¶
type TapestryRun struct {
ID string
DefinitionID string
Status TapestryStatus
CurrentStep string
StepResults []StepResult
Input map[string]any
StartedAt time.Time
EndedAt time.Time
Error string
Meta map[string]any
}
TapestryRun represents a single execution of a tapestry.
type TapestryRunFilter ¶
type TapestryRunFilter struct {
Status TapestryStatus
DefinitionID string
}
TapestryRunFilter narrows ListRuns queries.
type TapestryStartedPayload ¶
type TapestryStartedPayload struct {
RunID string `json:"run_id"`
DefinitionID string `json:"definition_id"`
}
Tapestry event payloads.
type TapestryStatus ¶
type TapestryStatus string
TapestryStatus tracks the lifecycle of a running workflow.
const ( TapestryPending TapestryStatus = "pending" TapestryRunning TapestryStatus = "running" TapestryCompleted TapestryStatus = "completed" TapestryFailed TapestryStatus = "failed" TapestryCancelled TapestryStatus = "cancelled" TapestryPaused TapestryStatus = "paused" )
type TapestryStep ¶
type TapestryStep struct {
Name string
Handler StepHandler
Retry int // max retry attempts (0 = no retry)
Timeout time.Duration
DependsOn []string // step names that must complete before this one
InputMapping map[string]string // maps step output keys to this step's input keys
Meta map[string]any
}
TapestryStep defines one step in a tapestry definition.
type TierTransitionPayload ¶
type TierTransitionPayload struct {
Key string `json:"key"`
FromTier StorageTier `json:"from_tier"`
ToTier StorageTier `json:"to_tier"`
Reason string `json:"reason"`
}
TierTransitionPayload is the payload for storage.tier.transition events. Experimental — may change before the first tiered storage module ships.
type TieredProvider ¶
type TieredProvider interface {
StorageProvider
// Tier returns which tier this provider handles.
Tier() StorageTier
// Promote moves an object from this tier to a higher one.
Promote(ctx context.Context, key string) error
// Relegate moves an object from this tier to a lower one.
Relegate(ctx context.Context, key string) error
}
TieredProvider extends StorageProvider with tiering support. Storage modules that support multiple tiers implement this.
type TracingProvider ¶
type TracingProvider interface {
// StartSpan begins a new span with the given name as a child of any
// span in ctx. Returns the context carrying the new span and the span
// itself. Call span.End() when the operation completes.
StartSpan(ctx context.Context, name string) (context.Context, Span)
}
TracingProvider creates spans for distributed tracing. Modules call this to wrap operations in spans; the provider handles export to whatever backend is configured (Jaeger, Zipkin, OTLP, or future protocols).
If no TracingProvider is registered, StartSpan returns the context unchanged and a no-op span — modules don't need nil checks.
This contract is provider-agnostic by design. A module that creates spans through TracingProvider works identically whether the backend is OpenTelemetry, a proprietary APM, or a future standard.
type Tx ¶
type Tx interface {
// SECURITY: Same SQL parameterization requirements as DatabaseProvider.Exec/Query.
Exec(ctx context.Context, query string, args ...any) (int64, error)
Query(ctx context.Context, query string, args ...any) (Rows, error)
}
Tx is a database transaction handle.
type ValidationResult ¶
type ValidationResult struct {
// Valid is true if the input passed all schema checks without errors.
// When Valid is true, Sanitized holds the (possibly cleaned) data
// that should be used in place of the original.
Valid bool
// Sanitized is the cleaned/sanitized version of the input data.
// When Valid is true, callers should use this instead of the raw input.
// When Valid is false, Sanitized may be nil or partial.
Sanitized []byte
// Errors is the list of validation failures. Empty when Valid is true.
// Each entry describes a specific failure (e.g., "field email must
// match pattern ^[^@]+@[^@]+$").
Errors []string
}
ValidationResult carries the outcome of an input validation call. Modules use this to decide whether to accept, reject, or sanitize incoming data before processing.
type Watchable ¶
type Watchable interface {
Watch(ctx context.Context, prefix string) (<-chan StorageEvent, error)
}
type WorkerPool ¶
type WorkerPool interface {
Submit(ctx context.Context, task WorkerTask) (string, error)
Status(ctx context.Context, taskID string) (WorkerTask, error)
Cancel(ctx context.Context, taskID string) error
List(ctx context.Context, filter *WorkerTaskFilter) ([]WorkerTask, error)
// Reassign moves a task from a dead or unresponsive node to a new one.
// If the task is already completed or cancelled, Reassign returns an error.
// The new node should re-execute the task from scratch unless the executor
// checks IdempotencyKey against an IdempotencyProvider.
Reassign(ctx context.Context, taskID, newNode string) error
}
WorkerPool schedules tasks across cluster nodes and tracks their lifecycle.
type WorkerTask ¶
type WorkerTask struct {
ID string
Type string
Payload []byte
AssignedNode string
Status WorkerTaskStatus
MaxRetries int
RetryCount int
Capabilities []string
CreatedAt time.Time
StartedAt time.Time
CompletedAt time.Time
LastHeartbeat time.Time
Error string
Meta map[string]any
// IdempotencyKey is an optional key that executors use with
// IdempotencyProvider to prevent duplicate execution. When a task
// is reassigned after a node failure, the new executor checks this
// key before re-executing. If empty, no idempotency guard is applied.
IdempotencyKey string
// HeartbeatInterval is how often the executor promises to call
// Heartbeat() while processing this task. The worker pool reaper
// uses this to detect stalled executors. If zero, the pool's
// DefaultHeartbeatTimeout is used.
HeartbeatInterval time.Duration
}
WorkerTask is a unit of work scheduled across the cluster. Meta carries task-type-specific context that executors interpret.
type WorkerTaskFilter ¶
type WorkerTaskFilter struct {
Status WorkerTaskStatus
Type string
AssignedNode string
}
WorkerTaskFilter narrows task queries.
type WorkerTaskStatus ¶
type WorkerTaskStatus string
WorkerTaskStatus represents the lifecycle of a distributed task.
const ( WorkerTaskStatusPending WorkerTaskStatus = "pending" WorkerTaskStatusAssigned WorkerTaskStatus = "assigned" WorkerTaskStatusRunning WorkerTaskStatus = "running" WorkerTaskStatusCompleted WorkerTaskStatus = "completed" WorkerTaskStatusFailed WorkerTaskStatus = "failed" WorkerTaskStatusCancelled WorkerTaskStatus = "cancelled" )
type WorkflowEngine ¶
type WorkflowEngine interface {
// RegisterDefinition stores a tapestry template for later execution.
// definition.ID is the key used by Run.
RegisterDefinition(ctx context.Context, definition TapestryDefinition) error
// RemoveDefinition removes a previously registered definition.
RemoveDefinition(ctx context.Context, definitionID string) error
// GetDefinition returns a registered definition, or nil if not found.
GetDefinition(ctx context.Context, definitionID string) (*TapestryDefinition, error)
// ListDefinitions returns all registered definitions.
ListDefinitions(ctx context.Context) ([]TapestryDefinition, error)
// Run starts a tapestry execution. input carries the initial
// data passed to the first step(s).
Run(ctx context.Context, definitionID string, input map[string]any) (string, error)
// Status returns the current state of a run.
Status(ctx context.Context, runID string) (*TapestryRun, error)
// Cancel stops a running tapestry. Already-completed steps
// are not rolled back.
Cancel(ctx context.Context, runID string) error
// Pause suspends a running tapestry at the next step boundary.
Pause(ctx context.Context, runID string) error
// Resume continues a paused tapestry.
Resume(ctx context.Context, runID string) error
// ListRuns returns all runs, optionally filtered by status or definitionID.
ListRuns(ctx context.Context, filter *TapestryRunFilter) ([]TapestryRun, error)
}
WorkflowEngine orchestrates multi-step tapestry executions. Discovered via FindByCapability(CapabilityWorkflowEngine). If no module implements this contract, individual Scheduler tasks can still run independently — tapestry execution is an optional layer.
Source Files
¶
- audit.go
- auth.go
- backup.go
- cache.go
- callpolicy.go
- capabilities.go
- circuitbreaker.go
- cluster.go
- configwatch.go
- database.go
- dataredaction.go
- deadletter.go
- distributedlock.go
- doc.go
- encryption.go
- events.go
- eventschema.go
- eventstore.go
- featureflag.go
- health.go
- idempotency.go
- identity.go
- input_validator.go
- logger.go
- mesh.go
- metrics.go
- module.go
- ratelimit.go
- retry.go
- scheduler.go
- secrets.go
- serialization.go
- settings.go
- spool.go
- storage.go
- tracing.go
- worker.go
- workflow.go