Chronicle

Identity (TypeID)

How Chronicle uses type-safe, prefix-qualified identifiers for every entity.

Every entity in Chronicle has a TypeID. TypeIDs are globally unique, K-sortable, URL-safe identifiers built on UUIDv7 with a human-readable prefix that tells you what kind of entity you're looking at.

A TypeID looks like this:

audit_01j9vk2qz3p4r5t6w7x8y9z0ab
stream_01j9vk2qz3p4r5t6w7x8y9z0ab
erasure_01j9vk2qz3p4r5t6w7x8y9z0ab

Prefixes

Chronicle defines seven entity prefixes:

PrefixEntityConstructor
audit_Audit eventid.NewAuditID()
stream_Hash chain streamid.NewStreamID()
erasure_GDPR erasure recordid.NewErasureID()
report_Compliance reportid.NewReportID()
retpol_Retention policyid.NewPolicyID()
archive_Retention archiveid.NewArchiveID()
plugin_Plugin registrationid.New(id.PrefixPlugin)

The id.ID struct

All entity types use the same id.ID struct with a valid flag. A zero-value id.ID represents a nil / unset identifier. You always construct IDs through the constructors or parsers — never by initialising the struct directly.

import "github.com/xraph/chronicle/id"

// Create new IDs
auditID  := id.NewAuditID()
streamID := id.NewStreamID()

// Parse from string (any prefix)
parsed, err := id.ParseAny("audit_01j9vk...")

// Parse with prefix validation (returns error if wrong prefix)
auditID, err := id.ParseAuditID("audit_01j9vk...")
streamID, err := id.ParseStreamID("stream_01j9vk...")

// Check for nil
if auditID.IsNil() { ... }

// Format as string
s := auditID.String() // "audit_01j9vk..."

Passing an erasure_ string to id.ParseAuditID returns an error — prefix validation is type-safe at parse time.

Serialization

id.ID implements all standard interfaces out of the box:

InterfaceRepresentation
encoding.TextMarshaler / TextUnmarshaler"audit_01j9vk..."
json.Marshaler / json.Unmarshaler"audit_01j9vk..."
driver.Valuer (database write)"audit_01j9vk..." as string
sql.Scanner (database read)accepts string or []byte

Nil IDs marshal as "" in JSON and as NULL in SQL.

Why TypeIDs?

  • K-sortable — UUIDv7 embeds a millisecond timestamp, so IDs naturally sort by creation time in database indexes.
  • Human-readable — the prefix tells you at a glance what kind of record you're looking at in logs, URLs, and database queries.
  • Type safetyParseAuditID vs ParseStreamID catches mismatched IDs at parse time rather than at query time.
  • Compact — base32-encoded UUIDs are shorter than UUID hex strings.

On this page