ルール:

  • マークダウン構造を保護する。
  • URLやコードを翻訳しない。
  • 翻訳された内容のみを返す。

MoeKoe Music 插件エコシステムを最初に作成した時、オンラインプラグイン市場という機能はまだありませんでした
後にコミュニティの提案により、このプラグイン市場が誕生しました 公式/コミュニティプラグインリポジトリを追加して製品機能を拡張

プラグインはコミュニティで開発されるので、プラグイン市場はどう管理すべきか?

最も直接的な方法は、すべてのプラグインソースコードを一つの大リポジトリにまとめることです。しかし、この案は考えれば考えるほど不自然に感じられました。それぞれのプラグインには、それぞれの作者、それぞれのリリースリズム、それぞれのビルド方法があります。これらをすべて公式リポジトリにまとめると、メンテナンスコストが高くなるだけでなく、責任範囲も曖昧になります。

したがって、このリポジトリは最終的には「プラグインソースコードリポジトリ」として設計されず、代わりに「プラグイン登録とインデックスリポジトリ」となりました。それは以下の数点を行います:

  • プラグインの上架、更新、下架、および報告の申請を受け取る
  • 基本的な検証と静的認識を自動的に行う
  • 人工的に承認されたプラグインのスナップショットを記録する
  • クライアントが読み込める plugins.json を維持する
  • READMEにプラグインリストを更新する、人々が読みやすくする

追跡可能な登記簿:誰が提出したか、どのバージョンが承認されたか、ダウンロード先はどこか、ネットワークやファイルの権限はどうか、すべて明確なデータにまとめられます。

市場インデックス、ソースコードリポジトリではなく

リポジトリのルートディレクトリで最も重要なファイルは plugins.json です。これがプラグイン市場が実際に消費するデータソースです。

{
  "id": "custom-app-background",
  "name": "カスタム背景画像",
  "description": "MoeKoe Musicにカスタム背景画像機能を提供し、透明度調節をサポート。",
  "iconUrl": "...",
  "version": "1.0.0",
  "minversion": "1.6.1",
  "...":"....",
  "buildRequired": false,
  "networkAccess": false,
  "fileAccess": false,
  "binaryContent": false,
  "snapshot": {
    "iconUrl": "...",
    "repository": "MoeKoeMusic/custom-app-background-plugin",
    "commitSha": "dbf72d38c8cf6b1d1cefdf8ce15798d565678995",
    "downloadUrl": "hxx.zip",
    "release": null
  }
}

私は市場が「プラグインリポジトリの「現在の最新コード」を常に記録するようにしないことを望んでいます。なぜなら、作者が今日提出したコードと、承認当日に見たコードが同じものではなかったかもしれないからです。プラグイン市場が本当に認めるべきは、承認されたバージョンです。

したがって、このプロジェクトには以下の核心原則があります:

上架されるのは、動き回るリポジトリのアドレスではなく、既にロックされたスナップショットです。

コンパイル不要のプラグインの場合、スナップショットはデフォルトブランチの当時のcommitにロックされます。コンパイルが必要なプラグインの場合、スナップショットは対応するReleaseタグと发行附件にロックされます。これにより、実際に問題が発生した場合でも、当時どのバージョンが承認されたかを振り返ることができます。

アクションが先に動く、人間が最後に決定する

ユーザーがIssueを提出する際には、以下の選択を行う必要があります:

  • 「新規上架」または「プラグインの更新」
  • GitHubリポジトリのアドレス
  • インストール前にコンパイルが必要かどうか

Actionが自動検証を行い、結果をIssueのコメントに書き込むと同時に、check-passedまたはcheck-failedタグをIssueに付ける。

自動化が事実を整理し、人間が最終的な判断を行います:

  1. ユーザーがIssueテンプレートを使用してプラグインを提出
  2. ActionがIssueフォームを解析
  3. リポジトリ、manifest、バージョン、作者の権限を検証
  4. プラグインのスナップショットをロック
  5. 検証結果を自動的にコメント
  6. メンテナンス者が確認
  7. メンテナンス者がClose as completedでIssueを閉じる
  8. 另一つのActionが検証結果を読み取り、plugins.jsonとREADME.mdの更新を生成するPR
  9. PRが合併されると、プラグインが正式に市場インデックスに入ります

ここで「閉じる方法」も利用されています。IssueがClose as not plannedの場合、インポートスクリプトは実行されません。つまり、GitHubの原生的なIssueステータスが審査ボタンとして利用されています。

スナップショットメカニズム

ユーザーが「インストール前にコンパイル不要」と言った場合:

  • リポジトリのデフォルトブランチを読み取る
  • 現在のcommit shaを取得
  • このcommit shaを使用してmanifest.jsonを読み取る
  • 固定のcommitのソースコードzipのURLを生成
  • zipをダウンロードし、解凍後、権限スキャンを行う
  • repository-treeタイプのスナップショットを生成

ユーザーが「コンパイルが必要」と言った場合:

  • 最新の利用可能なReleaseを取得
  • Releaseの最初の附件を取得
  • 発行附件をダウンロード
  • 附件を解凍し、manifest.jsonを読み取る
  • release-assetタイプのスナップショットを生成

この二つのパスは同じ問題を解決しています:プラグインのソースがどのように公開されても、最終的には検証可能、ダウンロード可能、追跡可能なスナップショットを取得し、最新のリポジトリの変動によりユーザーがダウンロードしたプラグインが承認時のものとは異なることがないようにします。

権限認識

セキュリティ検証は、単にスクリプトが頭で考えるだけでは不十分です。しかし、スクリプトはまず、メンテナンス者がどの点に注意を払うべきかをリスクポイントとして示すことができます:

  • manifestにどのような権限が宣言されているか
  • ソースコードや发行パッケージに典型的なAPIや実行ファイルが含まれているか

それは「リスクがある」という単なる言葉を提供するだけでなく、その能力がなぜ判断されたかを示します。例えば:

  • manifestにネットワークアクセスが宣言されている
  • ソースコードにfetchを使用している
  • .exe、.dll、.nodeなどの実行可能ファイルが見つかった
  • ソースコードにlocalStorageやindexedDBを使用している

これは完璧なセキュリティスキャンではありません。漏れがあるかもしれませんし、誤報も発生するかもしれません。しかし、その位置付けは、メンテナンス者が最も注意を払うべきポイントを事前に示すことです。それは「判事」としてではなく、「マーカー」のように働きます。

スナップショットデータの隠蔽

検証が完了すると、Issueにコメントを書き込みます。コメントには、人間が読める検証結果の他に、隠されたpayloadも含まれます。

以下のようなHTMLコメントが生成されます:

<!-- plugin-publish-snapshot:base64... -->

このデザインは非常に巧妙です。なぜなら、GitHub Actionsの異なるワークフロー間では常にメモリが共有されていないからです。上架検証はIssueが作成されたり編集されたりしたときに行われますが、実際にインポートされるのはIssueが閉じられたときです。その間には数時間から数日が経過するかもしれません。

それでは、閉じたときに当初の検証がどのスナップショットが承認されたかをどうやって知るのでしょうか?

答えは、Issueのコメントから読み取ることです。これにより、Issueのコメントは単なる「提示情報」だけでなく、軽量な審査記録としても機能します。これは別のデータベースやサービスを必要とせず、直接GitHubの記録能力を利用しています。

入庫アクション

実際にplugins.jsonに書き込むスクリプトはscripts/publish-plugin-close.jsです。

以下の数つの「門」を行います:

  • 現在のイベントがpublishクラスのIssueであること
  • Issueがstate_reason === 'completed'であること
  • Issueを閉じたユーザーがリポジトリのメンテナンス者であること
  • 検証コメントのpayloadがcheck-passedであること
  • payloadがロックされたdownloadUrlを持っていること

これらの「門」は、普通のユーザーがIssueを閉じたり、プロセスを偽造してプラグインを市場に書き込むことができないことを保証します。

ここに一つの詳細な点があります:プラグインの更新時には、元の作者を保持し、他の人が更新Issueを提出しても作者フィールドが変更されません。また、更新は元の作者本人によって提出され、リポジトリのアドレスも既存の記録と一致する必要があります。

新しいまたは更新されたプラグインはリストの最前面に配置されます。この選択はプラグイン市場の直感に合っています:最新の承認された内容が前面に配置され、ユーザーとメンテナンス者が最近の変更を簡単に見つけることができます。

最後に、現在のplugins.jsonを使用してMarkdownテーブルを生成し、READMEにプラグインリストを置き換えます。

下架と報告

そのプロセスは上架と非常に似ています:

  1. ユーザーが下架または報告のIssueを作成
  2. plugin-moderation-validate.jsがプラグインが存在するかを検証
  3. 作者が自発的に下架する場合、提出者が作者であるかを検証
  4. メンテナンス者が人工的に検証
  5. メンテナンス者がClose as completedでIssueを閉じる
  6. plugin-moderation-close.jsがプラグインの状態をdelistedに変更
  7. PRが自動的に生成され、plugins.jsonとREADMEの更新が行われます

AI検証

プロジェクトにはpublish-plugin-ai-audit.jsというものもあり、プラグインのスナップショットに対してAI静的検証を行います。

このスクリプトの考え方は以下の通りです:

  • 同じスナップショットをダウンロード
  • 最多24個の候補ファイルを選択
  • まずmanifest.json、package.json、エントリーファイル、ネットワーク/ファイル/ストレージ関連のファイルを優先
  • 内容をAIインターフェースに送信
  • 固定のJSONを返すように要求
  • 検証結果をIssueのコメントに書き込む

ここで良いと思うのは、AI検証が「最終的な判決」として設計されていないことです。それは単にメンテナンス者が参考にするものに過ぎません。

これにより、「AIが安全と言ったので自動的に上架」という方法よりも信頼性が高いです。

データベースやバックエンドサービスを使わない理由

このプロジェクトで最も面白いのは、実際にコードがどれほど複雑でないことよりも、できるだけ追加システムを導入しないことです。

GitHubが提供するものをできるだけ完全に利用しています:

  • Issue Formを申請フォームとして
  • Issueのコメントを審査フィードバックとスナップショット記録として
  • Labelを自動検証状態として
  • Close reasonを人工審査信号として
  • Pull Requestをデータ変更エントリとして
  • plugins.jsonを市場インデックスとして
  • READMEを公开展示ページとして
  • Gitの履歴を監査ログとして

したがって、バックエンドが不要で、データベースも必要なく、管理パネルも別に作成する必要はありません。オープンソース音楽プレイヤーのプラグイン市場にとって、この複雑さはちょうど良いものです。

ps: GitHub Actionsは本当に便利です、私の以前の阿珏のブログの国際化の道もそうでした。

結び

このプロジェクトを見直すと、それは「重いアーキテクチャ」のプラグインプラットフォームではありません。むしろ、それぞれのステップが追跡可能な登記システムのように見えます。

ユーザーがIssueを提出し、Actionが自動的にチェックし、メンテナンス者が人工的に確認し、PRが合併されるまで、すべての重要なアクションがGitHub上に残ります。すべての市場データがplugins.jsonに記録されます。問題が発生した場合には検索可能で、更新がある場合には記録が残り、下架がある場合には歴史が消えません。

それは完全なバックエンドを作成しようとせずに、プラグイン市場の最も核心の信頼連鎖を構築することを目指しています。

コミュニティプラグインエコシステムが本当に必要とする第一歩は、美しいページよりも、みんなが理解し、信頼し、振り返り、改善できるプロセスであるかもしれません。

このリポジトリMoeKoeMusic-Pluginsがそのように作成されました。

プラグイン市場のウェブ版

もちろん、これらは一歩一歩更新と改善して現在の結果に至りました。