Admin System Settings page:
- New /admin/settings route with channel key config
- QR code export with tiled print sheet (4x5 on US Letter)
- Server config display (HTTPS, port, auth, DCT/QR status)
- Environment info (version, Python, platform, KDF)
Navigation improvements:
- Icon-only nav with floating labels on hover
- Gold labels slide down below icons
- Gradient pill background on hover
Air-gap ready:
- All vendor libs now local (Bootstrap CSS/JS, Icons, html5-qrcode)
- QRious library for QR generation
- No external CDN dependencies
Other changes:
- Moved About link from nav to footer
- Channel QR export moved from about.html to admin/settings.html
- Print sheet button for QR codes (tiled US Letter output)
- Dev runner script (dev_run.sh) with r/q hotkeys
- Fixed navbar dropdown z-index
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Security:
- Remove instance/.secret_key and instance/stegasoo.db from git
- Add instance/ to .gitignore (was only ignoring frontends/web/instance/)
Lint fixes:
- Remove unused imports in temp_storage.py (os, shutil)
- Sort imports and fix f-string placeholders in cli.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CLI module now explains:
- Click command group hierarchy (tree diagram)
- JSON output pattern for scriptability
- Secure input handling (hide_input, confirmation_prompt)
- Dry-run mode pattern
- Batch processing with variadic args and progress callbacks
Web UI now explains:
- Flask architecture overview with ASCII diagram
- Subprocess isolation pattern (why we run stegasoo in subprocesses)
- Async job management with polling flow diagram
- Context processors for template globals
- Secret key persistence for session survival
- Environment-based configuration (12-factor style)
If you're reading this code trying to learn Flask/Click patterns,
these comments should actually teach you something useful.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When STEGASOO_HOSTNAME env var is not set, use socket.gethostname()
to get the actual machine hostname for certificate generation.
This ensures the cert includes proper hostname.local SAN.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The auto-generated SSL certificate now includes:
- hostname.local for mDNS browser access
- All detected local network IPs
This fixes browser access via stegasoo.local when HTTPS is enabled.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Encode/Decode UI:
- New accordion layout with 3 steps (encode) / 2 steps (decode)
- Gold step numbers with checkmarks on completion
- Dynamic right-aligned summaries as fields are filled
- Subtle gradient highlight on active accordion step
Webcam QR Scanning:
- Camera button for RSA key QR codes on encode/decode pages
- Camera button for channel key scanning
- 3-2-1 countdown capture for dense QR codes
- Proper scanner stop/restart on retry
- Backend decompression for STEGASOO-Z: compressed keys
RSA Key Print:
- Removed identifying text from QR print output
- Now prints plain QR code for discretion
Pi Image Script:
- Fixed 16GB resize to detect expand vs shrink
- Fresh images now properly EXPAND to 16GB
- Already-expanded images properly SHRINK to 16GB
UI Polish:
- Removed PIN helper text for compactness
- Fixed QR drop zone centering
- Fixed decode page element IDs for JS
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
QR Channel Key Sharing:
- Admin-only QR generator in about.html (was visible to all)
- QR button for saved keys on account page
- Fixed about() route missing channel status vars (bug)
Pi Build Optimization:
- Pre-built venv tarball support (39MB zstd, skips 20+ min compile)
- setup.sh auto-detects and extracts tarball if present
- Strip __pycache__/tests before tarball (295MB → 208MB)
Flash Script Improvements:
- flash-image.sh now uses config.json for headless WiFi setup
- Consistent wipe prompt on both flash scripts
- pull-image.sh re-enables auto-expand before shrinking
Build Docs:
- Added zstd and jq to pre-setup apt-get
- Documented fast build option with pre-built venv
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix .dockerignore to exclude *.img.xz files (was 2.3GB context)
- Remove deprecated 'version' attribute from docker-compose.yml
- Increase container memory limits to 2GB/1GB (prevent OOM on DCT)
- Add loading spinner to decode button during form submission
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- New temp_storage.py module stores files on disk instead of in-memory
- Multiple Gunicorn workers can now share temp files
- Startup cleanup removes leftover files from previous runs
- Dockerfile creates temp_files directory
- Added temp_files/ to .gitignore
Previously encode preview worked but download failed with "File expired"
because each worker had its own in-memory TEMP_FILES dict.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- wizard/setup now generate certs when HTTPS enabled
- app.py has proper error handling for cert failures
- Add custom SSL certificate documentation to INSTALL.md
- Include SANs for hostname, localhost, and local IP
Previously HTTPS could be enabled but certs weren't generated,
causing SSL_ERROR_RX_RECORD_TOO_LONG browser errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
About page:
- Version history now shows v4.1.2 prominently with accordion for older versions
- Shortened 'Error Correction Reed-Solomon' to 'DCT ECC / RS Code'
- Removed v4.1 badges from established features
API fixes:
- Export MAX_FILE_PAYLOAD_SIZE from constants
- Export calculate_capacity_by_mode from steganography
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Mobile-responsive CSS improvements:
- Larger touch targets for drop zones and buttons (56px min)
- Touch feedback with active states for touch devices
- Camera hint text on mobile ("Tap to take photo or choose file")
- Mode buttons stack vertically on small screens
- Full-width download buttons on mobile
- Navbar doesn't stick on mobile to save screen space
Release validation script (scripts/validate-release.sh):
- Automated pre-release checks: ruff, imports, encode/decode sanity
- Optional Docker build/test (--docker flag)
- Optional Pi smoke test via SSH (--pi flag)
- Pass/fail summary with exit codes
Other:
- Version bump to 4.1.2 (pyproject.toml, constants.py, __init__.py)
- Fixed ruff import sorting in cli.py
- Updated PLAN-4.1.2.md (all 9 features complete)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Progress bar support (v4.1.2):
- Web frontend: Real-time progress during encode with phase display
- CLI: --progress flag with rich library for encode command
- Backend: progress_file parameter for async progress reporting
DCT decode bug fix:
- Fixed InvalidMagicBytesError not being caught in early-exit check
- RS-protected format (v4.1.0+) has length prefix first, not magic bytes
- Exception handler now catches both ValueError and InvalidMagicBytesError
MOTD update:
- Added sparkly header to setup.sh MOTD (matches other rpi scripts)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New exceptions for specific decode failures:
- InvalidMagicBytesError: wrong mode or not a Stegasoo image
- ReedSolomonError: image too corrupted to recover
- NoDataFoundError, ModeMismatchError: additional clarity
Web UI now shows specific, actionable error messages:
- "Try a different mode (LSB/DCT)"
- "Image too corrupted, may have been re-saved"
- "Wrong credentials - check reference photo..."
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
#4 Forced First-Login Setup:
- Add before_request hook to redirect to /setup if no users exist
- Skip redirect for static files and setup routes
#5 Dropzone UX Fixes:
- Make preview images clickable to replace file
- Make entire drop zone clickable
- QR zone resets after 2s on error, allowing retry
- Clear file input on error so same file can be re-selected
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Show 6 key specs prominently as cards (Payload, Carrier, DCT/LSB capacity, Encryption, Error Correction)
- Add Reed-Solomon error correction info with v4.1 badge
- Move secondary specs to collapsible accordion
- Add reedsolo to "Built with" list
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- setup.sh: Add btop to apt install for temp monitoring
- first-boot-wizard: Add Step 4 for overclock configuration
- Detects Pi 4/5 model
- Asks about active cooling
- Offers appropriate overclock settings (2.0GHz Pi4, 2.8GHz Pi5)
- Prompts for restart if enabled
- decode.html: Make message box click-to-copy, remove separate button
- Shows "(click to copy)" hint
- Visual feedback on hover and copy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Shows running timer (e.g., "Encoding... 1:23") so users know
the operation is still working and not frozen.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>