railiance-fabric/railiance_fabric/schema_validation.py
codex 564dc59c4f Record repository UI status in the scanner and tolerate older jsonschema.
Adds the repo-ui-metadata extractor (ui_status yes/candidate/not_detected
plus ui_evidence), falls back to the legacy validator when jsonschema does
not accept a referencing registry, and covers unknown edge endpoints in the
graph explorer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 7458@bnt-lap001
Assistant-Session: 62534cdf-8348-48a7-9c0d-46e0f74c8eae
2026-09-22 08:06:04 +02:00

74 lines
2.4 KiB
Python

from __future__ import annotations
import warnings
from pathlib import Path
from typing import Any
import jsonschema
try:
from referencing import Registry, Resource
except ModuleNotFoundError:
Registry = None
Resource = None
from .loader import load_yaml
def schema_registry(schemas_dir: Path) -> Any:
if Registry is None or Resource is None:
return None
resources: list[tuple[str, Any]] = []
for path in sorted(schemas_dir.glob("*.schema.yaml")):
schema = load_yaml(path)
if not isinstance(schema, dict):
continue
resource = Resource.from_contents(schema)
resources.append((path.resolve().as_uri(), resource))
schema_id = schema.get("$id")
if isinstance(schema_id, str):
resources.append((schema_id, resource))
return Registry().with_resources(resources)
def draft202012_validator(schema_path: Path) -> jsonschema.Draft202012Validator:
schema = load_yaml(schema_path)
if not isinstance(schema, dict):
raise ValueError(f"schema must be a mapping: {schema_path}")
registry = schema_registry(schema_path.parent)
if registry is None:
return _legacy_validator(schema_path, schema)
try:
return jsonschema.Draft202012Validator(
schema,
registry=registry,
)
except TypeError as exc:
# jsonschema < 4.17 does not accept referencing.Registry. Keep the
# same schema set usable on older operator workstations.
if "unexpected keyword argument 'registry'" not in str(exc):
raise
return _legacy_validator(schema_path, schema)
def _legacy_validator(
schema_path: Path,
schema: dict[str, Any],
) -> jsonschema.Draft202012Validator:
store: dict[str, Any] = {}
for path in sorted(schema_path.parent.glob("*.schema.yaml")):
loaded_schema = load_yaml(path)
store[path.resolve().as_uri()] = loaded_schema
if isinstance(loaded_schema, dict):
schema_id = loaded_schema.get("$id")
if isinstance(schema_id, str):
store[schema_id] = loaded_schema
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning)
resolver = jsonschema.RefResolver(
base_uri=schema_path.resolve().as_uri(),
referrer=schema,
store=store,
)
return jsonschema.Draft202012Validator(schema, resolver=resolver)