42 lines
1.5 KiB
Python
42 lines
1.5 KiB
Python
# #region SourceIsolation [C:5] [TYPE Module] [SEMANTICS clean-release, source, isolation, validate, resource]
|
|
# @BRIEF Validate that all resource endpoints belong to the approved internal source registry.
|
|
# @LAYER: Domain
|
|
# @RELATION DEPENDS_ON -> [CleanReleaseModels]
|
|
# @INVARIANT: Any endpoint outside enabled registry entries is treated as external-source violation.
|
|
# @PRE: Source registry configured
|
|
# @POST: Source isolation violations identified
|
|
# @SIDE_EFFECT: None (read-only check)
|
|
# @DATA_CONTRACT: SourceURL -> ViolationReport
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Iterable
|
|
|
|
from ...models.clean_release import ResourceSourceRegistry
|
|
|
|
|
|
def validate_internal_sources(
|
|
registry: ResourceSourceRegistry, endpoints: Iterable[str]
|
|
) -> dict:
|
|
allowed_hosts = {
|
|
entry.host.strip().lower() for entry in registry.entries if entry.enabled
|
|
}
|
|
violations: list[dict] = []
|
|
|
|
for endpoint in endpoints:
|
|
normalized = (endpoint or "").strip().lower()
|
|
if not normalized or normalized not in allowed_hosts:
|
|
violations.append(
|
|
{
|
|
"category": "external-source",
|
|
"location": endpoint or "<empty-endpoint>",
|
|
"remediation": "Replace with approved internal server",
|
|
"blocked_release": True,
|
|
}
|
|
)
|
|
|
|
return {"ok": len(violations) == 0, "violations": violations}
|
|
|
|
|
|
# #endregion SourceIsolation
|