Document verification backend for KYC workflows — built with Spring Boot 3.5 and Java 21.
Handles secure document upload, integrity checks (SHA-256 dedup, EXIF stripping, magic-byte MIME validation), and admin review with a state-machine-enforced workflow. Every action is captured in a compliance-grade audit trail.
- JWT auth with BCrypt hashing and role-based access (USER / ADMIN)
- Document upload with magic-byte MIME validation (Apache Tika), SHA-256 dedup, and EXIF stripping
- State-machine-enforced workflow:
PENDING → UNDER_REVIEW → VERIFIED / REJECTED - Append-only audit trail with three-layer enforcement (no setters,
updatable=false, DB grants) - Global exception handler with consistent JSON error responses
- Interactive API docs at
/swagger-ui.html - Dockerized — one command to run the full stack
Java 21 · Spring Boot 3.5 · Spring Security · Spring State Machine · Hibernate/JPA · MySQL 8 · JJWT · Apache Tika · springdoc-openapi · Docker
git clone https://github.com/pragyan-tech/verifyhub.git
cd verifyhub
cp .env.example .env
# Edit .env — set DB_PASSWORD, JWT_SECRET, MYSQL_ROOT_PASSWORD
docker compose up --buildThen open:
- API: http://localhost:8080
- Swagger UI: http://localhost:8080/swagger-ui.html
Prerequisites: Java 21, Maven, MySQL 8.
mysql -u root -p < db-init/01-schema.sql
cp .env.example .env
mvn spring-boot:run| Method | Path | Access | Purpose |
|---|---|---|---|
| POST | /api/auth/register |
Public | Register + get JWT |
| POST | /api/auth/login |
Public | Login + get JWT |
| POST | /api/documents |
User | Upload document (multipart) |
| GET | /api/documents |
User | List your documents |
| GET | /api/documents/{id} |
User | Get document metadata |
| GET | /api/admin/documents/pending |
Admin | Review queue |
| POST | /api/admin/documents/{id}/start-review |
Admin | Claim for review |
| POST | /api/admin/documents/{id}/approve |
Admin | Approve |
| POST | /api/admin/documents/{id}/reject |
Admin | Reject (reason required) |
| GET | /api/admin/documents/{id}/audit-trail |
Admin | Full audit history |
Full docs with try-it-out at /swagger-ui.html.
- Magic-byte MIME validation — file types determined by content, not the client's
Content-Typeheader - Per-user (not global) dedup — catches the same user resubmitting the same file, without false positives across users
- EXIF stripping via re-encoding — output is stripped by construction, not by field removal
- State machine over branching — workflow rules live in one config file, not scattered service code
- 404 not 403 for unauthorized access — prevents document ID enumeration
- Same error for "user not found" vs "wrong password" — prevents username enumeration
- PDF metadata stripping is planned but not implemented (JPEG/PNG only currently)
- Audit uses default transaction propagation, so audit rolls back with parent failures. Production would move audit to an async queue.
- Orphan files possible if DB commit fails after file write. Production would add a reconciliation job.
- Access-only JWT for now; refresh tokens planned.