struct

KemalIdentity::ApiTokens::LifetimePolicy

Inherits Struct < Value < Object

How long a personal access token may live in this deployment.

An enterprise requires every token to expire within thirty days and forbids unbounded ones; the deployment next door permits a non-expiring deploy key. Both are correct, so this is absent by defaultService.new with no policy accepts what its caller asks for, including no expiry at all, which is the shipped behaviour and stays it.

Checked at issuance, and only there

A policy describes what may be created. It is not consulted on the authentication path: every request already reads the token's own expires_at, and re-deriving a limit per request would put a policy lookup on the hot path to answer a question the row already answers.

The consequence, which docs/02-security-model.md states rather than leaves to be discovered: tightening the policy does not shorten the tokens that already exist. A ninety-day token issued under the old rule keeps its ninety days. That is the honest behaviour for a rule about creation, and it is why Service#expire exists — an organisation that must apply a new limit retroactively walks its tokens and brings each deadline forward, which is one call per token and cannot lengthen anything by mistake.

policy = KemalIdentity::ApiTokens::LifetimePolicy.new(maximum: 30.days, default: 7.days)

Constructors

new(maximum : Time::Span, default : Time::Span | Nil = nil)
Source

Instance methods

default

What to use when the caller names no expiry. nil means an issuance with no expiry is refused rather than defaulted — the stricter reading, and the one an enterprise asking for this feature usually wants: a client that forgot to ask for a deadline should be told, not quietly given one.

Source
maximum

The furthest away an expiry may be, measured from the moment of issuance.

Source
resolve(expires_at : Time | Nil, now : Time) : Time | Nil

The expiry to store, filling in default when the caller named none. Returns nil when there is nothing to fill in, which #violation then refuses.

Source
violation(expires_at : Time | Nil, now : Time) : PolicyViolation | Nil

Why this expiry is unacceptable, or nil if it is fine.

Takes now rather than reading a clock: a policy is a value, and the one thing worse than a policy that cannot be tested is one that reads the system clock while being tested.

Source