AXIAM PHP SDK

DecisionMemo
in package

FinalYes

Client-side decision memo — CONTRACT.md §17.

Disabled by default. §11.2 rule 6's ban on caching allow/deny decisions is still the default behaviour; this is the single opt-in exception that section carves out, and a caller has to switch it on having read the cost.

What it costs

The staleness bound is the TTL, in both directions. A grant revoked on the server can still read as allowed for up to the TTL, and a grant just added can still read as denied for up to the TTL. That second direction is the one that surprises people: reads-your-own-writes is not guaranteed. An admin UI that grants a role and immediately re-checks is the case that breaks, and it breaks silently.

This mirrors the server's own bound rather than inventing a second staleness story — AXIAM__AUTHZ__DECISION_CACHE_TTL_SECS (default 5s) makes the same trade server-side. One deliberate difference: the server's setting is an unclamped integer, so an operator can configure a multi-hour staleness window. DecisionMemo::MAX_TTL_MS clamps this one at 5s, because the client has no reason to repeat that.

No lock: PHP's shared-nothing request model means one client instance is not shared across concurrent requests the way a Go or Java client is, so the cross-thread hazard the other SDKs guard against does not arise here. This memo lives and dies with the request that built the client.

Table of Contents

Constants

MAX_ENTRIES  : mixed = 1024
Entry cap before FIFO eviction (§17.1 rule 8). The memo is a latency optimisation, so dropping an entry is always correct — but it must drop rather than grow without bound.
MAX_TTL_MS  : mixed = 5000.0
The §17.1 rule 2 ceiling, in milliseconds. A configured TTL above this is clamped, not rejected: a caller who asked for a minute wants caching, and silently giving them the maximum safe value beats failing construction.

Methods

__construct()  : mixed
clear()  : void
Drops every entry (§17.1 rule 9).
count()  : int
Entry count, for tests.
effectiveTtlMs()  : float
The TTL after clamping, in milliseconds.
enabled()  : bool
Whether this memo does anything. `false` for the default configuration.
get()  : AccessDecision|null
A live decision for `$key`, if one is memoized and unexpired.
key()  : string
Builds the §17.1 rule 3 key: all four components, absent distinguished from present.
put()  : void
Memoizes a decision the server actually returned.
reportClamp()  : void
Emits a {@see ConfigClampedEvent} if the requested TTL was clamped (CONTRACT.md §19.2 rule 6).

Constants

MAX_ENTRIES

Entry cap before FIFO eviction (§17.1 rule 8). The memo is a latency optimisation, so dropping an entry is always correct — but it must drop rather than grow without bound.

public mixed MAX_ENTRIES = 1024

MAX_TTL_MS

The §17.1 rule 2 ceiling, in milliseconds. A configured TTL above this is clamped, not rejected: a caller who asked for a minute wants caching, and silently giving them the maximum safe value beats failing construction.

public mixed MAX_TTL_MS = 5000.0

Methods

__construct()

public __construct([float $ttlMs = 0.0 ][, callable(): float|null $clock = null ]) : mixed
Parameters
$ttlMs : float = 0.0

Requested TTL in milliseconds; 0.0 or less disables the memo, and anything above DecisionMemo::MAX_TTL_MS is clamped to it.

$clock : callable(): float|null = null

Injected millisecond clock, so the TTL can be tested without waiting.

clear()

Drops every entry (§17.1 rule 9).

public clear() : void

Called on login, verifyMfa, refresh and logout. Entries are keyed by subject, not by session, so a re-authentication as a different principal would otherwise read the previous principal's decisions.

count()

Entry count, for tests.

public count() : int
Return values
int

effectiveTtlMs()

The TTL after clamping, in milliseconds.

public effectiveTtlMs() : float
Return values
float

enabled()

Whether this memo does anything. `false` for the default configuration.

public enabled() : bool
Return values
bool

key()

Builds the §17.1 rule 3 key: all four components, absent distinguished from present.

public static key(string|null $subjectId, string $resourceId, string $action, string|null $scope) : string
Parameters
$subjectId : string|null
$resourceId : string
$action : string
$scope : string|null
Return values
string

put()

Memoizes a decision the server actually returned.

public put(string $key, AccessDecision $decision) : void

Callers must only reach here on success. §17.1 rule 7 forbids negative-caching a failure: memoizing a transport error as a deny would turn a blip into a TTL-long outage, and memoizing it as an allow is unthinkable.

Parameters
$key : string
$decision : AccessDecision

reportClamp()

Emits a {@see ConfigClampedEvent} if the requested TTL was clamped (CONTRACT.md §19.2 rule 6).

public reportClamp(float $requestedMs, TelemetryDispatcher $telemetry) : void

This is the clamp that matters most to get right: an operator who set a 60-second TTL believes their staleness bound is 60 seconds. It is five, and without this event nothing anywhere says so.

Nothing is emitted when the requested value was already inside the limit, or when the memo is disabled — an event that fires when nothing happened trains its reader to ignore it.

Parameters
$requestedMs : float
$telemetry : TelemetryDispatcher
On this page

Search results