# HolonBot - Serverless GitHub App
A scalable, serverless GitHub App bot built with Probot and deployed on Vercel. The bot automates repository management tasks, handles pull requests, issues, and provides automated responses to repository events.
## Features
- **Pull Request Management**: Welcome messages, automated comments, and labeling
- **Issue Handling**: Auto-labeling based on content, welcome messages
- **Review Management**: Automatic labeling based on review states
- **Repository Setup**: Initial structure creation for new repositories
- **Serverless Deployment**: No server maintenance required with Vercel
- **Secure Configuration**: Environment variables for all sensitive data
## Architecture
```
holonbot/
├── api/
│ ├── github-webhook.js # Vercel serverless function (webhook handler)
│ └── exchange-token.js # Vercel serverless function (OIDC token exchange)
├── lib/
│ ├── bot-handler.js # Core bot logic
│ ├── oidc.js # OIDC token verification
│ └── probot-client.js # Shared Probot instance
├── package.json # Dependencies and scripts
├── vercel.json # Vercel configuration
└── README.md # This file
```
## Prerequisites
- Node.js 18+ (for local development)
- GitHub account with appropriate permissions
- Vercel account (for deployment)
- GitHub App credentials
## Setup Instructions
### 1. Create a GitHub App
1. Go to [GitHub Developer Settings](https://github.com/settings/apps)
2. Click "New GitHub App"
3. Configure the app:
- **App name**: `HolonBot` (or your preferred name)
- **Homepage URL**: Your project's homepage
- **Webhook URL**: `https://your-vercel-domain.vercel.app/api/github-webhook` (placeholder for now)
- **Webhook secret**: Generate a strong random string (save this!)
### 2. Configure App Permissions
Under **Repository permissions**, set:
| Issues | Read & Write | Create comments and add labels |
| Pull Requests | Read & Write | Create comments and manage PRs |
| Checks | Read & Write | Handle check runs |
| Metadata | Read | Access repository information |
| Contents | Write | Create initial repository files |
Under **Subscribe to events**, select:
- Pull requests
- Issues
- Pull request reviews
- Repository creation
- Check runs
### 3. Generate and Save App Credentials
1. Save the **App ID** (displayed in the app settings)
2. Generate a **Private Key** and download the `.pem` file
3. Save the **Webhook secret** you generated earlier
### 4. Install the App
1. Install the GitHub App on your target repositories
2. Note which repositories you want the bot to work on
## Local Development
### 1. Clone and Setup
```bash
git clone <your-repo-url>
cd holonbot
npm install
```
### 2. Environment Variables
Create a `.env` file with your GitHub App credentials:
```env
APP_ID=your_app_id_here
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n"
WEBHOOK_SECRET=your_webhook_secret_here
NODE_ENV=development
LOG_LEVEL=debug
HOLON_OIDC_AUDIENCE=holon-token-broker
```
### 3. Run Locally
```bash
npm run dev
```
The bot will start and be ready to receive webhook events. Use a tool like [ngrok](https://ngrok.com/) to expose your local server to GitHub during development.
```bash
ngrok http 3000
```
Update your GitHub App's webhook URL to use the ngrok URL.
## Deployment to Vercel
### 1. Install Vercel CLI
```bash
npm i -g vercel
```
### 2. Login to Vercel
```bash
vercel login
```
### 3. Deploy
```bash
vercel --prod
```
### 4. Configure Environment Variables in Vercel
Go to your Vercel project dashboard and add these environment variables:
```
APP_ID=your_app_id_here
PRIVATE_KEY=your_private_key_content_here
WEBHOOK_SECRET=your_webhook_secret_here
NODE_ENV=production
LOG_LEVEL=info
```
**Important**: For the `PRIVATE_KEY`, include the entire key content including the `-----BEGIN RSA PRIVATE KEY-----` and `-----END RSA PRIVATE KEY-----` lines, with `\n` characters for line breaks.
### 5. Update GitHub App Webhook URL
1. Go back to your GitHub App settings
2. Update the **Webhook URL** to: `https://your-vercel-domain.vercel.app/api/github-webhook`
3. Click "Save changes"
## OIDC Token Exchange Security Model
`api/exchange-token.js` is hardened for GitHub Actions OIDC to GitHub App installation token exchange.
- OIDC JWT verification enforces:
- signature via GitHub JWKS
- `iss` = `https://token.actions.githubusercontent.com`
- `aud` in configured audiences (`HOLON_OIDC_AUDIENCE`, default: `holon-token-broker`)
- standard JWT time checks (`exp`, `nbf`)
- Claim validation enforces repository binding:
- `repository` / `repository_owner` format and consistency
- `repository_id` present and numeric
- `sub` starts with `repo:<owner>/<repo>:`
- Token issuance is bound to the same repository:
- broker fetches repo and verifies `repository_id`
- installation token is scoped with `repository_ids: [repo.id]`
- Default policy requires actor collaborator/member check before issuing token.
- `job_workflow_ref` can be required and restricted by allowlist.
- Replay protection denies duplicate `jti`/`run_id` within a TTL window.
- Rate limiting throttles repeated requests by `(repository, actor)`.
- Installation token defaults to least privilege:
- `contents: write`
- `pull_requests: write`
### Security Configuration
Optional (defaults shown):
- `HOLON_OIDC_AUDIENCE=holon-token-broker` (comma-separated accepted OIDC audiences)
- `HOLON_REQUIRE_ACTOR_COLLABORATOR=true`
- `HOLON_MIN_ACTOR_PERMISSION=read`
- `HOLON_REQUIRE_JOB_WORKFLOW_REF=true`
- `HOLON_ALLOWED_WORKFLOW_REFS=` (comma-separated exact refs)
- `HOLON_REQUIRE_DEFAULT_BRANCH_REF=true`
- `HOLON_ALLOW_PULL_REQUEST_REF=true` (when default-branch enforcement is on, also allow `refs/pull/*/(merge|head)`)
- `HOLON_ENABLE_REPLAY_PROTECTION=true`
- `HOLON_REPLAY_WINDOW_SECONDS=3600`
- `HOLON_ENABLE_RATE_LIMIT=true`
- `HOLON_RATE_LIMIT_WINDOW_SECONDS=60`
- `HOLON_RATE_LIMIT_MAX_REQUESTS=10`
- `HOLON_INSTALLATION_PERMISSIONS_JSON=` (JSON object; default is `{"contents":"write","pull_requests":"write"}`)
## Bot Behavior
### Pull Request Events
- **Opened/Reopened**: Bot posts a welcome message with checklist
- **Review Submitted**:
- Approved: Adds `approved` label
- Changes Requested: Adds `changes-requested` label
### Issue Events
- **Opened**: Bot posts a welcome message
- **Auto-labeling**: Automatically adds labels based on content:
- `bug` - for bug reports
- `enhancement` - for feature requests
- `question` - for questions
### Repository Events
- **Created**: Sets up initial repository structure with README.md and .gitignore
## Monitoring and Logs
- **Vercel Logs**: Access real-time logs from your Vercel dashboard
- **GitHub App Logs**: Monitor webhook delivery status in GitHub App settings
- **Local Logs**: Use `LOG_LEVEL=debug` for detailed local development logs
## Security Considerations
- ✅ All secrets stored in environment variables
- ✅ Webhook signature verification enabled
- ✅ Minimal permissions requested
- ✅ No sensitive data in codebase
- ✅ HTTPS enforced by Vercel
## Troubleshooting
### Common Issues
1. **403 Forbidden**: Check GitHub App permissions and installation
2. **Webhook delivery failures**: Verify webhook URL and secret
3. **Environment variables missing**: Ensure all required variables are set in Vercel
4. **Function timeouts**: Check Vercel function logs and increase duration if needed
### Debug Commands
```bash
# Test webhook delivery
curl -X POST https://your-app.vercel.app/api/github-webhook \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: ping" \
-H "X-Hub-Signature-256: sha256=..." \
-d '{"zen": "Non-blocking is better than blocking."}'
```
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Test thoroughly
5. Submit a pull request
## License
MIT License - see LICENSE file for details.
## Support
For issues and questions:
1. Check the troubleshooting section above
2. Review Vercel function logs
3. Check GitHub App delivery logs
4. Open an issue in this repository
---
**Built with ❤️ using [Probot](https://probot.github.io/) and deployed on [Vercel](https://vercel.com/)**