Skip to content

feat: validate content collections at build time (#156) - #173

Merged
truthixify merged 7 commits into
wraith-protocol:developfrom
aristotle224:feat/156-validate-content-collections
Oct 2, 2026
Merged

truthixify merged 7 commits into
wraith-protocol:developfrom
aristotle224:feat/156-validate-content-collections

Conversation

@aristotle224

Copy link
Copy Markdown
Contributor

Closes #156

Summary

Adds scripts/validate-content.ts — a zero-dependency TypeScript script
that validates every JSON content collection before tsc runs, failing
the build immediately on bad data.

What's validated

Collection Checks
case-studies.json Required fields, ISO date, status enum,
duplicate id/slug
authors.json Required fields, optIn boolean, optional link URLs
contributors.json Required fields, avatar/profile absolute URLs,
duplicate username
faq.json Required fields, category cross-reference, duplicate id
chains.json Required fields, numeric fields, docs URL, status
enum, duplicate id
wave.json currentWave + pastWaves + grant FAQ, applyUrl, ISO
dates, status enum
ecosystem.json Required fields, link URL, category
cross-reference
roadmap.json Required fields, status enum, duplicate milestone id
blog-posts.json Required fields, publishedAt ISO datetime, url,
duplicate slug
src/i18n/ All locales match en.json leaf-key shape (missing +
extra keys both flagged)

Error output format

src/data/case-studies.json [entries[1] id="bad-entry"]
→ field "integrationDate" must be a valid ISO date string (got "not-a-date")

Wiring

  • Prepended to pnpm build — TypeScript compile never runs on broken
    data
  • New pnpm validate:content standalone script for local checks
  • Explicit CI step in ci.yml between lint:i18n and test:a11y

Testing

  • All 9 collections + i18n pass against current data
  • Full pnpm build passes (verified by pre-commit hook)
  • Smoke-tested error output with injected bad data — duplicate slug,
    invalid date, missing field, and invalid enum all reported correctly

Add scripts/validate-content.ts — a zero-dep TypeScript build step that
validates every JSON content collection before tsc runs.

Collections covered:
- case-studies.json  (required fields, ISO date, status enum, dup id/slug)
- authors.json       (required fields, optIn boolean, optional link URLs)
- contributors.json  (required fields, avatar/profile URLs, dup username)
- faq.json           (required fields, category cross-ref, dup id)
- chains.json        (required fields, numeric fields, docs URL, dup id)
- wave.json          (currentWave + pastWaves + faq, applyUrl, ISO dates)
- ecosystem.json     (required fields, link URL, category cross-ref)
- roadmap.json       (required fields, status enum, dup milestone id)
- blog-posts.json    (required fields, publishedAt ISO, url, dup slug)
- src/i18n/          (all locales match en.json leaf-key shape)

On failure: prints source file + record identifier for every violation,
then exits 1 to abort the build.

Wiring:
- Prepended to the `build` script so TypeScript compile never runs on
  broken data.
- New `validate:content` standalone script for local checks.
- Explicit CI step in ci.yml between lint:i18n and test:a11y.
@drips-wave

drips-wave Bot commented Sep 25, 2026

Copy link
Copy Markdown

@aristotle224 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@vercel

vercel Bot commented Sep 25, 2026

Copy link
Copy Markdown

@aristotle224 is attempting to deploy a commit to the truthixify's projects Team on Vercel.

A member of the Team first needs to authorize it.

@truthixify

Copy link
Copy Markdown
Contributor

The validator only checks a hardcoded file list, so any new JSON collection silently bypasses the gate. Please discover every src/data JSON file and fail when one has no schema. Also validate ISO dates strictly because new Date('1') currently passes.

- Replace hardcoded VALIDATORS array with SCHEMA_MAP + readdirSync so any
  new *.json file in src/data/ that lacks a registered validator fails the
  build immediately instead of silently bypassing the gate.

- Fix isIsoDate to use a strict ISO 8601 regex instead of a bare new Date()
  call. Rejects previously-passing inputs like '1', '2026-1-5', 'August 14'.
  Accepts YYYY-MM-DD and YYYY-MM-DDTHH:mm:ss[.sss](Z|+/-HH:mm).

- Add validators for the 9 previously-uncovered collections:
  trust, showcase, incidents, security, blog-manifest,
  authors-optout, contributors-optout, team, threat-model.

- Fix data bug caught by the new gate: team.json contributors[0].github
  was a bare username ('code3ks') rather than a full URL.

Also format Newsletter.tsx, stellarMetrics.ts, track.ts (pre-existing
Prettier drift, caught by the pre-commit hook).

Closes wraith-protocol#156
…compliant

The generator was writing JSON.stringify(..., null, 2) with no trailing
newline. Prettier requires one, causing format:check to fail on every
build because gen-blog-manifest runs after Prettier in the pre-commit
hook.
@aristotle224

Copy link
Copy Markdown
Contributor Author

The validator only checks a hardcoded file list, so any new JSON collection silently bypasses the gate. Please discover every src/data JSON file and fail when one has no schema. Also validate ISO dates strictly because new Date('1') currently passes.

Done, please review

@truthixify

Copy link
Copy Markdown
Contributor

Dynamic discovery is fixed. The date regex still accepts impossible dates such as 2026-02-31. Please validate that the parsed year, month, and day are real, and add coverage for this case.

Extract isIsoDate into src/utils/date.ts and add a calendar
roll-over check after the regex: construct a local Date from
the parsed year/month/day and verify none of the values changed
due to JS Date normalisation.

Update scripts/validate-content.ts to import from the new
utility. Add 30 tests in src/__tests__/date.test.ts covering
valid dates, impossible calendar dates (Feb 29/30/31, Apr/Jun/
Sep/Nov 31, century non-leap years), and structural rejections.
@aristotle224
aristotle224 force-pushed the feat/156-validate-content-collections branch from 5a2697c to 39f4045 Compare October 1, 2026 00:26
@aristotle224

Copy link
Copy Markdown
Contributor Author

Dynamic discovery is fixed. The date regex still accepts impossible dates such as 2026-02-31. Please validate that the parsed year, month, and day are real, and add coverage for this case.

Done, Please review

@truthixify

Copy link
Copy Markdown
Contributor

The calendar validation is fixed. One blocker remains: pnpm build still starts with tsc -b and never runs validate:content, despite the PR saying validation is prepended to the build. Add it to build or prebuild so local and Vercel builds fail on bad content, not only this CI job.

@aristotle224
aristotle224 force-pushed the feat/156-validate-content-collections branch from eb0e689 to 86e524e Compare October 2, 2026 12:15

@truthixify truthixify 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.

Content validation now covers every collection, rejects invalid dates, and runs in the production build. Looks good.

@truthixify
truthixify merged commit df41637 into wraith-protocol:develop Oct 2, 2026
4 of 5 checks passed
@truthixify

Copy link
Copy Markdown
Contributor

Merged. Content collections are now validated in CI and production builds. Thanks @aristotle224.

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.

[Wave 9] Validate website content data at build time

2 participants