$comparisons Rows from * ABJ_404_Solution_ResponseBodyDeliveryEvidence::comparisonsIn(). Only * `step`, `emitted_bytes` and `delivered_bytes` are read; unknown fields * are tolerated so the persisted diagnostic shape stays additive. * @param int $maxStepChars Bound on each step name copied into the * verdict, so an unrecognised step reported by a hostile client cannot * grow the record. * @return array{bodyRewrittenInTransitCausal: bool, * bodyRewrittenInTransitSteps: string, bodySizeComparisonsMismatched: int, * bodySizeComparisonsMatched: int, bodySizeComparisonsUnknown: int} * Every field is scalar on purpose: the ladder copies only scalars into * the stage trace, and WHICH response was rewritten is the half of this * finding that makes it actionable. */ public static function fromComparisons(array $comparisons, int $maxStepChars = 32): array { $rewritten = array(); $matched = 0; $unknown = 0; foreach ($comparisons as $comparison) { if (!is_array($comparison)) { continue; } $emitted = $comparison['emitted_bytes'] ?? null; $delivered = $comparison['delivered_bytes'] ?? null; if (!is_numeric($emitted) || !is_numeric($delivered)) { $unknown++; continue; } if (abs((int)$delivered - (int)$emitted) > self::TOLERANCE_BYTES) { $step = is_scalar($comparison['step'] ?? null) ? (string)$comparison['step'] : ''; $rewritten[] = substr($step, 0, max(1, $maxStepChars)); continue; } $matched++; } return array( 'bodyRewrittenInTransitCausal' => $rewritten !== array(), 'bodyRewrittenInTransitSteps' => implode(',', $rewritten), 'bodySizeComparisonsMismatched' => count($rewritten), 'bodySizeComparisonsMatched' => $matched, 'bodySizeComparisonsUnknown' => $unknown, ); } }