OOMOL OpenConnector 셀프 호스팅 가이드
OOMOL OpenConnector는 오픈소스 셀프 호스팅 가능한 커넥터 서비스입니다. 에이전트나 내부 도구가 실제 외부 서비스를 호출해야 하면서 공급자 자격 증명, 권한, 실행 기록을 자체 환경에 유지하려는 경우에 사용하세요. GitHub, Gmail, Notion, Hacker News, Ably, Abstract, A-Leads 같은 서비스에 대해 MCP 또는 HTTP를 통해 타입이 지정된 작업을 노출합니다.
에이전트는 스키마, 범위, 실행 상태, 안전한 계정 레이블을 보지만, 원시 공급자 토큰, 작업 권한, 실행 기록은 배포 경계 내부에 유지됩니다.
제공하는 기능
- MCP, HTTP, OpenAPI, 웹 콘솔을 통해 공급자 작업을 노출하는 런타임.
- API 키, 사용자 지정 자격 증명, OAuth2 연결, 인증 없는 공급자를 위한 자격 증명 저장소.
- 에이전트가 호출하기 전에 호출 가능한 항목을 발견할 수 있도록 하는 타입 지정 작업 스키마.
- 사용자와 에이전트가 작업이 어떤 계정으로 실행될지 확인할 수 있도록 하는 연결 ID와 범위.
- 파일 URL이 필요한 작업을 위한 임시 파일 전송.
- 입력 요약을 마스킹하고 공급자 오류를 포함하는 최근 실행 로그.
- 작업이 사용될 때만 로드되는 로컬 실행기를 갖춘 공급자 카탈로그.
런타임을 실행할 위치를 선택한 다음 스토리지, 접근 제어, 공급자 연결, 에이전트용 MCP 또는 HTTP 진입점을 구성하세요.
배포 대상 선택
| 대상 | 사용 시점 | 스토리지 |
|---|---|---|
| Docker Compose | 가장 빠른 로컬 또는 단일 서버 배포를 원할 때 | /app/data에 마운트된 Docker 볼륨, /app/data/connect.sqlite에 SQLite. |
| 소스 런타임 | OOMOL OpenConnector 또는 공급자 실행기를 개발할 때 | OOMOL_CONNECT_DATA_DIR가 설정되지 않은 경우 로컬 ./data/connect.sqlite. |
| Cloudflare Workers | Cloudflare 호스팅 런타임 상태와 메타데이터 배포를 원할 때 | 런타임 레코드용 D1, 임시 전송 파일용 R2. |
런타임 준비
배포 전에 다음 값을 결정하세요:
| 값 | 중요한 이유 |
|---|---|
OOMOL_CONNECT_ADMIN_TOKEN | 자체 셸 외부에서 접근 가능할 때 웹 콘솔, /api, 로컬 API 참조를 보호합니다. |
OOMOL_CONNECT_ENCRYPTION_KEY | 저장된 공급자 자격 증명과 OAuth 클라이언트 시크릿을 암호화합니다. 시크릿 관리자에 보관하세요. |
OOMOL_CONNECT_ORIGIN | OAuth 콜백 URL에 사용되는 공개 오리진을 설정합니다. 브라우저가 터널, 도메인 또는 Worker URL을 통해 런타임에 접근할 때 필요합니다. |
| 런타임 토큰 | /v1 및 /mcp에 대한 에이전트 및 클라이언트 호출을 인증합니다. 웹 콘솔 Access 탭 또는 관리자 API에서 생성하세요. |
| 작업 정책 | /v1 및 MCP를 통해 실행할 수 있는 작업을 제한합니다. OOMOL_CONNECT_ALLOWED_ACTIONS 및 OOMOL_CONNECT_BLOCKED_ACTIONS을 사용하세요. |
런타임 데이터베이스를 민감 정보로 취급하세요. OOMOL_CONNECT_ENCRYPTION_KEY 없이도 OOMOL OpenConnector는 작동하지만, 공급자 시크릿이 민감한 로컬 SQLite 파일에 저장됩니다.
Docker Compose로 실행
OOMOL OpenConnector 저장소를 클론하고, 프로젝트 디렉터리로 이동한 뒤 런타임을 시작하세요:
git clone https://github.com/oomol-lab/open-connector.git
cd open-connector
docker compose up --build
웹 콘솔을 여세요:
http://localhost:3000
생성된 API 참조를 여세요:
http://localhost:3000/docs
인증 없는 작업으로 런타임을 확인하세요:
curl -s -X POST http://localhost:3000/v1/actions/hackernews.get_top_stories \
-H 'content-type: application/json' \
-d '{"input":{}}'
Docker Compose는 런타임 상태를 connector-data 볼륨에 저장합니다. 컨테이너는 SQLite를 다음 위치에 저장합니다:
/app/data/connect.sqlite
프라이빗 서버 배포의 경우 시작 전에 최소한 관리자 토큰과 암호화 키를 설정하세요:
이 예제는 Bash에서 실행하세요. 실제 자격 증명은 입력이 숨겨진 프롬프트에만 입력하고 셸 명령이나 명령 로그에 넣지 마세요.
(
set -eu
read -r -s -p "OOMOL_CONNECT_ADMIN_TOKEN: " OOMOL_CONNECT_ADMIN_TOKEN
echo
test -n "$OOMOL_CONNECT_ADMIN_TOKEN"
export OOMOL_CONNECT_ADMIN_TOKEN
read -r -s -p "OOMOL_CONNECT_ENCRYPTION_KEY: " OOMOL_CONNECT_ENCRYPTION_KEY
echo
test -n "$OOMOL_CONNECT_ENCRYPTION_KEY"
export OOMOL_CONNECT_ENCRYPTION_KEY
docker compose up --build
)
런타임이 공개 도메인이나 터널을 통해 노출되는 경우 관리자와 런타임 인증을 모두 요구하고 공개 오리진을 설정하세요:
(
set -eu
export OOMOL_CONNECT_ORIGIN="https://connect.example.com"
read -r -s -p "OOMOL_CONNECT_ADMIN_TOKEN: " OOMOL_CONNECT_ADMIN_TOKEN
echo
test -n "$OOMOL_CONNECT_ADMIN_TOKEN"
export OOMOL_CONNECT_ADMIN_TOKEN
read -r -s -p "OOMOL_CONNECT_RUNTIME_TOKEN: " OOMOL_CONNECT_RUNTIME_TOKEN
echo
test -n "$OOMOL_CONNECT_RUNTIME_TOKEN"
export OOMOL_CONNECT_RUNTIME_TOKEN
read -r -s -p "OOMOL_CONNECT_ENCRYPTION_KEY: " OOMOL_CONNECT_ENCRYPTION_KEY
echo
test -n "$OOMOL_CONNECT_ENCRYPTION_KEY"
export OOMOL_CONNECT_ENCRYPTION_KEY
docker compose up --build
)
환경에서 제공하는 런타임 토큰은 공개 배포를 부트스트랩할 때 유용합니다. 콘솔에서 생성한 oct_… 토큰을 선호하는 경우 첫 토큰을 생성하는 동안 런타임을 프라이빗으로 유지한 뒤 공개로 노출하세요.
Docker 이미지는 컨테이너 내부의 0.0.0.0에 바인딩됩니다. 호스트 방화벽, 리버스 프록시 또는 컨테이너 플랫폼으로 외부 접근을 제어하세요.
관리자 및 런타임 접근 보호
관리자 HTTP 클라이언트는 다음으로 /api, /docs 또는 웹 콘솔을 호출합니다:
Authorization: Bearer replace-with-an-admin-token
웹 콘솔 Access 탭에서 에이전트와 SDK 스타일 클라이언트용 런타임 토큰을 생성하세요. 토큰은 한 번만 표시되며 해시만 저장됩니다. 토큰이 없는 런타임은 localhost 또는 프라이빗 네트워크에 있어야 합니다.
관리자 API를 통해 생성할 수도 있습니다:
아래 인증 요청 예제에는 Python 3과 curl 7.76.0 이상이 필요합니다. 이 버전부터 모든 예제에 사용된 —fail-with-body 옵션을 지원합니다. 비밀 값은 숨겨진 입력으로 받아 표준 입력을 통해 curl에 전달하므로 명령줄 인수나 셸 기록에 자격 증명이 포함되지 않습니다.
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings
warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
raise SystemExit("A token is required")
payload = {'name': 'Claude Desktop'}
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
config += "data = " + json.dumps(json.dumps(payload)) + "\n"
subprocess.run(
['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'POST', 'http://localhost:3000/api/runtime-tokens', '--header', 'content-type: application/json'],
input=config, text=True, check=True,
)
PY
그런 다음 런타임 클라이언트는 다음으로 /v1 또는 /mcp을 호출합니다:
Authorization: Bearer oct_...
부트스트랩 스크립트와 하위 호환성을 위해 OOMOL_CONNECT_RUNTIME_TOKEN도 계속 허용됩니다:
(
set -eu
read -r -s -p "OOMOL_CONNECT_ADMIN_TOKEN: " OOMOL_CONNECT_ADMIN_TOKEN
echo
test -n "$OOMOL_CONNECT_ADMIN_TOKEN"
export OOMOL_CONNECT_ADMIN_TOKEN
read -r -s -p "OOMOL_CONNECT_RUNTIME_TOKEN: " OOMOL_CONNECT_RUNTIME_TOKEN
echo
test -n "$OOMOL_CONNECT_RUNTIME_TOKEN"
export OOMOL_CONNECT_RUNTIME_TOKEN
docker compose up --build
)
에이전트가 실행할 수 있는 작업을 제한하세요:
OOMOL_CONNECT_ALLOWED_ACTIONS="hackernews.*,github.get_current_user" docker compose up --build
더 넓은 허용 목록에 포함되어 있어도 특정 작업을 차단하세요:
OOMOL_CONNECT_ALLOWED_ACTIONS="github.*" \
OOMOL_CONNECT_BLOCKED_ACTIONS="github.delete_repository" \
docker compose up --build
API 키 공급자 연결
GitHub는 개인 액세스 토큰을 사용할 수 있어 간결한 API 키 예시입니다.
공급자 계약을 확인하세요:
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings
warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
raise SystemExit("A token is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
subprocess.run(
['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'GET', 'http://localhost:3000/api/providers/github'],
input=config, text=True, check=True,
)
PY
기본 GitHub 연결을 저장하세요:
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings
warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
raise SystemExit("A token is required")
payload = {'authType': 'api_key', 'values': {'apiKey': None}}
payload["values"]["apiKey"] = getpass.getpass("GitHub API key: ")
if not payload["values"]["apiKey"]:
raise SystemExit("An API key is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
config += "data = " + json.dumps(json.dumps(payload)) + "\n"
subprocess.run(
['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'PUT', 'http://localhost:3000/api/connections/github', '--header', 'content-type: application/json'],
input=config, text=True, check=True,
)
PY
런타임을 통해 GitHub를 호출하세요:
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings
warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("Runtime token: ")
if not token:
raise SystemExit("A token is required")
payload = {'input': {}}
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
config += "data = " + json.dumps(json.dumps(payload)) + "\n"
subprocess.run(
['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'POST', 'http://localhost:3000/v1/actions/github.get_current_user', '--header', 'content-type: application/json'],
input=config, text=True, check=True,
)
PY
구성된 연결과 에이전트에 노출되는 안전한 계정 ID를 확인하세요:
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings
warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
raise SystemExit("A token is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
subprocess.run(
['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'GET', 'http://localhost:3000/api/connections'],
input=config, text=True, check=True,
)
PY
이름이 지정된 연결
동일한 공급자에 여러 계정이 필요한 경우 connectionName을 추가하세요:
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings
warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
raise SystemExit("A token is required")
payload = {'authType': 'api_key', 'connectionName': 'work', 'values': {'apiKey': None}}
payload["values"]["apiKey"] = getpass.getpass("GitHub API key: ")
if not payload["values"]["apiKey"]:
raise SystemExit("An API key is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
config += "data = " + json.dumps(json.dumps(payload)) + "\n"
subprocess.run(
['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'PUT', 'http://localhost:3000/api/connections/github', '--header', 'content-type: application/json'],
input=config, text=True, check=True,
)
PY
실행 중에 해당 계정을 선택하세요:
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings
warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("Runtime token: ")
if not token:
raise SystemExit("A token is required")
payload = {'input': {}}
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
config += "data = " + json.dumps(json.dumps(payload)) + "\n"
subprocess.run(
['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'POST', 'http://localhost:3000/v1/actions/github.get_current_user', '--header', 'x-oo-connector-alias: work', '--header', 'content-type: application/json'],
input=config, text=True, check=True,
)
PY
alias 쿼리 매개변수도 허용됩니다.
OAuth 공급자 연결
OAuth 공급자는 자체 공급자 OAuth 앱을 사용합니다. 먼저 공급자 OAuth 앱에 콜백 URL을 설정하세요. 콜백 URL은 OpenConnector 오리진에 /oauth/callback를 더한 값입니다.
기본 포트에서 GitHub는 다음 콜백 URL을 사용합니다:
http://localhost:3000/oauth/callback
다른 오리진을 통해 런타임을 노출하는 경우 런타임 시작 전에 OOMOL_CONNECT_ORIGIN을 설정한 다음 콜백 URL에 해당 오리진을 사용하세요:
https://connect.example.com/oauth/callback
정확한 콜백 URL을 공급자 OAuth 앱에 붙여넣으세요.
웹 콘솔에서 OAuth 클라이언트를 저장하세요:
http://localhost:3000을 여세요.- GitHub 같은 공급자 페이지를 여세요.
- Configure OAuth Client 또는 Edit OAuth Client를 선택하세요.
- 공급자 앱의 Client ID와 Client Secret을 붙여넣으세요.
- Save OAuth Client를 선택하세요.
공급자에 추가 클라이언트 구성 필드가 필요한 경우 동일한 OAuth 클라이언트 양식에 입력하세요. 계속하기 전에 해당 공급자가 요구하는 필드를 노출하는 OpenConnector 콘솔 버전을 사용하세요.
OAuth 클라이언트를 저장한 후 공급자 페이지에서 Connect를 선택하세요. 공급자 권한 부여 화면을 승인하세요. 공급자가 OpenConnector로 다시 리디렉션한 후 공급자 페이지에 계정이 연결됨으로 표시되는지 확인하세요.
에이전트에 도구 제공
MCP 지원 클라이언트의 경우 클라이언트를 다음으로 지정하세요:
http://localhost:3000/mcp
MCP 서버는 발견 지향 도구를 노출합니다:
list_appssearch_actionsget_action_guideexecute_action
MCP 도구 메타데이터를 미리 보세요:
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings
warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("Runtime token: ")
if not token:
raise SystemExit("A token is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
subprocess.run(
['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'GET', 'http://localhost:3000/mcp/tools'],
input=config, text=True, check=True,
)
PY
HTTP 클라이언트의 경우 /v1 런타임 API를 사용하세요:
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings
warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("Runtime token: ")
if not token:
raise SystemExit("A token is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
subprocess.run(
['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'GET', 'http://localhost:3000/v1/actions'],
input=config, text=True, check=True,
)
PY
각 작업에는 입력 스키마, 범위, 공급자 권한, 현재 연결 ID, 요청 예시가 포함된 로컬 Markdown 가이드가 있습니다:
python3 - <<'PY'
import getpass
import json
import subprocess
import warnings
warnings.simplefilter("error", getpass.GetPassWarning)
token = getpass.getpass("OOMOL_CONNECT_ADMIN_TOKEN: ")
if not token:
raise SystemExit("A token is required")
config = "header = " + json.dumps("authorization: Bearer " + token) + "\n"
subprocess.run(
['curl', '--disable', '--silent', '--show-error', '--fail-with-body', '--config', '-', '--request', 'GET', 'http://localhost:3000/api/actions/github.get_current_user/agent.md'],
input=config, text=True, check=True,
)
PY
웹 콘솔에서는 각 작업에 대한 cURL, TypeScript, 에이전트 프롬프트 예시를 복사할 수도 있습니다.
소스에서 실행
OOMOL OpenConnector 또는 공급자 실행기를 개발할 때 소스 워크플로를 사용하세요. Node.js 22 이상을 사용하세요.
git clone https://github.com/oomol-lab/open-connector.git
cd open-connector
npm install
npm run build:web
npm run dev
npm install 및 npm run dev은 누락되었거나 오래된 로컬 생성 파일을 생성합니다.
소스에서 실행할 때 런타임 상태는 다음에 저장됩니다:
./data/connect.sqlite
다른 데이터 디렉터리를 사용하려면:
OOMOL_CONNECT_DATA_DIR=/path/to/data npm run dev
위에서 설명한 것과 동일한 관리자, 암호화, 오리진, 런타임 토큰, 작업 정책 환경 변수를 설정하세요.
Cloudflare Workers에 배포
Cloudflare Workers는 메타데이터 및 런타임 상태 배포 대상으로 지원됩니다.
저장소를 클론하고, Cloudflare 리소스를 생성한 뒤 배포하세요:
git clone https://github.com/oomol-lab/open-connector.git
cd open-connector
cp wrangler.example.jsonc wrangler.local.jsonc
npm install
npm run generate:catalog
npm run build:web
npx wrangler d1 create oomol-connect
npx wrangler r2 bucket create oomol-connect-transit-files
배포 전에 Cloudflare에서 반환된 D1 database_id로 무시된 wrangler.local.jsonc 파일을 업데이트하세요.
초기 설정 중에는 Worker를 비공개로 유지하세요. 로컬 Wrangler 설정에서 workers_dev와 preview_urls를 false로 설정하고 공개 라우트와 사용자 지정 도메인은 설정하지 마세요. 아래의 세 가지 secret을 모두 설정하기 전에는 공개 접근을 허용하지 마세요.
npx wrangler d1 migrations apply oomol-connect --remote --config wrangler.local.jsonc
npm run deploy:cloudflare
Wrangler로 시크릿을 설정하세요:
npx wrangler secret put OOMOL_CONNECT_ADMIN_TOKEN --config wrangler.local.jsonc
npx wrangler secret put OOMOL_CONNECT_RUNTIME_TOKEN --config wrangler.local.jsonc
npx wrangler secret put OOMOL_CONNECT_ENCRYPTION_KEY --config wrangler.local.jsonc
세 가지 secret을 모두 설정한 후 로컬 설정에서 원하는 공개 라우트를 활성화하고 다시 배포하세요.
wrangler.local.jsonc에서 OOMOL_CONNECT_ORIGIN을 공개 Worker 오리진으로 설정하세요. 관리자 토큰은 콘솔과 /api를 보호하고, 런타임 토큰은 첫 공개 요청부터 /v1 및 /mcp을 보호합니다.
Cloudflare는 오리진, 인증 토큰, 작업 정책, 전송 파일 제한, 자격 증명 암호화에 동일한 환경 변수 이름을 사용합니다. PORT, HOST, OOMOL_CONNECT_DATA_DIR는 로컬 Node 전용 설정입니다.
Worker 런타임은 카탈로그 메타데이터, /api 및 /v1 메타데이터 엔드포인트, 연결, 런타임 토큰, OAuth 구성 및 상태, R2 기반 전송 파일, 생성된 공급자 작업 실행기 레지스트리를 제공합니다. 읽지 않은 만료된 전송 파일을 자동으로 정리하려면 전송 버킷에 R2 수명 주기 규칙을 구성하세요.
배포 운영
지원 및 복구를 위해 다음 레코드를 사용 가능하게 유지하세요:
| 레코드 | 찾을 위치 |
|---|---|
| 런타임 데이터베이스 | Docker 볼륨, 로컬 OOMOL_CONNECT_DATA_DIR 또는 Cloudflare D1. |
| 임시 전송 파일 | 로컬 런타임의 경우 OOMOL_CONNECT_DATA_DIR/files, 또는 Cloudflare R2. |
| 관리자 토큰 및 암호화 키 | 시크릿 관리자. OOMOL OpenConnector는 암호화 키를 대신 저장하지 않습니다. |
| 런타임 토큰 접두사 | 웹 콘솔 Access 탭 또는 /api/runtime-tokens. 전체 런타임 토큰은 한 번만 표시됩니다. |
| 실행 기록 | 웹 콘솔 최근 실행 또는 GET /api/runs. |
파일 업로드 작업의 경우 로컬 전송 파일은 OOMOL_CONNECT_DATA_DIR/files 아래에 저장되며 기간에 따라 정리됩니다. OOMOL_CONNECT_TRANSIT_FILE_TTL_SECONDS 및 OOMOL_CONNECT_TRANSIT_FILE_MAX_BYTES으로 수명과 업로드 크기를 조정하세요.
문제 해결
| 증상 | 확인할 사항 |
|---|---|
웹 콘솔 또는 /api가 권한 없음을 반환합니다. | Authorization: Bearer <admin-token>를 전송하고 OOMOL_CONNECT_ADMIN_TOKEN이 실행 환경과 일치하는지 확인하세요. |
/v1 또는 /mcp이 권한 없음을 반환합니다. | Access 탭 또는 POST /api/runtime-tokens에서 생성한 런타임 토큰을 사용하세요. 관리자 토큰은 관리자 인터페이스용이며 런타임 클라이언트용이 아닙니다. |
| OAuth가 잘못된 호스트로 리디렉션됩니다. | OOMOL_CONNECT_ORIGIN을 사용자가 브라우저에서 여는 오리진으로 설정하고 런타임을 재시작한 뒤 공급자 앱에서 <openconnector-origin>/oauth/callback을 사용하세요. |
| 작업이 자격 증명을 찾을 수 없습니다. | /api/connections, 선택한 x-oo-connector-alias, 연결이 아직 사용 가능한지 확인하세요. |
| 작업이 차단됩니다. | OOMOL_CONNECT_ALLOWED_ACTIONS 및 OOMOL_CONNECT_BLOCKED_ACTIONS를 확인하세요. 차단된 작업은 더 넓은 허용 목록보다 우선합니다. |
| 이전에 작동하던 공급자 자격 증명이 실패합니다. | 토큰이 만료되었고 리프레시 토큰이 없으면 공급자를 다시 연결하거나, 암호화 키가 저장된 레코드와 여전히 일치하는지 확인하세요. |
Wanta