プラグインの配布
プラグインを作成したら、それをインストールする人々に無条件の信頼を求めることなく、自分のマシンから配布できるようにする必要があります。ZeroClaw の配布の仕組みには、2 つの独立したレイヤーがあります。Ed25519 マニフェスト署名(誰がこれを公開したか)とレジストリインストール(どのように配布されるか)です。このページでは、crates/zeroclaw-plugins/src/signature.rs、src/plugin_registry.rs、および host.rs 内のインストールパスと照合しながら、両方について説明します。
署名
署名済み
署名は正規マニフェストのバイト列を対象とします。ホストはTOMLを解析し、ルートにあるsignatureとpublisher_keyのエントリだけを削除し、ドキュメントの残りの部分を保持して、末尾の空行を削除します(signature.rs内のcanonical_manifest_bytes)。これにより署名を自己埋め込み可能にします。つまり、これらのルートフィールドを含めずにマニフェストに署名してから追加し、検証時にはチェック前にそれらを削除します。
知っておくべき2つの結果:
.wasmコンポーネント自体は署名の対象ではありません。署名が証明するのはマニフェスト、つまり発行者が保証する名前、バージョン、機能、権限です。転送中のアーティファクトの整合性が重要な場合は、レジストリのsha256ダイジェスト(後述)と組み合わせてください。config_schema.properties.signatureのような名前を持つネストされたフィールドや、signature_algorithmのように同様のプレフィックスが付いたルートフィールドは、引き続き署名対象になります。保持されたコンテンツの再フォーマットや並べ替えを行うと、署名が無効になります。マニフェストを確定した後、最後に署名します。- したがって、
config_schema.properties.api_token.x-secretのような設定公開マーカーは、署名対象となるポリシーです。ツールまたはチャネルのプロパティを、公開設定への露出とスコープ付きsecrets.getアクセスの間で変更するには、再ビルドして再署名する必要があります。 - 以前のプレフィックスベースの正規化処理によって署名されたパッケージは、そうしたエッジケースのいずれか、または削除されたフィールドに付加された TOML の装飾に依存していた場合にのみ、再署名が必要です。通常のマニフェストでは、署名対象の内容は変わりません。
キーとプロセス
署名は、ホストが検証に使うのと同じ ring プリミティブを介して Ed25519 を使用します。署名は base64url(パディングなし)で、公開鍵は 16 進エンコードされます。このクレートは完全なツールチェーン(signature.rs)を公開しています。generate_signing_key は PKCS#8 鍵ペアとその 16 進公開鍵を生成し、sign_manifest は正規バイト列に対する base64url 署名を生成し、public_key_hex は保存された秘密鍵から公開鍵を復元します。現時点では署名用の CLI ラッパーはありません。パブリッシャーは、リリースパイプライン内の短い Rust ヘルパーからこれらの関数を呼び出します。
署名済みマニフェストには、追加の root フィールドが2つ含まれます。signature(base64url 値)と publisher_key(16進数の公開鍵)です。[config_schema] を含む最初のテーブルヘッダーより前に、両方を配置してください。テーブルヘッダーの後に追加すると、TOML の規則ではそれらはそのテーブルのメンバーとなり、ホストは署名なしのマニフェストとして認識します。
name = "my-plugin"
version = "0.1.0"
signature = "<base64url-signature>"
publisher_key = "<hex-public-key>"
[config_schema]
type = "object"
properties = {}
additionalProperties = false
あなたを信頼するオペレーターは、その 16 進数キーを plugins.security.trusted_publisher_keys リストに追加します:
zeroclaw config set plugins.security.signature_mode strict
zeroclaw config set plugins.security.trusted_publisher_keys ["<your-key-hex>"]
検証の動作
検証は検出時とインストール時の両方で実行されます(host.rs から enforce_signature_policy が呼び出されます)。検出時は失敗したプラグインをスキップしてログに記録し、インストール時はエラーを返します。オペレーター側から見たモードマトリックスは次のとおりです。
| モード | 符号なし | 署名済み、キーは信頼されていません | 署名済み、署名が無効 | 署名済み・信頼済み |
|---|---|---|---|---|
disabled | ロード | ロードされますが、チェックされません | ロードされますが、チェックされません | ロードされますが、チェックされません |
permissive | 警告付きで読み込み | 警告付きで読み込み | 警告付きで読み込み | 読み込み済み、検証済み |
strict | 却下されました | 却下されました | 却下されました | ロード |
パブリッシャーとしてのあなたにとって strict が何を意味するかに注意してください: strict モードのオペレーターは、あなたの正確なキーが信頼セットにあり かつ マニフェストのバイトが検証される場合にのみ、あなたのプラグインを読み込みます。署名後のマニフェストの編集は、あなたによるものであれ配布経路上の誰かによるものであれ、インストールを壊します。それがポイントです。
レジストリの公開
インストールパスはローカルのプラグインディレクトリです。レジストリはコマンド実行時(zeroclaw plugin search / install)に参照される JSON インデックスにすぎません。どちらのコマンドも、プラグインホストがコンパイルされたバイナリにのみ存在します(build features を参照)。ビルド済みのリリースバイナリにはこれが含まれていません。デフォルトのインデックスは zeroclaw-labs/zeroclaw-plugins リポジトリの registry.json です。プライベートレジストリは URL を指定するだけで利用できます(コマンドごとの --registry <url>、または ZEROCLAW_PLUGIN_REGISTRY_URL 環境変数で、src/plugin_registry.rs の registry_url に従いこの順序で解決されます)。
レジストリエントリ(crates/zeroclaw-plugins/src/registry.rs の PluginRegistryEntry)は次を保持します: name、version、オプションの description と author、capabilities、アーカイブの url、および zip のオプションの sha256 ダイジェスト。
アーカイブコントラクト
zeroclaw plugin install <name> はエントリを解決し、zip をダウンロードし、ダイジェストが存在する場合は検証し、安全に展開して、抽出したディレクトリをローカルインストールが使用するのと同じ PluginHost::install パスに渡します。抽出は設計上防御的であり(src/plugin_registry.rs)、アーカイブはそれに耐えられる必要があります。
- zip にはルートレベルの
manifest.toml、またはそれを含むネストされたプラグインディレクトリがちょうど1つ含まれている必要があります。マニフェストが0個、または2個以上ある場合、アーカイブは拒否されます。 - パストラバーサル、絶対パス、または Windows ドライブ接頭辞を含むエントリ名は拒否されます。
- ダウンロードはストリーミング中に (50 MiB) に制限されているため、
Content-Lengthを送信しないサーバーが無制限のバッファリングを強制することはできません。展開も同じ上限に制限されているため、zip 爆弾が無制限に展開することはできません。
バージョン解決: インストーラーがベア名を受け取ると、インデックス内の最後に一致するエントリを選択します。ピン留めされた name@version は、正確にそのバージョンを選択します。レジストリ内で重複する名前は意図的に、古いものから順に並べてください。
検索は信頼境界ではありません
zeroclaw plugin search はインデックスに対する認証不要の検索であり、何かをインストール・有効化・実行することは一切ありません。セキュリティが機能するのはインストール時です。ダイジェスト検証、安全な展開、マニフェスト検証、そしてオペレーターの署名ポリシーが、ローカルパスからのインストールと同一に適用されます。それを踏まえて公開してください。インストール前のすべては信頼できない転送とみなしてください。
パブリッシャーのチェックリスト
[!IMPORTANT] コンパイル済みの
.wasmおよび.cwasmファイルはバイナリ成果物であり、多くの場合それぞれ数メガバイトになります。Git LFS を使わずに Git のソースツリーへコミットしないでください。リビルドのたびに素のブロブとしてコミットされると、リポジトリの履歴が永久的に肥大化し、git diffやレビューツールがそれらの処理でつまずきます。これらは他のビルド出力と同様に扱ってください。target/と*.wasm/*.cwasmを.gitignoreに追加し、代わりにリリース成果物やプラグインレジストリのアーカイブを通じて配布してください。どうしても成果物をツリー内に置く必要がある場合は、最初のコミットの前に LFS でパターンを追跡してください(git lfs track "*.wasm")。
- マニフェストを確定する: 名前、バージョン、機能、およびコードが使用する最小限の権限セット。
- コンポーネントをビルドする。スキルバンドルの場合は、すべての
SKILL.mdでフロントマターを検証する(discovery はnameとdescriptionを強制する)。 - 署名: Ed25519 キーの生成または読み込みを行い、正規化されたマニフェストのバイト列に署名し、
signatureとpublisher_keyを埋め込みます。 - プラグインディレクトリを zip 圧縮します(マニフェストは 1 つ、パストリックなし、50 MiB 未満)。
- ZIP の SHA-256 を計算し、ダイジェスト付きでレジストリエントリを公開します。
- 公開鍵の16進値を、オペレーターがレジストリとは独立して検証できる場所(自分のリポジトリやサイトなど)に公開してください。
strictモードのオペレーターが信頼するのは、レジストリではなく鍵そのものです。 - リリースのたびに:
versionをバンプし、再署名し(バージョン行はカノニカルバイト内にある)、再ダイジェストし、新しいエントリを古いエントリの後に追加する。