Trove

Ecosystem Integration

Auto-discovery hooks for Chronicle audit, Vault encryption, Dispatch jobs, Warden access control, and Prometheus metrics.

Trove integrates with the Forge ecosystem through auto-discovery hooks. Each hook checks for a specific service in the DI container and wires itself in when available. If a service isn't present, the hook is silently skipped.

Chronicle (Audit)

When chronicle.Emitter is in DI, Trove emits audit events for storage operations.

Events

EventTrigger
trove.object.createdObject uploaded or copied
trove.object.readObject downloaded
trove.object.deletedObject deleted
trove.object.copiedObject copied
trove.bucket.createdBucket created
trove.bucket.deletedBucket deleted
trove.upload.initiatedMultipart upload started
trove.upload.completedMultipart upload finalized
trove.upload.abortedMultipart upload cancelled
trove.cas.storedContent stored in CAS
trove.cas.gcCAS garbage collection ran

Event Metadata

Each event includes contextual metadata:

// Object events include:
{
    "bucket": "uploads",
    "key":    "photos/cat.jpg",
    "size":   204800,
}

// CAS events include:
{
    "size":         1024,
    "deduplicated": true,
}

// GC events include:
{
    "scanned":     1500,
    "deleted":     42,
    "freed_bytes": 8388608,
}

Setup

Chronicle audit is automatic when the Chronicle extension is loaded:

app := forge.New(
    forge.WithExtensions(
        chronicleext.New(),  // Provides chronicle.Emitter to DI
        troveext.New(),      // Auto-discovers and wires audit hook
    ),
)

Vault (Encryption Keys)

When store.Store from the Vault package is in DI, Trove auto-configures encryption middleware with Vault-managed keys.

How It Works

  1. The hook injects the Vault store.Store from DI
  2. Creates a KeyProvider that retrieves the encryption key from Vault
  3. The key is fetched from the secret path trove/data-encryption-key
  4. The key is passed to Trove's AES-256-GCM encryption middleware

Key Storage

Store the encryption key in Vault before starting Trove:

// Using vault's secret service:
secretSvc.Set(ctx, "trove/data-encryption-key", encryptionKey, appID)

The key must be raw bytes suitable for AES-256-GCM (32 bytes).

Setup

app := forge.New(
    forge.WithExtensions(
        vaultext.New(),  // Provides vault store to DI
        troveext.New(),  // Auto-discovers and configures encryption
    ),
)

Dispatch (Background Jobs)

When *engine.Engine from Dispatch is in DI, Trove registers background jobs.

Registered Jobs

Job NameDescription
trove.cleanup-expired-uploadsDeletes expired multipart upload sessions
trove.cas-gcRemoves unreferenced CAS objects (GC)

CAS Garbage Collection

The trove.cas-gc job calls CAS().GC() and logs results:

CAS garbage collection completed  scanned=1500  deleted=42  freed_bytes=8388608  errors=0

Setup

app := forge.New(
    forge.WithExtensions(
        dispatchext.New(), // Provides *engine.Engine to DI
        troveext.New(),    // Registers background jobs
    ),
)

Warden (Access Control)

When *warden.Engine is in DI, Trove applies authorization middleware to all routes.

Resource Types

ResourceApplied To
trove:bucketBucket CRUD operations
trove:objectObject CRUD operations
trove:uploadMultipart upload operations
trove:streamStreaming operations
trove:casCAS operations

Action Mapping

HTTP MethodAction
GET, HEADread
PUT, POSTcreate
DELETEdelete

How It Works

  1. For each request, the middleware extracts the resource type from the URL path
  2. Maps the HTTP method to an action
  3. Extracts the subject from the X-Subject-ID header (defaults to "anonymous")
  4. Calls warden.Engine.Check() with the subject, action, and resource
  5. Returns 403 Forbidden if denied, or passes through to the handler

Setup

app := forge.New(
    forge.WithExtensions(
        wardenext.New(),  // Provides *warden.Engine to DI
        troveext.New(),   // Applies authorization middleware
    ),
)

Prometheus Metrics

The metrics hook registers Prometheus metrics for monitoring Trove operations.

Metric Names

MetricTypeDescription
trove_objects_totalCounterTotal objects stored
trove_objects_size_bytesCounterTotal bytes stored
trove_uploads_activeGaugeActive multipart uploads
trove_uploads_completed_totalCounterCompleted uploads
trove_uploads_failed_totalCounterFailed uploads
trove_stream_bytes_sent_totalCounterBytes sent via streams
trove_stream_bytes_recv_totalCounterBytes received via streams
trove_middleware_duration_secondsHistogramMiddleware processing time
trove_cas_dedup_hits_totalCounterCAS deduplication hits
trove_cas_dedup_bytes_savedCounterBytes saved by dedup
trove_driver_latency_secondsHistogramStorage driver latency
trove_driver_errors_totalCounterStorage driver errors
trove_quota_usage_bytesGaugeCurrent quota usage
trove_quota_limit_bytesGaugeConfigured quota limit

Labels

  • bucket — bucket name
  • driver — storage driver name
  • operation — driver operation (get, put, delete, list, head, copy)

On this page