"""Unit: the session's privacy surface (phase 05, task 04, US-07). The store is anonymous by design (A16): the identity is a 24-byte random token and *nothing else*. These tests lock the surface so a PII field can never join without a test failing first: * **the `SessionRecord` field set** — exactly the task's nine fields (identity, name, progression, counters, stamps), * **a `repr()` scan** — a representative record (and a representative store) never carries `ip`, `user_agent`, `authorization` or `cookie` (case-insensitive), * **`SessionStore` has no attribute holding raw headers** — neither the record's fields nor the store's attributes name a `header` of any kind, and no dict-valued store attribute holds a header-like key. """ from __future__ import annotations import dataclasses import pytest from undercooked.server.clock import FakeClock from undercooked.server.sessions import BestRun, SessionRecord, SessionStore pytestmark = pytest.mark.unit #: The only fields a session record may hold (task 04's list). ALLOWED_RECORD_FIELDS = frozenset( { "token", "display_name", "created_at", "unlocked_level", "best", "rounds_played", "dishes_served", "last_seen", "endless_best", } ) #: The strings a session's repr must never contain (the PII markers). FORBIDDEN_REPR_SUBSTRINGS = ("ip", "user_agent", "authorization", "cookie") #: A request-header key that must never appear in the store's own data. HEADER_LIKE_KEYS = frozenset( {"host", "user-agent", "authorization", "cookie", "x-forwarded-for"} ) def _benign_record() -> SessionRecord: """A representative record with fixed, benign values (a random base64url token could incidentally contain a marker; the test needs a *guaranteed* shape, so the token is fixed too).""" return SessionRecord( token="t" * 32, display_name="Ada", created_at=1.0, unlocked_level=2, best={"01_kitchen": BestRun(score=100, stars=3, completed_at=2.0)}, rounds_played=4, dishes_served=9, last_seen=3.0, endless_best=None, ) def _benign_store() -> SessionStore: """A representative store: a `FakeClock`, one campaign entry, and one record inside (so a walk of its data covers the record's shape).""" store = SessionStore( max_entries=10, clock=FakeClock(start=1.0), campaign={"01_kitchen": 1} ) record = _benign_record() store.put(record) return store def test_the_record_field_set_is_exactly_the_task_list() -> None: fields = {field.name for field in dataclasses.fields(SessionRecord)} assert fields == ALLOWED_RECORD_FIELDS def test_the_record_repr_carrys_no_pii_markers() -> None: text = repr(_benign_record()).lower() for marker in FORBIDDEN_REPR_SUBSTRINGS: assert marker not in text, f"the record's repr carries {marker!r}" def test_the_store_repr_carrys_no_pii_markers() -> None: text = repr(_benign_store()).lower() for marker in FORBIDDEN_REPR_SUBSTRINGS: assert marker not in text, f"the store's repr carries {marker!r}" def test_the_record_and_the_best_run_are_slots_dataclasses() -> None: """Slots (not a `__dict__` bag) is the shape that keeps the field set auditable: a new field is a named, visible change.""" assert hasattr(SessionRecord, "__slots__") assert hasattr(BestRun, "__slots__") def test_neither_record_nor_store_names_a_header_attribute() -> None: record_fields = {field.name for field in dataclasses.fields(SessionRecord)} assert not any("header" in name.lower() for name in record_fields) store = _benign_store() assert not any("header" in name.lower() for name in dir(store)) assert not any("header" in name.lower() for name in vars(store)) def test_the_store_holds_no_request_header_mapping() -> None: """Every dict-valued attribute of the store is either `token -> record` or `level id -> order`: neither may hold a header-like key.""" store = _benign_store() for name, value in vars(store).items(): if isinstance(value, dict): assert not ( set(value) & HEADER_LIKE_KEYS ), f"store attribute {name!r} holds header-like keys" record = _benign_record() for field in dataclasses.fields(record): assert field.name.lower() not in HEADER_LIKE_KEYS, f"record field {field.name!r}" value = getattr(record, field.name) if isinstance(value, dict): assert not ( set(value) & HEADER_LIKE_KEYS ), f"record field {field.name!r} holds header-like keys" def test_the_store_never_minted_with_headers_keeps_none() -> None: """A store built the way the supervisor builds it (a clock and the campaign mapping only) exposes exactly its own five attributes — no header bag can hide in a constructor that does not take one.""" store = SessionStore( clock=FakeClock(), campaign={"01_kitchen": 1} ) assert set(vars(store)) == { "_max_entries", "_clock", "_campaign", "_records", "_evictions", }