Spyrl — Product Requirements Document (PRD)
Version: 1.0 · Date: 2026-10-31 · Status: Draft for review Related: brd.md (business requirements) · architecture.md · project-plan.md · summary.md · research/spryple-analysis.md · CONVENTIONS.md
This PRD defines what Spyrl must do, module by module, so that design, engineering and QA can build and verify it. It turns the business requirements in brd.md and the feature disposition in research/spryple-analysis.md (§19) into functional requirements, user stories, permissions, UI/UX rules, notifications, reports and non-functional requirements. Names, module codes, roles, ID schemes and release scope follow CONVENTIONS.md. If this document disagrees with CONVENTIONS.md, CONVENTIONS.md wins.
1. Document control
| Item | Value |
|---|---|
| Document | Product Requirements Document (PRD) |
| Product | Spyrl (working name), a multi-tenant HCM + Field-Force CRM SaaS for Indian SMEs |
| Owner | Product Management |
| Reviewers | Engineering lead, Payroll/compliance SME, QA lead, Security lead, Design lead |
| Approvers | Founder/CEO, Head of Engineering |
| Source of truth for IDs and scope | CONVENTIONS.md §3–§7 |
| Upstream | brd.md (BR-* requirements, business rules, objectives BO-*) |
| Downstream | Module design specs in the documentation site (modules/), the feature catalogue (features/), the API catalogue, test plans |
1.1 Revision history
| Version | Date | Author | Change |
|---|---|---|---|
| 0.1 | 2026-10-31 | Product | First complete draft from research baseline v1.0 and architecture v1.0 |
| 1.0 | 2026-10-31 | Product | Review-ready draft: all 16 modules, NFRs, catalogues, traceability |
1.2 How to read this document
- Evidence labels. Every statement about the reference product carries [Observed] (the Spryple Help Center documents it, cited with a role code and page, e.g.
(A: Leave Management)) or [Inferred] (it follows from documented workflows). Facts that come from screenshots reviewed in research §21 are cited as(research §21.x). Everything we design ourselves is [Proposed]. Spryple feature IDs (SP-<MOD>-NN) come from the research. - Requirement IDs.
FR-<MOD>-NNN(functional),NFR-<CAT>-NN(non-functional),US-<MOD>-NN(user story, acceptance criteriaAC1..nin Given/When/Then). IDs are stable: a removed requirement keeps its ID with the status "Withdrawn"; it is never renumbered. - Priority is MoSCoW for the release named in the row: Must (release cannot ship without it), Should (important; may slip one release with sign-off), Could (include if capacity allows), Won't (explicitly out of scope for that release; recorded to stop scope creep).
- Release is the release in which the requirement is first delivered (R0–R4, see §5). R0 items ship to customers as part of the R1 MVP general availability (GA).
- Statutory values (rates, ceilings, slabs, due dates, thresholds) are configurable examples to verify with a payroll/compliance expert before each release. The product never hard-codes them; they come from the versioned statutory pack (FR-PLT-009).
- Business traceability. Each module section lists the BRD module it traces to (e.g. "Traces to: BR-ATT-*"). Requirement-level links to individual BR IDs are maintained in the requirements tool once brd.md is baselined.
1.3 Role abbreviations used in permission matrices
| Abbrev. | Role key (CONVENTIONS.md §4) | Abbrev. | Role key |
|---|---|---|---|
| OWN | org_owner | SLA | sales_admin |
| HRA | hr_admin | SLM | sales_manager |
| HRM | hr_manager | FEX | field_executive |
| FNA | finance_admin | KIO | kiosk_operator |
| PRM | payroll_manager | INS | instructor |
| LM | line_manager (derived from reports_to) | AUD | auditor (read-only) |
| EMP | employee (everyone has it) | PLA / SUP | platform_admin / support_engineer |
Matrix cells show the default data scope of the seeded role: SELF, TEAM, DEPT, LOC, ORG, ORG(R) (read-only), — (no access). LOC* means "ORG or LOCATION, chosen at role assignment" as in CONVENTIONS §4. Tenants can clone and change seeded roles (FR-IAM-010); the matrices describe the seeded defaults only.
2. Product overview and vision
2.1 Problem
Indian SMEs with 10–1,000 employees run attendance, leave and payroll on spreadsheets, a biometric device's desktop software and a payroll accountant. Field-sales teams add WhatsApp check-ins and paper travel claims. The result is late and disputed salaries, missed statutory filings (EPF, ESI, PT, LWF, TDS), no audit trail and high HR effort at every month-end. Existing tools either cover HR without field force, or are enterprise suites that are too expensive and too hard to configure. See brd.md for the business case and objectives.
The reference product, Spryple, proves the demand for an SME suite that chains attendance → leave → payroll and adds field-force tracking [Observed] (research §1). It also shows the structural problems we must avoid: policies that are not effective-dated, duplicated rule screens, fixed leave types, default shared passwords, four separate mobile apps and missing statutory outputs [Observed/Inferred] (research §1, §17, §18).
2.2 Vision
"From punch to payslip, correctly, every month, without spreadsheets." Spyrl is the one system an Indian SME needs to know who worked, where, and what to pay them, compliant by default and simple enough that a 20-person company can go live in a week.
2.3 Product goals (MVP horizon)
| # | Goal | Measure (target at 6 months after R1 GA) |
|---|---|---|
| G1 | Fast self-serve go-live | Median time from sign-up to first locked payroll run ≤ 21 days; setup-wizard completion ≥ 70% of trials |
| G2 | Correct pay without manual adjustment | ≥ 98% of payslips need no post-lock correction (measured by reversal and off-cycle correction runs) |
| G3 | Statutory outputs ready on time | 100% of locked runs produce ECR, ESI, PT and bank files that pass format validation |
| G4 | Self-service adoption | ≥ 60% monthly active employees on mobile (ESS); ≥ 80% of leave and regularization requests raised by employees, not HR |
| G5 | Month-end effort cut | HR/payroll time from period close to payroll lock ≤ 2 working days for tenants ≤ 200 employees (customer survey + run timestamps) |
| G6 | Trust | Zero cross-tenant data incidents; zero default passwords; MFA on 100% of admin accounts |
2.4 Target customers and plans
| Segment | Typical profile | Plan (architecture.md §14) |
|---|---|---|
| Micro business | 5–50 staff, shop, clinic, small factory; owner runs HR on a phone | Lite: attendance + simple payroll, mobile-first |
| SME, office/plant | 50–500 staff, 1–10 locations, shifts, a part-time HR + payroll person | Standard: Core HR, ATT, LVE, PAY, ESS/MSS |
| SME, growing | 200–1,000 staff, multi-state, field teams | Professional: + CLM, EXT/F&F, ENG, SSO, API, advanced reports; add-ons FFM, TSM, LMS |
| Large or regulated | 1,000+ staff or isolation demands | Enterprise: dedicated cell, custom domain, SAML, 99.9% SLA |
"Lite" is an entitlement profile on the same product, not a separate app or data model [Proposed] (research §15, §19).
2.5 Scope summary
In scope (R0–R4): the 16 modules in CONVENTIONS.md §3. Out of scope until after R4: recruitment/ATS, performance management, surveys, asset management, helpdesk, invoicing for timesheets, CRM quotes/orders, payroll outside India (see §15).
3. Personas
Personas are written per role key. One person can hold several roles (e.g. the owner of a 30-person company is org_owner, hr_admin and payroll_manager).
| Role key | Persona | Goals | Pain points today | Primary surfaces |
|---|---|---|---|---|
org_owner | Ramesh, owner-director of a 120-person auto-parts unit in Pune | See headcount, attendance and payroll cost; approve payroll; stay compliant | Surprises at month-end; no single view; fear of PF/ESI notices | Web dashboard, mobile approvals |
hr_admin | Priya, HR lead who configures the system | Set up masters and policies once; change them safely mid-year | Rule changes that only apply to new joiners; duplicated settings | Web (setup, policies) |
hr_manager | Kavya, HR executive who runs daily operations | Onboard quickly, fix attendance, answer employee queries | Chasing documents; manual data entry; Excel imports that fail silently | Web; mobile for approvals |
finance_admin | Suresh, finance controller | Configure salary structures, statutory settings and bank accounts correctly | Statutory rates changing by state and date; formula errors | Web |
payroll_manager | Anil, payroll accountant (often an external consultant) | Run payroll in hours, not days; file statutory returns on time | Re-keying attendance; no variance check; portal files built by hand | Web (payroll workbench) |
line_manager | Deepa, production supervisor with 25 operators on 3 shifts | Approve requests fast; see who is absent; plan shifts and swaps | Requests on WhatsApp; no team calendar; shift swaps on paper | Mobile first; web for rosters |
employee | Imran, machine operator / office staff | Punch easily; apply for leave; see payslip and balance | Disputed absences; no visibility of balance or salary breakup | Mobile (ESS), kiosk |
field_executive | Lakshmi, medical representative visiting 12 doctors a day | Punch from the field; log visits; get travel paid | Manual visit reports; slow travel claims; battery drain | Mobile only |
sales_admin | Vikram, sales operations | Configure pipeline stages, territories and masters | Pipeline that does not match their sales process | Web |
sales_manager | Farhan, regional sales manager | See team location and visits; approve travel; move the pipeline | No proof of visits; inflated kms | Web map; mobile |
kiosk_operator | Front-desk receptionist at a plant gate | Punch staff in and out on a shared tablet | Buddy punching; queues at shift change | Mobile in kiosk mode |
instructor | Training coordinator | Publish mandatory courses; track completion | Paper attendance for POSH and safety training | Web |
auditor | Statutory or internal auditor (time-boxed) | Read records and audit logs without changing anything | Asking HR for exports | Web (read-only) |
platform_admin, support_engineer, billing_admin, release_manager | Spyrl staff | Provision, support and bill tenants safely | Not applicable (internal) | Platform admin console |
4. Product principles
| # | Principle | What it means in requirements | Anti-pattern we avoid (reference) |
|---|---|---|---|
| P1 | Configuration over customization | Every tenant difference is expressed through plans, feature flags, typed policies, masters, custom fields, templates or workflows (architecture.md §8). No per-tenant code branches. A request that cannot be met by configuration becomes a product feature behind a flag, available to all tenants on that plan. | Implementation-team Excel templates and vendor-side setup [Observed] (M: Attendance Management) |
| P2 | Effective-dated policies | Policies, assignments, compensation and statutory tables are versioned with valid_from/valid_to. Every change asks "effective from when?" and "apply to whom?" and shows the affected employees before saving. Recalculation is deterministic and reproducible. | "Changes do not affect existing employees" [Observed] (A: Employee Management; A: Leave Management) |
| P3 | One place for each rule | Each setting exists in exactly one typed policy, with help text and an example generated from its schema. No numbered free-text rules. | Probation, notice, lates and default shift each configured twice [Observed] (research §17 D4, D5) |
| P4 | Mobile-first ESS | Every employee and line-manager task in R1 is fully doable on the mobile app: punch, requests, approvals, payslips, balances. The web app is primary for configuration and payroll. One app for all roles. | Four separate apps [Observed] (research §15) |
| P5 | India compliance by default | EPF, ESI, PT, LWF, TDS, gratuity and statutory files are built in and driven by a centrally published, effective-dated statutory pack. Rates are data, never code. | Manually typed TDS; statutory "reports" instead of portal files [Observed/Inferred] (M: Payroll Management) |
| P6 | Privacy by design | Data minimisation; purpose-tagged sensitive fields; explicit consent for face and location; location only between punch-in and punch-out; masking by default; retention schedules; DPDP rights built in. | Plaintext password emails; "No data collected" store listing for a GPS app [Observed] (research §21.1, §21.2) |
| P7 | Secure by default | No default passwords, invite activation, MFA for admin roles, least-privilege roles with data scopes, full audit trail. | "Welcome1!" default password [Observed] (A: Employee Management) |
| P8 | Explainable numbers | Every computed value (day status, leave balance, payslip line, TDS) can show "how was this calculated?" with its inputs and policy version. | Opaque lates-to-leave deductions [Inferred] |
| P9 | Build less, finish more | The MVP covers attend-to-pay end to end before anything else. Breadth (LMS, CRM pipeline richness) waits until the core is proven. | — |
5. Release plan summary
Consistent with CONVENTIONS.md §7. Dates and milestones are in project-plan.md.
| Release | Theme | Modules and headline scope | Exit criteria (summary) |
|---|---|---|---|
| R0 | Foundations | PLT (provisioning, plans, entitlements, flags, statutory pack publishing), IAM (invite activation, MFA, roles × scopes, audit; OIDC SSO follows in R1), ORG (masters, policy framework, import framework, setup wizard), NTF core (templates, email/SMS/push, approval engine), CI/CD, observability | Tenant can be provisioned in < 2 min; isolation test suite green; audit on all writes |
| R1 — MVP | Attend-to-Pay core | EMP (hire, self-onboarding, directory, documents, checklists, job history), ATT (web/mobile punch with selfie + geo-fence, shifts, rotations, swaps, week-offs, regularization, permissions, OT with approval, extra days, penalties, biometric CSV/API import, period lock), LVE (leave-type builder, ledger, accruals, holidays, comp-off), PAY (structures, compensation, run lifecycle, EPF/ESI/PT/LWF/TDS with IT declarations, ECR/ESI/PT/LWF/bank files, payslips, arrears, variable pay, advances and loans, off-cycle), RPT (standard reports and dashboards), MOB (ESS + MSS) | MVP acceptance checklist (§16.2) passed by 3 pilot tenants running one parallel payroll each |
| R2 | Complete HR lifecycle | CLM, EXT (+ F&F), ENG, MOB kiosk + face verification, biometric device gateway, Form 16 / 24Q outputs, payroll journal export, public API and webhooks, SAML, multi-level (N-level) approvals | F&F settles through PAY; Form 16 generated for a full tax year in pilot |
| R3 | Field and projects | FFM (tracking with consent, visits, configurable pipeline, travel → CLM mileage), TSM (projects, weekly timesheets, approvals), calendar sync | Field add-on sold to ≥ 5 tenants; GPS ingest meets NFR-SCL-04 |
| R4 | Learning and scale | LMS (mandatory courses, completion, certificates), advanced analytics (custom reports, scheduled delivery at scale), dedicated-cell automation, accounting/ERP API connectors | Dedicated cell provisioned in < 1 day without manual steps |
Decisions that reconcile source documents.
- Accounting integration: a payroll journal file export (CSV and Tally XML) is in R2 (architecture.md §16); API connectors to Zoho Books and ERPs are in R4 (CONVENTIONS.md §7 "accounting/ERP integrations").
- TDS: the TDS engine with regime choice, IT declarations and proof submission is R1 (CONVENTIONS.md §7; research §21.11 notes Spryple shows "IT Declaration" in its menu). Form 16 and 24Q return data are R2.
- Attendance capture: R1 has web punch, mobile punch with selfie + geo-fence, and biometric CSV/API import. The device push gateway, kiosk mode and face verification are R2.
- Approvals: R1 supports up to two levels with delegation, conditions and escalation; arbitrary N levels (max 5) arrive in R2 (research §18).
6. Shared concepts used by all modules
These concepts are specified once here and referenced by module requirements.
6.1 Typed, effective-dated policies
A policy is a typed configuration object (JSON-schema validated, architecture.md §2.2) with versions. Each version has valid_from, an optional valid_to, a status (draft, active, retired) and a change note. A policy assignment links a policy to employees through applicability rules evaluated on the employee's effective job assignment: location, department, designation, grade, employment type, and optionally a named employee list.
| Concept | Rule |
|---|---|
| Resolution | For an employee on a date, the engine picks the assignment with the highest specificity (named list > designation > grade > department > location > employment type > tenant default). Ties are a validation error at save time. |
| Default | Every policy type has exactly one tenant-default assignment, so every employee always resolves to a policy. |
| Change | Editing an active policy creates a new version with a chosen valid_from. If valid_from is in a period that is not locked, affected days and balances are recomputed. Locked periods are never changed; differences flow as arrears or adjustments (FR-PAY-040, FR-LVE-022). |
| Preview | Before activation the UI shows the number and list of affected employees and, for attendance and leave, the number of days or balances that will be recomputed. |
| Policy types (R1) | password_policy (IAM), attendance_policy, shift, geofence, overtime_policy, regularization_policy (ATT), leave_policy per leave type, holiday_calendar (LVE), probation_notice_policy (EMP), pay_schedule, salary_structure, statutory_settings, payroll_policy (PAY), approval_workflow (NTF) |
6.2 Standard request lifecycle
All employee requests (attendance request, regularization, permission, shift change, leave, leave cancellation, comp-off, optional holiday, advance salary, IT declaration, claim, separation, timesheet) use the same base state machine, generalised from Spryple's approval pattern [Observed] (research SP-X-03).
- On-behalf requests: a user with the approve permission for the employee at the required scope may raise a request on the employee's behalf. It is auto-approved at that user's level and below, records
raised_byand a mandatory reason, and notifies the employee. Higher levels, if configured, still apply. Spryple auto-approves all on-behalf requests [Observed] (research SP-X-04); we add the reason, audit and higher-level check [Proposed]. - Locked periods: a request that touches a date inside a locked attendance/payroll period is blocked, or becomes an adjustment request that flows to the next open period (ATT and PAY define which).
- Delegation: an approver can delegate for a date range; the delegate's actions are recorded "on behalf of".
6.3 Audit, explainability and identifiers
- Every create/update/delete and every approval writes an
audit_event(actor, on-behalf-of, tenant, entity, before/after hash, IP, device, timestamp) (architecture.md §7). - Computed records (day status, balance, payroll line) store their inputs and policy version IDs, so the UI can show "how calculated".
- Human-readable IDs are per tenant and sequence-safe: employee code (configurable pattern, FR-ORG-004), request numbers
REQ-{MOD}-{YYYY}-{NNNNN}, claim IDCLM-{YYYY}-{NNNNN}, payroll runPR-{YYYYMM}-{NN}.
6.4 Masters pattern
All masters (departments, designations, leave types, expense categories, pipeline stages and so on) share one behaviour, generalised from Spryple [Observed] (research SP-X-01): create, edit, Active/Inactive, case-insensitive duplicate-name rejection, and deactivation that requires reassignment of linked active records. We add bulk reassignment, CSV import/export, and a "used by" count [Proposed].
7. Module specifications
Modules appear in CONVENTIONS.md §3 order. Each module has the same sub-sections. FR tables use the columns ID · Requirement · Priority · Release · Label.
7.1 PLT — Platform & Tenant Administration (control plane)
Traces to: BR-PLT-* · Release: R0 core, R1 billing and lifecycle, R2/R4 dedicated cells · Architecture: architecture.md §3–§5, §9, §14, §15
7.1.1 Purpose and scope
PLT is the control plane that Spyrl staff use to provision, configure, bill, support and upgrade tenants. Tenants see only a small part of it: their plan, usage, invoices, support-access log and data export.
| In scope | Out of scope |
|---|---|
| Tenant registry and lifecycle; self-serve trial; plans, entitlements and add-ons; feature flags; cell registry and placement; statutory pack publishing; metering and billing; break-glass support access; tenant export and deletion; platform announcements; health scores; custom domains; dedicated cells | Reseller/partner portal (post-R4); multi-region outside India; on-premise installs (architecture.md §10.2) |
7.1.2 Reference product summary
- Spryple's "Super Admin" is a tenant role (company owner), not a platform operator; the control plane is not exposed [Inferred] (research §3.2).
- Every Spryple login asks for a Company Code, which implies a shared multi-tenant deployment [Observed] (research SP-X-10); a self-serve trial exists at
trial.spryple.com[Observed] (research §21.1). - Onboarding is vendor-assisted: "the implementation team will provide the suggested Excel sheet" [Observed] (M: Attendance Management).
7.1.3 What we change and why [Proposed]
- A separate control plane with its own database is the system of record for tenants, plans, cells and flags (ADR-004), so tenant operations never require database access in the app plane.
- Self-serve provisioning in under 2 minutes, so trials do not depend on an implementation team.
- Statutory rates are published centrally as a versioned pack that each tenant inherits, so a PT slab change reaches every tenant once, with a change log.
- Support access is consented, time-boxed and visible to the tenant, replacing informal vendor access.
7.1.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-PLT-001 | Maintain a tenant registry with id, slug, company_code, legal name, plan, cell, region and status trial → active → past_due → suspended → churned → deleted; every status change is audited with actor and reason. | Must | R0 | [Proposed] |
| FR-PLT-002 | Self-serve sign-up (company name, owner name, work email, mobile with OTP, employee-count band, slug) provisions a tenant in a pooled cell in < 2 minutes: tenant row, seeded reference data (statutory pack, role templates, leave-type templates, notification templates), owner invite. Provisioning is idempotent and resumable. | Must | R0 | [Proposed] |
| FR-PLT-003 | Slugs are unique, 3–30 lowercase alphanumeric/hyphen characters, immutable after creation; a rename creates an alias that redirects. The company code for mobile login is a separate, human-friendly alias that can be changed by the owner. | Must | R0 | [Proposed] |
| FR-PLT-004 | Plans (Lite, Standard, Professional, Enterprise) and add-ons (Field Force, Timesheets, LMS, Face verification, WhatsApp) are defined as entitlement sets feature_key → limit. Tenant overrides are allowed. The app checks entitlements through a cached SDK (TTL ≤ 60 s). Disabled modules are hidden from navigation and their APIs return 403 entitlement_required. | Must | R0 | [Proposed] |
| FR-PLT-005 | Plan limits are soft: warn the owner at 90% and 100% of the employee limit; block creation of new active employees above 105%. Payroll processing, payslip access and statutory exports are never blocked for billing reasons between the 25th and the 5th without platform_admin approval. | Must | R1 | [Proposed] |
| FR-PLT-006 | Feature flags (OpenFeature-compatible) per tenant, cell, plan or percentage, including kill switches. Flag changes are audited and take effect in ≤ 60 s. | Must | R0 | [Proposed] |
| FR-PLT-007 | Cell registry (type pooled/dedicated, region, version, wave, capacity metrics) and tenant placement by plan and capacity rules (architecture.md §13 capacity triggers). | Must | R0 | [Proposed] |
| FR-PLT-008 | Move a tenant between cells with a logical export/import by tenant_id, row-count and checksum verification, and a routing cut-over; read-only window ≤ 30 minutes for a 1,000-employee tenant. | Should | R2 | [Proposed] |
| FR-PLT-009 | Publish a statutory pack: versioned, effective-dated reference data (EPF/EPS/EDLI rates and wage ceilings, ESI rates and thresholds, PT slabs by state, LWF by state, income-tax slabs and rebates by tax year and regime, gratuity ceiling, minimum wages where loaded). Tenants inherit the latest pack by default; a tenant may pin a version for a run with a reason. Payroll managers see a change log and an in-app banner when a new pack affects their states. | Must | R0 | [Proposed] |
| FR-PLT-010 | Daily usage metering per tenant: max active employees, GPS-tracked users, face-enrolled employees, SMS and WhatsApp counts, storage GB. Tenants see their own usage on a Billing page. | Must | R1 | [Proposed] |
| FR-PLT-011 | Billing through Razorpay Subscriptions: PEPM pricing with plan minimums, add-ons and metered usage; GST-compliant invoices; payment methods UPI AutoPay, cards, e-mandate; dunning with a 7-day grace banner, then suspended (read-only, payroll export still allowed). | Must | R1 | [Proposed] |
| FR-PLT-012 | Break-glass support access: a support_engineer requests access with a ticket reference and reason; scope read-only by default, write only with owner consent; time-box default 2 h, max 8 h; when the plan requires it, the tenant owner must consent in-app; every action is audited and listed in the tenant's Support access log. | Must | R0 | [Proposed] |
| FR-PLT-013 | Tenant data export on demand by org_owner: all entities as CSV/JSON plus a documents zip, delivered as an expiring link (24 h) and audited. | Must | R1 | [Proposed] |
| FR-PLT-014 | Tenant deletion: request by owner or after churn; grace period per contract (default 30 days, max 90); legal hold blocks deletion; deletion removes data from the database and object storage and issues a deletion certificate. Statutory payroll records are exported to the owner before deletion. | Must | R1 | [Proposed] |
| FR-PLT-015 | Platform announcements (in-app banner and email) targeted by plan, cell or tenant, with schedule and dismissal. | Should | R1 | [Proposed] |
| FR-PLT-016 | Tenant health score from activation (setup completion), adoption (DAU/MAU, punches per employee) and risk (failed runs, open tickets, past-due), shown on the platform console. | Should | R1 | [Proposed] |
| FR-PLT-017 | Platform admin console with platform roles (platform_admin, support_engineer, billing_admin, release_manager), mandatory MFA and IP allow-listing. | Must | R0 | [Proposed] |
| FR-PLT-018 | Rollout management: cell versions, waves, maintenance windows, per-tenant release notes; the payroll-window change freeze (25th–5th) is enforced for payroll-impacting flags. | Should | R1 | [Proposed] |
| FR-PLT-019 | Custom domain for Enterprise tenants: CNAME + TXT verification, automatic TLS, health check. | Should | R2 | [Proposed] |
| FR-PLT-020 | Dedicated-cell provisioning (own database on a shared app tier, or full stack) through Terraform modules with the same seed steps; assisted in R2, fully automated in < 1 day in R4. | Should (R2) / Must (R4) | R2/R4 | [Proposed] |
| FR-PLT-021 | Sandbox tenant for Enterprise: a copy of configuration (no personal data) refreshed on request. | Could | R2 | [Proposed] |
| FR-PLT-022 | Optional sample data at trial creation (fictional employees, one month of punches), removable with one action before go-live. | Could | R1 | [Proposed] |
7.1.5 Key entities
tenant (id, slug, company_code, legal_name, plan_id, cell_id, region, status, trial_ends_at), plan, entitlement (feature_key, limit), tenant_override, cell (type, region, version, wave, dsn_ref), feature_flag, statutory_pack (version, published_at, effective_from, items[]), usage_daily (tenant, metric, value, date), subscription, invoice, support_access_grant (engineer, reason, scope, starts, ends, consented_by), tenant_export, deletion_request.
7.1.6 Configuration settings
| Setting | Type | Default | Notes |
|---|---|---|---|
trial.length_days | integer 7–60 | 14 | Per plan |
limits.employee_soft_pct | integer | 105 | Hard block above this |
support.consent_required | boolean | true for Professional/Enterprise | Owner consent before write access |
support.max_grant_hours | integer 1–8 | 2 | |
deletion.grace_days | integer 30–90 | 30 | Contract-dependent |
statutory_pack.auto_inherit | boolean | true | If false, owner accepts each pack |
7.1.7 User stories
US-PLT-01 — Self-serve trial. As a prospective org_owner, I want to create a trial without talking to sales, so that I can evaluate Spyrl today.
- AC1: Given a unique slug and a verified mobile OTP, when I submit the sign-up form, then a tenant is provisioned and I receive an activation link by email within 2 minutes.
- AC2: Given a slug already in use, when I type it, then the form shows "This address is taken" with three suggestions before I submit.
- AC3: Given provisioning fails half-way, when the job retries, then no duplicate tenant, role or seed rows exist.
US-PLT-02 — Consented support access. As an org_owner, I want to approve and see every support access to my data, so that I stay in control.
- AC1: Given a support request for write access, when I approve it in-app, then the grant starts with the requested scope and ends automatically at its expiry.
- AC2: Given an active grant, when the engineer views an employee record, then the Support access log shows the engineer, time, entity and action within 1 minute.
- AC3: Given I revoke a grant, when the engineer makes the next request, then it is denied.
US-PLT-03 — Statutory pack update. As a payroll_manager, I want new PT slabs to apply from their effective date, so that I do not edit rates by hand.
- AC1: Given a pack with new Karnataka PT slabs effective 1 April, when it is published, then runs for periods from April use the new slabs and runs for March use the old ones.
- AC2: Given the pack affects a state where my tenant has employees, when I open Payroll, then a banner links to the change log.
US-PLT-04 — Plan limit. As an hr_manager, I want a clear warning before I hit my plan's employee limit, so that onboarding is not blocked by surprise.
- AC1: Given 100% of the limit is reached, when I add a new hire, then I see a warning and the hire is saved.
- AC2: Given 105% is reached, when I try to activate another employee, then the action is blocked with "Upgrade plan or deactivate employees", and payroll actions remain available.
US-PLT-05 — Tenant export. As an org_owner, I want to export all my data, so that I can leave or audit freely.
- AC1: Given I request an export, when it completes, then I receive a link valid for 24 h containing CSV/JSON for every module and a documents zip, and the request is audited.
7.1.8 Permissions
| Action | PLA | SUP | billing_admin | release_manager | OWN | Others |
|---|---|---|---|---|---|---|
| Create/suspend/delete tenant | ✓ | — | suspend for dunning | — | request deletion (own) | — |
| Change plan / overrides | ✓ | — | ✓ | — | upgrade self-serve (own) | — |
| Feature flags | ✓ | — | — | ✓ | — | — |
| Publish statutory pack | ✓ (two-person approval) | — | — | — | view / pin (own) | PRM, FNA view |
| Break-glass access | approve policy | request | — | — | consent / revoke / view log | — |
| Billing & invoices | ✓ | — | ✓ | — | view / pay (own) | — |
| Tenant export | ✓ | — | — | — | ✓ (own) | — |
7.1.9 UI/UX
- Platform console (web only): Tenants list (search by slug, name, owner email; filters by plan, status, cell), Tenant detail (plan, usage, health, flags, support grants, invoices), Cells, Flags, Statutory packs (diff view between versions), Announcements.
- Tenant side: Settings → Subscription (plan, usage vs limits, invoices, payment method), Settings → Support access (pending requests, active grants, log), Settings → Data export.
- Empty/error states: a suspended tenant sees a full-width read-only banner with "Pay now"; a failed payment shows the retry date; an export in progress shows progress and an email-on-ready note.
7.1.10 Notifications and automation
Trial ending (7, 3, 1 days before), payment failed, suspension notice, support-access request and expiry, statutory pack published, export ready, deletion scheduled and completed. See the catalogue in §12.
7.1.11 Reports and analytics
Platform: MRR, active tenants by plan, PEPM revenue, trial conversion, health-score distribution, usage by metric. Tenant: usage vs limits, invoice history, support access log.
7.1.12 Edge cases
- Owner email bounces during sign-up → the tenant stays
trial_pending; OTP-verified mobile can resend the invite by SMS. - Payment fails on the 26th (payroll window) → suspension is deferred to the 6th; a banner warns from day 1.
- A statutory pack is published with an error →
platform_adminpublishes a corrective version with the same effective date; runs that are calculated but not locked are flagged "recalculate"; locked runs are never changed automatically. - A tenant at its limit imports 50 hires → the dry-run reports how many will be blocked before commit.
7.2 ORG — Organisation Setup & Masters
Traces to: BR-ORG-* · Release: R0 (masters, policy framework, import framework), R1 (legal entities, setup wizard, custom fields)
7.2.1 Purpose and scope
ORG holds the tenant's structure (company, legal entities, locations, departments, designations, grades, employment types, cost centres, holiday calendars) and three shared frameworks that every module uses: the policy framework (§6.1), the data import framework and custom fields.
| In scope | Out of scope |
|---|---|
| Company profile and branding; legal entities and statutory registrations; locations with geo point and employee-code pattern; departments (hierarchy), designations, grades, employment types, cost centres; holiday calendars; policy framework; import framework; custom fields; setup wizard and go-live readiness; org chart | Position management and headcount budgeting (post-R4); multi-country entities |
7.2.2 Reference product summary
- Company information, departments and designations with Active/Inactive and no duplicates; departments cannot be inactivated until employees are transferred out [Observed] (A: Employee Management; SP-ORG-01..03).
- Work locations carry address, branch short code, map picker and a prefix + seed for employee-ID generation; the same prefix and seed share one sequence [Observed] (SP-ORG-04). Employee IDs look like "NE13", "TNK1" [Observed] (research §21.2).
- Company logo jpg/png ≤ 1 MB [Observed] (SP-ORG-05). Holidays by branch, date, type Public/Optional, name, with no duplicate date per branch [Observed] (SP-ORG-06).
- Optional department↔designation mapping (Rule 36) [Observed] (SP-ORG-07). ESI numbers are configured state-wise [Observed] (SP-PAY-03).
- No custom fields, no bulk reassignment and no legal-entity concept are documented [Inferred] (research §4.5, §20 Q8).
7.2.3 What we change and why [Proposed]
- Legal entities with PAN, TAN and statutory registrations, because EPF establishment codes, PT registrations and TAN (for TDS and Form 16) belong to an employer entity, not a branch.
- Policy framework with applicability and effective dating (§6.1) instead of numbered rules.
- Import framework with versioned templates, dry-run and row-level errors, so customers can self-migrate.
- Custom fields and bulk reassignment remove two common reasons for vendor customisation.
7.2.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-ORG-001 | Company profile: legal name, display name, logo (jpg/png/svg ≤ 1 MB), registered address, industry, default time zone (Asia/Kolkata), financial year (Apr–Mar fixed for payroll), leave cycle default (Jan–Dec or Apr–Mar). | Must | R0 | [Observed] SP-ORG-01/05 + [Proposed] |
| FR-ORG-002 | Legal entity with PAN, TAN, optional GSTIN, EPF establishment code, ESI employer code per state, PT registration per state, LWF registration per state, Shops & Establishment registration, authorised signatory (name, designation, signature image for Form 16 and letters). Every tenant has at least one. | Must | R1 | [Proposed] |
| FR-ORG-003 | Multiple legal entities per tenant; each employee belongs to exactly one legal entity at a time (effective-dated); payroll runs and statutory files are per legal entity. | Should | R1 | [Proposed] |
| FR-ORG-004 | Locations: name, branch code, legal entity, address, state (drives PT/LWF/holidays), PIN, geo point (map picker or search), time zone, status. | Must | R0 | [Observed] SP-ORG-04 + [Proposed] |
| FR-ORG-005 | Employee code generator: pattern with tokens {PREFIX}, {SEQ:n}, {YY}; sequence scope ORG, LEGAL_ENTITY or LOCATION; concurrency-safe and unique per tenant; codes are never reused; an HR user may override a code on create if it is unique. | Must | R0 | [Observed] SP-ORG-04 + [Proposed] |
| FR-ORG-006 | Departments as a hierarchy (parent, head employee, cost centre); designations; grades/bands (optional); employment types (seeded: Permanent, Probation, Contract, Fixed-term, Intern, Consultant, Apprentice). | Must | R0 | [Observed] SP-ORG-02/03 + [Proposed] |
| FR-ORG-007 | Department↔designation mapping as an optional setting that restricts designation choices in forms. | Could | R1 | [Observed] SP-ORG-07 |
| FR-ORG-008 | Cost centres master, assignable to departments and employees (effective-dated), used by the payroll journal. | Should | R1 | [Proposed] |
| FR-ORG-009 | Masters pattern for every master (§6.4): duplicate-name rejection, Active/Inactive, deactivation blocked while active links exist, bulk reassignment wizard, "used by" count, CSV import/export. | Must | R0 | [Observed] SP-X-01 + [Proposed] |
| FR-ORG-010 | Holiday calendars: named calendars assigned to locations; holiday date, name, type (Public, Optional/Restricted), optional half-day; duplicate dates per calendar rejected; copy a calendar to next year; changes trigger recomputation of unlocked attendance and leave durations. | Must | R0 | [Observed] SP-ORG-06 + [Proposed] |
| FR-ORG-011 | Policy framework: register policy types with JSON schemas; versions with valid_from/valid_to; assignment by applicability with specificity resolution; impact preview; one tenant default per type; generated forms and help text from the schema. | Must | R0 | [Proposed] |
| FR-ORG-012 | Data import framework: downloadable versioned Excel/CSV templates per entity; upload → validate → dry-run report (row, column, error, suggestion) → commit; idempotent by natural key; a committed batch can be rolled back within 24 h if no dependent records were created. Max 10,000 rows per file. | Must | R0 | [Observed] SP-EMP-10/SP-ATT-14 + [Proposed] |
| FR-ORG-013 | Custom fields for Employee (R1), and later Location, Claim, Client (R2/R3): types text, number, date, single/multi-select, boolean, file; required flag; section placement; visibility and edit permission per role; included in import templates and the report builder. Max 50 per entity. | Should | R1 | [Proposed] |
| FR-ORG-014 | Setup wizard with ordered steps (company → legal entity → locations → departments/designations → holidays → attendance policy → leave types → salary structure → statutory settings → import employees → invite users) and a go-live readiness score with blocking items (e.g. "No salary structure assigned to 12 employees"). | Must | R1 | [Proposed] |
| FR-ORG-015 | Branding: logo, primary colour (contrast-checked against WCAG AA), login background, email sender display name. | Should | R1 | [Proposed] |
| FR-ORG-016 | Org chart view from reports_to, filterable by department and location, with search; export as PNG/PDF. | Should | R1 | [Proposed] |
| FR-ORG-017 | Tenant label overrides for selected terms (e.g. "Comp-off" → "Compensatory leave"), applied in UI and notification templates. | Could | R2 | [Proposed] |
| FR-ORG-018 | Industry starter templates (Office, Factory with shifts, Retail, Field sales) that pre-fill policies and masters in the setup wizard. | Could | R1 | [Proposed] |
7.2.5 Key entities
company, legal_entity (pan, tan, gstin, epf_code, signatory), statutory_registration (entity, type EPF/ESI/PT/LWF/SE, state, number), location (code, entity, state, geo, tz, code_pattern), department (parent, head, cost_centre), designation, grade, employment_type, cost_centre, holiday_calendar, holiday (calendar, date, name, type, half_day), policy, policy_version (schema_id, payload, valid_from, valid_to, status), policy_assignment (rule, specificity), custom_field_def, import_batch (template_version, status, rows, errors).
7.2.6 Configuration settings
| Setting | Type | Default |
|---|---|---|
employee_code.pattern | string with tokens | {PREFIX}{SEQ:4} |
employee_code.scope | enum ORG / LEGAL_ENTITY / LOCATION | LOCATION |
leave_cycle | enum JAN_DEC / APR_MAR | JAN_DEC |
designation_mapping.enforced | boolean | false |
import.max_rows | integer | 10,000 |
import.rollback_window_hours | integer 0–72 | 24 |
7.2.7 User stories
US-ORG-01 — Location-based employee codes. As an hr_admin, I want each branch to have its own employee-code sequence, so that codes show the branch.
- AC1: Given location "Kukatpally" with prefix "KP" and seed 1 and scope LOCATION, when two HR users create hires there at the same time, then the codes are KP0001 and KP0002 with no duplicate.
- AC2: Given a hire is created and then deleted as a draft, when the next hire is created, then the deleted code is not reused.
US-ORG-02 — Effective-dated policy change. As an hr_admin, I want to change the late-grace minutes from 1 November for all employees, so that the change applies to existing staff too.
- AC1: Given an attendance policy assigned to 240 employees, when I create a new version effective 1 November, then the preview shows 240 employees and the number of unlocked days that will be recomputed.
- AC2: Given October is locked, when I set
valid_fromto 15 October, then the save is blocked with "15–31 Oct is in a locked period; choose 1 Nov or later, or unlock the period".
US-ORG-03 — Employee import with dry-run. As an hr_manager, I want to import 300 employees from Excel and see errors before anything is saved.
- AC1: Given a file with 3 invalid PANs and 1 unknown department, when I run the dry-run, then I see 4 row errors with column names and suggestions and nothing is committed.
- AC2: Given a clean file, when I commit, then 300 employees are created, and re-uploading the same file creates no duplicates.
US-ORG-04 — Deactivate a department. As an hr_admin, I want to deactivate a department and move its people in one step.
- AC1: Given a department with 14 active employees, when I deactivate it, then a reassignment wizard asks for the target department and an effective date, and the deactivation completes only after the reassignment.
US-ORG-05 — Go-live readiness. As an org_owner, I want to know what is missing before my first payroll.
- AC1: Given 12 active employees without a compensation record, when I open the setup checklist, then the readiness score lists "12 employees have no salary" as a blocking item with a link to fix it.
7.2.8 Permissions
| Action | OWN | HRA | HRM | FNA | PRM | LM | EMP | AUD |
|---|---|---|---|---|---|---|---|---|
| Company profile, branding | ORG | ORG | ORG(R) | ORG(R) | ORG(R) | — | — | ORG(R) |
| Legal entities, statutory registrations | ORG | ORG(R) | ORG(R) | ORG | ORG(R) | — | — | ORG(R) |
| Locations, departments, designations, grades | ORG | ORG | LOC*(R) | ORG(R) | ORG(R) | TEAM(R) | own (R) | ORG(R) |
| Holiday calendars | ORG | ORG | LOC* | — | ORG(R) | TEAM(R) | own (R) | ORG(R) |
| Policies (create/version/assign) | ORG | ORG (non-payroll) | ORG(R) | ORG (payroll) | ORG(R) | — | own policy (R) | ORG(R) |
| Imports | ORG | ORG | LOC* | ORG (pay data) | ORG (pay data) | — | — | — |
| Custom field definitions | ORG | ORG | — | — | — | — | — | ORG(R) |
7.2.9 UI/UX
- Web: Settings hub grouped as Organisation, People, Time, Pay, Notifications, Security, Integrations. Each master is a table with inline add/edit, status chips and a "used by" column. Policies use generated forms with a version timeline and a diff between versions. Imports use a 4-step stepper (Download template → Upload → Review errors → Commit).
- Mobile: read-only holiday list and company policies for employees.
- Empty states: "No locations yet. Add your first location to start punching." with the primary action; an import with errors shows a downloadable error file.
- Errors: duplicate name shows inline "A department named 'Sales' already exists (inactive). Reactivate it?".
7.2.10 Notifications and automation
Import completed/failed (to the uploader), policy version activated (to HR admins), holiday calendar changed (to affected employees, optional), readiness score blocking items (weekly digest during trial).
7.2.11 Reports and analytics
Masters export; headcount by location/department/designation (in RPT); policy assignment report ("which policy applies to whom on date X"); import history.
7.2.12 Edge cases
- A location changes state (rare, e.g. office move) → create a new location; PT/LWF follow the employee's effective location.
- Two policy assignments with equal specificity match one employee → rejected at save with the list of conflicting employees.
- A holiday is added for a past, unlocked date where employees were marked absent → their days are recomputed to H, and LOP is reversed.
- The employee-code pattern is changed → applies only to new codes; existing codes are unchanged.
7.3 IAM — Identity, Access & Security
Traces to: BR-IAM-* · Release: R0 (auth, roles, audit), R1 (SSO, device binding, privacy centre), R2 (SAML, API clients) · Architecture: architecture.md §6, §7
7.3.1 Purpose and scope
IAM authenticates users, authorises every action as a pair (permission, scope), protects sensitive fields, records the audit trail and implements privacy rights (consent, data-subject requests).
| In scope | Out of scope |
|---|---|
| Invite activation; password, OTP and MFA; OIDC/SAML SSO; sessions and devices; roles, permissions, scopes; field-level protection; segregation of duties; audit log; consent records and DPDP requests; API clients | Customer identity for end-customers of tenants; hardware tokens (FIDO2 is a future enhancement) |
7.3.2 Reference product summary
- The admin sets a user ID per employee; the password defaults to "Welcome1!" and is changed after login [Observed] (A: Employee Management; SP-IAM-01). The credentials email contains the URL, Company Code, username and the plaintext password [Observed] (research §21.2).
- Credentials are created manually after HR emails the Admin when onboarding completes [Observed] (M: Employee Management; SP-IAM-05).
- "Roles & Permissions" documentation duplicates "Users Login", so the permission model is undocumented [Observed doc defect] (research §17 D1).
- Password complexity is set through HR Policy Rules 1–9 [Observed] (SP-IAM-03); admin password reset by Location → Department → Employee, with an email to the employee [Observed] (SP-IAM-04).
- New phones need manager approval in the CRM app [Observed] (M: CRM Field Force Management).
7.3.3 What we change and why [Proposed]
- No default or emailed passwords. Users activate through a single-use invite link (72 h) sent automatically when an employee becomes active (fixes the manual hand-off and the plaintext password).
- A documented role builder: permissions × data scope, seeded templates, cloneable roles.
- MFA mandatory for admin and payroll roles; SSO on paid plans.
- Field-level protection and segregation of duties for payroll data.
- Privacy centre for DPDP consent and data-subject requests.
7.3.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-IAM-001 | Invite activation: when a user account is created (automatically on employee activation, or manually), send a single-use activation link valid 72 h by email, and by SMS/WhatsApp if only a mobile exists. The user sets a password (and MFA if required). Links can be resent (invalidating the old one) and revoked. No password is ever generated, emailed or shown to administrators. | Must | R0 | [Proposed] replaces [Observed] SP-IAM-01 |
| FR-IAM-002 | Login on web at {slug}.spyrl.app with email, username or mobile + password; on mobile with company code once, then the same credentials. Generic error messages that do not reveal whether a user exists. | Must | R0 | [Observed] SP-X-10 + [Proposed] |
| FR-IAM-003 | Typed password_policy: min length (8–64, default 10), character classes (default: any 3 of 4), history (default 5), optional expiry (default off), breached-password check against a k-anonymity list, argon2id hashing. | Must | R0 | [Observed] SP-IAM-03 Rules 1–9 redesigned |
| FR-IAM-004 | Brute-force protection: CAPTCHA after 3 failures; lock for 15 minutes after 5 failures in 15 minutes (configurable); per-IP and per-account rate limits; lock notification to the user. | Must | R0 | [Proposed] |
| FR-IAM-005 | Forgot password via email link or SMS OTP (10-minute validity). Admin "reset" sends a reset link; it never sets a password. All sessions are revoked on password change. | Must | R0 | [Observed] SP-IAM-04 redesigned |
| FR-IAM-006 | TOTP MFA with recovery codes; mandatory for org_owner, hr_admin, finance_admin, payroll_manager and platform roles; optional (or tenant-mandated) for others; MFA reset by org_owner with audit. | Must | R0 | [Proposed] |
| FR-IAM-007 | OIDC SSO with Google Workspace and Microsoft Entra ID (Standard plan and above); JIT linking only to an existing employee with the same verified email; "SSO only" enforcement per role group, with an owner break-glass password login. | Must | R1 | [Proposed] |
| FR-IAM-008 | SAML 2.0 SSO (Enterprise). | Should | R2 | [Proposed] |
| FR-IAM-009 | Permission model {module}.{resource}.{action}; a role is a set of permissions; a role assignment is role + scope + optional location/department filters + optional validity dates. Every API endpoint declares its permission. | Must | R0 | [Proposed] |
| FR-IAM-010 | Seeded role templates for every tenant role in CONVENTIONS.md §4; tenants can clone, edit and create custom roles; seeded originals are read-only and upgradeable by the platform; a role diff view shows permissions added/removed versus the template. | Must | R0 | [Proposed] |
| FR-IAM-011 | Data scopes SELF, TEAM (direct + indirect reports to a configurable depth, default unlimited), DEPARTMENT, LOCATION, ORG. TEAM is derived from the effective reports_to hierarchy and is never assigned manually. | Must | R0 | [Proposed] |
| FR-IAM-012 | Field-level protection for sensitive classes (compensation, bank, Aadhaar, PAN, health, biometric): masked in lists, exports and APIs unless the user has *.sensitive.read; an explicit "reveal" action is audited. Aadhaar shows only the last 4 digits everywhere except to emp.aadhaar.read. | Must | R0 | [Proposed] |
| FR-IAM-013 | Segregation of duties: a user can never approve their own request; optional tenant rule that the person who changed compensation or payroll inputs in a run cannot approve that run (FR-PAY-052). | Must | R1 | [Proposed] |
| FR-IAM-014 | Sessions: access token 15 min, rotating refresh token with reuse detection; web idle timeout (default 30 min, 5–480) and absolute lifetime (default 12 h); mobile refresh lifetime (default 30 days) with optional device biometric unlock; users and admins can list and revoke sessions. | Must | R0 | [Proposed] |
| FR-IAM-015 | Mobile device binding: the first login registers the device; when device_approval.required is on, a new device needs line-manager (or HR) approval before punches are accepted; remote sign-out and device block. | Must | R1 | [Observed] FFM device approvals + [Proposed] |
| FR-IAM-016 | Append-only audit log of all writes, approvals, sensitive reads, logins, permission changes and support access; viewer with filters (actor, entity, module, date); CSV export; retention per data class (payroll 8 years, others 3 years minimum). | Must | R0 | [Proposed] |
| FR-IAM-017 | Automatic access changes on lifecycle events: disable login at the last working day 23:59 location time; revoke admin roles on transfer if the role assignment is location-bound; re-enable on rehire only through a new invite. | Must | R1 | [Proposed] |
| FR-IAM-018 | Privacy centre: consent records per purpose (location at punch, continuous field tracking, face verification), shown to the employee with withdraw option; withdrawal disables the related feature for that employee and offers an alternative punch method. | Must | R1 | [Proposed] |
| FR-IAM-019 | Data-subject requests (access, correction, erasure, grievance): raised by employees, tracked with SLA (default 30 days, configurable, verify with counsel), fulfilled with an export or a correction workflow; erasure respects statutory retention and records the legal basis for retained data. | Must | R1 | [Proposed] |
| FR-IAM-020 | Security notifications: new-device login, password changed, MFA reset, role granted. | Should | R1 | [Proposed] |
| FR-IAM-021 | Admin access review report (users with admin/payroll permissions, last login, MFA status) with a quarterly reminder to the owner. | Should | R2 | [Proposed] |
| FR-IAM-022 | IP allow-list for admin and payroll roles (Professional+). | Could | R2 | [Proposed] |
| FR-IAM-023 | OAuth2 client-credentials API clients bound to one tenant, with scopes, rotation and revocation (for the public API). | Must | R2 | [Proposed] |
| FR-IAM-024 | "View as employee" impersonation by tenant admins. | Won't | — | [Proposed] (security risk; use the role preview instead) |
| FR-IAM-025 | Role preview: an admin can preview which menus and actions a role sees, without impersonating a real user. | Should | R1 | [Proposed] |
7.3.5 Key entities
user (tenant, employee_id, login identifiers, status), credential (argon2id hash, history), mfa_factor, invite (token hash, channel, expires_at, used_at), session, device (platform, model, push token, status, approved_by), permission, role (seeded flag, template version), role_permission, role_assignment (role, scope, filters, valid_from, valid_to), audit_event, consent_record (purpose, version, given_at, withdrawn_at), dsar_request, api_client.
7.3.6 Configuration settings
| Setting | Type | Default |
|---|---|---|
password_policy.* | typed policy | see FR-IAM-003 |
mfa.mandatory_roles | list of role keys | admin and payroll roles |
session.web_idle_minutes | integer 5–480 | 30 |
session.mobile_refresh_days | integer 1–90 | 30 |
device_approval.required | boolean | false (true recommended for field teams) |
device_approval.approver | enum LINE_MANAGER / HR | LINE_MANAGER |
sso.enforced_for | list of role keys | none |
sod.payroll_editor_cannot_approve | boolean | true |
team_scope.depth | integer or unlimited | unlimited |
7.3.7 User stories
US-IAM-01 — Activation without default passwords. As a new employee, I want to set my own password from a link, so that nobody else ever knows it.
- AC1: Given HR activates my employee record, when activation completes, then I receive an activation link by email (or SMS if I have no email) within 60 s.
- AC2: Given the link is older than 72 h or already used, when I open it, then I see "This link has expired" and a button to request a new one from HR.
- AC3: Given any admin views my user record, then no password or password hint is shown anywhere.
US-IAM-02 — Mandatory MFA for payroll. As an org_owner, I want everyone who can see salaries to use MFA.
- AC1: Given a user is granted
payroll_manager, when they next log in, then they must enrol TOTP before reaching any screen. - AC2: Given a user loses their phone, when they use a recovery code, then they log in and are prompted to re-enrol, and the event is audited.
US-IAM-03 — Custom role. As an hr_admin, I want a "Plant HR" role that can manage attendance only for Plant 1.
- AC1: Given I clone
hr_manager, remove payroll permissions and assign it with scope LOCATION = Plant 1, when the user opens Attendance, then only Plant 1 employees are listed. - AC2: Given the same user calls the API for a Plant 2 employee, then the response is 403 and the denial is audited.
US-IAM-04 — New device approval. As a line_manager, I want to approve a field executive's new phone, so that buddy punching from another phone is prevented.
- AC1: Given
device_approval.requiredis on, when my team member logs in on a new phone, then punches from that phone are rejected with "Device pending approval" and I get a push notification. - AC2: When I approve, then the old device is signed out and punches from the new phone are accepted.
US-IAM-05 — Withdraw location consent. As an employee, I want to withdraw consent for location capture.
- AC1: Given my attendance policy requires geo-fenced punch, when I withdraw location consent, then the app explains that I must punch on the kiosk or biometric device, and HR is notified to assign an alternative method.
US-IAM-06 — Sensitive field reveal. As an hr_manager without salary permission, I want to see the employee list without salary data.
- AC1: Given I export the employee list, when the file is generated, then compensation and bank columns are absent or masked.
- AC2: Given a
payroll_managerreveals an account number, then the reveal is written to the audit log.
7.3.8 Permissions
| Action | OWN | HRA | HRM | FNA | PRM | LM | EMP | AUD |
|---|---|---|---|---|---|---|---|---|
| Invite / resend / revoke user | ORG | ORG | LOC* | — | — | — | — | — |
| Reset password link / MFA reset | ORG | ORG (not OWN) | LOC* (link only) | — | — | — | SELF | — |
| Manage roles and assignments | ORG | ORG (cannot grant OWN or payroll roles) | — | grant PRM/FNA only with OWN approval | — | — | — | ORG(R) |
| Approve device | ORG | ORG | LOC* | — | — | TEAM | — | — |
| View audit log | ORG | ORG (non-payroll) | — | ORG (payroll) | ORG (payroll, R) | — | own activity | ORG(R) |
| Consent and DSAR | handle ORG | handle ORG | handle LOC* | — | — | — | SELF (raise, withdraw) | ORG(R) |
| Manage API clients | ORG | ORG | — | — | — | — | — | — |
7.3.9 UI/UX
- Web: login page with tenant branding; activation page with password strength meter; Security settings (password policy, MFA, SSO, sessions, devices); Users & Roles (users list with role chips and MFA status; role editor as a module × action grid with a scope selector; role preview); Audit log; Privacy (consents, requests).
- Mobile: company-code screen (remembered), login, biometric unlock, device-pending screen, Profile → Privacy with consent toggles and explanations.
- Error states: locked account shows time remaining; expired link offers "Ask HR to resend"; 403 pages explain which permission is missing ("You need Payroll access for Location Plant 2. Ask your administrator.").
7.3.10 Notifications and automation
Activation link; activation reminder after 48 h; password changed; new-device login; device pending approval (to approver); MFA enrolment required; consent withdrawn (to HR); DSAR received and due-soon (to HR and owner); quarterly access review (to owner).
7.3.11 Reports and analytics
Users and roles; MFA coverage; inactive users (no login > 60 days); device list; audit export; DSAR register with SLA status.
7.3.12 Edge cases
- An employee has no email and a shared family mobile → activation by SMS to the mobile; HR may hand over activation through the kiosk enrolment flow (R2).
- A manager leaves and their reports' TEAM scope moves to the new
reports_tofrom its effective date; pending approvals reassign to the new manager (FR-NTF-008). - A user holds two roles with different scopes → permissions are the union; scope is evaluated per permission.
- SSO user's IdP account is disabled but the Spyrl session is valid → refresh fails at the next rotation (≤ 15 min); SCIM deprovisioning is a future enhancement.
7.4 EMP — Core HR & Onboarding
Traces to: BR-EMP-* · Release: R1 (R2 rehire, R3 identity verification)
7.4.1 Purpose and scope
EMP is the system of record for people: hire to active employment, the effective-dated job history, personal and statutory identity data, documents, checklists, inductions, probation and self-service profile changes.
| In scope | Out of scope |
|---|---|
| New hires and pre-onboarding; employee profile; effective-dated job assignment (transfer, promotion, re-designation, manager change); documents with approval; onboarding checklists and induction; probation and confirmation; self-service change requests; directory; letters (basic templates); profile audit | Recruitment/ATS and offers (post-R4, §15); performance; asset management; separation (EXT, R2) |
7.4.2 Reference product summary
- New Hire requires First Name, Last Name, Hired On, Joining Date, Designation, Mobile and Emergency Contact; personal email is optional [Observed] (research §21.2; M: Employee Management, SP-EMP-04).
- A self-onboarding link lets the hire fill personal, contact, family, experience and education details and upload documents [Observed] (SP-EMP-05); the link expires after 24 hours [Observed] (research §21.2).
- HR completes Joining Formalities (official email, employment type, role, location, designation, department, reporting manager) [Observed] (SP-EMP-06). Profile fields include DOB, blood group, gender, marital status, Aadhaar number, languages, notice period, reporting manager department, residence and permanent address with "same as" [Observed] (research §21.2).
- Checklists per department, each item with an approver; "No Due" completes the checklist [Observed] (SP-EMP-01/07; research §21.2). Document approval with re-upload loop; HR uploads are auto-approved [Observed] (SP-EMP-08). Induction programs with type, department, conducted by, date/time, status [Observed] (SP-EMP-09; research §21.2).
- Probation is configured in two places, in months and in days [Observed] (research §17 D4). Promotions are a "Contract/Promotions" tab with no effective-dated job history documented [Inferred] (research §4.5).
7.4.3 What we change and why [Proposed]
- Effective-dated job assignments replace a flat profile, so payroll, policies and scopes are correct for any date.
- Activation triggers the invite automatically (FR-IAM-001); no manual credential step.
- Self-edit through change requests for sensitive fields (bank, name, PAN), so HR keeps control and has an audit trail.
- One probation/notice policy (typed, effective-dated) replaces the duplicate settings.
- A longer, safer pre-onboarding link (7 days, OTP-protected) because 24 h is too short for candidates gathering documents.
7.4.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-EMP-001 | Create a new hire with required fields First name, Last name, Offer/Hired-on date, Joining date, Designation, Mobile, Emergency contact; optional personal email, middle name, location, department, manager, employment type. The record starts as pre_joining. | Must | R1 | [Observed] SP-EMP-04 |
| FR-EMP-002 | Pre-onboarding link sent by email/SMS; valid until submitted or for preboarding.link_days (default 7, 1–30); each open requires an OTP to the registered mobile/email; the candidate can save drafts and submit once; HR can reopen sections with a comment. | Must | R1 | [Observed] SP-EMP-05 + [Proposed] |
| FR-EMP-003 | Profile sections: Personal (name parts, preferred name, DOB, gender with inclusive options incl. "prefer not to say", marital status optional, blood group, nationality, languages, photo); Contact (personal email, mobile, residence and permanent address with "same as", emergency contacts); Family and nominees (name, relationship, DOB, dependent flag, nomination % for EPF/gratuity); Education; Experience; Bank (account holder, account number, IFSC with format validation and bank/branch lookup); Identity (PAN, Aadhaar, UAN, ESI IP number, passport, driving licence). | Must | R1 | [Observed] research §21.2 + [Proposed] |
| FR-EMP-004 | Identity validation: PAN format AAAAA9999A; Aadhaar 12 digits with Verhoeff checksum, stored encrypted and masked; UAN 12 digits; IFSC AAAA0XXXXXX; duplicate PAN/Aadhaar/UAN within the tenant is blocked with a warning naming the existing employee code. | Must | R1 | [Proposed] |
| FR-EMP-005 | Joining formalities: HR reviews the submission, completes work info and activates the employee on or after the joining date; activation assigns the employee code (FR-ORG-005), creates the user and sends the invite (FR-IAM-001), assigns policies by applicability and creates the onboarding checklist. | Must | R1 | [Observed] SP-EMP-06 + [Proposed] |
| FR-EMP-006 | Effective-dated job assignment: legal entity, location, department, designation, grade, employment type, reports_to, cost centre, work email, notice period override. Every change has an effective date, a reason (Transfer, Promotion, Re-designation, Manager change, Correction) and a timeline view. Back-dated changes are allowed only into unlocked periods (else they require PAY arrears, FR-PAY-040). | Must | R1 | [Proposed] |
| FR-EMP-007 | Bulk job changes and bulk profile updates through the import framework (FR-ORG-012) with dry-run. | Must | R1 | [Observed] SP-EMP-10 + [Proposed] |
| FR-EMP-008 | Employee statuses: pre_joining → active → on_notice → exited; plus inactive (long leave, suspension) and no_show (never joined). Probation is an attribute with start, end and outcome. | Must | R1 | [Proposed] |
| FR-EMP-009 | Documents: tenant document types (with "required for activation" and "has expiry" flags); upload pdf/jpg/png ≤ 10 MB (virus-scanned); HR approve/reject with reason; email/push on each outcome; re-upload loop; HR uploads auto-approved; expiry reminders 30 days before expiry. | Must | R1 | [Observed] SP-EMP-08 + [Proposed] |
| FR-EMP-010 | Checklist engine (shared with EXT): templates by type (Onboarding, Offboarding, Custom) and applicability (department, location); items with owner (role or named user), due offset in days, required evidence (none/comment/file); assignment creates tasks; completion of all required items sets the checklist completed ("No Due"). | Must | R1 | [Observed] SP-EMP-01/07 + [Proposed] |
| FR-EMP-011 | Induction programs: type master, department, conducted by, date, start/end time, venue or link, attendees; invite email and calendar file; edit/cancel notifies attendees; attendance marking; shown on the employee home. | Should | R1 | [Observed] SP-EMP-02/09 |
| FR-EMP-012 | Typed probation_notice_policy (by applicability): probation length in days or months, notice period in days during and after probation, auto-confirm on/off. Confirmation due list; reminders to line manager and HR 15 days before probation end; actions Confirm / Extend (new end date) / Not confirmed (→ EXT). | Must | R1 | [Observed] SP-EMP-03 + Rules 10–15 consolidated |
| FR-EMP-013 | Self-service profile: per-field setting self_edit = direct, approval or none. Defaults: photo, languages, emergency contact, address = direct; legal name, DOB, bank, PAN, family/nominees = approval; job fields = none. Change requests go through NTF approval to HR. | Must | R1 | [Observed] Rule 34 + [Proposed] |
| FR-EMP-014 | Employee directory: search by name, code, phone; filters by location, department, designation, status; card and list views; tenant setting to hide personal mobile numbers from peers. | Must | R1 | [Proposed] |
| FR-EMP-015 | Profile change history: field, old value (masked if sensitive), new value, effective date, actor, source (UI, import, API, request). | Must | R1 | [Proposed] |
| FR-EMP-016 | Letter templates (appointment, confirmation, increment, address proof, custom) with merge fields; generate PDF with the signatory from the legal entity; store in documents; send to the employee. | Should | R1 | [Proposed] |
| FR-EMP-017 | Statutory onboarding helpers: capture previous-employer UAN and income (for TDS, linked to FR-PAY-061), EPF opt-out eligibility (Form 11-style declaration fields), ESI family details. | Must | R1 | [Proposed] |
| FR-EMP-018 | no_show handling: if not activated within N days of joining date (default 7), remind HR; HR marks no-show, which closes the record without creating a user. | Should | R1 | [Proposed] |
| FR-EMP-019 | Rehire: create a new employment linked to the previous record, carrying identity data, with the previous exit's rehire-eligibility flag shown. | Should | R2 | [Proposed] |
| FR-EMP-020 | PAN/Aadhaar/bank verification through third-party APIs (e.g. penny-drop for bank) with consent. | Could | R3 | [Proposed] |
| FR-EMP-021 | Contract workers via agency (vendor master, contract dates) without payroll. | Could | R2 | [Proposed] |
| FR-EMP-022 | E-sign of letters. | Won't | R1 | [Proposed] (post-R2 candidate) |
7.4.5 Key entities
employee (code, status, personal fields), employment (joining date, exit date, rehire link), job_assignment (effective-dated; entity, location, department, designation, grade, employment_type, reports_to, cost_centre, reason), identity_doc (type, number_enc, last4, verified), bank_account (enc), family_member, nomination, education, experience, document (type, file, status, expiry), checklist_template, checklist_item_template, checklist, task, induction_type, induction_program, induction_attendee, change_request, letter_template, letter.
7.4.6 Configuration settings
| Setting | Type | Default |
|---|---|---|
preboarding.link_days | integer 1–30 | 7 |
preboarding.sections_enabled | list | all |
profile.self_edit.<field> | enum direct/approval/none | see FR-EMP-013 |
directory.show_personal_mobile | boolean | false |
probation_notice_policy | typed policy | probation 6 months; notice 15 days in probation, 30 days after |
no_show.days_after_joining | integer | 7 |
documents.max_mb | integer 1–25 | 10 |
7.4.7 User stories
US-EMP-01 — Add a new hire. As an hr_manager, I want to add a hire with the minimum fields and send a pre-onboarding link.
- AC1: Given the required fields are filled, when I save, then the hire appears under Pre-joining and a link is sent to the mobile (and email if given).
- AC2: Given the PAN entered matches an active employee, when I save, then I see "PAN already used by KP0012 (active)" and cannot save without changing it.
US-EMP-02 — Self-onboarding. As a candidate, I want to fill my details on my phone over several days.
- AC1: Given a valid link, when I open it, then I must enter an OTP sent to my mobile.
- AC2: Given I saved a draft yesterday, when I reopen the link, then my data is still there.
- AC3: Given I submit, when HR reopens the Bank section with a comment, then I get a notification and only that section is editable.
US-EMP-03 — Activate on joining. As an hr_manager, I want activation to set up everything the employee needs on day one.
- AC1: Given work info is complete and the joining date is today, when I activate, then the employee code is generated, the attendance, leave and payroll policies resolve, the onboarding checklist is created and the activation link is sent.
- AC2: Given a required document type is missing, when I activate, then I am warned and can proceed only if
documents.block_activationis off.
US-EMP-04 — Promotion with effective date. As an hr_manager, I want to record a promotion effective 1 October with a new manager.
- AC1: Given the employee's October attendance is unlocked, when I save the change effective 1 October, then the new designation, manager and resolved policies apply from 1 October, and pending approvals raised from 1 October move to the new manager.
- AC2: Given September payroll is locked, when I set the effective date to 15 September, then I am told that compensation effects will be paid as arrears in the next run.
US-EMP-05 — Bank change request. As an employee, I want to change my salary account.
- AC1: Given bank details need approval, when I submit the new account and a cancelled-cheque image, then HR gets an approval task and my old account stays active until approval.
- AC2: Given approval happens after the payroll run is Approved, then the new account applies from the next run and I am told so.
US-EMP-06 — Probation confirmation. As a line_manager, I want a reminder before my report's probation ends.
- AC1: Given probation ends on 30 November, when it is 15 November, then I and HR get a reminder with Confirm/Extend/Not confirmed actions.
- AC2: When I choose Extend by 60 days, then the end date updates, the notice-period policy for probation continues, and the employee is notified.
US-EMP-07 — Onboarding checklist. As an IT owner of a checklist item, I want my task to appear in my inbox.
- AC1: Given the "Laptop issued" item is owned by the IT department head, when the checklist is created, then the task appears in their inbox with a due date of joining date + 1.
- AC2: When all required items are done, then the checklist shows Completed and the employee sees it on their home screen.
7.4.8 Permissions
| Action | OWN | HRA | HRM | FNA | PRM | LM | EMP | AUD |
|---|---|---|---|---|---|---|---|---|
| Create hire / activate | ORG | ORG | LOC* | — | — | — | — | — |
| View profile (non-sensitive) | ORG | ORG | LOC* | ORG | ORG | TEAM | SELF + directory card | ORG(R) |
| View sensitive (Aadhaar, bank, PAN) | ORG | reveal ORG | reveal LOC* | — | ORG (bank, PAN) | — | SELF | — |
| Change job assignment | ORG | ORG | LOC* | — | — | propose for TEAM (approval) | — | — |
| Approve change requests | ORG | ORG | LOC* | — | bank (optional second step) | — | raise SELF | — |
| Documents approve | ORG | ORG | LOC* | — | — | TEAM(R) | upload SELF | ORG(R) |
| Checklist tasks | ORG | ORG | LOC* | as owner | as owner | as owner | view SELF | ORG(R) |
| Probation actions | ORG | ORG | LOC* | — | — | TEAM (recommend) | view SELF | — |
7.4.9 UI/UX
- HR web: People list (saved views: Pre-joining, Joining this week, On probation, On notice), employee profile with tabs (Overview, Job & history timeline, Personal, Family, Bank & IDs, Documents, Checklists, Letters, Activity). A "Joining this week" board shows readiness (documents, checklist, bank) per hire.
- Candidate (mobile web, no app needed): stepper per section, camera upload for documents, progress bar, save draft.
- Employee mobile: Me tab with profile cards, edit button per section (showing "Needs HR approval" where applicable), documents with status chips, checklist status.
- Line manager: team list with probation-due and document-pending badges.
- Empty states: "No pre-joining hires. Add a new hire or import a list." Errors: identity format errors inline; duplicate identity with a link to the existing record (if permitted).
7.4.10 Notifications and automation
Pre-onboarding link and reminders (day 2 and 5 if not submitted); submission received (HR); section reopened (candidate); document approved/rejected; document expiring; activation link (via IAM); checklist task assigned/overdue; induction invite/changed/cancelled; probation due; change request outcome; no-show reminder; work anniversary and birthday feed (to ENG, R2).
7.4.11 Reports and analytics
Employee master report with column chooser and filters (Emp ID, name, office email, mobile, status, type, department, designation, location, gender, blood group, custom fields) [Observed column set, research §21.2]; joiners and leavers; probation due; document compliance (missing/expired); headcount trend; job-change history.
7.4.12 Edge cases
- Joining date moves after the link was sent → HR edits it; policies and code assignment follow the new date; no duplicate record.
- Two hires with the same name and DOB → allowed; identity duplicates are the only hard block.
- Employee changes manager mid-month while a leave request is pending → the pending approval moves to the new manager from the effective date (FR-NTF-008); already-approved requests stay approved.
- Aadhaar not provided (voluntary) → allowed; it is never mandatory except where the tenant marks it required for a specific legal purpose, with the purpose shown to the employee.
- Back-dated transfer across states → PT/LWF state changes from the effective date; locked months are settled by arrears/adjustments in the next run.
7.5 ATT — Attendance, Shifts & Time
Traces to: BR-ATT-* · Release: R1 (MVP-critical); R2 device gateway, kiosk and face (with MOB)
7.5.1 Purpose and scope
ATT captures presence from every channel, applies shift and attendance policy, computes a status for every employee-day and hands payroll a locked, explainable set of payable days, LOP, overtime, extra days and penalties.
| In scope (R1 unless noted) | Out of scope |
|---|---|
| Web punch; mobile punch with selfie + geo-fence; offline punch queue; biometric CSV/API import and device mapping; manual punch; shifts (fixed, flexible, night); rotations; rosters; week-off patterns; shift change and swap; day-computation engine with status codes; lates/early-go and late → leave deduction; attendance requests (WFH, On-duty, remote); regularization; permissions (short leave); overtime with approval; extra days; week-off penalties; period close and lock; device push gateway (R2); kiosk and face (R2, via MOB) | Continuous GPS tracking (FFM, R3); workforce demand forecasting and auto-rostering (post-R4); access-control hardware integration |
7.5.2 Reference product summary
- Capture channels: biometric with device-user mapping [Observed] (SP-ATT-13); Excel upload with a vendor-supplied template [Observed] (SP-ATT-14); mobile self check-in with face, geo-located check-in within a manager-configured location, receptionist "Front Office Check-in/out" [Observed] (SP-ATT-19); field punch with photo and address [Observed] (SP-ATT-20). Punch records show time, in/out, address and source ("Lite", "CRM", "MOBILEAPP") with first/last photos [Observed] (research §21.3).
- Geo-fence: a per-branch location with a geo-fencing radius (200 m in the example) [Observed] (research §21.3).
- Shift master: start/end, grace in/out, "lates more than N → deduct X leave", minimum hours [Observed] (SP-ATT-01). Rotations per location, assign and reassign with start shift and date [Observed] (SP-ATT-07). Per-employee week-offs with history [Observed] (SP-ATT-08). Shift change requests; the manager can swap shifts between employees on approval [Observed] (SP-ATT-09).
- Requests: attendance requests with work types WFH, WFO, On-Duty, Remote location, first/second half [Observed] (SP-ATT-02); permission in minutes, one per day, paid per Rule 29 [Observed] (SP-ATT-10); regularization by entering the out-time or converting to leave, plus manager bulk regularization [Observed] (SP-ATT-11/12); on-behalf requests auto-approved [Observed] (SP-ATT-04).
- Day status legend: A, P, W, L, H, HD, WP, HP, HL; counts accept halves [Observed] (research §21.3). "In case of multiple attendance sources, break timings are not considered" [Observed] (research §21.3).
- Rules are scattered across Shift master, HR Policy Rules 16–48 and Payroll Policies: half/full-day hours (27–28), flexible shifts (30–31), regularization lookback (32–33), default punch-out (35), lunch/tea durations (38–42), extra-day pay (43–45), week-off absence penalty (46–48) [Observed] (SP-IAM-03). Extra-day slabs per designation and penalty designations [Observed] (SP-ATT-17/18).
- Gaps: OT is only "hours beyond the shift" with no approval or multipliers; no period lock; no liveness for face; shift swaps without the counterpart's consent [Observed/Inferred] (research §5.4).
7.5.3 What we change and why [Proposed]
- One typed
attendance_policy(plusshift,geofence,overtime_policy,regularization_policy) assigned by applicability and effective-dated, replacing rules spread over three screens. - A deterministic day-computation engine that recomputes a day from its inputs whenever any input changes, and stores the explanation.
- Multiple geo-fences per location with radius and accuracy tolerance, and a choice to block or flag out-of-fence punches.
- Overtime needs approval and has a policy (minimum, rounding, caps, multipliers, pay vs comp-off).
- Swap consent from the counterpart before manager approval.
- Period lock tied to the payroll run, with post-lock corrections as next-period adjustments.
7.5.4 Day-status codes
Each day has two sessions (first half, second half). The engine assigns a session status and derives the day code. The first nine codes are the minimum set from research §21.3; OD, MP and NE are [Proposed].
| Code | Name | Derivation | Default payable value |
|---|---|---|---|
| P | Present | Both sessions present: worked minutes ≥ full-day threshold | 1 |
| A | Absent | No qualifying presence, leave or approved request on a working day | 0 (LOP) |
| HD | Half Day | Worked minutes ≥ half-day threshold and < full-day threshold, other half not covered | 0.5 |
| L | Leave | Both sessions on approved leave (including sandwich-counted days, LVE) | 1 if paid type; 0 if LOP type |
| HL | Half-day Leave | One session on approved leave; the other present, OD or absent (flag other_half) | leave half + other half value |
| W | Week-off | Scheduled week-off, not worked | 1; 0 if week-off penalty applies (flag penalty) |
| H | Holiday | Holiday on the employee's calendar (incl. an availed optional holiday, flag optional), not worked | 1 |
| WP | Week-off Present | Worked on a week-off ≥ minimum hours | 1 + extra-day / OT / comp-off eligibility |
| HP | Holiday Present | Worked on a holiday ≥ minimum hours | 1 + extra-day / OT / comp-off eligibility |
| OD | On Duty / Remote | Approved attendance request (WFH, On-duty, Remote) covering the session(s); work type stored as attribute | 1 (0.5 per session) |
| MP | Missed Punch | Single punch or unmatched pair, unresolved; provisional | missed_punch.provisional_value (default 0.5) until resolved; must be resolved before lock |
| NE | Not Employed | Before joining date or after exit date | excluded from period days |
Display adds modifiers: late (L-dot), early-go, out-of-fence, manual, regularized, OT approved. Session combinations not covered above (e.g. OD + absent) display as HD with the attribute shown.
7.5.5 Day computation
Engine rules:
- Attribution. A punch belongs to the shift instance whose window contains it: from
shift_start − window_before(default 4 h) toshift_end + window_after(default 6 h). Night shifts that cross midnight belong to the start date. - Pairing. Punches are sorted; the first is IN, the last is OUT; intermediate punches are breaks only when
breaks.from_punchesis on and all punches come from one source (as observed in Spryple, research §21.3). - Dedup. Punches for the same employee within
dedup_seconds(default 60) across sources collapse into one; all raw punches are kept. - Worked minutes = OUT − IN − unpaid break minutes (fixed per shift or actual from punches).
- Late if IN > shift start + grace-in; early-go if OUT < shift end − grace-out. Flexible shifts check only total hours (and core hours if set).
- Recompute is idempotent and triggered by any input change for dates in an unlocked period; p95 latency ≤ 5 min after the change (NFR-PERF-05).
7.5.6 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| Capture | ||||
| FR-ATT-001 | Web punch in/out from the browser; server time is authoritative; records IP, user agent and (if permitted) browser location; optional restriction to tenant IP ranges per policy. Source = WEB. | Must | R1 | [Proposed] |
| FR-ATT-002 | Mobile punch with selfie (front camera, compressed ≤ 300 KB) and device location (lat/long, accuracy); evidence kept for retention.punch_photo_days (default 180) then purged. Source = MOBILE. | Must | R1 | [Observed] SP-ATT-19/20 + [Proposed] |
| FR-ATT-003 | Geo-fences: each location has one or more circular fences (centre, radius 25–2,000 m, default 200 m). Policy geofence.mode = block, flag (allowed, needs reason, marked out-of-fence) or off. If reported accuracy is worse than geofence.max_accuracy_m (default 100 m), the punch is treated as out-of-fence for block mode prompts to retry, or flagged. | Must | R1 | [Observed] research §21.3 + [Proposed] |
| FR-ATT-004 | Employees can be allowed to punch at several locations (e.g. home branch + client sites) through their attendance policy. | Should | R1 | [Proposed] |
| FR-ATT-005 | Offline punch queue: the app stores punches with device time and elapsed time since the last server sync; uploads when online; the server accepts punches up to 72 h old, flags them offline, and flags clock_drift if device time differs from the computed server time by > 5 min. | Must | R1 | [Proposed] |
| FR-ATT-006 | Biometric device mapping: device master (serial, make, location) and mapping device user ID ↔ employee, with bulk import. | Must | R1 | [Observed] SP-ATT-13 |
| FR-ATT-007 | Biometric punch import through (a) CSV/Excel upload with a published template and column mapping, and (b) an authenticated punch-batch API (integration key per tenant); idempotent by (device, device user, timestamp). Unmapped device users go to an "Unmapped punches" queue. | Must | R1 | [Observed] SP-ATT-14 + [Proposed] |
| FR-ATT-008 | Device push gateway (ADMS-style HTTP push) with per-device secret, plus a sync agent for pull-only devices; device health (last seen, last punch, queue lag) with an alert after device.offline_alert_minutes (default 60) during shift hours. | Must | R2 | [Proposed] (architecture.md §16) |
| FR-ATT-009 | Manual punch entry or edit by HR with mandatory reason; original values kept; day marked manual. | Must | R1 | [Proposed] |
| FR-ATT-010 | Kiosk and face-verified punches are accepted from MOB kiosk mode (FR-MOB-012..015) with source KIOSK, and field punches from FFM with source FIELD (R3). | Must | R2 | [Observed] SP-ATT-19 redesigned |
| Shifts, rosters and week-offs | ||||
| FR-ATT-011 | Shift master: name, code, colour, start, end (total hours auto-calculated; crossing midnight allowed), unpaid break minutes, grace-in, grace-out, half-day and full-day thresholds (override policy), minimum minutes before OT counts, type fixed or flexible (required hours, optional core window). | Must | R1 | [Observed] SP-ATT-01 + Rules 27–31 consolidated |
| FR-ATT-012 | Shift assignment to one or many employees for a date range, with a week-off pattern; default shift per attendance policy for new joiners; bulk assignment by filter. | Must | R1 | [Observed] SP-ATT-06 + Rules 19–21/25–26 consolidated |
| FR-ATT-013 | Rotation sequences: ordered list of shifts with a step length (days or weeks), an anchor date and location; assign to employees with a start step and date; reassign from a date without changing past days. | Must | R1 | [Observed] SP-ATT-07 |
| FR-ATT-014 | Roster grid (employees × days) for line managers and HR: view and edit shifts and week-offs, copy a week, publish changes with notification; coverage row per shift per day (present / scheduled). | Should | R1 | [Observed] research §21.3 + [Proposed] |
| FR-ATT-015 | Drag-and-drop roster planning with minimum-coverage warnings. | Could | R2 | [Proposed] |
| FR-ATT-016 | Week-off patterns: fixed weekdays, nth-weekday rules (e.g. 2nd and 4th Saturday), rotating, or per-employee; effective-dated history. | Must | R1 | [Observed] SP-ATT-08 + Rules 16–18 |
| FR-ATT-017 | Shift change request: date range, from-shift (auto), to-shift, reason; optional swap with a named colleague, who must accept before the manager decides; approval updates both rosters. | Must | R1 (consent: Should) | [Observed] SP-ATT-09 + [Proposed] |
| FR-ATT-018 | Auto-shift detection for employees on a "multi-shift" policy: pick the allowed shift whose start is nearest to the first IN. | Should | R1 | [Proposed] |
| Day engine | ||||
| FR-ATT-019 | Day-computation engine as specified in §7.5.4–§7.5.5: session and day status, first IN, last OUT, worked, break, late and early-go minutes, OT candidate minutes, flags; stores inputs and policy version IDs; "How calculated" view. | Must | R1 | [Inferred] research §5.3 + [Proposed] |
| FR-ATT-020 | Missed-punch handling per missed_punch settings: default_out = none, shift end, or shift start + full-day hours; provisional value; auto-resolution at period close if still open (at_close = absent / half / present). | Must | R1 | [Observed] Rule 35 + [Proposed] |
| FR-ATT-021 | Break rules: fixed unpaid break per shift, or actual breaks from punches with lunch and tea durations and graces; excess break minutes reported. | Should | R1 | [Observed] Rules 38–42 |
| FR-ATT-022 | Late and early-go tracking per period; late → deduction rule: after late.free_count lates (default 3) in a period, each further late (or each block of N lates) deducts a configured fraction of a day from an ordered list of leave types (e.g. CL → EL → LOP) via the leave ledger. | Must | R1 | [Observed] SP-ATT-01, Rules 22–24 consolidated |
| Requests | ||||
| FR-ATT-023 | Attendance requests for work types from a tenant master (seeded: Work From Home, Work From Office, On Duty, Remote Location), date range, full/first half/second half, reason, attachment; produces OD sessions on approval; per-type limits per month. | Must | R1 | [Observed] SP-ATT-02 |
| FR-ATT-024 | Regularization: the employee sees days needing action (A, MP, HD, late) as alerts; actions: add missing time, raise an attendance request, or apply leave (LOP only if no balance); within regularization.lookback_days (default 7) and up to regularization.max_per_period (default 4). | Must | R1 | [Observed] SP-ATT-03/11, Rules 32–33 |
| FR-ATT-025 | Manager bulk regularization: lists of full-day and half-day exceptions for the team; multi-select → attendance request or leave on behalf (auto-approved at the manager level, reason required). | Must | R1 | [Observed] SP-ATT-12 |
| FR-ATT-026 | Permission (short leave): date, start time, duration in minutes, reason; limits permission.max_per_day (default 1), max_per_period (default 2), max_minutes (default 120); paid or unpaid; the approver may edit the duration before approving; approved minutes excuse late/early-go. | Must | R1 | [Observed] SP-ATT-10, Rule 29 |
| Overtime, extra days, penalties | ||||
| FR-ATT-027 | Typed overtime_policy: eligibility by applicability; basis (beyond shift end, beyond daily hours, beyond weekly hours); minimum minutes; rounding (down to 15/30/60); daily and period caps; multipliers per day type (working, week-off, holiday; e.g. 2× ordinary rate where the Factories Act applies, to verify); outcome pay, comp_off or employee_choice; approval pre, post or none. | Must | R1 | [Proposed] (fixes [Observed] gap) |
| FR-ATT-028 | OT approval: computed OT candidates appear as OT claims for the line manager, who approves all, part (edit minutes) or rejects; only approved OT is sent to PAY or credited as comp-off (FR-LVE-014). Pre-approval requests can be raised before the work. | Must | R1 | [Proposed] |
| FR-ATT-029 | Extra days on WP/HP: outcome per policy = extra-day pay, comp-off credit, or none; extra-day slabs per designation (min days worked, max days worked → eligible extra days) as observed. | Must | R1 | [Observed] SP-ATT-17, Rules 43–45 |
| FR-ATT-030 | Week-off penalty: when an employee is absent on the configured adjacent days (before, after or both), the week-off becomes unpaid (W + penalty); applicable designations/applicability; per-period cap. | Must | R1 | [Observed] SP-ATT-18, Rules 46–48 |
| Period, lock and output | ||||
| FR-ATT-031 | The attendance period follows the pay schedule window of the employee's pay group (e.g. 26th–25th) (FR-PAY-005). | Must | R1 | [Observed] SP-PAY-04 |
| FR-ATT-032 | Period close: a checklist shows unresolved MP, pending requests, pending OT claims and unmapped punches; HR can send reminders, auto-resolve per policy, then lock the period per pay group. Locked days cannot change. | Must | R1 | [Proposed] |
| FR-ATT-033 | Unlock requires att.period.unlock with reason and is allowed only while the dependent payroll run is not Approved or later; unlocking invalidates the run's calculation (status back to Draft). | Must | R1 | [Proposed] |
| FR-ATT-034 | Post-lock corrections (approved late requests, regularization of a locked day) create attendance adjustments (± payable days, OT minutes) carried into the next open period and shown on the payslip as "Attendance adjustment for | Must | R1 | [Proposed] |
| FR-ATT-035 | Payable-days output per employee per period: days in period, P, A, HD, L by type, LOP days, W, H, WP, HP, OD, penalties, extra days, approved OT minutes by multiplier, late-deduction days, adjustments. | Must | R1 | [Observed] SP-PAY-13 Payable Days + [Proposed] |
| FR-ATT-036 | Attendance upload (daily status or punches) via the import framework, for migration and for tenants without devices. | Must | R1 | [Observed] SP-ATT-14 |
| Views and anomalies | ||||
| FR-ATT-037 | Employee calendar with status codes and colours, first IN/last OUT, today's and next shift, pending alerts; month summary with half-day counts (e.g. 14.5). | Must | R1 | [Observed] SP-ATT-15, research §21.3 |
| FR-ATT-038 | Manager "Team today": scheduled, punched in, late, absent, on leave, OD, not yet punched; drill to punches with photos and fence status. | Must | R1 | [Observed] SP-ATT-15/19 |
| FR-ATT-039 | Anomaly flags and review queue: out-of-fence, offline/clock drift, punch from an unapproved device, selfie missing, impossible travel between consecutive punches (> 150 km/h). | Should | R1 | [Proposed] |
| FR-ATT-040 | Alternative fences: Wi-Fi BSSID allow-list and rotating QR code at a location. | Could | R2 | [Proposed] |
7.5.7 Key entities
punch_raw (employee, source, device, ts_device, ts_server, lat, lng, accuracy, photo_ref, fence_result, flags), device (serial, make, location, secret), device_user_map, shift, shift_assignment (employee, shift, from, to), rotation, rotation_step, rotation_assignment, weekoff_pattern, roster_day (materialised plan), attendance_day (employee, date, s1_status, s2_status, code, first_in, last_out, worked_min, late_min, early_min, ot_candidate_min, flags, inputs_hash, policy_version_ids), attendance_request, regularization, permission_request, shift_change_request, ot_claim, attendance_period (pay group, from, to, status open/closing/locked), attendance_adjustment, work_type, geofence.
7.5.8 Configuration settings (typed attendance_policy and related)
| Setting | Type | Default (example) |
|---|---|---|
thresholds.full_day_minutes / half_day_minutes | integer | 480 / 240 (Spryple example 8 h / 4 h) |
grace.in_minutes / grace.out_minutes | integer 0–120 | 10 / 10 |
capture.allowed_methods | set WEB, MOBILE, BIOMETRIC, KIOSK, FIELD | MOBILE, BIOMETRIC |
capture.selfie_required | boolean | true for MOBILE |
geofence.mode | enum block / flag / off | flag |
geofence.max_accuracy_m | integer 10–500 | 100 |
geofence.allowed_locations | list | home location |
punch.dedup_seconds | integer 0–600 | 60 |
punch.window_before_h / window_after_h | integer | 4 / 6 |
breaks.from_punches | boolean | false |
missed_punch.default_out | enum none / shift_end / start_plus_full_day | none |
missed_punch.provisional_value | enum 0 / 0.5 / 1 | 0.5 |
missed_punch.at_close | enum absent / half / present | absent |
late.free_count | integer 0–31 | 3 |
late.deduct_per | number (days) per late or per block | 0.5 per block of 3 |
late.deduct_order | ordered list of leave types | CL, EL, LOP |
regularization.lookback_days / max_per_period | integer | 7 / 4 |
permission.max_per_day / max_per_period / max_minutes / paid | integer / integer / integer / boolean | 1 / 2 / 120 / true |
weekoff_penalty.enabled / adjacent / applicability | boolean / enum before, after, both / rule | false / both / — |
extra_day.outcome / slabs[] | enum pay, comp_off, none / list | comp_off |
overtime_policy.* | typed policy | see FR-ATT-027; approval post, rounding 30, min 30 |
requests.work_types_enabled | list | WFH, On Duty |
roster.edit_by_line_manager | boolean | true |
device_approval.required | boolean (IAM) | false |
7.5.9 User stories
US-ATT-01 — Geo-fenced selfie punch. As an employee, I want to punch in from my phone at the plant gate.
- AC1: Given I am inside a 200 m fence and location accuracy is 30 m, when I tap Punch In and take a selfie, then the punch is accepted within 2 s and my home screen shows "In since 08:57".
- AC2: Given
geofence.mode = blockand I am 600 m away, when I tap Punch In, then the app shows "You are 600 m from Plant 1. Move closer or contact your manager" and no punch is stored. - AC3: Given
geofence.mode = flag, when I punch outside the fence, then I must enter a reason and the punch is marked out-of-fence for my manager.
US-ATT-02 — Offline punch. As an employee in a basement with no signal, I want my punch saved.
- AC1: Given no connectivity, when I punch, then the app shows "Saved offline, will sync" with the time.
- AC2: When connectivity returns within 72 h, then the punch is uploaded and the day is recomputed; if my phone clock was 20 minutes off, the punch is flagged
clock_drift.
US-ATT-03 — Night shift. As a line_manager, I want night-shift hours counted on the shift's start date.
- AC1: Given a shift 22:00–06:00 and punches at 21:55 on 3 Nov and 06:05 on 4 Nov, when the day is computed, then 3 Nov is P with 8 h 10 min and 4 Nov is not affected.
US-ATT-04 — Regularize a missed punch. As an employee, I want to fix a day where I forgot to punch out.
- AC1: Given yesterday is MP, when I open Alerts, then I can enter the out time with a reason.
- AC2: When my manager approves, then the day is recomputed (e.g. to P) and the alert disappears.
- AC3: Given the day is 10 days old and the lookback is 7 days, then the action is disabled with "Regularization window has passed; contact HR".
US-ATT-05 — Overtime approval. As a line_manager, I want to approve only genuine overtime.
- AC1: Given an operator worked 2 h 20 min beyond shift end with rounding 30 min, when OT is computed, then an OT claim of 2 h 00 min is created for me.
- AC2: When I approve 1 h 30 min, then 1 h 30 min at the working-day multiplier is sent to payroll and the rest is discarded with my note.
US-ATT-06 — Shift swap with consent. As an employee, I want to swap my Saturday night shift with a colleague.
- AC1: Given I request a swap with Ravi, when I submit, then Ravi must accept before my manager sees the request.
- AC2: When the manager approves, then both rosters change for that date and both of us are notified.
US-ATT-07 — Late deduction. As an hr_admin, I want every 3 lates after 3 free lates to deduct half a day of CL.
- AC1: Given an employee has 7 lates in the period, when the period closes, then 0.5 day is debited from CL (or the next type in order if CL is exhausted) with the reason "Late deduction: 4 lates beyond free count".
US-ATT-08 — Week-off penalty. As an hr_admin, I want week-offs unpaid when a worker is absent on both sides.
- AC1: Given penalty is on with
adjacent = bothand a worker is A on Saturday and Monday, when Sunday is computed, then Sunday shows W with the penalty flag and payable value 0.
US-ATT-09 — Period lock. As a payroll_manager, I want attendance frozen before I calculate payroll.
- AC1: Given 4 unresolved MP days, when I try to lock, then I see the list and can auto-resolve them per policy or send reminders.
- AC2: Given the period is locked and a manager approves a late regularization, then an attendance adjustment of +0.5 day is created in the next period.
US-ATT-10 — Biometric import. As an hr_manager, I want to import a day's device CSV without duplicates.
- AC1: Given a CSV with 1,200 punches of which 300 were imported yesterday, when I commit, then only 900 new punches are stored and affected days recompute.
- AC2: Given 5 device user IDs are unmapped, then those punches go to Unmapped punches for mapping.
US-ATT-11 — On-behalf attendance request. As a line_manager, I want to mark a team member On Duty for a client visit.
- AC1: Given I have
att.request.approve@TEAM, when I raise an On-duty request on their behalf with a reason, then it is approved at my level, the day becomes OD and the employee is notified.
7.5.10 Permissions
| Action | OWN | HRA | HRM | PRM | LM | EMP | KIO | AUD |
|---|---|---|---|---|---|---|---|---|
| Punch (own) | SELF | SELF | SELF | SELF | SELF | SELF | LOC (others, punch-only, R2) | — |
| View punches, photos, days | ORG | ORG | LOC* | ORG(R) | TEAM | SELF | — | ORG(R) |
| Raise requests (attendance, regularization, permission, shift change) | SELF | SELF | SELF + on behalf LOC* | SELF | SELF + on behalf TEAM | SELF | — | — |
| Approve requests and OT | ORG | ORG | LOC* | — | TEAM | — | — | — |
| Shifts, rotations, rosters, week-offs | ORG | ORG | LOC* | — | TEAM (if roster.edit_by_line_manager) | view SELF | — | ORG(R) |
| Attendance policies, geo-fences | ORG | ORG | LOC*(R) | ORG(R) | — | view own policy | — | ORG(R) |
| Manual punch, import, device mapping | ORG | ORG | LOC* | — | — | — | — | — |
| Lock period | ORG | ORG | LOC* | ORG | — | — | — | — |
| Unlock period | ORG | ORG (reason) | — | ORG (reason) | — | — | — | — |
7.5.11 UI/UX
- Employee mobile (primary): home card with a large Punch button showing state (In since / Out), fence status chip ("Inside Plant 1"), shift today; Alerts list; calendar month with codes and legend; request forms (attendance, regularization, permission, shift change) as bottom sheets; offline banner and pending-sync counter.
- Employee web: same calendar and requests; web punch button if allowed.
- Line manager mobile: Team today (counts + list), Approvals inbox (swipe approve/reject, bulk select), OT claims, team calendar; roster view (read and simple edits).
- HR web: Attendance workbench with tabs Daily (status grid with filters), Exceptions (MP, out-of-fence, anomalies), Requests, OT, Rosters, Devices & imports, Period close (checklist, lock button with a confirmation listing totals).
- States: before first shift assignment, show "No shift assigned. Ask HR" on the punch card; location permission denied shows a step-by-step enable guide and alternative methods; camera denied blocks selfie punch with guidance; a locked period shows a lock icon and disables edits with "Locked on 27 Oct by Anil".
7.5.12 Notifications and automation
Punch reminder at shift start + grace if not punched (push, opt-out); missed punch-out reminder at shift end + 1 h; alerts digest for pending regularizations (daily); request submitted/decided; swap consent requested; OT claim pending (manager, daily digest); roster published or changed; device offline (HR); period close reminder (HR, 2 days before window end); period locked (PRM); auto-resolution summary.
7.5.13 Reports and analytics
Monthly attendance register (code grid with counts), daily attendance, punch detail with photos and source, late and early-go, missed punch, overtime (claimed vs approved, by multiplier, cost estimate), extra days and penalties, shift-wise attendance and coverage, out-of-fence and anomalies, device health, payable-days summary, absenteeism rate trend (RPT). See §13.
7.5.14 Edge cases
- Duplicate source punches (biometric and mobile within a minute) → deduplicated; both are retained in raw data.
- Late-arriving biometric data for a past unlocked date → day recomputed; if the date is locked → the punch is stored and an adjustment suggestion is raised to HR.
- Shift change mid-period → days before and after use their own shift; the engine never back-applies a new shift to past days unless the assignment is back-dated.
- Employee joins mid-period → days before joining are NE and excluded from payable days.
- Holiday added after the day was computed → recompute to H (or HP if worked) and reverse LOP.
- Device clock wrong → device-time offset can be set per device; affected punches are re-timed with an audit entry.
- DST/time zones → India has no DST; locations carry a time zone for future non-IST sites; storage is UTC.
- Leave and punch on the same day → approved full-day leave wins; punches are kept and flagged "worked on leave" for HR (no automatic comp-off).
- Consent withdrawn for location → MOBILE punches are rejected with guidance to use another method (FR-IAM-018).
7.6 LVE — Leave & Holidays
Traces to: BR-LVE-* · Release: R1 (MVP-critical); R2 statutory leave templates; R3 calendar sync
7.6.1 Purpose and scope
LVE lets tenants define any leave type, credits balances through an auditable ledger, handles requests, cancellations, comp-off and optional holidays, and feeds LOP and encashment to payroll through ATT and PAY.
| In scope | Out of scope |
|---|---|
| Leave-type builder with templates; per-type policies (eligibility, accrual, caps, carry-forward, lapse, encashment, sandwich, notice, documents); ledger; accrual and year-end jobs; requests, cancellation, on-behalf; comp-off; optional holidays; advanced (negative) leave; opening balances; calendars; leave payroll bridge | Hourly leave (Won't R1); leave trading or donation between employees; holiday master (ORG, FR-ORG-010) |
7.6.2 Reference product summary
- Ten fixed leave types: Casual, Sick, Comp-off, Loss of Pay, Maternity, Paternity, Wedding, Bereavement, Earned, Advanced; activate or deactivate only [Observed] (A: Leave Management; SP-LVE-02).
- Per-type rules: quota, credit frequency (monthly/quarterly/half-yearly/yearly), sandwich flags, max per instance, minimum service months, advance notice days, lapse days, lapse → perks, document above N days, comp-off minimum hours and expiry days, carry-forward cap, maternity minimum gap between terms and maximum times, advanced leave borrowed against a monthly-accruing CL/SL/EL [Observed] (SP-LVE-03).
- Common rules: sandwich across weekends and holidays, past-dated leave window, configurable emails, leave cycle Apr–Mar or Jan–Dec, max optional holidays per year [Observed] (SP-LVE-01).
- Eligibility by gender and marital status (maternity for "married females", paternity for "married male") [Observed] (SP-LVE-04).
- Employee: balance-limited request with half days, history with edit/delete before approval, cancel approved future leave, comp-off only on week-off/holiday dates, optional holiday requests, view-only policies [Observed] (SP-LVE-05). Mobile request also captures contact number and emergency mail during leave [Observed] (research §21.4).
- Manager: cancellation approvals, on-behalf leave and comp-off (auto-approved, balance shown), reports and a Payroll Report (approved leaves, LOP and absent counts) [Observed] (SP-LVE-06).
- Policy changes apply only to new employees [Observed] (SP-LVE-07).
7.6.3 What we change and why [Proposed]
- Leave-type builder seeded with Spryple-like templates, so tenants add Restricted, Study, Sabbatical, Menstrual or state-specific leave without code.
- Ledger instead of a mutable balance, so every balance is explainable and auditable.
- Inclusive eligibility: marital status is never a condition; parental leave is gender-neutral (primary/secondary caregiver, adoption, surrogacy); statutory maternity eligibility is expressed through service/days-worked conditions, not marriage.
- Effective-dated policy versions with an explicit "apply to existing employees from date X" recalculation.
- Encashment through payroll instead of only "convert to perks".
7.6.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-LVE-001 | Leave-type builder: name, code, colour, paid/unpaid, category (General, Sick, Comp-off, LOP, Parental, Statutory, Special), unit (full/half day), active flag. Templates seed the ten observed types (Paternity becomes "Parental — secondary caregiver"). LOP is a system type that cannot be deleted. | Must | R1 | [Observed] SP-LVE-02 redesigned |
| FR-LVE-002 | Typed leave_policy per type and applicability, effective-dated, with the settings in §7.6.6. | Must | R1 | [Observed] SP-LVE-03 + [Proposed] |
| FR-LVE-003 | Inclusive eligibility: conditions by employment type, minimum service days, probation allowed, location, grade, and optional caregiver role; gender may be used only for types flagged statutory_gender_specific (e.g. maternity benefit) and never marital status; maternity eligibility supports a days-worked condition (e.g. 80 days in the preceding 12 months under the Maternity Benefit Act, to verify). | Must | R1 | [Proposed] (drops [Observed] SP-LVE-04) |
| FR-LVE-004 | Leave ledger per employee and type: entries opening, accrual, debit (request), reversal, adjustment, carry_forward, lapse, encashment, late_deduction, comp_off_credit, comp_off_expiry; each with date, quantity, source reference, policy version and actor. Balances are derived; concurrent debits are serialised per employee. | Must | R1 | [Proposed] |
| FR-LVE-005 | Accrual engine: credits per frequency (monthly, quarterly, half-yearly, yearly), at period start or end, idempotent per (employee, type, period); preview of the next run; backfill when a policy version changes. | Must | R1 | [Observed] SP-LVE-03 + [Proposed] |
| FR-LVE-006 | Pro-rata on joining and exit with rounding (nearest_half, down_half, none) and a joining-day cut-off (e.g. joined after the 15th → no credit that month). | Must | R1 | [Proposed] |
| FR-LVE-007 | Leave request: type (eligible types only, with live balance), from/to dates, first/second half on start and end days, reason, attachment, contact number and alternate email during leave; the day count is shown before submit. | Must | R1 | [Observed] SP-LVE-05, research §21.4 |
| FR-LVE-008 | Day counting excludes the employee's week-offs and holidays unless sandwich rules apply: sandwich.weekends (week-offs between two leave days are counted), sandwich.holidays (holidays between leave days are counted), and sandwich.adjacent (e.g. leave on Friday and Monday counts Saturday and Sunday). Uses the employee's own roster and holiday calendar. | Must | R1 | [Observed] SP-LVE-01/03 |
| FR-LVE-009 | Validations: balance (or negative allowance), max/min per request, advance notice days, backdated window days, document required above N days (upload now or within N days after return), max times per year or career, minimum gap between terms, overlap with existing requests or OD, dates in a locked period. Each failure gives a specific message. | Must | R1 | [Observed] SP-LVE-03 |
| FR-LVE-010 | Team conflict warning: show teammates on leave on the same dates to the employee (names only if permitted) and to the approver, with a configurable max-concurrent-absence warning per team. | Should | R1 | [Proposed] |
| FR-LVE-011 | Cancellation: before approval → withdraw; approved and fully in the future → cancellation request needing approval (CancelRequested in §6.2); partially taken → cancel remaining days only; past leave → HR only, unlocked period only. Approved cancellation posts a ledger reversal. | Must | R1 | [Observed] SP-LVE-05/06 |
| FR-LVE-012 | On-behalf leave and comp-off by line manager or HR, with balance shown and reason required; approved at the actor's level (§6.2). | Must | R1 | [Observed] SP-X-04 + [Proposed] |
| FR-LVE-013 | Optional holidays: per calendar list of optional holidays; yearly quota per policy (optional_holiday.max_per_year); request and approval; on-behalf; availed day shows as H with the optional flag in ATT. | Must | R1 | [Observed] SP-LVE-01/06 |
| FR-LVE-014 | Comp-off credit: (a) employee request for a worked week-off/holiday date with hours worked (only WP/HP dates selectable, minimum hours per policy, within the backdated window), or (b) automatic credit from approved ATT outcomes (extra day or OT as comp-off, FR-ATT-028/029). Credits expire after comp_off.expiry_days (default 60) with a reminder 7 days before. | Must | R1 | [Observed] SP-LVE-03/05 |
| FR-LVE-015 | Advanced (negative) leave: allow borrowing up to N days against a type that accrues monthly; the negative balance is recovered from future accruals; at exit the outstanding negative balance becomes an F&F deduction (EXT). | Should | R1 | [Observed] SP-LVE-02/03 |
| FR-LVE-016 | Year-end processing per leave cycle: preview and run carry-forward (with cap), lapse (with optional lapse days grace), and encashment candidates; idempotent and reversible until the next accrual runs. | Must | R1 | [Observed] SP-LVE-03 + [Proposed] |
| FR-LVE-017 | Leave encashment payout through PAY: at year end (from FR-LVE-016 candidates), on employee request (if allowed, with approval), and at F&F; amount = days × per-day rate from a formula on configured components (e.g. Basic / 26 or Basic / 30). | Should | R1 | [Proposed] |
| FR-LVE-018 | Opening balances by import (FR-ORG-012) and manual adjustments with reason, both as ledger entries. | Must | R1 | [Proposed] |
| FR-LVE-019 | Employee balance view per type (available, booked, pending, taken this cycle, expiring soon) and a ledger statement with "how calculated" for each entry. | Must | R1 | [Observed] SP-LVE-05 + [Proposed] |
| FR-LVE-020 | Calendars: my leave, team leave (line manager), organisation leave by location/department (HR); holidays list (next 3 and View all). | Must | R1 | [Observed] SP-LVE-05/06 |
| FR-LVE-021 | Policy documents: view-only company leave policy PDFs and a generated plain-language summary of the employee's own resolved policy. | Must | R1 | [Observed] SP-LVE-05 + [Proposed] |
| FR-LVE-022 | Locked-period protection: approvals, cancellations or policy changes that would alter a locked period do not change it; they create ledger and attendance adjustments in the next open period (FR-ATT-034). | Must | R1 | [Proposed] |
| FR-LVE-023 | Leave payroll bridge report: per employee per period approved leave by type, LOP days, absent days and encashment days, reconciled with ATT payable days. | Must | R1 | [Observed] SP-LVE-06 |
| FR-LVE-024 | Policy version migration: when a new version applies to existing employees, show a preview of balance changes (e.g. quota 12 → 15, pro-rated from 1 July) and post adjustment entries on activation. | Must | R1 | [Proposed] (fixes [Observed] SP-LVE-07) |
| FR-LVE-025 | Insufficient balance handling: offer to split a request into the available paid days plus LOP days, if the policy allows. | Should | R1 | [Proposed] |
| FR-LVE-026 | Statutory state leave templates (e.g. Shops & Establishments minimum entitlements by state), published with the statutory pack. | Could | R2 | [Proposed] |
| FR-LVE-027 | Calendar sync of approved leave to Google/Microsoft calendars (out-of-office event). | Should | R3 | [Proposed] (architecture.md §16) |
| FR-LVE-028 | Hourly leave units. | Won't | R1 | [Proposed] (use ATT permissions for short absences) |
7.6.5 Key entities
leave_type, leave_policy / leave_policy_version (per type, applicability), leave_ledger_entry (employee, type, date, qty, kind, source_ref, policy_version_id), leave_request (type, from, to, from_session, to_session, days, status, contact, alt_email, attachment), leave_request_day (date, session, counted, reason: sandwich/regular), comp_off_credit (worked_date, hours, expires_on, status), optional_holiday_request, leave_cycle_run (type, cycle, kind, status), encashment_request.
7.6.6 Configuration settings (typed leave_policy, per type)
| Setting | Type | Default (Casual Leave template example) |
|---|---|---|
entitlement.annual_days | decimal | 12 |
accrual.frequency / accrual.timing | enum monthly, quarterly, half_yearly, yearly / start, end | monthly / start |
accrual.prorate_joining / rounding / joining_cutoff_day | boolean / enum / integer | true / nearest_half / 15 |
eligibility.min_service_days / allow_in_probation / employment_types | integer / boolean / list | 0 / true / all |
request.max_days / min_days / half_day_allowed | decimal / decimal / boolean | 3 / 0.5 / true |
request.advance_notice_days / backdated_days | integer | 1 / 3 |
request.document_required_above_days | integer or null | null (Sick template: 2) |
limits.max_times_per_year / max_times_career / min_gap_years | integer or null | null |
sandwich.weekends / holidays / adjacent | boolean | false / false / false |
balance.max_cap / negative_allowed_days | decimal or null | null / 0 |
year_end.carry_forward_max / lapse / encash_max | decimal / boolean / decimal | 0 / true / 0 (Earned template: carry 30, encash 15) |
comp_off.min_hours / expiry_days / backdated_days | decimal / integer / integer | 4 / 60 / 30 (Comp-off template) |
approval.workflow | reference to NTF workflow | line manager, single level |
notifications.enabled | boolean | true |
Tenant-level: leave_cycle (ORG), optional_holiday.max_per_year (default 2), team_conflict.max_concurrent (default off).
7.6.7 User stories
US-LVE-01 — Apply for leave on mobile. As an employee, I want to apply for two days of casual leave and see the count before submitting.
- AC1: Given I select Thu–Fri with a CL balance of 4, when I pick the dates, then the form shows "2 days" and "Balance after: 2".
- AC2: Given Saturday and Sunday are my week-offs and sandwich weekends is off, when I select Fri–Mon, then the count is 2 days.
- AC3: Given sandwich weekends is on, when I select Fri–Mon, then the count is 4 days with Saturday and Sunday labelled "sandwich".
US-LVE-02 — Approve with team context. As a line_manager, I want to see who else is away before approving.
- AC1: Given two teammates are on leave on the same dates, when I open the request, then I see their names and the team's absence count for those dates.
- AC2: When I reject, then a reason is mandatory and the employee is notified with it.
US-LVE-03 — Cancel future leave. As an employee, I want to cancel approved leave next week.
- AC1: Given approved leave starting in 5 days, when I cancel, then the request moves to Cancellation requested and my manager is notified.
- AC2: When my manager approves the cancellation, then the ledger shows a reversal and my balance is restored.
- AC3: Given leave that started yesterday, when I try to cancel, then only the remaining future days can be cancelled.
US-LVE-04 — Comp-off from holiday work. As an employee who worked on a holiday, I want a comp-off credit.
- AC1: Given the day is HP with 6 h worked and the minimum is 4 h, when I request comp-off, then the request shows 1 day and goes to my manager.
- AC2: Given the credit is approved on 1 Nov with expiry 60 days, when 24 Dec arrives, then I get a reminder; on 31 Dec the unused credit expires with a ledger entry.
US-LVE-05 — Gender-neutral parental leave. As an hr_admin, I want parental leave available to any new parent.
- AC1: Given a "Parental — secondary caregiver" type with no gender condition, when an employee of any gender applies with the child's date of birth or adoption date, then the request is accepted if within the policy window.
- AC2: When I try to add marital status as an eligibility condition, then the policy editor does not offer that field.
US-LVE-06 — Mid-year policy change for everyone. As an hr_admin, I want to raise annual EL from 15 to 18 days from 1 July for existing employees.
- AC1: Given a new version effective 1 July, when I preview, then I see each employee's additional pro-rated credit (e.g. +1.5 days for July–December).
- AC2: When I activate, then adjustment entries are posted and the employee ledger shows "Policy update EL v3".
US-LVE-07 — Year-end carry-forward. As an hr_manager, I want to run the year-end process safely.
- AC1: Given carry-forward max 30 and encashment max 15, when I preview year-end for 31 Dec, then I see carry-forward, lapse and encashment per employee before running.
- AC2: Given I run it twice, then the second run makes no changes.
US-LVE-08 — Optional holiday. As an employee, I want to take Onam as an optional holiday.
- AC1: Given my quota is 2 and I have used 1, when I request Onam, then it goes for approval and, once approved, the day shows H (optional) and my quota shows 0 remaining.
7.6.8 Permissions
| Action | OWN | HRA | HRM | PRM | LM | EMP | AUD |
|---|---|---|---|---|---|---|---|
| Leave types and policies | ORG | ORG | ORG(R) | ORG(R) | — | own policy (R) | ORG(R) |
| Apply / cancel own | SELF | SELF | SELF | SELF | SELF | SELF | — |
| Apply on behalf | ORG | ORG | LOC* | — | TEAM | — | — |
| Approve requests and cancellations | ORG | ORG | LOC* | — | TEAM | — | — |
| View balances and ledger | ORG | ORG | LOC* | ORG(R) | TEAM | SELF | ORG(R) |
| Manual adjustment, opening import | ORG | ORG | LOC* | — | — | — | — |
| Year-end run | ORG | ORG | ORG (run) | ORG(R) | — | — | — |
| Encashment approval | ORG | ORG | LOC* | ORG (pay) | — | request SELF | — |
7.6.9 UI/UX
- Employee mobile: balance chips coloured by type on the Leave tab; Apply bottom sheet with a range calendar that greys week-offs and holidays, shows the live count and sandwich labels; history list with status chips and actions per status; comp-off and optional-holiday tabs; policy summary.
- Line manager: approvals inbox (shared with ATT), team leave calendar (month view with avatars), conflict banner inside each request.
- HR web: leave types (builder with template picker), policy editor with version timeline and preview, balances grid with ledger drill-down, year-end runner (preview → run), import for opening balances.
- States: no eligible leave type → "You are not yet eligible for leave. CL becomes available after 30 days of service (on 14 Dec)". Insufficient balance → offer split with LOP (FR-LVE-025). Locked period → "These dates are in a locked payroll period; HR will adjust in the next period".
7.6.10 Notifications and automation
Request submitted (approver), decided (employee, with reason), cancellation requested/decided, reminder for pending approvals (daily digest, escalation per NTF), comp-off expiring, balance credited (monthly, opt-in), year-end summary (employee), document pending after return (employee, HR), long leave starting (HR, for absence planning).
7.6.11 Reports and analytics
Leave balance (as on date), leave register (employee-wise, date-wise, type-wise, designation-wise), leave summary (worked days vs leave), comp-off register (credited, availed, expired), LOP report, encashment report, year-end report, leave trend and Bradford-style absence frequency (Could, R4).
7.6.12 Edge cases
- Holiday calendar changes after leave approval → the request's day count is recomputed; the ledger is adjusted (or a next-period adjustment if locked) and the employee is notified.
- Roster change makes a leave day a week-off → that day is no longer counted (unless sandwich applies).
- Employee transfers to a location with a different policy mid-cycle → the new policy applies from the transfer date; accruals are pro-rated across both versions.
- Leave spans two payroll periods, one locked → the locked part stays; the open part follows the change.
- Exit date before an approved future leave → the leave beyond the exit date is cancelled automatically with reversal.
- A request exceeding the balance at submission but valid at approval (accrual in between) → validation re-runs at approval time.
7.7 PAY — Payroll & Statutory Compliance (India)
Traces to: BR-PAY-* · Release: R1 (MVP-critical, highest risk); R2 Form 16, 24Q, journal export, F&F run, reimbursement payout, VDA; R4 accounting API connectors
7.7.1 Purpose and scope
PAY turns compensation, attendance and inputs into a correct, reproducible, approved and locked payroll, then produces payslips, bank files and statutory files for Indian employers.
| In scope | Out of scope |
|---|---|
| Salary components and formulas; structure templates; effective-dated compensation; pay schedules and pay groups; EPF, ESI, PT, LWF, TDS (with regime choice, IT declarations and proofs in R1), gratuity provision; inputs (attendance, one-time, recurring, variable pay, arrears, OT, extra days); advance salary and loans; run lifecycle with validation, variance, approval, lock, payment and reversal; off-cycle runs; payslips; bank files; ECR, ESI, PT and LWF files; Form 16 and 24Q data (R2); journal export (R2); F&F run (R2) | Direct filing on government portals (we generate files; architecture.md §16); payroll for employees outside India; payroll outsourcing services; earned wage access (§15); weekly or fortnightly pay frequencies (Won't R1) |
7.7.2 Reference product summary
- Pay groups are chosen by CTC range: name, CTC start–end, chosen earnings and deductions, each component as % (of CTC/Basic) or flat; components can be renamed for the payslip; status "Configuration in Progress → Active" [Observed] (A: Payroll Management; SP-PAY-05). A sample pay group is named "… without ESI", implying the structure decides statutory applicability [Inferred] (research §21.5).
- Assign / reassign pay group with a CTC breakdown (monthly/annual, EPF-aware), used for increments and new financial years [Observed] (M: Payroll Management; SP-PAY-10/11).
- Statutory configuration: EPF employee/employer contribution, admin charges, EDLI; ESI with "include employer contribution in CTC" and state-wise ESI numbers; PT by state with slabs; gratuity and VDA [Observed] (SP-PAY-02/03/07/08/13).
- Pay schedule: same or different payroll and leave windows (e.g. 25th–24th); salary basis "actual days in month" or "organisation working days" [Observed] (SP-PAY-04).
- Payroll policies (14 rules): advance-salary instalments and cooling-off, OT in salary, gratuity coverage, VDA, absent = LOP, dynamic payroll processing, ESI/EPF independent of LOP, minimum OT hours, variable-pay frequency, LOP-linked week-off deduction, extra-day payment [Observed] (SP-PAY-07).
- Monthly payroll: select FY and month → select employees → Calculate Salary → payslips published; only the Finance Manager can generate [Observed] (SP-PAY-12). No lock, approval or reversal is documented [Inferred] (research §7.3).
- Inputs: arrears by month/branch/employee with Pending/Paid [Observed] (SP-PAY-09); other deductions master [Observed] (SP-PAY-14); variable pay with calculation and distribution periods, monthly share or lump sum [Observed] (SP-PAY-17); TDS entered as a manual amount per employee [Observed] (SP-PAY-16), although the employee menu shows IT Declaration and Form 16 [Observed] (research §21.5).
- Advance salary: needs at least one payslip; amount ≤ gross; approval by Finance Manager; recovery tracking [Observed] (E: Payroll Management). The Advance Salary Report section is empty [Observed doc defect] (research §17 D9).
- Outputs: Monthly Payroll (PDF for bank), EPF download for the portal, ESI and PT reports, bank-wise salary summary [Observed] (SP-PAY-13/15). Portal-ready ECR/ESIC files and bank transfer files are not evidenced [Inferred] (research §7.3).
- Payslip shows earnings, deductions, other deductions, LOP, arrears, variable pay, gratuity, OT and extra days; sample earnings include fuel, vehicle maintenance and VDA; gratuity appears as an employee deduction [Observed] (research §21.5).
7.7.3 What we change and why [Proposed]
| Change | Why |
|---|---|
| Structure templates separate from effective-dated compensation | A CTC range should not decide the structure; a promotion at the same CTC, or an employee outside every range, must still work. History must be correct for arrears. |
| Formula components with a safe expression language | Tenants express their rules (e.g. HRA = 40% of Basic for non-metro) without vendor changes. |
| Run lifecycle Draft → Calculated → Reviewed → Approved → Locked → Paid → Reversed with immutable snapshots | Legal defensibility; no silent edits after payment; four-eyes control. |
| TDS engine with regime choice, declarations and proofs in R1 | Manual TDS is error-prone and Spryple appears to offer declarations (parity). |
| Portal-ready ECR, ESI, PT and LWF files and bank transfer files | The real month-end work is producing files the portals and banks accept. |
| Gratuity as an employer provision, not an employee deduction | Gratuity is an employer liability; showing it as a deduction misleads employees [Inferred critique] (research §21.5). |
| Advances and loans on a recovery ledger | Recovery must survive pauses, prepayments and exit. |
Statutory values in this section are examples to verify with a payroll/compliance expert. They live in the statutory pack (FR-PLT-009). Note: the Income-tax Act, 2025 replaces the Income-tax Act, 1961 from 1 April 2026 and renumbers sections and forms; this PRD uses the familiar names (Form 16, 24Q, Form 12BB, Form 12BA) as functional labels for "annual TDS certificate", "quarterly salary TDS return" and so on. The Labour Codes were brought into force in November 2025; central and state rules and their effect on wage definitions must be verified before R1 GA.
7.7.4 Core model
7.7.5 Payroll run lifecycle
| Transition | Who (default) | Preconditions | Effects |
|---|---|---|---|
| Create (Draft) | payroll_manager | Pay group and period open; no other open regular run for the same pay group and period | Inputs editable; employees included by pay group and employment dates |
| Calculate | payroll_manager | Attendance period locked, or the pay schedule uses an attendance cut-off (FR-PAY-005); no blocking validations | Snapshot of inputs; per-employee results; variance report |
| Review | payroll_manager or a designated reviewer | Every blocking issue cleared; every warning acknowledged or employee held | Run read-only except holds and comments |
| Approve | org_owner or finance_admin (workflow configurable, FR-PAY-035) | Approver did not edit inputs in this run when SoD is on (FR-PAY-036) | Approval recorded with totals hash |
| Lock | Approver or payroll_manager (auto-lock on approval is a setting) | Approved | Inputs and results immutable (Object Lock for artefacts); payslips, bank, statutory and journal files generated; payslips published at payslip.publish_at |
| Paid | payroll_manager | Locked | Payment date and UTR per employee (import or bulk mark); failed payments listed for re-issue |
| Reverse | payroll_manager requests, approver approves | Locked or Paid; reason required | A reversal run with negated lines is created and locked; the original shows "Reversed by PR-…"; a correction off-cycle can then be run. Statutory files for the period are regenerated as revised versions. |
7.7.6 Calculation pipeline (per employee, deterministic)
- Resolve snapshot: compensation versions active in the period (a mid-period revision splits the period into segments, each prorated), job assignment (state for PT/LWF, legal entity), statutory pack version, payroll policy version.
- Days: payable days and LOP from ATT (FR-ATT-035); salary basis from the pay schedule (calendar days, fixed 30, fixed 26, or organisation working days).
- Earnings: fixed components prorated by
payable_days / basis_dayswhereprorate = true; formula components evaluated in dependency order; OT = approved minutes × hourly-rate formula × multiplier; extra days; variable pay; arrears; one-time earnings; reimbursements (R2). - Wage bases: EPF wages, ESI wages, PT gross, LWF wages and gratuity wages from component flags, with the Labour Codes wage check if enabled (FR-PAY-015).
- Employee statutory deductions: EPF (and VPF), ESI, PT, LWF.
- TDS from the TDS engine (FR-PAY-050).
- Other deductions: advance and loan EMIs, recurring deductions, one-time deductions, penalties.
- Net pay = gross earnings − total deductions, rounded per
rounding.net(default nearest rupee, with a rounding line). If net < 0, deductions are applied in priority order (statutory → TDS → loans/advances → others) and unrecovered amounts are carried forward with a flag. - Employer cost: EPF employer (EPS + EPF), EDLI, admin charges, ESI employer, LWF employer, gratuity provision, other employer contributions → monthly CTC cost.
All money uses exact decimal arithmetic (no floating point), rounding is defined per component (nearest, up, down, to 1 or 0.01), and each line stores its formula, inputs and result for "how calculated".
7.7.7 Statutory reference values (examples to verify)
| Item | Example value in the statutory pack (verify before use) |
|---|---|
| EPF | Employee 12% of EPF wages; employer 12% split 8.33% EPS (on wages up to the ₹15,000 ceiling, i.e. max ₹1,250) and 3.67% EPF; EDLI 0.5% on wages up to ₹15,000; admin charges 0.5%; contributions above the ceiling optional per employee/employer |
| ESI | Employee 0.75%, employer 3.25% of ESI wages; coverage when gross wages ≤ ₹21,000 per month (₹25,000 for persons with disability); contribution periods April–September and October–March (coverage continues for the period once eligible) |
| PT | State-specific monthly slabs and special months (e.g. a higher February deduction in some states); annual cap ₹2,500 under the Constitution |
| LWF | State-specific employee and employer amounts, monthly, half-yearly (e.g. June/December) or annual |
| TDS | New regime as default with standard deduction and rebate per the tax year; old regime on employee choice; health and education cess 4%; surcharge slabs; higher rate when PAN is missing |
| Gratuity | 15/26 × last drawn wages × completed years of service; eligibility after 5 years of continuous service (shorter for fixed-term employees under the Code on Social Security, to verify); ceiling ₹20 lakh |
7.7.8 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| Set-up | ||||
| FR-PAY-001 | Component master: code, name, payslip label, type (Earning, Deduction, Employer contribution, Reimbursement, Variable, Statutory), calculation method (Flat, % of components, Formula, Monthly input, Slab lookup), prorate by payable days, part of CTC, taxability (taxable / exempt / partially exempt with rule reference), wage-base flags (EPF, ESI, PT, LWF, gratuity, Labour Codes "wages" vs "exclusion"), rounding, display order. Seeded with standard Indian components (Basic, DA, HRA, Conveyance, Special allowance, LTA, Bonus, OT, Arrears, EPF, ESI, PT, LWF, TDS). | Must | R1 | [Observed] SP-PAY-05 + [Proposed] |
| FR-PAY-002 | Safe formula language: arithmetic, min, max, round, if, comparisons; references to components, CTC, payable_days, basis_days, days_in_period, approved OT minutes, employee attributes (state, metro flag, grade, employment type); no loops or external calls; dependency ordering with cycle detection; "test with employee" preview. | Must | R1 | [Proposed] |
| FR-PAY-003 | Salary structure templates: named, versioned (Draft → Active → Retired), list of components with calculation per component; one balancing component (e.g. Special allowance = CTC − other CTC components) that can never go negative (save-time check across a CTC range preview). Templates replace CTC-range pay groups. | Must | R1 | [Observed] SP-PAY-05 redesigned |
| FR-PAY-004 | Employee compensation record, effective-dated: annual CTC (or monthly gross for Lite), structure template version, component overrides, pay group, reason (Joining, Increment, Promotion, Correction, Restructure); monthly and annual breakdown preview including employer contributions; history list (the employee's CTC history). | Must | R1 | [Observed] SP-PAY-10/11 + [Proposed] |
| FR-PAY-005 | Pay schedule: period window (calendar month, or custom start day such as 26th–25th); optional attendance cut-off earlier than the period end, with days after the cut-off assumed present and trued-up next period as adjustments; salary basis (calendar days, fixed 30, fixed 26, organisation working days); pay date; payslip publish rule. | Must | R1 | [Observed] SP-PAY-04, SP-PAY-07 (dynamic processing) |
| FR-PAY-006 | Pay groups: legal entity + pay schedule (+ optional location filter); each employee belongs to one pay group at a time through the compensation record. | Must | R1 | [Proposed] |
| FR-PAY-007 | EPF settings per legal entity from the statutory pack: rates, wage ceiling, employer split, EDLI and admin charges, per-employee options (contribute on actual wages above ceiling, VPF %, EPF exempt/excluded with reason), EPS eligibility (age 58 cut-off, pre-existing membership). | Must | R1 | [Observed] SP-PAY-02 + [Proposed] |
| FR-PAY-008 | ESI settings: rates, wage threshold, contribution-period continuity, employer codes by state, "include employer contribution in CTC" toggle; zero-day reason codes. | Must | R1 | [Observed] SP-PAY-03 + [Proposed] |
| FR-PAY-009 | PT: enabled states per legal entity, slabs from the statutory pack by the employee's work state, special months, exemption flags (e.g. persons with disability where a state exempts them). | Must | R1 | [Observed] SP-PAY-13 |
| FR-PAY-010 | LWF: enabled states, employee and employer amounts, frequency and deduction months from the statutory pack. | Must | R1 | [Proposed] (gap in [Observed]) |
| FR-PAY-011 | Gratuity: monthly provision as an employer contribution (optional CTC component), eligibility rules and formula from the pack; payout computed in F&F (FR-PAY-060). | Must | R1 | [Observed] SP-PAY-07 redesigned |
| FR-PAY-012 | Company bank accounts (debit accounts): bank, IFSC, account, branch address, bank-file format, and flags for which account pays salary, EPF, ESI or PT. | Must | R1 | [Observed] SP-PAY-06 |
| FR-PAY-013 | Typed payroll_policy: absent = LOP; OT included in salary; extra-day payment formula; LOP-linked week-off deduction; ESI/EPF behaviour on LOP; variable-pay frequency; advance and loan rules (FR-PAY-023/024); deduction priority; rounding; negative-net handling. | Must | R1 | [Observed] SP-PAY-07 consolidated |
| FR-PAY-014 | Minimum-wage check per state and skill category (where loaded in the pack): warning on compensation save and in pre-run validation. | Should | R1 | [Proposed] |
| FR-PAY-015 | Labour Codes wage check: if exclusions exceed 50% of total remuneration, add the excess to wages for EPF/gratuity bases per tenant setting; show the impact in the structure preview (verify the rule before enabling by default). | Should | R1 | [Proposed] |
| FR-PAY-016 | Variable DA: notification name, CPI points, rate per point, effective date, attachment; drives a VDA component. | Could | R2 | [Observed] SP-PAY-08 |
| FR-PAY-017 | Bulk salary revision: import or grid of new CTCs/templates with effective date, preview of monthly impact and arrears, revision letters (FR-EMP-016). | Should | R1 | [Observed] SP-PAY-11 + [Proposed] |
| FR-PAY-018 | Lite payroll profile: a "Simple" template (monthly salary × payable days / basis days, optional PT/EPF/ESI) on the same engine, with a simplified run screen. | Must | R1 | [Observed] research §21.5 (Lite report) |
| Inputs | ||||
| FR-PAY-019 | Attendance and leave inputs from the locked ATT period (FR-ATT-035) including adjustments from earlier periods; the run shows the ATT lock version used. | Must | R1 | [Observed] research §16 + [Proposed] |
| FR-PAY-020 | One-time earnings and deductions per employee per run via a grid or import (incentive, bonus, fine, canteen, uniform), with component and remark. | Must | R1 | [Observed] SP-PAY-14 + [Proposed] |
| FR-PAY-021 | Recurring deductions: master (name, default amount) assigned to employees with start/end months. | Must | R1 | [Observed] SP-PAY-14 |
| FR-PAY-022 | Variable pay plans: calculation period, distribution as monthly share or lump sum, amounts per employee (import), payout month. | Must | R1 | [Observed] SP-PAY-17 |
| FR-PAY-023 | Advance salary request: eligibility (at least advance.min_payslips payslips, default 1; amount ≤ advance.max_pct_of_gross of last gross, default 100%; cooling-off months after last recovery); instalments (1–advance.max_instalments, default 6); approval line manager (optional) → payroll manager; disbursed in the next run or off-cycle. | Must | R1 | [Observed] E: Payroll Management, SP-PAY-07 |
| FR-PAY-024 | Loans: type, principal, interest (0% default; simple or reducing), EMI schedule, start month; perquisite value flag for TDS on concessional loans (verify threshold). | Should | R1 | [Proposed] |
| FR-PAY-025 | Recovery ledger for advances and loans: scheduled EMIs, recovered amounts per run, pause/skip with approval, prepayment, outstanding balance, auto-flag to F&F at exit. | Must | R1 | [Observed] (recovery tracking) + [Proposed] |
| FR-PAY-026 | Salary hold and release per employee per run (with reason); held salaries are excluded from bank files and released in a later run or off-cycle. | Must | R1 | [Proposed] |
| FR-PAY-027 | Reimbursement payout: approved CLM claims flow as non-taxable/taxable reimbursement components into the next run (or a bank file outside payroll, per tenant setting). | Must | R2 | [Proposed] (fixes [Observed] gap) |
| Run lifecycle | ||||
| FR-PAY-028 | Payroll run per pay group and period with type Regular, Off-cycle (Bonus, Correction, Arrears-only, Supplementary), F&F (R2) or Reversal; ID PR-{YYYYMM}-{NN}. | Must | R1 | [Proposed] |
| FR-PAY-029 | Run state machine and transition rules as in §7.7.5; every transition audited with actor, time, totals hash and comment. | Must | R1 | [Proposed] |
| FR-PAY-030 | Pre-run validations, blocking: missing compensation, missing or invalid bank account (unless payment mode is cash/cheque), attendance not locked (unless cut-off mode), structure balancing component negative, duplicate run. Warnings: missing PAN (higher TDS), missing UAN for EPF members, minimum-wage breach, ESI threshold crossing, new joiners and leavers in period, net pay change > variance.threshold_pct. | Must | R1 | [Proposed] |
| FR-PAY-031 | Calculation engine per §7.7.6: deterministic, exact decimal, idempotent; 1,000 employees in < 5 minutes (NFR-PERF-04); per-line explanation; frozen input snapshot. | Must | R1 | [Proposed] |
| FR-PAY-032 | Recalculate selected employees in Calculated or Reviewed state after input fixes, without recalculating others. | Must | R1 | [Proposed] |
| FR-PAY-033 | Variance report against the previous locked run: per employee and per component, absolute and %; highlights above variance.threshold_pct (default 10%) with reasons (revision, LOP change, new component, arrears). | Must | R1 | [Proposed] |
| FR-PAY-034 | Review workspace: filters (warnings, variance, new joiners, leavers, held), per-employee payslip preview, comments, hold/release, mark reviewed. | Must | R1 | [Proposed] |
| FR-PAY-035 | Approval through an NTF workflow (default: one level, org_owner or finance_admin), showing totals by component, headcount, variance summary and statutory totals; approve or send back with reason. | Must | R1 | [Proposed] |
| FR-PAY-036 | Segregation of duties (setting sod.payroll_editor_cannot_approve, default on): a user who edited compensation or inputs included in the run cannot approve it; in single-person tenants the owner can waive SoD with an audited acknowledgement. | Must | R1 | [Proposed] |
| FR-PAY-037 | Lock: freezes the run; artefacts stored with object lock; generates payslips, bank files, statutory files and (R2) journal; closes inputs for that period; later changes become arrears or adjustments. | Must | R1 | [Proposed] |
| FR-PAY-038 | Paid: mark paid in bulk or per employee, import bank response/UTR file, list failed transfers and re-issue them in an off-cycle run or a new bank file. | Must | R1 | [Proposed] |
| FR-PAY-039 | Reversal: create a reversal run for a locked or paid run (full or selected employees) with reason and approval; regenerate revised statutory files; original artefacts remain retrievable. | Must | R1 | [Proposed] |
| FR-PAY-040 | Arrears: back-dated compensation changes, back-dated attendance adjustments and back-dated statutory changes recompute the affected locked periods in a shadow calculation and pay the difference per component (including EPF/ESI/PT effects) as arrears lines in the next run; manual arrear entries by month and employee are also supported; arrears appear on the payslip with the source month. | Must | R1 | [Observed] SP-PAY-09 + [Proposed] |
| FR-PAY-041 | Off-cycle runs (bonus, correction, supplementary, arrears-only, advance disbursement) with their own lifecycle, selectable employees and components; statutory deductions computed on the combined monthly wages where the rules require it. | Must | R1 | [Proposed] |
| Payslips and payments | ||||
| FR-PAY-042 | Payslip template (company logo, legal entity, employee details, PAN, UAN, bank masked, days summary: days in period, payable days, LOP; earnings, deductions, employer contributions (optional), arrears and variable pay with source, OT and extra days, net pay in figures and words, YTD totals, leave balances (optional), footer text); configurable layout within the template engine. | Must | R1 | [Observed] research §21.5 + [Proposed] |
| FR-PAY-043 | Payslip distribution: published in the app at payslip.publish_at (on lock or on pay date); email with password-protected PDF (default password pattern configurable, e.g. PAN + DOB); bulk download for HR; re-issue keeps version history. | Must | R1 | [Observed] SP-PAY-12 + [Proposed] |
| FR-PAY-044 | Bank transfer files: a generic NEFT/RTGS CSV plus bank-specific adapters (initial set of 3 banks chosen with pilot customers), split by debit account, excluding held and cash-paid employees, with control totals and a checksum. | Must | R1 | [Observed] SP-PAY-13/15 extended |
| Statutory outputs | ||||
| FR-PAY-045 | EPF ECR file in the EPFO ECR text format (UAN, name, gross wages, EPF wages, EPS wages, EDLI wages, EE share, EPS share, ER share, NCP days, refund of advances) per establishment, with pre-generation validation (UAN format, wage arithmetic) and a summary. | Must | R1 | [Proposed] (extends [Observed] SP-PAY-13) |
| FR-PAY-046 | ESI monthly contribution file in the ESIC upload format (IP number, name, days paid, wages, reason code for zero/partial days) per employer code. | Must | R1 | [Proposed] |
| FR-PAY-047 | PT return data per state: employee-wise deduction and slab-wise summary in the format the state requires (CSV/Excel where no upload format exists). | Must | R1 | [Observed] SP-PAY-13 extended |
| FR-PAY-048 | LWF return data per state and period. | Must | R1 | [Proposed] |
| FR-PAY-049 | Statutory payment tracking: record challan/TRRN numbers, amounts and dates for EPF, ESI, PT, LWF and TDS per period, needed for 24Q and audit. | Should | R1 | [Proposed] |
| Income tax (TDS) | ||||
| FR-PAY-050 | TDS engine: projects annual taxable salary (actuals to date + projected remaining months + declared and verified exemptions/deductions + previous-employer income), applies the employee's regime, slabs, standard deduction, rebate, surcharge and cess from the pack, and deducts (annual tax − TDS to date) / remaining months; handles one-time incomes in the month paid; manual override per employee per run with reason; tax worksheet visible to the employee. | Must | R1 | [Proposed] (replaces [Observed] SP-PAY-16) |
| FR-PAY-051 | Tax regime choice by the employee once per tax year in the declaration window (default: new regime if no choice), with a side-by-side tax comparison; HR can unlock a choice with reason. | Must | R1 | [Proposed] |
| FR-PAY-052 | IT declarations (Form 12BB-style): rent and landlord PAN (above threshold), home loan interest, investments and insurance, medical insurance, education loan, NPS, LTA, other deductions as enabled in the pack; open/close dates per tax year; declared amounts drive TDS until proofs are due. | Must | R1 | [Observed] research §21.5 (menu) + [Proposed] |
| FR-PAY-053 | Proof submission and verification: upload per declared item, verifier approves full/partial/rejects with reason; after the proof deadline TDS uses verified amounts only. | Must | R1 | [Proposed] |
| FR-PAY-054 | Previous-employer income and TDS for mid-year joiners (Form 12B-style data) entered by the employee or HR, included in projection and Form 16. | Must | R1 | [Proposed] |
| FR-PAY-055 | Form 16 (Part B generated; Part A imported from the TRACES download) per employee per tax year, digitally signable PDF, bulk generation and publication to employees. | Must | R2 | [Observed] research §21.5 (menu) + [Proposed] |
| FR-PAY-056 | 24Q quarterly return data for salary TDS (deductee details, challan mapping, annexure II salary details in Q4) in a format importable into the return preparation utility; validation report. | Must | R2 | [Proposed] |
| FR-PAY-057 | Perquisite statement (Form 12BA-style) for employees with perquisites (concessional loans, company assets). | Should | R2 | [Proposed] |
| Accounting, F&F, self-service, dashboards | ||||
| FR-PAY-058 | Payroll journal export on lock: CSV and Tally XML with ledger mapping per component, cost centre and legal entity; payable and statutory liability ledgers. | Must | R2 | [Proposed] (architecture.md §16) |
| FR-PAY-059 | API connectors to Zoho Books and ERP systems for journal posting. | Should | R4 | [Proposed] |
| FR-PAY-060 | F&F run hook: EXT triggers an F&F run type that computes salary to the last working day, leave encashment, gratuity (if eligible), notice pay or recovery, bonus/variable dues, loan and advance recovery, other deductions and TDS; the result is reviewed, approved, locked and paid like any run, and produces the F&F statement. | Must | R2 | [Proposed] (gap in [Observed]) |
| FR-PAY-061 | Employee self-service (web and mobile): payslips by tax year and month (view, download), CTC breakup and history, YTD earnings and deductions, tax worksheet, regime choice, declarations and proofs, advance request and recovery status, Form 16 download (R2). | Must | R1 | [Observed] E: Payroll Management, research §21.5 |
| FR-PAY-062 | Finance dashboard: payroll cost by month, department, location and legal entity; headcount paid; EPF/ESI/PT/LWF/TDS totals; run status per pay group; variance trend. | Must | R1 | [Observed] SP-PAY-01 + [Proposed] |
| FR-PAY-063 | Statutory bonus computation (Payment of Bonus Act: eligibility, wage ceiling, minimum/maximum %) as an off-cycle helper. | Could | R2 | [Proposed] |
| FR-PAY-064 | Weekly or fortnightly pay frequencies. | Won't | R1 | [Proposed] (revisit in R3 if factory demand appears) |
| FR-PAY-065 | Reproducibility: any locked run's payslips and files can be regenerated byte-for-byte from the snapshot for 8 years. | Must | R1 | [Proposed] |
7.7.9 Key entities
pay_component, formula, salary_structure / salary_structure_version / structure_component, compensation (employee, valid_from, valid_to, ctc_annual, structure_version_id, pay_group_id, reason), compensation_override, pay_schedule, pay_group, statutory_settings (per legal entity, type), company_bank_account, payroll_policy, pay_input (run, employee, component, amount, source), recurring_deduction, variable_pay_plan / variable_pay_entry, advance / loan / recovery_entry, salary_hold, pay_run (pay group, period, type, status, statutory_pack_version, att_lock_version, totals_hash), pay_run_employee (snapshot JSON, gross, deductions, net, status, hold), pay_run_line (component, amount, base, formula, explanation), arrear (source_period, component, amount), payslip (version, pdf_ref, published_at), bank_file, statutory_file (type, period, version, file_ref), statutory_payment, tax_regime_choice, it_declaration / it_declaration_item / it_proof, previous_employment_income, tds_projection, form16 (R2), return_24q (R2), journal_export (R2).
7.7.10 Configuration settings
| Setting | Type | Default (example) |
|---|---|---|
pay_schedule.period_start_day | integer 1–28 | 1 (calendar month) |
pay_schedule.attendance_cutoff_day | integer or null | null |
pay_schedule.salary_basis | enum calendar_days / fixed_30 / fixed_26 / org_working_days | calendar_days |
pay_schedule.pay_day | integer or "last working day" | last working day |
payslip.publish_at | enum on_lock / on_pay_date | on_pay_date |
payslip.password_pattern | template | {PAN}{DOB:DDMMYYYY} |
run.auto_lock_on_approval | boolean | false |
variance.threshold_pct | decimal | 10 |
rounding.net | enum nearest_1 / up_1 / none | nearest_1 |
deduction.priority | ordered list | statutory, TDS, loans, others |
advance.min_payslips / max_pct_of_gross / max_instalments / cooling_off_months | integer / decimal / integer / integer | 1 / 100 / 6 / 3 |
tds.default_regime | enum new / old | new |
tds.declaration_window / proof_window | date ranges per tax year | Apr 1–Apr 30 / Jan 1–Jan 31 |
sod.payroll_editor_cannot_approve | boolean | true |
reimbursement.payout_mode (R2) | enum payroll / separate_bank_file | payroll |
esi.include_employer_in_ctc | boolean | true |
epf.restrict_to_ceiling | boolean (per employee override) | true |
7.7.11 User stories
US-PAY-01 — Structure template independent of CTC. As a finance_admin, I want one structure for all staff grades with Basic at 50% of CTC and a balancing Special allowance.
- AC1: Given a template where Basic = 50% of monthly CTC, HRA = 40% of Basic, Conveyance = ₹1,600 flat and Special allowance is balancing, when I preview CTC ₹3,60,000, then the monthly breakup shows Basic ₹15,000, HRA ₹6,000, Conveyance ₹1,600 and Special allowance as the remainder after employer contributions.
- AC2: Given a CTC so low that Special allowance would be negative, when I preview, then the template shows "Balancing component negative below CTC ₹X" and cannot be activated without a minimum-CTC rule.
US-PAY-02 — Increment with arrears. As a payroll_manager, I want an increment approved in November but effective 1 September to be paid as arrears.
- AC1: Given September and October are locked, when I save the new compensation effective 1 September, then the November run shows arrears lines for September and October per component, with EPF and ESI recomputed on the arrears.
- AC2: The payslip shows "Arrears: Sep 2026, Oct 2026" with amounts per component.
US-PAY-03 — Run payroll with validation. As a payroll_manager, I want blocking issues listed before I calculate.
- AC1: Given 3 employees have no bank account, when I calculate, then the run stops with those 3 listed and links to fix them, unless I hold them.
- AC2: Given all blocking issues are fixed, when I calculate 400 employees, then the run reaches Calculated in under 2 minutes and a variance report is available.
US-PAY-04 — Approve with four eyes. As an org_owner, I want to approve payroll on my phone and know that the preparer could not approve it.
- AC1: Given the run is Reviewed, when I open the approval, then I see headcount, gross, net, employer cost, statutory totals and top variances.
- AC2: Given SoD is on and Anil edited inputs, when Anil tries to approve, then the action is disabled with "You edited this run; another approver is required".
US-PAY-05 — Lock and generate files. As a payroll_manager, I want all files ready when the run locks.
- AC1: When the run locks, then payslips, the bank file(s), ECR, ESI, PT and LWF files are generated, listed with checksums and downloadable.
- AC2: Given the ECR has a UAN with 11 digits, then generation fails validation and names the employee before lock completes.
US-PAY-06 — Reverse a wrong run. As a payroll_manager, I want to reverse a locked run for 5 employees who were paid twice.
- AC1: Given a locked run, when I request a reversal for 5 employees with a reason and it is approved, then a reversal run with negated lines is locked, the original shows "Partially reversed by PR-202611-02", and revised statutory files are generated.
US-PAY-07 — Choose tax regime and declare. As an employee, I want to compare regimes and declare my rent.
- AC1: Given the declaration window is open, when I open Tax, then I see projected annual tax under both regimes and can choose one.
- AC2: Given I choose the old regime and declare rent ₹15,000/month with landlord PAN, when the next run calculates, then my monthly TDS reflects the HRA exemption.
- AC3: Given the proof deadline passes without proof, when the following run calculates, then TDS uses verified amounts only and I am notified.
US-PAY-08 — Advance salary. As an employee, I want an advance of ₹20,000 repaid over 4 months.
- AC1: Given I have at least one payslip and my last gross was ₹30,000, when I request ₹20,000 in 4 instalments, then the request goes for approval.
- AC2: Given it is approved and disbursed in November, then December–March payslips show ₹5,000 recovery each and the recovery ledger shows the balance.
US-PAY-09 — Payslip on mobile. As an employee, I want to see my payslip and understand LOP.
- AC1: Given November is published, when I open Payslips, then I see net pay, earnings and deductions, payable days and LOP days, and can download a PDF.
- AC2: When I tap "LOP 1.5 days", then I see the dates and statuses from attendance that caused it.
US-PAY-10 — Mid-month joiner. As a payroll_manager, I want joiners paid pro-rata.
- AC1: Given an employee joined on 16 November with a 30-day calendar month, when the run calculates, then prorated components use 15/30 and days before joining are not counted as LOP.
US-PAY-11 — Held salary. As a payroll_manager, I want to hold an absconding employee's salary.
- AC1: Given I hold the salary with a reason, when the run locks, then the employee is excluded from the bank file but included in statutory files per the rules, and the held amount appears in a "Held salaries" report until released.
7.7.12 Permissions
| Action | OWN | HRA | HRM | FNA | PRM | LM | EMP | AUD |
|---|---|---|---|---|---|---|---|---|
| Components, templates, statutory settings, bank accounts, payroll policy | ORG | — | — | ORG | ORG(R) | — | — | ORG(R) |
| Compensation create/revise | ORG | — | — | ORG | ORG (if granted) | — | view SELF | ORG(R) masked |
| One-time and recurring inputs | ORG | — | LOC* (non-salary inputs, if granted) | ORG | ORG | — | — | ORG(R) |
| Create/calculate/review run | ORG | — | — | ORG(R) | ORG | — | — | ORG(R) |
| Approve run | ORG | — | — | ORG | — | — | — | — |
| Lock, mark paid, request reversal | ORG | — | — | ORG | ORG | — | — | — |
| Approve reversal | ORG | — | — | ORG | — | — | — | — |
| Download bank/statutory files | ORG | — | — | ORG | ORG | — | — | ORG(R) |
| Advance/loan approval | ORG | — | — | ORG | ORG | TEAM (first level, optional) | request SELF | — |
| Verify IT proofs | ORG | — | — | ORG | ORG | — | submit SELF | — |
| View payslips | ORG | — | — | ORG | ORG | — | SELF | ORG(R) |
hr_admin and hr_manager have no salary access by default; tenants may grant it through a custom role.
7.7.13 UI/UX
- Payroll workbench (web): a run page with a stepper Draft → Calculated → Reviewed → Approved → Locked → Paid; tiles for headcount, gross, net, employer cost; tabs Validations, Employees (grid with filters and payslip preview), Variance, Inputs, Files, Activity. Every money figure is right-aligned with
en-INgrouping (₹1,23,456.00). - Set-up: component editor with formula editor (autocomplete for component codes, live validation, "test with employee"); structure template preview across a CTC range; compensation editor with a timeline of versions.
- Approver (mobile and web): approval card with totals, variance highlights and statutory totals; Approve / Send back.
- Employee mobile: Pay tab with latest net pay, payslip list by tax year, "How was this calculated?" drill-down, Tax (regime comparison, declarations, proofs with camera upload), Advances.
- States: no compensation → "Your salary details are not set up yet; contact HR". Run blocked → validation list with "Fix" links. Locked run → read-only banner with lock time and actor. Payslip not yet published → "November payslip will be available on 30 Nov".
7.7.14 Notifications and automation
Attendance lock reminder (to HR, from PAY calendar); run calculated with warnings; review complete → approval requested; approved; locked (files ready); payslip published (employees, push + email); payment failed (PRM); declaration window opening/closing (employees, 7 days and 1 day before); proof deadline; proof verified/rejected; advance decision and disbursement; loan EMI paused; statutory due-date reminders (EPF/ESI 15th of next month, TDS 7th, PT per state — examples to verify); statutory pack changed (PRM).
7.7.15 Reports and analytics
Payroll register (salary register), payslip bulk export, bank-wise salary summary, EPF report and ECR, ESI report and file, PT report by state, LWF report, TDS projection and deduction register, declarations and proofs status, CTC report, payroll cost by department/location/cost centre, variance report, arrears report, advance and loan recovery report (fixes the empty Spryple report section), held salaries, payable-days report, statutory payment register, Form 16 status (R2), 24Q validation (R2). See §13.
7.7.16 Edge cases
- Mid-period revision → two segments prorated by days; statutory computed on the total.
- Employee crosses the ESI threshold mid contribution period → continues ESI until the period ends (per pack rules).
- Employee transfers state mid-month → PT and LWF per the state rule for that month (default: state on the last day of the period; configurable).
- Negative net → apply the deduction priority; carry forward the remainder; warn in review.
- Exit in the period before EXT is live (R1) → salary to the last working day in the regular run; F&F items handled as manual one-time inputs.
- Statutory pack correction after lock → no automatic change; a banner offers an arrears or correction run.
- Missing PAN → TDS at the higher rate per the pack; warning in validation.
- Rounding differences between component sum and net → a rounding line keeps net = gross − deductions exactly.
- Reversal after statutory filing → revised files are generated; the UI reminds the user that portal revisions are manual.
- Two pay groups for one employee in the same period (transfer between legal entities) → two runs; each legal entity files its own part; TDS projection combines both.
7.8 NTF — Notifications & Workflow (approvals engine)
Traces to: BR-NTF-* · Release: R0 core (templates, email/push/in-app, approval engine), R1 (SMS, WhatsApp, escalation, digests), R2 (N-level workflows, webhooks)
7.8.1 Purpose and scope
NTF delivers every message Spyrl sends and runs every approval. Modules publish domain events; NTF turns them into notifications through templates and channels, and turns requests into approval tasks through workflow definitions stored as data.
| In scope | Out of scope |
|---|---|
| Template catalogue with tenant overrides; channels (in-app, email, push, SMS, WhatsApp); preferences, quiet hours, digests; delivery tracking and retries; approval workflow engine (levels, conditions, approver resolution, delegation, escalation); unified approvals inbox; scheduled reminder rules; outbound webhooks (R2) | Marketing campaigns; two-way chat; editing every UI message (replaced by i18n bundles) |
7.8.2 Reference product summary
- Approvals follow one pattern (Submitted → Approved/Rejected with reason; edit/delete while Submitted; History tabs) across attendance, leave, comp-off, permission, shift change, separation, timesheet and claims [Observed] (research SP-X-03). On-behalf requests are auto-approved [Observed] (SP-X-04).
- Email notifications for onboarding, documents, induction, password reset and timesheet defaulters; leave emails are configurable [Observed] (SP-X-09). A Messages Master per module lets admins edit success/error messages shown with their screen name [Observed] (SP-X-02).
- Multi-level approval, delegation and escalation are not documented [Inferred] (research §20 Q2).
7.8.3 What we change and why [Proposed]
- Workflow as data: one engine and one inbox for every request type, with levels, conditions, delegation and SLA escalation.
- Reliable delivery: transactional outbox, retries and delivery status, so "I never got the email" can be checked.
- Messages Master is replaced by i18n resource bundles plus tenant overrides of notification templates and selected labels (FR-ORG-017); editing every UI string per tenant is a maintenance trap.
- India channels: DLT-registered SMS templates and opt-in WhatsApp as a metered add-on.
7.8.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-NTF-001 | Template catalogue keyed by event (§12) with per-channel variants, sandboxed Handlebars-like syntax, merge-field picker, preview with sample data, versioning and per-tenant overrides that can be reset to default. | Must | R0 | [Observed] SP-X-09 + [Proposed] |
| FR-NTF-002 | Channels: in-app inbox, email (SES, ap-south-1), push (Expo → FCM/APNs) in R0; SMS (MSG91/Gupshup) in R1; WhatsApp (Meta Cloud API via a BSP, add-on) in R1. Channel adapters are interchangeable. | Must (WhatsApp: Should) | R0/R1 | [Proposed] |
| FR-NTF-003 | SMS uses DLT-registered templates and sender IDs (India); WhatsApp uses pre-approved templates and requires recorded user opt-in. | Must | R1 | [Proposed] |
| FR-NTF-004 | User preferences per category and channel; categories flagged mandatory (security, payslip published, approval assigned) cannot be fully disabled (at least in-app stays on). | Must | R1 | [Proposed] |
| FR-NTF-005 | Quiet hours for push/SMS/WhatsApp (tenant default 21:00–08:00 local time, user-adjustable) except security and punch-related messages; approver daily digest option. | Should | R1 | [Proposed] |
| FR-NTF-006 | Delivery pipeline from the transactional outbox: retries with exponential backoff (max 5), provider failover for SMS, bounce/complaint handling for email, per-message status (queued, sent, delivered, failed, read for in-app), dead-letter queue and admin resend. | Must | R0 | [Proposed] |
| FR-NTF-007 | Workflow definitions per request type: ordered steps (R1: max 2 levels), each with an approver rule, optional condition (e.g. leave.days > 3, claim.amount > 5000, request.backdated = true), and an action on timeout; tenant default workflows are seeded per request type. | Must | R0 | [Proposed] |
| FR-NTF-008 | Approver resolution: line_manager, manager_of_manager, department_head, hr_of_location, role@scope, named user; resolved when the step starts. When the resolved approver changes (manager change, exit, role removal), pending tasks are reassigned to the new approver from the effective date and both are notified. If no approver resolves, the task goes to the tenant's fallback approver (default hr_admin). | Must | R0 | [Proposed] |
| FR-NTF-009 | Delegation: an approver delegates all or selected request types for a date range; the delegate acts "on behalf of"; auto-suggested when the approver has approved leave. | Must | R1 | [Proposed] |
| FR-NTF-010 | SLA reminders and escalation per step: remind after remind_after_hours (default 24), escalate after escalate_after_hours (default 72) to the next level or fallback approver, or auto-approve/auto-reject where the tenant explicitly configures it (never for payroll approval). | Must | R1 | [Proposed] |
| FR-NTF-011 | Unified approvals inbox (web and mobile): all pending tasks across modules with filters, context (balances, conflicts, attachments), bulk approve/reject with a common reason, deep links from push and email that require normal authentication. | Must | R1 | [Observed] SP-ATT-05 + [Proposed] |
| FR-NTF-012 | N-level workflows (max 5 steps) and parallel steps (any-one or all-of). | Should | R2 | [Proposed] |
| FR-NTF-013 | Scheduled reminder rules configurable by tenants from a catalogue (e.g. "document expiring in N days", "probation ends in N days", "birthday today"), with recipients and channels. | Should | R1 | [Proposed] |
| FR-NTF-014 | In-app inbox: read/unread, mark all read, filters, 90-day retention. | Must | R0 | [Proposed] |
| FR-NTF-015 | Email branding (logo, sender display name, reply-to) and, for Enterprise, a custom sending domain with SPF/DKIM verification. | Should (custom domain: R2) | R1 | [Proposed] |
| FR-NTF-016 | Outbound webhooks for selected domain events (employee.created, leave.approved, payroll.locked, punch.created …): HMAC SHA-256 signatures, retries with backoff, DLQ, replay, per-endpoint event filters. | Must | R2 | [Proposed] (architecture.md §16) |
| FR-NTF-017 | Tenant-editable text for every UI success and error message (Spryple Messages Master). | Won't | — | [Observed] SP-X-02 replaced |
| FR-NTF-018 | One-click approve directly from an email without signing in. | Won't | — | [Proposed] (security) |
7.8.5 Key entities
notification_template (event_key, channel, locale, version, body, tenant override), notification (recipient, event, channel, status, attempts, provider_ref), notification_preference, outbox_event, workflow_definition (request_type, version, steps[]), workflow_instance (request ref, current step, status), approval_task (approver, on_behalf_of, due_at, escalated, decision, reason), delegation, reminder_rule, webhook_endpoint, webhook_delivery.
7.8.6 Configuration settings
| Setting | Type | Default |
|---|---|---|
workflow.<request_type> | workflow definition | line manager, 1 level (payroll run: OWN or FNA) |
workflow.fallback_approver | role or user | hr_admin |
sla.remind_after_hours / escalate_after_hours | integer | 24 / 72 |
quiet_hours | time range | 21:00–08:00 |
channels.enabled | set | in-app, email, push |
digest.approvers | enum off / daily 09:00 | off |
whatsapp.enabled | boolean (add-on) | false |
7.8.7 User stories
US-NTF-01 — Two-level leave approval. As an hr_admin, I want leave longer than 3 days to need HR approval after the manager.
- AC1: Given a workflow with step 1 line manager and step 2
hr_of_locationwhendays > 3, when an employee applies for 5 days, then after the manager approves, the HR task is created and the request shows "Approved by manager, pending HR". - AC2: Given 2 days, then only the manager approves.
US-NTF-02 — Manager on leave. As a line_manager going on leave, I want my approvals handled.
- AC1: Given my leave is approved, when I open the inbox, then I am offered delegation to a chosen colleague for my leave dates.
- AC2: Given I did not delegate and a task waits 72 h, then it escalates to my manager and both of us are notified.
US-NTF-03 — Manager change. As an hr_manager, I want pending requests to follow the new manager.
- AC1: Given an employee's
reports_tochanges effective today, when the change is saved, then their 3 pending tasks move to the new manager and the old manager loses access to them.
US-NTF-04 — Delivery check. As an hr_manager, I want to see whether an employee received their activation SMS.
- AC1: Given a failed SMS, when I open the employee's notification log, then I see status Failed with the provider reason and a Resend button.
US-NTF-05 — Customise a template. As an hr_admin, I want the payslip email to include a line in Telugu.
- AC1: Given I edit the payslip-published email template, when I preview with sample data, then merge fields render and invalid fields are highlighted before save; Reset restores the default.
7.8.8 Permissions
| Action | OWN | HRA | HRM | FNA | PRM | LM | EMP |
|---|---|---|---|---|---|---|---|
| Edit templates and channels | ORG | ORG | — | payroll templates | — | — | — |
| Edit workflows | ORG | ORG (non-payroll) | — | ORG (payroll) | — | — | — |
| Act on approval tasks | assigned | assigned | assigned | assigned | assigned | assigned | assigned (swap consent) |
| Delegate own approvals | SELF | SELF | SELF | SELF | SELF | SELF | — |
| View delivery logs | ORG | ORG | LOC* | — | — | — | SELF |
| Manage webhooks (R2) | ORG | ORG | — | — | — | — | — |
7.8.9 UI/UX
- Inbox (web and mobile): tabs "To approve", "My requests", "Notifications"; cards show request type icon, employee, dates, key numbers and risk chips (conflict, backdated, over limit); swipe actions on mobile; bulk select on web.
- Workflow editor (web): a vertical list of steps with approver rule, condition builder (field, operator, value) and timeout action; test with an example request.
- Template editor: split view (editor, live preview), channel tabs, character count for SMS.
- Empty states: "You're all caught up" in the inbox; "No custom templates; defaults are in use".
7.8.10 Notifications and automation
NTF owns the catalogue in §12 and the escalation automation (FR-NTF-010).
7.8.11 Reports and analytics
Approval turnaround by request type and approver, SLA breaches and escalations, notification delivery rates by channel, failed messages, SMS/WhatsApp usage (metered).
7.8.12 Edge cases
- An approver is also the requester (e.g. a manager with no manager) → step resolves to the fallback approver; never self-approval.
- A request is edited while in step 2 → approvals reset to step 1 (§6.2).
- Escalation target is on leave with delegation → the delegate receives it.
- Provider outage → messages queue and retry; push and in-app continue; SMS fails over to the secondary provider.
7.9 RPT — Reporting, Dashboards & Exports
Traces to: BR-RPT-* · Release: R1 (standard reports, dashboards, exports); R4 (custom report builder, advanced analytics)
7.9.1 Purpose and scope
RPT provides one report framework: dataset definitions with scope-aware filters, column choice, export and scheduling, so "the same report per role" is one report evaluated at each role's data scope. Module sections list their reports; the full catalogue is §13.
| In scope | Out of scope |
|---|---|
| Report framework; standard report catalogue; persona dashboards; exports (Excel, CSV, PDF); saved views; scheduled delivery; KPI definitions; export governance; custom report builder and advanced analytics (R4) | A general BI tool; embedding third-party BI (customers can use exports or the API) |
7.9.2 Reference product summary
- Super Admin dashboard: employee count by location; employees by department by location; headcount (active, new, exit); attendance by work type (WFH, WFO, on duty, absent); employees on leave by department; leave counts; shift-based headcount by department; payroll amount by department by month [Observed] (SA: Super Admin Dashboard).
- Excel and PDF export on almost every report; a common filter idiom City-Branch → Manager → Employee → Period with Search and Clear [Observed] (SP-X-05, SP-X-06). Employee report with a column chooser [Observed] (SP-RPT-01).
- Reports are re-implemented per role and module, with no saved filters, scheduling, custom builder, drill-down or trend analytics [Inferred] (research §14).
7.9.3 What we change and why [Proposed]
- One framework, scope-aware: the same "Monthly attendance" report shows a line manager their TEAM and HR their LOCATION; less code, consistent numbers.
- Saved views and scheduled email delivery for routine month-end packs.
- Governed exports: masking, audit and watermarks, because exports are the main leak path for salary data.
- Custom builder only in R4, after the standard catalogue proves which datasets matter.
7.9.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-RPT-001 | Report framework: each report is a dataset definition (fields, types, sensitivity class, default columns), filters and permissions; row-level filtering by the viewer's (permission, scope); column chooser, sort, group totals. | Must | R1 | [Proposed] |
| FR-RPT-002 | Standard filter bar: Legal entity → Location → Department → Manager → Employee → Period, plus status and search; Clear resets. | Must | R1 | [Observed] SP-X-06 |
| FR-RPT-003 | Standard report catalogue as in §13 for R1 modules. | Must | R1 | [Observed] module reports + [Proposed] |
| FR-RPT-004 | Exports to Excel (xlsx), CSV and PDF; reports above 10,000 rows run asynchronously with an in-app/email link valid 24 h. | Must | R1 | [Observed] SP-X-05 + [Proposed] |
| FR-RPT-005 | Export governance: sensitive columns are omitted or masked unless the user holds the sensitive permission; every export is audited (who, report, filters, row count); PDFs carry a watermark with user and timestamp. | Must | R1 | [Proposed] |
| FR-RPT-006 | Persona dashboards: Owner (headcount, joiners/leavers, attendance today by status, payroll cost trend, pending approvals, compliance due dates), HR (exceptions, documents pending, probation due), Line manager (team today, approvals, leave calendar), Payroll (run status, variance, statutory totals), Employee (attendance month, balances, latest payslip). Includes the Spryple-equivalent org widgets listed in §7.9.2. | Must | R1 | [Observed] SA dashboard + [Proposed] |
| FR-RPT-007 | Drill-down from every dashboard tile to the underlying filtered list. | Should | R1 | [Proposed] |
| FR-RPT-008 | Saved views (filters + columns) per user, shareable with users who have the same permission. | Should | R1 | [Proposed] |
| FR-RPT-009 | Scheduled delivery: daily, weekly or monthly email of a saved view to users (evaluated at each recipient's scope) as a secure link; attachments only for non-sensitive reports. | Should | R1 | [Proposed] |
| FR-RPT-010 | KPI definitions with documented formulas: attrition rate, absenteeism %, late %, OT hours and cost, payroll cost per employee, leave utilisation, approval turnaround. | Should | R1 | [Proposed] |
| FR-RPT-011 | Custom report builder over curated datasets (fields, filters, grouping, simple charts), respecting scopes and sensitivity. | Should | R4 | [Proposed] |
| FR-RPT-012 | Advanced analytics: trends, attrition cohorts, absence patterns, OT cost forecasting, payroll cost forecasting. | Could | R4 | [Proposed] |
| FR-RPT-013 | Scheduled data feed (daily CSV to customer S3/SFTP) for external BI. | Could | R4 | [Proposed] |
7.9.5 Key entities
report_definition (key, dataset, fields, sensitivity), saved_view (owner, filters, columns, shared_with), report_job (status, rows, file_ref, expires_at), report_schedule (view, cron, recipients), kpi_definition.
7.9.6 Configuration settings
reports.async_threshold_rows (default 10,000), reports.link_ttl_hours (24), reports.pdf_watermark (on), schedule.max_per_user (10).
7.9.7 User stories
US-RPT-01 — Scope-aware report. As a line_manager, I want the monthly attendance report for my team only.
- AC1: Given I open Monthly attendance, then only my TEAM appears, and the Location filter lists only locations where my team works.
US-RPT-02 — Large export. As an hr_manager, I want a 30,000-row punch export.
- AC1: Given the result exceeds 10,000 rows, when I export, then the job runs in the background and I get a link within 15 minutes, valid for 24 h.
US-RPT-03 — Masked export. As an hr_manager without salary permission, when I export the employee master, then bank and CTC columns are not included and the export is audited.
US-RPT-04 — Monthly pack. As a payroll_manager, I want the payroll register emailed to the owner on lock day.
- AC1: Given a schedule "on payroll lock", when the run locks, then the owner receives a secure link to the register.
7.9.8 Permissions
Each report inherits the module's read permission and scope (e.g. att.day.read@TEAM). Owner and auditor see all reports at ORG scope (auditor read-only; no schedules). Payroll reports require pay.*.read. Export requires rpt.export in addition to the read permission (seeded for all admin and manager roles; employees can export only their own data).
7.9.9 UI/UX
- Reports hub (web): grouped by module, search, favourites, recently run; a report page with the filter bar, preview grid (first 500 rows), Export menu, Save view, Schedule.
- Dashboards: tile grid with responsive layout; each tile has a title, number, trend vs last period and a "View list" link; charts follow the accessible palette (§10).
- Mobile: dashboards for owner, line manager and employee; reports are web-only except "Team today" and personal statements.
- Empty state: "No data for the selected filters" with a Clear filters button; first-use dashboards show setup prompts.
7.9.10 Notifications and automation
Export ready; scheduled report delivered; schedule failed (to owner of the schedule).
7.9.11 Reports and analytics
See §13 for the full catalogue.
7.9.12 Edge cases
- A scheduled report's recipient loses permission → that recipient is skipped and the schedule owner is notified.
- Data changes during a long export → exports read from a consistent snapshot (one transaction or a replica at a point in time).
- Employee transferred mid-period → scope is evaluated on the record's effective assignment for each date (a manager sees days when the employee was in their team).
7.10 MOB — Mobile app (single app, role-based) + Kiosk mode
Traces to: BR-MOB-* · Release: R1 (ESS + MSS), R2 (kiosk + face verification), R3 (field features)
7.10.1 Purpose and scope
One Expo app for iOS and Android serves employees, managers, field staff and shared kiosks, with navigation driven by roles and entitlements (ADR-014).
| In scope | Out of scope |
|---|---|
| App shell, company-code onboarding, ESS, MSS, push, offline punch and cached reads, app security, version enforcement, kiosk mode, face enrolment and verification, field features (R3, specified in FFM) | Separate apps per product; tablet-optimised admin; smartwatch apps |
7.10.2 Reference product summary
- Four apps: Spryple HCM (attendance requests, face self check-in/out, approvals, Today Attendees, capture employee image, configure location, leave, payslips, Rewards & Recognition, Receptionist front-office check-in), Spryple Lite (add employee with monthly salary and shift, face profiles, reports), Spryple CRM (punch with photo, clients, activities, travel, leave) and Claims installed as "Spryple CRM" [Observed] (MOB: Spryple HR, Spryple Lite, Sales CRM Mobile Application, Claims Management; research §15).
- Face enrolment by manager or receptionist with Verified/Not Verified status; kiosk "Face Detections" with all/selected employees and camera flip; no liveness cue visible [Observed] (research §21.3). Lite was last released 2024-08 [Observed] (research §21.1).
- Store listings say "No data collected" while also "Shares location" [Observed] (research §21.1).
7.10.3 What we change and why [Proposed]
- One app, so employees install once and Lite is a plan, not a product.
- Kiosk mode replaces the receptionist login: a locked, location-scoped, punch-only device with face + liveness or PIN.
- Consent-gated face templates and accurate store data-safety declarations.
- Offline-first punching for factories and basements.
7.10.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-MOB-001 | Single Expo app (iOS 15+, Android 9+/API 28+) with role- and entitlement-driven tabs: Home, Attendance, Leave, Pay, Inbox, Me; Team for managers; Field for field executives (R3). | Must | R1 | [Proposed] |
| FR-MOB-002 | Company-code onboarding: resolve tenant → API base URL and branding; remember the tenant; support switching tenants for users with accounts in more than one. | Must | R1 | [Observed] SP-X-10 + [Proposed] |
| FR-MOB-003 | ESS: punch card, alerts, attendance calendar and requests, leave apply/history/balances, comp-off, optional holidays, payslips and tax, advances, profile and documents, holidays, policies, notifications inbox. | Must | R1 | [Observed] research §15 |
| FR-MOB-004 | MSS: team today, approvals inbox with bulk actions, team calendar, roster view and simple edits, on-behalf requests, device approvals, OT claims. | Must | R1 | [Observed] research §15 |
| FR-MOB-005 | Offline: punch queue (FR-ATT-005); cached read-only data (last 3 payslips, balances, holidays, calendar of the current month) with "last updated" time; clear offline banner. Requests other than punches require connectivity, but drafts are kept locally. | Must | R1 | [Proposed] |
| FR-MOB-006 | Push notifications with deep links into the relevant screen after authentication. | Must | R1 | [Proposed] |
| FR-MOB-007 | Device biometric (fingerprint/face ID) app unlock as a convenience, never as attendance proof. | Should | R1 | [Proposed] |
| FR-MOB-008 | Minimum supported version enforcement (426 Upgrade Required + store link) and OTA updates for JS-only fixes. | Must | R1 | [Proposed] (architecture.md §11) |
| FR-MOB-009 | Low-end device support: 2 GB RAM devices, install size ≤ 40 MB, usable on 2G/3G-class connections (punch payload ≤ 350 KB including selfie). | Must | R1 | [Proposed] |
| FR-MOB-010 | App security: tokens in secure storage; payslip and tax screens block screenshots on Android; rooted/jailbroken devices warned (block configurable); no sensitive data in logs or notifications text (e.g. "Your payslip is ready", not the amount). | Should | R1 | [Proposed] |
| FR-MOB-011 | Store data-safety and privacy labels declare location, photos, face data (R2) and their purposes accurately; in-app prominent disclosure before any OS permission prompt. | Must | R1 | [Proposed] (fixes [Observed] research §21.1) |
| FR-MOB-012 | Kiosk enrolment: HR enrols a device with a one-time kiosk code; the kiosk token is location-scoped and punch-only; the device shows only the kiosk screen (with OS pinning/guided-access guidance); exit needs an admin PIN. | Must | R2 | [Observed] SP-ATT-19 redesigned |
| FR-MOB-013 | Kiosk identification: face 1:N within the kiosk's location with liveness detection, or employee code + PIN; confirmation screen with name and photo; configurable "face + PIN" for high-assurance sites. | Must | R2 | [Proposed] |
| FR-MOB-014 | Face enrolment with explicit consent (FR-IAM-018): self-enrolment or assisted by HR/manager/kiosk operator; liveness at enrolment; store templates/embeddings rather than images where the provider allows; status Verified/Not verified; re-enrol and delete. | Must | R2 | [Observed] research §21.3 + [Proposed] |
| FR-MOB-015 | Face verification (1:1) on personal-device punches when the attendance policy requires it, with a match threshold and fallback to selfie + manager review on failure. | Should | R2 | [Proposed] |
| FR-MOB-016 | Kiosk offline mode: accepts PIN punches with a photo while offline, flags them offline, and verifies face on sync where possible. | Should | R2 | [Proposed] |
| FR-MOB-017 | Kiosk operator assisted punch for selected employees (e.g. visitors without phones), with reason and photo. | Must | R2 | [Observed] SP-ATT-19 (Receptionist) |
| FR-MOB-018 | Field features (tracking, visits, clients, travel) inside the same app, enabled by the FFM entitlement. | Must | R3 | [Proposed] |
| FR-MOB-019 | Hindi, Telugu and Tamil UI (with tenant-selectable defaults). | Should | R2 | [Proposed] (architecture.md §8) |
7.10.5 Key entities
device (IAM), kiosk_device (location, token, status, last_seen), face_template (employee, provider_ref, version, consent_id, status), offline_queue_item (device-side), app_version_policy.
7.10.6 Configuration settings
| Setting | Type | Default |
|---|---|---|
mobile.min_version | semver per platform | set per release |
mobile.block_rooted | boolean | false (warn) |
kiosk.identification | enum face / pin / face_and_pin | face |
kiosk.liveness_required | boolean | true |
face.match_threshold | provider-specific decimal | provider default |
face.retention_after_exit_days | integer | 30 |
7.10.7 User stories
US-MOB-01 — First run. As an employee, I want to set up the app in under a minute.
- AC1: Given I enter company code "acme", then the app shows ACME branding and the login screen; after activation it opens Home with the punch card.
US-MOB-02 — Manager approvals on the go. As a line_manager, I want to approve five leave requests from a push notification.
- AC1: When I tap the push, then the inbox opens after biometric unlock with the request; I can multi-select and approve all with one reason.
US-MOB-03 — Kiosk punch with liveness. As an employee at the factory gate, I want to punch by looking at the tablet.
- AC1: Given I am enrolled, when I face the kiosk, then liveness passes, my name and photo appear and the punch is recorded within 2 s.
- AC2: Given someone holds up my photo, then liveness fails, no punch is stored and the attempt is logged.
US-MOB-04 — Face consent. As an employee, I want to understand and control face enrolment.
- AC1: Given I have not consented, when HR starts enrolment, then I see the purpose, retention and alternative (PIN) and must accept before capture.
- AC2: When I withdraw consent, then my template is deleted within 24 h and the kiosk offers PIN for me.
US-MOB-05 — Forced upgrade. Given my app is below the minimum version, when I open it, then I see an upgrade screen with a store link and cannot punch until I upgrade (queued offline punches are still uploaded first).
7.10.8 Permissions
Navigation and actions follow the user's roles (§9). Kiosk devices hold only att.punch.create@LOCATION for others and att.kiosk.*; they cannot read any employee data except the name and photo shown on a successful match. kiosk_operator can additionally perform assisted punches for their LOCATION.
7.10.9 UI/UX
Mobile-first patterns in §10: bottom tabs, one primary action per screen, bottom-sheet forms, large touch targets (≥ 48 dp), status chips with text (not colour alone), skeleton loaders, pull-to-refresh, offline banner. Kiosk UI: full-screen camera with a guide oval, large clock, result screen for 3 s, high-contrast mode.
7.10.10 Notifications and automation
Push for approvals, request outcomes, punch reminders, payslip ready, announcements (R2), device approval; kiosk offline alert to HR (R2).
7.10.11 Reports and analytics
App adoption (DAU/MAU by role), app version distribution, offline punch share, kiosk usage and face-match failure rates (R2).
7.10.12 Edge cases
- Shared family phone → one user per device at a time; switching users clears cached data.
- Low storage → selfie compression and queue size limit (max 200 queued punches) with a warning.
- Time zone changed on the phone → server time rules; device time used only for offline punches with drift checks.
- Kiosk loses power mid-sync → queued punches persist and upload on restart (idempotent).
7.11 CLM — Claims & Expense Reimbursement
Traces to: BR-CLM-* · Release: R2 (R3 mileage from FFM travel; R4 OCR)
7.11.1 Purpose and scope
CLM lets employees claim expenses with bills, applies an expense policy, routes claims through verification and finance approval, and pays them through payroll or a bank file.
| In scope | Out of scope |
|---|---|
| Expense categories and policy (limits, receipts, per-diem, mileage); claims with multiple bills; duplicate detection; verify → approve → pay; payout via PAY or bank file; finance dashboard; mileage claims from FFM travel (R3); OCR (R4, Could) | Corporate cards; travel booking; vendor payments; GST input-credit filing (we only capture GST fields) |
7.11.2 Reference product summary
- A claim is one or more bills (reimbursement type, bill number, bill date, amount, file) plus a description → Submitted; employee tabs Submitted, In Progress, Paid, Rejected [Observed] (E: Claims Management).
- The manager verifies and can reject individual bills and enter a verified amount (mobile); the Finance Manager approves verified claims and marks them Paid; finance dashboard with counts by status, settlement ratio, previous vs current scorecard and paid amount by type [Observed] (M: Claims Management; A: Claims Management; research §9).
- Claim ID format
CL_GEN_<company>_<n>; bill image required with a 2 MB limit; type "Food Charges" seen; mobile statuses Submitted, Verified, Paid, Rejected with a reason [Observed] (research §21.6). - CRM travel records go Pending → Verified → Approved → Claimed in a separate path [Observed] (M/E: CRM Field Force Management).
- No limits, per-diem, mileage rates, duplicate detection or payroll payout are documented [Inferred] (research §9).
7.11.3 What we change and why [Proposed]
- An expense policy by category, grade and city tier, so limits are enforced at submission rather than argued at verification.
- One status model for all roles and one pipeline for both bills and travel (mileage claims generated from FFM travel in R3).
- Payout through payroll (or a bank file), closing the loop that Spryple leaves manual.
- Duplicate detection on bill number, amount, date and vendor.
7.11.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-CLM-001 | Expense categories master (seeded: Food, Travel – local, Travel – outstation, Lodging, Fuel, Mobile/Internet, Mileage, Other) with GL code and tax treatment. | Must | R2 | [Observed] research §21.6 + [Proposed] |
| FR-CLM-002 | Typed expense_policy by applicability: per-category limits per bill/day/month, by grade and city tier; receipt required above an amount; per-diem rates; mileage rate per vehicle type; claim submission window (days after bill date, default 60); currency INR only. | Must | R2 | [Proposed] |
| FR-CLM-003 | Claim with one or more bills: category, bill number, bill date, vendor, amount, optional GSTIN and GST amount, attachment (pdf/jpg/png ≤ 5 MB, camera capture), description; claim ID CLM-{YYYY}-{NNNNN}; save draft; submit. | Must | R2 | [Observed] E: Claims Management + [Proposed] |
| FR-CLM-004 | Policy checks at submission: over-limit bills are blocked or flagged (per policy over_limit = block / flag with justification); missing receipt; outside window. | Must | R2 | [Proposed] |
| FR-CLM-005 | Duplicate detection on (bill number, amount, date, vendor) and on file hash across the tenant; duplicates are blocked or flagged for the verifier. | Must | R2 | [Proposed] |
| FR-CLM-006 | Unified statuses: Draft → Submitted → Verified → Approved → Paid, with Rejected (reason) from Submitted or Verified, and Withdrawn by the employee before verification. The same names appear for every role. | Must | R2 | [Observed] research §9 redesigned |
| FR-CLM-007 | Verification by line manager (workflow via NTF): per-bill accept, reject (reason) or reduce to a verified amount; a selected-records summary before confirming. | Must | R2 | [Observed] M: Claims Management |
| FR-CLM-008 | Finance approval by payroll_manager (or configured role) with bulk approve; the approved amount can only be ≤ the verified amount. | Must | R2 | [Observed] |
| FR-CLM-009 | Payout: approved claims flow to the next payroll run as reimbursement components (FR-PAY-027), or into a separate reimbursement bank file; status becomes Paid when the run is Paid or the file is marked paid. | Must | R2 | [Proposed] |
| FR-CLM-010 | Finance dashboard: counts and amounts by status (current month), settlement ratio (paid / total), previous vs current month scorecard, paid amount by category. | Must | R2 | [Observed] research §9 |
| FR-CLM-011 | Mileage claims generated from verified FFM travel (km × policy rate), with the travel record attached, in the same pipeline. | Must | R3 | [Observed] travel approvals merged |
| FR-CLM-012 | Claim advances (cash advance against a trip, settled against claims). | Could | R3 | [Proposed] |
| FR-CLM-013 | Receipt OCR to pre-fill bill fields. | Could | R4 | [Proposed] |
| FR-CLM-014 | Outstanding claims at exit are listed in F&F (pay or reject). | Must | R2 | [Proposed] |
7.11.5 Key entities
expense_category, expense_policy (version), claim (code, employee, status, totals), claim_bill (category, bill_no, date, vendor, amount, gst, file, verified_amount, decision), claim_payout (run or bank file), mileage_claim_source (R3).
7.11.6 Configuration settings
expense_policy.* (limits, receipts, per-diem, mileage, window), claims.over_limit (block / flag, default flag), claims.payout_mode (payroll / bank file, default payroll), claims.max_file_mb (5), workflow.claim (line manager verify → finance approve).
7.11.7 User stories
US-CLM-01 — Submit a claim with bills on mobile. As a field_executive, I want to photograph three bills and submit one claim.
- AC1: Given I add three bills with photos, when I submit, then I see claim CLM-2027-00042 with total ₹2,350 and status Submitted.
- AC2: Given a food bill of ₹900 and a daily food limit of ₹600 with
over_limit = flag, then I must add a justification before submitting.
US-CLM-02 — Verify per bill. As a line_manager, I want to reduce one bill and reject another.
- AC1: When I set bill 1 to ₹600 verified and reject bill 3 with a reason, then the claim shows verified ₹1,450 and moves to Finance.
US-CLM-03 — Pay through payroll. As a payroll_manager, I want approved claims paid with salary.
- AC1: Given claims approved by the 20th, when the November run calculates, then each employee's payslip shows "Reimbursement" lines and the claims become Paid when the run is Paid.
US-CLM-04 — Duplicate bill. Given the same bill number, amount and date were claimed last month, when I submit, then the bill is flagged "Possible duplicate of CLM-2027-00011" for the verifier.
7.11.8 Permissions
| Action | OWN | HRA | PRM | FNA | LM | EMP/FEX | AUD |
|---|---|---|---|---|---|---|---|
| Categories and policy | ORG | ORG | ORG(R) | ORG | — | own policy (R) | ORG(R) |
| Submit / withdraw | SELF | SELF | SELF | SELF | SELF | SELF | — |
| Verify | ORG | — | — | — | TEAM | — | — |
| Approve / mark paid | ORG | — | ORG | ORG | — | — | — |
| View claims | ORG | ORG | ORG | ORG | TEAM | SELF | ORG(R) |
7.11.9 UI/UX
Mobile-first claim capture (camera, multi-bill list, running total, policy hints per category); manager verification screen with bill images side by side and per-bill actions; finance web grid with bulk approve and dashboard. Empty state: "No claims yet. Tap + to add a bill." Errors: file too large shows the limit; over-limit shows the remaining allowance.
7.11.10 Notifications and automation
Claim submitted (verifier), verified (finance, employee), approved, paid (employee), rejected (employee with reason), pending verification > 3 days (escalation), submission window closing for draft bills.
7.11.11 Reports and analytics
Claims register (Applied on, Employee, Claim ID, bill count, requested, verified, approved, paid, status, action on/by — extends the observed column set), claims by category, settlement ratio trend, policy exceptions, duplicates flagged, outstanding claims at exit.
7.11.12 Edge cases
- Policy changes after a bill date → the policy version effective on the bill date applies.
- Employee exits with claims in Submitted → routed to HR for decision in F&F.
- Payroll run reversed after claims were marked Paid → claims return to Approved and are paid in the correction run.
7.12 EXT — Exit & Full-and-Final Settlement
Traces to: BR-EXT-* · Release: R2
7.12.1 Purpose and scope
EXT manages resignation, termination and other separations through to clearance, F&F settlement, letters and access revocation.
| In scope | Out of scope |
|---|---|
| Resignation with approval chain; HR-initiated separation (termination, retirement, death, absconding, end of contract); notice period computation, shortfall, buy-out and waiver; clearance with owners; exit interview; F&F (via PAY-060); relieving and experience letters; access revocation; rehire eligibility; attrition analytics | Legal case management; gratuity trust administration; outplacement |
7.12.2 Reference product summary
- Offboarding settings: automatic clearance reminders and a notice period in days [Observed] (A: Exit Management). Termination categories and separation reasons as masters [Observed] (A: Exit Management).
- The employee raises a separation request (exit date, reason, notes), editable or cancellable before approval [Observed] (E: Exit Management). The HR Manager approves with an approved exit date or rejects — the reporting manager is skipped [Observed] (M: Exit Management); the rejection text says "approved" [Observed doc defect] (research §17 D7).
- Termination by employee + category → termination checklist; backdated termination window 0–60 days (Rule 37) [Observed] (M: Exit Management; SP-IAM-03).
- No F&F, exit interview, letters or access revocation are documented [Inferred] (research §8).
7.12.3 What we change and why [Proposed]
- Employee → line manager → HR approval with last-working-day (LWD) negotiation.
- Clearance with task owners (IT, Finance, Admin, manager) using the EMP checklist engine.
- F&F as a payroll run type, so settlement uses the same engine, approvals and files.
- Automatic access revocation at LWD 23:59 local time (FR-IAM-017).
7.12.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-EXT-001 | Resignation request: proposed LWD, reason (master), notes, attachment; system shows the policy LWD from the notice period (FR-EMP-012) and the shortfall days; edit or withdraw before final approval. | Must | R2 | [Observed] E: Exit Management + [Proposed] |
| FR-EXT-002 | Approval workflow line manager → HR (NTF): approve with an agreed LWD, request a discussion, or reject with reason; status on_notice from approval. | Must | R2 | [Observed] M: Exit Management redesigned |
| FR-EXT-003 | Notice handling: shortfall recovery (days × daily rate, formula), buy-out by employee, waiver by HR with reason, leave adjustment against notice if the policy allows. | Must | R2 | [Proposed] |
| FR-EXT-004 | HR-initiated separation with type (Termination, Retirement, End of contract, Death, Absconding) and category master; back-dated LWD allowed up to separation.backdate_max_days (default 30, 0–60) and only into unlocked payroll periods. | Must | R2 | [Observed] Rule 37 + [Proposed] |
| FR-EXT-005 | Clearance: offboarding checklist templates by applicability with owners (IT: laptop, access; Finance: advances; Admin: ID card; Manager: handover), due relative to LWD, evidence, "No Due" sign-off per owner. | Must | R2 | [Observed] SP-EMP-01 + [Proposed] |
| FR-EXT-006 | Exit interview: a configurable short questionnaire sent near LWD; responses visible to HR only; aggregated reasons in analytics. | Should | R2 | [Proposed] |
| FR-EXT-007 | F&F initiation: when clearance is complete (or forced by HR), create an F&F run (FR-PAY-060) pre-filled with pending salary, leave encashment balance, gratuity eligibility, notice pay/recovery, outstanding advances/loans, pending claims (FR-CLM-014) and assets not returned; F&F statement PDF. | Must | R2 | [Proposed] |
| FR-EXT-008 | Letters: relieving letter and experience letter from templates after F&F lock (or on LWD per setting); service certificate. | Must | R2 | [Proposed] |
| FR-EXT-009 | Access revocation at LWD 23:59 location time; ex-employees keep read-only access to their payslips and Form 16 through a limited "alumni" login for alumni.access_days (default 365) if enabled. | Must (alumni: Should) | R2 | [Proposed] |
| FR-EXT-010 | Rehire eligibility flag and exit reason on the employment record. | Should | R2 | [Proposed] |
| FR-EXT-011 | Absconding process: after N consecutive absent days (default 7), prompt HR to start an absconding case with notices sent and salary hold. | Should | R2 | [Proposed] |
| FR-EXT-012 | Resignation withdrawal after approval, with approval, before LWD. | Must | R2 | [Proposed] |
7.12.5 Key entities
separation (type, reason, requested_lwd, approved_lwd, status, shortfall_days, buyout, waiver), separation_reason, termination_category, clearance (checklist), exit_interview, fnf_case (run ref, statement ref), alumni_access.
7.12.6 Configuration settings
separation.backdate_max_days (30), workflow.resignation (LM → HR), notice.recovery_formula (e.g. (Basic + DA) / 30 × shortfall days), notice.allow_leave_adjustment (false), clearance.reminder_days (2), letters.issue_on (fnf_lock / lwd), alumni.enabled (true), alumni.access_days (365), absconding.days (7).
7.12.7 User stories
US-EXT-01 — Resign with notice shortfall. As an employee, I want to resign and see my notice obligations.
- AC1: Given a 30-day notice and a requested LWD 20 days away, when I fill the form, then I see "Shortfall 10 days; may be recovered or waived".
- AC2: When my manager approves with LWD +25 days and HR approves, then my status is On notice and clearance tasks are created.
US-EXT-02 — Clearance owners. As the IT owner, I want my clearance task listed with the LWD so I collect the laptop on time.
- AC1: Given LWD is 30 Nov, then my task is due 28 Nov and escalates to HR if not done by LWD.
US-EXT-03 — F&F. As a payroll_manager, I want the F&F pre-filled.
- AC1: Given clearance is complete, when the F&F run is created, then it includes salary to LWD, EL encashment of 12 days, gratuity (eligible, 6 years), shortfall recovery of 5 days and an outstanding advance of ₹10,000, each with its formula.
- AC2: When the F&F run is locked and paid, then the F&F statement and relieving letter are published to the employee's alumni access.
US-EXT-04 — Access revocation. Given LWD is today, when it is 23:59 at the employee's location, then the employee's sessions end and normal login is disabled; alumni login (if enabled) shows only payslips and letters.
7.12.8 Permissions
| Action | OWN | HRA | HRM | PRM | LM | EMP | Clearance owner |
|---|---|---|---|---|---|---|---|
| Raise resignation | SELF | SELF | SELF | SELF | SELF | SELF | — |
| Approve resignation | ORG | ORG | LOC* | — | TEAM (level 1) | — | — |
| HR-initiated separation | ORG | ORG | LOC* | — | propose TEAM | — | — |
| Clearance tasks | ORG | ORG | LOC* | finance tasks | own tasks | view SELF | assigned |
| F&F run | ORG (approve) | — | — | ORG | — | view own statement | — |
| Exit interview responses | ORG | ORG | LOC* | — | — | submit SELF | — |
7.12.9 UI/UX
Employee: Resign screen with policy LWD and shortfall explanation; status timeline (Submitted → Manager → HR → On notice → Clearance → F&F → Relieved). HR web: Separations board by stage; clearance progress per employee; F&F link to the payroll run. Empty: "No active separations". Errors: back-dated LWD into a locked period is blocked with an explanation.
7.12.10 Notifications and automation
Resignation submitted/decided; LWD reminders (7 days, 1 day) to employee, manager, clearance owners; clearance overdue; exit interview invitation; F&F ready for review; F&F paid; letters issued; access revoked (HR summary).
7.12.11 Reports and analytics
Attrition (voluntary/involuntary, by department, location, tenure band, reason), notice compliance (shortfall, waivers, buy-outs), clearance ageing, F&F turnaround (LWD → paid), rehire-eligible alumni.
7.12.12 Edge cases
- Death of an employee → separation type Death; F&F payable to nominees (FR-EMP-003 nominations); no notice recovery; gratuity eligibility per statute regardless of service length (verify).
- Employee on long leave during notice → leave beyond LWD cancelled automatically.
- Resignation withdrawn after F&F created → F&F run is cancelled if not locked; otherwise HR is told a reversal is needed.
7.13 ENG — Engagement: Announcements, Recognition
Traces to: BR-ENG-* · Release: R2
7.13.1 Purpose and scope
ENG provides company announcements with audience targeting and read tracking, and peer recognition.
| In scope | Out of scope |
|---|---|
| Announcements (targeted, scheduled, acknowledgements); recognition (types, messages, wall, reactions); birthday and work-anniversary feed | Surveys and eNPS (§15); rewards catalogues and points redemption; social chat |
7.13.2 Reference product summary
- Announcements: topic, title, publish from/to, description; Submit (Published) or Save as Draft; Published → edit/view/stop; Draft → edit/view; Completed → view/republish; Cancelled → view [Observed] (A: Employee Management; SP-ENG-01).
- Rewards & Recognition in the HCM app: send to a peer with a recognition type and message; Sent/Received lists; counts per type per employee [Observed] (MOB: Spryple HR). Types: Birthday, Outstanding, Job Well Done, Congratulations, Performance-based recognition; template messages with a 145-character limit [Observed] (research §21.9).
- No audience targeting, read receipts, reactions or public wall [Inferred] (research §13).
7.13.3 What we change and why [Proposed]
Audience targeting and read receipts make announcements useful for compliance notices; a recognition wall with reactions increases visibility at near-zero cost.
7.13.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-ENG-001 | Announcements with topic, title, rich-text body (sanitised), attachments, publish from/to, statuses Draft → Scheduled → Published → Completed, Stopped/Cancelled, and republish. | Must | R2 | [Observed] SP-ENG-01 |
| FR-ENG-002 | Audience targeting by location, department, designation, employment type or named list; preview of recipient count. | Must | R2 | [Proposed] |
| FR-ENG-003 | Read receipts and optional "acknowledge" button with an acknowledgement report (for policy notices). | Must | R2 | [Proposed] |
| FR-ENG-004 | Pin announcements; push/email on publish (configurable per announcement). | Should | R2 | [Proposed] |
| FR-ENG-005 | Recognition: send to one or more colleagues with a type from a tenant master (seeded with the five observed types) and a message (limit configurable, default 280 characters); visibility public (wall) or private. | Must | R2 | [Observed] research §21.9 + [Proposed] |
| FR-ENG-006 | Recognition wall with reactions and comments; admins can hide content with a reason (moderation). | Should | R2 | [Proposed] |
| FR-ENG-007 | Automatic birthday and work-anniversary posts (respecting an employee opt-out and hiding the birth year). | Should | R2 | [Proposed] |
| FR-ENG-008 | Manager-awarded points with redeemable rewards. | Won't | R2 | [Proposed] (future, §15) |
7.13.5 Key entities
announcement (topic, title, body, audience_rule, from, to, status, ack_required), announcement_receipt (read_at, ack_at), recognition_type, recognition (from, to[], type, message, visibility), reaction, comment.
7.13.6 Configuration settings
recognition.message_max_chars (280), recognition.default_visibility (public), eng.birthday_posts (on, with employee opt-out), announcement.default_channels (in-app + push).
7.13.7 User stories
US-ENG-01 — Targeted policy notice. As an hr_manager, I want to send the new safety policy to Plant 1 and track acknowledgements.
- AC1: Given audience Location = Plant 1 (412 employees), when I publish with acknowledgement required, then 412 employees receive it and the report shows acknowledged vs pending.
US-ENG-02 — Recognise a colleague. As an employee, I want to thank a colleague publicly.
- AC1: When I choose "Job Well Done", write a message within the limit and send, then it appears on the wall and the colleague gets a push.
US-ENG-03 — Stop an announcement. Given a published announcement, when I stop it, then it disappears from feeds and its status becomes Stopped; it can be republished later.
7.13.8 Permissions
| Action | OWN | HRA | HRM | LM | EMP | AUD |
|---|---|---|---|---|---|---|
| Create/publish announcements | ORG | ORG | LOC* | TEAM (if enabled) | — | — |
| View announcements | targeted | targeted | targeted | targeted | targeted | ORG(R) |
| Send recognition | ✓ | ✓ | ✓ | ✓ | ✓ | — |
| Moderate wall, manage types | ORG | ORG | LOC* | — | — | — |
| Recognition reports | ORG | ORG | LOC* | TEAM | SELF | ORG(R) |
7.13.9 UI/UX
Home feed card for unread announcements; announcement detail with Acknowledge; recognition composer as a bottom sheet with type chips; wall as a scrollable feed. Empty state: "No announcements yet". Accessibility: rich text renders with headings and alt text for images.
7.13.10 Notifications and automation
Announcement published (targeted channels), acknowledgement reminder (after 3 days), recognition received, birthday/anniversary (to the employee and optionally the team).
7.13.11 Reports and analytics
Announcement reach (delivered, read, acknowledged), recognition counts per type per employee [Observed], top recognisers and recipients by department.
7.13.12 Edge cases
Audience changes after publish (new joiner in Plant 1) → new eligible employees see active announcements; acknowledgement reports count them from their joining date. Recognition to an exited employee is blocked.
7.14 FFM — Field Force & Sales CRM
Traces to: BR-FFM-* · Release: R3 (paid add-on, per tracked user)
7.14.1 Purpose and scope
FFM lets field teams punch, record visits and activities against accounts, move leads through a configurable pipeline, collect payments, and get travel reimbursed, while managers see location and activity with privacy safeguards.
| In scope | Out of scope |
|---|---|
| Consent-gated location tracking (two modes) between punch-in and punch-out; live map and route replay; kms with snap-to-road; visits with geo-verification; accounts, contacts and associates (shared with TSM); configurable pipeline; activities and follow-ups; lead ageing; payment collection; assignments and beat plans; travel → CLM mileage; offline capture | Product catalogue, quotes, orders and invoicing (Could, post-R4); territory optimisation; dealer management; marketing automation |
7.14.2 Reference product summary
- GPS modes: Point-to-Point (route from punch-in, punch-out and visit activities) and GPS Monitoring (continuous from punch-in to punch-out); Google Maps; requires login, location permission and internet [Observed] (research §21.7). Manager GPS monitoring with battery % and punch counts [Observed] (M: CRM Field Force Management).
- Pipeline: Leads, Call for Demo, Demo Pending, Demo Completed, Future Leads, with lead-age colours green 0–7 days, amber 8–14, red 15+ [Observed] (M: CRM Field Force Management; research §21.7). A second client status set: Interested, Follow-up, Won, Lost, Not Interested [Observed] (E: Sales CRM Web Application).
- Activities: types VISIT, CALL, MESSAGE, MAIL; follow-up date/time; final price on Won [Observed] (research §21.7). Client associates (type, qualification, specialization) with sample data Doctor/MBBS/Cardiology, i.e. pharma field sales [Observed] (research §21.7). Client payments (method, collected amount; pending amount) [Observed] (research §21.7).
- Visit location verification indicator: matched, not matched, not available (first visit sets the client location) [Observed] (research §21.7). Travel approvals Pending → Verified → Approved → Claimed with an editable KM Revised field [Observed] (research §21.7).
- Reports: employee activity (visits, kms), tracking log (start/stay/travel durations, kms), employee summary [Observed] (M: CRM Field Force Management). Device approvals for new phones [Observed]. Leave and shift screens duplicated inside CRM [Observed] (research §21.7).
- No documented consent, work-hours limits or retention for tracking [Inferred] (research §11).
7.14.3 What we change and why [Proposed]
- Privacy first: explicit consent, tracking only between punch-in and punch-out, visible indicator, raw GPS retention 90 days.
- Configurable pipeline with industry templates (demo-led SaaS, pharma detailing, distribution) instead of two hard-coded status systems.
- Geo-verification with enforcement choice (block, flag or allow) rather than an indicator only.
- One Account/Contact model shared with TSM, and travel paid through CLM.
- No duplicated ATT/LVE screens: the field app uses the same ATT/LVE features.
7.14.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-FFM-001 | Tracking consent (FR-IAM-018) with plain-language disclosure before OS permission prompts; tracking runs only between punch-in and punch-out; a persistent on-screen/notification indicator while tracking. | Must | R3 | [Proposed] |
| FR-FFM-002 | Tracking modes per policy: point_to_point (punches + visits only) and continuous (adaptive sampling: default every 60 s or 100 m when moving, paused when stationary). | Must | R3 | [Observed] research §21.7 |
| FR-FFM-003 | Device telemetry with each batch: battery %, location permission state, GPS on/off, mock-location detection; gaps explained on the map ("GPS off 11:02–11:40"). | Must | R3 | [Observed] battery % + [Proposed] |
| FR-FFM-004 | Manager live map (last known position, status, battery) and route replay for a date; Google Maps or Mappls through the maps provider interface. | Must | R3 | [Observed] |
| FR-FFM-005 | Distance: snap-to-road with outlier filtering (speed > 150 km/h, accuracy > 100 m discarded); daily kms per employee; manager revised km with mandatory reason, original kept. | Must | R3 | [Observed] KM Revised + [Proposed] |
| FR-FFM-006 | Accounts (organisations), contacts and associates with configurable associate types, qualifications and specialisations; account geo-location; custom fields; import; shared with TSM clients. | Must | R3 | [Observed] research §21.7 + [Proposed] |
| FR-FFM-007 | Visits: check-in and check-out at an account with photo (optional), notes and outcome; geo-verification against the account location within visit.match_radius_m (default 200); enforcement block, flag or allow; first verified visit can set a missing account location (with manager confirmation). | Must | R3 | [Observed] visit verification + [Proposed] |
| FR-FFM-008 | Configurable pipeline: stages per tenant (name, order, probability, won/lost flags) with templates; one status system; stage history. | Must | R3 | [Observed] redesigned |
| FR-FFM-009 | Activities (Visit, Call, Message, Mail + tenant types) with follow-up date/time, scheduled vs exceeded status, image-only activity option, final value on Won. | Must | R3 | [Observed] research §21.7 |
| FR-FFM-010 | Lead ageing colours with configurable thresholds (default 0–7 green, 8–14 amber, 15+ red). | Should | R3 | [Observed] research §21.7 |
| FR-FFM-011 | Payment collection against a won deal: method, amount, reference, receipt photo; pending amount; daily collection summary. | Should | R3 | [Observed] research §21.7 |
| FR-FFM-012 | Assignments and beat plans: planned visits per day/week per executive; plan vs actual; reassignment of accounts and activities when an executive is unavailable. | Should | R3 | [Observed] reassignment + [Proposed] |
| FR-FFM-013 | Travel: daily travel record (kms, visits) → manager verify (revised km) → mileage claim in CLM (FR-CLM-011); minimum-visits rule for eligibility. | Must | R3 | [Observed] travel approvals merged |
| FR-FFM-014 | Offline: visits, activities and new accounts are queued offline with device time and synced later; GPS points are buffered up to 24 h. | Must | R3 | [Proposed] |
| FR-FFM-015 | Web add-client toggle and field-only creation options. | Could | R3 | [Observed] |
| FR-FFM-016 | Retention: raw GPS points kept 90 days (configurable lower), then only daily aggregates (kms, durations); visit locations kept with the visit. | Must | R3 | [Proposed] (architecture.md §7) |
| FR-FFM-017 | Products, quotes and orders. | Won't | R3 | [Proposed] (§15) |
7.14.5 Key entities
tracking_session (employee, punch refs, mode, consent_id), gps_point (monthly partitions: ts, lat, lng, accuracy, speed, battery), daily_travel (km_computed, km_revised, reason, status), account, contact, associate, associate_type, pipeline / pipeline_stage, deal (account, stage, value, owner), activity, visit (check-in/out, location, match_result), payment_collection, beat_plan / planned_visit.
7.14.6 Configuration settings
tracking.mode (point_to_point / continuous), tracking.interval_s (60), tracking.distance_m (100), visit.match_radius_m (200), visit.enforcement (flag), lead_age.thresholds (7, 14), travel.min_visits (0), gps.retention_days (90, max 90), pipeline.template (selected at set-up).
7.14.7 User stories
US-FFM-01 — Tracking only on duty. As a field_executive, I want tracking to stop when I punch out.
- AC1: Given consent and continuous mode, when I punch in, then tracking starts and the indicator shows; when I punch out, then no further points are recorded.
US-FFM-02 — Geo-verified visit. As a field_executive, I want to check in at a hospital.
- AC1: Given the account location and a 200 m radius with
flag, when I check in 450 m away, then the visit is saved as "Location not matched" and my manager sees the flag.
US-FFM-03 — Revise kms. As a sales_manager, I want to correct inflated kms.
- AC1: When I revise 84 km to 62 km with a reason, then the mileage claim uses 62 km and the record shows both values and my reason.
US-FFM-04 — Configure the pipeline. As a sales_admin, I want stages Prospect → Detailing → Sample given → Prescribing.
- AC1: When I save the stages, then deals move through them and the pipeline board shows them in order with ageing colours.
US-FFM-05 — Battery gap explained. Given an executive's phone dies at 15:10, when the manager replays the route, then the map shows "No data 15:10–16:30 (battery 2%)".
7.14.8 Permissions
| Action | OWN | SLA | SLM | LM | FEX | HRA | AUD |
|---|---|---|---|---|---|---|---|
| CRM masters, pipeline, tracking policy | ORG | ORG | ORG(R) | — | — | tracking policy ORG | ORG(R) |
| Live map, routes | ORG | — | TEAM / LOC* | TEAM | SELF | — | — |
| Accounts, deals, activities | ORG | ORG | TEAM | — | own + assigned | — | ORG(R) |
| Revise km, verify travel | ORG | — | TEAM | TEAM | — | — | — |
| Reassign accounts | ORG | ORG | TEAM | — | — | — | — |
7.14.9 UI/UX
Field app tab: Today (plan, follow-ups due, punch state), Accounts (search, nearby), Visit check-in (one tap, photo, outcome), Pipeline (list by stage), Collections. Manager web: map with team list (battery, last seen, status), route replay timeline, pipeline board, travel verification grid with a selected-records summary. Empty states guide to "Add your first account". Errors: permission denied shows how to enable location "while using the app" and the consequences.
7.14.10 Notifications and automation
Follow-up due and exceeded, visit plan published, lead ageing to red, device pending approval, tracking stopped unexpectedly during duty (to employee and, optionally, manager), travel pending verification, payment recorded.
7.14.11 Reports and analytics
Employee activity report (punches, visits, kms), tracking log, employee summary (first login, last logout, worked hours, new visits, new accounts, total visits, kms, activities) [Observed], visits vs plan, geo-verification exceptions, pipeline by stage and age, win rate, collections, travel and mileage cost.
7.14.12 Edge cases
Mock-location apps detected → points flagged and manager alerted. iOS background limits → significant-change mode fallback with lower accuracy, labelled on the map. Two executives visiting the same account → both visits recorded; the account owner unchanged.
7.15 TSM — Timesheets & Projects
Traces to: BR-TSM-* · Release: R3 (add-on)
7.15.1 Purpose and scope
TSM records time against projects and tasks, with approvals, defaulter nudges and effort-variance reporting for services teams.
| In scope | Out of scope |
|---|---|
| Clients (shared Accounts), projects, team assignment and project roles, tasks with estimates; weekly timesheet entry; attendance-hours cap; approvals; defaulters; period lock; dashboards; effort variance; billable-hours export | Invoicing and rates-to-invoice; resource capacity planning; Gantt charts |
7.15.2 Reference product summary
- Admin: Clients (contact, designation, number, email, start date, address), Projects, Assign Team, Tasks, Project Roles with no duplicates [Observed] (A: Time Sheet Management).
- Manager: dashboard (active projects, assigned employees, bench count, hours by project, status summary with and without variance, estimated vs consumed hours); Pending Approvals (bulk), History, Defaulters with "Send Notification" [Observed] (M: Time Sheet Management).
- Employee: Submit Timesheet rows (date, project, task, description, hours, %, task completed) and a "limit timesheet hours to attendance hours" rule [Observed] (E: Time Sheet Management), which is not in the HR policy list [Observed doc defect] (research §17 D11).
- Effort variance = (Actual − Planned) / Planned [Observed] (research §21.8).
7.15.3 What we change and why [Proposed]
Shared Accounts with FFM; a weekly grid entry (faster than per-row forms); billable flag; period lock; reminders through NTF.
7.15.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-TSM-001 | Projects: client (Account), project manager, start/end dates, estimated hours or days, status, billable default; project roles; team assignment with allocation %. | Must | R3 | [Observed] A: Time Sheet Management |
| FR-TSM-002 | Tasks with estimate, assignee(s), dates, status, % complete. | Must | R3 | [Observed] |
| FR-TSM-003 | Weekly timesheet grid (rows = project/task, columns = days) with notes, billable flag, copy last week; daily entry on mobile. | Must | R3 | [Proposed] |
| FR-TSM-004 | Attendance cap: optional rule that daily logged hours ≤ ATT worked hours (+ tolerance); leave and holidays prefilled as non-working. | Should | R3 | [Observed] E: Time Sheet Management |
| FR-TSM-005 | Submit per week; approval by project manager or line manager (configurable) with bulk approve/reject; history. | Must | R3 | [Observed] |
| FR-TSM-006 | Defaulters list (missing or unsubmitted timesheets) with one-click reminders and scheduled automatic reminders. | Must | R3 | [Observed] |
| FR-TSM-007 | Period lock (monthly) after approval; corrections after lock need HR/PM unlock with reason. | Should | R3 | [Proposed] |
| FR-TSM-008 | Dashboards: active projects, bench count (employees with < N% allocation), hours by project, estimated vs consumed. | Must | R3 | [Observed] |
| FR-TSM-009 | Effort variance report (planned vs actual hours, actual dates, variance %). | Must | R3 | [Observed] research §21.8 |
| FR-TSM-010 | Billable-hours export by client and project (CSV) for external invoicing. | Should | R3 | [Proposed] |
| FR-TSM-011 | Invoicing. | Won't | R3 | [Proposed] |
7.15.5 Key entities
project, project_role, project_member (allocation), task, timesheet_week (employee, week, status), timesheet_entry (date, project, task, hours, billable, note), timesheet_period (lock).
7.15.6 Configuration settings
timesheet.approver (project_manager / line_manager), timesheet.attendance_cap (off), timesheet.cap_tolerance_min (30), timesheet.reminder (Friday 16:00), bench.threshold_pct (20).
7.15.7 User stories
US-TSM-01 — Weekly entry. As an employee, I want to fill my week in one grid.
- AC1: Given two assigned tasks, when I enter hours per day and submit, then the week shows Submitted with total hours and goes to my approver.
- AC2: Given the attendance cap is on and I worked 7 h on Tuesday, when I log 9 h, then I see "Exceeds attendance hours (7 h)".
US-TSM-02 — Defaulter nudge. As a line_manager, when I open Defaulters on Monday, then I see who has not submitted last week and can remind all with one action.
US-TSM-03 — Effort variance. As an org_owner, when I open Effort variance for Project X (planned 400 h, actual 460 h), then variance shows +15%.
7.15.8 Permissions
| Action | OWN | HRA | Project manager (role) | LM | EMP | AUD |
|---|---|---|---|---|---|---|
| Projects, tasks, roles | ORG | ORG | own projects | — | — | ORG(R) |
| Log time | SELF | SELF | SELF | SELF | SELF | — |
| Approve timesheets | ORG | ORG | own projects | TEAM (if approver) | — | — |
| Reports | ORG | ORG | own projects | TEAM | SELF | ORG(R) |
7.15.9 UI/UX
Web weekly grid with keyboard navigation and totals; mobile daily entry. Manager approvals in the unified inbox. Empty: "You are not assigned to any project". Locked weeks shown read-only.
7.15.10 Notifications and automation
Weekly reminder; defaulter reminders; submitted/approved/rejected; project end approaching; task assigned.
7.15.11 Reports and analytics
Timesheet summary (by employee, project, client), effort variance, bench report, billable vs non-billable hours, defaulters history.
7.15.12 Edge cases
Employee removed from a project mid-week → existing entries stay; new entries blocked. Holiday in the week → prefilled; logging time on it is allowed only if attendance shows HP.
7.16 LMS — Learning Management
Traces to: BR-LMS-* · Release: R4 (narrow scope)
7.16.1 Purpose and scope
LMS delivers mandatory and optional courses, tracks completion and issues certificates, with priority on compliance training (POSH, safety, induction).
| In scope | Out of scope |
|---|---|
| Course catalogue; simple course builder (modules → sections → content); SCORM 1.2 import; quizzes; mandatory assignments by applicability with due dates; completion tracking; certificates; reminders; reports; badges (Could) | Authoring tools beyond the simple builder; live virtual classrooms; marketplace content; xAPI LRS |
7.16.2 Reference product summary
- Instructor Course Builder (title, tags, description, difficulty, category, prerequisites, image) → Module → Section → Content → review → submit; dashboard with leaderboard, progress, badges by category, recommended courses; reports (enrolled, completed, badges, points, certificates) [Observed] (I: LMS Instructor).
- Employee: Course Library, assessments, Learning Sphere, My Badges, My Certificates [Observed] (E: Learning Management System (LMS)). Certificate shows recipient, course, date, tenant, instructor signature and a Certificate ID such as
CERT250811174612SELE10, with no score or duration [Observed] (research §21.10). - No mandatory assignment, due dates, compliance training or SCORM is documented [Inferred] (research §12).
7.16.3 What we change and why [Proposed]
Start with mandatory compliance courses tied to onboarding and completion evidence, because that is what SMEs must prove; keep gamification optional.
7.16.4 Functional requirements
| ID | Requirement | Priority | Release | Label |
|---|---|---|---|---|
| FR-LMS-001 | Course with title, category, tags, description, difficulty, prerequisites, image, estimated duration; structure modules → sections → content (video URL, PDF, rich text). | Must | R4 | [Observed] I: LMS Instructor |
| FR-LMS-002 | SCORM 1.2 package import with completion and score tracking. | Should | R4 | [Proposed] |
| FR-LMS-003 | Quizzes (single/multiple choice) with pass mark and attempts limit. | Must | R4 | [Observed] assessments + [Proposed] |
| FR-LMS-004 | Mandatory assignment by applicability (location, department, designation, new joiners) with due date (absolute or days after joining), recurrence (e.g. yearly POSH refresher); linkable as an onboarding checklist item. | Must | R4 | [Proposed] |
| FR-LMS-005 | Progress and completion tracking with resume; completion evidence (date, score, time spent). | Must | R4 | [Proposed] |
| FR-LMS-006 | Certificates with a unique verifiable ID, recipient, course, completion date, score (optional) and signatory; public verification link (opt-in). | Must | R4 | [Observed] research §21.10 + [Proposed] |
| FR-LMS-007 | Reminders before due date and escalation to line manager when overdue. | Must | R4 | [Proposed] |
| FR-LMS-008 | Course review/publish workflow for instructors (draft → review → published → archived). | Should | R4 | [Observed] |
| FR-LMS-009 | Badges and points; leaderboard (opt-in). | Could | R4 | [Observed] |
| FR-LMS-010 | Recommended courses by role. | Could | R4 | [Observed] |
7.16.5 Key entities
course, course_module, course_section, content_item, scorm_package, quiz / question / attempt, assignment_rule, enrolment (status, due, progress, completed_at, score), certificate (code, issued_at), badge (Could).
7.16.6 Configuration settings
lms.certificate_id_pattern (CERT-{YYYY}-{NNNNNN}), lms.overdue_escalation_days (7), lms.leaderboard (off), lms.public_verification (off).
7.16.7 User stories
US-LMS-01 — Mandatory POSH course. As an hr_admin, I want every new joiner to complete POSH within 30 days.
- AC1: Given an assignment rule "new joiners, due 30 days after joining", when an employee is activated, then the course appears in their Learning tab with the due date and in their onboarding checklist.
- AC2: Given it is overdue by 7 days, then the line manager is notified.
US-LMS-02 — Certificate. As an employee, when I pass the quiz, then a certificate with a unique ID is issued and downloadable.
US-LMS-03 — Compliance report. As an hr_manager, when I open the POSH report for Plant 1, then I see assigned, completed, overdue and completion % by department.
7.16.8 Permissions
| Action | OWN | HRA | HRM | INS | LM | EMP | AUD |
|---|---|---|---|---|---|---|---|
| Create/publish courses | ORG | ORG | — | own courses | — | — | — |
| Assignment rules | ORG | ORG | LOC* | — | — | — | — |
| Learn, take quizzes | SELF | SELF | SELF | SELF | SELF | SELF | — |
| Reports | ORG | ORG | LOC* | own courses | TEAM | SELF | ORG(R) |
7.16.9 UI/UX
Employee Learning tab: Assigned (with due chips), Library, Certificates. Course player with progress, works on mobile, resumes offline-downloaded PDFs. Instructor web builder with outline tree and preview. Empty: "No courses assigned".
7.16.10 Notifications and automation
Course assigned, due soon (7 days, 1 day), overdue (employee, manager), certificate issued, course published (to targeted audience).
7.16.11 Reports and analytics
Enrolment and completion by course, department and location; overdue mandatory training; quiz scores; certificates issued; badges and points (if enabled).
7.16.12 Edge cases
Course content updated after completion → existing completions remain valid unless the instructor marks the change "requires re-completion". Employee transfers → new mandatory rules apply from the transfer date; completed courses carry over.
8. Non-functional requirements
Targets use the SLOs, RPO/RTO and controls in architecture.md §6–§13. "Stage A/B" refers to the hosting stages in architecture.md §10.2. Each NFR names how it is verified.
8.1 Performance (PERF)
| ID | Requirement | Target | Verification |
|---|---|---|---|
| NFR-PERF-01 | API latency per cell under normal load | p95 < 300 ms for reads, < 800 ms for writes (excluding exports and file generation) | k6 load tests in CI on staging; production RED metrics |
| NFR-PERF-02 | Punch acceptance (server acknowledgement of an online punch, selfie ≤ 300 KB) | p95 < 2 s | Synthetic punch check every 5 min; API metrics |
| NFR-PERF-03 | Web front end on a mid-range device over 4G | LCP ≤ 2.5 s (p75), INP ≤ 200 ms, initial JS ≤ 300 KB gzipped | Lighthouse CI, real-user monitoring |
| NFR-PERF-04 | Payroll calculation | 1,000 employees in < 5 min; 5,000 in < 20 min | Golden-data performance test per release |
| NFR-PERF-05 | Attendance day recompute after an input change | p95 ≤ 5 min; full-period recompute of 1,000 employees ≤ 10 min | Queue-age metrics; load test |
| NFR-PERF-06 | Notification sending from domain event to provider hand-off | p95 ≤ 60 s | Outbox-to-sent latency metric |
| NFR-PERF-07 | Reports | ≤ 10,000 rows: first page ≤ 5 s p95; larger exports asynchronous, ready ≤ 15 min | Report job metrics |
| NFR-PERF-08 | Mobile app on a 2 GB RAM Android device | Cold start ≤ 3 s; punch screen interactive ≤ 1 s from Home | Device-lab tests per release |
| NFR-PERF-09 | Import dry-run | 5,000 rows ≤ 2 min | Automated test |
| NFR-PERF-10 | Payslip publication after lock | 1,000 PDFs generated and emails queued ≤ 15 min | Job metrics |
8.2 Security (SEC)
| ID | Requirement | Target | Verification |
|---|---|---|---|
| NFR-SEC-01 | Application security baseline | OWASP ASVS Level 2; external penetration test before R1 GA and annually; no open critical or high findings at any GA | Pentest report; ASVS checklist |
| NFR-SEC-02 | Tenant isolation | FORCE ROW LEVEL SECURITY on 100% of tenant-owned tables; cross-tenant tests for 100% of repository methods; app DB role cannot bypass RLS; zero cross-tenant data incidents | CI policy-coverage check; isolation test suite |
| NFR-SEC-03 | Authentication | argon2id hashing; 15-min access tokens; rotating refresh tokens with reuse detection; MFA enforced for admin and payroll roles (100% coverage); zero default or emailed passwords | Automated tests; MFA coverage report |
| NFR-SEC-04 | Encryption | TLS 1.2+ with HSTS; KMS encryption at rest for DB, storage and backups; envelope encryption for Aadhaar, PAN, bank account and face templates | Config scans; key-usage audit |
| NFR-SEC-05 | Secrets | All secrets in AWS Secrets Manager/SSM; rotation ≤ 90 days; zero secrets in images or repositories | Secret scanning in CI; rotation report |
| NFR-SEC-06 | Vulnerability management | SAST, dependency and container scanning on every build; fix SLAs critical ≤ 7 days, high ≤ 30 days, medium ≤ 90 days | Scanner dashboards |
| NFR-SEC-07 | Abuse protection | Per-IP and per-tenant rate limits (default 600 requests/min per user); login lockout per FR-IAM-004; WAF managed rules | WAF and rate-limit metrics |
| NFR-SEC-08 | File handling | Type allow-list, size limits, malware scan before a file becomes downloadable; presigned URLs scoped to the tenant prefix with TTL ≤ 15 min | Automated tests |
| NFR-SEC-09 | Audit integrity | Append-only audit store with a hash chain; any tampering is detectable; platform access to tenant data only through audited break-glass grants (100%) | Daily chain verification job |
| NFR-SEC-10 | Outbound integrations | Webhooks are SSRF-safe (no private IP ranges), HMAC-signed, with retries and DLQ | Security tests |
8.3 Availability and recovery (AVL)
| ID | Requirement | Target | Verification |
|---|---|---|---|
| NFR-AVL-01 | Availability of web and API (monthly) | 99.5% in Stage A; 99.9% in Stage B and for Enterprise SLAs; planned maintenance ≤ 4 h/month, announced 72 h ahead, between 22:00 and 06:00 IST, never in the payroll window (25th–5th) except for emergency fixes | Synthetic monitoring; SLO reports |
| NFR-AVL-02 | Database RPO | ≤ 5 min (PITR); ≤ 24 h for a regional disaster | Quarterly DR drill |
| NFR-AVL-03 | Database RTO | ≤ 1 h for an AZ or cell failure (automatic failover ~2 min); ≤ 8 h for a regional disaster | Quarterly DR drill |
| NFR-AVL-04 | Object storage | RPO ≤ 15 min, RTO ≤ 4 h (versioning, cross-region replication, Object Lock for payroll artefacts) | DR drill |
| NFR-AVL-05 | Single-tenant restore | ≤ 2 h into a staging cell from per-tenant export or PITR extraction | Runbook test twice a year |
| NFR-AVL-06 | Graceful degradation | Mobile punches continue offline during outages and sync later; queues rebuild from the outbox; SMS provider failover; read-only mode for suspended tenants | Chaos test in staging per quarter |
| NFR-AVL-07 | DR drills | Quarterly, with measured RPO/RTO recorded | Drill reports |
8.4 Scalability (SCL)
| ID | Requirement | Target | Verification |
|---|---|---|---|
| NFR-SCL-01 | Pooled cell capacity | Up to 300 tenants or 30,000 active employees per pooled cell within PERF targets; new cell when architecture.md §13 triggers fire | Capacity dashboards |
| NFR-SCL-02 | Tenant size in a pooled cell | Up to 5,000 active employees; larger tenants are offered a dedicated cell | Load test with a 5,000-employee tenant |
| NFR-SCL-03 | Peak patterns | Month-end at 10× average job volume; 30% of a tenant's workforce punching within 10 minutes of shift start | Load tests |
| NFR-SCL-04 | GPS ingest (R3) | ≥ 200 points/s sustained per cell (e.g. 10,000 tracked users at one point per minute with headroom) before extracting the ingest service | Load test before R3 GA |
| NFR-SCL-05 | Fairness | Per-tenant job concurrency quotas so that one tenant's payroll or export cannot delay another tenant's jobs by more than 2× their normal duration | Queue metrics per tenant |
| NFR-SCL-06 | Data growth | Punches and GPS points in monthly partitions; partitions older than retention are dropped, not deleted row by row | Partition maintenance job |
8.5 Observability (OBS)
| ID | Requirement | Target | Verification |
|---|---|---|---|
| NFR-OBS-01 | Telemetry | OpenTelemetry traces, metrics and logs with tenant.id and cell.id on every request and job; errors traced 100%, normal traffic sampled (default 10%) | Telemetry coverage check |
| NFR-OBS-02 | Synthetic checks | Login, punch and leave-apply flows every 5 min per cell | Checkly/Grafana synthetic |
| NFR-OBS-03 | Alerting | SLO burn-rate alerts page on-call within 5 min; runbook link on every alert | Alert reviews |
| NFR-OBS-04 | Business SLOs per tenant | Payroll run success, payslip delivery, punch ingest lag, notification latency visible on the platform console | Console |
| NFR-OBS-05 | PII in telemetry | Zero salary, Aadhaar, PAN or bank values in logs and traces; redaction at the logger | Automated log-scan tests |
| NFR-OBS-06 | Client stability | Mobile crash-free sessions ≥ 99.5%; web error rate < 0.5% of sessions | Sentry |
8.6 Privacy (PRV)
| ID | Requirement | Target | Verification |
|---|---|---|---|
| NFR-PRV-01 | Notice and consent (DPDP Act 2023 and Rules; verify with counsel) | Purpose shown for each personal-data category; recorded consent for face and location; withdrawal effective ≤ 24 h | Privacy review per release |
| NFR-PRV-02 | Location minimisation | Location captured only at punch (ATT) or between punch-in and punch-out (FFM); never outside duty | Automated tests on the mobile app |
| NFR-PRV-03 | Retention | Raw GPS 90 days; punch photos 180 days; payroll records 8 years; face templates deleted ≤ 30 days after exit or consent withdrawal; automated purge with evidence logs | Purge job reports |
| NFR-PRV-04 | Data-subject requests | Fulfilled within the tenant-configured SLA (default 30 days) with a machine-readable export | DSAR register |
| NFR-PRV-05 | Data residency | All tenant data, backups and processing in India regions (ap-south-1, ap-south-2) unless the tenant consents otherwise | Infrastructure review |
| NFR-PRV-06 | Breach handling | Runbook supports notifying affected tenants without undue delay and within 72 h of confirmation (verify DPDP Rules timelines) | Annual tabletop exercise |
| NFR-PRV-07 | Non-production data | No production personal data in dev, UAT or preview; synthetic seed data only | Environment audits |
| NFR-PRV-08 | Fairness | No eligibility rule based on marital status; gender used only for statutory gender-specific benefits | Policy schema review |
8.7 Accessibility (ACC)
| ID | Requirement | Target | Verification |
|---|---|---|---|
| NFR-ACC-01 | Conformance | WCAG 2.1 AA for web and mobile | axe in CI (zero serious/critical violations); manual audit of top 20 flows per release |
| NFR-ACC-02 | Keyboard | All web functions operable by keyboard with visible focus and logical order | Manual test |
| NFR-ACC-03 | Contrast | Text ≥ 4.5:1, large text and UI components ≥ 3:1; tenant brand colours validated on save (FR-ORG-015) | Automated checks |
| NFR-ACC-04 | Touch targets | ≥ 44×44 pt (iOS) and 48×48 dp (Android) | Design review |
| NFR-ACC-05 | Screen readers | VoiceOver and TalkBack labels for all controls; status never conveyed by colour alone (codes and text accompany colours) | Manual test |
| NFR-ACC-06 | Text scaling | Usable at 200% text size / OS large fonts without loss of content | Device tests |
| NFR-ACC-07 | Timeouts | Users are warned before session timeout and can extend; kiosk result screens give ≥ 3 s and no unextendable time limits for input | Manual test |
8.8 Internationalisation and localisation (I18N)
| ID | Requirement | Target | Verification |
|---|---|---|---|
| NFR-I18N-01 | Languages | English in R1; Hindi, Telugu and Tamil for ESS/MSS in R2; 100% of UI strings externalised from R0 | String-extraction lint |
| NFR-I18N-02 | Formats | en-IN number grouping (₹1,23,45,678.00), INR only; dates DD-MMM-YYYY by default; 12/24-hour per tenant | Unit tests |
| NFR-I18N-03 | Time | Stored in UTC; displayed in the location's time zone (default Asia/Kolkata) | Unit tests |
| NFR-I18N-04 | Scripts | Unicode names in Indic scripts accepted and rendered correctly in UI, PDFs (payslips, letters) and exports | PDF rendering tests |
8.9 Maintainability (MNT)
| ID | Requirement | Target | Verification |
|---|---|---|---|
| NFR-MNT-01 | Module boundaries | Zero cross-module table access; lint and dependency-cruiser checks in CI | CI |
| NFR-MNT-02 | Test coverage | Payroll engine golden tests cover every statutory rule in the pack and every lifecycle transition; ≥ 80% line coverage on domain modules; e2e tests for every Must user story | CI reports |
| NFR-MNT-03 | Deployments | Zero-downtime expand/contract migrations; rollback by redeploying the previous image in ≤ 15 min | Release checklist |
| NFR-MNT-04 | Cadence | Weekly releases; payroll-impacting changes frozen 25th–5th except reviewed patches | Release calendar |
| NFR-MNT-05 | API stability | Public /v1 API changes are additive; deprecations announced ≥ 6 months ahead | API changelog |
| NFR-MNT-06 | Self-describing configuration | Every policy setting has a schema, help text and an example; docs generated from the schema | Schema lint |
| NFR-MNT-07 | Statutory agility | A statutory rate change is published as a pack (data, not code) within 1 business day of being verified | Pack publishing log |
| NFR-MNT-08 | Mobile support window | iOS 15+ and Android 9+; minimum app version enforced | API version checks |
8.10 Compliance (CMP)
| ID | Requirement | Target | Verification |
|---|---|---|---|
| NFR-CMP-01 | Statutory file formats | ECR, ESI, PT and LWF outputs pass the current portal or utility validation; re-tested monthly and whenever a format changes | Sample uploads / validators |
| NFR-CMP-02 | No hard-coded rates | Zero statutory rates or thresholds in code; all from the effective-dated statutory pack | Code scan rule |
| NFR-CMP-03 | Payroll record retention | Locked runs, payslips and statutory files retained 8 years with Object Lock (compliance mode) and byte-identical regeneration | Retention audit |
| NFR-CMP-04 | Tax correctness | TDS calculations validated against a reviewed test-case set for each new tax year before the April release; Form 16/24Q (R2) outputs validated with the official validation utility | Test reports |
| NFR-CMP-05 | Statutory registers | Wage, attendance, overtime and leave registers exportable in formats aligned with applicable central/state rules under the Labour Codes (formats to verify) | Should, R2 |
| NFR-CMP-06 | Auditability | Auditors can be given time-boxed read-only access (auditor role) and audit-log exports | Feature test |
| NFR-CMP-07 | Commercial compliance | GST-compliant subscription invoices; data-processing agreement available to every tenant | Finance and legal review |
9. Global permissions model
9.1 Model
- A permission is
{module}.{resource}.{action}(e.g.lve.request.approve). A role is a set of permissions. A role assignment binds a user to a role with a data scope and optional filters and validity dates (architecture.md §6.2). - Every check is the pair (permission, scope):
att.request.approve@TEAM. Scopes:SELF→TEAM(direct + indirect reports via effectivereports_to) →DEPARTMENT→LOCATION→ORG. - Sensitive classes (compensation, bank, Aadhaar, PAN, health, biometric) need an extra
*.sensitive.readpermission and are masked otherwise (FR-IAM-012). - Segregation of duties: never approve your own request; payroll editors cannot approve their own run when SoD is on (FR-PAY-036).
- Entitlements first: a permission has no effect if the tenant's plan does not include the module (FR-PLT-004).
- Tenants clone seeded roles; seeded originals stay read-only (FR-IAM-010).
9.2 Roles × modules (seeded defaults)
Legend: C configure, O operate (create/edit records, run processes), A approve, R read, S self-service only, — none. The scope follows in brackets.
| Module | OWN | HRA | HRM | FNA | PRM | LM | SLA | SLM | EMP | FEX | KIO | INS | AUD |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| PLT (tenant side) | C (ORG) | — | — | R billing | R statutory pack | — | — | — | — | — | — | — | R |
| ORG | C (ORG) | C (ORG) | R (LOC*) | C legal entities | R | R (TEAM) | — | — | R holidays | R holidays | — | — | R (ORG) |
| IAM | C (ORG) | C (ORG, limited) | O invites (LOC*) | — | — | A devices (TEAM) | — | A devices (TEAM) | S | S | — | — | R audit |
| EMP | C/O/A (ORG) | C/O/A (ORG) | O/A (LOC*) | R | R bank/PAN | R (TEAM) | — | R (TEAM) | S | S | — | — | R |
| ATT | C/O/A (ORG) | C/O/A (ORG) | O/A (LOC*) | — | R, lock (ORG) | O/A (TEAM) | — | O/A (TEAM) | S | S | O punch (LOC) | — | R |
| LVE | C/O/A (ORG) | C/O/A (ORG) | O/A (LOC*) | — | R | O/A (TEAM) | — | A (TEAM) | S | S | — | — | R |
| PAY | A (ORG) | — | — | C/A (ORG) | O (ORG) | A advances L1 (TEAM) | — | — | S | S | — | — | R (masked) |
| NTF | C (ORG) | C (ORG) | R logs (LOC*) | C payroll workflows | — | A tasks | — | A tasks | S | S | — | — | — |
| RPT | R (ORG) | R (ORG) | R (LOC*) | R pay (ORG) | R pay (ORG) | R (TEAM) | R CRM (ORG) | R (TEAM) | S | S | — | R own courses | R (ORG) |
| MOB | as roles | as roles | as roles | as roles | as roles | MSS | — | MSS + map | ESS | ESS + Field | Kiosk | — | — |
| CLM (R2) | C/A (ORG) | C (ORG) | — | C/A (ORG) | A/O pay (ORG) | A verify (TEAM) | — | A verify (TEAM) | S | S | — | — | R |
| EXT (R2) | A (ORG) | O/A (ORG) | O/A (LOC*) | — | O F&F (ORG) | A L1 (TEAM) | — | A L1 (TEAM) | S | S | — | — | R |
| ENG (R2) | C/O (ORG) | C/O (ORG) | O (LOC*) | — | — | O optional (TEAM) | — | — | S | S | — | — | R |
| FFM (R3) | C (ORG) | C tracking policy | — | — | — | R (TEAM) | C (ORG) | O/A (TEAM/LOC*) | — | S | — | — | R |
| TSM (R3) | C (ORG) | C (ORG) | — | — | — | A (TEAM) | — | — | S | S | — | — | R |
| LMS (R4) | C (ORG) | C (ORG) | O (LOC*) | — | — | R (TEAM) | — | — | S | S | — | C/O own courses | R |
Platform roles (platform_admin, support_engineer, billing_admin, release_manager) act only in the control plane; their access to tenant data is through break-glass grants (FR-PLT-012).
9.3 Scope resolution rules
- TEAM is computed from the effective
reports_tohierarchy on the date of the record (a manager sees a former report's days from when they were in the team). - LOCATION and DEPARTMENT scopes use the employee's effective job assignment on the record date.
- Multiple role assignments are unioned per permission; the widest scope wins for that permission only.
- Lists, reports, exports, search and API responses apply the same scope filter; there is no "export bypass".
10. Global UI/UX requirements
10.1 Design system
| Element | Requirement |
|---|---|
| Foundation | Shared design tokens in packages/ui (colour, type, spacing, radius, elevation) used by web (Tailwind 4 + shadcn/ui) and mobile (Expo) (CONVENTIONS.md §6) |
| Components | Data table (sort, filter, column chooser, bulk select, sticky header), filter bar (§7.9), form generator from policy schemas, stepper, timeline (effective-dated history), status chip, approval card, money field, date-range picker aware of week-offs and holidays, file uploader with camera, empty state, toast, confirmation dialog with consequence text |
| Status semantics | One colour + text label per state family across modules: neutral (Draft), info (Submitted / In approval), success (Approved / Paid / Present), warning (Pending action / Late / Flagged), danger (Rejected / Absent / Failed), muted (Cancelled / Withdrawn). Attendance codes always show the code letters, not colour alone |
| Numbers | Right-aligned money with en-IN grouping and ₹; tabular numerals in grids; decimals for days shown as halves (14.5) |
| Explainability | Computed values (day status, balance, payslip line, TDS) have a "How calculated" affordance that opens inputs, policy version and formula |
| Help | Contextual help on every setting, generated from its schema (description, example, effect); links to the documentation site |
| Copy | Plain, specific, action-oriented; errors say what happened, why and what to do ("You are 600 m from Plant 1. Move closer or ask your manager") |
10.2 Navigation per role
| Persona | Web (left navigation) | Mobile (bottom tabs) |
|---|---|---|
employee | Home, Attendance, Leave, Pay, Claims (R2), Learning (R4), Me | Home, Attendance, Leave, Pay, Me (Inbox via header) |
line_manager | + Team (today, calendar, roster), Approvals | + Team tab; Inbox badge |
hr_manager | People, Attendance workbench, Leave, Onboarding, Exits (R2), Reports, Inbox | ESS + Team + approvals |
hr_admin | + Settings (Organisation, Time, Leave, Notifications, Security) | ESS |
payroll_manager / finance_admin | Payroll workbench, Compensation, Tax, Statutory, Reports, Settings → Pay | ESS + run approvals |
org_owner | Dashboard, all modules, Subscription, Security, Support access | Dashboard, approvals (payroll), ESS |
field_executive | (web optional) Accounts, Pipeline | Home, Field, Attendance, Leave, Me |
sales_manager | Map, Pipeline, Travel, Team, Reports | Team, Map, Approvals |
kiosk_operator | — | Kiosk only |
auditor | Read-only dashboard, Reports, Audit log | — |
Global elements: tenant logo, global search (people, requests, runs within scope), notifications bell, help, profile menu with language and theme. A user with several roles sees a merged menu, never a role switcher.
10.3 Responsive behaviour
| Breakpoint | Behaviour |
|---|---|
| ≥ 1280 px (desktop) | Full admin workbenches, multi-column forms, side panels for detail |
| 768–1279 px (tablet) | Collapsible navigation; grids scroll horizontally with frozen first column; all admin tasks usable |
| < 768 px (mobile web) | ESS and approvals fully usable (for users without the app); admin configuration shows a "best on a larger screen" note but remains functional; candidate pre-onboarding is mobile-web-first |
10.4 Accessibility
WCAG 2.1 AA (NFR-ACC-01..07): semantic HTML and ARIA where needed, keyboard paths, focus management in dialogs, labelled form fields with inline errors linked to inputs, charts with data-table alternatives, captions or transcripts for LMS videos (R4).
10.5 Localisation
All strings in resource bundles; English in R1; Hindi, Telugu, Tamil in R2 for ESS/MSS; user-selectable language with tenant default; notification templates per locale; tenant label overrides (FR-ORG-017, R2); layouts tolerate 40% text expansion.
10.6 Offline behaviour on mobile
| Capability | Offline behaviour |
|---|---|
| Punch (personal device) | Queued with device time + elapsed-time proof; synced ≤ 72 h; flagged offline (FR-ATT-005) |
| Kiosk punch (R2) | PIN punches with photo queued; face verification on sync where possible (FR-MOB-016) |
| Field visits and activities (R3) | Queued and synced; GPS buffered up to 24 h (FR-FFM-014) |
| Read data | Last 3 payslips, balances, holidays, current-month calendar cached with "last updated" |
| Requests and approvals | Need connectivity; drafts saved locally; clear message "You're offline. We'll keep your draft." |
| Sensitive cache | Encrypted at rest on device; cleared on logout or user switch |
10.7 Kiosk mode (R2)
Location-scoped enrolment; full-screen camera with guide oval and live clock; face + liveness or code + PIN; large confirmation (name, photo, In/Out, time) for 3 s; no access to other screens; admin PIN to exit; offline queue; device health heartbeat; high-contrast and audio feedback options (FR-MOB-012..017).
10.8 Standard states
- Empty: explain what the area is for and give the primary action.
- Loading: skeletons for lists and cards; no spinner-only pages over 1 s.
- Errors: inline for fields; banner for page-level problems with retry; a support reference code on unexpected errors.
- Permission denied: say which permission or scope is missing and who can grant it.
- Locked data: lock icon with who locked it and when; actions disabled with a reason.
11. Integrations
Aligned with architecture.md §16. Every external provider sits behind an interface so it can be replaced without changing modules. All integrations are tenant-configurable, use India-region processing where available, and fail safely.
| Integration | Purpose | Pattern | Release | Requirements | Failure behaviour |
|---|---|---|---|---|---|
| Biometric devices (ZKTeco, eSSL and similar) | Punch capture | R1: CSV/Excel upload and authenticated punch-batch API with device-user mapping. R2: ADMS-style push gateway to ingest with per-device secrets, plus a Windows/Linux sync agent for pull-only devices | R1 / R2 | FR-ATT-006, -007, -008 | Idempotent re-delivery; unmapped punches queued; device-offline alerts |
| Face verification | Kiosk 1:N and personal 1:1 verification with liveness | FaceProvider.enroll/verify/liveness; first implementation AWS Rekognition (ap-south-1) or an on-device SDK; consent-gated | R2 | FR-MOB-013..015, FR-IAM-018 | Fallback to PIN or selfie + manager review; no punch lost |
| Maps and geocoding | Location picker, address lookup, distance, map views | Provider interface; Google Maps Platform or Mappls; snap-to-road for kms (R3) | R1 (geocode) / R3 (tracking) | FR-ORG-004, FR-ATT-003, FR-FFM-004/005 | Geo-fence checks are computed locally (no provider needed); maps degrade to coordinates |
| Transactional email | NTF adapter for Amazon SES (ap-south-1); bounce and complaint webhooks | R0 | FR-NTF-002, -006 | Retries; bounces mark the address and alert HR | |
| SMS | OTP, activation, critical alerts | NTF adapters for MSG91 and Gupshup with DLT-registered templates; provider failover | R1 | FR-NTF-002, -003 | Failover to the secondary provider |
| Optional notifications (metered add-on) | Meta WhatsApp Cloud API through a BSP; approved templates; recorded opt-in | R1 (Should) | FR-NTF-002, -003 | Falls back to SMS/push | |
| Push | Mobile notifications | Expo push → FCM/APNs | R0 | FR-NTF-002, FR-MOB-006 | In-app inbox always holds the message |
| Statutory portals (EPFO, ESIC, state PT/LWF, income-tax) | Compliance filing | File generation only (ECR, ESIC upload, PT/LWF data, 24Q data, Form 16); no portal automation (legal and fragility risk) | R1 (ECR/ESI/PT/LWF) / R2 (24Q, Form 16) | FR-PAY-045..048, -055, -056 | Validation before generation; versioned revised files |
| Banks | Salary and reimbursement payments | Bank-file adapters (generic NEFT/RTGS CSV + bank-specific formats); response/UTR import; host-to-host APIs later | R1 (files) / post-R4 (H2H) | FR-PAY-044, -038 | Control totals and checksums; failed transfers re-issued |
| Accounting | Payroll journal | R2: CSV and Tally XML export with ledger mapping. R4: API connectors (Zoho Books, ERPs) | R2 / R4 | FR-PAY-058, -059 | Export is regenerable from the locked snapshot |
| SSO | Workforce identity | OIDC (Google Workspace, Microsoft Entra ID) on Standard+; SAML 2.0 on Enterprise | R1 / R2 | FR-IAM-007, -008 | Owner break-glass password login |
| Public API and webhooks | Customer integrations (HRIS sync, BI, access control) | REST /v1 (OpenAPI 3.1), OAuth2 client credentials per tenant, per-client scopes and rate limits; signed webhooks (HMAC SHA-256) with retries and DLQ | R2 | FR-IAM-023, FR-NTF-016 | Replay from DLQ; 6-month deprecation policy |
| Calendar | Leave as out-of-office events | Google/Microsoft calendar APIs, per-user opt-in | R3 | FR-LVE-027 | Best-effort; no impact on leave status |
| Billing | Subscriptions and invoices | Razorpay Subscriptions (control plane) | R1 | FR-PLT-011 | Grace period and dunning; payroll never blocked in the window |
| Identity verification (optional) | PAN/bank verification | Third-party verification APIs with consent | R3 (Could) | FR-EMP-020 | Manual verification remains possible |
Public API scope (R2, Must): employees and job assignments (read/write), org masters (read/write), attendance punches (write) and days (read), leave requests and balances (read; create with workflow), payroll run summaries and payslip metadata (read, sensitive scopes separately granted), claims (read). No API writes to locked payroll data.
12. Notifications and automation catalogue
Channels: IA in-app, E email, P push, S SMS, W WhatsApp (add-on). "Configurable" means the tenant can edit the template and enable/disable the event; Mandatory events cannot be disabled (the template can still be edited).
| Event | Template key | Default channels | Recipients | Configurable? | Release |
|---|---|---|---|---|---|
| Tenant trial ending (7/3/1 days) | plt.trial.ending | E, IA | Owner | No (platform) | R1 |
| Payment failed / suspension notice | plt.billing.failed | E, IA | Owner, billing contact | No | R1 |
| Support access requested / started / ended | plt.support.access | E, IA | Owner | Mandatory | R0 |
| Statutory pack published (affects tenant) | plt.statpack.published | IA, E | PRM, FNA | Yes (channels) | R0 |
| Tenant export ready | plt.export.ready | E | Requester | No | R1 |
| Import completed / failed | org.import.done | IA, E | Uploader | Yes | R0 |
| Policy version activated | org.policy.activated | IA | HRA, FNA | Yes | R0 |
| Holiday calendar changed | org.holiday.changed | IA, P | Affected employees | Yes (off by default) | R1 |
| Account activation link | iam.invite | E or S (W optional) | New user | Mandatory | R0 |
| Activation reminder (48 h) | iam.invite.reminder | E/S | User, HR (cc) | Yes | R1 |
| Password changed / MFA reset / new-device login | iam.security.* | E, P | User | Mandatory | R0/R1 |
| Device pending approval | iam.device.pending | P, IA | Line manager / HR | Yes | R1 |
| Consent withdrawn | iam.consent.withdrawn | IA, E | HR | Mandatory | R1 |
| DSAR received / due in 5 days | iam.dsar.* | IA, E | HRA, Owner | Mandatory | R1 |
| Pre-onboarding link / reminders (day 2, day 5) | emp.preboarding.* | E, S | Candidate | Yes | R1 |
| Pre-onboarding submitted / section reopened | emp.preboarding.submitted / .reopened | IA, E / E, S | HR / Candidate | Yes | R1 |
| Document approved / rejected / expiring (30 days) | emp.document.* | IA, P, E | Employee (and HR for expiry) | Yes | R1 |
| Checklist task assigned / overdue | emp.task.* | IA, E | Task owner | Yes | R1 |
| Induction invite / changed / cancelled | emp.induction.* | E (with .ics), IA | Attendees | Yes | R1 |
| Probation ending (15 days) | emp.probation.due | IA, E | Line manager, HR | Yes | R1 |
| Profile change request decided | emp.change.decided | IA, P | Employee | Yes | R1 |
| Punch reminder (not punched by shift start + grace) | att.punch.reminder | P | Employee | Yes (user opt-out) | R1 |
| Missed punch-out reminder | att.punchout.reminder | P | Employee | Yes | R1 |
| Attendance alerts digest | att.alerts.digest | P, IA | Employee | Yes | R1 |
| Attendance / regularization / permission / shift-change request submitted | att.request.submitted | IA, P | Approver | Yes | R1 |
| Request decided | att.request.decided | IA, P | Employee | Yes | R1 |
| Swap consent requested | att.swap.consent | P, IA | Counterpart employee | Mandatory | R1 |
| OT claims pending (daily digest) | att.ot.pending | IA, E | Line manager | Yes | R1 |
| Roster published / changed | att.roster.changed | P, IA | Affected employees | Yes | R1 |
| Device offline | att.device.offline | E, IA | HR of location | Yes | R2 |
| Period close reminder / locked | att.period.* | IA, E | HRM, PRM | Yes | R1 |
| Leave submitted / decided / cancellation requested / decided | lve.request.* | IA, P (E optional) | Approver / employee | Yes | R1 |
| Comp-off expiring (7 days) | lve.compoff.expiring | P, IA | Employee | Yes | R1 |
| Year-end summary | lve.yearend.summary | IA, E | Employee | Yes | R1 |
| Leave document pending after return | lve.document.pending | P, IA | Employee, HR | Yes | R1 |
| Approval task assigned | ntf.task.assigned | IA, P | Approver | Mandatory (in-app) | R0 |
| Approval reminder / escalated | ntf.task.reminder / .escalated | IA, P, E | Approver, escalation target | Yes (timings) | R1 |
| Delegation started / ended | ntf.delegation.* | IA, E | Delegate, delegator | Yes | R1 |
| Approver changed (tasks reassigned) | ntf.task.reassigned | IA | Old and new approver | Yes | R0 |
| Payroll run calculated with warnings | pay.run.calculated | IA, E | PRM | Yes | R1 |
| Payroll approval requested / approved / sent back | pay.run.approval.* | IA, P, E | Approver / PRM | Mandatory | R1 |
| Payroll locked (files ready) | pay.run.locked | IA, E | PRM, FNA, Owner | Yes | R1 |
| Payslip published | pay.payslip.published | P, E (password-protected PDF), IA | Employee | Mandatory | R1 |
| Payment failed for employee | pay.payment.failed | IA, E | PRM | Mandatory | R1 |
| Declaration window opens / closes in 7 and 1 days | pay.itd.window | P, E, IA | Employees | Yes | R1 |
| Proof deadline / proof verified / rejected | pay.proof.* | P, E, IA | Employee | Yes | R1 |
| Advance / loan decided, disbursed, EMI paused | pay.advance.* | IA, P | Employee | Yes | R1 |
| Statutory due-date reminder (EPF, ESI, TDS, PT, LWF) | pay.statutory.due | IA, E | PRM, FNA | Yes (dates from pack) | R1 |
| Form 16 published | pay.form16.published | E, P, IA | Employee (incl. alumni) | Yes | R2 |
| Export ready / scheduled report delivered | rpt.export.ready / rpt.schedule.delivered | IA, E | Requester / recipients | Yes | R1 |
| Forced app upgrade | mob.upgrade.required | P | Users on old versions | No | R1 |
| Claim submitted / verified / approved / paid / rejected | clm.claim.* | IA, P | Verifier / finance / employee | Yes | R2 |
| Resignation submitted / decided; LWD reminders; clearance overdue; F&F ready / paid; letters issued | ext.* | IA, E, P | Employee, LM, HR, clearance owners, PRM | Yes | R2 |
| Announcement published / acknowledgement reminder | eng.announcement.* | IA, P (E optional) | Target audience | Yes | R2 |
| Recognition received; birthday / anniversary | eng.recognition.* | IA, P | Recipient (team optional) | Yes | R2 |
| Follow-up due / exceeded; lead ageing red; tracking stopped on duty; travel pending | ffm.* | P, IA | Field executive / manager | Yes | R3 |
| Timesheet reminder / defaulter / decided | tsm.* | P, E, IA | Employee / approver | Yes | R3 |
| Course assigned / due / overdue / certificate issued | lms.* | IA, E, P | Learner, LM (overdue) | Yes | R4 |
Automation jobs (scheduled, idempotent): leave accrual (daily check, posts per frequency), comp-off expiry (daily), attendance auto-resolution at period close, document expiry scan (daily), probation due scan (daily), absconding detection (daily, R2), punch reminder (per shift), statutory due-date reminders (per pack calendar), SLA escalation (every 15 min), retention purges (daily), metering snapshot (daily, control plane), scheduled reports (cron per schedule).
13. Reporting and analytics catalogue
Filters use the standard bar (Legal entity → Location → Department → Manager → Employee → Period) unless noted. Exports: X Excel, C CSV, P PDF. Persona scope follows §9.
| # | Report | Module | Personas | Key filters | Export | Release |
|---|---|---|---|---|---|---|
| 1 | Owner dashboard (headcount, joiners/leavers, attendance today, payroll cost trend, approvals pending, compliance due) | RPT | OWN | Legal entity, location | P | R1 |
| 2 | Org widgets: employees by location, by department by location, attendance by work type, on leave by department, shift-wise headcount, payroll by department by month | RPT | OWN, HRA, HRM | Location, period | X, P | R1 |
| 3 | Employee master (column chooser incl. custom fields) | EMP | HRA, HRM, AUD | Status, type, standard bar | X, C | R1 |
| 4 | Joiners and leavers | EMP | HRM, OWN | Period | X, P | R1 |
| 5 | Probation due / confirmations | EMP | HRM, LM | Due window | X | R1 |
| 6 | Document compliance (missing, pending, expired) | EMP | HRM | Document type, status | X | R1 |
| 7 | Job change history (transfers, promotions) | EMP | HRM, AUD | Change reason, period | X | R1 |
| 8 | Monthly attendance register (code grid + counts) | ATT | HRM, LM, PRM, AUD | Period, pay group | X, P | R1 |
| 9 | Daily attendance / current day (with punch photos) | ATT | HRM, LM | Date, status | X, P | R1 |
| 10 | Punch detail (all punches, source, location, fence result) | ATT | HRM, AUD | Date range, source, flag | X, C | R1 |
| 11 | Late and early-go | ATT | HRM, LM | Period, threshold | X | R1 |
| 12 | Missed punch | ATT | HRM, LM | Period | X | R1 |
| 13 | Overtime (claimed vs approved, by multiplier, cost estimate) | ATT | HRM, LM, PRM | Period, status | X | R1 |
| 14 | Extra days and penalties | ATT | HRM, PRM | Period | X | R1 |
| 15 | Shift-wise attendance and coverage | ATT | HRM, LM | Date, shift | X | R1 |
| 16 | Out-of-fence and anomaly review | ATT | HRM, LM | Flag type, period | X | R1 |
| 17 | Payable-days summary | ATT | PRM, HRM | Period, pay group | X, C | R1 |
| 18 | Device health and unmapped punches | ATT | HRM | Device, location | X | R2 |
| 19 | Leave balance (as on date) | LVE | HRM, LM, PRM | Date, leave type | X | R1 |
| 20 | Leave register (employee-, date-, type-, designation-wise) | LVE | HRM, LM | Period, type, status | X, P | R1 |
| 21 | Leave summary (worked vs leave days) | LVE | HRM, LM | Period | X | R1 |
| 22 | Comp-off register (credited, availed, expired) | LVE | HRM, LM | Period | X | R1 |
| 23 | Leave payroll bridge (approved leave, LOP, absent) | LVE | PRM, HRM | Period, pay group | X | R1 |
| 24 | Year-end carry-forward / lapse / encashment | LVE | HRM, PRM | Cycle | X | R1 |
| 25 | Salary register (payroll register) | PAY | PRM, FNA, OWN, AUD | Run, pay group | X, P | R1 |
| 26 | Bank-wise salary summary | PAY | PRM, FNA | Run, debit bank | X, P | R1 |
| 27 | EPF report + ECR file | PAY | PRM, FNA, AUD | Period, establishment | X, ECR text | R1 |
| 28 | ESI report + upload file | PAY | PRM, FNA | Period, employer code | X | R1 |
| 29 | PT report by state | PAY | PRM, FNA | Period, state | X, P | R1 |
| 30 | LWF report by state | PAY | PRM, FNA | Period, state | X | R1 |
| 31 | TDS deduction register and projection | PAY | PRM, FNA | Tax year, month | X | R1 |
| 32 | IT declarations and proofs status | PAY | PRM | Tax year, status | X | R1 |
| 33 | CTC and compensation history | PAY | FNA, PRM, OWN | Effective date, structure | X | R1 |
| 34 | Payroll cost by department / location / cost centre / legal entity | PAY | OWN, FNA | Period range | X, P | R1 |
| 35 | Variance report (run vs previous) | PAY | PRM, OWN | Run, threshold | X | R1 |
| 36 | Arrears report | PAY | PRM | Period, source month | X | R1 |
| 37 | Advance and loan recovery | PAY | PRM, FNA | Status, period | X | R1 |
| 38 | Held salaries | PAY | PRM | Run | X | R1 |
| 39 | Statutory payment register (challans) | PAY | PRM, FNA, AUD | Period, type | X | R1 |
| 40 | Form 16 status / 24Q validation | PAY | PRM | Tax year, quarter | X | R2 |
| 41 | Approval turnaround and SLA breaches | NTF | OWN, HRA | Request type, approver | X | R1 |
| 42 | Notification delivery and usage (SMS/WhatsApp) | NTF | HRA, OWN | Channel, status | X | R1 |
| 43 | Users, roles, MFA coverage, inactive users, audit export | IAM | OWN, HRA, AUD | Role, status | X, C | R0/R1 |
| 44 | DSAR register | IAM | HRA, OWN | Status | X | R1 |
| 45 | App adoption (DAU/MAU by role, versions) | MOB | OWN, HRA | Period | X | R1 |
| 46 | Claims register; claims by category; settlement ratio; policy exceptions | CLM | PRM, FNA, LM | Period, status, category | X, P | R2 |
| 47 | Attrition (by reason, tenure, department); notice compliance; clearance ageing; F&F turnaround | EXT | HRM, OWN | Period, type | X, P | R2 |
| 48 | Announcement reach and acknowledgements; recognition counts per type per employee | ENG | HRM, OWN | Announcement, period | X | R2 |
| 49 | Employee activity, tracking log, employee summary, visits vs plan, geo-verification exceptions | FFM | SLM, OWN | Date range, executive | X, P | R3 |
| 50 | Pipeline by stage and age; win rate; collections; travel and mileage cost | FFM | SLM, SLA, OWN | Period, stage | X | R3 |
| 51 | Timesheet summary, effort variance, bench, billable hours, defaulters | TSM | LM, OWN | Project, client, week | X, C | R3 |
| 52 | Course completion, overdue mandatory training, certificates | LMS | HRM, LM, INS | Course, due status | X | R4 |
| 53 | KPI pack: attrition rate, absenteeism %, late %, OT cost, payroll cost per employee, leave utilisation | RPT | OWN, HRA | Period | X, P | R1 (Should) |
| 54 | Custom reports and advanced analytics | RPT | OWN, HRA, FNA | Builder-defined | X, C | R4 |
14. Assumptions, dependencies and open questions
| # | Item | Type | Impact / handling |
|---|---|---|---|
| 1 | Statutory values (EPF, ESI, PT, LWF, TDS, gratuity, minimum wages) and file formats are verified by a payroll/compliance expert before each release | Dependency | Blocks R1 GA; owned by the compliance SME; delivered as statutory pack versions |
| 2 | Income-tax Act, 2025 section/form renumbering and Labour Codes rules (central and state) are mapped before R1 GA | Dependency | Affects TDS labels, Form 16/24Q (R2), wage-definition check (FR-PAY-015) |
| 3 | DPDP Act 2023 and Rules obligations (notice, consent, DSAR timelines, breach notification) are confirmed by counsel | Dependency | Affects FR-IAM-018/019, NFR-PRV-* |
| 4 | Three pilot tenants (one office, one factory with shifts, one multi-state) run one parallel payroll each before GA | Assumption | MVP acceptance (§16.2) |
| 5 | Bank-specific file formats for the first 3 banks are obtained from pilot customers' banks | Dependency | FR-PAY-044 |
| 6 | Biometric devices at pilots can export CSV or call an API in R1; push gateway arrives in R2 | Assumption | FR-ATT-007/008 |
| 7 | Spryple internals (permission granularity, multi-level approvals, TDS computation, device protocols, face provider, GPS sampling, pricing, multi-company, run locking, API) are unknown (research §20) | Open question | Our design does not depend on them; parity claims are limited to documented behaviour |
| 8 | Face verification provider choice (cloud vs on-device) and cost per verification | Open question | Decide before R2 build start; affects add-on pricing |
| 9 | Maps provider (Google vs Mappls) for R3 tracking costs | Open question | Decide before R3; geo-fence checks in R1 do not need a provider |
| 10 | Payslip default password pattern acceptable to customers (PAN + DOB) | Open question | Configurable; validate with pilots |
15. Future enhancements (post-R4)
Value and effort are relative (H/M/L). These are candidates, not commitments; each needs a business case in brd.md before planning.
| Enhancement | Description | Value | Effort | Notes (honest assessment) |
|---|---|---|---|---|
| Recruitment / ATS | Job requisitions, careers page, candidate pipeline, interviews, offers with e-sign, hand-off to EMP pre-onboarding | M | H | Valuable for growing SMEs but a crowded market (many cheap ATS tools). Integration with existing job portals is the hard part. Start with an offer-letter + hand-off flow, not a full ATS. |
| Performance management | Goals/OKRs, review cycles, 360 feedback, ratings feeding increments | M | H | Frequently requested, rarely used well by SMEs. A light "goals + annual review" with a link to bulk salary revision (FR-PAY-017) gives most of the value. |
| Surveys and eNPS | Pulse surveys, anonymous feedback, exit-interview analytics | M | L–M | Cheap to build on ENG and NTF; anonymity guarantees need care for small teams (minimum response thresholds). |
| Asset management | Asset register, assignment to employees, return at exit, depreciation export | M | M | Spryple lists it as a solution [Observed] (research §21.1). Fits EXT clearance well; keep it simple (no procurement). |
| Helpdesk / HR cases | Employee queries with categories, SLAs, knowledge base | M | M | Reduces HR load in 200+ employee tenants; could reuse the NTF workflow engine. |
| AI assistants | (a) Policy Q&A for employees grounded only in the tenant's own policies and their resolved settings; (b) payroll variance explanations in plain language; (c) attendance anomaly detection; (d) receipt OCR for claims | M–H | M | Highest-value use is explanation, not automation: "why is my LOP 1.5?" and "why did net pay drop?" must cite the computed inputs (P8). Requires strict tenant isolation of context, no training on tenant data, opt-in per tenant, and human approval for any action. Payroll numbers must never be produced by a model. |
| Earned wage access | Employees draw part of earned salary mid-month, recovered in payroll | M | M | Needs a regulated lending/NBFC partner; compliance and credit risk sit with the partner. Advance salary (FR-PAY-023) covers the basic need. |
| Host-to-host bank payments | Direct salary disbursement via bank APIs | M | M–H | Removes manual uploads but each bank differs; demand from larger tenants only. |
| CRM quotes, orders and product catalogue | Extend FFM for distribution businesses | M | H | Risks turning Spyrl into a full CRM; prefer integrations with existing order systems. |
| SCIM provisioning and FIDO2 keys | Enterprise identity lifecycle and phishing-resistant MFA | L–M | M | Needed only for Enterprise deals; SAML (R2) comes first. |
| Multi-country payroll | Payroll outside India | L | H | Out of scope for the SME India focus; would need partners. |
16. Traceability and MVP acceptance
16.1 Traceability matrix (module level)
BRD links are at module level (BR-
| Module | PRD section | FR range (count) | US range (count) | BRD | Research | First release |
|---|---|---|---|---|---|---|
| PLT | §7.1 | FR-PLT-001..022 (22) | US-PLT-01..05 (5) | BR-PLT-* | §3.2, §19, §21.1 | R0 |
| ORG | §7.2 | FR-ORG-001..018 (18) | US-ORG-01..05 (5) | BR-ORG-* | §4, SP-ORG-* | R0 |
| IAM | §7.3 | FR-IAM-001..025 (25) | US-IAM-01..06 (6) | BR-IAM-* | §4, SP-IAM-*, §21.2 | R0 |
| EMP | §7.4 | FR-EMP-001..022 (22) | US-EMP-01..07 (7) | BR-EMP-* | §4, SP-EMP-*, §21.2 | R1 |
| ATT | §7.5 | FR-ATT-001..040 (40) | US-ATT-01..11 (11) | BR-ATT-* | §5, SP-ATT-*, §21.3 | R1 |
| LVE | §7.6 | FR-LVE-001..028 (28) | US-LVE-01..08 (8) | BR-LVE-* | §6, SP-LVE-*, §21.4 | R1 |
| PAY | §7.7 | FR-PAY-001..065 (65) | US-PAY-01..11 (11) | BR-PAY-* | §7, SP-PAY-*, §21.5 | R1 |
| NTF | §7.8 | FR-NTF-001..018 (18) | US-NTF-01..05 (5) | BR-NTF-* | SP-X-02/03/04/09 | R0 |
| RPT | §7.9 | FR-RPT-001..013 (13) | US-RPT-01..04 (4) | BR-RPT-* | §14, SP-X-05/06 | R1 |
| MOB | §7.10 | FR-MOB-001..019 (19) | US-MOB-01..05 (5) | BR-MOB-* | §15, §21.1, §21.3 | R1 |
| CLM | §7.11 | FR-CLM-001..014 (14) | US-CLM-01..04 (4) | BR-CLM-* | §9, §21.6 | R2 |
| EXT | §7.12 | FR-EXT-001..012 (12) | US-EXT-01..04 (4) | BR-EXT-* | §8 | R2 |
| ENG | §7.13 | FR-ENG-001..008 (8) | US-ENG-01..03 (3) | BR-ENG-* | §13, §21.9 | R2 |
| FFM | §7.14 | FR-FFM-001..017 (17) | US-FFM-01..05 (5) | BR-FFM-* | §11, §21.7 | R3 |
| TSM | §7.15 | FR-TSM-001..011 (11) | US-TSM-01..03 (3) | BR-TSM-* | §10, §21.8 | R3 |
| LMS | §7.16 | FR-LMS-001..010 (10) | US-LMS-01..03 (3) | BR-LMS-* | §12, §21.10 | R4 |
| Total | 342 FRs | 89 user stories |
NFRs: PERF 10, SEC 10, AVL 7, SCL 6, OBS 6, PRV 8, ACC 7, I18N 4, MNT 8, CMP 7 (73 NFRs, §8).
16.2 MVP (R0 + R1) acceptance checklist
R1 GA requires every item below to pass on the production Stage A cell, demonstrated with three pilot tenants (§14 item 4).
Platform, security and data
- A new tenant is provisioned self-serve in < 2 minutes with seeded roles, templates and the current statutory pack (FR-PLT-002, FR-PLT-009).
- Isolation suite green: RLS on 100% of tenant tables; tenant B cannot read tenant A through any API, report, export or search (NFR-SEC-02).
- No default or emailed passwords; activation by invite only; MFA enforced on all admin and payroll accounts (FR-IAM-001, FR-IAM-006, NFR-SEC-03).
- Seeded roles and one custom role behave per §9, including TEAM scope after a manager change (FR-IAM-010/011, FR-NTF-008).
- Audit log records every write, approval, sensitive reveal and support access; tenant can view and export it (FR-IAM-016, FR-PLT-012).
- Consent records exist for location capture; withdrawal disables mobile punch with a working alternative (FR-IAM-018).
- External pentest has no open critical/high findings; OWASP ASVS L2 checklist complete (NFR-SEC-01).
- Backups, PITR and one DR drill completed with measured RPO ≤ 5 min and RTO ≤ 1 h (NFR-AVL-02/03/07).
- SLO dashboards, synthetic checks and on-call alerting live (NFR-OBS-01..03).
Set-up and people
- Setup wizard takes a tenant from empty to payroll-ready, with the readiness score showing no blocking items (FR-ORG-014).
- Employees, opening leave balances, compensation and YTD figures import with dry-run and no duplicates on re-upload (FR-ORG-012, FR-LVE-018).
- New hire → pre-onboarding → activation creates the code, user invite, policies and checklist automatically (FR-EMP-001..005, -010).
- A back-dated promotion changes policies and approver from its effective date and produces arrears for locked months (FR-EMP-006, FR-PAY-040).
Attendance and leave
- Mobile selfie punch inside and outside a 200 m fence behaves per
geofence.mode; offline punches sync with drift flags (FR-ATT-002/003/005). - Biometric CSV/API import is idempotent and handles unmapped users (FR-ATT-007).
- Day engine produces all codes in §7.5.4 correctly on a golden data set (incl. night shift, half days, WP/HP, week-off penalty, late deduction) and recomputes within 5 min of a change (FR-ATT-019..022, -029, -030, NFR-PERF-05).
- Rotations, week-off patterns, shift change and swap with consent work end to end (FR-ATT-013/016/017).
- Regularization, permissions and attendance requests flow through approval, including on-behalf (FR-ATT-023..026).
- OT is paid only after approval, with rounding, caps and multipliers (FR-ATT-027/028).
- Period close shows exceptions, locks, and post-lock corrections become next-period adjustments (FR-ATT-032..034).
- Leave types created from templates and one custom type; accrual, pro-rata, sandwich, cancellation, comp-off expiry and year-end run produce correct ledger entries (FR-LVE-001..016).
- An effective-dated leave policy change applies to existing employees with a previewed adjustment (FR-LVE-024).
Payroll and compliance
- Structure template + effective-dated compensation compute correct monthly breakups, including the balancing component check (FR-PAY-001..004).
- A full run passes through Draft → Calculated → Reviewed → Approved → Locked → Paid with SoD enforced and every transition audited (FR-PAY-028..038).
- A reversal and a correction off-cycle run work and regenerate revised statutory files (FR-PAY-039, -041).
- 1,000-employee payroll calculates in < 5 minutes (NFR-PERF-04).
- EPF, ESI, PT, LWF and TDS match the compliance SME's expected results on the golden test set for every pilot state (FR-PAY-007..010, -050; NFR-CMP-04).
- Employees choose a tax regime, declare investments, upload proofs, and TDS reflects verified amounts after the deadline (FR-PAY-051..053).
- ECR, ESI, PT and LWF files pass portal/utility validation; bank files for the pilot banks are accepted by the banks (FR-PAY-044..048, NFR-CMP-01).
- Payslips are published in the app and by password-protected email, and a locked run regenerates byte-identical artefacts (FR-PAY-042/043/065).
- Advance salary request → approval → disbursement → recovery ledger works across 4 months (FR-PAY-023/025).
- Each pilot's parallel run matches its legacy payroll, with every difference explained and signed off.
Experience
- Every R1 employee and line-manager story is doable in the mobile app on a 2 GB Android device and on iOS (FR-MOB-001..009, NFR-PERF-08).
- Unified approvals inbox handles all R1 request types with bulk actions, delegation and escalation (FR-NTF-007..011).
- Standard reports in §13 marked R1 are available with scope filtering and governed exports (FR-RPT-001..006).
- WCAG 2.1 AA automated checks pass with zero serious/critical issues; manual audit of top flows done (NFR-ACC-01).
17. Glossary
| Term | Meaning |
|---|---|
| Applicability rule | Condition (location, department, designation, grade, employment type, named list) deciding which policy version applies to an employee |
| Arrears | Difference paid in a later run for a back-dated change to a locked period |
| CTC | Cost to company: annual total of salary and employer contributions |
| Day code | Attendance status of an employee-day (P, A, HD, L, HL, W, H, WP, HP, OD, MP, NE) |
| ECR | Electronic Challan cum Return file for EPFO |
| F&F | Full-and-final settlement at exit |
| LOP | Loss of pay (unpaid day) |
| LWD | Last working day |
| LWF | Labour Welfare Fund (state-specific) |
| OD | On duty / remote work approved through an attendance request |
| Pay group | Employees processed together: one legal entity and one pay schedule |
| PEPM | Per employee per month (pricing metric) |
| PT | Professional Tax (state-specific) |
| Sandwich rule | Counting week-offs/holidays between or adjacent to leave days as leave |
| SoD | Segregation of duties |
| Statutory pack | Centrally published, versioned, effective-dated statutory reference data |
| Structure template | Reusable definition of salary components and calculations, independent of an employee's CTC |
| TDS | Tax deducted at source on salary |
| UAN | Universal Account Number (EPF) |
Synced from
/prd.mdin the repository root. Edit the root file, not this page.