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