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

# Audit and data subject requests

> The audit trail, what it masks, and how DSAR requests are received, verified and executed.

## The audit trail

Every state-changing operation writes an audit entry: who, what, when, on which entity,
with the before and after values. This is not best-effort — it is enforced in CI. A
state-changing route with no audit call in its import graph fails the build unless it
carries a justified allowlist entry.

Audit entries are also written on **error paths and fallback redirects**, because the
failed attempt is often the interesting one.

### What is masked

Sensitive values are masked before they are written. The masker covers authentication
and security material — passwords and hashes, tokens of every kind, API keys, private
keys, encryption keys, OTPs and PINs, confirmation codes — as well as identifiers like
AHV numbers and IBANs, where enough is preserved for debugging (the last digits of an
IBAN) without storing the value.

<Warning>
  The masker does **not** mask salary amounts. Payroll audit rows can therefore carry compensation
  values in their before/after snapshots. This is precisely why `audit:view` is `ADMIN`+ only and is
  deliberately withheld from `SYSTEM_ADMIN`.
</Warning>

### IP addresses

Client IPs are truncated before storage — enough to investigate an incident, not enough
to track an individual.

### AI operations

AI calls are audited as `AI_OPERATION`, with token usage in the metadata. What was sent
for processing, when, and on whose instruction is a query rather than an
investigation.

### Version logging

Deployed versions are recorded, so an audit entry can be tied to the code that produced
it.

## Data subject requests (DSAR)

Under the revised Swiss data-protection act, a person can ask what you hold about them,
ask for a copy, and ask for correction or erasure. The DSAR module handles the whole
process.

### Receiving a request

Requests arrive through a **public endpoint** — the requester may be a former employee
or a rejected applicant with no account. That endpoint is protected:

* **CAPTCHA** (Cloudflare Turnstile). Both `CAPTCHA_SECRET` and
  `NEXT_PUBLIC_CAPTCHA_SITE_KEY` must be set; a partial configuration **fails closed**,
  rejecting every submission with `CAPTCHA_REQUIRED` and logging a warning.
* **Identity verification** by a confirmation link to the address on file, so a request
  cannot be used to extract someone else's data.
* A **cooling period** between requests from the same subject, so the endpoint cannot be
  used to hammer the system.

### Processing

| Stage   | Permission     | Role        |
| ------- | -------------- | ----------- |
| View    | `dsar:view`    | `HR_STAFF`+ |
| Process | `dsar:process` | `HR_STAFF`+ |
| Execute | `dsar:execute` | `ADMIN`+    |

Preparing a response is HR work. **Executing** it — actually producing the export or
performing the erasure — is `ADMIN`+, because erasure is irreversible.

### What a request returns

An access request produces a structured export of everything held about the person
across modules: their user record, applications, employment periods, absences, time
entries, documents, correspondence, and payroll records.

### What erasure does not remove

Swiss law requires records to be retained regardless of an erasure request:

| Category                                | Why it stays                               |
| --------------------------------------- | ------------------------------------------ |
| Payroll records and payslips            | Statutory accounting and tax retention.    |
| Filed declarations                      | Already transmitted to the authority.      |
| Contracts                               | Contractual and evidentiary retention.     |
| Accounting documents including receipts | Statutory accounting retention.            |
| Audit entries                           | The integrity record of the system itself. |

The response states what was erased **and what was retained, with the legal basis**. A
response that quietly retains data is not a compliant response.

<Card title="Swiss data protection" icon="shield-halved" href="/swiss/data-protection">
  nDSG obligations, retention periods, and what the platform does about them.
</Card>
