From d8e9bdfd428399a287e497505211394c46018e92 Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Thu, 10 Sep 2026 09:57:06 +0800 Subject: [PATCH] fix: publish a fresh catalog surface --- .github/workflows/deploy.yml | 1 + README.md | 3 +- package.json | 1 + public/library-catalog-status.json | 7 ++++ scripts/check-library-catalog.mjs | 60 ++++++++++++++++++++++++++++ src/data/library-catalog-status.json | 7 ++++ src/pages/library.astro | 10 +++-- 7 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 public/library-catalog-status.json create mode 100644 scripts/check-library-catalog.mjs create mode 100644 src/data/library-catalog-status.json diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1a094bb..aded343 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -24,6 +24,7 @@ jobs: cache-dependency-path: package-lock.json - run: npm ci - run: npm run check:content + - run: npm run check:catalog - run: npm run build - run: npm run check:site - uses: actions/upload-pages-artifact@v5 diff --git a/README.md b/README.md index 0b96f68..cbf84d7 100644 --- a/README.md +++ b/README.md @@ -112,12 +112,13 @@ Node.js 22.12+ is required. ```bash npm ci npm run check:content +npm run check:catalog npm run build npm run check:site npm run check:external ``` -`npm run check` runs deterministic content/topology checks, the production build, and built-site metadata/internal-link/asset-budget checks. `check:external` is the separate network-dependent external-link pass. +`npm run check` runs the deterministic content/topology checks, production build, and built-site metadata/internal-link/asset-budget checks. `check:catalog` verifies the public catalog marker against the current catalog source commit and generation date; it requires network access. `check:external` performs the remaining network-dependent external-link pass separately. The GitHub Pages workflow builds only this repository and publishes `dist/`. Pull requests run deterministic checks; deployment occurs only from `main` or an explicit workflow dispatch. Domain Workbenches and other repositories are never bundled into the site artifact. diff --git a/package.json b/package.json index e202960..0b8a30a 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "scripts": { "dev": "astro dev", "build": "astro build", + "check:catalog": "node scripts/check-library-catalog.mjs", "preview": "astro preview", "astro": "astro", "check:content": "node scripts/check-content.mjs", diff --git a/public/library-catalog-status.json b/public/library-catalog-status.json new file mode 100644 index 0000000..90a8215 --- /dev/null +++ b/public/library-catalog-status.json @@ -0,0 +1,7 @@ +{ + "catalog_url": "https://raw.githubusercontent.com/SagaSmithAI/SagaSmith-dnd-content-library/main/content-library/index.json", + "generated_on": "2026-09-09", + "source_commit": "fe7b14643136f42c6a9f61f2618f3c3b2cd9632c", + "surface": "metadata_only", + "published_at": "2026-09-10" +} diff --git a/scripts/check-library-catalog.mjs b/scripts/check-library-catalog.mjs new file mode 100644 index 0000000..836e5aa --- /dev/null +++ b/scripts/check-library-catalog.mjs @@ -0,0 +1,60 @@ +import { readFile } from 'node:fs/promises'; +import { fileURLToPath } from 'node:url'; +import { dirname, resolve } from 'node:path'; + +const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const statusPath = resolve(root, 'src/data/library-catalog-status.json'); +const status = JSON.parse(await readFile(statusPath, 'utf8')); +const publicStatus = JSON.parse( + await readFile(resolve(root, 'public/library-catalog-status.json'), 'utf8'), +); +for (const field of ['catalog_url', 'generated_on', 'source_commit', 'surface', 'published_at']) { + if (status[field] !== publicStatus[field]) { + throw new Error(`catalog marker mismatch between src/data and public: ${field}`); + } +} + +const catalogResponse = await fetch(status.catalog_url, { + headers: { 'user-agent': 'SagaSmithAI-site-catalog-check/1' }, +}); +if (!catalogResponse.ok) { + throw new Error(`catalog index request failed: ${catalogResponse.status}`); +} +const catalog = await catalogResponse.json(); + +const commitsResponse = await fetch( + 'https://api.github.com/repos/SagaSmithAI/SagaSmith-dnd-content-library/commits?path=content-library/index.json&per_page=1', + { + headers: { + accept: 'application/vnd.github+json', + 'user-agent': 'SagaSmithAI-site-catalog-check/1', + }, + }, +); +if (!commitsResponse.ok) { + throw new Error(`catalog source lookup failed: ${commitsResponse.status}`); +} +const commits = await commitsResponse.json(); +const sourceCommit = commits?.[0]?.sha; +if (typeof sourceCommit !== 'string' || sourceCommit.length !== 40) { + throw new Error('catalog source lookup returned no commit'); +} + +if (status.generated_on !== catalog.generated_on) { + throw new Error( + `catalog date mismatch: marker=${status.generated_on}, index=${catalog.generated_on}`, + ); +} +if (status.source_commit !== sourceCommit) { + throw new Error( + `catalog source mismatch: marker=${status.source_commit}, main=${sourceCommit}`, + ); +} + +console.log( + JSON.stringify({ + fresh: true, + generated_on: status.generated_on, + source_commit: sourceCommit, + }), +); diff --git a/src/data/library-catalog-status.json b/src/data/library-catalog-status.json new file mode 100644 index 0000000..90a8215 --- /dev/null +++ b/src/data/library-catalog-status.json @@ -0,0 +1,7 @@ +{ + "catalog_url": "https://raw.githubusercontent.com/SagaSmithAI/SagaSmith-dnd-content-library/main/content-library/index.json", + "generated_on": "2026-09-09", + "source_commit": "fe7b14643136f42c6a9f61f2618f3c3b2cd9632c", + "surface": "metadata_only", + "published_at": "2026-09-10" +} diff --git a/src/pages/library.astro b/src/pages/library.astro index 9fcdea5..86c97a6 100644 --- a/src/pages/library.astro +++ b/src/pages/library.astro @@ -1,5 +1,6 @@ --- import SiteLayout from '../layouts/SiteLayout.astro'; +import catalogStatus from '../data/library-catalog-status.json'; --- 可校验,不等于可随意分发。Verifiable does not mean freely distributable.

当前目录用不可变 identity、版本、大小与 SHA-256 描述 Content Pack。仓库可见性只让索引可以被审计;每个 Pack、来源文档与嵌入资产仍保留各自许可、署名和分发限制。The current catalog describes Content Packs with immutable identities, versions, sizes, and SHA-256 checksums. Repository visibility makes the index auditable; every Pack, source document, and embedded asset retains its own license, attribution, and distribution restrictions.

-