-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add Audio & Integration system (Hybrid Fortress PR #201-C) #205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
9211aa6
feat: add website assets from PR #169
d-ulker 373da35
fix: replace HTML redirect favicon.ico with proper binary icon file
d-ulker 97a6f63
fix: update HTML to use modular CSS structure
d-ulker ad48b66
fix: address code review issues in comprehensive-demo.css
d-ulker bdd5d57
feat: add core CSS architecture files
d-ulker b228a9e
feat: add UI component CSS files
d-ulker 6095624
feat: add layout and interactive component CSS files
d-ulker 1b8466f
feat: add final component CSS files and documentation
d-ulker 3ba8ed0
feat: merge website assets with code review fixes
d-ulker ec81042
Merge branch 'main' of github.com:uelkerd/SAMO--DL
d-ulker ddf603f
Merge branch 'main' of github.com:uelkerd/SAMO--DL
d-ulker b3a46e5
Merge branch 'main' of github.com:uelkerd/SAMO--DL
d-ulker af6289c
Merge branch 'main' of github.com:uelkerd/SAMO--DL
d-ulker 35530fa
Merge branch 'main' of github.com:uelkerd/SAMO--DL
d-ulker d2f5d6e
Merge branch 'main' of github.com:uelkerd/SAMO--DL
d-ulker 7011ec9
feat: add Audio & Integration (PR #201-C) - voice recording & enhanceβ¦
d-ulker 9b2e15d
fix: address Copilot AI code suggestions
d-ulker e1e406f
fix: comprehensive test suite and code quality improvements
d-ulker 5c716b6
Fix hardcoded secrets security issue SCT-A000 in config test
d-ulker f50818b
Fix async test issue in voice-recorder.test.js
d-ulker a0121d7
Fix window.location mocking in config test for jsdom compatibility
d-ulker 6b045c1
Implement secure-by-default authentication
d-ulker 21ed2cf
Fix localhost API URL scheme to prevent certificate errors
d-ulker 83bc136
Implement comprehensive nitpick improvements from CodeRabbitAI
d-ulker 0079327
Implement secure authentication with build-time injection
d-ulker 88a88d4
Merge branch 'main' into feat/audio-integration-final
d-ulker 6d09794
fix: make build script idempotent and fix test window object pollution
d-ulker 210c7b8
feat: add comprehensive linting and formatting scripts
d-ulker 81e8df4
Merge branch 'feat/audio-integration-final' of github.com:uelkerd/SAMβ¦
d-ulker be6e04f
fix: improve client-side auth config to respect build-time injection
d-ulker 79fdbdf
feat: add API key authentication to protected endpoints
d-ulker b029e7b
feat: add mutual exclusivity validation for build flags
d-ulker 381208d
fix: make requireAuthPattern regex more flexible and robust
d-ulker ee8b2e7
fix: make processRecordedAudio properly throw errors for tests
d-ulker 9ab6120
fix: restore fortress compliance by removing non-essential files
d-ulker File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,104 +1,270 @@ | ||
| /** | ||
| * SAMO Configuration | ||
| * SAMO-DL API Configuration | ||
| * Centralized configuration for API endpoints and keys | ||
| * This file should be loaded before other JavaScript files | ||
| */ | ||
|
|
||
| window.SAMO_CONFIG = { | ||
| // API Configuration | ||
| API: { | ||
| BASE_URL: 'https://samo-unified-api-optimized-frrnetyhfa-uc.a.run.app', | ||
| ENDPOINTS: { | ||
| EMOTION: '/analyze/emotion', | ||
| SUMMARIZE: '/analyze/summarize', | ||
| JOURNAL: '/analyze/journal', | ||
| HEALTH: '/health', | ||
| READY: '/ready', | ||
| TRANSCRIBE: '/transcribe', | ||
| VOICE_JOURNAL: '/analyze/voice-journal' | ||
| }, | ||
| TIMEOUT: 45000, // 45 seconds (emotion analysis can take ~28s) | ||
| RETRY_ATTEMPTS: 3 | ||
| // API Configuration | ||
| API: { | ||
| // Base URL for the SAMO-DL API | ||
| // Replace with your actual deployment URL | ||
| BASE_URL: 'https://samo-unified-api-frrnetyhfa-uc.a.run.app', | ||
|
|
||
| // Alternative URLs for different environments | ||
| // Uncomment and modify as needed | ||
| // DEV_URL: 'http://localhost:8000', | ||
| // STAGING_URL: 'https://samo-staging-api.example.com', | ||
| // PROD_URL: 'https://samo-prod-api.example.com', | ||
|
|
||
| // API endpoints | ||
| ENDPOINTS: { | ||
| EMOTION: '/analyze/emotion', | ||
| SUMMARIZE: '/analyze/summarize', | ||
| JOURNAL: '/analyze/journal', | ||
| VOICE_JOURNAL: '/analyze/voice-journal', | ||
| HEALTH: '/health', | ||
| READY: '/ready', | ||
| TRANSCRIBE: '/transcribe', | ||
| OPENAI_PROXY: '/proxy/openai', | ||
|
|
||
| // Authentication endpoints | ||
| AUTH: { | ||
| REGISTER: '/auth/register', | ||
| LOGIN: '/auth/login', | ||
| REFRESH: '/auth/refresh', | ||
| LOGOUT: '/auth/logout', | ||
| PROFILE: '/auth/profile' | ||
| }, | ||
|
|
||
| // WebSocket endpoints | ||
| WS: { | ||
| CHAT: '/ws/chat', | ||
| TRANSCRIBE: '/ws/transcribe' | ||
| } | ||
| }, | ||
|
|
||
| // Default timeout settings (in milliseconds) | ||
| TIMEOUTS: { | ||
| DEFAULT: 10000, // 10 seconds | ||
| LONG_RUNNING: 30000, // 30 seconds | ||
| WEBSOCKET: 5000 // 5 seconds | ||
| }, | ||
|
|
||
| // Rate limiting configuration | ||
| RATE_LIMITS: { | ||
| MAX_REQUESTS_PER_MINUTE: 60, | ||
| BURST_LIMIT: 10 | ||
| }, | ||
|
|
||
| // OpenAI Configuration (for client-side text generation) | ||
| // Legacy compatibility - keep these for backward compatibility | ||
| TIMEOUT: 45000, // 45 seconds (emotion analysis can take ~28s) | ||
| RETRY_ATTEMPTS: 3, | ||
| API_KEY: null, // Set via server injection or user input // skipcq: SCT-A000 | ||
| REQUIRE_AUTH: (typeof window.PROD_REQUIRE_AUTH !== 'undefined') ? window.PROD_REQUIRE_AUTH : true // Build-time injected for production | ||
| }, | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| // OpenAI Configuration - DISABLED for security (use proxy instead) | ||
| // WARNING: Direct client-side OpenAI calls expose API keys! | ||
| // All OpenAI functionality must use the /proxy/openai endpoint | ||
| OPENAI: { | ||
| API_KEY: '', // Set via environment or server injection | ||
| API_URL: 'https://api.openai.com/v1/chat/completions', | ||
| MODEL: 'gpt-3.5-turbo', | ||
| MAX_TOKENS: 200, | ||
| TEMPERATURE: 0.7 | ||
| // API_URL: 'https://api.openai.com/v1/chat/completions', // DISABLED - Security risk | ||
| // MODEL: 'gpt-4o-mini', // DISABLED - Use proxy endpoint | ||
| // MAX_TOKENS: 4000, // DISABLED - Use proxy endpoint | ||
| // TEMPERATURE: 0.7 // DISABLED - Use proxy endpoint | ||
| }, | ||
|
|
||
| // External Services | ||
| EXTERNAL: { | ||
| HUGGINGFACE: { | ||
| API_URL: 'https://api-inference.huggingface.co/models/gpt2', | ||
| MAX_LENGTH: 150 | ||
| }, | ||
| GOOGLE_FONTS: 'https://fonts.googleapis.com', | ||
| CDN: { | ||
| BOOTSTRAP: 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css', | ||
| CHART_JS: 'https://cdn.jsdelivr.net/npm/chart.js', | ||
| FONT_AWESOME: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css' | ||
| } | ||
| // UI Configuration | ||
| UI: { | ||
| // Demo settings | ||
| DEMO: { | ||
| MAX_TEXT_LENGTH: 5000, | ||
| MAX_BATCH_SIZE: 10, | ||
| ENABLE_VOICE_RECORDING: true, | ||
| ENABLE_WEBSOCKET: true | ||
| }, | ||
|
|
||
| // Development/Production flags | ||
| ENVIRONMENT: 'production', // 'development' or 'production' | ||
| DEBUG: false, | ||
| // Monitoring refresh interval (in milliseconds) | ||
| MONITORING_REFRESH_INTERVAL: 30000, // 30 seconds | ||
|
|
||
| // Animation settings | ||
| ANIMATIONS: { | ||
| ENABLED: true, | ||
| DURATION: 300 | ||
| } | ||
| }, | ||
|
|
||
| // External Services | ||
| EXTERNAL: { | ||
| HUGGINGFACE: { | ||
| API_URL: 'https://api-inference.huggingface.co/models/gpt2', | ||
| MAX_LENGTH: 150 | ||
| }, | ||
| GOOGLE_FONTS: 'https://fonts.googleapis.com', | ||
| CDN: { | ||
| BOOTSTRAP: 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css', | ||
| CHART_JS: 'https://cdn.jsdelivr.net/npm/chart.js', | ||
| FONT_AWESOME: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css' | ||
| } | ||
| }, | ||
|
|
||
| // Development/Production flags | ||
| ENVIRONMENT: 'production', // 'development' or 'production' | ||
| DEBUG: false, | ||
|
|
||
| // Feature flags | ||
| FEATURES: { | ||
| ENABLE_OPENAI: true, // Enabled by default for core functionality | ||
| ENABLE_OPENAI: false, // DISABLED - Security risk (use /proxy/openai endpoint instead) | ||
| ENABLE_MOCK_DATA: false, // Always use real APIs | ||
| ENABLE_ANALYTICS: false | ||
| ENABLE_ANALYTICS: false, | ||
| ENABLE_AUTH: true, | ||
| ENABLE_VOICE_TRANSCRIPTION: true, | ||
| ENABLE_BATCH_PROCESSING: true, | ||
| ENABLE_TEXT_SUMMARIZATION: true, | ||
| ENABLE_REAL_TIME_MONITORING: true, | ||
| ENABLE_SECURITY_TESTING: true, | ||
| ENABLE_WEBSOCKET_CHAT: true | ||
| } | ||
| }; | ||
|
|
||
| // Environment-specific overrides - ALWAYS USE REAL APIS | ||
| // Environment-specific overrides - USE DEPLOYED API FOR DEVELOPMENT | ||
| if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') { | ||
| window.SAMO_CONFIG.ENVIRONMENT = 'development'; | ||
| window.SAMO_CONFIG.DEBUG = true; | ||
|
|
||
| // For demo testing, use production API directly (CORS is enabled on the server) | ||
| // Keep production URL and endpoints for localhost development | ||
| console.log('π§ Running in localhost development mode - using production API with CORS'); | ||
| // Use local unified API server; match page scheme to avoid cert/mixed-content issues | ||
| const scheme = window.location.protocol === 'https:' ? 'https' : 'http'; | ||
| const host = window.location.hostname === '127.0.0.1' ? '127.0.0.1' : 'localhost'; | ||
| window.SAMO_CONFIG.API.BASE_URL = `${scheme}://${host}:8002`; | ||
|
|
||
| // Only override REQUIRE_AUTH for localhost if not in production build | ||
| // This allows testing production auth behavior locally when needed | ||
| if (window.SAMO_CONFIG.API.REQUIRE_AUTH !== true) { | ||
| window.SAMO_CONFIG.API.REQUIRE_AUTH = false; // Disable auth for local dev convenience | ||
| } | ||
| // Note: ENDPOINTS remain unchanged from production config (no override needed) | ||
|
|
||
| console.log(`π§ Running in localhost development mode - using local API server at ${window.SAMO_CONFIG.API.BASE_URL}`); | ||
| console.log(`π Authentication required: ${window.SAMO_CONFIG.API.REQUIRE_AUTH}`); | ||
| } | ||
|
|
||
| // Optional: deep-freeze config in production (disabled for now due to testing complexity) | ||
| // TODO: Re-enable with more sophisticated detection to avoid interfering with tests | ||
| // if (window.SAMO_CONFIG.ENVIRONMENT === 'production' && !window.__TESTING__) { | ||
| // (function deepFreeze(obj) { | ||
| // Object.getOwnPropertyNames(obj).forEach((prop) => { | ||
| // const value = obj[prop]; | ||
| // if (value && typeof value === 'object') deepFreeze(value); | ||
| // }); | ||
| // return Object.freeze(obj); | ||
| // })(window.SAMO_CONFIG); | ||
| // } | ||
|
|
||
| // Helper function to get API URL with fallback | ||
| window.SAMO_CONFIG.getApiUrl = function(endpoint) { | ||
| const baseUrl = this.API.BASE_URL; | ||
| if (!baseUrl) { | ||
| console.warn('SAMO_CONFIG.API.BASE_URL is not set. Please configure your API endpoint.'); | ||
| return null; | ||
| } | ||
|
|
||
| if (typeof endpoint !== 'string' || endpoint.length === 0) { | ||
| console.warn('SAMO_CONFIG.getApiUrl called with invalid endpoint:', endpoint); | ||
| return null; | ||
| } | ||
|
|
||
| // Remove trailing slash from base URL and leading slash from endpoint | ||
| const cleanBaseUrl = baseUrl.replace(/\/$/, ''); | ||
| const cleanEndpoint = endpoint.startsWith('/') ? endpoint : '/' + endpoint; | ||
|
|
||
| return cleanBaseUrl + cleanEndpoint; | ||
| }; | ||
|
|
||
| // Helper function to get WebSocket URL | ||
| window.SAMO_CONFIG.getWebSocketUrl = function(endpoint) { | ||
| const baseUrl = this.API.BASE_URL; | ||
| if (!baseUrl) { | ||
| console.warn('SAMO_CONFIG.API.BASE_URL is not set. Cannot create WebSocket URL.'); | ||
| return null; | ||
| } | ||
|
|
||
| if (typeof endpoint !== 'string' || endpoint.length === 0) { | ||
| console.warn('SAMO_CONFIG.getWebSocketUrl called with invalid endpoint:', endpoint); | ||
| return null; | ||
| } | ||
|
|
||
| // Convert HTTPS to WSS | ||
| let wsUrl = baseUrl.replace(/^https:/, 'wss:').replace(/^http:/, 'ws:'); | ||
|
|
||
| // Remove trailing slash from base URL and leading slash from endpoint | ||
| wsUrl = wsUrl.replace(/\/$/, ''); | ||
| const cleanEndpoint = endpoint.startsWith('/') ? endpoint : '/' + endpoint; | ||
|
|
||
| return wsUrl + cleanEndpoint; | ||
| }; | ||
|
|
||
| // Deep merge utility function | ||
| window.SAMO_CONFIG.deepMerge = function(target, source) { | ||
| const result = { ...target }; | ||
|
|
||
| for (const key in source) { | ||
| if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
| if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) { | ||
| // Recursively merge objects | ||
| result[key] = this.deepMerge(target[key] || {}, source[key]); | ||
| } else { | ||
| // Replace primitives and arrays | ||
| result[key] = source[key]; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return result; | ||
| }; | ||
|
|
||
| // Server-side configuration injection (if available) | ||
| if (window.SAMO_SERVER_CONFIG) { | ||
| Object.assign(window.SAMO_CONFIG, window.SAMO_SERVER_CONFIG); | ||
| window.SAMO_CONFIG = window.SAMO_CONFIG.deepMerge(window.SAMO_CONFIG, window.SAMO_SERVER_CONFIG); | ||
| } | ||
|
|
||
| // Only log config in debug mode and redact sensitive fields | ||
| if (window.SAMO_CONFIG && window.SAMO_CONFIG.DEBUG) { | ||
| const sanitizedConfig = { ...window.SAMO_CONFIG }; | ||
| const sensitiveKeys = ['apiKey', 'secret', 'token', 'password', 'clientSecret']; | ||
|
|
||
| // Redact sensitive fields | ||
| sensitiveKeys.forEach(key => { | ||
| if (sanitizedConfig[key]) { | ||
| sanitizedConfig[key] = 'REDACTED'; | ||
| } | ||
| }); | ||
| // Recursive redaction utility function | ||
| window.SAMO_CONFIG.redactSensitiveValues = function(obj) { | ||
| if (obj === null || typeof obj !== 'object') { | ||
| return obj; | ||
| } | ||
|
|
||
| // Also check nested objects | ||
| if (sanitizedConfig.API) { | ||
| sensitiveKeys.forEach(key => { | ||
| if (sanitizedConfig.API[key]) { | ||
| sanitizedConfig.API[key] = 'REDACTED'; | ||
| } | ||
| }); | ||
| if (Array.isArray(obj)) { | ||
| return obj.map(item => this.redactSensitiveValues(item)); | ||
| } | ||
|
|
||
| if (sanitizedConfig.OPENAI) { | ||
| sensitiveKeys.forEach(key => { | ||
| if (sanitizedConfig.OPENAI[key]) { | ||
| sanitizedConfig.OPENAI[key] = 'REDACTED'; | ||
| } | ||
| }); | ||
| const result = {}; | ||
| const SENSITIVE_PATTERNS = [ | ||
| /^(api[-_]?key|authorization|x[-_]?api[-_]?key|bearer)$/i, // skipcq: SCT-A000 - security pattern definitions | ||
| /^(token|access[_-]?token|refresh[_-]?token)$/i, // skipcq: SCT-A000 - security pattern definitions | ||
| /^(secret|client[_-]?secret)$/i, // skipcq: SCT-A000 - security pattern definitions | ||
| /^(password|passwd)$/i, // skipcq: SCT-A000 - security pattern definitions | ||
| /^(credential|credentials|auth|authkey)$/i // skipcq: SCT-A000 - security pattern definitions | ||
| ]; | ||
|
|
||
| for (const [key, value] of Object.entries(obj)) { | ||
| const isSensitive = SENSITIVE_PATTERNS.some(re => re.test(key)); | ||
|
|
||
| if (isSensitive) { | ||
| result[key] = 'REDACTED'; | ||
| } else if (value && typeof value === 'object') { | ||
| result[key] = this.redactSensitiveValues(value); | ||
| } else { | ||
| result[key] = value; | ||
| } | ||
| } | ||
|
|
||
| return result; | ||
| }; | ||
|
|
||
| // Only log config in debug mode and redact sensitive fields | ||
| if (window.SAMO_CONFIG && window.SAMO_CONFIG.DEBUG) { | ||
| const sanitizedConfig = window.SAMO_CONFIG.redactSensitiveValues(window.SAMO_CONFIG); | ||
| console.log('π§ SAMO Configuration loaded (debug mode):', sanitizedConfig); | ||
| } | ||
|
|
||
| console.log('SAMO-DL configuration loaded successfully'); | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π§© Analysis chain
Production auth toggle needs enforcement.
API.API_KEYandAPI.REQUIRE_AUTH: falseare risky defaults. Ensure production builds or server injection setREQUIRE_AUTH: trueand that the backend enforces auth regardless of client config.Run to locate usages and confirm server overrides in prod:
π Script executed:
Length of output: 13940
π Script executed:
Length of output: 9827
Require client auth in production & enforce server-side API key validation.
REQUIRE_AUTHtotrueinwebsite/js/config.jsduring production builds (e.g., via build-time environment injection).require_api_keyindeployment/cloud-run/secure_api_server.py.π€ Prompt for AI Agents