Aller au contenu principal
Version: Cible · roadmap

Permissions

Qui a droit à quoi. Une permission est une politique rule qui porte sur l'acteur plutôt que sur l'action ; elle lit l'identité établie à la porte.

Tout est fermé, les grants ouvrent des opérations​

Par défaut, personne n'a droit à rien. Un profil reçoit des opérations des API du tenant, nommées par leur API : boutique.searchProducts, boutique.createOrder. Une opération qu'aucun profil de l'identité n'a reçue n'est jamais appelée pour elle.

profiles:
anonyme:
when: "identity.authenticated == false"
grants: [boutique.searchProducts, boutique.createOrder]
premium:
when: "identity.authenticated and 'premium' in identity.plans"
grants: [boutique.searchProducts, boutique.createOrder]
support:
when: "'support' in identity.roles"
grants: [paiement.proposeRefund, paiement.createRefund]
manager:
when: "'support-manager' in identity.roles"
grants: [paiement.proposeRefund, paiement.createRefund]
  • Le grant porte sur l'opération, pas sur la skill. Une même opération peut être atteinte par une skill, une tâche de playbook, le submit ou une automatisation : la garder elle, c'est les garder toutes.
  • Les grants s'additionnent entre les profils d'une même identité.
  • Les grants sont le seul endroit qui ouvre. Tout le reste (permissions, gardes, budgets, approbations, sous-identités) ne fait que resserrer ce qu'ils ont ouvert.
  • Le visiteur anonyme n'a pas d'exception : ce qu'il peut faire, le profil anonyme le reçoit.
  • Les opérations forment un ensemble fermé, lu dans l'OpenAPI : un grant qui nomme une opération inconnue est refusé au chargement.
  • Core vérifie le grant au moment où il appelle l'API du tenant, en relisant la config. Même si le graphe compilé se trompait, l'appel serait refusé.

Les permissions resserrent, phase par phase​

Dans ce que les grants ont ouvert, une garde permission réserve un moment précis à certains profils. Chaque phase répond à une seule question :

phasequestionce qui la règle
invokequi peut appeler la skill ?le grant de l'opération lue, puis une permission dans invoke.guards ; au retour, les kinds classent les items
presentquels kinds montre-t-on, et à qui ?une permission dans kinds.<k>.present
selectqui peut choisir quel kind ?une permission dans select ou kinds.<k>.select
submitqui peut soumettre ?le grant de l'opération d'écriture, et submitted_by

Une skill n'a pas de droit à elle : elle est utilisable si les opérations qu'elle appelle sont accordées, et si ses permissions le permettent. Un playbook s'ouvre si ses tâches requises sont faisables. Une automatisation n'a pas de profil à elle : ce qu'elle lance agit sous le propriétaire de la room qu'elle désigne (owner), avec ses grants.

Pour une règle qui ne sert qu'une fois, une garde require sur l'identité suffit, sans créer de profil : require: "'phone' in identity.verified".

Quand une preuve peut ouvrir la règle, Core ne refuse pas seulement : il demande l'authentification, avant l'appel pour invoke et present, au choix pour select, au submit pour submit, puis relance l'appel. Voir Demander l'authentification.

Ce qu'un profil voit : la permission dans present​

Les clients qui ne sont pas premium ne voient pas les produits premium :

skills:
- name: articles
invoke: {method: searchProducts}
kinds:
premium:
when: "$fields.tier == 'premium'"
present: {guards: [{permission: {profiles: [premium]}}]}
present:
fields:
name: {from: name, type: text, role: title}
tier: {from: tier, type: text}

Une permission dans present est une règle de sécurité, pas d'affichage :

  • Core retire l'item du résultat avant le modèle, sur les deux portes. Ni le modèle ni le widget ne le voient.
  • Les comptes se font après le filtre : « 12 produits » ne trahit pas les produits cachés.
  • Ce qu'on ne voit pas, on ne le choisit pas : select hérite de present. Sinon, le modèle pourrait ajouter un produit premium en devinant son id.
  • Quand l'API du tenant sait filtrer, mieux vaut lui passer le filtre, par un paramètre fixé par l'identité (set_by: [identity]). Le produit premium ne sort alors jamais de chez le tenant.

per_profile.present sans permission reste de l'interface : des colonnes en plus pour un manager. Voir Profils.

Réserver un kind au choix​

skills:
- name: rembourser
invoke: {method: proposeRefund}
kinds:
gros-montant:
when: "$fields.amount > 50"
select: {guards: [{permission: {profiles: [manager]}}]} # le support voit, le manager choisit
present:
fields:
name: {from: label, type: text, role: title}
amount: {from: amount, type: price, role: billed}

Le support voit le gros remboursement et peut le signaler ; seul le manager peut le choisir.

Les règles se combinent par intersection : une action est permise seulement si toutes les couches la permettent (station, skill, playbook, profil, sous-identité). Voir Comment les couches se combinent. Que ces couches ne se contredisent pas, c'est le graphe des permissions qui le vérifie au chargement.

Qui soumet​

Le droit de soumettre se règle dans le submit_guard, par submitted_by : le propriétaire vérifié de la room, la personne qui a envoyé l'agent, l'approbateur, un rôle, ou l'agent lui-même sous condition. Celui qui soumet doit aussi avoir le grant de l'opération d'écriture. Voir Le submit.

Les sous-identités déléguées​

Un client de la station crée des sous-identités pour ses agents, sur la page du tenant. Leurs limites — montant, horaires, adresses, skills interdites, confirmation au-delà d'un montant — sont des règles comme les autres. Elles ne peuvent que restreindre ; une limite qui élargirait la station est refusée. La station déclare ce qu'elle permet de limiter dans station.delegation.restrictions.