# HR suite — scope decision

**Status:** Suite complete + follow-ups shipped · **Date:** 2026-08-11 · **Next:** Insights / ATS / statutory / biometrics only  
**Source of truth for full schema/UI:** `vaops` (`074_hr_module.sql` + `backend/src/modules/hr*` + `frontend/src/pages/hr/*`)

This document is the gate for porting Attendance, Leave, Payroll, Fines, Assets, and Offboarding into WorkspaceOS (myspace / company-api).

---

## Decision

**Do not lift the entire vaops HR suite in one migration or PR.**

Port in thin vertical slices, each with its own migration, RBAC module keys, API, and UI. Ship **no HR nav items** until the first approved slice has a working screen.

Employee enrichment already landed (`060_employee_enrichment.sql`): manager, employment lifecycle, personal fields, `shift_mode`, basic salary, and portal provisioning. That is **not** the HR suite — it is prerequisite data only.

`hr_shift_policies` / `employee_shift_overrides` tables may already exist from enrichment. Treat them as **schema placeholders**. Do not add `hrShifts` routes, services, or nav until Phase A.

---

## Out of scope for the initial port

| Item | Reason |
|------|--------|
| Big-bang `074` dump | Too large; couples attendance → fines → payroll |
| HR Performance engine | myspace already has `/employee-performance`; avoid a second scoring system |
| HR Insights dashboard | Depends on attendance/leave/payroll data that does not exist yet |
| HR nav module in the rail | navConfig deliberately omits Hiring/HR until screens exist |
| Replacing employee portal auth | Already complete via `employeeUserAccount.ts` |

---

## Phased build order

Dependencies flow downward: later phases assume earlier ones are live.

### Phase A — Time foundation (first `hr_*` modules) — DONE

**Include:** Shifts admin + Attendance (punches, day ledger, holidays used for attendance calc).

| Deliverable | Notes |
|-------------|-------|
| `hrShifts` | CRUD global policy + per-employee override; wire `employees.shift_mode` |
| `hrAttendance` | Clock in/out (self), corrections (admin), day status |
| `hrHolidays` | Calendar for attendance day status (full leave module is Phase B) |
| Permissions | `hr_shifts`, `hr_attendance`, `hr_holidays` (+ `punch_own`, `punch_correct`, …) |
| UI | `/hr-shifts`, `/hr-attendance`, `/hr-holidays` under nav module **HR** |
| Migration | `061_hr_shifts_attendance.sql` |

**Exit criteria:** An active employee can punch against company or custom shift; admins see a day board.

### Phase B — Leave — DONE

**Include:** Leave types, balances, requests (approve/reject). Holidays remain Phase A (`/hr-holidays`).

| Deliverable | Notes |
|-------------|-------|
| `hrLeave` | Types, balances, requests; approve marks attendance `on_leave` |
| Day count | Skips weekends/non-work days via shift schedule + `hr_holidays` |
| Permissions | `hr_leave`, `hr_leave_types` |
| UI | `/hr-leave` under nav module **HR** |
| Migration | `062_hr_leave.sql` |

**Exit criteria:** Employee requests leave; manager/admin approves; balance updates; attendance days marked `on_leave`.

### Phase C — Offboarding — DONE

**Include:** Exit case + checklist; updates `employment_status` / account `status` on complete.

| Deliverable | Notes |
|-------------|-------|
| `hrOffboarding` | Case + checklist items |
| Lifecycle link | Start → `notice`; complete → `exited` + employee inactive + portal deactivate |
| Permissions | `hr_offboarding` |
| UI | `/hr-offboarding` under nav module **HR** |
| Migration | `063_hr_offboarding.sql` |

**Exit criteria:** One resignation flow completes and locks the portal login.

### Phase D — Assets & policies — DONE

**Include:** Asset inventory/assignment; policy docs + acknowledgements.

| Deliverable | Notes |
|-------------|-------|
| `hrAssets` | Inventory, categories, assign / return / retire |
| Policies | Same `hr_assets` RBAC; ack tracking via `/api/hr/policies` |
| Deferred | `employee_documents` (storage-heavy; optional) |
| Permissions | `hr_assets` |
| UI | `/hr-assets`, `/hr-policies` under nav module **HR** |
| Migration | `064_hr_assets_policies.sql` |

**Exit criteria:** Laptop assigned on hire path; policy ack recorded.

### Phase E — Fines — DONE

**Include:** Fine policies + ledger. **Requires Phase A attendance.**

| Deliverable | Notes |
|-------------|-------|
| `hrFines` | Policies, exemptions, ledger; reversible rows |
| Engine | Replaces Phase A stub; attendance rollup / ignore_prompt call `evaluateForEvent` |
| Permissions | `hr_fine_policies` (+ `exempt_employee`) |
| UI | `/hr-fines` (Policies + Ledger tabs) |
| Migration | `065_hr_fines.sql` |

**Exit criteria:** One late punch can create a reversible ledger row.

### Phase F — Compensation & payroll — DONE

**Include:** Salary components beyond `basic_salary`, payroll periods/lines. **Requires A + B + E for full deductions.**

| Deliverable | Notes |
|-------------|-------|
| Compensation | Components + per-employee amounts (`/api/hr/payroll/compensation`) |
| `hrPayroll` | Periods, lock (locks attendance), compute lines, approve |
| Payslips | HTML preview/print + email via `systemMailer` / Company SMTP |
| Permissions | `hr_payroll`, `hr_compensation` |
| UI | `/hr-payroll` (Periods / Compensation / Preview) |
| Migration | `066_hr_payroll.sql` |

**Exit criteria:** One locked period with net pay for a small employee set.

### Follow-up — Employee documents — DONE

| Deliverable | Notes |
|-------------|-------|
| `employee_documents` | Storage-backed vault; soft-delete → recovery |
| Permissions | `hr_documents` |
| UI | `/hr-documents` |
| Migration | `067_employee_documents.sql` |
| API | `/api/hr/documents` |

### Follow-up — HR Performance Engine — DONE

Separate from CRM **Employee Performance** (`/employee-performance`).

| Deliverable | Notes |
|-------------|-------|
| Settings + snapshots | Weights for tasks / CRM / attendance / fines |
| Permissions | `hr_performance` |
| UI | `/hr-performance-engine` |
| Migration | `068_hr_performance_engine.sql` |
| API | `/api/hr/performance-engine` |

---

## Explicit deferrals

1. **Country-specific statutory payroll** — not in vaops either; stay with simple net-pay lines.
2. **Biometric / device punch sources** — self + admin correction only in Phase A.
3. **Hiring ATS** — separate product area; not part of this HR suite decision.
4. **HR Insights dashboard** — optional analytics surface.

---

## Engineering rules

1. **One phase ≈ one migration series + one PR stack** (BE then FE), not a mega-PR.
2. **Reuse** employee enrichment columns; do not duplicate salary/manager on new tables without a join reason.
3. **Recovery / audit** — soft-delete + audit for HR entities, same as employees/projects.
4. **Portal** — staff login stays on existing employee portal users; HR self-service (punch/leave) uses the same auth.
5. **Fines** — `hrFines/fineEngine.evaluateForEvent` is live (Phase E).

---

## Current myspace state (baseline)

| Area | State |
|------|--------|
| Portal user provisioning | Done |
| Manager / employment lifecycle / salary / shift_mode | Done (enrichment) |
| `hr_shift_policies` / `employee_shift_overrides` | Live (enrichment + Shifts UI) |
| Attendance + holidays modules | Phase A done |
| Leave | Phase B done |
| Offboarding | Phase C done |
| Assets + policies | Phase D done |
| Fines | Phase E done |
| Payroll | Phase F done (payslip email enabled) |
| Employee documents | Done (`067`) |
| HR Performance Engine | Done (`068`) |
| HR nav | Full suite A–F + documents + performance engine |

---

## Next action when ready to build

Remaining deferrals: Insights, ATS, statutory payroll, biometrics. Run migrations `067` then `068` on deploy.
