libnoa 0.1.1

AI-native distributed version control system with per-agent workspace isolation, JSONL append-only logs, snapshot-based history, and full git protocol compatibility
Documentation
# オブジェクトストレージの設計

## 概要

noaはGitに着想を得たコンテンツアドレス型ストレージモデルを採用していますが、プラグ可能なバックエンドアーキテクチャを備えています。オブジェクトはSHA-256ハッシュでアドレス指定され、不透明なblobとして保存されます。

## オブジェクトタイプ

### Blob

生のファイルコンテンツ。`SHA256(content)`で識別されます。

```rust
pub struct BlobId(pub String); // 16進数エンコードされたSHA-256
```

デルタ圧縮なし。各一意のコンテンツは正確に1つのblobを生成します。重複コンテンツはハッシュによって自動的に重複排除されます。

### ツリー

ディレクトリ一覧。パスを子エントリ(blobまたはサブツリー)にマッピングします。

```rust
pub struct TreeEntry {
    pub name: String,
    pub kind: TreeEntryKind, // Blob または Tree
    pub hash: String,        // 子のSHA-256
}

pub struct TreeId(pub String); // SHA-256(msgpack(entries))
```

ツリーはコンパクトさと高速なデシリアライズのためにMessagePackでシリアライズされます。

## トレイト定義

```rust
#[async_trait]
pub trait ObjectStore: Send + Sync {
    async fn put_blob(&self, data: &[u8]) -> Result<BlobId>;
    async fn get_blob(&self, id: &BlobId) -> Result<Vec<u8>>;
    async fn put_tree(&self, entries: Vec<TreeEntry>) -> Result<TreeId>;
    async fn get_tree(&self, id: &TreeId) -> Result<Vec<TreeEntry>>;
}
```

## バックエンド

### RedbObjectStore (ローカル)

[redb](https://github.com/cberner/redb)組み込みキーバリューストアを使用します。

- 2つのテーブル: `blobs` (キー: ハッシュバイト, 値: コンテンツバイト) と `trees` (キー: ハッシュバイト, 値: msgpackエントリ)
- メモリマップドファイルによるゼロコピー読み取り
- 自動クラッシュリカバリ付きACIDトランザクション
- MVCCによるシングルライター、マルチリーダー
- 外部デーモン不要

### MinioObjectStore (リモート)

`aws-sdk-s3`経由でS3互換APIを使用します。

- パス形式アドレッシング: `<bucket>/blobs/<hash>`, `<bucket>/trees/<hash>`
- あらゆるS3互換バックエンドに対応 (MinIO, AWS S3, GCS等)
- 指数バックオフによる自動リトライ
- 分散デプロイメントに適している

## 設計判断

### SHA-1ではなくSHA-256を選んだ理由

GitはSHA-1を使用していますが、これは暗号学的に破られています (SHAttered攻撃, 2017年)。SHA-256は衝突耐性があり、広く利用可能です。

### デルタ圧縮がない理由

1. **シンプルさ**: デルタ圧縮 (Gitのパックファイル) は大幅な複雑さを追加します (スライディングウィンドウマッチング、thin packs、デルタチェーン)。
2. **書き込みパフォーマンス**: 直接blob書き込みはO(1)。デルタ圧縮には既存オブジェクトの読み取りが必要。
3. **AIエージェントのワークロード**: エージェントは頻繁にファイル全体を再生成します。古いバージョンは一時的 — デルタチェーンは短く多数になります。
4. **バックエンドへのオフロード**: S3/MinIOがストレージ層で重複排除を処理します。

### ツリーにMessagePackを選んだ理由

- JSONよりバイナリデータで30-50%小さい
- スキーマ柔軟性 (protobuf定義不要)
- `rmp-serde`によるRustエコシステム対応
- 高速なデシリアライズ

### SQLiteではなくredbを選んだ理由

- **型安全性**: redbはテーブル定義にRustジェネリクスを使用
- **パフォーマンス**: redbはRustワークロードに最適化 (ゼロコピー読み取り)
- **シンプルさ**: 単一依存関係、Cライブラリリンク不要
- **クラッシュ安全性**: redbの先行書き込みログはSQLiteのWALモードよりシンプル

トレードオフ: redbはSQLiteよりコミュニティが小さく、ツールオプションも少ないです。noaのユースケース(組み込みバイナリストレージ)では、このトレードオフは有利です。