Aller au contenu

Accès et capacités

Chaque lecture via /osl/query est limitée par un modèle de capacité + permission : qui demande (une chaîne de sujets en délégation), ce que chaque politique leur accorde sur le graphe sémantique, et comment ces grants se composent. Il est fail-closed par construction — le défaut est deny, et tout ce qui reste non résolu est écarté, jamais deviné.

Un sujet est un principal dans une chaîne de délégation. Il a l’un de trois types descriptifs :

Type Est
human Un utilisateur (nom d’utilisateur / email)
agent Un agent d’IA (avec un tag de vendor : Claude, ChatGPT, Gemini, …, ou custom)
machine Une charge de travail / un compte de service

L’accès est évalué sur une chaîne de principals, racine → feuille. Le sujet agissant est le dernier maillon. La composition a deux niveaux :

Au sein d’un principal

Toutes les politiques liant ce principal se combinent : les grants font union, l’obligation la plus forte l’emporte (deny > mask > redact), un deny explicite prime, et les conditions (plage d’IP, fenêtre horaire) ne conditionnent que l’ALLOW — un deny est inconditionnel.

À travers la chaîne

Les maillons se combinent par MEET (intersection) : une entité ou une colonne n’est accordée que si chaque maillon l’accorde. Le plafond de tier est le minimum (le plus restrictif) et le caviardage requis est l’union de ce que chaque maillon exige. Un maillon vide ou non rédigé réduit le meet à deny.

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

Le scope sémantique d’une politique est un ensemble de bindings, chacun indexé par un nodeId du domain-map (p. ex. entity:Customer, metric:aum). Un binding déclare :

Champ Signification
attributeGrants[] Grant par attribut : cleartext, mask, ou deny
filters[] (+ filtersBool) Prédicats de lignes qui délimitent quelles lignes sont visibles
grantedMetrics[] Grants de métriques autonomes
facetGrants[] Grant de contenu par facette (voir versions de caviardage)

Les grants sont positifs : une colonne qui n’est pas accordée est caviardée, jamais renvoyée comme NULL ni silencieusement retirée du schema. deny retire entièrement une colonne de la projection ; un deny global à la politique prime sur le grant de tout autre binding.

Les facettes de contenu sont gouvernées par des versions de caviardage nommées — un découplage entre un nom orienté humain et une identité physique, stable à l’octet :

  • Une RedactionVersion a un nom (la poignée console, p. ex. "PII básica") et un ensemble de tags (les classes de contenu qu’elle caviarde, p. ex. {email, phone}).
  • Les tags sont l’identité physique (inchangée à l’octet, utilisée comme clé de table) ; le nom n’est que pour l’authoring.
  • La version implicite original (sans tags) est la table de base.
  • Un facetGrant lie un nom de version requis par facette. La sélection est exact-or-deny : le moteur sert la version stockée dont les tags matchent exactement, ou refuse la facette — il ne se rabat jamais sur une version plus ou moins caviardée.
  • À travers une chaîne, les versions requises se composent par union des ensembles de tags (plus de caviardage est toujours sûr).

L’application est server-side, dans la cellule. Les résultats :

Situation Valeur renvoyée Dans le résultat ?
cleartext accordé original oui
Obligation mask *** oui
Obligation redact ⟦redacted⟧ oui (survit pour ORDER BY/GROUP BY)
deny / non accordé retiré de la projection

La sentinelle ⟦redacted⟧ signifie que la colonne survit avec une valeur gouvernée (donc la shape downstream est stable), plutôt que de devenir NULL ou de disparaître — c’est ce qui rend les joins cross-modaux fail-closed et le modèle composable.

La chaîne n’est pas un en-tête de confiance — c’est un token signé. La cellule génère et vérifie un JWT HS256 dont le payload contient la chaîne elle-même, de sorte qu’un appelant ne peut ni la raccourcir ni la falsifier sans casser la signature (une chaîne absente/invalide → deny). Voir Authentification.

Deux opérations en dry-run calculent la composition réelle sans servir de données (la console Enterprise les expose ; les APIs sont dans la cellule) :

  • :simulate — prévisualise une politique contre une query en tant que sujet unique.
  • :simulate-chain — compile l’ensemble complet des politiques rédigées du tenant sur une chaîne root → leaf (le MEET), renvoyant le scope composé plus une ventilation de la contribution par maillon. Un maillon non rédigé est signalé ; le meet se vide en un empty_meet fail-closed.