Table of Contents

Struct SecretLifetime

Namespace
MailFathom.Infrastructure.Secrets
Assembly
MailFathom.Infrastructure.dll

How long a configured secret stays usable: without limit, or until an absolute instant.

public readonly record struct SecretLifetime : IEquatable<SecretLifetime>
Implements
Inherited Members

Remarks

The two states are modelled rather than encoded. A nullable instant would say "no expiration" and "nobody filled this in" with the same value, and a sentinel timestamp far in the future would be a limit an operator never chose and a date some comparison eventually reaches. NoLimit is therefore its own value, and it is the value a setting that names no lifetime reads as — which is also why it is the struct default. The type's default and the setting's default agree deliberately, so an unassigned field cannot mean something the configuration never could.

A bounded lifetime is an absolute instant, never a duration. A duration would restart at every process start and at every configuration reload, so a credential an operator retired for a week would come back with the next deployment. An instant expires once and stays expired until the configuration that carries it changes.

The declaration is uniform across every secret; enforcement is not, because only a consumer knows what a lapsed credential means for the operation it serves. The MCP API keys enforce it by refusing an expired key, which is what makes overlapping keys a rotation rather than an outage. Elsewhere the lifetime is recorded and reported at startup, and the operations documentation says so rather than implying a control that does not exist.

Fields

NoLimitValue

The configured value that states a secret carries no expiration.

Properties

Expiration

Gets the instant the secret stops being usable, in UTC.

IsBounded

Gets whether the secret expires at an instant rather than lasting indefinitely.

NoLimit

Gets the lifetime of a secret that never expires, which is what an unconfigured lifetime reads as.

Methods

ExpiringAt(DateTimeOffset)

Creates a lifetime that ends at an absolute instant.

HasExpiredAt(DateTimeOffset)

Gets whether the secret has stopped being usable at a given instant.

ToString()

Returns the configured spelling of the lifetime, which carries no secret material.

TryParse(string?, out SecretLifetime)

Reads a configured lifetime.