package ucxl import ( "time" ) // UCXLCode represents a standardized UCXL response/error code type UCXLCode string // Standard UCXL response codes const ( // Success codes (2xx range) CodeSuccess UCXLCode = "UCXL-200-SUCCESS" CodeCreated UCXLCode = "UCXL-201-CREATED" CodeAccepted UCXLCode = "UCXL-202-ACCEPTED" CodeNoContent UCXLCode = "UCXL-204-NO_CONTENT" // Client error codes (4xx range) CodeBadRequest UCXLCode = "UCXL-400-BAD_REQUEST" CodeInvalidAddress UCXLCode = "UCXL-400-INVALID_ADDRESS" CodeInvalidPayload UCXLCode = "UCXL-400-INVALID_PAYLOAD" CodeUnauthorized UCXLCode = "UCXL-401-UNAUTHORIZED" CodeForbidden UCXLCode = "UCXL-403-FORBIDDEN" CodeNotFound UCXLCode = "UCXL-404-NOT_FOUND" CodeMethodNotAllowed UCXLCode = "UCXL-405-METHOD_NOT_ALLOWED" CodeConflict UCXLCode = "UCXL-409-CONFLICT" CodeUnprocessable UCXLCode = "UCXL-422-UNPROCESSABLE" CodeTooManyRequests UCXLCode = "UCXL-429-TOO_MANY_REQUESTS" // Server error codes (5xx range) CodeInternalError UCXLCode = "UCXL-500-INTERNAL_ERROR" CodeNotImplemented UCXLCode = "UCXL-501-NOT_IMPLEMENTED" CodeBadGateway UCXLCode = "UCXL-502-BAD_GATEWAY" CodeServiceUnavailable UCXLCode = "UCXL-503-SERVICE_UNAVAILABLE" CodeGatewayTimeout UCXLCode = "UCXL-504-GATEWAY_TIMEOUT" // UCXI-specific codes CodeResolutionFailed UCXLCode = "UCXL-404-RESOLUTION_FAILED" CodeStorageFailed UCXLCode = "UCXL-500-STORAGE_FAILED" CodeAnnounceFailed UCXLCode = "UCXL-500-ANNOUNCE_FAILED" CodeNavigationFailed UCXLCode = "UCXL-422-NAVIGATION_FAILED" CodeTemporalInvalid UCXLCode = "UCXL-400-TEMPORAL_INVALID" // Role-based collaboration codes CodeCollaborationFailed UCXLCode = "UCXL-500-COLLABORATION_FAILED" CodeInvalidRole UCXLCode = "UCXL-400-INVALID_ROLE" CodeExpertiseNotAvailable UCXLCode = "UCXL-404-EXPERTISE_NOT_AVAILABLE" CodeMentorshipUnavailable UCXLCode = "UCXL-404-MENTORSHIP_UNAVAILABLE" CodeProjectNotFound UCXLCode = "UCXL-404-PROJECT_NOT_FOUND" CodeCollaborationTimeout UCXLCode = "UCXL-408-COLLABORATION_TIMEOUT" ) // UCXLResponse represents a standardized UCXL success response type UCXLResponse struct { Response UCXLResponseData `json:"response"` } // UCXLResponseData contains the actual response data type UCXLResponseData struct { Code UCXLCode `json:"code"` Message string `json:"message"` Data interface{} `json:"data,omitempty"` Details interface{} `json:"details,omitempty"` RequestID string `json:"request_id"` Timestamp time.Time `json:"timestamp"` } // UCXLError represents a standardized UCXL error response type UCXLError struct { Error UCXLErrorData `json:"error"` } // UCXLErrorData contains the actual error data type UCXLErrorData struct { Code UCXLCode `json:"code"` Message string `json:"message"` Details interface{} `json:"details,omitempty"` Source string `json:"source"` Path string `json:"path"` RequestID string `json:"request_id"` Timestamp time.Time `json:"timestamp"` Cause *UCXLError `json:"cause,omitempty"` } // ResponseBuilder helps build standardized UCXL responses type ResponseBuilder struct { requestID string source string } // NewResponseBuilder creates a new response builder func NewResponseBuilder(requestID string, source string) *ResponseBuilder { if requestID == "" { requestID = generateRequestID() } if source == "" { source = "ucxi-server" } return &ResponseBuilder{ requestID: requestID, source: source, } } // Success creates a standardized success response func (rb *ResponseBuilder) Success(code UCXLCode, message string, data interface{}) *UCXLResponse { return &UCXLResponse{ Response: UCXLResponseData{ Code: code, Message: message, Data: data, RequestID: rb.requestID, Timestamp: time.Now().UTC(), }, } } // SuccessWithDetails creates a success response with additional details func (rb *ResponseBuilder) SuccessWithDetails(code UCXLCode, message string, data interface{}, details interface{}) *UCXLResponse { return &UCXLResponse{ Response: UCXLResponseData{ Code: code, Message: message, Data: data, Details: details, RequestID: rb.requestID, Timestamp: time.Now().UTC(), }, } } // Error creates a standardized error response func (rb *ResponseBuilder) Error(code UCXLCode, message string, path string) *UCXLError { return &UCXLError{ Error: UCXLErrorData{ Code: code, Message: message, Source: rb.source, Path: path, RequestID: rb.requestID, Timestamp: time.Now().UTC(), }, } } // ErrorWithDetails creates an error response with additional details func (rb *ResponseBuilder) ErrorWithDetails(code UCXLCode, message string, path string, details interface{}) *UCXLError { return &UCXLError{ Error: UCXLErrorData{ Code: code, Message: message, Details: details, Source: rb.source, Path: path, RequestID: rb.requestID, Timestamp: time.Now().UTC(), }, } } // ErrorWithCause creates an error response with a causal chain func (rb *ResponseBuilder) ErrorWithCause(code UCXLCode, message string, path string, cause *UCXLError) *UCXLError { return &UCXLError{ Error: UCXLErrorData{ Code: code, Message: message, Source: rb.source, Path: path, RequestID: rb.requestID, Timestamp: time.Now().UTC(), Cause: cause, }, } } // Convenience methods for common responses // OK creates a standard 200 OK response func (rb *ResponseBuilder) OK(data interface{}) *UCXLResponse { return rb.Success(CodeSuccess, "Request completed successfully", data) } // Created creates a standard 201 Created response func (rb *ResponseBuilder) Created(data interface{}) *UCXLResponse { return rb.Success(CodeCreated, "Resource created successfully", data) } // NoContent creates a standard 204 No Content response func (rb *ResponseBuilder) NoContent() *UCXLResponse { return rb.Success(CodeNoContent, "Request completed with no content", nil) } // BadRequest creates a standard 400 Bad Request error func (rb *ResponseBuilder) BadRequest(message string, path string) *UCXLError { return rb.Error(CodeBadRequest, message, path) } // InvalidAddress creates a UCXL-specific invalid address error func (rb *ResponseBuilder) InvalidAddress(message string, path string, addressDetails interface{}) *UCXLError { return rb.ErrorWithDetails(CodeInvalidAddress, message, path, map[string]interface{}{ "field": "address", "address": addressDetails, }) } // NotFound creates a standard 404 Not Found error func (rb *ResponseBuilder) NotFound(message string, path string) *UCXLError { return rb.Error(CodeNotFound, message, path) } // Unprocessable creates a standard 422 Unprocessable Entity error func (rb *ResponseBuilder) Unprocessable(message string, path string, validationErrors interface{}) *UCXLError { return rb.ErrorWithDetails(CodeUnprocessable, message, path, map[string]interface{}{ "validation_errors": validationErrors, }) } // InternalError creates a standard 500 Internal Server Error func (rb *ResponseBuilder) InternalError(message string, path string) *UCXLError { return rb.Error(CodeInternalError, message, path) } // MethodNotAllowed creates a standard 405 Method Not Allowed error func (rb *ResponseBuilder) MethodNotAllowed(allowedMethods []string, path string) *UCXLError { return rb.ErrorWithDetails(CodeMethodNotAllowed, "Method not allowed", path, map[string]interface{}{ "allowed_methods": allowedMethods, }) } // Collaboration-specific error builders // InvalidRole creates a UCXL-specific invalid role error func (rb *ResponseBuilder) InvalidRole(message string, path string, roleDetails interface{}) *UCXLError { return rb.ErrorWithDetails(CodeInvalidRole, message, path, map[string]interface{}{ "field": "role", "role_details": roleDetails, }) } // ExpertiseNotAvailable creates a UCXL-specific expertise not available error func (rb *ResponseBuilder) ExpertiseNotAvailable(message string, path string, expertiseDetails interface{}) *UCXLError { return rb.ErrorWithDetails(CodeExpertiseNotAvailable, message, path, map[string]interface{}{ "requested_expertise": expertiseDetails, "suggestion": "Try requesting more general expertise or check available experts", }) } // ProjectNotFound creates a UCXL-specific project not found error func (rb *ResponseBuilder) ProjectNotFound(message string, path string, projectID string) *UCXLError { return rb.ErrorWithDetails(CodeProjectNotFound, message, path, map[string]interface{}{ "field": "project_id", "project_id": projectID, "suggestion": "Verify the project ID is correct and accessible", }) } // CollaborationTimeout creates a UCXL-specific collaboration timeout error func (rb *ResponseBuilder) CollaborationTimeout(message string, path string, timeoutDetails interface{}) *UCXLError { return rb.ErrorWithDetails(CodeCollaborationTimeout, message, path, map[string]interface{}{ "timeout_reason": timeoutDetails, "suggestion": "Retry the collaboration request or check system load", }) } // CollaborationFailed creates a UCXL-specific collaboration failure error func (rb *ResponseBuilder) CollaborationFailed(message string, path string, failureDetails interface{}) *UCXLError { return rb.ErrorWithDetails(CodeCollaborationFailed, message, path, map[string]interface{}{ "failure_details": failureDetails, "suggestion": "Check system status and pubsub connectivity", }) } // Helper functions // GetHTTPStatus maps UCXL codes to HTTP status codes func GetHTTPStatus(code UCXLCode) int { switch code { case CodeSuccess: return 200 case CodeCreated: return 201 case CodeAccepted: return 202 case CodeNoContent: return 204 case CodeBadRequest, CodeInvalidAddress, CodeInvalidPayload, CodeTemporalInvalid, CodeInvalidRole: return 400 case CodeUnauthorized: return 401 case CodeForbidden: return 403 case CodeNotFound, CodeResolutionFailed, CodeExpertiseNotAvailable, CodeMentorshipUnavailable, CodeProjectNotFound: return 404 case CodeCollaborationTimeout: return 408 case CodeMethodNotAllowed: return 405 case CodeConflict: return 409 case CodeUnprocessable, CodeNavigationFailed: return 422 case CodeTooManyRequests: return 429 case CodeInternalError, CodeStorageFailed, CodeAnnounceFailed, CodeCollaborationFailed: return 500 case CodeNotImplemented: return 501 case CodeBadGateway: return 502 case CodeServiceUnavailable: return 503 case CodeGatewayTimeout: return 504 default: return 500 } } // generateRequestID creates a unique request ID func generateRequestID() string { // Simple UUID-like generator for request IDs return time.Now().Format("20060102-150405") + "-" + randomString(8) } // randomString generates a random string of the specified length func randomString(length int) string { const charset = "abcdefghijklmnopqrstuvwxyz0123456789" result := make([]byte, length) for i := range result { result[i] = charset[time.Now().UnixNano()%(int64(len(charset)))] } return string(result) }