# Masuk

Mini App bisa memasukkan orang yang sedang memakai Cowork dengan akun Micromeet-nya, lalu memanggil Micromeet atas nama orang itu dari backend-nya sendiri. Halaman tidak pernah melihat kata sandi, token, atau secret Mini App: Cowork hanya memberi halaman sebuah code sekali pakai, dan backend Mini App menukarnya dengan token.

Hanya Mini App terpasang yang paketnya sudah ditandatangani Micromeet, dengan sedikitnya satu domain server yang sudah diverifikasi, yang bisa memasukkan pengguna (lihat [Pengemasan dan Tanda Tangan](https://docs.micromeet.ai/id/miniapp-sdk/build.md)). Mini App bawaan tidak punya modul ini.

## MAESTROSDK.auth.login(params?) <Badge type="warning" text="Belum dirilis" />

Meminta code sekali pakai kepada Cowork, untuk Mini App ini dan orang yang sedang masuk ke Cowork.

### Parameter

| Field | Tipe | Wajib | Deskripsi |
|---|---|---|---|
| `scopes` | `string[]` | Tidak | Izin yang diminta Mini App, misalnya `['profile:read']`. Jika tidak diisi, berarti semua izin yang dibolehkan Micromeet untuk Mini App ini |

Pada panggilan pertama, Cowork menampilkan kartu kepada pengguna: nama dan pengembang Mini App, izin yang diminta, dan akun yang akan dipakai; tombolnya **Izinkan** dan **Batal**, dengan Batal sebagai pilihan bawaan. Kartu hanya muncul di tab yang sedang dilihat pengguna. Setelah diizinkan sekali, panggilan berikutnya untuk izin yang sama langsung mendapat code tanpa kartu.

### Nilai kembalian

`Promise<{ ok: true; code: string; region: 'SG' | 'HK' | 'ID'; expiresIn: number } | { ok: false; error: string }>`

Code hanya bisa dipakai sekali dan berlaku 5 menit (`expiresIn` dalam detik). Kirim `code` dan `region` ke backend Anda.

| `error` | Artinya |
|---|---|
| `unsigned` | Paket tidak ditandatangani Micromeet, atau halaman bukan Mini App yang terpasang |
| `tampered` | Ada file Mini App yang berubah setelah dipasang; Cowork sudah menutupnya |
| `host_signed_out` | Tidak ada yang masuk ke Cowork, atau halaman dibuka untuk akun lain. Jika ini tab yang sedang dilihat pengguna, Cowork membuka halaman masuknya |
| `user_cancelled` | Pengguna membatalkan, tab ada di latar belakang, atau akun berganti saat kartu terbuka |
| `app_not_available` | AppID ini tidak terdaftar di region ini, atau dinonaktifkan |
| `version_not_available` | Versi ini tidak terdaftar atau sudah dinonaktifkan: perbarui Mini App |
| `no_server_domain` | Versi ini tidak punya domain server yang sudah diverifikasi, atau salah satu domainnya tidak lagi terverifikasi (lihat [Pengemasan dan Tanda Tangan](https://docs.micromeet.ai/id/miniapp-sdk/build.md)) |
| `scope_denied` | Meminta izin yang tidak dibolehkan Micromeet untuk Mini App ini, atau `scopes` bukan daftar string |
| `rate_limited` | Terlalu banyak code dalam satu menit; coba lagi sebentar lagi |
| `network` | Cowork tidak bisa menghubungi Micromeet |

## MAESTROSDK.auth.status() <Badge type="warning" text="Belum dirilis" />

`Promise<{ signed: boolean; host: 'cowork'; hostSignedIn: boolean }>`. `signed` bernilai `true` jika tanda tangan paket valid dan tidak ada file yang berubah; `hostSignedIn` bernilai `true` jika ada yang masuk ke Cowork. Gunakan untuk menentukan apakah tombol masuk perlu ditampilkan.

## Di backend Mini App

Backend menyimpan client secret yang diberikan Micromeet saat mendaftarkan AppID, satu untuk setiap region tempat Mini App didaftarkan; jangan pernah menaruhnya di halaman atau paket. Backend berjalan di salah satu domain server Mini App yang sudah diverifikasi (lihat [Pengemasan dan Tanda Tangan](https://docs.micromeet.ai/id/miniapp-sdk/build.md)). Contoh langkah demi langkah ada di [Membuat Mini App dengan Masuk](https://docs.micromeet.ai/id/miniapp-sdk/sign-in-guide.md).

### Request dari halaman

Origin halaman adalah `miniapp://<appId>`. Jawab request-nya dengan `Access-Control-Allow-Origin: miniapp://<appId>`, dan preflight-nya (`OPTIONS`) dengan method dan header yang dikirimnya; jika tidak, request gagal di halaman sebelum sampai ke kode Anda. Simpan token Micromeet di backend dan beri halaman sesi milik Anda sendiri.

### Helper

`@micromeet-ai/miniapp-sdk/server` bisa dipakai dari ESM maupun CommonJS di Node.js 18 atau lebih baru.

```js
import { createMiniappAuthClient, MiniappAuthError } from '@micromeet-ai/miniapp-sdk/server';

const auth = createMiniappAuthClient({ appId: 'ai.example.app', clientSecret: process.env.MINIAPP_SECRET_HK });
const tokens = await auth.exchangeCode({ code, region });
const me = await auth.profile({ accessToken: tokens.accessToken, region: tokens.region });
```

| Opsi | Wajib | Keterangan |
|---|---|---|
| `appId` | Ya | AppID |
| `clientSecret` | Ya | Secret region yang dipanggil client ini; buat satu client per region |
| `coreUrl` | Tidak | `(region) => alamat`: Micromeet mana yang dipanggil. Default: produksi, per region |
| `fetch` | Tidak | Mengganti `fetch` global |
| `timeoutMs` | Tidak | Per request; default 15000 |

| Fungsi | Hasil |
|---|---|
| `exchangeCode({ code, region })` | Token: `accessToken`, `expiresIn` (detik), `refreshToken`, `scope` (daftar), `user: { ref, name, email }`, `institution: { iid, name }`, `region` |
| `refresh({ refreshToken, region })` | Set token baru; refresh token lama tidak berlaku lagi, simpan yang baru |
| `revoke({ refreshToken, region })` | Tidak ada; mengeluarkan orang itu dari Mini App |
| `profile({ accessToken, region })` | `{ ref, name, email, institution: { iid, name }, region }` (`profile:read`) |
| `call({ accessToken, region, path, body? })` | `data` dari `POST` ke route Micromeet yang menerima token Mini App |

Jika gagal, setiap fungsi melempar `MiniappAuthError` dengan `code` dari Micromeet dan `status` HTTP (lihat Galat di bawah).

### Token

| Token | Masa berlaku | Kegunaan |
|---|---|---|
| Access token | 15 menit | `Authorization: Bearer` pada route yang menerima token Mini App |
| Refresh token | 30 hari | `refresh` memberi pasangan baru; setiap refresh token hanya berlaku sekali |

- Gunakan region yang datang bersama code untuk semua panggilan berikutnya; token hanya berlaku di region-nya.
- Token berlaku untuk orang itu dan untuk institusi yang dipilihnya di Cowork saat masuk.
- `user.ref` adalah id tetap orang ini di Mini App ini (Mini App lain mendapat id lain): pakai sebagai kunci pengguna Anda.
- Kata sandi yang diubah, keluar dari semua perangkat, keluar dari institusi, versi yang dinonaktifkan, atau Mini App yang dinonaktifkan menghentikan token pada request berikutnya.

### Scope dan route

| Scope | Route | Hasil |
|---|---|---|
| `profile:read` | `POST /share/miniapp/profile` | `{ ref, name, email, institution: { iid, name }, region }` |

Token hanya berlaku pada route di tabel ini, untuk scope yang diizinkan orang itu, dan tidak pernah melebihi apa yang boleh dilakukan orang itu di Micromeet.

### Galat

| `code` | HTTP | Yang terjadi |
|---|---|---|
| `invalid_client` | 401 | AppID atau secret salah untuk region ini, atau secret sudah diganti |
| `invalid_grant` | 400 | Code sudah dipakai, lebih dari 5 menit, atau untuk AppID lain; refresh token sudah dipakai, dicabut, atau lebih dari 30 hari; atau orang itu mengganti kata sandi, keluar dari semua perangkat, atau keluar dari institusi: masuk lagi |
| `app_not_available` | 400 | Mini App dinonaktifkan di region ini |
| `version_not_available` | 400 | Versi yang dipakai orang itu saat masuk sudah dinonaktifkan: perbarui Mini App |
| `needLogin` | 401 | Pada route: access token kedaluwarsa atau tidak berlaku lagi. Panggil `refresh`; jika gagal, masuk lagi |
| `forbidden` | 403 | Pada route: token tidak memegang scope route itu, atau orang itu tidak boleh melakukan ini di Micromeet |
| `network` | — | Helper tidak bisa menghubungi Micromeet (`status` 0) |
| `params_invalid` | 400, atau — | `grant_type` salah; atau, di helper, region tidak dikenal atau `path` yang bukan route (`status` 0, tidak ada request terkirim) |

### Panggilan HTTP

Backend dalam bahasa lain melakukan panggilan yang sama. Masing-masing adalah `POST` dengan body JSON ke Micromeet di region code itu:

| Region | Alamat |
|---|---|
| SG | `https://crms-api.micromeet.ai` |
| HK | `https://crms-api-hk.micromeet.ai` |
| ID | `https://crms-api-id.micromeet.ai` |

| Path | Body | `data` di jawaban |
|---|---|---|
| `/miniapp-open/auth/token` | `{ "grant_type": "authorization_code", "app_id", "client_secret", "code" }` | `{ access_token, token_type: "Bearer", expires_in, refresh_token, scope, user: { ref, name, email }, institution: { iid, name }, region }`; `scope` dipisahkan spasi |
| `/miniapp-open/auth/token` | `{ "grant_type": "refresh_token", "app_id", "client_secret", "refresh_token" }` | Sama |
| `/miniapp-open/auth/revoke` | `{ "app_id", "client_secret", "refresh_token" }` | `{ revoked: true }` |
| `/share/miniapp/profile` | `{}`, dengan `Authorization: Bearer <access_token>` | `{ ref, name, email, institution: { iid, name }, region }` |

Berhasil dijawab dengan `{ "code": 0, "success": true, "data": … }`. Gagal dijawab dengan `{ "code": "<galat>", "msg": "…", "success": false }` dengan status HTTP seperti di Galat di atas.

## Terkait

- [Pengemasan dan Tanda Tangan](https://docs.micromeet.ai/id/miniapp-sdk/build.md): Kemas Mini App dan minta Micromeet menandatanganinya
- [Ikhtisar](https://docs.micromeet.ai/id/miniapp-sdk/overview.md): Semua modul Mini App SDK
