Implement TREV-WP-0002 Stage 0 foundation: schemas, pure fold, golden Phase
Delivers the offline runnable specification foundation for the Trust Layer
(TSD §3-§6), not a hosted Trust Service:
- JSON Schemas for Phase Manifest, Ledger Entry, Extension Contract, and
Conversion Attestation, encoding the Stage 0 working defaults (Q3 future
license enum, Q6 single-currency Phases, Q8 required longstop_at).
- src/target_revenue: pure Outstanding Target fold, SHA-256 hash-chain
verification, Ed25519 signing helpers, extension conformance checks
(including a core-term-redefinition heuristic), and conversion detection
that never requires an attestation document to determine conversion status.
- examples/phase-001: golden Phase package matching the concept doc's
worked example, generated via scripts/generate_golden_phase.py so the
hash chain is computed by the library itself, not hand-typed.
- 32 passing pytest tests covering manifest/ledger/extension conformance,
tamper/reorder detection, and the full lifecycle fold to conversion.
- docs/adr/ADR-0001: proposed (not accepted) Stage 0 stack choice, per the
WP-0002-T01 human-accept gate — implementation proceeded against the
proposal as the workplan note permits, but the task stays open.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 18:47:29 +02:00
|
|
|
import copy
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
from conftest import golden_entries, golden_manifest
|
|
|
|
|
|
|
|
|
|
from target_revenue import fold, hashing, validation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_golden_entries_are_individually_conformant():
|
|
|
|
|
for entry in golden_entries():
|
|
|
|
|
validation.validate_ledger_entry(entry)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_golden_entries_currency_matches_phase():
|
|
|
|
|
errors = validation.check_currency_consistency(golden_manifest(), golden_entries())
|
|
|
|
|
assert errors == []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_currency_mismatch_is_detected():
|
|
|
|
|
manifest = golden_manifest()
|
|
|
|
|
entries = copy.deepcopy(golden_entries())
|
|
|
|
|
entries[0]["currency"] = "EUR"
|
|
|
|
|
errors = validation.check_currency_consistency(manifest, entries)
|
|
|
|
|
assert len(errors) == 1
|
|
|
|
|
assert "EUR" in errors[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_golden_hash_chain_is_valid():
|
|
|
|
|
hashing.verify_chain(golden_entries())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_tampered_entry_breaks_hash_chain():
|
|
|
|
|
entries = copy.deepcopy(golden_entries())
|
|
|
|
|
entries[2]["amount"] = 999999 # tamper after the chain was computed
|
|
|
|
|
with pytest.raises(ValueError, match="hash chain broken"):
|
|
|
|
|
hashing.verify_chain(entries)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_reordered_entries_break_hash_chain():
|
|
|
|
|
entries = copy.deepcopy(golden_entries())
|
|
|
|
|
entries[1], entries[2] = entries[2], entries[1]
|
|
|
|
|
with pytest.raises(ValueError, match="hash chain broken"):
|
|
|
|
|
hashing.verify_chain(entries)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_fold_matches_concept_section_23_first_checkpoint():
|
2026-07-29 10:22:14 +02:00
|
|
|
"""specs/TargetRevenueLicenseConcept.md §23: after the first four entries,
|
Implement TREV-WP-0002 Stage 0 foundation: schemas, pure fold, golden Phase
Delivers the offline runnable specification foundation for the Trust Layer
(TSD §3-§6), not a hosted Trust Service:
- JSON Schemas for Phase Manifest, Ledger Entry, Extension Contract, and
Conversion Attestation, encoding the Stage 0 working defaults (Q3 future
license enum, Q6 single-currency Phases, Q8 required longstop_at).
- src/target_revenue: pure Outstanding Target fold, SHA-256 hash-chain
verification, Ed25519 signing helpers, extension conformance checks
(including a core-term-redefinition heuristic), and conversion detection
that never requires an attestation document to determine conversion status.
- examples/phase-001: golden Phase package matching the concept doc's
worked example, generated via scripts/generate_golden_phase.py so the
hash chain is computed by the library itself, not hand-typed.
- 32 passing pytest tests covering manifest/ledger/extension conformance,
tamper/reorder detection, and the full lifecycle fold to conversion.
- docs/adr/ADR-0001: proposed (not accepted) Stage 0 stack choice, per the
WP-0002-T01 human-accept gate — implementation proceeded against the
proposal as the workplan note permits, but the task stays open.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 18:47:29 +02:00
|
|
|
Development Credit $37,000, Remission Credit $18,000, Outstanding $45,000."""
|
|
|
|
|
manifest = golden_manifest()
|
|
|
|
|
first_four = golden_entries()[:4]
|
|
|
|
|
result = fold.fold_outstanding_target(
|
|
|
|
|
manifest["phase"]["initial_target"]["amount"], first_four
|
|
|
|
|
)
|
|
|
|
|
assert result.development_credit == 37000
|
|
|
|
|
assert result.remission_credit == 18000
|
|
|
|
|
assert result.outstanding_target == 45000
|
|
|
|
|
assert not result.is_converted
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_fold_reaches_zero_and_converts():
|
2026-07-29 10:22:14 +02:00
|
|
|
"""specs/TargetRevenueLicenseConcept.md §23: full six-entry sequence
|
Implement TREV-WP-0002 Stage 0 foundation: schemas, pure fold, golden Phase
Delivers the offline runnable specification foundation for the Trust Layer
(TSD §3-§6), not a hosted Trust Service:
- JSON Schemas for Phase Manifest, Ledger Entry, Extension Contract, and
Conversion Attestation, encoding the Stage 0 working defaults (Q3 future
license enum, Q6 single-currency Phases, Q8 required longstop_at).
- src/target_revenue: pure Outstanding Target fold, SHA-256 hash-chain
verification, Ed25519 signing helpers, extension conformance checks
(including a core-term-redefinition heuristic), and conversion detection
that never requires an attestation document to determine conversion status.
- examples/phase-001: golden Phase package matching the concept doc's
worked example, generated via scripts/generate_golden_phase.py so the
hash chain is computed by the library itself, not hand-typed.
- 32 passing pytest tests covering manifest/ledger/extension conformance,
tamper/reorder detection, and the full lifecycle fold to conversion.
- docs/adr/ADR-0001: proposed (not accepted) Stage 0 stack choice, per the
WP-0002-T01 human-accept gate — implementation proceeded against the
proposal as the workplan note permits, but the task stays open.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 18:47:29 +02:00
|
|
|
reaches Outstanding Target = 0 (Development Credit $67,000 + Remission
|
|
|
|
|
Credit $33,000 = Initial Target $100,000)."""
|
|
|
|
|
manifest = golden_manifest()
|
|
|
|
|
result = fold.fold_phase(manifest, golden_entries())
|
|
|
|
|
assert result.development_credit == 67000
|
|
|
|
|
assert result.remission_credit == 33000
|
|
|
|
|
assert result.outstanding_target == 0
|
|
|
|
|
assert result.is_converted
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_credit_reversal_reduces_development_credit():
|
|
|
|
|
entries = [
|
|
|
|
|
{
|
|
|
|
|
"id": "trsl:entry:t0001",
|
|
|
|
|
"phase": "trsl:phase:t",
|
|
|
|
|
"type": "development-credit",
|
|
|
|
|
"amount": 5000,
|
|
|
|
|
"currency": "USD",
|
|
|
|
|
"recognized_at": "2026-01-01T00:00:00Z",
|
|
|
|
|
"extension": {"id": "trsl:extension:development-license", "version": "1.0"},
|
|
|
|
|
"evidence_reference": "confidential:evidence:t0001",
|
|
|
|
|
"previous_entry_hash": "GENESIS",
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
entries.append(
|
|
|
|
|
{
|
|
|
|
|
"id": "trsl:entry:t0002",
|
|
|
|
|
"phase": "trsl:phase:t",
|
|
|
|
|
"type": "credit-reversal",
|
|
|
|
|
"amount": 5000,
|
|
|
|
|
"currency": "USD",
|
|
|
|
|
"recognized_at": "2026-01-02T00:00:00Z",
|
|
|
|
|
"evidence_reference": "confidential:evidence:t0002-refund",
|
|
|
|
|
"previous_entry_hash": hashing.entry_hash(entries[0]),
|
|
|
|
|
"reverses": "trsl:entry:t0001",
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
result = fold.fold_outstanding_target(100000, entries)
|
|
|
|
|
assert result.development_credit == 0
|
|
|
|
|
assert result.outstanding_target == 100000
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_remission_correction_can_reduce_over_remission():
|
|
|
|
|
entries = [
|
|
|
|
|
{
|
|
|
|
|
"id": "trsl:entry:t0001",
|
|
|
|
|
"phase": "trsl:phase:t",
|
|
|
|
|
"type": "remission-credit",
|
|
|
|
|
"amount": 20000,
|
|
|
|
|
"currency": "USD",
|
|
|
|
|
"recognized_at": "2026-01-01T00:00:00Z",
|
|
|
|
|
"extension": {"id": "trsl:policy:linear-longstop-v0", "version": "1.0"},
|
|
|
|
|
"evidence_reference": "confidential:evidence:t0001",
|
|
|
|
|
"previous_entry_hash": "GENESIS",
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
entries.append(
|
|
|
|
|
{
|
|
|
|
|
"id": "trsl:entry:t0002",
|
|
|
|
|
"phase": "trsl:phase:t",
|
|
|
|
|
"type": "remission-correction",
|
|
|
|
|
"amount": -5000,
|
|
|
|
|
"currency": "USD",
|
|
|
|
|
"recognized_at": "2026-01-02T00:00:00Z",
|
|
|
|
|
"evidence_reference": "confidential:evidence:t0002-correction",
|
|
|
|
|
"previous_entry_hash": hashing.entry_hash(entries[0]),
|
|
|
|
|
"reverses": "trsl:entry:t0001",
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
result = fold.fold_outstanding_target(100000, entries)
|
|
|
|
|
assert result.remission_credit == 15000
|
|
|
|
|
assert result.outstanding_target == 85000
|
2026-07-29 09:16:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_administrative_correction_development_adjusts_development_side():
|
|
|
|
|
entries = [
|
|
|
|
|
{
|
|
|
|
|
"id": "trsl:entry:t0001",
|
|
|
|
|
"phase": "trsl:phase:t",
|
|
|
|
|
"type": "administrative-correction-development",
|
|
|
|
|
"amount": 3000,
|
|
|
|
|
"currency": "USD",
|
|
|
|
|
"recognized_at": "2026-01-01T00:00:00Z",
|
|
|
|
|
"evidence_reference": "confidential:evidence:t0001-admin",
|
|
|
|
|
"previous_entry_hash": "GENESIS",
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
result = fold.fold_outstanding_target(100000, entries)
|
|
|
|
|
assert result.development_credit == 3000
|
|
|
|
|
assert result.remission_credit == 0
|
|
|
|
|
assert result.outstanding_target == 97000
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_administrative_correction_remission_adjusts_remission_side():
|
|
|
|
|
entries = [
|
|
|
|
|
{
|
|
|
|
|
"id": "trsl:entry:t0001",
|
|
|
|
|
"phase": "trsl:phase:t",
|
|
|
|
|
"type": "administrative-correction-remission",
|
|
|
|
|
"amount": 3000,
|
|
|
|
|
"currency": "USD",
|
|
|
|
|
"recognized_at": "2026-01-01T00:00:00Z",
|
|
|
|
|
"evidence_reference": "confidential:evidence:t0001-admin",
|
|
|
|
|
"previous_entry_hash": "GENESIS",
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
result = fold.fold_outstanding_target(100000, entries)
|
|
|
|
|
assert result.development_credit == 0
|
|
|
|
|
assert result.remission_credit == 3000
|
|
|
|
|
assert result.outstanding_target == 97000
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_administrative_correction_types_are_schema_valid():
|
|
|
|
|
from target_revenue import validation
|
|
|
|
|
|
|
|
|
|
for entry_type in (
|
|
|
|
|
"administrative-correction-development",
|
|
|
|
|
"administrative-correction-remission",
|
|
|
|
|
):
|
|
|
|
|
entry = {
|
|
|
|
|
"id": "trsl:entry:t0001",
|
|
|
|
|
"phase": "trsl:phase:t",
|
|
|
|
|
"type": entry_type,
|
|
|
|
|
"amount": 100,
|
|
|
|
|
"currency": "USD",
|
|
|
|
|
"recognized_at": "2026-01-01T00:00:00Z",
|
|
|
|
|
"evidence_reference": "confidential:evidence:t0001",
|
|
|
|
|
"previous_entry_hash": "GENESIS",
|
|
|
|
|
}
|
|
|
|
|
validation.validate_ledger_entry(entry)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_old_unsplit_administrative_correction_type_is_no_longer_valid():
|
|
|
|
|
"""The single ambiguous administrative-correction type was split
|
|
|
|
|
2026-07-29 (specs/TargetLedgerSpecification.md §2); it must no longer
|
|
|
|
|
validate as a known type."""
|
|
|
|
|
from target_revenue import validation
|
|
|
|
|
|
|
|
|
|
entry = {
|
|
|
|
|
"id": "trsl:entry:t0001",
|
|
|
|
|
"phase": "trsl:phase:t",
|
|
|
|
|
"type": "administrative-correction",
|
|
|
|
|
"amount": 100,
|
|
|
|
|
"currency": "USD",
|
|
|
|
|
"recognized_at": "2026-01-01T00:00:00Z",
|
|
|
|
|
"evidence_reference": "confidential:evidence:t0001",
|
|
|
|
|
"previous_entry_hash": "GENESIS",
|
|
|
|
|
}
|
|
|
|
|
with pytest.raises(validation.ConformanceError):
|
|
|
|
|
validation.validate_ledger_entry(entry)
|