From 2ef0f78541b65437818d3f1502457d3355557346 Mon Sep 17 00:00:00 2001 From: Jeppe B <2jepp9350@gmail.com> Date: Mon, 10 Aug 2026 08:45:10 +0200 Subject: [PATCH] test(api): lock MiniMax config redaction + isSet contract (#358) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regression coverage for the read-side shape that the frontend `ConfigurationXLVask.refreshMiniMaxApiKeyStatus` parses. Mirrors `BirdConfigSecretRedactionTest` — locks the contract that `api_key` is redacted with `isSet` reflecting actual persistence, so the XL Vask autopilot's `requireModuleEnabled` cannot silently break on a regression. No production-code change — backend already correct (verified live 2026-08-10 07:58 against `api-v2.truckwash.io` with both `{variable, value}` and raw-key payload shapes). Companion pleno-vue PR: #281 ("fix(pleno-vue): persist MiniMax API key across refresh + render fix"). --- .../MiniMaxConfigSecretRedactionTest.php | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 services/nginx/app/tests/Unit/MiniMax/MiniMaxConfigSecretRedactionTest.php diff --git a/services/nginx/app/tests/Unit/MiniMax/MiniMaxConfigSecretRedactionTest.php b/services/nginx/app/tests/Unit/MiniMax/MiniMaxConfigSecretRedactionTest.php new file mode 100644 index 00000000..8c78a6d1 --- /dev/null +++ b/services/nginx/app/tests/Unit/MiniMax/MiniMaxConfigSecretRedactionTest.php @@ -0,0 +1,131 @@ +config_classes = [ + MiniMaxSecretConfigDefinitionStub::class, + MiniMaxBoolConfigDefinitionStub::class, + ]; + } + + public function extract(object $db): array + { + return $this->extracted($db, 'SELECT test'); + } + } +} + +it('redacts configured MiniMax secrets while preserving isSet metadata', function (): void { + $rows = [ + ['module' => 'miniMax', 'variable' => 'api_key', 'type' => 'string', 'value' => 'never-return-this'], + ['module' => 'miniMax', 'variable' => 'enabled', 'type' => 'bool', 'value' => 'true'], + ]; + $result = new class($rows) { + public function __construct(private array $rows) + { + } + + public function fetch_assoc(): ?array + { + return array_shift($this->rows); + } + }; + $db = new class($result) { + public function __construct(private object $result) + { + } + + public function query(string $sql): object + { + return $this->result; + } + }; + + $config = (new MiniMaxModuleConfigRedactionHarness())->extract($db); + + expect($config[0])->toMatchArray([ + 'module' => 'miniMax', + 'variable' => 'api_key', + 'type' => 'string', + 'value' => '[redacted]', + 'isSecret' => true, + 'isSet' => true, + ])->and($config[1])->toMatchArray([ + 'module' => 'miniMax', + 'variable' => 'enabled', + 'type' => 'bool', + 'value' => true, + 'isSecret' => false, + 'isSet' => true, + ]); +}); + +it('reports isSet=false when the stored MiniMax api_key is empty', function (): void { + $rows = [ + ['module' => 'miniMax', 'variable' => 'api_key', 'type' => 'string', 'value' => ''], + ]; + $result = new class($rows) { + public function __construct(private array $rows) + { + } + + public function fetch_assoc(): ?array + { + return array_shift($this->rows); + } + }; + $db = new class($result) { + public function __construct(private object $result) + { + } + + public function query(string $sql): object + { + return $this->result; + } + }; + + $config = (new MiniMaxModuleConfigRedactionHarness())->extract($db); + + expect($config[0])->toMatchArray([ + 'module' => 'miniMax', + 'variable' => 'api_key', + 'type' => 'string', + 'value' => '', + 'isSecret' => true, + 'isSet' => false, + ]); +});