Skip to content

Repository files navigation

HR Assist

Centralized employment-verification platform for Kenyan companies.

HR Assist is the authoritative record of who worked where. Companies onboard their HR teams, HR records real employment against National IDs, and anyone with a need to verify a candidate's history (hiring managers, auditors, banks, landlords) runs a single search and gets a hash-chained, court-quality answer.

The system is keyed by National ID, not user accounts: a person's work history exists from the moment HR records it, regardless of whether the subject ever signs up. They can later create an account, prove the ID belongs to them, and the platform automatically links the existing history to their profile.

What's in the box

  • Authoritative records with cryptographic integrity hashes — nothing can be edited after finalisation; only terminations may be appended.
  • Hash-chained audit log — every state change is sha256-linked to the row before it, so any tampering is detectable. A nightly cron walks the chain and reports the first bad row.
  • Identity claim flow — users upload an ID photo, an admin reviews, the photo is shredded immediately after the review. No long-term storage of sensitive PII images.
  • Anti-collusion guard — Standard HRs cannot record or terminate work experiences for other HR staff at their own company; only the Head HR can. The HR's own employment record is created automatically on their appointment, so they never need to violate the self-block rule.
  • Multi-company support — a person may be HR (Head or Standard) at any number of companies simultaneously. Companies are independent — there is no cross-company "transfer" action.
  • Role-aware UI — System Admin, Head HR, Standard HR, and Employee each see a sidebar tailored to what they're allowed to do.

Tech stack

Layer Choice
Runtime PHP 8.3, Laravel 12
Auth Laravel Sanctum + TOTP 2FA
Frontend Server-rendered Blade + Tailwind (CDN) + Alpine.js
Database MySQL 8
Cache, sessions, queue Redis 7
Identity verification Smile ID (default) or Korapay (alternate)
Container Docker + docker-compose

Quick start (Docker)

Prerequisites: Docker Desktop. Nothing else is required on the host.

git clone https://github.com/Exile10/HR-Assist.git
cd HR-Assist
cp .env.example .env

docker compose up -d
docker compose exec app composer install
docker compose exec app php artisan key:generate
docker compose exec app php artisan migrate
docker compose exec app php artisan db:seed --class=Database\\Seeders\\MasterSeeder

Open http://localhost:8080.

MasterSeeder populates the database with one curated account per scenario (every role, every lifecycle event, every identity-claim state) plus enough bulk volume to test pagination and filters. It prints the full credentials list when it finishes; every account uses the password Demo!Pass2026.

A condensed walkthrough of the personas is in docs/scenarios.md.

What runs where

Service Host port Notes
App (nginx → php-fpm) 8080 The web UI and the JSON API at /api/v1
MySQL 3307 Connect with 127.0.0.1:3307, user hr_assist, pass secret
Mailpit 8025 Catches all outbound mail in dev
Redis (internal) Sessions, cache, queue

A queue worker and a scheduler container are also part of the compose file — they start automatically.

Roles and what each one can do

There are four roles. A user may hold more than one role across companies.

System Administrator — full override. Manages companies, identity claims, disputes, fraud cases, and audit. Can suspend/activate companies and appoint or revoke Head HRs.

Head HR (per company) — the senior HR for one specific company. Adds and removes Standard HR staff at their company, records and terminates work experiences (including for HR staff at the company), promotes Standard HRs to Head HR. The platform creates their own work-experience record automatically when they're appointed; they fill in their responsibilities themselves.

Standard HR (per company) — records work experiences and terminations for non-HR employees at one specific company. Cannot record their own employment (self-block) and cannot record for other HR staff at their company (anti-collusion). May search any National ID.

Employee — anyone with an account. Sees the work history recorded against their National ID, raises disputes when a record is wrong, manages their profile and 2FA. Identity verification is optional but unlocks the "verified" badge on their record.

Two-factor authentication

Each user can enable TOTP-based 2FA on their profile.

  1. Sign in, open Profile → Two-factor authentication, click Set up 2FA.
  2. Scan the QR code with Google Authenticator, 1Password, Authy, or similar. The same screen also shows the secret string for manual entry.
  3. Enter the 6-digit code the app generates and click Confirm & enable.
  4. From the next sign-in onward, after entering email + password the system asks for a fresh 6-digit code.

To disable 2FA later, the user must confirm with their current password. Each enable / disable is recorded in the audit log.

Identity verification

The platform calls a third-party identity API to verify the National ID against the Kenya National Registration Bureau. Two providers are wired up; pick one with NRB_DRIVER in .env.

  • smileid (default) — Smile ID Enhanced KYC. Get a partner ID and base64 API key from https://portal.usesmileid.com. Sandbox is free.
  • korapay — Korapay's identity API. Get a secret key from the Korapay dashboard.
  • fake — for offline development; always returns a synthetic match.
  • noop — degrades to "could not contact NRB" without making a request.

The NRB call from the admin "Identity claims" review is currently untested end-to-end; the integration code is in place and matches the published API contracts but you'll need a real sandbox key to run a live verification.

Documentation

Development

Run the test suite:

docker compose exec app php artisan test

The suite includes unit tests for the National ID validator and feature tests for register, login (including lockout), 2FA, RBAC, experience creation (with the self-block rule), and the audit hash chain.

To wipe and reseed:

docker compose exec app php artisan migrate:fresh
docker compose exec app php artisan db:seed --class=Database\\Seeders\\MasterSeeder

To stop the project (frees ports for other projects on the same machine):

docker compose stop                  # pause; volumes preserved, fast restart
docker compose down                  # stop + remove containers; volumes preserved
docker compose down -v               # also drop volumes (full wipe)

License

Proprietary. Unauthorised reproduction or use is prohibited.

About

Centralized employment-verification platform for Kenyan companies — Laravel 12, MySQL 8, hash-chained audit log, identity claims, anti-collusion guard, multi-company HR.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages