Files
igny8/unified-api/IMPLEMENTATION-PLAN-REMAINING.md

18 KiB

Implementation Plan - Remaining API Standard v1.0 Items

Date: 2025-01-XX
Status: Planning
Purpose: Complete implementation plan for remaining API Standard v1.0 compliance items


Executive Summary

Total Items: 10 remaining items
Critical Priority: 2 items
High Priority: 4 items
Medium Priority: 4 items

Estimated Time: 12-16 hours
Risk Level: Low (mostly adding permissions and refactoring response formats)


Table of Contents

  1. Critical Priority Items
  2. High Priority Items
  3. Medium Priority Items
  4. Implementation Order
  5. Testing Strategy
  6. Rollback Plan

Critical Priority Items

1. Fix Auth Endpoints to Use Unified Format

Issue: RegisterView, LoginView, ChangePasswordView, MeView in backend/igny8_core/auth/urls.py use raw Response() instead of unified format helpers.

Impact: These are the most frequently used endpoints and don't comply with the standard.

Files to Modify:

  • backend/igny8_core/auth/urls.py

Implementation Steps:

  1. Update RegisterView (lines 41-58)

    # BEFORE:
    return Response({
        'success': True,
        'message': 'Registration successful',
        'user': user_serializer.data
    }, status=status.HTTP_201_CREATED)
    
    # AFTER:
    from igny8_core.api.response import success_response, error_response
    
    return success_response(
        data={'user': user_serializer.data},
        message='Registration successful',
        status_code=status.HTTP_201_CREATED,
        request=request
    )
    
  2. Update LoginView (lines 66-134)

    • Replace all Response() calls with success_response() or error_response()
    • Ensure request_id is included
    • Fix error response format to use error + errors structure
  3. Update ChangePasswordView (lines 142-167)

    • Replace Response() with success_response() and error_response()
    • Ensure proper error format
  4. Update MeView (lines 175-188)

    • Replace Response() with success_response()
    • Ensure request_id is included
  5. Add imports at top of file:

    from igny8_core.api.response import success_response, error_response
    

Testing:

  • Test registration with valid/invalid data
  • Test login with valid/invalid credentials
  • Test change password with valid/invalid old password
  • Test /me endpoint
  • Verify all responses have success, data/error, request_id fields

Estimated Time: 2 hours


2. Fix AIPromptViewSet Permissions

Issue: AIPromptViewSet has permission_classes = [] which allows unauthenticated access.

Impact: Security vulnerability - anyone can access/modify AI prompts.

Files to Modify:

  • backend/igny8_core/modules/system/views.py (line 42)

Implementation Steps:

  1. Update permission_classes:

    # BEFORE:
    permission_classes = []  # Allow any for now (backward compatibility)
    
    # AFTER:
    from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess
    
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    
  2. Verify custom actions have proper permissions:

    • get_by_type - Should allow authenticated users
    • save_prompt - Should require IsEditorOrAbove (per standard: "Saving prompts requires editor/admin")
    • reset_prompt - Should require IsEditorOrAbove
  3. Update save_prompt action:

    @action(detail=False, methods=['post'], url_path='save', url_name='save')
    def save_prompt(self, request):
        """Save or update a prompt - requires editor or above"""
        # Add permission check
        from igny8_core.api.permissions import IsEditorOrAbove
        if not IsEditorOrAbove().has_permission(request, self):
            return error_response(
                error='Permission denied',
                status_code=status.HTTP_403_FORBIDDEN,
                request=request
            )
        # ... rest of implementation
    

Testing:

  • Test unauthenticated access (should return 401)
  • Test authenticated user access (should work)
  • Test save_prompt with viewer role (should return 403)
  • Test save_prompt with editor role (should work)

Estimated Time: 1 hour


High Priority Items

3. Update Billing ViewSets to Use Standard Permissions

Issue: All billing ViewSets use permissions.IsAuthenticated instead of IsAuthenticatedAndActive + HasTenantAccess.

Files to Modify:

  • backend/igny8_core/modules/billing/views.py

Implementation Steps:

  1. Update CreditBalanceViewSet (line 35)

    # BEFORE:
    permission_classes = [permissions.IsAuthenticated]
    
    # AFTER:
    from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess
    
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    
  2. Update CreditUsageViewSet (line 91)

    # BEFORE:
    permission_classes = [permissions.IsAuthenticated]
    
    # AFTER:
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    
  3. Update CreditTransactionViewSet (line 466)

    # BEFORE:
    permission_classes = [permissions.IsAuthenticated]
    
    # AFTER:
    from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner
    
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner]
    

    Note: Transactions require admin/owner per standard.

Testing:

  • Test with unauthenticated user (should return 401)
  • Test with authenticated user from different account (should return 403)
  • Test with authenticated user from same account (should work)
  • Test CreditTransactionViewSet with viewer/editor (should return 403)
  • Test CreditTransactionViewSet with admin/owner (should work)

Estimated Time: 1.5 hours


4. Update System Settings ViewSets to Use Standard Permissions

Issue: All 5 system settings ViewSets use permissions.IsAuthenticated instead of standard permissions.

Files to Modify:

  • backend/igny8_core/modules/system/settings_views.py

Implementation Steps:

  1. Update SystemSettingsViewSet (line 37)

    # BEFORE:
    permission_classes = [permissions.IsAuthenticated]
    
    # AFTER:
    from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner
    
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    
    # Update get_permissions() method to use IsAdminOrOwner for write operations
    def get_permissions(self):
        if self.action in ['create', 'update', 'partial_update', 'destroy']:
            return [IsAdminOrOwner()]
        return [IsAuthenticatedAndActive(), HasTenantAccess()]
    
  2. Update AccountSettingsViewSet (line 88)

    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    # Write operations should require IsAdminOrOwner (already handled by get_permissions)
    
  3. Update UserSettingsViewSet (line 148)

    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    
  4. Update ModuleSettingsViewSet (line 214)

    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    
  5. Update AISettingsViewSet (line 293)

    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    

Testing:

  • Test read operations with authenticated user (should work)
  • Test write operations with viewer/editor (should return 403)
  • Test write operations with admin/owner (should work)
  • Test with user from different account (should return 403)

Estimated Time: 2 hours


Medium Priority Items

5. Refactor Billing ViewSets to Use AccountModelViewSet

Issue: Billing ViewSets manually filter by account instead of using base class.

Files to Modify:

  • backend/igny8_core/modules/billing/views.py

Implementation Steps:

  1. Refactor CreditBalanceViewSet:

    • Change from viewsets.ViewSet to inherit from a base class
    • Since it's a custom action-only ViewSet, keep as ViewSet but ensure account filtering
    • Verify account is set correctly from request
  2. Refactor CreditUsageViewSet:

    # BEFORE:
    class CreditUsageViewSet(viewsets.ReadOnlyModelViewSet):
        def get_queryset(self):
            account = getattr(self.request, 'account', None)
            # ... manual filtering
    
    # AFTER:
    from igny8_core.api.base import AccountModelViewSet
    
    class CreditUsageViewSet(AccountModelViewSet):
        # Base class handles account filtering automatically
        def get_queryset(self):
            queryset = super().get_queryset()
            # Only add custom filtering here (operation_type, date range)
            # Account filtering is automatic
    
  3. Refactor CreditTransactionViewSet:

    # BEFORE:
    class CreditTransactionViewSet(viewsets.ReadOnlyModelViewSet):
        def get_queryset(self):
            account = getattr(self.request, 'account', None)
            # ... manual filtering
    
    # AFTER:
    class CreditTransactionViewSet(AccountModelViewSet):
        # Base class handles account filtering automatically
    

Testing:

  • Verify account filtering works correctly
  • Test with admin/developer (should see all accounts)
  • Test with regular user (should only see their account)
  • Verify custom filters still work (operation_type, date range)

Estimated Time: 2 hours


6. Refactor IntegrationSettingsViewSet to Use AccountModelViewSet

Issue: IntegrationSettingsViewSet inherits from viewsets.ViewSet instead of AccountModelViewSet.

Files to Modify:

  • backend/igny8_core/modules/system/integration_views.py

Implementation Steps:

  1. Change base class:

    # BEFORE:
    class IntegrationSettingsViewSet(viewsets.ViewSet):
    
    # AFTER:
    from igny8_core.api.base import AccountModelViewSet
    
    class IntegrationSettingsViewSet(AccountModelViewSet):
    
  2. Update methods to use base class features:

    • get_queryset() - Use base class method if model has account field
    • perform_create() - Use base class to set account
    • Verify account scoping works correctly
  3. Note: This ViewSet uses custom URL patterns, so ensure base class doesn't conflict.

Testing:

  • Test integration settings retrieval (should be account-scoped)
  • Test saving integration settings (should set account automatically)
  • Test with user from different account (should not see other account's settings)

Estimated Time: 1.5 hours


7. Add Explicit Standard Permissions to Auth ViewSets

Issue: Auth ViewSets inherit from AccountModelViewSet but don't explicitly set standard permissions.

Files to Modify:

  • backend/igny8_core/auth/views.py

Implementation Steps:

  1. Update UsersViewSet (line 135)

    from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner
    
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner]
    
  2. Update AccountsViewSet (line 270)

    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner]
    
  3. Update SubscriptionsViewSet (line 335)

    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner]
    
  4. Update SiteViewSet (line 472)

    from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess, IsEditorOrAbove
    
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess, IsEditorOrAbove]
    
  5. Update SectorViewSet (line 715)

    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess, IsEditorOrAbove]
    
  6. Update SiteUserAccessViewSet (line 396)

    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner]
    

Testing:

  • Test each ViewSet with appropriate roles
  • Verify tenant isolation works
  • Test with users from different accounts

Estimated Time: 1.5 hours


8. Add Role-Based Permissions to CreditTransactionViewSet

Issue: CreditTransactionViewSet should require IsAdminOrOwner per standard but currently only requires IsAuthenticated.

Files to Modify:

  • backend/igny8_core/modules/billing/views.py (line 466)

Implementation Steps:

  1. Update permissions:

    # This is already covered in item #3, but ensure it's implemented:
    from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner
    
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner]
    
  2. Verify in standard: Per API Standard v1.0, billing/transactions require admin/owner.

Testing:

  • Test with viewer role (should return 403)
  • Test with editor role (should return 403)
  • Test with admin role (should work)
  • Test with owner role (should work)

Estimated Time: 0.5 hours (included in item #3)


Implementation Order

Phase 1: Critical Security Fixes (3 hours)

  1. Fix AIPromptViewSet permissions (1 hour) - CRITICAL SECURITY
  2. Fix auth endpoints unified format (2 hours) - HIGH VISIBILITY

Phase 2: High Priority Permissions (3.5 hours)

  1. Update billing ViewSets permissions (1.5 hours)
  2. Update system settings ViewSets permissions (2 hours)

Phase 3: Base Class Refactoring (3.5 hours)

  1. Refactor billing ViewSets to use AccountModelViewSet (2 hours)
  2. Refactor IntegrationSettingsViewSet (1.5 hours)

Phase 4: Auth Module Permissions (1.5 hours)

  1. Add explicit permissions to auth ViewSets (1.5 hours)

Total Estimated Time: 11.5 hours


Testing Strategy

Unit Tests

File: backend/igny8_core/api/tests/test_auth_endpoints.py (NEW)

class AuthEndpointsTestCase(TestCase):
    def test_register_returns_unified_format(self):
        """Test register endpoint returns unified format"""
        response = self.client.post('/api/v1/auth/register/', {
            'email': 'test@example.com',
            'password': 'testpass123',
            'password_confirm': 'testpass123'
        })
        data = response.json()
        self.assertIn('success', data)
        self.assertTrue(data['success'])
        self.assertIn('data', data)
        self.assertIn('request_id', data)
    
    def test_login_returns_unified_format(self):
        """Test login endpoint returns unified format"""
        # ... test implementation
    
    def test_change_password_returns_unified_format(self):
        """Test change password endpoint returns unified format"""
        # ... test implementation
    
    def test_me_returns_unified_format(self):
        """Test /me endpoint returns unified format"""
        # ... test implementation

File: backend/igny8_core/api/tests/test_permissions_billing.py (NEW)

class BillingPermissionsTestCase(TestCase):
    def test_credit_balance_requires_authentication(self):
        """Test credit balance requires authentication"""
        # ... test implementation
    
    def test_credit_transactions_requires_admin(self):
        """Test credit transactions requires admin/owner"""
        # ... test implementation

Integration Tests

Update: backend/igny8_core/api/tests/test_integration_auth.py

  • Add tests for auth endpoints unified format
  • Test permission enforcement

Update: backend/igny8_core/api/tests/test_integration_billing.py

  • Add tests for permission enforcement
  • Test account scoping

Update: backend/igny8_core/api/tests/test_integration_system.py

  • Add tests for AIPromptViewSet permissions
  • Test system settings permissions

Manual Testing Checklist

  • Test registration with valid/invalid data
  • Test login with valid/invalid credentials
  • Test change password
  • Test /me endpoint
  • Test AIPromptViewSet with unauthenticated user (should fail)
  • Test AIPromptViewSet save_prompt with viewer (should fail)
  • Test billing endpoints with different roles
  • Test system settings with different roles
  • Test account isolation on all endpoints
  • Verify all responses have unified format

Rollback Plan

If Issues Arise:

  1. Immediate Rollback:

    • Revert git commits for problematic changes
    • Restore previous version
    • Monitor for issues
  2. Partial Rollback:

    • Revert specific module changes
    • Keep other improvements
    • Fix issues incrementally
  3. Feature Flag:

    • Add feature flag for new permissions
    • Disable if issues found
    • Re-enable after fixes

Rollback Order (if needed):

  1. Auth endpoints (most visible)
  2. Permissions (security critical)
  3. Base class refactoring (less visible)

Success Criteria

Definition of Done

  • All auth endpoints return unified format
  • All ViewSets use standard permissions
  • All ViewSets use base classes where applicable
  • All tests pass
  • Manual testing completed
  • No security vulnerabilities
  • CHANGELOG updated with accurate information

Metrics

  • Coverage: 100% of remaining items implemented
  • Test Coverage: >90% for modified code
  • Security: No endpoints allow unauthenticated access (except public endpoints)
  • Compliance: 100% compliance with API Standard v1.0

Notes

  • All changes should maintain backward compatibility where possible
  • Permission changes may require frontend updates if error handling changes
  • Test thoroughly before deploying to production
  • Update CHANGELOG.md after completion to reflect accurate status

Document Status: Implementation Plan
Last Updated: 2025-01-XX
Next Steps: Begin Phase 1 implementation