> ## 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 的仓库采用了内容寻址式数据结构。数据的保存、传输和校验依赖以下几个组件。

```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>(block 的集合)"]
    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 link（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;

// 解码单个 item
$data = CBOR::decode($bytes);

// 解码流开头的 item，并返回剩余部分
[$item, $remainder] = CBOR::decodeFirst($bytes);

// 解码流中所有 item
$items = CBOR::decodeAll($bytes);
```

### 用途

如果想手动计算和校验帖子的 CID，需要使用 CBOR 编码（另见 [verify 页面](/zh/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...`   | 旧规格（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 or 1

// 与字节表示互转
$bytes = CID::decodeBytes($cid);
$cid   = CID::encodeBytes($bytes);
```

***

## CAR (Content Addressable aRchive)

CAR 文件是把 AT Protocol 仓库以 block 序列形式存储的二进制格式。通过 `com.atproto.sync.getRepo` 获取的数据就是这种格式。

```mermaid theme={null}
graph TD
    A["CAR 文件"] --> B["头部<br>(root CID)"]
    A --> C["block 序列"]
    C --> D["Signed Commit<br>(签名 + prev CID)"]
    C --> E["MST 节点"]
    C --> F["record (CBOR)"]
```

### 解码

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

// 解码整个 CAR 文件（root 与全部 block）
['roots' => $roots, 'blocks' => $blocks] = CAR::decode($carData);

// 仅获取 root CID
$roots = CAR::decodeRoots($carData);

// 遍历 block
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/packages/laravel-bluesky/testing.md)
- [VOICEVOX for Laravel](/zh/packages/laravel-voicevox/index.md)
- [核心包与自定义驱动 - Feedable](/zh/packages/feedable/core.md)
- [Crypto —— AT Protocol 加密](/zh/packages/laravel-bluesky/crypto.md)
- [Feedable](/zh/packages/feedable/index.md)
