"""Tests for act.lifecycle module.""" import time import uuid import pytest from act.crypto import generate_ed25519_keypair, sign from act.errors import ACTCapabilityError, ACTPhaseError from act.lifecycle import transition_to_record from act.token import ( ACTMandate, ACTRecord, Capability, Delegation, ErrorClaim, TaskClaim, decode_jws, encode_jws, ) from act.crypto import verify @pytest.fixture def keys(): iss_priv, iss_pub = generate_ed25519_keypair() sub_priv, sub_pub = generate_ed25519_keypair() return iss_priv, iss_pub, sub_priv, sub_pub @pytest.fixture def mandate(keys): iss_priv, _, _, _ = keys m = ACTMandate( alg="EdDSA", kid="iss-key", iss="agent-a", sub="agent-b", aud="agent-b", iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()), task=TaskClaim(purpose="test"), cap=[Capability(action="read.data"), Capability(action="write.result")], delegation=Delegation(depth=0, max_depth=2, chain=[]), ) return m class TestTransitionToRecord: def test_basic_transition(self, mandate, keys): _, _, sub_priv, sub_pub = keys record, compact = transition_to_record( mandate, sub_kid="sub-key", sub_private_key=sub_priv, exec_act="read.data", par=[], status="completed", ) assert isinstance(record, ACTRecord) assert record.exec_act == "read.data" assert record.kid == "sub-key" assert record.iss == mandate.iss # preserved # Verify signature _, _, sig, si = decode_jws(compact) verify(sub_pub, sig, si) def test_with_hashes(self, mandate, keys): _, _, sub_priv, _ = keys record, _ = transition_to_record( mandate, sub_kid="k", sub_private_key=sub_priv, exec_act="write.result", par=[], status="completed", inp_hash="abc", out_hash="def", ) assert record.inp_hash == "abc" assert record.out_hash == "def" def test_with_error(self, mandate, keys): _, _, sub_priv, _ = keys record, _ = transition_to_record( mandate, sub_kid="k", sub_private_key=sub_priv, exec_act="read.data", par=[], status="failed", err=ErrorClaim(code="timeout", detail="request timed out"), ) assert record.status == "failed" assert record.err is not None assert record.err.code == "timeout" def test_rejects_bad_exec_act(self, mandate, keys): _, _, sub_priv, _ = keys with pytest.raises(ACTCapabilityError): transition_to_record( mandate, sub_kid="k", sub_private_key=sub_priv, exec_act="delete.everything", par=[], ) def test_preserves_phase1_claims(self, mandate, keys): _, _, sub_priv, _ = keys record, _ = transition_to_record( mandate, sub_kid="k", sub_private_key=sub_priv, exec_act="read.data", par=[], status="completed", ) assert record.iss == mandate.iss assert record.sub == mandate.sub assert record.aud == mandate.aud assert record.iat == mandate.iat assert record.exp == mandate.exp assert record.jti == mandate.jti assert record.task == mandate.task assert record.cap == mandate.cap