> For the complete documentation index, see [llms.txt](https://payana-saas.gitbook.io/payana-saas-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://payana-saas.gitbook.io/payana-saas-docs/arsitektur/konvensi-kunci.md).

# Konvensi Kunci

Beberapa pola yang berulang di seluruh lapisan sistem — memahaminya menjelaskan kenapa sistem ini didesain seperti sekarang, dan jadi rujukan pertama saat men-debug perilaku yang tidak terduga.

## 1. Identitas on-chain adalah Smart Account, bukan wallet login

Ini konvensi paling penting di seluruh codebase. Karyawan login dengan email/Google lewat Privy — itu mengautentikasi sebuah **EOA** (Externally Owned Account, alamat wallet tradisional). Tapi setiap transaksi gasless (`claimSalary`, `claimAdvance`, dst.) dieksekusi dengan `msg.sender` berupa **Smart Account** (ERC-4337) yang dihasilkan Privy dari EOA itu — dua alamat yang berbeda.

Pola yang benar, dipakai konsisten di semua kode yang membaca "siapa karyawan ini":

```ts
const smartAccountAddress = useSmartAccountAddress();
const employeeAddress = smartAccountAddress ?? address; // fallback ke EOA selagi resolve
```

Melewatkan konvensi ini — membandingkan EOA login langsung ke record on-chain yang sebenarnya dikunci ke Smart Account — adalah penyebab paling umum dari bug "data saya tidak muncul" di seluruh aplikasi.

## 2. Setiap CompanyVault adalah Paymaster untuk dirinya sendiri

Tidak ada satu Paymaster global untuk seluruh platform. Setiap perusahaan men-deploy `CompanyVault`-nya sendiri, dan vault itu langsung berfungsi sebagai Paymaster ERC-4337 untuk karyawannya sendiri — artinya biaya gas ditanggung dari saldo vault perusahaan itu, bukan dari anggaran platform terpusat. Ini juga berarti monitoring saldo gas (`paymasterMonitor`) berjalan **per perusahaan**, bukan satu alert global.

## 3. Alamat vault ditemukan secara dinamis, bukan dikonfigurasi statis

`payana-indexer` tidak pernah dikonfigurasi dengan daftar alamat `CompanyVault` secara manual. Sebagai gantinya, ia mengawasi event `VaultDeployed` dari `PayrollFactory` dan otomatis mulai mengindeks setiap vault baru yang tercipta. Menambahkan konfigurasi alamat vault statis akan membuat vault-vault baru tidak pernah terindeks — ini pernah jadi bug nyata sebelum pola factory-discovery diterapkan.

## 4. Tiga layanan harus sepakat soal generasi kontrak

`payana-contract`, `payana-backend`, dan `payana-indexer` semuanya membaca alamat kontrak dari environment variable masing-masing. Ketiganya **harus** menunjuk ke generasi deploy yang sama — mismatch alamat antar layanan adalah sumber bug paling umum kedua setelah masalah Smart Account vs EOA, biasanya muncul sebagai "data ada di satu tempat tapi tidak di tempat lain".

## 5. Backend membaca tabel indexer langsung, bukan lewat API-nya

Untuk kebutuhan seperti laporan compliance yang perlu menggabungkan data off-chain (dari skema `app`) dengan data on-chain terindeks (dari skema indexer), backend melakukan query SQL langsung ke skema indexer lewat client `postgres` dengan `search_path` yang diarahkan ke sana — bukan memanggil HTTP API milik `payana-indexer`. Ini karena keduanya berbagi satu database fisik yang sama, jadi query langsung lebih efisien daripada round-trip HTTP untuk operasi join.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://payana-saas.gitbook.io/payana-saas-docs/arsitektur/konvensi-kunci.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
