Kontrak API Federated: Auth, Idempotensi, dan Retry Terpadu membahas bagaimana merancang komunikasi yang konsisten di lingkungan federated dengan asumsi bahwa tidak ada instance tunggal yang memegang kendali mutlak (esensi "There Are No Instances in atproto"). Pendekatan ini menuntut desain autentikasi berbasis klaim terdistribusi, pola payload yang bisa diverifikasi lintas node, dan mekanisme idempotensi+retry yang tidak menciptakan efek samping ganda.

Memahami tantangan "tanpa instance tunggal"

Dalam arsitektur federated, setiap node memiliki data lokalnya sendiri dan harus bisa memverifikasi request tanpa menunggu authoritative instance. Maka desain kontrak API harus: (1) mempercayai klaim yang bisa diverifikasi secara kriptografis, (2) mendokumentasikan semantik idempoten yang konsisten, dan (3) menyusun retry + webhook ack yang bisa ditangani oleh banyak node tanpa konflik. Kesalahan umum termasuk mengasumsikan ada satu endpoint pusat untuk status, atau menutup retry ketika token tidak dikenal.

Autentikasi dan klaim di federasi

Alih-alih menaruh otoritas pada satu instance, gunakan token berformat JWT atau Signed Envelope yang mencantumkan klaim berikut:

  • Issuer yang merupakan node federated pembuat request.
  • Audience yang merujuk ke service tujuan spesifik atau group node yang perlu menerima request.
  • Nonce atau request-id yang juga digunakan untuk idempotensi.
  • Scope dan exp untuk membatasi cakupan dan masa berlaku.

Verifikasi token dilakukan dengan menyimpan kumpulan kunci publik node yang bisa diperbarui melalui registry federated. Saat node menerima payload, ia memverifikasi signature, memastikan audience cocok, dan menolak request jika nonce pernah digunakan oleh node itu sendiri (karena setiap node harus menjaga state nonce lokal).

Pola payload untuk memudahkan verifikasi

Payload harus mencantumkan metadata berupa:

  • request_id unik yang juga ada di token.
  • created_at dan node_origin.
  • Daftar resource yang dirujuk, lengkap dengan versi resource ketika tersedia.

Contoh:

{
  "request_id": "federated-req-123",
  "node_origin": "node-a.example",
  "operation": "publish",
  "resource": {
    "id": "post-789",
    "version": 42
  }
}

Node penerima bisa menggunakan request_id ini untuk mengecek idempotensi dan memastikan klaim sesuai.

Idempotensi tanpa state global

Idempotensi di federated berarti setiap node harus menyimpan status request minimal: berhasil, gagal, atau sedang diproses. Saat request baru masuk, node melakukan:

  1. Periksa apakah request_id pernah diproses; jika ya, kembalikan status akhir tanpa memicu efek samping.
  2. Jika belum, lakukan operasi dan mark status processing.
  3. Setelah operasi selesai, ubah status ke completed atau failed.

Status bisa disimpan di database lokal yang memungkinkan _fast lookup_. Kunci idempotensi harus menyertakan kombinasi node_origin + request_id untuk menghindari tabrakan antar node.

Gagal menyimpan status sebelum menjalankan efek samping adalah kesalahan umum. Pastikan tahap pertama adalah tulis status, baru eksekusi.

Retry dan webhook ack di lingkungan federated

Retry harus mempertimbangkan bahwa node tujuan bisa offline atau berperilaku lambat. Gunakan pola berikut:

  • Backoff terkontrol (misalnya linear atau jittered), tapi jangan mengandalkan centralized queue.
  • Payload retry-aware menyertakan header x-federated-retry-mechanism atau semacamnya agar penerima tahu ini retry.
  • Webhook ack harus dilakukan segera setelah request diterima atau disimpan dalam antrean internal. Jika node menerima webhook dengan request_id baru, ia harus segera membalas dengan status 202 dan menyimpan request untuk diproses.

Contoh alur:

  1. Node A mengirim request ke Node B, menyertakan token dan request_id.
  2. Node B memverifikasi token, menyimpan status processing, lalu mengirim ack 202.
  3. Jika Node A tidak menerima ack, ia melakukan retry dengan retry-count yang naik dan header x-federated-retry.
  4. Node B saat menerima retry memeriksa idempotensi; jika sudah processing, ia mengirim kembali ack 202 tanpa mengeksekusi ulang.

Kalau Node B sudah selesai (misalnya operasi berhasil), ia mengupdate status dan menolak retry selanjutnya dengan response 409 atau 200, bergantung kontrak.

Kesimpulan: konsistensi tanpa instance tunggal

Desain kontrak API federated harus memperhitungkan: autentikasi berbasis klaim yang diverifikasi lokal, idempotensi yang terikat pada request_id serta node origin, dan mekanisme retry/webhook ack yang menepis duplicate side effects. Dengan pendekatan ini, setiap node memegang kendali atas status request-nya tanpa harus bergantung pada instance pusat, tetap konsisten, dan bisa diintegrasikan antar federasi sesuai prinsip "There Are No Instances in atproto." Debugging fokus pada tiga hal: kegagalan verifikasi token (periksa kunci publik), status idempoten yang hilang (cek penyimpanan lokal), dan ack webhook yang tidak diterima (periksa log retry dan header).