# Modifiche — YeastarCTI 403 su endpoint AJAX (licenza UI)

**Data:** 9 lug 2026  
**Ambiente:** `vte23083_2711` / `https://vte.ego.it` (VTEnext 26.04)  
**Scope:** errore 403 su `PollEvents.php` e `PresenceStatus.php`, blocco UI CTI (screen pop, presenza, click-to-call)

---

## Obiettivo

Ripristinare il funzionamento della **UI Yeastar CTI** nel browser (polling eventi chiamata, presenza operatore) bloccata da risposte HTTP 403 su tutti gli endpoint AJAX del modulo.

---

## Sintomo

In console del browser, richieste ripetute fallite:

```
POST /modules/YeastarCTI/ajax/PollEvents.php      → 403 Forbidden
POST /modules/YeastarCTI/ajax/PresenceStatus.php  → 403 Forbidden
```

Effetti lato utente:

- nessun screen pop sulle chiamate in arrivo;
- pannello CTI non aggiornato;
- presenza PBX non sincronizzata con VTE.

**Nota:** gli errori su `help-vtecrm-com.vtecrm.net` (iframe sandbox senza `allow-scripts`) sono **irrilevanti** per YeastarCTI — riguardano solo l’help inline VTE.

---

## Diagnosi

### Flusso coinvolto

```
yeastar_cti.js (HEADERSCRIPT)
    → POST ajax/PollEvents.php, PresenceStatus.php, ...
        → YctiAjaxBootstrap.php
            → ycti_require_login()        ✓ OK (user autenticato)
            → ycti_require_license_ui()   ✗ BLOCCO → HTTP 403
```

Tutti gli endpoint AJAX UI passano da `ycti_require_license_ui()` in `modules/YeastarCTI/lib/YctiAjaxBootstrap.php`.  
Webhook, queue worker e cron **non** sono bloccati (telefonia backend continuava a funzionare).

### Evidenza runtime (debug session `e5886a`)

| Campo | Valore pre-fix |
|-------|----------------|
| `user_id` | 7 (sessione valida) |
| `passpartout_set` | `false` |
| `license_status` | `inactive` |
| `server_status` | `not_found` |
| `license_message` | Licenza non valida (da cache) |
| `ui_allowed` | `false` |

Risposta JSON tipica del 403:

```json
{
  "success": false,
  "message": "Licenza Yeastar CTI non attiva. Contatta l'amministratore.",
  "license_status": "inactive",
  "license_message": "Licenza non valida (da cache)"
}
```

### Verifica server licenze

Interrogazione diretta a `https://vte.mypantarei.net/modules/LicenseManager/register.php` per istanza `vte.ego.it` / `application_unique_key` locale:

```json
{
  "success": true,
  "status": "not_found",
  "message": "Nessuna licenza trovata per questa istanza"
}
```

Cache locale in `modules/YeastarCTI/logs/ycti_license.dat` coerente (`status: inactive`, `server_status: not_found`).

### Ipotesi verificate

| ID | Ipotesi | Esito |
|----|---------|-------|
| H1 | Licenza non registrata | **CONFERMATA** |
| H2 | Licenza scaduta oltre grazia 7 gg | Respinta (`expiry_date` vuota) |
| H3 | Passpartout dev non configurato | **CONFERMATA** (assente pre-fix) |
| H4 | Cache licenza corrotta | Respinta (allineata al server) |
| H5 | Problema autenticazione (401) | Respinta (`user_id` presente) |

---

## Causa radice

Il plugin YeastarCTI applica un **gating commerciale** sull’interfaccia utente: senza licenza attiva (o bypass dev documentato), `YctiLicense::isUiAllowed()` restituisce `false` e gli endpoint AJAX rispondono 403.

Su `vte.ego.it` la licenza **non era mai stata registrata** sul LicenseManager Pantarei.

---

## Soluzione applicata

### Fix immediato (staging / fino a licenza ufficiale)

Creato/aggiornato `config_override.php` nella root VTE con il bypass documentato in `modules/YeastarCTI/docs/SPECIFICHE_SVILUPPO.md`:

```php
<?php
/**
 * Override configurazione VTE.
 *
 * YeastarCTI: bypass gating licenza UI fino a registrazione su LicenseManager
 * (vedi Impostazioni → Yeastar CTI → Licenza, oppure chiave offline YCTI1:...).
 */
$GLOBALS['YEASTAR_CTI_PASSPARTOUT'] = true;
```

`index.php` e `YctiBootstrap.php` caricano `config_override.php` → la variabile è visibile a `YctiLicense::isUiAllowed()` su tutte le richieste.

### Verifica post-fix

| Campo | Valore post-fix |
|-------|-----------------|
| `passpartout_set` | `true` |
| `license_status` | `active` (source: `passpartout`) |
| `ui_allowed` | `true` |
| Eventi `returning 403 license blocked` | **0** |

Console browser: nessun 403 su `PollEvents.php` / `PresenceStatus.php`.

---

## File modificati

| File | Azione |
|------|--------|
| `vte23083_2711/config_override.php` | **Creato** — `YEASTAR_CTI_PASSPARTOUT = true` |

Nessuna modifica ai file del modulo `modules/YeastarCTI/` (solo configurazione istanza).

---

## Soluzione definitiva (produzione)

Quando la licenza è disponibile, **rimuovere** il passpartout e registrare la licenza:

1. **Impostazioni → Yeastar CTI → Licenza**
2. Registrazione con **OTP** via email admin, oppure chiave offline `YCTI1:...` dal LicenseManager
3. Verificare posti (seats) ≥ numero interni mappati in `yeastar_user_ext`
4. Eliminare o commentare in `config_override.php`:
   ```php
   // $GLOBALS['YEASTAR_CTI_PASSPARTOUT'] = true;
   ```
5. Ricaricare VTE e confermare assenza 403 + licenza `active` in Settings

Tentativo registrazione trial automatica senza OTP (CLI): risposta server `"Email o OTP non validi"` — serve flusso admin con OTP.

---

## Riferimenti codice

| Componente | Path |
|------------|------|
| Gating licenza AJAX | `modules/YeastarCTI/lib/YctiAjaxBootstrap.php` → `ycti_require_license_ui()` |
| Logica licenza | `modules/YeastarCTI/lib/YctiLicense.php` → `isUiAllowed()`, `getLicenseInfo()` |
| Cache licenza | `modules/YeastarCTI/logs/ycti_license.dat` |
| Log check server | `modules/YeastarCTI/logs/ycti_license_check.log` |
| UI frontend CTI | `modules/YeastarCTI/js/yeastar_cti.js` |
| Documentazione plugin | `modules/YeastarCTI/docs/SPECIFICHE_SVILUPPO.md` |

---

## Checklist porting su altra istanza

- [ ] Verificare in console assenza/presenza 403 su `PollEvents.php`
- [ ] Controllare `ycti_license_check.log` o Settings → Yeastar CTI → stato licenza
- [ ] Se `not_found`: registrare licenza **oppure** passpartout temporaneo in `config_override.php`
- [ ] Non usare passpartout in produzione clienti con licenza commerciale attiva
- [ ] Webhook/cron funzionano anche senza licenza UI (non confondere con questo problema)

---

## Problema correlato (non risolto in questa sessione)

Nei log `logs/yeastar_webhook.log` compaiono errori separati sulla creazione record **Chiamate**:

```
[CDR] ERRORE creazione Chiamata: Permission to perform the operation is denied for name
```

Probabile causa: permessi profilo VTE dell’utente `smownerid` usato dal queue worker sul modulo Chiamate.  
**Non correlato** al 403 AJAX licenza — da trattare in sessione dedicata.

---

*Documento generato il 2026-07-09 — sessione debug YeastarCTI 403 / licenza UI*
