# NewHire LINK Package Integration Guide

## Overview

`NewHire` submissions now use a secure **link-only package** flow in normal operation.
Instead of emailing attachments, the backend sends a token-backed package that can expose:

- the generated PDF
- an uploads ZIP
- individual sensitive file links
- OTP request / verify endpoints for step-up access

This guide is intended for frontend/admin UX work that consumes the Phase 4 + Phase 6 backend behavior.

---

## Package endpoint summary

Base path:

```text
/api/v1/admin/forms/new-hire/{formToken}
```

Routes:

| Route | Method | Purpose |
|---|---|---|
| `/pdf` | `GET` | Download the NewHire PDF |
| `/uploads.zip` | `GET` | Download the uploads ZIP package |
| `/files/{fileCategory}` | `GET` | Download an individual registered file |
| `/otp/request` | `POST` | Send a one-time code to the authenticated principal |
| `/otp/verify` | `POST` | Verify the code and grant temporary step-up access |

Sensitive file categories currently supported:

- `ID_BADGE`
- `GOV_ID_FRONT`
- `GOV_ID_REAR`
- `SSN_CARD`

---

## UX expectations

The package page should:

1. List all available downloadable items.
2. Explain that portal authentication is required.
3. Explain that some items require OTP step-up before download.
4. Show clear expiry / retry messaging when a token is invalid, expired, revoked, or exhausted.
5. Avoid exposing filesystem paths, storage details, or internal identifiers.

Recommended content blocks:

- **Secure package notice**
- **Available downloads list**
- **OTP prompt / verify flow**
- **Expiry and download-usage guidance**
- **Friendly error state for `403` / `404`**

---

## OTP flow

### 1. Request OTP

```http
POST /api/v1/admin/forms/new-hire/{formToken}/otp/request
```

Example response:

```json
{
  "success": true,
  "message": "Verification code sent.",
  "destination": "u***@example.com",
  "expiresAt": "2026-05-10T22:05:00Z"
}
```

### 2. Verify OTP

```http
POST /api/v1/admin/forms/new-hire/{formToken}/otp/verify
Content-Type: application/json

{
  "code": "123456"
}
```

Example response:

```json
{
  "success": true,
  "message": "Verification successful.",
  "grantedUntil": "2026-05-10T22:20:00Z"
}
```

### Expected error behavior

| Status | Meaning |
|---|---|
| `403` | Step-up required or OTP grant expired |
| `404` | Token invalid, expired, revoked, exhausted, or mismatched |
| `429` | Rate limit exceeded |

The backend uses the shared `ErrorResponse` contract via the global exception handler.

---

## Security notes for frontend work

- Treat `formToken` as opaque.
- Do not parse meaning out of the token.
- Do not cache sensitive download responses.
- Do not surface whether a token is expired vs revoked vs invalid; the backend intentionally normalizes this.
- Preserve the correlation ID header if you expose error details in admin tooling.

---

## Resend-email note

`POST /resend-email` still exists for operational fallback, but normal `NewHire` delivery should be considered **LINK-first**.
Frontend/package UX should not assume attachments are the routine path.

---

## Validation checklist

- [ ] PDF link downloads successfully.
- [ ] ZIP link downloads successfully.
- [ ] Sensitive file route returns `403` before OTP.
- [ ] OTP request succeeds for an authenticated Admin/Office user.
- [ ] OTP verify grants temporary access.
- [ ] Sensitive file route succeeds after OTP verification.
- [ ] Invalid/tampered token returns `404`.
- [ ] Expired/revoked/exhausted token returns `404`.
- [ ] Error states shown to the user do not leak internal storage details.

