Every Deployment Deserves Proof.
DeployProof records a SHA-256 fingerprint of every successful build on Solana Devnet and lets anyone verify it publicly. When a pipeline fails, it asks Gemini to explain why.
GitHub Actions ──webhook──▶ Backend ──▶ SQLite + job queue ──▶ Worker ──▶ Solana Memo (success)
└──▶ Gemini analysis (failure)
Anyone ──▶ Public verifier ──▶ Backend ──▶ reads the Solana transaction and compares it
Status: MVP per PRD/SRS v1.0.0. Devnet only (Mainnet RPC URLs are rejected at startup). Read Honest status before presenting it as finished.
- What it proves
- Features
- Architecture
- Tech Stack
- Screenshots
- Getting Started
- Installation
- Usage
- Testing
- API
- Documentation
- Deployment
- Contributing
- Honest Status
| It proves | It does not prove |
|---|---|
| A DeployProof wallet recorded this repo + commit + artifact hash on Solana at a point in time | That the artifact is running in production |
| The hash on-chain matches the record DeployProof indexed | That the build is reproducible |
| The memo was signed by a DeployProof wallet (not just anyone) | Anything about hashes DeployProof never indexed (no chain-wide scan) |
- ✅ Webhook Intake: GitHub Actions → Express backend, with shared secret authentication
- ✅ Idempotency: Unique key on
(repo, run id, run attempt)prevents duplicate processing - ✅ Job Queue: SQLite-backed persistent queue with retry logic and exponential backoff
- ✅ Solana Memo: Signs and sends SHA-256 hash via Solana Memo program on Devnet
- ✅ Verifier: Public endpoint to verify artifact hashes against blockchain records
- ✅ Gemini AI: Analyzes sanitized failure logs to provide root cause analysis
- ✅ Dashboard: Manage deployments, view stats, retry failed jobs
- ✅ Security: Log sanitization, constant-time secrets, rate limiting, body size limits
| Component | Responsibility |
|---|---|
| GitHub Actions | builds, hashes the artifact, reports success or failure. No wallet access |
| Backend API (Express) | authenticates and validates webhooks, stores data, serves dashboard and verifier |
| SQLite + Prisma | deployments and the persistent job queue |
| Worker (same process) | runs Solana and Gemini jobs in the background |
| Solana Devnet | public audit trail via the Memo program |
| Gemini | analyzes sanitized failure logs |
| React frontend | dashboard and public verifier |
routes → controllers → services → database
↓
workers/
utils/ (pure helpers)
- Webhook is authenticated, validated, saved with a
BLOCKCHAINjob, answered202. - Worker claims the job atomically.
- Signer-first send: build the memo transaction, sign it, save its signature on the job, then send and confirm.
- Read the transaction back and check it (program, no error, signer, payload). Only then the deployment becomes
COMPLETEDand getstxSignature.
Webhook → logs sanitized and trimmed → AI_ANALYSIS job → Gemini → validated JSON saved. Failed builds never produce a transaction.
| Problem | Decision |
|---|---|
| Crash or timeout after sending | the saved signature is checked first. A new transaction is built only after the old blockhash has expired and the old signature never landed, so no duplicate memos |
| Restart mid-job | PROCESSING jobs return to PENDING on startup |
| Job stranded by a transient DB error | the loop re-queues jobs PROCESSING for more than 5 minutes; claim failures are caught |
| Transaction in flight | WaitError re-queues in 10 s without using an attempt |
| Transient errors | up to 3 attempts, exponential backoff |
| Permanent errors (no SOL, memo too large, no Gemini key) | job FAILED immediately; recover with the retry endpoints |
- Backend: Node.js 20+, Express, TypeScript, Prisma (SQLite), Zod
- Blockchain: @solana/web3.js v1, Solana Devnet Memo program
- AI: Gemini API (REST
generateContentvia native fetch), modelgemini-3.5-flash-lite - Frontend: React 18, Vite, Tailwind CSS 4, React Router 6
- Testing: Vitest (backend)
Capture the dashboard, deployments, detail, verifier, and settings views before submission and place them under docs/screenshots/. See docs/SCREENSHOTS.md for the capture checklist and naming guide.
Needs Node.js 20+. Details and Docker are in docs/SETUP.md.
Copy-Item .env.example backend\.env
cd backend
npm install
npm run wallet:newPut the printed SOLANA_PRIVATE_KEY_BASE64=... line and two random secrets (WEBHOOK_SECRET, DASHBOARD_API_KEY) into backend\.env, then:
npx prisma migrate deploy
npm run devIn a second terminal:
cd frontend
npm install
npm run devOpen http://localhost:5173 → Settings → enter your DASHBOARD_API_KEY. Then fire test events:
cd backend
npm run webhook:test -- success
npm run webhook:test -- failure- Node.js 20+
- npm 10+
- SQLite3 support (Prisma handles this)
- Docker (optional, for containerized deployment)
git clone https://github.com/Bangkahdev/deployproof.git
cd deployproofcd backend
npm installcp .env.example .envUpdate the following:
DATABASE_URL: SQLite path (default:file:./dev.db)WEBHOOK_SECRET: ≥16 characters (GitHub sends inx-webhook-secret)DASHBOARD_API_KEY: ≥16 characters (for dashboard API access)SOLANA_PRIVATE_KEY_BASE64: Base64 of 64-byte secret keySOLANA_NETWORK:devnet(Mainnet is rejected)SOLANA_RPC_URL: Solana Devnet RPC URLGEMINI_API_KEY: Gemini API key (optional)GEMINI_MODEL:gemini-3.5-flash-liteFRONTEND_URL: Frontend URL (default:http://localhost:5173)
npm run wallet:newnpx prisma migrate deploynpm run devcd ../frontend
npm install
npm run dev- Open http://localhost:5173
- Go to Settings and enter your
DASHBOARD_API_KEY - View deployment statistics
- View deployment list and details
- Retry failed AI analysis or blockchain jobs
- Open the Verifier page
- Enter the artifact SHA-256 hash
- The backend queries the blockchain record and compares
- Results show
VERIFIEDorNOT_FOUND
Send a POST to /api/webhook/deployment with:
{
"repo": "owner/repository",
"commit": "abc123",
"buildHash": "sha256-hash",
"status": "success",
"workflowRunId": "123",
"runAttempt": 1,
"workflowUrl": "https://github.com/..."
}POST /api/deployments/:id/retry-ai- Retry AI analysisPOST /api/deployments/:id/retry-blockchain- Retry blockchain recording
cd backend
npm testtests/sanitize.test.ts: secret redaction, 200-line and 20 KB limits, ANSI strippingtests/memo.test.ts: memo serialization, 500-byte limit, matching, explorer URLtests/validation.test.ts: webhook payload rules, SHA-256 format
See docs/TESTING.md for the complete checklist.
# Backend
cd backend
npm run typecheck # TypeScript type checking
npm test # Run unit tests
npm run dev # Start development server
# Frontend
cd frontend
npm run build # Production build
npm run dev # Start dev server| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/health |
Health check | None |
| GET | /api/verify/:hash |
Verify artifact hash | Rate Limited |
| POST | /api/webhook/deployment |
Webhook intake | Shared Secret |
| GET | /api/dashboard/stats |
Dashboard stats | API Key |
| GET | /api/deployments |
List deployments | API Key |
| GET | /api/deployments/:id |
Get deployment | API Key |
| POST | /api/deployments/:id/retry-ai |
Retry AI | API Key |
| POST | /api/deployments/:id/retry-blockchain |
Retry Blockchain | API Key |
See docs/API.md for full API documentation.
| Doc | Read it to |
|---|---|
| docs/SETUP.md | install, configure and run locally or with Docker |
| docs/GITHUB_ACTIONS.md | connect a repository |
| docs/API.md | call the API |
| docs/ARCHITECTURE.md | understand how it works and why |
| docs/OPERATIONS.md | retries, wallet rotation, troubleshooting |
| docs/TESTING.md | what is tested, and the manual end-to-end checklist |
| docs/DEMO.md | run the hackathon demo |
cp .env.example .env
docker compose up --build- Frontend: http://localhost:8080
- Backend: http://localhost:3000
Copy examples/github-actions.yml to .github/workflows/deployproof.yml in your repository and adapt.
- Fork the repository
- Create a feature branch
- Make your changes
- Run the tests
Written against the SRS and reviewed, but not yet run end-to-end: the environment it was written in had no network access. Unit-tested offline: log sanitization and memo size limits (manually executed). Not yet verified: npm install/build, the full test suite, Docker, a real Devnet transaction, a real Gemini call. Run the checklist in docs/TESTING.md before submission.
- Devnet is not permanent storage and RPC providers can be down (the verifier then answers
VERIFICATION_UNAVAILABLE) - The dashboard API key lives in browser localStorage (use real auth beyond the MVP)
- The initial Prisma migrations are hand-written
Multi-tenant auth, GitLab/Bitbucket, custom Solana program, SLSA provenance and signed attestations, failure-pattern analysis.
MIT