HMS Mini — Human Resource Management
A mobile-first HR workspace: a statically exported Next.js frontend, NestJS API, PostgreSQL records, Redis sessions, S3 files and RabbitMQ promotion jobs. DM Sans is the shared interface font.
Documentation
Open /docs/ for the public documentation hub, with /docs/features/, /docs/changelogs/, /docs/readme/ and /docs/deploy/. For a fresh installation with your own credentials, follow DEPLOY.md. The public guides contain placeholders only. Run npm run docs:sync in the frontend after editing public Markdown files; development and builds also synchronize them automatically when the full checkout is available. Standalone Docker builds use the bundled snapshot.
Open the configured application
docker compose up --build -d
- Admin: http://localhost:3000/admin/login/
- Employee: http://localhost:3000/employee/login/
- Initial administrator: the email and password you chose with
admin:create.
The web container serves out/ through nginx and proxies /api/ to NestJS. The API port is internal to Compose. No Next.js server, middleware or server actions are required. Docker applies pending migrations under a PostgreSQL advisory lock before starting the API.
Admin and employee sessions use separate HTTP-only cookies and JWT audiences. Redis holds session TTLs; PostgreSQL is checked on every authenticated request for revocation and current account/role state. Role and permission changes invalidate affected sessions. The API is default-deny; @EmployeeAccess() explicitly enables employee routes and @Public() is limited to health/login/logout.
Start using the HR features
- Sign in as the initial administrator. Create departments, designations and shifts.
- Configure custom roles and their module/action permission matrix as needed.
- Add employees with a role, reporting manager, shift and initial password of at least 10 characters. New accounts must change that password before using their workspace.
- Employees sign in to record photo attendance, request leave/regularization and update assigned tasks. Their reporting manager reviews requests; administrators have the organization-wide queues.
- Configure help articles/tutorials and app information in the admin workspace. Guides and tutorials start empty; no fictitious employee or business records are seeded.
The initial bootstrap administrator has no employee record. Onboard an employee account to exercise the employee portal. Built-in roles are Super Admin, HR, Manager and Employee; Super Admin and HR have admin access. Managers and employees use the employee portal.
Environment mapping
Keep your own credentials in hms-mini-nest-js/.env (private, ignored by Git, excluded from image build contexts). .env.example contains placeholders only.
| Variable | Purpose |
|---|---|
DATABASE_URL | Main PostgreSQL: hms_admin authentication/uploads and hms_hr HR records |
REDIS_URL | Session TTLs and shared sign-in attempt limits |
VECTOR_DATABASE_URL | Separate location database, mapped and connected; reserved for future location/vector features |
ADMIN_JWT_SECRET | Server-only signing key for audience-separated admin/employee JWTs |
ADMIN_SESSION_TTL_SECONDS | Absolute lifetime; default 3600 seconds, valid 60–28800 |
WEB_ORIGIN | Exact allowed browser origin for API CORS and mutation-origin checks; currently http://localhost:3000 |
ADMIN_COOKIE_SECURE | false for local HTTP; use true for HTTPS deployments |
TRUST_PROXY | Compose enables this behind nginx, which overwrites forwarded IP headers |
ORG_TIMEZONE | Business calendar and shift timezone; Asia/Kolkata |
AWS_REGION | ap-southeast-2 |
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY | Server-only S3 credentials |
S3_BUCKET_STAGING | hms-mini-staging: destination of direct signed uploads |
S3_BUCKET_PRIMARY | hms-mini: destination of successfully promoted files |
S3_SIGNED_URL_TTL_SECONDS | Signed upload/download lifetime; default 300 seconds |
UPLOAD_MAX_BYTES | Maximum upload size; default and upper bound 25 MiB |
AMQP_URL | RabbitMQ URL; match the scheme and port to your broker listener |
AMQP_PROMOTION_QUEUE | Durable queue; hms-mini.files.promote |
AMQP_HEARTBEAT_SECONDS, AMQP_CONNECT_TIMEOUT_MS | Broker heartbeat and connection timeout |
FILE_WORKER_ENABLED | Starts the cohosted promotion/outbox worker; true for the configured stack |
PORT | API port; default 3001 |
_APP_SMTP_HOST, _APP_SMTP_PORT, _APP_SMTP_SECURE | SMTP server, port and implicit TLS flag; example Zoho India on 465 |
_APP_SMTP_USERNAME, _APP_SMTP_PASSWORD | Private sender account and SMTP/app password |
EMAIL_ENABLED, EMAIL_WORKER_ENABLED | Enable notification outbox creation and cohosted email delivery worker |
EMAIL_FROM_NAME, EMAIL_MAX_ATTEMPTS, AMQP_EMAIL_QUEUE | Sender display name, retry cap and durable email queue |
Only NEXT_PUBLIC_API_URL belongs in the frontend environment. Local .env.local uses http://localhost:3001; Docker excludes that file and uses /api. Public variables are fixed at build time. The location database is reserved for future work; this roadmap does not implement location search.
Exact upload lifecycle
POST /admin/files/uploadsor/files/uploadsaccepts{filename, contentType, size}and returns a signed S3 POST form with exact content-type and length conditions.- The browser sends that form directly to staging. No AWS secret or permanent object URL reaches the browser.
- The browser calls
POST .../uploads/:id/complete. The API checks ownership, expiration, object size/type, ETag and version, then durably records the queued work in PostgreSQL. - The outbox publishes a persistent message with broker confirmation. Queue outages leave the upload queued for retry.
- The worker locks the upload, conditionally copies that verified staged object to primary, checks the copy, and marks it ready. Duplicate jobs are idempotent; temporary copy failures back off, while missing/changed source objects fail safely.
- Status is available at
GET .../uploads/:id. Ready files receive short-lived signed URLs fromGET .../uploads/:id/download. Attendance and regularization reference owned, ready upload IDs.
The buckets are successive pipeline stages, not environment alternatives. Original staged objects remain after promotion; configure a staging retention/lifecycle policy appropriate to your retention needs. No blanket bucket deletion or lifecycle policy was applied.
WEB_ORIGIN is allowed for direct staging POST uploads. If the origin changes, update .env, rebuild the frontend when its API URL changes, and run:
cd hms-mini-nest-js
npm run storage:cors
The CORS script preserves unrelated bucket rules. API CORS allows GET, POST, PUT, PATCH, DELETE and OPTIONS with credentials and the mutation header. Use the same exact host/port in your browser as WEB_ORIGIN.
Development and checks
Node.js 24 and npm are required. For a fresh environment, copy the example files and populate server secrets before running:
cd hms-mini-nest-js
npm ci
npm run db:migrate
npm run admin:create -- --email admin@hms.local
npm run start:dev
The admin creation command reads a hidden password prompt. --password-stdin supports private automation; --reset-password intentionally replaces the password and revokes sessions. It does not change an existing account’s role or active status.
In another terminal:
cd hms-mini-next-js
npm ci
npm run dev
npm run build exports the frontend to out/; npm start serves that export. Both projects provide lint/build commands. Run npm run test:theme in the frontend for the real-provider DOM tests, and npm run test:surfaces after a frontend build for source/exported CSS palette checks (no browser executable required). Backend tests use isolated temporary PostgreSQL and Redis services, never the configured business database:
docker compose -f docker-compose.test.yml up -d --wait
cd hms-mini-nest-js
npm test -- --runInBand
npm run test:e2e -- --runInBand
cd ..
docker compose -f docker-compose.test.yml down
npm run redis:check reports read-only Redis ping latency, health counters and a bounded session-expiry sample without printing keys or credentials. Keep the API and its data services near each other to reduce network round trips.
npm run services:check verifies PostgreSQL, location PostgreSQL, Redis, both S3 buckets and AMQP without displaying credentials. node --env-file=.env scripts/verify-upload.mjs is an explicit live smoke check: it creates one disposable text file, verifies the real staging/queue/primary/download path, then deletes only its own objects and upload record. Run npm run build before that script.
Sample organization
To add linked, fictional data to the database configured by the backend .env:
cd hms-mini-nest-js
npm run db:seed -- --dry-run # validate in a transaction, then roll back
npm run db:seed # save the sample organization once
npm run db:seed:files # upload and link demo images/PDFs through the queue
The seed adds four departments, eight designations, three shifts, 14 employees (including managers and account-status examples), a custom permission role, 14 days of attendance, leave policies/balances/ledger/requests, regularizations, five projects, 26 tasks, sample help content, audit entries and cancelled email previews. Existing business records and app configuration are preserved. Help content is populated only if it is empty. Sample records use Demo labels and DEMO- employee codes.
Employee login details are saved in hms-mini-nest-js/.local/demo-credentials.json with private permissions and Git exclusion. Sample users must change their temporary password at first login. Try arjun.demo@example.test as an employee, vikram.demo@example.test as a manager, or asha.demo@example.test as HR. Inactive/suspended examples cannot sign in. No actual email is sent by seeding.
The seed uses the organization timezone and dates relative to its first run. Today's sample punches are illustrative schedules, even when run before the workday starts. Running the seed again preserves edits and passwords; it does not duplicate records or move dates. The optional file command adds four clearly labeled attendance illustrations and two supporting PDFs through staging and primary storage. These are fictional examples, not actual punch photographs or attendance evidence.
API and behavior notes
FEATURES.md lists all 28 admin and 24 employee features; PROGRESS.md (repository tracking file) records checks and acceptance status.
- Master resources:
/admin/roles,/departments,/designations,/employees,/shifts,/leave-policies,/projects,/tasks(all under/admin).GET /admin/catalogreturns permitted modules; lookups expose only fields needed by authorized forms. - Approval endpoints enforce pending-state transitions. Employee approvals are restricted to direct reports. A request cannot approve itself.
- Leave is counted in calendar days; half-day requests cover one date. Pending requests reserve available allowance. Approval deducts, cancellation restores exactly once, and manual adjustments are audited. Monthly quotas accrue on access as calendar months advance; carry-forward is capped by the policy.
- Time punches use server time, with a completed image upload ID. Overnight time-out closes an open punch within 24 hours. Older missing punches use regularization. Admins can insert missing attendance and override existing records with reasons.
- Attendance logs list recorded attendance; a missing date can be regularized and reports do not fabricate punch records. The dashboard separately reports people not checked in.
- Exports support CSV, Excel and PDF with server permission checks. Large list exports are capped at 10,000 records. CSV values are protected against spreadsheet formula execution.
- Shared light/dark/device appearance is managed by next-themes and applies to login, admin, employee and docs pages, with device persistence and employee account sync. Buttons retain their colors on hover; React Icons are used throughout the frontend. App preferences persist theme and locale. Navigation translations cover English, Hindi and Tamil; other configured locales fall back to English labels. HR-authored guides and tutorials display as published. Minimum supported version is enforced by the employee interface against
lib/app-version.ts. - Notifications are persisted in-app and, when enabled, queued for SMTP delivery through a transactional outbox and RabbitMQ. Onboarding, task assignment/reassignment, leave/regularization workflows and password-change/reset notices are covered. Passwords are not emailed. Admin Email delivery provides status and audited retries under settings permissions. Sent means accepted by SMTP; a crash before the database commit can redeliver with the same Message-ID. SMS is not configured.
npm run smtp:checkverifies TLS/authentication without sending mail. - Photo capture uses the mobile camera-capable file input. Native sharing uses the Web Share API with clipboard fallback. Store rating appears once HR configures a store URL.
Browser testing is intentionally left to the project owner. Build/API checks do not replace device-specific acceptance testing.