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>
This commit is contained in:
parent
658b1af00d
commit
57c7111cbc
28 changed files with 1751 additions and 7 deletions
61
tests/test_manifest_validation.py
Normal file
61
tests/test_manifest_validation.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import copy
|
||||
|
||||
import pytest
|
||||
from conftest import golden_manifest
|
||||
|
||||
from target_revenue import validation
|
||||
|
||||
|
||||
def test_golden_manifest_is_conformant():
|
||||
validation.validate_phase_manifest(golden_manifest())
|
||||
|
||||
|
||||
def test_manifest_missing_longstop_is_rejected():
|
||||
manifest = copy.deepcopy(golden_manifest())
|
||||
del manifest["phase"]["longstop_at"]
|
||||
with pytest.raises(validation.ConformanceError):
|
||||
validation.validate_phase_manifest(manifest)
|
||||
|
||||
|
||||
def test_manifest_bad_future_license_is_rejected():
|
||||
manifest = copy.deepcopy(golden_manifest())
|
||||
manifest["phase"]["future_license"] = "GPL-3.0"
|
||||
with pytest.raises(validation.ConformanceError):
|
||||
validation.validate_phase_manifest(manifest)
|
||||
|
||||
|
||||
def test_manifest_missing_required_field_is_rejected():
|
||||
manifest = copy.deepcopy(golden_manifest())
|
||||
del manifest["phase"]["initial_target"]
|
||||
with pytest.raises(validation.ConformanceError):
|
||||
validation.validate_phase_manifest(manifest)
|
||||
|
||||
|
||||
def test_manifest_rejects_unknown_top_level_field():
|
||||
manifest = copy.deepcopy(golden_manifest())
|
||||
manifest["unexpected_field"] = True
|
||||
with pytest.raises(validation.ConformanceError):
|
||||
validation.validate_phase_manifest(manifest)
|
||||
|
||||
|
||||
def test_initial_target_amount_immutable_across_versions():
|
||||
published = golden_manifest()
|
||||
candidate = copy.deepcopy(published)
|
||||
candidate["phase"]["initial_target"]["amount"] = 70000
|
||||
errors = validation.check_manifest_immutability(published, candidate)
|
||||
assert errors, "reducing initial_target.amount must be flagged"
|
||||
assert "initial_target.amount" in errors[0]
|
||||
|
||||
|
||||
def test_phase_id_immutable_across_versions():
|
||||
published = golden_manifest()
|
||||
candidate = copy.deepcopy(published)
|
||||
candidate["phase"]["id"] = "trsl:phase:example-002"
|
||||
errors = validation.check_manifest_immutability(published, candidate)
|
||||
assert errors
|
||||
assert "phase.id" in errors[0]
|
||||
|
||||
|
||||
def test_unchanged_manifest_has_no_immutability_violations():
|
||||
manifest = golden_manifest()
|
||||
assert validation.check_manifest_immutability(manifest, manifest) == []
|
||||
Loading…
Add table
Add a link
Reference in a new issue