Sentinel

Identity (TypeID)

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

Every entity in Sentinel gets a type-prefixed, K-sortable, UUIDv7-based identifier using the TypeID specification. IDs are validated at parse time to ensure the prefix matches the expected type.

Prefix table

TypePrefixGo typeExample
Suitesuite_id.SuiteIDsuite_01h2xcejqtf2nbrexx3vqjhp41
Casetcase_id.CaseIDtcase_01h2xcejqtf2nbrexx3vqjhp41
Eval Runerun_id.EvalRunIDerun_01h2xcejqtf2nbrexx3vqjhp41
Eval Resulteres_id.EvalResultIDeres_01h2xcejqtf2nbrexx3vqjhp41
Baselinebase_id.BaselineIDbase_01h2xcejqtf2nbrexx3vqjhp41
Red Teamrteam_id.RedTeamIDrteam_01h2xcejqtf2nbrexx3vqjhp41
Prompt Versionpver_id.PromptVersionIDpver_01h455vb4pex5vsknk084sn02q

Constructors

Each type has a constructor that generates a new UUIDv7-based ID with the correct prefix:

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

suiteID   := id.NewSuiteID()          // suite_01h...
caseID    := id.NewCaseID()           // tcase_01h...
runID     := id.NewEvalRunID()        // erun_01h...
resultID  := id.NewEvalResultID()     // eres_01h...
baselineID := id.NewBaselineID()      // base_01h...
redTeamID := id.NewRedTeamID()        // rteam_01h...
pvID      := id.NewPromptVersionID()  // pver_01h...

Parsing

Parse functions validate both the format and the prefix:

suiteID, err := id.ParseSuiteID("suite_01h2xcejqtf2nbrexx3vqjhp41")
// err is nil — prefix matches

_, err = id.ParseSuiteID("tcase_01h455vb4pex5vsknk084sn02q")
// err: id: expected prefix "suite", got "tcase"

K-sortability

TypeIDs embed UUIDv7 timestamps, making them naturally sortable by creation time. This means:

  • Database indexes on TypeID columns are efficient for time-range queries
  • IDs created later always sort after earlier IDs
  • No need for separate created_at indexes for ordering

Type safety

All ID types are aliases for typeid.TypeID. While Go does not enforce alias-level type safety at compile time, the prefix validation at parse time catches mismatches:

type SuiteID = typeid.TypeID
type CaseID = typeid.TypeID

Passing a case ID where a suite ID is expected will succeed at compile time but fail at parse time if the prefix is validated.

On this page