Skip to content

annikaholmqvist94/mini-ATS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

26 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Mini-ATS - Backend

Modern Applicant Tracking System built with Spring Boot, Supabase Auth, and PostgreSQL. Features JWT authentication, multi-tenant architecture, and a Kanban-style recruitment pipeline.

Spring Boot Java Supabase PostgreSQL


πŸ“‹ Table of Contents


🎯 Overview

Mini-ATS is a modern recruitment management platform that helps organizations track job candidates through a visual Kanban pipeline. Built with Spring Boot and Supabase, it features enterprise-grade authentication, multi-tenancy, and role-based access control.

Key Capabilities

  • πŸ” Supabase Authentication: JWT-based auth with ES256 validation
  • 🏒 Multi-tenant Architecture: Complete organization-level data isolation
  • πŸ“Š Kanban Pipeline: Visual tracking (NEW β†’ SCREENING β†’ INTERVIEW β†’ OFFER / REJECTED)
  • πŸ‘₯ User Management: Admin users can create organizations and manage users
  • πŸ“ Candidate Scorecards: 5-category rating system with auto-calculated averages
  • πŸ”’ Secure by Default: JWT validation, CORS protection, security headers

✨ Features

πŸ” Authentication & Authorization

  • βœ… Supabase Auth Integration

    • JWT token validation using JWKS (ES256)
    • Automatic user creation in both auth.users and public.users
    • Session management with secure tokens
  • βœ… Role-Based Access Control

    • ADMIN: Full system access, create users/orgs, manage all data
    • USER: Organization-scoped access only
  • βœ… Security Features

    • JWT validation on all protected endpoints
    • CORS configuration for allowed origins
    • Spring Security integration
    • Service Role Key for admin operations

πŸ‘₯ User Management

  • βœ… Admin and User roles
  • βœ… Organization-based access control
  • βœ… Admin impersonation (view any org's data)
  • βœ… User creation via Admin Panel:
    • Creates user in Supabase Auth
    • Creates matching record in public.users
    • Links with same UUID
    • Password management

πŸ’Ό Job Management

  • βœ… Create and manage job postings
  • βœ… Filter by status (ACTIVE/CLOSED/DRAFT)
  • βœ… Search by title and department
  • βœ… Track applications per job
  • βœ… Department-based organization

πŸ‘€ Candidate Management

  • βœ… Complete candidate profiles
  • βœ… LinkedIn profile integration
  • βœ… Skills management (array field)
  • βœ… Contact information storage
  • βœ… Search and filter capabilities
  • βœ… Scorecard System:
    • Technical Skills (1-5)
    • Communication (1-5)
    • Culture Fit (1-5)
    • Experience (1-5)
    • Leadership (1-5)
    • Auto-calculated overall rating
    • Real-time updates
  • βœ… Activity Timeline:
    • Track all candidate interactions
    • Notes and comments
    • Status changes

πŸ“Š Kanban Pipeline

  • βœ… Visual tracking across 5 stages
  • βœ… Drag-and-drop status updates
  • βœ… Enriched data (candidate + job info)
  • βœ… Filter by job or candidate
  • βœ… Pipeline statistics and metrics
  • βœ… Stage-specific business logic

πŸ—οΈ Architecture

Design Patterns

Pattern Usage
Builder Immutable domain entities (Lombok)
Repository Data access abstraction layer
DTO Immutable records for API contracts
Service Business logic separation
Filter JWT authentication via Spring Security

System Layers

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  REST Controllers (8)               β”‚
β”‚  - CORS protected                   β”‚
β”‚  - JWT authenticated                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Security Layer                     β”‚
β”‚  - JwtAuthenticationFilter          β”‚
β”‚  - JwtTokenValidator (ES256)        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Service Layer (7)                  β”‚
β”‚  - UserService                      β”‚
β”‚  - CandidateService                 β”‚
β”‚  - JobService                       β”‚
β”‚  - ApplicationService               β”‚
β”‚  - ScorecardService                 β”‚
β”‚  - ActivityService                  β”‚
β”‚  - SupabaseAuthService ⭐ (NEW)     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Repository Layer (7)               β”‚
β”‚  - Supabase implementations         β”‚
β”‚  - Direct REST API calls            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Supabase                           β”‚
β”‚  - PostgreSQL Database              β”‚
β”‚  - Auth System (JWT)                β”‚
β”‚  - JWKS Endpoint                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Database Schema

Key Tables:

  • auth.users - Supabase Auth users (managed by Supabase)
  • public.users - Application user profiles (linked to auth.users)
  • public.organizations - Tenant organizations
  • public.jobs - Job postings
  • public.candidates - Candidate profiles
  • public.applications - Pipeline stage tracking
  • public.scorecards - Candidate evaluations
  • public.activities - Audit trail

πŸ› οΈ Tech Stack

Core

Technology Version Purpose
Spring Boot 3.2.2 Application Framework
Java 17 Programming Language
Maven 3.8+ Build Tool
PostgreSQL 15+ Database (via Supabase)

Key Dependencies

Library Purpose
spring-boot-starter-web REST API
spring-boot-starter-security Security & Auth
jjwt (0.12.5) JWT validation (ES256)
postgresql Database driver
lombok Boilerplate reduction
jackson JSON serialization
httpclient5 Supabase API calls
dotenv-java Environment configuration

πŸš€ Getting Started

Prerequisites

java -version    # Java 17+
mvn -version     # Maven 3.8+

Quick Start

1. Clone Repository

git clone <your-repo-url>
cd mini-ATS

2. Configure Environment

Create .env file in project root:

# Supabase Configuration
SUPABASE_URL=https://xlrbdnnferxnitillzmt.supabase.co
SUPABASE_ANON_KEY=your_anon_key_here
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key_here

# Database Configuration
DB_URL=jdbc:postgresql://aws-0-eu-central-2.pooler.supabase.com:6543/postgres?user=postgres.xlrbdnnferxnitillzmt&password=YOUR_PASSWORD&pgbouncer=true
DB_USERNAME=postgres
DB_PASSWORD=your_db_password

# Application Configuration
SPRING_PROFILES_ACTIVE=dev
SERVER_PORT=8080

# JWT Configuration
SUPABASE_JWT_JWKS_URL=https://xlrbdnnferxnitillzmt.supabase.co/auth/v1/.well-known/jwks.json
JWT_EXPIRATION=86400000

# CORS Configuration (Frontend URLs)
CORS_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000,https://your-frontend.vercel.app

# Admin Configuration
ADMIN_DEFAULT_EMAIL=admin@acme.com
ADMIN_DEFAULT_PASSWORD=ChangeThisPassword123!

3. Build & Run

# Build
mvn clean install

# Run
mvn spring-boot:run

API available at: http://localhost:8080/api

4. Verify

curl http://localhost:8080/api/health

Expected response:

{
  "success": true,
  "data": "OK",
  "error": null,
  "timestamp": "2026-02-09T14:00:00Z"
}

πŸ” Authentication

Supabase JWT Authentication (ES256)

This application uses Supabase Authentication with JWT tokens validated using ES256 (Elliptic Curve) cryptography.

How It Works

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Frontend β”‚         β”‚  Backend β”‚         β”‚ Supabase β”‚
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
     β”‚                    β”‚                     β”‚
     β”‚ 1. Login           β”‚                     β”‚
     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>  β”‚
     β”‚                    β”‚                     β”‚
     β”‚ 2. JWT Token       β”‚                     β”‚
     β”‚ <──────────────────────────────────────  β”‚
     β”‚                    β”‚                     β”‚
     β”‚ 3. API Request     β”‚                     β”‚
     β”‚    + Bearer Token  β”‚                     β”‚
     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€> β”‚                     β”‚
     β”‚                    β”‚                     β”‚
     β”‚                    β”‚ 4. Fetch JWKS       β”‚
     β”‚                    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>  β”‚
     β”‚                    β”‚                     β”‚
     β”‚                    β”‚ 5. Public Keys      β”‚
     β”‚                    β”‚ <──────────────────  β”‚
     β”‚                    β”‚                     β”‚
     β”‚                    β”‚ 6. Validate Token   β”‚
     β”‚                    β”‚    (ES256)          β”‚
     β”‚                    β”‚                     β”‚
     β”‚ 7. Response        β”‚                     β”‚
     β”‚ <──────────────────│                     β”‚
     β”‚                    β”‚                     β”‚

Implementation Details

1. JwtTokenValidator.java

  • Fetches JWKS (JSON Web Key Set) from Supabase
  • Validates ES256 signatures using public keys
  • Extracts user email and ID from claims
  • Caches JWKS for performance

2. JwtAuthenticationFilter.java

  • Intercepts all HTTP requests
  • Extracts JWT from Authorization: Bearer <token> header
  • Validates token and sets Spring Security context
  • Fetches user role from database

3. SupabaseAuthService.java ⭐ NEW

  • Creates users in Supabase Auth via Admin API
  • Uses Service Role Key for privileged operations
  • Deletes users (rollback on errors)
  • Auto-confirms email

Creating New Users

Flow:

  1. Admin calls POST /api/users with user data + password
  2. Backend calls Supabase Admin API to create auth user
  3. Supabase returns auth user ID (UUID)
  4. Backend creates public.users record with same UUID
  5. User can immediately log in with credentials

Code Example:

@Service
public class UserService {
    
    @Transactional
    public UserDTO createUser(UserDTO userDTO) {
        // 1. Create in Supabase Auth
        String authUserId = supabaseAuthService.createAuthUser(
            userDTO.getEmail(),
            userDTO.getPassword()
        );
        
        // 2. Create in public.users with same ID
        User user = User.builder()
            .id(UUID.fromString(authUserId))  // ← Same ID!
            .email(userDTO.getEmail())
            .role(UserRole.fromString(userDTO.getRole()))
            .build();
        
        return UserDTO.fromEntity(userRepository.save(user));
    }
}

Security Features

  • βœ… ES256 Signatures: Asymmetric cryptography (public/private keys)
  • βœ… JWKS Validation: Fetch and verify public keys from Supabase
  • βœ… Token Expiration: Tokens expire after configured time
  • βœ… Role-Based Access: Extract user role from database
  • βœ… Spring Security Integration: Automatic authentication context
  • βœ… CORS Protection: Only allowed origins can call API

πŸ“š API Documentation

Base URL

http://localhost:8080/api

Response Format

Success:

{
  "success": true,
  "data": { ... },
  "error": null,
  "timestamp": "2026-02-09T14:00:00Z"
}

Error:

{
  "success": false,
  "data": null,
  "error": "Error message here",
  "timestamp": "2026-02-09T14:00:00Z"
}

Authentication

All protected endpoints require JWT token:

curl -H "Authorization: Bearer eyJhbGci..." \
  http://localhost:8080/api/users

Endpoints Summary

Resource Endpoints Description
Organizations 6 CRUD operations
Users 10 User management, authentication
Jobs 14 Job postings
Candidates 9 Candidate profiles
Applications 20 Kanban pipeline
Scorecards 8 Candidate evaluations ⭐
Activities 6 Audit trail ⭐
Health 4 System monitoring

Total: ~77 REST endpoints

Key Endpoints

Authentication & Users

# Get user by email (after login)
GET /api/users/email/{email}
Authorization: Bearer <token>

# Create new user (admin only)
POST /api/users
{
  "email": "newuser@acme.com",
  "fullName": "New User",
  "role": "USER",
  "organizationId": "uuid",
  "password": "SecurePass123!"
}

# Create admin user
POST /api/users/admin
{
  "email": "newadmin@acme.com",
  "fullName": "New Admin",
  "organizationId": "uuid",
  "password": "AdminPass123!"
}

Candidates

# Get candidates for organization
GET /api/candidates/organization/{orgId}

# Create candidate
POST /api/candidates
{
  "organizationId": "uuid",
  "fullName": "Anna Andersson",
  "email": "anna@example.com",
  "phone": "+46701234567",
  "linkedinUrl": "https://linkedin.com/in/anna",
  "skills": ["React", "TypeScript", "Node.js"],
  "summary": "Senior developer with 5 years experience"
}

Scorecards ⭐

# Create scorecard
POST /api/scorecards
{
  "candidateId": "uuid",
  "technicalSkills": 4,
  "communication": 5,
  "cultureFit": 4,
  "experience": 3,
  "leadership": 4
}

# Get scorecards for candidate
GET /api/scorecards/candidate/{candidateId}

Kanban Pipeline

# Get all applications for organization
GET /api/applications/organization/{orgId}

# Create application (add to pipeline)
POST /api/applications
{
  "candidateId": "uuid",
  "jobId": "uuid",
  "status": "NEW"
}

# Update application status (move in pipeline)
PATCH /api/applications/{id}/status
{
  "status": "INTERVIEW",
  "notes": "Scheduled for technical interview"
}

πŸ“ Project Structure

mini-ATS/
β”œβ”€β”€ src/main/java/com/miniats/
β”‚   β”œβ”€β”€ MiniAtsApplication.java          # Application entry point
β”‚   β”‚
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”œβ”€β”€ SecurityConfig.java          # Spring Security + JWT
β”‚   β”‚   β”œβ”€β”€ SupabaseConfig.java          # Supabase client
β”‚   β”‚   β”œβ”€β”€ WebConfig.java               # CORS configuration
β”‚   β”‚   └── DotenvConfig.java            # Environment variables
β”‚   β”‚
β”‚   β”œβ”€β”€ security/                        # ⭐ Authentication Layer
β”‚   β”‚   β”œβ”€β”€ JwtAuthenticationFilter.java # Intercepts requests
β”‚   β”‚   β”œβ”€β”€ JwtTokenValidator.java       # Validates ES256 tokens
β”‚   β”‚   └── SupabaseUserPrincipal.java   # User identity
β”‚   β”‚
β”‚   β”œβ”€β”€ controller/                      # REST API Controllers
β”‚   β”‚   β”œβ”€β”€ BaseController.java          # Common response methods
β”‚   β”‚   β”œβ”€β”€ UserController.java          # User management
β”‚   β”‚   β”œβ”€β”€ OrganizationController.java  # Organizations
β”‚   β”‚   β”œβ”€β”€ JobController.java           # Jobs
β”‚   β”‚   β”œβ”€β”€ CandidateController.java     # Candidates
β”‚   β”‚   β”œβ”€β”€ ApplicationController.java   # Pipeline
β”‚   β”‚   β”œβ”€β”€ ScorecardController.java     # Scorecards ⭐
β”‚   β”‚   └── ActivityController.java      # Activity timeline ⭐
β”‚   β”‚
β”‚   β”œβ”€β”€ service/                         # Business Logic
β”‚   β”‚   β”œβ”€β”€ UserService.java
β”‚   β”‚   β”œβ”€β”€ OrganizationService.java
β”‚   β”‚   β”œβ”€β”€ JobService.java
β”‚   β”‚   β”œβ”€β”€ CandidateService.java
β”‚   β”‚   β”œβ”€β”€ ApplicationService.java
β”‚   β”‚   β”œβ”€β”€ ScorecardService.java        # ⭐
β”‚   β”‚   β”œβ”€β”€ ActivityService.java         # ⭐
β”‚   β”‚   └── SupabaseAuthService.java     # ⭐ NEW: User creation
β”‚   β”‚
β”‚   β”œβ”€β”€ repository/                      # Data Access Layer
β”‚   β”‚   β”œβ”€β”€ UserRepository.java
β”‚   β”‚   β”œβ”€β”€ OrganizationRepository.java
β”‚   β”‚   β”œβ”€β”€ JobRepository.java
β”‚   β”‚   β”œβ”€β”€ CandidateRepository.java
β”‚   β”‚   β”œβ”€β”€ ApplicationRepository.java
β”‚   β”‚   β”œβ”€β”€ ScorecardRepository.java     # ⭐
β”‚   β”‚   β”œβ”€β”€ ActivityRepository.java      # ⭐
β”‚   β”‚   └── impl/                        # Supabase implementations
β”‚   β”‚       β”œβ”€β”€ SupabaseUserRepository.java
β”‚   β”‚       β”œβ”€β”€ SupabaseOrganizationRepository.java
β”‚   β”‚       β”œβ”€β”€ SupabaseJobRepository.java
β”‚   β”‚       β”œβ”€β”€ SupabaseCandidateRepository.java
β”‚   β”‚       β”œβ”€β”€ SupabaseApplicationRepository.java
β”‚   β”‚       β”œβ”€β”€ SupabaseScorecardRepository.java
β”‚   β”‚       └── SupabaseActivityRepository.java
β”‚   β”‚
β”‚   β”œβ”€β”€ domain/
β”‚   β”‚   β”œβ”€β”€ model/                       # Domain Entities (Immutable)
β”‚   β”‚   β”‚   β”œβ”€β”€ User.java
β”‚   β”‚   β”‚   β”œβ”€β”€ Organization.java
β”‚   β”‚   β”‚   β”œβ”€β”€ Job.java
β”‚   β”‚   β”‚   β”œβ”€β”€ Candidate.java
β”‚   β”‚   β”‚   β”œβ”€β”€ Application.java
β”‚   β”‚   β”‚   β”œβ”€β”€ Scorecard.java           # ⭐
β”‚   β”‚   β”‚   └── Activity.java            # ⭐
β”‚   β”‚   └── enums/
β”‚   β”‚       β”œβ”€β”€ UserRole.java
β”‚   β”‚       β”œβ”€β”€ JobStatus.java
β”‚   β”‚       β”œβ”€β”€ ApplicationStatus.java
β”‚   β”‚       └── ActivityType.java        # ⭐
β”‚   β”‚
β”‚   β”œβ”€β”€ dto/                             # Data Transfer Objects (Records)
β”‚   β”‚   β”œβ”€β”€ UserDTO.java
β”‚   β”‚   β”œβ”€β”€ OrganizationDTO.java
β”‚   β”‚   β”œβ”€β”€ JobDTO.java
β”‚   β”‚   β”œβ”€β”€ CandidateDTO.java
β”‚   β”‚   β”œβ”€β”€ ApplicationDTO.java
β”‚   β”‚   β”œβ”€β”€ ScorecardDTO.java            # ⭐
β”‚   β”‚   └── ActivityDTO.java             # ⭐
β”‚   β”‚
β”‚   └── exception/                       # Error Handling
β”‚       β”œβ”€β”€ GlobalExceptionHandler.java
β”‚       └── ResourceNotFoundException.java
β”‚
β”œβ”€β”€ src/main/resources/
β”‚   β”œβ”€β”€ application.yml                  # Spring Boot configuration
β”‚   └── logback-spring.xml              # Logging configuration
β”‚
β”œβ”€β”€ .env                                 # Environment variables (gitignored)
β”œβ”€β”€ .env.example                         # Example environment file
β”œβ”€β”€ pom.xml                              # Maven dependencies
β”œβ”€β”€ README.md                            # This file
└── .gitignore

βš™οΈ Configuration

Environment Variables

Required in .env:

# Supabase
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key

# Database
DB_URL=jdbc:postgresql://db.your-project.supabase.co:6543/postgres
DB_USERNAME=postgres
DB_PASSWORD=your_password

# JWT
SUPABASE_JWT_JWKS_URL=https://your-project.supabase.co/auth/v1/.well-known/jwks.json
JWT_EXPIRATION=86400000

# CORS (comma-separated)
CORS_ALLOWED_ORIGINS=http://localhost:5173,https://your-frontend.com

# Admin
ADMIN_DEFAULT_EMAIL=admin@acme.com
ADMIN_DEFAULT_PASSWORD=ChangeThisPassword123!

application.yml

Key configurations:

server:
  port: 8080
  servlet:
    context-path: /api

supabase:
  url: ${SUPABASE_URL}
  anon-key: ${SUPABASE_ANON_KEY}
  service-role-key: ${SUPABASE_SERVICE_ROLE_KEY}
  jwt:
    jwks-url: ${SUPABASE_JWT_JWKS_URL}
    expiration: ${JWT_EXPIRATION:86400000}

cors:
  allowed-origins: ${CORS_ALLOWED_ORIGINS}

logging:
  level:
    com.miniats: DEBUG
    org.springframework.security: DEBUG

πŸ”’ Security

Authentication Flow

  1. User logs in via frontend (Supabase Auth)
  2. Frontend receives JWT token (ES256 signed)
  3. Frontend sends token in Authorization: Bearer <token> header
  4. JwtAuthenticationFilter intercepts request
  5. JwtTokenValidator validates token:
    • Fetches JWKS from Supabase
    • Verifies ES256 signature
    • Checks expiration
  6. Spring Security sets authentication context
  7. Controller processes request with authenticated user

Security Headers

@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) {
        http
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            .csrf(csrf -> csrf.disable())
            .headers(headers -> headers
                .contentSecurityPolicy("default-src 'self'")
                .xssProtection()
                .frameOptions().deny()
            )
            .addFilterBefore(jwtAuthenticationFilter, 
                UsernamePasswordAuthenticationFilter.class);
    }
}

CORS Configuration

Only allowed origins can access the API:

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList(
        corsAllowedOrigins.split(",")
    ));
    configuration.setAllowedMethods(Arrays.asList(
        "GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"
    ));
    configuration.setAllowCredentials(true);
    return source;
}

Production Checklist

  • Use strong JWT secrets
  • Enable HTTPS only
  • Set secure CORS origins
  • Enable rate limiting
  • Configure firewall rules
  • Set up monitoring/alerts
  • Enable database backups
  • Implement request logging

🚒 Deployment

Build

mvn clean package

Output: target/mini-ats-1.0.0.jar

Run

java -jar target/mini-ats-1.0.0.jar

Deployment Platforms

Railway

  1. Push to GitHub
  2. Connect Railway to repo
  3. Set environment variables
  4. Deploy automatically

Heroku

heroku create mini-ats-backend
git push heroku main
heroku config:set SUPABASE_URL=...

AWS Elastic Beanstalk

  1. Upload JAR file
  2. Configure environment
  3. Deploy

Docker (Optional)

FROM eclipse-temurin:17-jre
COPY target/mini-ats-1.0.0.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]
docker build -t mini-ats .
docker run -p 8080:8080 --env-file .env mini-ats

πŸ› Troubleshooting

JWT Validation Fails

Problem: 401 Unauthorized errors

Solutions:

  1. Check SUPABASE_JWT_JWKS_URL is correct
  2. Verify token is not expired
  3. Check backend logs for specific error
  4. Verify user exists in both auth.users AND public.users

User Creation Fails

Problem: 400 Bad Request when creating users

Solutions:

  1. Verify SUPABASE_SERVICE_ROLE_KEY is set
  2. Check password meets requirements (min 6 chars)
  3. Verify email doesn't already exist
  4. Check Supabase dashboard for auth user creation

CORS Errors

Problem: Frontend can't connect

Solutions:

  1. Add frontend URL to CORS_ALLOWED_ORIGINS
  2. Restart backend after changing CORS
  3. Verify format: http://localhost:5173,https://other.com

Database Connection Issues

Problem: Can't connect to Supabase

Solutions:

  1. Verify DB_URL, DB_USERNAME, DB_PASSWORD
  2. Check Supabase project is running
  3. Verify network connectivity
  4. Check if using pooler URL (port 6543)

πŸ“– Related Documentation


πŸ”„ Development Workflow

Git Branches

Main branches:

  • main - Production-ready code

Completed features:

  • βœ… candidate-detail-view - Scorecards, notes, activity
  • βœ… integrate-jwt-auth - Supabase JWT authentication
  • βœ… admin-user-creation - User creation via Admin API

Making Changes

# Create feature branch
git checkout -b feature/my-feature

# Make changes and commit
git add .
git commit -m "feat: add my feature"

# Push to GitHub
git push origin feature/my-feature

# Merge when ready
git checkout main
git merge feature/my-feature
git push origin main

πŸ“Š System Statistics

Code Metrics:

  • REST Controllers: 8
  • Service Classes: 7
  • Repository Implementations: 7
  • Domain Entities: 7
  • DTOs: 7
  • Total Endpoints: ~77
  • Lines of Code: ~8,000

Test Coverage: (Add when tests are implemented)

  • Unit Tests: TBD
  • Integration Tests: TBD
  • Coverage: TBD%

πŸ“„ License

MIT License


πŸ™ Acknowledgments

Built with:

  • Spring Boot & Spring Security
  • Supabase for authentication & database
  • PostgreSQL
  • Maven
  • Lombok
  • Love ❀️ and coffee β˜•

Questions or issues? Open an issue on GitHub or contact the development team.


πŸ“ Changelog

v1.0.0 (2026-02-09)

  • βœ… Initial release
  • βœ… Supabase JWT authentication (ES256)
  • βœ… Multi-tenant architecture
  • βœ… Kanban pipeline
  • βœ… Candidate scorecards
  • βœ… Activity timeline
  • βœ… User management with Admin API
  • βœ… Complete CRUD operations

Upcoming Features

  • Email notifications
  • File upload (resumes, cover letters)
  • Calendar integration
  • Advanced search
  • Analytics dashboard
  • Export capabilities

About

Multi-tenant Applicant Tracking System (ATS) Backend built with Spring Boot 3 & Supabase. Features a RESTful API with 60+ endpoints, PostgreSQL integration, and a visual Kanban-flow architecture.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages