Beemer
Deploy: the 2026-09-21 code audit and its three verification rounds -- the quantity and relief allowlists, the five Canadian outcome readings, the IRPR s. 17 clock, the retrieval fixes and the performance work (approved_code 82525e1; curated baseline c32bd27 unchanged)
901bf8c Download tests/test_http_sessions.py from Beemer0/CanLex: direct link, hf CLI and curl.
- Browser
- Download file 5.56 kB
-
https://huggingface.co/spaces/Beemer0/CanLex/resolve/main/tests/test_http_sessions.py
- Command line
-
hf download hf://spaces/Beemer0/CanLex/tests/test_http_sessions.py
-
curl -L -o test_http_sessions.py https://huggingface.co/spaces/Beemer0/CanLex/resolve/main/tests/test_http_sessions.py
5.56 kB
| """Verification fixes 2026-09-22 (F3), SEC-1: one client can no longer lock | |
| every other client out of the HTTP transport. | |
| With mcp 1.30.0 the session manager CanLex built had a global cap of 10,000 | |
| open sessions and no per-client limit, so one unauthenticated client could | |
| fill it in about two minutes; every other client's `initialize` then got | |
| 503 'Too many open sessions' until the flood's sessions idled out (1800 s). | |
| The critic's live probe, with the cap scaled from 10,000 to 5: one client's | |
| six initializes [200, 200, 200, 200, 200, 503], another client's 503. | |
| Now server.session_manager_with_timeout passes max_sessions=None (the 1.27.2 | |
| behaviour, bounded by the idle timeout) and server.http_app -- the app | |
| __main__ serves -- adds canlex/ratelimit.py's SessionOpenLimit, on by | |
| default. These tests drive the real stack (FastMCP's streamable-HTTP app, | |
| the session manager, _Utf8Body, the cap) in-process with Starlette's | |
| TestClient, the cap scaled down through CANLEX_SESSION_OPEN_LIMIT. Clients | |
| are told apart by X-Forwarded-For, as Hugging Face's ingress supplies it. | |
| python -m unittest tests.test_http_sessions | |
| """ | |
| import io | |
| import logging | |
| import unittest | |
| from contextlib import redirect_stderr | |
| from mcp.server.fastmcp import FastMCP | |
| from starlette.testclient import TestClient | |
| from canlex import ratelimit, server | |
| INIT = {"jsonrpc": "2.0", "id": 1, "method": "initialize", | |
| "params": {"protocolVersion": "2025-03-26", "capabilities": {}, | |
| "clientInfo": {"name": "t", "version": "1"}}} | |
| ACCEPT = {"Accept": "application/json, text/event-stream"} | |
| FLOODER, OFFICER = "203.0.113.7", "198.51.100.9" | |
| def toy(): | |
| srv = FastMCP("t") | |
| def echo(word: str) -> str: | |
| return word | |
| return srv | |
| class HttpSessionTests(unittest.TestCase): | |
| def setUp(self): | |
| for name in ("mcp", "httpx"): | |
| log = logging.getLogger(name) | |
| self.addCleanup(log.setLevel, log.level) | |
| log.setLevel(logging.WARNING) | |
| # _Utf8Body prints each new client tag once: keep the set as it was | |
| seen = set(server._seen_clients) | |
| self.addCleanup(lambda: (server._seen_clients.clear(), | |
| server._seen_clients.update(seen))) | |
| quiet = redirect_stderr(io.StringIO()) | |
| quiet.__enter__() | |
| self.addCleanup(quiet.__exit__, None, None, None) | |
| def serve(self, srv, environ): | |
| err = io.StringIO() | |
| with redirect_stderr(err): | |
| app = server.http_app(srv, environ) | |
| client = TestClient(app, base_url="http://127.0.0.1:8000") | |
| client.__enter__() # runs the session manager's lifespan | |
| self.addCleanup(client.__exit__, None, None, None) | |
| return client, err.getvalue() | |
| def initialize(client, who): | |
| return client.post("/mcp", json=INIT, headers=dict(ACCEPT, **{"X-Forwarded-For": who})) | |
| def test_the_served_stack_has_no_global_cap_and_the_per_client_cap_on(self): | |
| srv = toy() | |
| _, err = self.serve(srv, {}) | |
| self.assertIsNone(server.SESSION_MAX_OPEN) | |
| self.assertIsNone(srv._session_manager.max_sessions) | |
| self.assertEqual(srv._session_manager.session_idle_timeout, server.SESSION_IDLE_SECONDS) | |
| self.assertIn("no global session cap", err) | |
| self.assertIn(f"at most {ratelimit.SESSION_OPEN_LIMIT} new sessions per client", err) | |
| def test_a_flood_from_one_client_leaves_another_able_to_initialize(self): | |
| srv = toy() | |
| client, _ = self.serve(srv, {"CANLEX_SESSION_OPEN_LIMIT": "3"}) | |
| flood = [self.initialize(client, FLOODER) for _ in range(8)] | |
| self.assertEqual([r.status_code for r in flood], [200] * 3 + [429] * 5) | |
| self.assertIn("Too many new sessions", flood[-1].text) | |
| officer = self.initialize(client, OFFICER) | |
| self.assertEqual(officer.status_code, 200) | |
| self.assertIn('"protocolVersion"', officer.text) | |
| self.assertEqual(len(srv._session_manager._server_instances), 4) | |
| # the flooder's own open sessions keep working: only new sessions are capped | |
| sid = flood[0].headers["mcp-session-id"] | |
| listed = client.post("/mcp", json={"jsonrpc": "2.0", "id": 2, "method": "tools/list"}, | |
| headers=dict(ACCEPT, **{"X-Forwarded-For": FLOODER, | |
| "mcp-session-id": sid, | |
| "mcp-protocol-version": "2025-03-26"})) | |
| self.assertEqual(listed.status_code, 200) | |
| self.assertIn('"echo"', listed.text) | |
| def test_even_under_a_global_cap_one_client_cannot_fill_it(self): | |
| """The critic's scaled stand-in (a global cap of 5) with the per-client | |
| cap at 3: before, the flood filled the table and the officer got 503.""" | |
| srv = toy() | |
| client, _ = self.serve(srv, {"CANLEX_SESSION_OPEN_LIMIT": "3"}) | |
| srv._session_manager.max_sessions = 5 | |
| self.assertEqual([self.initialize(client, FLOODER).status_code for _ in range(6)], | |
| [200] * 3 + [429] * 3) | |
| self.assertEqual(self.initialize(client, OFFICER).status_code, 200) | |
| def test_turned_off_the_flood_reaches_the_manager(self): | |
| srv = toy() | |
| client, err = self.serve(srv, {"CANLEX_SESSION_OPEN_LIMIT": "0"}) | |
| self.assertIn("no per-client cap on new sessions", err) | |
| self.assertEqual({self.initialize(client, FLOODER).status_code for _ in range(5)}, {200}) | |
| if __name__ == "__main__": | |
| unittest.main() | |