Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/achrafbenyounes_nexus-data-fabric.json
T

1 line
49 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "achrafbenyounes/nexus-data-fabric", "files": {"components/manual_tab.py": {"c0d23d06760a0a4332544285f96fd86ec9264a74": {"t": 1785596429.5037189, "n": 47220, "h": "04164af362274ef7", "c": "import streamlit as st\n\nMANUAL_CONTENT = {\n \"fr\": {\n \"intro\": {\n \"title\": \"1. Introduction à NEXUS Data Fabric\",\n \"content\": \"\"\"\nNEXUS Data Fabric est une plateforme **open-source** de conception de pipelines data, pensée pour les équipes data engineering modernes. Elle unifie dans une seule interface :\n\n- Le design visuel de pipelines **batch et streaming**\n- L'exécution sur **Apache Spark** (Python, Scala, Java)\n- L'intégration native avec **Databricks**, **Snowflake** et les 3 grands clouds\n- Un **AI Co-pilot** qui génère des configurations depuis le langage naturel\n- La gestion de la **qualité de données**, du **lineage** et des **data contracts**\n\n### Pourquoi NEXUS ?\n\n| Problème courant | Solution NEXUS |\n|---|---|\n| 4 outils, 4 interfaces, 4 monitorings | Un canvas unique, une observabilité unifiée |\n| Logique batch et streaming dupliquée | Kappa Architecture native |\n| Lineage partiel ou inexistant | Lineage colonne-à-colonne automatique |\n| Secrets hardcodés | Vault + rotation automatique |\n| Backfill manuel et risqué | Smart Backfill par IA |\n\n### Architecture générale\n\n```\nSources ──► [NEXUS Canvas] ──► Transforms ──► Sinks\n │\n ┌───────┴────────┐\n │ Orchestrateur │ ← Airflow-compatible\n │ AI Co-pilot │ ← LLM génératif\n │ DQ + Lineage │ ← Great Expectations\n │ Secrets Vault │ ← HashiCorp Vault\n └────────────────┘\n```\n\"\"\",\n },\n \"quickstart\": {\n \"title\": \"2. Démarrage rapide\",\n \"content\": \"\"\"\n### Installation locale\n\n```bash\n# Cloner le dépôt\ngit clone https://github.com/nexus-data/nexus-platform.git\ncd nexus-platform\n\n# Avec Docker Compose (recommandé)\ndocker compose up -d\n\n# Accès à l'UI\nopen http://localhost:8501\n```\n\n### Premier pipeline en 5 minutes\n\n**Étape 1 — Configurer un connecteur**\n\nAllez dans l'onglet `🔌 Connecteurs`, sélectionnez votre source (ex : PostgreSQL), remplissez les champs et cliquez **Tester la connexion**, puis **Sauvegarder**.\n\n**Étape 2 — Ouvrir le canvas**\n\nAllez dans l'onglet `🎨 Pipeline Canvas`. Donnez un nom à votre pipeline et choisissez le mode (Batch / Streaming / Hybride).\n\n**Étape 3 — Ajouter des nœuds**\n\nDans le panneau gauche, chaque type de nœud affiche des champs de configuration dynamiques :\n\n1. `Source` → `PostgreSQL` → remplissez **Schéma** et **Table / Query** → nommez-le → **Ajouter**\n2. `Transform` → `dbt SQL` → choisissez l'**Opération** (ex : Mart Model) → choisissez la **Matérialisation** → nommez-le → **Ajouter**\n3. `Sink` → `Snowflake` → remplissez **Database**, **Schema**, **Table** → choisissez le **Write Mode** → nommez-le → **Ajouter**\n\nLe canvas valide la structure en temps réel : un bandeau ✅ confirme que le pipeline possède au moins une Source et un Sink.\n\n**Étape 4 — Exporter et déployer**\n\nCliquez sur **Exporter YAML**. Le fichier généré inclut toute la configuration de chaque nœud et est compatible avec le scheduler NEXUS et Apache Airflow.\n\n```yaml\npipeline:\n name: mon-premier-pipeline\n mode: batch\n schedule: \"0 6 * * *\"\n nodes:\n - id: src_01\n type: Source\n connector: PostgreSQL\n dq_enabled: false\n config:\n Schema: public\n \"Table / Query\": orders\n - id: tr_01\n type: Transform\n connector: dbt SQL\n dq_enabled: true\n config:\n operation: Mart Model\n materialization: table\n dbt_target_profile: snowflake_prod\n threads: \"8\"\n - id: snk_01\n type: Sink\n connector: Snowflake\n dq_enabled: false\n config:\n Database: ANALYTICS\n Schema: MARTS\n Table: REVENUE_BY_REGION\n \"Write Mode\": overwrite\n```\n\n**Étape 5 — Monitorer**\n\nLe dashboard d'observabilité NEXUS (Grafana + OpenTelemetry) se lance automatiquement sur `http://localhost:3000`.\n\"\"\",\n },\n \"canvas\": {\n \"title\": \"3. Pipeline Canvas\",\n \"content\": \"\"\"\n### Vue d'ensemble\n\nLe Pipeline Canvas est le cœur de NEXUS. C'est une interface **low-code drag & drop** qui permet de concevoir des pipelines data complexes sans écrire de code d'infrastructure.\n\nLe panneau gauche construit le pipeline nœud par nœud ; le panneau droit affiche l'aperçu visuel en temps réel avec validation, et génère le YAML/JSON exportable.\n\n---\n\n### Types de nœuds\n\n#### 🔵 Source — Configuration dynamique\n\nLorsque vous sélectionnez un connecteur Source, un panneau **📥 Source configuration** apparaît avec les champs adaptés :\n\n| Connecteur | Champs disponibles |\n|---|---|\n| Kafka | Topic · Consumer Group · Format (JSON/Avro/Protobuf/CSV) · Offset (latest/earliest/timestamp) |\n| S3 / GCS / Azure Blob | Bucket/Path · Format (Parquet/CSV/JSON/ORC/Delta) · Partition Filter |\n| PostgreSQL / MySQL / Oracle / Redshift | Schema · Table / Query |\n| Snowflake / Databricks | Database · Schema · Table |\n| Google BigQuery | Dataset · Table |\n| MongoDB | Database · Collection · Filter Query |\n| REST API | Endpoint URL · HTTP Method · Auth (Bearer/API Key/OAuth2) |\n| SFTP | Remote Path · File Pattern · Format |\n\n#### 🟢 Transform — Opérations et configuration\n\nChaque connecteur Transform expose un sélecteur **🔧 Transformation Operation** contextuel, puis des options avancées dans un panneau **⚙️ Additional configuration** :\n\n| Connecteur | Opérations disponibles | Options avancées |\n|---|---|---|\n| **dbt SQL** | Staging Model · Intermediate Model · Mart Model · Snapshot · Test Suite | Materialization (table/view/incremental/ephemeral) · dbt Target Profile · Threads |\n| **Spark Python** | Filter & Clean · Join · Aggregate & Group By · Window Function · Deduplication · Feature Engineering · ML Training · ML Inference · Delta Merge (UPSERT) · Custom Logic | Spark Template (ETL/Streaming/ML Pipeline/Delta Lake) |\n| **Spark Scala** | Filter & Clean · Join · Aggregate · Window Function · Dedup · Delta Merge · ML Training · Custom | Spark Template |\n| **Spark Java** | Filter & Clean · Join · Aggregate · Window Function · Dedup · Delta Merge · Custom | Spark Template |\n| **Flink Job** | Tumbling Window · Sliding Window · Session Window · CEP Pattern Matching · Stateful Map/FlatMap · Async IO Enrichment · Table API Join | Window Size · Parallelism |\n| **Python UDF** | Map · Filter · FlatMap · Aggregate · Custom Python | Function Name |\n| **SQL Window** | ROW_NUMBER · RANK · DENSE_RANK · LAG · LEAD · SUM OVER · AVG OVER · COUNT OVER · NTILE · FIRST_VALUE/LAST_VALUE | Partition By · Order By |\n| **AI Enrich** | Text Enrichment · Entity Extraction (NER) · Sentiment Analysis · Classification · Translation · Summarization · Custom Prompt | LLM Model (Claude/GPT-4o/Mistral/Llama) · Input Columns · Output Column |\n| **ML Inference** | Binary Classification · Multi-class Classification · Regression · Clustering · Anomaly Detection · Recommendation · Time-Series Forecast | Model Path/URI · Feature Columns · Prediction Column |\n| **Data Masking** | Hash SHA-256 · Tokenize · Nullify · Format-Preserving Encryption · Pseudonymize · Redact (→ ***) · Generalize | Columns to Mask |\n| **Schema Validate** | Strict Validation · Lenient Validation · Drift Detection · Schema Registry Check · Data Contract Validation | Schema Source (Inline/Confluent/AWS Glue/S3) |\n| **Dedup** | Exact Dedup · Key-based (Keep First/Last/Max) · Fuzzy Dedup · Streaming Dedup | Dedup Key Columns |\n\nPour les connecteurs Spark (Python / Scala / Java), un sélecteur **Spark Language** apparaît également.\n\n#### 🔴 Sink — Configuration dynamique\n\nLorsque vous sélectionnez un connecteur Sink, un panneau **📤 Sink configuration** apparaît :\n\n| Connecteur | Champs disponibles |\n|---|---|\n| Snowflake | Database · Schema · Table · Write Mode (append/overwrite/merge) |\n| BigQuery | Dataset · Table · Write Mode |\n| Redshift / PostgreSQL | Schema · Table · Write Mode (append/upsert/overwrite) |\n| ClickHouse | Table · Engine (MergeTree/ReplacingMergeTree/AggregatingMergeTree) · Write Mode |\n| Databricks Delta | Catalog · Schema · Table · Write Mode · Merge Keys · Z-Order By |\n| S3 | Bucket/Path · Format · Partition By |\n| Kafka Topic | Topic · Format (JSON/Avro/Protobuf) |\n| Redis | Key Pattern (ex : `user:{id}`) · TTL (secondes) |\n| Elasticsearch | Index · ID Field |\n| Slack Alert | Channel · Message Template · Trigger Condition |\n| PagerDuty | Severity (critical/error/warning/info) · Filter Condition |\n\n---\n\n### Validation structurelle en temps réel\n\nLe canvas analyse le pipeline à chaque ajout de nœud et affiche un bandeau :\n\n- **✅ Structure du pipeline valide** — au moins une Source et un Sink sont présents\n- **⚠️ Pipeline sans nœud Source** — ajoutez une source de données\n- **⚠️ Pipeline sans nœud Sink** — ajoutez une destination\n\n---\n\n### Gestion des nœuds\n\nChaque nœud dans l'aperçu affiche :\n- L'**icône** de type (🔵 Source / 🟢 Transform / 🔴 Sink)\n- Le **nom** du nœud\n- Le connecteur entre crochets\n- Un badge **⚙ opération** pour les transforms (ex : `⚙ Mart Model`)\n- Un badge **Spark Language** si applicable\n- Un badge vert **DQ ✓** si les contrôles qualité sont activés\n- Un hint en italique avec la première valeur de configuration renseignée\n- Un bouton **✕** pour supprimer le nœud individuellement sans réinitialiser tout le pipeline\n\n---\n\n### Modes d'exécution\n\n**Batch** : Traitement planifié (cron), idéal pour les ETL quotidiens, les rapports, les exports.\n\n**Streaming** : Traitement en temps réel (< 1 seconde à quelques minutes de latence), idéal pour la détection de fraude, le monitoring, les recommandations.\n\n**Hybride** : NEXUS gère automatiquement la transition batch → streaming selon le volume et la latence cible. Un schedule cron est requis pour la composante batch.\n\n---\n\n### Data Quality intégrée\n\nChaque nœud Transform peut activer des contrôles DQ via la checkbox **Data Quality checks** :\n\n```yaml\ntransform:\n name: tr_dbt_revenue\n dq_enabled: true\n dq_checks:\n - type: not_null\n columns: [user_id, event_type]\n - type: unique\n columns: [event_id]\n - type: row_count_gte\n value: 1000\n - type: custom_sql\n query: \"SELECT COUNT(*) FROM {{ table }} WHERE amount < 0\"\n expect: 0\n```\n\nSi un contrôle échoue, le pipeline est mis en quarantaine et une alerte est envoyée.\n\n---\n\n### Export YAML / JSON enrichi\n\nLe pipeline exporté contient maintenant le bloc `config:` complet de chaque nœud, avec toutes les options renseignées dans l'interface. Exemple complet :\n\n```yaml\npipeline:\n name: kafka-dbt-snowflake\n mode: batch\n schedule: 0 6 * * *\n version: '1.0'\n nodes:\n - id: src_01\n name: source_kafka_events\n type: Source\n connector: Kafka\n dq_enabled: false\n config:\n Topic: nexus.events\n Consumer Group: nexus-consumer\n Format: JSON\n Offset: latest\n\n - id: tr_01\n name: transform_dbt_revenue\n type: Transform\n connector: dbt SQL\n dq_enabled: true\n config:\n operation: Mart Model\n materialization: incremental\n dbt_target_profile: snowflake_prod\n threads: '8'\n\n - id: snk_01\n name: sink_snowflake_analytics\n type: Sink\n connector: Snowflake\n dq_enabled: false\n config:\n Database: ANALYTICS\n Schema: MARTS\n Table: REVENUE_BY_REGION\n Write Mode: overwrite\n```\n\nLe fichier généré est versionnable en Git et déployable avec :\n```bash\nnexus pipeline deploy --file kafka-dbt-snowflake.yaml --env prod\n```\n\"\"\",\n },\n \"spark\": {\n \"title\": \"4. Support Apache Spark\",\n \"content\": \"\"\"\n### Langages supportés\n\nNEXUS génère du code Spark natif en **Python (PySpark)**, **Scala** et **Java**. Le générateur de code s'adapte au template choisi.\n\n### Templates disponibles\n\n#### ETL basique\nPipeline d'extraction → transformation → chargement. Inclut :\n- Lecture depuis S3 (format Parquet)\n- Nettoyage et déduplication\n- Data Quality via assertions\n- Écriture partitionnée vers la destination\n\n#### Streaming Kafka\nPipeline de consommation Kafka avec Spark Structured Streaming. Inclut :\n- Lecture depuis un topic Kafka avec gestion des offsets\n- Fenêtrage temporel (window / watermark)\n- Agrégations en temps réel\n- Écriture vers ClickHouse ou tout sink JDBC\n\n#### ML Pipeline\nPipeline d'entraînement et d'inférence Spark MLlib. Inclut :\n- Feature engineering (VectorAssembler, StandardScaler)\n- Entraînement avec validation croisée\n- Sélection du meilleur modèle\n- Sauvegarde du modèle sur S3\n\n#### Delta Lake\nPipeline de gestion de tables Delta Lake. Inclut :\n- Lecture du staging\n- MERGE (UPSERT) intelligent\n- OPTIMIZE + Z-ORDER pour les performances\n- VACUUM pour la gestion de la rétention\n\n### Configuration Spark recommandée\n\n| Workload | Exécuteurs | Mémoire/exec | Cœurs/exec |\n|---|---|---|---|\n| ETL standard | 4–8 | 4g | 2 |\n| Streaming | 2–4 | 2g | 2 |\n| ML training | 8–16 | 8g | 4 |\n| Delta MERGE | 4–8 | 4g | 2 |\n\n### Modes d'exécution Spark\n\n**Local** (`local[*]`) : Pour le développement et les tests. Pas de cluster requis.\n\n**YARN** : Pour les clusters Hadoop on-premise ou EMR.\n\n**Kubernetes** : Pour les déploiements cloud-native. NEXUS génère le Helm chart.\n\n**Databricks** : Utilise l'API Databricks Jobs API. NEXUS gère le cycle de vie du cluster.\n\n### Intégration Databricks\n\n```python\nfrom databricks.sdk import WorkspaceClient\n\nw = WorkspaceClient(\n host = \"https://adb-xxx.azuredatabricks.net\",\n token = os.environ[\"DATABRICKS_TOKEN\"]\n)\n\n# Soumettre un job via NEXUS\njob = w.jobs.submit(\n run_name = \"nexus-job-run\",\n tasks = [{\"task_key\": \"etl\", \"spark_python_task\": {\n \"python_file\": \"dbfs:/nexus/jobs/my_etl.py\"\n }}]\n)\n```\n\"\"\",\n },\n \"connectors\": {\n \"title\": \"5. Connecteurs\",\n \"content\": \"\"\"\n### Architecture des connecteurs\n\nChaque connecteur NEXUS est un plugin Python qui implémente l'interface `NexusConnector` :\n\n```python\nfrom nexus.connectors import NexusConnector\n\nclass SnowflakeConnector(NexusConnector):\n def read(self, spark, config) -> DataFrame:\n return spark.read.format(\"snowflake\").options(**config).load()\n\n def write(self, df, config, mode=\"overwrite\"):\n df.write.format(\"snowflake\").options(**config).mode(mode).save()\n\n def test_connection(self, config) -> bool:\n # Vérifie les credentials\n ...\n```\n\n### Snowflake\n\n**Prérequis** : compte Snowflake, warehouse actif, rôle avec permissions `USAGE` et `SELECT`.\n\n**Variables d'environnement recommandées** :\n```bash\nNEXUS_SF_ACCOUNT=myorg-myaccount\nNEXUS_SF_USER=my_user\nNEXUS_SF_PASSWORD=**** # ou private key\nNEXUS_SF_WAREHOUSE=COMPUTE_WH\nNEXUS_SF_DATABASE=NEXUS_DB\nNEXUS_SF_SCHEMA=PUBLIC\n```\n\n**Modes d'authentification** : Password, Key Pair (RSA), OAuth 2.0, SSO (SAML).\n\n### Databricks — Types d'abonnement et capacités\n\nNEXUS supporte **tous les types** d'abonnement Databricks. Choisissez votre type dans\nl'onglet Connecteurs → Databricks → colonne « Type d'abonnement ». Les champs s'adaptent automatiquement.\n\n| Type | Unity Catalog | SQL Warehouse | Service Principal | Identity Provider | URL pattern | Notes |\n|---|:---:|:---:|:---:|---|---|---|\n| 🆓 Free / Community Edition | ⚠️ limité | ✅ (1 small) | ❌ | none | `community.cloud.databricks.com` | Usage perso uniquement, très limité |\n| ☁️ AWS Standard | ❌ | ✅ | ❌ | AWS IAM / external SSO | `<workspace>.cloud.databricks.com` | Pas d'UC, gouvernance limitée |\n| ☁️ AWS Premium / Enterprise | ✅ | ✅ | ✅ | AWS IAM / external SSO | `<workspace>.cloud.databricks.com` | Production ready, gouvernance complète |\n| 🔷 Azure Standard | ❌ | ✅ | ❌ | Azure AD | `adb-<id>.<region>.azuredatabricks.net` | Intégré Azure AD |\n| 🔷 Azure Premium / Enterprise | ✅ | ✅ | ✅ | Azure AD | `adb-<id>.<region>.azuredatabricks.net` | Sécurité & gouvernance enterprise |\n| 🟡 GCP Standard | ❌ | ✅ | ❌ | Google IAM / Identity | `<workspace>.gcp.databricks.com` | Gouvernance limitée |\n| 🟡 GCP Premium / Enterprise | ✅ | ✅ | ✅ | Google IAM / Identity | `<workspace>.gcp.databricks.com` | Production ready |\n\n> ⚠️ **Azure Databricks Standard** : Unity Catalog non supporté et pas de Service Principal.\n> L'intégration Azure AD est disponible. Les tables sont dans `hive_metastore`.\n> Passez en **Premium ou Enterprise** pour Unity Catalog.\n\n**Méthodes d'authentification disponibles selon le type :**\n- **PAT (Personal Access Token)** : disponible sur tous les types.\n- **Azure AAD (Bearer token)** : Azure uniquement. Générez via `az account get-access-token`.\n- **Service Principal / OAuth M2M** : AWS Premium, Azure Premium, GCP Premium.\n\n**3 connecteurs Databricks simultanés** : NEXUS permet de configurer jusqu'à 3 connecteurs\nDatabricks indépendants (ex : Production AWS, Staging Azure, Dev Community). Dans le Pipeline Canvas,\nun sélecteur apparaît si plusieurs connecteurs sont configurés.\n\n**Prérequis** : workspace Databricks, cluster All-Purpose ou Job Cluster, Personal Access Token (ou AAD/SP selon le type).\n\n**Unity Catalog** : NEXUS supporte nativement Unity Catalog pour la gouvernance des données et le lineage cross-workspace. Sur les types sans Unity Catalog, le browser navigue dans `hive_metastore`.\n\n### Gestion des secrets\n\nNEXUS ne stocke jamais les credentials en clair. Toutes les connexions passent par le **Vault NEXUS** :\n\n```yaml\n# secrets.yaml (chiffré AES-256)\nnexus_secrets:\n snowflake_password:\n vault_path: secret/nexus/snowflake\n rotation: 90d\n databricks_token:\n vault_path: secret/nexus/databricks\n rotation: 30d\n```\n\n### Création d'un connecteur custom\n\n```bash\nnexus connector new --name my-custom-connector\n# Génère le squelette dans ./connectors/my_custom_connector/\n```\n\"\"\",\n },\n \"copilot\": {\n \"title\": \"6. AI Co-pilot\",\n \"content\": \"\"\"\n### Fonctionnement\n\nLe Co-pilot NEXUS est un assistant IA spécialisé dans la conception de pipelines data. Il comprend :\n\n- La topologie de vos connecteurs configurés\n- Vos contraintes SLA et de coût\n- Les patterns de pipelines courants (ETL, CDC, ML, alerting)\n- Les bonnes pratiques Spark et streaming\n\n### Exemples d'utilisation\n\n**Génération de pipeline**\n```\nUtilisateur : \"Crée un pipeline qui lit les commandes de PostgreSQL,\n calcule le CA par région avec dbt, et charge dans Snowflake\n tous les jours à 6h du matin.\"\n\nCo-pilot : ✅ Pipeline généré :\n - Source : PostgreSQL → table orders\n - Transform : dbt SQL → model revenue_by_region\n - Sink : Snowflake → table ANALYTICS.REVENUE\n - Schedule : 0 6 * * * (UTC)\n - SLA estimé : ~45 min\n```\n\n**Optimisation**\n```\nUtilisateur : \"Mon job Spark prend 3h, comment l'optimiser ?\"\n\nCo-pilot : J'analyse votre configuration...\n 1. Activez spark.sql.adaptive.enabled=true\n 2. Réduisez spark.default.parallelism à 200\n 3. Ajoutez .repartition(\"event_date\") avant l'écriture\n 4. Activez la compression Snappy : parquet.compression=SNAPPY\n → Gain estimé : -60% sur le temps d'exécution\n```\n\n**Débogage**\n```\nUtilisateur : \"Mon pipeline échoue avec OOM sur l'executor\"\n\nCo-pilot : Probable cause : shuffle de données déséquilibré.\n Solutions :\n 1. spark.executor.memory=8g (actuellement 4g)\n 2. spark.sql.shuffle.partitions=400\n 3. Vérifiez les skews avec df.groupBy(\"partition_col\").count()\n```\n\n### Modèles LLM supportés\n\n| Modèle | Usage | Latence |\n|---|---|---|\n| GPT-4o | Génération complexe | ~3s |\n| Claude 3.5 Sonnet | Génération + optimisation | ~2s |\n| Llama 3.1 (local) | Air-gapped / données sensibles | ~8s |\n| Mistral Large | Génération standard | ~2s |\n\n### Configuration\n\n```yaml\n# nexus.yaml\ncopilot:\n provider: anthropic # openai | anthropic | ollama | mistral\n model: claude-3-5-sonnet # selon le provider\n max_tokens: 4096\n context_window: pipelines + connectors + metrics\n data_privacy: true # anonymise les noms avant envoi au LLM\n```\n\"\"\",\n },\n \"deployment\": {\n \"title\": \"7. Déploiement\",\n \"content\": \"\"\"\n### Streamlit Cloud (recommandé pour débuter)\n\n```bash\n# 1. Forker le repo NEXUS sur GitHub\n# 2. Aller sur share.streamlit.io\n# 3. Connecter votre repo\n# 4. Configurer les secrets dans Settings → Secrets :\n\n[secrets]\nOPENAI_API_KEY = \"sk-...\"\nSNOWFLAKE_PASSWORD = \"****\"\nDATABRICKS_TOKEN = \"dapi...\"\n```\n\n### Docker Compose (développement)\n\n```yaml\n# docker-compose.yaml\nservices:\n nexus-ui:\n image: nexusdata/platform:latest\n ports: [\"8501:8501\"]\n environment:\n - NEXUS_SECRET_KEY=${SECRET_KEY}\n volumes:\n - ./pipelines:/app/pipelines\n\n nexus-scheduler:\n image: nexusdata/scheduler:latest\n depends_on: [postgres, redis]\n\n postgres:\n image: postgres:15-alpine\n environment:\n POSTGRES_DB: nexus_meta\n\n redis:\n image: redis:7-alpine\n```\n\n### Kubernetes (production)\n\n```bash\n# Via Helm Chart NEXUS\nhelm repo add nexus https://charts.nexusdata.io\nhelm install nexus nexus/nexus-platform \\\\\n --namespace nexus \\\\\n --set global.cloud=gcp \\\\\n --set spark.mode=kubernetes \\\\\n --set vault.enabled=true\n```\n\n### Variables d'environnement importantes\n\n| Variable | Description | Requis |\n|---|---|---|\n| `NEXUS_SECRET_KEY` | Clé de chiffrement interne | ✅ |\n| `NEXUS_VAULT_ADDR` | URL HashiCorp Vault | Production |\n| `NEXUS_DB_URL` | PostgreSQL pour les métadonnées | ✅ |\n| `NEXUS_REDIS_URL` | Redis pour le cache | ✅ |\n| `NEXUS_LOG_LEVEL` | DEBUG / INFO / WARN | Non |\n\"\"\",\n },\n \"best_practices\": {\n \"title\": \"8. Bonnes pratiques\",\n \"content\": \"\"\"\n### Design de pipelines\n\n**✅ À faire**\n- Un pipeline = une responsabilité unique (principe SRP)\n- Nommer les nœuds de façon descriptive : `src_postgres_orders`, `tr_dbt_revenue`, `snk_snowflake_analytics`\n- Versionner tous les pipelines YAML en Git\n- Définir un SLA par pipeline et configurer les alertes correspondantes\n- Activer la Data Quality sur chaque Transform\n- Utiliser des Data Contracts entre producteurs et consommateurs\n\n**❌ À éviter**\n- Pipelines \"catch-all\" qui font tout (extraction + ML + reporting)\n- Secrets en dur dans la configuration YAML\n- Ignorer les erreurs OOM Spark sans investiguer le skew\n- Désactiver les contrôles DQ en production\n\n### Spark\n\n```python\n# ✅ Bonne pratique : adaptive query execution\nspark.conf.set(\"spark.sql.adaptive.enabled\", \"true\")\nspark.conf.set(\"spark.sql.adaptive.coalescePartitions.enabled\", \"true\")\n\n# ✅ Bonne pratique : partitionner avant l'écriture\ndf.repartition(col(\"event_date\")).write.partitionBy(\"event_date\").parquet(...)\n\n# ✅ Bonne pratique : cache les DataFrames réutilisés\ndf_clean.cache()\ndf_clean.count() # force le cache\n\n# ❌ Mauvaise pratique : collect() sur un grand DataFrame\nall_rows = df.collect() # OOM garanti sur un gros dataset\n```\n\n### Streaming\n\n- Toujours définir un **watermark** pour les late arrivals\n- Configurer le **checkpointing** sur un stockage durable (S3, HDFS)\n- Surveiller le **lag Kafka** (objectif : < 10 000 messages)\n- Utiliser `processingTime` trigger plutôt que `once` en production\n\n### Sécurité\n\n- Activer le **RBAC NEXUS** : chaque équipe voit uniquement ses pipelines\n- Utiliser des **Service Accounts** dédiés par pipeline (principe du moindre privilège)\n- Auditer les accès aux données sensibles via le log NEXUS\n- Appliquer le **Data Masking** automatique sur les colonnes PII\n\n### Coût cloud\n\n| Levier | Économie potentielle |\n|---|---|\n| Spot Instances pour les jobs Spark batch | 60–80% |\n| Autoscaling Databricks (min/max workers) | 40–60% |\n| Compression Parquet + Z-ORDER ClickHouse | 30–50% I/O |\n| Partition pruning bien configuré | 20–40% scan |\n\"\"\",\n },\n },\n\n \"en\": {\n \"intro\": {\n \"title\": \"1. Introduction to NEXUS Data Fabric\",\n \"content\": \"\"\"\nNEXUS Data Fabric is an **open-source** data pipeline design platform built for modern data engineering teams. It unifies in a single interface:\n\n- Visual **batch and streaming** pipeline design\n- Execution on **Apache Spark** (Python, Scala, Java)\n- Native integration with **Databricks**, **Snowflake** and all 3 major clouds\n- An **AI Co-pilot** that generates configurations from natural language\n- **Data quality**, **lineage** and **data contracts** management\n\n### Why NEXUS?\n\n| Current pain | NEXUS solution |\n|---|---|\n| 4 tools, 4 interfaces, 4 monitoring stacks | Single canvas, unified observability |\n| Duplicated batch and streaming logic | Native Kappa Architecture |\n| Partial or missing lineage | Automatic column-level lineage |\n| Hardcoded secrets | Vault + automatic rotation |\n| Manual, risky backfills | AI-powered Smart Backfill |\n\n### General architecture\n\n```\nSources ──► [NEXUS Canvas] ──► Transforms ──► Sinks\n │\n ┌───────┴────────┐\n │ Orchestrator │ ← Airflow-compatible\n │ AI Co-pilot │ ← Generative LLM\n │ DQ + Lineage │ ← Great Expectations\n │ Secrets Vault │ ← HashiCorp Vault\n └────────────────┘\n```\n\"\"\",\n },\n \"quickstart\": {\n \"title\": \"2. Quick start\",\n \"content\": \"\"\"\n### Local installation\n\n```bash\n# Clone the repository\ngit clone https://github.com/nexus-data/nexus-platform.git\ncd nexus-platform\n\n# With Docker Compose (recommended)\ndocker compose up -d\n\n# Access the UI\nopen http://localhost:8501\n```\n\n### First pipeline in 5 minutes\n\n**Step 1 — Configure a connector**\n\nGo to the `🔌 Connectors` tab, select your source (e.g. PostgreSQL), fill in the fields and click **Test connection**, then **Save**.\n\n**Step 2 — Open the canvas**\n\nGo to the `🎨 Pipeline Canvas` tab. Give your pipeline a name and choose the mode (Batch / Streaming / Hybrid).\n\n**Step 3 — Add nodes**\n\nIn the left panel, each node type shows dynamic configuration fields:\n\n1. `Source` → `PostgreSQL` → fill in **Schema** and **Table / Query** → name it → **Add**\n2. `Transform` → `dbt SQL` → choose the **Operation** (e.g. Mart Model) → choose **Materialization** → name it → **Add**\n3. `Sink` → `Snowflake` → fill in **Database**, **Schema**, **Table** → choose **Write Mode** → name it → **Add**\n\nThe canvas validates the structure in real time: a ✅ banner confirms the pipeline has at least one Source and one Sink.\n\n**Step 4 — Export and deploy**\n\nClick **Export YAML**. The generated file includes the full configuration of each node and is compatible with the NEXUS scheduler and Apache Airflow.\n\n```yaml\npipeline:\n name: my-first-pipeline\n mode: batch\n schedule: \"0 6 * * *\"\n nodes:\n - id: src_01\n type: Source\n connector: PostgreSQL\n dq_enabled: false\n config:\n Schema: public\n \"Table / Query\": orders\n - id: tr_01\n type: Transform\n connector: dbt SQL\n dq_enabled: true\n config:\n operation: Mart Model\n materialization: table\n dbt_target_profile: snowflake_prod\n threads: \"8\"\n - id: snk_01\n type: Sink\n connector: Snowflake\n dq_enabled: false\n config:\n Database: ANALYTICS\n Schema: MARTS\n Table: REVENUE_BY_REGION\n \"Write Mode\": overwrite\n```\n\n**Step 5 — Monitor**\n\nThe NEXUS observability dashboard (Grafana + OpenTelemetry) starts automatically at `http://localhost:3000`.\n\"\"\",\n },\n \"canvas\": {\n \"title\": \"3. Pipeline Canvas\",\n \"content\": \"\"\"\n### Overview\n\nThe Pipeline Canvas is the heart of NEXUS. It is a **low-code drag & drop** interface that allows you to design complex data pipelines without writing infrastructure code.\n\nThe left panel builds the pipeline node by node; the right panel shows the live visual preview with validation and generates the exportable YAML/JSON.\n\n---\n\n### Node types\n\n#### 🔵 Source — Dynamic configuration\n\nWhen you select a Source connector, a **📥 Source configuration** panel appears with the relevant fields:\n\n| Connector | Available fields |\n|---|---|\n| Kafka | Topic · Consumer Group · Format (JSON/Avro/Protobuf/CSV) · Offset (latest/earliest/timestamp) |\n| S3 / GCS / Azure Blob | Bucket/Path · Format (Parquet/CSV/JSON/ORC/Delta) · Partition Filter |\n| PostgreSQL / MySQL / Oracle / Redshift | Schema · Table / Query |\n| Snowflake / Databricks | Database · Schema · Table |\n| Google BigQuery | Dataset · Table |\n| MongoDB | Database · Collection · Filter Query |\n| REST API | Endpoint URL · HTTP Method · Auth (Bearer/API Key/OAuth2) |\n| SFTP | Remote Path · File Pattern · Format |\n\n#### 🟢 Transform — Operations and configuration\n\nEach Transform connector exposes a contextual **🔧 Transformation Operation** selector, then advanced options in an **⚙️ Additional configuration** panel:\n\n| Connector | Available operations | Advanced options |\n|---|---|---|\n| **dbt SQL** | Staging Model · Intermediate Model · Mart Model · Snapshot · Test Suite | Materialization (table/view/incremental/ephemeral) · dbt Target Profile · Threads |\n| **Spark Python** | Filter & Clean · Join · Aggregate & Group By · Window Function · Deduplication · Feature Engineering · ML Training · ML Inference · Delta Merge (UPSERT) · Custom Logic | Spark Template (ETL/Streaming/ML Pipeline/Delta Lake) |\n| **Spark Scala** | Filter & Clean · Join · Aggregate · Window Function · Dedup · Delta Merge · ML Training · Custom | Spark Template |\n| **Spark Java** | Filter & Clean · Join · Aggregate · Window Function · Dedup · Delta Merge · Custom | Spark Template |\n| **Flink Job** | Tumbling Window · Sliding Window · Session Window · CEP Pattern Matching · Stateful Map/FlatMap · Async IO Enrichment · Table API Join | Window Size · Parallelism |\n| **Python UDF** | Map · Filter · FlatMap · Aggregate · Custom Python | Function Name |\n| **SQL Window** | ROW_NUMBER · RANK · DENSE_RANK · LAG · LEAD · SUM OVER · AVG OVER · COUNT OVER · NTILE · FIRST_VALUE/LAST_VALUE | Partition By · Order By |\n| **AI Enrich** | Text Enrichment · Entity Extraction (NER) · Sentiment Analysis · Classification · Translation · Summarization · Custom Prompt | LLM Model (Claude/GPT-4o/Mistral/Llama) · Input Columns · Output Column |\n| **ML Inference** | Binary Classification · Multi-class Classification · Regression · Clustering · Anomaly Detection · Recommendation · Time-Series Forecast | Model Path/URI · Feature Columns · Prediction Column |\n| **Data Masking** | Hash SHA-256 · Tokenize · Nullify · Format-Preserving Encryption · Pseudonymize · Redact (→ ***) · Generalize | Columns to Mask |\n| **Schema Validate** | Strict Validation · Lenient Validation · Drift Detection · Schema Registry Check · Data Contract Validation | Schema Source (Inline/Confluent/AWS Glue/S3) |\n| **Dedup** | Exact Dedup · Key-based (Keep First/Last/Max) · Fuzzy Dedup · Streaming Dedup | Dedup Key Columns |\n\nFor Spark connectors (Python / Scala / Java), a **Spark Language** selector is also shown.\n\n#### 🔴 Sink — Dynamic configuration\n\nWhen you select a Sink connector, a **📤 Sink configuration** panel appears:\n\n| Connector | Available fields |\n|---|---|\n| Snowflake | Database · Schema · Table · Write Mode (append/overwrite/merge) |\n| BigQuery | Dataset · Table · Write Mode |\n| Redshift / PostgreSQL | Schema · Table · Write Mode (append/upsert/overwrite) |\n| ClickHouse | Table · Engine (MergeTree/ReplacingMergeTree/AggregatingMergeTree) · Write Mode |\n| Databricks Delta | Catalog · Schema · Table · Write Mode · Merge Keys · Z-Order By |\n| S3 | Bucket/Path · Format · Partition By |\n| Kafka Topic | Topic · Format (JSON/Avro/Protobuf) |\n| Redis | Key Pattern (e.g. `user:{id}`) · TTL (seconds) |\n| Elasticsearch | Index · ID Field |\n| Slack Alert | Channel · Message Template · Trigger Condition |\n| PagerDuty | Severity (critical/error/warning/info) · Filter Condition |\n\n---\n\n### Real-time structural validation\n\nThe canvas analyses the pipeline on every node addition and displays a banner:\n\n- **✅ Pipeline structure is valid** — at least one Source and one Sink are present\n- **⚠️ Pipeline has no Source node** — add a data source\n- **⚠️ Pipeline has no Sink node** — add a destination\n\n---\n\n### Node management\n\nEach node in the preview shows:\n- The **type icon** (🔵 Source / 🟢 Transform / 🔴 Sink)\n- The **node name**\n- The connector in brackets\n- An **⚙ operation** badge for transforms (e.g. `⚙ Mart Model`)\n- A **Spark Language** badge if applicable\n- A green **DQ ✓** badge if quality checks are enabled\n- An italic hint with the first filled configuration value\n- A **✕** button to delete the node individually without resetting the whole pipeline\n\n---\n\n### Execution modes\n\n**Batch**: Scheduled processing (cron), ideal for daily ETLs, reports, exports.\n\n**Streaming**: Real-time processing (< 1 second to a few minutes of latency), ideal for fraud detection, monitoring, recommendations.\n\n**Hybrid**: NEXUS automatically manages the batch → streaming transition based on volume and target latency. A cron schedule is required for the batch component.\n\n---\n\n### Built-in Data Quality\n\nEach Transform node can enable DQ checks via the **Data Quality checks** checkbox:\n\n```yaml\ntransform:\n name: tr_dbt_revenue\n dq_enabled: true\n dq_checks:\n - type: not_null\n columns: [user_id, event_type]\n - type: unique\n columns: [event_id]\n - type: row_count_gte\n value: 1000\n - type: custom_sql\n query: \"SELECT COUNT(*) FROM {{ table }} WHERE amount < 0\"\n expect: 0\n```\n\nIf a check fails, the pipeline is quarantined and an alert is sent.\n\n---\n\n### Enriched YAML / JSON export\n\nThe exported pipeline now contains the full `config:` block for each node, with all options filled in the UI. Full example:\n\n```yaml\npipeline:\n name: kafka-dbt-snowflake\n mode: batch\n schedule: 0 6 * * *\n version: '1.0'\n nodes:\n - id: src_01\n name: source_kafka_events\n type: Source\n connector: Kafka\n dq_enabled: false\n config:\n Topic: nexus.events\n Consumer Group: nexus-consumer\n Format: JSON\n Offset: latest\n\n - id: tr_01\n name: transform_dbt_revenue\n type: Transform\n connector: dbt SQL\n dq_enabled: true\n config:\n operation: Mart Model\n materialization: incremental\n dbt_target_profile: snowflake_prod\n threads: '8'\n\n - id: snk_01\n name: sink_snowflake_analytics\n type: Sink\n connector: Snowflake\n dq_enabled: false\n config:\n Database: ANALYTICS\n Schema: MARTS\n Table: REVENUE_BY_REGION\n Write Mode: overwrite\n```\n\nThe generated file is Git-versionable and deployable with:\n```bash\nnexus pipeline deploy --file kafka-dbt-snowflake.yaml --env prod\n```\n\"\"\",\n },\n \"spark\": {\n \"title\": \"4. Apache Spark Support\",\n \"content\": \"\"\"\n### Supported languages\n\nNEXUS generates native Spark code in **Python (PySpark)**, **Scala** and **Java**. The code generator adapts to the chosen template.\n\n### Available templates\n\n#### Basic ETL\nExtract → transform → load pipeline. Includes:\n- Reading from S3 (Parquet format)\n- Cleaning and deduplication\n- Data Quality via assertions\n- Partitioned write to destination\n\n#### Kafka Streaming\nKafka consumer pipeline with Spark Structured Streaming. Includes:\n- Reading from a Kafka topic with offset management\n- Time windowing (window / watermark)\n- Real-time aggregations\n- Writing to ClickHouse or any JDBC sink\n\n#### ML Pipeline\nSpark MLlib training and inference pipeline. Includes:\n- Feature engineering (VectorAssembler, StandardScaler)\n- Training with cross-validation\n- Best model selection\n- Model saving to S3\n\n#### Delta Lake\nDelta Lake table management pipeline. Includes:\n- Staging read\n- Smart MERGE (UPSERT)\n- OPTIMIZE + Z-ORDER for performance\n- VACUUM for retention management\n\n### Recommended Spark configuration\n\n| Workload | Executors | Memory/exec | Cores/exec |\n|---|---|---|---|\n| Standard ETL | 4–8 | 4g | 2 |\n| Streaming | 2–4 | 2g | 2 |\n| ML training | 8–16 | 8g | 4 |\n| Delta MERGE | 4–8 | 4g | 2 |\n\n### Spark execution modes\n\n**Local** (`local[*]`): For development and testing. No cluster required.\n\n**YARN**: For on-premise Hadoop clusters or EMR.\n\n**Kubernetes**: For cloud-native deployments. NEXUS generates the Helm chart.\n\n**Databricks**: Uses the Databricks Jobs API. NEXUS manages the cluster lifecycle.\n\"\"\",\n },\n \"connectors\": {\n \"title\": \"5. Connectors\",\n \"content\": \"\"\"\n### Connector architecture\n\nEach NEXUS connector is a Python plugin that implements the `NexusConnector` interface:\n\n```python\nfrom nexus.connectors import NexusConnector\n\nclass SnowflakeConnector(NexusConnector):\n def read(self, spark, config) -> DataFrame:\n return spark.read.format(\"snowflake\").options(**config).load()\n\n def write(self, df, config, mode=\"overwrite\"):\n df.write.format(\"snowflake\").options(**config).mode(mode).save()\n\n def test_connection(self, config) -> bool: ...\n```\n\n### Snowflake\n\n**Prerequisites**: Snowflake account, active warehouse, role with `USAGE` and `SELECT` permissions.\n\n**Recommended environment variables**:\n```bash\nNEXUS_SF_ACCOUNT=myorg-myaccount\nNEXUS_SF_USER=my_user\nNEXUS_SF_PASSWORD=**** # or private key\nNEXUS_SF_WAREHOUSE=COMPUTE_WH\nNEXUS_SF_DATABASE=NEXUS_DB\nNEXUS_SF_SCHEMA=PUBLIC\n```\n\n**Auth modes**: Password, Key Pair (RSA), OAuth 2.0, SSO (SAML).\n\n### Databricks — Subscription types & capabilities\n\nNEXUS supports **all Databricks subscription types**. Select your type in the\nConnectors → Databricks tab under \"Subscription type\". Fields adjust automatically.\n\n| Type | Unity Catalog | SQL Warehouse | Service Principal | Identity Provider | URL pattern | Notes |\n|---|:---:|:---:|:---:|---|---|---|\n| 🆓 Free / Community Edition | ⚠️ limited | ✅ (1 small) | ❌ | none | `community.cloud.databricks.com` | Personal use only, heavily restricted |\n| ☁️ AWS Standard | ❌ | ✅ | ❌ | AWS IAM / external SSO | `<workspace>.cloud.databricks.com` | No Unity Catalog, limited governance |\n| ☁️ AWS Premium / Enterprise | ✅ | ✅ | ✅ | AWS IAM / external SSO | `<workspace>.cloud.databricks.com` | Production ready, full governance |\n| 🔷 Azure Standard | ❌ | ✅ | ❌ | Azure AD | `adb-<id>.<region>.azuredatabricks.net` | Integrated with Azure AD |\n| 🔷 Azure Premium / Enterprise | ✅ | ✅ | ✅ | Azure AD | `adb-<id>.<region>.azuredatabricks.net` | Enterprise-grade security and governance |\n| 🟡 GCP Standard | ❌ | ✅ | ❌ | Google IAM / Identity | `<workspace>.gcp.databricks.com` | Limited governance features |\n| 🟡 GCP Premium / Enterprise | ✅ | ✅ | ✅ | Google IAM / Identity | `<workspace>.gcp.databricks.com` | Production ready |\n\n> ⚠️ **Azure Databricks Standard**: Unity Catalog not supported and no Service Principal.\n> Azure AD integration available. Data is in `hive_metastore`.\n> Upgrade to **Premium or Enterprise** for Unity Catalog.\n\n**Available authentication methods by type:**\n- **PAT (Personal Access Token)**: available on all types.\n- **Azure AAD (Bearer token)**: Azure only. Generate via `az account get-access-token`.\n- **Service Principal / OAuth M2M**: AWS Premium, Azure Premium, GCP Premium.\n\n**Up to 3 simultaneous Databricks connectors**: NEXUS lets you configure up to 3 independent\nDatabricks connectors (e.g. AWS Production, Azure Staging, Community Dev). In the Pipeline Canvas,\na selector appears when multiple connectors are configured.\n\n**Prerequisites**: Databricks workspace, All-Purpose or Job Cluster, Personal Access Token (or AAD/SP depending on type).\n\n**Unity Catalog**: NEXUS natively supports Unity Catalog for data governance and cross-workspace lineage. On types without Unity Catalog, the browser navigates `hive_metastore`.\n\n### Secrets management\n\nNEXUS never stores credentials in plain text. All connections go through the **NEXUS Vault**:\n\n```yaml\nnexus_secrets:\n snowflake_password:\n vault_path: secret/nexus/snowflake\n rotation: 90d\n databricks_token:\n vault_path: secret/nexus/databricks\n rotation: 30d\n```\n\n### Creating a custom connector\n\n```bash\nnexus connector new --name my-custom-connector\n# Generates the skeleton in ./connectors/my_custom_connector/\n```\n\"\"\",\n },\n \"copilot\": {\n \"title\": \"6. AI Co-pilot\",\n \"content\": \"\"\"\n### How it works\n\nThe NEXUS Co-pilot is an AI assistant specialized in data pipeline design. It understands:\n\n- The topology of your configured connectors\n- Your SLA and cost constraints\n- Common pipeline patterns (ETL, CDC, ML, alerting)\n- Spark and streaming best practices\n\n### Usage examples\n\n**Pipeline generation**\n```\nUser : \"Create a pipeline that reads orders from PostgreSQL,\n computes revenue by region with dbt, and loads to\n Snowflake every day at 6am.\"\n\nCopilot: ✅ Pipeline generated:\n - Source : PostgreSQL → orders table\n - Transform : dbt SQL → revenue_by_region model\n - Sink : Snowflake → ANALYTICS.REVENUE table\n - Schedule : 0 6 * * * (UTC)\n - Estimated SLA : ~45 min\n```\n\n**Optimization**\n```\nUser : \"My Spark job takes 3 hours, how do I optimize it?\"\n\nCopilot: Analyzing your configuration...\n 1. Enable spark.sql.adaptive.enabled=true\n 2. Reduce spark.default.parallelism to 200\n 3. Add .repartition(\"event_date\") before writing\n 4. Enable Snappy compression: parquet.compression=SNAPPY\n → Estimated gain: -60% on execution time\n```\n\n### Supported LLM models\n\n| Model | Use | Latency |\n|---|---|---|\n| GPT-4o | Complex generation | ~3s |\n| Claude 3.5 Sonnet | Generation + optimization | ~2s |\n| Llama 3.1 (local) | Air-gapped / sensitive data | ~8s |\n| Mistral Large | Standard generation | ~2s |\n\n### Configuration\n\n```yaml\n# nexus.yaml\ncopilot:\n provider: anthropic\n model: claude-3-5-sonnet\n max_tokens: 4096\n context_window: pipelines + connectors + metrics\n data_privacy: true # anonymizes names before sending to LLM\n```\n\"\"\",\n },\n \"deployment\": {\n \"title\": \"7. Deployment\",\n \"content\": \"\"\"\n### Streamlit Cloud (recommended for getting started)\n\n```bash\n# 1. Fork the NEXUS repo on GitHub\n# 2. Go to share.streamlit.io\n# 3. Connect your repo\n# 4. Configure secrets in Settings → Secrets:\n\n[secrets]\nOPENAI_API_KEY = \"sk-...\"\nSNOWFLAKE_PASSWORD = \"****\"\nDATABRICKS_TOKEN = \"dapi...\"\n```\n\n### Docker Compose (development)\n\n```yaml\n# docker-compose.yaml\nservices:\n nexus-ui:\n image: nexusdata/platform:latest\n ports: [\"8501:8501\"]\n environment:\n - NEXUS_SECRET_KEY=${SECRET_KEY}\n volumes:\n - ./pipelines:/app/pipelines\n\n nexus-scheduler:\n image: nexusdata/scheduler:latest\n depends_on: [postgres, redis]\n\n postgres:\n image: postgres:15-alpine\n environment:\n POSTGRES_DB: nexus_meta\n\n redis:\n image: redis:7-alpine\n```\n\n### Kubernetes (production)\n\n```bash\nhelm repo add nexus https://charts.nexusdata.io\nhelm install nexus nexus/nexus-platform \\\\\n --namespace nexus \\\\\n --set global.cloud=gcp \\\\\n --set spark.mode=kubernetes \\\\\n --set vault.enabled=true\n```\n\n### Key environment variables\n\n| Variable | Description | Required |\n|---|---|---|\n| `NEXUS_SECRET_KEY` | Internal encryption key | ✅ |\n| `NEXUS_VAULT_ADDR` | HashiCorp Vault URL | Production |\n| `NEXUS_DB_URL` | PostgreSQL for metadata | ✅ |\n| `NEXUS_REDIS_URL` | Redis for cache | ✅ |\n| `NEXUS_LOG_LEVEL` | DEBUG / INFO / WARN | No |\n\"\"\",\n },\n \"best_practices\": {\n \"title\": \"8. Best practices\",\n \"content\": \"\"\"\n### Pipeline design\n\n**✅ Do**\n- One pipeline = one single responsibility (SRP principle)\n- Use descriptive node names: `src_postgres_orders`, `tr_dbt_revenue`, `snk_snowflake_analytics`\n- Version all YAML pipelines in Git\n- Define an SLA per pipeline and configure corresponding alerts\n- Enable Data Quality on each Transform\n- Use Data Contracts between producers and consumers\n\n**❌ Don't**\n- Create \"catch-all\" pipelines that do everything (extraction + ML + reporting)\n- Hardcode secrets in YAML configuration\n- Ignore Spark OOM errors without investigating skew\n- Disable DQ checks in production\n\n### Spark\n\n```python\n# ✅ Best practice: adaptive query execution\nspark.conf.set(\"spark.sql.adaptive.enabled\", \"true\")\nspark.conf.set(\"spark.sql.adaptive.coalescePartitions.enabled\", \"true\")\n\n# ✅ Best practice: partition before writing\ndf.repartition(col(\"event_date\")).write.partitionBy(\"event_date\").parquet(...)\n\n# ✅ Best practice: cache reused DataFrames\ndf_clean.cache()\ndf_clean.count() # force the cache\n\n# ❌ Bad practice: collect() on a large DataFrame\nall_rows = df.collect() # guaranteed OOM on large datasets\n```\n\n### Streaming\n\n- Always define a **watermark** for late arrivals\n- Configure **checkpointing** on durable storage (S3, HDFS)\n- Monitor **Kafka lag** (target: < 10,000 messages)\n- Use `processingTime` trigger rather than `once` in production\n\n### Security\n\n- Enable **NEXUS RBAC**: each team only sees their own pipelines\n- Use dedicated **Service Accounts** per pipeline (least privilege principle)\n- Audit access to sensitive data via the NEXUS log\n- Apply automatic **Data Masking** on PII columns\n\n### Cloud cost\n\n| Lever | Potential savings |\n|---|---|\n| Spot Instances for batch Spark jobs | 60–80% |\n| Databricks autoscaling (min/max workers) | 40–60% |\n| Parquet compression + Z-ORDER ClickHouse | 30–50% I/O |\n| Well-configured partition pruning | 20–40% scan |\n\"\"\",\n },\n },\n}\n\nSECTION_KEYS = [\"intro\", \"quickstart\", \"canvas\", \"spark\", \"connectors\", \"copilot\", \"deployment\", \"best_practices\"]\n\n\ndef render_manual(T, lang_key):\n st.markdown(f\"### {T['manual_title']}\")\n st.caption(T[\"manual_subtitle\"])\n st.divider()\n\n content_lang = MANUAL_CONTENT.get(lang_key, MANUAL_CONTENT[\"fr\"])\n search = st.text_input(f\"🔍 {T['manual_search']}\", placeholder=\"spark, kafka, snowflake, lineage...\")\n\n section_labels = [content_lang[k][\"title\"] for k in SECTION_KEYS]\n toc_labels = [T[f\"manual_s{i+1}\"] for i in range(8)]\n\n col_toc, col_content = st.columns([1, 3])\n\n with col_toc:\n st.markdown(f\"**{T['manual_toc']}**\")\n if \"manual_section\" not in st.session_state:\n st.session_state[\"manual_section\"] = 0\n for i, lbl in enumerate(toc_labels):\n btn_type = \"primary\" if st.session_state[\"manual_section\"] == i else \"secondary\"\n if st.button(lbl, key=f\"toc_{i}\", use_container_width=True, type=btn_type):\n st.session_state[\"manual_section\"] = i\n\n with col_content:\n idx = st.session_state.get(\"manual_section\", 0)\n key = SECTION_KEYS[idx]\n section = content_lang[key]\n\n if search:\n # Filter content\n matched = []\n for k in SECTION_KEYS:\n sec = content_lang[k]\n if search.lower() in sec[\"content\"].lower() or search.lower() in sec[\"title\"].lower():\n matched.append(sec)\n if matched:\n st.success(f\"🔍 {len(matched)} section(s) trouvée(s) / found\")\n for sec in matched:\n st.markdown(f\"#### {sec['title']}\")\n st.markdown(sec[\"content\"])\n st.divider()\n else:\n st.warning(f\"Aucun résultat pour '{search}' / No results for '{search}'\")\n else:\n st.markdown(f\"#### {section['title']}\")\n st.markdown(section[\"content\"])\n"}}}}