# DOP/1 — experimenteller kanonischer Objektcodec Status: **implementierter experimenteller Codec**, kein aktiviertes Remote-Protokoll. Referenz: `internal/objects`; feste unabhängig mit Python erzeugte Vektoren in `dop-v1-vectors.json`. Bestehende `dh-snapshot/1`-Objekte bleiben davon getrennt. ## Bytes und Identifikatoren Jedes Objekt ist genau `44 4f 50 00 01 TT LLLLLLLLLLLLLLLL PAYLOAD`: | Feld | Länge | Regel | |---|---:|---| | Magic | 4 | ASCII `DOP` gefolgt von NUL | | Version | 1 | exakt `01`; andere Versionen ablehnen | | Typ | 1 | 1 Blob, 2 Tree, 3 Commit-Inhalt, 4 Ref-Inhalt | | Payload-Länge | 8 | vorzeichenlos, Big Endian, ohne Varint | | Payload | deklarierte Länge | keine weiteren Bytes danach | ID = `dop1:sha256:` + lowercase hex SHA-256 **aller** Envelope-Bytes. Version und Typ stehen damit im Hash-Preimage und trennen die Typ-Domänen. Leere Blob-ID und vollständige Beispiele stehen in den Vektoren. SHA-256 ist keine Signatur und eine Autorenzeichenfolge ist kein Identitätsnachweis. Unbekannte Algorithmen, Versionen und Typen werden abgelehnt; kein permissiver Fallback auf v1-Snapshot-JSON. Maximale Blob-Payload: 32 MiB; andere: 4 MiB. Der Decoder prüft die Länge vor Allokation und erwartet exakt EOF. ## Metadaten-Kanonisierung Blobs enthalten rohe Bytes. Metadaten verwenden UTF-8 JSON mit genau den folgenden Feldern in dieser Reihenfolge, ohne Whitespace, ohne Zusatzfelder, ohne ausgelassene Felder, ohne Duplikate. Die Referenz rekonstruiert die typisierte Darstellung und verlangt Bytegleichheit. Strings verwenden die Go-`encoding/json`-Escape-Regeln: `"`, Backslash, Kontrollzeichen escaped; `<`, `>`, `&`, U+2028/U+2029 werden als lowercase `\u....` escaped; andere gültige UTF-8-Zeichen bleiben erhalten. Ganzzahlen werden dezimal ohne Pluszeichen oder führende Null ausgegeben. Keine Floats, kein Unicode-Normalisieren. Leere Arrays sind `[]`, nie `null`. Unbekannte Felder/Enums sind Fehler. Tree: `{"entries":[{"name":...,"kind":...,"mode":...,"object":...}]}`. Einträge nach rohen UTF-8-Namensbytes strikt aufsteigend, maximal 10.000. Kind `blob` erlaubt Mode 420/493 (0644/0755); `tree` nur 493. Namen sind einzelne Segmente, maximal 255 Bytes. Keine Traversierung, Separatoren, NUL/Kontrollzeichen, Windows-Gerätenamen, Doppelpunkt, nachlaufender Punkt/Space oder unter Unicode-Simple-Folding kollidierende Namen. Der Codec prüft IDs syntaktisch; die Graph-Prüfung muss separat sicherstellen, dass referenzierte Objekte existieren und vom erwarteten Typ sind. Commit-Inhalt: `{"tree":...,"parents":[],"author":...,"unix_time":...,"message":...}`. Tree muss DOP-ID sein; maximal 16 unterschiedliche geordnete Eltern-IDs. Der erste Parent ist der Hauptelternteil; kein Sortieren nach Hash. Zeit ist behauptete UTC-Unix-Sekunde 0..253402300799, kein Zeitbeweis. Autor: nichtleerer UTF-8-Claim bis 200 Bytes; Nachricht: UTF-8 bis 2048 Bytes. Commit-Inhalte dürfen einen DAG bilden; Autorisierung/Signatur sind separate Identitätsattestierungen über die **vollständige Objekt-ID**. Das experimentelle DIP-Modul ist hierfür ein Baustein; noch keine automatische Verknüpfung. Ref-Inhalt: `{"name":...,"target":...,"previous":...,"generation":...}`. Name nach Segmentregeln, Ziel DOP-ID, vorheriges Ziel DOP-ID oder leer für Anlage, Generation 1..2^64−1. Dies sind nur kanonische Update-Daten. Ein Server muss separat Signatur, ACL, Expected-Version/CAS und Zieldaten prüfen. Der Codec führt keine Ref-Updates aus und verleiht keine Schreibrechte. Proposal, Review, Release, Attribution, verschlüsselte Objekte und signierte Envelope-Typen sind **reservierte Ziele ohne zugewiesene Typbytes**. Sie werden derzeit abgelehnt, bis deren Kontexte, Schemas, Limits und Vektoren existieren. ## Fehler und Kompatibilität Unbekanntes Format/Version/Typ, Längenlimit, unvollständige oder zusätzliche Bytes, nichtkanonisches JSON, ungültige Referenz oder kollidierender Pfad sind harte Parserfehler. Noch keine stabilen Remote-Fehlercodes. `object-check --file FILE` validiert ein DOP-Objekt offline und zeigt Typ, Payload-Größe und ID. Legacy: `.dh/objects/xx/...` verwendet weiterhin raw SHA-256 und unverändertes Snapshot-JSON. Es gibt keine automatische DOP-Migration und keine Behauptung, dass rohe Snapshot-IDs domain-separated seien. Eine spätere Migration muss in einem neuen Namespace mit Opt-in, Backup und Rückverweisliste stattfinden. ## DDP/0.1-Kompatibilität Bestehende Discovery-Signaturen bleiben unverändert: JSON der typisierten `Payload` in Feldreihenfolge protocol,type,repo,name,category,description,version, priority,content_hash,timestamp,publisher; `omitempty` wie im Code. Ed25519 signiert diese Bytes; Event-ID ist SHA-256 von `ddp/0.1/event\0` + Payload + Signatur. Repo-ID ist SHA-256 von `decentralhub/repo/v0.1\0` + Publisher + NUL + Name, mit Präfix `dh:repo:`. Dieses Legacy-Protokoll wird nicht als stabiles DOP ausgegeben; ein künftiges DDP benötigt expliziten Signaturkontext und eigene Kanonisierungs-/Interoperabilitätsvektoren vor öffentlicher Stabilisierung.