INFO
INFO = 0
Something worth recording that needs nobody to act.
One thing a tripwire noticed, and the only shape a health signal travels in.
A value object rather than a loose array, because every consumer - the ledger, the circuit
breaker, a JSON payload on its way to an operator - reads the same four fields, and an array
lets a misspelled key become a silently absent field. Here a missing or misspelled key is a
TypeError at the call site: the constructor takes four typed arguments, and fromArray() feeds
them positionally, so a bad key arrives as NULL against a string parameter and stops there.
A finding asserts a SYMPTOM. It carries no verdict about a cause and no instruction to repair. What to do about it is RepairLadder's answer, and whether to try again is CircuitBreaker's.
Every field is readonly, so a finding that has been handed to the ledger cannot be edited by whoever reads it back. The properties are declared rather than promoted because scope and context are clamped during construction, and a promoted readonly property cannot be rewritten in the constructor body.
MAX_CONTEXT = 400
Longest context this will carry into the ledger.
An unbounded detail column is how a log table becomes the largest thing in the database. The cap is applied here, at construction, rather than at the storage boundary, so every ledger implementation inherits the bound instead of each one having to remember it.
__construct(string $code, int $severity, string $scope = '', string $context = '') : mixed
Constructs a finding.
| string | $code | Stable dotted identifier, such as "frame.digest_mismatch". |
| int | $severity | One of INFO, WARN, ERROR or CRITICAL. An ordinal outside that set is kept rather than refused, because the ladder reads severity with >= and so treats an unknown high value as critical, which is the safe direction to be wrong in. |
| string | $scope | What it was about; clamped to MAX_SCOPE. |
| string | $context | Human-readable detail; clamped to MAX_CONTEXT. |
fromArray(array $data) : self
Rebuilds a finding from the array jsonSerialize() produced.
All four keys are required. A missing or misspelled key resolves to NULL and then fails against a typed parameter, which is the whole reason this type exists: a health record that silently lost its scope is worse than one that refused to load.
| array | $data | Keys code, severity, scope and context. |
When a key is absent or holds the wrong type.
The finding, with scope and context re-clamped.
clamp(string $value, int $limit) : string
Cuts a string to a byte budget without leaving it unencodable.
A cut on a byte boundary can split a multibyte character, and one invalid sequence makes json_encode() refuse the entire record - so a truncated context would take the whole ledger row down with it. Only a value that was well-formed before the cut is repaired; binary that arrived broken is passed through as-is rather than being eaten a byte at a time.
| string | $value | The string to clamp. |
| int | $limit | Maximum length in bytes. |
At most $limit bytes.