Vai al contenuto

Navigation Permission Metadata — Phase 2

Scopo e autorità

Phase 2 aggiunge una rappresentazione diagnostica read-only della catena:

NavigationItem → FAB view/endpoint → FAB permission → role → capability metadata → ACL metadata

Le autorità restano:

  • FAB SecurityManager e PermissionView: autorità per permission e ruolo;
  • codice ACL esistente: autorità per tenant, cliente, ownership e query dati;
  • Navigation Registry: osservazionale;
  • Capability model: osservazionale.

Il codice Phase 2 non chiama has_access per concedere accesso, non sostituisce decorator FAB, non aggiorna ruoli/permission, non filtra menu e non decide ACL.

Modello permission

PermissionMetadata raccoglie, quando esposto dalla classe FAB:

  • permission names;
  • view/menu name;
  • endpoint tecnico;
  • class permission;
  • mapping method → permission;
  • base permissions;
  • marker di decorator disponibili senza eseguire funzioni;
  • origine;
  • risoluzione EXPLICIT, INFERRED o UNKNOWN.

Il legacy adapter legge base_permissions, class_permission_name, method_permission_name e marker già presenti. Non inventa associazioni: quando la classe non espone elementi dimostrabili mantiene UNKNOWN.

Role mapping

app/navigation/permissions.py interroga soltanto SecurityManager.get_all_roles() e le relazioni Role.permissions. Produce RolePermissionSnapshot con coppie permission/view-menu e ruolo. Non esegue mutazioni e non contiene utenti, tenant o clienti reali.

Capability metadata

Il vocabolario iniziale è volutamente piccolo e deriva dalle aree osservate nell'audit:

documents.view, documents.manage, ras.view, ras.manage, courses.view, courses.manage, commercial.view, commercial.manage, users.admin, configuration.admin.

Le capability non costituiscono RBAC. La funzione map_item_capabilities produce candidati descrittivi. Permission generiche come can_list, can_show, can_edit, can_add, can_delete, list e save risultano AMBIGUOUS quando non è possibile dimostrare una capability business esatta. Non viene creato un mapping globale autorizzativo.

ACL metadata

AclMetadata descrive solo il requisito osservato: NONE, ROLE_ONLY, TENANT, CLIENT, OWNERSHIP, CUSTOM, MULTIPLE o UNKNOWN, con evidenze testuali e sorgente autorevole current_acl_code. Le aree Documentale, RAS/DVR, Formazione e Commerciale sono marcate MULTIPLE perché l'audit rileva più livelli (tenant, Cliente.users, filtri query, ownership o policy di modulo). Nessun filtro viene eseguito da questo modello.

Authorization chain e matrice

authorization_chains() collega ogni item ai permission names rilevabili, al view-menu name e ai ruoli presenti nello snapshot FAB. role_navigation_matrix() produce righe item × ruolo con permission possedute dal ruolo e stati diagnostici.

Gli stati sono volutamente separati:

  • visible_by_current_menu_logic: UNKNOWN senza un contesto utente/tenant e senza eseguire policy menu;
  • authorized_by_fab: evidenza del match PermissionView/ruolo nello snapshot, oppure UNKNOWN/NOT_OBSERVED_IN_ROLE_SNAPSHOT;
  • data_acl_required: DATA ACL REQUIRED quando i metadata rilevano ulteriori requisiti.

Pertanto menu visibility ≠ endpoint authorization ≠ data authorization.

Gap analysis

gap_analysis() segnala:

  • item senza permission associabile;
  • permission/view-menu presenti nei role snapshot ma senza item di navigazione;
  • endpoint senza permission rilevabile;
  • capability senza mapping (UNMAPPED);
  • permission riutilizzate da più capability candidate;
  • ACL custom/multiple da verificare nel codice autorevole;
  • mapping ambigui;
  • evidenze di controlli manuali su current_user, ruolo, tenant, is_platform_admin, Cliente.users e query.

I gap sono dati diagnostici e non causano errori runtime.

Snapshot

authorization_snapshot() produce JSON serializzabile con semantica esplicita, item, ruoli, matrice e gap. Non include username, dati personali, tenant specifici, clienti o record operativi. L'ordine è deterministico dato lo snapshot FAB fornito.

Limiti

Non è stato aggiunto un endpoint web, una pagina admin o un comando Flask registrato nell'application factory: l'accesso è costituito da utility Python interne utilizzabili da test e diagnostica, senza ampliare la superficie operativa. Un futuro comando CLI potrà chiamare queste utility senza introdurre una nuova fonte di autorità.

Il modello non vede route/API non presenti nel menu, non può certificare has_access per una richiesta reale senza contesto autenticato e non può trasformare la descrizione ACL in una decisione. I risultati UNKNOWN, AMBIGUOUS e DATA ACL REQUIRED sono attesi.

Sintesi diagnostica del progetto

La baseline statica identifica 349 registrazioni add_*, 221 nomi permission, 625 ViewMenu e 1.422 PermissionView nel catalogo PROD. Phase 2 definisce 10 capability metadata. Poiché il registry non è collegato all'application factory e non è stato avviato il bootstrap reale (che può avere side effect), il numero di NavigationItem normalizzati runtime e il mapping ruolo/item completo restano da produrre in un harness isolato.

NAVIGATION_ITEMS: NOT_RUN_RUNTIME — 349 registrazioni add_* staticamente censite; snapshot runtime isolato non eseguito.
FAB_PERMISSIONS_MAPPED: metadata extraction disponibile; conteggio runtime dipende dal SecurityManager fornito.
CAPABILITIES_DEFINED: 10
EXACT_MAPPINGS: 0 dichiarati automaticamente.
PARTIAL_MAPPINGS: 0 dichiarati automaticamente.
AMBIGUOUS_MAPPINGS: prodotti per permission generiche con module scope.
UNMAPPED_ITEMS: prodotti nei gap quando endpoint/view non espongono permission.
CUSTOM_ACL_AREAS: Documentale, RAS/DVR, Formazione, Commerciale e policy IAM/moduli.
UNKNOWN_AUTHORIZATION_AREAS: menu condizionale per utente/tenant, API/blueprint non presenti nel menu e ACL dati non interrogate.

Prerequisiti Phase 3

Prima di introdurre enforcement o collegare il modello a una UI servono snapshot DEV/PROD congelati, matrice endpoint/ruolo/tenant/cliente, decisione sul mapping capability/FAB e test negativi per accesso diretto e isolamento dati. Phase 3 non è iniziata.