Status + answers to your three questions
1. Is the app healthy now?
No — the session-restore issue is still reproducing 100% of the time. We just re-tested live (fresh Incognito window, login with real credentials) and got the same result: the server mints a valid session row on login (verified via direct read-only query against our production Postgres — opaque random token, correct role, +24h expiry), but on page reload the user is bounced back to the login screen every time. The server-side write path works; the read-back on reload does not.
2. Python 3.14 vs runtime.txt
Confirmed on our side: runtime.txt contains exactly python-3.10 (single line, no whitespace, unchanged in git for ~3 months). Our local environment and our whole dependency set are built and tested against CPython 3.10.
Our deploy log reports Using Python 3.14.7 environment at /home/adminuser/venv — so after the post-apt-get-incident rebuild, runtime.txt appears not to be honored; the container is on 3.14.7, not 3.10.
Two questions:
- Is
python-3.10still a supported value forruntime.txton Community Cloud, or has the supported range been narrowed? - When
runtime.txtspecifies a version you no longer support, does the platform now silently fall back to the current default (3.14.x) instead of failing the build?
This is material to the cookie problem: our entire wheel set (including tornado’s C extensions and anything touching http.cookies / asyncio) was resolved and tested on 3.10, and the container is now on 3.14 — a far larger environment drift than the one dependency we pinned.
3. The _ar_session cookie mechanism (“does the hashing happen in the browser?”)
No hashing happens in the browser. The browser only ever holds a raw, opaque random token (secrets.token_urlsafe(32), 43 chars). The SHA-256 hashing is done server-side, in Python, on read: we hash the incoming token and look up sha256(token) in a sessions table. The raw token is never stored server-side; the browser never sees a hash.
How the cookie is written (this is the key detail):
- It is set client-side, in JavaScript —
document.cookie = '_ar_session=' + encodeURIComponent(token) + '; path=/; SameSite=Lax; max-age=86400'— executed inside ast.components.v1.html(...)component, i.e. from within its iframe writing towindow.parent.document.cookie. - It is not set via an HTTP
Set-Cookieresponse header from the server. - Confirmed in browser DevTools: after login the
_ar_sessioncookie is present on the app’s origin, with the expected Domain,Path=/,SameSite=Laxand expiry.
How it is read back:
- Server-side, via
st.context.cookies.get("_ar_session"). - Per Streamlit 1.56.0’s own source (
web/server/browser_websocket_handler.py→TornadoClientContext),st.context.cookiesis populated fromtornado_request.cookiesof the WebSocket upgrade handshake (GET /_stcore/stream,Upgrade: websocket). The docstring: “Captures headers, cookies, and client info from the initial WebSocket handshake.” - Observed failure: on reload,
st.context.cookiesreturns no_ar_session, even though the cookie is in the browser and — beingSameSite=Laxon the same origin — should be included on the same-origin WebSocket upgrade request.
Additional finding since our last check: we pinned tornado==6.4.2 in requirements.txt (Streamlit’s own metadata excludes tornado==6.5.0 explicitly, suggesting a known WS/cookie regression in that release line). Confirmed installed in the rebuilt container’s deploy log. The symptom is unchanged — 100% reproduction rate, identical behavior. This rules out our own dependency pin as the cause.
We also run an independent external WebSocket client (a GitHub Actions job with zero cookies, zero app logic — a bare websockets.connect() to wss://archirapid.streamlit.app/~/+/_stcore/stream every hour) that has been getting HTTP 502 on that same endpoint intermittently since the rebuild, with occasional green runs (partial recovery, not resolved). This points at the edge/WebSocket layer itself, not at our code or dependencies.
Explicit question: Does the cookie-stripping you suspect apply specifically to the Cookie: header of the WebSocket upgrade request (/_stcore/stream), or to any HTTP request as well? If it is the WS upgrade specifically, that would mean st.context.cookies currently cannot see any app-set cookie on Community Cloud in the platform’s present state.