Aller au contenu

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érents

Le 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 refused

Pas 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.