=====================================================
API Development Requirements
=====================================================

**AWX REST API Best Practices**

:Version: 1.0
:Date: September 2025
:Based on: AWX Enterprise Django REST Framework Analysis
:Generated by: Claude Code AI 

----

.. contents:: Table of Contents
   :depth: 3
   :local:

----

.. important::
   This document defines mandatory API development standards for enterprise-grade Django REST Framework applications based on AWX production patterns.

----

1. API Architecture and Configuration
=====================================

1.1 Django REST Framework Configuration
---------------------------------------

**REQUIRED**: Comprehensive DRF setup with enterprise-grade defaults:

.. code-block:: python

    # settings/defaults.py
    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'awx.api.pagination.Pagination',
        'PAGE_SIZE': 25,
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'awx.api.authentication.JWTAuthentication',
            'awx.api.authentication.SessionAuthentication',
            'awx.api.authentication.LoggedBasicAuthentication',
        ),
        'DEFAULT_PERMISSION_CLASSES': (
            'awx.api.permissions.ModelAccessPermission',
        ),
        'DEFAULT_PARSER_CLASSES': (
            'awx.api.parsers.JSONParser',
        ),
        'DEFAULT_RENDERER_CLASSES': (
            'awx.api.renderers.DefaultJSONRenderer',
            'awx.api.renderers.BrowsableAPIRenderer',
        ),
        'DEFAULT_METADATA_CLASS': 'awx.api.metadata.Metadata',
        'EXCEPTION_HANDLER': 'awx.api.views.api_exception_handler',
        'VIEW_DESCRIPTION_FUNCTION': 'awx.api.generics.get_view_description',
        'NON_FIELD_ERRORS_KEY': '__all__',
        'DEFAULT_VERSION': 'v2',
        'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
    }

**Configuration Requirements**:

- **Centralized Settings**: API configuration must be centralized and environment-aware
- **Version Control**: Default API version must be explicitly configured
- **Error Handling**: Custom exception handler for consistent error responses

1.2 Modular API Structure
-------------------------

**REQUIRED**: Organize API with clear separation of concerns:

.. code-block:: text

    api/
    ├── __init__.py
    ├── authentication.py       # Custom authentication classes
    ├── permissions.py          # Permission and access control
    ├── serializers.py          # Base serializer patterns
    ├── generics.py            # Custom view classes
    ├── pagination.py          # Pagination strategies
    ├── renderers.py           # Response formatters
    ├── fields.py              # Custom field types
    ├── exceptions.py          # Custom exception classes
    ├── metadata.py            # Field metadata for clients
    ├── urls/                  # Resource-specific URL modules
    │   ├── __init__.py
    │   ├── organization.py
    │   ├── user.py
    │   ├── project.py
    │   └── job_template.py
    └── views/                 # Resource-specific view modules
        ├── __init__.py
        ├── organization.py
        └── user.py

**Structural Requirements**:

- **Resource-Based Organization**: Each API resource must have its own module
- **URL Separation**: URL patterns organized by resource type
- **View Inheritance**: Consistent view hierarchy with shared base classes
- **Component Isolation**: Authentication, permissions, and serialization in separate modules

----

2. REST API Design Standards
============================

2.1 Core REST Principles
-------------------------

**MANDATORY**: All APIs must adhere to these fundamental principles:

.. list-table:: REST Design Requirements
   :header-rows: 1
   :widths: 30 70

   * - Principle
     - Implementation Requirement
   * - **Paginate Everything**
     - Any endpoint returning collections MUST be paginated
   * - **Performance Target**
     - Expected response time ≤ 250ms (1/4 second)
   * - **RBAC Filtering**
     - All collections MUST be filtered by user access permissions
   * - **API Discoverability**
     - All endpoints MUST be traversable from API root '/'
   * - **RESTful Verbs**
     - HTTP methods MUST follow REST conventions
   * - **Constant Time Queries**
     - Database queries MUST NOT vary with result set size

2.2 URL Pattern Standards
--------------------------

**REQUIRED**: Consistent RESTful URL patterns:

.. code-block:: python

    # Standard resource patterns
    urlpatterns = [
        # Collection endpoints
        re_path(r'^$', ResourceList.as_view(), name='resource_list'),

        # Instance endpoints
        re_path(r'^(?P<pk>[0-9]+)/$', ResourceDetail.as_view(), name='resource_detail'),

        # Nested resource relationships
        re_path(r'^(?P<pk>[0-9]+)/children/$', ResourceChildrenList.as_view(),
                name='resource_children_list'),

        # Action endpoints
        re_path(r'^(?P<pk>[0-9]+)/launch/$', ResourceLaunch.as_view(),
                name='resource_launch'),
        re_path(r'^(?P<pk>[0-9]+)/copy/$', ResourceCopy.as_view(),
                name='resource_copy'),
        re_path(r'^(?P<pk>[0-9]+)/callback/$', ResourceCallback.as_view(),
                name='resource_callback'),
    ]

**URL Requirements**:

- **Numeric Primary Keys**: Use ``(?P<pk>[0-9]+)`` pattern for resource IDs
- **Hierarchical Relationships**: Support nested resource access patterns
- **Action Endpoints**: Additional endpoints for resource-specific actions
- **Consistent Naming**: Follow ``resource_action`` naming convention

2.3 HTTP Method Standards
-------------------------

**REQUIRED**: Proper HTTP method usage:

.. list-table:: HTTP Method Requirements
   :header-rows: 1
   :widths: 15 25 60

   * - Method
     - Usage
     - Requirements
   * - **GET**
     - Retrieve resources
     - Idempotent, no side effects, cacheable
   * - **POST**
     - Create resources
     - Returns 201 Created with Location header
   * - **PUT**
     - Update/Replace resources
     - Idempotent, full resource replacement
   * - **PATCH**
     - Partial updates
     - Non-idempotent, partial resource modification
   * - **DELETE**
     - Remove resources
     - Idempotent, returns 204 No Content
   * - **OPTIONS**
     - Metadata discovery
     - Returns available methods and field metadata

----

3. Authentication and Authorization
===================================

3.1 Multi-Layer Authentication Stack
------------------------------------

**REQUIRED**: Implement comprehensive authentication system:

.. code-block:: python

    # api/authentication.py
    class LoggedBasicAuthentication(authentication.BasicAuthentication):
        """Basic authentication with comprehensive logging"""

        def authenticate(self, request):
            if not settings.AUTH_BASIC_ENABLED:
                return

            ret = super().authenticate(request)
            if ret:
                username = ret[0].username if ret[0] else '<none>'
                logger.info(
                    f"User {username} performed {request.method} "
                    f"to {request.path} through the API using Basic Auth"
                )
            return ret

    class SessionAuthentication(authentication.SessionAuthentication):
        """Enhanced session authentication with CSRF handling"""

        def authenticate(self, request):
            # Custom session validation logic
            return super().authenticate(request)

**Authentication Requirements**:

1. **JWT Authentication**: Primary token-based authentication
2. **Session Authentication**: Browser-based session support
3. **Basic Authentication**: With comprehensive request logging
4. **Authentication Logging**: All authentication events must be logged
5. **Fallback Support**: Multiple authentication methods for different clients

3.2 Role-Based Access Control (RBAC)
------------------------------------

**REQUIRED**: Implement comprehensive permission system:

.. code-block:: python

    # api/permissions.py
    class ModelAccessPermission(permissions.BasePermission):
        """Advanced model-based access control"""

        def has_permission(self, request, view):
            # Check view-level permissions
            if not hasattr(view, 'model'):
                return False

            # Parent resource permission checking
            if hasattr(view, 'parent_model'):
                parent_obj = view.get_parent_object()
                if not check_user_access(
                    request.user,
                    view.parent_model,
                    'read',
                    parent_obj
                ):
                    return False

            return True

        def has_object_permission(self, request, view, obj):
            # Object-level permission checking
            permission_map = {
                'GET': 'read',
                'POST': 'add',
                'PUT': 'change',
                'PATCH': 'change',
                'DELETE': 'delete',
            }

            required_permission = permission_map.get(request.method, 'read')
            return check_user_access(request.user, view.model, required_permission, obj)

**RBAC Requirements**:

- **Method-Specific Permissions**: Different permissions for GET, POST, PUT, DELETE
- **Object-Level Control**: Fine-grained access control on individual resources
- **Hierarchical Permissions**: Parent-child relationship permission inheritance
- **Data-Aware Permissions**: Access control based on request data content
- **Audit Trail**: All permission checks must be logged

3.3 API Token Management
------------------------

**REQUIRED**: Secure token handling patterns:

.. code-block:: python

    # Token-based authentication requirements
    JWT_SETTINGS = {
        'ACCESS_TOKEN_LIFETIME': timedelta(hours=1),
        'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
        'ROTATE_REFRESH_TOKENS': True,
        'BLACKLIST_AFTER_ROTATION': True,
        'ALGORITHM': 'RS256',
        'SIGNING_KEY': settings.JWT_PRIVATE_KEY,
        'VERIFYING_KEY': settings.JWT_PUBLIC_KEY,
    }

**Token Requirements**:

- **Short-Lived Access Tokens**: Maximum 1-hour expiration
- **Refresh Token Rotation**: Automatic rotation on refresh
- **Token Blacklisting**: Revoked tokens must be blacklisted
- **Asymmetric Encryption**: Use RS256 with key pairs
- **Secure Storage**: Private keys must be externally managed

----

4. Serialization and Data Validation
=====================================

4.1 Base Serializer Architecture
--------------------------------

**REQUIRED**: Implement consistent serializer patterns:

.. code-block:: python

    # api/serializers.py
    class BaseSerializer(serializers.ModelSerializer, metaclass=BaseSerializerMetaclass):
        """Base serializer with common enterprise patterns"""

        class Meta:
            fields = (
                'id', 'type', 'url', 'related', 'summary_fields',
                'created', 'modified', 'name', 'description'
            )
            summary_fields = ()
            summarizable_fields = ()

        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self._setup_summary_fields()
            self._setup_related_fields()

        def _setup_summary_fields(self):
            """Configure optimized nested data representation"""
            pass

        def _setup_related_fields(self):
            """Configure related resource URL fields"""
            pass

**Serializer Requirements**:

- **Base Class Inheritance**: All serializers must inherit from base serializer
- **Common Fields**: Standardized fields across all resources
- **Summary Fields**: Optimized nested data representation
- **Related URLs**: Structured related resource references
- **Metaclass Usage**: Custom metaclass for field inheritance

4.2 Custom Field Types
----------------------

**REQUIRED**: Domain-specific field validation:

.. code-block:: python

    # api/fields.py
    class BooleanNullField(NullFieldMixin, serializers.BooleanField):
        """Boolean field that allows null and empty string as False"""

        def to_internal_value(self, data):
            if data is None or data == '':
                return False
            return super().to_internal_value(data)

    class CharNullField(NullFieldMixin, serializers.CharField):
        """Char field that allows null input and coerces to empty string"""

        def to_internal_value(self, data):
            if data is None:
                return ''
            return super().to_internal_value(data)

    class JSONField(serializers.Field):
        """Custom JSON field with validation"""

        def to_representation(self, value):
            return json.loads(value) if isinstance(value, str) else value

        def to_internal_value(self, data):
            try:
                return json.dumps(data)
            except (TypeError, ValueError):
                raise serializers.ValidationError("Invalid JSON data")

**Field Requirements**:

- **Null Handling**: Consistent null value processing across field types
- **Type Coercion**: Automatic data type conversion where appropriate
- **Validation Mixins**: Reusable validation logic through mixins
- **Custom Serialization**: Domain-specific serialization logic

4.3 Data Validation Patterns
----------------------------

**REQUIRED**: Comprehensive validation strategies:

.. code-block:: python

    class ResourceSerializer(BaseSerializer):
        """Example resource serializer with validation"""

        class Meta(BaseSerializer.Meta):
            model = Resource
            fields = BaseSerializer.Meta.fields + ('status', 'type', 'configuration')

        def validate_configuration(self, value):
            """Field-level validation"""
            if not isinstance(value, dict):
                raise serializers.ValidationError("Configuration must be a JSON object")
            return value

        def validate(self, data):
            """Object-level validation"""
            if data.get('status') == 'active' and not data.get('configuration'):
                raise serializers.ValidationError(
                    "Active resources must have configuration"
                )
            return data

        def create(self, validated_data):
            """Custom creation logic with audit trail"""
            instance = super().create(validated_data)
            self._log_creation(instance)
            return instance

**Validation Requirements**:

- **Field-Level Validation**: Validate individual fields with custom logic
- **Object-Level Validation**: Cross-field validation rules
- **Business Logic Validation**: Domain-specific validation rules
- **Audit Logging**: All validation failures must be logged
- **Error Formatting**: Consistent error message structure

----

5. Performance and Optimization
===============================

5.1 Query Optimization Standards
--------------------------------

**MANDATORY**: Database query performance requirements:

.. warning::
   **Critical Performance Rule**: The number of database queries MUST be constant time and MUST NOT vary with the size of the result set.

.. code-block:: python

    # api/generics.py
    def optimize_queryset(queryset, view, remove_django_content_type=False):
        """Query optimization for API views"""

        # Select related for foreign keys
        if hasattr(view, 'select_related_fields'):
            queryset = queryset.select_related(*view.select_related_fields)

        # Prefetch related for many-to-many and reverse foreign keys
        if hasattr(view, 'prefetch_related_fields'):
            queryset = queryset.prefetch_related(*view.prefetch_related_fields)

        # Only select necessary fields
        if hasattr(view, 'only_fields'):
            queryset = queryset.only(*view.only_fields)

        return queryset

**Query Optimization Requirements**:

- **Constant Time Queries**: Query count independent of result set size
- **Select Related**: Use ``select_related()`` for foreign key relationships
- **Prefetch Related**: Use ``prefetch_related()`` for many-to-many relationships
- **Field Selection**: Use ``only()`` to limit selected fields
- **No Serializer Queries**: Database queries prohibited in serializers

5.2 Pagination Strategy
-----------------------

**REQUIRED**: Advanced pagination with performance optimization:

.. code-block:: python

    # api/pagination.py
    class Pagination(pagination.PageNumberPagination):
        """Enterprise pagination with performance features"""

        page_size_query_param = 'page_size'
        max_page_size = 200
        count_disabled = False

        def paginate_queryset(self, queryset, request, **kwargs):
            # Optional count disabling for large datasets
            self.count_disabled = 'count_disabled' in request.query_params

            if self.count_disabled:
                # Skip expensive COUNT query for large datasets
                return self._paginate_without_count(queryset, request)

            return super().paginate_queryset(queryset, request, **kwargs)

        def get_paginated_response(self, data):
            response_data = {
                'count': self.page.paginator.count if not self.count_disabled else None,
                'next': self.get_next_link(),
                'previous': self.get_previous_link(),
                'results': data
            }
            return Response(response_data)

**Pagination Requirements**:

- **Performance Optimization**: Optional count disabling for large datasets
- **Configurable Page Sizes**: Maximum page size limits with user control
- **Consistent Format**: Standardized pagination response format
- **Memory Efficiency**: Efficient memory usage for large result sets

5.3 Caching Strategies
----------------------

**REQUIRED**: Multi-level caching implementation:

.. code-block:: python

    # api/middleware.py
    class SettingsCacheMiddleware(MiddlewareMixin):
        """Clear settings cache on each request"""

        def process_request(self, request):
            from django.conf import settings
            if hasattr(settings, '_awx_conf_memoizedcache'):
                settings._awx_conf_memoizedcache.clear()

    class ResponseCacheMiddleware(MiddlewareMixin):
        """Cache API responses based on content type"""

        def process_response(self, request, response):
            # Cache responses for GET requests only
            if request.method == 'GET' and response.status_code == 200:
                cache_key = self._generate_cache_key(request)
                cache.set(cache_key, response.content, timeout=300)
            return response

**Caching Requirements**:

- **Settings Caching**: Intelligent configuration caching with invalidation
- **Response Caching**: Cache GET responses with appropriate TTL
- **Cache Invalidation**: Automatic cache clearing on data changes
- **Selective Caching**: Cache only appropriate endpoints and data

----

6. Error Handling and Status Codes
===================================

6.1 Custom Exception Hierarchy
------------------------------

**REQUIRED**: Comprehensive exception handling system:

.. code-block:: python

    # api/exceptions.py
    class APIException(Exception):
        """Base API exception with structured error format"""
        status_code = 400
        detail = "An error occurred"

        def __init__(self, detail=None, code=None):
            if detail is not None:
                self.detail = detail
            if code is not None:
                self.status_code = code

    class ActiveJobConflict(ValidationError):
        """Resource conflict with active jobs"""
        status_code = 409

        def __init__(self, active_jobs):
            super().__init__()
            self.detail = {
                "error": "Resource is being used by running jobs",
                "active_jobs": active_jobs,
                "conflict_type": "active_job_dependency"
            }

    class PermissionDenied(APIException):
        """Enhanced permission denied with context"""
        status_code = 403

        def __init__(self, detail=None, required_permission=None, resource=None):
            super().__init__(detail)
            self.detail = {
                "error": detail or "Permission denied",
                "required_permission": required_permission,
                "resource": resource
            }

**Exception Requirements**:

- **Structured Error Format**: Consistent error response structure
- **HTTP Status Codes**: Proper status code mapping for different error types
- **Context Information**: Rich error context for debugging and user feedback
- **Exception Hierarchy**: Logical exception inheritance structure

6.2 Global Exception Handler
-----------------------------

**REQUIRED**: Centralized exception processing:

.. code-block:: python

    # api/views/__init__.py
    def api_exception_handler(exc, context):
        """Enhanced exception handler with logging and standardization"""

        # Handle database integrity errors
        if isinstance(exc, IntegrityError):
            exc = ParseError("Database constraint violation: " + str(exc))

        # Handle Django field errors
        if isinstance(exc, FieldError):
            exc = ParseError("Invalid field specification: " + str(exc))

        # Handle permission errors with context
        if isinstance(exc, PermissionDenied):
            logger.warning(
                f"Permission denied for user {context['request'].user} "
                f"accessing {context['request'].path}"
            )

        # Use default DRF exception handler
        response = exception_handler(exc, context)

        # Add custom error metadata
        if response is not None:
            response.data['timestamp'] = timezone.now().isoformat()
            response.data['path'] = context['request'].path
            response.data['method'] = context['request'].method

        return response

**Exception Handler Requirements**:

- **Comprehensive Logging**: All exceptions must be logged with context
- **Error Transformation**: Convert database/system errors to API errors
- **Metadata Addition**: Include request context in error responses
- **Security Considerations**: Sanitize error messages for production

6.3 Status Code Standards
-------------------------

**REQUIRED**: Proper HTTP status code usage:

.. list-table:: Status Code Requirements
   :header-rows: 1
   :widths: 15 25 60

   * - Code
     - Usage
     - Implementation Requirements
   * - **200 OK**
     - Successful GET, PUT, PATCH
     - Include response timing headers
   * - **201 Created**
     - Successful POST
     - Include Location header with new resource URL
   * - **204 No Content**
     - Successful DELETE
     - No response body required
   * - **400 Bad Request**
     - Validation errors
     - Include detailed field-level error information
   * - **401 Unauthorized**
     - Authentication required
     - Include WWW-Authenticate header
   * - **403 Forbidden**
     - Permission denied
     - Include required permission information
   * - **404 Not Found**
     - Resource not found
     - Include suggested alternatives if available
   * - **409 Conflict**
     - Resource conflicts
     - Include conflict resolution information
   * - **422 Unprocessable Entity**
     - Business logic errors
     - Include business rule violation details
   * - **500 Internal Server Error**
     - System errors
     - Log full error details, return sanitized message

----

7. API Documentation and Discovery
==================================

7.1 OpenAPI/Swagger Integration
-------------------------------

**REQUIRED**: Comprehensive API documentation system:

.. code-block:: python

    # api/swagger.py
    class CustomSwaggerAutoSchema(SwaggerAutoSchema):
        """Enhanced Swagger schema generation"""

        def get_tags(self, operation_keys=None):
            """Generate logical API tags"""
            tags = []

            if hasattr(self.view, 'swagger_topic'):
                tags.append(str(self.view.swagger_topic).title())
            elif hasattr(self.view, 'serializer_class'):
                serializer = self.view.serializer_class
                if hasattr(serializer, 'Meta') and hasattr(serializer.Meta, 'model'):
                    model_name = serializer.Meta.model._meta.verbose_name_plural
                    tags.append(str(model_name).title())

            return tags

        def get_operation_id(self, operation_keys):
            """Generate unique operation IDs"""
            return '_'.join(operation_keys)

        def get_description(self):
            """Enhanced operation descriptions"""
            description = super().get_description()

            # Add permission requirements
            if hasattr(self.view, 'required_permissions'):
                description += f"\n\nRequired permissions: {self.view.required_permissions}"

            # Add rate limiting information
            if hasattr(self.view, 'throttle_classes'):
                description += f"\n\nRate limiting: Applied"

            return description

**Documentation Requirements**:

- **Auto-Generated Schemas**: Complete OpenAPI 3.0 schema generation
- **Logical Grouping**: API endpoints grouped by resource/functionality
- **Operation Metadata**: Detailed operation descriptions with examples
- **Permission Documentation**: Clear permission requirements for each endpoint
- **Response Examples**: Example responses for all status codes

7.2 Rich Field Metadata
-----------------------

**REQUIRED**: Comprehensive field information for clients:

.. code-block:: python

    # api/metadata.py
    class Metadata(metadata.SimpleMetadata):
        """Enhanced metadata with comprehensive field information"""

        def get_field_info(self, field):
            """Generate detailed field metadata"""
            field_info = super().get_field_info(field)

            # Add validation information
            field_info['validators'] = self._get_validator_info(field)

            # Add filtering capabilities
            field_info['filterable'] = getattr(field, 'filterable', False)
            field_info['searchable'] = getattr(field, 'searchable', False)

            # Add help text and examples
            field_info['help_text'] = getattr(field, 'help_text', None)
            field_info['example'] = getattr(field, 'example', None)

            # Add relationship information
            if hasattr(field, 'queryset'):
                field_info['related_model'] = field.queryset.model.__name__
                field_info['related_url'] = self._get_related_url(field)

            return field_info

        def _get_validator_info(self, field):
            """Extract validator information"""
            validators = []
            for validator in field.validators:
                validators.append({
                    'type': validator.__class__.__name__,
                    'message': getattr(validator, 'message', None)
                })
            return validators

**Metadata Requirements**:

- **Validation Rules**: Complete field validation information
- **Filtering Support**: Indicate which fields support filtering/searching
- **Relationship Data**: Information about related resources
- **Help Text**: User-friendly field descriptions and examples
- **Client Tooling**: Metadata suitable for auto-generating client SDKs

7.3 API Discoverability
-----------------------

**REQUIRED**: Complete API traversal from root endpoint:

.. code-block:: python

    # api/views/root.py
    class ApiRootView(APIView):
        """API root with complete endpoint discovery"""

        def get(self, request, format=None):
            """Return all available API endpoints"""
            endpoints = {
                'ping': reverse('api:ping', request=request),
                'config': reverse('api:config', request=request),
                'me': reverse('api:me', request=request),
                'dashboard': reverse('api:dashboard', request=request),
                'organizations': reverse('api:organization_list', request=request),
                'users': reverse('api:user_list', request=request),
                'teams': reverse('api:team_list', request=request),
                'projects': reverse('api:project_list', request=request),
                'inventories': reverse('api:inventory_list', request=request),
                'job_templates': reverse('api:job_template_list', request=request),
                'jobs': reverse('api:job_list', request=request),
            }

            # Add versioning information
            endpoints['current_version'] = request.version
            endpoints['available_versions'] = ['v1', 'v2']

            # Add authentication information
            endpoints['auth_methods'] = [
                'jwt', 'session', 'basic'
            ]

            return Response(endpoints)

**Discoverability Requirements**:

- **Complete Traversal**: All endpoints accessible from API root
- **Version Information**: Available API versions clearly indicated
- **Authentication Methods**: Supported authentication mechanisms listed
- **Relationship Links**: Related resource URLs in all responses

----

8. API Versioning Strategy
===========================

8.1 URL Path Versioning
-----------------------

**REQUIRED**: Clean URL-based versioning system:

.. code-block:: python

    # api/versioning.py
    class URLPathVersioning(BaseVersioning):
        """URL path-based API versioning"""

        version_param = 'version'
        default_version = 'v2'
        allowed_versions = ['v1', 'v2']

        def determine_version(self, request, *args, **kwargs):
            version = kwargs.get(self.version_param, self.default_version)
            if version not in self.allowed_versions:
                raise exceptions.NotFound(f"API version '{version}' not found")
            return version

        def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
            if request.version is not None:
                kwargs = {} if kwargs is None else kwargs
                kwargs[self.version_param] = request.version
            return super().reverse(viewname, args, kwargs, request, format, **extra)

**Versioning Requirements**:

- **URL Path Format**: Use ``/api/v{version}/`` format
- **Backward Compatibility**: Support multiple API versions simultaneously
- **Default Version**: Explicit default version configuration
- **Version Discovery**: Available versions discoverable from API root
- **Graceful Deprecation**: Clear deprecation timeline for old versions

8.2 Version-Specific Behavior
-----------------------------

**REQUIRED**: Handle version differences in views and serializers:

.. code-block:: python

    # api/views/versioned.py
    class VersionedViewMixin:
        """Mixin for version-aware view behavior"""

        def get_serializer_class(self):
            """Return version-specific serializer"""
            base_serializer = super().get_serializer_class()

            if self.request.version == 'v1':
                # Use legacy serializer for v1
                return getattr(self, 'v1_serializer_class', base_serializer)
            elif self.request.version == 'v2':
                # Use current serializer for v2
                return base_serializer

            return base_serializer

        def get_queryset(self):
            """Return version-specific queryset"""
            queryset = super().get_queryset()

            # Apply version-specific filtering
            if self.request.version == 'v1':
                # Legacy filtering logic
                queryset = self._apply_v1_filters(queryset)

            return queryset

**Version Management Requirements**:

- **Serializer Versioning**: Version-specific serializer classes
- **Behavior Versioning**: Different view behavior for different versions
- **Data Migration**: Automatic data format conversion between versions
- **Feature Flags**: Version-specific feature availability

----

9. Testing Requirements
=======================

9.1 Comprehensive Test Coverage
-------------------------------

**MANDATORY**: Complete API test coverage requirements:

.. important::
   **Critical Testing Rule**: Every API URL/endpoint MUST have unit test coverage with both positive and negative test cases.

.. code-block:: python

    # tests/api/test_resource.py
    class TestResourceAPI:
        """Comprehensive API testing for Resource endpoints"""

        def test_list_resources_success(self, api_client, user):
            """Test successful resource listing"""
            # Setup test data
            resources = ResourceFactory.create_batch(3)

            # Make request
            response = api_client.get('/api/v2/resources/')

            # Assertions
            assert response.status_code == 200
            assert response.data['count'] == 3
            assert len(response.data['results']) == 3

        def test_list_resources_permission_denied(self, api_client, user_without_permissions):
            """Test resource listing without permissions"""
            ResourceFactory.create_batch(3)

            api_client.force_authenticate(user=user_without_permissions)
            response = api_client.get('/api/v2/resources/')

            assert response.status_code == 403
            assert 'permission' in response.data['error'].lower()

        def test_create_resource_success(self, api_client, user):
            """Test successful resource creation"""
            data = {
                'name': 'Test Resource',
                'description': 'Test Description',
                'configuration': {'key': 'value'}
            }

            response = api_client.post('/api/v2/resources/', data)

            assert response.status_code == 201
            assert response.data['name'] == data['name']
            assert 'id' in response.data

        @pytest.mark.parametrize('invalid_data,expected_error', [
            ({'name': ''}, 'name'),
            ({'name': 'test'}, 'description'),
            ({'name': 'test', 'description': 'test', 'configuration': 'invalid'}, 'configuration'),
        ])
        def test_create_resource_validation_errors(self, api_client, user, invalid_data, expected_error):
            """Test resource creation validation"""
            response = api_client.post('/api/v2/resources/', invalid_data)

            assert response.status_code == 400
            assert expected_error in response.data

**Testing Requirements**:

- **Positive Test Cases**: Test all successful operation scenarios
- **Negative Test Cases**: Test all error conditions and edge cases
- **Permission Testing**: Test access control for all user types
- **Validation Testing**: Test all field validation rules
- **Parameterized Testing**: Use data-driven test approaches
- **Factory Pattern**: Use factories for test data generation

9.2 Performance Testing
-----------------------

**REQUIRED**: API performance validation:

.. code-block:: python

    # tests/api/test_performance.py
    class TestAPIPerformance:
        """Performance testing for API endpoints"""

        def test_query_count_constant(self, api_client, django_assert_num_queries):
            """Ensure query count doesn't vary with result set size"""

            # Test with small dataset
            ResourceFactory.create_batch(10)
            with django_assert_num_queries(5):  # Expected query count
                response = api_client.get('/api/v2/resources/')
                assert response.status_code == 200

            # Test with larger dataset - query count should remain same
            ResourceFactory.create_batch(90)  # Total 100 resources
            with django_assert_num_queries(5):  # Same query count
                response = api_client.get('/api/v2/resources/')
                assert response.status_code == 200

        def test_response_time_target(self, api_client):
            """Ensure response time meets performance targets"""
            import time

            start_time = time.time()
            response = api_client.get('/api/v2/resources/')
            end_time = time.time()

            response_time = end_time - start_time
            assert response_time < 0.25  # 250ms target
            assert response.status_code == 200

**Performance Test Requirements**:

- **Query Count Testing**: Verify constant-time database queries
- **Response Time Testing**: Validate performance targets (≤250ms)
- **Load Testing**: Test with realistic data volumes
- **Memory Usage**: Monitor memory consumption patterns

----

10. Security Requirements
=========================

10.1 Authentication Security
----------------------------

**REQUIRED**: Secure authentication implementation:

.. code-block:: python

    # Security configuration
    AUTHENTICATION_SECURITY = {
        'PASSWORD_RESET_TIMEOUT': 3600,  # 1 hour
        'LOGIN_ATTEMPT_LIMIT': 5,
        'LOGIN_LOCKOUT_DURATION': 300,   # 5 minutes
        'JWT_ACCESS_TOKEN_LIFETIME': 3600,  # 1 hour
        'JWT_REFRESH_TOKEN_LIFETIME': 604800,  # 7 days
        'SESSION_COOKIE_AGE': 1800,      # 30 minutes
        'CSRF_COOKIE_HTTPONLY': True,
        'SESSION_COOKIE_SECURE': True,
        'SESSION_COOKIE_SAMESITE': 'Lax',
    }

**Authentication Security Requirements**:

- **Rate Limiting**: Implement login attempt limiting
- **Token Expiration**: Short-lived access tokens with refresh mechanism
- **Secure Cookies**: HTTPOnly, Secure, and SameSite cookie attributes
- **Brute Force Protection**: Account lockout after failed attempts
- **Session Management**: Configurable session timeouts

10.2 Authorization Security
---------------------------

**REQUIRED**: Comprehensive access control:

.. code-block:: python

    # api/permissions.py
    class SecureModelAccessPermission(permissions.BasePermission):
        """Security-enhanced permission checking"""

        def has_permission(self, request, view):
            # Log all permission checks for security audit
            logger.info(
                f"Permission check: {request.user} accessing "
                f"{view.__class__.__name__} via {request.method}"
            )

            # Check user account status
            if not request.user.is_active:
                logger.warning(f"Inactive user {request.user} attempted access")
                return False

            # Check IP whitelist if configured
            if hasattr(settings, 'API_IP_WHITELIST'):
                client_ip = self._get_client_ip(request)
                if client_ip not in settings.API_IP_WHITELIST:
                    logger.warning(f"Access denied from IP {client_ip}")
                    return False

            return super().has_permission(request, view)

**Authorization Security Requirements**:

- **Audit Logging**: Log all access attempts and permission checks
- **Account Status Checking**: Verify user account is active
- **IP Whitelisting**: Optional IP-based access control
- **Principle of Least Privilege**: Minimal required permissions only
- **Session Validation**: Verify session integrity on each request

10.3 Data Protection
--------------------

**REQUIRED**: Secure data handling:

.. code-block:: python

    # api/serializers.py
    class SecureSerializer(BaseSerializer):
        """Security-enhanced serializer"""

        sensitive_fields = ['password', 'secret_key', 'private_key', 'token']

        def to_representation(self, instance):
            """Remove sensitive data from responses"""
            data = super().to_representation(instance)

            # Mask sensitive fields
            for field in self.sensitive_fields:
                if field in data:
                    data[field] = '***REDACTED***'

            return data

        def validate(self, attrs):
            """Enhanced validation with security checks"""
            attrs = super().validate(attrs)

            # Validate against known security patterns
            for field, value in attrs.items():
                if self._contains_injection_attempt(value):
                    logger.warning(f"Potential injection attempt in field {field}")
                    raise serializers.ValidationError(f"Invalid value for {field}")

            return attrs

**Data Protection Requirements**:

- **Sensitive Data Masking**: Automatic masking of sensitive fields in responses
- **Input Sanitization**: Validate and sanitize all input data
- **Injection Prevention**: Protect against SQL injection and XSS attacks
- **Data Encryption**: Encrypt sensitive data at rest and in transit
- **Audit Trail**: Log all data access and modification events

----

Compliance Checklist
=====================

API Design Standards
--------------------

.. list-table::
   :header-rows: 1
   :widths: 50 10

   * - Requirement
     - Status
   * - RESTful URL patterns implemented
     - ☐
   * - Proper HTTP method usage
     - ☐
   * - Consistent error responses
     - ☐
   * - Comprehensive pagination
     - ☐
   * - API versioning strategy
     - ☐
   * - OpenAPI documentation
     - ☐
   * - API discoverability from root
     - ☐
   * - Performance targets met (≤250ms)
     - ☐

Security Requirements
---------------------

.. list-table::
   :header-rows: 1
   :widths: 50 10

   * - Requirement
     - Status
   * - Multi-factor authentication
     - ☐
   * - RBAC implementation
     - ☐
   * - Secure token management
     - ☐
   * - Input validation and sanitization
     - ☐
   * - Audit logging
     - ☐
   * - Rate limiting
     - ☐
   * - Data encryption
     - ☐
   * - Security headers configured
     - ☐

Performance Standards
---------------------

.. list-table::
   :header-rows: 1
   :widths: 50 10

   * - Requirement
     - Status
   * - Constant-time database queries
     - ☐
   * - Query optimization implemented
     - ☐
   * - Effective caching strategy
     - ☐
   * - Pagination performance optimized
     - ☐
   * - Response time monitoring
     - ☐
   * - Memory usage optimized
     - ☐
   * - Database indexing proper
     - ☐
   * - No N+1 query problems
     - ☐

Testing Coverage
----------------

.. list-table::
   :header-rows: 1
   :widths: 50 10

   * - Requirement
     - Status
   * - 100% endpoint test coverage
     - ☐
   * - Positive and negative test cases
     - ☐
   * - Permission testing complete
     - ☐
   * - Performance testing implemented
     - ☐
   * - Security testing coverage
     - ☐
   * - Integration testing
     - ☐
   * - Load testing completed
     - ☐
   * - Automated test execution
     - ☐

----

References
==========

- **Django REST Framework Documentation**: https://www.django-rest-framework.org/
- **OpenAPI Specification**: https://swagger.io/specification/
- **HTTP Status Code Definitions**: https://tools.ietf.org/html/rfc7231#section-6
- **OAuth 2.0 Authorization Framework**: https://tools.ietf.org/html/rfc6749
- **JWT Best Practices**: https://tools.ietf.org/html/rfc8725
- **AWX Source Code**: https://github.com/ansible/awx

----

| **Document Maintainer**: API Development Team
| **Last Updated**: September 2025
| **Review Schedule**: Quarterly
| **Compliance Audit**: Monthly