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

# Architecture

> How Swiss HR Easy is put together — deployment model, module structure, and the shared layer.

## Deployment model: single-tenant

Every customer runs their **own Azure environment** — App Service, PostgreSQL Flexible
Server, Blob Storage, and Key Vault. There is no shared database and no cross-customer
data path. Multi-tenant is explicitly out of scope.

Practical consequences:

* Data residency is per customer. Swiss deployments run in Switzerland North.
* Configuration, feature flags, and integrations are per installation.
* Upgrades are per environment, so a customer can sit on a version while another moves.
* Within one installation there may still be **multiple legal employers** — see
  [Legal entities](/concepts/legal-entities).

## Technology

| Layer          | Choice                                                          |
| -------------- | --------------------------------------------------------------- |
| Framework      | Next.js 15 (App Router), React 18, TypeScript                   |
| Database       | PostgreSQL via Prisma — `prisma/schema.prisma` is the truth     |
| Auth           | Microsoft Entra ID (SSO) + signed magic links                   |
| Storage        | Azure Blob Storage                                              |
| Mail and Teams | Microsoft Graph                                                 |
| Secrets        | Azure Key Vault (field-encryption key, integration credentials) |
| Observability  | Azure Application Insights                                      |
| AI             | Anthropic Claude (reasoning), Voyage AI (embeddings)            |

## Module structure

Features live in `src/modules/{module}/` and expose a **single public contract**:

```
src/modules/{module}/
  services/     # business logic — the brain
  components/   # React components — the face
  types.ts      # module-specific types
  index.ts      # the only surface other modules may import
```

Anything not exported from `index.ts` is module-internal. Cross-module calls go through
the contract, never into another module's `services/` directly. This is
[ADR-004](/development/adr).

Shared, cross-cutting code lives in `src/lib/` — authentication and RBAC, audit
logging, the Prisma client singleton, storage, e-mail, Graph, crypto, and the Swiss
helpers (cantons, AHV numbers, address and phone normalisation).

## Modules at a glance

<Columns cols={3}>
  <Card title="Recruitment" href="/guides/recruitment/overview">
    Positions, pipeline, interviews, references, talent pools, job distribution.
  </Card>

  <Card title="Employee lifecycle" href="/guides/lifecycle/overview">
    Employment periods, leave, sick leave, holidays, on/offboarding.
  </Card>

  <Card title="Pre-boarding" href="/guides/lifecycle/preboarding-and-onboarding">
    The journey between "offer accepted" and "first day".
  </Card>

  <Card title="Contracts" href="/guides/lifecycle/contracts">
    Templates, placeholder variables, generation, e-signature.
  </Card>

  <Card title="Certificates" href="/guides/lifecycle/certificates">
    Arbeitszeugnis, Zwischenzeugnis, Arbeitsbestätigung.
  </Card>

  <Card title="Probation" href="/guides/lifecycle/probation">
    Reflective meeting companion and questionnaires.
  </Card>

  <Card title="Time tracking" href="/guides/time-absence/time-tracking">
    Entries, weekly summaries, ArG break compliance.
  </Card>

  <Card title="Payroll" href="/guides/payroll/overview">
    Monthly Lohnabrechnung engine and year-end declarations.
  </Card>

  <Card title="Bexio" href="/guides/payroll/bexio">
    Payroll-employee sync into bexio.
  </Card>

  <Card title="Compensation" href="/guides/people/compensation">
    Role catalog, salary bands, dated assignments.
  </Card>

  <Card title="Salary visibility" href="/guides/people/compensation">
    Masking and hand-picked salary access grants.
  </Card>

  <Card title="Budgeting" href="/guides/finance/budgeting">
    Five budgeting methods, forecasts, proposals.
  </Card>

  <Card title="Expenses" href="/guides/finance/expenses">
    Receipt OCR, Swiss categories, two-level approval.
  </Card>

  <Card title="Feedback" href="/guides/people/feedback">
    Cycles, continuous feedback, growth journeys, team vitality.
  </Card>

  <Card title="Surveys" href="/guides/people/surveys">
    Anonymous employee surveys with k-anonymity.
  </Card>

  <Card title="Decision making" href="/guides/people/decision-making">
    Consent, advice process, systemic consensus, dot voting.
  </Card>

  <Card title="Workflows" href="/guides/admin/workflows">
    The visual engine behind approvals and checklists.
  </Card>

  <Card title="Semantic search" href="/guides/ai/semantic-search">
    Embeddings, sentiment, event history, reasoning.
  </Card>

  <Card title="Document intelligence" href="/guides/ai/document-intelligence">
    Vectorless, reasoning-based retrieval over long documents.
  </Card>

  <Card title="Observability" href="/operations/monitoring">
    Structured logging and Application Insights correlation.
  </Card>

  <Card title="Organization" href="/guides/admin/settings-and-users">
    Locations, teams, and the manager graph.
  </Card>

  <Card title="Reports" href="/guides/admin/reports">
    Cross-module reporting and exports.
  </Card>

  <Card title="Notifications" href="/guides/admin/notifications-and-messages">
    In-app inbox and subscription preferences.
  </Card>
</Columns>

## How modules talk to each other

Modules communicate through an **in-process event bus** (`src/lib/events/`), not by
reaching into each other:

```typescript theme={null}
eventBus.emit("employee.onboarded", { employeeId });

eventBus.on("employee.onboarded", async (data) => {
  /* … */
});
```

Events are named `{module}.{entity}.{action}`. The pre-boarding orchestrator is the
clearest example: it listens for personal-data submission, document upload, and
contract signature, and advances the journey without those modules knowing it exists.
This is [ADR-005](/development/adr).

## Request path

Every API route follows the same skeleton — authenticate, check permission, check
ownership, validate input with Zod, delegate to a service, write an audit entry,
return a projected DTO. The rule set and the reasoning behind it are in
[API route conventions](/development/api-routes).
