` correlation key — the canonical request_id wire form * per `audit-event.schema.json` `properties.request_id.pattern` (the * non-legacy alternation `^req_[0-9A-HJKMNP-TV-Z]{26}$`). */ public static function generate_request_id(): string { return 'req_' . self::generate(); } private static function encode_timestamp( int $ms ): string { // 10 base32 chars × 5 bits = 50 bits; we use the low 48 bits of $ms // and zero-pad the top 2 bits. Encode MSB-first. $out = ''; for ( $i = 9; $i >= 0; $i-- ) { $out .= self::ALPHABET[ ( $ms >> ( $i * 5 ) ) & 0x1F ]; } return $out; } private static function encode_random( string $bytes ): string { // 10 bytes = 80 bits → 16 base32 chars × 5 bits. Process big-endian. // Promote to a 20-hex string then walk 5 bits at a time using the // bcmath-free trick: split into a 5-byte high half and a 5-byte low // half (both fit in PHP's native 64-bit int on 64-bit hosts). $hi = ( ord( $bytes[0] ) << 32 ) | ( ord( $bytes[1] ) << 24 ) | ( ord( $bytes[2] ) << 16 ) | ( ord( $bytes[3] ) << 8 ) | ord( $bytes[4] ); $lo = ( ord( $bytes[5] ) << 32 ) | ( ord( $bytes[6] ) << 24 ) | ( ord( $bytes[7] ) << 16 ) | ( ord( $bytes[8] ) << 8 ) | ord( $bytes[9] ); $out = ''; for ( $i = 7; $i >= 0; $i-- ) { $out .= self::ALPHABET[ ( $hi >> ( $i * 5 ) ) & 0x1F ]; } for ( $i = 7; $i >= 0; $i-- ) { $out .= self::ALPHABET[ ( $lo >> ( $i * 5 ) ) & 0x1F ]; } return $out; } /** * Big-endian increment of a 10-byte string by 1 (wraps at 2^80 — the wrap * window is astronomically wide; not bothering to detect overflow). */ private static function increment_bytes( string $bytes ): string { $out = $bytes; $carry = 1; for ( $i = 9; $i >= 0 && $carry > 0; $i-- ) { $sum = ord( $out[ $i ] ) + $carry; $out[ $i ] = chr( $sum & 0xFF ); $carry = $sum >> 8; } return $out; } }