---
suivi: 1514
date: 2026-09-10
sujet: Visibilité parcelles sans secteur (créateur ∪ dossier ∪ bypass)
chantier: foncier / parcelles / visibilite
type: feature
statut: poussé
hash: f55bff66
fichiers:
  - app/Models/Scopes/FoncierParcelleVisibiliteScope.php
  - app/Services/Foncier/FoncierParcelleVisibiliteService.php
  - app/Support/Acl/RecordAcl.php
  - tests/Unit/Parcelle1514SourceTest.php
  - tests/Feature/Foncier/FoncierParcelleVisibilite1514Test.php
  - tests/Unit/GsGemmePdgDroits1434SourceTest.php
  - tests/Unit/Parcelle1449SourceTest.php
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - docs/suivi/SUIVI_1514_visibilite_parcelles_sans_secteur.md
---

# SUIVI #1514 — visibilité parcelles sans secteur

## PROMPT ENVOYÉ

Décision Robin : restreindre la visibilité des parcelles à
créateur ∪ parcelle rattachée à un dossier foncier visible ∪ groupes
à accès total. Le secteur sort du filtre (tables et écran conservés,
usage futur : routage des demandes de contact). Ne pas toucher
`DepotFactureController` (#1513). Push `origin/main`.

## BASE GIT

HEAD de départ = `origin/main` = `f39f162a` (chore hash fiche #1513).
Le prompt citait `ecd8b99d` (#1512) avec #1513 en cours : **périmé**.
#1513 déjà sur main (`c2bd7c0f` + `f39f162a`). Aucun rebase. Fichier
`DepotFactureController` non touché.

## FICHES LUES

- **#1512 LEÇON** — parcelles ≠ dossiers : R1 géo ∪ créateur ∪ dossier
  vs `RecordHabilitationScope` + `BYPASS_VIEW_GROUPS` (avec GS_DSI).
  Impact : ne toucher que le scope parcelle et le bypass parcelle ;
  l’asymétrie GS_DSI est préexistante, signalée, non corrigée.
- **#1288 LEÇON** — morph `habilitable_*`, `retire_le`, R1d = usage
  pas visibilité. Impact : R1c et le commentaire R1d conservés tels
  quels ; R1a/R1e retirés.
- **#1508 LEÇON** — « partout » n’est pas un scope unique. Hors cause
  facture ; `FactureVisibility` non modifié.
- **#1463 / #1509 / #1510 LEÇON** — ne pas toucher Show.vue,
  `ParcelleCreationService`, Create.vue. Respecté.

## SYNTHÈSE

R1a (INSEE secteur) retiré. R1e (paquet négociation, entièrement
conditionné à `$codes`) retiré **explicitement** — conséquence
mécanique de la sortie du secteur, pas un choix séparé. R1b et les
deux chemins R1c inchangés. Miroir PHP `userCanViewParcelle` aligné
(plus de `codesInsee` ni `visibleViaPaquetProprietaire`).

Bypass parcelle (`m365GroupNames()` brut, jamais `hasAnyM365Group`) :

| Groupe | Avant | Après |
|--------|-------|-------|
| GS_DIRECTION_GENERALE | bypass | bypass |
| GS_ADMIN_ERP | bypass | bypass |
| GS_GEMME_PDG | bypass | **sort** |
| GS_HECTARE_DIRECTION | absent | bypass (inerte tant que le groupe M365 n’existe pas) |
| GS_DSI | hors bypass parcelle | inchangé (hors) |

`BYPASS_VIEW_GROUPS` (dossiers) **non modifié** : DG, GEMME_PDG,
GS_DSI, ADMIN.

`SecteurResolutionService::codesInseePourUtilisateur` conservé.
`FoncierParcelleVisibiliteService::codesInsee` conservé, **plus
appelé par le scope**. Consommateurs restants : filtre confort
`mon_secteur` (`ParcelleProspectionQuery`) et écran secteurs.

Bandeau `Prospection/Index.vue` **non refondu**. Il devient
trompeur : GEMME_PDG a encore `vue_complete` via
`groupeAccesTotalProspection` mais n’a plus le bypass SQL ;
`GS_HECTARE_DIRECTION` aura le bypass sans bandeau. Lot ultérieur
proposé : aligner `groupeAccesTotalProspection` sur
`BYPASS_PARCELLE_VIEW_GROUPS`.

Mesures Robin : 12 parcelles, créateurs = titulaires de secteur,
aucun suppléant → aucune parcelle orpheline.

## DÉPLOIEMENT-TEST

    git pull origin main
    php artisan optimize:clear
    php artisan view:clear
    php artisan journal:sync

Pas de migrate. Pas de route:clear. Pas de npm.

Comptes de test (PAS Robin) : Eric (35), un GS_HECTARE, un compte
sans groupe. Vérifier que la liste parcelles d’Eric reste les 6
qu’il a créées ; qu’un GS_HECTARE hors créateur/dossier ne voit pas
les parcelles d’autrui.

## LEÇON

Visibilité parcelles = créateur ∪ dossier visible ∪ bypass
(DG, ADMIN, HECTARE_DIRECTION). Le secteur n’est plus un droit, c’est
une donnée d’organisation. Les dossiers restent sur une autre règle
(`RecordHabilitationScope` + GS_DSI). Un bandeau « vue complète »
branché sur une liste de groupes distincte du bypass SQL ment dès
que les deux listes divergent. R1e meurt avec R1a : le retirer du
source, ne pas laisser un `if ($codes !== [])` mort.
