GitHub Integration — Setup Guide
Phase 49.3 (Light) — webhook-based notifications + UI sidebar feed for linked GitHub repos. Без bidirectional sync (це Phase 49.5+ Heavy).
ARC OS приймає webhook-події з прив'язаних GitHub repos і одночасно:
- Шле Telegram нотифікацію project owner'у
- Оновлює sidebar feed у Workspace ContextRail (polling 30s)
Архітектура
GitHub repo
│ (push / PR / CI / issue events)
▼
arc-os.co/api/webhooks/github
│ HMAC-SHA256 timing-safe verify (X-Hub-Signature-256)
│ Rate limit 100 req/min/project
│ Payload max 50KB
▼
shared/routes/github.ts handleGithubWebhook
├─→ DB: github_events (для UI feed)
└─→ shared/github-notifier.ts → Telegram (master bot token)
Підтримувані події: push, pull_request, workflow_run, issues. Решта (releases, deployments, discussions) ігноруються.
Multi-repo: один проект може link декілька repos (напр. frontend + backend + docs). Constraint: UNIQUE(project_name, owner, repo).
Швидкий setup (3 хвилини)
1. Згенеруй webhook URL+secret
arc github link <project-name> <owner/repo>
Приклад:
arc github link arc-v2 SerhiiInUa/citadel-v2
CLI поверне:
- Webhook URL —
https://arc-os.co/api/webhooks/github - Secret — 32-byte hex (унікальний на кожен link)
- Step-by-step instructions для GitHub UI
2. Додай webhook у GitHub repo
На сторінці https://github.com/<owner>/<repo>/settings/hooks:
- Натисни Add webhook
- Payload URL:
https://arc-os.co/api/webhooks/github - Content type:
application/json(важливо!) - Secret: встав значення з CLI output
- Which events? → "Let me select individual events":
- ☑ Pushes
- ☑ Pull requests
- ☑ Workflow runs
- ☑ Issues
- ☑ Active
- Натисни Add webhook
GitHub одразу шле тестовий ping event — він буде silently rejected (бо ARC очікує тільки supported types). Це нормально.
3. Перевір що працює
Зроби push у repo, або відкрий PR, або запусти workflow. Через ~1-3 секунди:
- Прийде Telegram нотифікація project owner'у з icon + summary + GitHub link
- Sidebar feed у Workspace ContextRail оновиться (через ~30s polling)
Управління links
Список прив'язаних repos
arc github links arc-v2
Видалити link
arc github unlink arc-v2 <id>
ID береться з arc github links output. Webhook на GitHub при цьому не видаляється автоматично — invalid signatures будуть silent reject. Кращий workflow: спочатку видали webhook у GitHub UI, потім arc github unlink.
Безпека
- HMAC-SHA256 signature — кожен webhook secret =
crypto.randomBytes(32).toString('hex')(256 біт ентропії) - Timing-safe compare —
node:crypto timingSafeEqualзапобігає timing attacks на signature verification - Silent reject — invalid signatures отримують
401 ""без body (no info leak до scanners) - Rate limit — 100 req/min per project (in-memory window). Перевищення →
429 Rate limited - Payload size limit — 50KB у handler, 64KB у nginx (захист від DoS)
- Multi-repo signature routing — handler шукає candidates за
repository.full_name, потім перевіряє signature кожного, перш ніж accept (запобігає secret reuse cross-project) - Public endpoint isolation — nginx config
/api/webhooks/githubмаєauth_basic offіproxy_read_timeout 5s
Що бачиш у sidebar
ContextRail (right panel у Workspace) показує секцію GitHub ⤵
- Auto-hidden якщо проект не має linked repos
- Останні 8 events (newest first)
- Per-event icon: GitBranch (push) / GitPullRequest (PR) / CircleCheck (CI success) / CircleAlert (CI failure) / CircleDot (issues)
- Relative time format: 30s, 5m, 2h, 1d
- Click row → opens GitHub URL у новій вкладці
- Polling кожні 30s (fresh data без manual refresh)
Telegram повідомлення
Master bot шле formatted message project owner'у:
🔀 [arc-v2] SerhiiInUa/citadel-v2
PR #42 opened: feat: add lazy worker lifecycle by @Sergei89
View on GitHub
Іконки:
- 📦 push
- 🔀 pull_request
- ✅ workflow_run (success)
- ❌ workflow_run (failure)
- ⚙️ workflow_run (other)
- 🐛 issues
Troubleshooting
Webhook returns 401 на тестовий ping
Очікувано — ARC silent rejects unsupported events (наприклад ping). Тільки production events (push, PR, workflow_run, issues) обробляються.
Webhook returns 401 на push event
- Перевір що в GitHub webhook налаштовано
Content type: application/json(неform-urlencoded) - Перевір secret — має точно збігатися з тим, що повернув
arc github link - Якщо secret загублено — видали link і створи знову (
arc github unlink→arc github link)
Sidebar feed пустий хоча Telegram приходить
- Перевір що ContextRail взагалі видно (≥1280px viewport)
- Hard refresh frontend (Ctrl+Shift+R) — компонент кешується
- Перевір DB:
sqlite3 data/citadel.db "SELECT COUNT(*) FROM github_events WHERE project_name='<name>';"
Telegram не приходить
- Перевір що project має
owner_idу DB:sqlite3 ... "SELECT name, owner_id FROM projects;" - Перевір master bot token у vault:
grep MASTER_BOT_TOKEN config/vault.json(повинен бути encrypted) - Webhook event у DB є, але notify failed → дивись master logs:
tmux capture-pane -t citadel-master -p | grep github-notifier
Rate limit hit
Hard limit 100 req/min/project. При CI з тисячами runners — підвищ у shared/routes/github.ts:RATE_MAX.
API endpoints
Детально: API Reference.
| Endpoint | Auth | Опис |
|---|---|---|
POST /api/crm/projects/:name/github |
JWT | Link repo |
GET /api/crm/projects/:name/github |
JWT | List links |
DELETE /api/crm/projects/:name/github/:id |
JWT | Unlink |
GET /api/crm/projects/:name/github/events?limit=N |
JWT | List events (max 200) |
POST /api/webhooks/github |
HMAC | Public receiver |
Roadmap
| Phase | Scope | Status |
|---|---|---|
| 49.3 | Webhook receiver + Telegram | ✅ DONE |
| 49.3.1 | UI sidebar feed | ✅ DONE |
| 49.4 | API polling, Workspace GitHub tab, multi-repo dashboard | BACKLOG (P2) |
| 49.5 | Bidirectional issue sync, auto-PR review workers | BACKLOG (P2) |