Module: Familia::SecureIdentifier

Included in:
Familia, VerifiableIdentifier
Defined in:
lib/familia/secure_identifier.rb

Instance Method Summary collapse

Instance Method Details

#generate_hex_idString

Generates a 256-bit cryptographically secure hexadecimal identifier.

Returns:

  • (String)

    A 64-character hex string representing 256 bits of entropy.



13
14
15
# File 'lib/familia/secure_identifier.rb', line 13

def generate_hex_id
  SecureRandom.hex(32)
end

#generate_hex_trace_idString

Note:

64 bits provides ~18 quintillion values, sufficient for request tracing.

Generates a 64-bit cryptographically secure hexadecimal trace identifier.

Returns:

  • (String)

    A 16-character hex string representing 64 bits of entropy.



21
22
23
# File 'lib/familia/secure_identifier.rb', line 21

def generate_hex_trace_id
  SecureRandom.hex(8)
end

#generate_id(base = 36) ⇒ String

Generates a cryptographically secure identifier, encoded in the specified base. By default, this creates a compact, URL-safe base-36 string.

Parameters:

  • base (Integer) (defaults to: 36)

    The base for encoding the output string (2-36, default: 36).

Returns:

  • (String)

    A secure identifier.



30
31
32
33
# File 'lib/familia/secure_identifier.rb', line 30

def generate_id(base = 36)
  target_length = SecureIdentifier.min_length_for_bits(256, base)
  generate_hex_id.to_i(16).to_s(base).rjust(target_length, '0')
end

#generate_trace_id(base = 36) ⇒ String

Generates a short, secure trace identifier, encoded in the specified base. Suitable for tracing, logging, and other ephemeral use cases.

Parameters:

  • base (Integer) (defaults to: 36)

    The base for encoding the output string (2-36, default: 36).

Returns:

  • (String)

    A secure short identifier.



40
41
42
43
# File 'lib/familia/secure_identifier.rb', line 40

def generate_trace_id(base = 36)
  target_length = SecureIdentifier.min_length_for_bits(64, base)
  generate_hex_trace_id.to_i(16).to_s(base).rjust(target_length, '0')
end

#shorten_to_trace_id(hex_id, base: 36) ⇒ String

Creates a deterministic 64-bit trace identifier from a longer hex ID.

This is a convenience method for truncate_hex(hex_id, bits: 64). Useful for creating short, consistent IDs for logging and tracing.

Parameters:

  • hex_id (String)

    The input hexadecimal string.

  • bits (Integer)

    The desired output bit length (e.g., 128, 64). Defaults to 128.

  • base (Integer) (defaults to: 36)

    The numeric base for the output string (2-36). Defaults to 36.

Returns:

  • (String)

    A new, shorter identifier in the specified base.



52
53
54
# File 'lib/familia/secure_identifier.rb', line 52

def shorten_to_trace_id(hex_id, base: 36)
  truncate_hex(hex_id, bits: 64, base: base)
end

#truncate_hex(hex_id, bits: 128, base: 36) ⇒ String

Deterministically truncates a hexadecimal ID to a specified bit length.

This function preserves the most significant bits of the input hex_id to create a shorter, yet still random-looking, identifier.

Parameters:

  • hex_id (String)

    The input hexadecimal string.

  • bits (Integer) (defaults to: 128)

    The desired output bit length (e.g., 128, 64). Defaults to 128.

  • base (Integer) (defaults to: 36)

    The numeric base for the output string (2-36). Defaults to 36.

Returns:

  • (String)

    A new, shorter identifier in the specified base.

Raises:

  • (ArgumentError)

    if hex_id is not a valid hex string, or if input_bits is less than the desired output bits.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/familia/secure_identifier.rb', line 67

def truncate_hex(hex_id, bits: 128, base: 36)
  target_length = SecureIdentifier.min_length_for_bits(bits, base)
  input_bits = hex_id.length * 4

  unless hex_id.match?(/\A[0-9a-fA-F]+\z/)
    raise ArgumentError, "Invalid hexadecimal string: #{hex_id}"
  end

  if input_bits < bits
    raise ArgumentError, "Input bits (#{input_bits}) cannot be less than desired output bits (#{bits})."
  end

  # Truncate by right-shifting to keep the most significant bits
  truncated_int = hex_id.to_i(16) >> (input_bits - bits)
  truncated_int.to_s(base).rjust(target_length, '0')
end