View raw

1 (** A trainee: the account that owns a routine, a workout in progress, and a 2 logbook. Identity lives in {!Hito_app}, not the core, because the core needs 3 none. 4 5 A {!credential} is a password verifier, never the password. The hash is 6 computed and checked here so that no other layer sees a plaintext password 7 for longer than one request. *) 8 9 type id = private string 10 (** An opaque account identity, assigned by an adapter. *) 11 12 val id : string -> id 13 val id_to_string : id -> string 14 15 type username = private string 16 (** A normalized username: trimmed and lowercased ASCII. *) 17 18 type username_error = 19 | Too_short (** Fewer than {!username_min_length} characters. *) 20 | Too_long (** More than {!username_max_length} characters. *) 21 22 val username_min_length : int 23 val username_max_length : int 24 25 val username : string -> (username, username_error) result 26 (** Normalizes and validates a username. Trims and lowercases the input, then 27 requires its length within {!username_min_length}..{!username_max_length} 28 inclusive. *) 29 30 val username_to_string : username -> string 31 val pp_username_error : Format.formatter -> username_error -> unit 32 33 type credential 34 (** A password verifier. Carries a salted hash, never the password. *) 35 36 val credential_of_hash : string -> credential 37 (** Wraps a stored hash read back from persistence. *) 38 39 val credential_to_hash : credential -> string 40 (** The stored hash, for persistence. *) 41 42 val hash_password : string -> credential 43 (** Salts and hashes a new password. Accepts any string; there is no length or 44 content policy on passwords. *) 45 46 val verify_password : credential -> string -> bool 47 (** Constant-time verification of a candidate password against the verifier. *) 48 49 type t = { id : id; username : username; credential : credential } 50 (** A stored account. *) 51