From 3845fa7206e0bddcb5f326b3c91d1e94fe761c5f Mon Sep 17 00:00:00 2001 From: pkupt Date: Thu, 3 Sep 2026 21:11:18 +0800 Subject: [PATCH 1/2] fix: name SHACL limit env vars in error messages The three limit-exceeded messages in validate_shacl now name the env var that controls each limit, and the SHACL validation guide documents all four resource-limit variables with their defaults. --- docs/guides/shacl-validation.md | 16 ++++++++++++++++ semantica/explorer/routes/ontology.py | 9 ++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/docs/guides/shacl-validation.md b/docs/guides/shacl-validation.md index 8ee40f7e..df81df04 100644 --- a/docs/guides/shacl-validation.md +++ b/docs/guides/shacl-validation.md @@ -707,6 +707,22 @@ report_dict = report.to_dict() --- +## Resource limits + +Live SHACL validation in the Explorer enforces four resource limits, all configurable +through environment variables. When a limit trips, the error message names the +variable that controls it. + +| Environment variable | Default | What it bounds | +| --- | --- | --- | +| `SEMANTICA_MAX_SHACL_TURTLE_BYTES` | `262144` (256 KB) | Size of the submitted SHACL Turtle | +| `SEMANTICA_MAX_SHACL_TRIPLES` | `1000` | Triple count of the parsed shapes graph | +| `SEMANTICA_MAX_SHACL_TIMEOUT` | `15.0` | Validation timeout in seconds | +| `SEMANTICA_MAX_SHACL_CONCURRENCY` | `4` | Concurrent validations per process | + +The first three are surfaced in the validation error message when exceeded; the +concurrency limit applies as a semaphore and does not appear in responses. + ## Using SHACL validation as a CI/CD gate Call this function as a pre-publish gate; exit code 1 blocks the pipeline. diff --git a/semantica/explorer/routes/ontology.py b/semantica/explorer/routes/ontology.py index e723d166..7fa547af 100644 --- a/semantica/explorer/routes/ontology.py +++ b/semantica/explorer/routes/ontology.py @@ -2877,7 +2877,8 @@ async def validate_shacl( status="error", message=( f"SHACL Turtle size ({len(_shacl_bytes)} bytes) " - f"exceeds maximum allowed size ({_MAX_SHACL_TURTLE_BYTES} bytes)." + f"exceeds maximum allowed size ({_MAX_SHACL_TURTLE_BYTES} bytes); " + f"set SEMANTICA_MAX_SHACL_TURTLE_BYTES to raise the limit." ), violations=[], ) @@ -2894,7 +2895,8 @@ async def validate_shacl( status="error", message=( f"SHACL graph triple count ({len(g)}) " - f"exceeds maximum allowed limit ({_MAX_SHACL_TRIPLES})." + f"exceeds maximum allowed limit ({_MAX_SHACL_TRIPLES}); " + f"set SEMANTICA_MAX_SHACL_TRIPLES to raise the limit." ), violations=[], ) @@ -2945,7 +2947,8 @@ async def validate_shacl( conforms=False, status="error", message=( - f"SHACL validation timed out after {_MAX_SHACL_TIMEOUT_SECONDS} seconds." + f"SHACL validation timed out after {_MAX_SHACL_TIMEOUT_SECONDS} seconds; " + f"set SEMANTICA_MAX_SHACL_TIMEOUT to raise the timeout." ), violations=[], ) From af56bd865d9c490fbd526fdb6a3572b8d6c09b65 Mon Sep 17 00:00:00 2001 From: pkupt Date: Thu, 3 Sep 2026 21:11:27 +0800 Subject: [PATCH 2/2] test: assert SHACL limit messages name the env var --- tests/explorer/test_ontology_subissue3.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/explorer/test_ontology_subissue3.py b/tests/explorer/test_ontology_subissue3.py index b24d596a..23192b96 100644 --- a/tests/explorer/test_ontology_subissue3.py +++ b/tests/explorer/test_ontology_subissue3.py @@ -735,6 +735,7 @@ onto:PersonShape a sh:NodeShape ; payload = response.json() assert payload["status"] == "error" assert "exceeds maximum allowed size" in payload["message"] + assert "SEMANTICA_MAX_SHACL_TURTLE_BYTES" in payload["message"] def test_validate_shacl_rejects_too_many_triples(client): @@ -757,6 +758,7 @@ onto:PersonShape a sh:NodeShape ; payload = response.json() assert payload["status"] == "error" assert "exceeds maximum allowed limit" in payload["message"] + assert "SEMANTICA_MAX_SHACL_TRIPLES" in payload["message"] def test_validate_shacl_handles_timeout(client): @@ -786,6 +788,7 @@ onto:PersonShape a sh:NodeShape ; payload = response.json() assert payload["status"] == "error" assert "timed out" in payload["message"] + assert "SEMANTICA_MAX_SHACL_TIMEOUT" in payload["message"] def test_validate_shacl_returns_unavailable_for_truncated_graph(client):