@ryuu-reinzz/ryuu-cli 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- package/docs/github.md +470 -0
- package/package.json +1 -1
- package/plugins/github/README.md +158 -0
- package/plugins/github/api.js +78 -0
- package/plugins/github/auth.js +45 -0
- package/plugins/github/backend.js +191 -0
- package/plugins/github/command.js +307 -0
- package/plugins/github/config.js +209 -0
- package/plugins/github/credentials.js +161 -0
- package/plugins/github/errors.js +49 -0
- package/plugins/github/index.js +41 -0
- package/plugins/github/manager.js +613 -0
- package/plugins/github/tool-helpers.js +259 -0
- package/plugins/github/tools-account.js +64 -0
- package/plugins/github/tools-actions.js +126 -0
- package/plugins/github/tools-issues.js +214 -0
- package/plugins/github/tools-pulls.js +267 -0
- package/plugins/github/tools-releases.js +87 -0
- package/plugins/github/tools-repos.js +430 -0
- package/plugins/github/tools.js +25 -0
- package/plugins/index.js +3 -1
- package/src/cli/commands.js +71 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,53 @@
|
|
|
3
3
|
Semua perubahan penting pada Ryuu Agent CLI didokumentasikan di sini.
|
|
4
4
|
Project ini mengikuti [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [0.5.2] - 2026-11-03
|
|
7
|
+
|
|
8
|
+
### Ditambahkan
|
|
9
|
+
|
|
10
|
+
- **`github_delete_repository`** — menghapus repository GitHub secara permanen.
|
|
11
|
+
Berisiko `destructive`, selalu melewati approval Ryuu, dan hanya berjalan bila
|
|
12
|
+
argumen `confirm` berisi `owner/repo` yang sama persis. Bisa dimatikan dengan
|
|
13
|
+
`/github config set confirmDestructive false`.
|
|
14
|
+
- **Panduan `/github` dan `/drive` di `/help`** — `/help` kini menampilkan daftar
|
|
15
|
+
subcommand kedua plugin selama plugin dimuat, dan `/help drive` menampilkan
|
|
16
|
+
tutorial seperti `/help github`.
|
|
17
|
+
|
|
18
|
+
### Diubah
|
|
19
|
+
|
|
20
|
+
- Safelist proxy backend menerima `DELETE /repos/{owner}/{repo}` khusus untuk
|
|
21
|
+
tool penghapusan repository; endpoint DELETE lain tetap ditolak.
|
|
22
|
+
|
|
23
|
+
## [0.5.1] - 2026-11-03
|
|
24
|
+
|
|
25
|
+
Rilis ini menambahkan integrasi GitHub App sebagai plugin opsional, dengan
|
|
26
|
+
seluruh kewenangan OAuth dan penyimpanan token berada di backend.
|
|
27
|
+
|
|
28
|
+
### Ditambahkan
|
|
29
|
+
|
|
30
|
+
- **Integrasi GitHub (`plugins/github/`)** dengan 35 tool AI: akun, repository,
|
|
31
|
+
branch/commit/file, issue, pull request, release, dan GitHub Actions.
|
|
32
|
+
- **Command `/github`**: `login` (browser), `login --device` (headless),
|
|
33
|
+
`logout`, `status`, `account`, `test`, `enable`, `disable`, `config`.
|
|
34
|
+
- **Gateway backend GitHub** (`website/api/lib/github/`) sebagai satu-satunya
|
|
35
|
+
pemegang Client Secret, Private Key, Webhook Secret, dan token pengguna.
|
|
36
|
+
CLI hanya memegang `cliToken` per akun yang disimpan terenkripsi
|
|
37
|
+
(AES-256-GCM) dan tidak pernah menerima access/refresh token GitHub.
|
|
38
|
+
- **OAuth GitHub App** dengan `state` sekali pakai, PKCE S256, sesi pairing
|
|
39
|
+
berumur pendek, polling sekali ambil, serta fallback device flow.
|
|
40
|
+
- **Auto-refresh token** di backend dengan single-flight dan rotasi refresh
|
|
41
|
+
token; `invalid_grant` menandai akun perlu login ulang.
|
|
42
|
+
- **Webhook `/webhooks/github`** dengan verifikasi HMAC SHA-256 constant-time,
|
|
43
|
+
deduplikasi delivery, dan pemrosesan asynchronous.
|
|
44
|
+
- **Approval** untuk seluruh operasi yang mengubah data; penghapusan file dan
|
|
45
|
+
merge pull request berisiko `destructive` dan dapat diblokir lewat
|
|
46
|
+
`confirmDestructive`.
|
|
47
|
+
|
|
48
|
+
### Catatan
|
|
49
|
+
|
|
50
|
+
- Plugin Google Drive tidak diubah perilakunya.
|
|
51
|
+
- Tidak ada Client Secret, Private Key, atau token GitHub di source code CLI.
|
|
52
|
+
|
|
6
53
|
## [0.5.0] - 2026-11-01
|
|
7
54
|
|
|
8
55
|
Rilis ini menambahkan sistem plugin dan integrasi Google Drive, sekaligus
|
package/docs/github.md
ADDED
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
# Integrasi GitHub — Ryuu CLI
|
|
2
|
+
|
|
3
|
+
Dokumen ini menjelaskan cara memasang, mengonfigurasi, memakai, dan menguji
|
|
4
|
+
integrasi GitHub pada Ryuu CLI. Integrasi terdiri dari dua bagian:
|
|
5
|
+
|
|
6
|
+
1. **Backend** (`/root/website/api`, modul `lib/github/`) — Integration Gateway
|
|
7
|
+
yang memegang seluruh kredensial GitHub App dan token pengguna.
|
|
8
|
+
2. **Plugin CLI** (`/root/agents/ryuu/plugins/github/`) — command `/github` dan
|
|
9
|
+
36 tool AI yang memanggil GitHub melalui gateway.
|
|
10
|
+
|
|
11
|
+
Tidak ada Client Secret, Private Key, Webhook Secret, access token, atau refresh
|
|
12
|
+
token di sisi CLI. CLI hanya memegang `cliToken` per akun yang disimpan
|
|
13
|
+
terenkripsi.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 1. Arsitektur
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
┌──────────────────────────┐ ┌─────────────────────────────────┐
|
|
21
|
+
│ Ryuu CLI │ │ Backend Ryuu (lib/github) │
|
|
22
|
+
│ plugins/github │ │ │
|
|
23
|
+
│ /github login ──────────┼───────▶│ POST /integrations/github/connect│
|
|
24
|
+
│ browser / device flow │ │ state + PKCE + URL otorisasi │
|
|
25
|
+
│ polling sesi ───────────┼───────▶│ GET /integrations/github/session│
|
|
26
|
+
│ cliToken (terenkripsi) │◀───────┤ cliToken (sekali ambil) │
|
|
27
|
+
│ │ │ │
|
|
28
|
+
│ tools GitHub ───────────┼───────▶│ ALL /integrations/github/api/* │
|
|
29
|
+
│ │ │ token pengguna + safelist │
|
|
30
|
+
└──────────────────────────┘ └───────────────┬─────────────────┘
|
|
31
|
+
│ HTTPS
|
|
32
|
+
┌──────────────▼──────────────┐
|
|
33
|
+
│ github.com / api.github.com │
|
|
34
|
+
│ GitHub App + instalasi │
|
|
35
|
+
└─────────────────────────────┘
|
|
36
|
+
|
|
37
|
+
GitHub ── webhook ──▶ POST /webhooks/github (signature HMAC SHA-256)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Prinsip:
|
|
41
|
+
|
|
42
|
+
- **Satu akun GitHub = satu record token** di backend. Tidak ada token global.
|
|
43
|
+
- Backend memakai penyimpanan JSON yang sudah menjadi pola proyek
|
|
44
|
+
(`~/.config/ryuu/github/data/tokens.json`) dengan atomic write + lock; bukan
|
|
45
|
+
database baru.
|
|
46
|
+
- Token disimpan dengan AES-256-GCM; kunci enkripsi terpisah dari data.
|
|
47
|
+
- CLI memanggil GitHub hanya lewat proxy backend, sehingga token tidak pernah
|
|
48
|
+
meninggalkan server.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 2. Prasyarat
|
|
53
|
+
|
|
54
|
+
- Node.js ≥ 22 di mesin CLI dan server backend.
|
|
55
|
+
- GitHub App sudah dibuat dan diinstal ke akun/organisasi.
|
|
56
|
+
- Backend dapat diakses publik pada domain yang terdaftar di GitHub App.
|
|
57
|
+
- `express` (sudah menjadi dependensi backend).
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 3. Membuat GitHub App
|
|
62
|
+
|
|
63
|
+
Buka **GitHub → Settings → Developer settings → GitHub Apps → New GitHub App**.
|
|
64
|
+
|
|
65
|
+
| Field | Nilai |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| App name | `Ryuu CLI` |
|
|
68
|
+
| Homepage URL | `https://restapi.ryuu-dev.my.id/site` |
|
|
69
|
+
| Callback URL | `https://restapi.ryuu-dev.my.id/integrations/github/callback` |
|
|
70
|
+
| Webhook URL | `https://restapi.ryuu-dev.my.id/webhooks/github` |
|
|
71
|
+
| Webhook secret | string acak panjang; simpan di konfigurasi backend |
|
|
72
|
+
| Expire user authorization tokens | **aktifkan** agar refresh token diterbitkan |
|
|
73
|
+
| Device flow | aktifkan bila ingin `login --device` |
|
|
74
|
+
| Request user authorization during installation | opsional |
|
|
75
|
+
|
|
76
|
+
Catat **App ID**, **Client ID**, dan buat **Client Secret** + **Private Key**
|
|
77
|
+
(`.pem`). Client ID bukan rahasia; Client Secret dan Private Key hanya boleh ada
|
|
78
|
+
di server.
|
|
79
|
+
|
|
80
|
+
### Permission minimum
|
|
81
|
+
|
|
82
|
+
| Permission | Level | Dipakai untuk |
|
|
83
|
+
| --- | --- | --- |
|
|
84
|
+
| Metadata | Read | Wajib untuk semua akses repository |
|
|
85
|
+
| Contents | Read | File, branch, commit, release |
|
|
86
|
+
| Contents | Write | Buat/ubah/hapus file, buat release |
|
|
87
|
+
| Issues | Read & Write | Issue dan komentar |
|
|
88
|
+
| Pull requests | Read & Write | PR, review, merge |
|
|
89
|
+
| Actions | Read | Workflow dan workflow run |
|
|
90
|
+
| Actions | Write | Menjalankan ulang workflow |
|
|
91
|
+
| Administration | Write | Membuat/mengubah repository |
|
|
92
|
+
|
|
93
|
+
Tidak meminta permission yang tidak dipakai (Secrets, Checks, Statuses,
|
|
94
|
+
Workflows, Packages, dll). Tidak ada tool penghapusan repository.
|
|
95
|
+
|
|
96
|
+
### Event webhook
|
|
97
|
+
|
|
98
|
+
Pilih minimal: **Push**, **Issues**, **Issue comment**, **Pull request**,
|
|
99
|
+
**Pull request review**, **Release**, **Installation**,
|
|
100
|
+
**Installation repositories**, **GitHub App authorization**.
|
|
101
|
+
|
|
102
|
+
### Instalasi
|
|
103
|
+
|
|
104
|
+
Setelah App dibuat, klik **Install App** dan pilih akun/organisasi serta
|
|
105
|
+
repository yang boleh diakses. Login saja tidak memberi akses ke seluruh
|
|
106
|
+
repository: akses adalah irisan antara permission App, persetujuan pengguna,
|
|
107
|
+
dan repository yang tercakup instalasi.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 4. Konfigurasi backend
|
|
112
|
+
|
|
113
|
+
Default file: `~/.config/ryuu/github/server.json` (Linux:
|
|
114
|
+
`$XDG_CONFIG_HOME`/`~/.config`; macOS: `~/Library/Application Support`;
|
|
115
|
+
Windows: `%APPDATA%`). Override: `RYUU_GITHUB_CONFIG=/path/server.json`.
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"appId": "<App ID>",
|
|
120
|
+
"clientId": "<Client ID>",
|
|
121
|
+
"clientSecret": "<Client Secret>",
|
|
122
|
+
"privateKeyPath": "/path/ryuu-cli.private-key.pem",
|
|
123
|
+
"webhookSecret": "<Webhook Secret>",
|
|
124
|
+
"redirectUri": "https://<domain>/integrations/github/callback",
|
|
125
|
+
"webhookUrl": "https://<domain>/webhooks/github",
|
|
126
|
+
"apiVersion": "2022-11-28"
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Field wajib: `appId`, `clientId`, `clientSecret`, `privateKeyPath`,
|
|
131
|
+
`webhookSecret`, `redirectUri`, `webhookUrl`. `apiVersion` default
|
|
132
|
+
`2022-11-28` (versi REST GitHub yang didukung implementasi ini).
|
|
133
|
+
|
|
134
|
+
Permission yang disarankan:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
chmod 700 ~/.config/ryuu/github
|
|
138
|
+
chmod 600 ~/.config/ryuu/github/server.json
|
|
139
|
+
chmod 600 /path/ryuu-cli.private-key.pem
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Kunci enkripsi token berada di `~/.config/ryuu/github/.keys/tokens.key` (0600)
|
|
143
|
+
atau dari `RYUU_GITHUB_TOKEN_KEY` (hex 64 karakter / base64 32 byte). Kunci tidak
|
|
144
|
+
boleh disimpan bersama file data token.
|
|
145
|
+
|
|
146
|
+
Backend membaca ulang konfigurasi saat mtime berubah; rotasi credential tidak
|
|
147
|
+
memerlukan restart. Jika field belum lengkap, endpoint menjawab HTTP 503 dengan
|
|
148
|
+
**nama field** yang belum diisi — bukan nilainya.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 5. Konfigurasi CLI
|
|
153
|
+
|
|
154
|
+
CLI hanya menyimpan pengaturan non-rahasia:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
<config>/integrations/github/config.json (0600)
|
|
158
|
+
<config>/integrations/github/state.json (0600)
|
|
159
|
+
<config>/integrations/github/credentials.enc (0600, cliToken terenkripsi)
|
|
160
|
+
<config>/.keys/github.key (0600)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Key yang dapat diubah:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
ryuu /github config set enabled true
|
|
167
|
+
ryuu /github config set confirmDestructive false
|
|
168
|
+
ryuu /github config set defaultRepo ryuu-reinzz/ryuu-cli
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`clientId` boleh tampil (publik). `clientSecret`, `privateKeyPath`,
|
|
172
|
+
`webhookSecret`, `accessToken`, `refreshToken`, dan `cliToken` tidak dapat
|
|
173
|
+
diubah dari CLI.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 6. Login
|
|
178
|
+
|
|
179
|
+
### Browser (utama)
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
ryuu /github login
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Alur:
|
|
186
|
+
|
|
187
|
+
1. CLI meminta backend membuat sesi sementara (`sessionId`, `pairingSecret`,
|
|
188
|
+
`state`, PKCE challenge, URL otorisasi).
|
|
189
|
+
2. Browser dibuka. Jika tidak ada browser, URL dicetak untuk dibuka manual.
|
|
190
|
+
3. Pengguna menyetujui akses di GitHub.
|
|
191
|
+
4. GitHub mengarahkan ke `/integrations/github/callback`.
|
|
192
|
+
5. Backend memvalidasi `state`, menukar `code` (client secret + PKCE verifier),
|
|
193
|
+
mengambil `GET /user`, dan menyimpan token terenkripsi.
|
|
194
|
+
6. Backend menerbitkan `cliToken` per akun dan menandai sesi `authorized`.
|
|
195
|
+
7. CLI polling dengan `pairingSecret`, menerima hasil **sekali**, lalu sesi
|
|
196
|
+
dihapus. Sesi kedaluwarsa setelah 10 menit.
|
|
197
|
+
|
|
198
|
+
Login otomatis mengaktifkan integrasi dan mendaftarkan tool pada sesi berjalan.
|
|
199
|
+
|
|
200
|
+
### Device flow (headless)
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
ryuu /github login --device
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
CLI menampilkan `verification_uri` dan `user_code`, lalu benar-benar melakukan
|
|
207
|
+
polling sampai GitHub menyelesaikan otorisasi (bukan hanya menampilkan kode).
|
|
208
|
+
Device flow harus diaktifkan pada pengaturan GitHub App.
|
|
209
|
+
|
|
210
|
+
Catatan PKCE: challenge dan verifier dikirim pada flow browser. GitHub belum
|
|
211
|
+
mendokumentasikan dukungan PKCE untuk OAuth App, sehingga jaminan utama adalah
|
|
212
|
+
`state` acak sekali pakai + Client Secret yang hanya ada di server. Dokumentasi
|
|
213
|
+
ini tidak mengklaim PKCE diverifikasi oleh GitHub.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## 7. Status, akun, dan test
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
ryuu /github status
|
|
221
|
+
ryuu /github account
|
|
222
|
+
ryuu /github test
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
`status` menampilkan status integrasi, login, enable/disable, respons backend,
|
|
226
|
+
masa berlaku access token, ketersediaan refresh token, jumlah instalasi, dan
|
|
227
|
+
lokasi file konfigurasi. Tidak ada token yang dicetak.
|
|
228
|
+
|
|
229
|
+
`account` menampilkan username, nama, tipe akun, URL profil, avatar, scope, dan
|
|
230
|
+
status autentikasi.
|
|
231
|
+
|
|
232
|
+
`test` memeriksa konfigurasi, sesi CLI, respons backend, `GET /user`, instalasi,
|
|
233
|
+
rate limit, App JWT/private key, dan status token. **Tidak** membuat, mengubah,
|
|
234
|
+
atau menghapus repository.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 8. Enable dan disable
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
ryuu /github enable
|
|
242
|
+
ryuu /github disable
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
- `enable` mendaftarkan tool ke registry agent. Konfigurasi dan sesi harus valid.
|
|
246
|
+
- `disable` hanya melepas tool. Akun, token, dan instalasi GitHub App tetap ada.
|
|
247
|
+
- Tool memeriksa ulang status saat eksekusi, jadi model yang memegang daftar tool
|
|
248
|
+
lama tidak bisa bertindak setelah disable.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## 9. Logout dan disconnect
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
ryuu /github logout
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Logout:
|
|
259
|
+
|
|
260
|
+
1. Meminta backend mencabut token (`DELETE /applications/{client_id}/token`).
|
|
261
|
+
2. Menghapus `cliToken` lokal dan kunci enkripsi CLI.
|
|
262
|
+
3. Menonaktifkan integrasi.
|
|
263
|
+
4. Tidak menghapus repository, issue, release, atau instalasi GitHub App.
|
|
264
|
+
|
|
265
|
+
Jika backend tidak dapat dihubungi, kredensial lokal tetap dihapus dan CLI
|
|
266
|
+
memberi tahu bahwa token di server mungkin masih tersimpan. Untuk memutus
|
|
267
|
+
instalasi sepenuhnya, lakukan dari **GitHub → Settings → Applications** atau
|
|
268
|
+
halaman instalasi App.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 10. Tools
|
|
273
|
+
|
|
274
|
+
| Kelompok | Tool |
|
|
275
|
+
| --- | --- |
|
|
276
|
+
| Akun | `github_get_me`, `github_get_user`, `github_get_rate_limit` |
|
|
277
|
+
| Repository | `github_list_repositories`, `github_get_repository`, `github_create_repository`, `github_update_repository`, `github_delete_repository`, `github_list_branches`, `github_get_branch`, `github_list_commits`, `github_get_commit`, `github_get_file_contents`, `github_create_or_update_file`, `github_delete_file`, `github_compare_commits` |
|
|
278
|
+
| Issue | `github_list_issues`, `github_get_issue`, `github_create_issue`, `github_update_issue`, `github_comment_issue`, `github_list_issue_comments` |
|
|
279
|
+
| Pull request | `github_list_pull_requests`, `github_get_pull_request`, `github_create_pull_request`, `github_update_pull_request`, `github_merge_pull_request`, `github_list_pull_request_files`, `github_review_pull_request` |
|
|
280
|
+
| Release | `github_list_releases`, `github_get_release`, `github_create_release` |
|
|
281
|
+
| Actions | `github_list_workflows`, `github_list_workflow_runs`, `github_get_workflow_run`, `github_rerun_workflow` |
|
|
282
|
+
|
|
283
|
+
Setiap tool memiliki schema input yang divalidasi registry, pemeriksaan
|
|
284
|
+
autentikasi, pembatasan output, dan deskripsi permission yang dibutuhkan.
|
|
285
|
+
|
|
286
|
+
Operasi yang mengubah data selalu melewati approval Ryuu:
|
|
287
|
+
|
|
288
|
+
- membuat/mengubah repository;
|
|
289
|
+
- menghapus repository;
|
|
290
|
+
- membuat/mengubah/menghapus file;
|
|
291
|
+
- membuat/mengubah issue dan komentar;
|
|
292
|
+
- membuat/mengubah/merge pull request dan review;
|
|
293
|
+
- membuat release;
|
|
294
|
+
- menjalankan ulang workflow.
|
|
295
|
+
|
|
296
|
+
`github_delete_file`, `github_merge_pull_request`, dan `github_delete_repository`
|
|
297
|
+
berisiko `destructive`. `confirmDestructive: false` memblokirnya sepenuhnya.
|
|
298
|
+
|
|
299
|
+
`github_delete_repository` adalah satu-satunya tool yang menghapus repository.
|
|
300
|
+
Selain approval Ryuu, handler-nya menuntut argumen `confirm` berisi
|
|
301
|
+
`owner/repo` yang sama persis, sehingga model tidak bisa menghapus repository
|
|
302
|
+
tanpa token konfirmasi eksplisit dari pengguna:
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## 11. Token kedaluwarsa dan refresh
|
|
307
|
+
|
|
308
|
+
GitHub App dapat menerbitkan access token yang kedaluwarsa (default 8 jam) dan
|
|
309
|
+
refresh token (default 6 bulan) bila opsi expire user authorization tokens
|
|
310
|
+
aktif. Jangan mengasumsikan durasi: backend memakai `expires_in` dan
|
|
311
|
+
`refresh_token_expires_in` dari respons aktual.
|
|
312
|
+
|
|
313
|
+
- Backend me-refresh otomatis bila access token tinggal ≤ 5 menit.
|
|
314
|
+
- Refresh memakai single-flight per akun, sehingga request paralel tidak
|
|
315
|
+
melakukan dua rotasi refresh token.
|
|
316
|
+
- Refresh token yang dirotasi disimpan; jika GitHub tidak mengirim yang baru,
|
|
317
|
+
token lama dipertahankan.
|
|
318
|
+
- `invalid_grant`/`bad_refresh_token` menandai akun `needsReconnect`; pengguna
|
|
319
|
+
diminta `/github login` lagi.
|
|
320
|
+
- Bila token tidak punya expiry (opsi expire dimatikan), token dipakai tanpa
|
|
321
|
+
refresh dan status menampilkan “tanpa masa berlaku”.
|
|
322
|
+
|
|
323
|
+
Perintah manual:
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
ryuu /github test
|
|
327
|
+
ryuu /github status
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
`/github test` melakukan pemeriksaan; refresh paksa tersedia di endpoint backend
|
|
331
|
+
`POST /integrations/github/refresh` (dipakai untuk diagnostik).
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## 12. Mengganti credential
|
|
336
|
+
|
|
337
|
+
1. **Client Secret baru**: buat di GitHub App settings, lalu perbarui
|
|
338
|
+
`clientSecret` di `server.json`. File dibaca ulang otomatis (mtime).
|
|
339
|
+
2. **Private Key baru**: generate, simpan dengan mode 0600, perbarui
|
|
340
|
+
`privateKeyPath`, lalu hapus key lama.
|
|
341
|
+
3. **Webhook Secret baru**: perbarui di GitHub dan `server.json`; delivery lama
|
|
342
|
+
yang belum diproses akan ditolak jika signature-nya memakai secret lama.
|
|
343
|
+
4. **Client ID/App ID berubah**: perbarui `clientId`/`appId`, lalu login ulang.
|
|
344
|
+
5. **Mengganti akun pengguna**: `/github logout`, lalu `/github login`.
|
|
345
|
+
|
|
346
|
+
Tidak ada perubahan source code yang diperlukan. Jangan menaruh nilai rahasia di
|
|
347
|
+
dokumentasi, issue, commit, atau log.
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## 13. Webhook
|
|
352
|
+
|
|
353
|
+
Endpoint: `POST /webhooks/github` (dipasang sebelum parser JSON global).
|
|
354
|
+
|
|
355
|
+
- Signature `X-Hub-Signature-256` (HMAC SHA-256, constant-time) wajib valid.
|
|
356
|
+
- `X-GitHub-Event` dan `X-GitHub-Delivery` divalidasi.
|
|
357
|
+
- Delivery duplikat diabaikan (`202 { duplicate: true }`).
|
|
358
|
+
- Event diproses asynchronous; respons `202` dikirim lebih dulu.
|
|
359
|
+
- Event yang didukung: `push`, `issues`, `issue_comment`, `pull_request`,
|
|
360
|
+
`pull_request_review`, `release`, `installation`,
|
|
361
|
+
`installation_repositories`, `github_app_authorization`.
|
|
362
|
+
- Handler hanya mencatat dan memperbarui data instalasi. Tidak ada aksi otomatis
|
|
363
|
+
yang mengubah repository.
|
|
364
|
+
- Payload dicatat dalam bentuk ter-redaksi.
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## 14. Batasan akses
|
|
369
|
+
|
|
370
|
+
- Login GitHub **tidak** berarti akses ke seluruh repository. Akses adalah
|
|
371
|
+
irisan permission App, persetujuan pengguna, dan repository yang tercakup
|
|
372
|
+
instalasi.
|
|
373
|
+
- Repository privat hanya terlihat bila instalasi mencakupnya.
|
|
374
|
+
- Organisasi dapat membatasi atau meninjau instalasi; administrator organisasi
|
|
375
|
+
mungkin perlu menyetujui.
|
|
376
|
+
- Endpoint tertentu memerlukan permission tambahan (mis. Administration write
|
|
377
|
+
untuk membuat repository).
|
|
378
|
+
- GitHub REST rate limit tetap berlaku; gunakan `github_get_rate_limit`.
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## 15. Catatan keamanan
|
|
383
|
+
|
|
384
|
+
- Client Secret, Private Key, dan Webhook Secret hanya ada di backend.
|
|
385
|
+
- Token pengguna disimpan terenkripsi (AES-256-GCM); kunci terpisah dari data.
|
|
386
|
+
- `cliToken` disimpan sebagai hash SHA-256, maksimal 5 per akun, dan memiliki
|
|
387
|
+
masa berlaku (default 30 hari).
|
|
388
|
+
- `pairingSecret` hanya dikembalikan ke CLI pembuat sesi dan dibandingkan
|
|
389
|
+
constant-time; sesi berumur 10 menit dan hasil login hanya bisa diambil sekali.
|
|
390
|
+
- Proxy API memakai safelist method+path; CLI tidak bisa memanggil endpoint
|
|
391
|
+
sembarang.
|
|
392
|
+
- Log tidak memuat Authorization header, token, atau secret.
|
|
393
|
+
- Approval Ryuu tidak bisa dilewati oleh tool; `confirmDestructive=false`
|
|
394
|
+
menambahkan lapisan blokir di handler.
|
|
395
|
+
- File rahasia dan data runtime tidak masuk Git (`lib/github/data/`, `.pem`,
|
|
396
|
+
`.env`, kunci).
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## 16. Testing lokal
|
|
401
|
+
|
|
402
|
+
Backend:
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
cd /root/website/api
|
|
406
|
+
npm test
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
CLI:
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
cd /root/agents/ryuu
|
|
413
|
+
node --test tests/unit/github.test.js tests/integration/github.test.js
|
|
414
|
+
npm run check
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Test memakai mock `fetch`/server lokal. **Jangan** menguji konektivitas domain
|
|
418
|
+
`restapi.ryuu-dev.my.id` dari VPS LXC: domain dan jaringan dikelola VPS induk.
|
|
419
|
+
Pengujian callback/webhook dari perangkat eksternal dapat dilakukan dengan:
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
curl -i "https://restapi.ryuu-dev.my.id/integrations/github/callback?state=invalid"
|
|
423
|
+
# harapan: 404 + halaman HTML "sesi tidak ditemukan", bukan error 500
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## 17. Troubleshooting
|
|
429
|
+
|
|
430
|
+
| Gejala | Penyebab umum | Tindakan |
|
|
431
|
+
| --- | --- | --- |
|
|
432
|
+
| 503 konfigurasi belum lengkap | `server.json` belum diisi | Isi field yang disebut pada pesan |
|
|
433
|
+
| `invalid_client` saat callback | Client Secret salah/berputar | Perbarui `clientSecret`, login ulang |
|
|
434
|
+
| `redirect_uri` mismatch | Callback URL di GitHub berbeda | Samakan `redirectUri` di App dan `server.json` |
|
|
435
|
+
| 401 signature webhook | Webhook Secret berbeda | Samakan secret di GitHub dan backend |
|
|
436
|
+
| 403 akses repository | Instalasi tidak mencakup repo | Instal/ubah akses App |
|
|
437
|
+
| Tool tidak muncul | Belum login atau disable | `/github login`, `/github enable` |
|
|
438
|
+
| Token perlu login ulang | Refresh token dicabut/kedaluwarsa | `/github login` |
|
|
439
|
+
| Rate limit | Kuota GitHub habis | Tunggu reset, cek `/github test` |
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## 18. Struktur file
|
|
444
|
+
|
|
445
|
+
```
|
|
446
|
+
/root/website/api/
|
|
447
|
+
├── index.js # memasang webhook + router
|
|
448
|
+
├── lib/github/
|
|
449
|
+
│ ├── index.js # factory integrasi
|
|
450
|
+
│ ├── config.js # konfigurasi server + validasi
|
|
451
|
+
│ ├── data/ # hanya jika diarahkan ke repo (di-ignore)
|
|
452
|
+
│ ├── encryption.js # AES-256-GCM + kunci terpisah
|
|
453
|
+
│ ├── store.js # atomic write + lock
|
|
454
|
+
│ ├── token-storage.js # record per akun + cliToken hash
|
|
455
|
+
│ ├── session.js # sesi login sementara
|
|
456
|
+
│ ├── oauth.js # PKCE, exchange, refresh, device flow
|
|
457
|
+
│ ├── app-token.js # App JWT + installation token
|
|
458
|
+
│ ├── token-manager.js # auto-refresh single-flight
|
|
459
|
+
│ ├── api.js # GitHub REST client
|
|
460
|
+
│ ├── signature.js # verifikasi webhook
|
|
461
|
+
│ ├── webhook.js # handler + dedupe + antrean
|
|
462
|
+
│ ├── router.js # endpoint + proxy
|
|
463
|
+
│ └── README.md
|
|
464
|
+
└── tests/github/ # 48 test lokal
|
|
465
|
+
|
|
466
|
+
/root/agents/ryuu/
|
|
467
|
+
├── plugins/github/ # plugin CLI
|
|
468
|
+
├── docs/github.md # dokumen ini
|
|
469
|
+
└── tests/{unit,integration}/github.test.js
|
|
470
|
+
```
|
package/package.json
CHANGED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Plugin GitHub — Ryuu CLI
|
|
2
|
+
|
|
3
|
+
Integrasi GitHub untuk agent Ryuu: akun, repository, file, issue, pull request,
|
|
4
|
+
release, dan GitHub Actions. Plugin ini mengikuti pola `plugins/google-drive/`
|
|
5
|
+
dan **tidak memegang kredensial GitHub rahasia apa pun**.
|
|
6
|
+
|
|
7
|
+
## Arsitektur singkat
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
ryuu /github login
|
|
11
|
+
│ POST /integrations/github/connect (sesi + URL)
|
|
12
|
+
▼
|
|
13
|
+
Backend Ryuu (Integration Gateway) ──HTTPS──▶ github.com / api.github.com
|
|
14
|
+
│ Client Secret, Private Key, Webhook Secret, token pengguna
|
|
15
|
+
│
|
|
16
|
+
└─ menerbitkan cliToken per akun
|
|
17
|
+
CLI menyimpan cliToken terenkripsi, lalu semua tools lewat backend.
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- **Backend** memiliki Client Secret, Private Key, Webhook Secret, access token,
|
|
21
|
+
dan refresh token.
|
|
22
|
+
- **CLI** hanya memiliki Client ID publik (boleh tampil), `cliToken` per akun
|
|
23
|
+
(AES-256-GCM di disk), dan cache identitas akun.
|
|
24
|
+
- Tools tidak pernah menerima access token GitHub; backend memasangnya saat
|
|
25
|
+
meneruskan request ke `api.github.com`.
|
|
26
|
+
|
|
27
|
+
## Struktur modul
|
|
28
|
+
|
|
29
|
+
| File | Tanggung jawab |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| `index.js` | Deskriptor plugin untuk host |
|
|
32
|
+
| `manager.js` | Lifecycle: login, logout, status, enable/disable, test |
|
|
33
|
+
| `config.js` | Konfigurasi non-rahasia + path OS + state cache |
|
|
34
|
+
| `credentials.js` | Penyimpanan `cliToken` terenkripsi |
|
|
35
|
+
| `auth.js` | Membuka browser + pesan kegagalan login |
|
|
36
|
+
| `backend.js` | HTTP client ke backend (connect, session, status, proxy) |
|
|
37
|
+
| `api.js` | Klien GitHub REST melalui gateway + pagination |
|
|
38
|
+
| `tools*.js` | 36 tool AI, dikelompokkan per domain |
|
|
39
|
+
| `tool-helpers.js` | Validasi owner/repo/ref/path + pembatasan output |
|
|
40
|
+
| `errors.js` | Error plugin + kode yang stabil |
|
|
41
|
+
| `command.js` | Handler `/github` |
|
|
42
|
+
|
|
43
|
+
## Konfigurasi lokal
|
|
44
|
+
|
|
45
|
+
Mengikuti direktori konfigurasi OS lewat `settingsDir()`:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
<config>/integrations/github/config.json (0600, non-rahasia)
|
|
49
|
+
<config>/integrations/github/state.json (0600, cache status)
|
|
50
|
+
<config>/integrations/github/credentials.enc (0600, cliToken terenkripsi)
|
|
51
|
+
<config>/.keys/github.key (0600, kunci enkripsi CLI)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Linux memakai `$XDG_CONFIG_HOME` atau `~/.config`, macOS memakai
|
|
55
|
+
`~/Library/Application Support`, Windows memakai `%APPDATA%`.
|
|
56
|
+
|
|
57
|
+
Key yang dapat diubah:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
/github config set enabled true|false
|
|
61
|
+
/github config set autoRefresh true|false
|
|
62
|
+
/github config set confirmDestructive true|false
|
|
63
|
+
/github config set defaultRepo owner/repo
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Client Secret, Private Key, Webhook Secret, endpoint backend, dan token tidak
|
|
67
|
+
dapat diubah dari CLI dan tidak pernah ditulis ke file konfigurasi.
|
|
68
|
+
|
|
69
|
+
## Command
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
/github login login lewat browser (utama)
|
|
73
|
+
/github login --device device flow untuk mesin headless
|
|
74
|
+
/github logout putuskan akun + hapus kredensial lokal
|
|
75
|
+
/github status status integrasi, akun, token, backend
|
|
76
|
+
/github account identitas akun GitHub terhubung
|
|
77
|
+
/github test diagnostik aman (tanpa mengubah repository)
|
|
78
|
+
/github enable daftarkan tool ke agent
|
|
79
|
+
/github disable lepas tool (akun/token tetap)
|
|
80
|
+
/github config tampilkan konfigurasi non-rahasia
|
|
81
|
+
/github config set ... ubah satu key
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`/github status`, `/github account`, dan `/github config` tidak pernah
|
|
85
|
+
menampilkan Client Secret, Private Key, Webhook Secret, access token, refresh
|
|
86
|
+
token, atau `cliToken`.
|
|
87
|
+
|
|
88
|
+
## Tool yang tersedia (36)
|
|
89
|
+
|
|
90
|
+
**Akun (3)** — `github_get_me`, `github_get_user`, `github_get_rate_limit`
|
|
91
|
+
|
|
92
|
+
**Repository (13)** — `github_list_repositories`, `github_get_repository`,
|
|
93
|
+
`github_create_repository`, `github_update_repository`,
|
|
94
|
+
`github_delete_repository`, `github_list_branches`,
|
|
95
|
+
`github_get_branch`, `github_list_commits`, `github_get_commit`,
|
|
96
|
+
`github_get_file_contents`, `github_create_or_update_file`,
|
|
97
|
+
`github_delete_file`, `github_compare_commits`
|
|
98
|
+
|
|
99
|
+
**Issue (6)** — `github_list_issues`, `github_get_issue`,
|
|
100
|
+
`github_create_issue`, `github_update_issue`, `github_comment_issue`,
|
|
101
|
+
`github_list_issue_comments`
|
|
102
|
+
|
|
103
|
+
**Pull request (7)** — `github_list_pull_requests`, `github_get_pull_request`,
|
|
104
|
+
`github_create_pull_request`, `github_update_pull_request`,
|
|
105
|
+
`github_merge_pull_request`, `github_list_pull_request_files`,
|
|
106
|
+
`github_review_pull_request`
|
|
107
|
+
|
|
108
|
+
**Release (3)** — `github_list_releases`, `github_get_release`,
|
|
109
|
+
`github_create_release`
|
|
110
|
+
|
|
111
|
+
**GitHub Actions (4)** — `github_list_workflows`,
|
|
112
|
+
`github_list_workflow_runs`, `github_get_workflow_run`,
|
|
113
|
+
`github_rerun_workflow`
|
|
114
|
+
|
|
115
|
+
`github_delete_repository` menghapus repository secara permanen dan hanya
|
|
116
|
+
berjalan bila argumen `confirm` berisi `owner/repo` yang sama persis; proxy
|
|
117
|
+
backend baru mengizinkannya lewat safelist `DELETE /repos/{owner}/{repo}`.
|
|
118
|
+
Penghapusan repository, penghapusan file, dan merge pull request berisiko
|
|
119
|
+
`destructive` dan selalu melewati approval Ryuu.
|
|
120
|
+
|
|
121
|
+
## Approval & keamanan
|
|
122
|
+
|
|
123
|
+
- `risk: read` berjalan tanpa prompt.
|
|
124
|
+
- Semua tool `write` memakai `requiresApproval: true`.
|
|
125
|
+
- `github_delete_file`, `github_merge_pull_request`, dan
|
|
126
|
+
`github_delete_repository` memakai
|
|
127
|
+
`risk: destructive` (approval wajib).
|
|
128
|
+
- `github_delete_repository` menuntut `confirm` = `owner/repo`; nilai lain
|
|
129
|
+
ditolak sebagai `VALIDATION_FAILED` sebelum request dibuat.
|
|
130
|
+
- `confirmDestructive: false` memblokir operasi destruktif di handler, bukan
|
|
131
|
+
hanya mengandalkan prompt.
|
|
132
|
+
- Tool memanggil `plugin.requireClient()` setiap kali, sehingga model yang
|
|
133
|
+
memegang daftar tool lama tidak bisa bertindak setelah `/github disable`.
|
|
134
|
+
- Output dibatasi: list dipotong, body panjang diringkas, isi file > 200 KB
|
|
135
|
+
hanya metadata.
|
|
136
|
+
|
|
137
|
+
## Testing
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
cd /root/agents/ryuu
|
|
141
|
+
node --test tests/unit/github.test.js tests/integration/github.test.js
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Test memakai mock backend lokal. Tidak ada koneksi ke domain produksi dan tidak
|
|
145
|
+
ada perubahan data GitHub nyata.
|
|
146
|
+
|
|
147
|
+
## Troubleshooting
|
|
148
|
+
|
|
149
|
+
| Gejala | Tindakan |
|
|
150
|
+
| --- | --- |
|
|
151
|
+
| `Belum ada akun GitHub yang terhubung` | `/github login` |
|
|
152
|
+
| `Integrasi GitHub sedang nonaktif` | `/github enable` |
|
|
153
|
+
| `Sesi CLI sudah berakhir` | `/github login` lagi |
|
|
154
|
+
| `Akses ditolak` pada repository privat | Pastikan GitHub App diinstal ke akun/organisasi dan repository itu dipilih |
|
|
155
|
+
| `Rate limit` | Tunggu reset; cek `/github test` |
|
|
156
|
+
| `confirmDestructive=false` | `/github config set confirmDestructive true` |
|
|
157
|
+
|
|
158
|
+
Dokumentasi lengkap: [`../../docs/github.md`](../../docs/github.md).
|