diff --git a/HANDOFF.md b/HANDOFF.md
index 8b04c71..44649a1 100644
--- a/HANDOFF.md
+++ b/HANDOFF.md
@@ -123,6 +123,30 @@ i pulsanti Modifica/Elimina in `campagna-index`/`campagna-show` sono sotto
`@can('settings.manage')`. Nota: `Campagna` non ha soft delete — l'eliminazione
è definitiva.
+Per i **territori** vale un modello leggermente diverso, perché la
+visualizzazione va aperta a tutti gli operativi: lista (`territori.index`) e
+dettaglio (`territori.show`) sono ora su `territori.assign` (che hanno admin,
+assistente e operatore); creazione/modifica/cestino restano su `territori.manage`
+(solo admin). Attenzione a due punti:
+
+- **Ordine delle rotte.** Le rotte letterali `territori/create` e
+ `territori/cestino` devono restare registrate PRIMA del wildcard
+ `territori/{territorio}`, altrimenti verrebbero catturate dalla rotta di
+ dettaglio.
+
+- **`TerritorioIndex` perde la copertura del middleware persistente.** Il suo
+ componente è ora servito da una rotta rilassata (`territori.assign`), quindi i
+ suoi metodi di mutazione (`toggleActive`, `togglePriority`, `deleteTerritorio`)
+ NON sono più protetti dal middleware di route e hanno un
+ `$this->authorize('territori.manage')` interno — senza, un operativo potrebbe
+ invocarli via `/livewire/update` col pulsante nascosto. Per difesa in
+ profondità lo stesso check è stato aggiunto anche a `TerritorioCreate::save`,
+ `TerritorioEdit::save`/`removePdf`, `TerritorioCestino::restore`/`forceDelete`
+ (che restano comunque su rotte `territori.manage`). I pulsanti
+ Modifica/toggle/Elimina/Nuovo/Cestino in `territorio-index`/`territorio-show`
+ sono sotto `@can('territori.manage')`; il link "Dettaglio" resta visibile a
+ tutti. Il menu laterale mostra "Territori" a chi ha `territori.assign`.
+
### Export/Import XML: backup completo e round-trip
`Livewire/Settings/XmlExchange` esporta e reimporta **tutti** i dati gestionali,
diff --git a/app/Livewire/Territori/TerritorioCestino.php b/app/Livewire/Territori/TerritorioCestino.php
index 769251a..c7ece4f 100644
--- a/app/Livewire/Territori/TerritorioCestino.php
+++ b/app/Livewire/Territori/TerritorioCestino.php
@@ -12,6 +12,8 @@ class TerritorioCestino extends Component
public function restore(int $id)
{
+ $this->authorize('territori.manage');
+
$territorio = Territorio::onlyTrashed()->findOrFail($id);
$territorio->restore();
activity()->causedBy(auth()->user())
@@ -22,6 +24,8 @@ class TerritorioCestino extends Component
public function forceDelete(int $id)
{
+ $this->authorize('territori.manage');
+
$territorio = Territorio::onlyTrashed()->findOrFail($id);
if ($territorio->assegnazioni()->exists()) {
diff --git a/app/Livewire/Territori/TerritorioCreate.php b/app/Livewire/Territori/TerritorioCreate.php
index 2c84bf4..e35c0cd 100644
--- a/app/Livewire/Territori/TerritorioCreate.php
+++ b/app/Livewire/Territori/TerritorioCreate.php
@@ -36,6 +36,8 @@ class TerritorioCreate extends Component
public function save()
{
+ $this->authorize('territori.manage');
+
$this->validate();
$data = [
diff --git a/app/Livewire/Territori/TerritorioEdit.php b/app/Livewire/Territori/TerritorioEdit.php
index a041385..4b2f097 100644
--- a/app/Livewire/Territori/TerritorioEdit.php
+++ b/app/Livewire/Territori/TerritorioEdit.php
@@ -49,6 +49,8 @@ class TerritorioEdit extends Component
public function save()
{
+ $this->authorize('territori.manage');
+
$this->validate();
$data = [
@@ -82,6 +84,8 @@ class TerritorioEdit extends Component
public function removePdf()
{
+ $this->authorize('territori.manage');
+
if ($this->territorio->pdf_path) {
Storage::disk('public')->delete($this->territorio->pdf_path);
if ($this->territorio->thumbnail_path) {
diff --git a/app/Livewire/Territori/TerritorioIndex.php b/app/Livewire/Territori/TerritorioIndex.php
index d984eb4..9e1e5fc 100644
--- a/app/Livewire/Territori/TerritorioIndex.php
+++ b/app/Livewire/Territori/TerritorioIndex.php
@@ -96,6 +96,11 @@ class TerritorioIndex extends Component
public function toggleActive(Territorio $territorio)
{
+ // La lista è ora visibile agli utenti operativi (territori.assign), ma
+ // modificare/eliminare i territori resta riservato all'amministratore.
+ // Il check DEVE stare nel metodo: la rotta index non lo garantisce più.
+ $this->authorize('territori.manage');
+
$territorio->update(['attivo' => !$territorio->attivo]);
activity()->causedBy(auth()->user())
->performedOn($territorio)
@@ -105,6 +110,8 @@ class TerritorioIndex extends Component
public function togglePriority(Territorio $territorio)
{
+ $this->authorize('territori.manage');
+
$territorio->update(['prioritario' => !$territorio->prioritario]);
activity()->causedBy(auth()->user())
->performedOn($territorio)
@@ -114,6 +121,8 @@ class TerritorioIndex extends Component
public function deleteTerritorio(Territorio $territorio)
{
+ $this->authorize('territori.manage');
+
activity()->causedBy(auth()->user())
->performedOn($territorio)
->log('soft_deleted');
diff --git a/resources/views/components/layouts/app.blade.php b/resources/views/components/layouts/app.blade.php
index fd41619..99e6ba0 100644
--- a/resources/views/components/layouts/app.blade.php
+++ b/resources/views/components/layouts/app.blade.php
@@ -70,7 +70,7 @@
Home
- @can('territori.manage')
+ @can('territori.assign')
diff --git a/resources/views/livewire/territori/territorio-index.blade.php b/resources/views/livewire/territori/territorio-index.blade.php
index 7e81a23..dd87cbd 100644
--- a/resources/views/livewire/territori/territorio-index.blade.php
+++ b/resources/views/livewire/territori/territorio-index.blade.php
@@ -4,6 +4,7 @@