Core ist eine tiefgehende interne Implementierung. Für normale Posts, Feed-Abrufe oder Benachrichtigungen wird es nicht benötigt. Ziehen Sie es heran, wenn Sie die Datenstrukturen des AT Protocols direkt manipulieren.
Überblick über das Datenmodell des AT Protocols
Repositorys des AT Protocols nutzen eine content-adressierte Datenstruktur. Für Speicherung, Übertragung und Verifizierung werden folgende Bausteine verwendet.
| Klasse | Rolle |
|---|
CBOR | Binäre Serialisierung |
CID | Content-Adressierung (Hash-Identifier) |
CAR | Lesen/Schreiben von Repository-Archiven |
TID | Zeitbasierter Record-Key |
Varint | Variable-Length-Integer-Encoding (intern) |
CBOR
Die Klasse CBOR bietet Encoding/Decoding im DAG-CBOR-Format, das das AT Protocol verwendet. Als Erweiterung des Standard-CBOR unterstützt es CID-Links (Tag 42).
Encoding
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); // Binärer String
Decoding
use Revolution\Bluesky\Core\CBOR;
// Ein einzelnes Item decodieren
$data = CBOR::decode($bytes);
// Das erste Item eines Streams decodieren und den Rest zurückgeben
[$item, $remainder] = CBOR::decodeFirst($bytes);
// Alle Items eines Streams decodieren
$items = CBOR::decodeAll($bytes);
Anwendungsfall
Wenn Sie die CID eines Posts manuell berechnen oder verifizieren möchten, wird CBOR-Encoding benötigt (siehe auch verify-Seite).
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)
Eine CID ist ein selbstbeschreibender Identifier auf Basis des Daten-Hashs. Das AT Protocol wickelt einen SHA-256-Hash in Multihash und codiert ihn zusätzlich mit Multicodec und Multibase.
CIDv0 und CIDv1
| Version | Encoding | Anfangszeichen | Verwendung |
|---|
| v0 | base58btc | Qm... | Alte Spezifikation (Blobs) |
| v1 | base32 | bafy... | Neue Spezifikation (Records) |
Wichtige API
use Revolution\Bluesky\Core\CID;
// CID aus Daten erzeugen
$cid = CID::encode($data, CID::DAG_CBOR); // für Records
$cid = CID::encode($data, CID::RAW); // Binärdaten (z. B. Bilder)
// CID verifizieren
$bool = CID::verify($data, $cid, CID::DAG_CBOR);
$bool = CID::verify($file, $cid, CID::RAW);
// CID zerlegen
$decoded = CID::decode($cid); // ['version', 'codec', 'hash']
// CID-Version prüfen
$version = CID::version($cid); // 0 oder 1
// Umwandlung in Byte-Repräsentation
$bytes = CID::decodeBytes($cid);
$cid = CID::encodeBytes($bytes);
CAR (Content Addressable aRchive)
Eine CAR-Datei ist ein Binärformat, das AT-Protocol-Repositorys als Folge von Blöcken speichert. Die über com.atproto.sync.getRepo abgerufenen Daten liegen in diesem Format vor.
Decoding
use Revolution\Bluesky\Core\CAR;
// Gesamte CAR-Datei decodieren (Root und alle Blöcke)
['roots' => $roots, 'blocks' => $blocks] = CAR::decode($carData);
// Nur die Root-CIDs abrufen
$roots = CAR::decodeRoots($carData);
// Über Blöcke iterieren
foreach (CAR::blockIterator($carData) as [$cid, $block]) {
// $cid: CID-String, $block: Binärdaten
}
// Als Record-Map abrufen
foreach (CAR::blockMap($carData) as $key => $record) {
// $key: Record-Key, $record: bereits decodiertes Array
}
Signed Commit verifizieren
Um zu prüfen, ob eine CAR-Datei tatsächlich zu einem bestimmten Nutzer gehört, wird die Signatur des Signed Commit mit dem öffentlichen Schlüssel aus dem DID-Document verifiziert.
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);
Beispielimplementierung: DownloadRepoCommand
TID (Timestamp Identifier)
TID ist eine zeitbasierte ID, die als Record-Key im AT Protocol verwendet wird. Sie kombiniert einen Mikrosekunden-Zeitstempel und eine Clock-ID zu einem 13-stelligen base32-encodierten String.
Erzeugen und Umwandeln
use Revolution\Bluesky\Core\TID;
// Die nächste TID erzeugen
$tid = TID::next();
echo $tid->toString(); // String wie "3jujm55ngfc24"
// TID aus einem String erstellen
$tid = TID::fromStr('3jujm55ngfc24');
// Aus Zeitstempel (Mikrosekunden) und Clock-ID erstellen
$tid = TID::fromTime(microtime(true) * 1000000, 0);
Aufbau einer TID
Mit TID::s32encode() und TID::s32decode() können Sie zwischen Integer und String hin- und herwandeln.
Varint (Variable-Length-Integer)
Varint ist ein internes Utility für die Binäranalyse von CAR/CBOR. Es wird normalerweise nicht direkt verwendet.
use Revolution\Bluesky\Core\Varint;
// Integer encodieren
$bytes = Varint::encode(1234);
// Aus einem Stream decodieren (Wert und verbrauchte Bytes zurückgeben)
[$value, $bytesRead] = Varint::decodeStream($stream);
Zum Mocken der Core-Funktionen
Da die Core-Funktionen (CBOR/CID/CAR/TID) keine externen Zugriffe durchführen, müssen sie in Tests nicht gemockt werden.
// Auch in Tests direkt verwendbar
$bytes = CBOR::encode(['text' => 'Hello']);
$cid = CID::encode($bytes, CID::DAG_CBOR);
$bool = CID::verify($bytes, $cid);
Weiterführende Links
Zuletzt geändert am 13. Juli 2026