Skip to documentation
HMS MiniDocumentation

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

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

  1. Sign in as the initial administrator. Create departments, designations and shifts.
  2. Configure custom roles and their module/action permission matrix as needed.
  3. 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.
  4. 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.
  5. 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.

VariablePurpose
DATABASE_URLMain PostgreSQL: hms_admin authentication/uploads and hms_hr HR records
REDIS_URLSession TTLs and shared sign-in attempt limits
VECTOR_DATABASE_URLSeparate location database, mapped and connected; reserved for future location/vector features
ADMIN_JWT_SECRETServer-only signing key for audience-separated admin/employee JWTs
ADMIN_SESSION_TTL_SECONDSAbsolute lifetime; default 3600 seconds, valid 60–28800
WEB_ORIGINExact allowed browser origin for API CORS and mutation-origin checks; currently http://localhost:3000
ADMIN_COOKIE_SECUREfalse for local HTTP; use true for HTTPS deployments
TRUST_PROXYCompose enables this behind nginx, which overwrites forwarded IP headers
ORG_TIMEZONEBusiness calendar and shift timezone; Asia/Kolkata
AWS_REGIONap-southeast-2
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEYServer-only S3 credentials
S3_BUCKET_STAGINGhms-mini-staging: destination of direct signed uploads
S3_BUCKET_PRIMARYhms-mini: destination of successfully promoted files
S3_SIGNED_URL_TTL_SECONDSSigned upload/download lifetime; default 300 seconds
UPLOAD_MAX_BYTESMaximum upload size; default and upper bound 25 MiB
AMQP_URLRabbitMQ URL; match the scheme and port to your broker listener
AMQP_PROMOTION_QUEUEDurable queue; hms-mini.files.promote
AMQP_HEARTBEAT_SECONDS, AMQP_CONNECT_TIMEOUT_MSBroker heartbeat and connection timeout
FILE_WORKER_ENABLEDStarts the cohosted promotion/outbox worker; true for the configured stack
PORTAPI port; default 3001
_APP_SMTP_HOST, _APP_SMTP_PORT, _APP_SMTP_SECURESMTP server, port and implicit TLS flag; example Zoho India on 465
_APP_SMTP_USERNAME, _APP_SMTP_PASSWORDPrivate sender account and SMTP/app password
EMAIL_ENABLED, EMAIL_WORKER_ENABLEDEnable notification outbox creation and cohosted email delivery worker
EMAIL_FROM_NAME, EMAIL_MAX_ATTEMPTS, AMQP_EMAIL_QUEUESender 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

  1. POST /admin/files/uploads or /files/uploads accepts {filename, contentType, size} and returns a signed S3 POST form with exact content-type and length conditions.
  2. The browser sends that form directly to staging. No AWS secret or permanent object URL reaches the browser.
  3. 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.
  4. The outbox publishes a persistent message with broker confirmation. Queue outages leave the upload queued for retry.
  5. 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.
  6. Status is available at GET .../uploads/:id. Ready files receive short-lived signed URLs from GET .../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/catalog returns 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:check verifies 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.

Documentation overview