- Complete UCXL protocol implementation with DHT storage layer - BZZZ Gateway for peer-to-peer networking and content distribution - Temporal navigation engine with version control and timeline browsing - Standardized UCXL error/response codes for Rust, Go, and Python - React-based UI with multi-tab interface and professional styling - libp2p integration for distributed hash table operations - Self-healing network mechanisms and peer management - Comprehensive IPC commands for Tauri desktop integration Major Components: - ucxl-core: Core UCXL protocol and DHT implementation - BZZZ Gateway: Local subnet peer discovery and content replication - Temporal Engine: Version control and state reconstruction - Cross-language standards: Unified error handling across implementations - Modern UI: Professional React interface with DHT and network monitoring Standards Compliance: - UCXL-ERROR-CODES.md and UCXL-RESPONSE-CODES.md v1.0 - Machine-readable error codes with structured payloads - Client guidance for retry logic and error handling - Cross-language compatibility with identical APIs 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
422 lines
11 KiB
Go
422 lines
11 KiB
Go
// Package ucxl_codes provides standardized UCXL error and response codes
|
|
// for consistent cross-service communication and client handling.
|
|
//
|
|
// Based on UCXL-ERROR-CODES.md and UCXL-RESPONSE-CODES.md v1.0
|
|
package ucxl_codes
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// UCXLErrorCode represents standard UCXL error codes following format: UCXL-<HTTP-class>-<SHORT_NAME>
|
|
type UCXLErrorCode string
|
|
|
|
const (
|
|
// 400 - Client Errors
|
|
ErrorInvalidAddress UCXLErrorCode = "UCXL-400-INVALID_ADDRESS"
|
|
ErrorMissingField UCXLErrorCode = "UCXL-400-MISSING_FIELD"
|
|
ErrorInvalidFormat UCXLErrorCode = "UCXL-400-INVALID_FORMAT"
|
|
|
|
// 401 - Authentication
|
|
ErrorUnauthorized UCXLErrorCode = "UCXL-401-UNAUTHORIZED"
|
|
|
|
// 403 - Authorization
|
|
ErrorForbidden UCXLErrorCode = "UCXL-403-FORBIDDEN"
|
|
|
|
// 404 - Not Found
|
|
ErrorNotFound UCXLErrorCode = "UCXL-404-NOT_FOUND"
|
|
|
|
// 409 - Conflict
|
|
ErrorConflict UCXLErrorCode = "UCXL-409-CONFLICT"
|
|
|
|
// 422 - Unprocessable Entity
|
|
ErrorUnprocessableEntity UCXLErrorCode = "UCXL-422-UNPROCESSABLE_ENTITY"
|
|
|
|
// 429 - Rate Limiting
|
|
ErrorRateLimit UCXLErrorCode = "UCXL-429-RATE_LIMIT"
|
|
|
|
// 500 - Server Errors
|
|
ErrorInternalError UCXLErrorCode = "UCXL-500-INTERNAL_ERROR"
|
|
|
|
// 503 - Service Unavailable
|
|
ErrorServiceUnavailable UCXLErrorCode = "UCXL-503-SERVICE_UNAVAILABLE"
|
|
|
|
// 504 - Gateway Timeout
|
|
ErrorGatewayTimeout UCXLErrorCode = "UCXL-504-GATEWAY_TIMEOUT"
|
|
)
|
|
|
|
// UCXLResponseCode represents standard UCXL response codes following format: UCXL-<HTTP-class>-<SHORT_NAME>
|
|
type UCXLResponseCode string
|
|
|
|
const (
|
|
// 200 - Success
|
|
ResponseOK UCXLResponseCode = "UCXL-200-OK"
|
|
|
|
// 201 - Created
|
|
ResponseCreated UCXLResponseCode = "UCXL-201-CREATED"
|
|
|
|
// 202 - Accepted (Async)
|
|
ResponseAccepted UCXLResponseCode = "UCXL-202-ACCEPTED"
|
|
|
|
// 204 - No Content
|
|
ResponseNoContent UCXLResponseCode = "UCXL-204-NO_CONTENT"
|
|
|
|
// 206 - Partial Content
|
|
ResponsePartialContent UCXLResponseCode = "UCXL-206-PARTIAL_CONTENT"
|
|
|
|
// 304 - Not Modified (Caching)
|
|
ResponseNotModified UCXLResponseCode = "UCXL-304-NOT_MODIFIED"
|
|
)
|
|
|
|
// HTTPStatus returns the HTTP status code for the error code
|
|
func (e UCXLErrorCode) HTTPStatus() int {
|
|
switch e {
|
|
case ErrorInvalidAddress, ErrorMissingField, ErrorInvalidFormat:
|
|
return 400
|
|
case ErrorUnauthorized:
|
|
return 401
|
|
case ErrorForbidden:
|
|
return 403
|
|
case ErrorNotFound:
|
|
return 404
|
|
case ErrorConflict:
|
|
return 409
|
|
case ErrorUnprocessableEntity:
|
|
return 422
|
|
case ErrorRateLimit:
|
|
return 429
|
|
case ErrorInternalError:
|
|
return 500
|
|
case ErrorServiceUnavailable:
|
|
return 503
|
|
case ErrorGatewayTimeout:
|
|
return 504
|
|
default:
|
|
return 500
|
|
}
|
|
}
|
|
|
|
// DefaultMessage returns the default error message for this code
|
|
func (e UCXLErrorCode) DefaultMessage() string {
|
|
switch e {
|
|
case ErrorInvalidAddress:
|
|
return "Invalid UCXL address format"
|
|
case ErrorMissingField:
|
|
return "Required field is missing"
|
|
case ErrorInvalidFormat:
|
|
return "Input does not match the expected format"
|
|
case ErrorUnauthorized:
|
|
return "Authentication credentials missing or invalid"
|
|
case ErrorForbidden:
|
|
return "Insufficient permissions for the action"
|
|
case ErrorNotFound:
|
|
return "Requested resource not found"
|
|
case ErrorConflict:
|
|
return "Conflict with current state"
|
|
case ErrorUnprocessableEntity:
|
|
return "Semantic validation failed"
|
|
case ErrorRateLimit:
|
|
return "Too many requests; rate limiting in effect"
|
|
case ErrorInternalError:
|
|
return "Internal server error"
|
|
case ErrorServiceUnavailable:
|
|
return "Service is currently unavailable"
|
|
case ErrorGatewayTimeout:
|
|
return "Downstream gateway timed out"
|
|
default:
|
|
return "Unknown error"
|
|
}
|
|
}
|
|
|
|
// IsClientError checks if this is a client error (4xx)
|
|
func (e UCXLErrorCode) IsClientError() bool {
|
|
status := e.HTTPStatus()
|
|
return status >= 400 && status < 500
|
|
}
|
|
|
|
// IsServerError checks if this is a server error (5xx)
|
|
func (e UCXLErrorCode) IsServerError() bool {
|
|
status := e.HTTPStatus()
|
|
return status >= 500 && status < 600
|
|
}
|
|
|
|
// ShouldRetry checks if this error should trigger a retry
|
|
func (e UCXLErrorCode) ShouldRetry() bool {
|
|
switch e {
|
|
case ErrorRateLimit, ErrorInternalError, ErrorServiceUnavailable, ErrorGatewayTimeout:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// HTTPStatus returns the HTTP status code for the response code
|
|
func (r UCXLResponseCode) HTTPStatus() int {
|
|
switch r {
|
|
case ResponseOK:
|
|
return 200
|
|
case ResponseCreated:
|
|
return 201
|
|
case ResponseAccepted:
|
|
return 202
|
|
case ResponseNoContent:
|
|
return 204
|
|
case ResponsePartialContent:
|
|
return 206
|
|
case ResponseNotModified:
|
|
return 304
|
|
default:
|
|
return 200
|
|
}
|
|
}
|
|
|
|
// DefaultMessage returns the default success message for this code
|
|
func (r UCXLResponseCode) DefaultMessage() string {
|
|
switch r {
|
|
case ResponseOK:
|
|
return "Request completed successfully"
|
|
case ResponseCreated:
|
|
return "Resource created successfully"
|
|
case ResponseAccepted:
|
|
return "Request accepted for processing"
|
|
case ResponseNoContent:
|
|
return "Request completed with no content to return"
|
|
case ResponsePartialContent:
|
|
return "Partial results returned"
|
|
case ResponseNotModified:
|
|
return "Resource not modified since last fetch"
|
|
default:
|
|
return "Success"
|
|
}
|
|
}
|
|
|
|
// IsAsync checks if this indicates an asynchronous operation
|
|
func (r UCXLResponseCode) IsAsync() bool {
|
|
return r == ResponseAccepted
|
|
}
|
|
|
|
// IsPartial checks if this indicates partial/incomplete results
|
|
func (r UCXLResponseCode) IsPartial() bool {
|
|
return r == ResponsePartialContent || r == ResponseAccepted
|
|
}
|
|
|
|
// UCXLErrorResponse represents the standardized UCXL error response payload
|
|
type UCXLErrorResponse struct {
|
|
Error UCXLError `json:"error"`
|
|
}
|
|
|
|
// UCXLError contains the error details
|
|
type UCXLError struct {
|
|
Code UCXLErrorCode `json:"code"`
|
|
Message string `json:"message"`
|
|
Details map[string]interface{} `json:"details,omitempty"`
|
|
Source string `json:"source"`
|
|
Path string `json:"path"`
|
|
RequestID string `json:"request_id"`
|
|
Timestamp time.Time `json:"timestamp"`
|
|
Cause string `json:"cause,omitempty"`
|
|
}
|
|
|
|
// UCXLSuccessResponse represents the standardized UCXL success response payload
|
|
type UCXLSuccessResponse struct {
|
|
Response UCXLResponse `json:"response"`
|
|
}
|
|
|
|
// UCXLResponse contains the response details
|
|
type UCXLResponse struct {
|
|
Code UCXLResponseCode `json:"code"`
|
|
Message string `json:"message"`
|
|
Data interface{} `json:"data,omitempty"`
|
|
Details map[string]interface{} `json:"details,omitempty"`
|
|
RequestID string `json:"request_id"`
|
|
Timestamp time.Time `json:"timestamp"`
|
|
}
|
|
|
|
// ErrorBuilder helps build standardized error responses
|
|
type ErrorBuilder struct {
|
|
code UCXLErrorCode
|
|
message string
|
|
details map[string]interface{}
|
|
source string
|
|
path string
|
|
requestID string
|
|
cause string
|
|
}
|
|
|
|
// NewErrorBuilder creates a new error builder with the specified code
|
|
func NewErrorBuilder(code UCXLErrorCode) *ErrorBuilder {
|
|
return &ErrorBuilder{
|
|
code: code,
|
|
details: make(map[string]interface{}),
|
|
source: "ucxl-api/v1",
|
|
path: "/",
|
|
requestID: fmt.Sprintf("req-%s", uuid.New().String()[:8]),
|
|
}
|
|
}
|
|
|
|
// Message sets a custom error message
|
|
func (b *ErrorBuilder) Message(message string) *ErrorBuilder {
|
|
b.message = message
|
|
return b
|
|
}
|
|
|
|
// Field adds details about the field that failed
|
|
func (b *ErrorBuilder) Field(field string, provided interface{}) *ErrorBuilder {
|
|
b.details["field"] = field
|
|
b.details["provided"] = provided
|
|
return b
|
|
}
|
|
|
|
// ExpectedFormat adds expected format information
|
|
func (b *ErrorBuilder) ExpectedFormat(format string) *ErrorBuilder {
|
|
b.details["expected_format"] = format
|
|
return b
|
|
}
|
|
|
|
// Detail adds a detail field
|
|
func (b *ErrorBuilder) Detail(key string, value interface{}) *ErrorBuilder {
|
|
b.details[key] = value
|
|
return b
|
|
}
|
|
|
|
// Source sets the source service
|
|
func (b *ErrorBuilder) Source(source string) *ErrorBuilder {
|
|
b.source = source
|
|
return b
|
|
}
|
|
|
|
// Path sets the request path
|
|
func (b *ErrorBuilder) Path(path string) *ErrorBuilder {
|
|
b.path = path
|
|
return b
|
|
}
|
|
|
|
// RequestID sets the request ID
|
|
func (b *ErrorBuilder) RequestID(requestID string) *ErrorBuilder {
|
|
b.requestID = requestID
|
|
return b
|
|
}
|
|
|
|
// Cause sets the error cause
|
|
func (b *ErrorBuilder) Cause(cause string) *ErrorBuilder {
|
|
b.cause = cause
|
|
return b
|
|
}
|
|
|
|
// Build creates the error response
|
|
func (b *ErrorBuilder) Build() *UCXLErrorResponse {
|
|
message := b.message
|
|
if message == "" {
|
|
message = b.code.DefaultMessage()
|
|
}
|
|
|
|
var details map[string]interface{}
|
|
if len(b.details) > 0 {
|
|
details = b.details
|
|
}
|
|
|
|
return &UCXLErrorResponse{
|
|
Error: UCXLError{
|
|
Code: b.code,
|
|
Message: message,
|
|
Details: details,
|
|
Source: b.source,
|
|
Path: b.path,
|
|
RequestID: b.requestID,
|
|
Timestamp: time.Now().UTC(),
|
|
Cause: b.cause,
|
|
},
|
|
}
|
|
}
|
|
|
|
// ResponseBuilder helps build standardized success responses
|
|
type ResponseBuilder struct {
|
|
code UCXLResponseCode
|
|
message string
|
|
data interface{}
|
|
details map[string]interface{}
|
|
requestID string
|
|
}
|
|
|
|
// NewResponseBuilder creates a new response builder with the specified code
|
|
func NewResponseBuilder(code UCXLResponseCode) *ResponseBuilder {
|
|
return &ResponseBuilder{
|
|
code: code,
|
|
details: make(map[string]interface{}),
|
|
requestID: fmt.Sprintf("req-%s", uuid.New().String()[:8]),
|
|
}
|
|
}
|
|
|
|
// Message sets a custom success message
|
|
func (b *ResponseBuilder) Message(message string) *ResponseBuilder {
|
|
b.message = message
|
|
return b
|
|
}
|
|
|
|
// Data sets the response data
|
|
func (b *ResponseBuilder) Data(data interface{}) *ResponseBuilder {
|
|
b.data = data
|
|
return b
|
|
}
|
|
|
|
// Detail adds a detail field
|
|
func (b *ResponseBuilder) Detail(key string, value interface{}) *ResponseBuilder {
|
|
b.details[key] = value
|
|
return b
|
|
}
|
|
|
|
// RequestID sets the request ID
|
|
func (b *ResponseBuilder) RequestID(requestID string) *ResponseBuilder {
|
|
b.requestID = requestID
|
|
return b
|
|
}
|
|
|
|
// Build creates the success response
|
|
func (b *ResponseBuilder) Build() *UCXLSuccessResponse {
|
|
message := b.message
|
|
if message == "" {
|
|
message = b.code.DefaultMessage()
|
|
}
|
|
|
|
var details map[string]interface{}
|
|
if len(b.details) > 0 {
|
|
details = b.details
|
|
}
|
|
|
|
return &UCXLSuccessResponse{
|
|
Response: UCXLResponse{
|
|
Code: b.code,
|
|
Message: message,
|
|
Data: b.data,
|
|
Details: details,
|
|
RequestID: b.requestID,
|
|
Timestamp: time.Now().UTC(),
|
|
},
|
|
}
|
|
}
|
|
|
|
// JSON marshaling helpers
|
|
|
|
// ToJSON converts the error response to JSON
|
|
func (e *UCXLErrorResponse) ToJSON() ([]byte, error) {
|
|
return json.Marshal(e)
|
|
}
|
|
|
|
// FromJSON creates an error response from JSON
|
|
func (e *UCXLErrorResponse) FromJSON(data []byte) error {
|
|
return json.Unmarshal(data, e)
|
|
}
|
|
|
|
// ToJSON converts the success response to JSON
|
|
func (r *UCXLSuccessResponse) ToJSON() ([]byte, error) {
|
|
return json.Marshal(r)
|
|
}
|
|
|
|
// FromJSON creates a success response from JSON
|
|
func (r *UCXLSuccessResponse) FromJSON(data []byte) error {
|
|
return json.Unmarshal(data, r)
|
|
} |