> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sertifikasitrainer.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SKKNI & WSP API

> Pencarian unit kompetensi, peta KUK, dan integrasi ke dokumen trainer.

Data **SKKNI** (Standar Kompetensi Kerja Nasional Indonesia) tidak diekstrak dari chat AI. Sistem mengambilnya dari **WSP API** setelah peserta memilih unit kompetensi.

## Kapan dipakai

| Flow              | SKKNI                                                     |
| ----------------- | --------------------------------------------------------- |
| Master workspace  | Referensi unit di beberapa bukti                          |
| Trainer workspace | **Wajib** — elemen, KUK, peta kompetensi untuk 15 dokumen |
| Branding          | Tidak dipakai                                             |

## Alur di UI trainer

```mermaid theme={null}
flowchart TD
  chat["Chat interviewer"] --> search["POST skkni/search"]
  search --> wsp["WSP semantic search"]
  wsp --> list["Daftar kandidat unit"]
  list --> pick["User pilih unit"]
  pick --> select["POST skkni/select"]
  select --> detail["GET unit detail + competency map"]
  detail --> canon["Update canonical state\nskkni_map, KUK, elemen"]
  canon --> gen["Generate trainer docs"]
```

## API endpoints

| Method | Path                                  | Fungsi                                |
| ------ | ------------------------------------- | ------------------------------------- |
| `POST` | `/documents/:documentId/skkni/search` | Cari unit dari konteks master JSON    |
| `POST` | `/documents/:documentId/skkni/select` | Pilih unit → simpan ke document state |

Kode: `apps/api/src/skkni/skkni.routes.ts`, `skkni.service.ts`

## WSP API

Base URL dari env:

```bash theme={null}
WSP_API_URL=https://...
WSP_API_KEY=...
```

Service memanggil:

| Operasi         | WSP path                       | Hasil                          |
| --------------- | ------------------------------ | ------------------------------ |
| Semantic search | `/search/semantic`             | Kandidat unit + skor relevansi |
| Unit detail     | `/units/{code}`                | Judul, deskripsi, elemen       |
| Competency map  | `/units/{code}/competency-map` | KUK per elemen                 |

Response divalidasi dengan Zod sebelum dipakai.

## State setelah select

Field document state yang terisi (contoh):

| Field             | Isi                     |
| ----------------- | ----------------------- |
| `skkni_map`       | Peta kompetensi lengkap |
| `unit_code`       | Kode unit terpilih      |
| `skkni_map_ready` | `true` di DB            |

Composer trainer membaca KUK/elemen dari state ini — **bukan** dari output chat mentah.

## Search input

`searchMaster()` memakai konteks dari `masterJson`:

* `expertise`, `activities`, `audience`, `outcome`
* `domain_hint`, `inferred_goal_label`

Hasil: array `SkkniCandidate` dengan `unitCode`, `title`, `relevanceScore`, `reason`.

## Error handling

* WSP down → search return kosong + log `[skkni] search failed`
* Unit tidak ditemukan → 404 dari API
* Select tanpa ownership document → 403

## Halaman terkait

* [Alur generate dokumen](/ai/overview) — "Unit SKKNI tidak diekstrak dari chat"
* [Prompt trainer](/ai/prompt-trainer) — pre/post test dari KUK
* [Glossarium](/architecture/glossarium#dokumen--ai)
