Skip to content

Aturan Deny yang Diam-diam Mati Setelah Upgrade OpenCode V2

Adityo Guni Waluyo

Upgrade harness membunuh config permission lama tanpa error. Cara saya menemukan deny yang mati dan membuktikannya dengan aksi nyata.

Ringkasan

Setelah upgrade ke V2, saya menemukan masalah dengan frontmatter yang tidak terbaca. Perubahan schema membuat aturan lama tidak berlaku. Sekarang saya harus memeriksa setiap file frontmatter dan melakukan percobaan aksi yang ditarang setelah setiap upgrade.

Pagi pertama setelah harness OpenCode di proyek KotaPortal selesai upgrade ke V2, saya melihat hal yang seharusnya mustahil: subagent frontend-designer sedang menjalankan perintah shell bebas, padahal frontmatter-nya menolak semua perintah shell kecuali enam baris whitelist yang saya tulis sendiri. Tidak ada error. Tidak ada peringatan. File config-nya masih terlihat persis seperti yang saya tinggalkan semalam.

Tebakan pertama saya: pasti ada bug di sesi itu, mungkin agent-nya beralih ke mode primary. Bukan itu. Yang berubah adalah schema frontmatter-nya. Dokumen V2 menyatakan frontmatter menerima field yang sama dengan entri konfigurasi "agents" [2], dan field permission kini berbentuk list tiga field: action, resource, effect [1]. Vocabulary-nya berganti nama. V1 memakai "permission", "bash", dan "task"; V2 memakai "permissions", "shell", dan "subagent" [1]. Nama lama tidak lagi ada di daftar field yang diterima. Dan tidak cuma permission. Field "temperature" serta "memory" di frontmatter lama ikut hilang tanpa suara, dan prasyarat preload skill yang pernah saya deklarasikan untuk subagent riset tidak pernah termuat; cara kerjanya kini lewat pemuatan skill eksplisit lewat tool "skill" dari instruksi prompt. Semua field mati itu sama-sama tidak menghasilkan error apa pun.

Dua Bentuk yang Terlihat Sama

Blok pertama adalah frontmatter lama yang saya kira masih berlaku; blok kedua adalah bentuk yang dibaca V2:

# V1 — tidak terbaca lagi di V2
---
mode: subagent
permission:
  bash:
    "*": deny
    "npm run lint": allow
  task: deny
---
# V2 — bentuk list yang berlaku
---
mode: subagent
permissions:
  - action: shell
    resource: "*"
    effect: deny
  - action: shell
    resource: "npm run lint*"
    effect: allow
  - action: subagent
    resource: "*"
    effect: deny
---

Kebijakannya identik: tolak semua shell, izinkan satu perintah whitelist, larang meluncurkan subagent. Dokumen V2 menjelaskan kenapa versi pertama diam saja. Aturan digabung berurutan dan kecocokan terakhir menang, dengan aturan agent ditambahkan paling akhir [1]. Kalau nama field dan action tidak dikenali, tidak ada aturan yang cocok, dan OpenCode jatuh ke default "ask" [1]. Dalam pengamatan saya, peta permission lama itu sama sekali tidak terbaca, jadi tidak ada aturan deny yang sempat menyanggah apa pun.

Yang paling membuat saya tidak nyaman justru perbandingannya. Di level konfigurasi global, perubahan schema diperlakukan hati-hati: dokumen V1 mencatat konfigurasi boolean "tools" lama sudah deprecated sejak v1.1.1 tapi "still supported for backwards compatibility" [3]. Dokumen V1 sendiri sudah menyebut akses tool agent "configured via permissions" [4], jadi vocabulary-nya lama berpindah bentuk. Di level frontmatter agent, audit saya tidak menemukan lapisan kompatibilitas serupa, dan dokumen V2 memang tidak menjanjikannya [2]. Perilaku diam-diri ini pengamatan pertama-tangan dari migrasi saya sendiri, bukan kontrak resmi vendor. Karena itu saya perlakukan sebagai hal yang wajib diverifikasi, bukan diasumsikan. Jalur V2 sendiri adalah rilis major yang nyata: catatan instalasi menyebut versi lama memasang OpenCode 1, dan rilisnya membawa tag Docker bernomor [5].

Membuktikan Deny dengan Aksi yang Ditarang

Metode verifikasi saya sekarang satu langkah: usahakan aksi yang ditarang. Minta subagent menjalankan perintah yang seharusnya deny. Kalau perintahnya jalan tanpa ditahan, aturan itu mati dan tidak peduli seperti apa bentuk YAML-nya.

Tes hijau tidak pernah melakukan ini. Suite menguji kode yang menulis fitur, bukan config yang menolak aksi; tidak ada assertion yang bertanya "apakah perintah ini seharusnya gagal". Dokumen V2 menegaskan kenapa satu percobaan langsung sudah cukup tegas: operasi yang menyentuh beberapa resource ditolak begitu ada satu "deny" [1], dan subagent berjalan dengan permission miliknya sendiri, bukan gabungan izin induknya [2]. Kalau child tidak punya aturan deny yang hidup, izin ketat di parent tidak menolong apa pun.

Praktik Baru Setiap Upgrade

Kini setiap harness upgrade di repo itu ditutup dua langkah yang sama. Baca ulang setiap file frontmatter di direktori agen terhadap schema yang sedang berlaku, lalu jalankan satu percobaan aksi yang ditarang per aturan deny. File config tetap terlihat rapi sebelum dan sesudah. Yang membedakan hanya satu hal yang bisa dilihat dari luar: aksi yang benar-benar ditolak.

Sumber:

Sources

[1] https://opencode.ai/v2/docs/permissions

[2] https://opencode.ai/v2/docs/agents

[3] https://opencode.ai/docs/permissions

[4] https://opencode.ai/docs/agents

[5] https://opencode.ai/v2/docs

Artikel terkait