tagid - Typed Unique Identifiers for Rust Entities
tagid provides a robust system for defining and managing typed unique identifiers in Rust. It supports multiple ID generation strategies (CUID, UUID, Snowflake) and enables rich semantic tracking via Provenance.
Core Architecture
The tagid system is built on the principle of Zero-Cost Semantic Tagging. It separates the identity of an object from its origin and its presentation.
Component Overview
graph TD
subgraph "Core Types"
ID[Id<T, ID>]
Sourced[Sourced<E, S>]
end
subgraph "Traits"
Label[Label]
Provenance[Provenance]
Entity[Entity]
end
subgraph "Presentation"
Labeled[Labeled<T, ID>]
LabelMode{LabelMode}
end
ID --> Sourced
Sourced --> Label
Sourced --> Provenance
Sourced -.-> |Implements if S=Generated| Entity
ID -.-> |Produces| Labeled
Labeled --> LabelMode
Features
- Typed Identifiers: Define entity-specific IDs with compile-time safety.
- Provenance Tracking: Tag IDs with their origin (External, Generated, Imported, etc.).
- Opaque External IDs: Preserve prefixes (like Stripe's
cus_) exactly as received. - Explicit Labeling: Opt-in human-readable formatting for logs and UIs.
- Multiple ID Generators: CUID, UUID (v4/v7), Snowflake, ULID.
- Framework Integration: Seamless support for
serdeandsqlx.
The 6 Axes of tagid Design
- Provenance: Encode the origin of an ID (8 core types) at the type level with zero runtime cost.
- Strict Opaqueness: Treat external identifiers as atomic atoms—no stripping or parsing of prefixes.
- Presentation vs. Data:
DisplayandSerializeare strictly canonical; human-friendly context is opt-in via.labeled(). - Behavior Control: Type safety ensures only
GeneratedIDs can be created via.next_id(). - LabelPolicy Bridge: Sensible defaults for human output based on the ID's origin.
- Metadata Separation: Auxiliary data lives in
Descriptortypes outside the core identifier.
Usage
Internal Generation
use ;
use ;
;
type UserId = ;
External Opaque IDs
use ;
use ;
;
type CustomerId = ;
Data Flow (Canonical Integrity)
flowchart LR
In([External Source]) -->|from_source| ID[tagid Typed ID]
ID -->|as_str| DB[(Database)]
ID -->|Serialize| JSON[JSON API]
ID -->|labeled| Logs[[Structured Logs]]
style ID fill:#f96,stroke:#333,stroke-width:2px
Installation
Add tagid to your Cargo.toml:
[]
= { = "1.0", = ["uuid", "sqlx"] }
Examples
Detailed patterns in the examples/ directory:
01_basic_generation.rs: Internal ID creation.02_external_opaque_ids.rs: Handling foreign system identifiers.03_labeling_modes.rs: Using Policies and Overrides.04_advanced_scenarios.rs: Technical deep dive into the 6 Axes of tagid Design.05_distributed_strategies.rs: Swapping CUID, Snowflake, and ULID.
Design Documents
For a deep dive into the architecture and principles:
- tagid Redesign Specification (Technical Deep Dive)
- Provenance-Aware Construction Patterns (When and how to create IDs)
Contributing
Contributions are welcome! Open an issue or submit a pull request on GitHub.
License
This project is licensed under the MIT License.