diff --git a/.gitignore b/.gitignore index 863238c..e640caf 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,12 @@ __pycache__/ .pytest_cache/ .mypy_cache/ .ruff_cache/ +.coverage +.coverage.* +htmlcov/ + +# Offline dependency wheelhouse (built on staging machine, not committed) +wheelhouse/ # Secrets & local environment (keep .env.example) .env diff --git a/docs/operations/offline-install.md b/docs/operations/offline-install.md new file mode 100644 index 0000000..f1ea977 --- /dev/null +++ b/docs/operations/offline-install.md @@ -0,0 +1,59 @@ +# Offline (air-gapped / 폐쇄망) install + +The deployment target has **no internet**. All Python dependencies must be +carried across the air gap as pre-downloaded wheels. The build/staging machine +(which has internet) does the downloading; the target only installs. + +## Prerequisites + +- Same OS + CPU architecture + **Python 3.13** on build and target machines + (wheels are platform- and version-specific). +- The repository itself transferred to the target. + +## 1. On the build machine (has internet) + +```bash +# Runtime only: +pip download -r requirements.txt -d wheelhouse/ + +# Or runtime + test tooling: +pip download -r requirements-dev.txt -d wheelhouse/ +``` + +This fills `wheelhouse/` with every wheel (including transitive deps). + +## 2. Transfer + +Copy both the repository and the `wheelhouse/` directory to the target via the +approved air-gap transfer process (e.g. removable media). + +## 3. On the target machine (no internet) + +```bash +python -m venv .venv +. .venv/bin/activate # Windows: .venv\Scripts\activate +pip install --no-index --find-links wheelhouse/ -r requirements.txt +``` + +`--no-index` guarantees pip never reaches out to the internet; `--find-links` +points it at the local wheelhouse. + +## 4. Verify offline + +```bash +# Confirm no network access is attempted and imports resolve: +python -c "import numpy, cv2, PIL; print('deps ok')" +python -m pytest -q # if test deps were installed +``` + +## Notes + +- The operator GUI (`web/operator-gui/`) is fully self-contained: all + scripts/styles are local and the Pretendard font is bundled + (`assets/fonts/PretendardVariable.woff2`). No CDN fetch at runtime. +- External **search** APIs (Google / Naver / Cloud Vision) are an allowed + runtime exception and require outbound access to those providers ONLY. They + are optional; missing credentials disable the provider (see the startup + provider-readiness log). +- `COPYRIGHTER_AUTH_TOKEN` should be set in `.env` for any multi-operator or + networked deployment so the data routes require a shared token. diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..780ff7e --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,5 @@ +# Development / test dependencies (Python 3.13). Includes runtime deps. +-r requirements.txt +pytest==8.4.2 +pytest-cov==6.0.0 +pytest-timeout==2.4.0 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6074324 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,11 @@ +# Runtime dependencies for the Copyrighter operator server (Python 3.13). +# +# The server, analysis, and integration layers use the Python 3.13 standard +# library (http.server, sqlite3, urllib). The ONLY third-party runtime imports +# are the image-processing libraries below (PIL, cv2, numpy), loaded lazily. +# +# Air-gapped (폐쇄망) target: install these from offline wheels, never from the +# internet. See docs/operations/offline-install.md. +numpy==2.3.5 +opencv-python-headless==4.13.0.92 +pillow==12.2.0