---
title: "ADR-044: Signed OAuth expiry buffers avoid wrapping"
manual: "Secrets Vault"
version: "main"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-vault:adr-044-signed-oauth-expiry-buffers@main"
source: "Developer/Adr/ADR-044-SignedOAuthExpiryBuffers.rst"
rendered: "2026-10-31T22:32:37+00:00"
---

# ADR-044: Signed OAuth expiry buffers avoid wrapping {#adr-044-signed-oauth-expiry-buffers}

## Status {#status}

Accepted

## Date {#date}

2026-10-10

## Context {#context}

`OAuthToken::isExpired()` accepts a signed integer buffer. A positive buffer
considers the token expired early; a negative one extends its lifetime. The
existing DateTime relative-string calculation can wrap for `PHP_INT_MAX` and
classify a token as valid again. `PHP_INT_MIN` also produces an unparseable
relative string. The existing Fuzz test caught PHPUnit assertion failures as
`Throwable` and accepted them, hiding the positive-limit wrong answer.

## Decision {#decision}

Keep the public constructor and method signatures. Sample the real current time
once in `isExpired()` and delegate comparison to a private predicate. It admits
fixed DateTime inputs in precision tests without adding a public clock API.
With buffer zero retain the existing DateTime object comparison, including its
microsecond precision.

For a nonzero buffer whose native Unix timestamps convert to PHP integers,
compare the current instant to the mathematical expiry timestamp minus the
signed buffer. Check the subtraction bounds first: an adjusted expiry below
`PHP_INT_MIN` is already expired; one above `PHP_INT_MAX` is still future.
If the whole seconds are equal, compare the original microsecond fields too.
Do not turn integer overflow into floating point arithmetic or feed an extreme
signed quantity into DateTime's relative-string parser.

Where native timestamp conversion raises its range exception, retain the
previous DateTime modification and object comparison. This preserves existing
valid behavior on a PHP build with narrower integers and adds no public failure
boundary or requirement for 64-bit PHP. It does not enlarge DateTime's own
calendar or timestamp range.

Regression oracles capture execution exceptions and assert their exact result
outside catches. The existing extreme-buffer Fuzz assertion must not be caught
as an acceptable execution failure.

## Consequences {#consequences}

Positive and negative buffer meanings remain available without a new clock API
or interface method. Whole-second arithmetic uses elapsed Unix seconds, with the
fractional part preserved. Token-cache and OAuth grant selection are unchanged.

Native 64-bit tests cover ordinary signed buffers, both integer-limit buffers,
and representable timestamp extremes. Fixed DateTime cases cover before, equal
and after fractional expiry for zero, positive and negative buffers. The public
wrapper retains real-clock expiry tests. Deliberate faults must fail behavioral
assertions rather than merely cause framework errors. Controlled DateTime
subclasses exercise both native range-exception types and the unchanged object
comparison; they also prove buffer zero avoids conversion. A real
conversion-range event does not occur on that native matrix. A narrower-integer
runtime remains a separate compatibility check, not a claimed successful test
here.

## References {#references}

-   [PHP timestamp conversion](https://www.php.net/manual/en/datetime.gettimestamp.php)
-   [PHP microsecond formatting](https://www.php.net/manual/en/datetime.format.php)
-   [ADR-008: HTTP client](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-008-http-client@main)
