Complete rebrand cleanup: remaining env vars and references
Fix STEGASOO_* env vars → FIELDWITNESS_* and VERISOO_* → FIELDWITNESS_* across stego module, attest module, and frontends. Wire format identifiers (VERISOO\x00 magic bytes, STEGASOO-Z: QR prefixes) intentionally preserved for backwards compatibility. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
490f9d4a1d
commit
88f5571bf9
10
CLAUDE.md
10
CLAUDE.md
@ -34,9 +34,9 @@ src/fieldwitness/ Core library
|
||||
__init__.py Package init, __version__ (0.2.0)
|
||||
_availability.py Runtime checks for optional subpackages (has_stego, has_attest)
|
||||
api.py Optional unified FastAPI app (uvicorn fieldwitness.api:app)
|
||||
audit.py Append-only JSON-lines audit log (~/.fieldwitness/audit.jsonl)
|
||||
audit.py Append-only JSON-lines audit log (~/.fwmetadata/audit.jsonl)
|
||||
cli.py Click CLI entry point (fieldwitness command)
|
||||
paths.py All ~/.fieldwitness/* path constants (single source of truth, lazy resolution)
|
||||
paths.py All ~/.fwmetadata/* path constants (single source of truth, lazy resolution)
|
||||
config.py Unified config loader (FieldWitnessConfig dataclass + JSON)
|
||||
exceptions.py FieldWitnessError, ChainError, ChainIntegrityError, ChainAppendError, KeystoreError
|
||||
metadata.py Extract-then-strip EXIF pipeline with field classification
|
||||
@ -179,7 +179,7 @@ Stego and Attest are inlined subpackages, not separate pip packages:
|
||||
- **Extract-then-strip model**: Stego strips all EXIF (carrier is vessel); attestation
|
||||
extracts evidentiary EXIF (GPS, timestamp) then strips dangerous fields (device serial)
|
||||
- **subprocess_stego.py copies verbatim** from fieldwitness.stego -- it's a crash-safety boundary
|
||||
- **All state under ~/.fieldwitness/** -- one directory to back up, one to destroy.
|
||||
- **All state under ~/.fwmetadata/** -- one directory to back up, one to destroy.
|
||||
`FIELDWITNESS_DATA_DIR` env var relocates everything (cover mode, USB mode)
|
||||
- **Offline-first**: All static assets vendored, no CDN. pip wheels bundled for airgap install
|
||||
- **Flask blueprints**: stego, attest, fieldkit, keys, admin, dropbox, federation
|
||||
@ -208,10 +208,10 @@ Stego and Attest are inlined subpackages, not separate pip packages:
|
||||
- **Transport-aware stego**: --transport whatsapp|signal|telegram auto-selects DCT/JPEG
|
||||
and pre-resizes carrier for platform survival
|
||||
|
||||
## Data directory layout (`~/.fieldwitness/`)
|
||||
## Data directory layout (`~/.fwmetadata/`)
|
||||
|
||||
```
|
||||
~/.fieldwitness/
|
||||
~/.fwmetadata/
|
||||
config.json Unified configuration (FieldWitnessConfig dataclass)
|
||||
audit.jsonl Append-only audit trail (JSON-lines)
|
||||
carrier_history.json Carrier reuse tracking database
|
||||
|
||||
18
README.md
18
README.md
@ -48,7 +48,7 @@ fieldwitness init
|
||||
fieldwitness serve
|
||||
```
|
||||
|
||||
This creates the `~/.fieldwitness/` directory structure, generates an Ed25519 identity and
|
||||
This creates the `~/.fwmetadata/` directory structure, generates an Ed25519 identity and
|
||||
channel key, writes a default config, and starts an HTTPS web UI on
|
||||
`https://127.0.0.1:5000`.
|
||||
|
||||
@ -146,7 +146,7 @@ responses.
|
||||
|
||||
### Field Security (Fieldkit)
|
||||
|
||||
- **Killswitch** -- emergency destruction of all data under `~/.fieldwitness/`, ordered by
|
||||
- **Killswitch** -- emergency destruction of all data under `~/.fwmetadata/`, ordered by
|
||||
sensitivity (keys first, then data, then logs). Includes:
|
||||
- **Deep forensic scrub** -- removes `__pycache__`, `.pyc`, pip `dist-info`, pip
|
||||
download cache, and scrubs shell history entries containing "fieldwitness"
|
||||
@ -307,7 +307,7 @@ FieldWitness ships four configuration presets at `deploy/config-presets/`:
|
||||
| `critical-threat.json` | 3 min | On | 6h / 1h grace | "System Statistics" |
|
||||
|
||||
```bash
|
||||
cp deploy/config-presets/high-threat.json ~/.fieldwitness/config.json
|
||||
cp deploy/config-presets/high-threat.json ~/.fwmetadata/config.json
|
||||
```
|
||||
|
||||
See [docs/deployment.md](docs/deployment.md) for the full deployment guide including
|
||||
@ -317,7 +317,7 @@ security hardening, Kubernetes manifests, systemd services, and operational secu
|
||||
|
||||
## CLI Reference
|
||||
|
||||
All commands accept `--data-dir PATH` to override the default `~/.fieldwitness` directory,
|
||||
All commands accept `--data-dir PATH` to override the default `~/.fwmetadata` directory,
|
||||
and `--json` for machine-readable output.
|
||||
|
||||
```
|
||||
@ -488,7 +488,7 @@ through Flask blueprints. Served by **Waitress** (production WSGI server) by def
|
||||
|
||||
## Configuration
|
||||
|
||||
FieldWitness loads configuration from `~/.fieldwitness/config.json`. All fields have sensible defaults.
|
||||
FieldWitness loads configuration from `~/.fwmetadata/config.json`. All fields have sensible defaults.
|
||||
`fieldwitness init` writes the default config file.
|
||||
|
||||
### Config fields
|
||||
@ -522,7 +522,7 @@ FieldWitness loads configuration from `~/.fieldwitness/config.json`. All fields
|
||||
|
||||
| Variable | Description |
|
||||
|---|---|
|
||||
| `FIELDWITNESS_DATA_DIR` | Override the data directory (default: `~/.fieldwitness`). Enables portable USB mode and cover/duress directory naming |
|
||||
| `FIELDWITNESS_DATA_DIR` | Override the data directory (default: `~/.fwmetadata`). Enables portable USB mode and cover/duress directory naming |
|
||||
|
||||
---
|
||||
|
||||
@ -582,10 +582,10 @@ deploy/ Deployment artifacts
|
||||
config-presets/ Threat level presets (low/medium/high/critical)
|
||||
```
|
||||
|
||||
### Data directory (`~/.fieldwitness/`)
|
||||
### Data directory (`~/.fwmetadata/`)
|
||||
|
||||
```
|
||||
~/.fieldwitness/
|
||||
~/.fwmetadata/
|
||||
config.json Unified configuration
|
||||
audit.jsonl Append-only audit trail
|
||||
carrier_history.json Carrier reuse tracking database
|
||||
@ -612,7 +612,7 @@ Sensitive directories (`identity/`, `auth/`, `certs/`, and the root) are created
|
||||
Argon2id from user-supplied factors. Attest uses Ed25519 for signing. These serve
|
||||
different security purposes and are kept strictly separate.
|
||||
|
||||
**Killswitch priority.** The killswitch destroys all data under `~/.fieldwitness/`, including
|
||||
**Killswitch priority.** The killswitch destroys all data under `~/.fwmetadata/`, including
|
||||
the audit log. This is intentional -- in a field compromise scenario, data destruction
|
||||
takes precedence over audit trail preservation. The deep forensic scrub extends beyond
|
||||
the data directory to remove Python bytecache, pip metadata, pip download cache, shell
|
||||
|
||||
@ -593,7 +593,7 @@ RestartSec=5
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=strict
|
||||
ProtectHome=read-only
|
||||
ReadWritePaths=/home/fieldwitness/.fieldwitness
|
||||
ReadWritePaths=/home/fieldwitness/.fwmetadata
|
||||
PrivateTmp=yes
|
||||
|
||||
[Install]
|
||||
|
||||
@ -1602,7 +1602,7 @@ const Stego = {
|
||||
// Webcam QR scanning for RSA key (v4.1.5)
|
||||
document.getElementById('rsaQrWebcam')?.addEventListener('click', () => {
|
||||
this.showQrScanner((text) => {
|
||||
// Check for raw PEM or compressed format (STEGASOO-Z: prefix)
|
||||
// Check for raw PEM or compressed format (legacy STEGASOO-Z: prefix)
|
||||
const isRawPem = text.includes('-----BEGIN') && text.includes('KEY-----');
|
||||
const isCompressed = text.startsWith('STEGASOO-Z:');
|
||||
if (isRawPem || isCompressed) {
|
||||
@ -1672,7 +1672,7 @@ const Stego = {
|
||||
// Webcam QR scanning for RSA key (v4.1.5)
|
||||
document.getElementById('rsaQrWebcam')?.addEventListener('click', () => {
|
||||
this.showQrScanner((text) => {
|
||||
// Check for raw PEM or compressed format (STEGASOO-Z: prefix)
|
||||
// Check for raw PEM or compressed format (legacy STEGASOO-Z: prefix)
|
||||
const isRawPem = text.includes('-----BEGIN') && text.includes('KEY-----');
|
||||
const isCompressed = text.startsWith('STEGASOO-Z:');
|
||||
if (isRawPem || isCompressed) {
|
||||
|
||||
@ -325,7 +325,7 @@
|
||||
<div class="alert alert-info mt-3 mb-0">
|
||||
<i class="bi bi-info-circle me-2"></i>
|
||||
This server is running in <strong>public mode</strong>.
|
||||
Set <code>STEGASOO_CHANNEL_KEY</code> to enable server-wide channel isolation.
|
||||
Set <code>FIELDWITNESS_CHANNEL_KEY</code> to enable server-wide channel isolation.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@ -33,7 +33,7 @@ from .crypto import verify_signature, load_public_key_from_bytes
|
||||
|
||||
# Configuration via environment
|
||||
DATA_DIR = Path(os.environ.get("FIELDWITNESS_DATA_DIR", Path.home() / ".fieldwitness"))
|
||||
BASE_URL = os.environ.get("VERISOO_BASE_URL", "https://attest.io")
|
||||
BASE_URL = os.environ.get("FIELDWITNESS_BASE_URL", "https://attest.io")
|
||||
|
||||
app = FastAPI(
|
||||
title="Attest",
|
||||
|
||||
@ -686,8 +686,8 @@ def serve(host: str, port: int) -> None:
|
||||
|
||||
\b
|
||||
ENVIRONMENT VARIABLES:
|
||||
VERISOO_DATA_DIR Override data directory
|
||||
VERISOO_BASE_URL Base URL for proof links (default: https://attest.io)
|
||||
FIELDWITNESS_DATA_DIR Override data directory
|
||||
FIELDWITNESS_BASE_URL Base URL for proof links (default: https://attest.io)
|
||||
|
||||
\b
|
||||
SECURITY NOTES:
|
||||
|
||||
@ -37,9 +37,9 @@ try:
|
||||
has_jpegio_support,
|
||||
calculate_dct_capacity,
|
||||
)
|
||||
HAS_STEGASOO = True
|
||||
HAS_STEGO = True
|
||||
except ImportError:
|
||||
HAS_STEGASOO = False
|
||||
HAS_STEGO = False
|
||||
has_dct_support = lambda: False
|
||||
has_jpegio_support = lambda: False
|
||||
|
||||
@ -50,7 +50,7 @@ except ImportError:
|
||||
|
||||
# Fixed public seed for Attest proof links
|
||||
# This is intentionally public - anyone should be able to extract the proof link
|
||||
VERISOO_SEED = b"attest"
|
||||
ATTEST_SEED = b"attest"
|
||||
|
||||
# Base URL for proof links
|
||||
DEFAULT_BASE_URL = "https://attest.io"
|
||||
@ -250,7 +250,7 @@ def embed_proof_in_jpeg(
|
||||
ImportError: If stego is not available
|
||||
ValueError: If image is too small or embedding fails
|
||||
"""
|
||||
if not HAS_STEGASOO:
|
||||
if not HAS_STEGO:
|
||||
raise ImportError(
|
||||
"DCT embedding requires stego. "
|
||||
"Ensure stego is installed or available at ../stego"
|
||||
@ -268,7 +268,7 @@ def embed_proof_in_jpeg(
|
||||
stego_bytes, stats = embed_in_dct(
|
||||
data=payload,
|
||||
carrier_image=image_data,
|
||||
seed=VERISOO_SEED,
|
||||
seed=ATTEST_SEED,
|
||||
output_format="jpeg",
|
||||
color_mode="color",
|
||||
)
|
||||
@ -291,13 +291,13 @@ def extract_proof_from_jpeg(image_data: bytes) -> str | None:
|
||||
Returns:
|
||||
Proof URL string or None if not found/invalid
|
||||
"""
|
||||
if not HAS_STEGASOO:
|
||||
if not HAS_STEGO:
|
||||
return None
|
||||
|
||||
try:
|
||||
payload = extract_from_dct(
|
||||
stego_image=image_data,
|
||||
seed=VERISOO_SEED,
|
||||
seed=ATTEST_SEED,
|
||||
)
|
||||
|
||||
# Validate it looks like a proof link
|
||||
@ -327,7 +327,7 @@ def get_embed_method(image_path: Path) -> str:
|
||||
suffix = image_path.suffix.lower()
|
||||
|
||||
if suffix in DCT_FORMATS:
|
||||
if HAS_STEGASOO and has_jpegio_support():
|
||||
if HAS_STEGO and has_jpegio_support():
|
||||
return "dct"
|
||||
else:
|
||||
return "xmp" # Fallback to XMP if stego unavailable
|
||||
@ -485,7 +485,7 @@ def extract_proof_link(image_path: Path) -> ExtractResult:
|
||||
suffix = image_path.suffix.lower()
|
||||
|
||||
# Try DCT for JPEG
|
||||
if suffix in DCT_FORMATS and HAS_STEGASOO:
|
||||
if suffix in DCT_FORMATS and HAS_STEGO:
|
||||
try:
|
||||
image_data = image_path.read_bytes()
|
||||
proof_link = extract_proof_from_jpeg(image_data)
|
||||
@ -523,14 +523,14 @@ def extract_proof_link(image_path: Path) -> ExtractResult:
|
||||
|
||||
def can_embed_dct() -> bool:
|
||||
"""Check if DCT embedding is available."""
|
||||
return HAS_STEGASOO and has_jpegio_support()
|
||||
return HAS_STEGO and has_jpegio_support()
|
||||
|
||||
|
||||
def get_embed_capabilities() -> dict[str, Any]:
|
||||
"""Get information about available embedding capabilities."""
|
||||
return {
|
||||
"dct_available": HAS_STEGASOO and has_dct_support(),
|
||||
"jpeg_native": HAS_STEGASOO and has_jpegio_support(),
|
||||
"dct_available": HAS_STEGO and has_dct_support(),
|
||||
"jpeg_native": HAS_STEGO and has_jpegio_support(),
|
||||
"xmp_available": True, # Always available
|
||||
"supported_dct_formats": list(DCT_FORMATS) if can_embed_dct() else [],
|
||||
"supported_xmp_formats": list(XMP_FORMATS | RAW_FORMATS),
|
||||
|
||||
@ -199,11 +199,11 @@ class KeystoreManager:
|
||||
|
||||
def has_channel_key(self) -> bool:
|
||||
"""Check if a channel key is configured."""
|
||||
return bool(os.environ.get("STEGASOO_CHANNEL_KEY")) or self._channel_key_file.exists()
|
||||
return bool(os.environ.get("FIELDWITNESS_CHANNEL_KEY")) or self._channel_key_file.exists()
|
||||
|
||||
def get_channel_key(self) -> str | None:
|
||||
"""Get the channel key, or None if not configured."""
|
||||
env_key = os.environ.get("STEGASOO_CHANNEL_KEY")
|
||||
env_key = os.environ.get("FIELDWITNESS_CHANNEL_KEY")
|
||||
if env_key:
|
||||
return env_key
|
||||
if self._channel_key_file.exists():
|
||||
@ -246,7 +246,7 @@ class KeystoreManager:
|
||||
# representation to back up, so we refuse rather than silently skip.
|
||||
if not self._channel_key_file.exists():
|
||||
raise KeystoreError(
|
||||
"Channel key is set via STEGASOO_CHANNEL_KEY environment variable "
|
||||
"Channel key is set via FIELDWITNESS_CHANNEL_KEY environment variable "
|
||||
"and cannot be rotated through fieldwitness. Unset the variable and store "
|
||||
"the key in the keystore first."
|
||||
)
|
||||
|
||||
@ -30,7 +30,7 @@ _PATH_DEFS: dict[str, tuple[str, ...]] = {
|
||||
# on fragile filesystem mtime.
|
||||
"IDENTITY_META": ("identity", "identity.meta.json"),
|
||||
# Stego state
|
||||
"STEGASOO_DIR": ("stego",),
|
||||
"FIELDWITNESS_DIR": ("stego",),
|
||||
"CHANNEL_KEY_FILE": ("stego", "channel.key"),
|
||||
# Attest attestation storage
|
||||
"ATTESTATIONS_DIR": ("attestations",),
|
||||
@ -84,7 +84,7 @@ def ensure_dirs() -> None:
|
||||
dirs = [
|
||||
BASE_DIR,
|
||||
__getattr__("IDENTITY_DIR"),
|
||||
__getattr__("STEGASOO_DIR"),
|
||||
__getattr__("FIELDWITNESS_DIR"),
|
||||
__getattr__("ATTESTATIONS_DIR"),
|
||||
__getattr__("CHAIN_DIR"),
|
||||
__getattr__("AUTH_DIR"),
|
||||
|
||||
@ -22,7 +22,7 @@ from .channel import (
|
||||
validate_channel_key,
|
||||
)
|
||||
|
||||
# Audio support — gated by STEGASOO_AUDIO env var and dependency availability
|
||||
# Audio support — gated by FIELDWITNESS_AUDIO env var and dependency availability
|
||||
from .constants import AUDIO_ENABLED, VIDEO_ENABLED
|
||||
|
||||
# Crypto functions
|
||||
@ -87,7 +87,7 @@ else:
|
||||
encode_audio = None
|
||||
decode_audio = None
|
||||
|
||||
# Video support — gated by STEGASOO_VIDEO env var and ffmpeg + audio deps
|
||||
# Video support — gated by FIELDWITNESS_VIDEO env var and ffmpeg + audio deps
|
||||
if VIDEO_ENABLED:
|
||||
from .decode import decode_video
|
||||
from .encode import encode_video
|
||||
|
||||
@ -45,7 +45,7 @@ from pathlib import Path
|
||||
from typing import Literal
|
||||
|
||||
# Configure logging for API frontend
|
||||
_log_level = os.environ.get("STEGASOO_LOG_LEVEL", "").strip().upper()
|
||||
_log_level = os.environ.get("FIELDWITNESS_LOG_LEVEL", "").strip().upper()
|
||||
if _log_level and hasattr(logging, _log_level):
|
||||
logging.basicConfig(
|
||||
level=getattr(logging, _log_level),
|
||||
@ -53,7 +53,7 @@ if _log_level and hasattr(logging, _log_level):
|
||||
datefmt="%H:%M:%S",
|
||||
stream=sys.stderr,
|
||||
)
|
||||
elif os.environ.get("STEGASOO_DEBUG", "").strip() in ("1", "true", "yes"):
|
||||
elif os.environ.get("FIELDWITNESS_DEBUG", "").strip() in ("1", "true", "yes"):
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
format="[%(asctime)s.%(msecs)03d] [%(levelname)s] [%(name)s] %(message)s",
|
||||
|
||||
@ -32,7 +32,7 @@ PROJECT_CONFIG_DIR = Path("./config")
|
||||
API_KEYS_FILE = "api_keys.json"
|
||||
|
||||
# Environment variable for API key (alternative to file)
|
||||
API_KEY_ENV_VAR = "STEGASOO_API_KEY"
|
||||
API_KEY_ENV_VAR = "FIELDWITNESS_API_KEY"
|
||||
|
||||
|
||||
def _hash_key(key: str) -> str:
|
||||
|
||||
@ -12,7 +12,7 @@ Use cases:
|
||||
- Public instances: No channel key = compatible with any instance without a channel key
|
||||
|
||||
Storage priority:
|
||||
1. Environment variable: STEGASOO_CHANNEL_KEY
|
||||
1. Environment variable: FIELDWITNESS_CHANNEL_KEY
|
||||
2. Config file: ~/.stego/channel.key or ./config/channel.key
|
||||
3. None (public mode - compatible with any instance without a channel key)
|
||||
|
||||
@ -39,7 +39,7 @@ CHANNEL_KEY_LENGTH = 32 # Characters (excluding dashes)
|
||||
CHANNEL_KEY_FORMATTED_LENGTH = 39 # With dashes
|
||||
|
||||
# Environment variable name
|
||||
CHANNEL_KEY_ENV_VAR = "STEGASOO_CHANNEL_KEY"
|
||||
CHANNEL_KEY_ENV_VAR = "FIELDWITNESS_CHANNEL_KEY"
|
||||
|
||||
# Config locations (in priority order)
|
||||
CONFIG_LOCATIONS = [
|
||||
@ -200,7 +200,7 @@ def get_channel_key() -> str | None:
|
||||
Get the current channel key from environment or config.
|
||||
|
||||
Checks in order:
|
||||
1. STEGASOO_CHANNEL_KEY environment variable
|
||||
1. FIELDWITNESS_CHANNEL_KEY environment variable
|
||||
2. ./config/channel.key file
|
||||
3. ~/.stego/channel.key file
|
||||
|
||||
|
||||
@ -533,7 +533,7 @@ def audio_encode(
|
||||
if not AUDIO_ENABLED:
|
||||
raise click.UsageError(
|
||||
"Audio support is disabled. Install audio extras (pip install stego[audio]) "
|
||||
"or set STEGASOO_AUDIO=1 to force enable."
|
||||
"or set FIELDWITNESS_AUDIO=1 to force enable."
|
||||
)
|
||||
|
||||
from .audio_steganography import calculate_audio_lsb_capacity
|
||||
@ -723,7 +723,7 @@ def audio_decode(
|
||||
if not AUDIO_ENABLED:
|
||||
raise click.UsageError(
|
||||
"Audio support is disabled. Install audio extras (pip install stego[audio]) "
|
||||
"or set STEGASOO_AUDIO=1 to force enable."
|
||||
"or set FIELDWITNESS_AUDIO=1 to force enable."
|
||||
)
|
||||
|
||||
from .decode import decode_audio
|
||||
@ -819,7 +819,7 @@ def audio_info(ctx, audio):
|
||||
if not AUDIO_ENABLED:
|
||||
raise click.UsageError(
|
||||
"Audio support is disabled. Install audio extras (pip install stego[audio]) "
|
||||
"or set STEGASOO_AUDIO=1 to force enable."
|
||||
"or set FIELDWITNESS_AUDIO=1 to force enable."
|
||||
)
|
||||
|
||||
from .audio_steganography import calculate_audio_lsb_capacity
|
||||
@ -964,7 +964,7 @@ def video_encode(
|
||||
if not VIDEO_ENABLED:
|
||||
raise click.UsageError(
|
||||
"Video support is disabled. Install ffmpeg and audio extras, "
|
||||
"or set STEGASOO_VIDEO=1 to force enable."
|
||||
"or set FIELDWITNESS_VIDEO=1 to force enable."
|
||||
)
|
||||
|
||||
from .encode import encode_video
|
||||
@ -1137,7 +1137,7 @@ def video_decode(
|
||||
if not VIDEO_ENABLED:
|
||||
raise click.UsageError(
|
||||
"Video support is disabled. Install ffmpeg and audio extras, "
|
||||
"or set STEGASOO_VIDEO=1 to force enable."
|
||||
"or set FIELDWITNESS_VIDEO=1 to force enable."
|
||||
)
|
||||
|
||||
from .decode import decode_video
|
||||
@ -1232,7 +1232,7 @@ def video_info(ctx, video):
|
||||
if not VIDEO_ENABLED:
|
||||
raise click.UsageError(
|
||||
"Video support is disabled. Install ffmpeg and audio extras, "
|
||||
"or set STEGASOO_VIDEO=1 to force enable."
|
||||
"or set FIELDWITNESS_VIDEO=1 to force enable."
|
||||
)
|
||||
|
||||
from .video_utils import calculate_video_capacity, get_video_info
|
||||
@ -1713,7 +1713,7 @@ def info(ctx, full):
|
||||
click.echo(json.dumps(info_data, indent=2))
|
||||
else:
|
||||
# Fastfetch-style output
|
||||
click.echo(f"\033[1mSTEGASOO\033[0m v{__version__}")
|
||||
click.echo(f"\033[1mFIELDWITNESS\033[0m v{__version__}")
|
||||
click.echo("─" * 36)
|
||||
|
||||
# Service status
|
||||
@ -1819,7 +1819,7 @@ def channel_generate(ctx, save, save_user):
|
||||
click.echo(f"Saved to: {path}")
|
||||
else:
|
||||
click.echo("To use this key:")
|
||||
click.echo(f' export STEGASOO_CHANNEL_KEY="{key}"')
|
||||
click.echo(f' export FIELDWITNESS_CHANNEL_KEY="{key}"')
|
||||
click.echo()
|
||||
click.echo("Or save to config:")
|
||||
click.echo(" stego channel generate --save")
|
||||
|
||||
@ -320,7 +320,7 @@ def detect_stego_mode(encrypted_data: bytes) -> str:
|
||||
# Environment variables to enable/disable optional feature families.
|
||||
# Values: "auto" (default — detect dependencies), "1"/"true" (force on),
|
||||
# "0"/"false" (force off even if deps are installed).
|
||||
# Pi builds or minimal installs can set STEGASOO_AUDIO=0 to stay image-only.
|
||||
# Pi builds or minimal installs can set FIELDWITNESS_AUDIO=0 to stay image-only.
|
||||
|
||||
import os as _os
|
||||
|
||||
@ -370,8 +370,8 @@ def _resolve_feature(toggle: str | bool, dep_check: callable) -> bool:
|
||||
return dep_check()
|
||||
|
||||
|
||||
_audio_toggle = _parse_feature_toggle("STEGASOO_AUDIO")
|
||||
_video_toggle = _parse_feature_toggle("STEGASOO_VIDEO")
|
||||
_audio_toggle = _parse_feature_toggle("FIELDWITNESS_AUDIO")
|
||||
_video_toggle = _parse_feature_toggle("FIELDWITNESS_VIDEO")
|
||||
|
||||
AUDIO_ENABLED: bool = _resolve_feature(_audio_toggle, _check_audio_deps)
|
||||
VIDEO_ENABLED: bool = _resolve_feature(_video_toggle, _check_video_deps)
|
||||
|
||||
@ -4,14 +4,14 @@ Stego Debugging Utilities
|
||||
Debugging, logging, and performance monitoring tools.
|
||||
|
||||
Configuration:
|
||||
STEGASOO_LOG_LEVEL env var controls log level:
|
||||
FIELDWITNESS_LOG_LEVEL env var controls log level:
|
||||
- Not set or empty: logging disabled (production default)
|
||||
- DEBUG: verbose debug output (encode/decode flow, crypto params, etc.)
|
||||
- INFO: operational messages (format detection, mode selection)
|
||||
- WARNING: potential issues (fallback KDF, format transcoding)
|
||||
- ERROR: operation failures
|
||||
|
||||
STEGASOO_DEBUG=1 is a shorthand for STEGASOO_LOG_LEVEL=DEBUG
|
||||
FIELDWITNESS_DEBUG=1 is a shorthand for FIELDWITNESS_LOG_LEVEL=DEBUG
|
||||
|
||||
CLI: stego --debug encode ... (sets DEBUG level for that invocation)
|
||||
|
||||
@ -47,12 +47,12 @@ VALIDATION_ASSERTIONS = True # Enable runtime validation assertions
|
||||
|
||||
def _configure_from_env() -> bool:
|
||||
"""Configure logging from environment variables. Returns True if debug enabled."""
|
||||
# STEGASOO_DEBUG=1 is shorthand for DEBUG level
|
||||
if os.environ.get("STEGASOO_DEBUG", "").strip() in ("1", "true", "yes"):
|
||||
# FIELDWITNESS_DEBUG=1 is shorthand for DEBUG level
|
||||
if os.environ.get("FIELDWITNESS_DEBUG", "").strip() in ("1", "true", "yes"):
|
||||
_setup_logging(logging.DEBUG)
|
||||
return True
|
||||
|
||||
level_str = os.environ.get("STEGASOO_LOG_LEVEL", "").strip().upper()
|
||||
level_str = os.environ.get("FIELDWITNESS_LOG_LEVEL", "").strip().upper()
|
||||
if level_str and level_str in _LEVEL_MAP:
|
||||
_setup_logging(_LEVEL_MAP[level_str])
|
||||
return level_str == "DEBUG"
|
||||
|
||||
@ -314,7 +314,7 @@ def decode_audio(
|
||||
if not AUDIO_ENABLED:
|
||||
raise ExtractionError(
|
||||
"Audio support is disabled. Install audio extras (pip install stego[audio]) "
|
||||
"or set STEGASOO_AUDIO=1 to force enable."
|
||||
"or set FIELDWITNESS_AUDIO=1 to force enable."
|
||||
)
|
||||
|
||||
from .audio_utils import detect_audio_format, transcode_to_wav
|
||||
@ -434,7 +434,7 @@ def decode_video(
|
||||
if not VIDEO_ENABLED:
|
||||
raise ExtractionError(
|
||||
"Video support is disabled. Install video extras and ffmpeg, "
|
||||
"or set STEGASOO_VIDEO=1 to force enable."
|
||||
"or set FIELDWITNESS_VIDEO=1 to force enable."
|
||||
)
|
||||
|
||||
from .video_utils import detect_video_format
|
||||
|
||||
@ -382,7 +382,7 @@ def encode_audio(
|
||||
if not AUDIO_ENABLED:
|
||||
raise AudioError(
|
||||
"Audio support is disabled. Install audio extras (pip install stego[audio]) "
|
||||
"or set STEGASOO_AUDIO=1 to force enable."
|
||||
"or set FIELDWITNESS_AUDIO=1 to force enable."
|
||||
)
|
||||
|
||||
from .audio_utils import detect_audio_format, transcode_to_wav
|
||||
@ -485,7 +485,7 @@ def encode_video(
|
||||
if not VIDEO_ENABLED:
|
||||
raise VideoError(
|
||||
"Video support is disabled. Install video extras and ffmpeg, "
|
||||
"or set STEGASOO_VIDEO=1 to force enable."
|
||||
"or set FIELDWITNESS_VIDEO=1 to force enable."
|
||||
)
|
||||
|
||||
from .video_utils import detect_video_format
|
||||
|
||||
Loading…
Reference in New Issue
Block a user