diff --git a/tests/helpers.py b/tests/helpers.py new file mode 100644 index 0000000..2f5c275 --- /dev/null +++ b/tests/helpers.py @@ -0,0 +1,54 @@ +"""Shared test helpers. + +issue_code() requires a live agent session, so tests that mint codes have to +prove key possession the same way production does rather than reaching past the +boundary. These helpers do that so the tests stay readable. +""" + +import base64 + +from sigil import identity, keys, viewcodes +from sigil.store import Store + + +def enrol(store, agent="bigpickle"): + """Enrol agent with a fresh key. Returns (private, public).""" + private, public = keys.generate() + secret = identity.seed_bootstrap(store, agent) + identity.enrol(store, agent, keys.export_public_b64(public), secret) + return private, public + + +def sign(private, nonce): + return base64.b64encode(private.sign(nonce.encode())).decode() + + +def agent_token(store, private, agent="bigpickle", limit=5000, window=60): + """Full challenge-response, ending in a live agent session token. + + The rate limit is opened wide by default: tests that legitimately mint many + codes should not trip the production quota. The quota itself is asserted in + test_hardening.TestRateLimits. + """ + chal = identity.challenge(store, agent, limit=limit, window=window) + sig = sign(private, chal["nonce"]) + return identity.verify( + store, chal["nonce"], sig, limit=limit, window=window + )["token"] + + +def issue(store, private, agent="bigpickle", **kw): + """Mint a view code the way production does: authenticate, then ask. + + `limit`/`window` tune both the challenge quota and the code quota, since a + test that mints many codes trips both. + """ + quota = {k: kw[k] for k in ("limit", "window") if k in kw} + token = agent_token(store, private, agent, **quota) + return viewcodes.issue_code(store, token, **kw) + + +def fresh(agent="bigpickle"): + store = Store(":memory:") + private, _ = enrol(store, agent) + return store, private \ No newline at end of file