- Uses python312 from AUR for jpegio 3.13 compatibility
- Self-contained venv in /opt/stegasoo
- Includes systemd service files for web and API
- CLI symlinked to /usr/bin/stegasoo
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added zstandard>=0.22.0 to base image dependencies
- Updated verification to check zstd import
- Bumped base image version label to 4.2.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- rebuild: cleans everything, rebuilds base and services with --no-cache
- Updated help text to clarify full vs rebuild
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CLI generate command:
- --qr <file.png|jpg> to save RSA key as QR image
- --qr-ascii to print ASCII QR code to terminal
API endpoints:
- POST /generate-key-qr - generate QR from key_pem
- Supports png, jpg, and ascii output formats
- Uses zstd compression by default
- Added has_qrcode_write to /capabilities
Core:
- generate_qr_code() now supports jpg/jpeg output format
- New generate_qr_ascii() for terminal display
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
zstd is now the default compression algorithm across all frontends,
so it should always be installed with the base package.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- RSA key size capped at 3072 bits (4096 too large for QR codes)
- Added zstd compression for QR code RSA keys (better ratio than zlib)
- New prefix STEGASOO-ZS: for zstd, backward compatible with STEGASOO-Z: (zlib)
- Added zstandard dependency to web/api/compression extras
- Updated all docs, CLI options, and web UI to reflect 3072 max
- Version bump to 4.2.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When encode form was submitted in async mode, validation errors
returned HTML (render_template) instead of JSON, causing
"Unexpected token '<'" parse errors in the browser.
Added _error_response() helper that returns JSON in async mode
and HTML flash in sync mode.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create stegasoo-api.service for FastAPI on port 8000
- Prompt user during setup with security warning (no auth)
- Default to disabled (recommended)
- Update help text and start commands for both services
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Worker was writing 25% then calling decode() without progress_file,
so library couldn't update progress. Now passes progress_file through
so library's extraction/RS-decode progress updates work.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Reduce PROGRESS_INTERVAL from 2000 to 500 for responsive updates
- Scale extraction progress to 5-70% range
- Add progress updates before/after RS decode (75% and 95%)
- RS decode is the slow part, now visible in progress
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Show "Deriving keys (may take a moment)..." during Argon2 phase
to set user expectations on slower devices
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update TEMP_FILE_EXPIRY constant (300 -> 600 seconds)
- Update all UI references to the new 10 minute expiry
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add indeterminate (barber pole) animation during Argon2/initializing phase
- Prevent progress from jumping backwards (fixes flash-to-zero bug)
- Initial progress write at 5% when embedding actually starts
- Reset progress tracking on new operations
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added run_in_thread() helper using asyncio.to_thread()
- /encode, /encode/file, /decode use thread pool for CPU-bound ops
- /encode/multipart, /decode/multipart also updated
- Server can now handle concurrent requests without blocking
- Updated version header to v4.2.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use scipy.fft.dctn/idctn with axes=(1,2) to process 500 blocks at once
- Extract bits in batch using numpy array indexing
- Vectorized QIM embedding with array operations
- Tests pass, roundtrip verified
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add reedsolo>=1.7.0 to Dockerfile and Dockerfile.base for DCT
error correction (fixes DCT decode failures in container)
- Update all documentation to use docker/docker-compose.yml paths
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move Dockerfile, Dockerfile.base, docker-compose.yml to docker/
- Update docker-compose.yml with correct context paths
- Update scripts/build.sh to use new paths
- Update DOCKER_QUICKSTART.md with new commands
- Add scripts/build.sh to tracked files
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Run on Pi after from-source build to create:
stegasoo-rpi-runtime-env-arm64.tar.zst (~50-60MB)
Contains pyenv + Python 3.12 + venv with all deps.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add grid icon to LSB button to match DCT soundwave icon
- Add divider between mode and output options (hidden on mobile)
- Wraps cleanly on small screens
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Shows ABCD-••••-3456 instead of ABCD...3456 to indicate
the key is longer and has been redacted.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Convert DCT/LSB (encode) and Auto/LSB/DCT (decode) to use
Bootstrap btn-group style matching Color/Gray and JPEG/PNG.
Better mobile layout - all options on one line.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Display ABCD...3456 instead of full masked fingerprint.
Full fingerprint still visible in tooltip on hover.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Step 3 now offers three choices:
- Skip (public mode)
- Generate new key
- Enter existing key (for joining team deployments)
Validates entered keys using Python channel module before accepting.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove pv (showed read progress, not write progress)
- Use dd status=progress for actual write progress
- Reduce block size to 1M (better for slow SD cards)
- Remove conv=fsync (sync at end instead, faster)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Run fsck.vfat on boot partition and e2fsck on root partition
after flashing to catch and fix any corruption.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
resize2fs only fills the partition. Need growpart first to
expand the partition to fill the disk, then resize2fs to
expand the filesystem.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>