{
  "file": "F23-llm-catalog-and-connections.md",
  "bullet": "Create validation (`F23.conn-create-validation`).",
  "ids": [
    "F23.conn-create-validation"
  ],
  "line": 313,
  "script": "control-agent-server api POST /api/llm/provider-connections --json '{\"display_name\": \"qa-f23-bad\"}' --expect 422 \\\n  --check detail.0.type eq missing --check detail.0.loc contains api_key --save F23.conn-create-validation/no-key\ncontrol-agent-server api POST /api/llm/provider-connections --json '{\"api_key\": \"<redacted:api_key>\"}' --expect 422 \\\n  --check detail.0.type eq missing --check detail.0.loc contains display_name\ncontrol-agent-server api POST /api/llm/provider-connections --json '{\"display_name\": \"qa-f23-bad\", \"api_key\": \"\"}' --expect 422 \\\n  --check detail.0.type eq too_short --check detail.0.loc contains api_key\ncontrol-agent-server api POST /api/llm/provider-connections --json '{\"display_name\": \"\", \"api_key\": \"<redacted:api_key>\"}' --expect 422 \\\n  --check detail.0.type eq string_too_short --check detail.0.loc contains display_name\ncontrol-agent-server api POST /api/llm/provider-connections --json '{\"display_name\": \"qa-f23-bad\", \"provider\": \"\", \"api_key\": \"<redacted:api_key>\"}' --expect 422 \\\n  --check detail.0.type eq string_too_short --check detail.0.loc contains provider\ncontrol-agent-server api POST /api/llm/provider-connections --expect 422 --check detail.0.type eq string_too_long \\\n  --json \"{\\\"display_name\\\": \\\"$(printf 'q%.0s' $(seq 129))\\\", \\\"api_key\\\": \\\"<redacted:api_key>\\\"}\"\ncontrol-agent-server api POST /api/llm/provider-connections --expect 422 --check detail.0.type eq extra_forbidden --check detail.0.loc contains extra_headers \\\n  --json '{\"display_name\": \"qa-f23-bad\", \"api_key\": \"<redacted:api_key>\", \"extra_headers\": {\"Authorization\": \"Bearer qa-f23\"}}' --save F23.conn-create-validation/extra\ncontrol-agent-server api POST /api/llm/provider-connections --expect 422 --check detail.0.type eq extra_forbidden --check detail.0.loc contains id \\\n  --json '{\"id\": \"qa-f23-chosen\", \"display_name\": \"qa-f23-bad\", \"api_key\": \"<redacted:api_key>\"}'\ncontrol-agent-server api GET /api/llm/provider-connections --check . len-eq 2 --check . not-contains qa-f23-bad\n",
  "exit_code": 0,
  "elapsed_ms": 4226,
  "failed_line": null,
  "failed_command": null,
  "stdout": "{\n  \"ok\": true,\n  \"status\": 422,\n  \"request\": {\n    \"method\": \"POST\",\n    \"path\": \"/api/llm/provider-connections\",\n    \"query\": [],\n    \"auth\": \"header\",\n    \"body\": {\n      \"display_name\": \"qa-f23-bad\"\n    },\n    \"files\": []\n  },\n  \"response\": {\n    \"status\": 422,\n    \"headers\": {\n      \"content-length\": \"117\",\n      \"content-type\": \"application/json\"\n    },\n    \"body\": {\n      \"detail\": [\n        {\n          \"type\": \"missing\",\n          \"loc\": [\n            \"body\",\n            \"api_key\"\n          ],\n          \"msg\": \"Field required\",\n          \"input\": {\n            \"display_name\": \"qa-f23-bad\"\n          }\n        }\n      ]\n    },\n    \"truncated\": false\n  },\n  \"elapsed_ms\": 97,\n  \"checks\": [\n    {\n      \"check\": \"detail.0.type eq missing\",\n      \"ok\": true,\n      \"actual\": \"missing\"\n    },\n    {\n      \"check\": \"detail.0.loc contains api_key\",\n      \"ok\": true,\n      \"actual\": \"[\\\"body\\\", \\\"api_key\\\"]\"\n    }\n  ],\n  \"saved\": \"/workspace/verification-artifacts/runs/20261013-024155-0956-map-f23/evidence/F23.conn-create-validation/no-key.json\"\n}\n{\n  \"ok\": true,\n  \"status\": 422,\n  \"request\": {\n    \"method\": \"POST\",\n    \"path\": \"/api/llm/provider-connections\",\n    \"query\": [],\n    \"auth\": \"header\",\n    \"body\": {\n      \"api_key\": \"<redacted:api_key>\"\n    },\n    \"files\": []\n  },\n  \"response\": {\n    \"status\": 422,\n    \"headers\": {\n      \"content-length\": \"117\",\n      \"content-type\": \"application/json\"\n    },\n    \"body\": {\n      \"detail\": [\n        {\n          \"type\": \"missing\",\n          \"loc\": [\n            \"body\",\n            \"display_name\"\n          ],\n          \"msg\": \"Field required\",\n          \"input\": {\n            \"api_key\": \"<redacted>\"\n          }\n        }\n      ]\n    },\n    \"truncated\": false\n  },\n  \"elapsed_ms\": 67,\n  \"checks\": [\n    {\n      \"check\": \"detail.0.type eq missing\",\n      \"ok\": true,\n      \"actual\": \"missing\"\n    },\n    {\n      \"check\": \"detail.0.loc contains display_name\",\n      \"ok\": true,\n      \"actual\": \"[\\\"body\\\", \\\"display_name\\\"]\"\n    }\n  ]\n}\n{\n  \"ok\": true,\n  \"status\": 422,\n  \"request\": {\n    \"method\": \"POST\",\n    \"path\": \"/api/llm/provider-connections\",\n    \"query\": [],\n    \"auth\": \"header\",\n    \"body\": {\n      \"display_name\": \"qa-f23-bad\",\n      \"api_key\": \"\"\n    },\n    \"files\": []\n  },\n  \"response\": {\n    \"status\": 422,\n    \"headers\": {\n      \"content-length\": \"197\",\n      \"content-type\": \"application/json\"\n    },\n    \"body\": {\n      \"detail\": [\n        {\n          \"type\": \"too_short\",\n          \"loc\": [\n            \"body\",\n            \"api_key\"\n          ],\n          \"msg\": \"Value should have at least 1 item after validation, not 0\",\n          \"input\": \"\",\n          \"ctx\": {\n            \"field_type\": \"Value\",\n            \"min_length\": 1,\n            \"actual_length\": 0\n          }\n        }\n      ]\n    },\n    \"truncated\": false\n  },\n  \"elapsed_ms\": 89,\n  \"checks\": [\n    {\n      \"check\": \"detail.0.type eq too_short\",\n      \"ok\": true,\n      \"actual\": \"too_short\"\n    },\n    {\n      \"check\": \"detail.0.loc contains api_key\",\n      \"ok\": true,\n      \"actual\": \"[\\\"body\\\", \\\"api_key\\\"]\"\n    }\n  ]\n}\n{\n  \"ok\": true,\n  \"status\": 422,\n  \"request\": {\n    \"method\": \"POST\",\n    \"path\": \"/api/llm/provider-connections\",\n    \"query\": [],\n    \"auth\": \"header\",\n    \"body\": {\n      \"display_name\": \"\",\n      \"api_key\": \"<redacted:api_key>\"\n    },\n    \"files\": []\n  },\n  \"response\": {\n    \"status\": 422,\n    \"headers\": {\n      \"content-length\": \"152\",\n      \"content-type\": \"application/json\"\n    },\n    \"body\": {\n      \"detail\": [\n        {\n          \"type\": \"string_too_short\",\n          \"loc\": [\n            \"body\",\n            \"display_name\"\n          ],\n          \"msg\": \"String should have at least 1 character\",\n          \"input\": \"\",\n          \"ctx\": {\n            \"min_length\": 1\n          }\n        }\n      ]\n    },\n    \"truncated\": false\n  },\n  \"elapsed_ms\": 92,\n  \"checks\": [\n    {\n      \"check\": \"detail.0.type eq string_too_short\",\n      \"ok\": true,\n      \"actual\": \"string_too_short\"\n    },\n    {\n      \"check\": \"detail.0.loc contains display_name\",\n      \"ok\": true,\n      \"actual\": \"[\\\"body\\\", \\\"display_name\\\"]\"\n    }\n  ]\n}\n{\n  \"ok\": true,\n  \"status\": 422,\n  \"request\": {\n    \"method\": \"POST\",\n    \"path\": \"/api/llm/provider-connections\",\n    \"query\": [],\n    \"auth\": \"header\",\n    \"body\": {\n      \"display_name\": \"qa-f23-bad\",\n      \"provider\": \"\",\n      \"api_key\": \"<redacted:api_key>\"\n    },\n    \"files\": []\n  },\n  \"response\": {\n    \"status\": 422,\n    \"headers\": {\n      \"content-length\": \"148\",\n      \"content-type\": \"application/json\"\n    },\n    \"body\": {\n      \"detail\": [\n        {\n          \"type\": \"string_too_short\",\n          \"loc\": [\n            \"body\",\n            \"provider\"\n          ],\n          \"msg\": \"String should have at least 1 character\",\n          \"input\": \"\",\n          \"ctx\": {\n            \"min_length\": 1\n          }\n        }\n      ]\n    },\n    \"truncated\": false\n  },\n  \"elapsed_ms\": 94,\n  \"checks\": [\n    {\n      \"check\": \"detail.0.type eq string_too_short\",\n      \"ok\": true,\n      \"actual\": \"string_too_short\"\n    },\n    {\n      \"check\": \"detail.0.loc contains provider\",\n      \"ok\": true,\n      \"actual\": \"[\\\"body\\\", \\\"provider\\\"]\"\n    }\n  ]\n}\n{\n  \"ok\": true,\n  \"status\": 422,\n  \"request\": {\n    \"method\": \"POST\",\n    \"path\": \"/api/llm/provider-connections\",\n    \"query\": [],\n    \"auth\": \"header\",\n    \"body\": {\n      \"display_name\": \"qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\",\n      \"api_key\": \"<redacted:api_key>\"\n    },\n    \"files\": []\n  },\n  \"response\": {\n    \"status\": 422,\n    \"headers\": {\n      \"content-length\": \"284\",\n      \"content-type\": \"application/json\"\n    },\n    \"body\": {\n      \"detail\": [\n        {\n          \"type\": \"string_too_long\",\n          \"loc\": [\n            \"body\",\n            \"display_name\"\n          ],\n          \"msg\": \"String should have at most 128 characters\",\n          \"input\": \"qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\",\n          \"ctx\": {\n            \"max_length\": 128\n          }\n        }\n      ]\n    },\n    \"truncated\": false\n  },\n  \"elapsed_ms\": 109,\n  \"checks\": [\n    {\n      \"check\": \"detail.0.type eq string_too_long\",\n      \"ok\": true,\n      \"actual\": \"string_too_long\"\n    }\n  ]\n}\n{\n  \"ok\": true,\n  \"status\": 422,\n  \"request\": {\n    \"method\": \"POST\",\n    \"path\": \"/api/llm/provider-connections\",\n    \"query\": [],\n    \"auth\": \"header\",\n    \"body\": {\n      \"display_name\": \"qa-f23-bad\",\n      \"api_key\": \"<redacted:api_key>\",\n      \"extra_headers\": {\n        \"Authorization\": \"Bearer qa-f23\"\n      }\n    },\n    \"files\": []\n  },\n  \"response\": {\n    \"status\": 422,\n    \"headers\": {\n      \"content-length\": \"148\",\n      \"content-type\": \"application/json\"\n    },\n    \"body\": {\n      \"detail\": [\n        {\n          \"type\": \"extra_forbidden\",\n          \"loc\": [\n            \"body\",\n            \"extra_headers\"\n          ],\n          \"msg\": \"Extra inputs are not permitted\",\n          \"input\": {\n            \"Authorization\": \"<redacted>\"\n          }\n        }\n      ]\n    },\n    \"truncated\": false\n  },\n  \"elapsed_ms\": 67,\n  \"checks\": [\n    {\n      \"check\": \"detail.0.type eq extra_forbidden\",\n      \"ok\": true,\n      \"actual\": \"extra_forbidden\"\n    },\n    {\n      \"check\": \"detail.0.loc contains extra_headers\",\n      \"ok\": true,\n      \"actual\": \"[\\\"body\\\", \\\"extra_headers\\\"]\"\n    }\n  ],\n  \"saved\": \"/workspace/verification-artifacts/runs/20261013-024155-0956-map-f23/evidence/F23.conn-create-validation/extra.json\"\n}\n{\n  \"ok\": true,\n  \"status\": 422,\n  \"request\": {\n    \"method\": \"POST\",\n    \"path\": \"/api/llm/provider-connections\",\n    \"query\": [],\n    \"auth\": \"header\",\n    \"body\": {\n      \"id\": \"qa-f23-chosen\",\n      \"display_name\": \"qa-f23-bad\",\n      \"api_key\": \"<redacted:api_key>\"\n    },\n    \"files\": []\n  },\n  \"response\": {\n    \"status\": 422,\n    \"headers\": {\n      \"content-length\": \"122\",\n      \"content-type\": \"application/json\"\n    },\n    \"body\": {\n      \"detail\": [\n        {\n          \"type\": \"extra_forbidden\",\n          \"loc\": [\n            \"body\",\n            \"id\"\n          ],\n          \"msg\": \"Extra inputs are not permitted\",\n          \"input\": \"qa-f23-chosen\"\n        }\n      ]\n    },\n    \"truncated\": false\n  },\n  \"elapsed_ms\": 47,\n  \"checks\": [\n    {\n      \"check\": \"detail.0.type eq extra_forbidden\",\n      \"ok\": true,\n      \"actual\": \"extra_forbidden\"\n    },\n    {\n      \"check\": \"detail.0.loc contains id\",\n      \"ok\": true,\n      \"actual\": \"[\\\"body\\\", \\\"id\\\"]\"\n    }\n  ]\n}\n{\n  \"ok\": true,\n  \"status\": 200,\n  \"request\": {\n    \"method\": \"GET\",\n    \"path\": \"/api/llm/provider-connections\",\n    \"query\": [],\n    \"auth\": \"header\",\n    \"body\": null,\n    \"files\": []\n  },\n  \"response\": {\n    \"status\": 200,\n    \"headers\": {\n      \"content-length\": \"358\",\n      \"content-type\": \"application/json\"\n    },\n    \"body\": [\n      {\n        \"id\": \"60e5410bc7854d5fba0fa8ddea14dd05\",\n        \"display_name\": \"qa-f23-deepseek\",\n        \"provider\": \"deepseek\",\n        \"base_url\": null,\n        \"created_at\": 1791859334,\n        \"updated_at\": 1791859334,\n        \"api_key_set\": true\n      },\n      {\n        \"id\": \"d91bced5bd6c478b9262fa67483b7876\",\n        \"display_name\": \"qa-f23-default\",\n        \"provider\": \"custom\",\n        \"base_url\": null,\n        \"created_at\": 1791859334,\n        \"updated_at\": 1791859334,\n        \"api_key_set\": true\n      }\n    ],\n    \"truncated\": false\n  },\n  \"elapsed_ms\": 49,\n  \"checks\": [\n    {\n      \"check\": \". len-eq 2\",\n      \"ok\": true,\n      \"actual\": \"[{\\\"id\\\": \\\"60e5410bc7854d5fba0fa8ddea14dd05\\\", \\\"display_name\\\": \\\"qa-f23-deepseek\\\", \\\"provider\\\": \\\"deepseek\\\", \\\"base_url\\\": null, \\\"created_at\\\": 1791859334, \\\"updated_at\\\": 1791859334, \\\"api_key_set\\\": true}, {\\\"id\\\"\\u2026\"\n    },\n    {\n      \"check\": \". not-contains qa-f23-bad\",\n      \"ok\": true,\n      \"actual\": \"[{\\\"id\\\": \\\"60e5410bc7854d5fba0fa8ddea14dd05\\\", \\\"display_name\\\": \\\"qa-f23-deepseek\\\", \\\"provider\\\": \\\"deepseek\\\", \\\"base_url\\\": null, \\\"created_at\\\": 1791859334, \\\"updated_at\\\": 1791859334, \\\"api_key_set\\\": true}, {\\\"id\\\"\\u2026\"\n    }\n  ]\n}\n",
  "stderr": ""
}
