Rust
イベント
該当するコンテンツが見つかりませんでした
マガジン
該当するコンテンツが見つかりませんでした
技術ブログ
こんにちは!ファインディの大石( @bicstone )、甲斐( @karukan013L23 )、千田( @_c0909 )です。先日、ファインディはベルサール羽田空港で開催された「TSKaigi 2026」に協賛しました。 今回はDevRelメンバーとフロントエンドエンジニア3名で参加し、ブース運営を行いました。本記事ではTSKaigi 2026において印象深かったセッションの紹介や登壇、ブース出展などの活動内容を紹介します。 ブースで実施したユーティリティ型アンケートの集計結果(480票)も後半で公開していますので、ぜひ最後までお読みください。 TSKaigi 2026について 印象深かったセッション 【大石】TS 7: How We Got There 【甲斐】tscからtsgoへ ── DenoのTypeScript基盤はどう変わったか 【千田】Oxlint は ESLint / typescript-eslint を置き換えられるか? 【大石】CfP登壇: TypeScript 6.0での型推論修正を追う ファインディの活動 アンケート結果 さいごに お知らせ TSKaigi 2026について TSKaigiは日本最大級のTypeScriptをテーマとした技術カンファレンスです。東京都大田区のベルサール羽田空港にて、2026年5月22日(金)〜23日(土)に開催されました。 2026.tskaigi.org 印象深かったセッション 興味深いセッションが多くありましたが、その中でも3名それぞれが印象に残ったセッションを紹介します。 【大石】TS 7: How We Got There 2026.tskaigi.org TypeScriptチームのJake Baileyさんによる、TypeScript 7をGo言語へ移植した経緯と成果についての基調講演です。 特に印象的だったのは、Goを採用した理由を体系的に知ることができた点です。 JavaScriptではスレッド間でオブジェクトを共有できず、async/awaitが関数全体に伝播してしまうため、並列化が困難でした。 Goのgoroutineを活かすことで、Parse・Bind・Emitの各フェーズを並列化し、Checkerも複数並べることで高速化を実現しています。 VS Code (Electron) のプロジェクトを tsc と tsgo それぞれで実行した際の所要時間とCPU使用率の差を見せていただいたデモでは、マルチスレッドの活用やCPU使用率の変化が一目で分かり、なぜ大幅な高速化を実現できたのか直感的に理解できました。 発表のなかで繰り返し強く呼びかけられていたのが、コミュニティからのフィードバックでした。「ぜひbetaやnightlyを試してほしい」「VS CodeのNative Preview拡張を入れてほしい」「クラッシュやコンパイル挙動の変化、特にAPIへの意見を送ってほしい」と呼びかけていました。 過去1年でコミュニティから1141件のIssueと1487件のマージ済みPRが寄せられ、テレメトリ経由のクラッシュ情報も含め、利用者からの報告が開発の方向性を支えていることが伝わってきました。 私たちのチームでは、すでにコミット時のフックで tsgo を試験的に採用しています。今後は開発フロー全体への導入を進めながら、検知した問題は積極的にフィードバックを送っていきたいです。 ファインディでも従来からOSSへのIssue起票やPull Requestの作成、メディア企画を通じた寄付などの形で支援を続けてきましたが、TypeScriptのように多くの利用者を抱えるプロジェクトでは、利用者一人ひとりの報告こそが大きな貢献になることを再認識しました。 これまで断片的にしか追えていなかったTypeScript 7について体系的に理解でき、とても学びの多い発表でした。社内にもぜひ共有していきたいと思います。 【甲斐】tscからtsgoへ ── DenoのTypeScript基盤はどう変わったか 2026.tskaigi.org Denoのmaguroさんによる、DenoのTypeScript基盤を tsc から tsgo へ移行する取り組みについてのセッションです。 元々DenoはTypeScriptをフォークしたパッケージを使用し、Deno Rust側と必要な情報をやり取りし、Deno固有の概念を tsc が解釈できるよう、 tsc にパッチを当てたものをDeno binaryの中に埋め込んでいました。 tsgo への移行の最初のアプローチは tsgo をフォークし、Deno固有の概念を tsgo に渡せるようにするアプローチでした。 tsgo はDeno固有の概念をそのまま解決できないため、Deno Rust側で処理できるよう対応しています。LSP対応のコスト、フォークしたパッケージのメンテナンスコストが高く、現在はフォーク版ではなく公式のTypeScriptパッケージを利用するアプローチが試みられています。 TypeScript向けにDenoの依存と型をローカル生成することで、パッチを当てずにDeno固有の概念を解釈できる構成にしています。 特に印象的だったのは、DenoのWeb標準の哲学を少し曲げてでもTypeScriptで扱える形に寄せていった点です。Deno binaryの中→Deno binaryの外→Deno projectの外へTypeScriptパッケージが押し出されており、フォークによる運用コストの増加を避けつつ実行可能なアプローチをとっています。 型チェックを使用したい他のライブラリも同様にフォーク以外の選択肢を模索しており、方向性は同じだがそれぞれ異なるアプローチになっていることが興味深かったです。 普段Denoは使用していませんでしたが、現在の形に辿り着くまでにどのような意思決定があったかを見ていくことで、ここに至るまでの課題や意思決定ごとのトレードオフを学ぶことができ、現在の思想を理解する助けとなりました。 今後もツールチェーンやライブラリの意思決定の背景を学ぶ機会を定期的に設けていきたいなと思います。 【千田】Oxlint は ESLint / typescript-eslint を置き換えられるか? 2026.tskaigi.org 株式会社うるるの藤田翔雅さんによる、OxlintがESLint / typescript-eslintをどこまで置き換えられるのかを整理したセッションです。 特に印象的だったのは、Type-Aware Linting(型情報を使ったLint)の有無でパフォーマンスが大きく変わる点をベンチマークで示していたことです。 型情報を使わない比較ではESLintの8.213秒に対しOxlintは0.304秒と約27倍速く、型情報を使うルールを有効にしてもESLintの16.121秒に対しOxlintは0.807秒と約20倍速いという結果でした。 型情報を使わないLintが構文解析だけで完結するのに対し、型情報を使うLintはプロジェクト全体の型グラフ構築( tsc / tsgo )を必要とするためボトルネックになる、という構造的な解説も理解の助けになりました。 導入判断についても踏み込んでおり、型情報を使わないLintであればOxlintは主要ルールを十分カバーしており移行は現実的である一方、 oxlint-tsgolint によるType-Aware Lintingはまだ非安定版であること、カスタムルールを抱えるプロジェクトでは移行コストが上がることなど、現場目線のトレードオフが具体的に語られていました。 結論として、非Type-Aware LintingであればOxlintへの移行を推奨するというメッセージが明快でした。 私たちのチームでもESLint + Prettierを利用しており、CIの実行時間は継続的な課題です。すでにOxc系(Oxlint + Oxfmt)への移行を計画しており、既存のプロダクトはType-Aware Lintingに依存しない構成となっています。 本セッションの「非Type-Aware LintingならOxlint移行を推奨」という結論は私たちの状況に当てはまり、実際の移行計画に重ねて考える良い機会になりました。 【大石】CfP登壇: TypeScript 6.0での型推論修正を追う 当日のCfP枠では、大石が「プロパティの順序で型推論が壊れる!? TypeScript 6.0の修正からContext-Sensitivityの仕組みを追う」というタイトルで登壇しました。 プロパティの記述順序を入れ替えるだけで型推論が壊れる挙動を入口に、TypeScript 6.0でマージされたPRの中身まで踏み込んだ内容です。詳細は別記事にまとめていますので、あわせてご覧ください。 tech.findy.co.jp speakerdeck.com ファインディの活動 ファインディはGoldスポンサーとして協賛し、ブース出展という形で支援しました。 ブースでは「よく使うユーティリティ型」をテーマにしたアンケート企画を実施しました。普段の開発でよく使うユーティリティ型を選んでいただく内容で、2日間かけて多くの方に投票いただきました。 TSKaigi2026始まりました!入口すぐです! お待ちしております🌟 #TSkaigi2026 #tskaigi pic.twitter.com/ecf1Zzok0V — いわさき@Findy DevRel (@iwasakitchen) 2026年5月22日 x.com アンケートの最終結果はこちらになります。たくさんの投票ありがとうございました。 TSKaigi 2026改めて2日間ご参加いただき、ありがとうございました!よく使うユーティリティの「型」は?の最終結果です!😊🎊 #TSkaigi #TSkaigi2026 pic.twitter.com/0Nt4xun2bQ — いわさき@Findy DevRel (@iwasakitchen) 2026年5月23日 x.com アンケート結果 総数:480票 順位 ユーティリティ型 割合 票数 1位 Record<Keys, Type> 33.3% 160票 2位 Pick<T, Keys> 17.7% 85票 3位 Readonly<T> 14.6% 70票 4位 Partial<T> 9.4% 45票 5位 ReturnType<T> 8.8% 42票 6位 Exclude<T, U> 4.2% 20票 7位 Extract<T, U> 2.5% 12票 8位 NonNullable<T> 2.5% 12票 9位 Awaited<T> 1.0% 5票 - その他 6.0% 29票 その他内訳 ユーティリティ型 票数 その他・使っていない 22票 Omit<T, Keys> 5票 Beautify<T> 1票 & 、 | 1票 加えて、マーケティング担当のメンバーがAIを活用して自ら開発したルーレットアプリと、ファインディオリジナルのノベルティをご用意し、立ち寄っていただいた方に楽しんでいただきました。 さいごに セッションは多岐にわたるなかで、私たちが特に注目したのはGoによるコンパイラの再実装(コンパイラ本体のネイティブ化)、tscからtsgoへの基盤刷新(他ランタイムによる採用)、Rust製Linterの可能性(周辺ツールへの波及)でした。 3つを通して、TypeScriptエコシステムがNative実装へと動いている流れを実感する2日間となりました。TSKaigiはとても温かい素敵なコミュニティで、いち参加者としても多くの学びと交流の機会を得ることができました。 カンファレンスの開催にあたりご尽力いただいた、運営スタッフの皆様、関係者の皆様、登壇者の皆様に感謝申し上げます。 お知らせ 同日参加したファインディのDevRelメンバーによるレポート記事も公開されています。あわせてご覧ください。 note.com TSKaigi 2026のアフターイベント「TSKaigi Night talks 〜after conference〜」をスポンサー企業9社で共催します。当日のCfP枠で採択されなかった知見もコミュニティへ還元することを目的としたイベントです。 ファインディからは千田が「OSSのUIライブラリでESLintのカスタムルールを作っている話」、甲斐が「Temporal - TypeScript 6.0で始める新しい日時API」というテーマで登壇予定です。 2026年6月10日(水)19:00から、ファインディのイベントスペースにて開催します。TSKaigi 2026に参加された方も、参加できなかった方も、ぜひお越しください。 findy.connpass.com ファインディでは一緒に働くメンバーを募集しています! 興味がある方はこちらから ↓ herp.careers
本ブログは 2026 年 4 月 7 日に公開された Amazon Science Blog “ Verifying and optimizing post-quantum cryptography at Amazon ” を翻訳したものです。 自動推論によって、セキュリティ、性能、保守性の要求をどのように両立させるか。 現在、安全なオンライン通信は 公開鍵暗号 によって実現されています。主に RSA と楕円曲線暗号 (ECC) が使われており、その安全性はある計算問題が困難であるという仮定に依存しています。しかし、これらの問題は 従来の コンピュータでは困難と考えられているものの、十分に大規模な量子コンピュータでは扱える可能性があります。「Store now, decrypt later」(今保存して後で復号) 攻撃は、暗号化された情報を傍受しておき、量子コンピュータで復号できるようになるまで保持する攻撃です。こうした攻撃が技術的に実現可能になるよりはるか前から、対策が必要となります。 ポスト量子暗号 (PQC) は、従来のコンピュータ上で動作しながら量子コンピューティングに対しても安全な暗号です。2024 年、米国国立標準技術研究所 (NIST) は 8 年にわたる標準化作業を経て、標準規格 FIPS-203 を公開しました。FIPS-203 では、量子コンピュータからの攻撃に対して安全と考えられている鍵共有メカニズムとして、Module-Lattice-Based Key Encapsulation Mechanism (ML-KEM) が規定されています。 本記事では、Amazon Automated Reasoning Group、AWS Cryptography、そしてオープンソースコミュニティが協力して、ML-KEM のオープンソースかつ形式的に検証された最適化実装をどのように作り上げ、お客様を「Store now, decrypt later」攻撃から最高の保証と最小のコストで保護しているかをご紹介します。 優れた暗号エンジニアリングとは何か? Amazon の Customer Obsession に従い、AWS は暗号ソリューションに取り組む際、次の 3 つの目標を優先します。 お客様のデータのセキュリティ : 暗号は安全に実装することが極めて難しく、わずかな欠陥でもお客様のプライバシーを危険にさらす可能性があるため、万全を期す必要があります お客様の体験 : 暗号には計算コストが伴います。AWS はこれを最小化し、お客様に最小のコストと最良の体験を提供します ソリューションを将来にわたって保守する能力 : 保守に費やす時間が少ないほど、お客様のためにより多くのイノベーションを生み出せます しかし、これらの目標の間にはトレードオフがあります。シンプルなコードは保守も安全な記述も最も簡単ですが、動作が遅くなりがちです。一方、高速なコードは監査が難しく、エラーが起きやすい傾向があります。 自動推論 によって、AWS はこのトレードオフを解消し、安全で、高速で、保守しやすい暗号ソリューションを同時にお客様に提供できます。 なぜ新たな ML-KEM 実装が必要なのか ML-KEM (旧称 Kyber) は実装の観点から十分に研究されています。一方では、 Kyber リファレンスコード が、長年精査されてきたクリーンな C 言語実装を提供しています。他方では、ML-KEM をさまざまな指標やプラットフォーム向けに最適化する方法を記述した数多くの研究論文があります。 2024 年に AWS Cryptography と Amazon Automated Reasoning Group が直面した課題は、リファレンス実装のシンプルさと、研究で明らかになった最適化の可能性を、本番環境で使える単一の実装に組み合わせることでした。 2024 年、AWS Cryptography と Amazon Automated Reasoning Group は、徹底的に精査された ML-KEM リファレンス実装のシンプルさと、研究で明らかになった最適化の可能性を、本番環境で使える単一の実装 mlkem-native にまとめるという課題に取り組みました。 同じ頃、AWS は Linux Foundation の Post-Quantum Cryptography Alliance (PQCA) の創設メンバーとなりました。PQCA は、「標準化過程にあるポスト量子暗号アルゴリズムの高保証ソフトウェア実装の構築を目指すオープンソースプロジェクトの集合」である Post-Quantum Cryptography Package (PQCP) を立ち上げました。 そこで AWS は独自にコードを開発するのではなく、チームメンバーが PQCP に参加し、まもなく mlkem-native を立ち上げました。これは、ML-KEM リファレンス実装と、最適化および形式的検証に関する研究を組み合わせることを目的とした、ML-KEM の高保証・高性能 C 言語実装です。 速く、そして慎重なコーディング mlkem-native のモジュラー設計は、ML-KEM の高レベルロジックをカバーする フロントエンド と、性能が重要なすべてのサブルーチンを担当する バックエンド を組み合わせています。各サブルーチン (SHA3 の基礎となる Keccak 置換や、高速な多項式演算の基礎となる数論変換 (NTT) を含む) には、特定のハードウェア向けにネイティブに記述された、高効率な複数の実装が用意されています。デフォルトの C 言語実装に加えて、mlkem-native は AArch64、x86_64、RISC-V64 向けのアセンブリ/組み込み関数バックエンドを提供しています。 mlkem-native のモジュラー設計は、ML-KEM の高レベルロジックをカバーするフロントエンドと、性能が重要なサブルーチンの複数のハードウェア固有実装からなるバックエンドを組み合わせています。 保守性のために重要なのは、フロントエンドとバックエンドの間のインターフェイスが固定されていることです。新しいターゲットアーキテクチャ向けの最適化を追加する開発者は、バックエンド仕様に従って選択したバックエンド機能を実装し、フロントエンドはそのまま維持します。バックエンド仕様の策定は、見かけほど単純ではないことが分かりました。これについては以下で説明します。 限界を知る メモリ安全性 C プログラミング言語のよく知られた課題は、バッファオーバーフローのリスクです。メモリ領域の指定された境界を超えて書き込むと、データ構造が破壊され、悪意を持って悪用されると非特権コードの実行につながる可能性があります。こうした問題の総称が メモリ安全性 です。Rust のようなメモリ安全な言語は、範囲外アクセスの影響を制限できます (たとえば、未定義動作を示す代わりにパニックする)。しかし、間違いそのものを防ぐわけではありません。 型安全性 もう一つのよく知られた課題は ML-KEM の実装に関するもので、整数オーバーフローのリスク、つまり 型安全性 の側面です。RSA や ECC と同様に、ML-KEM はモジュラー演算に依存しています。モジュラー演算では、演算の結果を特定の数 (ML-KEM の場合は素数 3,329 で、 MLKEM_Q または単に q と表記) で割り、その剰余だけが次に持ち越されます。剰余演算子はパーセント記号 % で表されます。 論理的には、ML-KEM で 2 つの数 x と y を加算または乗算する必要がある場合、( x + y ) % q および ( x * y ) % q を計算する必要があります。たとえば、(294 * 38) % q = 11,172 % q = 1,185 となります。このような「即時」のモジュラー q 演算は、データを「正規」範囲 {0, 1, 2, … , q -1} で表すために常にモジュラー還元を適用するもので、極めて遅くなります。 効率的な ML-KEM 実装では、代わりに「遅延」モジュラー q 演算を使用します。データはできるだけ長くモジュラー還元なしで操作され、最悪の場合のオーバーフローのリスクが生じたときにのみ還元が行われます。さらに、これにより Montgomery 還元のような不完全な還元アルゴリズムが使えるようになります。これは高速ですが、必ずしも完全に還元された出力を返すわけではありません。 ML-KEM の場合、モジュラー q = 3,329 のデータは通常、符号付き 16 ビット整数に格納されます。ML-KEM の数多くの算術ルーチン全体で遅延演算を扱う際には、データの最悪値の境界を追跡し、それらの境界が 16 ビット整数の限界を超える可能性のある箇所にモジュラー還元を挿入することが不可欠です。この領域での小さな間違いは、テストで見逃されることがあります。なぜなら、平均的な境界は最悪値の境界よりはるかに小さい傾向があるためです。そして、本番環境でランダムに表面化することがあります。 バッファ境界、特に算術境界の追跡は、時間がかかり、エラーが起きやすい作業です。たとえば、低レベルの算術関数の出力境界を弱めると、まったく別の関数で稀に算術オーバーフローが発生することがあります。これを手作業で確認するには、緻密なドキュメント作成と熟練した監査担当者が必要なだけでなく、開発が遅くなります。 mlkem-native では、C Bounded Model Checker (CBMC) というツールを使用して、C レベルでメモリ安全性と型安全性を自動的に検証しています。各関数について、機械可読かつ人間可読な契約をソースコードに追加してバッファと算術データの境界を指定し、CBMC にそれらの境界に対してバッファオーバーフローや算術オーバーフローが発生し得ないことを自動的に検証させます。 モジュラー還元の簡単な例を見てみましょう。 void mlk_poly_reduce_c(mlk_poly *r) __contract__( requires(memory_no_alias(r, sizeof(mlk_poly))) assigns(memory_slice(r, sizeof(mlk_poly))) ensures(array_bound(r->coeffs, 0, MLKEM_N, 0, MLKEM_Q))) { unsigned i; for (i = 0; i < MLKEM_N; i++) __loop__( invariant(i <= MLKEM_N) invariant(array_bound(r->coeffs, 0, i, 0, MLKEM_Q))) { /* Barrett reduction, giving signed canonical representative */ int16_t t = mlk_barrett_reduce(r->coeffs[i]); /* Conditional addition to get unsigned canonical representative */ r->coeffs[i] = mlk_scalar_signed_to_unsigned_q(t); } mlk_assert_bound(r, MLKEM_N, 0, MLKEM_Q); } 関連する部分を一つずつ見ていきましょう。まず、 __contract__( … ) に注目します。簡単に言うと、 memory_no_alias と memory_slice の行は、コードが読み書きできるメモリを指定しています。これはメモリ安全性に関連します。 ensures(array_bound(…)) 句は型安全性に関連しています。これは、関数が戻った時点でデータが区間 [0, 1, …, q ) 内にあることを 保証する ことを指定します。証明では、 __loop__(invariant(…)) があり、ループがこの境界を段階的にどう確立するかを指定しています。 i 番目のイテレーションでは、 i 番目の係数まで成立します。最後に、実装は実質的に mlk_barrett_reduce と mlk_scalar_signed_to_unsigned_q を組み合わせています。CBMC はこれらの内部を見ず、それらの契約に置き換えます。 int16_t mlk_barrett_reduce(int16_t a) __contract__( ensures(return_value > -MLKEM_Q_HALF && return_value < MLKEM_Q_HALF) { ... } int16_t mlk_scalar_signed_to_unsigned_q(int16_t c) __contract__( requires(c > -MLKEM_Q && c < MLKEM_Q) ensures(return_value >= 0 && return_value < MLKEM_Q) ensures(return_value == (int32_t)c + (((int32_t)c < 0) * MLKEM_Q)) { ... } mlk_barrett_reduce がまず対称的な出力区間 ( -q /2, …, q /2) を確立し、次に mlk_scalar_signed_to_unsigned_q がそれを [0,1, …, q ) にマッピングしているのが分かります。この例では、仕様が望ましい形で整合していることを目視で簡単に確認できますが、より複雑な例ではそれほど明確ではありません。いずれにせよ、CBMC が自動的にチェックしてくれます。 速く動かしながら安全を保つ 上述の CBMC 証明は、mlkem-native の C コードに対するメモリ安全性と型安全性を確立します。しかし、mlkem-native の最も性能が重要な部分 (Keccak 置換と数論変換) は、AArch64 と x86_64 向けに手作業で最適化されたアセンブリで実装されています。 mlkem-native のアセンブリ実装に対して、高い性能を維持しつつ保証を得るために、AWS は次の 3 つのコンポーネントを使用しています。アセンブリのスーパーオプティマイザーである SLOTHY、対話型定理証明器である HOL Light、そして HOL Light 上に構築されたアセンブリ用検証基盤である s2n-bignum です。これらを組み合わせることで、開発者がクリーンで保守しやすいアセンブリを記述しつつ、デプロイされるコードが正当性の形式的保証を伴ってピーク性能を達成するワークフローが可能になります。 高性能なアセンブリを手で書くと、根本的なトレードオフが生じます。計算を明確に表現するクリーンで監査可能なコードは遅く、高速なコードは密で、マイクロアーキテクチャ固有で、保守が困難です。SLOTHY はマイクロアーキテクチャ固有の最適化を自動化することで、このトレードオフを解消します。アセンブリプログラムを制約充足問題に変換し、制約ソルバーを使用して最適な命令スケジュールとレジスタ割り当てを見つけ、最適化されたアセンブリを出力します。開発者は計算のロジックを重視したクリーンなコードを書き、SLOTHY が高速なコードを生成します。 AWS は、すべての AArch64 および x86_64 アセンブリルーチンの機能的正当性を、HOL Light と s2n-bignum を使用して証明します。SLOTHY が使用される場所では、特定の命令順序やレジスタ割り当てに依存しないように証明が記述されます。したがって、証明を調整することなく、特定のマイクロアーキテクチャ向けにコードを再最適化できます。この「事後」検証アプローチは、アセンブリで表現された計算の数学的な正しさを、それがどのように生成されたかにかかわらず確立します。特に、SLOTHY は信頼できるコンピューティングベース (TCB) から除外されます。 誠実さを保つ 形式的検証は決して絶対的なものではありません。すべての証明は、形式的なオブジェクト (仕様とモデル) を非形式的な現実世界の要件とシステムに結び付けるものであり、これらの結び付きにはギャップが生じます。形式的仕様は実際に必要なものを捉えているか? 形式的モデルは実際のシステムを忠実に反映しているか? 証明基盤自体は健全か? お客様の信頼を獲得し維持するには、これらの限界について透明性を保つ必要があります。そこで AWS は、 SOUNDNESS.md と題したドキュメントを作成・公開しました。ここでは、mlkem-native で何が証明され、何が仮定され、残存リスクがどこにあるかを、HOL Light 証明で使用されるハードウェアモデルの忠実性、CBMC のより大きな TCB、2 つの検証スタック間の手動の橋渡しに至るまでマッピングしています。各ギャップについて、実施されている緩和策を説明し、今後の作業の概要を示しています。 AWS の目標は完璧を主張することではなく、透明性を通じて信頼を獲得することです。コミュニティの皆様には SOUNDNESS.md を批判的に読み、AWS の前提に異議を唱え、残存するギャップを埋めることにご協力いただければ幸いです。 本番環境への展開 mlkem-native は、AWS サービス全体の安全な通信を支える Amazon のオープンソース暗号ライブラリ AWS-LC に統合されています。この統合では、自動インポーターを使用して mlkem-native のソースコードをアップストリームリポジトリから直接取り込み、AWS-LC が最新の検証済み実装と同期し続けることを保証します。 この統合は手間を最小限に抑えるよう設計されています。mlkem-native のモジュラーアーキテクチャにより、AWS-LC はコアの ML-KEM ロジックをインポートしながら、プラットフォーム固有のコンポーネントには独自の実装を提供できます。たとえば、AWS-LC は mlkem-native の暗号プリミティブを既存の FIPS-202 (SHA-3) 実装にマッピングし、AWS-LC の乱数生成およびメモリゼロ化関数を使用し、必要な場合はペアワイズ一貫性テストなど FIPS モード機能を有効にします。これを可能にしているのは、検証済みコードを変更することなく mlkem-native の API を AWS-LC のインフラストラクチャに橋渡しする薄い互換性レイヤーです。 重要なのは、メモリ安全性と型安全性を証明する CBMC 契約が、インポートされたソースコード内に保持されていることです。プリプロセッサがコンパイルされたバイナリからこれらを削除しますが、ソース内には残り、コードの保証の機械チェック可能なドキュメントとして機能します。これは、実装と共に移動する一種の「生きた証明」です。 さらに、mlkem-native も AWS-LC もオープンソースで寛容なライセンスのため、その利点は AWS の枠を超えて広がります。誰でも mlkem-native を自社のシステムに統合し、同じ性能と保証の組み合わせを得ることができます。形式的検証成果物 (CBMC 契約と HOL Light 証明) はリポジトリの一部であり、関連するすべてのツールはオープンソースであり、セットアップと証明チェックのスクリプトが提供されているため、AWS のセキュリティ主張を独立に検証できます。 インパクト mlkem-native の開発は、自動推論を体系的に適用すれば、暗号エンジニアリングの 3 つの目標 (セキュリティ、性能、保守性) が衝突しないことを示しています。 CBMC は、複雑な算術全体で境界を手動で追跡する作業から AWS を解放し、テストでは見逃されて本番環境でランダムに表面化するエラーを捕捉しました。アノテーションはソースコード内に機械チェック可能なドキュメントとして残り、コードを同時により保守しやすく、より安全にします。HOL Light と s2n-bignum により、AWS は数学的な正当性の確実性を持って積極的なアセンブリ最適化をデプロイできました。SLOTHY により、特定のマイクロアーキテクチャ向けにピーク性能を達成しながら、クリーンで監査可能なコードを書くことができました。そして、証明は最適化に依存しないように記述されているため、検証をやり直すことなくコードのターゲットを変更できます。 その結果、従来の開発で達成できるものよりも、同時により安全で、より高速で、より保守しやすい実装が実現しました。AWS はお客様のセキュリティ、お客様の体験、そして革新する能力の間で妥協しませんでした。自動推論は 3 つすべてを実現したのです。 AWS-LC-FIPS リリース プラットフォーム 処理 3.1 4.0 改善倍率 c7i Keygen 30899 65146 2.1 Encaps 30623 61233 2.0 Decaps 25141 51545 2.0 c7g Keygen 29617 71134 2.4 Encaps 28482 66874 2.3 Decaps 23919 64765 2.3 Amazon の暗号ライブラリ AWS-LC で ML-KEM リファレンス実装から mlkem-native に切り替えた際の性能影響。ML-KEM-768 の性能は c7i および c7g EC2 インスタンスで測定されています。数値は 1 秒あたりの処理数を表します (高いほど良い)。ベースラインは ML-KEM の C リファレンス実装を含む AWS-LC-FIPS 3.1 リリースです。AWS-LC-FIPS 4 リリースは mlkem-native でビルドされています。プラットフォームは Intel(R) Xeon(R) Platinum 8488C を搭載した c7i と、Graviton 3 プロセッサを搭載した c7g です。 謝辞 同僚の John Harrison 氏 (Automated Reasoning Group の senior principal applied scientist) には、HOL Light での AArch64 アセンブリ証明の大部分を提供し、また HOL Light 対話型定理証明器および s2n-bignum 検証基盤の保守を担当いただいたことに感謝します。mlkem-native は AWS だけでなく、オープンソースコミュニティの多くのメンバーが関わる共同作業です。とりわけ、共同保守者である zeroRISC の Matthias Kannwischer 氏に感謝します。彼は AWS と共に mlkem-native を立ち上げ、以来プロジェクトの成功に重要な役割を果たしてきました。 著者について Hanno Becker Hanno Becker は Amazon の Automated Reasoning Group の principal applied scientist です。元 Mbed TLS の開発者で、Arm 上の高性能 (ポスト量子) 暗号に情熱を注いでいます。SLOTHY スーパーオプティマイザーの作者でもあります。 Rod Chapman Rod Chapman は Amazon Web Services (AWS) の senior principal scientist です。 Dusan Kostic Dusan Kostic は Amazon Web Services (AWS) の senior applied scientist です。 本ブログは Security Solutions Architect の 中島 章博 が翻訳しました。
はじめに こんにちは。RevComm でエンジニアをしている 林 です。 MiiTel Phone では長らく ESLint + Prettier をフロントエンドの lint / formatter として使ってきましたが、約 1,300 ファイル規模の React + TypeScript プロジェクトで CI と AI コーディングループのフィードバックがどうしても重くなってきていました。 今回、Rust 製ツールチェインである Oxc ベースの Oxlint / Oxfmt へ完全移行したので、その経緯と方法、得られたメリット・デメリットについて紹介します。 Oxc とは Oxc (The JavaScript Oxidation Compiler) は、パーサー・リンター (Oxlint)・フォーマッター (Oxfmt)・トランスパイラーといった JS/TS ツールチェインを Rust で書き直す OSS プロジェクトです。今回扱うのは次の 2 つ。 Oxlint: ESLint 互換のルールセットを持つ Rust 製リンター。 公式ドキュメント では ESLint 比 50〜100 倍速いとしている。JS Plugins (Alpha) と Type-Aware Linting (Alpha) も順次拡張中 Oxfmt: 2026-02 に Beta。Prettier v3.8 の JS/TS conformance 100% を達成し、出力互換を保ったまま高速化できる 開発主体は VoidZero Inc. — Vue.js / Vite の作者 Evan You 氏が 2024 年に設立したスタートアップです。Vite / Vitest / Rolldown / tsdown / Oxc を開発しています。 Biome ではなく Oxc を選んだ理由 似た立ち位置のツールに Biome がありますが、決め手は速度や Prettier 互換ではなく、周辺ツール全体を束ねる存在 ( Vite+ ) でした。 観点 Oxc (Oxlint / Oxfmt) Biome 開発主体 VoidZero (Vite 作者の会社) Biome コミュニティ 周辺ツールとの統合 Vite+ で build / test / lint / format が同じロードマップに乗る 独立型 規則互換性 ESLint ルール名 / Prettier 出力と互換重視 独自ルールセット中心 Vite+ は Vite / Vitest / Oxlint / Oxfmt / Rolldown / tsdown を vp という単一 CLI に束ねた統合ツールチェインです。 今回のプロジェクトも将来的に Vite+ への合流を視野に入れており、その時点で Oxlint / Oxfmt に乗っておいて良かったと言える状態を作りたかったのが Oxc 採用の主な動機です。 Biome に乗ると、将来 Vite+ に揃えたいときに lint / format をもう一度乗り換えるコストが再発します。 移行理由 1. CI / pre-commit / editor の速度がボトルネックになっていた 全件 lint で 13 秒、format チェックで 5 秒というのは、単体で見ればまだ我慢できる範囲です。ただし PR ごとに何度も走り、ローカルの保存時 lint や pre-commit hook でも体感に効いてくるため、合計すると無視できない時間になっていました。 2. AI コーディング時代のフィードバックループ Claude Code や Codex などの AI エージェントがほとんどのコードを書くようになると、lint は人間による最終レビューの代替手段から、 AI がコードを書く途中でその場でミスを弾いて修正する仕組み に役割を変えます。 具体的には、エージェントの編集ごとに lint と formatter を回し、エラーを次のターンに即フィードバックして自己修正させるという使い方です。 ESLint の 1 ファイルあたり 1.72 秒という所要時間ではこのループに乗せづらく、Oxlint の 0.43 秒で初めて現実的になりました。 AGENTS.md / CLAUDE.md の自然言語ガイドは読んだ後に指示が守られるかどうかはお祈りレベルの保証しかなく、絶対に止めたい違反はツール側で機械的に弾いた方が確実です。 lint にその役割を担わせる場合、速度がそのままループの成立可否になります。加えて、一度入れたルールはその後の全セッションに効くので、AI が書くコード量が増えるほど 1 ルールあたりの効果が積み重なっていきます。 3. 設定の簡素化と依存削減 ESLint 設定は eslint.config.js が 220 行、プラグインが 11 個ぶら下がっていました。Oxlint の native plugin で同等のカバレッジが取れるなら、設定もぐっとシンプルになります。 @eslint/compat のような互換レイヤーや、フォーマッター衝突回避のための周辺パッケージも整理できます。 4. Prettier 互換性が確保された Oxfmt が Prettier v3.8 互換 100% を達成したことで、フォーマッターを乗り換えると全ファイルに差分が出るという移行最大の壁が消えました。これがなければ移行コストが見合わなかったので、Beta リリースを待ってから着手する予定でした。 移行方法 Oxc は単一ツールではなく個別のツール群なので、Prettier → Oxfmt と ESLint → Oxlint をそれぞれ独立した PR で進めました。先に Oxfmt 側を済ませてから Oxlint に取りかかる順番です。 Prettier から Oxfmt 1. 差分ゼロ確認 まずローカルで src 配下の全ファイル (約 1,300 ファイル) について、 prettier --write の結果と oxfmt の結果が一致するか git diff で確認しました。 Beta とはいえ Prettier conformance テストが通っているので、現行コードに対しては実用上問題なしと判断しています。 2. 設定ファイル変換 Oxfmt は Prettier 設定からの自動変換コマンドを持っているので、これを使います。 npx oxfmt --migrate=prettier 生成された .oxfmtrc.json の例 ↓ { " $schema ": " ./node_modules/oxfmt/configuration_schema.json ", " semi ": true , " trailingComma ": " all ", " singleQuote ": true , " printWidth ": 120 , " tabWidth ": 2 } .prettierrc / .prettierignore は削除します。 3. scripts / hooks / codegen の置き換え // package.json (抜粋) { " scripts ": { " lint:oxfmt ": " oxfmt --check 'src/**/*.{ts,tsx,mdx}' ", " fix:oxfmt ": " oxfmt 'src/**/*.{ts,tsx,mdx}' " } } pre-commit hook の Prettier エントリも oxfmt に置き換え、 graphql-codegen の afterAllFileWrite や独自 codegen スクリプトで prettier --write を呼び出していた箇所も npx oxfmt に差し替えます。CI ワークフローのジョブ名もここで変更しました。 4. eslint-config-prettier はこの段階では据え置き 公式ドキュメント の推奨に従い、この段階では eslint-config-prettier をそのまま残しました。フォーマッタと衝突する ESLint ルール ( indent など) を無効化する役割は、Prettier でも Oxfmt でも変わらないためです。 なお ESLint 本体を撤去する後続の Oxlint 移行 PR で、同パッケージも併せて削除しています。 ESLint から Oxlint Prettier 移行と違ってこちらは挙動の互換性を見るだけではなく、ルールセットの取捨選択が必要です。方針として「native plugin 主軸、必要なものだけ JS Plugins (Alpha) で補う」を取りました。 1. 完全移行か併用か Oxlint 公式ドキュメントは「小〜中規模は完全置換、大規模は ESLint との併用を推奨」としています。併用したい場合は eslint-plugin-oxlint で Oxlint が拾えるルールを ESLint 側で重複排除し、両者を直列で回すのが定石です。 { " scripts ": { " lint ": " oxlint && eslint . " } } ちなみに今回は 1,300 ファイル規模ながら完全移行を選びました。主な理由は以下です。 速度メリットが消える: 全件 lint で oxlint 0.35s + eslint 12.96s ≈ 13.31s となり、現状とほぼ変わらず、AI ループ用 hook に乗せる速度を取り戻せない 設定の二重管理: eslint-plugin-oxlint で重複排除すると、独自設定 ( no-restricted-globals のカスタム設定など) が無効化されたり、既存の inline // eslint-disable-next-line ... が "Unused eslint-disable directive" として警告化されたりした ロードマップとの整合: 将来 Vite+ に揃えたい以上、併用は足がかりにもならない 「完全移行で破綻するほど大規模か」「速度を hook ループに取り戻したいか」が判断の分岐点で、以降のステップは完全移行ルートの内容です。 2. プラグインの仕分け 既存の ESLint プラグインを、native で代替可能 / JS Plugins で残す / 捨てる の 3 つに分類します。 既存の ESLint plugin 対応方針 typescript-eslint native typescript plugin react / react-hooks native react plugin (react-hooks 同梱) jest native jest plugin unused-imports typescript/no-unused-vars で代替 react-compiler eslint-plugin-react-hooks v6+ に統合されたため native でカバー testing-library / jest-dom oxlint jsPlugins (Alpha) 経由で src/__tests__/** 限定で残す storybook 撤退。 storybook build と Chromatic 視覚回帰で代替 import ( import/order ) oxfmt の sortImports に寄せる (後述) JS Plugins は ESLint プラグインをそのまま読み込めて便利ですが、Alpha かつ Oxlint の Rust native で速いという売りを部分的に削るレイヤなので、メインでは使いませんでした。 テスト系の 2 プラグインだけは「テスト信頼性に直接効くので確実に止めたい」「スコープが __tests__ 配下に閉じている」という条件が揃ったので、限定的に採用しています。 3. 自動変換 + 手調整 flat config からの自動変換は oxlint-migrate が使えます。 npx @oxlint/migrate <optional-eslint-flat-config-path> 生成された JSON に対して、native plugin で対応するルール名 ( @typescript-eslint/... → typescript/... など) の最終調整と、JS Plugins / overrides の追加を手で行います。最終的に出来上がった構成の骨子は次のような形です。 { " $schema ": " ./node_modules/oxlint/configuration_schema.json ", " plugins ": [ " typescript ", " oxc ", " react ", " jest " ] , " jsPlugins ": [ " eslint-plugin-testing-library ", " eslint-plugin-jest-dom " ] , " categories ": { " correctness ": " error ", " suspicious ": " error ", " pedantic ": " off ", " perf ": " off ", " restriction ": " off ", " style ": " off ", " nursery ": " off " } , " rules ": { // ... プロジェクト固有の制約ルール ... } , " overrides ": [ { " files ": [ " src/__tests__/**/*.{ts,tsx} " ] , " rules ": { " testing-library/no-node-access ": " error ", " jest-dom/prefer-in-document ": " error " // ... 他のテスト系ルール ... } } ] } plugins キーを書くと Oxlint のデフォルト plugin セットを上書きします。 typescript / oxc はデフォルトで有効ですが、明示的に書いておかないと意図せず外れる事故が起きやすいので注意が必要です。 もう一つ押さえておきたいのが categories と rules の関係です。 categories は Oxlint のルールを 7 種類 (correctness / suspicious / pedantic / perf / restriction / style / nursery) で一括 ON/OFF する仕組みで、今回は correctness (明らかなバグ) と suspicious (疑わしいコード) のみ error 、それ以外は off にしています。 優先順位は rules > categories なので、 categories.correctness: "error" で一括有効化したうえで、違反が多くて即修正できないルールだけを rules: { "no-extra-boolean-cast": "off" } で個別に逃がす、という使い方ができます。 次の「違反ルールは一時 off」はまさにこの優先順位を使った運用です。 4. 違反ルールは一時 off → follow-up で再有効化 Oxlint デフォルトの correctness カテゴリには、ESLint で off にしていたルールも一部入っています。本 PR で既存コードに手を入れない方針を取ったため、違反が出るルールは一度 off にしておき、別 PR で違反修正 + 再有効化する形にしました。 具体的には no-extra-boolean-cast , no-unneeded-ternary , no-useless-rename , no-useless-catch , jest/require-to-throw-message , react/jsx-key などです。1 PR にまとめると差分が膨大になって reviewer の負担になるので、ルールごとに小さく切り出すと進めやすかったです。 再有効化漏れを防ぐため、一時 off にしたルールはトラッキングチケットに「ルール名 / 違反件数 / 担当 / follow-up PR」のチェックリストで一覧化し、各 follow-up PR から逆リンクを張る運用にしています。 一方で oxlint-migrate の出力には Oxlint で未対応のルールも並びます。今回は @typescript-eslint/no-floating-promises のような type-aware 系 (本移行のスコープ外として別途段階導入する想定) と、 storybook/* のように代替手段ありで撤退と判断したものが中心でした。 未対応ルールは .oxlintrc.json に書いても効かないため、設定からは削除しています。 5. CI / pre-commit の切り替え // package.json (抜粋) { " scripts ": { " lint:oxlint ": " oxlint --deny-warnings src ", " fix:oxlint ": " oxlint --fix --deny-warnings src " } } Prettier から Oxfmt への移行段階で残していた eslint-config-prettier も含め、ESLint 関連 devDependencies はすべて削除しています。 6. import order は Oxfmt の sortImports に寄せる eslint-plugin-import の import/order ルールに相当する機能は Oxlint native にはありません。Oxfmt の sortImports で customGroups / groups を指定すれば、 pathGroups 相当のグループ分けが再現できるので、こちらに寄せました。 // .oxfmtrc.json (sortImports 部のみ抜粋) { " sortImports ": { " customGroups ": [ { " groupName ": " internal-modules ", " elementNamePattern ": [ " <your-dir-1>/** ", " <your-dir-2>/** " ] } ] , " groups ": [ " builtin ", " external ", " internal-modules ", [ " parent ", " sibling ", " index " ] , " style ", " unknown " ] , " newlinesBetween ": true , " order ": " asc " } } これにより lint と format の責務がきれいに分かれ、import の並び替えは Oxfmt の --fix で完結するようになりました。なお sortImports を有効化したコミットは全ファイルに差分が出るので、 .git-blame-ignore-revs に登録して git blame の汚染を防いでいます。 移行したことによるメリット 効果を数字でまとめると次の通りです。 項目 移行前 (ESLint / Prettier) 移行後 (Oxlint / Oxfmt) 倍率 全件 lint (約 1,300 ファイル) 12.96s 0.35s 約 37 倍 全件 format チェック 5.2s 0.5s 約 10 倍 単一ファイル lint 1.72s 0.43s 約 4 倍 設定行数 (lint) eslint.config.js 約 220 行 + 11 プラグイン .oxlintrc.json 約 80 行 — 数字には表れない次のような効果もありました。 単一ファイル lint が hook に乗る速度に収まり、AI エージェントの編集ループ内で常時走らせられるようになった Claude Code の PostToolUse hook で確実に止められる品質チェックをかけられるようになり、エージェントが見逃すエラーを一段減らせた ESLint 10 への移行で必要になる @eslint/compat のような互換レイヤが不要になった devDependencies が ESLint 本体 + 11 プラグイン分減り、 npm install 時間と node_modules サイズが改善 import order を Oxfmt 側に寄せたことで、lint と format の責務分離がクリアになった 移行したことによるデメリット JS Plugins が Alpha なので、 testing-library / jest-dom を残している部分は互換性が壊れるリスクを抱えている type-aware ルール ( no-floating-promises など) は速度トレードオフで今回意識的に lint 層から外している。Alpha 卒業待ちというより、現状の type-aware は 1 ファイルあたり数秒オーダーで hook ループのミリ秒単位の速さに載らないという判断。該当する欠陥は tsc と統合テストでカバーし、lint 層の速度を死守する方針 ESLint / Prettier に比べてコミュニティが小さく、トラブル時の情報量が少ない さいごに 今回の移行は単なる lint / formatter の乗り換えではなく、AI のフィードバックループそのものを速くするための改善でした。lint を hook ループに載せられるか否かが、AI が書くコードの品質に直接効いてくる時代になっています。 次に視野に入れているのは Type-Aware Linting です。たとえば no-floating-promises は AI が書いたコードで起きがちな await 漏れを検出できるルールで、 tsc だけでは取りこぼしやすく本来 lint で止めたい類の問題です。ただし現状の type-aware lint は速度的にまだ重く、hook の高速ループには乗せづらいため、当面は tsc とテストでカバーしつつ常時 hook には組み込まない方針でいく予定です。 AI 時代のフロントエンド開発環境として、これからもフィードバックループ全体の最適化を続けていきたいと思います。 参考文献 Oxc - The JavaScript Oxidation Compiler VoidZero - The Future of JavaScript Tooling Vite+ - The Unified Toolchain for the Web Oxlint Linter Guide Oxlint Configuration Oxlint JS Plugins (Alpha) Oxlint Type-Aware Linting Oxfmt Beta announcement (2026-02-24) Migrate from Prettier - Oxc oxlint-migrate (GitHub) eslint-plugin-oxlint (GitHub)
動画
該当するコンテンツが見つかりませんでした







