> ## 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.

# Final Paycheck & Termination Pay Compliance — Integration

> Status: \U0001F4DD Planned Last Updated: 2026-03-25 Constitution: §1.2 (core boundaries), §1.3 (integration patterns)

**Spec:** [HR-30](../../../specs/hr/specs/HR-30-final-paycheck-termination-pay-compliance.md)\
**Status:** 📝 Planned\
**Last Updated:** 2026-03-25\
**Constitution:** §1.2 (core boundaries), §1.3 (integration patterns)

***

## Integration Overview

| Integration         | Pattern        | Direction             | Status     |
| ------------------- | -------------- | --------------------- | ---------- |
| HR-03               | Event consumer | HR-30 consumes        | 📝 Planned |
| HR-07               | Data / export  | HR-30 → HR-07 staging | 📝 Planned |
| HR-06, HR-05, HR-11 | Same-core read | HR-30 reads           | 📝 Planned |
| PF-10               | Notifications  | HR-30 → PF-10         | 📝 Planned |
| PF-30               | RBAC           | Permission keys       | 📝 Planned |

***

## Consumed Events

### `hr_employee_terminated`

**Publisher:** HR-03 (HR core)\
**Subscriber:** HR-30\
**Status:** Planned registry entry (see [EVENT\_CONTRACTS.md](./EVENT_CONTRACTS.md))\
**Trigger:** Employment status set to terminated; existing lifecycle pipeline.

**Payload (align with HR-03 / platform event envelope per [EVENT\_CONTRACTS.md](./EVENT_CONTRACTS.md)):**

The event follows the platform event envelope pattern with top-level `event_name`, `event_id`, `timestamp`, and a `metadata` object. The business payload is wrapped inside the envelope.

```typescript theme={null}
interface HrEmployeeTerminatedEventEnvelope {
  event_name: 'hr_employee_terminated';
  event_id: string; // UUID for idempotency and deduplication
  timestamp: string; // ISO 8601 UTC timestamp
  metadata: {
    source: string;
    version: string;
    correlation_id?: string;
  };
  payload: HrEmployeeTerminatedPayload;
}

interface HrEmployeeTerminatedPayload {
  employee_id: string;
  organization_id: string;
  termination_date: string; // ISO date
  termination_type: 'voluntary' | 'involuntary' | 'retirement' | 'end_contract';
  offboarding_instance_id?: string | null;
}
```

**Idempotency & Retry Semantics:**

* **Deduplication key:** `event_id` (must be unique per event instance)
* **Business idempotency:** Unique partial index or application check on `(organization_id, employee_id, termination_date)` ensures at-most-once creation of final paycheck request
* **Retry behavior:** Consumer must handle duplicate `event_id` gracefully (idempotent INSERT); retries with same `event_id` are no-ops
* **Ordering:** Events for the same `employee_id` should be processed in `timestamp` order where possible; out-of-order events are handled via business-key uniqueness check

**Consumer action (HR-30):**

1. Verify `event_id` not already processed (optional deduplication table or log check).
2. Map `termination_type` to HR-30 enum per spec Clarifications.
3. Insert `hr_final_paycheck_requests` if no row for `(organization_id, employee_id, termination_date)` with non-cancelled status.
4. Enqueue calculation job (status → `calculating`).

Publishers and consumers must follow [EVENT\_CONTRACTS.md](./EVENT_CONTRACTS.md) rules for envelope structure, metadata fields, and idempotency guarantees.

***

## Published Events (optional Phase 2)

### `hr_final_paycheck_status_changed`

**Publisher:** HR-30
**Subscribers:** PF-10 (notifications), HR-07 (future pay run hooks)
**Status:** 📝 Planned — event type is defined in `KnownEventName` but not yet seeded in `fw_workflow_events`. Confirm registration in seed data during implementation.

**Payload (draft):**

```typescript theme={null}
interface HrFinalPaycheckStatusChangedPayload {
  event_name: 'hr_final_paycheck_status_changed';
  request_id: string;
  employee_id: string;
  organization_id: string;
  previous_status: string;
  new_status: string;
  deadline_date: string;
  timestamp: string;
}
```

***

## HR-07 Handoff

**Phase 1:** CSV export from UI + documented column mapping (employee id, amounts, pay date).\
**Phase 2:** Structured RPC or edge function `hr_export_final_pay_for_run` returning JSON lines for payroll import — **blocked on** HR-07 pay-run API shape; tracked in [PENDING\_CONTRACTS.md](./PENDING_CONTRACTS.md).

***

## Platform Integration Layer

* Use `@/platform/events` (or existing HR event dispatcher) for emitting/consuming typed events.
* Notifications: `@/platform/notifications` patterns; **no PHI** in notification body (ids and deadline only).

***

## Security

* All access gated by RLS + `hr_has_permission` / `is_hr_admin` / `hr_is_manager_of` / `is_self_employee` per spec.
* Edge functions: `verify_jwt: true`; `getCorsHeaders`; structured logger.

***

## References

* [CROSS\_CORE\_INTEGRATIONS.md](./CROSS_CORE_INTEGRATIONS.md) — matrix row HR-30
* [EVENT\_CONTRACTS.md](./EVENT_CONTRACTS.md)
* [CONTRACT\_VALIDATION\_CHECKLIST.md](./CONTRACT_VALIDATION_CHECKLIST.md)
