Spring Boot API for the existing React HR portal. It targets PostgreSQL/Supabase or an on-prem PostgreSQL database.
JdbcTemplateservices map the normalizedhrschema into the JSON shape used by the frontend.- Flyway
V1contains the attached employee master schema. On a fresh database it creates the HR schemas; on an existing Supabase database,baseline-on-migrate=truetreats the current schema as version 1. - Flyway
V2adds backend-owned tables for profile change requests and emergency contacts. - Flyway
V5removes the old app-user UAM tables; access is derived from the employee's current division. - Flyway
V6is the sales ticket schema already applied in production; attendance starts atV7. - Auth uses
hr.employee.email, stores the principal in the HTTP session cookie, and temporarily accepts employee code as the password. - PDPA-sensitive fields are read from
hr_restricted.employee_piionly forhrusers.
Use the same hostname for frontend and backend during local development so the session cookie is sent consistently.
Your local Supabase values are in .env.local, which is ignored by Git. To start with that file:
cd backend
set -a
source .env.local
set +a
./mvnw spring-boot:runFor another Supabase project, copy .env.example to .env.local and fill in the host, user, and password.
Then run the frontend with API mode:
cd ../frontend
VITE_API_BASE_URL=http://127.0.0.1:8080 npm run dev| Variable | Required | Default | Notes |
|---|---|---|---|
SPRING_PROFILES_ACTIVE |
No | none | Use prod on Render/production. |
SPRING_DATASOURCE_URL |
Yes outside local Postgres | jdbc:postgresql://localhost:5432/hris |
PostgreSQL JDBC URL. Add sslmode=require for Supabase. |
SPRING_DATASOURCE_USERNAME |
Yes outside local Postgres | postgres |
Database user. Prefer a least-privilege app role. |
SPRING_DATASOURCE_PASSWORD |
Yes outside local Postgres | postgres |
Database password. Keep in .env.local or host secrets only. |
DB_POOL_SIZE |
No | 10 |
Hikari maximum pool size. |
DB_MIN_IDLE |
No | 1 |
Hikari minimum idle connections. Production override sets this to 0. |
APP_FLYWAY_ENABLED |
No | true |
Runs schema migrations on startup. |
APP_CORS_ALLOWED_ORIGINS |
No | local Vite origins | Comma-separated absolute http or https origins. Wildcards are rejected. |
APP_ATTENDANCE_AGENT_TOKEN |
Yes for attendance agent | empty | Shared secret required by POST /api/attendance/punch in X-GLR-Agent-Token. |
SERVER_SESSION_COOKIE_SECURE |
No | true |
Set false only for local plain-HTTP backend runs. |
cd backend
./mvnw testThe tests cover business rules, service behavior, validation, controller auth/permission checks, and security-sensitive auth behavior.
APP_FLYWAY_ENABLED=trueThe attendance module exposes:
POST /api/attendance/punchfor the SC700 agent. RequiresX-GLR-Agent-Token.POST /api/attendance/imports/datfor HR-only.datbackfill imports.GET /api/attendance/punches?from=2020-11-01&to=2020-12-31for attendance history. Employee users see only their own punches; HR/MD/CEO users see all punches and may filter withemployeeId.
The .dat import expects JSON with site_code, device_code, file_name, and content. It parses the six tab-separated SC700 columns, inserts unique punches into hr.attendance_punch, and writes import counts/errors into hr.attendance_import_file and hr.attendance_import_error.
Recommended production hardening:
- Use a dedicated app database role with least-privilege grants. See docs/least-privilege-db-role.md for the
hr_appscript + rollout runbook (issue #25). - Grant
hr_restrictedaccess only if this API is allowed to serve PDPA-sensitive fields to HR. - Put TLS and secure cookie settings behind the production reverse proxy.
- Replace the temporary password flow with your organization IAM or a password reset workflow.