> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Core — AT Protocol 코어 조작

> Laravel Bluesky의 Core 모듈. CBOR 인코딩, CID를 통한 내용 검증, CAR 파일 조작, TID를 통한 시계열 레코드 키 생성을 설명합니다.

<Warning>
  Core는 고급 내부 구현입니다. 일반적인 게시·피드 취득·알림 등에는 필요 없습니다. AT Protocol의 데이터 구조를 직접 조작하는 경우에 참조하세요.
</Warning>

## AT Protocol의 데이터 모델 개요

AT Protocol의 저장소는 콘텐츠 주소형 데이터 구조를 채택하고 있습니다. 데이터의 저장·전송·검증에 다음 요소가 사용됩니다.

```mermaid theme={null}
graph TD
    A["PHP 데이터(배열)"] --> B["CBOR 인코드<br>(DAG-CBOR)"]
    B --> C["SHA-256 해시"]
    C --> D["CID<br>(Content Identifier)"]
    D --> E["CAR 파일<br>(블록의 집합)"]
    E --> F["저장소<br>(Merkle Search Tree)"]
```

| 클래스      | 역할               |
| -------- | ---------------- |
| `CBOR`   | 바이너리 직렬화         |
| `CID`    | 콘텐츠 주소(해시 식별자)   |
| `CAR`    | 저장소 아카이브 읽기·쓰기   |
| `TID`    | 시계열 레코드 키        |
| `Varint` | 가변 길이 정수 인코딩(내부) |

***

## CBOR

`CBOR` 클래스는 AT Protocol이 채택한 [DAG-CBOR](https://ipld.io/specs/codecs/dag-cbor/spec/) 형식의 인코드·디코드를 제공합니다. 표준 CBOR의 확장으로 CID 링크(태그 42)를 지원합니다.

### 인코드

```php theme={null}
use Revolution\Bluesky\Core\CBOR;

$record = [
    '$type'     => 'app.bsky.feed.post',
    'text'      => 'Hello, Bluesky!',
    'createdAt' => '2025-01-01T00:00:00.000Z',
];

$bytes = CBOR::encode($record); // 바이너리 문자열
```

### 디코드

```php theme={null}
use Revolution\Bluesky\Core\CBOR;

// 단일 아이템 디코드
$data = CBOR::decode($bytes);

// 스트림의 첫 아이템을 디코드하고 나머지를 반환
[$item, $remainder] = CBOR::decodeFirst($bytes);

// 스트림의 모든 아이템을 디코드
$items = CBOR::decodeAll($bytes);
```

### 용도

게시의 CID를 수동으로 계산·검증하고 싶은 경우에는 CBOR 인코드가 필요합니다([verify 페이지](/ko/packages/laravel-bluesky/verify)도 참조).

```php theme={null}
use Revolution\Bluesky\Core\CBOR;
use Revolution\Bluesky\Core\CID;

$record = data_get($block, 'value');
$cbor   = CBOR::encode($record);
$bool   = CID::verify($cbor, data_get($block, 'cid'));
```

***

## CID (Content Identifier)

CID는 데이터의 해시를 기반으로 한 자기 기술형 식별자입니다. AT Protocol에서는 SHA-256 해시를 multihash로 감싸고, 나아가 multicodec와 multibase로 인코드합니다.

```mermaid theme={null}
graph LR
    A["데이터 (CBOR/Raw)"] --> B["SHA-256"]
    B --> C["multihash"]
    C --> D["multicodec<br>(dag-cbor / raw)"]
    D --> E["CIDv1<br>(base32 / base58btc)"]
```

### CIDv0과 CIDv1

| 버전 | 인코딩       | 첫 글자      | 용도          |
| -- | --------- | --------- | ----------- |
| v0 | base58btc | `Qm...`   | 오래된 사양(블롭)  |
| v1 | base32    | `bafy...` | 새로운 사양(레코드) |

### 주요 API

```php theme={null}
use Revolution\Bluesky\Core\CID;

// 데이터에서 CID를 생성
$cid = CID::encode($data, CID::DAG_CBOR); // 레코드용
$cid = CID::encode($data, CID::RAW);      // 바이너리(이미지 등)

// CID를 검증
$bool = CID::verify($data, $cid, CID::DAG_CBOR);
$bool = CID::verify($file, $cid, CID::RAW);

// CID를 해석
$decoded = CID::decode($cid); // ['version', 'codec', 'hash']

// CID의 버전을 확인
$version = CID::version($cid); // 0 or 1

// 바이트 표현으로 변환
$bytes = CID::decodeBytes($cid);
$cid   = CID::encodeBytes($bytes);
```

***

## CAR (Content Addressable aRchive)

CAR 파일은 AT Protocol 저장소를 블록의 열로 저장하는 바이너리 포맷입니다. `com.atproto.sync.getRepo`로 취득한 데이터가 이 형식입니다.

```mermaid theme={null}
graph TD
    A["CAR 파일"] --> B["헤더<br>(루트 CID)"]
    A --> C["블록 열"]
    C --> D["Signed Commit<br>(서명 + prev CID)"]
    C --> E["MST 노드"]
    C --> F["레코드(CBOR)"]
```

### 디코드

```php theme={null}
use Revolution\Bluesky\Core\CAR;

// CAR 파일 전체를 디코드(루트와 모든 블록)
['roots' => $roots, 'blocks' => $blocks] = CAR::decode($carData);

// 루트 CID만 취득
$roots = CAR::decodeRoots($carData);

// 블록을 순회
foreach (CAR::blockIterator($carData) as [$cid, $block]) {
    // $cid: CID 문자열, $block: 바이너리 데이터
}

// 레코드 맵으로 취득
foreach (CAR::blockMap($carData) as $key => $record) {
    // $key: 레코드 키, $record: 디코드된 배열
}
```

### 서명된 Commit의 검증

CAR 파일이 해당 사용자의 것인지 확인하려면, Signed Commit의 서명을 DID Document의 공개 키로 검증합니다.

```php theme={null}
use Revolution\Bluesky\Core\CAR;
use Revolution\Bluesky\Crypto\DidKey;
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Support\DidDocument;

$did = 'did:plc:***';

$didDoc    = DidDocument::make(Bluesky::identity()->resolveDID($did)->json());
$publicKey = DidKey::parse($didDoc->publicKey());

$signed    = CAR::signedCommit($carData);
$bool      = CAR::verifySignedCommit($signed, $publicKey);
```

샘플 구현: [DownloadRepoCommand](https://github.com/invokable/laravel-bluesky/blob/main/src/Console/DownloadRepoCommand.php)

***

## TID (Timestamp Identifier)

TID는 AT Protocol의 레코드 키에 사용되는 시계열 ID입니다. 마이크로초 단위 타임스탬프와 클록 ID를 조합해, base32로 인코드한 13자의 문자열입니다.

```
예: 3jujm55ngfc24
```

### 생성·변환

```php theme={null}
use Revolution\Bluesky\Core\TID;

// 다음 TID를 생성
$tid = TID::next();
echo $tid->toString(); // "3jujm55ngfc24" 같은 문자열

// 문자열로부터 TID를 생성
$tid = TID::fromStr('3jujm55ngfc24');

// 타임스탬프(마이크로초)와 클록 ID에서 생성
$tid = TID::fromTime(microtime(true) * 1000000, 0);
```

### TID의 구조

```mermaid theme={null}
graph LR
    A["63비트 정수"] --> B["53비트: 타임스탬프<br>(마이크로초)"]
    A --> C["10비트: 클록 ID"]
    B --> D["base32 인코드<br>(13자)"]
    C --> D
```

`TID::s32encode()`와 `TID::s32decode()`로 정수와 문자열을 상호 변환할 수 있습니다.

***

## Varint (가변 길이 정수)

`Varint`는 CAR / CBOR의 바이너리 해석에 사용되는 내부 유틸리티입니다. 일반적으로 직접 사용하지 않습니다.

```php theme={null}
use Revolution\Bluesky\Core\Varint;

// 정수를 인코드
$bytes = Varint::encode(1234);

// 스트림에서 디코드(값과 소비 바이트 수를 반환)
[$value, $bytesRead] = Varint::decodeStream($stream);
```

***

## Core 기능의 목킹에 대해

Core 기능(CBOR/CID/CAR/TID)은 외부 접근을 하지 않으므로, 테스트 시에 목킹할 필요가 없습니다.

```php theme={null}
// 테스트에서도 직접 사용 가능
$bytes = CBOR::encode(['text' => 'Hello']);
$cid   = CID::encode($bytes, CID::DAG_CBOR);
$bool  = CID::verify($bytes, $cid);
```

***

## 참고 링크

* [AT Protocol: Repository spec](https://atproto.com/specs/repository)
* [AT Protocol: CID spec](https://atproto.com/specs/data-model#cid-formats)
* [IPLD: DAG-CBOR spec](https://ipld.io/specs/codecs/dag-cbor/spec/)

<Info>
  Source: [src/Core/](https://github.com/invokable/laravel-bluesky/tree/main/src/Core)
</Info>


## Related topics

- [테스트](/ko/packages/laravel-bluesky/testing.md)
- [코어 패키지와 커스텀 드라이버 - Feedable](/ko/packages/feedable/core.md)
- [Feedable](/ko/packages/feedable/index.md)
- [엔진 API 모드: 토크 (텍스트 음성 합성) - VOICEVOX for Laravel](/ko/packages/laravel-voicevox/engine-talk.md)
- [클라이언트 모드: 토크 (텍스트 음성 합성) - VOICEVOX for Laravel](/ko/packages/laravel-voicevox/client-talk.md)
