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

# Environment variables

> Every setting, what it does, and which must never be set in production.

The full annotated list is `.env.example` in the repository. This page groups it by
purpose and flags the ones that matter operationally.

<Warning>
  Secrets belong in **Key Vault** in production, not in App Service configuration. See
  [Deployment](/operations/deployment#secrets).
</Warning>

## Core

| Variable                     | Purpose                          |
| ---------------------------- | -------------------------------- |
| `DATABASE_URL`               | PostgreSQL connection string.    |
| `NEXTAUTH_URL`               | The installation's base URL.     |
| `NEXTAUTH_SECRET`            | Session signing secret.          |
| `NEXT_PUBLIC_APP_URL`        | Base URL exposed to the browser. |
| `NEXT_PUBLIC_DEFAULT_LOCALE` | `de`, `fr` or `en`.              |

## Microsoft Entra ID and Graph

| Variable                                        | Purpose                                            |
| ----------------------------------------------- | -------------------------------------------------- |
| `AZURE_AD_CLIENT_ID` / `_SECRET` / `_TENANT_ID` | Single-tenant app registration for SSO.            |
| `NEXT_PUBLIC_AZURE_AD_CLIENT_ID` / `_TENANT_ID` | Browser-side MSAL.                                 |
| `GRAPH_CLIENT_ID` / `GRAPH_CLIENT_SECRET`       | Mailbox, calendar and Teams access.                |
| `OUTLOOK_MAILBOX_EMAIL`                         | The shared HR mailbox.                             |
| `TEAMS_TEAM_ID` / `TEAMS_CHANNEL_ID`            | Notification target.                               |
| `ALLOWED_EMAIL_DOMAINS`                         | Domains that may auto-create an applicant account. |

<Warning>
  Set `ALLOWED_EMAIL_DOMAINS` in production. Unset, the Entra tenant boundary alone gates implicit
  signup — legacy behaviour, logged as a warning.
</Warning>

## Storage and secrets

| Variable                                  | Purpose                                                                    |
| ----------------------------------------- | -------------------------------------------------------------------------- |
| `AZURE_STORAGE_CONNECTION_STRING`         | Blob storage.                                                              |
| `AZURE_STORAGE_CONTAINER_NAME`            | Container for documents.                                                   |
| `AZURE_KEY_VAULT_URI`                     | Vault URL. The managed identity needs `Key Vault Secrets User`.            |
| `AZURE_KEY_VAULT_FIELD_ENCRYPTION_SECRET` | Secret name; defaults to `field-encryption-key`.                           |
| `TOKEN_ENCRYPTION_KEY`                    | The field-encryption key. Provided directly **only** in local development. |

In production the bootstrap fetches the key from Key Vault and stashes it in
`TOKEN_ENCRYPTION_KEY` for the runtime. Locally, leave Key Vault unset and supply the
key directly.

## Authentication behaviour

| Variable                         | Purpose                                                              |
| -------------------------------- | -------------------------------------------------------------------- |
| `MAGIC_LINK_SECRET`              | Magic-link signing secret.                                           |
| `MAGIC_LINK_EXPIRY_MINUTES`      | Default 60.                                                          |
| `ONBOARDING_LINK_EXPIRY_MINUTES` | Default 10080 (seven days).                                          |
| `COOKIE_SECURE`                  | Defaults to true. Set `false` **only** for local `http://localhost`. |
| `ENABLE_DEV_LOGIN`               | Local bypass. Must be unset in production.                           |

<Warning>
  `ENABLE_DEV_LOGIN` is not a feature flag. It requires exactly `"true"`, a non-production
  `NODE_ENV`, and a non-production host — but production deployments must leave it unset regardless.
</Warning>

## Integrations

| Variable group                                              | Integration                                                                    |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `SECO_API_URL` / `_USERNAME` / `_PASSWORD`                  | SECO Job-Room. Credentials from SECO; staging and production endpoints differ. |
| `NEXT_PUBLIC_JOBROOM_BASE_URL`                              | Job-Room links in the UI.                                                      |
| `BEXIO_CLIENT_ID` / `_SECRET` / `_REDIRECT_URI` / `_SCOPES` | bexio. Needs `payroll_employee_edit`.                                          |
| `DOCUSIGN_*`                                                | DocuSign JWT-grant integration, plus an optional webhook HMAC secret.          |
| `CAPTCHA_SECRET` + `NEXT_PUBLIC_CAPTCHA_SITE_KEY`           | Turnstile on the public DSAR endpoints.                                        |

<Warning>
  The two CAPTCHA variables must be set **together**. A partial configuration fails closed: a
  warning is logged and every DSAR submission is rejected with `CAPTCHA_REQUIRED`.
</Warning>

## AI

| Variable                             | Purpose                                                                        |
| ------------------------------------ | ------------------------------------------------------------------------------ |
| `ANTHROPIC_API_KEY`                  | Reasoning, generation, extraction.                                             |
| `VOYAGE_API_KEY`                     | Embeddings for semantic search.                                                |
| `AI_MODEL_<FEATURE>`                 | Per-feature model override — swap or roll back without a deploy.               |
| `LLM_MODEL`, `CERTIFICATE_LLM_MODEL` | Legacy overrides; still win over defaults for the features that honoured them. |

## Scheduling

| Variable      | Purpose                                                                                                        |
| ------------- | -------------------------------------------------------------------------------------------------------------- |
| `CRON_SECRET` | Shared secret the scheduler presents to the protected cron endpoints. Generate with `openssl rand -base64 32`. |

## Optional

| Variable                   | Purpose                                                                                         |
| -------------------------- | ----------------------------------------------------------------------------------------------- |
| `GOOGLE_SITE_VERIFICATION` | Search Console meta-tag verification. Not a secret; also administrator-configurable in-product. |
| `LOCAL_IMPORT_HOME_PATH`   | Local document import. **Leave unset in production** — the feature is for local development.    |
| `LINEAR_API_KEY`           | In-app feedback dialog → issue tracker.                                                         |

## Feature flags

`FEATURE_<NAME>=true|false` for each module. See
[Feature flags](/operations/feature-flags).

## Production checklist

* [ ] Secrets in Key Vault; the managed identity has `Key Vault Secrets User`.
* [ ] `ALLOWED_EMAIL_DOMAINS` set to the customer's domains.
* [ ] `ENABLE_DEV_LOGIN` unset.
* [ ] `COOKIE_SECURE` unset or `true`.
* [ ] `LOCAL_IMPORT_HOME_PATH` unset.
* [ ] `CRON_SECRET` set and configured in the scheduled workflows.
* [ ] CAPTCHA pair set, or both deliberately unset.
* [ ] SECO and DocuSign pointing at **production** endpoints, not staging or demo.
