> ## 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 產生時序 record key。

<Warning>
  Core 屬於進階的內部實作。一般貼文、feed 取得、通知等操作不需使用。若要直接操作 AT Protocol 的資料結構時再參考。
</Warning>

## AT Protocol 資料模型概觀

AT Protocol 的儲存庫採用內容定址（content-addressed）的資料結構。以下要素會用於資料的儲存、傳輸與驗證。

```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`    | 時序 record key |
| `Varint` | 可變長度整數編碼（內部）  |

***

## CBOR

`CBOR` 類別提供 AT Protocol 採用的 [DAG-CBOR](https://ipld.io/specs/codecs/dag-cbor/spec/) 格式編解碼。作為標準 CBOR 的擴充，支援 CID 連結（tag 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 頁面](/zh-TW/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 會以 multihash 包裹 SHA-256 雜湊，再以 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...`   | 舊規格（blob）   |
| v1 | base32    | `bafy...` | 新規格（record） |

### 主要 API

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

// 從資料產生 CID
$cid = CID::encode($data, CID::DAG_CBOR); // 用於 record
$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 或 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["header<br>(root CID)"]
    A --> C["區塊序列"]
    C --> D["Signed Commit<br>(簽章 + prev CID)"]
    C --> E["MST 節點"]
    C --> F["record (CBOR)"]
```

### 解碼

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

// 解碼整份 CAR 檔（root 與所有區塊）
['roots' => $roots, 'blocks' => $blocks] = CAR::decode($carData);

// 僅取得 root CID
$roots = CAR::decodeRoots($carData);

// 迭代區塊
foreach (CAR::blockIterator($carData) as [$cid, $block]) {
    // $cid：CID 字串，$block：二進位資料
}

// 以 record map 取得
foreach (CAR::blockMap($carData) as $key => $record) {
    // $key：record key，$record：已解碼陣列
}
```

### 驗證帶有簽章的 Commit

若要確認 CAR 檔是否屬於該使用者，可以 DID Document 中的公鑰驗證 Signed Commit 的簽章。

```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 record key 的時序 ID。將微秒級的時間戳與 clock 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');

// 從時間戳（微秒）與 clock ID 建立
$tid = TID::fromTime(microtime(true) * 1000000, 0);
```

### TID 的結構

```mermaid theme={null}
graph LR
    A["63 位元整數"] --> B["53 位元：時間戳<br>(微秒)"]
    A --> C["10 位元：clock 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 功能的 mock

由於 Core 功能（CBOR/CID/CAR/TID）不涉及外部存取，因此在測試時無需 mock。

```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

- [測試](/zh-TW/packages/laravel-bluesky/testing.md)
- [核心套件與自訂驅動 - Feedable](/zh-TW/packages/feedable/core.md)
- [Crypto — AT Protocol 加密](/zh-TW/packages/laravel-bluesky/crypto.md)
- [Feedable](/zh-TW/packages/feedable/index.md)
- [Engine API 模式:Talk(文字語音合成)- VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/engine-talk.md)
