# Penerbit Terpercaya

**Push ke Hub dari CI tanpa menyimpan secret `HF_TOKEN`.**

Job CI Anda membuktikan identitasnya ke Hugging Face menggunakan token OpenID Connect (OIDC) berumur pendek dari penyedia CI Anda, dan sebagai gantinya mendapatkan token Hugging Face berumur pendek. Tidak perlu menyimpan atau merotasi token HF sebagai rahasia.

| | Personal Access Token | Penerbit Terpercaya |
| --- | --- | --- |
| Masa Hidup | Sampai dicabut | 1 jam |
| Penyimpanan | Rahasia CI | Tidak ada yang perlu disimpan |
| Rotasi | Manual | Otomatis, setiap kali dijalankan |
| Jika bocor | Valid hingga Anda mencabutnya | Maksimal sekitar 1 jam, dan dibatasi pada satu repo |

Trusted Publishers memiliki konsep yang sama dengan [Trusted Publishers](https://docs.pypi.org/trusted-publishers/) di PyPI dan [Trusted Publishing](https://docs.npmjs.com/trusted-publishers) di npm.

## Contoh cepat: menerbitkan model dari GitHub Actions

Anda memelihara `acme/awesome-model` di HF Hub dan ingin CI di repositori `acme/awesome-model-training` yang di-hosting secara eksternal (di GitHub, GitLab, atau penyedia mana pun yang patuh OIDC) untuk mendorong checkpoint baru — tanpa rahasia `HF_TOKEN`.

### 1. Konfigurasikan penerbit tepercaya di Hub

Di `https://huggingface.co/acme/awesome-model/settings`, buka **Trusted Publishers** dan tambahkan:

- **Penyedia**: GitHub Actions
- **Klaim** (semua harus cocok agar pertukaran berhasil):
  - `repository` = `acme/awesome-model-training`
  - `branch` = `main`
  - `workflow` = `publish.yml`

> [!TIP]
> `repository` saja membatasi penerbit ke repositori GitHub. Tambahkan `branch` dan/atau `workflow` untuk juga menguncinya ke cabang atau file workflow — disarankan.

### 2. Tambahkan workflow ke repo GitHub Anda

`.github/workflows/publish.yml`:

```yaml
name: Publish to Hugging Face

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  publish:
    runs-on: ubuntu-latest

    permissions:
      id-token: write  # required so the job can request an OIDC token
      contents: read

    steps:
      - uses: actions/checkout@v4

      - name: Install the hf CLI
        run: |
          curl -LsSf https://hf.co/cli/install.sh | bash
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"

      - name: Upload checkpoint
        env:
          # The HF repo to publish to. For non-model repos, prefix accordingly:
          #   datasets/acme/awesome-dataset, spaces/acme/awesome-space, kernels/acme/awesome-kernel
          HF_OIDC_RESOURCE: acme/awesome-model
        run: hf upload acme/awesome-model ./checkpoint . --commit-message "Publish from ${GITHUB_SHA::7}"
```

Itu saja. Di GitHub Actions, CLI `hf` (`huggingface_hub>=1.19.0`) mendeteksi provider, melakukan pertukaran, dan secara otomatis menggunakan token yang dihasilkan. Anda hanya perlu mengatur `HF_OIDC_RESOURCE`.

> [!TIP]
> Menerbitkan ke beberapa repositori dalam satu eksekusi (misalnya, model **dan** dataset)? Atur `HF_OIDC_RESOURCE` per langkah agar setiap token memiliki cakupan pada repositori yang dituju oleh langkah tersebut.

#### Penyedia CI lainnya

CLI `hf` saat ini hanya membuat ID token secara native di GitHub Actions. Di GitLab, CircleCI, Bitbucket, atau penyedia lainnya, buat ID token Anda sendiri (lihat [Penyedia CI yang didukung](#supported-ci-providers)) dan teruskan melalui `HF_OIDC_ID_TOKEN` — CLI akan menukarnya secara langsung:

```yaml
# GitLab CI (.gitlab-ci.yml)
publish:
  id_tokens:
    HF_ID_TOKEN:
      aud: https://huggingface.co
  script:
    - curl -LsSf https://hf.co/cli/install.sh | bash
    - export PATH="$HOME/.local/bin:$PATH"
    - HF_OIDC_ID_TOKEN="$HF_ID_TOKEN" HF_OIDC_RESOURCE="acme/awesome-model" hf upload acme/awesome-model ./checkpoint .
```

Contoh kerja lengkap:

- GitHub Actions — [`github.com/coyotte508/publish-to-hf`](https://github.com/coyotte508/publish-to-hf)
- GitLab CI — [`gitlab.com/coyotte508/publish-to-hf`](https://gitlab.com/coyotte508/publish-to-hf)

## Dua jenis: penerbit repo dan identitas CI/CD

| Rasa | Dikonfigurasi pada | Yang Anda dapatkan | Gunakan untuk… |
| --- | --- | --- | --- |
| **Penerbit tepercaya repo** | **Pengaturan → Penerbit Terpercaya** sebuah repo | Token dengan **akses tulis ke repositori tersebut** (atau [akses hanya-baca](#read-only-repo-publishers)) | Publikasikan model, dataset, Space, kernel, atau bucket dari CI, atau tarik yang privat |
| **Identitas CI/CD akun** | [**Pengaturan autentikasi → Akses CI/CD**](https://huggingface.co/settings/authentication#ci-cd-access) akun Anda | Token hanya-baca dengan cakupan `gated-repos`, ditambah `inference-api` jika Anda memilih untuk mengaktifkannya | Baca **repo bergerbang yang dapat Anda akses**, gunakan batas laju Anda, dan secara opsional panggil Inference Providers dari CI |

Kedua token kedaluwarsa setelah 60 menit. Anda memerlukan peran **Write** pada repo Hub untuk mengelola penerbit tepercaya-nya.

### Mengakses repositori bergerbang dari CI

Jika Anda hanya perlu *membaca* repositori bergerbang (misalnya mengunduh model dari sebuah job), tambahkan identitas CI/CD pada akun Anda di bawah [**Authentication settings → CI/CD Access**](https://huggingface.co/settings/authentication#ci-cd-access) alih-alih pada repositori tertentu, lalu gunakan **username** Anda sebagai resource.

Pada **GitHub Actions**, CLI `hf` melakukan pertukaran untuk Anda, cukup atur `HF_OIDC_RESOURCE`:

```yaml
      - name: Download a gated model
        env:
          HF_OIDC_RESOURCE: your-hf-username
        run: hf download acme/gated-model
```

Pada **provider lain**, buat ID token Anda sendiri (lihat [Provider CI lain](#other-ci-providers)) dan teruskan melalui `HF_OIDC_ID_TOKEN`:

```bash
# $ID_TOKEN is the OIDC token your provider minted (e.g. $HF_ID_TOKEN on GitLab)
HF_OIDC_ID_TOKEN="$ID_TOKEN" HF_OIDC_RESOURCE="your-hf-username" hf download acme/gated-model
```

Token yang dihasilkan dapat membaca repositori bergerbang yang Anda miliki aksesnya dan menggunakan batas laju akun Anda. Token ini **tidak dapat** menulis apa pun, dan **tidak dapat** membaca repositori pribadi Anda. Untuk menarik repositori pribadi dari CI, gunakan [publisher repositori hanya-baca](#read-only-repo-publishers) sebagai gantinya.

> [!TIP]
> Butuh token itu sendiri (untuk `curl`, `git clone`, atau alat yang membaca `HF_TOKEN`)? `hf auth token` melakukan pertukaran dan mencetak token berumur pendek ke stdout:
>
> ```yaml
>       - name: Get a short-lived HF token
>         env:
>           HF_OIDC_RESOURCE: your-hf-username  # or a repo, e.g. acme/awesome-model
>         run: echo "HF_TOKEN=$(hf auth token)" >> "$GITHUB_ENV"
> ```
>
> Ini berfungsi dengan identitas CI/CD dan penerbit repo — token di-scope ke apa pun yang ditunjuk oleh `HF_OIDC_RESOURCE`.

### Penerbit repositori hanya-baca

Secara default, trusted publisher sebuah repo mencetak token yang dapat melakukan push ke repo tersebut. Jika sebuah workload hanya perlu *pull* sebuah repo (misalnya, untuk mengunduh model atau dataset privat dari job CI atau platform eksternal yang menerbitkan token OIDC-nya sendiri), centang **Read-only** saat menambahkan publisher. Token yang ditukarkan kemudian dapat membaca konten repo tetapi tidak dapat menulis ke dalamnya, dan entri tersebut menampilkan lencana **Read-only** dalam daftar. Ini berlaku untuk model, dataset, Spaces, kernel, dan bucket.

Pertukarannya sendiri tidak berubah. Arahkan `HF_OIDC_RESOURCE` (atau `resource`) ke repo.

```yaml
    permissions:
      id-token: write  # required so the job can request an OIDC token

    steps:
      - name: Download a private model
        env:
          HF_OIDC_RESOURCE: acme/private-model
        run: hf download acme/private-model
```

Seperti pengaturan penerbit lainnya, izin ini ditetapkan saat pembuatan. Untuk mengubahnya, hapus penerbit tersebut dan tambahkan kembali.

### Memanggil Penyedia Inferensi dari CI

Token dari identitas CI/CD bersifat hanya-baca secara default. Untuk memungkinkan token tersebut juga memanggil Inference Providers, centang **Izinkan panggilan Inference Providers** saat menambahkan identitas — token yang ditukarkan kemudian membawa scope `inference-api` di samping `gated-repos`, dan entri tersebut menampilkan lencana **Inference** dalam daftar.

Penggunaan inference **ditagihkan ke akun Anda**, persis seperti jika Anda yang membuat permintaan tersebut — jadi batasi klaimnya secara ketat (`repository` *dan* `branch` dan/atau `workflow`) sebelum mengaktifkannya.

```yaml
      - name: Run inference from CI
        env:
          HF_OIDC_RESOURCE: your-hf-username
        run: |
          export HF_TOKEN="$(hf auth token)"
          python inference_script.py
```

Penerbit repo tidak memenuhi syarat — token mereka ber-scope repo dan tidak dapat memanggil Inference Providers. Kemampuan ini ditetapkan saat pembuatan; untuk mengubahnya, hapus identitas tersebut dan tambahkan kembali.

## Penyedia CI yang didukung

UI pengaturan dilengkapi dengan preset untuk penyedia di bawah ini, tetapi penyedia mana pun yang sesuai dengan OIDC juga dapat digunakan (AWS, GCP, Buildkite, IdP Anda sendiri, …).

| Penyedia | Penerbit | Cara mendapatkan token ID |
| --- | --- | --- |
| **GitHub Actions** | `https://token.actions.githubusercontent.com` | Set `permissions: id-token: write`, lalu panggil endpoint metadata dengan `audience=https://huggingface.co`. [Dokumentasi](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect). |
| **GitLab CI** | `https://gitlab.com` (atau URL self-hosted Anda) | Deklarasikan `id_tokens: { HF_ID_TOKEN: { aud: https://huggingface.co } }` pada job; baca `$HF_ID_TOKEN`. [Dokumentasi](https://docs.gitlab.com/ci/yaml/#id_tokens). |
| **CircleCI** | `https://oidc.circleci.com/org/<org-uuid>` | Gunakan `$CIRCLE_OIDC_TOKEN_V2` (v2 memungkinkan Anda mengatur audiens di pengaturan proyek). [Dokumentasi](https://circleci.com/docs/openid-connect-tokens/). |
| **Bitbucket Pipelines** | `https://api.bitbucket.org/2.0/workspaces/<workspace>/pipelines-config/identity/oidc` | Setel `oidc: true` pada langkah; baca `$BITBUCKET_STEP_OIDC_TOKEN`. [Dokumentasi](https://support.atlassian.com/bitbucket-cloud/docs/integrate-pipelines-with-resource-servers-using-oidc/). |

Setelah Anda memiliki token ID, panggilan pertukaran identik di semua penyedia — hanya **claims** yang Anda konfigurasikan di sisi Hub yang berbeda.

## Cara kerjanya

1. Penyedia CI Anda menerbitkan **token ID OIDC** berumur pendek yang mendeskripsikan pekerjaan (repo mana, branch mana, workflow mana, …).
2. Alur kerja Anda `POST` token tersebut ke `https://huggingface.co/oauth/token`, bersama dengan `resource` (repo atau nama pengguna yang ingin diakses).
3. Hub memeriksa tanda tangan dan klaim token terhadap penerbit yang Anda konfigurasikan untuk sumber daya tersebut, lalu mengembalikan token Hugging Face.

```
┌──────────┐  1. mint ID token   ┌──────────┐  2. exchange   ┌────────────┐
│ CI job   │ ─────────────────▶  │ CI OIDC  │ ──────────────▶│ huggingface│
│          │                     │ issuer   │                │  /oauth/   │
│          │ ◀──────────────────────────────────────────────│  token     │
└──────────┘        3. short-lived HF token (valid 1 h)      └────────────┘
```

## Referensi API

Endpoint, permintaan, dan respons

**Endpoint:** `POST https://huggingface.co/oauth/token` dengan `Content-Type: application/json`.

Tidak diperlukan autentikasi klien — token ID OIDC mengautentikasi permintaan. Pertukaran mengikuti [RFC 8693 — OAuth 2.0 Token Exchange](https://www.rfc-editor.org/rfc/rfc8693.html).

**Tubuh permintaan:**

| Bidang | Wajib | Nilai |
| --- | --- | --- |
| `grant_type` | ya | `urn:ietf:params:oauth:grant-type:token-exchange` |
| `subject_token_type` | ya | `urn:ietf:params:oauth:token-type:id_token` |
| `subject_token` | ya | Token ID OIDC mentah (JWT) dari penyedia CI Anda. Klaim `aud`-nya **harus** berupa `https://huggingface.co`. |
| `resource` | ya | Repo Hub (`namespace/name`, `datasets/namespace/name`, `spaces/namespace/name`, `kernels/namespace/name`, `buckets/namespace/name`) atau **username** Hub (tanpa garis miring) untuk token yang berscope pengguna. |

**Respons sukses:**

```json
{
  "access_token":      "hf_jwt_…",   // "hf_oauth_…" for user resources
  "token_type":        "bearer",
  "expires_in":        3600,
  "issued_token_type": "urn:ietf:params:oauth:token-type:access_token"
}
```

**Galat** — `400 Bad Request` dengan badan gaya OAuth:

| `error` | Mengapa |
| --- | --- |
| `invalid_request` | Parameter hilang/tidak valid, atau format `resource` salah. |
| `invalid_grant` | Repo atau user tidak ditemukan; tidak ada publisher yang cocok dengan issuer ini; claims yang dikonfigurasi tidak cocok; pemeriksaan signature atau audience gagal; akun terkunci. |

Saat CLI `hf` melakukan pertukaran, kegagalan akan menampilkan kode `error` beserta `(Request ID: …)` — sertakan Request ID tersebut saat melaporkan masalah agar kami dapat menelusuri pertukaran tersebut di log kami.

## Model keamanan

- **Tokens memiliki masa berlaku singkat.** 60 menit sejak saat pertukaran — hitungan waktu baru dimulai saat Anda memanggil endpoint, bukan saat workflow dimulai. Tidak ada refresh token; tugas yang berlangsung lama harus melakukan pertukaran ulang.
- **Token repo bersifat khusus untuk repo tersebut.** Token untuk `acme/awesome-model` tidak dapat mengakses `acme/anything-else`. Push dikaitkan dengan pengguna sistem sintetis `[OIDC]`, dengan referensi ke issuer dan subject asal. Token dari publisher read-only hanya dapat membaca repo tersebut.
- **Token pengguna bersifat hanya-baca.** `gated-repos` scope secara default — tidak ada penulisan, tidak ada repositori privat, dan tidak ada manajemen akun. `inference-api` scope opsional menambahkan panggilan Inference Providers (ditagihkan ke akun Anda), tetapi tetap tidak ada akses penulisan atau repositori privat.
- **Klaim dicocokkan secara persis, atau berdasarkan prefiks jika preset penyedia membutuhkannya** (misalnya `workflow_ref` dari GitHub). Tidak ada regex.
- **Log audit.** Penambahan atau penghapusan penerbit dicatat, dan pertukaran yang berhasil memperbarui waktu terakhir digunakan.

## Lihat juga

- [Tokens Akses Pengguna](./security-tokens) — pilihan yang tepat untuk manusia dan skrip sekali jalan
- [OAuth / Masuk dengan HF](./oauth) — endpoint `/oauth/token` yang sama, digunakan untuk alur interaktif
- [Mengelola Spaces dengan GitHub Actions](./spaces-github-actions)
- [Integrasi GitHub Actions untuk Hub](./repositories-github-actions)

