// Package constants provides global constants used across the application. package constants import ( "fmt" "time" ) // ============================================================================== // HTTP CONTENT TYPES // ============================================================================== const ( ContentTypeJSON = "application/json" ContentTypeHTML = "text/html; charset=utf-8" ContentTypeHTMLFragment = "text/html" // For HTMX fragments ContentTypePlainText = "text/plain; charset=utf-8" ContentTypePlainSimple = "text/plain" // For Accept header matching ContentTypePDF = "application/pdf" ContentTypeFormURLEnc = "application/x-www-form-urlencoded" ) // ============================================================================== // HTTP HEADERS // ============================================================================== const ( HeaderContentType = "Content-Type" HeaderContentDisposition = "Content-Disposition" HeaderContentLength = "Content-Length" HeaderCacheControl = "Cache-Control" HeaderXContentTypeOpts = "X-Content-Type-Options" // HTMX headers HeaderHXRequest = "HX-Request" HeaderHXTrigger = "HX-Trigger" ) // ============================================================================== // CACHE CONTROL VALUES // ============================================================================== const ( // CachePublic1Hour is for relatively static content (1 hour) CachePublic1Hour = "public, max-age=3600" // CachePublic1Day is for static files in production (1 day) CachePublic1Day = "public, max-age=86400" // CachePublic5Min is for dynamic content that can be cached briefly CachePublic5Min = "public, max-age=300, must-revalidate" // CacheNoStore prevents caching entirely CacheNoStore = "no-cache, no-store, must-revalidate" // CacheStatic is for truly static assets (1 year) CacheStatic = "public, max-age=31536000, immutable" ) // Cache durations in seconds const ( CacheDuration1Hour = 3600 CacheDuration5Min = 300 CacheDuration1Year = 31536000 CacheDuration1Day = 86400 CacheDuration1Week = 604800 CacheDuration1Month = 2592000 ) // ============================================================================== // LANGUAGE CODES // ============================================================================== const ( LangEnglish = "en" LangSpanish = "es" LangDefault = LangEnglish ) // SupportedLanguages is the set of valid language codes var SupportedLanguages = map[string]bool{ LangEnglish: true, LangSpanish: true, } // AllLangs returns all supported language codes func AllLangs() []string { return []string{LangEnglish, LangSpanish} } // IsValidLang checks if a language code is supported func IsValidLang(lang string) bool { return SupportedLanguages[lang] } // ValidateLang returns an error if the language code is unsupported. // It provides helpful error messages showing all supported languages. func ValidateLang(lang string) error { if !IsValidLang(lang) { return fmt.Errorf("unsupported language: %s (supported: %v)", lang, AllLangs()) } return nil } // ============================================================================== // CV PREFERENCES // ============================================================================== const ( CVLengthShort = "short" CVLengthLong = "long" CVIconsShow = "show" CVIconsHide = "hide" CVThemeDefault = "default" CVThemeClean = "clean" ) // ============================================================================== // COOKIE SETTINGS // ============================================================================== const ( CookieMaxAge = 365 * 24 * 60 * 60 // 1 year in seconds CookiePath = "/" ) // ============================================================================== // RATE LIMITING // ============================================================================== const ( RateLimitPDFRequests = 3 RateLimitPDFWindow = 1 * time.Minute RateLimitGeneralRequests = 100 RateLimitGeneralWindow = 1 * time.Minute RateLimitContactRequests = 5 RateLimitContactWindow = 1 * time.Hour ) // ============================================================================== // TIMEOUTS // ============================================================================== const ( TimeoutPDFGeneration = 30 * time.Second TimeoutHTTPRequest = 10 * time.Second TimeoutIdleConnection = 120 * time.Second TimeoutGracefulShutdown = 30 * time.Second FormMinSubmitTime = 2 * time.Second // Min time form must be displayed (bot protection) ) // ============================================================================== // DIRECTORIES // ============================================================================== const ( DirData = "data" DirTemplates = "templates" DirPartials = "templates/partials" DirStatic = "static" ) // ============================================================================== // PDF DIMENSIONS // ============================================================================== const ( A4WidthInches = 8.27 A4HeightInches = 11.69 ) // ============================================================================== // CSRF PROTECTION // ============================================================================== const ( CSRFTokenLength = 32 CSRFTokenTTL = 24 * time.Hour CSRFCookieName = "csrf_token" CSRFFormField = "csrf_token" CSRFCleanupPeriod = 1 * time.Hour ) // ============================================================================== // CLEANUP INTERVALS // ============================================================================== const ( RateLimitCleanupPeriod = 10 * time.Minute // For contact rate limiter RateLimitGeneralCleanupPeriod = 1 * time.Minute // For general rate limiter ) // ============================================================================== // SECURITY // ============================================================================== const ( // HSTS max-age (1 year) HSTSMaxAge = "max-age=31536000; includeSubDomains; preload" // Content type options NoSniff = "nosniff" // Frame options FrameOptionsSameOrigin = "SAMEORIGIN" // XSS Protection XSSProtection = "1; mode=block" // Referrer Policy ReferrerPolicy = "strict-origin-when-cross-origin" ) // ============================================================================== // SECURITY HEADERS // ============================================================================== const ( HeaderXFrameOptions = "X-Frame-Options" HeaderXXSSProtection = "X-XSS-Protection" HeaderReferrerPolicy = "Referrer-Policy" HeaderPermissionsPolicy = "Permissions-Policy" HeaderCSP = "Content-Security-Policy" HeaderHSTS = "Strict-Transport-Security" HeaderRetryAfter = "Retry-After" HeaderXForwardedFor = "X-Forwarded-For" HeaderXRealIP = "X-Real-IP" HeaderXCSRFToken = "X-CSRF-Token" ) // ============================================================================== // REQUEST HEADERS // ============================================================================== const ( HeaderUserAgent = "User-Agent" HeaderAccept = "Accept" HeaderOrigin = "Origin" HeaderReferer = "Referer" HeaderXRequestedWith = "X-Requested-With" HeaderXBrowserReq = "X-Browser-Request" ) // Header values const ( HeaderValueXMLHTTPRequest = "XMLHttpRequest" ) // ============================================================================== // ENVIRONMENT // ============================================================================== const ( EnvProduction = "production" EnvDevelopment = "development" EnvVarGOEnv = "GO_ENV" EnvVarPort = "PORT" DefaultPort = "1999" ) // ============================================================================== // COOKIE NAMES // ============================================================================== const ( CookieCVLength = "cv-length" CookieCVIcons = "cv-icons" CookieCVLanguage = "cv-language" CookieCVTheme = "cv-theme" CookieColorTheme = "color-theme" ) // ============================================================================== // COLOR THEMES // ============================================================================== const ( ColorThemeLight = "light" ColorThemeDark = "dark" ) // ============================================================================== // ROUTES // ============================================================================== const ( RouteHome = "/" RouteHealth = "/health" RouteExportPDF = "/export/pdf" RouteAPIContact = "/api/contact" RouteAPICmdK = "/api/cmd-k" )