Skip to content

fix(validate-members): hold sources.landscape.collectedAt to the snapshot - #1312

Merged
mrbobbytables merged 1 commit into
mainfrom
fix/validate-members-collected-at
Oct 11, 2026
Merged

mrbobbytables merged 1 commit into
mainfrom
fix/validate-members-collected-at

Conversation

@mrbobbytables

Copy link
Copy Markdown
Member

Finding (#1270)

scripts/validate-members.mjs cross-checks members.json's sources.landscape block against the committed enduser-landscape.json snapshot on revision and sourceUrl only. collectedAt, written by the generator from the same snapshot in the same statement, was held to nothing, and it is the one field of the three the site renders (DirectoryFreshness formats it into the "last synced" note). A stale or unparseable collectedAt passed validate:members while the page printed a date the data did not support, or silently dropped the sentence.

What changes

  • scripts/validate-members.mjs: the existing provenance comparison gains data.sources?.landscape?.collectedAt !== landscape.collectedAt. It compares against the snapshot root, not snapshot.source, which is where generate-members.mjs copies it from. Same error path and message as before (members.json.sources.landscape: landscape provenance must match enduser-landscape.json).
  • tests/validate-members-membership.test.mjs: the fixture's sources.landscape now carries collectedAt like real generator output, run() takes a provenance override, and a new test pins that a different valid timestamp, an unparseable one, null and absent all fail while the matching value passes.
  • tests/e2e-data-fixture-validity.test.mjs: the data-variant/members.json row (which sets collectedAt to "not a timestamp" on purpose) now records the error it gains, replacing the comment that said closing this gap should produce exactly that.

Verification

  • node --test on the three touched suites: 54 pass. With the validator change reverted, 2 fail (the new case and the fixture-validity row), so the tests pin the rule rather than restate it.
  • npm run validate:members on the committed data: Validated 101 members (the committed collectedAt already matches the snapshot).
  • npm run test:unit:coverage:check: green, src 100/100 (the new || arm is covered).
  • check:format: clean.

Closes #1270

…shot

validate-members.mjs cross-checked the landscape provenance block in
members.json against enduser-landscape.json on revision and sourceUrl only.
collectedAt, the third field the generator writes from the same snapshot in
the same statement, was held to nothing, and it is the one of the three the
site renders: DirectoryFreshness formats it into the "last synced" note. A
members.json whose collectedAt was stale or unparseable relative to the
snapshot passed validation while the page printed a date the data did not
support, or silently dropped the sentence.

Fold collectedAt into the existing comparison. It sits on the snapshot root,
not on snapshot.source, which is where generate-members.mjs copies it from.

tests/validate-members-membership.test.mjs gains the case (a different valid
timestamp, an unparseable one, null and absent all fail; the matching value
passes) and its fixture now carries collectedAt like the generator's output.
tests/e2e-data-fixture-validity.test.mjs records that the data-variant
members.json overlay, which sets collectedAt to "not a timestamp" on purpose,
now gains exactly this error, replacing the row's note that it should.

Closes #1270

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Bob Killen <bkillen@linuxfoundation.org>
@mrbobbytables
mrbobbytables added this pull request to the merge queue Oct 11, 2026
Merged via the queue into main with commit 355cc9b Oct 11, 2026
7 checks passed
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.

[quality] validate-members.mjs checks landscape revision and sourceUrl against the snapshot but not collectedAt, the one field the page renders

1 participant