'application/json'], json_encode($body)); $request->headers->set('x-seal-key', base64_encode($key ?? $this->key())); if ($optIn) { $request->headers->set('x-seal', '1'); } return $request; } public function test_always_mode_seals_with_session_key_and_is_reversible(): void { $response = (new SealResponse())->handle( $this->request(), fn () => new JsonResponse(['data' => ['password' => 'Cloud226*()']]), 'always', ); $body = $response->getData(true); $this->assertArrayNotHasKey('data', $body); $this->assertStringNotContainsString('Cloud226', $response->getContent()); $this->assertSame( ['data' => ['password' => 'Cloud226*()']], json_decode(ResponseCipher::open($body['enc'], $this->key()), true), ); $this->assertNull(ResponseCipher::open($body['enc'], str_repeat('x', 32))); } public function test_passthrough_without_key_or_opt_in(): void { $noKey = Request::create('/x'); $noKey->headers->set('x-seal', '1'); $plain = (new SealResponse())->handle($noKey, fn () => new JsonResponse(['a' => 1])); $this->assertSame(['a' => 1], $plain->getData(true)); $noOptIn = (new SealResponse())->handle($this->request(), fn () => new JsonResponse(['a' => 1])); $this->assertSame(['a' => 1], $noOptIn->getData(true)); } public function test_opt_in_seals_errors_and_opens_request_body(): void { $sealed = ['enc' => ResponseCipher::seal(json_encode(['name' => 'An']), $this->key())]; $response = (new SealResponse())->handle( $this->request($sealed, optIn: true), fn (Request $r) => new JsonResponse(['got' => $r->input('name')], 422), ); $this->assertSame(422, $response->getStatusCode()); $this->assertSame( ['got' => 'An'], json_decode(ResponseCipher::open($response->getData(true)['enc'], $this->key()), true), ); } public function test_request_sealed_with_stale_key_gets_428(): void { $sealed = ['enc' => ResponseCipher::seal('{"a":1}', str_repeat('o', 32))]; $response = (new SealResponse())->handle( $this->request($sealed, optIn: true), fn () => new JsonResponse(['ok' => true]), ); $this->assertSame(428, $response->getStatusCode()); } }