Saltar al contenido principal
Core es una implementación interna avanzada. No es necesaria para las operaciones habituales como publicar, obtener feeds o notificaciones. Consúltala cuando manipules directamente las estructuras de datos del AT Protocol.

Visión general del modelo de datos de AT Protocol

El repositorio de AT Protocol adopta una estructura de datos direccionable por contenido. Para almacenar, transferir y verificar los datos se emplean los siguientes elementos.
ClaseRol
CBORSerialización binaria
CIDDireccionamiento por contenido (identificador basado en hash)
CARLectura/escritura del archivo del repositorio
TIDClave de record cronológica
VarintCodificación de enteros de longitud variable (interno)

CBOR

La clase CBOR ofrece codificación y decodificación en el formato DAG-CBOR que adopta AT Protocol. Como extensión de CBOR estándar, admite enlaces CID (tag 42).

Codificar

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); // cadena binaria

Decodificar

use Revolution\Bluesky\Core\CBOR;

// Decodifica un único elemento
$data = CBOR::decode($bytes);

// Decodifica el primer elemento del stream y devuelve el resto
[$item, $remainder] = CBOR::decodeFirst($bytes);

// Decodifica todos los elementos del stream
$items = CBOR::decodeAll($bytes);

Uso

Si quieres calcular o verificar manualmente el CID de una publicación, necesitas la codificación CBOR (ver también la página verify).
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)

El CID es un identificador autodescriptivo basado en el hash de los datos. En AT Protocol se envuelve el hash SHA-256 con multihash y, adicionalmente, se codifica con multicodec y multibase.

CIDv0 y CIDv1

VersiónCodificaciónPrefijoUso
v0base58btcQm...Especificación antigua (blobs)
v1base32bafy...Especificación nueva (records)

API principal

use Revolution\Bluesky\Core\CID;

// Genera un CID a partir de los datos
$cid = CID::encode($data, CID::DAG_CBOR); // para records
$cid = CID::encode($data, CID::RAW);      // binario (imágenes, etc.)

// Verifica un CID
$bool = CID::verify($data, $cid, CID::DAG_CBOR);
$bool = CID::verify($file, $cid, CID::RAW);

// Analiza un CID
$decoded = CID::decode($cid); // ['version', 'codec', 'hash']

// Comprueba la versión del CID
$version = CID::version($cid); // 0 o 1

// Conversión a representación de bytes
$bytes = CID::decodeBytes($cid);
$cid   = CID::encodeBytes($bytes);

CAR (Content Addressable aRchive)

El archivo CAR es un formato binario que almacena el repositorio del AT Protocol como una secuencia de bloques. Los datos obtenidos con com.atproto.sync.getRepo vienen en este formato.

Decodificar

use Revolution\Bluesky\Core\CAR;

// Decodifica todo el archivo CAR (raíz y todos los bloques)
['roots' => $roots, 'blocks' => $blocks] = CAR::decode($carData);

// Obtener solo los root CID
$roots = CAR::decodeRoots($carData);

// Iterar por bloques
foreach (CAR::blockIterator($carData) as [$cid, $block]) {
    // $cid: cadena CID, $block: datos binarios
}

// Obtener como mapa de records
foreach (CAR::blockMap($carData) as $key => $record) {
    // $key: clave del record, $record: array decodificado
}

Verificación del Signed Commit

Para comprobar que el archivo CAR pertenece a esa persona usuaria, verifica la firma del Signed Commit con la clave pública del DID Document.
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);
Ejemplo de implementación: DownloadRepoCommand

TID (Timestamp Identifier)

El TID es un ID cronológico que se usa como clave de record en AT Protocol. Combina una marca temporal en microsegundos con un ID de reloj y se codifica en base32 como una cadena de 13 caracteres.
Ejemplo: 3jujm55ngfc24

Generación y conversión

use Revolution\Bluesky\Core\TID;

// Genera el siguiente TID
$tid = TID::next();
echo $tid->toString(); // Cadena tipo "3jujm55ngfc24"

// Crea un TID desde una cadena
$tid = TID::fromStr('3jujm55ngfc24');

// Crea desde marca temporal (microsegundos) e ID de reloj
$tid = TID::fromTime(microtime(true) * 1000000, 0);

Estructura del TID

Con TID::s32encode() y TID::s32decode() puedes convertir entre entero y cadena.

Varint (entero de longitud variable)

Varint es una utilidad interna que se usa en el parsing binario de CAR / CBOR. Normalmente no se utiliza directamente.
use Revolution\Bluesky\Core\Varint;

// Codifica un entero
$bytes = Varint::encode(1234);

// Decodifica desde un stream (devuelve valor y bytes consumidos)
[$value, $bytesRead] = Varint::decodeStream($stream);

Sobre el mock de las funciones Core

Las funciones Core (CBOR/CID/CAR/TID) no realizan accesos externos, por lo que no es necesario mockearlas en las pruebas.
// Se pueden usar directamente en las pruebas
$bytes = CBOR::encode(['text' => 'Hello']);
$cid   = CID::encode($bytes, CID::DAG_CBOR);
$bool  = CID::verify($bytes, $cid);

Enlaces de referencia

Source: src/Core/
Última modificación el 13 de julio de 2026