Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Git
.git
.gitignore

# IDE
.idea
.vscode
*.swp
*.swo

# Environment files (secrets)
.env
*.pem

# Build artifacts
gitvigil
*.exe
*.dll
*.so
*.dylib

# Test files
*_test.go
coverage.out
coverage.html

# Documentation
*.md
!README.md
docs/

# Docker files (not needed in context)
docker-compose*.yml
Dockerfile*

# Misc
.DS_Store
Thumbs.db
tmp/
17 changes: 17 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
GITHUB_APP_CLIENT_SECRET=34f253c2285ebdb408e230950eeb2da6eecad40d
GITHUB_APP_ID=2765088
GITHUB_APP_CLIENT_ID=Iv23li9lM5FdeHqeNZ6o
GITHUB_WEBHOOK_SECRET=my_secret_token_123
GITHUB_PRIVATE_KEY_PATH=./git-vigil.2026-01-30.private-key.pem

# Database
DATABASE_URL=postgres://postgres:postgres@localhost:5432/gitvigil?sslmode=disable

# Server
PORT=8080
BASE_URL=https://harshs-macbook-pro.ruffe-minor.ts.net

# Detection thresholds
BACKDATE_SUSPICIOUS_HOURS=24
BACKDATE_CRITICAL_HOURS=72
STREAK_INACTIVITY_HOURS=72
45 changes: 45 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# GitVigil Environment Configuration
# Copy this file to .env and fill in your values

# ===================
# GitHub App Settings
# ===================
# Get these from your GitHub App settings page
GITHUB_APP_ID=your_app_id
GITHUB_APP_CLIENT_ID=your_client_id
GITHUB_APP_CLIENT_SECRET=your_client_secret

# Webhook secret (set in GitHub App settings)
GITHUB_WEBHOOK_SECRET=your_webhook_secret

# Path to your GitHub App's private key PEM file
GITHUB_PRIVATE_KEY_PATH=./your-app.private-key.pem

# ===================
# Database Settings
# ===================
# PostgreSQL connection string
# For Docker Compose: postgres://gitvigil:gitvigil@db:5432/gitvigil?sslmode=disable
# For local dev: postgres://postgres:postgres@localhost:5432/gitvigil?sslmode=disable
DATABASE_URL=postgres://gitvigil:gitvigil@localhost:5432/gitvigil?sslmode=disable

# Database password (used by Docker Compose)
DB_PASSWORD=gitvigil

# ===================
# Server Settings
# ===================
PORT=8080
BASE_URL=https://your-domain.com

# ===================
# Detection Thresholds
# ===================
# Hours after which a commit is flagged as suspicious (default: 24)
BACKDATE_SUSPICIOUS_HOURS=24

# Hours after which a commit is flagged as critical (default: 72)
BACKDATE_CRITICAL_HOURS=72

# Hours of inactivity before streak is at risk (default: 72)
STREAK_INACTIVITY_HOURS=72
121 changes: 121 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

GitVigil is a hackathon monitoring GitHub App that detects commit backdating, monitors force-pushes, validates licenses, tracks activity streaks, and provides reviewer insights.

**Module:** `github.com/harshpatel5940/gitvigil`

## Development Commands

```bash
# Build
go build -o gitvigil ./cmd/main.go

# Run (requires PostgreSQL and .env configured)
go run ./cmd/main.go

# Test
go test ./...

# Format
go fmt ./...

# Vet
go vet ./...
```

## Architecture

```
cmd/main.go # HTTP server, config, graceful shutdown
internal/
├── config/config.go # Load .env, validate settings
├── database/
│ ├── database.go # pgx connection pool
│ ├── migrate.go # Embedded migration runner
│ └── migrations/ # SQL schema files
├── github/
│ └── app.go # JWT auth, installation tokens
├── webhook/
│ ├── handler.go # /webhook endpoint, push event processing
│ └── signature.go # HMAC-SHA256 verification
├── detection/
│ └── detector.go # Backdate, license, streak detection
├── analysis/
│ ├── commits.go # Conventional Commits parsing
│ ├── distribution.go # Contribution distribution (Gini coefficient)
│ └── volume.go # Daily builder vs deadline dumper
├── scorecard/
│ └── handler.go # /scorecard API endpoint
├── auth/
│ └── handler.go # /auth/github/callback OAuth
├── api/
│ ├── handler.go # Base API with JSON helpers
│ ├── repositories.go # Repository list/get endpoints
│ ├── installations.go # Installation list/get endpoints
│ └── stats.go # System statistics endpoint
└── models/
├── repository.go # Repository CRUD
├── commit.go # Commit stats
├── alert.go # Alert types and CRUD
├── contributor.go # Contributor stats
└── installation.go # Installation CRUD
```

## API Endpoints

- `POST /webhook` - Receives GitHub push/installation events
- `GET /scorecard?repo=owner/name` - Returns repository analysis JSON
- `GET /auth/github/callback` - OAuth callback
- `GET /health` - Health check

**Management API (v1):**
- `GET /api/v1/repositories` - List all monitored repositories
- `GET /api/v1/repositories/:id` - Get single repository
- `GET /api/v1/installations` - List all GitHub App installations
- `GET /api/v1/installations/:id` - Get installation details
- `GET /api/v1/installations/:id/repositories` - List repos for installation
- `GET /api/v1/stats` - System-wide statistics

## Configuration

Environment variables (`.env`):
- `GITHUB_APP_ID`, `GITHUB_APP_CLIENT_ID`, `GITHUB_APP_CLIENT_SECRET`
- `GITHUB_WEBHOOK_SECRET` - For webhook signature verification
- `GITHUB_PRIVATE_KEY_PATH` - Path to RSA private key PEM
- `DATABASE_URL` - PostgreSQL connection string
- `PORT`, `BASE_URL`
- `BACKDATE_SUSPICIOUS_HOURS` (default: 24), `BACKDATE_CRITICAL_HOURS` (default: 72)
- `STREAK_INACTIVITY_HOURS` (default: 72)

## Self-Hosting with Docker

```bash
# Quick start
cp .env.example .env
# Edit .env with your GitHub App credentials

# Start services
make docker-up

# View logs
make docker-logs

# Stop services
make docker-down
```

## Detection Logic

**Backdate Detection**: Compares webhook receive time vs commit `author.date`. Flags commits with >24h difference as suspicious, >72h as critical.

**Force Push**: Detects `forced: true` on push events.

**Streak Tracking**: Marks repos as "at_risk" after 72 hours of inactivity.

**Conventional Commits**: Validates `feat:`, `fix:`, `docs:`, etc. prefixes.

**Contribution Patterns**: Identifies "deadline_dumper" (>50% commits in last 20% of time) vs "daily_builder" (consistent activity).
65 changes: 65 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# =============================================================================
# GitVigil Dockerfile
# Multi-stage build for minimal, secure production image
# =============================================================================

# -----------------------------------------------------------------------------
# Build Stage
# -----------------------------------------------------------------------------
FROM golang:1.23-alpine AS builder

# Install build dependencies
RUN apk add --no-cache git ca-certificates tzdata

# Create non-root user for runtime
RUN adduser -D -g '' appuser

WORKDIR /app

# Download dependencies first (better caching)
COPY go.mod go.sum ./
RUN go mod download

# Copy source code
COPY . .

# Build the binary
# - CGO_ENABLED=0: Static binary, no C dependencies
# - -ldflags="-s -w": Strip debug info for smaller binary
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
-ldflags="-s -w" \
-o /gitvigil \
./cmd/main.go

# -----------------------------------------------------------------------------
# Runtime Stage
# -----------------------------------------------------------------------------
FROM alpine:3.19

# Install runtime dependencies
RUN apk --no-cache add ca-certificates tzdata

# Import user from builder
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group

WORKDIR /app

# Copy binary from builder
COPY --from=builder /gitvigil .

# Copy migrations (embedded in binary, but keep for reference)
COPY --from=builder /app/internal/database/migrations ./internal/database/migrations

# Use non-root user
USER appuser

# Expose default port
EXPOSE 8080

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1

# Run the application
ENTRYPOINT ["/app/gitvigil"]
Loading