本文へスキップ
SheetForge

Web プラグインマーケット

Web アプリには、SheetForge のプラグインをブラウザーへインストールするためのプラグインマーケットがあり、それとは別に、GitHub の URL から未レビューのプラグインをサイドロードするための経路もあります。同じマーケットは、UIToolkit で作り直された形で、Unity の内部にも同梱されています。

レジストリ — 一つの静的ファイルを、二つの読み手が読む

マーケットの一覧は、単一の静的なレジストリファイル(public/registry/plugins.json)から得られます。これは、Web アプリと、Unity 内蔵のマーケットウィンドウの両方が読み取ります。リストは一つだけなので、二つのサーフェスは常に同じカタログを表示します。

SheetForge は、プラグインのバイナリを ホストしません。それを行うのは、各作者自身の GitHub リリース です。レジストリのエントリは、メタデータと固定されたハッシュであり、プラグインのコピーではありません。

ハッシュ固定 — コアが一バイトも見る前の整合性

すべてのレジストリエントリは、そのプラグインが承認されたときに記録された SHA-256 を持っています。取得時には、受け取ったすべてのバイトが、コアに届く前に、そのハッシュと照合されます。一バイトでも一致しなければ拒否されます。

これが、「バイナリが他人の GitHub 上にある」ことを安全にしている仕組みです: リリースはどこからでも再ダウンロードできますが、読み込まれるのは承認された正確なバイトだけです。

サーバープロキシ経由のワンクリックインストール

ブラウザーは GitHub のリリースアセットを直接取得できません——クロスオリジン(CORS)のルールがそれをブロックします。そのため、取得は サーバープロキシの経路(api/market/artifactlib/market/install.tsArtifactProxy を通じて配線されています)を通ります。これはサーバー側でリリースを取得し、それをストリーミングして返します。そのためインストールは ワンクリック で完了します。

プロキシがリリースに到達できない場合に備えて、手動でのダウンロード&アップロード の経路が、二次的なフォールバックとして残っています。これは まったく同じ ハッシュチェックを通過します——アップロードされたファイルも、プロキシ経由のファイルと同じだけしか信頼されません。

互換性ゲート — 整合性の後、登録の前

ハッシュチェックを通過することは、そのバイトが承認されたものであることを証明します。それは、このホストがそのプラグインの形式を読めるかどうかについては、何も語りません——それは第二の、別の問いです。

その答えは、検証済みの DLL 自体 から得られます: そのプラグインがどの世代のプラグインフォーマットに対してビルドされたか、そして要求する最低ホストバージョンを名指しする、アセンブリレベルの宣言です。

  • 一覧は広告であり、決定するのはアセンブリです。 レジストリのエントリは同じ二つの値(pluginFormatminHost)を持つため、カタログはダウンロード前にそれを表示できます。ゲート自体は、検証を通過したばかりのバイトから宣言を読み取ります。一覧の表示が古くなっていることはあっても、コンパイル済みの宣言が古くなることはありません。
  • 一つのゲートを、三つの経路が使います。 マーケットからのインストール、サイドロード、そして通常のローカルファイルは、すべて同じ述語を尋ねます。そのため、どの経路も、他の経路が拒否するものをこっそり受け入れることはできません。
  • アセンブリ単位で、全部か無かです。 拒否されたアセンブリは 何も 登録しません——契約の半分だけが登録されることは決してありません——そして、その拒否は、そのアセンブリが宣言した内容と、このホストが読み取った内容を名指しします。
  • 宣言がなくても問題ありません。 その属性が存在する前にビルドされたプラグインは、ホスト要件のない最も古い世代として読み取られるため、これまでどおりに読み込まれます。

キャッシュとアンロード

ハッシュチェックを通過したバイトは、ブラウザー(IndexedDB)にキャッシュされます。そのため、一覧で有効化されたプラグインは、以降の訪問では自動的に読み込まれます——有効化は一度だけで済みます。

プラグインの無効化や削除は 即座に 反映されます: アプリはコアに、そのアセンブリをプラグイン構成から外してセッションを組み直すよう指示するため、そのプラグインのセル型・enum・テンプレート・カラー プリセット・スタジオ アクション・キャンバスのオーバーレイは、リフレッシュなしで消えます。(.NET 自体はアセンブリをアンロードしません — バイトはページ内に残りますが、何もしません。同じプラグインを再び有効化すると、コアは二度目の読み込みをせず、残っているアセンブリを再度有効にします。)

GitHub URL から未レビューのプラグインをサイドロードする

キュレーションされたレジストリとは別に、任意の GitHub URL をアプリに渡して、未レビュー のプラグインをサイドロードすることができます(lib/market/sideload.tsapi/market/github によって提供されます)。これは、カタログにはまだないプラグインを試すためのものです。

この軸は、検証済みのレジストリエントリではなく ユーザーが渡す URL を受け取るため、SSRF 対策 を直接強制する唯一の場所になっています:

  • URL は GitHub 系のホスト——github.comraw.githubusercontent.comrelease-assets.githubusercontent.com など——に解決されなければならず、これは小文字化した上で厳密に照合されます。
  • 内部ネットワーク へ漏れ出してしまうようなリダイレクトは、その境界でブロックされます。

サイドロードされたアーティファクトは、別個の所有者タグ(sideload:)の下にキャッシュされます。そのため、たまたまレジストリのエントリとバイトを共有する未レビューのプラグインがあっても、それはキュレーション済みのものとは別に保たれます——サイドロードが、承認済みのプラグインになりすますことは決してありません。

インポート元としての GitHub

どちらの経路も、プラグインのバイトを同じパイプラインに通します:

  • レジストリからのインストール は、作者の GitHub リリースにホストされているアーティファクトを、サーバープロキシ経由で取得し、固定された SHA-256 と照合します。
  • サイドロード は、生の GitHub URL を受け取り、GitHub 系のホストに限定した上で、同じ方法でバイトを照合します。

どちらの場合も、GitHub のリリースアセットに対するブラウザーの CORS 制限はサーバー側で処理され、整合性は、コアが何かを読み込む前に、クライアント側のハッシュチェックによって保たれます。

Unity 内のマーケット

Unity のプラグインマーケットは、Web のマーケットに似せて UIToolkit で作り直されました——詳細ペインの横にカードグリッドが並び、同じ 静的レジストリを読み取り、同じハッシュ不一致の拒否と、全面的な信頼を求めるインストール通知を備えています。

サインインと、ブラウザーに保持されるプラグイン一覧・プリセットは Web 専用のまま です。Unity のウィンドウは、カタログとインストールのためのサーフェスです。

関連ページ

  • SheetForge Web — このマーケットが存在するブラウザーアプリ
  • プラグイン作成 — マーケットのエントリが指すプラグインを構築する