WASM 플러그인
기능 게이팅된 WASM 플러그인 시스템: 매니페스트, 기능 선언, 권한, 서명 검증.
Revka는 WebAssembly 플러그인을 로드하여 런타임을 커스텀 도구, 채널, 메모리 백엔드, 옵저버 훅으로 확장할 수 있습니다. 각 플러그인은 manifest.toml과 .wasm 모듈을 포함하는 디렉터리입니다. 호스트는 로컬 디스크에서 플러그인을 탐색하고, 선택적으로 매니페스트의 Ed25519 서명을 검증한 뒤, 로드된 플러그인 목록을 CLI와 게이트웨이 API를 통해 노출합니다.
이 서브시스템 전체는 plugins-wasm Cargo 기능 플래그로 컴파일 시점에 게이팅됩니다. 표준 Revka 빌드에는 포함되지 않으므로, revka plugin CLI 서브커맨드와 GET /api/plugins 엔드포인트는 해당 기능을 포함하여 빌드된 바이너리에서만 존재합니다. 커스텀 WASM 확장을 개발하거나, 배포용으로 패키징하거나, 운영자가 로드할 플러그인을 제한하려는 경우에 이 페이지를 참고하세요.
기능 활성화
섹션 제목: “기능 활성화”플러그인 시스템은 두 가지 조건을 모두 충족해야 합니다.
-
빌드 게이트 — Revka를 해당 기능과 함께 컴파일해야 합니다.
Terminal window cargo build --release --features plugins-wasmplugins-wasm은full기능 세트에 포함되므로,--features full빌드에도 포함됩니다. -
설정 게이트 —
config.toml에서 시스템을 활성화해야 합니다.[plugins]enabled = true
기능이 컴파일에서 제외된 경우, CLI 서브커맨드와 API 라우트가 아예 존재하지 않습니다. 기능이 포함되어 있지만 [plugins] enabled = false인 경우, API는 plugins_enabled: false와 빈 플러그인 목록을 반환하며 플러그인 도구는 등록되지 않습니다.
전체 기능 매트릭스는 Cargo 기능 플래그 & ADR을, config.toml 로드 방식은 설정 개요를 참고하세요.
모든 플러그인 설정은 [plugins] 아래에 위치하며, 서명 정책은 [plugins.security]에 중첩됩니다.
[plugins]enabled = true # 마스터 스위치 (기본값: false)plugins_dir = "~/.revka/plugins" # 플러그인 위치 (기본값 표시)auto_discover = false # 시작 시 자동 탐색 (기본값: false)max_plugins = 50 # 최대 플러그인 수 (기본값: 50)
[plugins.security]signature_mode = "disabled" # "disabled" | "permissive" | "strict" (기본값: "disabled")trusted_publisher_keys = [] # 16진수 인코딩된 Ed25519 퍼블리셔 공개 키 목록| 키 | 타입 | 기본값 | 의미 |
|---|---|---|---|
plugins.enabled | bool | false | 플러그인 시스템의 마스터 스위치입니다. |
plugins.plugins_dir | string | ~/.revka/plugins | 플러그인 서브 디렉터리가 위치하는 디렉터리입니다. 앞의 ~/는 홈 디렉터리로 확장됩니다. |
plugins.auto_discover | bool | false | 시작 시 플러그인을 자동으로 탐색하고 로드합니다. |
plugins.max_plugins | usize | 50 | 로드할 수 있는 최대 플러그인 수입니다. |
plugins.security.signature_mode | string | "disabled" | 서명되지 않았거나 검증할 수 없는 플러그인을 처리하는 방식입니다. 서명 모드를 참고하세요. |
plugins.security.trusted_publisher_keys | string[] | [] | 신뢰하는 퍼블리셔의 16진수 인코딩된 Ed25519 공개 키 목록입니다. |
플러그인 레이아웃
섹션 제목: “플러그인 레이아웃”각 플러그인은 plugins_dir 아래에 별도의 디렉터리로 존재합니다. 호스트는 해당 디렉터리를 스캔하여 manifest.toml이 포함된 서브 디렉터리를 플러그인 후보로 처리합니다.
~/.revka/plugins/└── my-plugin/ ├── manifest.toml # 필수 └── plugin.wasm # 컴파일된 모듈 (manifest.wasm_path에서 지정한 경로)디스크의 플러그인 디렉터리 이름이 매니페스트의 name과 일치할 필요는 없지만, CLI를 통해 설치할 경우 호스트는 manifest.name을 딴 디렉터리로 플러그인을 복사합니다.
매니페스트 (manifest.toml)
섹션 제목: “매니페스트 (manifest.toml)”매니페스트는 호스트의 PluginManifest로 역직렬화되는 TOML 파일입니다. name, version, wasm_path, capabilities는 필수이며, 나머지는 선택 사항입니다.
name = "my-plugin"version = "0.1.0"description = "What this plugin does"author = "Acme Corp"wasm_path = "plugin.wasm" # .wasm 경로, 이 매니페스트 기준 상대 경로capabilities = ["tool"] # tool, channel, memory, observer 중 하나 이상permissions = ["http_client", "file_read"]
# 선택 사항 — 서명된 플러그인에만 존재:signature = "<base64url Ed25519 signature>"publisher_key = "<hex Ed25519 public key>"| 필드 | 타입 | 필수 여부 | 의미 |
|---|---|---|---|
name | string | 예 | 고유한 플러그인 식별자입니다. |
version | string | 예 | 플러그인 버전 문자열입니다. |
description | string | 아니오 | 사람이 읽을 수 있는 설명입니다. |
author | string | 아니오 | 작성자 이름 또는 조직명입니다. |
wasm_path | string | 예 | 매니페스트 기준 .wasm 파일의 상대 경로입니다. |
capabilities | string[] | 예 | 플러그인이 제공하는 기능입니다 (아래 참고). |
permissions | string[] | 아니오 | 플러그인이 요청하는 호스트 기능입니다 (아래 참고). 기본값은 빈 목록입니다. |
signature | string | 아니오 | 정규화된 매니페스트에 대한 Base64url 인코딩된 Ed25519 서명입니다. |
publisher_key | string | 아니오 | 서명자의 16진수 인코딩된 Ed25519 공개 키입니다. |
기능 선언
섹션 제목: “기능 선언”capabilities는 플러그인의 확장 유형을 선언합니다. 값은 snake_case로 직렬화됩니다.
| 기능 | 의미 |
|---|---|
tool | 하나 이상의 호출 가능한 도구를 제공합니다. |
channel | 메시징 채널 구현을 제공합니다. |
memory | 메모리 백엔드를 제공합니다. |
observer | 옵저버 / 메트릭 백엔드를 제공합니다. |
플러그인은 하나 이상의 기능을 선언할 수 있습니다. 현재 호스트는 tool 기능을 가진 플러그인만 에이전트의 도구 레지스트리에 연결합니다 — 플러그인 도구를 참고하세요.
permissions는 플러그인이 요청하는 호스트 기능의 집합입니다. 매니페스트에서 보조적인 메타데이터로 기록 및 보고되며, 값은 snake_case로 직렬화됩니다.
| 권한 | 부여 내용 |
|---|---|
http_client | HTTP 요청을 수행합니다. |
file_read | 파일 시스템에서 읽습니다 (샌드박스 내). |
file_write | 파일 시스템에 씁니다 (샌드박스 내). |
env_read | 환경 변수를 읽습니다. |
memory_read | 에이전트 메모리를 읽습니다. |
memory_write | 에이전트 메모리에 씁니다. |
플러그인 도구
섹션 제목: “플러그인 도구”[plugins] enabled = true인 경우, 런타임은 plugins_dir에 대한 플러그인 호스트를 구성하고, tool 기능을 가진 모든 플러그인을 에이전트 레지스트리의 도구로 등록합니다. 도구 이름은 플러그인의 manifest.name이며, 설명은 매니페스트의 description에서 가져옵니다.
현재 등록된 각 플러그인 도구는 다음의 고정된 단일 파라미터 스키마를 노출합니다.
{ "type": "object", "properties": { "input": { "type": "string", "description": "Input for the plugin" } }, "required": ["input"]}서명 검증
섹션 제목: “서명 검증”플러그인 매니페스트는 Ed25519로 서명할 수 있습니다. 서명 대상은 정규화된 매니페스트 — signature와 publisher_key 줄을 제거한 TOML 내용 — 이므로, 플러그인은 서명하는 파일 안에 자신의 서명을 포함할 수 있습니다. 다른 필드를 편집하면 서명이 무효화됩니다.
signature_mode는 서명되지 않았거나 검증할 수 없는 플러그인을 호스트가 처리하는 방식을 제어합니다.
| 모드 | 동작 |
|---|---|
disabled | 기본값. 서명 검사를 하지 않습니다. 탐색된 모든 플러그인이 로드됩니다. |
permissive | 가능한 경우 검증합니다. 서명 없음, 미신뢰, 또는 유효하지 않은 플러그인은 경고를 기록하지만 여전히 로드됩니다. |
strict | 서명되지 않은 플러그인, trusted_publisher_keys에 없는 키로 서명된 플러그인, 서명 검증에 실패한 플러그인을 거부합니다. |
검증은 두 단계로 이루어집니다. 먼저 매니페스트의 publisher_key가 trusted_publisher_keys에 존재해야 합니다 (대소문자 구분 없는 16진수 비교) — 그렇지 않으면 플러그인은 미신뢰 상태가 됩니다. 그런 다음 정규화된 매니페스트 바이트에 대해 Ed25519 서명을 검증합니다. strict 모드에서는 미신뢰 퍼블리셔, 유효하지 않은 서명, 또는 서명 누락 모두 탐색 중 해당 플러그인을 건너뛰게 합니다.
잠긴 호스트를 운영하려면 플러그인에 서명하고 키를 고정하세요.
[plugins.security]signature_mode = "strict"trusted_publisher_keys = [ "a1b2c3d4e5f6...your-publisher-public-key-hex...",]이 내용이 Revka의 전반적인 신뢰 모델에서 어떤 위치를 차지하는지는 보안 모델을 참고하세요.
CLI에서 플러그인 관리
섹션 제목: “CLI에서 플러그인 관리”plugins-wasm 빌드에서 revka plugin 서브커맨드는 플러그인 디렉터리를 관리합니다.
revka plugin list설치된 각 플러그인을 name vX.Y.Z — description 형식으로 출력하거나, No plugins installed.를 출력합니다.
revka plugin install /path/to/plugin-dir소스(디렉터리 또는 매니페스트 경로)에서 manifest.toml을 읽고, 설정된 서명 정책을 적용한 뒤, 매니페스트와 .wasm을 manifest.name을 딴 디렉터리로 plugins_dir 아래에 복사합니다. 매니페스트나 .wasm이 누락된 경우, 또는 같은 이름의 플러그인이 이미 로드된 경우 실패합니다.
revka plugin info my-plugin플러그인의 이름, 버전, 설명, 기능, 권한, 그리고 해석된 .wasm 경로를 출력합니다.
revka plugin remove my-plugin호스트에서 플러그인을 제거하고 plugins_dir 아래의 해당 디렉터리를 삭제합니다.
전역 플래그 및 환경 설정은 CLI 개요를 참고하세요.
API로 플러그인 목록 조회
섹션 제목: “API로 플러그인 목록 조회”게이트웨이는 대시보드에서 플러그인 상태를 표시할 수 있도록 로드된 플러그인 목록을 노출합니다. 이 라우트는 plugins-wasm 빌드에서만 존재합니다.
GET /api/plugins — Bearer 토큰이 필요합니다.
GET /api/pluginsAuthorization: Bearer rk_<token>응답:
{ "plugins_enabled": true, "plugins_dir": "~/.revka/plugins", "plugins": [ { "name": "my-plugin", "version": "0.1.0", "description": "What this plugin does", "capabilities": ["tool"], "loaded": true } ]}| 필드 | 의미 |
|---|---|
plugins_enabled | [plugins] enabled를 반영합니다. false인 경우 plugins는 항상 비어 있습니다. |
plugins_dir | 설정된 플러그인 디렉터리입니다 (미확장, 예: ~/.revka/plugins). |
plugins[].name / version / description | 매니페스트에서 가져옵니다. |
plugins[].capabilities | 매니페스트의 기능 목록입니다. |
plugins[].loaded | 해석된 .wasm 파일이 디스크에 존재하면 true입니다. |
기능이 활성화되어 있지만 플러그인 디렉터리가 존재하지 않는 경우, plugins는 빈 배열입니다. 이 엔드포인트는 페어링된 Bearer 토큰이 필요합니다 — 토큰 발급 방법은 페어링 및 인증을 참고하세요.