PluginProbe
404 Solution / trunk
404 Solution vtrunk
4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.0 4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.1.7 4.1.6 4.1.5 4.1.4 4.1.3 trunk 2.30.0 All 109 releases
404-solution / includes / diagnostics / RequiredCheckpointIdentityEvidence.php

RequiredCheckpointIdentityEvidence.php in 404 Solution trunk, at includes/diagnostics/RequiredCheckpointIdentityEvidence.php

237 lines 9.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 /**
8 * Selects the latest schema-complete checkpoint for each required identity.
9 *
10 * These records carry discriminators that ordinary request-group ranking can
11 * omit even though an older complete sample is more useful than a newer
12 * partial one. This policy is deliberately independent of request lifecycle
13 * and byte-budget decisions: it answers only whether a record proves a
14 * required evidence identity.
15 */
16 final class ABJ_404_Solution_RequiredCheckpointIdentityEvidence {
17
18 /**
19 * Evidence identities mapped to their schema predicate.
20 *
21 * @var array<string, string>
22 */
23 private const SELECTORS = array(
24 'client_receipt' => 'isClientReceipt',
25 'size_receipt' => 'isSizeReceipt',
26 'concurrent_control' => 'isConcurrentControlReceipt',
27 'same_site_census' => 'isSameSiteCensus',
28 'row_loop_activity' => 'isRowLoopActivity',
29 'query_identity' => 'isQueryIdentity',
30 'query_cap' => 'isQueryCap',
31 'row_operation_normal' => 'isRowOperationNormal',
32 'row_operation_cap' => 'isRowOperationCap',
33 'row_operation_unavailable' => 'isRowOperationUnavailable',
34 'render_option_io_cap' => 'isRenderOptionIoCap',
35 'browser_attempt' => 'isBrowserAttempt',
36 'browser_storage_unavailable' => 'isBrowserStorageUnavailable',
37 'browser_table_storage_unavailable' => 'isBrowserTableStorageUnavailable',
38 'boot_generation' => 'isBootGeneration',
39 'detach_counterbalance' => 'isDetachCounterbalance',
40 'recorder_phases' => 'isRecorderPhases',
41 );
42
43 /** @var array<int, string> */
44 private const CANARY_TRANSPORT_FIELDS = array(
45 'payload_variant',
46 'content_encoding',
47 'transfer_bytes',
48 'encoded_body_bytes',
49 'decoded_body_bytes',
50 'resource_timing_state',
51 );
52
53 /** @var array<int, string> */
54 private const ROW_ACTIVITY_FIELDS = array(
55 'hook_active',
56 'hook_calls',
57 'hook_top',
58 'cache_calls',
59 'cache_ms',
60 'cache_src',
61 );
62
63 /** @var array<int, string> */
64 private const RECORDER_PHASE_FIELDS = array(
65 'intent_append',
66 'directory_resolve',
67 'directory_create',
68 'host_pressure_probe',
69 'envelope_build',
70 'append',
71 );
72
73 /**
74 * @param array<int, string> $lines JSONL lines, oldest first.
75 * @return array<int, string>
76 */
77 public static function select(array $lines): array {
78 $selected = array_fill_keys(array_keys(self::SELECTORS), '');
79 foreach (array_reverse($lines) as $line) {
80 $record = json_decode($line, true);
81 if (!is_array($record)) {
82 continue;
83 }
84 foreach (self::SELECTORS as $identity => $predicate) {
85 if ($selected[$identity] === '' && self::{$predicate}($record)) {
86 $selected[$identity] = $line;
87 }
88 }
89 if (!in_array('', $selected, true)) {
90 break;
91 }
92 }
93 return array_values(array_filter(
94 $selected,
95 static fn(string $line): bool => $line !== ''
96 ));
97 }
98
99 /** @param array<mixed, mixed> $record */
100 private static function isClientReceipt(array $record): bool {
101 return self::hasReceiptJoins($record, 'canary_step_client_receipt');
102 }
103
104 /** @param array<mixed, mixed> $record */
105 private static function isSizeReceipt(array $record): bool {
106 return self::hasReceiptJoins($record, 'canary_step_client_receipt')
107 && in_array($record['payload_variant'] ?? '', array('compressible', 'incompressible'), true)
108 && self::hasKeys($record, self::CANARY_TRANSPORT_FIELDS);
109 }
110
111 /** @param array<mixed, mixed> $record */
112 private static function isConcurrentControlReceipt(array $record): bool {
113 return ABJ_404_Solution_ConcurrentControlReceipt::isCompleteJournalRecord($record);
114 }
115
116 /** @param array<mixed, mixed> $record */
117 private static function isSameSiteCensus(array $record): bool {
118 return is_array($record['same_site_census'] ?? null)
119 && array_key_exists('same_site_requests', $record);
120 }
121
122 /** @param array<mixed, mixed> $record */
123 private static function isRowLoopActivity(array $record): bool {
124 return ($record['event'] ?? '') === 'row_loop_progress'
125 && self::hasKeys($record, self::ROW_ACTIVITY_FIELDS);
126 }
127
128 /** @param array<mixed, mixed> $record */
129 private static function isQueryIdentity(array $record): bool {
130 return ($record['event'] ?? '') === 'query_probe'
131 && self::hasKeys($record, array('q', 'src', 'sql_id'));
132 }
133
134 /** @param array<mixed, mixed> $record */
135 private static function isQueryCap(array $record): bool {
136 return ($record['event'] ?? '') === 'query_probe_capped'
137 && self::hasKeys($record, array('q', 'limit'));
138 }
139
140 /** @param array<mixed, mixed> $record */
141 private static function isRowOperationNormal(array $record): bool {
142 return ($record['event'] ?? '') === 'row_operation_end'
143 && self::hasKeys($record, array('operation_id', 'kind'));
144 }
145
146 /** @param array<mixed, mixed> $record */
147 private static function isRowOperationCap(array $record): bool {
148 return ($record['event'] ?? '') === 'row_operation_capped'
149 && self::hasKeys($record, array('recorded', 'max_records'));
150 }
151
152 /** @param array<mixed, mixed> $record */
153 private static function isRowOperationUnavailable(array $record): bool {
154 return ($record['event'] ?? '') === 'row_operation_unavailable'
155 && self::hasKeys($record, array('kind', 'reason'));
156 }
157
158 /** @param array<mixed, mixed> $record */
159 private static function isRenderOptionIoCap(array $record): bool {
160 return ($record['event'] ?? '') === 'render_option_io_capped'
161 && self::hasKeys($record, array('phase', 'recorded', 'max_records'));
162 }
163
164 /** @param array<mixed, mixed> $record */
165 private static function isBrowserAttempt(array $record): bool {
166 $report = is_array($record['report'] ?? null) ? $record['report'] : array();
167 $environment = is_array($report['env'] ?? null) ? $report['env'] : array();
168 return ($record['event'] ?? '') === 'client_prior_attempt'
169 && is_array($report['storage_health'] ?? null)
170 && is_array($environment['drift'] ?? null);
171 }
172
173 /** @param array<mixed, mixed> $record */
174 private static function isBrowserStorageUnavailable(array $record): bool {
175 $report = is_array($record['report'] ?? null) ? $record['report'] : array();
176 $storage = is_array($report['storage_health'] ?? null)
177 ? $report['storage_health'] : array();
178 return self::isBrowserAttempt($record)
179 && ($storage['status'] ?? '') === 'unavailable';
180 }
181
182 /** @param array<mixed, mixed> $record */
183 private static function isBrowserTableStorageUnavailable(array $record): bool {
184 $report = is_array($record['report'] ?? null) ? $record['report'] : array();
185 return self::isBrowserStorageUnavailable($record)
186 && ($report['part'] ?? '') === 'table';
187 }
188
189 /** @param array<mixed, mixed> $record */
190 private static function isBootGeneration(array $record): bool {
191 $opcache = is_array($record['boundary_opcache'] ?? null)
192 ? $record['boundary_opcache'] : array();
193 return in_array($record['event'] ?? '', array(
194 'boot_plugin_entry', 'plugins_loaded', 'init', 'admin_init', 'ajax_dispatch',
195 ), true)
196 && array_key_exists('build_generation_consistent', $record)
197 && array_key_exists('matches_checkpoint_logger', $opcache);
198 }
199
200 /** @param array<mixed, mixed> $record */
201 private static function isDetachCounterbalance(array $record): bool {
202 return ($record['event'] ?? '') === 'detach_ab_mode'
203 && self::hasKeys($record, array('part', 'ordinal', 'pair_ordinal'));
204 }
205
206 /** @param array<mixed, mixed> $record */
207 private static function isRecorderPhases(array $record): bool {
208 $previous = is_array($record['previous_checkpoint_write'] ?? null)
209 ? $record['previous_checkpoint_write'] : array();
210 $phases = is_array($previous['phases_us'] ?? null) ? $previous['phases_us'] : array();
211 return self::hasKeys($phases, self::RECORDER_PHASE_FIELDS);
212 }
213
214 /** @param array<mixed, mixed> $record */
215 private static function hasReceiptJoins(array $record, string $event): bool {
216 return ($record['envelope'] ?? '') === ABJ_404_Solution_CheckpointRecordFactory::ENVELOPE_FULL
217 && ($record['event'] ?? '') === $event
218 && is_string($record['carried_by'] ?? null)
219 && $record['carried_by'] !== ''
220 && is_string($record['step_request_id'] ?? null)
221 && $record['step_request_id'] !== '';
222 }
223
224 /**
225 * @param array<mixed, mixed> $record
226 * @param array<int, string> $fields
227 */
228 private static function hasKeys(array $record, array $fields): bool {
229 foreach ($fields as $field) {
230 if (!array_key_exists($field, $record)) {
231 return false;
232 }
233 }
234 return true;
235 }
236 }
237