6.3 KiB
ENC/ASL-LOG/1 — Encoding Specification for ASL Append-Only Log
Status: Draft Owner: Niklas Rydberg Version: 0.1.0 SoT: No Last Updated: 2025-11-16 Linked Phase Pack: N/A Tags: [encoding, log, deterministic]
Document ID: ENC/ASL-LOG/1
Layer: Log Encoding Profile (on top of ASL/LOG/1)
Depends on (normative):
ASL/LOG/1— semantic log behavior and replay rules
Informative references:
ASL/STORE-INDEX/1— store lifecycle and replay contracts
© 2025 Niklas Rydberg.
License
Except where otherwise noted, this document (text and diagrams) is licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).
The identifier registries and mapping tables (e.g. TypeTag IDs, HashId assignments, EdgeTypeId tables) are additionally made available under CC0 1.0 Universal (CC0) to enable unrestricted reuse in implementations and derivative specifications.
Code examples in this document are provided under the Apache License 2.0 unless explicitly stated otherwise. Test vectors, where present, are dedicated to the public domain under CC0 1.0.
1. Purpose
This document defines the exact encoding of the ASL append-only log.
It translates ASL/LOG/1 semantics into a deterministic bytes-on-disk format.
It does not define log semantics (see ASL/LOG/1).
2. Encoding Principles
- Little-endian integers
- Packed structures (no compiler padding)
- Forward-compatible versioning via header fields
- Deterministic serialization: identical log content -> identical bytes
- Hash-chained integrity as defined by ASL/LOG/1
3. Log File Layout
+----------------+
| LogHeader |
+----------------+
| LogRecord[] |
+----------------+
- LogHeader: fixed-size, mandatory, begins file
- LogRecord[]: append-only entries, variable number
4. LogHeader
#pragma pack(push,1)
typedef struct {
uint64_t magic; // "ASLLOG01"
uint32_t version; // Encoding version (1)
uint32_t header_size; // Total header bytes including this struct
uint64_t flags; // Reserved, must be zero for v1
} LogHeader;
#pragma pack(pop)
Notes:
magicis ASCII bytes:0x41 0x53 0x4c 0x4c 0x4f 0x47 0x30 0x31versionallows forward compatibility
5. LogRecord Envelope
Each record is encoded as:
#pragma pack(push,1)
typedef struct {
uint64_t logseq; // Monotonic sequence number
uint32_t record_type; // Record type tag
uint32_t payload_len; // Payload byte length
uint8_t payload[payload_len];
uint8_t record_hash[32]; // Hash-chained integrity (SHA-256)
} LogRecord;
#pragma pack(pop)
Hash chain rule (normative):
record_hash = H(prev_record_hash || logseq || record_type || payload_len || payload)
prev_record_hashis the previous record'srecord_hash- For the first record,
prev_record_hashis 32 bytes of zero His SHA-256 for v1
Readers MUST skip unknown record_type values using payload_len and MUST
continue replay without failure.
6. Record Type IDs (v1)
These type IDs bind the ASL/LOG/1 semantics to bytes-on-disk:
| Type ID | Record Type |
|---|---|
| 0x01 | SEGMENT_SEAL |
| 0x10 | TOMBSTONE |
| 0x11 | TOMBSTONE_LIFT |
| 0x20 | SNAPSHOT_ANCHOR |
| 0x30 | ARTIFACT_PUBLISH |
| 0x31 | ARTIFACT_UNPUBLISH |
6.1 Payload Schemas (v1)
All payloads are little-endian and packed. Variable-length fields are encoded
inline and accounted for by payload_len.
6.1.1 ArtifactRef
#pragma pack(push,1)
typedef struct {
uint32_t hash_id; // Hash algorithm identifier
uint16_t digest_len; // Digest length in bytes
uint16_t reserved0; // Must be 0
uint8_t digest[digest_len];
} ArtifactRef;
#pragma pack(pop)
Notes:
digest_lenMUST be > 0.- If StoreConfig fixes the hash,
digest_lenMUST match that hash's length.
6.1.2 SEGMENT_SEAL (Type 0x01)
#pragma pack(push,1)
typedef struct {
uint64_t segment_id; // Store-local segment identifier
uint8_t segment_hash[32]; // SHA-256 over the segment file bytes
} SegmentSealPayload;
#pragma pack(pop)
Implementation note (segment identity): In this repository, segment_id is
allocated when a segment is created (before writing records) and persisted via
store metadata (e.g., filename or catalog). The segment_hash is computed over
the exact on-disk segment bytes including header, records, digest bytes,
extents, and footer; the hash is taken after the footer is written so the seal
commits to the footer metadata.
6.1.3 TOMBSTONE (Type 0x10)
#pragma pack(push,1)
typedef struct {
ArtifactRef artifact;
uint32_t scope; // Opaque to ASL/LOG/1
uint32_t reason_code; // Opaque to ASL/LOG/1
} TombstonePayload;
#pragma pack(pop)
6.1.4 TOMBSTONE_LIFT (Type 0x11)
#pragma pack(push,1)
typedef struct {
ArtifactRef artifact;
uint64_t tombstone_logseq; // logseq of the tombstone being lifted
} TombstoneLiftPayload;
#pragma pack(pop)
6.1.5 SNAPSHOT_ANCHOR (Type 0x20)
#pragma pack(push,1)
typedef struct {
uint64_t snapshot_id;
uint8_t root_hash[32]; // Hash of snapshot-visible state
} SnapshotAnchorPayload;
#pragma pack(pop)
6.1.6 ARTIFACT_PUBLISH (Type 0x30)
#pragma pack(push,1)
typedef struct {
ArtifactRef artifact;
} ArtifactPublishPayload;
#pragma pack(pop)
6.1.7 ARTIFACT_UNPUBLISH (Type 0x31)
#pragma pack(push,1)
typedef struct {
ArtifactRef artifact;
} ArtifactUnpublishPayload;
#pragma pack(pop)
7. Versioning Rules
version = 1for this specification.- New record types MAY be added without bumping the version.
- Layout changes to
LogHeaderorLogRecordrequire a new version.
8. Relationship to Other Layers
| Layer | Responsibility |
|---|---|
| ASL/LOG/1 | Semantic log behavior and replay rules |
| ASL-STORE-INDEX | Store lifecycle and snapshot/log contracts |
| ENC-ASL-LOG | Exact byte layout for log encoding (this doc) |
| ENC-ASL-CORE-INDEX | Exact byte layout for index segments |