Conversation
pedramamini
commented
Nov 27, 2025
- MAESTRO: Add /web/ route namespace for web interface*
- MAESTRO: Add WebSocket upgrade handler for web clients at /ws/web
- MAESTRO: Add optional PIN/token authentication for web interface
- MAESTRO: Broadcast session state changes to connected web clients
- MAESTRO: Send current theme on initial WebSocket connection
- MAESTRO: Broadcast theme changes to connected web clients
- MAESTRO: Add rate limiting for web interface endpoints
- MAESTRO: Implement /api/sessions endpoint to return actual session data
- MAESTRO: Implement /api/session/:id endpoint for detailed session data
- MAESTRO: Implement /api/session/:id/send POST endpoint for sending commands
- MAESTRO: Implement /api/session/:id/interrupt POST endpoint for session interruption
- MAESTRO: Implement /api/theme GET endpoint for current theme configuration
- MAESTRO: Extract theme types to shared location for web interface
- MAESTRO: Create ThemeProvider component for web interface
- MAESTRO: Create CSS custom properties generator for web interface theme system
- MAESTRO: Create reusable Button component for web interface
- MAESTRO: Create reusable Input and TextArea components for web interface
- MAESTRO: Create reusable Badge component for web interface status indicators
- MAESTRO: Create reusable Card component for web interface
- MAESTRO: Create useWebSocket hook for web interface connection management
- MAESTRO: Create useSessions hook for real-time session state management
- MAESTRO: Create separate Vite config for web interface build
- MAESTRO: Add npm run build:web script for web interface bundling
- MAESTRO: Integrate web build into main build process
- MAESTRO: Serve built web assets from Fastify static handler
- MAESTRO: Configure code splitting for mobile vs desktop web bundles
- MAESTRO: Create mobile entry point with utilities and configuration
- MAESTRO: Add mobile app shell with dynamic connection status header
- MAESTRO: Add comprehensive responsive viewport meta tags for mobile browsers
- MAESTRO: Add PWA manifest for Add to Home Screen support
- MAESTRO: Add service worker for PWA offline capability
- MAESTRO: Add pull-to-refresh functionality for mobile session list
- MAESTRO: Add horizontal scrollable session pill bar for mobile web
- MAESTRO: Add long-press session info popover for mobile session pills
- MAESTRO: Add collapsible group headers to mobile session pill bar
- MAESTRO: Add All Sessions view with larger cards for mobile web
- MAESTRO: Add sticky bottom CommandInputBar for mobile web interface
- MAESTRO: Add large touch-friendly textarea input for mobile command bar
- MAESTRO: Add mode toggle button (AI/Terminal) to mobile command input bar
- MAESTRO: Add interrupt button (red X) to mobile command input bar
- MAESTRO: Add auto-expanding textarea for mobile command input (up to 4 lines)
- MAESTRO: Add command history drawer with swipe-up gesture for mobile web
- MAESTRO: Add recent command chips for quick-tap reuse in mobile web
- MAESTRO: Add slash command autocomplete popup for mobile web
- MAESTRO: Add haptic feedback for mobile web command input
- MAESTRO: Add session status banner for mobile web interface
- MAESTRO: Add cost tracker to mobile web session status banner
- MAESTRO: Add context window usage bar to mobile web session status banner
- MAESTRO: Add collapsible last response preview to mobile web session status banner
- MAESTRO: Add tap-to-expand full-screen response viewer for mobile web
- MAESTRO: Add share button to copy last response to clipboard in mobile web
- MAESTRO: Add syntax highlighting for code blocks in mobile web response viewer
- MAESTRO: Add copy button for each code block in mobile web response viewer
- MAESTRO: Add swipe left/right navigation between responses in mobile web response viewer
- MAESTRO: Add pinch-to-zoom for code readability in mobile web response viewer
- MAESTRO: Add notification permission request on first visit for mobile web
- MAESTRO: Add push notifications for AI response completion in mobile web
- MAESTRO: Add unread response badge count for mobile web PWA
- MAESTRO: Add voice input button for speech-to-text in mobile web
- MAESTRO: Add quick actions menu for mobile web send button
- MAESTRO: Add swipe gestures for common actions in mobile web
- MAESTRO: Add offline queue for commands typed while disconnected
- MAESTRO: Add connection status indicator with retry button for mobile web
- MAESTRO: Add device color scheme preference support for mobile web
Created dedicated web interface route namespace in WebServer class: - /web - Root endpoint returning available interfaces info - /web/desktop - Desktop web interface entry point (placeholder) - /web/desktop/* - Wildcard for client-side routing - /web/mobile - Mobile web interface entry point (placeholder) - /web/mobile/* - Wildcard for client-side routing - /web/api - Web API namespace root with endpoint discovery This establishes the foundation for the new web interface that will provide both desktop (collaborative) and mobile (remote control) access to Maestro sessions.
- Added new WebSocket endpoint at /ws/web for web interface clients - Implemented client connection tracking with unique client IDs - Added connection/disconnection event handling with logging - Added message handling for ping/pong, subscribe, and echo - Added broadcastToWebClients() method for real-time updates - Added getWebClientCount() method for monitoring connected clients - Imported WebSocket from 'ws' for readyState checks - Added WebClient and WebClientMessage type definitions
- Add WebAuthConfig type and auth state management in WebServer
- Generate 6-character alphanumeric PINs (excludes confusing chars)
- Support authentication via:
- WebSocket query string (?token=XXX)
- WebSocket auth message { type: 'auth', token: '<token>' }
- REST API headers (Authorization: Bearer or X-Auth-Token)
- Add IPC handlers for auth management:
- webserver:getAuthConfig
- webserver:setAuthEnabled (auto-generates token if needed)
- webserver:generateNewToken
- webserver:setAuthToken
- webserver:getConnectedClients
- Persist auth settings in electron-store
- Add /web/api/auth/status and /web/api/auth/verify endpoints
Added real-time session state broadcasting to the web interface:
- Added broadcastSessionStateChange() method to broadcast when session state,
name, or input mode changes
- Added broadcastSessionAdded() and broadcastSessionRemoved() methods for
tracking session lifecycle
- Added broadcastSessionsList() method for bulk session sync
- Modified sessions:setAll IPC handler to detect session changes and broadcast
them to all authenticated web clients
- Added setGetSessionsCallback() to allow web server to fetch current sessions
- Send initial sessions_list to newly connected/authenticated web clients
- Only broadcast to authenticated clients for security
WebSocket message types added:
- session_state_change: { type, sessionId, state, name?, toolType?, inputMode?, cwd?, timestamp }
- session_added: { type, session, timestamp }
- session_removed: { type, sessionId, timestamp }
- sessions_list: { type, sessions, timestamp }
- Add WebTheme type and GetThemeCallback to web-server.ts - Add setGetThemeCallback method to WebServer class - Send theme after sessions list on initial connection - Send theme after auth success for authenticated clients - Create src/main/themes.ts with all theme definitions for main process - Wire up theme callback in index.ts using getThemeById helper
Added broadcastThemeChange method to WebServer class and integrated it with the settings:set IPC handler to automatically notify all connected web clients when the user switches themes in the desktop app.
- Install @fastify/rate-limit package - Configure rate limiting with sensible defaults: - 100 requests/minute for GET endpoints - 30 requests/minute for POST endpoints (more restrictive) - Add RateLimitConfig interface for configuration - Apply rate limiting to all /web/* routes - Add /web/api/rate-limit endpoint to check current limits - Skip rate limiting for /health endpoint - Custom error response with retry-after information - Support for X-Forwarded-For header for proxied requests
Updated the /api/sessions endpoint to use the getSessionsCallback to return real session data instead of an empty array placeholder. Added authentication and rate limiting to the endpoint.
- Add SessionDetail interface with extended session fields (aiLogs, shellLogs, usageStats, claudeSessionId, isGitRepo) - Add GetSessionDetailCallback type and setGetSessionDetailCallback method - Implement /api/session/:id endpoint with authentication and rate limiting - Returns 404 for non-existent sessions, 503 if callback not configured - Wire up callback in index.ts to fetch session data from sessions store - Update header comments to reflect current implementation status
…mmands Add POST endpoint to send commands to active sessions via the web API: - Add WriteToSessionCallback type for session input - Implement /api/session/:id/send endpoint with rate limiting (POST limits) - Validate command presence and type before processing - Check session exists before attempting to write - Wire up callback in index.ts using processManager.write()
…on interruption Add REST API endpoint to send SIGINT/Ctrl+C signal to sessions via the web interface. This allows mobile and desktop web clients to gracefully interrupt running AI agents or terminal processes. - Add InterruptSessionCallback type for session interrupt operations - Add setInterruptSessionCallback method to WebServer class - Create /api/session/:id/interrupt POST endpoint with authentication and rate limiting - Wire up callback in main process to use ProcessManager.interrupt()
…ation Added a new REST API endpoint at /api/theme that returns the currently configured theme. The endpoint: - Is protected by token-based authentication (if enabled) - Is rate limited using GET rate limit config - Returns the theme object with all color values - Returns 503 if theme service not configured - Returns 404 if no theme is currently set
- Create src/shared/theme-types.ts with Theme, ThemeId, ThemeMode, ThemeColors types - Add isValidThemeId type guard utility function - Update renderer types to re-export from shared location - Update main process themes.ts to use shared types - Update web-server.ts to import Theme from shared instead of defining WebTheme - This enables the web interface build to access theme types without duplicating code
- Add src/web/components/ThemeProvider.tsx with React context for theming - Provide useTheme and useThemeColors hooks for child components - Include default theme (Dracula) for initial render before WebSocket connection - Update tsconfig.json to include src/web and src/shared directories
…me system Add utility module that converts theme colors to CSS custom properties: - generateCSSProperties(): Creates property map from theme - generateCSSString(): Outputs CSS with :root selector - injectCSSProperties(): Adds/updates style element in document head - removeCSSProperties(): Cleans up injected styles - setElementCSSProperties(): Applies to specific elements - cssVar(): Helper for inline style usage CSS variables use --maestro-* prefix with kebab-case naming (e.g., theme.colors.bgMain -> --maestro-bg-main). ThemeProvider now automatically injects CSS properties when theme changes, enabling CSS-based theming alongside React context.
Add Button and IconButton components with theme support: - Multiple variants: primary, secondary, ghost, danger, success - Three sizes: sm, md, lg - Loading state with spinner animation - Support for left/right icons - Full width option - IconButton variant for icon-only buttons - Uses theme colors via useTheme hook
Add Input, TextArea, and InputGroup components following the same patterns as the Button component with theme support via useTheme() hook. Features: - Three variants: default, filled, ghost - Three sizes: sm, md, lg - Error state support with visual feedback - Icon support (left/right) for Input component - Auto-resize capability for TextArea - InputGroup wrapper for label, helper text, and error display
…icators Add Badge component with multiple variants for session states: - success (green): Ready/idle sessions - warning (yellow): Agent thinking/busy - error (red): No connection/error - connecting (orange with pulse): Connecting state - info (accent color): Informational badges - default: Neutral styling Includes three badge styles (solid, outline, subtle, dot) and convenience components StatusDot and ModeBadge for common use cases.
Add Card component with support for multiple variants (default, elevated, outlined, filled, ghost), padding options, and interactive states. Includes: - CardHeader subcomponent for consistent headers with title/subtitle/actions - CardBody subcomponent for main content with padding control - CardFooter subcomponent for footer actions with optional border - SessionCard convenience component for session list items Supports interactive states (clickable, selected, disabled) with keyboard navigation and accessibility attributes.
…ment Add a comprehensive useWebSocket hook that handles: - WebSocket connection lifecycle (connect, disconnect, reconnect) - Authentication flow (token-based auth via query param or message) - Real-time message handling for sessions, themes, and state changes - Automatic reconnection with configurable attempts and delays - Heartbeat/ping functionality for connection health - Full TypeScript support with typed message interfaces
Implements a useSessions hook that wraps useWebSocket to provide: - Real-time session list management with add/remove/update handlers - Active session tracking and selection - Session interaction methods (sendCommand, interrupt, switchMode) - Sessions grouped by tool type - Client-side state tracking (isSending, lastError) preserved across updates - Auto-connect option and refresh capability
- Add vite.config.web.mts with dedicated web interface configuration - Configure build output to dist/web/ directory - Set up code splitting with React in separate chunk - Enable source maps for development debugging - Add dev server proxy for API and WebSocket connections - Create index.html entry point with mobile-optimized meta tags - Create main.tsx with device detection for mobile/desktop routing - Add index.css with Tailwind, CSS custom properties, and animations - Create placeholder mobile/desktop App components for Phase 1/2 - Update tailwind.config.mjs to include src/web files
- Add build:web step to main build script chain - Add dev:web script for standalone web development server - Web assets now built automatically during npm run build - Packaged app will include dist/web/* via existing files glob
- Install @fastify/static for serving static files - Add resolveWebAssetsPath method to find web assets in dist/web - Register @fastify/static plugin to serve assets at /web/assets/ - Add serveIndexHtml helper that transforms asset paths for SPA - Update /web/desktop and /web/mobile routes to serve index.html - Transform relative ./assets/ paths to /web/assets/ for proper routing
Updated vite.config.web.mts to use dynamic chunk naming and manual chunking function for better code splitting: - Mobile and desktop apps now build into separate named chunks - React dependencies are isolated in their own chunk for caching - Dynamic chunkFileNames function preserves mobile/desktop naming - Added webpackChunkName magic comments in main.tsx for clarity Build output now shows distinct bundles: mobile-*.js, desktop-*.js, main-*.js, and react-*.js for optimal lazy loading.
Add src/web/mobile/index.tsx as the proper module entry point for the mobile web interface. This includes: - Re-exports of MobileApp component for cleaner imports - Mobile configuration options (haptics, voice input, offline queue) - Mobile viewport breakpoint constants - Safe area padding defaults for notched devices - Haptic feedback utilities with pattern presets - Gesture threshold constants for swipe/pull-to-refresh detection - Voice input support detection Updated main.tsx to import from './mobile' instead of './mobile/App' to leverage the new entry point for better code organization.
- Integrate useWebSocket hook for real-time connection state - Add MobileHeader component with Badge-based status indicator - Display different UI states: disconnected, connecting, connected - Enable retry button when disconnected - Use proper safe-area insets for notched devices (env()) - Enable/disable input controls based on connection state
…rowsers - Enhanced viewport meta tag with minimum-scale, maximum-scale for zoom control - Added theme-color meta tags with media queries for light/dark preference - Added format-detection to disable auto-linking of phone/dates/emails - Added msapplication-tap-highlight for Edge browser support - Added mobile-web-app-capable and application-name for Android PWA - Added dynamic viewport height (dvh) with -webkit-fill-available fallback - Added iOS-specific fixes for rubber-banding and touch zoom - Added touch-action: manipulation to prevent double-tap zoom - Added input font-size fix to prevent iOS Safari zoom on focus - Added touch callout and user-select controls for interactive elements - Added .scrollable utility class for momentum scrolling
- Create manifest.json with app metadata, icons, and shortcuts - Add PWA icon generation script (scripts/generate-pwa-icons.mjs) - Configure Vite public directory for static PWA assets - Add apple-touch-icon links for iOS home screen - Add favicon links for browser tabs - Include npm script for regenerating PWA icons
- Move side effects (toast notifications, queued message processing) out of state updater functions to avoid double-invocation issues in StrictMode - Add support for built-in slash commands (like /synopsis, /clear) in the remote command handler, not just custom AI commands - Add refs for slash command functions so remote handler can access latest function versions Claude ID: 3dd3573f-bed1-4a0e-984c-10081124092a Maestro ID: 5a166b38-b7e9-47f0-a8ff-0113c65f2682
- Add live:disableAll IPC handler to properly disconnect all live sessions when turning off remote access mode - Mobile: Input bar now expands drawer-style on small screens when focused, shrinking message history area for better keyboard space - Mobile: Replace "All Sessions" pill with hamburger menu icon at the start of session pill bar for consistent navigation - Mobile: Remove pull-to-refresh feature for simpler interaction model - Desktop: Simplify TerminalOutput auto-scroll logic using three separate useEffects that only check hasExpandedLogs Claude ID: 3dd3573f-bed1-4a0e-984c-10081124092a Maestro ID: 5a166b38-b7e9-47f0-a8ff-0113c65f2682
PR #4 Review: Web Interface ImplementationExecutive SummaryThis PR adds a comprehensive web interface (~19,600 lines across 75 files) enabling mobile and desktop browser access to Maestro. While the implementation shows excellent UX design and clean architecture, there are critical security vulnerabilities that must be addressed before merging. Overall Risk Assessment: HIGH CRITICAL SECURITY ISSUES (Must Fix Before Merge)CRIT-1: Insufficient Authentication ModelFile: src/main/web-server.ts:196, 214, 359-384 Issue: The current token-based auth has serious weaknesses:
Recommendation:
CRIT-2: No CSRF ProtectionFile: src/main/web-server.ts:667-713, 748-793 Issue: POST endpoints lack CSRF protection. A malicious website could execute commands in user sessions. Recommendation:
CRIT-3: Command Injection RiskFile: src/main/index.ts:1876-1916 Issue: The notification:speak handler spawns child processes with user-supplied commands without proper validation. Recommendation:
HIGH-1: WebSocket Input ValidationFile: src/main/web-server.ts:899-1081 Issue: WebSocket messages lack validation. Malformed messages could cause crashes. Recommendation:
HIGH-2: Inadequate Rate LimitingFile: src/main/web-server.ts:171-176 Current limits:
Recommendation:
MEDIUM PRIORITY ISSUESMED-1: Missing Security HeadersAdd CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy MED-2: Memory Leak RisksWebSocket clients map has no size limits or cleanup for stale connections. MED-3: No HTTPS SupportWeb server runs on HTTP only, vulnerable to MITM on local network. MED-4: localStorage Data Not ValidatedJSON.parse operations lack try-catch and validation. POTENTIAL BUGSBUG-1: Race Condition in Session State Updatessrc/main/index.ts:536-578 - Session state changes broadcasted during iteration. BUG-2: WebSocket Reconnection Issuessrc/web/hooks/useWebSocket.ts:594-610 - Stale state in closure. BUG-3: Missing try-catch for JSON.parseCorrupted localStorage data will crash the app. MISSING ELEMENTSNo TestsZero test files found in src/web/ directory. Required:
No Error BoundariesReact components lack error boundaries. No DocumentationMissing security model docs, API docs, setup guide. POSITIVE HIGHLIGHTS
ACTION ITEMSMust Fix Before Merge:
Should Fix Soon:
Nice to Have:
Estimated effort to fix critical issues: 3-5 days FINAL VERDICTDo not merge until critical security issues are resolved. This PR adds valuable functionality but introduces significant security risks:
The authentication model needs a complete overhaul. Once security issues are addressed, this will be an excellent addition to Maestro. Size: Very Large (~19,600 additions, 75 files) |
- Web server now starts only when user enables the web interface (lazy initialization) - Added live:startServer and live:stopServer IPC handlers for explicit control - live:disableAll now also stops the server and cleans up resources - Enlarged QR code from 100px to 240px for easier mobile scanning - Pinned hamburger menu button outside scroll container in session pill bar - Disabled WebSocket auto-reconnect (users retry manually via button) - Shortened AI input placeholder on small screens Claude ID: 3dd3573f-bed1-4a0e-984c-10081124092a Maestro ID: 5a166b38-b7e9-47f0-a8ff-0113c65f2682
Code Review: PR #4 - Web Interface for MaestroExecutive SummaryComprehensive security review of PR #4 adding web interface with WebSocket support, PWA capabilities, and mobile interface. This is a substantial addition (~20,000 lines across 75 files) introducing remote access to Maestro. Overall Assessment: Excellent architectural thinking and solid patterns, but CRITICAL security vulnerabilities must be addressed before merging. CRITICAL ISSUES (Must Fix Before Merge)1. CORS Configuration Too Permissive - SEVERITY: CRITICALLocation: src/main/web-server.ts 2. Server Binds to 0.0.0.0 - SEVERITY: HIGHLocation: src/main/web-server.ts 3. Authentication Relies Solely on URL Token - SEVERITY: HIGHLocation: src/main/web-server.ts 4. Command Injection Risk - SEVERITY: HIGHLocation: src/main/web-server.ts, src/main/index.ts 5. Rate Limiting Insufficient - SEVERITY: MEDIUM-HIGHLocation: src/main/web-server.ts IMPORTANT ISSUES (Should Fix)
POSITIVE ASPECTS
TEST COVERAGE GAPSCritical areas need tests: authentication, rate limiting, command injection, WebSocket security, CORS, session state race conditions DOCUMENTATION NEEDS
FINAL VERDICT: REQUEST CHANGESMust Fix Before Merge:
Should Fix Soon After:
Excellent work overall! Once security issues are addressed, this will be a fantastic addition to Maestro. The architecture is sound, code quality is high, and the feature set is comprehensive. Review Scope: 75 files, ~20,000 lines |
Pull Request Review: Web Interface ImplementationOverviewThis is an extensive PR adding a comprehensive web interface for Maestro (~19,689 additions). The implementation includes both a mobile PWA and desktop web interface with real-time WebSocket communication, authentication, and session management. Critical Security Concerns🔴 HIGH SEVERITY: Security Token in URL PathLocation: The security model relies on a UUID token embedded in the URL path:
Recommendations:
Reference: OWASP Top 10:2021 A01:2021-Broken Access Control 🔴 MEDIUM SEVERITY: No CSRF ProtectionLocation: POST endpoints in POST endpoints ( Recommendations:
🟡 MEDIUM SEVERITY: Command Injection Surface ExpandedLocation: Commands from the web interface are routed through Current Controls:
Recommendations:
🟡 MEDIUM SEVERITY: WebSocket Message ValidationLocation: Message handling in
Recommendations:
Security Best Practices Observed ✅
Code Quality Issues🟡 High Complexity FunctionsLocation: The CommandInputBar component is extremely large and handles multiple concerns:
Recommendation: Split into smaller, focused components 🟡 Inconsistent Error HandlingLocation: Multiple files Error handling varies across the codebase:
Recommendation: Standardize error responses and add error tracking 🟡 Missing Input ValidationLocation: The
Performance Considerations🟡 Broadcast EfficiencyLocation:
🟡 Memory ManagementLocation: Session logs are truncated for web preview (first 3 lines/500 chars) but full logs are still sent. Consider:
Testing Gaps🔴 No Tests IncludedThis PR adds a significant amount of code (~19,689 lines) without accompanying tests. Critical areas needing tests:
Documentation Issues🟡 Missing Security DocumentationThe PR lacks documentation on:
Architecture Concerns🟡 Tight Coupling Between Desktop and WebThe web interface relies heavily on desktop app state via callbacks. Consider:
Mobile-Specific Issues🟡 PWA Service Worker CachingLocation: Service worker implementation needs review:
Positive Aspects ⭐
Recommendations SummaryBefore Merge (Blockers):
High Priority (Post-Merge):
Medium Priority:
Additional Files to ReviewGiven the size, I recommend focused review of:
Final AssessmentThis PR represents a substantial feature addition with strong UX design but needs security hardening before production use. The code quality is generally good, but the security model needs review and documentation. Recommendation: Approve with conditions - address critical security concerns and add documentation before enabling by default. Estimated Risk Level: Medium-High (due to expanded attack surface and authentication model) Review completed using Claude Code PR review workflow. For questions about specific findings, please reference line numbers in the location sections. |
Address PR review feedback: - Issue #1: Add early returns in openModal, closeModal, and closeAll to skip Map recreation when state hasn't changed. Prevents unnecessary selector re-evaluations across all subscribers. - Issue #2: Add JSDoc to useModalActions() explaining that the ~40 selector subscriptions are intentionally transitional — identical to old Context behavior. Components should migrate to direct useModalStore(selectModalOpen(...)) calls for granular subscriptions. - Issue #5: Add 14 new tests covering no-op guard behavior (7 tests including render count verification), getModalActions() API surface and cross-call store sharing (3 tests), and useModalActions() reactive state and compatibility (4 tests). Issues #3 (memory leak) and #4 (type overloads) are not actionable: 47 fixed modal IDs is bounded, and ModalDataFor<T> already resolves to undefined for unmapped modals.
Adds investigation and planning documents for: 1. PRICING-BUGFIXES-PHASE2.md - Summary of 5 issues found during testing: - Issue RunMaestro#1: Agent Settings Detection - WORKING CORRECTLY - Issue RunMaestro#2: Folder Toggle Shows Blank - Minor bug, fix ready - Issue RunMaestro#3: Folder Detection Shows API - Critical bug, fix ready - Issue RunMaestro#4: Analysis of RunMaestro#1 vs RunMaestro#3 - Issue RunMaestro#5: Dashboard costs - Requires separate plan 2. PRICING-DASHBOARD-COST-FIX.md - Comprehensive plan for Issue RunMaestro#5: - Root cause: Costs stored at API rates, billing mode never applied - Solution: Recalculate at storage time with proper billing mode - 6-phase implementation plan with database schema changes - Risk assessment and mitigation strategies - Timeline estimate: 12-18 hours Auto Run fix documents created in /app/__AUTORUN/: - PRICING-FIX-02-FOLDER-TOGGLE.md - PRICING-FIX-03-FOLDER-DETECTION.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>