mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
* fix: remove all automatic third-party egress (OSM tiles, Scalar fonts, editor Google Fonts, AI model download fallbacks) Phone-home audit follow-up. The product no longer makes any automatic third-party request; user-initiated click-outs stay, and production now fails closed on missing AI models. 1. GPS leak via OSM tiles: the strip-metadata panel auto-loaded tile.openstreetmap.org tiles encoding the photo's GPS position. The Leaflet mini-map is gone; coordinates render as text plus an explicit View on map link (openstreetmap.org, opens on click only). Removed tile.openstreetmap.org from the CSP img-src, dropped the leaflet dependency, added the viewOnMap i18n key to all 21 locales. 2. Scalar docs fonts: /api/docs loaded Inter and JetBrains Mono from fonts.scalar.com. Scalar now renders with withDefaultFonts: false and both --scalar-font and --scalar-font-code pinned to system stacks; fonts.scalar.com removed from the docs CSP font-src. Verified by injecting GET /api/docs/: config carries withDefaultFonts false and the served page has no fonts.scalar.com reference. 3. Editor Google Fonts: the editor font picker built fonts.googleapis.com stylesheet URLs for 25 web fonts the served CSP already blocked. The remote loading path is deleted; the picker now offers system fonts only, with a SELF_HOSTED_FONTS seam (FontFace API, same origin) for bundling fonts later. Unknown families saved in old documents fall back to the browser default. 4. Python sidecar fails closed on model downloads: new packages/ai/python/offline_guard.py gates every runtime download fallback (inpaint, outpaint, restore, noise_removal, detect_faces, enhance_faces, face_landmarks, red_eye_removal, remove_bg, ocr, transcribe, upscale) behind SNAPOTTER_ALLOW_MODEL_DOWNLOAD=1 with an actionable error. Bundled models keep working untouched. 5. OCR and transcription library-internal downloads: unbundled PaddleOCR language and detection fallbacks now raise the guard error naming the language instead of resolving models over the network; faster-whisper gets local_files_only when downloads are off. 6. GFPGAN and CodeFormer cwd-relative weights: facexlib and codeformer-pip resolve helper weights relative to the process cwd and fetch them from GitHub when absent. They are now symlinked from the installed bundle files under MODELS_PATH/gfpgan/facelib before the libraries load, failing closed when unresolvable. Defense in depth: HF_HUB_OFFLINE=1 and TRANSFORMERS_OFFLINE=1 are set in the runtime image and in the sidecar spawn env; install_feature.py lifts them for user-initiated bundle installs and restores them afterwards (it can run in-process inside the dispatcher). SNAPOTTER_ALLOW_MODEL_DOWNLOAD is documented in .env.example, default off. Validation: typecheck 9/9 workspaces, Biome clean on touched files, 5178 unit tests pass, py_compile on all touched scripts, guard behavior exercised in both dispatcher exec and per-request import modes, zero remaining runtime references to the three hosts. Docker build and live AI inference need post-merge verification on the GPU host. Claude-Session: https://claude.ai/code/session_01XGB4pGvTvb7sUX4JN745U7 * fix: allow AI model downloads by default, make strict offline mode opt-in Product call: ease of use first. The download gating from the previous commit inverts its default: runtime model fetches (public model weights only, never user data) are allowed out of the box so AI tools self-heal, and SNAPOTTER_ALLOW_MODEL_DOWNLOAD=0 becomes the explicit strict offline mode for airgapped deployments, where every fallback raises the actionable error instead of fetching. Changes: offline_guard blocks only on an explicit 0/false; the unconditional HF_HUB_OFFLINE/TRANSFORMERS_OFFLINE image ENV is removed and bridge.ts sets those flags for the sidecar only in strict mode; .env.example documents the new default; install_feature's lift/restore stays. All bundled-path preferences, pre-existence checks, and symlink pre-placement remain, so installed bundles never trigger a download. The OSM, Scalar font, and editor font fixes are unchanged. Validation rerun: typecheck 9/9, Biome clean on touched files, 5178 unit tests pass, py_compile on touched scripts, guard behavior verified for unset/1 (allowed) and 0/false (blocked with the new message). Claude-Session: https://claude.ai/code/session_01XGB4pGvTvb7sUX4JN745U7
98 lines
3.3 KiB
Bash
98 lines
3.3 KiB
Bash
# Server
|
|
PORT=1349
|
|
AUTH_ENABLED=true
|
|
DEFAULT_USERNAME=admin
|
|
DEFAULT_PASSWORD=admin
|
|
STORAGE_MODE=local
|
|
|
|
# Cleanup
|
|
FILE_MAX_AGE_HOURS=72
|
|
CLEANUP_INTERVAL_MINUTES=60
|
|
|
|
# Upload & Batch (0 = unlimited)
|
|
MAX_UPLOAD_SIZE_MB=0
|
|
MAX_BATCH_SIZE=0
|
|
CONCURRENT_JOBS=0
|
|
MAX_MEGAPIXELS=0
|
|
|
|
# Rate limiting (0 = disabled)
|
|
RATE_LIMIT_PER_MIN=0
|
|
|
|
# Users (0 = unlimited)
|
|
MAX_USERS=0
|
|
|
|
# Processing (0 = auto/unlimited)
|
|
MAX_WORKER_THREADS=0
|
|
PROCESSING_TIMEOUT_S=0
|
|
MAX_PIPELINE_STEPS=0
|
|
MAX_CANVAS_PIXELS=0
|
|
MAX_SVG_SIZE_MB=0
|
|
MAX_LOGO_SIZE_KB=2048
|
|
MAX_SPLIT_GRID=100
|
|
MAX_PDF_PAGES=0
|
|
MAX_VIDEO_DURATION_S=0
|
|
MAX_AUDIO_DURATION_S=0
|
|
MAX_VIDEO_BITRATE_KBPS=0
|
|
LIBREOFFICE_TIMEOUT_S=120
|
|
# Engine binary overrides (default: $PATH lookup)
|
|
# FFMPEG_PATH=
|
|
# FFPROBE_PATH=
|
|
# QPDF_PATH=
|
|
# SOFFICE_PATH=
|
|
# PDFCPU_PATH=
|
|
# SNAPOTTER_HW_ACCEL= # nvenc|vaapi: hardware encoder family (default software)
|
|
|
|
# AI tools fetch missing model files automatically (public model weights only,
|
|
# never user data). Set 0 for airgapped deployments to guarantee zero outbound
|
|
# fetches; missing models then produce actionable errors instead of downloads.
|
|
SNAPOTTER_ALLOW_MODEL_DOWNLOAD=1
|
|
|
|
SESSION_DURATION_HOURS=168
|
|
LOGIN_ATTEMPT_LIMIT=10
|
|
|
|
# Set to true in CI/dev to skip the forced password-change on the default admin
|
|
# SKIP_MUST_CHANGE_PASSWORD=false
|
|
# DB_PATH removed in 2.0 -- see DATABASE_URL below
|
|
WORKSPACE_PATH=./tmp/workspace
|
|
FILES_STORAGE_PATH=./data/files
|
|
DEFAULT_THEME=light
|
|
DEFAULT_LOCALE=en
|
|
APP_NAME=snapotter
|
|
|
|
# --- 2.0 foundation ---
|
|
# Postgres connection (required; this default matches docker-compose.dev.yml)
|
|
# Start the dev stack first: docker compose -f docker-compose.dev.yml up -d
|
|
DATABASE_URL=postgres://snapotter:snapotter@localhost:5432/snapotter
|
|
# Redis connection (required; this default matches docker-compose.dev.yml)
|
|
REDIS_URL=redis://localhost:6379
|
|
|
|
# Job spine tuning
|
|
SYNC_WAIT_MS=8000 # sync-response window (ms) before returning 202
|
|
JOBS_RETENTION_DAYS=30 # completed-job metadata TTL (days)
|
|
AUDIT_RETENTION_DAYS=0 # audit-log TTL (0 = keep forever)
|
|
LOG_DIR=./data/logs # rotating log ring for support bundles
|
|
# JOB_TIMEOUT_FAST_S=120 # timeout for fast pools (image, docs), seconds
|
|
# JOB_TIMEOUT_LONG_S=7200 # timeout for long pools (ai, media), seconds
|
|
# SCRATCH_PATH= # worker scratch dir (default: OS tmpdir/snapotter-scratch)
|
|
|
|
# Prometheus metrics: GET /api/v1/metrics requires an authenticated admin
|
|
# (scrapers need a session cookie or API key with system:health permission).
|
|
|
|
# --- Analytics ---
|
|
# Basic analytics are included by default. SnapOtter works normally without them.
|
|
# To disable: docker compose build --build-arg SNAPOTTER_ANALYTICS=off
|
|
|
|
# One-time SQLite import on first boot (1.x upgrade path). Leave unset normally.
|
|
# SQLITE_MIGRATE_PATH=/data/snapotter.db
|
|
|
|
# --- OpenTelemetry Distributed Tracing (enterprise only) ---
|
|
# Requires a valid enterprise license with distributed_tracing feature.
|
|
# Set OTEL_EXPORTER_OTLP_ENDPOINT to enable. All other vars are optional.
|
|
# Docs: https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/
|
|
# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
# OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
|
|
# OTEL_EXPORTER_OTLP_HEADERS=
|
|
# OTEL_SERVICE_NAME=snapotter-api
|
|
# OTEL_TRACES_SAMPLER=parentbased_always_on
|
|
# OTEL_TRACES_EXPORTER=otlp
|