From a8f6ae1dd27cd4e5d1187436022f79ed75f2c4f3 Mon Sep 17 00:00:00 2001 From: "Aaron D. Lee" Date: Sat, 3 Jan 2026 22:21:23 -0500 Subject: [PATCH] Add 4.1.0 feature plan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Multi-user support (16+1 admin) - Channel key QR codes (web + CLI) - Advanced tools: capacity calc, metadata stripper, stego detector, image compare, header peek, batch mode ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- PLAN-4.1.0.md | 422 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 422 insertions(+) create mode 100644 PLAN-4.1.0.md diff --git a/PLAN-4.1.0.md b/PLAN-4.1.0.md new file mode 100644 index 0000000..7226e06 --- /dev/null +++ b/PLAN-4.1.0.md @@ -0,0 +1,422 @@ +# Stegasoo 4.1.0 Plan + +## Overview + +Version 4.1.0 is a feature release focusing on small-group deployment improvements and new utilities. + +## Goals + +1. **Multi-User Support** - Admin can create up to 16 users for shared deployments +2. **Channel Key QR** - Easy visual sharing of channel keys via QR codes +3. **CLI Channel Commands** - Manage channel keys from command line +4. **Advanced Tools** - Image/stego utilities (TBD) + +--- + +## Feature 1: Multi-User Support + +### Requirements + +- 16 users + 1 admin maximum (17 total) +- First user created at setup is always admin +- Admin can add/delete users, reset passwords +- Regular users can only change their own password +- No self-registration (admin-invite only) + +### Database Changes + +**Update User model in `frontends/web/models.py`:** + +```python +class User(db.Model): + id = Column(Integer, primary_key=True) + username = Column(String(80), unique=True, nullable=False) + password_hash = Column(String(255), nullable=False) + role = Column(String(20), default='user') # 'admin' or 'user' + created_at = Column(DateTime, default=datetime.utcnow) +``` + +**Migration:** Add `role` and `created_at` columns. Existing users get `role='admin'`. + +### New Routes + +| Route | Method | Access | Description | +|-------|--------|--------|-------------| +| `/admin/users` | GET | admin | List all users | +| `/admin/users/new` | GET, POST | admin | Create user form | +| `/admin/users//delete` | POST | admin | Delete user | +| `/admin/users//reset-password` | POST | admin | Generate temp password | + +### New Decorator + +```python +# auth.py +def admin_required(f): + @wraps(f) + def decorated(*args, **kwargs): + if not current_user.is_authenticated: + return redirect(url_for('login')) + if current_user.role != 'admin': + flash('Admin access required', 'error') + return redirect(url_for('index')) + return f(*args, **kwargs) + return decorated +``` + +### UI Changes + +**Navigation (for admin users):** +- Add "Users" link in navbar (visible only to admin) + +**Account page (`/account`):** +- Admin sees link to user management +- All users see their own password change form + +**New template: `templates/admin/users.html`:** +- Table: Username | Role | Created | Actions +- Actions: Reset Password, Delete (disabled for self) +- "Add User" button (disabled if at 16 user limit) +- Show count: "3 of 16 users" + +**New template: `templates/admin/user_new.html`:** +- Username field (email-style allowed) +- Password field (auto-populated with random 8-char, admin can override) +- Submit โ†’ confirmation page shows password once with copy button + +### Validation + +- Username: 3-80 chars, alphanumeric + underscore/hyphen + @/. for email-style +- Password: 8+ chars (same as current) +- Can't delete yourself +- Can't demote the last admin +- Deleting user immediately invalidates their sessions + +--- + +## Feature 2: Channel Key QR + +### Web UI + +**About page additions:** + +If `STEGASOO_CHANNEL_KEY` environment variable is set: + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Channel Key โ”‚ +โ”‚ โ”‚ +โ”‚ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ Your server uses a โ”‚ +โ”‚ โ–ˆโ–ˆ โ–ˆโ–ˆ private channel key. โ”‚ +โ”‚ โ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆ Share this QR with โ”‚ +โ”‚ โ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆ others to join. โ”‚ +โ”‚ โ–ˆโ–ˆ โ–ˆโ–ˆ โ”‚ +โ”‚ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ [Copy Key] [Download]โ”‚ +โ”‚ โ”‚ +โ”‚ Key: abc123...xyz โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +- QR generated server-side using `qrcode` library +- "Copy Key" copies text to clipboard +- "Download QR" saves as PNG + +**Implementation:** + +```python +# about route addition +@app.route('/about') +def about(): + channel_key = os.environ.get('STEGASOO_CHANNEL_KEY', '') + channel_qr_b64 = None + if channel_key: + # Generate QR as base64 PNG + qr = qrcode.make(channel_key) + buffer = BytesIO() + qr.save(buffer, format='PNG') + channel_qr_b64 = base64.b64encode(buffer.getvalue()).decode() + return render_template('about.html', + channel_key=channel_key, + channel_qr=channel_qr_b64) +``` + +### CLI Commands + +**New command group: `stegasoo channel`** + +```bash +# Generate a new channel key +stegasoo channel generate +# Output: +# Channel Key: stg_abc123...xyz789 +# +# โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ +# โ–ˆโ–ˆ โ–ˆโ–ˆ +# โ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆ +# ... +# +# Set in environment: export STEGASOO_CHANNEL_KEY="stg_abc123..." + +# Show current key (from env or argument) +stegasoo channel show +# Output: +# Channel Key: stg_abc123...xyz789 + +# Display QR in terminal (ASCII) +stegasoo channel qr +# Output: ASCII QR code + +# Save QR as PNG +stegasoo channel qr -o channel-key.png +# Output: Saved to channel-key.png + +# Explicit format selection +stegasoo channel qr --format ascii # Terminal (default) +stegasoo channel qr --format png -o - # PNG to stdout +``` + +**Implementation notes:** + +- Use `qrcode[pil]` for PNG output +- Use `qrcode` with `print_ascii()` for terminal +- Read key from `--key` argument or `STEGASOO_CHANNEL_KEY` env var +- `generate` uses existing `generate_channel_key()` from `stegasoo.channel` + +--- + +## File Changes Summary + +### New Files + +| File | Description | +|------|-------------| +| `frontends/web/templates/admin/users.html` | User management page | +| `frontends/web/templates/admin/user_new.html` | Add user form | + +### Modified Files + +| File | Changes | +|------|---------| +| `frontends/web/models.py` | Add `role`, `created_at` to User | +| `frontends/web/auth.py` | Add `@admin_required`, user management routes | +| `frontends/web/templates/base.html` | Add Users link for admins | +| `frontends/web/templates/account.html` | Add admin link | +| `frontends/web/templates/about.html` | Add channel key QR section | +| `src/stegasoo/cli.py` | Add `channel` command group | + +--- + +## Testing Plan + +### Multi-User + +1. Fresh install โ†’ first user is admin +2. Admin can create users up to limit (16) +3. Admin can't create 17th user (shows error) +4. Regular user can log in, encode/decode +5. Regular user can't access `/admin/users` +6. Admin can reset user password +7. Admin can delete user +8. Admin can't delete self +9. Existing 4.0.2 databases upgrade correctly (single user becomes admin) + +### Channel Key QR + +1. About page shows nothing if no channel key +2. About page shows QR + key if channel key set +3. Copy button works +4. Download gives valid PNG +5. QR scans correctly to key value + +### CLI + +1. `channel generate` creates valid key + shows QR +2. `channel show` displays current key +3. `channel qr` outputs ASCII to terminal +4. `channel qr -o file.png` saves PNG +5. Commands work with `--key` override +6. Commands read from env var + +--- + +## Feature 3: Advanced Tools + +### Included Tools + +| Tool | Web | CLI | Description | +|------|-----|-----|-------------| +| **Capacity Calculator** | โœ“ | โœ“ | Upload image โ†’ show DCT/LSB capacity | +| **Metadata Stripper** | โœ“ | โœ“ | Remove EXIF/metadata from image | +| **Stego Detector** | โœ“ | โœ“ | Analyze image for signs of hidden data | +| **Image Compare** | โœ“ | - | Side-by-side before/after diff | +| **Header Peek** | โœ“ | โœ“ | Check for Stegasoo header without decrypting | +| **Batch Mode** | - | โœ“ | Encode/decode multiple files | + +### Web UI: `/tools` Page + +New page with card-based layout: + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ ๐Ÿ› ๏ธ Advanced Tools โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ โ”‚ +โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ +โ”‚ โ”‚ ๐Ÿ“ Capacity โ”‚ โ”‚ ๐Ÿงน Metadata โ”‚ โ”‚ +โ”‚ โ”‚ Calculator โ”‚ โ”‚ Stripper โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ Check how much โ”‚ โ”‚ Remove EXIF โ”‚ โ”‚ +โ”‚ โ”‚ data fits โ”‚ โ”‚ before encoding โ”‚ โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ”‚ โ”‚ +โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ +โ”‚ โ”‚ ๐Ÿ” Stego โ”‚ โ”‚ ๐Ÿ”Ž Header โ”‚ โ”‚ +โ”‚ โ”‚ Detector โ”‚ โ”‚ Peek โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ Analyze image โ”‚ โ”‚ Check for โ”‚ โ”‚ +โ”‚ โ”‚ for hidden data โ”‚ โ”‚ Stegasoo data โ”‚ โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ”‚ โ”‚ +โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ +โ”‚ โ”‚ โš–๏ธ Image โ”‚ โ”‚ +โ”‚ โ”‚ Compare โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ Before/after โ”‚ โ”‚ +โ”‚ โ”‚ diff view โ”‚ โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ”‚ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +Each card opens a modal or expands inline for the tool interface. + +### CLI Structure + +```bash +# Capacity calculator +stegasoo capacity image.jpg +stegasoo capacity image.jpg --format json + +# Metadata stripper +stegasoo strip image.jpg # Output to image_stripped.jpg +stegasoo strip image.jpg -o clean.jpg # Custom output +stegasoo strip image.jpg --in-place # Overwrite original + +# Stego detector +stegasoo detect image.jpg +stegasoo detect image.jpg --verbose # Detailed analysis + +# Header peek +stegasoo peek image.jpg +# Output: "Stegasoo DCT header detected" or "No Stegasoo header found" + +# Batch mode +stegasoo encode --batch manifest.json # JSON with files + credentials +stegasoo decode --batch input_dir/ --out output_dir/ +``` + +### Tool Details + +#### Capacity Calculator +- Input: Image file +- Output: Dimensions, megapixels, DCT capacity, LSB capacity +- Web: Upload zone + results panel +- CLI: Table or JSON output + +#### Metadata Stripper +- Input: Image file +- Output: Clean image (EXIF/metadata removed) +- Show what was removed (camera model, GPS, etc.) +- Preserve image quality + +#### Stego Detector +- Input: Image file +- Analysis: + - Chi-square analysis (LSB detection) + - DCT coefficient histogram analysis + - Visual inspection hints +- Output: Likelihood score + findings +- Note: Detection is probabilistic, not definitive + +#### Image Compare +- Input: Two images (original + stego) +- Output: + - Side-by-side view + - Difference overlay (amplified) + - Pixel-level stats (PSNR, SSIM) +- Web only (visual tool) + +#### Header Peek +- Input: Image file +- Output: Header found (yes/no), mode (DCT/LSB), embedded size estimate +- Does NOT decrypt - just checks for valid header structure +- Useful for "is this a stego image?" without credentials + +#### Batch Mode +- CLI only +- Manifest file (JSON) or directory-based +- Progress bar for multiple files +- Error handling per-file (continue on failure) + +--- + +## Migration Notes + +### Database Migration + +For existing 4.0.2 installations: + +```python +# migrations/add_user_role.py +def upgrade(): + # Add columns with defaults + op.add_column('user', sa.Column('role', sa.String(20), default='user')) + op.add_column('user', sa.Column('created_at', sa.DateTime)) + + # Set existing users as admin (they were the first user) + op.execute("UPDATE user SET role = 'admin' WHERE role IS NULL") + op.execute("UPDATE user SET created_at = datetime('now') WHERE created_at IS NULL") +``` + +Or simpler: detect on startup, update schema automatically (current pattern). + +--- + +## Out of Scope + +- Per-user channel keys +- User groups/teams +- API authentication tokens +- User activity logging +- Password complexity rules beyond length + +--- + +## Estimated Effort + +| Component | Complexity | +|-----------|------------| +| Database schema change | Low | +| Admin routes + templates | Medium | +| Access control decorator | Low | +| About page QR | Low | +| CLI channel commands | Medium | +| Advanced Tools (TBD) | Medium-High | +| Testing | Medium | + +--- + +## Decisions + +1. **Temp password flow:** Password field auto-populates with random 8-char password. Admin can override if desired. Show password once on confirmation page. + +2. **Session handling:** Yes - deleting a user immediately invalidates their active sessions (ban hammer). + +3. **Username rules:** Sane requirements, email-style allowed. Validation: 3-80 chars, alphanumeric, underscore, hyphen, @ and . for email-style. + +--- + +## Approval + +- [x] Plan reviewed +- [x] Questions resolved +- [ ] Ready to implement