플러그인 매니페스트

이 페이지

모든 샌드박스 플러그인은 package.json 옆에 emdash-plugin.jsonc를 가지고 있습니다. 이것은 수동으로 편집되며 플러그인의 아이덴티티, 신뢰 계약(capabilities, hosts, storage) 및 레지스트리가 표시하는 프로필 필드를 보유합니다. emdash-plugin init은 하나를 스캐폴딩하며, CLI는 build, dev, validate, bundlepublish를 위해 자동으로 ./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": "[email protected]" },

	// 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. 일반적으로 생략 — 아래 참조.

slugpublisher가 함께 패키지의 아이덴티티를 형성합니다. EmDash는 이들로부터 자동으로 패키지의 전체 식별자를 도출합니다.

versionpackage.json에 있습니다

빌드는 매니페스트의 versionpackage.json#version과 조정합니다:

  • 둘 다 설정되고 동일함 → 괜찮음.
  • 둘 다 설정되고 다름 → 하드 에러.
  • 하나만 설정됨 → 해당 값이 우선됨.
  • 둘 다 설정되지 않음 → 하드 에러.

npm 배포 플러그인의 권장 패턴은 매니페스트에서 version을 생략하고 package.json이 유일한 진실의 원천이 되도록 하는 것입니다(릴리스 도구가 이미 거기서 범프합니다). package.json이 없는 레지스트리 전용 플러그인은 매니페스트에 version을 설정해야 합니다 — 그것을 둘 다른 곳이 없습니다.

프로필

이들은 레지스트리 목록을 제공합니다. license, 저자(author 또는 authors) 및 보안 연락처(security 또는 securityContacts)가 필수이며, 나머지는 선택 사항입니다.

필드필수비고
licenseSPDX 표현식("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, allowedHostsstorage입니다. 세 가지 모두 기본적으로 비어 있으므로 추가 권한이 필요하지 않은 플러그인은 이들을 완전히 생략할 수 있습니다.

{
	"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:writectx를 통해 사이트 콘텐츠 읽기 / 변경.
media:read / media:write미디어 읽기 / 쓰기.
users:read사용자 레코드 읽기.
email:sendctx를 통해 이메일 전송.
network:requestctx.http를 통한 아웃바운드 HTTP, allowedHosts로 제한됨.
network:request:unrestricted모든 호스트로의 아웃바운드 HTTP. network:request 대신 사용됨.
hooks.email-transport:register이메일 전송 훅 등록.
hooks.email-events:register이메일 수명 주기 훅 등록.
hooks.page-fragments:registerpage:fragments 훅 등록(네이티브 전용).

CLI가 시행하는 두 가지 필드 간 규칙(에디터의 JSON-Schema 체크는 시행하지 않음 — emdash-plugin validate 실행):

  • network:request는 비어 있지 않은 allowedHosts필요로 합니다. 플러그인이 정말로 모든 호스트에 도달해야 하는 경우 대신 network:request:unrestricted를 사용하세요.
  • network:request:unrestrictedallowedHosts가 비어 있어야 합니다 — 제한되지 않은 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.tsadmin 경로도 제공해야 합니다 — 스키마는 이를 강제할 수 없습니다(경로 이름은 매니페스트가 아닌 소스에서 조사됩니다)만 런타임은 이를 확인합니다.

퍼블리셔 고정

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는 매니페스트를 완전히 건너뜁니다(기본 경로에 하나가 있으면 경고하여 퍼블리셔 핀 보안 스토리가 표시되도록 유지합니다).

다음