Salta ai contenuti

Accesso e capacità

Ogni lettura tramite /osl/query è limitata da un modello di capacità + permesso: chi sta chiedendo (una catena di soggetti di delega), cosa ogni policy concede loro sul grafo semantico, e come quelle concessioni si compongono. È fail-closed per costruzione — il default è deny, e qualsiasi cosa non risolta viene scartata, mai indovinata.

Un soggetto è un principal in una catena di delega. Ha uno di tre tipi descrittivi:

Tipo È
human Un utente (username / email)
agent Un agente di IA (con un tag di vendor: Claude, ChatGPT, Gemini, …, o custom)
machine Un workload / service account

L’accesso viene valutato su una catena di principal, radice → foglia. Il soggetto agente è l’ultimo anello. La composizione ha due livelli:

All'interno di un principal

Tutte le policy che vincolano quel principal si combinano: le concessioni si uniscono (union), l’obbligazione più forte vince (deny > mask > redact), un deny esplicito prevale, e le condizioni (range di IP, finestra temporale) fanno da gate solo sull’ALLOW — un deny è incondizionato.

Lungo la catena

Gli anelli si combinano con MEET (intersezione): un’entità o colonna è concessa solo se ogni anello la concede. Il tetto di tier è il minimo (il più restrittivo) e l’oscuramento richiesto è l’union di ciò che ogni anello richiede. Un anello vuoto o non scritto fa collassare il meet a deny.

Link 0 (manager): { client, email: cleartext }
Link 1 (employee): { client, email: mask }
────────────────────────────────────────────── MEET
Effective: { client, email: mask } ← the column survives, obligated to mask

Lo scope semantico di una policy è un insieme di binding, ciascuno con chiave un nodeId del domain-map (es. entity:Customer, metric:aum). Un binding dichiara:

Campo Significato
attributeGrants[] Concessione per attributo: cleartext, mask, o deny
filters[] (+ filtersBool) Predicati di riga che delimitano quali righe sono visibili
grantedMetrics[] Concessioni di metrica autonome
facetGrants[] Concessione di contenuto per facet (vedi versioni di oscuramento)

Le concessioni sono positive: una colonna non concessa viene oscurata, mai restituita come NULL né scartata in silenzio dallo schema. deny rimuove del tutto una colonna dalla projection; un deny globale della policy prevale su qualsiasi concessione di altri binding.

I facet di contenuto sono governati da versioni di oscuramento con nome — un disaccoppiamento tra un nome rivolto alle persone e un’identità fisica, stabile a livello di byte:

  • Una RedactionVersion ha un nome (l’handle della console, es. "PII básica") e un insieme di tag (le classi di contenuto che oscura, es. {email, phone}).
  • I tag sono l’identità fisica (invariata a livello di byte, usata come chiave di tabella); il nome serve solo per l’authoring.
  • La versione implicita original (senza tag) è la tabella base.
  • Un facetGrant vincola un nome di versione richiesto per facet. La selezione è exact-or-deny: il motore serve la versione memorizzata i cui tag coincidono esattamente, oppure nega il facet — non ripiega mai su una versione più o meno oscurata.
  • Lungo una catena, le versioni richieste si compongono per union degli insiemi di tag (più oscuramento è sempre sicuro).

L’applicazione è server-side, nella cella. Gli esiti:

Situazione Valore restituito Nel risultato?
Concessa cleartext originale
Obbligazione mask ***
Obbligazione redact ⟦redacted⟧ sì (sopravvive per ORDER BY/GROUP BY)
deny / non concessa scartata dalla projection

La sentinella ⟦redacted⟧ significa che la colonna sopravvive con un valore governato (così la forma a valle è stabile), invece di diventare NULL o sparire — ed è ciò che rende i join cross-modali fail-closed e il modello componibile.

La catena non è un header fidato — è un token firmato. La cella conia e verifica un JWT HS256 il cui payload contiene la catena stessa, così un chiamante non può accorciarla o falsificarla senza rompere la firma (una catena assente/non valida → deny). Vedi Autenticazione.

Due operazioni dry-run calcolano la composizione reale senza servire dati (la console Enterprise le espone; le API sono nella cella):

  • :simulate — anteprima di una policy contro una query come soggetto singolo.
  • :simulate-chain — compila l’intero set di policy scritte del tenant su una catena root → leaf (il MEET), restituendo lo scope composto più una ripartizione dei contributi per anello. Un anello non scritto viene segnalato; il meet si svuota in un empty_meet fail-closed.