Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c860cc9
vectors: add golden canonicalization tools (Py/Rust/Go) and entry vec…
flyingrobots Nov 3, 2025
957e499
cbor: add canonical tools (Py/Go) + CI; C step for blake3 over canoni…
flyingrobots Nov 3, 2025
b76047b
Update gitignore to include 'tmp/'
flyingrobots Nov 4, 2025
167dfe1
docs/spec: add FS↔M anchors + mapping table; model: add M‑x anchors
flyingrobots Nov 4, 2025
10f89cd
chore: remove accidental tmp/junit.xml and ignore tmp/
flyingrobots Nov 4, 2025
5b84d3d
merge: incorporate chore/mantine-v7 into docs/release-wasm-fs-m-ancho…
flyingrobots Nov 4, 2025
3b64ea8
docs+ci: merge chore/mantine-v7 stashed changes (README badges/notes,…
flyingrobots Nov 4, 2025
6478464
Update gitignore
flyingrobots Nov 4, 2025
8ecb871
tests(feedback): add checks for FEEDBACK.md items (WASM panic handler…
flyingrobots Nov 4, 2025
1b2d6c4
fix(wasm-demo): add #[panic_handler] for no_std and adjust panic hand…
flyingrobots Nov 4, 2025
521f848
feedback: mark WASM panic handler as Resolved with build evidence
flyingrobots Nov 4, 2025
08e6b7a
ci(release): tighten tag trigger to semver, add tag guard if:, add di…
flyingrobots Nov 4, 2025
6b12b04
docs(compliance): fix broken links to spec/model, reconstruct error t…
flyingrobots Nov 4, 2025
9d4468a
wasm-demo: enable size opts (strip=true, panic=abort); Makefile: remo…
flyingrobots Nov 4, 2025
d4fff2c
tests(feedback): stabilize wasm Makefile check in generator; all feed…
flyingrobots Nov 4, 2025
e95d20f
feedback: mark remaining items as Resolved/Already Fixed with evidenc…
flyingrobots Nov 4, 2025
0775342
tests(feedback): add remaining checks; fixes across docs/ci/harness; …
flyingrobots Nov 4, 2025
c580459
chore: remove FEEDBACK.md from branch (gitignored; kept tests and fix…
flyingrobots Nov 5, 2025
5c869e8
chore(wasm-demo): remove committed build artifacts; ignore target/ an…
flyingrobots Nov 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Release Artifacts

on:
push:
tags:
- 'v*'

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Prepare assets
run: |
mkdir -p dist
zip -r dist/schemas.zip schemas
zip -r dist/vectors.zip tests/vectors scripts/vectors
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
dist/schemas.zip
dist/vectors.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Tag-triggered release workflows need safeguards to prevent accidental/invalid releases.

The workflow triggers on any tag matching v*. This is permissive and could inadvertently release from development/experiment tags (e.g., v-wip, v.test). Consider:

  1. Stricter tag pattern: v[0-9]+.[0-9]+.[0-9]+* for semantic versioning.
  2. Branch guard: Add a condition to only release from main (or similar).
  3. Draft releases: Use draft: true in softprops/action-gh-release@v2 to require manual promotion.

Apply this diff to tighten the trigger pattern and add a branch guard:

 on:
   push:
     tags:
-      - 'v*'
+      - 'v[0-9]+.[0-9]+.[0-9]+*'

 permissions:
   contents: write

 jobs:
   release:
     runs-on: ubuntu-latest
+    if: github.ref_type == 'tag' && startsWith(github.ref, 'refs/tags/v')
     steps:

Or, use softprops/action-gh-release draft mode for manual promotion:

       - name: Create GitHub Release
         uses: softprops/action-gh-release@v2
         with:
+          draft: true
           files: |
             dist/schemas.zip
             dist/vectors.zip
🧰 Tools
🪛 YAMLlint (1.37.1)

[warning] 3-3: truthy value should be one of [false, true]

(truthy)


[error] 34-34: too many blank lines (1 > 0)

(empty-lines)

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,6 @@ fastlane/test_output
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/*.code-snippets

# Temp artifacts
tmp/
21 changes: 10 additions & 11 deletions docs/compliance/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Version: 0.1.0

## 1. Purpose

The compliance suite ensures that any implementation of the **Ledger-Kernel** (e.g., `libgitledger`, `ledger-core-rust`, `ledger-js`) adheres to the invariants, semantics, and deterministic behavior defined in [`SPEC`](../spec/) and [`MODEL`](../model/).
The compliance suite ensures that any implementation of the **Ledger-Kernel** (e.g., `libgitledger`, `ledger-core-rust`, `ledger-js`) adheres to the invariants, semantics, and deterministic behavior defined in [`SPEC.md`](./SPEC.md) and [`MODEL.md`](./MODEL.md).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify link targets: SPEC.md and MODEL.md.

Line 14 updates references to ./SPEC.md and ./MODEL.md. Confirm these files exist at the compliance directory level or adjust relative paths accordingly. Broken links will harm navigation and compliance tracking.


🏁 Script executed:

#!/bin/bash
# Verify SPEC.md and MODEL.md exist relative to compliance/index.md
cd docs/compliance || exit 1
for file in SPEC.md MODEL.md; do
  if [ -f "$file" ]; then
    echo "✓ Found: $file"
  else
    # Check parent directories
    if [ -f "../spec/formal-spec.md" ] && [ "$file" = "SPEC.md" ]; then
      echo "$file not found locally; check if reference should be ../spec/formal-spec.md"
    elif [ -f "../spec/model.md" ] && [ "$file" = "MODEL.md" ]; then
      echo "$file not found locally; check if reference should be ../spec/model.md"
    else
      echo "$file NOT FOUND; relative link is broken"
    fi
  fi
done

Length of output: 65


🏁 Script executed:

#!/bin/bash
# Explore repository structure and locate relevant files
echo "=== Searching for index.md files ==="
fd -t f "index.md" . | head -20

echo ""
echo "=== Searching for SPEC.md files ==="
fd -t f "SPEC.md" . | head -20

echo ""
echo "=== Searching for MODEL.md files ==="
fd -t f "MODEL.md" . | head -20

echo ""
echo "=== Checking docs/ directory structure ==="
fd -t d "docs" . | head -10
fd -t f . docs/ 2>/dev/null | head -30

Length of output: 1164


🏁 Script executed:

#!/bin/bash
# Extract line 14 from docs/compliance/index.md to verify the exact links
echo "=== Content around line 14 in docs/compliance/index.md ==="
sed -n '10,18p' docs/compliance/index.md

Length of output: 492


Fix broken documentation links: use correct relative paths to SPEC.md and MODEL.md.

The links ./SPEC.md and ./MODEL.md in line 14 are broken. These files reside at the repository root, not in docs/compliance/. Update to:

  • ../../SPEC.md
  • ../../MODEL.md

Broken links will render as dead ends in the compliance documentation and break navigation flow.

🤖 Prompt for AI Agents
In docs/compliance/index.md around line 14, the relative links ./SPEC.md and
./MODEL.md point to files in the repo root but resolve incorrectly from
docs/compliance/; update the two links to use the correct relative paths
../../SPEC.md and ../../MODEL.md so they point to the repository root files.


A compliant implementation must **pass all mandatory tests** and **expose proofs or logs**
demonstrating correctness.
Expand Down Expand Up @@ -123,14 +123,14 @@ $ make determinism

Implementations must emit standardized error codes:

| **Code** | **Name** | **Meaning** |
|----------|----------|-------------|
| `E_APPEND_REJECTED` | Append Rejected | Append violates invariants |
| `E_SIG_INVALID` | Invalid Signature | Attestation verification failed |
| `E_POLICY_FAIL` | Policy Failed | Policy evaluation false |
| `E_REPLAY_MISMATCH` | Replay Mismatch | Non-deterministic replay |
| `E_TEMPORAL_ORDER` | Temporal Order | Timestamp regression |
| `E_NAMESPACE` | Namespace Conflict | Cross-ledger conflict |
| **Code** | **Name** | **Meaning** |
|----------|-----------|--------------|
| `E_APPEND_REJECTED` Append violates invariants |
| `E_SIG_INVALID` Attestation verification failed |
| `E_POLICY_FAIL` Policy evaluation false |
| `E_REPLAY_MISMATCH` Non-deterministic replay |
| `E_TEMPORAL_ORDER` Timestamp regression |
| `E_NAMESPACE` Cross-ledger conflict |

This allows cross-implementation comparison of failure semantics.

Expand Down Expand Up @@ -201,8 +201,7 @@ The report includes version, platform, test summary, and digests.

---

## 12. Future Work

12. Future Work
- Property-based generator for randomized append/replay sequences
- Integration with CI/CD to auto-validate pull requests
- Optional differential testing between implementations
3 changes: 3 additions & 0 deletions docs/implementation/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ title: Error Model

WIP.

::: tip See also
For user-level execution of the compliance suite, see [Running the Compliance Harness](/cli/harness).
:::
30 changes: 30 additions & 0 deletions docs/spec/formal-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This section defines the normative, testable rules for Ledger‑Kernel. Clauses

## 1. Data Structures

<a id="fs-1"></a>
### FS‑1 Entry (Abstract)
An Entry SHALL be an immutable record addressable by a collision‑resistant content hash. Conceptually, an Entry comprises:

Expand All @@ -19,6 +20,7 @@ An Entry SHALL be an immutable record addressable by a collision‑resistant con

An Entry MUST serialize deterministically (FS‑10) and be committed as a conventional Git commit under a namespaced ref (see FS‑8, FS‑12).

<a id="fs-2"></a>
### FS‑2 Attestation (Abstract)
An Attestation SHALL bind a signer identity to an Entry’s content hash using a specified algorithm. At minimum it MUST include:

Expand All @@ -30,6 +32,7 @@ An Attestation SHALL bind a signer identity to an Entry’s content hash using a

Verification MUST succeed with repository‑local material (FS‑6).

<a id="fs-3"></a>
### FS‑3 Policy Result (Abstract)
Policy evaluation SHALL be deterministic and side‑effect free. Its result is a boolean decision and MAY include structured diagnostics:

Expand All @@ -40,6 +43,7 @@ Policy engines MUST NOT read clocks, randomness, network, or ambient I/O (FS‑9

## 2. Operations

<a id="fs-4"></a>
### FS‑4 append(R, L, E)
To append, an implementation MUST:

Expand All @@ -51,37 +55,47 @@ To append, an implementation MUST:

If any step fails, the implementation MUST NOT advance the ref and MUST return an error.

<a id="fs-5"></a>
### FS‑5 replay(R, L)
Replay SHALL fold the deterministic transition function over the ordered Entries (M‑2) from the genesis to head, producing `state(L)`. Replay MUST NOT consult external state.

<a id="fs-6"></a>
### FS‑6 verify(R, L)
Verification SHALL check the entire history of `L` for conformity: ordering, fast‑forward ref evolution, canonical hashes, required attestations, deterministic policy acceptance, and deterministic replay equivalence. Verification MUST be possible using repository‑local data only (no network).

## 3. Determinism & Constraints

<a id="fs-7"></a>
### FS‑7 Append‑Only & Total Order
The set of Entries under the ledger ref SHALL form a single linear chain with no merges or parallel branches. Once committed, Entries MUST NOT be modified or deleted.

<a id="fs-8"></a>
### FS‑8 Fast‑Forward Only (Ref Semantics)
The ledger ref `p` SHALL advance only by fast‑forward such that `Parent(Eᵢ₊₁) = Hash(Eᵢ)`. Non‑FF updates (rebase, force‑push, merge) are forbidden.

<a id="fs-9"></a>
### FS‑9 Policy Determinism
Policy engines SHALL be deterministic. They MUST NOT access monotonic or wall‑clock time, random number generators, network, filesystem, or environment state except for explicitly whitelisted, immutable inputs provided by the host. Given identical inputs, evaluation MUST yield identical outputs.

<a id="fs-10"></a>
### FS‑10 Canonical Serialization & Hashing
Entries and Attestations SHALL serialize to a canonical byte sequence unambiguously (e.g., stable field order, UTF‑8, normalized newlines). The content hash used for identity and signatures MUST be computed over this canonical form. The canonicalization procedure MUST be documented and stable.

<a id="fs-11"></a>
### FS‑11 Temporal Monotonicity
Entry timestamps SHALL be monotonically non‑decreasing relative to their parent. Implementations MAY enforce stricter monotonicity policies via the policy engine.

<a id="fs-12"></a>
### FS‑12 Namespaces & Storage
Ledger data SHALL be stored under a dedicated ref namespace (e.g., `refs/_ledger/<ns>`). Attestations and policies MAY use auxiliary refs under the same namespace as defined in Wire Format. Implementations MUST NOT rely on non‑Git storage to satisfy core verification (FS‑6).

## 4. Errors & Reporting

<a id="fs-13"></a>
### FS‑13 Error Domains
Implementations SHOULD expose structured error domains: `parse`, `canonicalize`, `hash`, `attestation`, `policy`, `ordering`, `ff`, `io`, `internal`.

<a id="fs-14"></a>
### FS‑14 Diagnostics
Verification and append failures SHOULD include machine‑readable diagnostics sufficient to reproduce the decision offline.

Expand All @@ -93,6 +107,22 @@ Verification and append failures SHOULD include machine‑readable diagnostics s
- FS‑6 substantiates M‑8 (offline verification).
:::

## 5.1 FS↔M Mapping

The following table links Model clauses (M‑x) to the normative Formal Spec clauses (FS‑x):

| Model (M‑x) | Summary | Formal Spec (FS‑x) |
| --- | --- | --- |
| M‑1 | Ledger structure (L = (p, E, A, P)) | [FS‑1](#fs-1), [FS‑2](#fs-2), [FS‑3](#fs-3) |
| M‑2 | State and transition, replay as fold | [FS‑5](#fs-5), [FS‑10](#fs-10) |
| M‑3 | Admission predicate V(L,S,E) | [FS‑3](#fs-3), [FS‑4](#fs-4) |
| M‑4 | Append‑only | [FS‑7](#fs-7) |
| M‑5 | Fast‑forward only | [FS‑8](#fs-8) |
| M‑6 | Total order (single chain) | [FS‑7](#fs-7), [FS‑8](#fs-8) |
| M‑7 | Deterministic replay | [FS‑5](#fs-5), [FS‑9](#fs-9), [FS‑10](#fs-10) |
| M‑8 | Offline verify | [FS‑6](#fs-6) |
| M‑9 | Policy determinism | [FS‑3](#fs-3), [FS‑9](#fs-9) |

## 6. References

- [Model](/spec/model)
Expand Down
141 changes: 136 additions & 5 deletions docs/spec/model-source.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,143 @@
---
title: Model Source (Unannotated)
Author: J. Kirby Ross <[email protected]> (https://github.com/flyingrobots)
Created: 2025-10-27
License: MIT
Scope: This document defines the minimal, requisite semantics and invariants that a Git-native ledger implementation must satisfy to be considered compliant.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Minor: Add language specifiers to all fenced code blocks (MD040).

Fenced blocks at lines 5, 20, 26, 32 lack language identifiers (e.g., ```math or ```latex). While semantically neutral for content display, explicitly declaring the block type improves tooling and accessibility.

-```
+```math
 \mathcal{R} = (\mathcal{O}, \mathcal{R_{efs}})
-```
+```

Repeat for all remaining code fences.

Also applies to: 20-20, 26-26, 32-32

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

5-5: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In docs/spec/model-source.md around lines 5, 20, 26, and 32, several fenced code
blocks are missing language specifiers; update each opening fence to include an
appropriate language identifier (e.g., ```math or ```latex) that reflects the
block content, leaving the closing fences as-is so the blocks remain properly
delimited; ensure the chosen identifier matches the block semantics for tooling
and accessibility.

Status: Draft
Summary: Defines the invariants, operations, and compliance requirements for a Git-native append-only ledger.
Version: 0.1.0
---

# Model Source (Unannotated)
# **A Formal State-Transition Model for a Git-Native Verifiable Ledger**

This page is auto‑generated from the repository‑root `MODEL.md` during the docs build to preserve the canonical, unannotated text.
## Abstract

> The curated specification lives at [/spec/model](/spec/model). This page mirrors the raw source for reference.
We present a formal state-transition model for a verifiable ledger kernel operating natively on a Git-based Directed Acyclic Graph (DAG). The model defines a ledger as a totally ordered sequence of entries, where each entry represents an atomic state transition. We formalize the system's core components: a pure state transition function $\mathcal{T}$, a constraint-based policy engine $\mathcal{P}$, and a cryptographic attestation mechanism $\mathcal{A}$. The central thesis of our model is the guarantee of **deterministic replayability**, where the ledger's final state is a pure function of its entry-set. This formalism provides a verifiable foundation for trusted, distributed systems, such as software supply chain attestation or decentralized registries.

<!-- The build step copies MODEL.md here. -->
---

## 1. Introduction

The Git object model, fundamentally a content-addressed Directed Acyclic Graph (DAG), provides a robust mechanism for tracking provenance. However, its inherent support for branching and non-linear histories complicates its use as a linear, append-only ledger. This paper introduces a formal model that superimposes a **totally ordered state machine** onto the Git DAG. We achieve this by constraining a specific Git reference (ref) to a fast-forward-only commit history, where each commit constitutes a **ledger entry** ($\mathcal{E}$). This model establishes the semantic bridge between low-level Git objects and high-level, verifiable ledger state transitions, enabling deterministic replay and cryptographic verification of the ledger's history and state.

---

## 2. Formal Model Definition

Let a Git repository be a tuple $\mathcal{R} = (\mathcal{O}, \mathcal{R_{efs}})$, where $\mathcal{O}$ is a content-addressed object store (a set of Git objects) and $\mathcal{R_{efs}}$ is a mapping from reference paths to commit identifiers (hashes).

We define a **Ledger Entry**, $\mathcal{E}$, as a commit object $C \in \mathcal{O}$ that adheres to a specific data schema (e.g., contains `/_ledger/entry.json` and associated attestations).

We define a Ledger, $\mathcal{L}$, as a tuple:

$$
\mathcal{L} = (p, \mathbf{E}, \mathcal{A}, \mathcal{P})
$$

where:

- $p$ is the persistent reference path (e.g., `refs/heads/main-ledger`) in $\mathcal{R_{efs}}$.
- $\mathbf{E} = \langle \mathcal{E}_0, \mathcal{E}_1, \dots, \mathcal{E}_n \rangle$ is a **totally ordered sequence** of ledger entries. This ordering is strictly enforced by the commit ancestry relation under $p$, s.t. $\text{Parent}(\mathcal{E}_{i+1}) = \text{Hash}(\mathcal{E}_i)$.
- $\mathcal{A}$ is the set of all attestations, where each $\mathcal{A}_k \in \mathcal{A}$ is cryptographically bound to a specific entry $\mathcal{E}_i \in \mathbf{E}$.
- $\mathcal{P}$ is a set of policies applicable to $\mathcal{L}$.

The _head_ of the ledger $\mathcal{L}$ corresponds to the commit hash $\text{Hash}(\mathcal{E}_n)$, which is the value of $\mathcal{R_{efs}}[p]$.

---

## 3. The State Transition System

The ledger's semantics are defined by a deterministic state transition system.

Let $\mathcal{S}$ be the set of all possible ledger states. We define the initial state as the empty set: $\mathcal{S}_0 = \emptyset$.

We define a pure, deterministic state transition function $\mathcal{T}$:

$$
\mathcal{T} : \mathcal{S} \times \mathcal{E} \to \mathcal{S}
$$

Given a current state $\mathcal{S}_i$ (derived from entry $\mathcal{E}_i$), the subsequent state $\mathcal{S}_{i+1}$ is produced by applying the next entry $\mathcal{E}_{i+1}$:

$$
\mathcal{S}_{i+1} = \mathcal{T}(\mathcal{S}_i, \mathcal{E}_{i+1})
$$

The function $\mathcal{T}$ must be **deterministic** and **pure**; it must produce an identical output state $\mathcal{S}_{i+1}$ given identical inputs $(\mathcal{S}_i, \mathcal{E}_{i+1})$, with no reliance on external I/O, network state, or stochastic processes.

### 3.1. State Re-computation (Replay)

The complete state $\mathcal{S}_n$ of a ledger $\mathcal{L}$ with $n$ entries is the result of a functional fold (or reduction) over the entry sequence $\mathbf{E}$:

$$
\mathcal{S}_n = \text{foldl}(\mathcal{T}, \mathcal{S}_0, \mathbf{E})
$$

Recursively, this is defined as:

- $\text{Replay}(\langle \rangle) = \mathcal{S}_0$
- $\text{Replay}(\langle \mathcal{E}_0, \dots, \mathcal{E}_i \rangle) = \mathcal{T}(\text{Replay}(\langle \mathcal{E}_0, \dots, \mathcal{E}_{i-1} \rangle), \mathcal{E}_i)$

This property is the foundation of the system's verifiability.

---

## 4. Transition Validity

Important: For a new entry $\mathcal{E}_{i+1}$ to be appended to the ledger at state $\mathcal{S}_i$, a global validity predicate $\mathcal{V}$ must evaluate to true.

$$
\mathcal{V}(\mathcal{E}_{i+1}, \mathcal{E}_i, \mathcal{S}_i, \mathcal{P}) \to \{\text{true}, \text{false}\}
$$

The predicate $\mathcal{V}$ is the logical conjunction of the following constraints:

1. Ancestry Constraint: The entry must maintain the fast-forward chain.

$$
\text{ParentHash}(\mathcal{E}_{i+1}) \equiv \text{Hash}(\mathcal{E}_i)
$$

2. Temporal Monotonicity: The entry's timestamp must be non-decreasing.

$$
\text{Timestamp}(\mathcal{E}_{i+1}) \geq \text{Timestamp}(\mathcal{E}_i)
$$

3. Policy Adherence: The entry must satisfy all active policies $\mathcal{P}_k \in \mathcal{P}$, evaluated against the current state $\mathcal{S}_i$. (See §5).

$$
\mathcal{P}_{\text{all}}(\mathcal{E}, \mathcal{S}) = \bigwedge_{k \in \mathcal{P}} \mathcal{P}_k(\mathcal{E}, \mathcal{S}) \equiv \text{true}
$$

4. Attestation Validity: All attestations $\mathcal{A}_k$ attached to $\mathcal{E}_{i+1}$ must be cryptographically valid. (See §6).

$$
\forall \mathcal{A}_k:\; \mathcal{V}_{\text{attest}}\!\left(\mathcal{A}_k,\; \text{Hash}(\mathcal{E}_{i+1})\right) \equiv \text{true}
$$

If $\mathcal{V}$ fails, the transition is rejected, and the entry $\mathcal{E}_{i+1}$ is not appended to the ledger $\mathcal{L}$.

---

### **5. Policy as a State Constraint**

A policy is a pure function (a predicate) that constrains valid transitions.

Policies are executed _before_ the state transition function $\mathcal{T}$ is applied. They are evaluated using the candidate entry ($\mathcal{E}_{i+1}$) and the previous state ($\mathcal{S}_i$).

Policies are composable, typically via logical conjunction:

$$
\mathcal{P}_{\text{all}}(\mathcal{E}, \mathcal{S}) = \bigwedge_{k \in \mathcal{P}} \mathcal{P}_k(\mathcal{E}, \mathcal{S}) \equiv \text{true}
$$

---

### **6. Attestation Model**

An attestation $\mathcal{A}$ provides a non-repudiable cryptographic binding between an external identity (signer) and a specific ledger entry $\mathcal{E}$.

Let $\mathcal{A}$ be a tuple $\mathcal{A} = (\text{signer\_id}, \sigma)$, where $\sigma$ is a digital signature.

The verification function $\mathcal{V}_{\text{attest}}$ (informally) checks that each attestation’s signature verifies against the entry hash with the signer’s public key.
Loading