MINARA
Minara 사용하기클라이언트 및 인터페이스메시징 플랫폼

Signal

로컬 signal-cli 서브프로세스를 통한 프라이버시 중심 알림. SDK 없음, Meta 없음, 제3자 중계 없음.

🟢 런타임 준비 완료. Signal에는 HTTP API가 없으므로, Minara는 로컬에서 signal-cli를 호출합니다. 전송 전용입니다. Signal 프로토콜은 메시지 편집을 지원하지 않으므로, 헬퍼는 token을 버퍼링하다가 최종화 시점에 한 번에 전송합니다.

제공 기능

  • 본인 Signal 계정을 통한 종단간 암호화 알림
  • 비즈니스 계정 불필요, 제3자 중계 없음
  • 메시지당 최대 4,096자(헬퍼 기본값)
  • channel을 통한 메시지별 수신자 지정. 메시지를 보낼 수 있는 E.164 형식 번호여야 합니다

사전 요구 사항

signal-cli는 Java 기반 Signal 클라이언트로, 등록, 키 자료, 전송 파이프라인을 처리합니다. Minara에는 포함되어 있지 않으므로, 호스트에 별도로 설치한 뒤 전화번호를 지정해야 합니다.

Minara 부팅 시 호스트의 PATH에서 signal-cli를 찾을 수 없으면, signal 공급자는 게이트웨이 맵에서 자동으로 제외됩니다. Agent는 정상적으로 시작되며, 다른 공급자도 계속 동작합니다. 이 방식 덕분에 Signal은 선택적으로 사용할 수 있고, 다른 사용자의 부팅 흐름에 영향을 주지 않습니다.

설정

1. signal-cli 설치

macOS (Homebrew):

brew install signal-cli

Linux / Docker: 업스트림 저장소의 안내를 참고하세요. github.com/AsamK/signal-cli 대부분의 배포판에서 Java 17 이상이 필요합니다.

설치 확인:

signal-cli --version

2. 발신 번호 등록

Signal 계정에 연결되지 않은 전화번호를 사용하세요(이미 Signal 앱에 연결된 경우 먼저 해제해야 합니다):

signal-cli -u +15555550100 register

Signal이 인증 코드가 담긴 SMS를 발송합니다. 다음 명령으로 등록을 완료합니다:

signal-cli -u +15555550100 verify 123456

최초 1회 작업입니다. 이후 전송에 사용할 키가 디스크에 캐싱됩니다.

3. 셸에서 테스트 전송(동작 확인)

Minara에 연결하기 전에 signal-cli 자체가 정상 동작하는지 확인합니다:

signal-cli -u +15555550100 send -m "hello" +15555550200

수신자의 Signal 앱에 1초 이내로 메시지가 도착해야 합니다. 이 단계에서 실패하면 Minara로는 해결되지 않습니다. signal-cli를 먼저 수정하세요.

4. Minara 설정

minara auth messaging add signal

또는 프로젝트 루트의 .env 파일에 직접 추가합니다:

SIGNAL_CLI_NUMBER=+15555550100
SIGNAL_RECIPIENT=+15555550200
SIGNAL_CLI_BINARY=signal-cli

두 번호 모두 엄격한 E.164 형식이어야 합니다. 앞에 +, 국가 코드, 숫자만 허용되며, 공백이나 하이픈은 사용할 수 없습니다. Minara는 send_message() 호출마다 수신자를 재검증하므로, 잘못된 오버라이드는 통과하지 못합니다.

SIGNAL_CLI_BINARY는 선택 사항입니다. signal-cli를 기본 PATH 검색 범위 외부에 설치했다면 절대 경로로 지정하세요.

5. Minara를 통한 테스트

minara auth messaging test signal

보안 설계. Signal을 다르게 처리하는 이유

Signal은 서브프로세스를 실행합니다. 이는 CLAUDE.md §4a Bucket B에 해당합니다. apps/agent/src/messaging/signal.ts 모듈은 guardCommand / detectJail 적용 대상에서 제외됩니다. 그 이유는 다음과 같습니다:

  1. argv가 정적입니다. signal-cli -u <number> send -m <body> -- <recipient> 형태이며, LLM 입력이 플래그에 연결되지 않습니다.
  2. 두 전화번호는 모두 엄격한 E.164 정규식으로 검증됩니다. 발신 번호는 팩토리 시점에, 수신 번호는 전송마다 검증합니다.
  3. 메시지 본문은 별도의 -m 슬롯으로 전달되며, 명령 문자열에 직접 연결되지 않습니다.
  4. 수신자 앞의 -- 종결자는 검증된 입력에서도 선행 하이픈 플래그 주입 시도를 차단합니다.
  5. 자식 프로세스는 shell: false로 실행되므로, 특수 문자에 대한 셸 해석이 없습니다.

LLM이 볼 수 있는 문자열은 argv에 도달하지 않습니다. 소스를 확인하면 해당 모듈의 doc comment에 "Bucket B" 주석이 있습니다.

수신자 오버라이드

send_message({
  provider: "signal",
  channel: "+15555559999",
  text: "Critical: position liquidation imminent",
})

문제 해결

부팅 시 signal 공급자가 마운트되지 않는 경우

  • signal-cli가 PATH에 없습니다. which signal-cli로 확인하고, 설치를 수정하거나 SIGNAL_CLI_BINARY에 절대 경로를 지정하세요.
  • 환경 변수가 설정되지 않았습니다. 팩토리가 게이트웨이를 반환하려면 SIGNAL_CLI_NUMBERSIGNAL_RECIPIENT 모두 비어 있지 않아야 합니다.

"Rate limit exceeded (429)"

  • Signal은 자동화 사용에 대해 발신자당 공격적인 속도 제한을 적용합니다. 알림을 너무 자주 보내지 마세요. 간격을 두거나 여러 이벤트를 하나의 메시지로 합치세요.

"Invalid E.164 format"

  • 두 번호 모두 +<국가코드><번호> 형식에 숫자만 허용됩니다. 공백, 하이픈, 괄호는 사용할 수 없습니다. Minara는 (202) 555-1234를 거부합니다. +12025551234 형식을 사용하세요.

"Unregistered user"

  • 수신자가 Signal에 가입하지 않았거나, 계정이 삭제 또는 연결 해제된 상태입니다. Signal이 해당 전화번호를 인식하지 못하면 메시지를 전송할 수 없습니다.

참조

목차