Every event type emitted by the Nimbus controller, grouped by subsystem.
Events are sealed subclasses of NimbusEvent (see nimbus-core/src/main/kotlin/dev/nimbuspowered/nimbus/event/Events.kt). They are emitted on the internal EventBus and — after running through EventRoutes.toEventMessage() — serialised into the wire format pushed over /api/events and stored in the audit log.
actor is used by AuditCollector for the audit_log table. It is not currently included in the WebSocket payload — the actor visible in the audit log does not round-trip through /api/events today.
SERVICE_READY is the point at which service.ready() pattern matched in stdout (or the SDK plugin reported ready). Use it rather than SERVICE_STARTING for "is available to players" logic.
Important semantic. Controller modules do not own top-level sealed subclasses of NimbusEvent. Instead they emit NimbusEvent.ModuleEvent(moduleId, type, data) — but the serializer unwraps this and sends the envelope's type directly at the top level, with moduleId folded into the data map where relevant. That's why PERMISSION_GROUP_CREATED, PUNISHMENT_ISSUED, BACKUP_COMPLETED etc. appear as first-class type strings on the wire, even though they are dispatched through ModuleEvent internally.
Module events below use the same frame format. moduleId is included so generic subscribers can filter by owning module without pattern-matching on the type.
id, targetName, sizeBytes, durationMs, status (SUCCESS / PARTIAL)
BACKUP_FAILED
id, targetName, reason
BACKUP_RESTORED
id, targetName, targetPath, triggeredBy
BACKUP_PRUNED
count, freedBytes, scheduleClass
BACKUP_COMPLETED with status = "PARTIAL" is emitted when some target (e.g. a remote-node service, or a missing mysqldump binary) was skipped with a WARN but the archive was written successfully. Treat PARTIAL as "inspect the record details" rather than "failure".
WebSocket — connect to /api/events with a bearer token. Every event shows up as one frame. See WebSocket reference.
Remote CLI / multiplex — subscribers to /api/console/stream receive events inside { "type": "event", "event": { ... } } envelopes. STRESS_TEST_UPDATED and NODE_HEARTBEAT are suppressed here to keep the CLI readable.
Audit log — AuditCollector persists a filtered subset of events (actor-attributable ones) to the audit_log table with the actor field preserved. Query with GET /api/audit.
In-process — modules and core subsystems subscribe via EventBus.subscribe() and receive the raw sealed-class instances, including the full actor field and strongly-typed properties.
The MODULE_EVENT envelope is the sanctioned way for a 3rd-party module to push its own events without forking Events.kt. Use:
eventBus.emit(NimbusEvent.ModuleEvent( moduleId = "my-module", type = "MY_THING_HAPPENED", data = mapOf("target" to name, "reason" to reason)))
The type string is what external subscribers see in the top-level type field, so pick something stable and uppercase. Include moduleId in the data too if you want receivers to filter without namespacing the type.