diff --git a/src/codex32/correction.py b/src/codex32/correction.py index 9abd345..5df1a1c 100644 --- a/src/codex32/correction.py +++ b/src/codex32/correction.py @@ -22,7 +22,7 @@ """Fixed BCH correction derived from PR #70, with reverse-indexed coordinates.""" from collections.abc import Callable, Sequence -from dataclasses import dataclass, replace +from dataclasses import dataclass, field, replace from functools import cache, lru_cache from math import comb from time import monotonic @@ -85,8 +85,8 @@ def __init__( class CorrectionEdit: kind: Literal["substitution", "erasure", "insertion", "deletion", "transposition"] reverse_index: int - observed: str - replacement: str + observed: str = field(repr=False) + replacement: str = field(repr=False) @dataclass(frozen=True, slots=True) diff --git a/tests/test_public_api.py b/tests/test_public_api.py index 09d66d4..1901802 100644 --- a/tests/test_public_api.py +++ b/tests/test_public_api.py @@ -11,7 +11,16 @@ from data.bip93_vectors import VECTOR_2 import codex32 -from codex32 import CorrectionCandidate, Header, MasterSeed, Share, parse_codex32 +from codex32 import ( + CorrectionCandidate, + CorrectionContext, + Header, + MasterSeed, + Profile, + Share, + correct, + parse_codex32, +) from codex32.errors import InvalidIdentifier, InvalidShareIndex, InvalidThreshold @@ -95,6 +104,16 @@ def test_artifact_default_rendering_does_not_disclose_recovery_text() -> None: assert repr(share) == "Share()" +def test_correction_edits_do_not_render_recovery_characters() -> None: + text = VECTOR_2["share_A"] + candidate = correct(CorrectionContext(Profile.MS), text[:9] + "?" * 8 + text[17:])[0] + rendered = repr(candidate) + + assert len(candidate.edits) == 8 + assert all(f"'{edit.replacement}'" not in rendered for edit in candidate.edits) + assert "observed" not in rendered and "replacement" not in rendered + + def test_master_seed_default_rendering_does_not_disclose_seed_material() -> None: secret = MasterSeed.from_seed(bytes(range(16)), identifier="test")