2323from datetime import datetime , timezone
2424from pathlib import Path
2525from urllib .error import URLError
26+ from urllib .parse import urlparse
2627from urllib .request import Request , urlopen
2728
2829import sys
3940if _services_root not in sys .path :
4041 sys .path .insert (0 , _services_root )
4142
42- from common .audit_chain import AuditChain
43+ from common .audit_chain import AuditChain # noqa: E402
4344
4445log = logging .getLogger ("quarantine" )
4546
@@ -176,6 +177,37 @@ def _policy_version_id() -> str:
176177 return str (info )
177178
178179
180+ def _stage_gguf_guard_manifest (pipeline_details : dict | None ) -> None :
181+ """Move a generated GGUF guard manifest into the registry directory."""
182+ if not pipeline_details :
183+ return
184+ manifest_info = pipeline_details .get ("gguf_guard_manifest" , {})
185+ if not isinstance (manifest_info , dict ) or not manifest_info .get ("generated" ):
186+ return
187+ manifest_path = manifest_info .get ("manifest_path" )
188+ if not manifest_path :
189+ return
190+
191+ source = Path (manifest_path )
192+ dest = REGISTRY_DIR / source .name
193+ try :
194+ if source .resolve () != dest .resolve ():
195+ if not source .exists ():
196+ log .warning ("gguf-guard manifest missing before registry promotion: %s" , source )
197+ manifest_info ["generated" ] = False
198+ manifest_info ["manifest_path" ] = ""
199+ return
200+ shutil .move (str (source ), str (dest ))
201+ log .info ("moved gguf-guard manifest to registry dir: %s" , dest .name )
202+ except OSError as e :
203+ log .warning ("could not stage gguf-guard manifest %s: %s" , source , e )
204+ manifest_info ["generated" ] = False
205+ manifest_info ["manifest_path" ] = ""
206+ return
207+
208+ manifest_info ["manifest_path" ] = dest .name
209+
210+
179211def _service_headers () -> dict [str , str ]:
180212 """Return inter-service auth headers when a token is configured."""
181213 try :
@@ -188,6 +220,15 @@ def _service_headers() -> dict[str, str]:
188220 return headers
189221
190222
223+ def _http_urlopen (target , timeout : int = 30 ):
224+ """Open only HTTP(S) URLs for registry service calls."""
225+ raw_url = target .full_url if isinstance (target , Request ) else str (target )
226+ scheme = urlparse (raw_url ).scheme .lower ()
227+ if scheme not in {"http" , "https" }:
228+ raise URLError (f"unsupported URL scheme: { scheme or 'none' } " )
229+ return urlopen (target , timeout = timeout ) # nosec B310
230+
231+
191232def promote_to_registry (filename : str , file_hash : str , size_bytes : int ,
192233 scan_results : dict , model_type : str = "llm" ,
193234 source_url : str = "" ,
@@ -227,8 +268,9 @@ def promote_to_registry(filename: str, file_hash: str, size_bytes: int,
227268 if fp :
228269 payload ["gguf_guard_fingerprint" ] = fp
229270 manifest_info = pipeline_details .get ("gguf_guard_manifest" , {})
230- if manifest_info .get ("generated" ):
231- payload ["gguf_guard_manifest" ] = manifest_info .get ("manifest_path" , "" )
271+ manifest_path = manifest_info .get ("manifest_path" , "" )
272+ if manifest_info .get ("generated" ) and manifest_path :
273+ payload ["gguf_guard_manifest" ] = Path (manifest_path ).name
232274
233275 try :
234276 req = Request (
@@ -237,7 +279,7 @@ def promote_to_registry(filename: str, file_hash: str, size_bytes: int,
237279 headers = _service_headers (),
238280 method = "POST" ,
239281 )
240- with urlopen (req , timeout = 30 ) as resp :
282+ with _http_urlopen (req , timeout = 30 ) as resp :
241283 result = json .loads (resp .read ())
242284 log .info ("registry promotion response: %s" , result )
243285 return resp .status == 201
@@ -304,6 +346,7 @@ def process_artifact(artifact_path: Path) -> bool:
304346
305347 # Collect scan result summary
306348 details = result .get ("details" , {})
349+ _stage_gguf_guard_manifest (details )
307350 scan_summary = _build_scan_summary (details )
308351
309352 # Extract source revision
@@ -410,6 +453,7 @@ def process_directory(artifact_dir: Path) -> bool:
410453 )
411454
412455 details = result .get ("details" , {})
456+ _stage_gguf_guard_manifest (details )
413457 scan_summary = _build_scan_summary (details )
414458 scan_summary ["model_type" ] = "diffusion"
415459
0 commit comments