-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontrol_flow.hum
More file actions
103 lines (76 loc) · 1.88 KB
/
Copy pathcontrol_flow.hum
File metadata and controls
103 lines (76 loc) · 1.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
module examples.control_flow
task find_active_session(user: UserId, sessions: Sessions) -> Result Session, SessionError {
why:
find the first non-expired session for a user
uses:
sessions
clock.now
needs:
sessions belongs to trusted store
ensures:
returned session belongs to user
returned session is not expired
fails when:
no active session exists
watch for:
sessions may be empty
expired sessions must not authenticate
cost:
time: O(sessions)
space: O(1)
allocates: nothing
check: compile
avoids:
nested scan over users and sessions
allocation inside loop
tradeoffs:
linear scan is acceptable for small local session lists
does:
for each session in sessions {
if session.user == user and session.expires_at > clock.now {
return session
}
}
fail SessionError.not_found
}
task make_unique_token(random: SecureRandom, sessions: Sessions) -> Result SessionToken, TokenError {
why:
create a token that is not already present in the session store
uses:
random
sessions
needs:
random is cryptographically secure
ensures:
token is not already in sessions
protects:
attacker cannot predict token
fails when:
unique token is not found within bounded attempts
watch for:
random source may repeat values
loop must remain bounded
cost:
time: O(1)
space: O(1)
allocates: up to 16 token candidates
check: compile
avoids:
unbounded retry loop
predictable token generation
does:
change attempts: UInt = 0
while attempts < 16 {
keeps:
attempts <= 16
changes:
attempts
does:
let token = random token()
if sessions does not contain token {
return token
}
set attempts = attempts + 1
}
fail TokenError.too_many_collisions
}