Retention
Policy-based event archival and purge.
Chronicle's retention system automatically archives and purges audit events according to configurable policies. The retention.Enforcer runs periodically (or on demand) and applies each policy to its matching events.
Policy
A retention.Policy defines how long events of a given category are kept:
| Field | Type | Description |
|---|---|---|
ID | id.ID | TypeID with retpol_ prefix |
Category | string | Category to apply to. Use "*" for all categories. |
Duration | time.Duration | Retain events for this duration. Events older than this are candidates. |
Archive | bool | If true, write to the archive sink before purging. |
AppID | string | Application scope. |
Create a policy
Via the HTTP API
POST /v1/retentionRequest body:
{
"category": "auth",
"duration": "2160h",
"archive": true
}Via the store directly
import (
"time"
"github.com/xraph/chronicle/retention"
"github.com/xraph/chronicle/id"
)
policy := &retention.Policy{
ID: id.NewPolicyID(),
Category: "auth",
Duration: 90 * 24 * time.Hour, // 90 days
Archive: true,
AppID: "myapp",
}
err := store.SavePolicy(ctx, policy)Enforcer
retention.NewEnforcer(store, archiveSink, logger) creates the enforcer. archiveSink may be nil if no archival is needed.
import "github.com/xraph/chronicle/retention"
enforcer := retention.NewEnforcer(myStore, s3Sink, logger)
result, err := enforcer.Enforce(ctx)
fmt.Printf("archived=%d purged=%d retained=%d\n",
result.Archived, result.Purged, result.Retained)Enforce iterates all policies, finds events older than Duration, optionally writes them to the archive sink, then deletes them from the store.
EnforceResult
| Field | Type | Description |
|---|---|---|
Archived | int64 | Events written to the archive sink |
Purged | int64 | Events removed from the store |
Retained | int64 | Events still within retention window |
Archive sink
When Policy.Archive = true, the enforcer writes the events to the configured sink.Sink before purging. The archive sink receives the batch via sink.Write(ctx, events).
Configure the archive sink via the extension:
ext := extension.New(
extension.WithStore(s),
extension.WithArchiveSink(s3Sink),
)Automated scheduling
The extension.WithRetentionInterval(d) option starts a background goroutine that calls Enforce every d:
ext := extension.New(
extension.WithStore(s),
extension.WithRetentionInterval(24 * time.Hour),
extension.WithArchiveSink(s3Sink),
)Set to 0 to disable automatic enforcement.
HTTP endpoints
| Method | Path | Description |
|---|---|---|
GET | /v1/retention | List retention policies |
POST | /v1/retention | Create or update a policy |
DELETE | /v1/retention/:id | Delete a policy |
POST | /v1/retention/enforce | Trigger immediate enforcement |
GET | /v1/retention/archives | List archive records |