Initial curated RAGcore source from c16667f0c9397e2bfc8dd0255b114fba23c8d05e

This commit is contained in:
Public Source Publisher committed 2026-10-01 01:34:21 +02:00
commit 7ca726caf2
659 files changed
+98171

No files matched your search

+88
View File
@@ -0,0 +1,88 @@
"""SignedTokenCodec: tamper-evidence and expiry."""
from __future__ import annotations
import base64
from collections.abc import Callable
from datetime import UTC, datetime, timedelta
import pytest
from ragcore.application.auth import SignedTokenCodec, TokenExpiredError, TokenTamperedError
SECRET = b"0" * 32
def _codec(clock: Callable[[], datetime] | None = None) -> SignedTokenCodec:
kwargs = {} if clock is None else {"clock": clock}
return SignedTokenCodec(secret=SECRET, **kwargs)
def test_round_trips_a_payload() -> None:
codec = _codec()
token = codec.encode({"sub": "alice"}, expires_at=datetime.now(UTC) + timedelta(minutes=5))
body = codec.decode(token)
assert body["sub"] == "alice"
def test_tampered_payload_is_rejected() -> None:
codec = _codec()
token = codec.encode({"sub": "alice"}, expires_at=datetime.now(UTC) + timedelta(minutes=5))
body_b64, signature_b64 = token.split(".", 1)
tampered = f"{body_b64}x.{signature_b64}"
with pytest.raises(TokenTamperedError):
codec.decode(tampered)
def test_tampered_signature_is_rejected() -> None:
codec = _codec()
token = codec.encode({"sub": "alice"}, expires_at=datetime.now(UTC) + timedelta(minutes=5))
body_b64, signature_b64 = token.split(".", 1)
# Flip a bit in the *decoded* signature bytes and re-encode, rather than
# editing the base64 text directly: replacing only the last character of
# a base64 string can, depending on the byte length, land on padding
# bits that don't change the decoded value at all -- flipping a real
# byte always changes the signature.
padding = "=" * (-len(signature_b64) % 4)
raw_signature = bytearray(base64.urlsafe_b64decode(signature_b64 + padding))
raw_signature[0] ^= 0xFF
tampered_signature_b64 = base64.urlsafe_b64encode(bytes(raw_signature)).rstrip(b"=").decode()
tampered = f"{body_b64}.{tampered_signature_b64}"
with pytest.raises(TokenTamperedError):
codec.decode(tampered)
def test_malformed_token_shapes_are_rejected() -> None:
codec = _codec()
for malformed in ("", "no-dot-at-all", "a.b.c", "."):
with pytest.raises(TokenTamperedError):
codec.decode(malformed)
def test_different_secret_cannot_decode_another_codecs_token() -> None:
codec_a = SignedTokenCodec(secret=b"a" * 32)
codec_b = SignedTokenCodec(secret=b"b" * 32)
token = codec_a.encode({"sub": "alice"}, expires_at=datetime.now(UTC) + timedelta(minutes=5))
with pytest.raises(TokenTamperedError):
codec_b.decode(token)
def test_expired_token_is_rejected_distinctly_from_tampering() -> None:
clock_time = {"now": datetime(2026, 1, 1, tzinfo=UTC)}
codec = _codec(clock=lambda: clock_time["now"])
token = codec.encode({"sub": "alice"}, expires_at=clock_time["now"] + timedelta(minutes=5))
clock_time["now"] = clock_time["now"] + timedelta(minutes=6)
with pytest.raises(TokenExpiredError):
codec.decode(token)
def test_secret_must_be_at_least_32_bytes() -> None:
with pytest.raises(ValueError, match="32 bytes"):
SignedTokenCodec(secret=b"too-short")
def test_expires_at_must_be_timezone_aware() -> None:
codec = _codec()
naive = datetime.fromisoformat("2026-01-01T00:00:00")
with pytest.raises(ValueError, match="timezone-aware"):
codec.encode({"sub": "alice"}, expires_at=naive)