Repository navigation
Conversation
Both CI jobs currently fail two seconds after starting, before any build
step runs:
##[error]This request has been automatically failed because it uses a
deprecated version of `actions/cache: v2`.
GitHub has closed down actions/cache v1 and v2 and now auto-fails runs
that reference them at action-download time, so the workflow cannot get
as far as `make test` or the bazel e2e target.
Bump actions/cache to v4 to unblock that, and bump the remaining actions
still on the Node 12 runtime at the same time:
- actions/checkout v2 -> v4
- actions/setup-node v2.1.4 -> v4
- haskell/actions/setup v1 -> haskell-actions/setup v2 (repository moved)
Tool versions are left as they are (GHC 8.8.3, stack 2.5.1, Node 12.x) so
this change is limited to action versions. haskell-actions/setup v2 still
exposes the stack-path output the cache step depends on.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
With the deprecated actions bumped, the Haskell job now reaches `make test` and fails there instead: `make test` depends on the `schema` target, which fetches the EDItEUR archives, and editeur.org now answers bazel's request with `202 Accepted` instead of the zip. The test suite does not need those archives. Everything under test/ reads fixtures/test_*.xsd; the only reader of ./schema is schemaRoot in src/Lib.hs, which is the code-generation path. The dependency was an over-specification that tied the whole feedback loop for the parser to the availability of an external service. Drop it from `test` and keep it on `build`, where generating code really does need the schema. This does not fix the 202 itself: generation and tracking new schema releases still need the download. Also introduce docs/adr/ to record decisions like this one, with a template, an index, and the two decisions made here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
- @bazel/bazelisk 1.7.3 -> 1.28.1 - @types/node 14.14.25 -> 22.20.2 fast-xml-parser is deliberately left at 3.17.6 here. It has two open advisories (GHSA-x3cc-x39p-42qx, GHSA-gh4j-gqv2-49f6) that are only fixed in 5.6.1+, and that major bump changes the parser API the TypeScript reader template uses, so it needs its own change with the template migration. The lockfile is regenerated with --lockfile-version 1 rather than being allowed to move to v3. rules_nodejs 3.1.0 runs npm_install with its own bundled npm, and the CI job still runs Node 12.x; neither reads a v3 lockfile's `packages` key, so they would silently re-resolve instead of honouring the lock. The lockfile version can move once the Node toolchain and rules_nodejs are updated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
The previous commit dropped the `schema` prerequisite from `make test` on the claim that nothing under test/ reads schema/. That claim was wrong, and review caught it: fixtures/test_mixed_html.xsd included ../schema/v2/ONIX_XHTML_Subset.xsd directly. Xsd.getSchema follows includes recursively and resolves that relative path with readFile, which throws when the file is absent, and schema/ is gitignored — so on a clean checkout the suite would have failed instead of running. Commit 9352123 confirms the dependency was deliberate: it added `test: schema` in the same change that deleted the vendored 2_1_rev03_schema/ tree and repointed this fixture at ../schema/v2/. Rather than restore the prerequisite, move what the fixture needs into the repository. test_mixed_html_xhtml_subset.xsd declares the 40 element names the fixture refers to, each as a mixed complex type. That is the property the assertions actually rest on: TestModel expects Model.collectElements to come back empty, and that filter keeps only elements with complexMixed = False, so the test means "XHTML elements do not leak into models". Deleting the include instead would have made the assertion vacuous. The stand-in is written here rather than copied from the EDItEUR distribution, so it raises no redistribution question. ADR-0002 is rewritten around what is actually true, including why the dependency was real and why a stand-in is enough. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
Keeps this stacked branch's CI running the corrected test suite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
3.17.6 carries two open advisories (GHSA-x3cc-x39p-42qx prototype pollution via tag or attribute name, GHSA-gh4j-gqv2-49f6 comment and CDATA injection). Both are fixed only from 5.6.1, and the major bump replaces the module-level `parse` with an `XMLParser` instance, so the reader template has to move with it. v5 reports the XML declaration as a top-level `?xml` key, which v3 did not, so the parsed object would have gained a key the ONIXMessage type does not describe. Passing ignoreDeclaration restores the previous shape. Checked by parsing fixtures/20201200.onix with both versions installed side by side and comparing the serialised results: v3 and v5 differ by default (53110 vs 53124 bytes, `?xml` present only in v5) and are byte-identical with ignoreDeclaration set. `npm audit` now reports 0 vulnerabilities. generated/typescript/v2/reader.ts is updated alongside the template. The reader templates contain no mustache tags, so the generator copies them through unchanged and the two files are byte-identical by construction — verified with diff both before and after this change. That keeps the committed output the same as what regenerating would produce, which cannot be run here because it needs the EDItEUR schema. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
Review pointed out that nothing actually enforced keeping the lockfile at version 1: the previous commit produced it by passing --lockfile-version 1 by hand, so the next plain `npm install` on a modern npm would have quietly rewritten it to v3. An .npmrc makes the format a property of the repository instead of of whoever ran the command. Verified: with this file, `npm install` on npm 10.9.7 leaves package-lock.json unchanged at v1; without it the same command rewrites it to v3. node_modules/ was never listed in .gitignore, which makes committing it by accident easy once anyone runs npm install in a checkout. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
レビュー結果移行そのものの作り方は正しいです。 必須1. 実体参照のデコード差分 — v3 はデフォルトで実体参照をデコードせず、v5 は
なぜ問題か: v5 の挙動のほうが XML 仕様として正しく、v3 のほうがバグでした。つまり直すべきではありません。問題は、PR 本文が「出力はバイト単位で同一」と書いていることで、これは事実上の破壊的変更を隠してしまっています。 修正案(どちらか):
推奨2. ONIX に PI が入ることは稀ですが、送信側が挿入すると 3. 数値変換の差分(先頭ゼロは無害、桁数と e 記法は差が出る) まず結論として、ONIX コードの 差が出るのは以下です:
16 桁までは一致するので ISBN-13 / GTIN-13( 4. CI の Node が 12.x のまま —
5. TS reader を触るテストが 1 つもない CI の e2e は 任意6. v5 の新しい上限で例外になるケースがある
いずれも修正不要ですが、把握しておく価値はあります。 7. 混在コンテンツでのキー順が変わる deep equal では同じで、 8. 指摘するに値はしますが、優先度は低いです。この try/catch は完全な no-op で、書かなくても呼び出し側から見た挙動は 1 ビットも変わりません。本 PR が持ち込んだものではなく元からあるコードなので、この PR で必ず消すべきとは思いません。ただ reader を触るのは今回が良い機会ではあります。消す場合はテンプレートと生成物の両方を同時に直してください(下記のとおり 2 つは完全に同一である必要があります)。 9. 既存の別問題(本 PR の範囲外、参考まで)
検証した内容すべてリポジトリ外の一時ディレクトリで、v3 と v5 を並列インストールして実施しました。 A. フィクスチャのパリティ(再現できました) (
B. フィクスチャにない入力での網羅比較(15 ケース)
先頭ゼロについて実データで確認した結果(v3 / v5 とも完全同一): C. テンプレートと生成物の同一性(主張どおりでした)
D. v3 と v5 のデフォルトオプション比較 v5 の E. リポジトリ全体の残存チェック(クリーンでした) v3 API の残りも古い peer range もありません。Go 側の reader / template は XML パーサに依存しないため無関係です。 F. lock ファイル 追加された 7 パッケージ( G. 型チェック リポジトリの
検証できなかったこと
Generated by Claude Code |
Review showed the "byte-identical output" claim was vacuous. Parity held
on fixtures/20201200.onix because that file contains no entity references
at all — every & in it sits inside CDATA. v3 returns "&" unexpanded
where v5 decodes it, and real ONIX data uses & constantly in titles
and author biographies, so consumers of the generated reader will see the
difference.
Keep v5's behaviour rather than pinning processEntities: false. v3 was
wrong — a parser that hands back the escape instead of the character
forces callers to decode twice — and suppressing that fix to preserve a
byte-for-byte diff would take the security release while cancelling the
bug fix shipped with it. ADR-0005 records the decision and the reasoning.
ignoreDeclaration only hides the XML declaration; any other processing
instruction still came through as a `?name` key. Add ignorePiTags so the
parsed shape stays limited to the document's own elements. Reproduced
both differences directly:
v3 {"r":{"t":"Marks & Spencer"}}
v5 {"r":{"t":"Marks & Spencer","?pi":""}}
v5 +flag {"r":{"t":"Marks & Spencer"}}
The ADR also records two things this change does not address: 17-digit
and longer numbers switch from number to string, and leading-zero ONIX
codes like "01" are coerced to 1 by both versions alike — a real bug, but
not one this migration introduces.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
|
レビューありがとうございます。必須 1 件と推奨 1 件を反映しました (fc66629)。特に必須の指摘は、こちらの検証設計の欠陥を突いています。 必須: 「バイト一致」は空振りで成立していたご指摘のとおりです。 再現しました。 ONIX の実データでは書名や著者略歴に 対応方針:
|
Without .npmrc on this branch, a plain npm install rewrites the lockfile to version 3, which is exactly what that file exists to prevent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
fast-xml-parserの脆弱性 2 件を塞ぎます。API の破壊的変更と出力の挙動変更を伴うため、#57 から切り出した PR です。base は #57 (
claude/update-node-toolchain-and-npm-deps)。さらにその下に #56 があります。動機
最初の修正版は 5.7.0 です。3.17.6 に留まる限り塞げません。
挙動が変わります(重要)
当初この PR は「出力はバイト単位で一致する」と説明していましたが、それは誤りでした。レビューで、検証に使った
fixtures/20201200.onixにエンティティ参照が 1 つも含まれていない(&はすべて CDATA の内側)ことが判明しました。一致は、差が出る条件を入力が満たしていなかったから成立していたにすぎません。v3 は
&を展開せず文字列のまま返し、v5 はデコードします。ONIX の実データでは書名や著者略歴に&が日常的に現れるため、利用者が確実に踏む差です。processEntities: falseで v3 を再現する道は採りませんv3 の挙動は仕様として正しくありません。
&は&のエスケープであり、展開せずに返すのは利用者に二重デコードを強いることです。後方互換性はこのリポジトリの中心ですが、それは間違った出力を永続させることではありません。差分を消すためにprocessEntities: falseを指定すると、脆弱性の修正だけを取り込んで、同じリリースのバグ修正を打ち消すことになります。判断とその理由は ADR-0005 に記録しました。TypeScript サポートが README 上まだ "Not yet" 段階であることも判断材料です。
変更内容
ignoreDeclaration: v5 は XML 宣言を?xmlキーとして返すため抑制ignorePiTags: 宣言以外の処理命令も?nameキーで漏れるため抑制(レビュー指摘)npm auditはfound 0 vulnerabilitiesになりました。generated/を手で書き換えている点このファイルに限っては生成器が恒等写像です。
readerテンプレートに mustache タグは 1 つも無く、Lib.hsもsubstitute t ()とスキーマを渡さずに描画します((Right t, Reader) -> unpack $ substitute t ())。テンプレートと生成物はバイト一致し、再生成した場合の出力と同一です。再生成自体はこの環境では実行できません(ADR-0003 / #58)。既知の未解決問題(この PR の範囲外)
"01"のような先頭ゼロの ONIX コードが数値1に変換される。v3/v5 どちらでも同じ挙動で、この移行が持ち込む問題ではありませんが実データを壊すバグです。ADR-0005 に記録し、別 PR で対応しますnumber(精度欠落)、v5 がstring。ISBN-13 / GTIN-13 は 13 桁なので影響なし🤖 Generated with Claude Code
https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z