4.7 KiB
🚨 ROO: MANDATORY ARCHITECTURAL AUDIT & DOCUMENTATION (v201)
Context
This document aligns the system with the "Personal Workspace" vision (Every user has a private organization/garage). It documents the current reality of the system to identify where the logic is broken.
🔍 Task 1: Forensic Logic Analysis
1. User-Org Link
- Database Schema: In the
userstable (identity.users), there is NOdefault_organization_id. - Current Linkage: A user is linked to their "Private Garage" (or multiple garages) via two relationships:
- Ownership:
organizations.owner_id->users.id - Membership:
organization_members.user_id->users.id
- Ownership:
- Scope Field: The
userstable has ascope_idfield (andscope_level), but it is oftenNonebecause the registration/KYC flow does not explicitly set it to the newly created Organization ID.
2. Auth Payload
- Login Response: Looked at
backend/app/api/v1/endpoints/auth.py. The/loginendpoint creates a JWT token withscope_id: str(user.scope_id) if user.scope_id else str(user.id). Sinceuser.scope_idis often null, the token just duplicates theuser.id. /users/meEndpoint: It returns theUserResponseschema (fromapp.schemas.user), which includesscope_id: Optional[str] = None. It does not return a specificorganization_idarray or the user's active/default organization ID to the frontend.
3. Frontend Storage
- Auth Store (
frontend/src/stores/authStore.js): Fetches/users/meand stores the raw response inuserProfile.value. It decodes the JWT to get the user's role, but it does not store or manage an activeorganization_idstate. - Garage Store (
frontend/src/stores/garageStore.js): Contains logic to add a vehicle, but the active organization is not retrieved from the user's profile. Instead, it relies on the payload passed from components and falls back to a hardcoded1.
4. The "Hardcode" Hunt
Every file where organization_id: 1 or any hardcoded ID is used instead of a dynamic value from the store:
frontend/src/components/actions/AddVehicleModal.vue: Explicitly hardcodesorganizationId: 1in its payload.frontend/src/views/AddVehicle.vue: Containsorganization_id: 1 // default organization.frontend/src/stores/garageStore.js: Inside theaddVehicleaction, it explicitly defaults toorganization_id: vehicle.organizationId || 1 // Default org ID.backend/app/api/v1/endpoints/assets.py: When creating expenses/maintenance costs, it falls back toorganization_id=asset.current_organization_id or asset.owner_org_id or 1.
📝 Task 2: Real State of the System (The Gap)
Database Level
When a new user completes KYC (complete_kyc in AuthService), a new "Personal" Organization is dynamically created (e.g., {last_name} Széfe). The user is assigned as the OWNER in the OrganizationMember table, and the organizations.owner_id is set. However, user.scope_id is never updated to point to this new organization.
API Level
The frontend calls /login and /users/me, but neither endpoint returns the actual ID of the user's newly created Organization. The frontend receives only the generic UserResponse with scope_id: null. The frontend has no knowledge of which organization_id belongs to the logged-in user.
Frontend Level
Because the frontend (AddVehicleModal, AddVehicle view, and garageStore) does not receive the user's organization ID, it just gives up and blindly sends organization_id: 1 on every POST request to create a vehicle.
The Gap (Contradictions)
- The Vision: Every user has their own Organization/Garage.
- The Code: The Backend creates the Organization but doesn't tell the Frontend what its ID is.
- The Result: The Frontend ignores the Backend's logic and assigns every new vehicle to Organization
1(usually the Superadmin or System's default organization), completely breaking data isolation and the "Private Garage" architecture.
🔬 Task 3: Verification of the "Tester_Pro" account
- User: ID 28 (
tester_pro@profibot.hu) - Database Status: Querying the database shows that User 28 has
scope_id: None. - True Organization: In the
organization_memberstable, User 28 belongs to Org ID: 15 (Name: "Profibot Test Fleet") with the roleADMIN. - Why the frontend does NOT use this ID:
- The API never provides
Org ID: 15to the frontend during login or profile fetch. AddVehicleModal.vueandgarageStore.jsare hardcoded to send1if they don't explicitly receive an ID. SinceauthStoredoesn't know about15, it sends1. Consequently, Tester_Pro's vehicles are saved into the wrong organization.
- The API never provides