Consolidate stegasoo and verisoo into soosef monorepo
Merge stegasoo (v4.3.0, steganography) and verisoo (v0.1.0, attestation) as subpackages under soosef.stegasoo and soosef.verisoo. This eliminates cross-repo coordination and enables atomic changes across the full stack. - Copy stegasoo (34 modules) and verisoo (15 modules) into src/soosef/ - Convert all verisoo absolute imports to relative imports - Rewire ~50 import sites across soosef code (cli, web, keystore, tests) - Replace stegasoo/verisoo pip deps with inlined code + pip extras (stego-dct, stego-audio, attest, web, api, cli, fieldkit, all, dev) - Add _availability.py for runtime feature detection - Add unified FastAPI mount point at soosef.api - Copy and adapt tests from both repos (155 pass, 1 skip) - Drop standalone CLI/web frontends; keep FastAPI as optional modules - Both source repos tagged pre-monorepo-consolidation on GitHub Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -123,8 +123,8 @@ def create_app(config: SoosefConfig | None = None) -> Flask:
|
||||
|
||||
# Stegasoo capabilities
|
||||
try:
|
||||
from stegasoo import HAS_AUDIO_SUPPORT, get_channel_status, has_dct_support
|
||||
from stegasoo.constants import (
|
||||
from soosef.stegasoo import HAS_AUDIO_SUPPORT, get_channel_status, has_dct_support
|
||||
from soosef.stegasoo.constants import (
|
||||
DEFAULT_PASSPHRASE_WORDS,
|
||||
MAX_FILE_PAYLOAD_SIZE,
|
||||
MAX_MESSAGE_CHARS,
|
||||
@@ -164,7 +164,7 @@ def create_app(config: SoosefConfig | None = None) -> Flask:
|
||||
|
||||
# Verisoo availability
|
||||
try:
|
||||
import verisoo # noqa: F401
|
||||
import soosef.verisoo # noqa: F401
|
||||
|
||||
has_verisoo = True
|
||||
except ImportError:
|
||||
@@ -241,13 +241,13 @@ def _register_stegasoo_routes(app: Flask) -> None:
|
||||
"""
|
||||
import temp_storage
|
||||
from auth import admin_required, login_required
|
||||
from stegasoo import (
|
||||
from soosef.stegasoo import (
|
||||
export_rsa_key_pem,
|
||||
generate_credentials,
|
||||
get_channel_status,
|
||||
load_rsa_key,
|
||||
)
|
||||
from stegasoo.constants import (
|
||||
from soosef.stegasoo.constants import (
|
||||
DEFAULT_PASSPHRASE_WORDS,
|
||||
MAX_PIN_LENGTH,
|
||||
MIN_PASSPHRASE_WORDS,
|
||||
@@ -255,7 +255,7 @@ def _register_stegasoo_routes(app: Flask) -> None:
|
||||
TEMP_FILE_EXPIRY,
|
||||
VALID_RSA_SIZES,
|
||||
)
|
||||
from stegasoo.qr_utils import (
|
||||
from soosef.stegasoo.qr_utils import (
|
||||
can_fit_in_qr,
|
||||
generate_qr_code,
|
||||
)
|
||||
|
||||
@@ -273,7 +273,7 @@ def verify_and_reset_admin_password(recovery_key: str, new_password: str) -> tup
|
||||
Returns:
|
||||
(success, message) tuple
|
||||
"""
|
||||
from stegasoo.recovery import verify_recovery_key
|
||||
from soosef.stegasoo.recovery import verify_recovery_key
|
||||
|
||||
stored_hash = get_recovery_key_hash()
|
||||
if not stored_hash:
|
||||
|
||||
@@ -21,7 +21,7 @@ bp = Blueprint("attest", __name__)
|
||||
|
||||
def _get_storage():
|
||||
"""Get verisoo LocalStorage pointed at soosef's attestation directory."""
|
||||
from verisoo.storage import LocalStorage
|
||||
from soosef.verisoo.storage import LocalStorage
|
||||
|
||||
from soosef.paths import ATTESTATIONS_DIR
|
||||
|
||||
@@ -30,7 +30,7 @@ def _get_storage():
|
||||
|
||||
def _get_private_key():
|
||||
"""Load the Ed25519 private key from soosef identity directory."""
|
||||
from verisoo.crypto import load_private_key
|
||||
from soosef.verisoo.crypto import load_private_key
|
||||
|
||||
from soosef.paths import IDENTITY_PRIVATE_KEY
|
||||
|
||||
@@ -139,7 +139,7 @@ def attest():
|
||||
auto_exif = request.form.get("auto_exif", "on") == "on"
|
||||
|
||||
# Create the attestation
|
||||
from verisoo.attestation import create_attestation
|
||||
from soosef.verisoo.attestation import create_attestation
|
||||
|
||||
attestation = create_attestation(
|
||||
image_data=image_data,
|
||||
@@ -167,7 +167,7 @@ def attest():
|
||||
|
||||
# Save our own identity so we can look it up during verification
|
||||
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
|
||||
from verisoo.models import Identity
|
||||
from soosef.verisoo.models import Identity
|
||||
|
||||
pub_key = private_key.public_key()
|
||||
pub_bytes = pub_key.public_bytes(Encoding.Raw, PublicFormat.Raw)
|
||||
@@ -217,7 +217,7 @@ def _verify_image(image_data: bytes) -> dict:
|
||||
matches — list of match dicts (record, match_type, distances, attestor_name)
|
||||
record_count — total records searched
|
||||
"""
|
||||
from verisoo.hashing import compute_all_distances, hash_image, is_same_image
|
||||
from soosef.verisoo.hashing import compute_all_distances, hash_image, is_same_image
|
||||
|
||||
query_hashes = hash_image(image_data)
|
||||
storage = _get_storage()
|
||||
|
||||
@@ -41,7 +41,7 @@ def register_stego_routes(app, **deps):
|
||||
temp_storage = deps["temp_storage"]
|
||||
_has_qrcode_read = deps.get("has_qrcode_read", False)
|
||||
|
||||
from stegasoo import (
|
||||
from soosef.stegasoo import (
|
||||
HAS_AUDIO_SUPPORT,
|
||||
CapacityError,
|
||||
DecryptionError,
|
||||
@@ -60,13 +60,13 @@ def register_stego_routes(app, **deps):
|
||||
validate_rsa_key,
|
||||
validate_security_factors,
|
||||
)
|
||||
from stegasoo.channel import resolve_channel_key
|
||||
from stegasoo.constants import (
|
||||
from soosef.stegasoo.channel import resolve_channel_key
|
||||
from soosef.stegasoo.constants import (
|
||||
TEMP_FILE_EXPIRY,
|
||||
THUMBNAIL_QUALITY,
|
||||
THUMBNAIL_SIZE,
|
||||
)
|
||||
from stegasoo.qr_utils import (
|
||||
from soosef.stegasoo.qr_utils import (
|
||||
decompress_data,
|
||||
extract_key_from_qr,
|
||||
is_compressed,
|
||||
@@ -686,7 +686,7 @@ def register_stego_routes(app, **deps):
|
||||
return _error_response(result.error_message)
|
||||
|
||||
# Pre-check payload capacity BEFORE encode (fail fast)
|
||||
from stegasoo.steganography import will_fit_by_mode
|
||||
from soosef.stegasoo.steganography import will_fit_by_mode
|
||||
|
||||
payload_size = (
|
||||
len(payload.data) if hasattr(payload, "data") else len(payload.encode("utf-8"))
|
||||
@@ -1613,8 +1613,8 @@ def register_stego_routes(app, **deps):
|
||||
@app.route("/about")
|
||||
def about():
|
||||
from auth import get_current_user
|
||||
from stegasoo import has_argon2
|
||||
from stegasoo.channel import get_channel_status
|
||||
from soosef.stegasoo import has_argon2
|
||||
from soosef.stegasoo.channel import get_channel_status
|
||||
|
||||
channel_status = get_channel_status()
|
||||
current_user = get_current_user()
|
||||
@@ -1644,7 +1644,7 @@ def register_stego_routes(app, **deps):
|
||||
@login_required
|
||||
def api_tools_capacity():
|
||||
"""Calculate image capacity for steganography."""
|
||||
from stegasoo.dct_steganography import estimate_capacity_comparison
|
||||
from soosef.stegasoo.dct_steganography import estimate_capacity_comparison
|
||||
|
||||
carrier = request.files.get("image")
|
||||
if not carrier:
|
||||
@@ -1666,7 +1666,7 @@ def register_stego_routes(app, **deps):
|
||||
"""Strip EXIF/metadata from image."""
|
||||
import io
|
||||
|
||||
from stegasoo.utils import strip_image_metadata
|
||||
from soosef.stegasoo.utils import strip_image_metadata
|
||||
|
||||
image_file = request.files.get("image")
|
||||
if not image_file:
|
||||
@@ -1689,7 +1689,7 @@ def register_stego_routes(app, **deps):
|
||||
@login_required
|
||||
def api_tools_exif():
|
||||
"""Read EXIF metadata from image."""
|
||||
from stegasoo.utils import read_image_exif
|
||||
from soosef.stegasoo.utils import read_image_exif
|
||||
|
||||
image_file = request.files.get("image")
|
||||
if not image_file:
|
||||
@@ -1718,7 +1718,7 @@ def register_stego_routes(app, **deps):
|
||||
@login_required
|
||||
def api_tools_exif_update():
|
||||
"""Update EXIF fields in image."""
|
||||
from stegasoo.utils import write_image_exif
|
||||
from soosef.stegasoo.utils import write_image_exif
|
||||
|
||||
image_file = request.files.get("image")
|
||||
if not image_file:
|
||||
@@ -1757,7 +1757,7 @@ def register_stego_routes(app, **deps):
|
||||
@login_required
|
||||
def api_tools_exif_clear():
|
||||
"""Remove all EXIF metadata from image."""
|
||||
from stegasoo.utils import strip_image_metadata
|
||||
from soosef.stegasoo.utils import strip_image_metadata
|
||||
|
||||
image_file = request.files.get("image")
|
||||
if not image_file:
|
||||
|
||||
@@ -73,7 +73,7 @@ def _get_channel_info(resolved_key):
|
||||
Returns:
|
||||
(mode, fingerprint) tuple
|
||||
"""
|
||||
from stegasoo import get_channel_status, has_channel_key
|
||||
from soosef.stegasoo import get_channel_status, has_channel_key
|
||||
|
||||
if resolved_key == "":
|
||||
return "public", None
|
||||
@@ -94,7 +94,7 @@ def _get_channel_info(resolved_key):
|
||||
def encode_operation(params: dict) -> dict:
|
||||
"""Handle encode operation."""
|
||||
logger.debug("encode_operation: mode=%s", params.get("embed_mode", "lsb"))
|
||||
from stegasoo import FilePayload, encode
|
||||
from soosef.stegasoo import FilePayload, encode
|
||||
|
||||
# Decode base64 inputs
|
||||
carrier_data = base64.b64decode(params["carrier_b64"])
|
||||
@@ -173,7 +173,7 @@ def _write_decode_progress(progress_file: str | None, percent: int, phase: str)
|
||||
def decode_operation(params: dict) -> dict:
|
||||
"""Handle decode operation."""
|
||||
logger.debug("decode_operation: mode=%s", params.get("embed_mode", "auto"))
|
||||
from stegasoo import decode
|
||||
from soosef.stegasoo import decode
|
||||
|
||||
progress_file = params.get("progress_file")
|
||||
|
||||
@@ -227,7 +227,7 @@ def decode_operation(params: dict) -> dict:
|
||||
|
||||
def compare_operation(params: dict) -> dict:
|
||||
"""Handle compare_modes operation."""
|
||||
from stegasoo import compare_modes
|
||||
from soosef.stegasoo import compare_modes
|
||||
|
||||
carrier_data = base64.b64decode(params["carrier_b64"])
|
||||
result = compare_modes(carrier_data)
|
||||
@@ -240,7 +240,7 @@ def compare_operation(params: dict) -> dict:
|
||||
|
||||
def capacity_check_operation(params: dict) -> dict:
|
||||
"""Handle will_fit_by_mode operation."""
|
||||
from stegasoo import will_fit_by_mode
|
||||
from soosef.stegasoo import will_fit_by_mode
|
||||
|
||||
carrier_data = base64.b64decode(params["carrier_b64"])
|
||||
|
||||
@@ -259,7 +259,7 @@ def capacity_check_operation(params: dict) -> dict:
|
||||
def encode_audio_operation(params: dict) -> dict:
|
||||
"""Handle audio encode operation (v4.3.0)."""
|
||||
logger.debug("encode_audio_operation: mode=%s", params.get("embed_mode", "audio_lsb"))
|
||||
from stegasoo import FilePayload, encode_audio
|
||||
from soosef.stegasoo import FilePayload, encode_audio
|
||||
|
||||
carrier_data = base64.b64decode(params["carrier_b64"])
|
||||
reference_data = base64.b64decode(params["reference_b64"])
|
||||
@@ -324,7 +324,7 @@ def encode_audio_operation(params: dict) -> dict:
|
||||
def decode_audio_operation(params: dict) -> dict:
|
||||
"""Handle audio decode operation (v4.3.0)."""
|
||||
logger.debug("decode_audio_operation: mode=%s", params.get("embed_mode", "audio_auto"))
|
||||
from stegasoo import decode_audio
|
||||
from soosef.stegasoo import decode_audio
|
||||
|
||||
progress_file = params.get("progress_file")
|
||||
_write_decode_progress(progress_file, 5, "reading")
|
||||
@@ -370,9 +370,9 @@ def decode_audio_operation(params: dict) -> dict:
|
||||
|
||||
def audio_info_operation(params: dict) -> dict:
|
||||
"""Handle audio info operation (v4.3.0)."""
|
||||
from stegasoo import get_audio_info
|
||||
from stegasoo.audio_steganography import calculate_audio_lsb_capacity
|
||||
from stegasoo.spread_steganography import calculate_audio_spread_capacity
|
||||
from soosef.stegasoo import get_audio_info
|
||||
from soosef.stegasoo.audio_steganography import calculate_audio_lsb_capacity
|
||||
from soosef.stegasoo.spread_steganography import calculate_audio_spread_capacity
|
||||
|
||||
audio_data = base64.b64decode(params["audio_b64"])
|
||||
|
||||
@@ -397,7 +397,7 @@ def audio_info_operation(params: dict) -> dict:
|
||||
|
||||
def channel_status_operation(params: dict) -> dict:
|
||||
"""Handle channel status check (v4.0.0)."""
|
||||
from stegasoo import get_channel_status
|
||||
from soosef.stegasoo import get_channel_status
|
||||
|
||||
status = get_channel_status()
|
||||
reveal = params.get("reveal", False)
|
||||
|
||||
Reference in New Issue
Block a user