# Target Ledger Specification (Normative Extract) **Document version:** TRF-Ledger-0.1 **Status:** Normative extract, Stage 0 **Extracted from:** `spec/TargetRevenueLicenseConcept.md` §17 and `specs/TechnicalSpecificationDocument.md` §3.2 **Machine-readable counterpart:** `schemas/ledger_entry.schema.json` — implemented and tested under `workplans/TREV-WP-0002-trust-service-foundation.md` T03 (`src/target_revenue/hashing.py`, `src/target_revenue/fold.py`). This document is the prose normative reference; the schema and library are the authoritative machine-checkable implementation. --- ## 1. Purpose The Target Ledger is the append-only record of everything that moves a Phase's Outstanding Target. It is the sole input, together with the Phase Manifest, to the Outstanding Target fold and therefore to Conversion Event detection (`specs/TargetRevenueFrameworkCore.md` §1.7–§1.8). ## 2. Entry types (closed set) | Type | Effect on fold | Notes | |---|---|---| | `development-credit` | `+= amount` to Development Credit | Rule 4: normally arises only from settled payments. | | `remission-credit` | `+= amount` to Remission Credit | Rule 5: never represented as revenue. | | `credit-reversal` | `-= amount` from Development Credit | Rule 8: compensating entry; requires `reverses` pointing to the original entry id. Never edits or deletes the original. | | `remission-correction` | `+= amount` to Remission Credit (amount may be negative) | Requires `reverses`. | | `administrative-correction` | `+= amount` to Development Credit | **Stage 0 simplification:** a generic correction bucket, not yet specialized by which side of the target it corrects. Revisit if this proves ambiguous in practice. | | `conversion-checkpoint` | No numeric effect | Marker only. | This set is closed for Stage 0: a project **must not** invent new entry types; new monetization behavior belongs in an extension (`specs/MonetizationExtensionSpecification.md`), not a new ledger entry type. ## 3. Required entry fields | Field | Type | Notes | |---|---|---| | `id` | string (URN `trsl:entry:`) | Globally unique, monotonically orderable. | | `phase` | string (Phase URN) | Must reference a published Phase Manifest. | | `type` | enum (§2) | | | `amount` | decimal | Sign convention per §2. | | `currency` | ISO 4217 code | **Must match** the Phase's `initial_target.currency` (working default Q6). No FX conversion in the pure fold; a currency mismatch is rejected, not converted. | | `recognized_at` | ISO 8601 timestamp | Settlement time, not invoice time (Rule 4; working default Q10: `payment-settled` recognition only). | | `extension.id` / `extension.version` | string / string | Required for `development-credit` / `remission-credit`: identifies the monetization profile or degeneration policy that produced the entry. | | `evidence_reference` | URI (`confidential:` scheme allowed) | Tiered per working default Q10 (E0 opaque id / E1 settled payment reference / E2 contract+invoice+settlement). | | `previous_entry_hash` | hex-64 or literal `GENESIS` | SHA-256 of the prior entry's canonical serialization for this Phase (§4). | | `signature` | string | Ed25519 signature over the canonical serialization (working default Q14); optional in Stage 0 fixtures, required for any public claim. | | `reverses` | string (entry URN) | Required on `credit-reversal` and `remission-correction`. | ## 4. Hash chain and canonical serialization **Working default (Q14), accepted via ADR-0001:** canonical serialization is JSON with sorted keys, no insignificant whitespace, UTF-8 encoding, excluding the `signature` and `previous_entry_hash` fields themselves. The chain hash is SHA-256 over that serialization. The first entry for a Phase has `previous_entry_hash: GENESIS`; every subsequent entry's `previous_entry_hash` must equal the SHA-256 digest of the immediately preceding entry's canonical bytes. Reference implementation: `src/target_revenue/hashing.py::entry_hash`, `verify_chain`. ## 5. Corrections without erasure Per Rule 8, the ledger is append-only. A correction or reversal is always a **new** entry (`credit-reversal`, `remission-correction`, or `administrative-correction`) referencing the entry it corrects via `reverses` — never an edit or deletion of the original. This preserves the audit trail even when the correction is disputed. ## 6. Outstanding Target fold (normative definition) ```text Outstanding Target = max(0, Initial Target − Σ(development-credit, administrative-correction) − Σ(remission-credit, remission-correction) + Σ(credit-reversal)) ``` Equivalently, per entry type effect in §2, folded left-to-right over the Phase's entries in ledger order. The fold is **pure**: identical `(Initial Target, entries)` input always yields identical output, with no hidden state (TSD §6.1). Reference implementation: `src/target_revenue/fold.py::fold_outstanding_target`. The fold **must** be independently reproducible by any conformant external tool from the Phase Manifest and Target Ledger alone — no Trust Service state is required (PRD NFR-1). ## 7. Currency consistency rule Working default Q6: every entry's `currency` must equal the Phase's `initial_target.currency`. A mismatch is rejected outright in Stage 0; there is no FX conversion step in the pure fold. A future FX extension may be registered, but until then multi-currency Phases are out of scope. Reference implementation: `src/target_revenue/validation.py::check_currency_consistency`. ## 8. Not covered here - Phase Manifest fields: `specs/PhaseManifestSpecification.md`. - Extension contract fields referenced by `extension.id`/`extension.version`: `specs/MonetizationExtensionSpecification.md`. - Conversion Attestation document schema: `specs/TechnicalSpecificationDocument.md` §3.5 (a dedicated extract is not yet planned; the TSD section remains authoritative). - Signature key management and rotation: working default Q14 notes an append-only key history document; not yet specified in a dedicated file.