| name | design_patterns-markl_id |
| description | Use when working with content-addressable identifiers, markl IDs, blob digests, purpose-tagged hashes, blech32 encoding, or encryption keys. Also applies when encountering markl.Id, MarklId, FormatHash, purpose@digest syntax, or hash format selection.
|
| triggers | ["markl","markl.Id","MarklId","blech32","blob digest","purpose@digest","FormatHash","content addressable","hash format"] |
Markl ID System
Overview
Markl IDs are dodder's content-addressable identifiers. Each ID combines a
purpose tag, a format specifier (hash algorithm or key type), and binary data
into a single value. Human-readable representation uses blech32 encoding (a
bech32 variant using - as separator). The system supports multiple hash
algorithms, cryptographic key types, and encryption identifiers through a
unified interface.
Structure
type Id struct {
purposeId string
format domain_interfaces.MarklFormat
data []byte
}
String Representation
Without purpose: format-encodeddata
With purpose: purpose@format-encodeddata
Example: dodder-blob-digest-sha256-v1@sha256-qpzry9x8gf2tvdw0s3jn54khce6mua7l...
Purpose Tags
Purposes give semantic meaning to otherwise opaque identifiers:
| Purpose Constant | Meaning |
|---|
PurposeBlobDigestV1 | SHA-256 digest of blob content |
PurposeObjectDigestV1 | SHA-256 digest of full object |
PurposeObjectSigV1 | Ed25519 signature of object |
PurposeRepoPubKeyV1 | Repository public key |
Supported Formats
| Format ID | Type | Usage |
|---|
sha256 | Hash | Default blob content hashing |
blake2b256 | Hash | Alternative content hashing |
ed25519_pub | Key | Repository public keys |
ed25519_sec | Key | Repository secret keys |
ed25519_sig | Signature | Object signatures |
age_x25519_pub | Key | Age encryption public keys |
age_x25519_sec | Key | Age encryption secret keys |
nonce | Nonce | Cryptographic nonces |
Blech32 Encoding
Blech32 is a modified bech32 encoding using - instead of 1 as the
separator between the human-readable prefix and the data portion. It provides:
- Base32 encoding with checksum validation (6 bytes)
- Human-readable prefix carrying the format ID
- Case-insensitive with validation
func Encode(hrp string, data []byte) ([]byte, error)
func Decode(encoded string) (hrp string, data []byte, err error)
Pool Integration
Markl IDs are pooled for efficient memory management:
var idPool interfaces.PoolPtr[Id, *Id] = pool.MakeWithResetable[Id]()
func GetId() (domain_interfaces.MarklIdMutable, interfaces.FuncRepool) {
return idPool.GetWithRepool()
}
Creating and Parsing IDs
Parsing from string
var id markl.Id
err := id.Set("purpose@format-encodeddata")
The Set method splits on @ to extract purpose, then decodes the blech32
body to extract format and data.
Comparing IDs
func Equals(a, b domain_interfaces.MarklId) bool {
}
Binary serialization
bytes, err := id.MarshalBinary()
err = id.UnmarshalBinary(bytes)
Text serialization
text, err := id.MarshalText()
err = id.UnmarshalText(text)
Common Mistakes
| Mistake | Correct Approach |
|---|
| Comparing IDs by string representation | Use markl.Equals() which compares format + data |
| Creating IDs without pooling in hot paths | Use markl.GetId() with repool |
| Assuming all IDs use SHA-256 | Check format.GetMarklFormatId() — multiple formats exist |
| Using bech32 instead of blech32 | Dodder uses - separator (blech32), not 1 (bech32) |