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

# Job distribution

> The careers page, the SECO Job-Room, and multi-channel posting.

A published position can reach candidates through three routes. They are independent —
you can use the careers page alone, or add channels as you need them.

## 1. The careers page

Every installation serves a public careers page from its own host. It renders published
positions in the visitor's locale, respects the internal-only and restricted visibility
settings, and takes applications directly into the pipeline.

The page inherits the installation's branding — logo, colours, and typography are
configured under **Settings → Branding**.

## 2. The SECO Job-Room (Stellenmeldung)

Switzerland requires vacancies in occupations with high unemployment to be reported to
the public employment service before they are advertised anywhere else. Swiss HR Easy
implements this as a tracked lifecycle rather than a checkbox.

### The lifecycle

| Status               | Meaning                                                                 |
| -------------------- | ----------------------------------------------------------------------- |
| `NOT_REQUIRED`       | The occupation is not subject to the reporting duty.                    |
| `PENDING_JOBROOM`    | Reported to the Job-Room; the embargo on public advertising is running. |
| `RAV_REVIEW`         | The embargo has elapsed; the RAV may still send candidates.             |
| `EMPLOYER_RESPONDED` | You have reported back how many RAV candidates you invited and hired.   |
| `CLEARED`            | The obligation is discharged for this vacancy.                          |

On submission the platform records the Job-Room ID, the management URL, and the
**earliest permitted external publication date**, computed as five *working* days
ahead — Swiss national public holidays and weekends excluded, with Easter-relative
holidays calculated rather than hard-coded.

<Note>
  The Job-Room access token is stored separately from the management URL and is never embedded in a
  persisted link. A URL with a token in it leaks the token to every proxy and log along the way.
</Note>

### Staying in sync

A scheduled job polls SECO for each open Stellenmeldung and sweeps the ones whose
embargo has expired from `PENDING_JOBROOM` into `RAV_REVIEW`. Both sweeps are batched
with an explicit cap so a catch-up run cannot turn into an unbounded query; anything
over the cap is picked up on the next run. The endpoint is protected by a shared
`CRON_SECRET`.

If SECO credentials are not configured, the module degrades cleanly: reporting is
tracked manually and the poll reports zero polled rather than failing.

### RAV feedback

When the RAV sends candidates, you record how many you invited and how many you hired,
with an optional note. That closes the loop and moves the Meldung to
`EMPLOYER_RESPONDED`.

<Card title="The legal detail" icon="scale-balanced" href="/swiss/stellenmeldepflicht">
  Which occupations are covered, what the embargo actually forbids, and what you must keep on file.
</Card>

## 3. Multi-channel distribution

Positions can be pushed to commercial job boards through an aggregator, so one publish
action reaches LinkedIn, Indeed, jobs.ch and others without separate logins. A position
is mapped to a channel payload once and re-used per channel.

<Warning>
  The multi-channel aggregator client is currently a **stub**: it implements the interface and
  returns placeholder responses so the surrounding flow can be built and tested, but it does not
  post to live boards until credentials and the real API integration are in place. The careers page
  and the SECO Job-Room are fully implemented.
</Warning>

## Turning distribution off

Set `FEATURE_JOB_DISTRIBUTION=false` to hide the distribution surfaces on an
installation that only advertises through its own careers page.
