'']); self::assertNotEmpty($errors); self::assertStringContainsString('INTERNAL_JOB_TOKEN', $errors[0]); } public function testMissingKeyIsRejected(): void { $errors = Config::collectErrors([]); self::assertNotEmpty($errors); self::assertStringContainsString('INTERNAL_JOB_TOKEN', $errors[0]); } public function testShortHexIsRejected(): void { $errors = Config::collectErrors(['internal_job_token' => str_repeat('a', 31)]); self::assertNotEmpty($errors); } public function testNonHexIsRejected(): void { // 32+ chars but contains non-hex — caught by the charset rule. $errors = Config::collectErrors([ 'internal_job_token' => 'this-token-is-32-plus-chars-but-not-hex-at-all', ]); self::assertNotEmpty($errors); } public function testWeakLiteralFooIsRejected(): void { // The exact case the SEC_REVIEW called out. $errors = Config::collectErrors(['internal_job_token' => 'foo']); self::assertNotEmpty($errors); } public function testThirtyTwoHexCharsAccepted(): void { $errors = Config::collectErrors([ 'internal_job_token' => str_repeat('a', 32), ]); self::assertSame([], $errors); } public function testSixtyFourHexCharsAcceptedDocumentedForm(): void { // openssl rand -hex 32 → 64 hex chars; the documented form. $errors = Config::collectErrors([ 'internal_job_token' => bin2hex(random_bytes(32)), ]); self::assertSame([], $errors); } public function testUppercaseHexAccepted(): void { $errors = Config::collectErrors([ 'internal_job_token' => str_repeat('A', 32), ]); self::assertSame([], $errors); } public function testValidateOrExitWritesToStderrAndExits(): void { // Run the failing branch in a subprocess so we can observe both // the non-zero exit and the STDERR text without taking down PHPUnit. $script = <<<'PHP' 'too-short']); PHP; $autoload = var_export(__DIR__ . '/../../../vendor/autoload.php', true); $script = sprintf($script, $autoload); $tmp = tempnam(sys_get_temp_dir(), 'cfg'); self::assertIsString($tmp); file_put_contents($tmp, $script); $stderr = ''; $process = proc_open( [PHP_BINARY, $tmp], [1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes, ); self::assertIsResource($process); fclose($pipes[1]); $stderr = (string) stream_get_contents($pipes[2]); fclose($pipes[2]); $exitCode = proc_close($process); @unlink($tmp); self::assertSame(1, $exitCode); self::assertStringContainsString('INTERNAL_JOB_TOKEN', $stderr); } }