
# Affectations et gardes d'atterrissage

L'[atterrissage après connexion](/fr/docs/auth-post-login) achemine une session vers la bonne page. Deux mécanismes rendent cet acheminement _correct_ : le jeton qui résout les enregistrements qu'un utilisateur peut atteindre, et la page qui arrête un visiteur anonyme avant même que le résolveur ne s'exécute.

## Le jeton d'affectation

`$currentUser.assignments.<table>` se résout en l'ensemble des ID d'enregistrement issus des lignes `user_access` de l'utilisateur pour `<table>` — une [table de périmètre](/fr/docs/auth-sessions) déclarée dans `auth.scopeTables`. Il apparaît sous deux formes, au comportement différent.

### Indexée — dans une URL d'atterrissage

La forme à enregistrement unique `$currentUser.assignments.<table>[0]` substitue le _premier_ ID d'affectation, produisant un lien direct vers cet enregistrement :

```yaml
roles:
  - name: customer-admin
    defaultLanding: /portal/clients/$currentUser.assignments.clients[0]
    pickerLanding: /portal/select/clients
```

Un rôle peut contenir **au plus un** tel jeton — avec deux, le résolveur ne peut déduire quel périmètre décompter. Un `pickerLanding` ne doit en contenir **aucun** : par définition, le cas multi-enregistrements n'a pas d'ID unique à substituer. Les deux règles sont appliquées au décodage de la configuration.

### Non indexée — dans un filtre dataSource

La forme nue `$currentUser.assignments.<table>` se résout en la liste complète des ID : une page de sélection liste donc exactement les enregistrements que l'utilisateur peut atteindre, et aucun autre.

```yaml
pages:
  - name: client-picker
    path: /portal/select/clients
    access: authenticated
    components:
      - type: list
        props: { id: clients }
        dataSource:
          table: clients
          filter:
            - field: id
              operator: in
              value: $currentUser.assignments.clients
        children:
          - type: text
            content: $record.name
```

C'est ce qui rend le sélecteur sûr à exposer : le filtre est résolu côté serveur à partir de la session, un utilisateur ne peut donc pas l'élargir en modifiant une requête.

## La page `landingPath` est le garde d'accès

`landingPath` doit être adossé à une **page co-localisée** déclarée au même `path`. Cette page est le garde d'accès non authentifié : son bloc `access` renvoie les visiteurs anonymes vers `/login` avant que le résolveur d'atterrissage ne s'exécute. Pour un visiteur authentifié, le résolveur redirige d'abord : la page elle-même est donc généralement vide et n'est jamais rendue.

```yaml
auth:
  landingPath: /portal
  # ...

pages:
  - name: portal-landing
    path: /portal
    access:
      require: authenticated
      redirectTo: /login
    components: [] # never rendered for authed users — the resolver redirects first
```

:::callout
**Oublier la page de garde est l'erreur la plus courante ici.** `landingPath: /portal` sans page `/portal` laisse les visiteurs anonymes sans protection au chemin de montage. Associez toujours le chemin de montage à une page qui exige l'authentification.
:::

Les premières ébauches de cette conception interdisaient qu'une page entre en collision avec `landingPath`. L'implémentation inverse cela : la collision _est_ le mécanisme, et la page en collision est obligatoire.

## Pages connexes

- [Atterrissage après connexion](/fr/docs/auth-post-login) — `landingPath`, `defaultLanding` et le tableau de résolution.
- [Sessions](/fr/docs/auth-sessions) — `scopeTables`, `user_access` et `$currentUser.activeAssignment`.
- [Rôles & RBAC](/fr/docs/auth-roles-rbac) — les rôles sur lesquels les règles d'atterrissage sont déclarées.
- [Pages](/fr/docs/pages-overview) — `access` de page et `dataSource.filter`.
