Module: Sessions::EndReason

Defined in:
lib/sessions/end_reason.rb

Overview

Canonical lifecycle vocabulary for registry rows.

v0.1.x used “row missing + event tombstone” as the revocation signal. That made Warden infer security intent from absence, which is exactly how quiet housekeeping ended up looking too much like a real logout. v0.2 moves the source of truth onto the session row itself: events are audit trail, not liveness state.

External precedents:

Constant Summary collapse

LOGOUT =
"logout"
EXPIRED =
"expired"
SUPERSEDED =
"superseded"
REVOKED =
%w[
  user_revoked
  admin_revoked
  password_change
  logout_everywhere
  pruned
  unknown
].freeze
INTERNAL =
[SUPERSEDED].freeze
EVENTS =
{
  LOGOUT => "logout",
  EXPIRED => "expired"
}.freeze
KICKING =
([LOGOUT, EXPIRED] + REVOKED).freeze

Class Method Summary collapse

Class Method Details

.event_for(reason) ⇒ Object



55
56
57
58
59
60
# File 'lib/sessions/end_reason.rb', line 55

def event_for(reason)
  normalized = normalize(reason)
  return nil if internal?(normalized)

  EVENTS.fetch(normalized, "revoked")
end

.internal?(reason) ⇒ Boolean

Returns:

  • (Boolean)


47
48
49
# File 'lib/sessions/end_reason.rb', line 47

def internal?(reason)
  INTERNAL.include?(normalize(reason))
end

.kicks_on_resume?(reason) ⇒ Boolean

Returns:

  • (Boolean)


51
52
53
# File 'lib/sessions/end_reason.rb', line 51

def kicks_on_resume?(reason)
  KICKING.include?(normalize(reason))
end

.normalize(reason) ⇒ Object



42
43
44
45
# File 'lib/sessions/end_reason.rb', line 42

def normalize(reason)
  value = reason.to_s.presence || "unknown"
  value == "revoked" ? "user_revoked" : value
end

.revoked_reason_for(reason) ⇒ Object



62
63
64
65
# File 'lib/sessions/end_reason.rb', line 62

def revoked_reason_for(reason)
  normalized = normalize(reason)
  event_for(normalized) == "revoked" ? normalized : nil
end