Files
fkysly 6a7d99ebd1 Fix review findings: token exposure, fail-opens, CAT_IDS duplication
Self-review of the migration commit found six problems; this fixes all of them.

Security — pr-gate.yml checked out refs/pull/N/merge and ran `npm ci` plus the
PR's own scripts with GITHUB_TOKEN in scope, i.e. it executed fork-supplied
code with a token: exactly the pull_request_target footgun the workflow's own
comment said it avoids. It now checks out only the base repo's default branch;
the PR contributes nothing but the content of data/plugins/*.yml, extracted
with `git archive` and read as data.

Fail-opens — three paths reported success when a check couldn't actually run:
- a missing/unparseable gate-result.json was reported as a passing check; it
  now posts a failure explaining the gate itself broke
- an unparseable package.json fell through hasBundle() as if it were fine; it
  is now rejected outright (as uninstallable as a missing manifest)
- a git failure in the changed-files diff read as "no changes" via `|| true`;
  the diff now goes through a file with set -e so the step fails instead

Consistency — CAT_IDS lived in both build-site.mjs and lib/entries.mjs and
reorder-categories.py only rewrote the former, so a reorder would desync the
generator from the site. build-site.mjs now imports the shared array and the
reorder script rewrites lib/entries.mjs then regenerates the READMEs.

Smuggling — generate-readme.mjs --check only compared the marker blocks, so an
entry added outside them (a duplicated category heading after END PLUGINS)
would ship to the site with no YAML backing it. --check now also asserts the
parsed URL set of each README equals data/plugins exactly, both directions.

Also: GATE_EFFECTIVE_FROM is derived from the commit that added pr-gate.yml
instead of a hardcoded date (which would have wrongly gated the ~30 PRs opened
earlier the same day), and the check-run link to contributing.md is absolute.
2026-08-16 16:25:55 +08:00
..