diff --git a/server-connection/.cursor/rules/api.mdc b/server-connection/.cursor/rules/api.mdc new file mode 100644 index 0000000..a2265c9 --- /dev/null +++ b/server-connection/.cursor/rules/api.mdc @@ -0,0 +1,54 @@ +--- +description: Standar dan aturan API geonet-console +globs: ["geonet-console/app/Http/**", "geonet-console/routes/**", "geonet-console/docapi/**"] +alwaysApply: false +--- + +# API Rules — geonet-console + +## Base URL + +- Production: `https://console.gisportal.id/api/v1` +- Internal: `http://127.0.0.1:8091/api/v1` + +## Auth + +- Semua endpoint butuh `Authorization: Bearer ` kecuali `/auth/login`, `/auth/refresh`, `/auth/token-guide` +- Token: JWT (dari login LDAP), API Token (personal), atau Service Token (antar-service) +- Gunakan `ApiActor` dari `ApiAuthService::resolve()` — **jangan** `Auth::user()` + +## Format Response + +**Success:** +```json +{"data": {...}, "message": "success"} +``` + +**Error:** +```json +{"message": "Error message", "errors": {"field": ["msg"]}} +``` + +## Menambah Endpoint Baru + +1. Controller di `app/Http/Controllers/Api/V1/` +2. Service di `app/Services/` +3. Route di `routes/api.php` dengan middleware auth + rate limit +4. **Update `docapi/index.md`** — wajib +5. Buat `docapi/services//.md` +6. Tambah audit log untuk aksi write via `AuditLogService` + +## Scope Convention + +| Scope | Akses | +|-------|-------| +| `ldap:read` | Baca data LDAP | +| `ldap:write` | Ubah data LDAP | +| `databases:read` | Baca database registry | +| `databases:write` | Ubah status database | +| `project-search:read` | Query project search | + +## Rate Limit + +- Login: 5 req/menit +- General: 60 req/menit diff --git a/server-connection/.cursor/rules/architecture.mdc b/server-connection/.cursor/rules/architecture.mdc new file mode 100644 index 0000000..40f62a2 --- /dev/null +++ b/server-connection/.cursor/rules/architecture.mdc @@ -0,0 +1,44 @@ +--- +description: Prinsip arsitektur dan pattern yang wajib diikuti +globs: ["geonet-console/app/**"] +alwaysApply: false +--- + +# Architecture Rules — geonet-console + +## Layer Structure + +``` +Routes (routes/api.php) + → Middleware (auth, rate limit, scope) + → Controller (Http/Controllers/Api/V1/) — thin, validasi only + → Service (Services/) — business logic + → Model (Models/) — Eloquent + → Database +``` + +## Prinsip Wajib + +- **Service layer** untuk semua logic — jangan taruh logic di controller atau model +- **ApiActor** sebagai identity caller — jangan `Auth::user()` +- **Audit log** untuk semua aksi write — via `AuditLogService` +- **Jangan duplikasi Zabbix** — monitoring real-time tetap di Zabbix +- **PostgreSQL untuk app baru** — SQL Server hanya legacy/GIS + +## Sistem Boundaries + +| Komponen | Tanggung Jawab | +|----------|----------------| +| geonet-console | IT portal: auth, LDAP mgmt, DB registry, API | +| Zabbix | Monitoring server real-time — jangan duplikasi | +| QNAP OSS | File storage (avatar) — via S3 API | +| Active Directory | Identity source — auth via LDAP | +| GeoNetAgent | Asset management endpoint (repo terpisah) | + +## Perubahan Arsitektur + +Jika ada perubahan arsitektur signifikan: +1. Buat ADR di `docs/adr/ADR-NNNN-judul.md` +2. Update diagram di `docs/diagrams/` +3. Update `docs/architecture/` yang relevan +4. Jangan delete ADR lama — buat baru yang reference ADR lama diff --git a/server-connection/.cursor/rules/database.mdc b/server-connection/.cursor/rules/database.mdc new file mode 100644 index 0000000..472c1a6 --- /dev/null +++ b/server-connection/.cursor/rules/database.mdc @@ -0,0 +1,45 @@ +--- +description: Aturan database — koneksi, migration, naming +globs: ["geonet-console/database/**", "geonet-console/app/Models/**", "geonet-console/config/database.php"] +alwaysApply: false +--- + +# Database Rules — geonet-console + +## Koneksi + +| Name | DB | Host | +|------|----|------| +| `pgsql` (default) | `databaselist_app` | `audit-postgres` container | +| `audit` | `databaselist_audit` | `audit-postgres` container | +| `mssql` | `master` | 10.100.1.25:1433 (read-only) | +| `project_search` | `geonet_project_search` | 10.100.1.25 (Fase 4) | + +## Larangan + +- ❌ JANGAN ubah `DB_CONNECTION` ke `sqlite` +- ❌ JANGAN jalankan `migrate:fresh` di production +- ❌ JANGAN tulis ke `mssql` — read-only + +## Migration Convention + +- File: `YYYY_MM_DD_HHMMSS_verb_noun_table.php` +- Nama tabel: `snake_case` plural +- Selalu buat rollback (`down()`) yang benar +- Gunakan `connection('audit')` untuk migration audit DB + +## Naming + +| Tipe | Konvensi | +|------|----------| +| Tabel | `snake_case` plural | +| Kolom | `snake_case` | +| FK | `_id` | +| Timestamp | `*_at` suffix (`created_at`, `last_used_at`) | + +## Audit Log Wajib + +Setiap aksi write wajib log via: +```php +AuditLogService::log($actor, $action, $target, $payload); +``` diff --git a/server-connection/.cursor/rules/deployment.mdc b/server-connection/.cursor/rules/deployment.mdc new file mode 100644 index 0000000..26d3a35 --- /dev/null +++ b/server-connection/.cursor/rules/deployment.mdc @@ -0,0 +1,44 @@ +--- +description: Aturan dan prosedur deployment +globs: ["scripts/**", "*.yaml", "Dockerfile", ".env.example"] +alwaysApply: false +--- + +# Deployment Rules + +## Deploy geonet-console + +```powershell +.\scripts\deploy-geonet-console.ps1 +``` + +Atau manual: +1. `tar -czf` — exclude vendor, .git, node_modules +2. Upload via `Start-Process cmd.exe` + SSH cat +3. Extract di `/opt/stacks/geonet-console/` +4. `docker compose up -d --build --force-recreate` + +## Larangan Deploy + +- ❌ JANGAN overwrite `.env` di server +- ❌ JANGAN jalankan `migrate:fresh` di production +- ❌ JANGAN gunakan `&&` di PowerShell — gunakan `;` + +## Setelah Deploy + +- Cek: `docker ps --filter name=geonet-console` +- Cek log: `docker logs geonet-console --tail 30` +- Test URL: `https://console.gisportal.id` + +## Stack Paths di Server 10.100.1.24 + +| App | Path | +|-----|------| +| geonet-console | `/opt/stacks/geonet-console/` | +| databaselist | `/opt/stacks/databaselist/` | +| sqlservercheck | `/opt/stacks/sqlservercheck/` | +| my-portal | `/opt/stacks/my-portal/` | + +## SSH + +Semua SSH ke 10.100.1.24 wajib minta persetujuan user terlebih dahulu. diff --git a/server-connection/.cursor/rules/documentation.mdc b/server-connection/.cursor/rules/documentation.mdc new file mode 100644 index 0000000..a12ef7d --- /dev/null +++ b/server-connection/.cursor/rules/documentation.mdc @@ -0,0 +1,32 @@ +--- +description: Kapan dan bagaimana harus update dokumentasi +globs: ["**/*.md", "**/*.php", "**/*.ps1"] +alwaysApply: true +--- + +# Documentation Rules + +## Wajib Update Setelah: + +- **Endpoint API baru/berubah** → update `geonet-console/docapi/index.md` + buat `docapi/services//.md` +- **Perubahan arsitektur** → update `docs/architecture/` + buat ADR baru di `docs/adr/` +- **Env var baru** → update `geonet-console/.env.example` + `docs/environment.md` +- **Bug fix penting** → tambah ke `docs/issues.md` (section Fixed) +- **Deploy procedure berubah** → update `docs/deployment.md` +- **Server/infra berubah** → update `docs/server.md` + `.cursor/me.md` +- **Akhir sesi pengembangan** → update `perintah.md` (Sync terakhir) + +## ADR Rules + +- ADR = Architecture Decision Record — tidak pernah dihapus +- Jika keputusan berubah → buat ADR baru yang references ADR lama +- Simpan di `docs/adr/ADR-NNNN-judul.md` +- Status: Proposed / Accepted / Superseded / Deprecated + +## Definition of Done + +Implementasi dianggap selesai jika: +- [ ] Code bekerja dan test lulus +- [ ] `docapi/` diperbarui (untuk perubahan API) +- [ ] `perintah.md` diperbarui (Sync terakhir) +- [ ] Tidak ada secret/credential di code atau dokumentasi diff --git a/server-connection/.cursor/rules/security.mdc b/server-connection/.cursor/rules/security.mdc new file mode 100644 index 0000000..494748b --- /dev/null +++ b/server-connection/.cursor/rules/security.mdc @@ -0,0 +1,37 @@ +--- +description: Aturan keamanan wajib — credential, SSH, secret management +globs: ["**/*"] +alwaysApply: true +--- + +# Security Rules + +## Larangan Mutlak + +- ❌ JANGAN commit file `.env` ke repository +- ❌ JANGAN commit password, API key, token, atau private key +- ❌ JANGAN tampilkan nilai secret di output, log, atau response API +- ❌ JANGAN hardcode credential di code PHP atau PowerShell +- ❌ JANGAN overwrite `.env` di server saat deploy — `.env` berisi credentials production + +## Lokasi Secret yang Benar + +| Secret | Lokasi | +|--------|--------| +| App credentials | `/opt/stacks/geonet-console/.env` di server 10.100.1.24 | +| LDAP bind password | `.env` server (tidak di repo) | +| QNAP OSS secret key | `.env` server (tidak di repo) | +| SSH private key | `~/.ssh/` di laptop developer | +| MikroTik RSA key | `~/.ssh/id_rsa_mikrotik` | + +## SSH Rules + +- SSH commands ke server **wajib minta persetujuan user** sebelum dijalankan +- Jangan auto-run SSH command yang bersifat destructive +- SSH key: `id_ed25519` untuk server Linux, `id_rsa_mikrotik` untuk MikroTik + +## Untuk AI Agent + +- Jika diminta buat credential baru → catat lokasi penyimpanan di `docs/environment.md` (bukan nilainya) +- Jika ditemukan token di code → laporkan ke user, jangan commit +- Jika perlu generate APP_KEY → instruksikan user run `php artisan key:generate` di server diff --git a/server-connection/README.md b/server-connection/README.md new file mode 100644 index 0000000..245a109 --- /dev/null +++ b/server-connection/README.md @@ -0,0 +1,104 @@ +# server-connection — IT Operations Monorepo + +Monorepo untuk aplikasi IT internal dan skrip infrastruktur **GIS Portal** (`gisportal.id`). + +> **AI Agent & Developer baru:** Mulai dari [`docs/context-index.md`](docs/context-index.md) — peta navigasi seluruh dokumentasi. + +--- + +## Aplikasi + +| Folder | URL Produksi | Stack | Status | +|--------|-------------|-------|--------| +| `geonet-console/` | https://console.gisportal.id | Laravel 12 + PHP 8.3 | ✅ Production | +| `databaselist/` | https://databaselist.gisportal.id | Laravel (legacy) | ⚠️ Legacy → akan di-redirect ke geonet-console | +| `sqlservercheck/` | https://sqlservercheck.gisportal.id | PHP slim | ✅ Running | + +--- + +## Quick Deploy + +```powershell +# Deploy geonet-console (default) +.\scripts\deploy-geonet-console.ps1 + +# Deploy databaselist (legacy) +.\scripts\deploy-databaselist.ps1 +.\scripts\deploy-databaselist.ps1 -NoBuild # restart saja + +# Deploy sqlservercheck +.\scripts\deploy-sqlservercheck.ps1 +``` + +--- + +## Quick Start — Lokal Dev (geonet-console) + +```powershell +# Clone & setup env +cd geonet-console +cp .env.example .env +# Edit .env — isi DB credentials, LDAP, OSS + +# Build & jalankan di Docker +docker compose up -d --build + +# Akses +# App: http://localhost:8091 +# API: http://localhost:8091/api/v1 +``` + +--- + +## Infrastruktur Server + +| Role | IP | OS | +|------|----|----| +| **Reverse Proxy + Docker** | 10.100.1.24 | CentOS Linux 8 | +| **Database (PostgreSQL + SQL Server)** | 10.100.1.25 | Ubuntu 18.04 LTS | +| **Active Directory / LDAP** | 10.100.1.40 | Windows Server 2012 R2 | +| **NAS QNAP TS-932X** | 10.100.1.10 | QTS 5.2.9 | +| **Ollama AI VM** | 10.100.1.26 | Ubuntu 22.04 LTS | +| **Zabbix** | 10.100.1.42 | Ubuntu 22.04 LTS | +| **MikroTik CCR2004** | 10.100.1.1 | RouterOS 7.5 | + +--- + +## Struktur Monorepo + +``` +server-connection/ +├── geonet-console/ — Laravel 12 unified IT portal +├── databaselist/ — Legacy Laravel (akan di-deprecated) +├── sqlservercheck/ — Tool cek SQL Server koneksi +├── scripts/ — Deploy & SSH helper scripts +│ ├── deploy-geonet-console.ps1 +│ ├── deploy-databaselist.ps1 +│ ├── ssh-remote.ps1 — SSH ke reverse proxy +│ ├── ssh-mikrotik.ps1 — SSH ke MikroTik +│ ├── ssh-ollama.ps1 — SSH ke Ollama VM +│ └── ssh-qnap.ps1 — SSH ke QNAP NAS +├── server/ — Audit server + MikroTik configs +├── docs/ — Dokumentasi lengkap ⭐ +├── .cursor/ — AI context (rules, me, context-index) +├── AGENTS.md — Aturan AI agent +├── perintah.md — Protokol sync + quick reference +└── readme.txt — SSH commands cepat +``` + +--- + +## Dokumentasi Lengkap + +Lihat [`docs/context-index.md`](docs/context-index.md) untuk peta dokumentasi. + +| Topik | File | +|-------|------| +| Status proyek | `docs/project-status.md` | +| Arsitektur sistem | `docs/architecture/system-overview.md` | +| API geonet-console | `docs/api/overview.md` | +| Deploy guide | `docs/deployment.md` | +| Environment vars | `docs/environment.md` | +| Server & SSH | `docs/server.md` | +| Database | `docs/database.md` | +| Troubleshooting | `docs/troubleshooting.md` | diff --git a/server-connection/docs/adr/ADR-0001-monorepo-structure.md b/server-connection/docs/adr/ADR-0001-monorepo-structure.md new file mode 100644 index 0000000..d89e569 --- /dev/null +++ b/server-connection/docs/adr/ADR-0001-monorepo-structure.md @@ -0,0 +1,39 @@ +# ADR-0001 — Struktur Monorepo server-connection + +**Tanggal:** 2025-xx-xx +**Status:** Accepted + +--- + +## Konteks + +Perlu mengelola beberapa aplikasi IT internal (geonet-console, databaselist, sqlservercheck), skrip deploy, dan skrip infrastruktur (MikroTik, SSH) dalam satu repositori. + +## Keputusan + +Menggunakan **monorepo** dengan struktur folder per-aplikasi: + +``` +server-connection/ +├── geonet-console/ +├── databaselist/ +├── sqlservercheck/ +├── scripts/ +└── server/ +``` + +## Alasan + +- Semua aplikasi dikelola oleh satu tim IT kecil +- Deploy scripts saling terkait (SSH ke server yang sama) +- Mudah cross-reference antara app code dan infra scripts +- Tidak perlu manage banyak repo untuk skala tim kecil + +## Alternatif Ditolak + +- **Polyrepo (repo terpisah per app):** Terlalu banyak overhead untuk tim kecil, sync deploy scripts jadi sulit + +## Konsekuensi + +- Semua perubahan ada di satu commit history +- Harus hati-hati agar `.env` tidak masuk ke satu folder yang salah saat deploy diff --git a/server-connection/docs/adr/ADR-0002-database-postgresql.md b/server-connection/docs/adr/ADR-0002-database-postgresql.md new file mode 100644 index 0000000..dd0002b --- /dev/null +++ b/server-connection/docs/adr/ADR-0002-database-postgresql.md @@ -0,0 +1,34 @@ +# ADR-0002 — PostgreSQL untuk Aplikasi Baru + +**Tanggal:** 2025-xx-xx +**Status:** Accepted + +--- + +## Konteks + +Perlu memilih database engine untuk aplikasi internal baru (geonet-console). Sudah ada SQL Server 2019 di 10.100.1.25 untuk legacy/GIS. + +## Keputusan + +**PostgreSQL** sebagai database default untuk aplikasi baru. SQL Server hanya untuk legacy atau GIS yang sudah terikat. + +## Alasan + +- Open source, tidak ada biaya lisensi +- Support pgvector (dibutuhkan Fase 4 Ollama AI search) +- Laravel Eloquent support penuh untuk PostgreSQL +- Docker container mudah — `postgres:15` image resmi +- JSON/JSONB support untuk metadata fleksibel + +## Alternatif Ditolak + +- **SQL Server:** Berlisensi mahal, tidak support pgvector, sudah dipakai untuk GIS legacy +- **MySQL:** Tidak support pgvector, kurang fitur JSON vs PostgreSQL +- **SQLite:** Tidak cocok untuk multi-container atau concurrency production + +## Konsekuensi + +- `DB_CONNECTION=pgsql` wajib di `compose.yaml` — jangan ubah ke sqlite +- Legacy SQL Server tetap dipertahankan untuk database registry read-only +- Nama DB saat ini masih `databaselist_app` (nama legacy, rencana rename di Fase 3) diff --git a/server-connection/docs/adr/ADR-0003-ldap-authentication.md b/server-connection/docs/adr/ADR-0003-ldap-authentication.md new file mode 100644 index 0000000..d8556b6 --- /dev/null +++ b/server-connection/docs/adr/ADR-0003-ldap-authentication.md @@ -0,0 +1,34 @@ +# ADR-0003 — Auth via LDAP Active Directory + +**Tanggal:** 2025-xx-xx +**Status:** Accepted + +--- + +## Konteks + +Perlu menentukan mekanisme autentikasi untuk geonet-console. Sudah ada Active Directory di 10.100.1.40 (domain `gisportal.id`) yang mengelola semua user dan laptop IT. + +## Keputusan + +Autentikasi melalui **LDAP bind ke Active Directory**. Tidak ada user lokal di geonet-console. Setelah berhasil bind, server mengeluarkan **JWT** untuk sesi selanjutnya. + +## Alasan + +- Semua user IT sudah ada di AD — tidak perlu manage user terpisah +- Single source of truth untuk identity +- Group AD (`Domain Admins`, `IT-Admin`, dll.) dipakai untuk RBAC +- Tidak perlu forgot password / registration flow (AD yang kelola) + +## Alternatif Ditolak + +- **Local user DB:** Perlu manage password terpisah, duplikasi identity +- **OAuth2 external (Google, dll.):** Tidak cocok untuk internal IT tool +- **Kerberos SSO:** Kompleksitas tinggi untuk tim kecil + +## Konsekuensi + +- `LDAP_BIND_PASSWORD` wajib diisi di `.env` server +- Jika AD 10.100.1.40 down → login tidak bisa (unavoidable tradeoff) +- JWT refresh tersedia agar user tidak perlu login ulang terlalu sering +- Admin group: `Domain Admins`, `Administrators`, `Enterprise Admins` diff --git a/server-connection/docs/adr/ADR-0004-qnap-object-storage.md b/server-connection/docs/adr/ADR-0004-qnap-object-storage.md new file mode 100644 index 0000000..6e8847c --- /dev/null +++ b/server-connection/docs/adr/ADR-0004-qnap-object-storage.md @@ -0,0 +1,36 @@ +# ADR-0004 — QNAP OSS untuk File Storage + +**Tanggal:** 2026-xx-xx +**Status:** Accepted + +--- + +## Konteks + +geonet-console perlu storage untuk avatar user. Awalnya disimpan di filesystem lokal Docker container, tapi container rebuild akan menghapus semua file. + +## Keputusan + +Menggunakan **QNAP QuObjects (OSS)** — S3-compatible object storage di 10.100.1.10:8010. Laravel menggunakan disk `oss` dengan driver `s3` + `use_path_style_endpoint=true`. + +## Alasan + +- QNAP TS-932X sudah ada di infrastruktur (tidak perlu beli) +- S3-compatible → bisa pakai Laravel `s3` driver standar +- File persists meski container rebuild atau crash +- URL publik via Nginx proxy (`file.gisportal.id/super-apps/`) tanpa expose QNAP langsung + +## Alternatif Ditolak + +- **Docker volume lokal:** File hilang saat image recreate, tidak scalable +- **NFS mount:** Lebih kompleks, risiko hanging mount +- **Cloud S3 (AWS, Cloudflare R2):** Biaya, data harus internal +- **Minio:** Perlu server/container tambahan, QNAP sudah ada + +## Konsekuensi + +- Bucket `super-apps` wajib di-set `public-read` (`X-Container-Read: .r:*,.rlistings`) +- ACL bisa ter-reset → monitoring manual atau script cek berkala +- Format access key: `:` (format QNAP) +- Driver `s3` wajib pakai `use_path_style_endpoint=true` (QNAP tidak support virtual hosted-style) +- `OSS_SECRET_ACCESS_KEY` hanya ada di `.env` server — tidak di repo diff --git a/server-connection/docs/adr/README.md b/server-connection/docs/adr/README.md new file mode 100644 index 0000000..2e65c5f --- /dev/null +++ b/server-connection/docs/adr/README.md @@ -0,0 +1,14 @@ +# Architecture Decision Records (ADR) + +ADR mendokumentasikan keputusan arsitektur penting, alasan di baliknya, dan alternatif yang dipertimbangkan. + +**Aturan:** ADR tidak boleh dihapus. Jika keputusan berubah, buat ADR baru. + +--- + +| ADR | Judul | Status | +|-----|-------|--------| +| [ADR-0001](ADR-0001-monorepo-structure.md) | Struktur Monorepo server-connection | Accepted | +| [ADR-0002](ADR-0002-database-postgresql.md) | PostgreSQL untuk Aplikasi Baru | Accepted | +| [ADR-0003](ADR-0003-ldap-authentication.md) | Auth via LDAP Active Directory | Accepted | +| [ADR-0004](ADR-0004-qnap-object-storage.md) | QNAP OSS untuk File Storage | Accepted | diff --git a/server-connection/docs/api/error-codes.md b/server-connection/docs/api/error-codes.md new file mode 100644 index 0000000..409c764 --- /dev/null +++ b/server-connection/docs/api/error-codes.md @@ -0,0 +1,72 @@ +# API — Error Codes + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## HTTP Status Codes + +| Code | Keterangan | Penyebab Umum | +|------|------------|---------------| +| 200 | OK | Request berhasil | +| 201 | Created | Resource baru dibuat | +| 204 | No Content | Berhasil, tanpa body (misal DELETE) | +| 400 | Bad Request | Request tidak valid | +| 401 | Unauthorized | Token tidak ada, expired, atau salah | +| 403 | Forbidden | Token valid tapi tidak punya scope | +| 404 | Not Found | Resource tidak ditemukan | +| 422 | Unprocessable Entity | Validasi gagal | +| 429 | Too Many Requests | Rate limit terlampaui | +| 500 | Internal Server Error | Error server | + +--- + +## Format Error Response + +```json +{ + "message": "Deskripsi error", + "errors": { + "field_name": ["Validasi pesan 1", "Validasi pesan 2"] + } +} +``` + +**Untuk 401/403 (tanpa errors field):** +```json +{ + "message": "Unauthenticated." +} +``` + +--- + +## Contoh Error + +**422 Validation:** +```json +{ + "message": "The given data was invalid.", + "errors": { + "username": ["The username field is required."], + "password": ["The password field is required."] + } +} +``` + +**401 Unauthorized:** +```json +{"message": "Unauthenticated."} +``` + +**429 Rate Limit:** +```json +{"message": "Too Many Attempts."} +``` + +--- + +## Lihat Juga + +- `geonet-console/docapi/common-error.md` — error codes per service (lebih detail) +- `geonet-console/docapi/common-response.md` — format response lengkap diff --git a/server-connection/docs/api/overview.md b/server-connection/docs/api/overview.md new file mode 100644 index 0000000..b7e6311 --- /dev/null +++ b/server-connection/docs/api/overview.md @@ -0,0 +1,77 @@ +# API Overview — geonet-console + +> **Base URL:** `https://console.gisportal.id/api/v1` +> **Internal:** `http://127.0.0.1:8091/api/v1` +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Auth + +Semua endpoint (kecuali `/auth/login`, `/auth/refresh`, `/auth/token-guide`) memerlukan header: + +``` +Authorization: Bearer +``` + +Token bisa berupa: +- **JWT** — dari `POST /auth/login` +- **API Token** — personal access token +- **Service Token** — token antar-service + +--- + +## Format Response Standard + +**Success:** +```json +{"data": {...}, "message": "success"} +``` + +**Success list:** +```json +{"data": [...], "meta": {"total": 42, "page": 1}} +``` + +**Error:** +```json +{"message": "Pesan error", "errors": {"field": ["Validasi"]}} +``` + +--- + +## Endpoints Ringkas + +| Service | Endpoint Utama | Scope | +|---------|---------------|-------| +| Auth | `POST /auth/login` | Public | +| Me | `GET /me` | — | +| LDAP Users | `GET /ldap/users` | `ldap:read` | +| LDAP Groups | `GET /ldap/groups` | `ldap:read` | +| Databases | `GET /databases` | `databases:read` | +| Service Tokens | `GET /service-tokens` | — | +| Project Search | `POST /project-search/ask` | `project-search:read` | + +--- + +## Rate Limiting + +| Endpoint | Limit | +|----------|-------| +| `/auth/login` | 5 req/menit | +| General | 60 req/menit | + +--- + +## Docs Detail + +| File | Isi | +|------|-----| +| `service-auth.md` | Login, refresh, token guide, `/me` | +| `service-ldap.md` | LDAP users & groups | +| `service-database.md` | Database registry | +| `service-tokens.md` | Service token CRUD | +| `service-project-search.md` | AI project search | +| `error-codes.md` | Error format & codes | + +> Dokumentasi lengkap juga di `geonet-console/docapi/` (lebih detail, per-endpoint). diff --git a/server-connection/docs/api/service-auth.md b/server-connection/docs/api/service-auth.md new file mode 100644 index 0000000..6f5c44d --- /dev/null +++ b/server-connection/docs/api/service-auth.md @@ -0,0 +1,93 @@ +# API — Auth Service + +> **Base URL:** `https://console.gisportal.id/api/v1` + +--- + +## POST /auth/login + +Login via LDAP Active Directory. Tidak butuh auth header. + +**Request:** +```json +{"username": "rbsetiawan", "password": "password123"} +``` + +**Response 200:** +```json +{ + "token": "eyJ0eXAiOiJKV1Qi...", + "expires_at": "2026-07-06T09:00:00+07:00", + "user": { + "username": "rbsetiawan", + "display_name": "R B Setiawan", + "groups": ["Domain Admins", "IT-Admin"] + } +} +``` + +**Response 401:** Credentials salah atau user tidak ada di AD. +**Rate limit:** 5 req/menit. + +--- + +## POST /auth/refresh + +Refresh JWT tanpa login ulang (token lama masih valid). + +**Header:** `Authorization: Bearer ` + +**Response 200:** +```json +{"token": "eyJ0eXAiOiJKV1Qi...", "expires_at": "2026-07-06T09:00:00+07:00"} +``` + +--- + +## GET /auth/token-guide + +Panduan penggunaan token. Public, tidak butuh auth. + +**Response 200:** HTML atau JSON guide. + +--- + +## GET /me + +Info user yang sedang login. + +**Header:** `Authorization: Bearer ` + +**Response 200:** +```json +{ + "username": "rbsetiawan", + "display_name": "R B Setiawan", + "email": "rbsetiawan@gisportal.id", + "department": "IT", + "groups": ["Domain Admins", "IT-Admin"], + "avatar_url": "https://file.gisportal.id/super-apps/avatars/rbsetiawan-AbCd.jpg" +} +``` + +--- + +## PUT /me/avatar + +Upload avatar user (base64 encoded). + +**Header:** `Authorization: Bearer ` + +**Request:** +```json +{"data": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."} +``` + +- Max size: 300KB (base64) +- Format: JPEG, PNG +- Disimpan ke QNAP OSS bucket `super-apps` + +**Response 200:** +```json +{"avatar_url": "https://file.gisportal.id/super-apps/avatars/rbsetiawan-AbCd1234.jpg"} +``` diff --git a/server-connection/docs/api/service-database.md b/server-connection/docs/api/service-database.md new file mode 100644 index 0000000..0ebf6d7 --- /dev/null +++ b/server-connection/docs/api/service-database.md @@ -0,0 +1,43 @@ +# API — Database Registry + +> **Base URL:** `https://console.gisportal.id/api/v1` +> **Auth:** `Authorization: Bearer ` + scope `databases:read` + +--- + +## GET /databases + +List semua database yang terdaftar di registry. + +**Response 200:** +```json +{ + "data": [ + { + "id": "uuid", + "name": "GIS_Production", + "type": "mssql", + "host": "10.100.1.25", + "port": 1433, + "status": "online", + "last_checked_at": "2026-06-29T09:00:00+07:00" + } + ] +} +``` + +--- + +## POST /databases/{database}/offline + +Tandai database sebagai offline (scope: `databases:write`). + +**Request:** +```json +{"reason": "Maintenance scheduled"} +``` + +**Response 200:** +```json +{"status": "offline", "updated_at": "2026-06-29T09:00:00+07:00"} +``` diff --git a/server-connection/docs/api/service-ldap.md b/server-connection/docs/api/service-ldap.md new file mode 100644 index 0000000..3192267 --- /dev/null +++ b/server-connection/docs/api/service-ldap.md @@ -0,0 +1,114 @@ +# API — LDAP Service + +> **Base URL:** `https://console.gisportal.id/api/v1` +> **Auth:** `Authorization: Bearer ` + scope `ldap:read` / `ldap:write` + +--- + +## LDAP Users + +### GET /ldap/users + +List semua user Active Directory. + +**Response 200:** +```json +{ + "data": [ + { + "username": "rbsetiawan", + "display_name": "R B Setiawan", + "email": "rbsetiawan@gisportal.id", + "department": "IT", + "groups": ["Domain Admins"], + "enabled": true + } + ] +} +``` + +--- + +### GET /ldap/users/{username} + +Detail user LDAP. + +--- + +### PUT /ldap/users/{username} + +Update user LDAP (scope: `ldap:write`). + +**Request:** +```json +{"display_name": "Nama Baru", "department": "IT Infra"} +``` + +--- + +### POST /ldap/users/{username}/groups + +Tambah user ke group AD (scope: `ldap:write`). + +**Request:** +```json +{"group": "IT-Admin"} +``` + +--- + +### DELETE /ldap/users/{username}/groups/{group} + +Hapus user dari group AD (scope: `ldap:write`). + +--- + +## LDAP Groups + +### GET /ldap/groups + +List semua group AD. + +**Response 200:** +```json +{ + "data": [ + {"name": "Domain Admins", "member_count": 3}, + {"name": "IT-Admin", "member_count": 5} + ] +} +``` + +--- + +### GET /ldap/groups/{group} + +Detail group termasuk daftar member. + +--- + +### POST /ldap/groups + +Buat group baru di AD (scope: `ldap:write`, admin only). + +**Request:** +```json +{"name": "IT-GIS", "description": "GIS Team"} +``` + +--- + +### POST /ldap/groups/{group}/members + +Tambah member ke group. + +**Request:** +```json +{"username": "rbsetiawan"} +``` + +--- + +### DELETE /ldap/groups/{group}/members/{username} + +Hapus member dari group. diff --git a/server-connection/docs/api/service-project-search.md b/server-connection/docs/api/service-project-search.md new file mode 100644 index 0000000..8ba2142 --- /dev/null +++ b/server-connection/docs/api/service-project-search.md @@ -0,0 +1,73 @@ +# API — Project Search (AI) + +> **Base URL:** `https://console.gisportal.id/api/v1` +> **Auth:** `Authorization: Bearer ` + scope `project-search:read` +> **Status:** Fase 4 — endpoint terdaftar, implementasi belum aktif + +--- + +## GET /project-search/sources + +Daftar sumber data yang tersedia untuk pencarian. + +**Response 200:** +```json +{ + "data": [ + {"id": "project", "name": "Project Files", "path": "\\\\10.100.1.10\\project", "status": "not_indexed"}, + {"id": "marketing", "name": "Marketing Files", "status": "not_indexed"} + ] +} +``` + +--- + +## GET /project-search/index/status + +Status indeks per source. + +**Response 200:** +```json +{ + "data": [ + {"source": "project", "total_files": 0, "indexed_files": 0, "last_indexed_at": null} + ] +} +``` + +--- + +## POST /project-search/ask + +Query natural language ke project files. + +**Request:** +```json +{ + "query": "dokumen IGN untuk proyek Kendal", + "sources": ["project"], + "limit": 5 +} +``` + +**Response 200 (saat aktif):** +```json +{ + "answer": "Dokumen IGN untuk proyek Kendal tersedia di...", + "sources": [ + {"file": "\\\\10.100.1.10\\project\\2025\\Kendal\\IGN.pdf", "score": 0.95} + ] +} +``` + +--- + +## Catatan + +Implementasi lengkap memerlukan: +1. Indexer worker di VM 10.100.1.26 (crawl + embed) +2. pgvector di `geonet_project_search` PostgreSQL +3. Ollama model `nomic-embed-text` untuk embedding +4. Ollama model `qwen2.5` untuk answer generation + +Lihat `server/ollama-nas-project-search-requirements.md` untuk requirement detail. diff --git a/server-connection/docs/api/service-tokens.md b/server-connection/docs/api/service-tokens.md new file mode 100644 index 0000000..b869a06 --- /dev/null +++ b/server-connection/docs/api/service-tokens.md @@ -0,0 +1,98 @@ +# API — Service Tokens + +> **Base URL:** `https://console.gisportal.id/api/v1` +> **Auth:** `Authorization: Bearer ` + +Service Token adalah token antar-service (bukan user token). Contoh: GeoNetAgent Collector menggunakan service token untuk POST laporan. + +--- + +## GET /service-tokens + +List semua service tokens. + +**Response 200:** +```json +{ + "data": [ + { + "id": "uuid", + "name": "GeoNetAgent Production", + "service": "geonetagent", + "abilities": ["agent:report"], + "expires_at": "2027-06-29T00:00:00+07:00", + "last_used_at": "2026-06-29T09:00:00+07:00", + "revoked_at": null + } + ] +} +``` + +--- + +## POST /service-tokens + +Buat service token baru. + +**Request:** +```json +{ + "name": "GeoNetAgent Production", + "service": "geonetagent", + "abilities": ["agent:report"], + "expires_at": "2027-06-29" +} +``` + +**Response 201:** Token value hanya ditampilkan sekali saat create. +```json +{ + "id": "uuid", + "token": "plain-text-token-nilai-ini-simpan-sekarang", + "name": "GeoNetAgent Production" +} +``` + +--- + +## POST /service-tokens/{id}/revoke + +Revoke token (non-destructive, bisa di-unrevoce). + +--- + +## POST /service-tokens/{id}/regenerate + +Generate token baru, token lama invalid. + +--- + +## DELETE /service-tokens/{id} + +Hapus token permanen. + +--- + +## GET /service-tokens/active + +Semua token aktif (tidak expired, tidak di-revoke). + +--- + +## GET /service-tokens/expired + +Semua token yang sudah expired. + +--- + +## GET /service-tokens/by-service/{service} + +Token berdasarkan nama service. + +**Contoh:** `GET /service-tokens/by-service/geonetagent` + +--- + +## Sync ke GeoNetAgent DB + +Token yang dibuat di geonet-console di-sync otomatis ke tabel `agent_tokens` di `geonetagent_dev` PostgreSQL via `AgentTokenSyncService`. GeoNetAgent Collector bisa validasi token dari DB-nya sendiri. diff --git a/server-connection/docs/architecture/authentication-flow.md b/server-connection/docs/architecture/authentication-flow.md new file mode 100644 index 0000000..046af92 --- /dev/null +++ b/server-connection/docs/architecture/authentication-flow.md @@ -0,0 +1,89 @@ +# Architecture — Authentication Flow + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Auth Methods + +| Method | Digunakan Untuk | Class | +|--------|-----------------|-------| +| **JWT (LDAP login)** | User via browser/app | `LdapJwtService` | +| **API Token** | Developer / personal access | `ApiToken` model | +| **Service Token** | Antar-service | `ServiceToken` model | + +--- + +## Alur Login LDAP → JWT + +```mermaid +sequenceDiagram + participant CLIENT as Browser / App + participant GC as geonet-console + participant LDAP as Active Directory (10.100.1.40) + participant JWT as LdapJwtService + + CLIENT->>GC: POST /api/v1/auth/login {username, password} + GC->>LDAP: LDAP bind dengan credentials user + LDAP-->>GC: bind success / fail + alt bind gagal + GC-->>CLIENT: 401 Unauthorized + end + GC->>GC: LdapAuthService::attempt() — validasi grup admin (jika diperlukan) + GC->>JWT: generate JWT payload {username, groups, iat, exp} + JWT-->>GC: signed JWT token + GC-->>CLIENT: 200 {token, expires_at} +``` + +--- + +## Alur Request dengan Bearer Token + +```mermaid +sequenceDiagram + participant CLIENT as Client + participant GC as geonet-console + participant DB as PostgreSQL + + CLIENT->>GC: GET /api/v1/* \nAuthorization: Bearer + GC->>GC: ApiAuthService::resolve(token) + alt JWT token + GC->>GC: decode + validasi JWT + GC->>GC: buat ApiActor{type: user, identifier, groups} + else API Token + GC->>DB: lookup api_tokens WHERE token_hash = ? + GC->>GC: buat ApiActor{type: api_token, scopes} + else Service Token + GC->>DB: lookup service_tokens WHERE token = ? AND active + GC->>GC: buat ApiActor{type: service_token, abilities} + end + GC->>GC: Controller pakai ApiActor + GC-->>CLIENT: Response +``` + +--- + +## LDAP Config + +| Parameter | Nilai | +|-----------|-------| +| Host | `10.100.1.40` | +| Port | `389` | +| Bind DN | `Administrator@gisportal.id` | +| Base DN | `DC=gisportal,DC=id` | +| Admin Groups | `Domain Admins`, `Administrators`, `Enterprise Admins` | + +--- + +## Service Token Flow (Antar-Service) + +``` +GeoNetAgent Collector + → POST /api/v1/agent/report + → Authorization: Bearer + → geonet-console: lookup service_tokens + → ApiActor{type: service_token, service: "geonetagent"} + → proses request +``` + +Service token di-sync ke `geonetagent_dev.agent_tokens` via `AgentTokenSyncService`. diff --git a/server-connection/docs/architecture/database-flow.md b/server-connection/docs/architecture/database-flow.md new file mode 100644 index 0000000..079ca28 --- /dev/null +++ b/server-connection/docs/architecture/database-flow.md @@ -0,0 +1,78 @@ +# Architecture — Database Flow + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Database Connections + +``` +geonet-console Laravel + │ + ├── pgsql (default) → audit-postgres:5432/databaselist_app + │ Metadata: ldap_user_meta, service_tokens, api_tokens, database_connections + │ + ├── audit → audit-postgres:5432/databaselist_audit + │ Audit log: audit_logs + │ + ├── mssql → 10.100.1.25:1433/master + │ Read-only: database registry (SQL Server) + │ + └── project_search → 10.100.1.25:5432/geonet_project_search + Vector search index (Fase 4 — Ollama) +``` + +--- + +## Alur Write — API Request + +```mermaid +sequenceDiagram + participant API as API Request + participant SVC as Service Layer + participant PGSQL as PostgreSQL (app) + participant AUDIT as PostgreSQL (audit) + + API->>SVC: Update LDAP user meta + SVC->>PGSQL: UPDATE ldap_user_meta SET ... + SVC->>AUDIT: INSERT audit_logs {actor, action, payload} + PGSQL-->>SVC: OK + AUDIT-->>SVC: OK + SVC-->>API: 200 success +``` + +**Aturan:** Semua aksi write wajib log ke audit DB via `AuditLogService`. + +--- + +## Alur Read — Database Registry + +``` +GET /api/v1/databases + → DatabaseConnectionManager::listAll() + → mssql connection → SELECT name, state FROM sys.databases + → PostgreSQL (pgsql) → SELECT * FROM database_connections + → merge + return +``` + +--- + +## Vector Search (Fase 4 — Belum Aktif) + +``` +POST /api/v1/project-search/ask {query} + → ProjectSearchService::ask() + → OllamaService::embed(query) → 10.100.1.26:11434 + → project_search DB → SELECT ... ORDER BY embedding <-> $vector + → OllamaService::generate(context + query) + → return {answer, sources} +``` + +--- + +## Catatan Penting + +- `DB_CONNECTION=pgsql` di `compose.yaml` override `.env` — jangan ubah +- `project_search` koneksi ke 10.100.1.25 external — migration gagal jika unreachable (non-critical) +- OAuth keys ada di Docker volume `app_storage` (bukan DB) +- Audit DB (`databaselist_audit`) terpisah dari app DB untuk isolasi diff --git a/server-connection/docs/architecture/deployment-architecture.md b/server-connection/docs/architecture/deployment-architecture.md new file mode 100644 index 0000000..3707da1 --- /dev/null +++ b/server-connection/docs/architecture/deployment-architecture.md @@ -0,0 +1,88 @@ +# Architecture — Deployment Architecture + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Topology + +``` +Internet / LAN + │ HTTPS :443 + ▼ +┌──────────────────────────────────────────────────┐ +│ Nginx Reverse Proxy (10.100.1.24) │ +│ /etc/nginx/conf.d/production/ │ +│ - geonet-console.conf → console.gisportal.id │ +│ - databaselist.conf → databaselist.gisportal.id│ +│ /etc/nginx/conf.d/nas.conf │ +│ - file.gisportal.id/super-apps/ → QNAP OSS │ +└──────────────┬───────────────────────────────────┘ + │ proxy_pass 127.0.0.1:8091 + ▼ + ┌──────────────────────────────┐ + │ geonet-console Container │ + │ PHP 8.3 + Laravel 12 │ + │ PHP-FPM + Nginx (in-cont) │ + │ supervisord │ + │ Port: :8091 │ + └──────────┬───────────────────┘ + │ + ┌──────────┴──────────────────┐ + │ audit-postgres Container │ + │ PostgreSQL 15 │ + │ - databaselist_app │ + │ - databaselist_audit │ + └─────────────────────────────┘ + +External: + QNAP OSS (10.100.1.10:8010) — avatar storage + LDAP AD (10.100.1.40) — authentication + SQL Server (10.100.1.25) — DB registry read +``` + +--- + +## Docker Compose (geonet-console) + +```yaml +services: + geonet-console: + build: . + ports: + - "127.0.0.1:8091:80" + env_file: .env + depends_on: [audit-postgres] + restart: unless-stopped + volumes: + - app_storage:/var/www/html/storage + + audit-postgres: + image: postgres:15 + env_file: .env + restart: unless-stopped + volumes: + - audit_pg_data:/var/lib/postgresql/data + +volumes: + app_storage: + audit_pg_data: +``` + +--- + +## Stack Paths di Server + +| Stack | Path | +|-------|------| +| geonet-console | `/opt/stacks/geonet-console/` | +| databaselist | `/opt/stacks/databaselist/` | +| sqlservercheck | `/opt/stacks/sqlservercheck/` | +| my-portal | `/opt/stacks/my-portal/` | + +--- + +## SSL + +HTTPS via Let's Encrypt (certbot) di Nginx 10.100.1.24. Semua domain `*.gisportal.id` di-terminate di Nginx. +Port 80 redirect → 443. diff --git a/server-connection/docs/architecture/folder-structure.md b/server-connection/docs/architecture/folder-structure.md new file mode 100644 index 0000000..789da59 --- /dev/null +++ b/server-connection/docs/architecture/folder-structure.md @@ -0,0 +1,106 @@ +# Architecture — Folder Structure + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Struktur Monorepo + +``` +server-connection/ +│ +├── README.md — Project overview + quick start +├── AGENTS.md — Aturan AI agent +├── perintah.md — Quick reference + protokol sync +├── readme.txt — SSH & deploy commands ringkas +├── rules — Requirement bisnis manual +├── rules-adv — Requirement bisnis lanjutan +│ +├── geonet-console/ — Laravel 12 unified IT portal +│ ├── context-index.md ← Entry point AI untuk proyek ini +│ ├── DOCKGE.md ← Ringkasan deploy & env vars +│ ├── .env.example ← Template env vars +│ ├── compose.yaml ← Docker Compose +│ ├── Dockerfile ← Multi-stage PHP 8.3 build +│ ├── docker/entrypoint.sh ← Startup script +│ ├── app/ +│ │ ├── Http/Controllers/Api/V1/ +│ │ ├── Models/ +│ │ ├── Services/ +│ │ └── Support/ +│ ├── config/ +│ ├── database/migrations/ +│ ├── routes/api.php +│ ├── docapi/ ← Dokumentasi API lengkap +│ │ ├── README.md +│ │ ├── index.md +│ │ ├── authentication.md +│ │ ├── common-response.md +│ │ ├── common-error.md +│ │ ├── integration-guide.md +│ │ └── services/ +│ └── resources/ +│ +├── databaselist/ — Legacy Laravel (deprecated) +│ +├── sqlservercheck/ — Tool cek SQL Server +│ +├── scripts/ — Deploy & SSH scripts +│ ├── deploy-geonet-console.ps1 +│ ├── deploy-databaselist.ps1 +│ ├── deploy-sqlservercheck.ps1 +│ ├── deploy-geonet-console-nginx.ps1 +│ ├── ssh-remote.ps1 +│ ├── ssh-mikrotik.ps1 +│ ├── ssh-ollama.ps1 +│ ├── ssh-qnap.ps1 +│ ├── ssh-zabbix.ps1 +│ ├── setup-ssh-mikrotik.ps1 +│ ├── cutover-geonet-console.ps1 +│ ├── geonet-indexer/ ← Indexer worker scripts (Fase 4) +│ └── *.ps1 / *.sh +│ +├── server/ — Audit & MikroTik configs +│ ├── host.md ← Daftar host & IP +│ ├── ollama-nas-project-search-requirements.md +│ ├── *-audit.txt ← Audit snapshot server +│ ├── mikrotik-*.rsc ← MikroTik scripts +│ └── nginx/ +│ +├── docs/ — Dokumentasi lengkap ⭐ +│ ├── context-index.md ← Entry point AI +│ ├── architecture/ +│ ├── api/ +│ ├── adr/ +│ ├── diagrams/ +│ ├── onboarding/ +│ └── decisions/ +│ +├── .cursor/ — AI context +│ ├── context-index.md +│ ├── me.md ← Profil + infrastruktur +│ ├── rules/ +│ │ ├── 00-project-context.mdc +│ │ ├── 01-enterprise-principles.mdc +│ │ ├── 02-implementation-status.mdc +│ │ ├── 03-ai-behavior.mdc +│ │ ├── 04-geonet-uiux.mdc +│ │ ├── 05-laravel-backend.mdc +│ │ └── 06-infrastructure.mdc +│ └── adr/ +│ +└── config-check.rsc — MikroTik config check script +``` + +--- + +## Konvensi Penamaan + +| Tipe | Konvensi | Contoh | +|------|----------|--------| +| PHP file | `PascalCase.php` | `LdapAuthService.php` | +| DB tabel | `snake_case` plural | `ldap_user_meta` | +| Route | `/kebab-case` | `/api/v1/ldap/users` | +| Script PS1 | `verb-noun.ps1` | `deploy-geonet-console.ps1` | +| Doc file | `kebab-case.md` | `system-overview.md` | +| ADR | `ADR-NNNN-title.md` | `ADR-0001-monorepo-structure.md` | diff --git a/server-connection/docs/architecture/request-flow.md b/server-connection/docs/architecture/request-flow.md new file mode 100644 index 0000000..807c36e --- /dev/null +++ b/server-connection/docs/architecture/request-flow.md @@ -0,0 +1,66 @@ +# Architecture — Request Flow + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Alur Request Browser → API + +```mermaid +sequenceDiagram + participant B as Browser / Next.js + participant NGX as Nginx (10.100.1.24) + participant GC as geonet-console (:8091) + participant DB as PostgreSQL (audit-postgres) + participant LOG as Audit DB + + B->>NGX: HTTPS GET console.gisportal.id/api/v1/ldap/users + NGX->>GC: proxy_pass 127.0.0.1:8091 + GC->>GC: Middleware: auth (ApiAuthService::resolve) + GC->>GC: Rate limit check + GC->>GC: Controller → LdapUserService + GC->>DB: Query jika diperlukan (ldap_user_meta) + DB-->>GC: data + GC->>LOG: AuditLogService::log() (untuk write actions) + GC-->>NGX: JSON response + NGX-->>B: JSON response +``` + +--- + +## Middleware Stack (geonet-console) + +| Middleware | Fungsi | +|-----------|--------| +| `throttle:60,1` (general) | Rate limit umum | +| `throttle:5,1` (login) | Rate limit login | +| `auth.api` | Resolve Bearer token → ApiActor | +| `scope:` | Cek scope/ability token | + +--- + +## Route Groups + +``` +/api/v1/auth/* — Public (tidak butuh auth) +/api/v1/me — Auth: JWT atau API Token +/api/v1/ldap/* — Auth + scope: ldap:read / ldap:write +/api/v1/databases/* — Auth + scope: databases:read / databases:write +/api/v1/service-tokens/*— Auth (JWT atau token dengan akses service) +/api/v1/project-search/*— Auth + scope: project-search:read +``` + +--- + +## File Upload Flow (Avatar) + +``` +Client → PUT /api/v1/me/avatar {data: base64} + → geonet-console: decode base64 + → Storage::disk('oss')->put('avatars/', $content) + → QNAP OSS (http://10.100.1.10:8010) + → ldap_user_meta.avatar = 'avatars/' (path relatif) + → return {avatar_url: 'https://file.gisportal.id/super-apps/avatars/'} +``` + +Avatar URL: via Nginx proxy `/super-apps/` → QNAP OSS → bucket `super-apps` (public-read) diff --git a/server-connection/docs/architecture/storage.md b/server-connection/docs/architecture/storage.md new file mode 100644 index 0000000..2555cf5 --- /dev/null +++ b/server-connection/docs/architecture/storage.md @@ -0,0 +1,57 @@ +# Architecture — Storage + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## QNAP OSS — Object Storage (Avatar) + +| Item | Nilai | +|------|-------| +| Provider | QNAP QuObjects (S3-compatible) | +| Host | `10.100.1.10:8010` | +| Bucket | `super-apps` | +| ACL | `public-read` | +| URL Publik | `https://file.gisportal.id/super-apps/` | +| Laravel Disk | `oss` (`config/filesystems.php`) | +| Driver | `s3` dengan `use_path_style_endpoint=true` | + +### Cara Kerja Avatar + +``` +PUT /api/v1/me/avatar {data: base64} + → decode base64 → Storage::disk('oss')->put('avatars/', $content) + → simpan path relatif 'avatars/' di ldap_user_meta.avatar + → return {avatar_url: 'https://file.gisportal.id/super-apps/avatars/'} +``` + +### Nginx Proxy OSS + +`/etc/nginx/conf.d/nas.conf`: +```nginx +location /super-apps/ { + proxy_pass http://10.100.1.10:8010/v1/AUTH_super-apps/super-apps/; +} +``` + +--- + +## Docker Volume — App Storage + +| Volume | Mount | Isi | +|--------|-------|-----| +| `app_storage` | `/var/www/html/storage` | Session, logs, OAuth keys | +| `audit_pg_data` | `/var/lib/postgresql/data` | PostgreSQL data | + +> OAuth keys (`oauth-private.key`, `oauth-public.key`) di-generate otomatis saat container pertama kali start, disimpan di `app_storage`. + +--- + +## NAS QNAP SMB (Fase 4 — Project Search) + +| Share | Path | Dipakai Untuk | +|-------|------|---------------| +| `\\10.100.1.10\project` | `/mnt/qnap/project` | Indexer crawl project files | +| `\\10.100.1.10\Marketing` | `/mnt/qnap/marketing` | Indexer (future) | + +Indexer di Ollama VM (10.100.1.26) mount SMB → crawl → embed → simpan ke pgvector. diff --git a/server-connection/docs/architecture/system-overview.md b/server-connection/docs/architecture/system-overview.md new file mode 100644 index 0000000..e12e0aa --- /dev/null +++ b/server-connection/docs/architecture/system-overview.md @@ -0,0 +1,77 @@ +# Architecture — System Overview + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Diagram Sistem + +```mermaid +graph TB + subgraph CLIENTS["Clients"] + BROWSER["Browser\n(IT Admin, User)"] + NEXTJS["Next.js PWA\nmy.gisportal.id"] + AGENT["PowerShell Agent\n(Endpoint Windows)"] + end + + subgraph SERVER24["10.100.1.24 — App Server (CentOS 8)"] + NGX["Nginx\nSSL termination\nReverse Proxy"] + GC["geonet-console\nLaravel 12 + PHP 8.3\n:8091"] + PGCON["audit-postgres\nPostgreSQL\n(container)"] + end + + subgraph SERVER25["10.100.1.25 — Database Server"] + MSSQL["SQL Server 2019\n:1433"] + PGSEARCH["PostgreSQL\ngeonet_project_search\n(pgvector - Fase 4)"] + end + + subgraph INFRA["Infrastruktur Existing"] + AD["AD / LDAP\n10.100.1.40"] + QNAP["QNAP NAS\n10.100.1.10\nOSS + SMB"] + OLLAMA["Ollama VM\n10.100.1.26\n(Fase 4)"] + ZABBIX["Zabbix\n10.100.1.42"] + MIKROTIK["MikroTik CCR2004\n10.100.1.1"] + end + + BROWSER -->|HTTPS| NGX + NEXTJS -->|HTTPS API| NGX + AGENT -->|HTTPS POST| NGX + NGX -->|:8091| GC + GC --> PGCON + GC -->|LDAP bind| AD + GC -->|read registry| MSSQL + GC -->|OSS S3 avatar| QNAP + GC -.->|Fase 4| PGSEARCH + GC -.->|Fase 4| OLLAMA + NGX -->|/super-apps/| QNAP + + style GC fill:#2196F3,color:#fff + style PGCON fill:#FF9800,color:#fff + style NGX fill:#607D8B,color:#fff +``` + +--- + +## Komponen + +| Komponen | Role | Host | +|----------|------|------| +| **Nginx** | SSL termination + reverse proxy | 10.100.1.24 | +| **geonet-console** | IT portal — auth, LDAP mgmt, DB registry, API | 10.100.1.24:8091 | +| **audit-postgres** | PostgreSQL app + audit DB | container di 10.100.1.24 | +| **Active Directory** | Auth source (LDAP bind) | 10.100.1.40 | +| **SQL Server** | Database registry (read-only) | 10.100.1.25:1433 | +| **QNAP OSS** | Avatar + file storage (S3-compatible) | 10.100.1.10:8010 | +| **Zabbix** | Server/VM monitoring real-time | 10.100.1.42 | +| **MikroTik** | Gateway, firewall, routing | 10.100.1.1 | +| **Ollama VM** | AI inference (Fase 4) | 10.100.1.26:11434 | + +--- + +## Prinsip Arsitektur + +- **Geonet-console** = unified IT portal, bukan tool tunggal +- **Jangan duplikasi Zabbix** — monitoring real-time tetap di Zabbix +- **LDAP sebagai auth source** — tidak ada local user di geonet-console +- **PostgreSQL untuk app baru** — SQL Server hanya untuk legacy/GIS +- **QNAP OSS untuk file** — bukan filesystem lokal server diff --git a/server-connection/docs/changelog.md b/server-connection/docs/changelog.md new file mode 100644 index 0000000..3adad8c --- /dev/null +++ b/server-connection/docs/changelog.md @@ -0,0 +1,86 @@ +# Changelog — server-connection + +--- + +## [Doc 1.0.0] — 2026-06-29 + +### Added (Dokumentasi) +- `README.md` — root README lengkap +- `docs/context-index.md` ⭐ — AI entry point utama +- `docs/project-status.md` +- `docs/roadmap.md` +- `docs/todo.md` +- `docs/issues.md` +- `docs/changelog.md` (file ini) +- `docs/environment.md` +- `docs/server.md` +- `docs/deployment.md` +- `docs/development.md` +- `docs/database.md` +- `docs/troubleshooting.md` +- `docs/monitoring.md` +- `docs/security.md` +- `docs/glossary.md` +- `docs/architecture/system-overview.md` +- `docs/architecture/folder-structure.md` +- `docs/architecture/request-flow.md` +- `docs/architecture/authentication-flow.md` +- `docs/architecture/database-flow.md` +- `docs/architecture/storage.md` +- `docs/architecture/deployment-architecture.md` +- `docs/api/overview.md` +- `docs/api/service-auth.md` +- `docs/api/service-ldap.md` +- `docs/api/service-database.md` +- `docs/api/service-tokens.md` +- `docs/api/service-project-search.md` +- `docs/api/error-codes.md` +- `docs/adr/README.md` + ADR-0001 s/d ADR-0004 +- `docs/diagrams/*.mmd` +- `docs/onboarding/first-day.md` +- `docs/onboarding/local-setup.md` +- `docs/onboarding/coding-standard.md` +- `docs/decisions/technology-stack.md` +- `docs/decisions/naming-convention.md` +- `.cursor/rules/coding.mdc` +- `.cursor/rules/architecture.mdc` +- `.cursor/rules/documentation.mdc` +- `.cursor/rules/api.mdc` +- `.cursor/rules/database.mdc` +- `.cursor/rules/security.mdc` +- `.cursor/rules/deployment.mdc` + +--- + +## [2026-06-23] — geonet-console + +### Added +- Service Tokens: CRUD API + sync ke GeoNetAgent DB (`AgentTokenSyncService`) +- Service Tokens: migration, model, service, API endpoints, UI, audit log + +--- + +## [2026-06-11] — Infrastructure + +### Changed +- Lengkapi `me.md` & `perintah.md` — URL produksi, indeks file +- Selaraskan server-connection / GeoNetAgent context + +--- + +## [2026-06-xx] — geonet-console + +### Added +- PWA Fase B: install banner + cache stale-while-revalidate +- Avatar upload ke QNAP OSS (migrasi dari local storage) + +--- + +## [2026-05-xx] — geonet-console + +### Added +- LDAP Auth + JWT (login, refresh, token-guide) +- LDAP User & Group Management API +- Database Registry API +- Audit log ke DB terpisah +- Personal API Token diff --git a/server-connection/docs/context-index.md b/server-connection/docs/context-index.md new file mode 100644 index 0000000..ebc76eb --- /dev/null +++ b/server-connection/docs/context-index.md @@ -0,0 +1,155 @@ +# Context Index — server-connection ⭐ AI Entry Point + +> **Terakhir Diperbarui:** 2026-06-29 +> **Versi:** 2.0.0 + +--- + +## Filosofi + +Proyek ini menerapkan **AI Native Development**: +- Repository = sumber kebenaran utama (Single Source of Truth) +- AI tidak boleh mengandalkan riwayat percakapan +- Developer sering berpindah perangkat — konteks harus tersimpan di repo +- Implementasi tanpa dokumentasi = belum selesai + +--- + +## Urutan Membaca + +1. **File ini** — peta navigasi +2. `.cursor/me.md` — profil user + inventaris infrastruktur +3. `perintah.md` — quick reference + protokol sync +4. `.cursor/rules/` — behavior rules AI +5. Dokumen spesifik task (lihat tabel di bawah) + +--- + +## Proyek dalam Repo Ini + +| Proyek | URL | Stack | Status | Context | +|--------|-----|-------|--------|---------| +| **geonet-console** | https://console.gisportal.id | Laravel 12 | ✅ Production | [`geonet-console/context-index.md`](../geonet-console/context-index.md) | +| **databaselist** | https://databaselist.gisportal.id | Laravel legacy | ⚠️ Legacy | — | +| **sqlservercheck** | https://sqlservercheck.gisportal.id | PHP | ✅ Running | — | + +> AI yang bekerja pada proyek spesifik **wajib membaca context-index proyek tersebut**. + +--- + +## Peta Dokumentasi + +### `docs/` — Flat Files + +| File | Isi | Baca Saat | +|------|-----|-----------| +| `docs/project-status.md` | Status modul, backlog, known issues | Selalu | +| `docs/roadmap.md` | Fase pengembangan, milestone | Planning | +| `docs/todo.md` | Next actions berprioritas | Sebelum coding | +| `docs/issues.md` | Known bugs + workaround | Debug | +| `docs/changelog.md` | Riwayat perubahan | Reference | +| `docs/environment.md` | Env vars (tanpa secret) | Setup, deploy | +| `docs/server.md` | Server list, SSH, Docker | Deploy, infra | +| `docs/deployment.md` | Step-by-step deploy | Deploy | +| `docs/development.md` | Setup lokal, coding standard | Onboarding | +| `docs/database.md` | Schema DB, migrations, koneksi | DB change | +| `docs/troubleshooting.md` | Debug common problems | Debug | +| `docs/monitoring.md` | Zabbix, health check | Monitoring | +| `docs/security.md` | Credential management | Security | +| `docs/glossary.md` | Kamus istilah | Reference | + +### `docs/architecture/` — Arsitektur + +| File | Isi | +|------|-----| +| `system-overview.md` | Diagram sistem + komponen | +| `folder-structure.md` | Struktur monorepo | +| `request-flow.md` | Alur request API | +| `authentication-flow.md` | Auth LDAP → JWT | +| `database-flow.md` | DB connections, read/write | +| `storage.md` | QNAP OSS object storage | +| `deployment-architecture.md` | Server topology, Docker, Nginx | + +### `docs/api/` — API Documentation + +| File | Isi | +|------|-----| +| `overview.md` | Base URL, auth, format response | +| `service-auth.md` | Login, refresh, token guide | +| `service-ldap.md` | LDAP users & groups | +| `service-database.md` | Database registry | +| `service-tokens.md` | Service tokens | +| `service-project-search.md` | AI project search | +| `error-codes.md` | Error format standard | + +### `docs/adr/` — Architecture Decision Records + +| ADR | Keputusan | +|-----|-----------| +| `ADR-0001-monorepo-structure.md` | Struktur monorepo + folder convention | +| `ADR-0002-database-postgresql.md` | PostgreSQL untuk app baru | +| `ADR-0003-ldap-authentication.md` | Auth via LDAP Active Directory | +| `ADR-0004-qnap-object-storage.md` | QNAP OSS untuk file storage | + +### `.cursor/` — AI Context (Detail Teknis) + +| File | Isi | +|------|-----| +| `.cursor/context-index.md` | Entry point detail (versi lama) | +| `.cursor/me.md` | Profil user + inventaris infrastruktur | +| `.cursor/rules/00-project-context.mdc` | Struktur repo, host SSH, deploy | +| `.cursor/rules/01-enterprise-principles.mdc` | Prinsip enterprise & UX | +| `.cursor/rules/02-implementation-status.mdc` | Status fitur geonet-console | +| `.cursor/rules/03-ai-behavior.mdc` | Perilaku agent, larangan | +| `.cursor/rules/04-geonet-uiux.mdc` | Standar UI/UX | +| `.cursor/rules/05-laravel-backend.mdc` | Backend Laravel | +| `.cursor/rules/06-infrastructure.mdc` | SSH, MikroTik, deploy | + +--- + +## Quick Reference + +### URL Produksi + +| Fungsi | URL | +|--------|-----| +| Geonet Console login | https://console.gisportal.id | +| LDAP Users | https://console.gisportal.id/ldap-users | +| API Docs | https://console.gisportal.id/api-docs | +| REST API | https://console.gisportal.id/api/v1 | +| Databaselist (legacy) | https://databaselist.gisportal.id | +| SQL Server Check | https://sqlservercheck.gisportal.id/ts | + +### Deploy Commands + +```powershell +.\scripts\deploy-geonet-console.ps1 +.\scripts\deploy-databaselist.ps1 +.\scripts\deploy-sqlservercheck.ps1 +``` + +### SSH Commands + +| Server | Command | +|--------|---------| +| Reverse Proxy | `ssh -m hmac-sha1 root@10.100.1.24 -p 22` | +| Database | `ssh -m hmac-sha1 root@10.100.1.25 -p 22` | +| AD/LDAP | `ssh -m hmac-sha1 Administrator@10.100.1.40 -p 22` | +| MikroTik | `.\scripts\ssh-mikrotik.ps1` | +| QNAP NAS | `.\scripts\ssh-qnap.ps1` | +| Ollama VM | `.\scripts\ssh-ollama.ps1` | +| Zabbix | `.\scripts\ssh-zabbix.ps1` | + +> SSH commands ke server **wajib minta persetujuan user** sebelum dijalankan. + +--- + +## Aturan Utama AI + +1. Baca `docs/context-index.md` ini terlebih dahulu +2. Baca `.cursor/me.md` untuk konteks infrastruktur +3. Untuk geonet-console: baca `geonet-console/context-index.md` dan `geonet-console/docapi/` +4. Setelah selesai: update `perintah.md` (Sync terakhir) +5. ADR tidak boleh dihapus — buat baru jika keputusan berubah +6. **Jangan commit secret** ke repository +7. **JANGAN overwrite `.env`** saat deploy — `.env` server berisi credentials production diff --git a/server-connection/docs/database.md b/server-connection/docs/database.md new file mode 100644 index 0000000..a582292 --- /dev/null +++ b/server-connection/docs/database.md @@ -0,0 +1,126 @@ +# Database Documentation + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Koneksi Database + +| Connection Name | Driver | Host | Database | Dipakai Untuk | +|----------------|--------|------|----------|----------------| +| `pgsql` (default) | PostgreSQL | `audit-postgres` (container) | `databaselist_app` | App metadata, user meta, tokens, settings | +| `audit` | PostgreSQL | `audit-postgres` (container) | `databaselist_audit` | Audit log aktivitas | +| `project_search` | PostgreSQL | `10.100.1.25` (external) | `geonet_project_search` | Indeks AI project search (Fase Ollama) | +| `mssql` | SQL Server | `10.100.1.25:1433` | `master` | Database registry (read-only) | + +> `DB_CONNECTION=pgsql` di `compose.yaml` override nilai di `.env`. **Jangan ubah ke sqlite.** + +--- + +## Database: `databaselist_app` (PostgreSQL App) + +### Tabel Utama + +| Tabel | Model | Keterangan | +|-------|-------|------------| +| `ldap_user_meta` | `LdapUserMeta` | Metadata user LDAP (avatar, settings, last login) | +| `ldap_group_meta` | `LdapGroupMeta` | Metadata group LDAP | +| `database_connections` | `DatabaseConnection` | Registry database (SQL Server, PostgreSQL, dll.) | +| `service_tokens` | `ServiceToken` | Token antar-service (sync ke GeoNetAgent) | +| `api_tokens` | `ApiToken` | Personal API token per user | +| `oauth_access_tokens` | — | Laravel Passport/Sanctum tokens | +| `oauth_personal_access_clients` | — | OAuth clients | + +### `ldap_user_meta` + +| Kolom | Tipe | Keterangan | +|-------|------|------------| +| `id` | bigint PK | | +| `username` | varchar UNIQUE | LDAP username | +| `avatar` | varchar nullable | Path relatif di OSS: `avatars/` | +| `display_name` | varchar nullable | | +| `email` | varchar nullable | | +| `department` | varchar nullable | | +| `last_login_at` | timestamp nullable | Terakhir login | +| `created_at` | timestamp | | +| `updated_at` | timestamp | | + +### `service_tokens` + +| Kolom | Tipe | Keterangan | +|-------|------|------------| +| `id` | bigint PK | | +| `name` | varchar | Nama token | +| `service` | varchar | Nama service pemilik | +| `token` | varchar UNIQUE | Token value (hashed) | +| `abilities` | json | Scopes/abilities | +| `expires_at` | timestamp nullable | | +| `last_used_at` | timestamp nullable | | +| `revoked_at` | timestamp nullable | | +| `created_at` | timestamp | | + +--- + +## Database: `databaselist_audit` (Audit Log) + +### `audit_logs` + +| Kolom | Tipe | Keterangan | +|-------|------|------------| +| `id` | bigint PK | | +| `actor` | varchar | Username atau service yang melakukan aksi | +| `actor_type` | varchar | `user`, `api_token`, `service_token` | +| `action` | varchar | Nama aksi (mis. `ldap.user.update`) | +| `target_type` | varchar nullable | Resource yang diubah | +| `target_id` | varchar nullable | ID resource | +| `payload` | json nullable | Data sebelum/sesudah perubahan | +| `ip_address` | varchar nullable | | +| `created_at` | timestamp | | + +--- + +## Migration + +### Cara Menjalankan Migration + +Migration berjalan **otomatis saat container start** via `docker/entrypoint.sh`. + +Untuk manual: +```bash +docker exec geonet-console php artisan migrate --force +``` + +### Catatan Penting + +- Migration `project_search` DB membutuhkan koneksi ke `10.100.1.25` — jika tidak reachable, container tetap start tapi log warning muncul. +- Jangan jalankan `migrate:fresh` di production. +- OAuth keys di-generate otomatis dan disimpan di Docker volume `app_storage`. + +--- + +## Akses Database (Lokal) + +```bash +# Masuk ke container PostgreSQL +docker exec -it audit-postgres psql -U geonet_app -d databaselist_app + +# Dari server 10.100.1.24 +ssh -m hmac-sha1 root@10.100.1.24 -p 22 +docker exec -it audit-postgres psql -U geonet_app -d databaselist_app +``` + +--- + +## SQL Server (Registry Read-Only) + +SQL Server di `10.100.1.25:1433` digunakan oleh geonet-console hanya untuk **membaca daftar database** (database registry). Tidak ada write ke SQL Server dari geonet-console. + +Driver: `pdo_sqlsrv` (terinstall di container via Dockerfile) + +--- + +## Lihat Juga + +- `geonet-console/database/migrations/` — semua migration files +- `geonet-console/config/database.php` — konfigurasi koneksi +- `geonet-console/.env.example` — env vars database diff --git a/server-connection/docs/decisions/naming-convention.md b/server-connection/docs/decisions/naming-convention.md new file mode 100644 index 0000000..08581d6 --- /dev/null +++ b/server-connection/docs/decisions/naming-convention.md @@ -0,0 +1,70 @@ +# Decisions — Naming Convention + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## File & Folder + +| Tipe | Konvensi | Contoh | +|------|----------|--------| +| PHP Class file | `PascalCase.php` | `LdapAuthService.php` | +| Blade template | `kebab-case.blade.php` | `user-profile.blade.php` | +| Migration | `YYYY_MM_DD_HHMMSS_verb_table.php` | `2026_06_23_create_service_tokens_table.php` | +| PowerShell script | `verb-noun.ps1` | `deploy-geonet-console.ps1` | +| Docs markdown | `kebab-case.md` | `system-overview.md` | +| ADR | `ADR-NNNN-title.md` | `ADR-0001-monorepo-structure.md` | +| Mermaid diagram | `purpose.mmd` | `deployment.mmd` | + +--- + +## Database + +| Tipe | Konvensi | Contoh | +|------|----------|--------| +| Tabel | `snake_case` plural | `ldap_user_meta`, `service_tokens` | +| Kolom | `snake_case` | `last_used_at`, `display_name` | +| FK | `_id` | `user_id`, `token_id` | +| Index | `__index` | `service_tokens_service_index` | +| DB name | `_` | `databaselist_app`, `databaselist_audit` | + +--- + +## API Routes + +| Konvensi | Contoh | +|----------|--------| +| `/kebab-case` plural | `/api/v1/ldap/users` | +| Path param | `/api/v1/service-tokens/{id}` | +| Nested resource | `/api/v1/ldap/users/{username}/groups` | +| Action non-CRUD | `POST /api/v1/service-tokens/{id}/revoke` | + +--- + +## PHP / Laravel + +| Tipe | Konvensi | Contoh | +|------|----------|--------| +| Class | `PascalCase` | `LdapAuthService` | +| Method | `camelCase` | `resolveToken()` | +| Variable | `camelCase` | `$apiActor` | +| Constant | `UPPER_SNAKE_CASE` | `TOKEN_TYPE_JWT` | + +--- + +## Env Variables + +Semua `UPPER_SNAKE_CASE`: +``` +APP_NAME, DB_CONNECTION, LDAP_HOST, OSS_ENDPOINT +``` + +--- + +## Git Commit + +``` +: +``` + +Contoh: `feat: tambah endpoint regenerate service token` diff --git a/server-connection/docs/decisions/technology-stack.md b/server-connection/docs/decisions/technology-stack.md new file mode 100644 index 0000000..1bd4b57 --- /dev/null +++ b/server-connection/docs/decisions/technology-stack.md @@ -0,0 +1,78 @@ +# Decisions — Technology Stack + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Backend — Laravel 12 (PHP 8.3) + +**Dipilih karena:** +- Tim familiar dengan PHP/Laravel +- Eloquent ORM + migration system matang +- Built-in: auth, queue, mail, broadcast +- Komunitas besar, LTS roadmap jelas + +**Ditolak:** +- FastAPI (Python): Dipakai di GeoNetAgent — pilihan valid, tapi tim lebih familiar Laravel untuk portal +- Node.js/Express: Less familiar, lebih cocok untuk real-time + +--- + +## Database — PostgreSQL + +**Dipilih karena:** +- Open source, tidak ada biaya lisensi +- Support pgvector untuk Fase 4 (Ollama AI search) +- JSON/JSONB support +- Docker official image reliable + +**Ditolak:** +- MySQL: Tidak support pgvector +- SQL Server: Berlisensi, sudah ada hanya untuk GIS legacy + +--- + +## Auth — LDAP Active Directory + +**Dipilih karena:** +- Semua user IT sudah di AD +- Single source of truth identity +- Tidak perlu manage password terpisah + +--- + +## File Storage — QNAP QuObjects (OSS) + +**Dipilih karena:** +- Hardware sudah ada (QNAP TS-932X) +- S3-compatible → Laravel `s3` driver standar +- File persist lintas container rebuild + +--- + +## AI Search — Ollama + pgvector (Fase 4) + +**Dipilih karena:** +- Self-hosted, data tidak keluar jaringan internal +- Ollama: mudah deploy + model management +- pgvector: tetap di PostgreSQL yang sudah ada + +**Ditolak:** +- OpenAI API: Data sensitif tidak boleh keluar, biaya berulang +- Elasticsearch: Overkill untuk skala ini + +--- + +## Monitoring — Zabbix + +**Dipilih karena:** +- Sudah berjalan di 10.100.1.42 +- Manage semua server + network + +**Prinsip:** Jangan duplikasi fungsi Zabbix di aplikasi custom. + +--- + +## Infrastruktur Jaringan — MikroTik CCR2004 + +Sudah ada, dikelola via RouterOS scripts (`server/*.rsc`). diff --git a/server-connection/docs/deployment.md b/server-connection/docs/deployment.md new file mode 100644 index 0000000..65b35d1 --- /dev/null +++ b/server-connection/docs/deployment.md @@ -0,0 +1,132 @@ +# Deployment Guide + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Deploy geonet-console + +### Via Script (Direkomendasikan) + +```powershell +.\scripts\deploy-geonet-console.ps1 +``` + +### Manual Step-by-Step + +**Step 1 — Buat archive (dari Windows)** +```powershell +tar -czf "$env:TEMP\geonet-console.tar.gz" ` + --exclude="vendor" --exclude=".git" --exclude="node_modules" ` + -C "D:\Project\app on git\server-connection\geonet-console" . +``` + +**Step 2 — Upload ke server** +```powershell +Start-Process -FilePath "cmd.exe" -ArgumentList ` + '/c ssh -m hmac-sha1 root@10.100.1.24 -p 22 "cat > /tmp/geonet-console.tar.gz" < "%TEMP%\geonet-console.tar.gz"' ` + -Wait -NoNewWindow +``` + +**Step 3 — Extract & deploy di server** +```bash +ssh -m hmac-sha1 root@10.100.1.24 -p 22 +cd /opt/stacks/geonet-console +tar -xzf /tmp/geonet-console.tar.gz -C . && rm /tmp/geonet-console.tar.gz +docker compose up -d --build --force-recreate +``` + +**Step 4 — Verifikasi** +```bash +docker ps --filter name=geonet-console +docker logs geonet-console --tail 30 +curl -s https://console.gisportal.id/health || curl -s http://127.0.0.1:8091/health +``` + +--- + +## Deploy Nginx Config + +```powershell +.\scripts\deploy-geonet-console-nginx.ps1 +``` + +Atau manual: +```bash +ssh -m hmac-sha1 root@10.100.1.24 -p 22 +nginx -t && nginx -s reload +``` + +--- + +## Deploy databaselist (Legacy) + +```powershell +.\scripts\deploy-databaselist.ps1 # build + deploy +.\scripts\deploy-databaselist.ps1 -NoBuild # restart saja +``` + +--- + +## Deploy sqlservercheck + +```powershell +.\scripts\deploy-sqlservercheck.ps1 +``` + +--- + +## Apply DB Migration + +Migration berjalan otomatis saat container start. Untuk manual: +```bash +ssh -m hmac-sha1 root@10.100.1.24 -p 22 +docker exec geonet-console php artisan migrate --force +``` + +--- + +## Setup Pertama Kali (Fresh Deploy) + +```bash +ssh -m hmac-sha1 root@10.100.1.24 -p 22 +mkdir -p /opt/stacks/geonet-console +# Upload file dari laptop (lihat step manual di atas) +cd /opt/stacks/geonet-console +cp .env.example .env +nano .env # isi semua credentials +docker compose up -d --build +``` + +--- + +## Rollback + +```bash +ssh -m hmac-sha1 root@10.100.1.24 -p 22 +cd /opt/stacks/geonet-console +docker compose down +# Upload versi sebelumnya +docker compose up -d --build +``` + +--- + +## Checklist Deployment + +- [ ] Kode terbaru di-commit ke repo lokal +- [ ] Tidak ada file `.env` yang ikut ter-archive +- [ ] Script atau manual upload berhasil +- [ ] `docker compose up -d --build` sukses +- [ ] Container status `Up` (`docker ps`) +- [ ] `https://console.gisportal.id` accessible +- [ ] Login LDAP berhasil +- [ ] Avatar endpoint berfungsi (`GET /me` punya `avatar_url`) +- [ ] Update `perintah.md` (Sync terakhir) + +--- + +## Penting + +> ⚠️ **JANGAN overwrite `.env`** saat deploy — `.env` server berisi credentials production yang tidak ada di repo. +> ⚠️ Extract **tanpa** `--strip-components` agar struktur folder tetap benar. diff --git a/server-connection/docs/development.md b/server-connection/docs/development.md new file mode 100644 index 0000000..7335ae4 --- /dev/null +++ b/server-connection/docs/development.md @@ -0,0 +1,147 @@ +# Development Guide + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Model Kerja + +Pengembangan dilakukan **remote** — kode di-edit di laptop Windows, build & run di server `10.100.1.24`. Tidak ada Docker lokal. + +``` +Laptop (edit kode) → deploy script → Server 10.100.1.24 (build + run) +``` + +--- + +## Setup Lokal (geonet-console) + +### Prerequisites + +- PowerShell 5.1+ +- Git +- SSH key terdaftar di server (lihat `readme.txt`) + +### Workflow Development + +```powershell +# 1. Edit kode di laptop +# (VS Code → geonet-console/) + +# 2. Deploy ke server untuk testing +.\scripts\deploy-geonet-console.ps1 + +# 3. Cek log untuk debug +ssh -m hmac-sha1 root@10.100.1.24 -p 22 "docker logs geonet-console --tail 50" +``` + +### Setup SSH Key (Sekali) + +```powershell +ssh-keygen -t ed25519 -f "$env:USERPROFILE\.ssh\id_ed25519" -C "dev@$(hostname)" -N "" + +# Daftarkan ke reverse proxy +type "$env:USERPROFILE\.ssh\id_ed25519.pub" | ssh -m hmac-sha1 root@10.100.1.24 -p 22 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" +``` + +--- + +## Struktur Kode — geonet-console + +``` +geonet-console/ +├── app/ +│ ├── Http/Controllers/Api/V1/ — API controllers +│ ├── Models/ — Eloquent models +│ ├── Services/ — Business logic +│ └── Support/ — ApiActor, helpers +├── config/ +│ ├── database.php — Koneksi DB (pgsql, audit, mssql, project_search) +│ └── filesystems.php — Disk 'oss' (QNAP OSS S3) +├── database/migrations/ — Migration files +├── routes/api.php — Semua route API v1 +├── docapi/ — Dokumentasi API (WAJIB BACA sebelum tambah endpoint) +├── docker/entrypoint.sh — Startup: migrate, cache, OAuth keys +├── compose.yaml — Docker Compose +└── .env.example — Template env vars +``` + +--- + +## Coding Standard (Laravel) + +- **Service Layer**: Logic bisnis di `app/Services/`, bukan di controller +- **Controller tipis**: Controller hanya validasi input → call service → return response +- **ApiActor**: Gunakan `ApiActor` (dari `ApiAuthService`) untuk identitas user, bukan `Auth::user()` +- **Audit log**: Setiap aksi write wajib log ke `AuditLogService` +- **Response format**: Gunakan format standar — lihat `docapi/common-response.md` +- **Error handling**: Gunakan error code standar — lihat `docapi/common-error.md` + +--- + +## Commit Convention + +``` +: +``` + +| Type | Kapan | +|------|-------| +| `feat` | Fitur baru | +| `fix` | Bug fix | +| `api` | Perubahan API endpoint | +| `db` | Migration atau perubahan DB | +| `infra` | Nginx, Docker, deploy scripts | +| `docs` | Dokumentasi | +| `chore` | Config, deps, cleanup | + +--- + +## Menambah Endpoint API Baru + +1. Buat controller di `app/Http/Controllers/Api/V1/` +2. Buat service di `app/Services/` +3. Daftarkan route di `routes/api.php` +4. Tambah middleware auth + audit log +5. **Update `geonet-console/docapi/index.md`** +6. Buat file dokumentasi di `geonet-console/docapi/services//` +7. Update `docs/api/` jika endpoint termasuk scope publik + +--- + +## Environment di Server (Edit Langsung) + +```bash +ssh -m hmac-sha1 root@10.100.1.24 -p 22 +nano /opt/stacks/geonet-console/.env +docker compose -f /opt/stacks/geonet-console/compose.yaml restart geonet-console +``` + +--- + +## Debugging + +```bash +# Log real-time +ssh -m hmac-sha1 root@10.100.1.24 -p 22 "docker logs geonet-console -f" + +# Laravel log +ssh -m hmac-sha1 root@10.100.1.24 -p 22 "docker exec geonet-console tail -f storage/logs/laravel.log" + +# PHP artisan tinker +ssh -m hmac-sha1 root@10.100.1.24 -p 22 "docker exec -it geonet-console php artisan tinker" + +# Cek migration status +ssh -m hmac-sha1 root@10.100.1.24 -p 22 "docker exec geonet-console php artisan migrate:status" +``` + +--- + +## Branch Strategy + +| Branch | Tujuan | +|--------|--------| +| `main` / `master` | Production — push = deploy manual | +| `dev` | Development — testing sebelum ke main | +| `feature/` | Fitur baru | +| `fix/` | Bug fix | diff --git a/server-connection/docs/diagrams/authentication.mmd b/server-connection/docs/diagrams/authentication.mmd new file mode 100644 index 0000000..2daa28a --- /dev/null +++ b/server-connection/docs/diagrams/authentication.mmd @@ -0,0 +1,20 @@ +sequenceDiagram + participant C as Client + participant GC as geonet-console + participant AD as Active Directory (10.100.1.40) + participant JWT as LdapJwtService + + C->>GC: POST /api/v1/auth/login {username, password} + GC->>AD: LDAP bind + AD-->>GC: bind result + alt gagal + GC-->>C: 401 Unauthorized + end + GC->>JWT: generate JWT {username, groups, exp} + JWT-->>GC: signed token + GC-->>C: 200 {token, expires_at} + + Note over C,GC: Subsequent requests + C->>GC: GET /api/v1/* Bearer token + GC->>GC: ApiAuthService::resolve(token) + GC-->>C: Response diff --git a/server-connection/docs/diagrams/database.mmd b/server-connection/docs/diagrams/database.mmd new file mode 100644 index 0000000..f35bd34 --- /dev/null +++ b/server-connection/docs/diagrams/database.mmd @@ -0,0 +1,23 @@ +graph TB + subgraph GC["geonet-console (Laravel)"] + APP["Application"] + end + + subgraph PGCONT["audit-postgres (container di 10.100.1.24)"] + APPDB["databaselist_app\n- ldap_user_meta\n- service_tokens\n- api_tokens\n- database_connections"] + AUDITDB["databaselist_audit\n- audit_logs"] + end + + subgraph EXT["External (10.100.1.25)"] + MSSQL["SQL Server 2019\n- database registry (read)"] + PGSEARCH["PostgreSQL\ngeonet_project_search\n(pgvector — Fase 4)"] + end + + APP -->|pgsql connection| APPDB + APP -->|audit connection| AUDITDB + APP -->|mssql connection read-only| MSSQL + APP -.->|project_search Fase 4| PGSEARCH + + style APPDB fill:#FF9800,color:#fff + style AUDITDB fill:#9C27B0,color:#fff + style MSSQL fill:#607D8B,color:#fff diff --git a/server-connection/docs/diagrams/deployment.mmd b/server-connection/docs/diagrams/deployment.mmd new file mode 100644 index 0000000..6396b99 --- /dev/null +++ b/server-connection/docs/diagrams/deployment.mmd @@ -0,0 +1,28 @@ +graph LR + subgraph DEV["Developer (Laptop Windows)"] + CODE["Edit Kode\ngeonet-console/"] + SCRIPT[".\scripts\deploy-geonet-console.ps1"] + end + + subgraph TRANSFER["Transfer"] + TAR["tar -czf\ngeonet-console.tar.gz"] + SCP["SSH upload\ncat > /tmp/*.tar.gz"] + end + + subgraph SERVER["Server 10.100.1.24"] + EXTRACT["Extract\n/opt/stacks/geonet-console/"] + DC["docker compose up -d\n--build --force-recreate"] + GC["Container\ngeonet-console"] + NGX["Nginx\nconsole.gisportal.id"] + end + + CODE --> SCRIPT + SCRIPT --> TAR + TAR --> SCP + SCP --> EXTRACT + EXTRACT --> DC + DC --> GC + NGX -->|proxy_pass :8091| GC + + style GC fill:#2196F3,color:#fff + style NGX fill:#607D8B,color:#fff diff --git a/server-connection/docs/diagrams/system.mmd b/server-connection/docs/diagrams/system.mmd new file mode 100644 index 0000000..221c8c3 --- /dev/null +++ b/server-connection/docs/diagrams/system.mmd @@ -0,0 +1,38 @@ +graph TB + subgraph CLIENTS["Clients"] + B["Browser\n(IT Admin)"] + NEXTJS["Next.js PWA\nmy.gisportal.id"] + end + + subgraph SERVER24["10.100.1.24 — App Server"] + NGX["Nginx\nSSL + Reverse Proxy"] + GC["geonet-console\nLaravel 12\n:8091"] + PGCON["audit-postgres\nPostgreSQL"] + end + + subgraph SERVER25["10.100.1.25 — DB Server"] + MSSQL["SQL Server 2019"] + PGSEARCH["PostgreSQL\npgvector (Fase 4)"] + end + + subgraph INFRA["Infrastruktur"] + AD["Active Directory\n10.100.1.40"] + QNAP["QNAP NAS\n10.100.1.10\nOSS S3"] + OLLAMA["Ollama VM\n10.100.1.26\n(Fase 4)"] + ZABBIX["Zabbix\n10.100.1.42"] + MK["MikroTik\n10.100.1.1"] + end + + B -->|HTTPS| NGX + NEXTJS -->|HTTPS API| NGX + NGX -->|:8091| GC + GC --> PGCON + GC -->|LDAP bind| AD + GC -->|read registry| MSSQL + GC -->|avatar S3| QNAP + GC -.->|Fase 4| PGSEARCH + GC -.->|Fase 4| OLLAMA + NGX -->|/super-apps/ proxy| QNAP + + style GC fill:#2196F3,color:#fff + style NGX fill:#607D8B,color:#fff diff --git a/server-connection/docs/environment.md b/server-connection/docs/environment.md new file mode 100644 index 0000000..a2f8510 --- /dev/null +++ b/server-connection/docs/environment.md @@ -0,0 +1,100 @@ +# Environment Variables + +> **Terakhir Diperbarui:** 2026-06-29 +> ⚠️ **Jangan commit nilai secret ke repository.** Template ada di `geonet-console/.env.example`. + +--- + +## geonet-console (Laravel 12) + +File: `/opt/stacks/geonet-console/.env` di server 10.100.1.24. + +### App + +| Variable | Contoh | Keterangan | +|----------|--------|------------| +| `APP_NAME` | `Geonet Console` | Nama aplikasi | +| `APP_ENV` | `production` | Environment | +| `APP_KEY` | `base64:...` | **SECRET** — auto-generate jika kosong | +| `APP_URL` | `https://console.gisportal.id` | URL produksi | +| `APP_DEBUG` | `false` | Debug mode (false di production) | + +### Database + +| Variable | Keterangan | +|----------|------------| +| `DB_CONNECTION` | `pgsql` — **wajib**, jangan ubah ke sqlite | +| `DB_HOST` | `audit-postgres` (container) | +| `DB_PORT` | `5432` | +| `DB_DATABASE` | `databaselist_app` | +| `DB_USERNAME` | `geonet_app` | +| `APP_DB_PASSWORD` | **SECRET** — password PostgreSQL app | +| `AUDIT_DB_DATABASE` | `databaselist_audit` | + +### LDAP / Active Directory + +| Variable | Keterangan | +|----------|------------| +| `LDAP_HOST` | `10.100.1.40` | +| `LDAP_PORT` | `389` | +| `LDAP_BASE_DN` | `DC=gisportal,DC=id` | +| `LDAP_BIND_DN` | `Administrator@gisportal.id` | +| `LDAP_BIND_PASSWORD` | **SECRET** — password AD bind account | +| `LDAP_ADMIN_GROUPS` | `Domain Admins,Administrators,Enterprise Admins` | + +### SQL Server (Registry) + +| Variable | Keterangan | +|----------|------------| +| `MSSQL_HOST` | `10.100.1.25` | +| `MSSQL_PORT` | `1433` | +| `MSSQL_DATABASE` | `master` | +| `MSSQL_USERNAME` | `sa` | +| `MSSQL_PASSWORD` | **SECRET** | + +### QNAP OSS (Object Storage — Avatar) + +| Variable | Keterangan | +|----------|------------| +| `OSS_ENDPOINT` | `http://10.100.1.10:8010` | +| `OSS_ACCESS_KEY_ID` | Format: `:` | +| `OSS_SECRET_ACCESS_KEY` | **SECRET** — lihat `.env` di server | +| `OSS_BUCKET` | `super-apps` | +| `OSS_REGION` | `us-east-1` | +| `OSS_PUBLIC_URL` | `https://file.gisportal.id/super-apps` | + +### Mail (SMTP) + +| Variable | Keterangan | +|----------|------------| +| `MAIL_HOST` | `sc138.idcloudhosting.cloud` | +| `MAIL_PORT` | `465` | +| `MAIL_USERNAME` | `support@geonet.co.id` | +| `MAIL_PASSWORD` | **SECRET** | +| `MAIL_ENCRYPTION` | `ssl` | + +### Ollama AI (Fase — Belum aktif) + +| Variable | Keterangan | +|----------|------------| +| `OLLAMA_BASE_URL` | `http://10.100.1.26:11434` | +| `OLLAMA_MODEL` | `qwen2.5` | + +--- + +## Lokasi Secret + +| Secret | Lokasi | +|--------|--------| +| Semua credentials app | `/opt/stacks/geonet-console/.env` di server 10.100.1.24 | +| PostgreSQL password | `.env` (tidak di repo) | +| LDAP bind password | `.env` (tidak di repo) | +| QNAP OSS secret key | `.env` (tidak di repo) | +| SQL Server password | `.env` (tidak di repo) | +| SSH private keys | `~/.ssh/` di laptop developer | + +--- + +## Template + +Gunakan `geonet-console/.env.example` sebagai template — sudah berisi semua variable dengan placeholder aman. diff --git a/server-connection/docs/glossary.md b/server-connection/docs/glossary.md new file mode 100644 index 0000000..257227a --- /dev/null +++ b/server-connection/docs/glossary.md @@ -0,0 +1,25 @@ +# Glossary + +--- + +| Istilah | Definisi | +|---------|----------| +| **server-connection** | Nama repo — monorepo aplikasi IT internal & skrip infrastruktur | +| **geonet-console** | Aplikasi Laravel 12 unified IT portal (`console.gisportal.id`) | +| **databaselist** | Aplikasi legacy Laravel (akan di-redirect ke geonet-console) | +| **gisportal.id** | Domain produksi internal untuk semua layanan IT | +| **ApiActor** | Class representasi identity caller API (user, api_token, service_token) | +| **Service Token** | Token antar-service (bukan user token) — misal GeoNetAgent → geonet-console | +| **Audit DB** | Database `databaselist_audit` — log semua aktivitas write | +| **LDAP** | Lightweight Directory Access Protocol — digunakan untuk auth via Active Directory | +| **JWT** | JSON Web Token — format token setelah login LDAP | +| **QNAP OSS** | QNAP QuObjects Object Storage — S3-compatible, dipakai untuk avatar storage | +| **Stack path** | Path Docker stack di server, misal `/opt/stacks/geonet-console/` | +| **Reverse Proxy** | Server 10.100.1.24 — menjalankan Nginx + Docker untuk semua app | +| **pgvector** | PostgreSQL extension untuk vector similarity search (dipakai Ollama search) | +| **Indexer** | Worker yang crawl file di QNAP NAS → embed → simpan ke pgvector | +| **ADR** | Architecture Decision Record — dokumen keputusan arsitektur permanen | +| **PWA** | Progressive Web App — fitur offline + installable di geonet-console | +| **MikroTik CCR2004** | Router/firewall jaringan — 10.100.1.1 | +| **Dockge** | UI manajemen Docker stack di server 10.100.1.24 | +| **DoD** | Definition of Done — kriteria selesai suatu fase | diff --git a/server-connection/docs/issues.md b/server-connection/docs/issues.md new file mode 100644 index 0000000..51b277e --- /dev/null +++ b/server-connection/docs/issues.md @@ -0,0 +1,74 @@ +# Known Issues + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## 🔶 Known Limitations + +### [LIMITATION] project_search DB timeout saat startup + +- **Dampak:** Migration warning di log saat container start jika 10.100.1.25 tidak reachable +- **Penyebab:** `project_search` connection ke 10.100.1.25 external — migration gagal jika tidak reachable +- **Workaround:** Fungsi utama app tidak terpengaruh. Warning bisa diabaikan. +- **Prioritas:** Low + +--- + +### [LIMITATION] OSS Bucket ACL bisa ter-reset + +- **Dampak:** Avatar URL tidak bisa diakses publik — `403 Forbidden` +- **Penyebab:** QNAP QuObjects kadang reset ACL container ke private +- **Workaround:** Jalankan Swift API untuk set ulang `X-Container-Read: .r:*,.rlistings` +- **Prioritas:** Medium + +--- + +### [LIMITATION] DB nama masih `databaselist_app` / `databaselist_audit` + +- **Dampak:** Nama DB tidak konsisten dengan nama proyek baru `geonet-console` +- **Rencana:** Rename ke `geonet_console_app` + `geonet_console_audit` di Fase 3 +- **Prioritas:** Low + +--- + +### [LIMITATION] Tidak ada backup otomatis + +- **Dampak:** Jika server crash, data hilang +- **Workaround:** Manual `pg_dump` ke NAS QNAP +- **Prioritas:** Medium + +--- + +## ✅ Fixed + +### [FIXED] OAuth keys hilang saat rebuild container + +- **Penyebab:** OAuth keys tidak persist di Docker volume +- **Fix:** `docker/entrypoint.sh` generate keys ke volume `app_storage` dan cek sebelum generate ulang +- **Tanggal Fix:** 2026-06-xx + +--- + +## 🔴 Open Issues + +### [OPEN] UI Redirect databaselist → geonet-console belum aktif + +- **Dampak:** User masih bisa akses `databaselist.gisportal.id` yang legacy +- **Rencana:** Redirect di Fase 3 setelah semua fitur databaselist dimigrasi +- **Prioritas:** Medium + +--- + +## Cara Melaporkan Issue Baru + +Tambahkan di file ini: + +```markdown +### [OPEN] Judul Issue +- **Dampak:** ... +- **Penyebab:** ... +- **Workaround:** ... +- **Prioritas:** High / Medium / Low +- **Ditemukan:** YYYY-MM-DD +``` diff --git a/server-connection/docs/monitoring.md b/server-connection/docs/monitoring.md new file mode 100644 index 0000000..1c2b055 --- /dev/null +++ b/server-connection/docs/monitoring.md @@ -0,0 +1,76 @@ +# Monitoring + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Stack Monitoring + +| Tool | URL | Fungsi | +|------|-----|--------| +| **Zabbix** | `http://10.100.1.42` | Monitoring server, VM, network real-time | +| **Docker health** | Manual via SSH | Cek container status | + +--- + +## Boundary Zabbix vs Aplikasi + +| Fungsi | Tool | +|--------|------| +| Uptime server, CPU, RAM, disk real-time | **Zabbix** | +| Alert threshold (CPU spike, disk penuh) | **Zabbix** | +| Container health | Manual `docker ps` | +| Audit aktivitas user | **geonet-console** (`audit_logs` DB) | +| DB registry health check | **geonet-console** (`/databases` endpoint) | + +**Aturan:** Jangan duplikasi fungsi Zabbix di aplikasi custom. + +--- + +## Cek Container Health + +```bash +ssh -m hmac-sha1 root@10.100.1.24 -p 22 + +# Status semua container +docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" + +# Log geonet-console +docker logs geonet-console --tail 50 + +# Laravel error log +docker exec geonet-console tail -f storage/logs/laravel.log +``` + +--- + +## Audit Log (geonet-console) + +Semua aksi write tercatat di `databaselist_audit.audit_logs`. + +```bash +# Query audit log terbaru +docker exec -it audit-postgres psql -U geonet_app -d databaselist_audit \ + -c "SELECT actor, action, created_at FROM audit_logs ORDER BY created_at DESC LIMIT 20;" +``` + +--- + +## Zabbix + +```bash +# SSH ke Zabbix +.\scripts\ssh-zabbix.ps1 +# atau +ssh -m hmac-sha1 root@10.100.1.42 -p 22 +``` + +--- + +## Health Check URL + +| Aplikasi | URL | +|----------|-----| +| geonet-console | `https://console.gisportal.id` (200 = OK) | +| databaselist | `https://databaselist.gisportal.id` | +| sqlservercheck | `https://sqlservercheck.gisportal.id/ts` | diff --git a/server-connection/docs/onboarding/coding-standard.md b/server-connection/docs/onboarding/coding-standard.md new file mode 100644 index 0000000..3597837 --- /dev/null +++ b/server-connection/docs/onboarding/coding-standard.md @@ -0,0 +1,72 @@ +# Onboarding — Coding Standard + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## PHP / Laravel (geonet-console) + +- **Service Layer wajib** — logic bisnis di `app/Services/`, bukan di controller +- Controller: validasi → service → return response (tipis) +- Gunakan `ApiActor` dari `ApiAuthService` — jangan gunakan `Auth::user()` +- Setiap aksi write → `AuditLogService::log()` +- Response mengikuti format di `docapi/common-response.md` +- Error mengikuti format di `docapi/common-error.md` + +--- + +## Database + +- Driver default: **PostgreSQL** (`pgsql`) — jangan ubah ke sqlite +- Migration: `database/migrations/` — jalankan otomatis via entrypoint +- Nama tabel: `snake_case` plural (`ldap_user_meta`, `service_tokens`) +- Selalu gunakan connection name eksplisit untuk non-default DB + +--- + +## PowerShell Scripts + +- Gunakan `Start-Process -FilePath "cmd.exe"` untuk pipe SSH (bukan heredoc) +- Jangan gunakan `&&` — gunakan `;` sebagai separator di PowerShell +- SSH flag wajib: `-m hmac-sha1` untuk semua server (kecuali QNAP/Ollama yang pakai key terpisah) + +--- + +## Commit Convention + +``` +: +``` + +| Type | Kapan | +|------|-------| +| `feat` | Fitur baru | +| `fix` | Bug fix | +| `api` | Perubahan/tambah endpoint | +| `db` | Migration atau perubahan DB | +| `infra` | Nginx, Docker, scripts | +| `docs` | Dokumentasi | +| `chore` | Config, deps | + +--- + +## Aturan Dokumentasi + +- Tambah endpoint baru → update `geonet-console/docapi/index.md` +- Buat file dokumentasi di `geonet-console/docapi/services//` +- Perubahan arsitektur → update `docs/architecture/` + buat ADR baru +- Akhir sesi → update `perintah.md` (Sync terakhir) + +--- + +## Naming Convention + +| Tipe | Konvensi | +|------|----------| +| PHP Class | `PascalCase` | +| PHP method | `camelCase` | +| DB tabel | `snake_case_plural` | +| Route | `/kebab-case` | +| Env var | `UPPER_SNAKE_CASE` | +| Script | `verb-noun.ps1` | +| Doc file | `kebab-case.md` | diff --git a/server-connection/docs/onboarding/first-day.md b/server-connection/docs/onboarding/first-day.md new file mode 100644 index 0000000..1b34222 --- /dev/null +++ b/server-connection/docs/onboarding/first-day.md @@ -0,0 +1,67 @@ +# Onboarding — First Day + +> **Untuk:** Developer atau AI Agent baru yang bekerja di repo `server-connection`. + +--- + +## Bacaan Wajib (Urutan) + +1. [`docs/context-index.md`](../context-index.md) ← mulai dari sini +2. [`.cursor/me.md`](../../.cursor/me.md) — profil user + inventaris infrastruktur +3. [`perintah.md`](../../perintah.md) — quick reference +4. [`geonet-console/context-index.md`](../../geonet-console/context-index.md) — jika task terkait geonet-console +5. [`geonet-console/docapi/index.md`](../../geonet-console/docapi/index.md) — semua API endpoint + +--- + +## Pahami Monorepo + +Repo ini berisi: +- **geonet-console** — aplikasi utama (Laravel 12) di `console.gisportal.id` +- **scripts/** — deploy + SSH helper untuk Windows PowerShell +- **server/** — audit server + MikroTik configs +- **docs/** — dokumentasi yang sedang kamu baca ini + +--- + +## URL Penting + +| URL | Keterangan | +|-----|------------| +| https://console.gisportal.id | geonet-console production | +| https://console.gisportal.id/api/v1 | REST API | +| https://console.gisportal.id/api-docs | API Docs UI | +| https://databaselist.gisportal.id | Legacy (akan di-redirect) | + +--- + +## Cara Kerja Dev + +```powershell +# Kode di laptop → deploy ke server via script +.\scripts\deploy-geonet-console.ps1 + +# Tidak ada Docker lokal — build & run di server 10.100.1.24 +``` + +--- + +## Server Penting + +| Server | IP | Akses | +|--------|----|-| +| App + Nginx | 10.100.1.24 | `ssh -m hmac-sha1 root@10.100.1.24 -p 22` | +| Database | 10.100.1.25 | `ssh -m hmac-sha1 root@10.100.1.25 -p 22` | +| AD/LDAP | 10.100.1.40 | `ssh -m hmac-sha1 Administrator@10.100.1.40 -p 22` | + +> ⚠️ SSH ke server **wajib minta persetujuan user** — jangan auto-run. + +--- + +## Aturan Penting + +- Jangan commit `.env` atau secret ke repo +- Jangan overwrite `.env` di server saat deploy +- Update `perintah.md` (Sync terakhir) setelah sesi pengembangan +- Gunakan `docapi/` di geonet-console untuk dokumentasi endpoint API detail +- Implementasi tanpa dokumentasi = belum selesai diff --git a/server-connection/docs/onboarding/local-setup.md b/server-connection/docs/onboarding/local-setup.md new file mode 100644 index 0000000..fd5fcf7 --- /dev/null +++ b/server-connection/docs/onboarding/local-setup.md @@ -0,0 +1,75 @@ +# Onboarding — Local Setup + +> Setup untuk mulai develop di repo `server-connection`. + +--- + +## Prerequisites + +- Windows (OS dev) +- PowerShell 5.1+ +- Git +- VS Code (atau editor pilihan) +- SSH key terdaftar di server 10.100.1.24 + +--- + +## Clone Repo + +```powershell +git clone "D:\Project\app on git\server-connection" +cd "D:\Project\app on git\server-connection" +``` + +--- + +## Setup SSH Key (Sekali) + +```powershell +# Buat key baru (jika belum ada) +ssh-keygen -t ed25519 -f "$env:USERPROFILE\.ssh\id_ed25519" -C "dev@$(hostname)" -N "" + +# Daftarkan ke server 10.100.1.24 +type "$env:USERPROFILE\.ssh\id_ed25519.pub" | ssh -m hmac-sha1 root@10.100.1.24 -p 22 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" + +# Verifikasi tanpa password +ssh -o BatchMode=yes -m hmac-sha1 root@10.100.1.24 -p 22 "hostname" +``` + +--- + +## Workflow Dev (geonet-console) + +```powershell +# 1. Edit kode di laptop +# VS Code → D:\Project\app on git\server-connection\geonet-console\ + +# 2. Deploy ke server untuk test +.\scripts\deploy-geonet-console.ps1 + +# 3. Cek hasil +# https://console.gisportal.id +``` + +--- + +## Verifikasi Setup + +```powershell +# Test SSH ke server +.\scripts\ssh-remote.ps1 -Command "docker ps --filter name=geonet-console" + +# Test akses URL produksi +curl https://console.gisportal.id/api/v1/auth/token-guide +``` + +--- + +## Alat Bantu + +| Alat | Fungsi | +|------|--------| +| `.\scripts\ssh-remote.ps1` | SSH shell atau command ke 10.100.1.24 | +| `.\scripts\ssh-mikrotik.ps1` | SSH ke MikroTik | +| `.\scripts\ssh-ollama.ps1` | SSH ke Ollama VM | +| `.\scripts\ssh-qnap.ps1` | SSH ke QNAP NAS | diff --git a/server-connection/docs/project-status.md b/server-connection/docs/project-status.md new file mode 100644 index 0000000..89c2acf --- /dev/null +++ b/server-connection/docs/project-status.md @@ -0,0 +1,66 @@ +# Project Status + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Snapshot Cepat + +| Proyek | Status | Keterangan | +|--------|--------|------------| +| **geonet-console** | ✅ Production | Laravel 12 + LDAP auth + API running | +| **databaselist** | ⚠️ Legacy | Akan di-redirect ke geonet-console | +| **sqlservercheck** | ✅ Running | Tool diagnostik SQL Server | +| **Ollama NAS Search** | 📋 Direncanakan | POC belum diimplementasi | + +--- + +## geonet-console — Modul Selesai + +| Modul | Keterangan | +|-------|------------| +| ✅ Auth LDAP + JWT | Login AD, refresh token, token-guide | +| ✅ User Profile (`/me`) | Avatar upload ke QNAP OSS | +| ✅ LDAP User Management | CRUD user AD via API | +| ✅ LDAP Group Management | CRUD group + member management | +| ✅ Database Registry | List + offline mark database | +| ✅ Service Tokens | Token antar-service + sync ke GeoNetAgent DB | +| ✅ Audit Log | Log aktivitas ke DB terpisah | +| ✅ API Token (personal) | User bisa buat API token untuk akses programatik | +| ✅ PWA Fase A | Manifest + service worker + offline page | +| ✅ PWA Fase B | Install banner + cache stale-while-revalidate | +| ✅ Project Search API | Endpoint `/project-search/*` (UI belum ada) | + +--- + +## geonet-console — Modul Belum Dibuat (Backlog) + +| Modul | Prioritas | Keterangan | +|-------|-----------|------------| +| **Ollama AI assistant** | High | POC indexer + pgvector + chat UI | +| **Project index UI** | High | Tampilkan status indeks di UI | +| **License registry** | Medium | Parser GM + ESRI license dari NAS | +| **Redirect databaselist → geonet-console** | Medium | Fase 3 migration | +| **Email SMTP reset password** | Medium | Forgot password LDAP via SMTP | +| **Group Permission Management UI** | Low | UI untuk atur LDAP group permissions | + +--- + +## Technical Debt + +| Item | Prioritas | Keterangan | +|------|-----------|------------| +| DB `databaselist_app` nama harus direname | Medium | Nama DB legacy, target: `geonet_console_app` (Fase 3) | +| `project_search` DB di 10.100.1.25 | Low | Kalau 10.100.1.25 tidak reachable, migration gagal — tidak pengaruhi app utama | +| OAuth keys di Docker volume | Low | `app_storage` — perlu backup strategi | + +--- + +## Known Issues + +Lihat [`issues.md`](issues.md) untuk detail. + +| Issue | Dampak | +|-------|--------| +| `project_search` DB timeout | Migration gagal saat 10.100.1.25 unreachable (non-critical) | +| Bucket OSS ACL bisa ter-reset | Avatar tidak bisa diakses publik — fix via Swift API | diff --git a/server-connection/docs/roadmap.md b/server-connection/docs/roadmap.md new file mode 100644 index 0000000..41f19e3 --- /dev/null +++ b/server-connection/docs/roadmap.md @@ -0,0 +1,57 @@ +# Roadmap + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Status Saat Ini + +``` +✅ Fase 1 — Foundation Selesai: Auth LDAP, LDAP mgmt, DB registry, Service Tokens +✅ Fase 2 — Service Tokens Selesai: Token antar-service + sync ke GeoNetAgent +🔄 Fase 3 — Konsolidasi Aktif: Redirect databaselist → geonet-console +⏳ Fase 4 — Ollama AI Search Planned: Project search + license registry +⏳ Fase 5 — Advanced Features Planned: Permission mgmt UI, email reset, dll. +``` + +--- + +## Fase 3 — Konsolidasi (Aktif) + +- [ ] Redirect `databaselist.gisportal.id` → `console.gisportal.id` +- [ ] Rename DB: `databaselist_app` → `geonet_console_app` +- [ ] Rename DB: `databaselist_audit` → `geonet_console_audit` +- [ ] Stack path rename: `/opt/stacks/databaselist` → deprecated + +--- + +## Fase 4 — Ollama AI Project Search + +**DoD:** IT bisa query project di NAS dengan bahasa alami melalui geonet-console. + +- [ ] Setup pgvector di 10.100.1.25 (`geonet_project_search` DB) +- [ ] Deploy indexer worker di Ollama VM (10.100.1.26) +- [ ] Mount SMB QNAP di Ollama VM +- [ ] Indeks metadata folder `project` (crawl + embed) +- [ ] UI project search di geonet-console +- [ ] Audit log pencarian aktif +- [ ] RBAC per source (Marketing/Sales sensitif) + +--- + +## Fase 5 — Advanced Features + +- [ ] License registry (parser GM + ESRI license dari NAS) +- [ ] Email forgot password LDAP via SMTP +- [ ] Group permission management UI +- [ ] Backup otomatis DB ke QNAP +- [ ] Migrasi Ollama ke Windows 11 + GPU (~6 bulan) + +--- + +## Lihat Juga + +- `docs/project-status.md` — status detail per modul +- `docs/todo.md` — next actions berprioritas +- `AGENTS.md` — detail rencana Ollama + NAS search +- `server/ollama-nas-project-search-requirements.md` — requirement lengkap diff --git a/server-connection/docs/security.md b/server-connection/docs/security.md new file mode 100644 index 0000000..b64f4b9 --- /dev/null +++ b/server-connection/docs/security.md @@ -0,0 +1,61 @@ +# Security + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Larangan Mutlak + +- ❌ Jangan commit `.env` ke repository +- ❌ Jangan commit password, API key, token, private key ke repository +- ❌ Jangan tampilkan nilai secret di output AI / log +- ❌ Jangan hardcode credentials di kode PHP atau script + +--- + +## Model Autentikasi + +| Method | Digunakan Untuk | Keterangan | +|--------|-----------------|------------| +| **JWT (LDAP)** | User login via browser | Login AD → JWT, expire configurable | +| **API Token** | Developer / personal access | Token per-user, scope-limited | +| **Service Token** | Antar-service (misal GeoNetAgent) | Token per-service, bisa di-sync | + +--- + +## Credential Management + +| Secret | Lokasi | +|--------|--------| +| Semua `.env` app | `/opt/stacks/geonet-console/.env` di server — **tidak di repo** | +| LDAP bind password | `.env` server | +| PostgreSQL password | `.env` server | +| QNAP OSS secret key | `.env` server | +| SQL Server password | `.env` server | +| SSH private key | `~/.ssh/id_ed25519` di laptop developer | +| MikroTik SSH key (RSA) | `~/.ssh/id_rsa_mikrotik` di laptop | + +--- + +## Nginx Security Headers + +geonet-console sudah punya: +- `Strict-Transport-Security` (HSTS) +- `X-Frame-Options: SAMEORIGIN` +- Rate limiting: login 5 req/menit, general traffic + +--- + +## Aturan SSH + +- SSH ke server **wajib minta persetujuan user** sebelum dijalankan +- Jangan auto-run SSH command destructive (rm, truncate, dll) +- Edit `.env` hanya di server langsung — jangan sync dari laptop + +--- + +## Aturan AI Agent + +- Jika diminta membuat credential baru: catat **lokasi penyimpanan** di `docs/environment.md`, bukan nilainya +- Jika token bocor: instruksikan user rotasi manual — jangan buat token baru di repo +- Jangan commit apapun yang mengandung password, token, atau key diff --git a/server-connection/docs/server.md b/server-connection/docs/server.md new file mode 100644 index 0000000..73ecdc3 --- /dev/null +++ b/server-connection/docs/server.md @@ -0,0 +1,118 @@ +# Server Information + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Daftar Server + +| Role | IP | OS | SSH Command | +|------|----|----|-------------| +| **Reverse Proxy + Docker** | 10.100.1.24 | CentOS Linux 8 | `ssh -m hmac-sha1 root@10.100.1.24 -p 22` | +| **Database (PostgreSQL + SQL Server)** | 10.100.1.25 | Ubuntu 18.04 LTS | `ssh -m hmac-sha1 root@10.100.1.25 -p 22` | +| **Active Directory / LDAP** | 10.100.1.40 | Windows Server 2012 R2 | `ssh -m hmac-sha1 Administrator@10.100.1.40 -p 22` | +| **Main Webserver** | 10.100.1.41 | Windows Server 2012 R2 | `ssh -m hmac-sha1 Administrator@10.100.1.41 -p 22` | +| **NAS QNAP TS-932X** | 10.100.1.10 | QTS 5.2.9 | `ssh -i "$env:USERPROFILE\.ssh\id_ed25519" -o IdentitiesOnly=yes -m hmac-sha1 admin@10.100.1.10 -p 22` | +| **Ollama AI VM** | 10.100.1.26 | Ubuntu 22.04 LTS | `ssh -i "$env:USERPROFILE\.ssh\id_rsa_geonet_laptop" -o IdentitiesOnly=yes -m hmac-sha1 root@10.100.1.26 -p 22` | +| **Zabbix** | 10.100.1.42 | Ubuntu 22.04 LTS | `.\scripts\ssh-zabbix.ps1` | +| **MikroTik CCR2004** | 10.100.1.1 | RouterOS 7.5 | `.\scripts\ssh-mikrotik.ps1` | + +> QNAP & Ollama: Wajib **PowerShell** (bukan CMD) agar `$env:USERPROFILE` terbaca. +> SSH commands ke server **wajib minta persetujuan user** sebelum dijalankan. + +--- + +## Server 10.100.1.24 — Reverse Proxy + Docker + +### Services Running + +| Stack | Container | Port Host | Path | +|-------|-----------|-----------|------| +| geonet-console | `geonet-console` | `127.0.0.1:8091` | `/opt/stacks/geonet-console/` | +| databaselist (legacy) | `databaselist` | (legacy) | `/opt/stacks/databaselist/` | +| sqlservercheck | `sqlservercheck` | — | `/opt/stacks/sqlservercheck/` | +| my-portal (Next.js) | `my-portal` | `127.0.0.1:8092` | `/opt/stacks/my-portal/` | + +### Nginx Config + +| File | Domain | +|------|--------| +| `/etc/nginx/conf.d/production/geonet-console.conf` | `console.gisportal.id` | +| `/etc/nginx/conf.d/production/databaselist.conf` | `databaselist.gisportal.id` | +| `/etc/nginx/conf.d/nas.conf` | `file.gisportal.id` (QNAP OSS proxy) | + +### Perintah Umum + +```bash +# Cek semua container +docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" + +# Log container +docker logs geonet-console --tail 50 -f + +# Restart container +docker restart geonet-console + +# Nginx reload +nginx -t && nginx -s reload +``` + +--- + +## Server 10.100.1.25 — Database + +```bash +ssh -m hmac-sha1 root@10.100.1.25 -p 22 + +# PostgreSQL (dalam container di 10.100.1.24 — bukan langsung di .25) +# SQL Server: 10.100.1.25:1433 — dipakai geonet-console untuk database registry + +# Akses PostgreSQL (di container dari server 10.100.1.24) +docker exec -it audit-postgres psql -U geonet_app -d databaselist_app +``` + +--- + +## Domain Map + +| Domain | Backend | Keterangan | +|--------|---------|------------| +| `console.gisportal.id` | 10.100.1.24 → container :8091 | geonet-console | +| `databaselist.gisportal.id` | 10.100.1.24 → container legacy | databaselist legacy | +| `sqlservercheck.gisportal.id` | 10.100.1.24 → container | sqlservercheck | +| `file.gisportal.id/super-apps/` | 10.100.1.24 → QNAP OSS :8010 | Object storage proxy | + +--- + +## Transfer File ke Server (Windows → Linux) + +```powershell +# Buat archive +tar -czf "$env:TEMP\geonet-console.tar.gz" ` + --exclude="vendor" --exclude=".git" --exclude="node_modules" ` + -C "D:\Project\app on git\server-connection\geonet-console" . + +# Upload via cmd.exe (wajib pakai Start-Process di PowerShell) +Start-Process -FilePath "cmd.exe" -ArgumentList ` + '/c ssh -m hmac-sha1 root@10.100.1.24 -p 22 "cat > /tmp/geonet-console.tar.gz" < "%TEMP%\geonet-console.tar.gz"' ` + -Wait -NoNewWindow + +# Extract di server +ssh -m hmac-sha1 root@10.100.1.24 -p 22 "tar -xzf /tmp/geonet-console.tar.gz -C /opt/stacks/geonet-console && rm /tmp/geonet-console.tar.gz" +``` + +> ⚠️ **JANGAN overwrite `.env`** saat deploy — `.env` server berisi credentials production. + +--- + +## SSL + +HTTPS via Let's Encrypt (certbot) di 10.100.1.24. Semua domain `*.gisportal.id` di-terminate di Nginx. + +--- + +## Backup + +- Docker volumes: manual backup (belum otomatis) +- `.env` server: disimpan hanya di server (tidak di repo) +- Database backup: manual via `pg_dump` ke NAS QNAP diff --git a/server-connection/docs/todo.md b/server-connection/docs/todo.md new file mode 100644 index 0000000..9c157c5 --- /dev/null +++ b/server-connection/docs/todo.md @@ -0,0 +1,68 @@ +# TODO List + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## 🔴 High Priority + +### Ollama AI Search — Setup Infrastruktur +- **Deskripsi:** Install Ollama + model di VM 10.100.1.26, setup pgvector di 10.100.1.25 +- **File:** `scripts/geonet-indexer/`, `server/ollama-nas-project-search-requirements.md` +- **Estimasi:** 1-2 minggu +- **Dependency:** Ollama VM sudah vCPU 16 (siap) + +### Redirect databaselist → geonet-console +- **Deskripsi:** Nginx redirect `databaselist.gisportal.id` ke `console.gisportal.id` +- **File:** `server/nginx/`, `scripts/deploy-geonet-console-nginx.ps1` +- **Estimasi:** 1 hari +- **Dependency:** Semua fitur databaselist sudah tersedia di geonet-console + +--- + +## 🟡 Medium Priority + +### Backup Otomatis Database +- **Deskripsi:** Script cronjob `pg_dump` → upload ke QNAP NAS +- **File:** `scripts/backup.sh` (buat baru) +- **Estimasi:** 1-2 hari +- **Dependency:** QNAP SSH access tersedia + +### License Registry — Parser GM & ESRI +- **Deskripsi:** Parse file license dari NAS, simpan ke `license_registry` PostgreSQL +- **File:** `scripts/geonet-indexer/`, geonet-console API +- **Estimasi:** 2-3 minggu +- **Dependency:** Fase 4 Ollama search + +### Email Forgot Password LDAP +- **Deskripsi:** Kirim link reset password LDAP via SMTP `support@geonet.co.id` +- **File:** `geonet-console/app/Services/`, routes +- **Estimasi:** 2-3 hari +- **Dependency:** - + +### Rename DB databaselist_* → geonet_console_* +- **Deskripsi:** Rename DB dari nama legacy ke nama baru yang konsisten +- **File:** `geonet-console/config/database.php`, migrations, `.env` +- **Estimasi:** 2-4 jam (dengan downtime) +- **Dependency:** Backup DB selesai + +--- + +## 🟢 Low Priority + +### Group Permission Management UI +- **Deskripsi:** UI untuk atur mapping LDAP group → permissions di geonet-console +- **File:** `geonet-console/resources/views/`, controllers +- **Estimasi:** 2-3 hari +- **Dependency:** - + +### Monitoring Dashboard UI +- **Deskripsi:** Halaman status server + container health di geonet-console +- **File:** `geonet-console/app/Services/ZabbixService.php` (baru) +- **Estimasi:** 3-5 hari +- **Dependency:** Zabbix API token + +### OpenAPI / Swagger Export +- **Deskripsi:** Auto-generate OpenAPI spec dari docapi/ untuk integrasi tools +- **Estimasi:** 1-2 hari +- **Dependency:** - diff --git a/server-connection/docs/troubleshooting.md b/server-connection/docs/troubleshooting.md new file mode 100644 index 0000000..ca680bd --- /dev/null +++ b/server-connection/docs/troubleshooting.md @@ -0,0 +1,119 @@ +# Troubleshooting + +> **Terakhir Diperbarui:** 2026-06-29 + +--- + +## Login gagal — "Invalid credentials" + +**Cek:** +1. Server AD 10.100.1.40 reachable dari container +2. `LDAP_BIND_PASSWORD` di `.env` benar +3. Akun AD aktif (tidak expired/locked) + +```bash +ssh -m hmac-sha1 root@10.100.1.24 -p 22 +docker exec -it geonet-console php artisan tinker +# app(\App\Services\LdapAuthService::class)->attempt('username', 'password') +``` + +--- + +## Avatar tidak bisa diupload / ditampilkan + +**Penyebab 1:** OSS credentials salah +```bash +docker exec -it geonet-console php artisan tinker +# Storage::disk('oss')->put('test.txt', 'hello') +``` + +**Penyebab 2:** Bucket ACL ter-reset (tidak public-read) +```bash +curl -X POST http://10.100.1.10:8010/v1/AUTH_super-apps/super-apps \ + -H "X-Auth-Token: " \ + -H "X-Container-Read: .r:*,.rlistings" +``` + +--- + +## Container tidak mau start + +```bash +ssh -m hmac-sha1 root@10.100.1.24 -p 22 +docker ps -a --filter name=geonet-console +docker logs geonet-console --tail 100 +``` + +**Penyebab umum:** +- `APP_KEY` kosong → `docker exec geonet-console php artisan key:generate` +- Port 8091 sudah terpakai → `netstat -tlnp | grep 8091` +- `.env` tidak ada → `cp .env.example .env && nano .env` + +--- + +## Migration gagal saat startup + +Error `project_search` DB (10.100.1.25) tidak reachable: +``` +SQLSTATE[HY000] [2002] Connection refused +``` +Ini **non-critical** — fungsi utama app tetap berjalan. `project_search` hanya untuk Ollama search (belum aktif). + +--- + +## Deploy script error — transfer file + +```powershell +# Gunakan cmd.exe method (bukan heredoc di PowerShell) +Start-Process -FilePath "cmd.exe" -ArgumentList ` + '/c ssh -m hmac-sha1 root@10.100.1.24 -p 22 "cat > /tmp/project.tar.gz" < "%TEMP%\project.tar.gz"' ` + -Wait -NoNewWindow +``` + +Jangan gunakan `&&` di PowerShell — gunakan `;`. + +--- + +## SSH "Could not negotiate a key exchange algorithm" + +```powershell +# Tambahkan flag -m hmac-sha1 +ssh -m hmac-sha1 root@10.100.1.24 -p 22 +``` + +--- + +## MikroTik — SSH key tidak diterima + +```powershell +# RouterOS 7.5 butuh RSA +.\scripts\setup-ssh-mikrotik.ps1 -KeyType rsa + +# Recovery manual (via Winbox): +# /user ssh-keys remove [find user=admin] +# /ip ssh set password-authentication=yes +``` + +--- + +## Nginx error setelah config update + +```bash +ssh -m hmac-sha1 root@10.100.1.24 -p 22 +nginx -t && nginx -s reload +``` + +--- + +## Perintah Darurat + +```bash +# Restart semua container +docker restart geonet-console audit-postgres + +# Cek semua container +docker ps --format "table {{.Names}}\t{{.Status}}" + +# Paksa rebuild +docker compose -f /opt/stacks/geonet-console/compose.yaml up -d --build --force-recreate +``` diff --git a/server-connection/perintah.md b/server-connection/perintah.md index eb8ef18..5a98c93 100644 --- a/server-connection/perintah.md +++ b/server-connection/perintah.md @@ -148,3 +148,4 @@ SSH reverse proxy: `ssh -m hmac-sha1 root@10.100.1.24 -p 22` · Edit `.env` hany | 2026-06-11 | Lengkapi `me.md` & `perintah.md` — URL produksi, indeks file, selaraskan server-connection / GeoNetAgent | | 2026-06-23 | Implementasi fitur Service Tokens di geonet-console (migration, model, service, API endpoints, UI, audit log) | | 2026-06-23 | Implementasi sinkronisasi Service Tokens → geonetagent_dev.agent_tokens (AgentTokenSyncService, Opsi C) | +| 2026-06-29 | Audit & lengkapi dokumentasi server-connection: buat docs/ lengkap (context-index, architecture, api, adr, diagrams, onboarding, decisions), README.md root, .cursor/rules/ tambahan (documentation, security, deployment, api, database, architecture) |