Metadata-Version: 2.4
Name: capture-pkg
Version: 0.3.3
Summary: A modular capture package for integration with x-ray application and PyPI distribution.
Author-email: wisnubaldas <wisnubaldas@gmail.com>
License-Expression: MIT
Keywords: capture,x-ray,hyfetch,imaging
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: hyfetch>=1.4.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-env>=1.0.0; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"

# capture-pkg

[![PyPI Version](https://img.shields.io/pypi/v/capture-pkg.svg)](https://pypi.org/project/capture-pkg/)
[![Python Version](https://img.shields.io/pypi/pyversions/capture-pkg.svg)](https://pypi.org/project/capture-pkg/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A modular Python package providing capture capabilities and HyFetch console branding for the **x-ray** application and standalone Python services. Includes a hardware-bound licensing system with HMAC-SHA256 digital signature verification.

---

## ✨ Features

- **HyFetch Console Branding**: Automatic system fetch console banner with custom `xenogender` preset and `fastfetch` / `neofetch` backend.
- **Non-Blocking Auto Configuration**: Auto-generates `hyfetch.json` when missing to ensure non-interactive servers (FastAPI/Uvicorn) never hang on setup wizards.
- **FastAPI / Server Ready**: Provides helper functions (`print_banner()`, `get_info()`, `process_capture()`) ready for API consumption.
- **CLI Executable**: Pre-configured terminal command `capture-pkg`.
- **Hardware-Bound Licensing**: HMAC-SHA256 signed license locked to MAC Address and Disk Serial.
- **Auto-Update**: Automatically checks PyPI for new versions in the background and installs updates without interrupting the server.

---

## 🚀 Quick Start

### 1. Installation from PyPI

```bash
pip install capture-pkg
```

### 2. Run CLI Command

Execute directly in your terminal to see the HyFetch banner and package status:

```bash
capture-pkg
```

---

## 💻 Usage in Python & FastAPI (`x-ray`)

### Import in FastAPI App / Routes

```python
from fastapi import APIRouter
import capture_pkg

router = APIRouter()

# Display HyFetch banner at server startup (Non-blocking)
capture_pkg.print_banner()

@router.get("/api/v1/capture/info")
def get_capture_info():
    return capture_pkg.get_info()

@router.post("/api/v1/capture/process")
def trigger_capture(bl_number: str, camera_id: int = 1):
    return capture_pkg.process_capture(source_id=bl_number, camera_id=camera_id)
```

---

## 🔐 License Management

### Cara Kerja Lisensi

Lisensi di-generate oleh **developer/vendor** menggunakan `generate-license` CLI dan kemudian dikirimkan ke server klien. Lisensi dikunci ke hardware spesifik (MAC Address dan/atau Disk Serial) dengan tanda tangan digital HMAC-SHA256.

### 1. Ambil Hardware Fingerprint Server Klien

Sebelum generate lisensi, minta klien menjalankan perintah ini di server mereka untuk mendapatkan MAC Address dan Disk Serial:

```bash
# Jalankan di server klien (x-ray server)
python -c "from capture_pkg.license_verifier import get_hardware_fingerprint; import json; print(json.dumps(get_hardware_fingerprint(), indent=2))"
```

Contoh output:
```json
{
  "mac_address": "A4:BB:6D:12:34:56",
  "disk_serial": "WD-WX12345ABCDE",
  "platform": "Linux-5.15.0-x86_64"
}
```

### 2. Generate Lisensi Klien (di mesin developer/vendor)

Gunakan CLI `generate-license` setelah `capture-pkg` ter-install di environment developer:

```bash
# Generate lisensi terikat MAC Address dan Disk Serial klien
generate-license \
  --client "PT. Pelabuhan Indonesia" \
  --mac "A4:BB:6D:12:34:56" \
  --disk "WD-WX12345ABCDE" \
  --expiry "2027-12-31" \
  --output "license_client.json"
```

```bash
# Generate lisensi hanya terikat MAC Address (tanpa cek disk)
generate-license \
  --client "PT. Terminal Petikemas Surabaya" \
  --mac "A4:BB:6D:12:34:56" \
  --expiry "2026-12-31"
```

```bash
# Generate lisensi tanpa binding hardware (berlaku di semua mesin, kurang aman)
generate-license \
  --client "Demo License" \
  --expiry "2025-06-30"
```

```bash
# Generate lisensi menggunakan hardware mesin developer saat ini
generate-license \
  --client "Developer Internal" \
  --mac this \
  --disk this \
  --expiry "2099-12-31" \
  --output "license_dev.json"
```

Contoh output sukses:
```
===================================================
      SUCCESS GENERATING SIGNED CLIENT LICENSE
===================================================
  File Path   : /home/dev/license_client.json
  Issued To   : PT. Pelabuhan Indonesia
  Bound MAC   : A4:BB:6D:12:34:56
  Bound Disk  : WD-WX12345ABCDE
  Expiry Date : 2027-12-31
  Anti-Tamper : HMAC-SHA256 Signature Embedded
===================================================
```

### 3. Kirim & Pasang Lisensi di Server Klien

Salin file `license_client.json` ke server klien dan letakkan di salah satu lokasi berikut (dicek berurutan):

| Prioritas | Path |
|---|---|
| 1 | `<working directory>/license.lic` |
| 2 | `<working directory>/license.json` |
| 3 | `~/.config/x-ray/license.json` |
| 4 | `%APPDATA%/x-ray/license.json` *(Windows only)* |

```bash
# Contoh: salin ke direktori kerja x-ray
cp license_client.json /opt/x-ray/license.json
```

### 4. Verifikasi Lisensi di Server Klien

```bash
# Verifikasi manual via Python
python -c "from capture_pkg.license_verifier import verify_license; import json; print(json.dumps(verify_license(), indent=2))"
```

Contoh output jika valid:
```json
{
  "status": "valid",
  "license_id": "LIC-20260101120000",
  "issued_to": "PT. Pelabuhan Indonesia",
  "expiry_date": "2027-12-31",
  "signature_verified": true,
  "hardware_verified": true
}
```

---

## ⚙️ Environment Variables

Semua variabel berikut dikonfigurasi di `.env` project **x-ray** (server klien), bukan di `capture_pkg`:

| Variabel | Default | Keterangan |
|---|---|---|
| `APP_ENV` | `production` | Set ke `development` untuk menonaktifkan pengecekan lisensi |
| `CAPTURE_LICENSE_ENFORCE` | `false` | Set ke `true` untuk memaksa cek lisensi meskipun `APP_ENV=development` (berguna untuk QA) |
| `CAPTURE_UPDATE_INTERVAL_DAYS` | `7` | Interval hari pengecekan update otomatis dari PyPI |
| `CAPTURE_DISABLE_AUTOUPDATE` | `false` | Set ke `true` untuk menonaktifkan auto-update |

### Contoh konfigurasi `.env` x-ray

```env
# Mode Development — lisensi dinonaktifkan
APP_ENV=development

# Mode Production — lisensi aktif (nilai default, tidak perlu diset eksplisit)
APP_ENV=production

# Mode QA — development tapi tetap enforce lisensi
APP_ENV=development
CAPTURE_LICENSE_ENFORCE=true

# Auto-update setiap 30 hari sekali
CAPTURE_UPDATE_INTERVAL_DAYS=30

# Nonaktifkan auto-update (tidak direkomendasikan)
CAPTURE_DISABLE_AUTOUPDATE=true
```

### Tabel Perilaku License Gate

| `APP_ENV` | `CAPTURE_LICENSE_ENFORCE` | Hasil |
|---|---|---|
| `production` (default) | apa saja | 🔒 **ENFORCE** — lisensi selalu dicek |
| `development` | tidak diset / `false` | ✅ **BYPASS** — lisensi dilewati |
| `development` | `true` | 🔒 **ENFORCE** — tetap dicek untuk keperluan QA |

---

## 🔄 Auto-Update dari PyPI

`capture-pkg` secara otomatis mengecek versi terbaru di PyPI setiap **7 hari** (dapat dikonfigurasi). Proses ini berjalan di **background thread** sehingga tidak memblokir startup server x-ray.

**Alur kerja:**
1. Saat `import capture_pkg` — library cek kapan terakhir kali pengecekan dilakukan
2. Jika sudah melewati interval → spawn background thread
3. Background thread cek PyPI API (`https://pypi.org/pypi/capture-pkg/json`)
4. Jika ada versi baru → `pip install --upgrade capture-pkg` dijalankan otomatis
5. Versi baru aktif setelah x-ray di-**restart** berikutnya

**State file** disimpan di: `~/.config/capture-pkg/update_state.json`

```bash
# Lihat status update terakhir
cat ~/.config/capture-pkg/update_state.json
```

---

## 🛠️ Local Development (Editable Mode)

When developing or modifying `capture-pkg` locally, install in **editable mode**:

```bash
cd capture_pkg
pip install -e .[dev]
```

> **Note**: In editable mode (`pip install -e .`), any code changes made in `capture_pkg/` take effect **immediately** without needing to reinstall!

---

## 📦 Package Publishing & Update Workflow

PyPI package releases are immutable. Whenever you update code and want to publish a new release:

### 1. Configure PyPI Token Credentials
Create a `.env` file in the project root:

```env
TWINE_USERNAME=__token__
TWINE_PASSWORD=pypi-AgEIcHlwaS5vcmcC...
```

### 2. Bump Version Number
Update the version in both `pyproject.toml` and `capture_pkg/__init__.py`:

```toml
# pyproject.toml
version = "0.4.0"
```

```python
# capture_pkg/__init__.py
__version__ = "0.4.0"
```

### 3. Build Distribution Packages
Clean previous artifacts and build new `.whl` and `.tar.gz` archives:

```bash
python -m build
```

### 4. Upload to PyPI (Manual)
Publish the new version using Twine:

```bash
python -m twine upload dist/*
```

---

## 🚀 Mekanisme & Workflow GitLab CI/CD

Project ini dilengkapi dengan pipeline otomatis **GitLab CI/CD** (`.gitlab-ci.yml`) untuk memastikan pengujian kualitas kode dan mempublikasikan versi baru secara otomatis ke PyPI tanpa perlu proses build manual di komputer lokal.

### 🔄 Alur Mekanisme Pipeline (Visual Diagram)

```
[ Git Push / Tag ]
       │
       ▼
 ┌───────────┐      Gagal     ┌────────────────────────┐
 │ Stage 1:  ├───────────────►│ ❌ Stop Pipeline        │
 │   TEST    │                │ (Publish Dibatalkan)   │
 └─────┬─────┘                └────────────────────────┘
       │ Lolos (Passed)
       ▼
 ┌───────────┐     Bukan Tag  ┌────────────────────────┐
 │ Is Git    ├───────────────►│ ⏹️ Finish               │
 │   Tag?    │  (Normal Push) │ (Hanya menjalankan Test)│
 └─────┬─────┘                └────────────────────────┘
       │ Ya (Tag format v*.*.*)
       ▼
 ┌───────────┐
 │ Stage 2:  │ ──► Build Wheel (.whl) ──► Upload ke PyPI
 │  PUBLISH  │    (python -m build)      (twine upload via PYPI_API_TOKEN)
 └───────────┘
```

---

### 📋 Tahapan Pipeline (Pipeline Stages)

Pipeline dikonfigurasi menjadi 2 tahapan (*stages*):

1. **Stage 1: `test` (`test:job`)**
   - **Kapan berjalan**: Setiap ada `git push` ke branch apapun atau ketika Git Tag di-push.
   - **Tugas**: Menginstall dependency pengembangan (`pip install .[dev]`) dan menjalankan seluruh unit test (`pytest tests/ -v`).
   - **Pengamanan**: Jika ada test yang gagal (*failed*), pipeline langsung terhenti. Stage `publish` **tidak akan pernah berjalan** jika pengujian gagal.

2. **Stage 2: `publish` (`pypi:publish`)**
   - **Kapan berjalan**: Hanya berjalan secara otomatis jika commit tersebut memiliki **Git Tag dengan format versi** (misal: `v0.3.2`, `v1.0.0`).
   - **Tugas**: 
     1. Melakukan kompilasi/build package distribution archives (`python -m build`).
     2. Mengunggah hasil build ke PyPI menggunakan Twine dengan mengonsumsi variable `PYPI_API_TOKEN`.

---

### 🔐 1. Setup Prasyarat Token di GitLab

Sebelum rilis otomatis dapat berjalan, daftarkan Token PyPI ke GitLab Repository:

1. Buka dashboard PyPI: **[https://pypi.org/manage/account/token/](https://pypi.org/manage/account/token/)**
2. Buat API Token baru dengan scope paket `capture-pkg`.
3. Masuk ke Repository GitLab: **Settings > CI/CD > Variables**.
4. Tambahkan Variable baru:
   - **Key**: `PYPI_API_TOKEN`
   - **Value**: `pypi-AgEIcHlwa...` *(Token dari PyPI)*
   - **Type**: Variable
   - **Flags**: Centang `Protect variable` dan `Mask variable`.

---

### 📦 2. Langkah Rilis Versi Baru

Untuk merilis update ke PyPI, ikuti 3 langkah sederhana ini dari terminal Anda:

```bash
# 1. Update angka versi di pyproject.toml dan capture_pkg/__init__.py (misal: 0.3.2)
# 2. Commit perubahan kode tersebut
git add .
git commit -m "chore: release version 0.3.2"

# 3. Buat Git Tag berawalan 'v' lalu push tag tersebut ke remote
git tag v0.3.2
git push origin master --tags
```

> **Catatan**: Begitu `git push --tags` dieksekusi, GitLab CI/CD akan otomatis mengambil alih, menjalankan pengujian, dan meng-upload versi baru tersebut ke PyPI!


---

## 📄 License

Distributed under the [MIT License](LICENSE).
