Skip to content

fix: lexicon framework terms - #540

Merged
eddie-knight merged 3 commits into
ossf:mainfrom
eddie-knight:fix/lexicon-framework-terms
Aug 27, 2026
Merged

fix: lexicon framework terms#540
eddie-knight merged 3 commits into
ossf:mainfrom
eddie-knight:fix/lexicon-framework-terms

Conversation

@eddie-knight

@eddie-knight eddie-knight commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

This removes duplicate metadata/lexicon entries and removes references that are not in use.

Also adjusts the template to accommodate:

  • :120 switches the link source from lexicon lookup to a direct anchor — this is what replaces the deleted entries.
  • :136 creates the anchor that line points at. Nothing could link into the External Frameworks table before; every row was unaddressable. Without this line, :120 produces dead links instead of working ones.

Edit: Claude recommended some CI changes to avoid drift in the future. See below for that info.

🤖

This removes duplicate metadata/lexicon entries and references that are not in use, and hardens the checks that keep them from coming back.

What the template change actually fixes

Framework relations rendered through addLinks, which produced reference-style links into the lexicon glossary rather than the External Frameworks table. Only 9 of the 14 frameworks linked at all, and two of those linked wrongly:

  • **BSI-TR-03185-2**, **PSSCRM**, **Scorecard**, **UKSSCOP** rendered as bare bold text, having no lexicon entry.
  • **ISO-[18974][OpenChain]** was mangled. The OpenChain entry carried the synonym 18974, and addLinks substring-matched it inside the identifier ISO-18974, splitting the ID and emitting a link in the middle of it.
  • **[SAMM][Proactive Software Supply Chain Risk Management Framework]** pointed at the wrong framework. That title was the duplicated lexicon term, so SAMM's link resolved to P-SSCRM's glossary anchor — and the duplicate caused the same link definition to be emitted twice in one document.

So the duplicate lexicon entry was not cosmetic: it produced a wrong link destination in published output.

The template changes:

  • :120 switches the link source from lexicon lookup to a direct anchor — this is what replaces the deleted entries.
  • :136 creates the anchor that line points at. Nothing could link into the External Frameworks table before; every row was unaddressable. Without this line, :120 produces dead links instead of working ones.

All 14 frameworks now render uniformly as [ID](#fw-ID) into the table, with no reference-style or mangled links remaining.

Validation

Routing framework names through the lexicon was the wrong mechanism — a short synonym could corrupt a longer identifier. Direct anchors remove that class of bug, and the new checks keep the data behind them honest:

  • A mapping document must target a mapping-reference declared in the catalog metadata. The empty string is not exempt: it is the one value that fails invisibly, since both validate and cue vet pass while the renderer drops the document from the relations and the crosswalk in silence.
  • The reverse: a mapping-reference declared in metadata with no mapping document behind it renders a row nothing can link to.
  • Lexicon names are compared case-folded and across synonyms, since addLinks resolves a name to the first entry declaring it and asLink folds terms into anchors. This required dropping two more synonyms: Vulnerability Reporting claimed Coordinated Vulnerability Disclosure, which is its own entry with a different definition, and the SLSA entry repeated its own term.
  • The reference ID shape is constrained in CUE, on both the catalog metadata and each mapping document's target reference, so an ID containing a space cannot render a broken anchor.

Both new checks are covered by tests. Rendered output is byte-identical to before the validation changes, and anchors remain 14/14.

…ries

Each framework was defined twice: once in metadata.yaml as a
mapping-reference (id, title, version, url, description) and again in
lexicon.yaml as a term. The compiled document rendered both, with two
independently maintained descriptions, and the two files were joined only
by string coincidence -- template.md piped each control's framework ID
through addLinks, which matched it against lexicon terms and synonyms and
silently emitted bare text when nothing matched.

Four of the fourteen mapped frameworks were already unlinked that way
(Scorecard, ISO-18974, UKSSCOP, BSI-TR-03185-2), and lexicon.yaml carried
two entries both titled "Proactive Software Supply Chain Risk Management
Framework", the second holding OWASP SAMM's definition.

Link framework relations directly to the External Frameworks table row
instead, giving each row a stable anchor, and delete the eleven duplicated
lexicon entries. All fourteen mapped frameworks now resolve. The entry for
Supply-chain Levels for Software Artifacts stays: its SLSA synonym is a
live auto-link target in OSPS-BR criteria text.

Add two validator checks so this cannot drift again silently: a mapping
document's target reference must be declared in the catalog metadata, and
lexicon terms must be unique.

Signed-off-by: Eddie Knight <knight@linux.com>
DORA, NIS2, CSbDP, CSAG, USCTM and MAF were declared as
mapping-references but no mapping document has ever targeted them. They
came over in the Gemara v1 migration (ossf#494) from the pre-migration
frameworks.yaml, where they were declaration-only as well.

The compiled catalog is published to grc.store on release, so each one
would ship as a framework reference a consumer could resolve but never
match against, and each rendered a row in the External Frameworks table
that no control could link to.

The source material is not lost. The crosswalk workbook in docs/ keeps a
sheet per framework, and four of them are substantially filled in --
though none reference a single OSPS control ID, so the crosswalk itself
was never started. Re-add each reference alongside its mapping document.

Every remaining reference now has exactly one mapping document, and every
row in the External Frameworks table is the target of at least one
control relation.

Signed-off-by: Eddie Knight <knight@linux.com>
@eddie-knight eddie-knight changed the title Fix/lexicon framework terms fix: lexicon framework terms Aug 26, 2026
funnelfiasco
funnelfiasco previously approved these changes Aug 27, 2026
The mapping-reference check exempted the empty string, which is the one
value that fails invisibly: both `validate` and `cue vet` pass while the
renderer drops the document from the relations and the crosswalk without
a word. Blanking one reference-id removed all 9 SLSA relations from the
compiled document and left its table row orphaned, with no error.

- Drop the `fw != ""` guard so an empty ID is an error like any other
  undeclared one.
- Add the reverse check: a mapping-reference declared in metadata with no
  mapping document behind it renders a row nothing can link to. This is
  the state the previous commit cleaned out by hand.
- Compare lexicon names case-folded and across synonyms. addLinks
  resolves a name to the first entry declaring it and asLink folds terms
  into anchors, so names differing only by case share one destination.
  Ownership is tracked per entry, so two entries sharing a term still
  collide while a synonym repeating its own term stays allowed.
- Constrain the reference ID shape in CUE, on both the catalog metadata
  and each mapping document's target reference, so an ID with a space
  cannot render a broken anchor.
- Drop the two lexicon synonyms the stricter check rejects: Vulnerability
  Reporting claimed Coordinated Vulnerability Disclosure, which is its
  own entry with a different definition, and the SLSA entry repeated its
  own term.
- Cover both new checks with tests, and drop two spellcheck words left
  over from the removed references.

Rendered output is byte-identical, and anchors remain 14/14.

@SecurityCRob SecurityCRob left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@eddie-knight
eddie-knight merged commit b15c631 into ossf:main Aug 27, 2026
7 checks passed

@evankanderson evankanderson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this changes the format of anchor references, but that should only take effect for new baseline versions because of the way we check in the compiler outputs for existing versions.

eddie-knight added a commit that referenced this pull request Aug 28, 2026
* feat: auto-generate mapping document links and crosswalk on the website

Each compiled version page's External Frameworks table now links the
framework's Gemara mapping document on grc.store, and the reverse
crosswalk generator (previously unused by the site) renders one section
per framework and is wired into the Pages build as devel-crosswalk.md.
A new --artifact-version compile flag pins the grc.store links to a
published release tag; unset, they point at the latest version.

Signed-off-by: Eddie Knight <knight@linux.com>

* Add 2026-08-26 release candidate

Compiled RC page set (controls, checklist, and the new external
framework crosswalk), linked from the versions list. Release notes for
2026-08-26 are drafted but stay commented out until the release, which
will also promote the page to Current Version per the usual process.

Signed-off-by: Eddie Knight <knight@linux.com>

* Add make dev for local site preview

Compiles the devel pages the same way web-publish.yml does (including
the new crosswalk) and serves the site with Jekyll at 127.0.0.1:4000.
devel-crosswalk.md joins the other generated devel pages in .gitignore.

Signed-off-by: Eddie Knight <knight@linux.com>

* fix: guard artifactURL against empty ids; regenerate RC pages post-rebase

An empty artifact id now yields an empty URL from artifactURL rather
than a link to the bare grc.store namespace, with a test covering the
pinned, unpinned, and empty cases.

The 2026-08-26 RC page is regenerated against main after #540, which
removed the unmapped framework metadata rows and the framework lexicon
entries (including the duplicate PSSCRM term) and linked each
per-control framework relation to its row in the External Frameworks
table — where the new Mapping Document column links to grc.store.

Signed-off-by: Eddie Knight <knight@linux.com>

* fix: drop SLSA lexicon entry and dead CI/CD anchors

SLSA was the one framework #540 left in the lexicon, so it still
rendered as a glossary entry alongside its External Frameworks row. The
validator now rejects any lexicon term or synonym that shadows a
mapping-reference id, so a framework can't reappear in the glossary.

asLink mapped every non-letter to '-', but kramdown deletes '/' when
deriving a heading id, so each [CI/CD Pipeline] link pointed at the
dead anchor #ci-cd-pipeline instead of #cicd-pipeline. Drop '/' the
way '.' already is, with a test pinning the anchor scheme.

RC page regenerated; historical release pages are left as released.

Signed-off-by: Eddie Knight <knight@linux.com>

* Release version 2026.08.28 of the Baseline

Converts the release-candidate pages to the final release: pages
recompiled with grc.store mapping links pinned to v2026.08.28, nav and
index updated to make v2026.08.28 the current version, and the drafted
release notes published.

* docs: document the release steps in CONTRIBUTING.md

* docs: drop release steps from CONTRIBUTING.md in favor of the release issue template

* docs: sync release issue template with current release process

---------

Signed-off-by: Eddie Knight <knight@linux.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants