diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml
new file mode 100644
index 0000000..9d7838b
--- /dev/null
+++ b/.forgejo/workflows/ci.yml
@@ -0,0 +1,33 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22'
+
+ - name: Install dependencies
+ run: npm ci --no-audit --no-fund
+
+ - name: Check syntax (semua file JS)
+ shell: bash
+ run: |
+ fail=0
+ while IFS= read -r f; do
+ node --check "$f" || { echo "SYNTAX FAIL: $f"; fail=1; }
+ done < <(find . -name '*.js' -not -path './node_modules/*' -not -path './.git/*' -not -path './public/vendor/*')
+ exit $fail
+
+ - name: Unit tests
+ run: node tests/unit/area-access.test.js
diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml
new file mode 100644
index 0000000..b2374d0
--- /dev/null
+++ b/.forgejo/workflows/release.yml
@@ -0,0 +1,45 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - 'v*'
+
+jobs:
+ release:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Build archive & release
+ shell: bash
+ env:
+ TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
+ TAG: ${{ github.ref_name }}
+ run: |
+ set -euo pipefail
+ VERSION="${TAG#v}"
+ NOTES="docs/RELEASE_NOTES_v${VERSION}.md"
+
+ python3 - "$TAG" "$NOTES" > payload.json <<'PY'
+ import json, os, sys
+ tag, notes = sys.argv[1], sys.argv[2]
+ body = open(notes, encoding="utf-8").read() if os.path.exists(notes) else "Rilis " + tag
+ print(json.dumps({"tag_name": tag, "name": tag, "body": body, "draft": False, "prerelease": False}))
+ PY
+
+ git archive --format=zip --prefix="open-isp-${VERSION}/" -o "/tmp/open-isp-${VERSION}.zip" HEAD
+
+ ID=$(curl -fsS -X POST "$API/releases" \
+ -H "Authorization: token $TOKEN" \
+ -H "Content-Type: application/json" \
+ -d @payload.json | python3 -c 'import sys, json; print(json.load(sys.stdin)["id"])')
+
+ curl -fsS -X POST "$API/releases/$ID/assets?name=open-isp-${VERSION}.zip" \
+ -H "Authorization: token $TOKEN" \
+ -H "Content-Type: application/zip" \
+ --data-binary "@/tmp/open-isp-${VERSION}.zip"
+
+ echo "Release $TAG dibuat dengan asset open-isp-${VERSION}.zip"
diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml
new file mode 100644
index 0000000..9d7838b
--- /dev/null
+++ b/.gitea/workflows/ci.yml
@@ -0,0 +1,33 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22'
+
+ - name: Install dependencies
+ run: npm ci --no-audit --no-fund
+
+ - name: Check syntax (semua file JS)
+ shell: bash
+ run: |
+ fail=0
+ while IFS= read -r f; do
+ node --check "$f" || { echo "SYNTAX FAIL: $f"; fail=1; }
+ done < <(find . -name '*.js' -not -path './node_modules/*' -not -path './.git/*' -not -path './public/vendor/*')
+ exit $fail
+
+ - name: Unit tests
+ run: node tests/unit/area-access.test.js
diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml
new file mode 100644
index 0000000..b2374d0
--- /dev/null
+++ b/.gitea/workflows/release.yml
@@ -0,0 +1,45 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - 'v*'
+
+jobs:
+ release:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Build archive & release
+ shell: bash
+ env:
+ TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
+ TAG: ${{ github.ref_name }}
+ run: |
+ set -euo pipefail
+ VERSION="${TAG#v}"
+ NOTES="docs/RELEASE_NOTES_v${VERSION}.md"
+
+ python3 - "$TAG" "$NOTES" > payload.json <<'PY'
+ import json, os, sys
+ tag, notes = sys.argv[1], sys.argv[2]
+ body = open(notes, encoding="utf-8").read() if os.path.exists(notes) else "Rilis " + tag
+ print(json.dumps({"tag_name": tag, "name": tag, "body": body, "draft": False, "prerelease": False}))
+ PY
+
+ git archive --format=zip --prefix="open-isp-${VERSION}/" -o "/tmp/open-isp-${VERSION}.zip" HEAD
+
+ ID=$(curl -fsS -X POST "$API/releases" \
+ -H "Authorization: token $TOKEN" \
+ -H "Content-Type: application/json" \
+ -d @payload.json | python3 -c 'import sys, json; print(json.load(sys.stdin)["id"])')
+
+ curl -fsS -X POST "$API/releases/$ID/assets?name=open-isp-${VERSION}.zip" \
+ -H "Authorization: token $TOKEN" \
+ -H "Content-Type: application/zip" \
+ --data-binary "@/tmp/open-isp-${VERSION}.zip"
+
+ echo "Release $TAG dibuat dengan asset open-isp-${VERSION}.zip"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 110053f..a3cd576 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,24 @@
Format mengikuti [Keep a Changelog](https://keepachangelog.com/) dan [Semantic Versioning](https://semver.org/).
-## [Unreleased] — setelah v0.5.1
+## [0.5.3] — 2026-11-05 — "forge-lime"
+
+### Ditambahkan
+- **Pembatasan wilayah kerja**: teknisi & kolektor hanya melihat/menangani pelanggan, tiket, perangkat, dan tagihan di area tugasnya (dukung multi-area). Admin/root tetap penuh.
+- **Inventaris gudang**: alur stok keluar (FIFO / serial number), retur barang bekas, stock opname dengan selisih otomatis, detail unit per barang, statistik stok, serta harga & supplier.
+- **Edit slip payroll**: rincian gaji (tunjangan, potongan, bonus, lembur) dapat diubah selama status masih draft; total dihitung ulang otomatis.
+- **AI & Self-Healing**: provider AI OpenAI-compatible (DeepSeek default, OpenAI, Groq, OpenRouter, custom/Ollama), bot Telegram menjawab pertanyaan admin, dan auto-repair jaringan (status isolir vs tagihan, secret PPPoE hilang/tertukar profil, sesi RADIUS menggantung, IP ACS kosong) dengan **toggle on/off** di Pengaturan.
+- **Security Watchdog**: deteksi brute-force login admin/kasir/teknisi/kolektor dan MikroTik, blokir IP sementara, alert suara (TTS soundbox) + notifikasi admin.
+- **Batas sesi login**: admin/kasir/teknisi/kolektor maksimal 2 sesi per akun, pelanggan 3 sesi; sesi lama diputus otomatis dan session ID dirotasi saat login.
+
+### Diperbaiki
+- Tab **Status** di halaman login pelanggan kini mengikuti setting `uptime_url` (sebelumnya selalu menuju URL lama `status.skyfiber.qzz.io`).
+- Kolom API key AI disamarkan (`type=password`) agar tidak tampil di layar/screenshot.
+
+### Dokumentasi
+- 10 screenshot aplikasi (desktop + mobile) di `docs/screenshots/`.
+
+## [0.5.2] — 2026-10-14 — "mirror-gitea"
### Diperbaiki
- Kolom **IP Address** di **GenieACS Pro** kini tampil saat **mode pencarian** (sebelumnya kosong).
diff --git a/README.md b/README.md
index 7f518d8..837bc68 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-> 🪞 **Mirror.** Repo asli, pengembangan & **rilis/unduhan** ada di **Gitea**: https://gitea.oxpoe.qzz.io/oxpoe/open-isp/releases · GitHub hanya cermin kode.
+> 🪞 **Repositori utama:** [Gitea](https://gitea.oxpoe.xyz/oxpoe/open-isp) · [Forgejo](https://forgejo.oxpoe.xyz/oxpoe/open-isp) — rilis & unduhan ada di sana. GitHub hanya cermin kode.
@@ -11,18 +11,34 @@
-
+
-
-
-
+
+
+
---
**OPEN-ISP** adalah aplikasi billing dan manajemen ISP yang lengkap: tagihan otomatis, isolir otomatis, pembayaran (QRIS/webhook), perangkat MikroTik (PPPoE & hotspot), OLT PON multi-vendor, TR-069 (GenieACS/ACS), RADIUS, peta jaringan, notifikasi WhatsApp & Telegram, hingga portal self-service pelanggan dalam satu platform — semuanya berjalan mandiri (self-hosted) dengan SQLite sebagai basis data. **NOTE:** dibuat dan ditulis oleh AI ([Deepseek](https://github.com/deepseek-ai)), on [opencode](https://github.com/anomalyco/opencode).
+## Tangkapan Layar
+
+| Dashboard Admin | Daftar Pelanggan |
+|---|---|
+|  |  |
+
+| Inventaris & Stok Keluar | Pengaturan AI & Self-Healing |
+|---|---|
+|  |  |
+
+| Login Pelanggan | Dashboard Pelanggan |
+|---|---|
+|  |  |
+
+Selengkapnya (10 gambar, desktop + mobile): [`docs/screenshots/`](docs/screenshots/).
+
## Fitur
- **Billing & pembayaran** — tagihan bulanan otomatis (cron tanggal 1), promo & prorata per paket, kode unik/QRIS, konfirmasi bukti transfer, webhook notifikasi pembayaran, cetak invoice, bayar tunggal/massal, void/unpay.
@@ -37,7 +53,11 @@
- **Speed test** — server internal maupun eksternal (preset provider diatur admin), mode embed/tab, tombol Muat Ulang & Bersihkan Cache.
- **PWA** — dapat dipasang di HP, offline, pembaruan otomatis (bar "versi baru tersedia").
- **Bilingual** — antarmuka Indonesia / English (bisa diganti dari UI).
-- **Lain-lain** — inventaris gudang, tiket dukungan, laporan, monitoring sistem (CPU/RAM/disk), ODP, backup/restore database, audit log.
+- **Inventaris gudang** — stok masuk, keluar (FIFO / serial number), retur, stock opname, detail unit, harga & supplier, statistik stok.
+- **AI & otomatisasi** — provider AI OpenAI-compatible (DeepSeek/OpenAI/Groq/OpenRouter/custom), bot Telegram AI, dan **self-healing** jaringan dengan toggle on/off.
+- **Keamanan** — security watchdog brute-force (app + MikroTik), batas sesi login per akun (staff 2, pelanggan 3), rotasi session ID, alert suara/Telegram.
+- **Pembatasan wilayah** — teknisi & kolektor hanya mengakses pelanggan/tiket/perangkat di area tugasnya.
+- **Lain-lain** — tiket dukungan, laporan, monitoring sistem (CPU/RAM/disk), ODP, backup/restore database, audit log.
## Tangkapan Layar
@@ -56,7 +76,7 @@
-Selengkapnya: **[Wiki OPEN-ISP](https://gitea.oxpoe.qzz.io/oxpoe/open-isp/wiki)**.
+Selengkapnya: **[Wiki OPEN-ISP](https://gitea.oxpoe.xyz/oxpoe/open-isp/wiki)**.
## Mulai Cepat
@@ -69,7 +89,7 @@ Klik badge di atas untuk membuka **Codespaces** — dependensi & data demo disia
### Docker (disarankan)
```bash
-git clone https://gitea.oxpoe.qzz.io/oxpoe/open-isp.git
+git clone https://gitea.oxpoe.xyz/oxpoe/open-isp.git
cd open-isp
docker compose up -d
```
@@ -105,8 +125,8 @@ Dukungan sukarela tetap diterima lewat menu **Dukung OPEN-ISP** di aplikasi.
## Dokumentasi
- [`docs/`](docs/) — referensi teknis (skema database, OID OLT, integrasi RADIUS/MikroTik, checklist backup, dll.).
-- [Wiki](https://gitea.oxpoe.qzz.io/oxpoe/open-isp/wiki) — panduan instalasi, konfigurasi, tutorial, FAQ (sedang disusun).
-- [Issues](https://gitea.oxpoe.qzz.io/oxpoe/open-isp/issues) — laporan bug & permintaan fitur.
+- [Wiki](https://gitea.oxpoe.xyz/oxpoe/open-isp/wiki) — panduan instalasi, konfigurasi, tutorial, FAQ (sedang disusun).
+- [Issues](https://gitea.oxpoe.xyz/oxpoe/open-isp/issues) — laporan bug & permintaan fitur.
## Teknologi
@@ -118,7 +138,7 @@ Dirilis dengan lisensi **ISC** — bebas digunakan, dimodifikasi, dan didistribu
- **Base kode & repo**: [alijayanet/billing-rtrw](https://github.com/alijayanet/billing-rtrw) — dibuat oleh **Alijaya Net**. Terima kasih banyak atas base kode dan repo yang bermanfaat.
- **Add-on**: GoWA (WhatsApp gateway), LibreSpeed & OpenSpeedTest (speed test), Uptime Kuma (monitoring, opsional), notification-forwarder.
-- **Dikembangkan oleh** [oxpoe](https://gitea.oxpoe.qzz.io/oxpoe) — **code by DeepSeek V4.1 Flash — max, on opencode**.
+- **Dikembangkan oleh** [oxpoe](https://gitea.oxpoe.xyz/oxpoe) — **code by DeepSeek V4.1 Flash — max, on opencode**.
- Terima kasih untuk para kontributor dan komunitas ISP Indonesia.
## Dukungan & Donasi
diff --git a/docs/RELEASE_NOTES_v0.5.3.md b/docs/RELEASE_NOTES_v0.5.3.md
new file mode 100644
index 0000000..3a4dd11
--- /dev/null
+++ b/docs/RELEASE_NOTES_v0.5.3.md
@@ -0,0 +1,66 @@
+# OPEN-ISP v0.5.3 — "forge-lime"
+
+Rilis ini menggabungkan pembaruan fitur dari repo upstream (`alijayanet/billing-rtrw`) yang relevan untuk fork ini, plus perbaikan bug login/sesi.
+
+## Yang baru
+
+### 1. Pembatasan wilayah kerja
+- Teknisi hanya melihat/mengambil tiket, pelanggan, perangkat, dan peta di area tugasnya.
+- Kolektor hanya melihat & menagih pelanggan di area/tugasnya, termasuk lewat APK (dashboard & pay-bill).
+- Mendukung multi-area (`area` dipisah koma), kosong/`semua` = tanpa batas.
+- Pelanggan baru yang didaftarkan teknisi otomatis masuk area teknisi tersebut.
+
+### 2. Inventaris gudang
+- Stok keluar dengan FIFO atau serial number spesifik.
+- Retur barang bekas/copotan.
+- Stock opname (sesuaikan stok sistem dengan fisik, selisih dicatat).
+- Detail unit per barang, daftar serial tersedia, statistik stok, harga & supplier.
+- Semua transaksi tercatat dengan sisa stok di log.
+
+### 3. Edit slip payroll
+- Rincian gaji bisa diubah selama berstatus draft; gross, potongan, dan net dihitung ulang otomatis.
+
+### 4. AI & Self-Healing
+- Provider AI lewat satu jalur OpenAI-compatible: **DeepSeek (default)**, OpenAI, Groq, OpenRouter, atau custom (Ollama/LM Studio).
+- Bot Telegram menjawab pertanyaan admin (termasuk tool: cek pelanggan, perangkat, dll).
+- Self-healing memeriksa & memperbaiki:
+ - pelanggan terisolir padahal tagihan lunas,
+ - secret PPPoE hilang / tertukar profil isolir,
+ - pelanggan terisolir tapi masih aktif di MikroTik,
+ - sesi RADIUS menggantung,
+ - IP modem ACS kosong.
+- **Toggle on/off di Pengaturan** (default nonaktif) + tombol Diagnosa / Perbaiki Sekarang.
+
+### 5. Security Watchdog
+- Deteksi brute-force login admin/kasir/teknisi/kolektor dan login MikroTik.
+- Blokir IP sementara 15 menit setelah 5 percobaan gagal.
+- Alert suara (TTS) via soundbox + notifikasi admin.
+
+### 6. Batas sesi login
+- Admin/kasir/teknisi/kolektor: maksimal **2** sesi per akun.
+- Pelanggan: maksimal **3** sesi per akun.
+- Sesi tertua diputus otomatis saat melebihi batas; session ID dirotasi saat login (anti session fixation).
+- Sesi tetap tersimpan saat service restart (cookie 30 hari, rolling).
+
+## Perbaikan
+- Tab **Status** di login pelanggan kini mengikuti setting `uptime_url`, bukan URL lama.
+- Kolom API key AI disamarkan di halaman Pengaturan.
+
+## Dokumentasi
+- 10 screenshot (desktop + mobile) di `docs/screenshots/`.
+
+## Cara upgrade
+
+```bash
+git pull
+npm install
+# restart service (pm2 / systemd / docker compose)
+```
+
+Migrasi database berjalan otomatis saat aplikasi start (kolom inventaris & tabel sesi login).
+
+Pengaturan AI (opsional): **Pengaturan → AI & Self-Healing** — pilih provider, isi API key/model, lalu nyalakan auto-repair bila sudah yakin.
+
+---
+
+**Full changelog:** [CHANGELOG.md](../CHANGELOG.md)
diff --git a/package.json b/package.json
index d26342b..830e35f 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "open-isp",
- "version": "0.5.2",
- "description": "OPEN-ISP — sistem billing & manajemen ISP open-source (PWA pelanggan, multi-OLT, RADIUS, WhatsApp, QRIS)",
+ "version": "0.5.3",
+ "description": "OPEN-ISP \u2014 sistem billing & manajemen ISP open-source (PWA pelanggan, multi-OLT, RADIUS, WhatsApp, QRIS)",
"main": "app-customer.js",
"scripts": {
"start": "node app-customer.js",
diff --git a/version.txt b/version.txt
index cb0c939..be14282 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-0.5.2
+0.5.3