ADS-B aéronefs militaires — exemple de source de données
Installez une source de données déclarative via un Scrydon Pack, synchronisez-la et exploitez-la depuis Analytics → Sources de données — historique de synchronisation, rétention en direct, table sous-jacente et suppression. Exemple ADS-B complet avec les parcours UI et développeur.
Téléchargements
Les deux fichiers sont générés par le script de build de la documentation (apps/docs/scripts/build-pack-examples.ts) à partir d'un manifeste source unique situé à apps/docs/examples/scrydon-pack-adsb-aircraft/manifest.ts. Ils sont régénérés à chaque bun run dev / bun run build de l'application de documentation — ce sont les mêmes octets, simplement deux formes de distribution pour la même source de données.
| Fichier | Utilisation |
|---|---|
| 📦 scrydon-pack-adsb-aircraft.scrydon-pack.tar.gz | Recommandé — installation via l'interface. Deux étapes : l'administrateur d'organisation admet le pack dans Paramètres → Packs (catalogue uniquement — rien n'est encore matérialisé) ; l'utilisateur de l'espace de travail le sélectionne dans Analytics → Marketplace pour instancier la source de données dans son environnement. |
| 📥 adsb-lol-military-declarative.json | Appliquez directement le manifeste déclaratif brut via curl vers POST /api/table/data-sources/apply — le parcours développeur qui contourne l'enveloppe pack. Utile pour les tests scriptés. |
Chemin A — installation via l'interface (recommandé)
L'installation d'un pack se déroule en deux étapes par conception — voir ADR 2026-05-30 pour la justification. L'étape 1 catalogue le pack au niveau de l'organisation ; l'étape 2 instancie la source de données dans un environnement d'espace de travail.
Étape 1 — L'administrateur d'organisation télécharge le pack
- En tant qu'administrateur d'organisation, ouvrez Paramètres → Packs.
- Déposez le fichier
scrydon-pack-adsb-aircraft.scrydon-pack.tar.gztéléchargé sur la zone de dépôt (ou cliquez pour le sélectionner). La boîte de dialogue affiche l'id du packscrydon-pack-adsb-aircraft, la version1.0.0et un résumé de contribution en une ligne : 1 source de données. - Cochez Je comprends que ce pack n'est pas signé… et cliquez sur Télécharger. Le pack est admis dans le catalogue de l'organisation. Aucune ligne
data_sourcen'est encore créée — les packs contenant uniquement des sources de données reportent la matérialisation à l'étape 2 (le téléchargement se termine silencieusement et le pack apparaît dans la marketplace).
Étape 2 — L'utilisateur de l'espace de travail instancie la source de données
- En tant qu'utilisateur de l'espace de travail, ouvrez
apps/analyticset confirmez qu'un espace de travail et un environnement sont sélectionnés (sélecteur en haut à droite). - Ouvrez Marketplace dans la barre latérale. La carte
scrydon-pack-adsb-aircraftapparaît avec un unique bouton Installer dans cet environnement (le pack contient exactement une source de données qui n'est pas encore présente dans cet environnement). - Cliquez sur Installer dans cet environnement. La plateforme appelle
packs.install({ contentKinds: ["data-source"], workspaceEnvironmentId })→ api-table enregistre une ligne dansdata_sourcelimitée à votre environnement. - Ouvrez Sources de données dans la barre latérale — la nouvelle ligne apparaît avec Source :
adsb-lol-military-declarative, Fournisseur :adsb-lol, Intervalle : 60s, Statut :En attente. - Ouvrez le menu d'actions de la ligne et cliquez sur Synchroniser maintenant. Attendez-vous à une notification verte avec le nombre de lignes écrites ; le Statut passe à
Sainet la Dernière synchronisation s'affiche après l'actualisation automatique.
Le parcours d'installation via la marketplace (Better Auth packs.install avec contentKinds: ["data-source"]) atteint le même endpoint d'application api-table via le délégué installResolvedPack des sources de données, de sorte que les installations ultérieures du même pack dans des environnements différents produisent des lignes identiques.
Chemin B — appliquer le JSON directement (développeur)
Ignorez l'outillage de création de pack et appliquez directement le manifeste brut à l'endpoint interne /data-sources/apply d'api-table. Cela emprunte le même chemin de code que le hook installDataSource du chemin A — les deux convergent vers POST /api/table/data-sources/apply.
Il s'agit de l'exercice de bout en bout le plus rapide pour :
- le domaine des sources de données api-table (ligne dans
data_source, colonnes d'état de synchronisation mises à jour à chaque tick), - le runtime de sondage générique dans
@scrydon/better-auth-integrations/host/declarative-poll/runtime.ts(HTTP fetch → sélectionitemsPath→ mapping de champs → validation des lignes), - la vue Analytics → Sources de données (badge de statut, heure de dernière synchronisation, compteur de lignes écrites, action « Synchroniser maintenant »).
Le manifeste ci-dessous est la source canonique adsb-lol-military-declarative de @scrydon/sdk-authoring, sérialisée en JSON simple. Le test de parité golden dans le monorepo affirme que cela produit des lignes identiques octet par octet à la source de code équivalente sur la même fixture — donc une fois que « Synchroniser maintenant » réussit, vous exercez le runtime de sondage en production contre une vraie API publique.
L'endpoint est protégé par authentification interne (x-scrydon-internal-dev: 1 en développement, Dapr SPIFFE en production) et accepte les appelants détenant la capacité data-source:apply — platform (réconciliateur/tick), agentic (import de pack) et api-platform (le délégué marketplace Better Auth). L'appel curl ci-dessous utilise l'en-tête de développement ; en production, l'appel parvient via l'un de ces trois appelants attestés par Dapr.
Prérequis
Vous disposez d'une stack Scrydon locale en cours d'exécution. Le service api-table doit répondre :
curl -fsS http://localhost:7500/api/table/healthVous avez besoin d'un identifiant d'organisation pour délimiter la source de données. Récupérez-le depuis la table organization de votre base de données auth, ou depuis l'URL de n'importe quelle page limitée à une organisation dans l'interface de la plateforme.
export ORG="<your-org-uuid>"Le manifeste
Voici le manifeste déclaratif complet. Il s'agit de JSON pur — sans fonctions, sans code. Le bundler de pack émet exactement cette forme à partir de defineDataSource({...}).
{
"kind": "table",
"id": "adsb-lol-military-declarative",
"vendor": "adsb-lol",
"displayName": "ADS-B Lol — Military Aircraft (declarative)",
"scope": "global",
"table": {
"name": "aircraft_position",
"primaryKey": ["icao24", "seenAt"],
"timestampColumn": "seenAt",
"columns": [
{ "name": "icao24", "dataType": "string", "isPrimaryKey": true },
{ "name": "callsign", "dataType": "string", "nullable": true },
{ "name": "registration", "dataType": "string", "nullable": true },
{ "name": "aircraftType", "dataType": "string", "nullable": true },
{ "name": "category", "dataType": "string", "nullable": true },
{ "name": "latitude", "dataType": "decimal" },
{ "name": "longitude", "dataType": "decimal" },
{ "name": "altitudeFeet", "dataType": "int", "nullable": true },
{ "name": "groundSpeedKnots", "dataType": "double", "nullable": true },
{ "name": "heading", "dataType": "double", "nullable": true },
{ "name": "seenAt", "dataType": "timestamp", "isPrimaryKey": true }
]
},
"ingest": {
"mode": "poll",
"intervalSec": 60,
"minIntervalSec": 30,
"request": {
"url": "https://api.adsb.lol/v2/mil",
"method": "GET",
"headers": { "accept": "application/json" }
},
"response": { "itemsPath": "$.ac" },
"filter": {
"requireNonNull": ["hex", "lat", "lon"]
},
"mapping": {
"icao24": { "path": "hex" },
"callsign": { "path": "flight", "transform": "trim_to_null" },
"registration": { "path": "r" },
"aircraftType": { "path": "t" },
"category": { "path": "category" },
"latitude": { "path": "lat" },
"longitude": { "path": "lon" },
"altitudeFeet": {
"path": "alt_baro",
"transform": "value_map",
"args": { "map": { "ground": 0 }, "passthrough": "number", "default": null }
},
"groundSpeedKnots": { "path": "gs", "transform": "number_or_null" },
"heading": { "path": "track", "transform": "number_or_null" },
"seenAt": {
"path": "seen",
"transform": "iso_from_epoch_offset",
"args": {
"basePath": "$.now",
"baseUnit": "ms",
"offsetUnit": "s",
"direction": "subtract"
}
}
}
}
}Ce que fait chaque bloc
| Bloc | Objectif |
|---|---|
kind: "table" | Le seul type de source supporté aujourd'hui — déclare une destination en forme de lignes. |
id | Identité stable. api-table effectue un upsert sur (organization_id, id) — ré-appliquer le même manifeste met à jour la ligne en place. |
vendor | Slug du fournisseur en forme libre affiché dans la liste des sources de données. |
scope: "global" | Une source pour toute l'organisation. (Le périmètre par espace de travail est prévu dans la feuille de route.) |
table.primaryKey | Clé primaire composite utilisée pour dédupliquer les résultats du sondage dans la table silver. |
table.columns[] | La liste exacte des colonnes — dataType + nullable + isPrimaryKey correspondent directement au DDL de la table silver. |
ingest.intervalSec / minIntervalSec | Cadence du tick (60s ici) et plancher appliqué par le planificateur. |
ingest.request | Spécification de la requête HTTP simple. Sans code, sans signature — headers et query sont des chaînes statiques. |
ingest.response.itemsPath | Sélecteur de type JSONPath atteignant le tableau de lignes dans l'enveloppe de réponse. |
ingest.filter.requireNonNull | Filtre au niveau de la ligne : ignore les éléments dont les chemins listés sont null/undefined. |
ingest.mapping[<column>] | Une entrée par nom dans table.columns[]. path lit le champ source ; transform + args optionnels le reformatent. Les transformations supportées sont documentées dans data-sources/index.mdx#field-mappings. |
Appliquer le manifeste
Téléchargez le fichier JSON lié ci-dessus, puis assemblez le corps de la requête d'application. Le chemin le plus propre utilise jq pour que le JSON soit composé de façon sûre (sans problèmes d'échappement shell) :
# 1) Téléchargez le manifeste une fois.
curl -fsS -o adsb-lol-military-declarative.json \
http://localhost:4001/static/scrydon-pack-adsb-aircraft/adsb-lol-military-declarative.json
# 2) Composez le corps de la requête d'application et envoyez-le en POST.
jq -n \
--arg org "$ORG" \
--slurpfile manifest adsb-lol-military-declarative.json \
'{ organizationId: $org, packId: "scrydon-pack-adsb-aircraft", packVersion: "1.0.0", manifest: $manifest[0] }' \
| curl -fsS -X POST http://localhost:7500/api/table/data-sources/apply \
-H 'content-type: application/json' \
-H 'x-scrydon-internal-dev: 1' \
-d @-Réponse attendue :
{ "sourceId": "adsb-lol-military-declarative" }Si vous préférez ne pas dépendre de jq, enregistrez le corps complet de la requête sur disque une fois et envoyez-le directement en POST :
ORG="<your-org-uuid>"
jq -n --arg org "$ORG" \
--slurpfile manifest adsb-lol-military-declarative.json \
'{ organizationId: $org, packId: "scrydon-pack-adsb-aircraft", packVersion: "1.0.0", manifest: $manifest[0] }' \
> apply-body.json
curl -fsS -X POST http://localhost:7500/api/table/data-sources/apply \
-H 'content-type: application/json' \
-H 'x-scrydon-internal-dev: 1' \
-d @apply-body.jsonExploiter et observer (Analytics → Sources de données)
Une fois la source instanciée dans votre environnement, tout ce qui suit est accessible en quelques clics — sans SDK, sans appels API. Voici l'expérience complète de l'opérateur pour n'importe quelle source de données, en utilisant l'exemple ADS-B comme sujet concret.
En tant qu'utilisateur de l'espace de travail, allez dans apps/analytics → Sources de données. Chaque source installée dans l'environnement courant est une ligne affichant Source, Fournisseur, Intervalle, Statut, Dernière synchronisation, Lignes et Dernière erreur. Une source fraîchement installée affiche Statut : En attente jusqu'à sa première synchronisation. La vue est limitée à l'environnement d'espace de travail sélectionné dans le sélecteur en haut à droite.
Ouvrez le menu d'actions ⋯ de la ligne et choisissez Synchroniser maintenant. Le badge passe à Synchronisation… pendant l'exécution du sondage — une récupération externe peut prendre quelques secondes à une minute — puis la ligne se rafraîchit automatiquement : Statut → Sain, Dernière synchronisation se met à jour et Lignes indique combien ont été écrites. Vous n'avez pas à attendre l'intervalle planifié ; cela exécute le même tick à la demande.
Cliquez sur la ligne pour ouvrir son panneau de détail, qui affiche :
- Mode d'écriture — comment les nouvelles lignes arrivent (
upsert,changed-only,appendoureplace). En lecture seule : il est fixé lors de l'installation de la source (voir Modes d'écriture). - Rétention — un contrôle modifiable (traité ci-après).
- Historique de synchronisation — les ticks les plus récents : quand chacun a eu lieu, l'événement (ex. lignes en upsert), le nombre de lignes concernées et tout message d'erreur.
- Ouvrir la table — un raccourci direct vers la table sous-jacente, où vous pouvez parcourir et interroger les lignes ingérées. (Apparaît une fois que la première synchronisation a provisionné la table.)
Dans le panneau de détail, définissez la Rétention sur la fenêtre que vous souhaitez conserver — pour l'exemple ADS-B, par exemple 7 jours — et enregistrez. La plateforme conserve uniquement les partitions journalières les plus récentes de la table et supprime les anciennes automatiquement ; la modification prend effet immédiatement, sans reconstruction de la table ni rechargement des données. Effacez le champ pour revenir à la valeur par défaut de la source. Voir Rétention pour la façon dont la valeur par défaut est définie.
En bas du panneau de détail, la Zone de danger contient Supprimer la source de données. La suppression est irréversible : après confirmation, la plateforme supprime la table sous-jacente et toutes ses lignes, supprime la source et arrête son planification. Si le pack qui a contribué cette source n'a contribué rien d'autre, le pack d'origine est également supprimé — ainsi, pour un pack à source unique comme cet exemple ADS-B, « Supprimer la source de données » nettoie à la fois la source et le pack en une seule étape.
Si le pack contient également d'autres contenus (une ontologie, des workflows ou d'autres sources de données), la source est quand même supprimée mais le pack est conservé — une notification vous en informe — et vous désinstallez le pack lui-même depuis Paramètres → Packs quand vous êtes prêt. Cette action est irréversible ; réinstaller le pack est le moyen de récupérer la source.
Si une synchronisation échoue
Si le Statut passe à Erreur, survolez la cellule Dernière erreur (ou lisez-la dans le panneau de détail). Les causes les plus courantes :
| Erreur | Signification | Que faire |
|---|---|---|
data_source_connection_required | La source nécessite un identifiant (son request référence un authRef), mais aucune connexion activée n'existe pour votre organisation. | Connectez le compte dans les paramètres de l'organisation sous le nom attendu par le pack, puis synchronisez à nouveau. Cet exemple ADS-B n'utilise aucun identifiant, vous ne devriez donc pas voir cette erreur. |
invalid_installed_manifest | Le manifeste stocké a échoué à la revalidation complète au moment du tick — ex. un type de colonne ou un nom de transformation incorrect. | Réinstallez le pack avec un manifeste corrigé. |
egress_denied | La garde de sortie a bloqué l'URL de la requête (elle doit être https:// et résoudre vers un hôte public). | Confirmez que l'hôte de la source est accessible et autorisé dans votre environnement. |
5xx en amont | L'API externe était momentanément indisponible ou limitée en débit (api.adsb.lol l'est parfois). | Cliquez à nouveau sur Synchroniser maintenant — les ticks sont idempotents. |
Aparté développeur — vérifier la ligne et l'état de synchronisation en base de données
L'interface opérateur ci-dessus est la surface supportée. Si vous développez localement et souhaitez confirmer la ligne sous-jacente directement :
SELECT source_id, status, last_sync_at, last_rows_written, last_error, consecutive_failures
FROM data_source
WHERE organization_id = :ORG;Après une Synchronisation maintenant réussie :
source_id | status | last_sync_at | last_rows_written | last_error | consecutive_failures
-----------------------------+--------+---------------------+-------------------+------------+----------------------
adsb-lol-military-declarative | ok | 2026-05-28 14:02:11 | 37 | | 0D'où vient ce manifeste
La source TypeScript se trouve à packages/sdk-authoring/src/integrations/data-source/adsb-lol-military-declarative.ts — elle appelle defineDataSource({...}) avec la même forme. Le bundler de pack sérialise l'argument de l'appel en JSON et l'émet dans un sous-répertoire data-source/ à l'intérieur d'un .scrydon-pack.tar.gz. L'endpoint /data-sources/apply accepte ce JSON directement, ce que démontre cette page : le même manifeste, simplement sans l'enveloppe pack.
Si vous souhaitez livrer la source dans un pack plutôt que de l'appliquer manuellement, suivez le parcours Auteur dans sdks/authoring/data-sources.