canot

Documentation

Une commande, ses possibilités, et un accès pour votre agent. Le détail se demande à l'agent MCP ou se lit ici.

Les commandesSortie en localAvec un agent (MCP)Le scanArrivée sur siteHébergeurs

Canot : les commandes

Canot répète votre départ d'une plateforme de données, dans vos propres comptes. Une commande suffit :

uvx canot drill SOURCE DESTINATION

SOURCE est la plateforme à quitter (Snowflake, Databricks, BigQuery), DESTINATION l'endroit où la copie est écrite. Les valeurs en MY_… sont à remplacer par les vôtres. Canot copie les tables en Apache Iceberg, compare tout, rejoue vos requêtes les plus coûteuses et écrit un dossier de preuve signé. Il ne vous envoie rien : pas de télémétrie.

# Snowflake vers un dossier local
uvx canot drill "snowflake://MY_ACCOUNT/MY_DATABASE?user=MY_USER" ./iceberg

# Databricks vers un stockage S3 de votre choix
uvx canot drill "databricks://MY_WORKSPACE.cloud.databricks.com/sql/1.0/warehouses/MY_WAREHOUSE_ID?catalog=MY_CATALOG" "s3://my-bucket/canot?endpoint=https://s3.internal:9000&region=us-east-1"

# BigQuery vers un hébergeur européen
uvx canot drill "bigquery://MY_PROJECT/MY_DATASET?location=EU" scaleway:fr-par --bucket my-bucket

Si un connecteur manque, Canot affiche la commande exacte à lancer (par exemple uvx --from "canot[bigquery]" canot drill …).

Les commandes

CommandeCe qu'elle fait
canot scan SOURCERadiographie en lecture seule : inventaire, volumes, consommation, ce qui ne part pas, rejouabilité des requêtes. Écrit scan.html (à transmettre), scan.json et des CSV. Voir scan.
canot drill SOURCE DESTINATIONExercice de sortie complet : copie, comparaison table par table, rejeu des requêtes, dossier de preuve signé.
canot demoDémonstration de 30 secondes, sans compte ni données : un distributeur fictif et un exercice complet.
canot verify-evidence DOSSIERVérifie la chaîne et la signature d'un dossier de preuve. --expect-pub refuse un dossier signé par une autre clé.
canot teardown DESTINATIONSupprime les données copiées.
canot snowflake-setupÉcrit le script SQL d'accès en lecture seule à faire relire et lancer par un administrateur. --generate-key crée la paire de clés.
canot bigquery-setupÉcrit le script gcloud du rôle personnalisé en lecture seule.
canot init-tolerancesÉcrit un fichier de tolérances de comparaison à relire avec vous.
canot demo-data CHEMINCrée une base DuckDB de démonstration.
canot mcpServeur MCP : la documentation et l'explication de vos rapports, pour un agent. Voir Avec un agent.

Toutes les commandes acceptent --debug (trace complète en cas d'erreur).

canot drill

Options utiles :

OptionRôle
--bucket NOMObligatoire avec un raccourci d'hébergeur (scaleway:fr-par, ovh:gra, outscale:eu-west-2, ionos:eu-central-1, stackit:eu01, aws:eu-west-3).
--catalog URICatalogue Iceberg : sqlite:///…, ou env:NOM_DE_VARIABLE pour PostgreSQL (canot[postgres]). Par défaut : un fichier SQLite dans le dossier de sortie.
--out DOSSIEROù écrire le rapport et le dossier de preuve (défaut canot-out).
--tables SCHEMA.TABLE …Limiter à certaines tables.
--queries FICHIER.sqlRejouer vos propres requêtes. Par défaut : les plus coûteuses de l'historique de la plateforme.
--top NNombre de requêtes de l'historique à rejouer (défaut 20).
--tolerances FICHIER.tomlTolérances de comparaison (arrondis, horodatages).
--credit-price USDPrix du crédit Snowflake de votre contrat. Sans lui : une fourchette du prix catalogue, datée.
--replay-max-gb NTaille maximale d'une table chargée en mémoire pour rejouer les requêtes (défaut 2).
--key CHEMINClé de signature (défaut ~/.canot/evidence.key, ou la variable CANOT_EVIDENCE_KEY_PATH).

Résultat dans --out : report.html (lisible par un comité), report.json, le dossier de preuve (evidence.jsonl, evidence.sig, evidence.pub) et relire.sql. La signature atteste que le dossier n'a pas été modifié depuis sa signature. Elle n'atteste ni l'auteur ni la date.

canot scan

uvx canot scan "snowflake://MY_ACCOUNT/MY_DATABASE?user=MY_USER" --level 2

--level 1|2|3 (défaut 3) règle jusqu'où lire ; --credit-price remplace le prix catalogue ; --include-sql-text écrit aussi le SQL brut dans un fichier à part (jamais par défaut). Détail des lectures, des droits et des garanties : scan.

Les sources

SourceFormeAuthentification
BigQuerybigquery://PROJET/dataset1,dataset2?location=EU ; sans dataset : tous ceux du projet ; autre projet : bigquery://FACTURATION/projet-donnees.datasetidentifiants applicatifs Google (gcloud auth application-default login)
Snowflakesnowflake://COMPTE/BASE?user=…&warehouse=…&role=…&schemas=A,Bpaire de clés : variable SNOWFLAKE_PRIVATE_KEY_PATH (recommandé) ou SNOWFLAKE_PASSWORD
Databricksdatabricks://HÔTE/CHEMIN_HTTP_DE_L_ENTREPÔT?catalog=…variable DATABRICKS_TOKEN (jeton en lecture) ; connecteur non encore testé sur un vrai compte
DuckDBmaison.duckdbaucune

Sortie en local ou on-prem

Pas de cloud à l'arrivée : un dossier suffit.

uvx canot drill "snowflake://MY_ACCOUNT/MY_DATABASE?user=MY_USER" ./iceberg

Canot écrit la copie au format Iceberg dans ./iceberg et le dossier de preuve dans canot-out/. La copie ne dépend pas de l'outil : DuckDB, Spark ou Trino la lisent. Le fichier relire.sql donne les commandes DuckDB pour recompter chaque table :

duckdb < canot-out/relire.sql
ArrivéeCommande
Dossier local ou monté (disque, NAS, partage)canot drill SOURCE /chemin/vers/le/dossier
Stockage compatible S3 chez vous (MinIO, Ceph, NetApp…)canot drill SOURCE "s3://coffre/canot?endpoint=https://s3.interne:9000&region=us-east-1"
Proxy d'entreprise, autorité de certification interneajoutez &proxy=http://proxy.interne:3128 et &ca=/chemin/ca.pem à l'URL S3
Catalogue PostgreSQL--catalog env:CANOT_CATALOG_URI (mot de passe dans la variable, jamais sur la ligne de commande)

Les clés du stockage passent par CANOT_S3_ACCESS_KEY et CANOT_S3_SECRET_KEY (ou la configuration scw). État de chaque cas (testé ou seulement branché) : sur-site.

Les hébergeurs

scaleway:fr-par, ovh:gra, outscale:eu-west-2, ionos:eu-central-1, stackit:eu01, aws:eu-west-3, avec --bucket. Vérifiez chaque point de terminaison dans la console de l'hébergeur. La qualification SecNumCloud, quand elle compte pour vous, dépend de l'offre précise : voir cibles.

Avec un agent (MCP)

Beaucoup d'équipes travaillent avec un agent. canot mcp lui donne la documentation de Canot et lui explique vos rapports, sans rien envoyer à personne : le serveur tourne sur votre machine.

Installation dans Claude Code :

claude mcp add canot -- uvx --from "canot[mcp]" canot mcp

Ou dans la configuration MCP de votre client (Claude Desktop, Cursor, VS Code…) :

{
  "mcpServers": {
    "canot": { "command": "uvx", "args": ["--from", "canot[mcp]", "canot", "mcp"] }
  }
}

Outils exposés :

OutilCe qu'il fait
commandesListe les commandes et leurs options.
chercher_doc(requete)Cherche dans la documentation et rend les passages.
lire_doc(sujet)Rend une page entière : commandes, scan, sur-site, cibles, ecarts.
expliquer_scan(chemin)Lit un scan.json et le résume : constats, lectures non faites, chiffres estimés, ce qui est à examiner.
expliquer_rapport(chemin)Lit un report.json d'exercice : écarts, tables et requêtes en cause, causes connues du catalogue.

Les outils lisent des fichiers que vous désignez. Ils n'ouvrent aucune connexion à vos plateformes.

Pour les agents qui lisent le web : canot.io/llms.txt et canot.io/llms-full.txt.

Pour aller plus loin

  • scan : ce qui est lu, avec quels droits, et les garanties.
  • sur-site : arrivée locale ou sur votre stockage.
  • cibles : hébergeurs et pays.
  • ecarts : ce que deux moteurs rendent différemment, mesuré.
  • Une aide pour l'exécuter sur votre périmètre : canot.io.

canot scan : ce qui est lu, avec quels droits

Le scan produit scan.html (à transmettre), scan.json et des CSV. Il décrit votre plateforme ; il ne recommande ni de partir ni de rester.

Garanties

  • Lecture seule. Chaque requête passe par une garde avant d'être envoyée : seuls SELECT, SHOW, DESCRIBE et ALTER SESSION SET sont admis. Tout le reste est refusé sans rien envoyer. Les fonctions SYSTEM$ sont refusées aussi.
  • Jamais le contenu des tables. Le scan lit des métadonnées et l'historique d'exécution. Il ne demande aucun droit de lecture sur les données.
  • Le SQL brut n'est pas écrit. Les littéraux sont masqués (WHERE email = ?), les requêtes qui contiennent un mot de passe ou un secret sont comptées puis jetées. Le texte brut n'est écrit qu'avec --include-sql-text, dans scan-sql-brut.json (droits 0600), et le rapport le signale.
  • Identités pseudonymisées. Les utilisateurs et rôles de requêtes sont remplacés par un pseudonyme (HMAC, sel tiré à chaque scan et jamais écrit). Les e-mails, identifiants de connexion et adresses IP ne sont jamais lus. Les chemins de stockage sont réduits au nom du compartiment.
  • Aucune lecture silencieusement perdue. Chaque lecture est consignée « lu » ou « non lu » avec sa raison. Une valeur non lue reste vide, jamais 0.

Niveaux (--level, 3 par défaut)

NiveauContenuDroits en plus
1Inventaire, types de colonnes, volumes, historique facturé, consommation, objets (vues, routines, tâches, stages, partages…), dépendancesmétadonnées et consommation
2+ formes de requêtes normalisées et leur rejouabilité, lectures et écritures par table, politiquesaccès à l'historique des requêtes
3+ rôles propriétaires, outils clients, types d'utilisateurs, capacités réservéesdroits et sessions

Ce que vos droits ne permettent pas est consigné « non lu » dans le rapport (constat F12) : le scan lit ce qui lui est ouvert et dit ce qu'il n'a pas vu.

Snowflake

canot snowflake-setup --generate-key --base MA_BASE écrit le script à relire et à lancer par un administrateur. Il crée un rôle, un entrepôt XS qui se suspend après 60 s, un plafond de crédits, et accorde les rôles de base de Snowflake :

Rôle de baseNiveauSert à
SNOWFLAKE.OBJECT_VIEWER1tables, colonnes, vues, routines, tâches, stages, dépendances
SNOWFLAKE.USAGE_VIEWER1volumes, crédits, historique, chargements
SNOWFLAKE.GOVERNANCE_VIEWER2historique des requêtes, lectures par table, politiques, étiquettes
SNOWFLAKE.SECURITY_VIEWER3rôles, utilisateurs (nom et type seulement), sessions

Jamais demandés : IMPORTED PRIVILEGES, MANAGE GRANTS, IMPORT SHARE, USAGE sur les fonctions, READ sur les stages.

Limites connues : ACCOUNT_USAGE a une latence de 45 minutes à 3 heures (jusqu'à 2 jours pour l'historique de chargement). Le rapport affiche la latence de chaque lecture. ACCESS_HISTORY exige l'édition Enterprise ; sans elle, les lectures par table se déduisent de TABLE_QUERY_PRUNING_HISTORY avec une confiance moyenne.

BigQuery

canot bigquery-setup --project MON_PROJET --member user:… écrit le script gcloud d'un rôle personnalisé canotScanner. Permissions obligatoires : bigquery.jobs.create, bigquery.jobs.listAll, bigquery.datasets.get, bigquery.tables.list, bigquery.tables.get, bigquery.tables.getIamPolicy, bigquery.routines.list, bigquery.routines.get, bigquery.models.list, bigquery.models.getMetadata, bigquery.reservations.list, bigquery.reservationAssignments.list, bigquery.capacityCommitments.list, bigquery.bireservations.get, bigquery.config.get. Optionnelles : bigquery.rowAccessPolicies.list, bigquery.transfers.get, bigquery.connections.list, bigquery.dataPolicies.list.

Jamais : bigquery.tables.getData, ni les rôles bigquery.user ou jobUser.

Points de méthode :

  • Une requête INFORMATION_SCHEMA par région (les régions ne sont pas hiérarchiques : EU ne couvre pas europe-west1). BigQuery facture au moins 10 Mo par requête de ce type, sans cache : le scan plafonne chaque requête et fait un essai à blanc avant.
  • Les volumes viennent de TABLE_STORAGE quand elle est lisible, sinon de l'API tables.get. Canot ne modifie jamais le paramétrage du projet pour l'activer.
  • Sous une politique de lignes, total_bytes_billed est vide : le rapport le dit au lieu d'afficher 0.
  • Le palier gratuit est partagé par le compte de facturation : il n'est pas imputable par projet.

Lire les chiffres

Chaque chiffre porte sa nature : mesuré (lu tel quel), calculé (déduit de mesures, formule donnée), estimé (fourchette et hypothèses), non lu ou non estimé (avec la raison). Les prix sont des repères datés et sourcés ; passez --credit-price avec le prix de votre contrat pour les remplacer. Le coût de lecture et la durée d'une copie sont des estimations de planification : canot drill les remplace par des mesures.

La rejouabilité mesure combien de formes de requêtes sont traduites vers DuckDB et acceptées par lui, sur un squelette vide typé à partir de vos colonnes. Accepté ne veut pas dire résultat identique : seul canot drill compare les résultats. Les requêtes sur des tables hors du périmètre lu, les requêtes dont la plateforme ne donne pas le texte et les requêtes de métadonnées sont comptées à part, hors taux.

Ce que le scan ne voit pas

Les lectures par l'API Storage Read et les requêtes lancées depuis d'autres projets (BigQuery), les consommateurs de partages et RESULT_SCAN (Snowflake), les traitements plus rares que la fenêtre lue (365 jours sur Snowflake, 90 à 180 jours sur BigQuery). La fenêtre réelle est affichée à côté de chaque constat.

Arrivée sur site

Canot écrit la copie au format Apache Iceberg. L'arrivée peut être un dossier de votre réseau, ou un stockage compatible S3 que vous hébergez.

DestinationCommandeÉtat
Dossier local ou monté (NAS, disque, partage)--to /chemin/vers/le/dossiertesté
Stockage compatible S3 hébergé chez vous--to "s3://coffre/canot?endpoint=https://s3.interne:9000&region=us-east-1"testé sur un serveur S3 local (moto)
Catalogue personnalisé (SQLite ailleurs)--catalog sqlite:///chemin/catalogue.dbtesté
Catalogue PostgreSQL--catalog env:CANOT_CATALOG_URI avec pip install 'canot[postgres]'branché, pas encore testé contre un vrai PostgreSQL
Proxy d'entreprise...?proxy=http://proxy.interne:3128 dans l'URL S3branché, pas encore testé
Autorité de certification interne...?ca=/chemin/ca.pem dans l'URL S3 (transmise par AWS_CA_BUNDLE)branché, pas encore testé

Les clés du stockage passent par CANOT_S3_ACCESS_KEY et CANOT_S3_SECRET_KEY (ou la configuration scw). Un mot de passe de catalogue se met dans une variable d'environnement, jamais sur la ligne de commande : --catalog env:NOM_DE_LA_VARIABLE.

Relire la copie sans Canot

Chaque exercice écrit un fichier relire.sql à côté du rapport. Il contient les commandes DuckDB qui comptent les lignes de chaque table copiée :

duckdb < canot-out/relire.sql

La copie ne dépend donc pas de l'outil : n'importe quel moteur qui lit Iceberg (DuckDB, Spark, Trino) peut la lire. Pour un stockage S3, créez d'abord un secret DuckDB avec vos clés (voir le fichier).

Ce qui n'est pas pris en charge

Écrire directement dans PostgreSQL, ClickHouse ou un autre moteur de base : la copie reste en Iceberg, que ces moteurs savent lire. Pas d'installation hors ligne documentée pour l'instant.

Nettoyer

canot teardown --to "s3://coffre/canot?endpoint=https://s3.interne:9000&region=us-east-1"

Cibles : hébergeurs souverains et pays

Canot écrit sur tout stockage compatible S3. Raccourcis intégrés (--to <hébergeur>:<région> --bucket <nom>). Vérifiez chaque point de terminaison dans la console de l'hébergeur avant usage : ils sont à confirmer.

RaccourciHébergeurPaysRemarque
scaleway:fr-par (aussi nl-ams, pl-waw)ScalewayFR, NL, PLpas qualifié SecNumCloud (à vérifier)
ovh:graOVHcloudFRoffre SNC qualifiée SecNumCloud (à vérifier sur la liste ANSSI)
outscale:eu-west-2OutscaleFRqualification à renouveler fin 2026 (à vérifier)
ionos:eu-central-1IONOSDE
stackit:eu01STACKIT (groupe Schwarz)DE
aws:eu-west-3AWSFRpas un cloud souverain ; AWS European Sovereign Cloud existe aussi

Le même principe dans d'autres pays de l'UE

Le Data Act s'applique dans toute l'UE : mêmes règles de changement de fournisseur (art. 23 à 31), mêmes frais à zéro à partir du 12 janvier 2027. Ce qui change d'un pays : le superviseur financier qui applique DORA, l'autorité qui contrôle le Data Act, et les exigences nationales de souveraineté.

PaysPourquoi c'est intéressantHébergeurs locaux
Allemagneplus gros marché ; BaFin applique DORA ; forte culture souverainetéSTACKIT, IONOS, Open Telekom Cloud
Pays-Basplace financière, beaucoup de scale-ups sur SnowflakeLeaseweb
Italiebanques et assurances nombreusesAruba, Seeweb
Espagnebanques ; Data Act via la CNMCIONOS, Arsys
Pologne, pays nordiquesfort usage du cloud, hébergeurs locauxScaleway Varsovie, UpCloud

À confirmer avant de vendre : l'autorité compétente désignée dans chaque pays et les listes de qualification nationales (équivalents de SecNumCloud : C5 en Allemagne, ACN en Italie, ENS en Espagne).

Une question, ou un test à proposer ? Nous écrire