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
-
.digest(code) ⇒ Object
What gets persisted instead of the code (P-7).
-
.format(code) ⇒ Object
Group into 4-char blocks for display: "3F7K-9B2D-…".
-
.generate(length: 16) ⇒ Object
16 chars ≈ 80 bits — fine for a short-lived, single-use code.
-
.normalize(input) ⇒ Object
Accept a pasted code in any spacing or case.
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 |