Skip to content
🚧 Early alpha — building the foundation. See the roadmap →

SKOS→STRM direction convention — broadMatch means the OBJECT is broader

Created Updated

STRM predicates read subject-verb-object. SKOS mapping properties read “subject has-a-X-match” — the property names the object’s role.

SSSOM/SKOS predicateSKOS semanticsSTRM predicate_id
skos:exactMatchperfect synonymis_equivalent_to
skos:closeMatchnear-synonymis_approximate_to
skos:broadMatchobject is broader (subject ⊂ object)is_narrower_than
skos:narrowMatchobject is narrower (subject ⊃ object)is_broader_than
skos:relatedMatchoverlappingintersects_with

And one hop upstream, the OLIR chain: subset of (focal ⊂ reference) → skos:broadMatch → is_narrower_than. The OLIR→SKOS leg was always correct; only the SKOS→STRM leg was inverted.

The original map read skos:broadMatch → is_broader_than with the comment “subject is broader than object” — a misreading of SKOS. Per the SKOS reference, A skos:broadMatch B asserts that A has a broader match B — B is the broader concept. The error shipped identically in both implementations (src/import/sssom-importer.ts and the mirror in tools/crosswalk-from-olir.ts), so tool and plugin agreed with each other while both disagreeing with the standard. Flagged 2026-06-03 while building CRI→800-53 edges; resolved 2026-06-12 as a bug (no evidence anywhere of an intentional non-standard convention).

Why direction matters (and what never broke)

Section titled “Why direction matters (and what never broke)”
  • Coverage counts were always right — the pivot groups by subject_id/object_id, not direction.
  • Committed SSSOM TSVs were never wrong — they store the SKOS predicate (the wire format). This is exactly why crosswalk-edge notes preserve sssom_predicate alongside the normalized predicate_id: the wire truth survives a normalization bug.
  • What was wrong: every directional predicate_id in generated edge notes, and anything downstream that would have trusted them — the v0.1.7 exporters (STRM/OSCAL) would have shipped inverted assertions.
  • nist-csf-2:DE is_narrower_than cri-profile:DE — CRI’s DETECT extends CSF’s (adds “technology and”), so CSF ⊂ CRI ✓
  • nist-800-53:AC-2 is_broader_than cri-profile:GV.RR-02.06 — an 800-53 control ⊃ a single CRI diagnostic statement ✓

Unit test “importSssom — SKOS→STRM direction convention” (tests/sssom-importer.test.ts) pins broadMatch → is_narrower_than and narrowMatch → is_broader_than through the real importer. If it fails, someone re-inverted one of the two copies of the map — they must change together (the tool mirror documents this in place).

All three proving-ground edge sets (2026-06-12): CSF→800-53 (740), CRI→800-53 (1,039), CSF→CRI (154). The CSF→CRI set is the visible proof — its 92 directional edges flipped from is_broader_than to is_narrower_than (CSF concepts are subsets of CRI’s extended versions).