Cette page décrit ce que fait le serveur, pas ce que votre régulateur exige. Faites correspondre ces mécanismes à vos propres obligations légales (RGPD, nLPD suisse, règles sectorielles) avec votre conseil juridique.
Journalisation du courrier
La journalisation copie en silence le courrier correspondant vers une boîte journal ou un archiveur externe, par organisation. C’est l’équivalent des fonctions Postfixalways_bcc / sender_bcc_maps / recipient_bcc_maps, traité comme des données plutôt que comme des éditions de fichier de configuration. L’usage typique est une obligation d’archivage (art. 30 RGPD) ou une règle sectorielle.
Désactivée par défaut. Pas de règles, pas de journalisation : rien n’est copié tant qu’un administrateur n’a pas créé de règle.
Les règles
Une règle de journalisation a trois dimensions :
Les deux formes de destination diffèrent par la garde du contenu :
- Boîte : la copie est réingérée dans une boîte journal locale. Elle reste donc dans le périmètre de stockage de l’organisation, sous la même protection au repos que tout le reste du courrier.
- Externe : une copie est relayée vers un archiveur externe (un service d’archivage dédié ou un autre serveur que vous exploitez).
Invariants
- Le trafic de relais n’est jamais journalisé. Le courrier relayé pour les comptes
serviceconserve la promesse de rétention éphémère : un smarthost n’archive pas le courrier de ses clients. - Une copie journal n’est jamais rejournalisée. Une copie archivée dans une boîte y est rangée directement et n’est jamais remise une seconde fois. Une copie relayée vers un archiveur externe porte un en-tête
X-Oximail-Journaled: quand elle revient par le port 25 depuis une adresse detrusted_ips, l’en-tête est cru et la copie n’est pas journalisée de nouveau. Depuis toute autre adresse, l’en-tête est retiré à l’arrivée : un expéditeur ne peut pas se soustraire à l’archivage en le tapant, et la limite de sauts de la RFC 5321 borne un aller-retour mal configuré. À l’intérieur du serveur, une copie se reconnaît à la ligne de file qui la porte, jamais à un en-tête. - Les destinations sont isolées par organisation. Une règle ne peut viser qu’une boîte de sa propre organisation (l’isolation par tenant de la couche de stockage, ADR-015).
- La journalisation est au mieux, et ne bloque jamais le courrier. Un échec de journalisation est journalisé bruyamment, mais le message remis ou soumis n’est pas affecté : l’archivage ne doit pas devenir une panne de remise (ADR-017).
- Une évaluation par message, sur chaque chemin vers une boîte. Les règles entrantes s’appliquent au courrier arrivé par le port 25, au courrier interne (un membre qui écrit à un collègue), aux redirections locales et aux avis de remise, une fois par message quel que soit le nombre de destinataires locaux : un message à cinq collègues donne une copie par destination. Les règles sortantes s’appliquent une fois après la mise en file d’une soumission non relayée. Le courrier interne peut donc être journalisé dans les deux sens, une fois comme courrier sortant de l’expéditeur et une fois comme courrier entrant des destinataires.
Gérer les règles
Par la CLI :JournalingRule/get et JournalingRule/set sous la capacité urn:oximail:params:jmap:v2:admin (réservée aux administrateurs).
Effacement de compte (RGPD art. 17 / DSAR)
Supprimer un compte n’est pas unDELETE : c’est une opération en plusieurs étapes à portée juridique, et un crash ou une relance opérateur ne doit jamais la laisser à moitié faite ni l’exécuter deux fois. OxiMail exécute chaque effacement de compte comme une machine à phases enregistrée en base :
- Au plus un effacement vivant par compte, par construction. Un index unique partiel rend impossible un second effacement concurrent du même compte, à travers les processus : une suppression par l’API d’administration et une suppression CLI sur la même machine ne peuvent pas se courir dessus.
- Durable et reprenable. Chaque phase enregistre sa progression. Un pilote qui meurt en vol (crash, timeout de proxy) laisse un travail qu’un worker de maintenance adopte et reprend, grâce à un bail avec battement de cœur ; un balayage au démarrage rattrape les orphelins. La passe est découplée de la connexion HTTP qui l’a demandée : un timeout de proxy ne peut pas l’annuler.
- Visible quand ça coince. Un travail garé sur un échec durable apparaît dans
oximail erasure list --stucket dans la métriqueoximail_erasure_jobs_stuck: un effacement mis en file atteint un état terminal ou se signale comme bloqué, jamais à moitié fait en silence. - Des adaptateurs minces. L’API d’administration et la CLI pilotent la même orchestration ; il n’existe qu’un seul moteur d’effacement.
Ce que fait chaque phase
- Gel de l’agence. Avant tout effacement, le compte perd sa capacité à produire de nouvelles données : il est désactivé, ses tokens sont révoqués, la soumission SMTP répond
550, les réponses automatiques d’absence sont supprimées, et ses envois planifiés ou en fenêtre d’annulation sont annulés à la source. L’effacement refuse ensuite d’avancer tant qu’il reste une entrée sortante non remise dans la file (échec bruyant ; la file se vide dans la limite de la durée de vie des réessais, ou un opérateur annule les entrées via l’API de file). Chaque chemin qui émet du courrier au nom d’un compte est nommé dans un registre avec la garde qui l’arrête, sous le contrôle d’un audit de source (ADR-118). - Caviardage des résidus. Les copies du courrier que le partant a envoyé à ses collègues continuent de le nommer dans les boîtes des survivants, dans les colonnes structurées et dans les en-têtes bruts du message. La passe réécrit ces copies par le chemin d’ingestion normal : les en-têtes d’identité se replient sur une sentinelle non routable (
former-user@<domaine>.invalid), les colonnes d’adresses sont caviardées en tenant compte de la structure (un destinataire homonyme n’est jamais touché), et le corps du message n’est pas modifié : c’est la correspondance des destinataires. Les jetons dans les Message-ID, les propres enregistrements À/Cc des survivants et les apparitions limitées aux en-têtes de trace sont documentés hors périmètre. Une copie placée sous le séquestre légal d’un collègue est laissée telle quelle, puisque le séquestre fige la pièce comme preuve (RGPD art. 17, §3, e) : l’effacement s’achève pour tout le reste, la copie est consignée avec les adresses du partant scellées sous la clé de l’organisation, et le travailleur de maintenance des effacements la caviarde quand le séquestre expire ou est levé.account delete --dry-runcompte ces copies à l’avance, etoximail doctor(erasure_held_residue) nomme celles qui attendent encore et la date de la première fin de séquestre. - Retrait de l’identité. Les principals d’annuaire du sujet sont nettoyés de leurs données personnelles et conservés comme pierres tombales : des ancres de graphe qui empêchent l’historique de chat et de notifications d’être réattribué en silence, sans porter aucune identité. Chaque droit du partant est retiré de chaque carte
shareWith(chaque propriétaire survivant reçoit un changement enregistré pour se resynchroniser), les instantanés d’acteur dans les notifications des survivants perdent nom et adresse, et un principal en pierre tombale est refusé comme nouveau bénéficiaire : un repartage ne peut pas défaire le retrait. Les principals de ressource et de lieu que le partant avait simplement créés (salles de réunion) survivent intacts : ils appartiennent à l’organisation. - Balayage des données. Les lignes du compte sont supprimées table par table, ses documents sont retirés de l’index de recherche plein texte, et ses fichiers de blobs sont supprimés du disque dès que plus rien d’autre ne les référence (il n’y a plus de crypto-suppression depuis ADR-148 : le contenu est écrit en clair, effacer veut donc dire supprimer). Le balayage échoue bruyamment sur une vraie erreur au lieu de déclarer un succès par-dessus des lignes survivantes.
- Complétion. Un unique enregistrement durable et non identifiant est écrit : des compteurs de résultat (dont
held_residue, les copies qu’un séquestre légal garde encore) plus une référence de ticket DSAR optionnelle, rattachés à la pierre tombale d’identité. Tout texte d’erreur sur la ligne du travail est effacé à l’état terminal, pour qu’aucun message d’échec ne puisse transporter une adresse personnelle dans l’enregistrement durable.
Le tampon de réversibilité
L’effacement est volontairement difficile à défaire, mais une erreur d’opérateur (mauvais compte) exige un chemin de récupération honnête. Pendant le retrait d’identité, le delta de clés de chaque droit de partage retiré (les seuls bits du partant, objet par objet, jamais la carte entière) est capturé chiffré avec la clé maîtresse de l’organisation dans un tampon de réversibilité à durée de vie annoncée :- 7 jours par défaut, ancrés au moment de la mise en file ; surcharge par organisation
erasure.reversal_ttl_days. oximail erasure undo <job-id>fusionne chaque delta dans la carte actuelle sous comparaison-et-échange : une modification intermédiaire du propriétaire n’est jamais écrasée.--grantee <principal>restaure les droits sur un autre principal vivant : après un effacement terminé, c’est la vraie récupération. On reprovisionne la personne, puis on réattribue à sa nouvelle identité (validé, provenance auditée).- Passé l’échéance, la restauration est refusée côté serveur, même si les lignes existent encore physiquement ; un faucheur supprime les lignes expirées sans condition.
Suivre une demande depuis la surface d’administration
Un administrateur supprime un compte depuis la surface d’administration parPrincipal/setAdmin {status: "deleted", erasureRef} (API d’administration) : le compte est gelé, purgeAfter dit quand le travailleur d’effacement ordonnera la purge, et status: "active" avant cette date l’annule. ErasureJob/queryAdmin et ErasureJob/getAdmin (capacité d’administration, lecture seule) suivent la demande de là jusqu’à son enregistrement de complétion, là où seule la console la montrait (erasure list). Une demande vit à deux endroits au cours de sa vie, et les deux sont servis :
- Programmée : aucun job n’existe encore. L’
idde l’objet est celui du compte,jobIdvautnull,phasevaut"scheduled", etblockeddit pourquoi et depuis quand, si le travailleur l’a trouvée échue et refusée (une conservation légale, une garde orpheline). - Job : une fois mise en file, la demande continue comme son job (
id=jobId,phasel’une des phases ci-dessus), avec les mêmesaccountIdeterasureRef; l’objet programmé répondnotFoundà partir de là. Un compte peut porter plusieurs jobs au fil du temps (un nouvel effacement aprèserasure undo), c’est donc l’identifiant du job qui désigne un job.
principalId, email tant que la ligne du compte existe, purgeAfter, enqueuedAt, updatedAt, reversalDeadline, actor, error, stats et, une fois achevé, completion ({auditId, at}), l’enregistrement que résout erasure prove. La date de chaque phase intermédiaire n’est pas servie : le substrat garde la phase courante et la date de son dernier changement, pas un historique. queryAdmin filtre sur phase, erasureRef et principalId, sans tri ni position : les suppressions programmées d’abord, la purge la plus proche en tête, puis les jobs, du plus récent au plus ancien. Il n’existe aucun verbe d’écriture ; la preuve reste à la console.
Prouver que c’est fait
Donnez une référence DSAR à l’effacement au moment de la suppression, et résolvez-la plus tard :prove résout la référence vers l’enregistrement de complétion non identifiant : la preuve durable que l’effacement de l’art. 17 a été exécuté (responsabilité de l’art. 5, §2). L’enregistrement vit aussi longtemps que le journal d’administration, 365 jours ; au-delà, il est purgé et la pierre tombale reste, sans référence. Le code de sortie 1 signifie qu’il n’y a pas d’enregistrement, et le message nomme les trois lectures, pour que « purgé » ne se lise pas « jamais arrivé » : l’effacement n’est pas achevé (oximail erasure list), il a été lancé sans --dsar, ou il s’est achevé il y a plus de 365 jours et son enregistrement a disparu.
Effacements et restaurations
Une sauvegarde est une copie du passé : restaurer celle d’avant un effacement ramène la personne effacée (compte, courrier, nom) et retire de la base toute trace que l’effacement a eu lieu. Rien dans les données ne permet de le voir. La réponse des autorités est qu’une sauvegarde peut garder des données effacées jusqu’à sa rotation, à condition qu’une restauration ne les remette pas en usage. OxiMail en fait une propriété de la machine plutôt qu’une ligne de procédure :- Le registre des effacements. Chaque effacement achevé ajoute une ligne à
erasure-ledger.jsonl, à côté de la base : organisation, compte, travail, instant, référence DSAR. Des identifiants seulement, ni adresse ni nom. La ligne est écrite avant que le travail soit marqué achevé : un effacement que le registre ne connaît pas n’est pas achevé. Le registre vit dans le répertoire de données, donc toute sauvegarde l’emporte, quel que soit l’outil (instantané de l’hyperviseur,oximail backup, autre outil), et comme il ne fait que grandir, la copie la plus récente couvre la restauration de n’importe quelle sauvegarde plus ancienne.oximail restoregarde l’union de la copie de la machine et de celle de la sauvegarde. - Une personne ramenée par une restauration est gelée, puis effacée à nouveau. Un compte que le registre nomme et que la base contient de nouveau est gelé (pas de connexion, pas de livraison en son nom, rien n’est envoyé en son nom) par
oximail restore, par le serveur au démarrage avant d’accepter des connexions, et à chaque passage de maintenance. La métriqueoximail_erasure_resurrected_accountsles compte, etoximail doctor(erasure_ledger) échoue.oximail erasure replayles liste ;--applyrefait l’effacement avec sa référence DSAR d’origine.--from <copie>lit une copie plus récente du registre gardée ailleurs et, avec--apply, ajoute ses lignes au registre local. - La fenêtre qui reste, ce sont les effacements achevés après la sauvegarde restaurée.
[erasure] ledger_hookla ferme : une commande à vous, lancée après chaque effacement achevé avec le chemin du registre en dernier argument (scpvers une autre machine,rclone,restic). Pas de shell, chemin absolu. Sans crochet,doctor erasure_ledgeravertit tant qu’un effacement est plus récent que la dernière sauvegarde que la machine connaît ; avec, tant que le crochet n’a pas expédié les dernières lignes.
Le journal d’administration
Tout acte d’administration écrit une ligne dans le journal d’administration, en ajout seul et chaîné : l’empreinte de chaque ligne couvre la précédente, par chaîne (tenant, compte), si bien queverify dit si une chaîne a été coupée ou altérée. Ce que la chaîne garantit, c’est la preuve d’altération, pas la longévité : la rétention est de 365 jours (AUDIT_LOG_RETENTION_DAYS, annoncée en retentionDays sur la capability auditlog), contre une durée de sept ans qu’aucune norme ne soutenait ; une purge est ancrée pour que la chaîne reste vérifiable après elle.
- Un acte du nœud lui-même a un domicile. Appairer une organisation, la suspendre, tourner la clé de travail, enrôler ou retirer une racine, activer le journal des accès : ce sont des actes du compte de personne, et le journal ne leur laissait qu’une ligne de service. Ils vivent désormais dans la chaîne propre du tenant, avec un enregistrement d’origine (genèse, purge ou attestation, le point avant lequel rien n’est jugé).
oximail audit-log list --tenantla lit,--accountlit la chaîne d’une personne ;audit-log verifyparcourt chaque chaîne du tenant ancrée sur son origine (sortie 0 valide, 1 dégradée, une chaîne ancienne sans ancre ou des lignes non hachées, 2 rompue), prend--sincepour une fenêtre et--witness <hash>pour une empreinte de queue lue hors de la box, la sauvegarde d’hier, qui doit encore être dans la chaîne ;audit-log attest --by <nom> --applyrebase la réconciliation de l’état contre l’histoire à maintenant et ajoute une ligne d’attestation chaînée, refusée si la chaîne n’est pas valide.doctor audit_logparcourt la chaîne du tenant et chaque chaîne de compte, et juge à chaque ronde la tête de chaque chaîne de compte contre son origine. - Une chaîne est ancrée dès sa première ligne. Le point d’écriture dépose une origine de genèse avec la première ligne hachée d’un sujet, dans la même transaction ; les sujets antérieurs ont été rattrapés une fois. Auparavant, seule une purge de rétention écrivait l’origine d’un compte, ce qui ne peut arriver avant l’horizon de 365 jours, si bien qu’
audit-log verifysortait1sur toute box saine pendant la première année de chaque compte :unanchoredredevient l’exception qu’il prétend être. - Un acte sur quelqu’un se range sous cette personne. Poser le mot de passe de quelqu’un (
account.password_set, distinct d’account.password_changed, une personne qui change le sien), couper une de ses sessions d’appareil ou un de ses mots de passe d’application, rediriger son adresse à son départ : la ligne vit dans la chaîne de la personne à qui l’acte arrive, l’administrateur nommé en acteur, parce que la question qu’on pose en incident est « qu’est-il arrivé à ce compte ». Un octroi de compte et son retrait (celui d’un départ compris) s’écrivent dans la chaîne du propriétaire, un octroi de portée organisation dans celle du tenant (account/grant.set,account/grant.revoked,tenant/grant.set,tenant/grant.revoked, avec le bénéficiaire et l’état précédent : collections, niveau, échéance), dans la même transaction que la ligne d’accès : un octroi qu’on ne peut pas journaliser n’est pas écrit, et une échéance qui n’est pas un instant RFC 3339 est refusée avant toute écriture. Par bénéficiaire, on retrouve les lignes par action (audit-log list --action) et par le champgrantee, pas par une seconde ligne. - L’acteur est le compte qui parle. Une ligne nomme le compte authentifié, jamais le propriétaire qu’un appel
shared:du même lot désignait : un administrateur qui glissait unPrincipal/setAdmindans un tel lot faisait écrire une ligne dont l’acteur et la chaîne étaient le propriétaire du compte partagé, sa propre identité n’apparaissant nulle part. - Un verbe de console lancé par un agent le dit. Un binaire peut servir les verbes de console à un agent sur la box (un verbe par outil, un mutateur montre d’abord son essai à blanc) ; le lanceur déclare le canal dans l’environnement (
OXIMAIL_CLI_CHANNEL=agent, avecOXIMAIL_CLI_DECIDED_BY, le nom de la personne qui a ouvert la session, exigé à côté ; toute autre valeur refuse la commande). Une telle ligne se range encli-agentsous le nom de cette personne (decidedBy), jamais enclicomme une commande qu’elle aurait tapée, et une lignecli-agentsans nom est refusée : « cette personne a validé un essai à blanc qu’un agent lui présentait » est le fait qu’on cherche six mois plus tard. - Une ligne écrite pendant une requête dit d’où elle vient : l’adresse du client que le transport a résolue (proxy compris) et la session d’appareil à laquelle l’identifiant appartient, transmises par la requête, jamais déclarées par un gestionnaire ; pas de
User-Agent, une affirmation que le client choisit. L’identité de l’acteur est réservée au lecteur administrateur. - Une réécriture légitime est un acte de la chaîne. La rédaction d’effacement et un rekey de principal réécrivaient des colonnes hachées dans le dos de la chaîne, si bien que chaque ligne touchée se lisait altérée ; elles écrivent désormais par la chaîne.
- L’effacement ne touche plus le journal. Ses identifiants sont des pseudonymes qui vivent douze mois au plus, couverts par la finalité (sécurité et imputabilité), et la personne effacée en est informée ; l’ancienne passe de désidentification a disparu.
- Le registre des noms d’action est fermé, avec une porte. Trois noms d’action sans émetteur ont été retirés, une ligne portant un vecteur de causalité est refusée à l’écriture, et une extension liée au binaire journalise par le préfixe
ext:<module>/<objet>.<verbe>au lieu de faire échouer chaque mutation auditée enserverFail. - Sur le fil,
AuditEvent/get|query|changes|verifysousurn:ietf:params:jmap:auditlog. Un administrateur de locataire lit la chaîne d’un autre compte en la nommant (accountIdsurget,queryetverify) ; quiconque d’autre nomme un autre compte reçoitforbidden, et un identifiant qui ne désigne aucun compte de l’organisation se lit comme une liste vide, jamais comme un oracle d’existence (verifyrépondaccountNotFound).AuditEvent/getsert pour chaque événementhash,prevHash,chainFormat,actorCommitmentetsubjectCommitment, jamais les nonces, pour qu’un vérificateur sans la base recalcule les liens.AuditEvent/verifynomme sa portée :accountIdest honoré, jamais remplacé en silence par le compte de l’appelant ;scope: "tenant"(administrateur) parcourt toutes les chaînes que l’appelant administre, celle du tenant comprise, l’une après l’autre ; sansafternicursor, la marche part de l’origine et juge la tête (head:genesis,purged,attested,unanchored,removed,origin_invalid;windowedpour une marche partielle) ;witness {id, hash}, une queue gardée d’une réponse antérieure, doit encore être dans la chaîne avec cette empreinte, sinonvalid: false,reason: "witness_absent". Elle parcourt au plusmaxEventsPerVerify(2000) événements : une plage plus large est tronquée, jamais refusée, la réponse dittruncated: trueet portenextCursor, opaque et exclusif, qui encode la jonction que le serveur revérifie à la reprise (aucun événement compté deux fois, aucun trou à la frontière ; une jonction disparue ou changée est refusée nommément ;nextAfterest encore envoyé pendant un cycle). La réponse compte ce qu’elle n’a pas pu juger au lieu de le cacher (chainsWalked,chainsBroken,unhashedCount,deidentifiedCount,tailInFuture), nomme son dernier événement avec sa chaîne (tail {id, hash, accountId}), et une rupture avec la sienne (brokenAtId,brokenAccountId), puisque sousscope: "tenant"un identifiant seul ne pourrait pas s’ouvrir ;reasonest un code fermé, la phrase du vérificateur est dansdescription. Une borne de temps surverifyouqueryest retamponnée dans la forme canonique avant d’atteindre le SQL, ou refusée en nommant la valeur : elle était comparée comme du texte, si bien que16/09/2026laissait tout entrer, que10:30:00Zsans millisecondes excluait l’instant même qu’elle nommait, et que les deux annonçaientvalid: true.
Le journal des accès aux données
Qui a lu, listé, écrit, partagé, exporté ou détruit les données d’une autre personne (ADR-150) : un second journal, dans sa propre table et sa propre chaîne, servi par les mêmes méthodesAuditEvent sous une capability distincte, urn:oximail:params:jmap:accesslog, avec la même rétention de 365 jours. Le sujet est le propriétaire de la donnée, l’acteur celui qui lit : Bob qui lit la boîte partagée d’Alice est une ligne dans le journal d’Alice, acteur Bob. Un assistant IA qui lit pour un compte est actorKind: agent.
- L’accès par un tiers seulement. Les lectures et écritures d’un propriétaire sur ses propres données ne sont pas tracées (le cas du jeton volé se voit par la session d’appareil, l’adresse et le journal d’exploitation). Un bénéficiaire, un administrateur, un agent, un lien de partage, un export le sont.
- Le grain est l’action nommable, une ligne par invocation admise porteuse de données, jamais une par objet :
opparmiread,list,write,share,export,destroy,levelparmimetadata,content, le type de ressource et une liste bornée des identifiants servis, indexée pour que « qui a lu X » ait une réponse ; unFETCH 1:*IMAP est une ligne avec un ensemble d’UID. Les listes structurelles (boîte, date, mots-clés, identifiants) sont exemptes, même entre comptes ; une liste dont le filtre porte sur le contenu (text,body,subject,from,to) est tracéelist/content, si bien que « Bob a cherché X dans la boîte d’Alice » est nommable. Un refus laisse aussi une ligne (outcome: denied). Hors périmètre, dit clairement :Core/*,/changes, l’annuaire, et toute lecture sans acteur humain (Sieve, règles, indexation, anti-spam). - Écrit au seam du répartiteur après le gestionnaire, un seul site pour quelque 150 méthodes, plus trois portes hors JMAP :
/jmap/download,FETCHIMAP,GET/REPORTDAV ; la décision en nomme une quatrième, l’export des données du sujet (art. 15 / art. 20), qui n’est pas encore servie : il n’existe aujourd’hui ni verbe ni méthode d’export DSAR, et le mode de déprovisionnementexportest refusé plutôt que de supprimer sous un nom qui promet la conservation. Là où un agenda partagé a réduit ou retiré des événements, la ligne porte les comptesreducedToTimeetwithheld. - Activé par locataire, une personne décide.
oximail tenant update --access-log on --by <nom> --access-log-mode strict|best-effort:--byest un nom déclaré écrit sur la ligne d’audit de la bascule, parce qu’une mesure de contrôle a une personne qui en répond, et la ligne est purgée avec le reste, si bien quedoctoravertit à 185 jours que la décision doit se renouveler.strictrefuse un accès qu’il n’a pas pu tracer (rien ne sort sans trace ; les pannes du journal deviennent celles du locataire) ;best-effortle sert, compte l’échec suroximail_access_log_append_failed_totalet traceSERVED UNLOGGED. Un mode que le serveur ne sait pas lire est strict. La bascule se lit toutes les 30 s ;--access-log offexige--yes, est une ligne d’audit, jamais une purge, et n’existe qu’à la console. Désactivé : rien n’est écrit, rien n’échoue, la capability n’est pas annoncée. Le coût, mesuré : nul sur l’accès d’un propriétaire à ses propres données, environ un quart de milliseconde par appel tracé au p50, un plafond de quelques centaines de lignes tracées par seconde et par box. - La lecture. L’administrateur du locataire, et le sujet pour ses propres lignes ; un bénéficiaire n’apprend jamais qu’il a été journalisé ;
sourceIpet la session sont réservés à l’administrateur.oximail access-log list --account <sujet>(les lignes d’une personne),--object-type Email --object-id <id>(« qui a lu X »),--actor <email> --since <ts>(« qu’a fait tel collaborateur », à travers les sujets, refusé sans fenêtre) ;access-log verifyparcourt les chaînes et rapporte la première rupture (sortie 2). Aucun verbe de suppression n’existe, ni JMAP ni CLI.doctor access_logrend l’âge de la dernière ligne, le mode et la chaîne sur le dernier jour, et avertit sur un locataire sans journal.
oximail journal list lit les deux journaux ensemble, du plus récent au plus ancien, pour une personne (--account), un objet (--object-type + --object-id) ou un acteur (--actor --since), chaque ligne nommant son journal, les comptes par adresse, l’adresse du client et la session d’appareil. Il ne prouve rien : les deux verbes verify le font.
Les textes envoyés à des tiers
Quelques messages quittent le serveur au nom de l’exploitant, vers des personnes qui n’ont pas de compte ici : le code qui confirme une destination de transfert est le premier. Qui en reçoit un doit savoir qui est responsable, où son adresse est traitée et à qui écrire. Ces faits sont déclarés, jamais déduits du réseau : l’organisation déclare son responsable et son pays d’établissement, l’instance son exploitant et les pays où les données sont traitées (l’identité légale d’une organisation). Le texte mondial ne cite aucune loi. OxiMail tourne dans toutes les juridictions : les textes qu’il livre disent ce qui se passe (le responsable, les pays de traitement, le contact, l’échéance) sans nommer la loi ni l’autorité d’un pays. Le rappel de départ deoximail account offboard --grant-mailbox-to suit la même règle. Il dit que l’accès ouvre chaque dossier du courrier de la personne qui part, un dossier privé compris, qu’elle doit d’abord retirer ses éléments privés, et qu’un élément marqué privé ne s’ouvre pas avant d’avoir vérifié ce que permet le droit du lieu où vous exploitez (privacyReminder en --json).
Une variante nationale ajoute les paragraphes qui nomment une loi. Un exploitant dont le conseil juridique a rédigé le texte d’un pays l’installe sous forme de fichier ; le serveur écrit alors ses paragraphes après le texte mondial, dans la même langue. OxiMail ne livre aucune variante : il n’en publiera une qu’une fois son contenu validé par un praticien.
- Deux textes acceptent une variante.
[forward-confirmation]a dix emplacements, écrits dans cet ordre :law,purposeAndBasis,sourceAndCategories,recipients,retention,rights,objection(un paragraphe à lui),transferSafeguards(une table indexée par fondement de transfert, un paragraphe par pays de traitement dont le fondement déclaré en demande un),authorityetdpo.[departure-reminder]en a un seul,text, queaccount offboardaffiche à côté du rappel mondial (privacyReminderNationalen--json). - Un ensemble fermé de variables, remplies avec l’identité déclarée seulement :
{account},{controller},{hoster},{contact},{dpo},{authority},{countries},{country}. Un emplacement dont le texte nomme une valeur que personne n’a déclarée se rabat sur son compagnon<emplacement>IfUndeclared, ou il est omis (sans bruit pour{dpo}: un délégué à la protection des données n’existe que là où il est désigné). - Un fichier sert en entier ou pas du tout. Une section, une clé ou une variable inconnue, une valeur vide ou qui porte un caractère de contrôle font refuser tout le fichier ; le tiers reçoit alors le texte mondial et le serveur journalise une erreur à chaque message. Une variante ne sert jamais pour une personne physique, ni pour une organisation sans nom déclaré et sans contact déclaré.
- Ce dont la variante a besoin se déclare à la console, rien n’est cherché ailleurs : la subdivision de l’établissement, l’autorité de contrôle, et le fondement de chaque transfert à l’étranger (
adequacy-decision,data-privacy-framework,standard-contractual-clauses,binding-corporate-rules).
oximail doctor dit quel texte reçoivent les tiers de chaque organisation (legal_notice : skipped sans répertoire legal-notices/, fail pour un fichier illisible, warn pour un emplacement qui nomme une valeur non déclarée ou un fichier que l’identité ne permet pas d’utiliser), et quels champs de l’identité manquent encore (legal_identity nomme les champs, jamais leurs valeurs ; une personne physique sans nom est en règle).
Aide-mémoire CLI
Voir la référence CLI pour chaque option, et Exploitation pour les métriques et les workers concernés.