1. app/web/utils/validators.py - Added 'finalizing' to valid_statuses list
2. app/web/models.py - Updated status field comment to document all valid statuses
3. app/web/jobs/scan_job.py
- Added transition to 'finalizing' status before output file generation
- Sets current_phase = 'generating_outputs' during this phase
- Wrapped output generation in try-except with proper error handling
- If output generation fails, scan is marked 'completed' with warning message (scan data is still valid)
4. app/web/api/scans.py
- Added _recover_orphaned_scan() helper function for smart recovery
- Modified stop_running_scan() to:
- Allow stopping scans with status 'running' OR 'finalizing'
- When scanner not in registry, perform smart recovery instead of returning 404
- Smart recovery checks for output files and marks as 'completed' if found, 'cancelled' if not
5. app/web/services/scan_service.py
- Enhanced cleanup_orphaned_scans() with smart recovery logic
- Now finds scans in both 'running' and 'finalizing' status
- Returns dict with stats: {'recovered': N, 'failed': N, 'total': N}
6. app/web/app.py - Updated caller to handle new dict return type from cleanup_orphaned_scans()
Expected Behavior Now
1. Normal scan flow: running → finalizing → completed
2. Stop on active scan: Sends cancel signal, becomes 'cancelled'
3. Stop on orphaned scan with files: Smart recovery → 'completed'
4. Stop on orphaned scan without files: → 'cancelled'
5. App restart with orphans: Startup cleanup uses smart recovery
Allow users to add ports to expected list directly from scan results page
instead of navigating through site config pages. The button appears next
to unexpected ports and updates the site IP configuration via the API.
- Add site_id and site_ip_id to scan result data for linking to config
- Add "Mark Expected" button next to unexpected ports in scan detail view
- Implement markPortExpected() JS function to update site IP settings
- Replace subprocess.run() with Popen for cancellable processes
- Add cancel() method to SneakyScanner with process termination
- Track running scanners in registry for stop signal delivery
- Handle ScanCancelledError to set scan status to 'cancelled'
- Add POST /api/scans/<id>/stop endpoint
- Add 'cancelled' as valid scan status
- Add Stop button to scans list and detail views
- Show cancelled status with warning badge in UI
- Add API endpoint GET /api/scans/by-ip/{ip_address} to retrieve
last 10 scans containing a specific IP
- Add ScanService.get_scans_by_ip() method with ScanIP join query
- Add search box to global navigation header
- Create dedicated search results page at /search/ip
- Update API documentation with new endpoint
Save screenshot_dir to database when scans complete so the directory
is properly cleaned up on scan deletion. Previously the field was never
populated, causing screenshots to remain after deleting scans.
Update sslyze to 6.2.0 and cryptography to 46.0.0 to fix certificate
handling issues with negative serial numbers (RFC 5280 compliance).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add certificate details modal to scan detail page with subject, issuer,
validity dates, serial number, self-signed indicator, SANs, and TLS
version support with expandable cipher suites
- Fix bug where certificate data was not being saved to database due to
incorrect path lookup (was checking http_info['certificate'] instead of
http_info['ssl_tls']['certificate'])
- Update requirements: add sslyze 6.0.0 and upgrade cryptography to >=42.0.0
to fix 'No module named cryptography.x509.verification' error
- Save JSON/HTML/ZIP paths to database when scans complete
- Remove orphaned scan-config-id reference causing JS errors
- Add showAlert function to scan_detail.html and scans.html
- Increase notification z-index to 9999 for modal visibility
- Replace inline alert creation with consistent toast notifications