1
0
forked from wrenn/wrenn
Co-authored-by: Tasnim Kabir Sadik <tksadik@omukk.dev>

Reviewed-on: wrenn/wrenn#50
This commit is contained in:
2026-05-24 21:10:37 +00:00
parent 4707f16c76
commit 05ddf62399
203 changed files with 15815 additions and 9344 deletions

View File

@ -7,8 +7,18 @@ import (
// EventPublisher pushes events onto the notification stream.
// Satisfied by *channels.Publisher.
//
// Publish writes durably (Redis stream + SSE Pub/Sub mirror) and is delivered
// to subscribed channels. Use for actions that users may want webhook/telegram
// notifications about.
//
// PublishTransient writes only to the SSE Pub/Sub mirror — no durable stream,
// no channel delivery. Use for ephemeral UI signals (e.g., status transitions
// while a sandbox is starting/pausing) that should reach the dashboard but
// must not spam subscribers.
type EventPublisher interface {
Publish(ctx context.Context, e Event)
PublishTransient(ctx context.Context, e Event)
}
// ActorKind identifies what initiated an event.
@ -27,42 +37,77 @@ type Actor struct {
Name string `json:"name,omitempty"`
}
// SystemActor returns the canonical actor for system-initiated events
// (TTL reaper, reconciler-inferred state, cleanup-on-error).
func SystemActor() Actor {
return Actor{Type: ActorSystem}
}
// Resource identifies the object the event relates to.
type Resource struct {
ID string `json:"id"`
Type string `json:"type"`
}
// Event is the canonical notification payload published to the Redis stream
// and delivered to channel subscribers.
type Event struct {
Event string `json:"event"`
Timestamp string `json:"timestamp"`
TeamID string `json:"team_id"`
Actor Actor `json:"actor"`
Resource Resource `json:"resource"`
}
// Outcome encodes whether an action succeeded or failed.
type Outcome string
// Event type constants.
const (
CapsuleCreated = "capsule.created"
CapsuleRunning = "capsule.running"
CapsulePaused = "capsule.paused"
CapsuleDestroyed = "capsule.destroyed"
SnapshotCreated = "template.snapshot.created"
SnapshotDeleted = "template.snapshot.deleted"
HostUp = "host.up"
HostDown = "host.down"
OutcomeSuccess Outcome = "success"
OutcomeError Outcome = "error"
)
// AllEventTypes is the complete set of valid event type strings.
var AllEventTypes = []string{
CapsuleCreated,
CapsuleRunning,
CapsulePaused,
CapsuleDestroyed,
SnapshotCreated,
SnapshotDeleted,
// Event is the canonical notification payload published to the Redis stream
// and delivered to channel subscribers.
//
// Outcome distinguishes success vs. failure for action events. It is empty
// for events with no success/error semantics (state.changed, host.up, host.down).
// Error carries the failure reason when Outcome == OutcomeError.
// Metadata carries event-specific structured context (e.g., reason, from/to
// state for transitions, inferred=true for reconciler-derived events).
type Event struct {
Event string `json:"event"`
Outcome Outcome `json:"outcome,omitempty"`
Timestamp string `json:"timestamp"`
TeamID string `json:"team_id"`
Actor Actor `json:"actor"`
Resource Resource `json:"resource"`
Metadata map[string]string `json:"metadata,omitempty"`
Error string `json:"error,omitempty"`
}
// Event type constants. Group-level names: subscription matches on Event,
// Outcome is a payload field so webhook recipients can distinguish success
// from failure without separate subscriptions.
const (
// Durable, subscribable. First boot only (subsequent unpauses are CapsuleResume).
CapsuleCreate = "capsule.create"
CapsulePause = "capsule.pause"
CapsuleResume = "capsule.resume"
CapsuleDestroy = "capsule.destroy"
// Durable, subscribable.
SnapshotCreate = "template.snapshot.create"
SnapshotDelete = "template.snapshot.delete"
// Durable, no outcome (binary by name).
HostUp = "host.up"
HostDown = "host.down"
// Transient (SSE-only via PublishTransient). Not subscribable.
// Metadata: from, to (sandbox status strings).
CapsuleStateChanged = "capsule.state.changed"
)
// SubscribableEventTypes is the set of event types users can subscribe to
// via channels (webhook, telegram, shoutrrr). Excludes transient events.
var SubscribableEventTypes = []string{
CapsuleCreate,
CapsulePause,
CapsuleResume,
CapsuleDestroy,
SnapshotCreate,
SnapshotDelete,
HostUp,
HostDown,
}