콘텐츠로 이동

비용, 감사, ClawHub, 자격 증명 API

비용 추적 및 예산 상태, 감사 로그 조회/검증, ClawHub 마켓플레이스, 암호화된 자격 증명 및 gcloud 설정 저장소.

이 엔드포인트들은 실행 중인 Revka 게이트웨이의 운영 및 보안 영역을 담당합니다: 에이전트의 비용 지출 현황, 보안 관련 이벤트의 변조 방지 감사 추적, ClawHub 스킬 마켓플레이스, 그리고 워크플로우 자격 증명과 Cloud Run 설정을 지원하는 두 가지 메타데이터 전용 저장소가 포함됩니다. 이를 활용해 대시보드의 비용 및 감사 페이지를 구동하거나, 자체 도구로 지출 데이터를 수집하거나, 커뮤니티 스킬을 설치하거나, 워크플로우 단계를 암호화된 자격 증명에 연결할 수 있습니다.

여기에 있는 대부분의 라우트는 페어링 흐름에서 발급된 bearer 토큰을 필요로 합니다. 일부는 의도적으로 다르게 동작합니다: GET /api/cost는 인증 없이 읽기 전용 텔레메트리를 제공하며, 비용 수집 및 자격 증명 확인 엔드포인트는 사용자 bearer 토큰이 아닌 내부 서비스 토큰을 요구합니다 — 이 경우 명시적으로 안내되어 있습니다. 비용 및 관찰 가능성 설정에 대해서는 비용 추적 및 예산관찰 가능성 및 트레이싱을 참고하세요. 감사 로그 내부 구조는 감사 로그를 참고하세요.

모든 /api/* 라우트는 64 KiB의 요청 본문 제한과 설정 가능한 타임아웃(기본값 30초, 환경 변수 REVKA_GATEWAY_TIMEOUT_SECS)을 공유하며, 일부 라우트에는 별도 오버라이드가 있습니다.

Revka는 모든 LLM API 호출의 토큰 수와 계산된 USD 비용을 <workspace>/state/costs.jsonl에 JSONL 원장으로 저장합니다. 추적기는 세션, 일별, 월별 합계를 집계하고 모델별, 에이전트별, 런타임 소스별(gateway, channel, sidecar)로 지출을 분류합니다. 프로세스 전역 싱글톤이 게이트웨이와 채널 경로가 단일 원장과 단일 예산 확인을 공유하도록 보장합니다. 레거시 .revka/costs.db 저장소는 첫 시작 시 자동으로 마이그레이션되며, 잘못된 형식의 JSONL 줄은 읽기 실패 대신 경고와 함께 건너뜁니다.

비용은 [cost.prices] 아래에 설정된 모델별 가격을 사용하여 (tokens / 1_000_000) × price_per_million으로 계산됩니다. 모델 조회는 퍼지 매칭 방식으로 동작합니다: 정확히 일치하는 항목, provider/model 형식, / 이후의 접미사, 접두사 순으로 시도합니다. 일치하는 가격 항목이 없으면 해당 레코드는 비용 0으로 저장됩니다(디버그 로그 기록).

GET /api/cost는 비용 요약을 반환합니다. 인증이 필요하지 않습니다 — 이는 대시보드가 사용하는 읽기 전용 운영자 텔레메트리입니다. 비용 추적이 비활성화된 경우, 오류 대신 완전히 0으로 채워진 요약을 반환합니다(budget.state"disabled"로 설정), 이를 통해 대시보드가 정상적으로 저하됩니다.

GET /api/cost
{
"cost": {
"session_cost_usd": 0.42,
"daily_cost_usd": 1.87,
"monthly_cost_usd": 12.34,
"total_tokens": 184320,
"request_count": 57,
"by_model": { },
"by_agent": { },
"by_source": { },
"budget": {
"enabled": true,
"daily_limit_usd": 10.0,
"monthly_limit_usd": 100.0,
"warn_at_percent": 80,
"daily_remaining_usd": 8.13,
"monthly_remaining_usd": 87.66,
"daily_percent": 18.7,
"monthly_percent": 12.34,
"state": "ok"
}
}
}

by_model, by_agent, by_source 분류는 현재 프로세스 수명 기간만 집계합니다. daily_cost_usdmonthly_cost_usd는 전체 원장에서 읽어옵니다. 소스 태그가 없는 레코드는 by_source에서 "runtime"으로 분류됩니다.

신뢰할 수 있는 사이드카(예: operator-mcp 런타임)에서 공유 원장으로 토큰 사용량을 전달하려면 POST /api/cost/usage를 사용하세요. 이 엔드포인트는 예산 원장을 변경하므로 서비스 토큰으로 제한됩니다 — bearer 토큰이 아닌 X-Revka-Service-Token 헤더에 전달해야 합니다.

POST /api/cost/usage
X-Revka-Service-Token: <service-token>
Content-Type: application/json
{
"model": "gpt-4o",
"provider": "openai",
"input_tokens": 1000,
"output_tokens": 250,
"source": "sidecar",
"agent_id": "my-agent",
"agent_title": "My Agent"
}

model만 필수입니다. providersource는 생략하거나 비워두면 "sidecar"로 기본 설정됩니다. 수집에 성공하면 { "recorded": true, "usage": { ... } }를 반환합니다. 비용 추적이 비활성화된 경우 200과 함께 { "recorded": false, "reason": "cost tracking disabled" }를 반환하며, 유효한 서비스 토큰이 없는 요청은 401을 반환합니다.

예산은 [cost] 섹션에서 설정하며, 전역 추적기에 의해 세션이 아닌 프로세스 단위로 적용됩니다. 경고 및 초과 임계값은 현재 사용량만이 아니라 예상 합계(현재 사용량 + 대기 중인 호출의 예상 비용)와 비교됩니다.

[cost]
enabled = true
daily_limit_usd = 10.0 # default
monthly_limit_usd = 100.0 # default
warn_at_percent = 80 # warn at 80% of a limit
allow_override = false # allow a --override flag to bypass
[cost.enforcement]
mode = "warn" # "warn" | "block" | "route_down"
route_down_model = "gpt-4o-mini" # used with "route_down"
reserve_percent = 10 # reserve 10% for critical ops
[cost.prices]
"claude-sonnet-4-20250514" = { input = 3.0, output = 15.0 } # USD per 1M tokens
"gpt-4o" = { input = 2.5, output = 10.0 }

mode 설정은 한도 초과 시 동작을 제어합니다:

모드예산 초과 시 동작
warn경고를 기록하고 요청을 허용합니다 (기본값)
block요청을 거부합니다
route_down더 저렴한 route_down_model로 전환합니다

비용 요약의 budget.state 필드는 현재 상태를 반영합니다: "ok", "warning" (warn_at_percent 초과), "exceeded" (한도 초과), 또는 "disabled". 전체 설정 참조 및 가격 테이블 형식은 비용 추적 및 예산을 참고하세요.

감사 로그는 보안 관련 이벤트(명령 실행, 파일 접근, 설정 변경, 인증 성공/실패, 정책 위반, 일반 보안 이벤트)의 추가 전용 변조 방지 기록입니다. 각 항목은 SHA-256 해시 체인(entry_hash = SHA-256(prev_hash || canonical_JSON_of_content))으로 연결되며 단조 증가하는 sequence를 가지므로, 과거 항목을 수정하면 이후의 모든 항목이 무효화됩니다. 항목은 선택적으로 HMAC-SHA256으로 서명할 수 있습니다. 로그를 사용하려면 설정에서 [security.audit] enabled = true가 필요합니다(기본값).

[security.audit]
enabled = true # default
log_path = "audit.log" # relative to the revka dir
max_size_mb = 100 # rotate at this size
sign_events = false # optional HMAC-SHA256 signing

GET /api/audit는 bearer 토큰 인증 후 최근 이벤트를 최신순으로 반환합니다.

GET /api/audit?limit=50&event_type=command_execution&since=2026-01-01T00:00:00Z
Authorization: Bearer <token>
파라미터타입기본값설명
limitint50 (최대 500)반환할 최대 이벤트 수
event_typestring타입으로 필터링 (아래 참조)
sinceRFC 3339이벤트 타임스탬프의 하한값

event_typecommand_execution, file_access, config_change, auth_success, auth_failure, policy_violation, 또는 security_event를 허용합니다. 응답은 이벤트 목록에 개수와 audit_enabled 플래그를 함께 반환합니다:

{
"events": [
{
"timestamp": "2026-06-18T10:00:00Z",
"event_id": "<uuid>",
"event_type": "command_execution",
"actor": { "channel": "telegram", "user_id": "123", "username": "@alice" },
"action": { "command": "ls -la", "risk_level": "low", "approved": false, "allowed": true },
"result": { "success": true, "exit_code": 0, "duration_ms": 15 },
"security": { "policy_violation": false, "rate_limit_remaining": 19, "sandbox_backend": "firejail" },
"sequence": 42,
"prev_hash": "<64 hex>",
"entry_hash": "<64 hex>",
"signature": "<64 hex>"
}
],
"count": 1,
"audit_enabled": true
}

signature 필드는 sign_events = true일 때만 포함됩니다. 감사 로깅이 비활성화된 경우, 엔드포인트는 빈 events 배열, count: 0, audit_enabled: false와 함께 200을 반환합니다 — 감사가 비활성화된 경우에도 대시보드가 오류를 반환하지 않습니다.

GET /api/audit/verify는 온디스크 로그를 순회하며 해시 체인을 처음부터 끝까지 검증합니다. 변조를 감지하는 가장 빠른 방법입니다: 항목이 수정, 삭제, 또는 순서가 변경된 경우 검증이 실패합니다.

GET /api/audit/verify
Authorization: Bearer <token>
{ "verified": true, "entry_count": 1842 }

체인이 손상된 경우(또는 감사가 활성화되지 않은 경우), verified: false와 함께 실패 내용을 설명하는 error를 반환합니다:

{ "verified": false, "error": "chain broken at sequence 41" }

HMAC 서명을 활성화하려면 게이트웨이 시작 전REVKA_AUDIT_SIGNING_KEY 환경 변수에 32바이트 키(64자리 16진수)를 설정하세요 — 로거는 생성 시점에 이를 읽으며, 키가 누락되거나 길이가 잘못된 경우 시작이 실패합니다. 로그 로테이션은 체인을 genesis로 초기화하므로, 각 로테이션된 .N.log 아카이브는 독립적으로 검증할 수 있습니다. 체인 형식, 서명 설정, CLI 검증에 대해서는 감사 로그를 참고하세요.

ClawHub는 clawhub.ai의 스킬 마켓플레이스입니다. 이 라우트들은 마켓플레이스 API를 프록시하여 스킬을 검색하고, 트렌딩 스킬을 탐색하고, 상세 정보를 확인하고, 원클릭으로 로컬 Kumiho 메모리 및 워크스페이스에 스킬을 설치할 수 있습니다. 네 가지 라우트 모두 bearer 토큰이 필요합니다.

GET /api/clawhub/search?q=rust+debugging&limit=20
GET /api/clawhub/trending?limit=20
GET /api/clawhub/skills/{slug}
POST /api/clawhub/install/{slug}
Authorization: Bearer <token>
파라미터위치기본값설명
qquery필수 (검색 시)검색어
limitquery20최대 결과 수
slugpathClawHub 스킬 슬러그

GET /api/clawhub/skills/{slug}는 스킬 상세 정보를 반환하며, 사용 가능한 경우 렌더링된 SKILL.mdskill_md 필드에 첨부합니다. POST /api/clawhub/install/{slug}는 스킬의 SKILL.md를 가져와 ~/.revka/workspace/skills/<slug>.md에 저장하고, Kumiho memory_projectSkills 공간에 스킬을 아이템으로 등록(published로 리비전 태그 지정)한 후 다음을 반환합니다:

{
"installed": true,
"slug": "rust-debugging",
"name": "Rust Debugging",
"kref": "kref://CognitiveMemory/Skills/rust-debugging.skill",
"description": "Systematic Rust debugging workflow"
}

ClawHub가 비활성화된 경우 라우트는 400{"error": "ClawHub integration disabled"}를 반환하며, 마켓플레이스에 연결할 수 없는 경우 502를 반환합니다.

[clawhub]
enabled = true # default
api_url = "https://clawhub.ai" # default — base URL for the ClawHub API
api_token = "clh_..." # optional; only required to publish skills
타입기본값설명
enabledbooltrueClawHub 통합 활성화
api_urlstring"https://clawhub.ai"ClawHub API의 기본 URL (사설 인스턴스를 사용하는 경우 변경)
api_tokenstring?미설정clh_… 토큰; 스킬 게시 시에만 필요 — 익명 탐색 및 설치는 토큰 없이 동작

설치된 스킬은 대시보드에서 생성된 스킬과 동일한 등록 경로를 사용하므로, 스킬, 도구 및 통합 페이지스킬 API에 표시됩니다.

인증 프로필 — 자격 증명 저장소

섹션 제목: “인증 프로필 — 자격 증명 저장소”

인증된 서비스를 호출하는 워크플로우 단계는 인증 프로필에 바인딩됩니다: 게이트웨이의 SecretStore를 통해 ChaCha20-Poly1305 AEAD로 저장 시 암호화된 자격 증명입니다. 저장소는 서로 다른 신뢰 수준을 가진 두 가지 인터페이스로 나뉩니다 — bearer 인증 메타데이터 뷰, 그리고 자격 증명을 복호화하는 유일한 수단인 서비스 토큰 전용 resolve 경로입니다.

GET /api/auth/profiles # list metadata (bearer)
POST /api/auth/profiles # create a static-token profile (bearer)
DELETE /api/auth/profiles/{id} # delete a profile (bearer)
POST /api/auth/profiles/{id}/resolve # decrypt the credential (service token only)

GET /api/auth/profiles는 메타데이터 요약을 반환합니다 — 토큰 필드가 없음에 유의하세요:

{
"profiles": [
{
"id": "github:My Token",
"provider": "github",
"profile_name": "My Token",
"kind": "token",
"account_id": null,
"workspace_id": null,
"expires_at": null,
"created_at": "2026-06-18T10:00:00Z",
"updated_at": "2026-06-18T10:00:00Z"
}
]
}

POST /api/auth/profiles는 정적 토큰(API 키) 프로필을 생성합니다. 평문 token은 저장 전에 저장소에서 암호화되며 응답에 포함되지 않습니다. 응답은 새 메타데이터 요약과 201 Created입니다.

POST /api/auth/profiles
Authorization: Bearer <token>
Content-Type: application/json
{ "provider": "github", "profile_name": "My Token", "token": "ghp_..." }
필드필수 여부참고
provider공급자 식별자, 예: github
profile_name사람이 읽을 수 있는 레이블; provider와 결합하여 id를 형성
token원시 bearer / API 키 (저장 시 암호화)
account_id아니요선택적 계정 힌트
kind아니요기본값은 "token". "api_key"는 동의어. "oauth"400으로 거부됩니다 — OAuth 프로필은 /config 동의 흐름을 통해 생성해야 합니다

처리가 필요한 생성 응답: 필드 누락 또는 지원되지 않는 kind의 경우 400, 동일한 provider+profile_name 프로필이 이미 존재하는 경우 409, 그리고 IP당 속도 제한 도달 시 429(60초 내 10회 시도 후 5분 잠금, 루프백 호출자는 제외). 제한기는 소켓 피어만 신뢰하며 X-Forwarded-For는 무시합니다.

POST /api/auth/profiles/{id}/resolve는 자격 증명을 복호화하여 반환합니다. X-Revka-Service-Token 헤더(상수 시간 비교)가 필요하며, 중간 요소가 비밀을 캐시하지 않도록 응답에 Cache-Control: no-store를 설정합니다.

POST /api/auth/profiles/{id}/resolve
X-Revka-Service-Token: <service-token>
{
"token": "ghp_...",
"kind": "token",
"provider": "github",
"profile_name": "My Token",
"expires_at": null
}

알 수 없는 id404를 반환합니다. 빈 정적 토큰은 410 Gone(auth_profile_empty 코드 포함)을 반환하며, expires_at이 과거인 OAuth 프로필은 410 Gone(auth_profile_expired 코드 포함)을 반환합니다. 이를 통해 런타임이 만료된 자격 증명을 전송하는 대신 해당 단계를 실패 처리합니다.

서비스 토큰은 게이트웨이 시작 시 생성되어 <state_dir>/service-token에 저장됩니다(POSIX에서 모드 0600). 이는 사용자 대상 페어링 bearer 토큰과 구별됩니다 — 페어링 및 인증보안 모델을 참고하세요.

이 메타데이터 전용 엔드포인트들은 호스트의 gcloud SDK 설정 프로필을 나열하고 생성하며, 워크플로우 편집기의 Cloud Run / A2A IAM 선택기를 지원합니다. gcloud 설정은 로컬 Cloud SDK 자격 증명 저장소의 자격 증명을 참조하지만 그 자체는 비밀이 아니므로, 응답에는 표시 메타데이터만 포함됩니다 — 액세스, 리프레시, 또는 ID 토큰은 포함되지 않습니다. 두 라우트 모두 bearer 토큰과 20초 타임아웃으로 gcloud를 실행합니다.

GET /api/gcloud/configs
POST /api/gcloud/configs
Authorization: Bearer <token>

GET /api/gcloud/configsgcloud config configurations list를 실행하고 파싱된 설정을 반환합니다. gcloudPATH에 없으면 오류 대신 available: false를 반환하여 UI가 해당 기능을 숨길 수 있습니다:

{
"available": true,
"configs": [
{
"name": "default",
"is_active": true,
"account": "[email protected]",
"project": "construct-498201",
"run_region": "us-central1",
"compute_region": "us-central1"
}
],
"error": null
}

POST /api/gcloud/configs는 새 설정을 생성하고(gcloud config configurations create --no-activate) 제공된 속성을 설정합니다.

POST /api/gcloud/configs
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "my-config",
"project": "my-gcp-project",
"account": "[email protected]",
"run_region": "us-central1",
"compute_region": "us-central1"
}
필드필수 여부참고
nameASCII 영숫자와 -, _, .; 문자 또는 숫자로 시작해야 함; 최대 64자
projectGCP 프로젝트 ID (core/project)
account아니요계정 이메일 (core/account)
run_region아니요Cloud Run 리전 (run/region)
compute_region아니요컴퓨트 리전 (compute/region)

성공 시 응답은 생성된 GcloudConfigSummary201입니다. 중복 이름은 409를 반환하고, gcloud 바이너리가 없으면 503(gcloud_not_found 코드)을 반환하며, 잘못된 입력은 특정 코드와 함께 400을 반환합니다(예: gcloud_config_invalid_name).

메서드 및 경로인증용도
GET /api/cost없음비용 요약 및 예산 상태
POST /api/cost/usage서비스 토큰사이드카 토큰 사용량을 원장에 수집
GET /api/auditbearer최근 감사 이벤트 (필터링 가능)
GET /api/audit/verifybearer감사 해시 체인 검증
GET /api/clawhub/searchbearerClawHub 스킬 검색
GET /api/clawhub/trendingbearerClawHub 트렌딩 스킬
GET /api/clawhub/skills/{slug}bearerClawHub 스킬 상세 정보
POST /api/clawhub/install/{slug}bearer로컬 Kumiho에 스킬 설치
GET /api/auth/profilesbearer자격 증명 프로필 메타데이터 목록 조회
POST /api/auth/profilesbearer정적 토큰 자격 증명 프로필 생성
DELETE /api/auth/profiles/{id}bearer자격 증명 프로필 삭제
POST /api/auth/profiles/{id}/resolve서비스 토큰자격 증명 복호화 및 반환
GET /api/gcloud/configsbearergcloud 설정 프로필 목록 조회
POST /api/gcloud/configsbearergcloud 설정 프로필 생성