You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sourcelume.apache.org by an...@apache.org on 2026/10/11 16:38:28 UTC
(sourcelume-spec) 02/02: Require @context and assert the record type survives expansion
This is an automated email from the ASF dual-hosted git repository.
ANierbeck pushed a commit to branch spec-followup
in repository https://gitbox.apache.org/repos/asf/sourcelume-spec.git
commit 0855fe702cf3d3fe943617274b1b1bcfcca92bcb
Author: anierbeck <ac...@codecentric.de>
AuthorDate: Sun Oct 11 18:38:17 2026 +0200
Require @context and assert the record type survives expansion
Review findings on the canonical context change:
- @context is now a required property. The const only applies when the
key is present, and tools/validate.py injects the local context, so a
record without @context used to pass the command line check although
other JSON-LD processors cannot expand it.
- The valid-record test asserts that the expanded graph contains
rdf:type sl:ProvenanceRecord. Without a focus node the SHACL shapes
pass vacuously; the assertion fails if the namespace and the shapes
drift apart.
- The context section no longer claims the file is already served at the
canonical address; the release process publishes it.
Apache-ai: Yes
Generated-by: pi (claude-sonnet-5-5)
Reviewed-by: anierbeck
---
schema/0.0.1/sourcelume.schema.json | 1 +
spec/0.0.1/index.md | 2 +-
tests/test_validate.py | 17 +++++++++++++++++
3 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/schema/0.0.1/sourcelume.schema.json b/schema/0.0.1/sourcelume.schema.json
index 2436313..14031ac 100644
--- a/schema/0.0.1/sourcelume.schema.json
+++ b/schema/0.0.1/sourcelume.schema.json
@@ -7,6 +7,7 @@
"required": [
"id",
"type",
+ "@context",
"identifier",
"name",
"license",
diff --git a/spec/0.0.1/index.md b/spec/0.0.1/index.md
index 19a2a06..c4ecbc2 100644
--- a/spec/0.0.1/index.md
+++ b/spec/0.0.1/index.md
@@ -37,7 +37,7 @@ claim's accuracy — it gives the claim a consistent shape so it *can* be verifi
Records reference the context with the canonical IRI
`https://sourcelume.apache.org/context/0.0.1/sourcelume.jsonld` and no other `@context` value.
-The context is published at that address and is not modified after release. Its namespace is the
+The context is published at that address by the release process and is not modified after release. Its namespace is the
stable `https://sourcelume.apache.org/ns#`, so term IRIs stay the same across versions. Inline
`@context` objects and other context IRIs are rejected.
diff --git a/tests/test_validate.py b/tests/test_validate.py
index f6d1efc..9279943 100644
--- a/tests/test_validate.py
+++ b/tests/test_validate.py
@@ -23,6 +23,8 @@ import tempfile
import unittest
from pathlib import Path
+from rdflib import RDF, Graph, URIRef
+
# Add tools directory to path so we can import validate
REPO_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO_ROOT / "tools"))
@@ -74,10 +76,25 @@ class ValidateToolTests(unittest.TestCase):
validator = validate.load_validator()
shapes_path = validate.SCHEMA_DIR / "sourcelume.shacl.ttl"
+ # The expanded graph must carry the ProvenanceRecord type, otherwise the
+ # SHACL shapes have no focus node and the run below would pass vacuously.
+ context = json.loads((REPO_ROOT / "context" / "0.0.1" / "sourcelume.jsonld").read_text())["@context"]
+ graph = Graph()
+ graph.parse(data=json.dumps({**valid_record, "@context": context}), format="json-ld")
+ expected = URIRef("https://sourcelume.apache.org/ns#ProvenanceRecord")
+ self.assertIn((URIRef(valid_record["id"]), RDF.type, expected), graph)
+
# This should return True for a valid record
result = validate.validate_example(example_path, validator, shapes_path)
self.assertTrue(result)
+ def test_missing_context_is_required(self) -> None:
+ """A record without @context fails: other processors cannot expand it."""
+ record = self._record_with_content_period("2024-01-01T00:00:00Z", None)
+ del record["@context"]
+ errors = list(validate.load_validator().iter_errors(record))
+ self.assertEqual([e.message for e in errors], ["'@context' is a required property"])
+
def test_schema_pins_the_canonical_context_iri(self) -> None:
"""The schema's @context const and the validator's constant must agree."""
schema = validate.load_validator().schema
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@sourcelume.apache.org
For additional commands, e-mail: commits-help@sourcelume.apache.org