Shield

Identity (TypeID)

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

Every entity in Shield 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
Scanscan_id.ScanIDscan_01h2xcejqtf2nbrexx3vqjhp41
Policypol_id.PolicyIDpol_01h2xcejqtf2nbrexx3vqjhp41
Findingfind_id.FindingIDfind_01h2xcejqtf2nbrexx3vqjhp41
PII Tokenpii_id.PIITokenIDpii_01h2xcejqtf2nbrexx3vqjhp41
Compliance Reportcrpt_id.ComplianceReportIDcrpt_01h2xcejqtf2nbrexx3vqjhp41
Safety Checkschk_id.CheckIDschk_01h2xcejqtf2nbrexx3vqjhp41
Instinctinst_id.InstinctIDinst_01h455vb4pex5vsknk084sn02q
Judgmentjdg_id.JudgmentIDjdg_01h455vb4pex5vsknk084sn02q
Awarenessawr_id.AwarenessIDawr_01h455vb4pex5vsknk084sn02q
Valueval_id.ValueIDval_01h455vb4pex5vsknk084sn02q
Reflexrflx_id.ReflexIDrflx_01h455vb4pex5vsknk084sn02q
Boundarybnd_id.BoundaryIDbnd_01h455vb4pex5vsknk084sn02q
SafetyProfilesprf_id.SafetyProfileIDsprf_01h455vb4pex5vsknk084sn02q

Constructors

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

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

scanID    := id.NewScanID()           // scan_01h...
policyID  := id.NewPolicyID()         // pol_01h...
instID    := id.NewInstinctID()       // inst_01h...
judgID    := id.NewJudgmentID()       // jdg_01h...
profileID := id.NewSafetyProfileID()  // sprf_01h...

Parsing

Parse functions validate both the format and the prefix:

scanID, err := id.ParseScanID("scan_01h2xcejqtf2nbrexx3vqjhp41")
// err is nil — prefix matches

_, err = id.ParseScanID("inst_01h455vb4pex5vsknk084sn02q")
// err: id: expected prefix "scan", got "inst"

Use id.ParseAny when you need to accept any valid TypeID regardless of prefix:

anyID, err := id.ParseAny("inst_01h455vb4pex5vsknk084sn02q")
// anyID.Prefix() == "inst"

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

On this page