# 🏒 Garage-Centric Hierarchy Audit Report **Audit Date**: 2026-03-29 **Issue**: #179 - SYSTEM ARCHITECT - CODE & SCHEMA AUDIT **Auditor**: Fast Coder (Core Developer) ## πŸ“‹ Executive Summary This audit verifies the implementation of the "Masterbook 2.0.1 Hierarchy": **User β†’ Org (Private/Corp) β†’ Branch β†’ Garage β†’ Vehicle**. The audit reveals that the core hierarchy is partially implemented with some gaps that need to be addressed. ## πŸ” Current Implementation Status ### βœ… **IMPLEMENTED CORRECTLY** #### 1. Registration Step 2 - Private Organization Creation - **Location**: `backend/app/services/auth_service.py` - `complete_kyc()` method - **Status**: βœ… **FULLY IMPLEMENTED** - **Details**: When a user completes KYC (Registration Step 2), the system: - Creates an `Organization` with `OrgType.individual` - Sets `user.scope_id = str(new_org.id)` - Creates a default `Branch` with `name="Home Base"` and `is_main=True` - Creates `OrganizationMember` with `role="OWNER"` - **Code Reference**: Lines 159-191 in `auth_service.py` #### 2. Organization Model - **Location**: `backend/app/models/marketplace/organization.py` - **Status**: βœ… **COMPLETE** - **Schema**: `fleet.organizations` - **Key Fields**: `id`, `full_name`, `org_type`, `owner_id`, `status`, `is_active` - **Relationships**: Has `branches` relationship to `Branch` model #### 3. Branch Model (Acting as Garage) - **Location**: `backend/app/models/marketplace/organization.py` - `Branch` class - **Status**: βœ… **COMPLETE** - **Schema**: `fleet.branches` - **Key Fields**: `id` (UUID), `organization_id`, `name`, `is_main`, `address_id` - **Note**: No dedicated "Garage" model exists - Branch serves as the Garage container #### 4. Asset Model - **Location**: `backend/app/models/vehicle/asset.py` - `Asset` class - **Status**: βœ… **COMPLETE** - **Schema**: `vehicle.assets` - **Key Fields**: `id` (UUID), `vin`, `license_plate`, `current_organization_id`, `owner_org_id` ### ⚠️ **PARTIALLY IMPLEMENTED / GAPS IDENTIFIED** #### 1. Asset to Branch/Garage Linkage - **Status**: ❌ **MISSING** - **Issue**: Assets are linked to Organizations via `current_organization_id` and `owner_org_id`, but there's no direct `branch_id` or `garage_id` field to specify which Branch/Garage the asset belongs to. - **Current**: Assets use `AssetAssignment` model for many-to-many relationship with Organizations - **Required**: Add `branch_id` field to Asset model #### 2. Verified Purchase Date Field - **Status**: ⚠️ **PARTIAL** - **Current Fields**: - `first_registration_date` in Asset model (line 48) - `activation_date` in AssetFinancials model (line 146) - **Missing**: Explicit `verified_purchase_date` field for cost cut-off logic - **Required**: Add `verified_purchase_date` to AssetFinancials model #### 3. Relocation Performed Flag - **Status**: ❌ **MISSING** - **Issue**: No `relocation_performed` flag for one-time relocation logic - **Required**: Add boolean `relocation_performed` field to Asset model ## πŸ—ΊοΈ Hierarchy Mapping ``` User (identity.users) ↓ Organization (fleet.organizations) ← Private Org created during KYC ↓ Branch (fleet.branches) ← Acts as "Garage" container ↓ Asset (vehicle.assets) ← Missing direct branch_id linkage ``` ## πŸ“Š Database Schema Analysis ### Current Asset-Organization Relationship ```sql -- Current linkage (via AssetAssignment) asset_assignments (fleet schema) asset_id β†’ vehicle.assets.id organization_id β†’ fleet.organizations.id -- Direct fields in Asset assets (vehicle schema) current_organization_id β†’ fleet.organizations.id owner_org_id β†’ fleet.organizations.id ``` ### Missing Branch Linkage ```sql -- PROPOSED ADDITION to Asset model ALTER TABLE vehicle.assets ADD COLUMN branch_id UUID REFERENCES fleet.branches(id); ``` ## πŸ”§ Required Code Modifications ### 1. Asset Model Updates (`backend/app/models/vehicle/asset.py`) ```python # Add to Asset class (around line 64): branch_id: Mapped[Optional[uuid.UUID]] = mapped_column( PG_UUID(as_uuid=True), ForeignKey("fleet.branches.id"), nullable=True ) relocation_performed: Mapped[bool] = mapped_column( Boolean, default=False, server_default=text("false") ) # Add relationship: branch: Mapped[Optional["Branch"]] = relationship("Branch") ``` ### 2. AssetFinancials Model Updates ```python # Add to AssetFinancials class: verified_purchase_date: Mapped[Optional[datetime]] = mapped_column( DateTime(timezone=True), nullable=True ) ``` ### 3. Schema Updates Required - Run `sync_engine.py` after model changes - **DO NOT** use Alembic migrations directly per project rules ## πŸ§ͺ Test Script for Hierarchy Verification A test script has been prepared to verify the separation logic: ```python # Test: Create 1 Private Garage car and 1 Corporate Branch car # Verify GET /vehicles (with active scope_id) only shows cars belonging to specific context ``` **Test Logic**: 1. Create User A with Private Organization (Org A) 2. Create User B with Corporate Organization (Org B) 3. Add Vehicle 1 to Org A's Branch 4. Add Vehicle 2 to Org B's Branch 5. Verify User A only sees Vehicle 1 when calling GET /vehicles 6. Verify User B only sees Vehicle 2 when calling GET /vehicles ## 🚨 Critical Findings ### 1. **Scope Isolation Works** The `user.scope_id` mechanism correctly isolates data at the Organization level. When a user queries `/vehicles`, the API filters by `current_organization_id = user.scope_id`. ### 2. **Branch-Level Isolation Missing** While Organization-level isolation exists, there's no Branch-level filtering. All assets in an Organization are visible regardless of which Branch they belong to. ### 3. **Cost Cut-off Logic Incomplete** Without `verified_purchase_date` and `relocation_performed` fields, the historical cost tracking and one-time relocation logic cannot be properly implemented. ## πŸ“ Recommendations ### **HIGH PRIORITY** 1. **Add `branch_id` to Asset model** - Enable Branch/Garage level asset management 2. **Add `verified_purchase_date` to AssetFinancials** - Support cost cut-off logic 3. **Add `relocation_performed` flag to Asset** - Enable one-time relocation tracking ### **MEDIUM PRIORITY** 4. Update API endpoints to respect `branch_id` in queries 5. Enhance admin interface to show Branch assignment for assets 6. Add Branch filtering to vehicle listing endpoints ### **LOW PRIORITY** 7. Consider creating dedicated `Garage` model if Branch semantics differ significantly 8. Add Branch-level permissions for fleet managers ## πŸ”„ Synchronization Process **STRICT RULE**: Apply changes ONLY via `sync_engine.py`: ```bash docker compose exec roo-helper python3 /app/backend/app/scripts/sync_engine.py ``` **DO NOT** use Alembic migrations directly. The sync engine is the primary source of truth for schema generation in Masterbook 2.0.1 architecture. ## πŸ“ˆ Next Steps 1. **User Approval**: Present this "Gap Report" for approval before implementing changes 2. **Implementation**: Apply the three high-priority model modifications 3. **Sync**: Run `sync_engine.py` to update database schema 4. **Testing**: Execute the hierarchy verification test script 5. **Validation**: Confirm GET /vehicles endpoint respects scope isolation --- **Audit Completed**: 2026-03-29 **Next Review**: After gap implementation approval