
# Visualizza in anteprima una policy dell'organizzazione

`POST /v1/organizations/{org_id}/policies/{policy_kind}:preview` · autorizzazione `organizations:write`

Valuta un oggetto di impostazioni candidato senza salvarlo. Il body è lo stesso previsto per [creare o sostituire una policy](/docs/api/management/organization-policies/put), e il server lo verifica con le stesse regole e con lo stesso controllo del piano, quindi un candidato che `PUT` rifiuterebbe viene rifiutato qui con lo stesso codice di problema. Non viene scritto nulla: nessuna policy, nessuna voce di audit e nessun evento. La richiesta non accetta `If-Match` né `Idempotency-Key`, e la risposta non contiene `ETag`.

La risposta conta gli utenti a cui si applica il candidato (`basis` `users_in_scope`), non gli utenti che verrebbero bloccati, con una sola eccezione: `phishing_resistant` (vedi sotto). Le condizioni che si conoscono solo al momento dell'accesso, o che il servizio delle policy non possiede, non vengono filtrate; `not_evaluated` le elenca in modo che il conteggio non venga mai letto come più di quanto sia.

| Tipo | Utenti conteggiati | `not_evaluated` |
|---|---|---|
| `authentication_methods` | Membri attivi dell'organizzazione | `credentials` |
| `mfa` (`required_for` `admins` o `all`) | Membri attivi dell'organizzazione | `mfa_enrollment`; anche `admin_scope` per `admins` |
| `phishing_resistant` (`required_for` `admins` o `all`) | Membri attivi dell'organizzazione senza una credenziale WebAuthn accettata (`basis` `users_without_webauthn`, vedi sotto) | `credential_policy`; anche `admin_scope` per `admins` |
| `sso_enforcement` `org_context` | Membri attivi dell'organizzazione, meno `bypass_user_ids` | `federated_sign_in` |
| `sso_enforcement` `verified_domains` | Membri attivi, più gli utenti attivi dell'ambiente con un indirizzo email su un dominio verificato di questa organizzazione, meno `bypass_user_ids` | `federated_sign_in` |
| `session` | Membri attivi dell'organizzazione | nessuno |
| `ip_allowlist` | Membri attivi dell'organizzazione | `client_ip`; anche `admin_scope` per `admins` |

Per `phishing_resistant`, il conteggio e il campione sono gli utenti nell'ambito che oggi non possono accedere in modo resistente al phishing: utenti senza una credenziale WebAuthn attiva (una passkey, oppure una chiave di sicurezza usata come primo fattore) che l'allowlist di AAGUID accetta. L'allowlist è quella del candidato, oppure quella dell'ambiente quando quella del candidato è vuota; con un'allowlist, una credenziale conta solo se il suo modello è elencato e la sua attestazione è stata verificata. Le credenziali in attesa, revocate o sospettate di clonazione non vengono contate. `credential_policy` significa che il requisito di attestazione dell'ambiente, la regola della passkey legata al dispositivo e lo stato del modello di autenticatore non vengono applicati, quindi il conteggio può essere inferiore al numero di utenti che verrebbero bloccati. Quando l'ambito contiene più di 10.000 utenti, la risposta ricorre a `users_in_scope` con `passkey_enrollment`. Se i dati delle credenziali non possono essere letti, la richiesta fallisce con `503` e non viene restituito alcun conteggio.

`required_for` `none` e `mode` `off` non contano nessuno. Un membro attivo è un membro la cui membership è attiva e il cui utente non è bloccato; ogni utente viene contato una sola volta. `admin_scope` significa che `admins` viene contato come tutti i membri, che è il modo in cui l'accesso lo applica oggi. Gli utenti di un'altra organizzazione o di un altro ambiente non vengono mai contati.

## Richiesta

| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
| `org_id` | path | sì | ID dell'organizzazione (`org_…`). |
| `policy_kind` | path | sì | Tipo di policy: `authentication_methods`, `mfa`, `phishing_resistant`, `sso_enforcement`, `session` o `ip_allowlist`. Qualsiasi altro valore restituisce `404`. |
| `settings` | object | sì | L'oggetto di impostazioni candidato del tipo, con gli stessi campi previsti per `PUT`. |

Body della richiesta:

```json
{
  "settings": {
    "required_for": "all",
    "allowed_factors": [
      "totp",
      "webauthn"
    ],
    "enrollment_grace_days": 7
  }
}
```

## Risposta

`200 OK`. `sample` contiene al massimo 20 utenti dell'insieme conteggiato, ordinati per ID, con solo l'ID utente.

| Campo | Tipo | Descrizione |
|---|---|---|
| `organization_id` | string | ID dell'organizzazione (`org_…`). |
| `policy_kind` | string | Il tipo di cui è stata visualizzata l'anteprima. |
| `basis` | string | Ciò che `affected_count` conta: `users_in_scope` oppure, per `phishing_resistant`, `users_without_webauthn`. Potrebbero essere aggiunti nuovi valori. |
| `affected_count` | integer | Numero di utenti che `basis` conta. |
| `sample` | array | Al massimo 20 oggetti con `user_id` (`usr_…`). |
| `not_evaluated` | array | Condizioni che il conteggio non filtra: `admin_scope`, `credentials`, `mfa_enrollment`, `passkey_enrollment`, `federated_sign_in`, `client_ip`, `credential_policy`. Potrebbero essere aggiunti nuovi valori. |

```json
{
  "organization_id": "org_01j9xk3m7q8r2s4t6v8w0y2z4a",
  "policy_kind": "mfa",
  "basis": "users_in_scope",
  "affected_count": 2,
  "sample": [
    {
      "user_id": "usr_01j9xk3m7q8r2s4t6v8w0y2z4b"
    },
    {
      "user_id": "usr_01j9xk3m7q8r2s4t6v8w0y2z4c"
    }
  ],
  "not_evaluated": [
    "mfa_enrollment"
  ]
}
```

## Errori

| HTTP | code | Quando |
|---|---|---|
| 400 | `unknown_field` | Il body contiene un campo che non è nello schema. |
| 403 | `plan_feature_unavailable` | Il tipo o l'allowlist di AAGUID richiede un piano superiore; il problema riporta `feature` e `required_plan`. |
| 404 | `not_found` | L'organizzazione non esiste oppure il tipo è sconosciuto. |
| 409 | `domain_not_verified` | `sso_enforcement` con `mode` `verified_domains` richiede un dominio verificato sull'organizzazione. |
| 409 | `connection_test_required` | Attivare `sso_enforcement` (da `off` oppure da nessuna policy) richiede un test di accesso riuscito della configurazione attuale di almeno uno dei `connection_ids` nelle ultime 24 ore. Esegui un test di connessione (`POST /v1/connections/{connection_id}:test`) e riprova. |
| 409 | `organization_pending_deletion` | L'organizzazione è in attesa di eliminazione self-service. |
| 422 | `validation_failed` | Un campo di impostazioni è sconosciuto o non valido; `errors[]` punta a `/settings/…`. |
| 422 | `policy_weaker_than_parent` | L'impostazione è più debole di quella dell'ambiente; `errors[]` punta al campo più debole. |
| 422 | `at_least_one_method` | `authentication_methods` non lascia alcun metodo di accesso. |
| 401 | `unauthenticated` | La credenziale manca, non è valida o è stata revocata. |
| 403 | `insufficient_permissions` | La credenziale non ha l'autorizzazione richiesta. |
| 429 | `rate_limited` | È stato superato il limite di richieste; riprova dopo il periodo `Retry-After`. |
| 503 | `service_unavailable` | Una dipendenza non è temporaneamente disponibile (per `phishing_resistant`, anche quando i dati delle credenziali non possono essere letti); riprova dopo il periodo `Retry-After`. |

## Esempio

```bash
curl -X POST https://api.eu.keenauth.com/v1/organizations/org_01j9xk3m7q8r2s4t6v8w0y2z4a/policies/mfa:preview \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"settings":{"required_for":"all","allowed_factors":["totp","webauthn"]}}'
```

```bash
keenauth organizations policies preview org_01j9xk3m7q8r2s4t6v8w0y2z4a mfa \
  --data '{"settings":{"required_for":"all","allowed_factors":["totp","webauthn"]}}'
```
