Production-grade backend for Maintainer Brief - AI-powered GitHub repository analysis.
- 🔐 Secure authentication via Supabase Auth
- 🔗 Read-only GitHub integration
- 🤖 AI-powered analysis (4 output types)
- 📊 Job queue with progress tracking
- 📅 Automated scheduling (weekly/biweekly)
- 📧 Email & Slack notifications
- 📤 Export to Markdown/PDF
- 🛡️ Rate limiting & encryption
- ♻️ Idempotency & retries
- Runtime: Node.js + TypeScript
- Framework: Fastify
- Database: PostgreSQL (Supabase)
- Auth: Supabase Auth (JWT)
- Queue: BullMQ + Redis
- AI: OpenAI API
- GitHub: Octokit (REST API)
- Node.js 18+
- PostgreSQL (via Supabase)
- Redis
- OpenAI API key
- GitHub OAuth App
cd maintainer-brief-backend
npm installCopy .env.example to .env and fill in your credentials:
cp .env.example .envRequired values:
SUPABASE_URL,SUPABASE_ANON_KEY,SUPABASE_SERVICE_ROLE_KEYDATABASE_URL(Supabase Postgres connection string)REDIS_URLOPENAI_API_KEYGITHUB_CLIENT_ID,GITHUB_CLIENT_SECRETENCRYPTION_KEY(generate with:openssl rand -hex 32)
Run migrations to create all tables:
npm run build
npm run migrateThis creates:
users(Supabase auth integration)github_accounts(OAuth tokens, encrypted)repos(connected repositories)repo_settings(per-repo configuration)analysis_jobs(job queue & status)analysis_outputs(AI-generated content)export_requests(export jobs)
Development mode (with hot reload):
npm run devProduction mode:
npm run build
npm startWorker process (for job processing):
npm run workerScheduler (for automated runs):
npm run schedulerHealth check:
curl http://localhost:3000/healthExpected response:
{
"status": "ok",
"timestamp": "2025-12-16T...",
"redis": "connected",
"database": "connected"
}All endpoints (except /health) require authentication via Supabase JWT in the Authorization header:
Authorization: Bearer <supabase-jwt-token>
GET /health
- No auth required
- Returns system status
POST /github/connect
{
"code": "github-oauth-code"
}- Exchanges OAuth code for access token
- Stores encrypted token
- Returns github_account record
GET /github/repos
- Lists all repos user has access to on GitHub
- Use to populate repo selection UI
POST /repos
{
"full_name": "owner/repo",
"github_repo_id": "123456",
"default_branch": "main",
"is_private": false
}- Connects a repo for analysis
- Creates default settings
GET /repos
- Lists user's connected repos
- Includes last_analyzed timestamp & status
GET /repos/:repoId
- Detailed repo info + settings + last job
PATCH /repos/:repoId/settings
{
"branch": "main",
"analysis_depth": "deep",
"output_tone": "detailed",
"ignore_paths": ["node_modules/**", "dist/**"],
"schedule": "weekly",
"notify_email": true,
"notify_slack": false
}POST /repos/:repoId/analyze
- Triggers manual analysis
- Returns job ID
- Idempotent (checks for recent runs)
GET /jobs/:jobId
{
"id": "uuid",
"status": "running",
"progress": 60,
"started_at": "...",
"error_message": null
}GET /repos/:repoId/jobs
- Lists recent jobs for a repo
GET /repos/:repoId/outputs/latest
- Returns latest outputs for all 4 types:
maintainer_briefcontributor_quickstartrelease_summarygood_first_issues
GET /outputs/:outputId
{
"id": "uuid",
"type": "maintainer_brief",
"content_markdown": "# Maintainer Brief\n...",
"confidence": 0.92,
"sources_json": {
"commits": ["sha1", "sha2"],
"prs": [123, 456],
"issues": [789]
},
"created_at": "..."
}POST /outputs/:outputId/export
{
"format": "markdown"
}- Supported formats:
markdown,pdf,github_release - Returns export_request ID
GET /exports/:exportId
{
"id": "uuid",
"status": "succeeded",
"file_url": "https://storage.../file.md"
}# After OAuth flow, exchange code for token
curl -X POST http://localhost:3000/github/connect \
-H "Authorization: Bearer $SUPABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"code": "github_oauth_code_here"}'curl http://localhost:3000/github/repos \
-H "Authorization: Bearer $SUPABASE_TOKEN"curl -X POST http://localhost:3000/repos \
-H "Authorization: Bearer $SUPABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"full_name": "facebook/react",
"github_repo_id": "10270250",
"default_branch": "main",
"is_private": false
}'curl -X POST http://localhost:3000/repos/$REPO_ID/analyze \
-H "Authorization: Bearer $SUPABASE_TOKEN"curl http://localhost:3000/jobs/$JOB_ID \
-H "Authorization: Bearer $SUPABASE_TOKEN"curl http://localhost:3000/repos/$REPO_ID/outputs/latest \
-H "Authorization: Bearer $SUPABASE_TOKEN"curl -X POST http://localhost:3000/outputs/$OUTPUT_ID/export \
-H "Authorization: Bearer $SUPABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"format": "markdown"}'src/
├── config/ # Environment validation & config
├── db/ # Database client & migrations
├── auth/ # Supabase JWT middleware
├── github/ # Octokit client & data fetchers
├── ai/ # OpenAI client & prompt builders
├── analysis/ # Pipeline orchestration
├── queue/ # BullMQ setup & worker
├── notifications/ # Email & Slack
├── scheduler/ # Cron jobs for automation
├── routes/ # Fastify route handlers
├── utils/ # Encryption, retry, rate-limit
└── server.ts # Main entry point
- ✅ All GitHub tokens encrypted at rest (AES-256-GCM)
- ✅ Supabase JWT verification on all protected routes
- ✅ Row-level ownership checks (users can only access their data)
- ✅ Input validation with Zod schemas
- ✅ Rate limiting (configurable per endpoint)
- ✅ No GitHub write operations (read-only)
- ✅ Secrets in environment variables only
Analysis jobs go through these stages:
- Queued (0%) - Job created, waiting for worker
- Fetching (25%) - Collecting GitHub data
- Generating (60%) - Running AI prompts
- Saving (85%) - Storing outputs
- Done (100%) - Job complete, notifications sent
To prevent duplicate work:
- Jobs generate a
github_snapshot_hashfrom: repo ID + branch + latest commit SHA + depth setting - If a job with the same hash succeeded within the last 24 hours, return that job instead
- Clients can safely retry
POST /repos/:repoId/analyze
Run tests:
npm testRun tests in watch mode:
npm test:watchTests cover:
- Auth middleware (JWT verification)
- Repo ownership checks
- Idempotency hashing
- Prompt output structure
- Rate limiting
- Create new project on Railway
- Add PostgreSQL + Redis services
- Connect GitHub repo
- Set environment variables
- Add start command:
npm run build && npm start - Deploy worker separately with:
npm run build && npm run worker - Deploy scheduler separately with:
npm run build && npm run scheduler
docker build -t maintainer-brief-backend .
docker run -p 3000:3000 --env-file .env maintainer-brief-backendKey metrics to monitor:
- Job success/failure rate
- Average job duration
- Queue depth
- API response times
- GitHub API rate limit remaining
- OpenAI token usage
- GitHub API: 5,000 requests/hour (authenticated)
- OpenAI API: Depends on your tier
- Our API: 100 requests/minute per user (configurable)
For issues or questions, contact: [email protected]
MIT