-
-
Notifications
You must be signed in to change notification settings - Fork 0
Data Model
Trove stores its catalog in SQLite.
The schema is migration-driven. Migrations live in:
internal/store/migrations
The database is opened and migrated automatically by the server.
| Table | Purpose |
|---|---|
agents |
Known Trove agents, token hashes, platform/version, heartbeat state. |
hosts |
Hosts reported by agents. |
services |
Current and recently removed catalog entries. |
events |
State, health, and agent transition history. |
image_checks |
Registry freshness cache per image reference. |
alert_state |
Observed/notified state per incident key. |
alert_channel_deliveries |
Temporary per-channel success records while a fan-out retry is incomplete. |
meta |
Internal key/value metadata such as migration version and alert cursor. |
| Migration | Description |
|---|---|
0001_init.sql |
Base schema: agents, hosts, services, events, meta. |
0002_image_checks.sql |
Adds image freshness cache. |
0003_service_parent.sql |
Adds nullable services.parent_id for parent/child service relationships. |
0004_event_model.sql |
Rebuilds events around kind, agent events, and denormalized display fields. |
0005_alert_notified.sql |
Adds alert_state.notified so alert delivery state is separate from observed value. |
0006_health_detail.sql |
Adds short human-readable health context to services. |
0007_alert_channel_deliveries.sql |
Tracks successful channels so retries target only failed destinations. |
Agents store:
- name
- token hash
- platform
- version
- report interval
- created time
- last seen time
- last status
Plaintext tokens are never stored. The server stores SHA-256 hashes.
Hosts belong to agents.
A host is identified by:
- agent ID
- hostname
The host also stores platform metadata as JSON. Examples include Docker version or other platform facts that are useful to display but not worth dedicated columns.
Services belong to hosts.
A service is correlated by:
- host ID
- external ID
external_id is the platform-native stable identifier, such as a container ID, Kubernetes UID, VM ID, or unit name depending on the agent.
Important fields:
namekindimageimage_digeststatehealthhealth_detailports_jsonlabels_jsonparent_idfirst_seen_atlast_seen_atupdated_at
services.parent_id is nullable.
It is used for relationships such as:
Deployment -> Pod
StatefulSet -> Pod
DaemonSet -> Pod
The migration deliberately avoids a strict foreign key for this column. Parent links are resolved during ingest, and dangling references are simple to handle in application code.
Events are append-only transition records within retention.
Kinds:
statehealthagent
Events denormalize display fields such as service name, hostname, and agent name. This is deliberate. An event should remain readable even after the service row is later pruned.
image_checks is a cache, not core inventory.
It stores:
- image reference
- latest digest
- status
- last error
- checked time
- next check time
The ingest path does not call registries. Freshness checks run in the background.
alert_state tracks per-incident alert delivery state.
The key idea is that Trove stores two separate facts:
- what bad value is currently known
- whether a notification was actually sent for it
That second fact lives in notified.
This avoids dropping resolved alerts during reconnect or cooldown edge cases.
alert_channel_deliveries handles a separate fan-out problem. If one channel succeeds and another fails, Trove remembers the success and retries only the failed channel. Rows are temporary and disappear when every configured destination has accepted the notification.
ApplyReport runs inside one SQLite transaction.
For each report:
- refresh agent heartbeat and metadata
- upsert the host
- load existing services for that host
- upsert reported services
- emit state and health events for changed values
- resolve parent links
- mark missing services as
removed - commit
Applying the same report twice should not create duplicate transition events.
When a service disappears from a full-state report, Trove marks it:
state = "removed"
health = "unknown"
It records a state event once.
Removed services remain visible until maintenance pruning removes them after TROVE_REMOVED_RETENTION.