From 035ea17844835eb17d87cb0cec1f3ee69c7ea847 Mon Sep 17 00:00:00 2001 From: kcar Date: Wed, 27 May 2026 04:16:22 +0100 Subject: [PATCH] fix: prevent platform admin from being auto-enrolled in default school Two root causes fixed: 1. seed_environment.py: KevlarAI website was 'https://kevlarai.com' (real domain) instead of 'https://kevlarai.test'. Also, seed step 8 now patches kcar's auth user_metadata to set user_type='platform_admin' on every reset+seed, so the fix is self-healing and doesn't require manual DB edits. 2. provisioning_service.py: user_type_map now maps 'platform_admin' to ('superadmin', 'superadmin'), so _ensure_membership() is never called for platform admin accounts and they are never silently enrolled in the default institute. Co-Authored-By: Claude Sonnet 4.6 --- .../database/services/provisioning_service.py | 1 + run/initialization/seed_environment.py | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/modules/database/services/provisioning_service.py b/modules/database/services/provisioning_service.py index 52b79bb..da0aef7 100644 --- a/modules/database/services/provisioning_service.py +++ b/modules/database/services/provisioning_service.py @@ -263,6 +263,7 @@ class ProvisioningService: "admin": ("superadmin", "superadmin"), "super_admin": ("superadmin", "superadmin"), "superadmin": ("superadmin", "superadmin"), + "platform_admin": ("superadmin", "superadmin"), } neo_user_type, worker_type = user_type_map.get(user_type_raw, (user_type_raw or "standard", user_type_raw or "standard")) diff --git a/run/initialization/seed_environment.py b/run/initialization/seed_environment.py index d37e196..502ea95 100644 --- a/run/initialization/seed_environment.py +++ b/run/initialization/seed_environment.py @@ -203,7 +203,7 @@ def seed() -> Dict[str, Any]: "name": KEVLARAI_NAME, "urn": KEVLARAI_URN, "status": "active", - "website": "https://kevlarai.com", + "website": "https://kevlarai.test", "address": {"line1": "1 AI Lane", "city": "London", "postcode": "EC1A 1BB"}, "metadata": {"headteacher": "Alex Admin", "seeded": True}, }, on_conflict="id") @@ -392,6 +392,22 @@ def seed() -> Dict[str, Any]: errors.append(f"kcar_admin: {e}") logger.error(f" {e}") + # Fix kcar's auth user_metadata so user_type is "platform_admin", not "teacher". + # Without this, POST /user/init assigns kcar to the default school on first login. + try: + r = requests.patch( + f"{url}/auth/v1/admin/users/{KCAR_ID}", + headers=headers, + json={"user_metadata": {"user_type": "platform_admin"}}, + ) + if r.status_code in (200, 201): + logger.info(" kcar → user_type: platform_admin ✓") + else: + logger.warning(f" kcar user_metadata patch failed ({r.status_code}): {r.text[:120]}") + except Exception as e: + errors.append(f"kcar_user_type: {e}") + logger.error(f" {e}") + # ── Summary ─────────────────────────────────────────────────────────────── results["success"] = len(errors) == 0 results["errors"] = errors