Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
halo-record — AI 에이전트를 위한 변조 방지 감사 추적: 해시 체인 방식의 런타임 레코드, 의존성 없음, 누구나 검증 가능. | Kitploit
도구/GitHubGitHub/bkuan001/halo-record
ForensicsSupply Chain SecurityIncident ResponseAI Security
GitHubbkuan001/halo-record

halo-record

AI 에이전트를 위한 변조 방지 감사 추적: 해시 체인 방식의 런타임 레코드, 의존성 없음, 누구나 검증 가능.

저장소 보기웹사이트
6366618시간 10분 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

halo-record

변조 감지 가능한 AI 에이전트용 감사 추적 — 해시 체인으로 연결된 Runtime Record를 고객이 직접 확인할 수 있는 Runtime Report로 렌더링합니다.

에이전트가 수행하는 모든 작업(도구 호출, 모델 호출, 데이터 접근, 승인)은 추가 전용(append-only) 해시 체인 로그의 하나의 Runtime Record가 되며, Runtime Report는 그 체인을 자체 검증 가능한 HTML 페이지로 렌더링한 것입니다. 체인의 체크포인트를 보유한 누구든지 이를 생산한 주체를 신뢰하지 않고도 그 뒤의 레코드가 변경되지 않았음을 검증할 수 있습니다 — 그 체크포인트가 핵심 요소입니다. 체인 자체만으로는 기록기를 운영하는 주체를 제외한 모든 이에 대해 변조 감지가 가능합니다(LIMITS.md §1). 고객의 보안 팀이 "귀하의 에이전트가 우리 데이터로 무엇을 했습니까?"라고 물을 때, 문단 대신 링크 하나를 건네면 됩니다. 보안 검토는 이미 SOC 2 체크리스트 옆에서 AI 관련 질문을 던지고 있으며, 점점 더 그 질문들은 ISO 42001, EU AI Act의 기록 보존 조항, 그리고 고객 자체 설문지에서 나옵니다. 오늘날에는 서면 보증서만으로도 통과됩니다. 이 프로젝트의 배팅은 그것이 오래가지 않으리라는 것입니다.

Help Net Security 에 소개됨 (2026년 8월).

레코드 형식은 개방되어 있으며 자유롭게 구현할 수 있습니다. 이 패키지는 참조 구현입니다: 기록기, 검증기, 증인 클라이언트, 보고서 서버.

halo-record를 사용 중이거나 고려 중이신가요? 누구이며 무엇을 위해 사용하는지 알려주세요 → Who's using halo-record?

직접 확인하세요

에이전트 내부에 기록기를 설치하라는 요청을 받고 있습니다. 그것을 믿음으로 받아들여서는 안 됩니다:

  • 런타임 의존성 제로. 표준 라이브러리만 사용합니다. pip install halo-record는 정확히 하나의 패키지만 설치합니다.
  • 네트워크 호출 없음, 단 세 가지 옵트인 호출 제외 — 증인에 대한 앵커링(대상 ID, 레코드 수, 두 개의 체인 지문 — 헤드와 체인 루트 — 를 전송), 증인의 체크포인트 다시 읽기(대상 ID 전송), 그리고 RFC 3161 타임스탬프(체크포인트의 상태 해시만 Timestamp Authority에 전송). 모두 직접 호출하지 않는 한 비활성화되어 있으며, 레코드 내용은 절대 인프라를 벗어나지 않습니다.
  • 원시 도구 인수는 해시되며, 함께 마스킹된 요약이 제공됩니다. 인수는 정규화된 해시와 요약으로 저장됩니다: 알려진 비밀 및 PII 패턴이 마스킹된 인수 텍스트로, 200자로 제한됩니다. 어떤 패턴에도 일치하지 않는 짧은 입력은 요약에 전체가 나타납니다. 해시 전용 모드(summaries=False)는 요약을 전혀 남기지 않습니다. 마스킹은 최선의 노력(일반적인 비밀 및 PII 형식에 대한 정규식과 엔트로피 포괄 규칙)이므로, 심층 방어로 취급하고 보장으로 여기지 마십시오. summary 외에 제공하는 결과 필드는 주어진 그대로 봉인됩니다(LIMITS §13).
  • 감사하기에 충분히 작음. 약 5,300줄의 Python(공백과 주석을 제외한 코드 줄 수). 오후 한나절이면 전부 읽을 수 있습니다.
  • Apache-2.0.
  • 문서가 일급 시민입니다. LIMITS.md(체인이 증명할 수 없는 것), PRIVACY.md(레코드에 포함되는 내용과 머신을 떠나는 것), RETENTION.md(보존 정책 하에서의 운영), 그리고 REVIEWERS.md — 4개 명령의 독립 검사와 검토 결과를 위한 인용 형식.

각 계층이 증명하는 것 — 이 프로젝트의 핵심 구분(LIMITS.md §1): 직접 보유한 체인은 이미 누군가가 보유한 헤드를 기준으로 레코드가 편집되지 않았음을 증명합니다. 운영자 외부에 보관된 체크포인트만이 어떤 것도 제거되지 않았음을 증명합니다. 그리고 어떤 해시도 모든 작업이 포착되었음을 증명하지 못합니다.

설치 전에 하나 보기: 샘플 Runtime Report — 가상 데이터, 실제 체인, 그리고 지켜보는 동안 브라우저에서 스스로 재검증됩니다.

60초 데모

에이전트가 필요하지 않습니다. uv를 사용하면 설치할 것이 없습니다:``` uvx --from halo-record halo demo --serve

root@kitploit:~
또는 고전적인 방식:```
pip install halo-record
halo demo --serve

둘 중 하나는 두 고객을 둔 가상의 지원 에이전트 벤더를 스캐폴딩하고, 체인을 목격하며(운영자 외부의 한 곳을 대신하는 로컬 witness 파일 포함 — LIMITS.md §1 참조), 게이트가 적용된 Runtime Reports를 제공하고, 브라우저에서 운영자 콘솔을 엽니다. 그런 다음 변조 테스트를 시도해 보세요: .jsonl 파일 중 하나에서 한 줄을 삭제하고 다시 로드하세요. 보고서가 이를 잡아냅니다.

자신만의 에이전트 기록하기

경계에서 한 줄:```python from halo_record import trace

agent = trace(run_my_agent, profile="my-agent", log="audit.jsonl") # wraps your entrypoint; records the run boundary to ./audit.jsonl — add record_call() or a framework adapter at each tool boundary to capture individual calls

root@kitploit:~
`from halo import ...` 편의 심(shim)도 함께 제공되지만, PyPI의 `halo` 이름은 무관한 터미널 스피너 패키지에 속해 있으며, 해당 패키지가 설치되어 있으면 임포트에서 우선권을 가진다. `halo_record`는 모호하지 않으므로 예제에서는 이를 사용한다.

`log=`가 없으면 레코드는 `~/.halo/my-agent.jsonl`로 간다(에이전트당 체인 하나). 래퍼는 실행 경계를 봉인하며, 증거는 호출별 레코드에 남는다. 이를 프레임워크 어댑터(아래 매트릭스)로 캡처하거나 — 명시적으로 캡처할 수도 있으며, 이는 위임 링크가 어떻게 연결되는지도 보여준다:```python
from halo_record import Recorder, record_call

rec = Recorder("audit.jsonl")

with record_call(rec, "crm.lookup", {"account": "acct-9"}) as call:            # one sealed record per tool call
    call.result = crm.lookup("acct-9")

with record_call(rec, "payments.refund", {"amount": 120},
                 parent_id=rec.last_record_id()) as call:                      # child links to the action that spawned it
    call.result = payments.refund(120)

그런 다음 보고서를 렌더링합니다:``` halo report audit.jsonl -o report.html # one chain -> self-verifying HTML halo serve ./records --port 8721 # all tenants, gated per customer

root@kitploit:~
quickstart는 브라우저에서 자신의 에이전트 Runtime Report를 보고 있을 때 끝납니다. JSONL 파일만 받고 보고서를 받지 못했다면 뭔가 잘못된 것입니다: 이슈를 열어주세요.

### 검증 블록

가드레일이나 정책 계층이 해당 작업을 검사했다면, 그 판정이 레코드에 실릴 수 있습니다 — 게이트가 무엇을 결정했는지 기록하는 선택적 블록으로, 다른 모든 필드와 마찬가지로 해시 체인에 봉인됩니다:```python
from halo_record import build

build("tool_call", "security", tool="payments.refund",
      verification={"status": "allowed", "verifier": "gate/1.2",
                    "policy_ref": "sha256:1f3a...",
                    "checked_at": "2026-08-01T12:00:00Z"})

레코드에 다음과 같이 봉인됩니다:```json "verification": {"status": "allowed", "verifier": "gate/1.2", "policy_ref": "sha256:1f3a...", "checked_at": "2026-08-01T12:00:00Z"}

root@kitploit:~
`record_call(...)`은 동일한 `verification=` 키워드를 받습니다. `status`는 블록 내에서 필수이며, `verifier`, `policy_ref`, `checked_at`은 선택 사항입니다. 각 상태의 의미는 다음과 같습니다:

| 상태 | 게이트가 보고하는 내용 | 작업이 실행되었는가? |
|---|---|---|
| `allowed` | 작업을 허용함 | 예 — 작업이 진행됨 |
| `blocked` | 작업을 거부함 | 이 필드가 아니라 통합에 의해 결정됨 — 레코드가 여전히 결과를 담고 있을 수 있으며, 차단만으로는 미실행을 입증하지 못함 |
| `modified` | 실행 전에 작업을 변경함 — `action.input`은 수정 후 **실행된 대로**의 작업을 설명함 | 예, 변경된 형태로 |
| `unverified` | 실행되었으나(또는 참조되었으나) 판단을 내리지 않음 — 검증 주장이 전혀 이루어지지 않았음을 의미하는 블록 부재와는 구별됨 | 예 — 판정 없이 작업이 진행됨 |

이 블록은 운영자의 통합 코드에 의해 제공되며, 게이트가 말했다고 보고하는 내용을 기록합니다 — `principal`과 동일한 신뢰 태세입니다([LIMITS](https://github.com/bkuan001/halo-record/blob/main/LIMITS.md#11-verification-status-is-the-gates-report-not-halos-finding) 참조). 봉인은 상태가 사후에 편집되지 않았음을 증명하지만, 검사가 발생했는지, 판정이 올바른지, 또는 차단된 작업이 실행되지 않았는지는 증명하지 않습니다. 이는 독립적인 검증이 아닙니다.

`policy_ref`를 증거로 사용할 수 있으려면 규칙 세트의 콘텐츠 해시를 사용하고 규칙 세트 아티팩트를 보관하십시오 — 해석할 수 없는 레이블은 해당 필드를 장식적으로 만듭니다.

## 이미 실행 중인 것에 연결하기

| 경계에서 캡처됨 | 기존 텔레메트리에서 수집됨 |
|---|---|
| 네이티브 레코더 (`from halo_record import trace`) | OpenTelemetry GenAI 스팬 |
| MCP 인터셉터 | LiteLLM 콜백 |
| LangChain / LangGraph 콜백 | Langfuse 내보내기 |
| OpenAI Agents SDK 훅 | 모든 게이트웨이 / 리버스 프록시 로그 |
| Claude Agent SDK 훅 | Claude Code 및 Codex CLI `PostToolUse` 훅 (도구 실행 후 발동) |

프레임워크 어댑터와 수집 경로는 각 레코드에 `source` 태그를 찍으므로, 보고서는 각 증거가 어떻게 수집되었는지 공개합니다. 캡처된 레코드와 수집된 레코드는 동일한 체인에 존재합니다.

LangChain / LangGraph의 경우, 이는 콜백 핸들러입니다:```python
from halo_record import Recorder
from halo_record.integrations.langchain import HaloCallbackHandler

recorder = Recorder("audit.jsonl")
result = my_chain.invoke(inputs, config={"callbacks": [HaloCallbackHandler(recorder)]})   # every tool call becomes a record

MCP의 경우, 하나의 호출이 클라이언트 세션을 감싸며 — 그러면 어떤 MCP를 사용하는 에이전트든, 어떤 프레임워크가 구동하든 관계없이 모든 도구 호출에 대해 레코드를 내보냅니다:```python from halo_record.integrations.mcp import instrument_client_session

instrument_client_session(session, Recorder("audit.jsonl"), server="stripe") # every session.call_tool() is now recorded

root@kitploit:~
게이트웨이 또는 프록시 로그(Cloudflare AI Gateway, Portkey, 모델 앞단의 nginx)의 경우, 로그 행을 체인에 매핑합니다 — 경계에서 캡처된 것이 아니라 수집된 것으로 명시적으로 태그됩니다:```python
from halo_record.integrations.gateway import record_log

record_log(Recorder("audit.jsonl"), {"tool": "gen_ai:gpt-4o", "model": "gpt-4o", "status": 200, "subject": "acme-corp"})

OpenTelemetry GenAI 스팬을 생성하는 모든 것(CrewAI, LlamaIndex, OTel 계측이 적용된 대부분의 에이전트 프레임워크)은 OTel 어댑터를 통해 체인에 들어오며, TypeScript 패키지는 Vercel AI SDK와 JS 에이전트 생태계를 위한 네이티브 어댑터를 제공합니다. 여러분의 스택에 맞는 어댑터가 없다면 이슈를 열어주세요. 대부분의 어댑터는 약 100줄 정도입니다.

코딩 에이전트 기록하기 (Claude Code 또는 Codex)

Claude Code는 모든 도구 호출 후에 PostToolUse 훅을 발생시킵니다. 이를 halo hook으로 지정하면 각 작업 — 파일 쓰기, 셸 명령, MCP 커넥터 호출 — 이 로컬 체인의 레코드가 됩니다. 코드 변경 없이 설정 항목 하나만 추가하면 됩니다:```json { "hooks": { "PostToolUse": [ {"matcher": "*", "hooks": [{"type": "command", "command": "halo hook"}]} ] } }

root@kitploit:~
`~/.claude/settings.json`에 추가하면 레코드가 `~/.halo/audit.jsonl`에 기록됩니다(`$HALO_LOG`로 재정의 가능). 데이터, 네트워크, 외부 상태에 접근하지 않는 순수 오케스트레이션 도구는 건너뜁니다 — 이 체인은 사고가 아니라 신뢰 경계를 넘는 행위를 기록합니다. `HALO_HASH_ONLY=1`을 설정하면 요약 없이 콘텐츠 해시만 기록합니다. `HALO_AGENT_VERSION`(그리고 선택적으로 `HALO_AGENT_MODEL`)을 설정하면 모든 레코드를 이를 생성한 에이전트 빌드에 바인딩합니다 — 감사자가 특정 기간에 실행 중이던 버전을 물을 때, 내보내기는 기억이 아니라 컬럼으로 답합니다.

Codex CLI는 동일한 이벤트 형태로 동일한 라이프사이클 훅을 제공합니다(훅은 기본적으로 활성화됨). 다음을 `~/.codex/hooks.json`에 추가하면 Codex의 셸 명령, `apply_patch` 편집, MCP 호출이 동일한 체인에 기록됩니다:```json
{
  "hooks": {
    "PostToolUse": [
      {"matcher": ".*", "hooks": [{"type": "command", "command": "halo hook"}]}
    ]
  }
}

훅은 이벤트 자체와 두 가지를 구분하며(Codex는 turn_id와 model을 추가함) 각 레코드에 claude-code 또는 codex라고 라벨을 붙입니다. HALO_HOOK_AGENT를 설정하면 하나를 강제할 수 있습니다. 둘 다 수집 계층입니다. PostToolUse 훅은 도구가 실행된 후에 발생하므로, 레코드는 하네스가 보고하는 내용으로부터 구성됩니다.

보고서가 "이 실행이 어떤 규칙 아래에서 발생했는가?"에 답하기를 원한다면, HALO_AUTHORITY_FILE을 세션의 유효 권한에 대한 JSON 스냅샷으로 설정하십시오. 프라이버시를 안전하게 유지하십시오. 원시 프롬프트, 비공개 정책 텍스트, 시크릿, 전체 도구 스키마가 아니라 해시와 참조를 사용하십시오. 알려진 시크릿 형식은 봉인 시점에 마스킹되지만, 해시와 참조는 그대로 통과하며 자유 형식 텍스트는 감지되지 않습니다(LIMITS §6 참조). snapshot_id는 기반 권한이 변경되지 않은 동안에만 재사용하십시오. 동일한 id와 변경되지 않은 내용을 가진 연속 레코드는 압축됩니다. 변경된 내용에 대해 재사용된 id는 전체가 저장되며, 이때 고지가 함께 표시됩니다.```json { "snapshot_id": "auth_2026_07_08T1100Z", "captured_at": "2026-07-08T11:00:00Z", "scope": "session", "workspace": {"path_hash": "sha256:...", "git_commit": "abc1234"}, "refs": [ {"kind": "project_rules", "id": "CLAUDE.md", "hash": "sha256:...", "loaded": true, "truncated": false}, {"kind": "mcp_tool_registry", "id": "filesystem", "hash": "sha256:..."} ], "omissions": [{"kind": "private_policy", "reason": "customer_secret", "hash": "sha256:..."}], "stale_if": ["project_rules_hash_changed", "mcp_tool_registry_hash_changed"] }

root@kitploit:~
| `-s` | `--server` | `SERVER` | `http://localhost:8080` | 서버 URL |
| `-t` | `--token` | `TOKEN` | | 인증 토큰 |
| `-o` | `--output` | `OUTPUT` | | 출력 파일 |
| `-f` | `--format` | `FORMAT` | `json` | 출력 형식 |
| `-v` | `--verbose` | | | 상세 출력 |
| `-q` | `--quiet` | | | 조용한 모드 |
| `-h` | `--help` | | | 도움말 표시 |
| `-V` | `--version` | | | 버전 표시 |

### 예제

```bash
# 기본 사용법
tool --server http://localhost:8080

# 인증 포함
tool --server http://localhost:8080 --token abc123

# 출력 형식 지정
tool --output results.json --format json

# 상세 모드
tool --verbose --server http://localhost:8080

설정

설정 파일

설정 파일은 다음 위치에서 찾을 수 있습니다:

  1. ./config.yaml
  2. ~/.config/tool/config.yaml
  3. /etc/tool/config.yaml

환경 변수

설정 예제

root@kitploit:~
server: http://localhost:8080
token: your-token-here
format: json
verbose: false
timeout: 30

# 고급 설정
advanced:
  retry_count: 3
  retry_delay: 5
  max_connections: 10

문제 해결

일반적인 문제

연결 거부됨

서버가 실행 중이고 지정된 포트에서 수신 대기 중인지 확인하세요:

root@kitploit:~
# 서버가 실행 중인지 확인
curl http://localhost:8080/health

# 포트가 사용 중인지 확인
netstat -tulpn | grep 8080

인증 실패

토큰이 유효하고 만료되지 않았는지 확인하세요:

root@kitploit:~
# 토큰 확인
tool --server http://localhost:8080 --token $TOKEN --verbose

권한 거부됨

파일 권한을 확인하세요:

root@kitploit:~
# 파일 권한 확인
ls -la /path/to/file

# 권한 수정
chmod 644 /path/to/file

디버그 모드

디버그 로깅을 활성화하려면:

root@kitploit:~
# 환경 변수 사용
export TOOL_DEBUG=true
tool --server http://localhost:8080

# 또는 명령줄 플래그 사용
tool --debug --server http://localhost:8080

로그

로그는 다음 위치에 저장됩니다:

  • Linux: ~/.local/share/tool/logs/
  • macOS: ~/Library/Logs/tool/
  • Windows: %APPDATA%\tool\logs\

기여

기여를 환영합니다! 풀 리퀘스트를 제출하기 전에 다음 지침을 읽어주세요.

개발 환경

root@kitploit:~
# 저장소 복제
git clone https://github.com/example/tool.git
cd tool

# 가상 환경 생성
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate

# 의존성 설치
pip install -r requirements.txt
pip install -r requirements-dev.txt

# 테스트 실행
pytest tests/

코드 스타일

  • Python 코드에는 PEP 8을 따릅니다
  • 커밋 전에 black과 flake8을 실행하세요
  • 모든 새로운 기능에 대해 테스트를 작성하세요
  • 필요에 따라 문서를 업데이트하세요

풀 리퀘스트 프로세스

  1. 저장소를 포크하세요
  2. 기능 브랜치를 생성하세요 (git checkout -b feature/amazing-feature)
  3. 변경 사항을 커밋하세요 (git commit -m 'Add amazing feature')
  4. 브랜치에 푸시하세요 (git push origin feature/amazing-feature)
  5. 풀 리퀘스트를 여세요

버그 보고

버그를 보고할 때 다음을 포함하세요:

  • 운영 체제 및 버전
  • Python 버전
  • 도구 버전
  • 문제를 재현하는 단계
  • 예상 동작
  • 실제 동작
  • 관련 로그 또는 오류 메시지

라이선스

이 프로젝트는 MIT 라이선스에 따라 라이선스가 부여됩니다. 자세한 내용은 LICENSE 파일을 참조하세요.

감사의 글

  • 이 프로젝트에 기여한 모든 분들께 감사드립니다
  • 오픈소스 커뮤니티에 감사드립니다
  • 영감과 지원을 주신 모든 분들께 감사드립니다

연락처

  • 저자: Your Name
  • 이메일: [email protected]
  • GitHub: @yourusername
  • 웹사이트: https://example.com

지원

이 프로젝트가 유용하다고 생각되시면:

  • ⭐ 저장소에 별을 눌러주세요
  • 🐛 버그를 보고해주세요
  • 💡 새로운 기능을 제안해주세요
  • 📖 문서를 개선해주세요
  • ☕ 개발자에게 커피를 사주세요

면책 조항: 이 도구는 교육 및 테스트 목적으로만 제공됩니다. 자신이 소유하거나 테스트 권한이 있는 시스템에서만 사용하세요. 무단 접근은 불법이며 비윤리적입니다.```sh HALO_AUTHORITY_FILE=./authority.json halo hook

root@kitploit:~
스냅샷은 액션 레코드와 동일한 해시 체인에 봉인됩니다. 좋은 기본값은 시작 시 세션 수준 스냅샷 하나를 만들고, 규칙, Skills, 훅, MCP 도구 레지스트리 또는 컴팩션 정책이 변경될 때 새 스냅샷을 만드는 것입니다. 긴 세션을 간결하게 유지하기 위해 동일한 `authority.snapshot_id`를 가진 연속 레코드는 첫 번째 전체 스냅샷 이후에 컴팩션됩니다. 이후 레코드는 `{"snapshot_id": "...", "same_as_previous": true}`만 유지합니다. 포인터는 해시 체인으로 유지되지만, 부피가 큰 refs/omissions/stale-if 블록은 모든 액션마다 반복되지 않습니다. (컴팩션은 레코더 프로세스별로 이루어집니다. 도구 호출마다 하나의 프로세스를 생성하는 훅 스타일 캡처는 이전 전체 스냅샷이 꼬리 레코드가 아닐 때마다 전체 본문을 다시 저장하므로, 단명 프로세스는 재사용 가드를 위해 체인 크기를 희생합니다.)

SDK 사용자는 동일한 블록을 직접 붙입니다 — `build(..., authority={...})` 또는 `record_call(..., authority={...})`; 해시 전용 캡처도 동일한 표면입니다(이들 중 어느 것이든 `summaries=False`):```python
from halo_record import Recorder, record_call

rec = Recorder("audit.jsonl")
with record_call(rec, "crm.lookup", {"account": "acct-9"},
                 authority={"snapshot_id": "auth_1", "rules_hash": "sha256:..."},
                 summaries=False) as call:              # hash-only: no summaries, no excerpts
    call.result = crm.lookup("acct-9")

그런 다음, 평소처럼:``` halo verify ~/.halo/audit.jsonl halo report ~/.halo/audit.jsonl -o report.html

root@kitploit:~
post-action 훅을 노출하는 모든 에이전트 런타임은 동일한 명령을 공급할 수 있습니다 — 훅은 stdin으로 JSON 형식의 이벤트 하나를 읽고 레코드 하나를 추가합니다.

하나의 체인, 한 번에 하나의 작성자. 체인은 연결 리스트입니다: 같은 head를 읽고 둘 다 추가하는 두 작성자는 체인을 분기시키며(같은 선행자를 주장하는 두 레코드), 검증은 영향을 받은 레코드의 이름을 밝힙니다. `Recorder`는 사이드카 잠금(여기서는 POSIX `flock`; TypeScript 패키지에서는 잠금 디렉터리)으로 자체 추가를 직렬화하며, `halo hook`은 `Recorder`를 통해 추가하므로 위의 훅 설정은 보호됩니다. 체인 파일에 직접 쓰는 모든 것 — 직접 만든 훅, 병렬 워커, 로그 전송기 — 은 head 읽기 후 추가 시퀀스 전반에 걸쳐 동등한 배타적 잠금을 보유하거나 프로세스별 체인에 기록해야 합니다. [LIMITS.md 섹션 9](https://github.com/bkuan001/halo-record/blob/main/LIMITS.md#9-single-writer-chains)는 언어 간 경계를 포함하여 이 내용을 전부 다룹니다.

## 기록이 실패할 때

두 통합 스타일은 의도적으로 반대 방향으로 실패합니다 — 감당할 수 있는 실패를 선택하세요:

- **프레임워크 어댑터(LangChain, 콜백 관리자를 통한 훅)는 열린 상태로 실패합니다.** 레코드를 쓸 수 없으면(디스크 가득 참, 권한), 에이전트의 작업은 정상적으로 완료되고 레코드는 손실됩니다. LangChain 핸들러는 stderr에 큰 경고를 출력하고 손실을 집계하지만(`handler.lost_records`), 체인 자체에서는 결코 기록되지 않은 레코드를 보여줄 수 없습니다 — 멈춘 체인도 여전히 검증됩니다. 주기적인 witness 체크포인트가 멈춘 체인을 가시화합니다: 도착하지 않는 예상 체크포인트가 경보입니다.
- **네이티브 `trace()` 래퍼는 닫힌 상태로 실패합니다.** 레코드를 쓸 수 없으면 예외가 에이전트의 작업으로 전파됩니다 — 증거 없으면 작업도 없습니다. 더 엄격하며, 에이전트를 중단시킬 수 있습니다.

어느 기본값도 모든 사람에게 맞지는 않습니다; 자신이 어느 것을 실행 중인지 알아두세요.

## 무결성 vs. 완전성 (이 부분을 읽으세요)

각 계층이 무엇을 증명하는지 정확히 파악하세요 — 서로 다른 주장이며, 그 차이가 핵심입니다:

자체 보유 체인은 **확립된 head에 대한 무결성**을 증명합니다: 누군가 이미 보유한 체인 head가 주어지면, 그 뒤의 레코드에 대한 모든 편집, 재정렬, 삭제가 탐지 가능해집니다. 그 자체로 — 운영자 외부의 누군가가 head를 보기 전에는 — 체인은 내부 일관성을 증명할 뿐, 이력을 증명하지 않습니다: 운영자는 레코드를 삭제하고 다시 봉인할 수 있으며, 새 파일은 검증을 통과합니다. 체인은 그 head가 운영자의 통제를 벗어나는 순간 **역사적으로 커밋**됩니다.

그것이 witness입니다: 체인의 주기적 체크포인트를 보유한 운영자 외부의 당사자 — subject id, 레코드 수, 두 개의 체인 지문(head와 체인 루트); 정확한 페이로드, 그 외에는 아무것도. 체크포인트는 커밋된 이력의 재작성을 탐지 가능하게 만들며, 놓친 체크포인트 자체가 가시적인 이벤트입니다:```
halo anchor audit.jsonl witness.jsonl           # anchor a checkpoint to a local witness
halo anchor audit.jsonl witness.jsonl --check   # completeness verdict against it

특히 시간의 경우, 외부 RFC 3161 타임스탬프는 체크포인트가 스스로 주장하는 시계를 운영자가 통제하지 않는 Timestamp Authority의 증명으로 대체합니다 — "이 체인은 늦어도 T 시점에 이 헤드에 도달했다"는 것으로, 호스팅 인프라 없이 제3자가 검증할 수 있습니다. 기본 TSA는 무료 freetsa.org(평가용으로 적합)이며, 프로덕션에서는 --tsa로 상용 TSA(DigiCert / Sectigo / 자체 TSA)를 지정하십시오:``` halo anchor audit.jsonl witness.jsonl --timestamp # attach a TSA time proof to the checkpoint halo anchor audit.jsonl witness.jsonl --check # reads the token's claimed time

root@kitploit:~
`--check`는 토큰이 이 체인 상태에 바인딩되어 있는지 확인하고 증명된 시간을 읽지만, TSA의 서명을 **검증하지는 않습니다** — 이는 의도적으로 표준 도구에 맡겨, 검토자가 우리 코드를 신뢰하지 않도록 한 것입니다. 시간을 독립적으로 검증하려면(보안 검토자에게 건네는 것이 바로 이것입니다):```
# tsa.token_b64 lives in the witness log; decode the latest one to a standard .tsr file
python3 -c 'import json,base64; cps=[json.loads(l) for l in open("witness.jsonl") if l.strip()]; t=[c["tsa"] for c in cps if c.get("tsa")][-1]; open("token.tsr","wb").write(base64.b64decode(t["token_b64"])); print(t["digest"])'
curl -s -o tsa-ca.pem https://freetsa.org/files/cacert.pem     # CA for the default TSA (a commercial TSA publishes its own)
openssl ts -verify -digest <the digest printed above> -in token.tsr -CAfile tsa-ca.pem   # → "Verification: OK"

또 하나의 경계를 분명히 말하자면, 체인도 증인도 모든 실제 행동이 기록기를 통과했다는 것을 증명하지는 않는다. 그것은 캡처 완전성(capture completeness) — 기록기가 스택 어디에 위치하는지(네이티브 계측, 훅, 게이트웨이 수집)에 관한 속성이지, 어떤 해시의 속성도 아니다. 기록에 source 태그가 붙는 이유가 바로 이것이다. 이 페이지 상단의 "직접 확인하기" 아래에 있는 주장 표가 이 세 계층을 요약한 것이다.

누구나 증인을 운영할 수 있다. 직접 운영하는 증인은 이력을 당신에게 귀속시킨다. 그것을 당신의 고객에게 귀속시키려면 고객이 신뢰할 만한 이유가 있는 증인이 필요하다. 어느 쪽이든 프로토콜은 열려 있다.

호스팅되고 공인된 증인이 이 프로젝트가 자립하는 방식이다. 얼리 액세스: [email protected].

체인 내의 개인 데이터

체인은 추가 전용(append-only)이다. 기록에 봉인된 것은 무엇이든 그대로 남는다. 왜냐하면 그것을 제거하면 그 이후의 모든 것에 대한 검증이 깨지기 때문이다. 도구 인수는 이미 처리되어 있다 — 해시와 200자로 제한된 마스킹된 요약으로 저장된다(해시 전용 모드에서는 요약을 보관하지 않는다).

그 문장의 한계에 주목하라: 마스킹된, 제거된 것이 아니다. LIMITS.md 섹션 6은 이름이나 우편 주소에는 신뢰할 만한 패턴이 없어서 둘 다 탐지되지 않고 둘 다 마스킹되지 않는다고 명시한다. 그리고 subject는 당신이 제공하는 텍스트를 담는 유일한 필드가 아니다 — principal, approver, session_id, agent, authority, data 그리고 모든 요약도 마찬가지다.

효과가 있는 패턴: 체인에는 안정적인 가명 id를 넣고, 개인과의 매핑은 삭제할 수 있는 시스템에 보관하라. 그러면 삭제 요청은 매핑을 삭제함으로써 충족된다. subject는 사람이 아니라 테넌트 조직을 가리키도록 유지하라:```python from halo_record import build

build("tool_call", "privacy", subject={"id": "acme", "name": "Acme Corp"})

root@kitploit:~
이를 강제하는 설정은 없습니다 — 기록기를 어떻게 호출하는지에 관한 규율입니다.
이는 삭제를 다루기 쉽게 만들 뿐이며, 익명화가 아니고, 아직 내장된
보존 기간이나 정리 기능도 없습니다.
[LIMITS.md 섹션 13](https://github.com/bkuan001/halo-record/blob/main/LIMITS.md#13-personal-data-and-erasure)에 전체 필드
목록이 있고, 매핑이 사라진 뒤에도 저장된 입력 지문이 추측 가능한 값을 확인할 수 있는
이유를 설명하며, 검토자가 물어야 할 질문들로 끝맺습니다.

모델 호출을 기록하세요 (구매자의 첫 번째 질문: "어떤 모델이 내 데이터를 보았나?"):```python
from halo_record import record_model_call

record_model_call(rec, provider="anthropic", model="claude-sonnet-4-6",
                  zdr=True, purpose="draft support reply",
                  subject="acme")   # tool=model.generate, scope=model:anthropic

컴플라이언스 스택에서의 위치

halo-record는 증거 계층이지 인증이 아닙니다. 이는 평가 프레임워크가 서로 다른 표현으로 계속 요구하는 산출물을 생성합니다. 아래 모든 항목에 적용되는 한 가지 범위 주석: 이는 기록에 대한 무결성 주장이며, 운영자에 대한 완전성은 체크포인트를 보유한 외부 증인이 필요합니다 (LIMITS.md §1).

  • 보안 설문지 및 SOC 2 검토: AI 섹션에 스크린샷과 산문 대신 검증 가능한 Runtime Report로 답변하십시오.
  • AIUC-1: 변조 감지 로깅 증거(E015.4)와 권한 부여 이벤트가 포함된 실행 체인 기록(E015.2 — 명시된 격차 포함: 추론 추적은 캡처되지 않음)을 생성하며, 이는 표준의 Accountability 통제 E015가 명시하는 것입니다. E015 자체는 필수이며, E015.2와 E015.4는 그 보충 계층입니다: 통과에 필수는 아니지만, 고객이나 규제 기관이 요청할 때 벤더가 채택하는 것입니다. 체인이 의존 당사자가 신뢰할 이유가 있는 증인에 앵커링되면 — 운영자가 자체 운영하는 증인은 이를 제공하지 않습니다 — 이는 감사 시점에 재구성되는 것이 아니라 지속적으로 증인된 체인입니다(체인에 입력되는 내용은 여전히 캡처 표면에 의해 제한됩니다). 의도적으로 범위 밖에 있는 항목을 포함한 통제별 증거 매핑은 AIUC.md에 있습니다.
  • OWASP Top 10 for Agentic Applications 2026: 10가지 위협 중 8가지가 기록에 대한 결정론적 정책 규칙에 매핑되고, 2가지는 이유와 함께 범위 밖으로 표시되며, 팩은 실행 가능하게 제공됩니다. 공식 OWASP 산출물이 아닌 대략적인 커뮤니티 매핑입니다. OWASP.md를 참조하십시오.
  • AARM (CSA): AARM이 명시하는 변조 감지 작업 영수증을 생성합니다 — R5, 그리고 R6의 봉인 부분(신원은 해시에 봉인되지만 암호학적으로 인증되지는 않음). halo-record는 영수증 계층이며, 완전한 AARM 시스템을 위해서는 집행 게이트웨이와 함께 사용하십시오. AARM.md를 참조하십시오.
  • Agentic Trust Controls: ATC의 증거 통제 뒤에 있는 런타임 기록 — 변조 감지 작업 로깅(RBM-03)과 권한 증명의 기록 부분(AID-05; 집행 부분은 게이트에 속함)을 하나의 체인된 기록으로. ATC.md를 참조하십시오.
  • CSA AI Controls Matrix (AICM) / STAR for AI: LOG 도메인 증거 — 감사 기록 생성, 미탐지 수정에 대해 봉인, 입력 및 출력 이벤트 로깅 — 이 AICM.md에 통제별로 매핑되어 있습니다. CSA 자체의 v1.1 크로스워크는 해당 도메인을 AIUC-1 E015에 연결합니다.
  • MITRE ATLAS: 에이전트 텔레메트리 완화(AML.M0024)를 ATLAS 자체가 요구하지 않는 무결성 속성으로 구현 — 로그는 운영자 외부의 누군가가 검증할 수 있습니다. 를 참조하십시오.

이 중 어느 것도 그 자체로 인증하지 않습니다. 이는 평가자가 검증 가능한 것을 볼 수 있게 해줍니다. 경계 — halo-record가 의도적으로 하지 않는 것, 그리고 검토자가 물을 때 무엇을 말해야 하는지 — 는 LIMITS.md에 문서화되어 있습니다.

GRC 플랫폼에 증거 가져오기

대부분의 GRC 플랫폼(Vanta, Drata 및 유사 제품)은 업로드된 파일을 통제에 대한 사용자 정의 증거로 수용합니다. halo-record의 내보내기는 해당 흐름에 바로 들어가도록 구축되었습니다:```bash halo export audit.jsonl --from 2026-06-01 --to 2026-06-30 -o evidence.csv

scope the export to the actions a control covers

halo export audit.jsonl --from 2026-06-01 --to 2026-06-30 --tool email.send --tool db.query -o evidence.csv

root@kitploit:~
이것은 감사 창(audit window)에 대해 두 개의 파일을 작성합니다: CSV(기록된 각 작업당 한 행으로, 왼쪽에서 오른쪽으로 *언제 → 무슨 일이 있었는지 → 누가 → 어떤 권한으로 → 무엇이 플래그되었는지 → 출처 → 검증 방법* 순으로 그룹화되며, 호출과 그 결과에 대한 수정된 평이한 언어 요약, 각각을 생성한 에이전트 빌드와 모델, 그것이 대신하여 실행된 신원, 그것을 유발한 레코드, 그 승인 결정과 범위, 그리고 모든 개인 데이터 범주 또는 수집된 위협 플래그를 포함합니다)와 CSV를 그 출처에 연결하는 매니페스트(`evidence.csv.manifest.json`)입니다 — 체인의 헤드 해시는 그것을 그것이 나온 검증 가능한 로그에 연결하고, `csv_sha256`은 내보낸 파일 자체의 해시이므로, 내보낸 후 편집된 CSV는 더 이상 매니페스트와 일치하지 않습니다. 통제가 특정 작업만을 포괄할 때는 `--tool`로 모집단을 좁히십시오; 매니페스트는 필터를 기록하므로, 범위가 지정된 내보내기는 전체 모집단으로 읽히는 대신 그것이 부분집합임을 공개합니다. 둘 다 로깅 또는 모니터링 통제에 대해 업로드하십시오; 검토자가 체인을 직접 검증하고자 할 때는 Runtime Report HTML을 첨부하십시오. 내보내기는 검증에 실패한 체인에서는 실행을 거부합니다.

네이티브 푸시 통합 — 증거가 귀하의 플랫폼에 자동으로 도착하는 것 — 은 로드맵에 있습니다. 위의 파일 경로는 업로드된 증거를 수용하는 모든 플랫폼에서 오늘날 작동합니다.

## CLI```
halo verify   validate schema + hash chain (exit 1 broken, 3 empty chain; CI-friendly)
halo report   render a chain as a self-verifying HTML Runtime Report
              (--from/--to: a date-windowed report covering only the review period)
halo policy   corroborate a chain against a declarative policy pack
              (per-rule pass / violation / evidence-gap; exit 1 violated, 3 nothing in scope)
halo serve    serve per-tenant reports over HTTP, access-scoped per customer
halo grant    designate a report recipient (email or domain)
halo viewers  list who has unlocked a gated report
halo anchor   witness a chain head, or --check completeness (exit 1 incomplete, 3 unwitnessed)
halo witness-serve  run a witness over HTTP: vendors anchor chain heads, viewers fetch checkpoints
halo demo     scaffold the full vendor demo (record -> witness -> gated report)
halo export   date-bounded evidence export: CSV + manifest tied to the chain head
halo sample   emit a valid example log
halo hash     canonical sha256 of a JSON value
halo hook     Claude Code PostToolUse hook

무결성 모델

레코드의 해시를 계산하려면: integrity.hash를 제외하고 integrity.prev_hash를 이전 레코드의 해시로 설정한 레코드를 가져와서, RFC 8785(JSON 정규화 스킴)로 정규화하고, 바이트를 SHA-256으로 해싱한다. 첫 번째 레코드의 prev_hash는 64개의 0이다. 검증은 모든 해시를 다시 계산하고 모든 링크를 확인한다. 비밀은 필요하지 않다. 바로 그게 핵심이다.

검증자가 알아채지 못하게 체인을 조작할 수 있다고 생각하는가? 시도와 결과는 여기에 있다.

전체 필드 참조: halo-record.schema.json.

TypeScript

동일한 레코더가 Node용으로도 제공된다: halo-record-ts. 동일한 체인 형식, 동일한 증인 프로토콜. 어느 언어로 작성된 레코드든 어느 검증기로든 검증된다.

커뮤니티 예제

trail-halo-poc — Halo 레코드의 주체 권한을 TRAIL 자격 증명에 결합하는 커뮤니티 개념 증명: 상호 조직–에이전트 바인딩과 조직 서명 범위 부여가 Halo 체인에 기록되며, 적대적 검증 제품군을 포함한다.

기여

이슈, 토론, 풀 리퀘스트를 환영한다 — 기본 규칙은 CONTRIBUTING.md를 참조하라 (짧은 버전: 테스트 필수, 작은 PR, 스키마 변경은 먼저 논의).

라이선스

Apache-2.0

도구 다운로드
주장자체 보유 체인+ 외부 체크포인트+ 신뢰할 수 있는 포착
확립된 아티팩트에 대한 편집 감지✔✔✔
커밋된 이력의 재작성 감지—✔✔
누락/지연된 체크포인트 감지—✔ (합의된 주기)✔
모든 작업이 기록되었음을 증명——포착 경계에 따라 다름
변수설명기본값
TOOL_SERVER서버 URLhttp://localhost:8080
TOOL_TOKEN인증 토큰
TOOL_FORMAT출력 형식json
TOOL_VERBOSE상세 출력 활성화false
TOOL_TIMEOUT요청 타임아웃 (초)30
ATLAS.md
  • EU AI Act / ISO 42001 / NIST AI RMF: 이러한 프레임워크가 설명하는 기록 보관 및 로깅 의무는 동일한 산출물 클래스입니다 — EU-AI-ACT.md, ISO42001.md, NIST-AI-RMF.md에 보수적으로 매핑되어 있습니다.