Module: Persona::ClaimCode

Defined in:
lib/persona/claim_code.rb

Overview

Single-use claim codes (docs/spec §6): generation, input normalization, display formatting, and digest-at-rest. Codes use Crockford base32 (no I, L, O, U) so they survive being read aloud or typed. Storage keeps only the digest; consumption is the consumer's concern (single-use, atomic — P-7).

Constant Summary collapse

ALPHABET =
'0123456789ABCDEFGHJKMNPQRSTVWXYZ'.freeze

Class Method Summary collapse

Class Method Details

.digest(code) ⇒ Object

What gets persisted instead of the code (P-7).



32
33
34
# File 'lib/persona/claim_code.rb', line 32

def digest(code)
  Digest::SHA256.hexdigest(normalize(code))
end

.format(code) ⇒ Object

Group into 4-char blocks for display: "3F7K-9B2D-…".



27
28
29
# File 'lib/persona/claim_code.rb', line 27

def format(code)
  normalize(code).scan(/.{1,4}/).join('-')
end

.generate(length: 16) ⇒ Object

16 chars ≈ 80 bits — fine for a short-lived, single-use code. Raise the length for codes expected to sit unused for long periods.



17
18
19
# File 'lib/persona/claim_code.rb', line 17

def generate(length: 16)
  Array.new(length) { ALPHABET[SecureRandom.random_number(ALPHABET.length)] }.join
end

.normalize(input) ⇒ Object

Accept a pasted code in any spacing or case.



22
23
24
# File 'lib/persona/claim_code.rb', line 22

def normalize(input)
  input.to_s.upcase.gsub(/[^0-9A-Z]/, '')
end