"""Anti-goal tests: things that MUST NOT work across the two refimpls. Forging one token type as the other, or building mixed-type DAGs, must be rejected. These tests pin the negative space so silent drift cannot erase the type boundary. """ from __future__ import annotations import pytest from act.errors import ACTValidationError from act.token import decode_jws as act_decode_jws from ect.verify import verify as ect_verify, VerifyOptions class TestNoForgery: def test_act_compact_is_not_verifiable_as_ect( self, act_record_builder, dual_resolver ): """Feeding an ACT compact into ECT.verify must raise — the typ gate is the wall.""" _, ect_resolver = dual_resolver compact, _ = act_record_builder() opts = VerifyOptions(resolve_key=ect_resolver) with pytest.raises(ValueError, match="invalid typ parameter"): ect_verify(compact, opts) def test_ect_compact_is_not_verifiable_as_act( self, ect_payload_builder, dual_resolver ): """Feeding an ECT compact into ACT decoder must raise.""" act_resolver, _ = dual_resolver compact, _ = ect_payload_builder() with pytest.raises(ACTValidationError): act_decode_jws(compact) class TestNoMixedTypeDAG: """Documents what cross-type storage actually does in practice. Finding: neither refimpl performs runtime isinstance checks on the objects it stores — Python duck-typing means an ECT Payload that happens to expose `.jti` can be appended to ACTLedger without error. This is a real interop hazard worth surfacing in the compatibility matrix rather than papering over. """ def test_act_ledger_does_not_type_check_ect_payload( self, ect_payload_builder ): """ACTLedger.append accepts anything with a `.jti` attribute. This is NOT a good thing — it just means the refimpl relies on caller discipline. Production bridges must enforce type checks externally. """ from act.ledger import ACTLedger ledger = ACTLedger() _, ect_pl = ect_payload_builder() # Append does not raise — duck typing lets the ECT Payload # pass through because it has .jti. Pinning this as a # documented hazard. seq = ledger.append(ect_pl) # type: ignore[arg-type] assert isinstance(seq, int) def test_ect_ledger_interface_for_act_record(self, act_record_builder): """ECT MemoryLedger surface — document whatever happens when fed an ACT record. This is a doc anchor; the exact behaviour depends on which method the ledger exposes.""" from ect.ledger import MemoryLedger ledger = MemoryLedger() _, act_rec = act_record_builder() # Inspect the concrete API to document which methods exist; # none are typed strictly in Python, so we accept either # "raises" or "silently stores" and pin whichever is current. tried = [] for name in ("append", "add", "record", "put", "store"): meth = getattr(ledger, name, None) if meth is None: continue tried.append(name) try: meth(act_rec) # type: ignore[arg-type] except Exception: pass break # Just require that we found a callable surface and exercised it. assert tried, "ect.MemoryLedger should expose at least one write API"