すべてのサンドボックス化されたプラグインは、package.json の隣に emdash-plugin.jsonc を持っています。これは手動で編集され、プラグインのアイデンティティ、トラストコントラクト(capabilities、hosts、storage)、およびレジストリが表示するプロフィールフィールドを保持します。emdash-plugin init がスキャフォールドを作成し、CLI は build、dev、validate、bundle、publish のために自動的に ./emdash-plugin.jsonc を読み取ります。
ファイルは JSONC です:コメントと末尾のカンマが許可されています。
以下の例は、画像ギャラリープラグインの完全なマニフェストを示しています:
{
"$schema": "./node_modules/@emdash-cms/plugin-cli/schemas/emdash-plugin.schema.json",
"slug": "gallery",
"publisher": "did:plc:abc123def456",
"license": "MIT",
"author": { "name": "Jane Doe", "url": "https://example.com" },
"security": { "email": "security@example.com" },
// Optional profile
"name": "Gallery",
"description": "Image gallery block for EmDash.",
"keywords": ["gallery", "images"],
"repo": "https://github.com/example/plugin-gallery",
// Trust contract
"capabilities": ["content:read"],
"allowedHosts": [],
"storage": {}
}
アイデンティティ
| フィールド | 必須 | 備考 |
|---|---|---|
slug | はい | パブリッシャーの名前空間内の URL セーフな ID。/^[a-z][a-z0-9_-]*$/、最大 64 文字。 |
publisher | はい | あなたの Atmosphere アカウントの DID またはハンドル。パブリッシャーピンニングを参照。 |
version | いいえ | ビルドメタデータなしの Semver 2.0。通常は省略します — 以下を参照。 |
slug と publisher が一緒になってパッケージのアイデンティティを形成します。EmDash はそれらから自動的にパッケージの完全な識別子を導出します。
version は package.json に存在します
ビルドはマニフェストの version を package.json#version と照合します:
- 両方が設定され等しい → 問題なし。
- 両方が設定され異なる → ハードエラー。
- 一方が設定されている → その値が優先されます。
- どちらも設定されていない → ハードエラー。
npm 配布プラグインの推奨パターンは、マニフェストから version を省略し、package.json を唯一の真実の源とすることです(リリースツールがそこですでにバンプしています)。package.json のないレジストリのみのプラグインは、マニフェストに version を設定する必要があります — それを置く他の場所がありません。
プロフィール
これらはレジストリリストにフィードします。license、著者(author または authors)、およびセキュリティ連絡先(security または securityContacts)は必須です。残りはオプションです。
| フィールド | 必須 | 備考 |
|---|---|---|
license | はい | SPDX 式("MIT"、"Apache-2.0"、"MIT OR Apache-2.0")。最初の公開時に使用されます。後続の公開では既存のプロフィールが優先されます。 |
author / authors | はい | どちらか一方。単一の著者の場合は author: { name, url?, email? }、複数の場合は authors: [...](≤ 32)。両方を設定するとエラーになります。 |
security / securityContacts | はい | どちらか一方。各連絡先には少なくとも email または url が必要です。複数の場合は securityContacts: [...](≤ 8)。両方を設定するとエラーになります。 |
name | いいえ | 表示名。デフォルトは slug です。 |
description | いいえ | 短く保つ(約 140 文字)。長い値はリストで切り捨てられる可能性があります。 |
keywords | いいえ | ≤ 5 エントリ。 |
repo | いいえ | ソースリポジトリの https:// URL。 |
本当に複数ない限り、単数形の author / security を使用してください — これが一般的なケースであり、スキャフォールドがそれを出力します。
トラストコントラクト
トラストコントラクトは capabilities、allowedHosts、および storage です。3つすべてがデフォルトで空なので、追加の特権を必要としないプラグインはそれらを完全に省略できます。
{
"capabilities": ["network:request", "content:read"],
"allowedHosts": ["api.example.com", "*.cdn.example.com"],
"storage": {
"events": { "indexes": ["timestamp"] },
"submissions": { "indexes": ["email"], "uniqueIndexes": ["token"] }
}
}
Capabilities
認識される名前:
| Capability | 付与 |
|---|---|
content:read / content:write | ctx を介してサイトコンテンツを読み取り/変更。 |
media:read / media:write | メディアを読み取り/書き込み。 |
users:read | ユーザーレコードを読み取り。 |
email:send | ctx を介してメールを送信。 |
network:request | ctx.http を介したアウトバウンド HTTP、allowedHosts に制限。 |
network:request:unrestricted | 任意のホストへのアウトバウンド HTTP。network:request の代わりに使用。 |
hooks.email-transport:register | メールトランスポートフックを登録。 |
hooks.email-events:register | メールライフサイクルフックを登録。 |
hooks.page-fragments:register | page:fragments フックを登録(ネイティブのみ)。 |
CLI が強制する2つのクロスフィールドルール(エディタの JSON-Schema チェックは行いません — emdash-plugin validate を実行してください):
network:requestは空でないallowedHostsを必要とします。プラグインが本当に任意のホストに到達する必要がある場合は、代わりにnetwork:request:unrestrictedを使用してください。network:request:unrestrictedはallowedHostsが空であることを必要とします — 制限のない capability はすでにすべてのホストを許可しているため、リストはそれと矛盾します。
ホストパターンは素のホスト名です(スキーム、パス、または空白なし)。先頭の *. はサブドメインを許可します:*.cdn.example.com。
Storage
コレクション名 → インデックス設定のマップ。コレクション名は同じ /^[a-z][a-z0-9_]*$/ ルールに従います(ランタイムは名前を SQL テーブルサフィックスとして使用します)。インデックスはフィールド名または複合配列です。uniqueIndexes もクエリ可能です — indexes にもリストしないでください。
"storage": {
"events": { "indexes": ["timestamp", ["collection", "timestamp"]] }
}
管理画面
オプション。サンドボックス化されたプラグインは、Block Kit を通じて管理ページとダッシュボードウィジェットをレンダリングします。マニフェストは、それらが表示される場所のみを宣言します。プラグインに管理 UI がない場合は、admin キーを完全に省略してください。
"admin": {
"pages": [{ "path": "/gallery", "label": "Gallery", "icon": "image" }],
"widgets": [{ "id": "recent-uploads", "title": "Recent uploads", "size": "half" }]
}
admin.pages または admin.widgets を宣言するプラグインは、Block Kit コンテンツをレンダリングする src/plugin.ts の admin ルートも提供する必要があります — スキーマはそれを強制できません(ルート名はマニフェストからではなくソースから調査されます)が、ランタイムはそれをチェックします。
パブリッシャーピンニング
publisher は公開アイデンティティをピンするので、誤って間違ったアカウントでプラグインを公開することはできません。
最初の公開が成功すると、マニフェストの publisher がアクティブなセッションと一致する場合、それは書かれたままになります。emdash-plugin init でスキャフォールドを作成して空白のままにした場合、CLI はアクティブなセッションの DID をマニフェストに書き戻します。
以下の例は、CLI が書き込む行を示しており、読みやすさのために解決されたハンドルがコメントとして追加されています:
"publisher": "did:plc:abc123def456", // jane.example.com
後続のすべての公開で、CLI はアクティブなセッションとピンされた publisher を DID に解決して比較します。不一致は MANIFEST_PUBLISHER_MISMATCH で即座に失敗します — オーバーライドフラグはありません。意図的に解決してください:
- 間違ったセッション:
emdash-plugin switch <did>、次に再度公開します。 - 本当に新しいパブリッシャーにプラグインを譲渡する場合:マニフェストの
publisherを編集します。
公開せずに検証
emdash-plugin validate # ./emdash-plugin.jsonc
emdash-plugin validate path/ # 特定のディレクトリ
クロスフィールドルールを含む、tsc スタイルの file:line:column 診断によるオフラインスキーマチェック。プリコミットフックまたは CI ステップに適しています。重複キーと不明なキーはエラーです(厳格モードは "licens" のタイプミスをキャッチします)。
CLI フラグは依然として優先されます
明示的なフラグ(--license、--author-name、…)は、両方が設定されている場合にマニフェスト値をオーバーライドします — CI オーバーライドに便利です。--no-manifest はマニフェストを完全にスキップします(デフォルトパスに存在する場合は警告するため、パブリッシャーピンのセキュリティストーリーが見えたままになります)。