> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# IRS Worker Classification & 1099-NEC — Compliance Evidence

> Controls: Uses createNotificationIfNew for 24h deduplication; no tax IDs in payloads; service-role only.

**Created:** 2026-03-25\
**Status:** Pre-Production Review\
**Owner:** HR (Workforce & HRIS)

***

## 1. Regulatory References

| Regulation                                  | Citation                                              | HR-34 Control                                                                                                                                                                            |
| ------------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| IRS Worker Classification (20-factor test)  | IRS Rev. Rul. 87-41; Pub 15-A                         | `hr_contractor_classification_tests` table with `behavioral_control`, `financial_control`, `relationship_type` JSONB fields; mandatory `rationale` text; `overall_classification` result |
| 1099-NEC Reporting Threshold                | 26 USC §6041A; IRS Form 1099-NEC                      | `hr_get_contractor_1099_totals` RPC aggregates approved time entries; `useContractor1099Export` hook applies \$600 filing threshold                                                      |
| Arizona Independent Contractor (ARS 23-902) | ARS §23-902 (worker classification for workers' comp) | Classification test UI captures all IRS factors; results stored with `reviewed_by` audit trail                                                                                           |
| Tax ID Protection                           | IRS Pub 1281; HIPAA analog for financial PII          | `tax_id_encrypted` column; `hr.contractor.tax_id.read` permission gate; no tax IDs in notification payloads                                                                              |

***

## 2. Database Controls

### 2.1 Classification Documentation

| Control                    | Implementation                                                                                                         | Evidence                                                                                  |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Structured IRS factor test | `hr_contractor_classification_tests` with `behavioral_control`, `financial_control`, `relationship_type` JSONB columns | Migration exists; RLS test: `tests/rls/hr/hr-contractor-classification-tests.rls.test.ts` |
| Mandatory rationale        | `rationale TEXT NOT NULL` on classification tests                                                                      | Schema constraint; unit test validates non-empty                                          |
| Audit trail                | `reviewed_by`, `created_by`, `updated_by`, `created_at`, `updated_at` columns                                          | Standard audit columns on all 6 tables                                                    |
| Organization isolation     | RLS via `hr_has_org_access` SECURITY DEFINER                                                                           | 18 RLS tests across 6 tables                                                              |

### 2.2 Financial Data Protection

| Control                        | Implementation                                                             | Evidence                                                                                               |
| ------------------------------ | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| Tax ID access restriction      | `hr.contractor.tax_id.read` permission key                                 | Permission seeded in `pf_module_permissions`; gated in UI via `useHasPermission`                       |
| Approved-only 1099 aggregation | `hr_get_contractor_1099_totals` RPC filters `approval_status = 'approved'` | RPC is SECURITY DEFINER; unit test: `tests/unit/cores/hr/contractor-1099-export.test.ts`               |
| Amount calculation integrity   | `calculateTimeEntryAmount(hours, rate)` with rounding                      | Unit test: `tests/unit/cores/hr/contractor-workforce-utils.test.ts` (5 cases including float rounding) |
| Notification payload safety    | No tax IDs in `pf_notifications.data`                                      | Code review: `contractorNotifications.ts` uses only `contractor_id`, `contract_id`, `due_date`         |

***

## 3. RLS Test Evidence

| Table                                | Test File                                                     | Tests  | Isolation Verified                 |
| ------------------------------------ | ------------------------------------------------------------- | ------ | ---------------------------------- |
| `hr_staffing_agencies`               | `tests/rls/hr/hr-staffing-agencies.rls.test.ts`               | 3      | ✅ Own-org CRUD + cross-org blocked |
| `hr_contractors`                     | `tests/rls/hr/hr-contractors.rls.test.ts`                     | 3      | ✅ Own-org CRUD + cross-org blocked |
| `hr_contractor_contracts`            | `tests/rls/hr/hr-contractor-contracts.rls.test.ts`            | 3      | ✅ Own-org CRUD + cross-org blocked |
| `hr_contractor_classification_tests` | `tests/rls/hr/hr-contractor-classification-tests.rls.test.ts` | 3      | ✅ Own-org CRUD + cross-org blocked |
| `hr_contractor_time_entries`         | `tests/rls/hr/hr-contractor-time-entries.rls.test.ts`         | 3      | ✅ Own-org CRUD + cross-org blocked |
| `hr_contractor_credentials`          | `tests/rls/hr/hr-contractor-credentials.rls.test.ts`          | 3      | ✅ Own-org CRUD + cross-org blocked |
| **Total**                            | 6 files                                                       | **18** | **All pass**                       |

***

## 4. Unit & Integration Test Evidence

| Suite                | File                                                       | Tests  | Coverage                                                                          |
| -------------------- | ---------------------------------------------------------- | ------ | --------------------------------------------------------------------------------- |
| Utility functions    | `tests/unit/cores/hr/contractor-workforce-utils.test.ts`   | 17     | Amount calc, renewal window, expiry, formatters, badges                           |
| 1099 export logic    | `tests/unit/cores/hr/contractor-1099-export.test.ts`       | 10     | Filing threshold (\$600), edge cases, RPC coercion                                |
| Notification helpers | `tests/unit/cores/hr/contractorNotifications.test.ts`      | 10     | Window logic for renewals and credentials                                         |
| Integration CRUD     | `tests/integration/hr/contractor-crud.integration.test.ts` | 7      | Full lifecycle: agency → contractor → contract → time → classification → approval |
| **Total**            | 4 files                                                    | **44** |                                                                                   |

***

## 5. SECURITY DEFINER Helpers

| Function                                                           | Purpose                      | Recursion-Safe                                      |
| ------------------------------------------------------------------ | ---------------------------- | --------------------------------------------------- |
| `hr_has_org_access(org_id, user_id)`                               | Org membership check for RLS | ✅ Queries `pf_user_role_assignments` directly       |
| `hr_contractor_manager_can_see_contractor(contractor_id, user_id)` | Department-scoped visibility | ✅ Joins via non-RLS path                            |
| `hr_get_contractor_1099_totals(org_id, tax_year)`                  | Approved payment aggregation | ✅ SECURITY DEFINER; service-role or org-access gate |

***

## 6. Permission Keys

| Key                          | Purpose                        | Seeded |
| ---------------------------- | ------------------------------ | ------ |
| `hr.contractor.view`         | View contractor profiles       | ✅      |
| `hr.contractor.manage`       | Create/edit/delete contractors | ✅      |
| `hr.contractor.tax_id.read`  | View encrypted tax IDs         | ✅      |
| `hr.contractor.time.approve` | Approve/reject time entries    | ✅      |
| `hr.contractor.classify`     | Perform classification tests   | ✅      |
| `hr.staffing_agency.manage`  | Manage staffing agencies       | ✅      |

***

## 7. Edge Function (Batch Reminders)

| Function                          | Purpose                                                          | Deployed |
| --------------------------------- | ---------------------------------------------------------------- | -------- |
| `contractor-compliance-reminders` | Cron-triggered batch scan for expiring contracts and credentials | ✅        |

**Controls:** Uses `createNotificationIfNew` for 24h deduplication; no tax IDs in payloads; service-role only.

***

## 8. Open Items

| Item                                                | Status                                       | Risk                                              |
| --------------------------------------------------- | -------------------------------------------- | ------------------------------------------------- |
| `tax_id_encrypted` actual encryption implementation | Deferred to HR-PAY-04 Phase 2                | Medium — column exists but encryption at-rest TBD |
| HR-PAY-04 1099-NEC filing automation                | Stub + export hook complete; filing deferred | Low — manual export available                     |
| Admin guide documentation                           | T-DOC-ADMIN recommended, not MVP-blocking    | Low                                               |

***

## 9. Sign-Off

* [ ] Security review: RLS + permission gates verified
* [ ] Compliance review: Classification UI captures IRS factors
* [ ] Tax data review: No tax IDs in notifications or client logs
* [ ] Test evidence: 62 total tests (18 RLS + 44 unit/integration)
