from __future__ import annotations import unittest from cognitive_agent.auth import ( AuthConfig, SessionCodec, SlidingWindowLimiter, hash_password, verify_password, ) def auth_config() -> AuthConfig: return AuthConfig( enabled=True, username="demo-user", password_hash=hash_password( "correct horse battery staple", salt=b"0123456789abcdef", iterations=100_000, ), session_secret=b"s" * 64, session_ttl_seconds=3600, login_attempts=3, login_window_seconds=60, requests_per_minute=10, trust_proxy_headers=False, ) class AuthenticationUnitTests(unittest.TestCase): def test_password_hash_verification(self) -> None: encoded = auth_config().password_hash self.assertTrue(verify_password("correct horse battery staple", encoded)) self.assertFalse(verify_password("wrong password", encoded)) self.assertNotIn("correct horse battery staple", encoded) def test_signed_session_rejects_tampering_and_expiry(self) -> None: codec = SessionCodec(auth_config()) token = codec.issue("demo-user", now=1000) self.assertEqual(codec.verify(token, now=1001), "demo-user") self.assertIsNone(codec.verify(token + "x", now=1001)) self.assertIsNone(codec.verify(token, now=4600)) def test_sliding_window_limiter_returns_retry_after(self) -> None: limiter = SlidingWindowLimiter(limit=2, window_seconds=60) limiter.record("client", now=100) limiter.record("client", now=110) self.assertEqual(limiter.retry_after("client", now=120), 40) self.assertEqual(limiter.retry_after("client", now=161), 0) if __name__ == "__main__": unittest.main()