# TODO.md

## Completed Tasks ✅

- [x] Update project directory from 'camera-control' to 'dslr'
  - [x] Search for all occurrences of 'camera-control' in the codebase
  - [x] Update URLs in app.php endpoint configuration
  - [x] Remove unnecessary imageRelay.php from dslr directory
  - [x] Update documentation references in CLAUDE.md

- [x] Simplify capture process to direct synchronous execution
  - [x] Remove wrapper script implementation from capture.php
  - [x] Implement direct execution of captureImageDSLRInstall
  - [x] Update CLAUDE.md documentation to reflect current implementation
  - [x] Test synchronous capture execution

- [x] Implement multi-space image delivery
  - [x] Modify captureImageDSLRInstall script to accept GOOGLE_CHAT_SPACE_ID environment variable
  - [x] Update capture.php to pass space ID via environment variable
  - [x] Create newcode.txt with modified script for deployment
  - [x] Update documentation to reflect multi-space implementation

- [x] Code review: Fix 27 issues across security, bugs, architecture, and quality
  - [x] **Security: Centralize credentials** - Created `config.php` (gitignored) with all SSH credentials as constants; removed hardcoded credentials from capture.php, settings.php, errors.php, testRelay.php, testStorage.php
  - [x] **Security: Command injection prevention** - Added `sanitizeShellParam()` for shell-interpolated values, `validateIPAddress()` for IP inputs
  - [x] **Security: SSL verification** - Re-enabled `CURLOPT_SSL_VERIFYPEER` in `makeApiCall()`
  - [x] **Security: Debug log authentication** - Added `DEBUG_LOG_KEY` auth check to `showDebugLogs()`
  - [x] **Security: Webhook verification** - Added Google Chat verification token check in `handleRequest()`
  - [x] **Security: Safe unserialize** - Used `['allowed_classes' => false]` in `getCameraList()`
  - [x] **Bug: capture.php dead code** - Removed `exit()` on line 3 that made entire file non-functional
  - [x] **Bug: Undefined $wrapperScript** - Removed reference to undefined variable in capture.php
  - [x] **Bug: Duplicate regex in settings.php** - Removed duplicate patterns for Camera Time, Capture Target, Review Time
  - [x] **Bug: Dead code path in handleSlashCommand** - Added `isset($handler['url'])` guard
  - [x] **Bug: app-home.php garbled emoji encoding** - Rewrote `createAppHomePage()` with clean UTF-8 strings
  - [x] **Bug: app-home.php using global camera.txt** - Updated `getCurrentCameraInfo()` to use space-specific database
  - [x] **Architecture: Shared functions** - Created `includes/functions.php` with `logChatError()`, `validateJsonResponse()`, `safeJsonResponse()`, `sendJsonResponse()`
  - [x] **Architecture: app.php inclusion guard** - Added `basename($_SERVER['SCRIPT_FILENAME'])` guard so app.php can be safely `require_once`d
  - [x] **Architecture: Atomic locking** - Rewrote `acquireLock()` with `flock()` for race-condition-free locking
  - [x] **Architecture: Removed dead demo code** - Removed `handleDemoSubmit()` and `getAdvancedDemoDialog()` (~150 lines)
  - [x] **Quality: display_errors disabled** - All files use `DISPLAY_ERRORS` constant (false in production)
  - [x] **Quality: Debug log rotation** - Added size-based rotation for debug-requests.log and error logs
  - [x] **Quality: Input validation** - Replaced loose IP regex in input.php with `filter_var(FILTER_VALIDATE_IP)`
  - [x] **Quality: setCameraDialog.php cleanup** - Removed garbage `EOF < /dev/null` artifact
  - [x] **Quality: Action name comments** - Added comments explaining legacy action names (how_many_response = Capture, etc.)
  - [x] **Testing: Created test suite** - 5 test files with 107 tests, all passing (config, functions, lock system, space database, camera list)
  - [x] **Verification** - All 17 PHP files pass `php -l` syntax check; no hardcoded credentials in tracked files; config.php in .gitignore; file permissions set

## Pending Tasks 📋

- [ ] **IMPORTANT**: Update Google Cloud Console Configuration
  - [ ] Update webhook URL: `https://www.livetimelapse.com.au/ai/google-chat/dslr/app.php`
  - [ ] Update App Home URL: `https://www.livetimelapse.com.au/ai/google-chat/dslr/app-home.php`
  - [ ] These must be updated in Google Cloud Console → Chat API → Configuration

## Future Enhancements 🚀

- [ ] Implement JavaScript error logging system as per CLAUDE.md requirements
- [ ] Consider implementing rate limiting for API endpoints
- [ ] Add health check endpoint for monitoring
- [ ] Implement service account-based image posting as alternative to webhooks
- [ ] Create webhook URL management interface for manual configuration
- [ ] Document webhook setup process for space administrators

## Notes 📝

- The imageRelay.php used by captureImageDSLRInstall is located at `/ai/google-chat/php-tools/imageRelay.php`
- All camera-control references have been updated to dslr
- File permissions should be set to claude:webproject with 775 for directories and 664 for files
- Multi-space image delivery: Implemented via GOOGLE_CHAT_SPACE_ID environment variable
- Credentials are centralized in `config.php` (gitignored) - never commit this file
- Shared utility functions live in `includes/functions.php` - use `require_once` to include
- app.php has an inclusion guard - safe to `require_once` from other files for access to space DB functions
- Test suite: Run `php testing/run_tests.php` to verify all 107 tests pass
- Google Chat webhook limitations: Webhooks cannot be created or accessed programmatically - must be manually configured through web UI