From 263e6e9b75c30ea07732aebbfe31485b78b81e3f Mon Sep 17 00:00:00 2001 From: Aletheia Date: Tue, 7 Jul 2026 20:06:55 +0200 Subject: [PATCH] fix: OAuth token endpoint multipart support + governor_enabled bool round-trip Ported from the Android edition's server: - Add python-multipart: the OAuth endpoints parse credentials with request.form(), and Starlette needs this package when a client POSTs the token request as multipart/form-data. Without it those requests 500'd ('the small auth bug'). - governor_enabled now round-trips SQLite's 0/1 as JSON true/false on read and normalises any truthy input to 0/1 on write. Strict clients (kotlinx-serialization) reject anything else. Co-Authored-By: Claude Fable 5 --- requirements-server.txt | 1 + server/auth.py | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/requirements-server.txt b/requirements-server.txt index 87b71b0..f8b73c5 100644 --- a/requirements-server.txt +++ b/requirements-server.txt @@ -5,3 +5,4 @@ websockets>=12.0 bcrypt>=4.1.0 PyJWT>=2.8.0 python-dotenv>=1.0.0 +python-multipart>=0.0.9 diff --git a/server/auth.py b/server/auth.py index b279c5c..4498c28 100644 --- a/server/auth.py +++ b/server/auth.py @@ -67,6 +67,10 @@ def get_safety_config(user_id: str) -> dict: "cooldown_threshold", "cooldown_exit", "cooldown_duration"): if row[key] is not None: result[key] = row[key] + # SQLite has no bool — coerce the int back to bool so the JSON response + # uses true/false. Strict Kotlin clients refuse to parse 0/1 as Boolean. + if "governor_enabled" in result: + result["governor_enabled"] = bool(result["governor_enabled"]) return result @@ -77,6 +81,11 @@ def set_safety_config(user_id: str, overrides: dict) -> dict: "cooldown_threshold", "cooldown_exit", "cooldown_duration", } filtered = {k: v for k, v in overrides.items() if k in allowed_keys} + # Normalise governor_enabled to a real 0/1 int — kotlinx-serialization on + # the Android side will reject a String "true" / "false" or a bare bool + # round-tripped through SQLite as anything other than int. + if "governor_enabled" in filtered: + filtered["governor_enabled"] = int(bool(filtered["governor_enabled"])) conn = _get_conn() existing = conn.execute(