ReactorAnswer
in package
What a reactor handler decided (CONTRACT.md §22.4, §22.10).
One of three answers — allow, deny or mutate — with require_mfa available on
login.post_auth as a flag on the allow answer.
The constructor is private and the only way in is the four named constructors below, which is what makes §22.4's rules structural rather than documented:
- There is no way to spell
allow+patch, because the allow constructors take no patch. A patch attached to anallowis a reply whose author and whose reader disagree about what will happen; the server refuses it rather than resolving it. require_mfais not a separate decision value — it rides onallow, andallow+require_mfa: trueonlogin.post_authresolves to proceed only after step-up.- A mutation is carried unfiltered. This SDK never reduces a handler's patch to the event's allowed subset (§22.4 rule 1, §22.10 rule 3).
Table of Contents
Constants
- ALLOW : mixed = 'allow'
- Wire value: proceed unchanged (§22.4).
- DEFAULT_DENY_REASON : mixed = 'denied by reactor'
- What the server substitutes when a deny carries no reason. Stated here so a caller reading a deny answer back sees the same string the audit record will.
- DENY : mixed = 'deny'
- Wire value: refuse the operation (§22.4).
- MUTATE : mixed = 'mutate'
- Wire value: proceed, applying a field-allow-listed patch (§22.4).
Methods
- allow() : self
- Proceed unchanged.
- allowWithStepUp() : self
- Proceed only after step-up authentication — `allow` + `require_mfa: true`.
- decision() : string
- The wire decision string: `allow`, `deny` or `mutate`.
- deny() : self
- Refuse the operation.
- mutate() : self
- Proceed, applying `$patch` — a flat map of string to string, valid on a mutable event only. There is no nested or typed patch in v1.
- patch() : array<string, string>|null
- The mutation patch, or null on a non-mutate answer.
- reason() : string|null
- The deny reason, or null when absent (in which case it is omitted).
- requireMfa() : bool
- Whether this answer demands step-up authentication.
Constants
ALLOW
Wire value: proceed unchanged (§22.4).
public
mixed
ALLOW
= 'allow'
DEFAULT_DENY_REASON
What the server substitutes when a deny carries no reason. Stated here so a caller reading a deny answer back sees the same string the audit record will.
public
mixed
DEFAULT_DENY_REASON
= 'denied by reactor'
DENY
Wire value: refuse the operation (§22.4).
public
mixed
DENY
= 'deny'
MUTATE
Wire value: proceed, applying a field-allow-listed patch (§22.4).
public
mixed
MUTATE
= 'mutate'
Methods
allow()
Proceed unchanged.
public
static allow() : self
Return values
selfallowWithStepUp()
Proceed only after step-up authentication — `allow` + `require_mfa: true`.
public
static allowWithStepUp() : self
Valid on login.post_auth ONLY. The runtime refuses it on any other event
rather than putting a reply on the wire the server would reject as
require_mfa_not_supported (§22.4 row 7).
On the federated sign-in paths (SAML ACS, OIDC callback) there is no step-up
branch to take, so a require_mfa answer fails the sign-in rather than
being silently dropped. A reactor that needs step-up there should answer
self::deny() and drive enrolment out of band (§22.5).
Return values
selfdecision()
The wire decision string: `allow`, `deny` or `mutate`.
public
decision() : string
Return values
stringdeny()
Refuse the operation.
public
static deny([string $reason = '' ]) : self
The reason is audited; a deny with no reason still denies, and the server
substitutes self::DEFAULT_DENY_REASON. An empty reason is therefore
omitted from the reply rather than sent as "" — the omission is inside the
signed bytes (§22.2), so it is not cosmetic.
A deny short-circuits the chain: no later reactor is consulted (§22.6).
Parameters
- $reason : string = ''
Return values
selfmutate()
Proceed, applying `$patch` — a flat map of string to string, valid on a mutable event only. There is no nested or typed patch in v1.
public
static mutate(array<string, string> $patch) : self
The patch is sent UNFILTERED (§22.4 rule 1, §22.10 rule 3). One forbidden key rejects the whole patch server-side, including the fields that would have been fine, and this SDK does NOT quietly drop the offender to rescue the rest: doing so would leave the reactor author believing a field was set when it was dropped, which is the exact failure the server refuses to produce. Use ReactorEventSpec::patchFieldAllowed() to check a key before you build the patch, not after.
Parameters
- $patch : array<string, string>
Return values
selfpatch()
The mutation patch, or null on a non-mutate answer.
public
patch() : array<string, string>|null
Return values
array<string, string>|nullreason()
The deny reason, or null when absent (in which case it is omitted).
public
reason() : string|null
Return values
string|nullrequireMfa()
Whether this answer demands step-up authentication.
public
requireMfa() : bool