1616_TEMPLATES_URL = "/api/v1/control-templates"
1717
1818
19+ def _valid_template_render_payload () -> dict [str , object ]:
20+ return {
21+ "template" : {
22+ "description" : "Regex denial template" ,
23+ "parameters" : {
24+ "pattern" : {
25+ "type" : "regex_re2" ,
26+ "label" : "Pattern" ,
27+ },
28+ },
29+ "definition_template" : {
30+ "description" : "Template-backed control" ,
31+ "execution" : "server" ,
32+ "scope" : {"step_types" : ["llm" ], "stages" : ["pre" ]},
33+ "condition" : {
34+ "selector" : {"path" : "input" },
35+ "evaluator" : {
36+ "name" : "regex" ,
37+ "config" : {"pattern" : {"$param" : "pattern" }},
38+ },
39+ },
40+ "action" : {"decision" : "deny" },
41+ },
42+ },
43+ "template_values" : {"pattern" : "hello" },
44+ }
45+
46+
1947def _create_control (client : TestClient , name : str | None = None ) -> int :
2048 payload = {
2149 "name" : name or f"control-{ uuid .uuid4 ().hex [:12 ]} " ,
@@ -65,6 +93,13 @@ def test_schema_endpoint_reachable_with_non_admin_key(
6593 assert resp .status_code == 200 , resp .text
6694
6795
96+ def test_schema_endpoint_openapi_is_public (client : TestClient ) -> None :
97+ schema = client .app .openapi ()
98+
99+ operation = schema ["paths" ][f"{ _CONTROLS_URL } /schema" ]["get" ]
100+ assert operation .get ("security" ) == []
101+
102+
68103# ---------------------------------------------------------------------------
69104# CONTROLS_READ operations: AUTHENTICATED suffices.
70105# ---------------------------------------------------------------------------
@@ -209,7 +244,7 @@ def test_non_admin_cannot_validate_control_data(
209244 json = {"data" : VALID_CONTROL_PAYLOAD },
210245 )
211246
212- # Then: validation is admin-only
247+ # Then: validation requires CONTROLS_CREATE.
213248 assert resp .status_code == 403 , resp .text
214249
215250
@@ -218,10 +253,10 @@ def test_non_admin_cannot_render_template(non_admin_client: TestClient) -> None:
218253 # When: a non-admin attempts to render a template
219254 resp = non_admin_client .post (
220255 f"{ _TEMPLATES_URL } /render" ,
221- json = { "template" : {}, "template_values" : {}} ,
256+ json = _valid_template_render_payload () ,
222257 )
223258
224- # Then: rendering is admin-only
259+ # Then: rendering requires CONTROLS_CREATE.
225260 assert resp .status_code == 403 , resp .text
226261
227262
@@ -275,7 +310,7 @@ def test_unauthenticated_cannot_render_template(
275310 # When: a client without credentials attempts to render
276311 resp = unauthenticated_client .post (
277312 f"{ _TEMPLATES_URL } /render" ,
278- json = { "template" : {}, "template_values" : {}} ,
313+ json = _valid_template_render_payload () ,
279314 )
280315
281316 # Then: the request is rejected
@@ -311,4 +346,3 @@ def test_no_auth_mode_allows_writes_without_credentials(
311346 # Then: the create succeeds because auth is disabled at the provider
312347 assert resp .status_code == 200 , resp .text
313348 assert "control_id" in resp .json ()
314-
0 commit comments