La surface externe
Deux publics vivent hors de l’administration : celui qui n’a pas de compte du tout, et celui qui en a un chez vous sans être un de vos employés. Le noyau les traite séparément, et séparément de l’administration.
Une page publique, déclarée par le serveur
from kewos.public_pages import PublicPage, register_public_page
register_public_page( PublicPage( slug="rendez-vous", kind="booking", title="public.booking.title", # une clé i18n config={"service_endpoint": "/public/appointment/services"}, ))Le portail public lit GET /public/pages/rendez-vous, trouve le kind, et rend le composant
générique correspondant. Votre module n’écrit aucun écran : il déclare un genre et une
configuration, et l’interdiction n°48 tient toute seule. Le config est opaque pour le noyau :
c’est votre module qui en connaît la forme.
Le portail : chaque client, ses fiches
Un client au portail n’est pas un utilisateur de l’administration. Table distincte, cookie distinct, portée d’API distincte, et aucune élévation possible (interdictions n°27 et n°32).
Pour lui montrer quelque chose, un module déclare quel modèle lui est accessible et par quel champ il en est le propriétaire :
from kewos.portal.access import register_portal_accessible
register_portal_accessible("library_loan", owner_field="member_id")Le filtrage se fait dans l’ORM, pas dans un endpoint. Toute lecture reçoit son
WHERE member_id = <le client connecté>. Exécuté :
adhérents visibles par le client au portail 1 : [(1, 'Alice Nguyen')]sans contexte portail : 4 adhérentsLe même code, la même requête, deux résultats : la barrière ne dépend pas de l’endroit d’où l’on appelle.
Un modèle non déclaré n’est pas filtré : il est refusé
C’est la propriété la plus importante de la page, et elle se voit à l’exécution :
le catalogue (non déclaré) : PortalAccessRefusedError -> model 'library_title' not declared portal-accessible ; portal session refusedPas une liste vide, pas un filtre : un refus. Le défaut par défaut est fermé, donc un module qui oublierait de protéger un endpoint ne peut pas fuiter par lui : la session refuse la requête avant lui. Vous décidez explicitement ce qu’un client voit ; tout le reste n’existe pas pour lui.
Le lien magique
Un client au portail s’authentifie par un lien signé, sans mot de passe : un jeton HMAC compact avec une durée de vie, vérifié sans écrire une ligne en base à l’émission ni à la vérification. Ce n’est pas le même mécanisme que les liens sécurisés, qui, eux, s’adressent à quelqu’un qui n’a aucun compte, même au portail.