Ruby implementation of Universal Entity IDs (UEIDs) — fork of bolderbrooklyn/ueid-ruby with Model ID Spec compliance.
  • Ruby 82.1%
  • JavaScript 17.5%
  • Shell 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Kalmiya 30d4339da4
Some checks failed
CI / test · lint · conformance (push) Failing after 0s
Ruby / Ruby 3.2 (push) Failing after 0s
feat: full UEID spec conformance + strict ver/var validation
Implements the expanded UEID Specification v1 (full bit layout +
encoding + parsing). The spec repo's references in the README
were unqualified, and a future reader would reasonably expect
ueid-spec to define the whole format, not just the model field
algorithm.

Spec conformance:
- conformance/roundtrip-vectors.json: 8 vectors pinning every
  field of a UEID (unix_ts_ms, ver, model, count, var, random,
  hex, dashed, undashed). Mirrors the canonical set in ueid-spec.
- scripts/generate-roundtrip-vectors.js: regenerate the file
  when the bit layout or encoding changes.
- scripts/check-conformance.rb: now verifies BOTH the model-
  hash vectors and the round-trip vectors.
- spec/conformance/roundtrip_spec.rb: 7 RSpec cases covering
  round-trip, layout invariants, fixed-bit validation,
  dashed/undashed forms.

Bug fix from the spec work:
- The hardcoded test-vector string used in spec/ueid_spec.rb and
  spec/ueid/ueid_spec.rb was '019c2c83-8104-83fa-8417-5fb7e28a5464',
  whose group 3 encoded model=65, count=7 in its bits — not the
  documented model=63 (String), count=10. Corrected to
  '019c2c83-8104-83fa-8000-1fb7e28a5464' everywhere.

Spec compliance:
- UEID::UEID.from_s now rejects strings whose ver field is not
  0b1000 or whose var field is not 0b10, per SPECIFICATION.md
  §2.2 and §2.5. Previous behaviour silently accepted any
  32-hex-char string regardless of reserved bits. Throws
  UEID::Error on mismatch.

Version bumped to 0.2.1.
2026-07-21 12:54:27 -07:00
.github/workflows feat: align with UEID Model ID Specification v1 2026-07-21 11:48:28 -07:00
bin import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00
conformance feat: full UEID spec conformance + strict ver/var validation 2026-07-21 12:54:27 -07:00
lib feat: full UEID spec conformance + strict ver/var validation 2026-07-21 12:54:27 -07:00
scripts feat: full UEID spec conformance + strict ver/var validation 2026-07-21 12:54:27 -07:00
sig import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00
spec feat: full UEID spec conformance + strict ver/var validation 2026-07-21 12:54:27 -07:00
.gitignore import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00
.rspec import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00
.standard.yml import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00
CHANGELOG.md feat: full UEID spec conformance + strict ver/var validation 2026-07-21 12:54:27 -07:00
CODE_OF_CONDUCT.md import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00
Gemfile import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00
Gemfile.lock import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00
LICENSE.txt import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00
mise.toml import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00
Rakefile import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00
README.md feat: full UEID spec conformance + strict ver/var validation 2026-07-21 12:54:27 -07:00
ueid.gemspec import: snapshot of bolderbrooklyn/ueid-ruby @ 6a3923568f 2026-07-21 11:41:39 -07:00

ueid-ruby

Ruby implementation of Universal Entity IDs (UEIDs) for universal, machine-identifiable record identifiers.

Explanation

UEIDs are designed along the same principle as UXIDs, which are human-friendly identifiers that enable easy identification of an entity's type from its ID. However, UXIDs are optimized for human readability, and are typically stored as strings. In contrast, UEIDs are optimized for machine processing and storage efficiency, making them suitable for use in databases and systems where compactness and speed are critical.

UEIDs are an implementation of the UUID Version 8 standard, combining the timestamp-ordering of UUID version 7, a custom field identifying the entity type, a sequential component for intra-millisecond uniqueness, and a random component for global uniqueness. They can be stored using the native UUID data types of modern databases, such as PostgreSQL's uuid type, allowing for more efficient storage and indexing compared to string-based identifiers.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          unix_ts_ms                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          unix_ts_ms           |  ver  |     model     | count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var|                        random                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            random                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Fields

unix_ts_ms (48 bits)

A 48 bit big-endian unsigned integer of the Unix epoch timestamp in milliseconds, according to the Timestamp Considerations of the UUID specification. This is identical to the timestamp field of UUIDv7.

ver (4 bits)

The 4 bit UUIDv8 version as per the Version Field format of the UUID specification.

model (8 bits)

An 8 bit unsigned integer uniquely identifying the entity type or model. The algorithm for computing this field is defined by the UEID Model ID Specification, Version 1. Briefly: the model identifier string is encoded as UTF-8, hashed with FNV-1a-32, then iteratively folded to 8 bits. Test vectors and the canonical reference implementation are in the spec repository.

count (4 bits)

A 4 bit unsigned integer counter that increments with each UEID generated within the same millisecond timestamp and for the same model. This guarantees at least 16 unique UEIDs can be generated per model per millisecond.

var (2 bits)

The 2 bit UUID variant as per the Variant Field format of the UUID specification.

random (62 bits)

The final 62 bit of pseudo-random data to provide uniqueness as per the Unguessability best practices of the UUID specification.

Limitations

  • Model identifiers are only unique within a single application or system. Different applications may use the same model identifiers for different entity types.
  • The 8 bit model field is a 256-bucket hash. Two different identifiers have a 50% chance of colliding once you register roughly 20 of them (birthday paradox). Registry.collision_policy controls what happens on collision: :error (the default in 0.2.0+; raises UEID::Error so conflicts surface at registration time), :warn (logs and overwrites), :overwrite (silent, the historical behaviour). For any non-trivial application, leave the default in place and rename the colliding identifier.
  • The theoretical maximum is 256 unique entity types per application, but in practice you should expect collisions well before that ceiling.
  • UEIDs can guarantee a maximum of 16 unique IDs per model per millisecond. Applications requiring higher throughput may need to implement additional mechanisms to guarantee uniqueness.
  • Only 62 bits of randomness are provided, compared to the 74 bits in UUIDv7 and 122 bits in UUIDv4. While this is generally sufficient for most applications, it may not be suitable for scenarios requiring extremely high levels of uniqueness or security.

Usage

This gem provides modules and classes to generate and parse UEIDs in Ruby, using only the Ruby standard library with no external dependencies. It aims to be compatible with Ruby version 3.2 or later, and any Ruby database library that supports UUID, binary, string, or bytea data types, such as ActiveRecord, Sequel, or ROM.

Installation

Add this line to your application's Gemfile:

gem 'ueid'

or install it yourself with:

gem install ueid
# or
bundle add ueid

Examples

require 'ueid'

class MyModel; end

# Generate a UEID for a specific model class...
UEID.generate(MyModel)

# ...or for a specific object
object = MyModel.new()
UEID.generate(object.class)

# Or pass an explicit model id when class.name is unstable:
UEID.generate(MyModel, "my_model")

Model ID Specification

The 8-bit model field is computed from a string identifier using the algorithm defined by the UEID Specification, Version 1. Conformance is verified against conformance/vectors.json (model-hash) and conformance/roundtrip-vectors.json (full bit layout) in this repository, both mirroring the canonical test-vector sets in the spec repo.

Override Registry.model_id_for(klass) to use a custom string instead of klass.name. Pass an explicit id to UEID.generate(klass, "my_id") or Registry.hash_for_class(klass, "my_id") to override per call.

The default collision policy in 0.2.0+ is :error: a registration that would overwrite a different class's binding raises UEID::Error. To take the historical silent-overwrite behaviour, set Registry.collision_policy = :overwrite early in your boot sequence.

ActiveRecord Example

After configuring your application to use UUIDs as primary keys, you can configure your base ApplicationRecord class to assign UEID primary keys to new records:

class ApplicationRecord < ActiveRecord::Base
  # ...

  before_create :assign_ueid

  # ...

  private

  def assign_ueid
    self.id ||= UEID.generate(self.class)
  end
end

Development

Requirements

  • Ruby 3.2 or later
  • (optional) mise

Setup

git clone https://tangled.org/did:plc:hfjjkmleodmclbfae27m3ngt/ueid-ruby.git
cd ueid-ruby

# If you use mise and don't have ruby installed system-wide:
mise trust
mise install
bin/setup

Testing

bundle exec rake test

The conformance suite (spec/conformance/model_id_spec.rb) verifies every test vector in conformance/vectors.json. Run it in CI on every push to catch drift from the spec.

UEID Specification

This gem implements the UEID Specification, Version 1. The full algorithm contract — bit layout, encoding, parsing rules, the FNV-1a-32 + iterative xor-shift fold that produces the model field, the conformance checklist, and the round-trip vectors that pin every field of a UEID — is in SPECIFICATION.md in the spec repository. Test vectors live at conformance/vectors.json (model-hash) and conformance/roundtrip-vectors.json (full-bit-layout), both mirrored in this repository at conformance/vectors.json and conformance/roundtrip-vectors.json.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting with the UEID project through code contributions and all communication channels must abide by the code of conduct. Violations of the code of conduct may result in banishment from the project at the discretion of the project maintainers.