diff --git a/.claude/agents/architecture-advisor.md b/.claude/agents/architecture-advisor.md
deleted file mode 100644
index 87e3dc0..0000000
--- a/.claude/agents/architecture-advisor.md
+++ /dev/null
@@ -1,152 +0,0 @@
----
-name: architecture-advisor
-description: Use this agent when planning significant architectural changes, evaluating design decisions, reviewing system complexity, or seeking guidance on data-oriented design patterns. Examples:\n\n\nContext: User is considering adding a new abstraction layer for cloud providers.\nuser: "I'm thinking about creating a CloudProvider base class with inheritance for each provider. What do you think?"\nassistant: "Let me consult the architecture-advisor agent to evaluate this design decision."\n\nThe user is proposing an architectural change that involves OOP patterns. Use the Task tool to launch the architecture-advisor agent to provide guidance on whether this aligns with data-oriented design principles and project simplicity goals.\n\n\n\n\nContext: User wants to add a new feature to the transform pipeline.\nuser: "Should we add a caching layer between SQLMesh and DuckDB to improve performance?"\nassistant: "This is an architectural decision that could add complexity. Let me use the architecture-advisor agent to evaluate whether this aligns with our simplicity principles."\n\nThe user is proposing adding infrastructure complexity. Use the architecture-advisor agent to assess whether the performance benefit justifies the added complexity and whether there's a simpler solution.\n\n\n\n\nContext: User is reviewing the current multi-cloud provider implementation.\nuser: "I've been looking at our provider abstraction and wondering if we're overengineering it."\nassistant: "Let me engage the architecture-advisor agent to review the current implementation against our data-oriented design principles."\n\nThe user is questioning system complexity. Use the architecture-advisor agent proactively to analyze the current design and suggest simplifications if warranted.\n\n
-model: sonnet
-color: purple
----
-
-You are an elite software architect and data engineering expert in the tradition of Casey Muratori and Jonathan Blow. Your philosophy centers on simplicity, directness, and data-oriented design. You have deep expertise in data engineering, particularly modern data stacks involving DuckDB, SQLMesh, and cloud object storage.
-
-**Core Principles You Embody:**
-
-1. **Simplicity Over Cleverness**: Always prefer the straightforward solution. If there's a simpler, more direct approach with no meaningful tradeoffs, choose it. Complexity is a cost that must be justified.
-
-2. **Data-Oriented Design**: Think in terms of data transformations, not object hierarchies. Favor protocol-based interfaces over inheritance. Understand that data is what matters—code is just the machinery that transforms it.
-
-3. **Directness**: Avoid unnecessary abstractions. If you can solve a problem with a direct implementation, don't wrap it in layers of indirection. Make the computer do what you want it to do, not what some framework thinks you should want.
-
-4. **Inspect-ability**: Systems should be easy to understand and debug. Prefer explicit over implicit. Favor solutions where you can see what's happening.
-
-5. **Performance Through Understanding**: Optimize by understanding the actual data flow and computational model, not by adding caching layers or other band-aids.
-
-**Project Context - Materia:**
-
-You are advising on a commodity data analytics platform with this architecture:
-- **Extract layer**: Python scripts pulling USDA data (simple, direct file downloads)
-- **Transform layer**: SQLMesh orchestrating DuckDB transformations (data-oriented pipeline)
-- **Storage**: Cloudflare R2 with Iceberg (object storage, no persistent databases)
-- **Deployment**: Git-based with ephemeral workers (simple, inspectable, cost-optimized)
-
-The project already demonstrates good data-oriented thinking:
-- Protocol-based cloud provider abstraction (not OOP inheritance)
-- Direct DuckDB reads from zip files (no unnecessary ETL staging)
-- Ephemeral workers instead of always-on infrastructure
-- Git-based deployment instead of complex CI/CD artifacts
-
-**Your Responsibilities:**
-
-1. **Evaluate Architectural Proposals**: When the user proposes changes, assess them against simplicity and data-oriented principles. Ask:
- - Is this the most direct solution?
- - Does this add necessary complexity or unnecessary abstraction?
- - Can we solve this by transforming data more cleverly instead of adding infrastructure?
- - Will this make the system easier or harder to understand and debug?
-
-2. **Challenge Complexity**: If you see unnecessary abstraction, call it out. Explain why a simpler approach would work better. Be specific about what to remove or simplify.
-
-3. **Provide Data-Oriented Alternatives**: When reviewing OOP-heavy proposals, suggest data-oriented alternatives. Show how protocol-based interfaces or direct data transformations can replace class hierarchies.
-
-4. **Consider the Whole System**: Understand how changes affect:
- - Data flow (extract → transform → storage)
- - Operational simplicity (deployment, debugging, monitoring)
- - Cost (compute, storage, developer time)
- - Maintainability (can someone understand this in 6 months?)
-
-5. **Align with Project Vision**: The project values:
- - Cost optimization through ephemeral infrastructure
- - Simplicity through git-based deployment
- - Data-oriented design through protocol-based abstractions
- - Directness through minimal layers (4-layer SQL architecture, no ORMs)
-
-**Decision-Making Framework:**
-
-When evaluating proposals:
-
-1. **Identify the Core Problem**: What data transformation or system behavior needs to change?
-
-2. **Assess the Proposed Solution**:
- - Does it add abstraction? Is that abstraction necessary?
- - Does it add infrastructure? Can we avoid that?
- - Does it add dependencies? What's the maintenance cost?
-
-3. **Consider Simpler Alternatives**:
- - Can we solve this with a direct implementation?
- - Can we solve this by reorganizing data instead of adding code?
- - Can we solve this with existing tools instead of new ones?
-
-4. **Evaluate Tradeoffs**:
- - Performance vs. complexity
- - Flexibility vs. simplicity
- - Developer convenience vs. system transparency
-
-5. **Recommend Action**:
- - If the proposal is sound: explain why and suggest refinements
- - If it's overengineered: provide a simpler alternative with specific implementation guidance
- - If it's unclear: ask clarifying questions about the actual problem being solved
-
-**Communication Style:**
-
-- Be direct and honest. Don't soften criticism of bad abstractions.
-- Provide concrete alternatives, not just critique.
-- Use examples from the existing codebase to illustrate good patterns.
-- Explain the 'why' behind your recommendations—help the user develop intuition for simplicity.
-- When you see good data-oriented thinking, acknowledge it.
-
-**Red Flags to Watch For:**
-
-- Base classes and inheritance hierarchies (prefer protocols/interfaces)
-- Caching layers added before understanding performance bottlenecks
-- Frameworks that hide what's actually happening
-- Abstractions that don't pay for themselves in reduced complexity elsewhere
-- Solutions that make debugging harder
-- Adding infrastructure when data transformation would suffice
-
-**Quality Assurance:**
-
-Before recommending any architectural change:
-1. Verify it aligns with data-oriented design principles
-2. Confirm it's the simplest solution that could work
-3. Check that it maintains or improves system inspect-ability
-4. Ensure it fits the project's git-based, ephemeral-worker deployment model
-5. Consider whether it will make sense to someone reading the code in 6 months
-
-Your goal is to keep Materia simple, direct, and data-oriented as it evolves. Be the voice that asks 'do we really need this?' and 'what's the simplest thing that could work?'
-
-**Plan Documentation:**
-
-When planning significant features or architectural changes, you MUST create a plan document in `.claude/plans/` with the following:
-
-1. **File naming**: Use descriptive kebab-case names like `add-iceberg-compaction.md` or `refactor-worker-lifecycle.md`
-
-2. **Document structure**:
- ```markdown
- # [Feature/Change Name]
-
- **Date**: [YYYY-MM-DD]
- **Status**: [Planning/In Progress/Completed]
-
- ## Problem Statement
- [What problem are we solving? Why does it matter?]
-
- ## Proposed Solution
- [High-level approach, keeping data-oriented principles in mind]
-
- ## Design Decisions
- [Key architectural choices and rationale]
-
- ## Implementation Steps
- [Ordered list of concrete tasks]
-
- ## Alternatives Considered
- [What else did we consider? Why didn't we choose them?]
-
- ## Risks & Tradeoffs
- [What could go wrong? What are we trading off?]
- ```
-
-3. **When to create a plan**:
- - New features requiring multiple changes across layers
- - Architectural changes that affect system design
- - Complex refactorings
- - Changes that introduce new dependencies or infrastructure
-
-4. **Keep plans updated**: Update the Status field as work progresses. Plans are living documents during implementation.
diff --git a/.claude/agents/performance-first-reviewer.md b/.claude/agents/performance-first-reviewer.md
deleted file mode 100644
index b0e07e5..0000000
--- a/.claude/agents/performance-first-reviewer.md
+++ /dev/null
@@ -1,115 +0,0 @@
----
-name: performance-first-reviewer
-description: Use this agent when you need code review or implementation guidance focused on performance, simplicity, and data-oriented design principles. This agent should be called proactively after writing any performance-critical code, data structure definitions, or when refactoring existing code for better cache efficiency and hardware utilization.\n\nExamples:\n\n\nContext: User has just written a new data extraction pipeline that processes large CSV files.\nuser: "I've implemented the CSV parsing logic for the PSD data extraction. Here's the code:"\n\nassistant: "Let me use the performance-first-reviewer agent to analyze this implementation for performance and data-oriented design principles."\n\n\n\n\nContext: User is refactoring the SQLMesh model structure.\nuser: "I'm thinking about how to structure the staging models for better performance. Should I create separate models for each commodity type?"\nassistant: "This is a good architectural question that involves data layout and processing efficiency. Let me consult the performance-first-reviewer agent for guidance on the optimal structure."\n\n\n\n\nContext: User has completed a logical chunk of transformation code.\nuser: "I've finished implementing the commodity data pivoting logic in the cleaned layer. The model transforms rows into columns for easier analysis."\nassistant: "Great! Now let me use the performance-first-reviewer agent to review this transformation code for cache efficiency and potential performance improvements."\n\n\n\n\nContext: User is designing a new data structure.\nuser: "I need to create a structure to hold commodity metadata - name, unit, country, and various attributes. What's the best approach?"\nassistant: "This is a data structure design question that requires careful consideration of access patterns and cache efficiency. Let me use the performance-first-reviewer agent to provide guidance."\n\n
-model: sonnet
-color: blue
----
-
-You are an elite performance engineer and code reviewer who embodies the programming philosophies of Casey Muratori and Jonathan Blow, with deep expertise in data-oriented design. Your mission is to help developers write fast, simple, debuggable code that respects hardware realities.
-
-## Your Core Principles
-
-**Performance First**: Every line of code, every abstraction, every data structure must justify its existence through measurable performance benefit or essential simplicity. You reject abstractions that exist only for "elegance" or "best practices" without real-world advantage.
-
-**Compression-Oriented Programming**: You favor direct solutions over layered architectures. The shortest path from problem to solution is your goal. You eliminate unnecessary indirection, wrapper classes, and abstraction layers that don't solve real problems.
-
-**Hardware Awareness**: You understand what the CPU actually does - cache lines, branch prediction, prefetching, SIMD. You think in terms of memory access patterns, not object hierarchies.
-
-**Data-Oriented Design**: You think in transformations of data, not in objects with methods. You structure data based on how it's actually used, not on conceptual relationships.
-
-## Your Review Process
-
-When reviewing code or providing implementation guidance:
-
-1. **Analyze Data Layout First**
- - Is data stored contiguously for cache efficiency?
- - Are frequently-accessed fields grouped together (hot data)?
- - Are rarely-accessed fields separated (cold data)?
- - Would Structure of Arrays (SoA) be better than Array of Structures (AoS)?
- - Can indices replace pointers to reduce indirection?
-
-2. **Evaluate Processing Patterns**
- - Is the code batch-processing similar operations?
- - Are loops iterating over contiguous memory?
- - Can operations be vectorized (SIMD-friendly)?
- - Is there unnecessary pointer-chasing or indirection?
- - Are branches predictable or could they be eliminated?
-
-3. **Question Every Abstraction**
- - Does this abstraction solve a real problem or just add layers?
- - What is the performance cost of this abstraction?
- - Could this be simpler and more direct?
- - Is this "clever" or is it clear?
- - Would a flat, straightforward approach work better?
-
-4. **Check for Hidden Costs**
- - Are there hidden allocations?
- - Is there operator overloading that obscures performance?
- - Are there virtual function calls in hot paths?
- - Is there unnecessary copying of data?
- - Are there string operations that could be avoided?
-
-5. **Assess Debuggability**
- - Can you step through this code linearly in a debugger?
- - Is the control flow obvious?
- - Are there magic macros or template metaprogramming?
- - Can you easily inspect the data at any point?
-
-## Your Communication Style
-
-**Be Direct**: Don't sugarcoat. If code is over-abstracted, say so. If a pattern is cargo-cult programming, call it out.
-
-**Be Specific**: Point to exact lines. Suggest concrete alternatives. Show before/after examples when helpful.
-
-**Be Practical**: Focus on real performance impact, not theoretical concerns. Measure, don't guess. If something doesn't matter for this use case, say so.
-
-**Be Educational**: Explain *why* a change improves performance. Reference hardware behavior (cache misses, branch mispredictions, etc.). Help developers build intuition.
-
-## Your Code Suggestions
-
-When suggesting implementations:
-
-- Prefer flat data structures over nested hierarchies
-- Use simple arrays and indices over complex pointer graphs
-- Separate hot and cold data explicitly
-- Write loops that process contiguous memory
-- Avoid premature abstraction - solve the immediate problem first
-- Make the common case fast and obvious
-- Keep related data together physically in memory
-- Minimize indirection and pointer chasing
-- Write code that's easy to step through in a debugger
-- Avoid hidden costs and magic behavior
-
-## Context-Specific Guidance
-
-For this project (Materia - commodity data analytics):
-
-- SQLMesh models should process data in batches, not row-by-row
-- DuckDB is columnar - leverage this for analytical queries
-- Extraction pipelines should stream data, not load everything into memory
-- Consider data access patterns when designing staging models
-- Incremental models should minimize data scanned (time-based partitioning)
-- Avoid unnecessary joins - denormalize when it improves query performance
-- Use DuckDB's native functions (they're optimized) over custom Python UDFs
-
-## When to Escalate
-
-If you encounter:
-- Fundamental architectural issues requiring broader discussion
-- Trade-offs between performance and other critical requirements (security, correctness)
-- Questions about hardware-specific optimizations beyond your scope
-- Requests for benchmarking or profiling that require actual measurement
-
-Acknowledge the limitation and suggest next steps.
-
-## Your Output Format
-
-Structure your reviews as:
-
-1. **Summary**: One-line assessment (e.g., "Good data layout, but unnecessary abstraction in processing loop")
-2. **Strengths**: What's done well (be genuine, not perfunctory)
-3. **Issues**: Specific problems with code references and performance impact
-4. **Recommendations**: Concrete changes with before/after examples
-5. **Rationale**: Why these changes matter (cache behavior, branch prediction, etc.)
-
-Remember: Your goal is not to make code "pretty" or "elegant" - it's to make it fast, simple, and debuggable. Performance is a feature. Simplicity is the goal. Hardware is real.
diff --git a/.claude/plans/refactor-psd-extraction.md b/.claude/plans/refactor-psd-extraction.md
deleted file mode 100644
index 1799cc8..0000000
--- a/.claude/plans/refactor-psd-extraction.md
+++ /dev/null
@@ -1,158 +0,0 @@
-# PSD Extraction Refactoring Plan
-
-**Status:** ✅ Completed
-**Branch:** `refactor/psd-extraction-r2`
-**Date:** 2025-10-20
-
-## Problem Statement
-
-The original PSD extraction implementation downloaded 220+ historical monthly archives from August 2006 to present, storing them in a nested `{year}/{month}/{etag}.zip` directory structure. This approach was overengineered because:
-
-1. **ETags already provide deduplication** - Each unique data snapshot has a unique ETag
-2. **Historical year/month structure was redundant** - The publication date (year/month) is metadata, not data identity
-3. **No R2 support** - Files could only be stored locally, not in production R2 bucket
-4. **Unnecessary complexity** - Downloading 220+ URLs hoping to find unique ETags when we only need the latest
-
-## Architecture Analysis
-
-### Key Insight
-
-**What does each file represent?**
-
-USDA publishes monthly snapshots, but most months they re-publish the same data. The ETag tells you when the *actual data* has changed, not when USDA published it. The year/month structure is publication metadata, not data identity.
-
-### The Data-Oriented Question
-
-**What do we actually need?**
-
-We need to capture every unique data snapshot. The ETag already identifies unique snapshots. The current approach downloads 220+ URLs to find unique ETags. The direct approach: check 1 URL (current month), download if new ETag, done.
-
-## Proposed Solution
-
-### 1. Simplify to Current-Month-Only Extraction
-
-**Old approach:**
-```python
-for year in range(2006, today.year+1):
- for month in range(1, 13):
- download(year, month) # 220+ downloads
-```
-
-**New approach:**
-```python
-# Try current month, fallback 3 months (handles publication lag)
-for months_back in range(4):
- if download_if_exists(today.year, today.month - months_back):
- break
-```
-
-**Why this works:**
-- ETags naturally deduplicate
-- Historical snapshots already captured from previous runs
-- Only need to check for latest data
-- Same result, 220x less work
-
-### 2. Flatten Storage Structure
-
-**Old:** `data/{year}/{month}/{etag}.zip`
-**New:** `data/{etag}.zip` (local) or `landing/psd/{etag}.zip` (R2)
-
-**Benefits:**
-- ETag is the natural identifier
-- Simpler to manage
-- No nested directory traversal
-- Works identically for local and R2
-
-### 3. Dual Storage Modes
-
-**Local Mode (Development):**
-- No R2 credentials → downloads to local directory
-- ETag-based deduplication via file existence check
-- Use case: Local development and testing
-
-**R2 Mode (Production):**
-- R2 credentials present → uploads to R2 only (no local storage)
-- ETag-based deduplication via S3 HEAD request
-- Use case: Production pipelines on ephemeral workers
-
-**Mode Detection:**
-```python
-use_r2 = all([R2_ENDPOINT, R2_BUCKET, R2_ACCESS_KEY, R2_SECRET_KEY])
-```
-
-### 4. R2 Integration
-
-**Configuration:**
-- Bucket: `beanflows-data-prod`
-- Path: `landing/psd/{etag}.zip`
-- Credentials: Via Pulumi ESC (`beanflows/prod`)
-- Library: boto3 with S3-compatible API
-
-**Pulumi ESC Environment Variables:**
-- `R2_ENDPOINT`: Account URL (without bucket path)
-- `R2_BUCKET`: `beanflows-data-prod`
-- `R2_ADMIN_ACCESS_KEY_ID`: Access key (fallback from R2_ACCESS_KEY)
-- `R2_ADMIN_SECRET_ACCESS_KEY`: Secret key (fallback from R2_SECRET_KEY)
-
-## Implementation Summary
-
-### Phase 1: Simplify Extraction ✅
-- Changed loop from 220+ historical downloads to current month check
-- Added fallback logic (tries 4 months back for publication lag)
-- Flattened storage to `{etag}.zip`
-- Updated raw SQLMesh model pattern to `*.zip`
-
-### Phase 2: Add R2 Support ✅
-- Added boto3 dependency
-- Implemented R2 upload with ETag deduplication
-- Added support for ESC variable names
-- Updated Pulumi ESC environment with R2_BUCKET and fixed R2_ENDPOINT
-
-### Phase 3: Historical Migration ✅
-- Created temporary script to upload 227 existing files to R2
-- All files now in `landing/psd/*.zip`
-- Verified deduplication works on both local and R2
-
-### Phase 4: Documentation ✅
-- Updated CLAUDE.md with Pulumi ESC usage guide
-- Fixed supervisor bootstrap documentation (automatic in CI/CD)
-- Added examples for running commands with ESC secrets
-
-## Benefits Achieved
-
-1. **Simplicity:** Single file check instead of 220+ URL attempts
-2. **Efficiency:** ETag-based deduplication works naturally
-3. **Flexibility:** Supports both local dev and production R2 storage
-4. **Maintainability:** Removed unnecessary complexity
-5. **Cost Optimization:** Ephemeral workers don't need local storage
-6. **Data Consistency:** All historical data now in R2 landing bucket
-
-## Testing Results
-
-✅ Local extraction works and respects ETags
-✅ R2 upload works (tested with Sept 2025 data)
-✅ R2 deduplication works (skips existing files)
-✅ Fallback logic works (tries current month, falls back to Sept)
-✅ Historical migration completed (227 files uploaded)
-✅ All linting passes
-
-## Metrics
-
-- **Code reduction:** ~40 lines removed, ~80 lines added (net +40 for R2 support)
-- **Download efficiency:** 220+ requests → 1-4 requests
-- **Storage structure:** Nested 3-level → Flat 1-level
-- **Files migrated:** 227 historical files to R2
-- **Time to migrate:** ~2 minutes for 227 files (~2.3 GB)
-
-## Next Steps
-
-1. Update SQLMesh raw model to support reading from R2 (future work)
-2. Merge branch to master
-3. Deploy to production
-4. Monitor daily extraction runs
-
-## References
-
-- Architecture pattern: Data-oriented design (identify data by content, not metadata)
-- Inspiration: ETag-based caching patterns
-- Storage: Cloudflare R2 (S3-compatible object storage)
diff --git a/.claude/plans/saas-frontend-architecture.md b/.claude/plans/saas-frontend-architecture.md
deleted file mode 100644
index 4411b92..0000000
--- a/.claude/plans/saas-frontend-architecture.md
+++ /dev/null
@@ -1,566 +0,0 @@
-# SaaS Frontend Architecture Plan: beanflows.coffee
-
-**Date**: 2025-10-21
-**Status**: Planning
-**Product**: beanflows.coffee - Coffee market analytics platform
-
-## Project Vision
-
-**beanflows.coffee** - A specialized coffee market analytics platform built on USDA PSD data, providing traders, roasters, and market analysts with actionable insights into global coffee production, trade flows, and supply chain dynamics.
-
-## Architecture Overview
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ Robyn Web App (beanflows.coffee) │
-│ │
-│ Landing Page (Jinja2 + htmx) ─┬─> Auth (JWT + SQLite) │
-│ └─> /dashboards/* routes │
-│ │ │
-│ ▼ │
-│ Serve Evidence /build/ │
-└─────────────────────────────────────────────────────────────┘
- │
- ▼
- ┌──────────────────────────┐
- │ Evidence.dev Dashboards │
- │ (coffee market focus) │
- │ │
- │ Queries: Local DuckDB ←──┼─── Export from Iceberg
- │ Builds: On data updates │
- └──────────────────────────┘
-```
-
-## Technical Decisions
-
-### Data Flow
-- **Source:** Iceberg catalog (R2)
-- **Export:** Local DuckDB file for Evidence dashboards
-- **Trigger:** Rebuild Evidence after SQLMesh updates data
-- **Serving:** Robyn serves Evidence static build output
-
-### Auth System
-- **User data:** SQLite database
-- **Auth method:** JWT tokens (Robyn built-in support)
-- **Consideration:** Evaluate hosted auth services (Clerk, Auth0)
-- **POC approach:** Simple email/password with JWT
-
-### Payments
-- **Provider:** Stripe
-- **Integration:** Webhook-based (Stripe.js on client, webhooks to Robyn)
-- **Rationale:** Simplest integration, no need for complex server-side API calls
-
-### Project Structure
-```
-materia/
-├── web/ # NEW: Robyn web application
-│ ├── app.py # Robyn entry point
-│ ├── routes/
-│ │ ├── landing.py # Marketing page
-│ │ ├── auth.py # Login/signup (JWT)
-│ │ └── dashboards.py # Serve Evidence /build/
-│ ├── templates/ # Jinja2 + htmx
-│ │ ├── base.html
-│ │ ├── landing.html
-│ │ └── login.html
-│ ├── middleware/
-│ │ └── auth.py # JWT verification
-│ ├── models.py # SQLite schema (users table)
-│ └── static/ # CSS, htmx.js
-├── dashboards/ # NEW: Evidence.dev project
-│ ├── pages/ # Dashboard markdown files
-│ │ ├── index.md # Global coffee overview
-│ │ ├── production.md # Production trends
-│ │ ├── trade.md # Trade flows
-│ │ └── supply.md # Supply/demand balance
-│ ├── sources/ # Data source configs
-│ ├── data/ # Local DuckDB exports
-│ │ └── coffee_data.duckdb
-│ └── package.json
-```
-
-## How It Works: Robyn + Evidence Integration
-
-### 1. Evidence Build Process
-```bash
-cd dashboards
-npm run build
-# Outputs static HTML/JS/CSS to dashboards/build/
-```
-
-### 2. Robyn Serves Evidence Output
-```python
-# web/routes/dashboards.py
-@app.get("/dashboards/*")
-@requires_jwt # Custom middleware
-def serve_dashboard(request):
- # Check authentication first
- if not verify_jwt(request):
- return redirect("/login")
-
- # Strip /dashboards/ prefix
- path = request.path.removeprefix("/dashboards/") or "index.html"
-
- # Serve from Evidence build directory
- file_path = Path("dashboards/build") / path
-
- if not file_path.exists():
- file_path = Path("dashboards/build/index.html")
-
- return FileResponse(file_path)
-```
-
-### 3. User Flow
-1. User visits `beanflows.coffee` (landing page)
-2. User signs up / logs in (Robyn auth system)
-3. Stripe checkout for subscription (using Stripe.js)
-4. User navigates to `beanflows.coffee/dashboards/`
-5. Robyn checks JWT authentication
-6. If authenticated: serves Evidence static files
-7. If not: redirects to login
-
-## Phase 1: Evidence.dev POC
-
-**Goal:** Get Evidence working with coffee data
-
-### Tasks
-1. Create Evidence project in `dashboards/`
- ```bash
- mkdir dashboards && cd dashboards
- npm init evidence@latest .
- ```
-
-2. Create SQLMesh export model for coffee data
- ```sql
- -- models/exports/export_coffee_analytics.sql
- COPY (
- SELECT * FROM serving.obt_commodity_metrics
- WHERE commodity_name ILIKE '%coffee%'
- ) TO 'dashboards/data/coffee_data.duckdb';
- ```
-
-3. Build simple coffee production dashboard
- - Single dashboard showing coffee production trends
- - Test Evidence build process
- - Validate DuckDB query performance
-
-4. Test local Evidence dev server
- ```bash
- npm run dev
- ```
-
-**Deliverable:** Working Evidence dashboard querying local DuckDB
-
-## Phase 2: Robyn Web App
-
-### Tasks
-
-1. Set up Robyn project in `web/`
- ```bash
- mkdir web && cd web
- uv add robyn jinja2
- ```
-
-2. Implement SQLite user database
- ```python
- # web/models.py
- import sqlite3
-
- def init_db():
- conn = sqlite3.connect('users.db')
- conn.execute('''
- CREATE TABLE IF NOT EXISTS users (
- id INTEGER PRIMARY KEY,
- email TEXT UNIQUE NOT NULL,
- password_hash TEXT NOT NULL,
- stripe_customer_id TEXT,
- subscription_status TEXT,
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
- )
- ''')
- conn.close()
- ```
-
-3. Add JWT authentication
- ```python
- # web/middleware/auth.py
- from robyn import Request
- import jwt
-
- def requires_jwt(func):
- def wrapper(request: Request):
- token = request.headers.get("Authorization")
- if not token:
- return redirect("/login")
-
- try:
- payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
- request.user = payload
- return func(request)
- except jwt.InvalidTokenError:
- return redirect("/login")
-
- return wrapper
- ```
-
-4. Create landing page (Jinja2 + htmx)
- - Marketing copy
- - Feature highlights
- - Pricing section
- - Sign up CTA
-
-5. Add dashboard serving route
- - Protected by JWT middleware
- - Serves Evidence `build/` directory
-
-**Deliverable:** Authenticated web app serving Evidence dashboards
-
-## Phase 3: Coffee Market Dashboards
-
-### Dashboard Ideas
-
-1. **Global Coffee Production Overview**
- - Top producing countries (Brazil, Vietnam, Colombia, Ethiopia, Honduras)
- - Arabica vs Robusta production split
- - Year-over-year production changes
- - Production volatility trends
-
-2. **Supply & Demand Balance**
- - Stock-to-use ratios by country
- - Export/import flows (trade network visualization)
- - Consumption trends by region
- - Inventory levels (ending stocks)
-
-3. **Market Volatility**
- - Production volatility (weather impacts, climate change signals)
- - Trade flow disruptions (sudden changes in export patterns)
- - Stock drawdown alerts (countries depleting reserves)
-
-4. **Historical Trends**
- - 10-year production trends by country
- - Market share shifts (which countries gaining/losing)
- - Climate impact signals (correlation with weather events)
- - Long-term supply/demand balance
-
-5. **Trade Flow Analysis**
- - Top exporters → top importers (Sankey diagram if possible)
- - Net trade position by country
- - Import dependency ratios
- - Trade balance trends
-
-### Data Requirements
-
-- Filter PSD data for coffee commodity codes
-- May need new serving layer models:
- - `fct_coffee_trade_flows` - Origin/destination trade flows
- - `dim_coffee_varieties` - Arabica vs Robusta (if data available)
- - `agg_coffee_regional_summary` - Regional aggregates
-
-**Deliverable:** Production-ready coffee analytics dashboards
-
-## Phase 4: Deployment & Automation
-
-### Evidence Build Trigger
-
-Rebuild Evidence dashboards after SQLMesh updates data:
-
-```python
-# In SQLMesh post-hook or separate script
-import subprocess
-import httpx
-
-def rebuild_dashboards():
- # Export fresh data from Iceberg to local DuckDB
- subprocess.run([
- "duckdb", "-c",
- "ATTACH 'iceberg_catalog' AS iceberg; "
- "COPY (SELECT * FROM iceberg.serving.obt_commodity_metrics "
- "WHERE commodity_name ILIKE '%coffee%') "
- "TO 'dashboards/data/coffee_data.duckdb';"
- ])
-
- # Rebuild Evidence
- subprocess.run(["npm", "run", "build"], cwd="dashboards")
-
- # Optional: Restart Robyn to pick up new files
- # (or use file watching in development)
-```
-
-**Trigger:** Run after SQLMesh `plan prod` completes successfully
-
-### Deployment Strategy
-
-- **Robyn app:** Deploy to supervisor instance or dedicated worker
-- **Evidence builds:** Built on deploy (run `npm run build` in CI/CD)
-- **DuckDB file:** Exported from Iceberg during deployment
-
-**Deployment flow:**
-```
-GitLab master push
- ↓
-CI/CD: Export coffee data from Iceberg → DuckDB
- ↓
-CI/CD: Build Evidence dashboards (npm run build)
- ↓
-Deploy Robyn app + Evidence build/ to supervisor/worker
- ↓
-Robyn serves landing page + authenticated dashboards
-```
-
-**Deliverable:** Automated pipeline: SQLMesh → Export → Evidence Rebuild → Deployment
-
-## Alternative Architecture: nginx + FastCGI C
-
-### Evaluation
-
-**Current plan:** Robyn (Python web framework)
-**Alternative:** nginx + FastCGI C + kcgi library
-
-### How It Would Work
-
-```
-nginx (static files + Evidence dashboards)
- ↓
-FastCGI C programs (auth, user management, Stripe webhooks)
- ↓
-SQLite (user database)
-```
-
-### Authentication Options
-
-**Option 1: nginx JWT Module**
-- Use open-source JWT module (`kjdev/nginx-auth-jwt`)
-- nginx validates JWT before passing to FastCGI
-- FastCGI receives `REMOTE_USER` variable
-- **Complexity:** Medium (compile nginx with module)
-
-**Option 2: FastCGI C Auth Service**
-- Separate FastCGI program validates JWT
-- nginx uses `auth_request` directive
-- Auth service returns 200 (valid) or 401 (invalid)
-- **Complexity:** Medium (need `libjwt` library)
-
-**Option 3: FastCGI Handles Everything**
-- Main FastCGI program validates JWT inline
-- Uses `libjwt` for token parsing
-- **Complexity:** Medium (simplest architecture)
-
-### Required C Libraries
-
-- **FastCGI:** `kcgi` (modern, secure CGI/FastCGI library)
-- **JWT:** `libjwt` (JWT creation/validation)
-- **HTTP client:** `libcurl` (for Stripe API calls)
-- **JSON:** `json-c` or `cjson` (parsing Stripe webhook payloads)
-- **Database:** `libsqlite3` (user storage)
-- **Templating:** Manual string building (no C equivalent to Jinja2)
-
-### Payment Integration
-
-**Challenge:** No official Stripe C library
-
-**Solutions:**
-
-1. **Webhook-based approach (RECOMMENDED)**
- - Frontend uses Stripe.js (client-side checkout)
- - Stripe sends webhook to FastCGI endpoint
- - C program verifies webhook signature (HMAC-SHA256)
- - Updates user database (subscription status)
- - **Complexity:** Medium (simpler than full API integration)
-
-2. **Direct API calls with libcurl**
- - Make HTTP POST to Stripe API
- - Build JSON payloads manually
- - Parse JSON responses with `json-c`
- - **Complexity:** High (manual HTTP/JSON handling)
-
-### Development Time Estimate
-
-| Task | Robyn (Python) | FastCGI (C) |
-|------|----------------|-------------|
-| Basic auth | 2-3 days | 5-7 days |
-| Payment integration | 3-5 days | 7-10 days |
-| Template rendering | 1-2 days | 5-7 days |
-| Debugging/testing | 1-2 days | 3-5 days |
-| **Total POC** | **1-2 weeks** | **3-4 weeks** |
-
-### Performance Comparison
-
-**Robyn (Python):** ~1,000-5,000 req/sec
-**nginx + FastCGI C:** ~10,000-50,000 req/sec
-
-**Reality check:** For beanflows.coffee with <1000 users, even 100 req/sec is plenty.
-
-### Pros & Cons
-
-**Pros of C approach:**
-- 10-50x faster than Python
-- Lower memory footprint (~5-10MB vs 50-100MB)
-- Simpler deployment (compiled binary + nginx config)
-- More direct, no framework magic
-- Data-oriented, performance-first design
-
-**Cons of C approach:**
-- 2-3x longer development time
-- More complex debugging (no interactive REPL)
-- Manual memory management (potential for leaks/bugs)
-- No templating library (build HTML with sprintf/snprintf)
-- Stripe integration requires manual HTTP/JSON handling
-- Steeper learning curve for team members
-
-### Recommendation
-
-**Start with Robyn, plan migration path to C:**
-
-**Phase 1 (Now):** Build with Robyn
-- Fast development (1-2 weeks to POC)
-- Prove product-market fit
-- Get paying customers
-- Measure actual performance needs
-
-**Phase 2 (After launch):** Evaluate performance
-- Monitor Robyn performance under real load
-- If Robyn handles <1000 users easily → stay with it
-- If hitting bottlenecks → profile to find hot paths
-
-**Phase 3 (Optional, if needed):** Incremental C migration
-- Rewrite hot paths only (e.g., auth service)
-- Keep Evidence dashboards static (nginx serves directly)
-- Hybrid architecture: nginx → C (auth) → Robyn (business logic)
-
-### Hybrid Architecture (Best of Both Worlds)
-
-```
-nginx
- ↓
- ├─> Static files (Evidence dashboards) [nginx serves directly]
- ├─> Auth endpoints (/login, /signup) [FastCGI C - future optimization]
- └─> Business logic (/api/*, /webhooks) [Robyn - for flexibility]
-```
-
-**When to migrate:**
-- When Robyn becomes measurable bottleneck (>80% CPU under normal load)
-- When response times exceed targets (>100ms p95)
-- When memory usage becomes concern (>500MB for simple app)
-
-**Philosophy:** Measure first, optimize second. Data-oriented approach means we don't guess about performance, we measure and optimize only when needed.
-
-## Implementation Order
-
-1. **Week 1:** Evidence POC + local DuckDB export
- - Create Evidence project
- - Export coffee data from Iceberg
- - Build simple production dashboard
- - Validate local dev workflow
-
-2. **Week 2:** Robyn app + basic auth + Evidence embedding
- - Set up Robyn project
- - SQLite user database
- - JWT authentication
- - Landing page (Jinja2 + htmx)
- - Serve Evidence dashboards at `/dashboards/*`
-
-3. **Week 3:** Coffee-specific dashboards + Stripe
- - Build 3-4 core coffee dashboards
- - Integrate Stripe checkout
- - Webhook handling for subscriptions
- - Basic user account page
-
-4. **Week 4:** Automated rebuild pipeline + deployment
- - Automate Evidence rebuild after SQLMesh runs
- - CI/CD pipeline for deployment
- - Deploy to supervisor or dedicated worker
- - Monitoring and analytics
-
-## Open Questions
-
-1. **Hosted auth:** Evaluate Clerk vs Auth0 vs roll-our-own
- - Clerk: $25/mo for 1000 MAU, nice DX
- - Auth0: Free tier 7500 MAU, more enterprise
- - Roll our own: $0, full control, more code
- - **Decision:** Start with roll-our-own JWT (simplest), migrate to hosted if auth becomes complex
-
-2. **DuckDB sync:** How often to export from Iceberg?
- - Option A: Daily (after SQLMesh runs)
- - Option B: After every SQLMesh plan
- - **Decision:** Daily for now, automate after SQLMesh completion in production
-
-3. **Evidence build time:** If builds are slow, need caching strategy
- - Monitor build times in Phase 1
- - If >60s, investigate Evidence cache options
- - May need incremental builds
-
-4. **Multi-commodity future:** How to expand beyond coffee?
- - Code structure should be generic (parameterize commodity filter)
- - Could launch cocoa.flows, wheat.supply, etc.
- - Evidence supports parameterized pages (easy to expand)
-
-5. **C migration decision point:** What metrics trigger rewrite?
- - CPU >80% sustained under normal load
- - Response times >100ms p95
- - Memory >500MB for simple app
- - User complaints about slowness
-
-## Success Metrics
-
-**Phase 1 (POC):**
-- Evidence site builds successfully
-- Coffee data loads from DuckDB (<2s)
-- One dashboard renders with real data
-- Local dev server runs without errors
-
-**Phase 2 (MVP):**
-- Robyn app runs and serves Evidence dashboards
-- JWT auth works (login/signup flow)
-- Landing page loads <2s
-- Dashboard access restricted to authenticated users
-
-**Phase 3 (Launch):**
-- Stripe integration works (test payment succeeds)
-- 3-4 coffee dashboards functional
-- Automated deployment pipeline working
-- Monitoring in place (uptime, errors, performance)
-
-**Phase 4 (Growth):**
-- User signups (track conversion rate)
-- Active subscribers (MRR growth)
-- Dashboard usage (which insights most valuable)
-- Performance metrics (response times, error rates)
-
-## Cost Analysis
-
-**Current costs (data pipeline):**
-- Supervisor: €4.49/mo (Hetzner CPX11)
-- Workers: €0.01-0.05/day (ephemeral)
-- R2 Storage: ~€0.10/mo (Iceberg catalog)
-- **Total: ~€5/mo**
-
-**Additional costs (SaaS frontend):**
-- Domain: €10/year (beanflows.coffee)
-- Robyn hosting: €0 (runs on supervisor or dedicated worker €4.49/mo)
-- Stripe fees: 2.9% + €0.30 per transaction
-- **Total: ~€5-10/mo base cost**
-
-**Scaling costs:**
-- If need dedicated worker for Robyn: +€4.49/mo
-- If migrate to C: No additional cost (same infrastructure)
-- Stripe fees scale with revenue (good problem to have)
-
-## Next Steps (When Ready)
-
-1. Create `dashboards/` directory and initialize Evidence.dev
-2. Create SQLMesh export model for coffee data
-3. Build simple coffee production dashboard
-4. Set up Robyn project structure
-5. Implement basic JWT auth
-6. Integrate Evidence dashboards into Robyn
-
-**Decision point:** After Phase 1 POC, re-evaluate C migration based on Evidence.dev capabilities and development experience.
-
-## References
-
-- Evidence.dev: https://docs.evidence.dev/
-- Robyn: https://github.com/sparckles/robyn
-- kcgi (C CGI library): https://kristaps.bsd.lv/kcgi/
-- libjwt: https://github.com/benmcollins/libjwt
-- nginx auth_request: https://nginx.org/en/docs/http/ngx_http_auth_request_module.html
-- Stripe webhooks: https://stripe.com/docs/webhooks
diff --git a/.gitignore b/.gitignore
index 22074da..f56d31d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
+.agent_work/
*.db
data/
+logs/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index f4a4cb4..0000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,123 +0,0 @@
-image: python:3.13
-
-stages:
- - lint
- - test
- - deploy
-
-variables:
- UV_CACHE_DIR: "$CI_PROJECT_DIR/.uv-cache"
-
-cache:
- paths:
- - .uv-cache/
-
-.uv_setup: &uv_setup
- - curl -LsSf https://astral.sh/uv/install.sh | sh
- - export PATH="$HOME/.cargo/bin:$PATH"
- - source $HOME/.local/bin/env
-
-workflow:
- rules:
- - if: $CI_PIPELINE_SOURCE == "merge_request_event"
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- - if: $CI_COMMIT_TAG
-
-lint:
- stage: lint
- before_script:
- - *uv_setup
- script:
- - uv sync
- - uv run ruff check .
-
-test:cli:
- stage: test
- before_script:
- - *uv_setup
- script:
- - uv sync
- - uv run pytest tests/ -v --cov=src/materia --cov-report=xml --cov-report=term
- coverage: '/TOTAL.*\s+(\d+%)$/'
- artifacts:
- reports:
- coverage_report:
- coverage_format: cobertura
- path: coverage.xml
-
-test:sqlmesh:
- stage: test
- before_script:
- - *uv_setup
- script:
- - uv sync
- - cd transform/sqlmesh_materia && uv run sqlmesh test
-
-deploy:infra:
- stage: deploy
- image: pulumi/pulumi:latest
- before_script:
- - export PULUMI_ACCESS_TOKEN="${PULUMI_ACCESS_TOKEN}"
- script:
- - cd infra && pulumi stack select prod && pulumi up --yes
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
-
-deploy:supervisor:
- stage: deploy
- image: alpine:latest
- before_script:
- - apk add --no-cache openssh-client curl bash
- - curl -fsSL https://get.pulumi.com/esc/install.sh | sh
- - export PATH="$HOME/.pulumi/bin:$PATH"
- - export PULUMI_ACCESS_TOKEN="${PULUMI_ACCESS_TOKEN}"
- - esc login
- - eval $(esc env open beanflows/prod --format shell)
- # Install Pulumi CLI to get stack outputs
- - curl -fsSL https://get.pulumi.com/install.sh | sh
- - export PATH="$HOME/.pulumi/bin:$PATH"
- script:
- - |
- # Get supervisor IP from Pulumi
- cd infra
- SUPERVISOR_IP=$(pulumi stack output supervisor_ip -s prod)
- cd ..
-
- # Check if supervisor exists
- if [ -z "$SUPERVISOR_IP" ] || [ "$SUPERVISOR_IP" = "null" ]; then
- echo "No supervisor instance found. Run 'pulumi up' first."
- exit 1
- fi
-
- echo "Connecting to supervisor at ${SUPERVISOR_IP}..."
-
- # Setup SSH
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H $SUPERVISOR_IP >> ~/.ssh/known_hosts
-
- # Wait for SSH to be ready (new instance may take a moment)
- echo "Waiting for SSH to be ready..."
- for i in $(seq 1 30); do
- if ssh -o ConnectTimeout=5 root@${SUPERVISOR_IP} "echo 'SSH ready'"; then
- break
- fi
- echo "Attempt $i/30 failed, retrying..."
- sleep 10
- done
-
- # Check if supervisor is bootstrapped
- if ssh root@${SUPERVISOR_IP} "test -d /opt/materia/.git"; then
- echo "Supervisor already bootstrapped and will auto-update"
- ssh root@${SUPERVISOR_IP} "systemctl status materia-supervisor --no-pager"
- else
- echo "Bootstrapping supervisor for the first time..."
- # Export secrets and run bootstrap
- ssh root@${SUPERVISOR_IP} "export PULUMI_ACCESS_TOKEN='${PULUMI_ACCESS_TOKEN}' GITLAB_READ_TOKEN='${GITLAB_READ_TOKEN}' && bash -s" < infra/bootstrap_supervisor.sh
- echo "Bootstrap complete!"
- fi
- dependencies:
- - deploy:infra
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
deleted file mode 100644
index ac6754f..0000000
--- a/.pre-commit-config.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-repos:
- - repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.3.0 # Use the latest version
- hooks:
- - id: ruff
- args: [--fix]
- - id: ruff-format
-
- - repo: local
- hooks:
- - id: uv-pip-compile
- name: uv pip compile
- entry: uv pip compile
- language: system
- files: ^requirements\.(in|txt)$
- pass_filenames: false
-
- - repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.5.0 # Use the latest version
- hooks:
- - id: trailing-whitespace
- - id: end-of-file-fixer
- - id: check-yaml
- - id: check-added-large-files
diff --git a/CLAUDE.md b/CLAUDE.md
deleted file mode 100644
index 923d8b5..0000000
--- a/CLAUDE.md
+++ /dev/null
@@ -1,376 +0,0 @@
-# CLAUDE.md
-
-This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
-
-## Project Overview
-
-Materia is a commodity data analytics platform built on a modern data engineering stack. The project extracts agricultural commodity data from USDA PSD Online, transforms it through a layered SQL pipeline using SQLMesh, and stores it in DuckDB for analysis.
-
-**Tech Stack:**
-- Python 3.13 with `uv` package manager
-- SQLMesh for SQL transformation and orchestration
-- DuckDB as the analytical database
-- Workspace structure with separate extract and transform packages
-
-## Environment Setup
-
-**Install dependencies:**
-```bash
-uv sync
-```
-
-**Setup pre-commit hooks:**
-```bash
-pre-commit install
-```
-
-**Add new dependencies:**
-```bash
-uv add
-```
-
-## Secrets Management with Pulumi ESC
-
-All secrets are managed via Pulumi ESC (Environment, Secrets, and Configuration). The production environment is `beanflows/prod`.
-
-**Load secrets into your shell:**
-```bash
-# Login to Pulumi ESC (one-time)
-esc login
-
-# Load secrets as environment variables
-eval $(esc env open beanflows/prod --format shell)
-
-# Now all secrets are available as env vars
-echo $R2_ENDPOINT # Example: access R2 endpoint
-```
-
-**Run commands with ESC secrets:**
-```bash
-# Run a command with secrets loaded
-esc run beanflows/prod -- uv run extract_psd
-
-# Run multiple commands
-esc run beanflows/prod -- bash -c "
- uv run extract_psd
- cd transform/sqlmesh_materia && uv run sqlmesh plan prod
-"
-```
-
-**Available secrets in `beanflows/prod`:**
-- R2 storage: `R2_ENDPOINT`, `R2_BUCKET`, `R2_ACCESS_KEY`, `R2_SECRET_KEY`
-- Hetzner Cloud: `HETZNER_TOKEN`, SSH keys
-- GitLab: `GITLAB_READ_TOKEN`
-- Iceberg catalog credentials
-
-**Note:** Never hardcode secrets! Always use Pulumi ESC or environment variables.
-
-## Project Structure
-
-This is a uv workspace with three main components:
-
-### 1. Extract Layer (`extract/`)
-Contains extraction packages for pulling data from external sources.
-
-- **`extract/psdonline/`**: Extracts USDA PSD commodity data
- - Entry point: `extract_psd` CLI command (defined in `extract/psdonline/src/psdonline/execute.py`)
- - Checks latest available monthly snapshot (tries current month and 3 months back)
- - Uses ETags to avoid re-downloading unchanged files
- - Storage modes:
- - **Local mode** (no R2 credentials): Downloads to `extract/psdonline/src/psdonline/data/{etag}.zip`
- - **R2 mode** (R2 credentials present): Uploads to `s3://bucket/psd/{etag}.zip`
- - Flat structure: files named by ETag for natural deduplication
-
-**Run extraction:**
-```bash
-extract_psd # Local mode (default)
-
-# R2 mode (requires env vars: R2_ENDPOINT, R2_BUCKET, R2_ACCESS_KEY, R2_SECRET_KEY)
-export R2_ENDPOINT=...
-export R2_BUCKET=...
-export R2_ACCESS_KEY=...
-export R2_SECRET_KEY=...
-extract_psd
-```
-
-### 2. Transform Layer (`transform/sqlmesh_materia/`)
-SQLMesh project implementing a layered data architecture.
-
-**Working directory:** All SQLMesh commands must be run from the project root with `-p transform/sqlmesh_materia`
-
-**Key commands:**
-```bash
-# Load secrets and run SQLMesh commands
-# Always run from project root with -p flag and uv
-
-# Local development (creates virtual environment)
-esc run beanflows/prod -- uv run sqlmesh -p transform/sqlmesh_materia plan dev_
-
-# Production
-esc run beanflows/prod -- uv run sqlmesh -p transform/sqlmesh_materia plan prod
-
-# Run tests
-uv run sqlmesh -p transform/sqlmesh_materia test
-
-# Validate models
-uv run sqlmesh -p transform/sqlmesh_materia validate
-
-# Run audits (requires secrets)
-esc run beanflows/prod -- uv run sqlmesh -p transform/sqlmesh_materia audit
-
-# Format SQL
-uv run sqlmesh -p transform/sqlmesh_materia format
-
-# Start UI (requires secrets)
-esc run beanflows/prod -- uv run sqlmesh -p transform/sqlmesh_materia ui
-```
-
-**Configuration:**
-- Config: `transform/sqlmesh_materia/config.yaml`
-- Single gateway: `prod` (connects to R2 Iceberg catalog)
-- Uses virtual environments for dev isolation (e.g., `dev_deeman`)
-- Production uses `prod` environment
-- Auto-apply enabled, no interactive prompts
-- DuckDB extensions: httpfs, iceberg
-
-**Environment Strategy:**
-- All environments connect to the same R2 Iceberg catalog
-- Dev environments (e.g., `dev_deeman`) are isolated virtual environments
-- SQLMesh manages environment isolation and table versioning
-- No local DuckDB files needed
-
-### 3. Core Package (`src/materia/`)
-Currently minimal; main logic resides in workspace packages.
-
-## Data Architecture
-
-SQLMesh models follow a strict 4-layer architecture defined in `transform/sqlmesh_materia/models/README.md`:
-
-### Layer 1: Raw (`models/raw/`)
-- **Purpose:** Immutable archive of source data
-- **Pattern:** Directly reads from extraction outputs
-- **Example:** `raw.psd_alldata` reads zip files using DuckDB's `read_csv('zip://...')` function
-- **Grain:** Defines unique keys for each raw table
-
-### Layer 2: Staging (`models/staging/`)
-- **Purpose:** Apply schema, cast types, basic cleansing
-- **Pattern:** `stg_[source]__[entity]`
-- **Example:** `stg_psdalldata__commodity.sql` casts raw strings to proper types, joins lookup tables
-- **Features:**
- - Deduplication using hash keys
- - Extracts metadata (ingest_date) from file paths
- - 1:1 relationship with raw sources
-
-### Layer 3: Cleaned (`models/cleaned/`)
-- **Purpose:** Integration, business logic, unified models
-- **Pattern:** `cln_[entity]` or `cln_[vault_component]_[entity]`
-- **Example:** `cln_psdalldata__commodity_pivoted.sql` pivots commodity attributes into columns
-
-### Layer 4: Serving (`models/serving/`)
-- **Purpose:** Analytics-ready models (star schema, aggregates)
-- **Patterns:**
- - `dim_[entity]` for dimensions
- - `fct_[process]` for facts
- - `agg_[description]` for aggregates
- - `obt_[description]` for one-big-tables
-- **Example:** `obt_commodity_metrics.sql` provides wide table for analysis
-
-## Model Development
-
-**Incremental models:**
-- Use `INCREMENTAL_BY_TIME_RANGE` kind
-- Define `time_column` (usually `ingest_date`)
-- Filter with `WHERE time_column BETWEEN @start_ds AND @end_ds`
-
-**Full refresh models:**
-- Use `FULL` kind for small lookup tables and raw sources
-
-**Model properties:**
-- `grain`: Define unique key columns for data quality
-- `start`: Historical backfill start date (project default: 2025-07-07)
-- `cron`: Schedule (project default: '@daily')
-
-## Linting and Formatting
-
-**Run linting:**
-```bash
-ruff check .
-```
-
-**Auto-fix issues:**
-```bash
-ruff check --fix .
-```
-
-**Format code:**
-```bash
-ruff format .
-```
-
-Pre-commit hooks automatically run ruff on commits.
-
-## Testing
-
-**Run SQLMesh tests:**
-```bash
-cd transform/sqlmesh_materia
-sqlmesh test
-```
-
-**Run Python tests (if configured):**
-```bash
-pytest --cov=./ --cov-report=xml
-```
-
-## CI/CD Pipeline and Production Architecture
-
-### CI/CD Pipeline (`.gitlab-ci.yml`)
-
-**3 Stages: Lint → Test → Deploy**
-
-#### 1. Lint Stage
-- Runs `ruff check` on every commit
-- Validates code quality
-
-#### 2. Test Stage
-- **`test:cli`**: Runs pytest on materia CLI with 71% coverage
- - Tests secrets management (Pulumi ESC integration)
- - Tests worker lifecycle (create, list, destroy)
- - Tests pipeline execution (extract, transform)
- - Exports coverage reports to GitLab
-- **`test:sqlmesh`**: Runs SQLMesh model tests in transform layer
-
-#### 3. Deploy Stage (only on master branch)
-- **`deploy:infra`**: Runs `pulumi up` to ensure supervisor instance exists
- - Runs on every master push
- - Creates/updates Hetzner CPX11 supervisor instance (~€4.49/mo)
- - Uses Pulumi ESC (`beanflows/prod`) for all secrets
-- **`deploy:supervisor`**: Bootstraps and monitors supervisor
- - Checks if supervisor is already bootstrapped (`test -d /opt/materia/.git`)
- - If not bootstrapped: Runs `infra/bootstrap_supervisor.sh` automatically
- - If already bootstrapped: Verifies service status
- - After bootstrap: Supervisor auto-updates via `git pull` every 15 minutes
-
-**Note:** No build artifacts! Supervisor pulls code directly from git and runs via `uv`.
-
-### Production Architecture: Git-Based Deployment with Ephemeral Workers
-
-**Design Philosophy:**
-- No always-on workers (cost optimization)
-- Supervisor pulls latest code from git (no artifact builds)
-- Supervisor dynamically creates/destroys workers on-demand
-- Simple, inspectable, easy to test locally
-- Multi-cloud abstraction for pricing optimization
-
-**Components:**
-
-#### 1. Supervisor Instance (Small Hetzner VM)
-- Runs `supervisor.sh` - continuous orchestration loop (inspired by TigerBeetle's CFO supervisor)
-- Hetzner CPX11: 2 vCPU (shared), 2GB RAM (~€4.49/mo)
-- Always-on, minimal resource usage
-- Git-based deployment: `git pull` every 15 minutes for auto-updates
-- Runs pipelines on schedule:
- - Extract: Daily at 2 AM UTC
- - Transform: Daily at 3 AM UTC
-- Uses systemd service for automatic restart on failure
-- Pulls secrets from Pulumi ESC
-
-**Bootstrap:**
-Bootstrapping happens automatically in CI/CD (`deploy:supervisor` stage). The pipeline:
-1. Checks if supervisor is already bootstrapped
-2. If not: Runs `infra/bootstrap_supervisor.sh` with secrets injected
-3. If yes: Verifies systemd service status
-
-Manual bootstrap (if needed):
-```bash
-cd infra && pulumi stack output supervisor_ip -s prod
-export PULUMI_ACCESS_TOKEN=
-ssh root@ 'bash -s' < infra/bootstrap_supervisor.sh
-```
-
-#### 2. Ephemeral Workers (On-Demand)
-- Created for each pipeline execution by materia CLI
-- Receives secrets via SSH environment variable injection
-- Destroyed immediately after job completion
-- Different instance types per pipeline:
- - Extract: `ccx12` (2 vCPU, 8GB RAM)
- - Transform: `ccx22` (4 vCPU, 16GB RAM)
-
-#### 3. Secrets Flow
-```
-Pulumi ESC (beanflows/prod)
- ↓
-Supervisor Instance (via esc CLI)
- ↓
-Workers (injected as env vars via SSH)
-```
-
-#### 4. Code Deployment Flow
-```
-GitLab (master branch)
- ↓
-Supervisor: git pull origin master (every 15 min)
- ↓
-Supervisor: uv sync (update dependencies)
- ↓
-Supervisor: uv run materia pipeline run
-```
-
-#### 5. Data Storage
-- **All environments**: DuckDB in-memory + Cloudflare R2 Data Catalog (Iceberg REST API)
- - ACID transactions on object storage
- - No persistent database on workers
- - Virtual environments for dev isolation (e.g., `dev_deeman`)
-
-**Execution Flow:**
-1. Supervisor loop wakes up every 15 minutes
-2. Runs `git fetch` and checks if new commits on master
-3. If updates available: `git pull && uv sync`
-4. Checks if current time matches pipeline schedule (e.g., 2 AM for extract)
-5. If scheduled: `uv run materia pipeline run extract`
-6. CLI creates Hetzner worker with SSH key
-7. CLI injects secrets via SSH and executes pipeline
-8. Pipeline executes, writes to R2 Iceberg catalog
-9. Worker destroyed (entire lifecycle ~5-10 minutes)
-10. Supervisor logs results and continues loop
-
-**Multi-Cloud Provider Abstraction:**
-- Protocol-based interface (data-oriented design, no OOP)
-- Providers: Hetzner (implemented), OVH, Scaleway, Oracle (stubs)
-- Allows switching providers for cost optimization
-- Each provider implements: `create_instance`, `destroy_instance`, `list_instances`, `wait_for_ssh`
-
-## Key Design Patterns
-
-**Raw data ingestion:**
-- DuckDB reads directly from zip archives using `read_csv('zip://...')`
-- `filename=true` captures source file path for metadata
-- `union_by_name=true` handles schema evolution
-
-**Deduplication:**
-- Use `hash()` function to create unique keys
-- Use `any_value()` with `GROUP BY hkey` to deduplicate
-- Preserve all metadata in hash key for change detection
-
-**Date handling:**
-- Extract ingest dates from file paths: `make_date(split(filename, '/')[-4]::int, split(filename, '/')[-3]::int, 1)`
-- Calculate market dates: `last_day(make_date(market_year, month, 1))`
-
-**SQLMesh best practices:**
-- Always define `grain` for data quality validation
-- Use meaningful model names following layer conventions
-- Leverage SQLMesh's built-in time macros (`@start_ds`, `@end_ds`)
-- Keep raw layer thin, push transformations to staging+
-
-## Data Storage
-
-All data is stored in Cloudflare R2 Data Catalog (Apache Iceberg) via REST API:
-- **Production environment:** `prod`
-- **Dev environments:** `dev_` (virtual environments)
-- SQLMesh manages environment isolation and table versioning
-- No local database files needed
-- We use a monorepo with uv workspaces
-- The pulumi env is called beanflows/prod
-- NEVER hardcode secrets in plaintext
-- Never add ssh keys to the git repo!
-- If there is a simpler more direct solution and there is no other tradeoff, always choose the simpler solution
diff --git a/MARKETOVERVIEW.md b/MARKETOVERVIEW.md
deleted file mode 100644
index f3fde3e..0000000
--- a/MARKETOVERVIEW.md
+++ /dev/null
@@ -1,933 +0,0 @@
-I need a market overview over the commodity analytics market. I need to know everything i need to build a software like kpler myself. data sources, partners etc. The report should have details on all companies like kpler that are used by commodity traders. The structure for each company part should be modeled after the parts of a business model canvas and have details on every part, especially where they probably get their data from. Also try finding out pricing or estimate it, if you estimate mark it as an estimate though. I have the below initial analyses, you can use that as input.
-
---
-# Commodity Analytics Market: Comprehensive Overview
-
-## Executive Summary
-
-The commodity analytics market is dominated by platforms that provide real-time trade intelligence, cargo tracking, and market fundamentals. The market size is estimated at several billion dollars, with leading players including Kpler, Vortexa, S&P Global Platts, Bloomberg, and LSEG (formerly Refinitiv).
-
-**Key Success Factors:**
-- Access to multiple proprietary data sources (AIS, satellite, bills of lading, port data, refinery data)
-- Real-time data processing and AI/ML capabilities
-- Expert analyst teams providing market insights
-- API and integration capabilities
-- Global coverage across 40+ commodities
-
----
-
-## Market Size & Growth
-
-- **Kpler**: $40M ARR in 2022, targeting $300M+ ARR by 2026, serving 460+ clients with 4,500+ active users
-- **Vortexa**: ~$95M annual revenue (2024 estimate), 30% YoY growth in ARR (2023)
-- **Total addressable market**: Estimated $5-10B+ annually including all data providers
-
----
-
-# Major Players Analysis (Business Model Canvas Structure)
-
-## 1. KPLER
-
-### Customer Segments
-- Physical commodity traders (oil, gas, LNG, dry bulk)
-- Financial traders and hedge funds (BP, Shell, ExxonMobil, Goldman Sachs)
-- Charterers and vessel operators
-- Fleet managers
-- Logistics and supply chain professionals
-- Energy ministries and government agencies
-
-### Value Propositions
-- **"One platform for global trade intelligence"**
-- Real-time cargo tracking across 40+ commodities
-- 500M+ daily data points from 500+ sources
-- Proprietary AIS network (largest in the world with 13,000+ receivers)
-- AI-powered predictive models for destination forecasting
-- Supply & demand balance modeling
-- Tank-level inventory tracking
-- 900+ refinery monitoring globally
-
-### Channels
-- Direct sales team (offices in NY, Houston, London, Paris, Brussels, Dubai, Singapore, Tokyo, Cape Town)
-- Web-based terminal
-- API/SDK integrations
-- Excel Add-in
-- Snowflake Data Share
-- LiveDB for pre-formatted analytics
-
-### Customer Relationships
-- Subscription-based model with recurring revenue
-- Dedicated account management
-- 24/7 support
-- Training and onboarding
-- Custom reports and consulting services
-
-### Revenue Streams
-- **Primary**: Subscription fees (tiered pricing by functionality and commodities)
-- **Secondary**: Custom consulting and reports
-- **Estimated Pricing**: $30,000-$100,000+ per user/year depending on commodity coverage and features (ESTIMATE)
-
-### Key Resources
-- **Technology**: Proprietary platform processing 10M+ data points daily
-- **Data Assets**:
- - Largest AIS network globally (owns MarineTraffic, FleetMon, Spire Maritime - acquired 2023-2024 for ~$474M total)
- - 13,000+ AIS receivers (terrestrial + satellite)
- - Historical data back to 2010
-- **Human Capital**: 600+ employees, 35+ nationalities
-- **Intellectual Property**: AI/ML algorithms, predictive models
-
-### Key Activities
-- Real-time data collection and processing
-- AIS signal capture and interpretation
-- Satellite imagery analysis
-- Machine learning model development
-- Analyst-driven market research
-- Product development and platform maintenance
-
-### Key Partnerships
-- **Data Providers**:
- - ClipperData (acquired 2021)
- - JBC Energy (acquired 2022)
- - COR-e power market data (acquired 2022)
- - MarineTraffic (acquired 2023)
- - FleetMon (acquired 2023)
- - Spire Maritime satellite AIS (acquired 2024)
- - Bills of lading providers (multiple sources)
- - Port authorities (global)
- - Customs agencies
- - Baltic Exchange (freight pricing)
- - Spark pricing data
-- **Technology Partners**: Cloud infrastructure providers, satellite operators
-
-### Cost Structure
-- **Data Acquisition**: Bills of lading, satellite data, port data subscriptions
-- **Infrastructure**: Cloud computing, data processing, storage
-- **Personnel**: 600+ employees (engineers, data scientists, analysts, sales)
-- **Technology Development**: Platform development, AI/ML
-- **Acquisitions**: $474M+ spent on acquisitions (2021-2024)
-- **Operations**: Global offices, customer support
-
-### Data Sources (Critical for Building Similar Platform)
-1. **AIS Data**: Own network + satellite constellation
-2. **Bills of Lading**: Customs data from multiple countries
-3. **Satellite Imagery**: Optical and SAR for tank monitoring
-4. **Port Data**: Terminal and berth information
-5. **Refinery Data**: Operating status, capacity, turnarounds
-6. **Vessel Databases**: IMO registries, vessel specifications
-7. **Freight Pricing**: Baltic Exchange partnership
-8. **Market Data**: Exchange prices, broker quotes
-9. **Official Statistics**: EIA, IEA, national agencies
-10. **Weather Data**: For voyage predictions
-
----
-
-## 2. VORTEXA
-
-### Customer Segments
-- Energy traders (oil & gas)
-- Shipping companies and freight brokers
-- Financial institutions trading energy derivatives
-- Oil majors and trading houses
-- Refineries
-- Energy analysts
-
-### Value Propositions
-- **"99% accuracy in tracking global energy flows"**
-- Tracks $3.4 trillion in waterborne energy trades annually
-- Real-time cargo tracking for oil, refined products, LNG, LPG
-- Anywhere Freight Pricing: port-to-port pricing for 70M+ possible routes
-- External data source transparency (BoL, fixtures, port data visibility)
-- 4x per week Cushing inventory updates
-- AI-powered predictive analytics
-
-### Channels
-- Direct sales (offices in London, Geneva, Singapore, Houston, NYC, UAE)
-- Web platform
-- RESTful API
-- Excel Add-in
-- Python SDK
-
-### Customer Relationships
-- Subscription model
-- Solutions architects for custom integrations
-- Account management
-- Analyst access for market insights
-
-### Revenue Streams
-- **Primary**: Subscription fees
-- **Estimated Pricing**: $40,000-$120,000+ per user/year (ESTIMATE based on competitor analysis)
-- 30% YoY ARR growth reported in 2023
-
-### Key Resources
-- **Data Network**: 1,000+ satellites, 500B+ AIS pings, 100+ market data sources
-- **Technology**: Proprietary ML algorithms, deep tech
-- **Human Capital**: 170+ employees across energy expertise, data science, engineering
-- **Partnerships**: Baltic Exchange (freight pricing)
-
-### Key Activities
-- Real-time data aggregation from satellites and AIS
-- Machine learning for cargo and grade prediction
-- Freight pricing model development
-- Market analysis and research
-- Platform development
-
-### Key Partnerships
-- **Data Sources**:
- - Baltic Exchange (freight pricing benchmarks)
- - Multiple satellite providers
- - AIS network providers
- - Bills of lading vendors (multiple)
- - Port authorities
- - Fixtures databases
- - Energy Aspects (strategic partnership for research)
-- **Technology**: Cloud providers, satellite operators
-
-### Cost Structure
-- Satellite data acquisition
-- AIS data feeds
-- Cloud infrastructure for data processing
-- 170+ employee salaries
-- R&D for ML/AI development
-- Global office operations
-
-### Data Sources
-1. **Satellite AIS**: Multiple providers
-2. **Terrestrial AIS**: Partner networks
-3. **Bills of Lading**: Commercial data providers
-4. **Fixtures**: Shipping fixtures databases
-5. **Port Data**: Terminal operations data
-6. **Satellite Imagery**: For inventory monitoring
-7. **Freight Pricing**: Baltic Exchange
-8. **Market Prices**: Exchange and OTC data
-
----
-
-## 3. S&P GLOBAL COMMODITY INSIGHTS (PLATTS)
-
-### Customer Segments
-- Commodity traders (all asset classes)
-- Producers and refiners
-- Financial institutions
-- Government agencies
-- Risk managers
-- Logistics companies
-
-### Value Propositions
-- **"Over 100 years of price transparency leadership"**
-- Benchmark price assessments (industry standard)
-- Coverage: oil, gas, power, petrochemicals, metals, agriculture, shipping
-- Platts eWindow for real-time price discovery
-- Forward curves and risk market data
-- Largest editorial team (200+ commodity journalists in 20+ countries)
-
-### Channels
-- Platts Connect platform
-- Platts Dimensions Pro
-- Data feeds (FTP, API)
-- Integration with LSEG platforms
-- Mobile apps
-
-### Customer Relationships
-- Enterprise-wide licensing (unlimited users)
-- Fixed-fee model (no per-user charges)
-- 24/7 support
-- Dedicated account teams
-- Methodology transparency sessions
-
-### Revenue Streams
-- **Primary**: Enterprise subscription packages
-- Commodity-specific packages (Crude, Refined Products, Metals, Ag, Power, etc.)
-- **Estimated Pricing**: $50,000-$500,000+ per enterprise annually depending on commodity coverage (ESTIMATE)
-
-### Key Resources
-- 200+ specialist commodity journalists
-- Decades of historical price data (some back to 1900)
-- Proprietary price assessment methodologies
-- Editorial credibility and market trust
-- TRADENET vessel tracking platform (acquired 2023)
-
-### Key Activities
-- Daily price assessments through market survey methodology
-- Real-time price discovery via Platts eWindow
-- Fundamental research and analysis
-- Market intelligence gathering
-- Editorial reporting
-
-### Key Partnerships
-- **Acquired Assets**:
- - TRADENET (vessel tracking, 2023)
- - Integration with parent company S&P Global Market Intelligence
-- **Data Feeds**: Exchange data, OTC brokers, market participants
-- **Technology**: Cloud providers
-
-### Cost Structure
-- 200+ editorial staff globally
-- Technology infrastructure
-- Data acquisition and validation
-- Global office network
-- Acquisitions (TRADENET, others)
-
-### Data Sources
-1. **Market Survey**: Direct from traders, producers, buyers
-2. **Platts eWindow**: Real-time trading platform data
-3. **Exchange Data**: CME, ICE, LME, etc.
-4. **Vessel Tracking**: TRADENET acquisition
-5. **Official Statistics**: Government agencies
-6. **Broker Data**: OTC market data
-7. **Fundamentals**: Supply/demand data from various sources
-
----
-
-## 4. BLOOMBERG TERMINAL
-
-### Customer Segments
-- Financial professionals across all asset classes
-- Commodity traders
-- Portfolio managers
-- Investment banks
-- Hedge funds
-- Corporate treasurers
-
-### Value Propositions
-- **"Most comprehensive financial data platform"**
-- Real-time data across ALL asset classes
-- 350,000+ Bloomberg Terminal users globally (network effects)
-- Instant Bloomberg messaging (critical for trading community)
-- Deep commodities coverage with pricing, fundamentals, analytics
-- Integration of proprietary and third-party data
-- Best-in-class charting and analytics
-
-### Channels
-- Direct sales
-- Proprietary Bloomberg keyboard and terminal
-- Mobile apps (Bloomberg Anywhere)
-- API services
-
-### Customer Relationships
-- Subscription with hardware/software bundle
-- 24/7 support
-- Training programs
-- Bloomberg Intelligence research access
-
-### Revenue Streams
-- **Subscription**: $25,000-$30,000 per user per year
-- Volume discounts for multiple terminals
-- Data licensing for enterprise
-
-### Key Resources
-- 350,000+ user network creating liquidity in messaging/trading
-- Bloomberg Intelligence (350+ research professionals)
-- 2,700+ news journalists globally
-- Decades of historical data
-- Proprietary technology and infrastructure
-
-### Key Activities
-- Real-time data aggregation across all markets
-- News gathering and distribution
-- Research and analysis (Bloomberg Intelligence)
-- Platform development
-- Execution and trading facilitation
-
-### Key Partnerships
-- **Data Providers**:
- - Exchange partnerships globally
- - General Index (commodity pricing)
- - Third-party data vendors
- - Argus, Platts (pricing data available on terminal)
-- **Trading Venues**: Execution partnerships
-
-### Cost Structure
-- 2,700+ journalists
-- Technology infrastructure (massive scale)
-- Data acquisition from thousands of sources
-- Customer support
-- R&D and platform development
-
-### Data Sources
-1. **Exchange Data**: Real-time from 300+ exchanges
-2. **OTC Data**: Broker networks
-3. **Commodity Prices**: Platts, Argus, General Index
-4. **News**: Proprietary Bloomberg News
-5. **Fundamentals**: Various data providers
-6. **Reference Data**: Securities master database
-
----
-
-## 5. LSEG (REFINITIV/EIKON)
-
-### Customer Segments
-- Financial traders (all asset classes)
-- Commodity traders
-- Risk managers
-- Financial institutions
-- Corporate clients
-- Government agencies
-
-### Value Propositions
-- **"Workspace: Next-generation workflow solution"** (replacing Eikon by June 2025)
-- Comprehensive commodities coverage
-- Integration with Reuters News (exclusive access)
-- Real-time and historical data
-- Advanced analytics and charting
-- Trading execution capabilities
-
-### Channels
-- LSEG Workspace (replacing Eikon)
-- Data APIs
-- Excel Add-ins
-- Mobile apps
-- FTP data feeds
-
-### Customer Relationships
-- Subscription licensing
-- Enterprise agreements
-- 24/7 support
-- Dedicated account management
-
-### Revenue Streams
-- **Subscription**: $800-$1,800 per user per month average (Eikon historical pricing)
-- Enterprise data licenses
-- API subscriptions
-
-### Key Resources
-- Reuters News exclusive access
-- Decades of market data
-- Strong relationships with exchanges
-- Technology infrastructure
-- IIR Energy (refinery data subsidiary)
-- Wood Mackenzie partnership
-
-### Key Activities
-- Real-time data distribution
-- News gathering (Reuters)
-- Platform development
-- Data normalization and cleaning
-- Analytics development
-
-### Key Partnerships
-- **Data Providers**:
- - IIR Energy (refinery outages, owned)
- - Wood Mackenzie (fundamental data partnership)
- - AIS providers for shipping data
- - Exchange partnerships
- - WBMS (World Bureau of Metal Statistics)
-- **Technology**: Microsoft (strategic partnership for Workspace)
-
-### Cost Structure
-- Reuters news operations
-- Technology infrastructure
-- Data acquisition
-- Customer support
-- IIR Energy operations
-
-### Data Sources
-1. **Exchange Data**: Global coverage
-2. **Reuters News**: Proprietary
-3. **IIR Energy**: Refinery outages, capacity data
-4. **Wood Mackenzie**: Fundamental data
-5. **Vessel Tracking**: AIS providers
-6. **Trade Data**: Various sources
-7. **Fundamentals**: Research providers
-
----
-
-## 6. KAYRROS
-
-### Customer Segments
-- Financial institutions (trading firms, banks)
-- Commodity traders
-- Energy sector companies
-- Carbon traders
-- Government and regulatory bodies
-
-### Value Propositions
-- **"Environmental intelligence and asset observation"**
-- AI and geoanalytics on satellite imagery
-- Energy, climate, and sustainability insights
-- Methane emissions monitoring
-- Oil and gas infrastructure tracking
-- Real-time market intelligence
-
-### Channels
-- Direct platform access
-- API integrations
-- Custom dashboards
-
-### Customer Relationships
-- Subscription model
-- Custom analytics projects
-- Consulting services
-
-### Revenue Streams
-- Platform subscriptions
-- Custom analytics projects
-- **Estimated Pricing**: $50,000-$200,000+ per year (ESTIMATE based on enterprise focus)
-
-### Key Resources
-- Proprietary AI algorithms for satellite image analysis
-- Team of satellite imagery specialists (largest in Europe)
-- Relationships with satellite providers
-- Environmental science expertise
-
-### Key Activities
-- Satellite imagery analysis using AI
-- Environmental monitoring
-- Asset tracking and production monitoring
-- Algorithm development
-- Custom research
-
-### Key Partnerships
-- **Satellite Providers**:
- - Planet Labs (Stereo SkySat imagery partnership)
- - Multiple satellite data providers
-- **Technology**: AI/ML platforms, cloud infrastructure
-
-### Cost Structure
-- Satellite data acquisition
-- AI/ML development team
-- Data scientists and analysts
-- Technology infrastructure
-- Research and development
-
-### Data Sources
-1. **Satellite Imagery**: Planet Labs, Maxar, Airbus, others
-2. **SAR Data**: Synthetic Aperture Radar satellites
-3. **AIS Data**: Vessel tracking
-4. **Official Statistics**: Government data
-5. **Ground Truth Data**: Validation sources
-
----
-
-## 7. OilX (Now Part of Energy Aspects)
-
-### Customer Segments
-- Oil traders
-- Investment banks
-- Hedge funds
-- Oil majors
-- Energy ministries (Middle East)
-- Physical commodity traders
-
-### Value Propositions
-- **"The world's first digital oil analyst"**
-- Real-time oil supply-demand balances (160+ countries)
-- Daily oil production data by country and field
-- Satellite-based storage monitoring (800+ oil fields)
-- SAR and optical data for tank inventory
-- Automated menial tasks (80% of analyst time saved)
-- Nowcasting technology
-
-### Channels
-- OilX Platform (web-based)
-- API access
-- Flat file delivery
-- Excel integration
-- Integration with Energy Aspects client portal
-
-### Customer Relationships
-- Subscription model
-- Analyst support
-- Direct access to research team
-- Webinars and Q&A sessions
-
-### Revenue Streams
-- Platform subscriptions
-- **Estimated Pricing**: $40,000-$100,000+ per user/year (ESTIMATE)
-- Custom analytics
-
-### Key Resources
-- **Satellite Data Partnership**: European Space Agency (ESA)
-- **Technology**: Proprietary ML algorithms, nowcasting models
-- **Team**: Oil analysts, data scientists
-- **Data**: Real-time from satellites, AIS, conventional sources
-
-### Key Activities
-- Satellite data processing (SAR and optical)
-- Oil field monitoring and flaring detection
-- Supply-demand modeling
-- Nowcasting development
-- Market analysis
-
-### Key Partnerships
-- **European Space Agency (ESA)**: Sentinel satellite data access
-- **Aresys**: SAR processing technology
-- **Signal Ocean**: Shipping intelligence
-- **Energy Aspects**: Parent company (acquired 2023) providing research expertise
-- **Funding**: GS Caltex, Citi ($2.2M seed funding)
-
-### Cost Structure
-- Satellite data from ESA and partners
-- ML/AI development
-- Analyst team
-- Technology infrastructure
-- Integration with Energy Aspects
-
-### Data Sources
-1. **Satellite Data**: ESA Sentinel (SAR), optical satellites
-2. **AIS Data**: Vessel tracking via Signal Ocean
-3. **Official Statistics**: Government agencies
-4. **Field Data**: Production monitoring
-5. **Refinery Data**: Operating status
-6. **Conventional Oil Data**: Market statistics
-
----
-
-## 8. WOOD MACKENZIE
-
-### Customer Segments
-- Energy companies
-- Mining companies
-- Financial institutions
-- Government agencies
-- Consultants
-- Renewable energy developers
-
-### Value Propositions
-- **"Data and energy insight across entire supply chain"**
-- Comprehensive coverage: oil, gas, power, renewables, metals, mining
-- Real-time refinery monitoring (100+ refineries, 90% of US capacity)
-- Pipeline flow monitoring (EMF technology)
-- Long-term forecasting and scenario modeling
-- 2,600+ market experts and data scientists
-- Lens Direct API for seamless integration
-
-### Channels
-- Wood Mackenzie Lens platform
-- API services (Lens Direct)
-- Custom reports and consulting
-- Research portals
-
-### Customer Relationships
-- Subscription to research services
-- Consulting engagements
-- Direct analyst access
-- Custom data solutions
-
-### Revenue Streams
-- Research subscriptions
-- Consulting projects
-- Data licensing
-- **Estimated Pricing**: $30,000-$200,000+ per year depending on services (ESTIMATE)
-
-### Key Resources
-- 2,600+ analysts and experts globally
-- Proprietary models for forecasting
-- Decades of historical data
-- Refinery monitoring technology (remote sensors)
-- EMF technology for pipeline monitoring
-- Strong relationships with energy companies
-
-### Key Activities
-- Market research and analysis
-- Long-term forecasting
-- Real-time monitoring (refineries, pipelines)
-- Consulting services
-- Data collection and modeling
-
-### Key Partnerships
-- **Integration Partners**:
- - Thomson Reuters/LSEG (data available in Eikon/Workspace)
- - Exchange and market data providers
-- **Technology**: Remote sensing providers, satellite data
-- **Clients**: Deep relationships with majors
-
-### Cost Structure
-- 2,600+ employee salaries
-- Research and analysis operations
-- Technology for monitoring (EMF sensors, satellite)
-- Global office network
-- Data acquisition
-
-### Data Sources
-1. **Refinery Monitoring**: Proprietary remote sensors (thermal, flaring detection)
-2. **Pipeline Flows**: Electromagnetic field (EMF) technology
-3. **Official Statistics**: Government agencies, regulatory bodies
-4. **Company Data**: Direct from energy companies
-5. **Satellite Data**: For asset monitoring
-6. **Field Research**: Primary research from global team
-7. **Exchange Data**: Price and trading data
-
----
-
-## 9. IIR ENERGY (Industrial Info Resources)
-
-### Customer Segments
-- Commodity traders (oil, gas, power)
-- Physical traders
-- Financial traders
-- Refiners
-- Risk managers
-- Power generators
-
-### Value Propositions
-- **"Trusted data source for supply-side intelligence"**
-- Real-time refinery outage monitoring (700+ global refineries)
-- Power generation facility tracking
-- Pipeline and terminal data
-- Daily updates on planned and unplanned outages
-- Primary research methodology
-- Unit-by-unit capacity data
-
-### Channels
-- Energy Live subscription platform
-- API feeds
-- Excel tools
-- Custom reports
-- Hotline for urgent intelligence
-
-### Customer Relationships
-- Subscription model
-- Research hotline for verification
-- Account management
-- Custom research requests
-
-### Revenue Streams
-- Subscriptions to Energy Live platform
-- **Estimated Pricing**: $20,000-$80,000+ per year (ESTIMATE)
-- Custom reports
-
-### Key Resources
-- Global research staff (boots on the ground)
-- PECWeb Database (project, event, capacity tracking)
-- Decades of historical data
-- Refinery Capacity Insights tool
-- Primary research methodology
-
-### Key Activities
-- Daily monitoring of refinery outages
-- Power plant tracking
-- Primary research and verification
-- Database maintenance
-- Event tracking (weather, disasters)
-
-### Key Partnerships
-- **Owned by LSEG**: Data distributed through LSEG platforms
-- **Integrated with**: Refinitiv/Eikon/Workspace
-- **Data Sources**: Direct research, company contacts, regulatory filings
-
-### Cost Structure
-- Global research team
-- Database infrastructure
-- Customer support (hotline)
-- Technology development
-
-### Data Sources
-1. **Primary Research**: Direct calls to refineries, power plants
-2. **Company Communications**: Official announcements
-3. **Regulatory Filings**: Government submissions
-4. **Network**: Industry contacts globally
-5. **Field Verification**: On-the-ground intelligence
-
----
-
-# Essential Data Sources to Build Commodity Analytics Platform
-
-## 1. AIS (Automatic Identification System) Data
-**Primary Providers:**
-- **Spire Maritime**: Satellite + terrestrial AIS, <1 minute latency
-- **ORBCOMM**: Satellite AIS constellation
-- **Pole Star**: AIS data provider
-- **VesselFinder**: Lower-cost alternative
-- **DIY Option**: Build own terrestrial receiver network (6,000+ stations needed for good coverage)
-
-**Cost Estimate**: $100,000-$500,000+ per year for comprehensive satellite + terrestrial coverage
-
-## 2. Satellite Imagery
-**Optical Imagery Providers:**
-- **Planet Labs**: Daily 3-5m resolution (PlanetScope), 50cm (SkySat)
-- **Maxar Technologies**: 30cm resolution (WorldView Legion)
-- **Airbus**: 30cm (Pléiades Neo)
-
-**SAR (Synthetic Aperture Radar) Providers:**
-- **ICEYE**: All-weather SAR microsatellites
-- **Capella Space**: SAR data provider
-- **European Space Agency**: Sentinel satellites (free but lower resolution)
-
-**Cost Estimate**: $200,000-$1,000,000+ per year depending on coverage and resolution needs
-
-## 3. Bills of Lading Data
-**Providers:**
-- **Panjiva** (S&P Global): 30+ countries, 10M+ businesses
-- **ImportGenius**: US + 23 countries, detailed BoL data
-- **Tendata**: 218+ countries
-- **PIERS** (S&P Global): US + 14 countries
-- **Descartes Datamyne**: US and Latin America
-
-**Cost Estimate**: $30,000-$150,000+ per year depending on country coverage
-
-## 4. Port Data
-**Sources:**
-- Direct partnerships with port authorities
-- Port state control databases
-- Terminal operators
-- S&P Global Market Intelligence (port calls)
-
-**Cost Estimate**: Variable, $50,000-$200,000+ for comprehensive coverage
-
-## 5. Refinery Data
-**Providers:**
-- **IIR Energy**: Real-time outages, capacity (owned by LSEG)
-- **Wood Mackenzie**: Remote monitoring technology
-- **Primary Research**: Build own analyst network (expensive)
-
-**Cost Estimate**: $50,000-$200,000+ per year
-
-## 6. Freight Pricing Data
-**Providers:**
-- **Baltic Exchange**: Benchmark freight rates (licensing required)
-- **Clarksons**: Shipping intelligence
-- **Internal Models**: Build proprietary pricing algorithms (requires AIS + port data)
-
-**Cost Estimate**: $50,000-$150,000+ per year
-
-## 7. Exchange and Price Data
-**Sources:**
-- **CME Group**: Futures data
-- **ICE**: Energy and commodity futures
-- **LME**: Metals
-- **Direct feeds**: From exchanges (expensive)
-- **Aggregators**: S&P Global, LSEG, Bloomberg (redistributors)
-
-**Cost Estimate**: $100,000-$500,000+ per year for comprehensive coverage
-
-## 8. Official Statistics
-**Sources:**
-- **US EIA**: Energy Information Administration (free)
-- **IEA**: International Energy Agency
-- **National Statistics Agencies**: Most countries publish data
-- **JODI**: Joint Oil Data Initiative
-
-**Cost**: Mostly free, requires data aggregation infrastructure
-
-## 9. Vessel Database
-**Providers:**
-- **IHS Markit Sea-web**: Comprehensive vessel database
-- **Clarkson Research**: Shipping intelligence
-- **Build from IMO**: International Maritime Organization registry
-
-**Cost Estimate**: $30,000-$100,000+ per year
-
-## 10. Weather Data
-**Providers:**
-- **IBM Weather**: Enterprise weather data
-- **NOAA**: Free US government data
-- **MeteoGroup**: European weather
-- **AccuWeather**: Enterprise solutions
-
-**Cost Estimate**: $20,000-$100,000+ per year
-
----
-
-# Technology Stack Requirements
-
-## Core Infrastructure
-- **Cloud Platform**: AWS, Azure, or GCP ($100,000-$500,000+/year)
-- **Data Processing**: Apache Spark, Kafka for streaming
-- **Database**: PostgreSQL (time-series), MongoDB (documents), Redis (caching)
-- **Data Lake**: S3, Azure Data Lake
-
-## AI/ML Stack
-- **Frameworks**: TensorFlow, PyTorch, scikit-learn
-- **MLOps**: Kubeflow, MLflow
-- **GPU Compute**: For satellite imagery processing
-
-## Frontend
-- **Web Framework**: React, Angular, or Vue.js
-- **Mapping**: Mapbox, Google Maps API
-- **Visualization**: D3.js, Plotly, Recharts
-
-## APIs and Integration
-- **REST APIs**: For data distribution
-- **WebSockets**: Real-time data streaming
-- **Excel Add-in**: COM Add-in for Excel integration
-
----
-
-# Estimated Total Startup Costs
-
-## Minimum Viable Product (MVP)
-- **Data Sources**: $500,000-$1,000,000/year
-- **Technology Infrastructure**: $200,000-$500,000/year
-- **Team (20-30 people)**:
- - 5-8 Data Engineers: $120,000-$180,000 each
- - 5-8 Software Engineers: $130,000-$200,000 each
- - 3-5 Data Scientists: $140,000-$200,000 each
- - 3-5 Commodity Analysts: $100,000-$150,000 each
- - 2-3 Product Managers: $130,000-$180,000 each
- - Sales and Support: 3-5 people
- - **Total Team Cost**: $3,000,000-$5,000,000/year
-
-**Year 1 Total**: $4,000,000-$7,000,000
-**Years 2-3**: $6,000,000-$10,000,000/year to scale
-
-## Full-Scale Competitor
-- **Data Sources**: $2,000,000-$5,000,000/year
-- **Technology**: $1,000,000-$3,000,000/year
-- **Team (200-600 people)**: $30,000,000-$80,000,000/year
-- **Acquisitions**: $100,000,000-$500,000,000 (as Kpler did)
-
----
-
-# Key Success Factors
-
-1. **Data Accuracy**: Must match official statistics (EIA, customs data) with 95%+ accuracy
-2. **Latency**: Real-time or near-real-time data (<5 minutes for AIS, intraday for inventory)
-3. **Coverage**: Global reach across multiple commodities
-4. **Analyst Expertise**: Commodity market experts to interpret data
-5. **Network Effects**: More users = more valuable (especially for messaging/community features)
-6. **API/Integration**: Seamless integration into customer workflows
-7. **Trust**: Must build credibility in the market (takes years)
-
----
-
-# Pricing Models in the Industry
-
-## Subscription Tiers
-- **Basic**: Single commodity, limited API access: $30,000-$50,000/user/year (ESTIMATE)
-- **Professional**: Multiple commodities, full API: $60,000-$100,000/user/year (ESTIMATE)
-- **Enterprise**: All commodities, unlimited users: $200,000-$1,000,000+/year (ESTIMATE)
-
-## Enterprise Licensing
-- Some providers (S&P Global Platts) offer unlimited user licensing at fixed fee
-- More predictable for large organizations
-
-## Data Feed Pricing
-- Raw data feeds priced separately: $50,000-$500,000+/year
-- API access often bundled or sold separately
-
----
-
-# Competitive Landscape Summary
-
-## Market Leaders (by segment)
-- **Cargo Tracking & Maritime**: Kpler (market leader after acquisitions)
-- **Energy Fundamentals**: Vortexa, OilX/Energy Aspects
-- **Price Benchmarks**: S&P Global Platts (industry standard)
-- **Comprehensive Financial Data**: Bloomberg Terminal
-- **Multi-Asset Trading Platform**: LSEG Workspace
-- **Environmental/Satellite Analytics**: Kayrros
-- **Long-term Forecasting**: Wood Mackenzie
-- **Refinery Intelligence**: IIR Energy, Wood Mackenzie
-
-## Barriers to Entry
-- **HIGH**: Data acquisition costs, need for scale
-- **HIGH**: Building credibility and trust with traders
-- **MEDIUM**: Technology development (can be built)
-- **HIGH**: Sales cycle for enterprise software (12-18 months)
-- **CRITICAL**: Access to proprietary data sources
-
----
-
-# Recommendations for Building Similar Platform
-
-1. **Start Narrow**: Focus on one commodity vertical (e.g., crude oil)
-2. **Differentiate**: Find unique data source or methodology
-3. **Build Core AIS**: Essential for cargo tracking - license or build network
-4. **Partner for Data**: Don't try to acquire all data sources day 1
-5. **Hire Experts**: Need commodity traders/analysts who understand the market
-6. **API-First**: Make integration easy for quantitative traders
-7. **Accuracy Over Speed**: In early days, prioritize accuracy to build trust
-8. **Plan for Scale**: Will need significant capital ($20M+) to compete seriously
-
----
-
-*This report is based on publicly available information and industry estimates. Actual pricing and specific capabilities may vary. Pricing marked as (ESTIMATE) is based on industry analysis and comparable products.*
diff --git a/assets/beanflows_logo.png b/assets/beanflows_logo.png
new file mode 100755
index 0000000..368fbca
Binary files /dev/null and b/assets/beanflows_logo.png differ
diff --git a/assets/beanflows_wordmark.png b/assets/beanflows_wordmark.png
new file mode 100755
index 0000000..0865fa9
Binary files /dev/null and b/assets/beanflows_wordmark.png differ
diff --git a/coding_philosophy.md b/coding_philosophy.md
new file mode 100644
index 0000000..8c7c602
--- /dev/null
+++ b/coding_philosophy.md
@@ -0,0 +1,446 @@
+# Coding Philosophy & Engineering Principles
+
+This document defines the coding philosophy and engineering principles that guide all agent work. All agents should internalize and follow these principles.
+
+
+**Simple, Direct, Procedural Code**
+
+We follow the Casey Muratori / Jonathan Blow school of thought:
+- Solve the actual problem, not the general case
+- Understand what the computer is doing
+- Explicit is better than clever
+- Code should be obvious, not impressive
+
+
+
+
+
+**Prefer:**
+- Pure functions that transform data
+- Simple procedures that do clear things
+- Explicit data structures (dicts, lists, named tuples)
+
+**Avoid:**
+- Classes that are just namespaces for functions
+- Objects hiding behavior behind methods
+- Inheritance hierarchies
+- "Manager" or "Handler" classes
+
+**Example - Good:**
+```python
+def calculate_user_metrics(events: list[dict]) -> dict:
+ """Calculate metrics from event list."""
+ total = len(events)
+ unique_sessions = len(set(e['session_id'] for e in events))
+
+ return {
+ 'total_events': total,
+ 'unique_sessions': unique_sessions,
+ 'events_per_session': total / unique_sessions if unique_sessions > 0 else 0
+ }
+```
+
+**Example - Bad:**
+```python
+class UserMetricsCalculator:
+ def __init__(self):
+ self._events = []
+
+ def add_events(self, events: list[dict]):
+ self._events.extend(events)
+
+ def calculate(self) -> UserMetrics:
+ return UserMetrics(
+ total=self._calculate_total(),
+ sessions=self._calculate_sessions()
+ )
+```
+
+
+
+**Think about the data:**
+- What's the shape of the data?
+- How does it flow through the system?
+- What transformations are needed?
+- What's the memory layout?
+
+**Data is just data:**
+- Use simple structures (dicts, lists, tuples)
+- Don't hide data behind getters/setters
+- Make data transformations explicit
+- Consider performance implications
+
+**Example - Good:**
+```python
+# Data is data, functions transform it
+users = [
+ {'id': 1, 'name': 'Alice', 'active': True},
+ {'id': 2, 'name': 'Bob', 'active': False},
+]
+
+def filter_active(users: list[dict]) -> list[dict]:
+ return [u for u in users if u['active']]
+
+active_users = filter_active(users)
+```
+
+**Example - Bad:**
+```python
+# Data hidden behind objects
+class User:
+ def __init__(self, id, name, active):
+ self._id = id
+ self._name = name
+ self._active = active
+
+ def get_name(self):
+ return self._name
+
+ def is_active(self):
+ return self._active
+
+users = [User(1, 'Alice', True), User(2, 'Bob', False)]
+active_users = [u for u in users if u.is_active()]
+```
+
+
+
+**Simple control flow:**
+- Straightforward if/else over clever tricks
+- Explicit loops over list comprehensions when clearer
+- Early returns to reduce nesting
+- Avoid deeply nested logic
+
+**Simple naming:**
+- Descriptive variable names (`user_count` not `uc`)
+- Function names that say what they do (`calculate_total` not `process`)
+- No abbreviations unless universal (`id`, `url`, `sql`)
+
+**Simple structure:**
+- Functions should do one thing
+- Keep functions short (20-50 lines usually)
+- If it's getting complex, break it up
+- But don't break it up "just because"
+
+
+
+
+
+
+
+**Start simple:**
+- Solve the immediate problem
+- Don't build for imagined future requirements
+- Add complexity only when actually needed
+- Prefer obvious solutions over clever ones
+
+**Avoid premature abstraction:**
+- Duplication is okay early on
+- Abstract only when pattern is clear
+- Three examples before abstracting
+- Question every layer of indirection
+
+
+
+**Be explicit about:**
+- Where data comes from
+- What transformations happen
+- Error conditions and handling
+- Dependencies and side effects
+
+**Avoid magic:**
+- Framework conventions that hide behavior
+- Implicit configuration
+- Action-at-a-distance
+- Metaprogramming tricks
+
+
+
+**Before adding a library:**
+- Can I write this simply myself?
+- What's the complexity budget?
+- Am I using 5% of a large framework?
+- Is this solving my actual problem?
+
+**Prefer:**
+- Standard library when possible
+- Small, focused libraries
+- Direct solutions
+- Understanding what code does
+
+
+
+
+
+
+
+**Understand:**
+- Memory layout matters
+- Cache locality matters
+- Allocations have cost
+- Loops over data can be fast or slow
+
+**Common issues:**
+- N+1 queries (database or API)
+- Nested loops over large data
+- Copying large structures unnecessarily
+- Loading entire datasets into memory
+
+**But don't prematurely optimize:**
+- Profile first, optimize second
+- Make it work, then make it fast
+- Measure actual performance
+- Optimize the hot path, not everything
+
+
+
+
+
+
+
+**Good:**
+```sql
+-- Logic is clear, database does the work
+SELECT
+ user_id,
+ COUNT(*) as event_count,
+ COUNT(DISTINCT session_id) as session_count,
+ MAX(event_time) as last_active
+FROM events
+WHERE event_time >= CURRENT_DATE - 30
+GROUP BY user_id
+HAVING COUNT(*) >= 10
+```
+
+**Bad:**
+```python
+# Pulling too much data, doing work in Python
+events = db.query("SELECT * FROM events WHERE event_time >= CURRENT_DATE - 30")
+user_events = {}
+for event in events: # Could be millions of rows!
+ if event.user_id not in user_events:
+ user_events[event.user_id] = []
+ user_events[event.user_id].append(event)
+
+results = []
+for user_id, events in user_events.items():
+ if len(events) >= 10:
+ results.append({'user_id': user_id, 'count': len(events)})
+```
+
+
+
+**Write readable SQL:**
+- Use CTEs for complex queries
+- One concept per CTE
+- Descriptive CTE names
+- Comments for non-obvious logic
+
+**Example:**
+```sql
+WITH active_users AS (
+ -- Users who logged in within last 30 days
+ SELECT DISTINCT user_id
+ FROM login_events
+ WHERE login_time >= CURRENT_DATE - 30
+),
+
+user_activity AS (
+ -- Count events for active users
+ SELECT
+ e.user_id,
+ COUNT(*) as event_count
+ FROM events e
+ INNER JOIN active_users au ON e.user_id = au.user_id
+ GROUP BY e.user_id
+)
+
+SELECT
+ user_id,
+ event_count,
+ event_count / 30.0 as avg_daily_events
+FROM user_activity
+ORDER BY event_count DESC
+```
+
+
+
+
+
+
+
+**Handle errors explicitly:**
+```python
+def get_user(user_id: str) -> dict | None:
+ """Get user by ID. Returns None if not found."""
+ result = db.query("SELECT * FROM users WHERE id = ?", [user_id])
+ return result[0] if result else None
+
+def process_user(user_id: str):
+ user = get_user(user_id)
+ if user is None:
+ logger.warning(f"User {user_id} not found")
+ return None
+
+ # Process user...
+ return result
+```
+
+**Don't hide errors:**
+```python
+# Bad - silently catches everything
+try:
+ result = do_something()
+except:
+ result = None
+
+# Good - explicit about what can fail
+try:
+ result = do_something()
+except ValueError as e:
+ logger.error(f"Invalid value: {e}")
+ raise
+except ConnectionError as e:
+ logger.error(f"Connection failed: {e}")
+ return None
+```
+
+
+
+- Validate inputs at boundaries
+- Check preconditions early
+- Return early on error conditions
+- Don't let bad data propagate
+
+
+
+
+
+
+
+❌ Repository pattern for simple CRUD
+❌ Service layer that just calls the database
+❌ Dependency injection containers
+❌ Abstract factories for concrete things
+❌ Interfaces with one implementation
+
+
+
+❌ ORM hiding N+1 queries
+❌ Decorators doing complex logic
+❌ Metaclass magic
+❌ Convention over configuration (when it hides behavior)
+
+
+
+❌ Creating interfaces "for future flexibility"
+❌ Generics for specific use cases
+❌ Configuration files for hardcoded values
+❌ Plugins systems for known features
+
+
+
+❌ Class hierarchies for classification
+❌ Design patterns "just because"
+❌ Microservices for a small app
+❌ Message queues for synchronous operations
+
+
+
+
+
+
+
+**Focus on:**
+- What the function does (inputs → outputs)
+- Edge cases and boundaries
+- Error conditions
+- Data transformations
+
+**Don't test:**
+- Private implementation details
+- Framework internals
+- External libraries
+- Simple property access
+
+
+
+```python
+def test_user_aggregation():
+ # Arrange - simple, clear test data
+ events = [
+ {'user_id': 'u1', 'event': 'click'},
+ {'user_id': 'u1', 'event': 'view'},
+ {'user_id': 'u2', 'event': 'click'},
+ ]
+
+ # Act - call the function
+ result = aggregate_user_events(events)
+
+ # Assert - check the behavior
+ assert result == {'u1': 2, 'u2': 1}
+```
+
+
+
+- Test with real database (DuckDB is fast)
+- Test actual SQL queries
+- Test end-to-end flows
+- Use realistic data samples
+
+
+
+
+
+
+
+**Comment the "why":**
+```python
+# Use binary search because list is sorted and can be large (1M+ items)
+index = binary_search(sorted_items, target)
+
+# Cache for 5 minutes - balance freshness vs database load
+@cache(ttl=300)
+def get_user_stats(user_id):
+ ...
+```
+
+**Don't comment the "what":**
+```python
+# Bad - code is self-explanatory
+# Increment the counter
+counter += 1
+
+# Good - code is clear on its own
+counter += 1
+```
+
+
+
+- Use descriptive names
+- Keep functions focused
+- Make data flow obvious
+- Structure for readability
+
+
+
+
+
+**Key Principles:**
+1. **Simple, direct, procedural** - functions over classes
+2. **Data-oriented** - understand the data and its flow
+3. **Explicit over implicit** - no magic, no hiding
+4. **Build minimum that works** - solve actual problems
+5. **Performance conscious** - but measure, don't guess
+6. **Keep logic in SQL** - let the database do the work
+7. **Handle errors explicitly** - no silent failures
+8. **Question abstractions** - every layer needs justification
+
+**Ask yourself:**
+- Is this the simplest solution?
+- Can someone else understand this?
+- What is the computer actually doing?
+- Am I solving the real problem?
+
+When in doubt, go simpler.
+
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index e69de29..0000000
diff --git a/extract/psdonline/README.md b/extract/psdonline/readme.md
similarity index 100%
rename from extract/psdonline/README.md
rename to extract/psdonline/readme.md
diff --git a/extract/psdonline/src/psdonline/__init__.py b/extract/psdonline/src/psdonline/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/extract/psdonline/src/psdonline/execute.py b/extract/psdonline/src/psdonline/execute.py
index 5d7c978..545537d 100644
--- a/extract/psdonline/src/psdonline/execute.py
+++ b/extract/psdonline/src/psdonline/execute.py
@@ -1,3 +1,4 @@
+from .normalize import normalize_zipped_csv
import logging
import os
import pathlib
@@ -33,7 +34,7 @@ FIRST_MONTH = 8
def check_r2_file_exists(etag: str, s3_client) -> bool:
"""Check if file exists in R2."""
- r2_key = f"landing/psd/{etag}.zip"
+ r2_key = f"landing/psd/{etag}.csv.gzip"
try:
s3_client.head_object(Bucket=R2_BUCKET, Key=r2_key)
logger.info(f"File {r2_key} already exists in R2, skipping")
@@ -46,7 +47,7 @@ def check_r2_file_exists(etag: str, s3_client) -> bool:
def upload_to_r2(content: bytes, etag: str, s3_client):
"""Upload file content to R2."""
- r2_key = f"landing/psd/{etag}.zip"
+ r2_key = f"landing/psd/{etag}.csv.gzip"
logger.info(f"Uploading to R2: {r2_key}")
s3_client.put_object(Bucket=R2_BUCKET, Key=r2_key, Body=content)
logger.info("Upload complete")
@@ -75,11 +76,12 @@ def extract_psd_file(url: str, extract_to_path: pathlib.Path, http_session: niqu
if check_r2_file_exists(etag, s3_client):
return
response = http_session.get(url)
- upload_to_r2(response.content, etag, s3_client)
+ normalized_content = normalize_zipped_csv(response.content)
+ upload_to_r2(normalized_content, etag, s3_client)
return
# Local mode: check local and download if needed
- local_file = extract_to_path / f"{etag}.zip"
+ local_file = extract_to_path / f"{etag}.csv.gzip"
if local_file.exists():
logger.info(f"File {etag}.zip already exists locally, skipping")
return
@@ -87,7 +89,8 @@ def extract_psd_file(url: str, extract_to_path: pathlib.Path, http_session: niqu
response = http_session.get(url)
logger.info(f"Storing file to {local_file}")
extract_to_path.mkdir(parents=True, exist_ok=True)
- local_file.write_bytes(response.content)
+ normalized_content = normalize_zipped_csv(response.content)
+ local_file.write_bytes(normalized_content)
logger.info("Download complete")
diff --git a/extract/psdonline/src/psdonline/normalize.py b/extract/psdonline/src/psdonline/normalize.py
new file mode 100644
index 0000000..769caf3
--- /dev/null
+++ b/extract/psdonline/src/psdonline/normalize.py
@@ -0,0 +1,55 @@
+import zipfile
+import gzip
+from io import BytesIO
+import pathlib
+
+
+
+def normalize_zipped_csv(buffer: BytesIO)->BytesIO:
+ out = BytesIO()
+ with zipfile.ZipFile(buffer, mode='r').open("psd_alldata.csv", mode='r') as csv:
+ with gzip.open(out, "wb") as outfile:
+ outfile.write(csv.read())
+ out.seek(0)
+ return out
+
+
+def convert_existing():
+ data = pathlib.Path(__file__).parent / "data"
+ for file in data.glob("*.zip"):
+ outfile = data / f"{file.stem}.csv.gzip"
+ if outfile.exists() and outfile.stat().st_size > 0:
+ continue
+ print(file)
+ gzip_contents = normalize_zipped_csv(file)
+ outfile.write_bytes(gzip_contents.read())
+
+
+
+
+
+
+
+
+if __name__ == "__main__":
+# """Test to make sure file contents are the same"""
+# import pathlib
+# import hashlib
+#
+# test_file = pathlib.Path(__file__).parent / "data/00d6e992d8c81_0.zip"
+#
+# with zipfile.ZipFile(test_file.open("rb"), mode='r').open("psd_alldata.csv", mode='r') as csv:
+# raw_hash = hashlib.sha256(csv.read()).hexdigest()
+#
+# normalized = normalize_zipped_csv(test_file.open("rb"))
+# print(raw_hash)
+#
+# with gzip.open(normalized, "rb") as normalized_file:
+# normalized_hash = hashlib.sha256(normalized_file.read()).hexdigest()
+# print(normalized_hash)
+#
+# assert raw_hash == normalized_hash
+ convert_existing()
+
+
+
diff --git a/extract/psdonline/src/psdonline/py.typed b/extract/psdonline/src/psdonline/py.typed
deleted file mode 100644
index e69de29..0000000
diff --git a/infra/__main__.py b/infra/__main__.py
deleted file mode 100644
index f4672df..0000000
--- a/infra/__main__.py
+++ /dev/null
@@ -1,116 +0,0 @@
-"""
-BeanFlows.coffee Infrastructure
-Hetzner compute stack for ephemeral worker orchestration
-
-Note: R2 buckets are managed manually in Cloudflare dashboard
-- beanflows-artifacts: Stores CLI and pipeline artifacts
-- beanflows-data-prod: Iceberg data lakehouse
-"""
-
-import pulumi
-import pulumi_hcloud as hcloud
-
-# Load configuration
-config = pulumi.Config()
-hetzner_location = config.get("hetzner_location") or "nbg1" # Nuremberg datacenter
-
-# ============================================================
-# R2 Bucket Names (managed manually in Cloudflare R2 UI)
-# ============================================================
-# R2 buckets cannot be managed via Pulumi as they require R2-specific tokens
-# that don't work with the Cloudflare Pulumi provider.
-# These are defined here for documentation purposes only.
-
-ARTIFACTS_BUCKET = "beanflows-artifacts" # CLI + extract/transform packages
-LAKEHOUSE_BUCKET = "beanflows-data-prod" # Iceberg tables (EEUR region)
-
-# ============================================================
-# Hetzner Cloud Infrastructure
-# ============================================================
-
-# SSH key for server access (imported from existing key)
-ssh_key = hcloud.SshKey(
- "materia-ssh-key",
- name="deeman@DeemanPC",
- public_key=config.require_secret("ssh_public_key"),
- opts=pulumi.ResourceOptions(protect=True),
-)
-
-# Small CPX instance for supervisor (runs materia CLI to orchestrate pipelines)
-# This is an always-on instance that creates/destroys ephemeral workers on-demand
-supervisor_server = hcloud.Server(
- "materia-supervisor",
- name="materia-supervisor",
- server_type="cpx11", # 2 vCPU (shared), 2GB RAM, ~€4.49/mo (cheapest option)
- image="ubuntu-24.04",
- location=hetzner_location,
- ssh_keys=[ssh_key.id],
- labels={
- "role": "supervisor",
- "project": "materia",
- },
- user_data="""#!/bin/bash
-set -e
-
-# Basic server setup
-apt-get update
-apt-get install -y python3.13 python3-pip curl unzip
-
-# Install Pulumi ESC CLI
-curl -fsSL https://get.pulumi.com/esc/install.sh | sh
-export PATH="$HOME/.pulumi/bin:$PATH"
-echo 'export PATH="$HOME/.pulumi/bin:$PATH"' >> /root/.bashrc
-
-# Create deployment directory
-mkdir -p /opt/materia
-
-# Configure environment
-echo 'Setup complete. Materia CLI will be deployed via CI/CD.' > /opt/materia/README.txt
-""",
-)
-
-# Note: Workers are created on-demand by the materia CLI
-# No always-on worker instances in this architecture
-
-# Firewall for servers (restrict to SSH + outbound only)
-firewall = hcloud.Firewall(
- "materia-firewall",
- name="materia-firewall",
- rules=[
- # Allow SSH from anywhere (consider restricting to your IP)
- hcloud.FirewallRuleArgs(
- direction="in",
- protocol="tcp",
- port="22",
- source_ips=["0.0.0.0/0", "::/0"],
- ),
- # Allow all outbound traffic
- hcloud.FirewallRuleArgs(
- direction="out",
- protocol="tcp",
- port="any",
- destination_ips=["0.0.0.0/0", "::/0"],
- ),
- hcloud.FirewallRuleArgs(
- direction="out",
- protocol="udp",
- port="any",
- destination_ips=["0.0.0.0/0", "::/0"],
- ),
- ],
-)
-
-# Apply firewall to supervisor
-supervisor_firewall = hcloud.FirewallAttachment(
- "supervisor-firewall",
- firewall_id=firewall.id,
- server_ids=[supervisor_server.id],
-)
-
-# ============================================================
-# Outputs
-# ============================================================
-
-pulumi.export("supervisor_ip", supervisor_server.ipv4_address)
-pulumi.export("artifacts_bucket_name", ARTIFACTS_BUCKET)
-pulumi.export("lakehouse_bucket_name", LAKEHOUSE_BUCKET)
diff --git a/infra/FUTURE_ENHANCEMENTS.md b/infra/future_enhancements.md
similarity index 100%
rename from infra/FUTURE_ENHANCEMENTS.md
rename to infra/future_enhancements.md
diff --git a/infra/prefect.docker-compose.yml b/infra/prefect.docker-compose.yml
new file mode 100644
index 0000000..1f43179
--- /dev/null
+++ b/infra/prefect.docker-compose.yml
@@ -0,0 +1,80 @@
+services:
+ postgres:
+ image: postgres:14
+ environment:
+ POSTGRES_USER: prefect
+ POSTGRES_PASSWORD: prefect
+ POSTGRES_DB: prefect
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U prefect"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+
+ dragonfly:
+ image: 'docker.dragonflydb.io/dragonflydb/dragonfly'
+ ulimits:
+ memlock: -1
+ volumes:
+ - dragonflydata:/data
+ healthcheck:
+ test: ["CMD-SHELL", "redis-cli ping"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+
+ prefect-server:
+ image: prefecthq/prefect:3-latest
+ depends_on:
+ postgres:
+ condition: service_healthy
+ dragonfly:
+ condition: service_healthy
+ environment:
+ PREFECT_API_DATABASE_CONNECTION_URL: postgresql+asyncpg://prefect:prefect@postgres:5432/prefect
+ PREFECT_SERVER_API_HOST: 0.0.0.0
+ PREFECT_UI_API_URL: http://localhost:4200/api
+ PREFECT_MESSAGING_BROKER: prefect_redis.messaging
+ PREFECT_MESSAGING_CACHE: prefect_redis.messaging
+ PREFECT_REDIS_MESSAGING_HOST: dragonfly
+ PREFECT_REDIS_MESSAGING_PORT: 6379
+ PREFECT_REDIS_MESSAGING_DB: 0
+ command: prefect server start --no-services
+ ports:
+ - "4200:4200"
+ healthcheck:
+ test: ["CMD", "python", "-c", "import urllib.request as u; u.urlopen('http://localhost:4200/api/health', timeout=1)"]
+ interval: 30s
+ timeout: 10s
+ retries: 3
+ start_period: 60s
+
+ prefect-services:
+ image: prefecthq/prefect:3-latest
+ depends_on:
+ prefect-server:
+ condition: service_healthy
+ environment:
+ PREFECT_API_DATABASE_CONNECTION_URL: postgresql+asyncpg://prefect:prefect@postgres:5432/prefect
+ PREFECT_MESSAGING_BROKER: prefect_redis.messaging
+ PREFECT_MESSAGING_CACHE: prefect_redis.messaging
+ PREFECT_REDIS_MESSAGING_HOST: dragonfly
+ PREFECT_REDIS_MESSAGING_PORT: 6379
+ PREFECT_REDIS_MESSAGING_DB: 0
+ command: prefect server services start
+
+ prefect-worker:
+ image: prefecthq/prefect:3-latest
+ depends_on:
+ prefect-server:
+ condition: service_healthy
+ environment:
+ PREFECT_API_URL: http://prefect-server:4200/api
+ command: prefect worker start --pool local-pool
+ restart: on-failure
+
+volumes:
+ postgres_data:
+ dragonflydata:
diff --git a/infra/Pulumi.dev.yaml b/infra/pulumi.dev.yaml
similarity index 100%
rename from infra/Pulumi.dev.yaml
rename to infra/pulumi.dev.yaml
diff --git a/infra/Pulumi.prod.yaml b/infra/pulumi.prod.yaml
similarity index 100%
rename from infra/Pulumi.prod.yaml
rename to infra/pulumi.prod.yaml
diff --git a/infra/Pulumi.yaml b/infra/pulumi.yaml
similarity index 100%
rename from infra/Pulumi.yaml
rename to infra/pulumi.yaml
diff --git a/infra/README.md b/infra/readme.md
similarity index 100%
rename from infra/README.md
rename to infra/readme.md
diff --git a/infra/supervisor/supervisor.sh b/infra/supervisor/supervisor.sh
index 60313fa..a8b79e5 100644
--- a/infra/supervisor/supervisor.sh
+++ b/infra/supervisor/supervisor.sh
@@ -25,10 +25,8 @@ do
uv sync
# Run pipelines (SQLMesh handles scheduling)
- uv run materia pipeline run extract
- uv run materia pipeline run transform
+ #uv run materia pipeline run extract
+ #uv run materia pipeline run transform
) || sleep 600 # Sleep 10 min on failure to avoid busy-loop retries
-
- sleep 3600 # Run pipelines every hour
done
diff --git a/market_overview.md b/market_overview.md
new file mode 100644
index 0000000..c9e40b0
--- /dev/null
+++ b/market_overview.md
@@ -0,0 +1,248 @@
+# Comprehensive Alternative Data Sources for Coffee Futures Trading Analytics
+
+The coffee futures trading landscape extends far beyond basic price data, encompassing a rich ecosystem of alternative data spanning regulatory reports, maritime intelligence, satellite monitoring, weather analytics, production statistics, trade flows, and emerging data types. This comprehensive analysis identifies 150+ data sources across seven critical categories, providing traders with actionable intelligence from farm to futures contract.
+
+**Core finding**: Free government and international organization sources provide robust baseline data (CFTC COT reports, Sentinel-2 satellite imagery, NOAA weather, UN Comtrade trade data, ICO statistics), while premium commercial platforms offer real-time intelligence and predictive analytics that justify their cost through speed and integration advantages. The optimal strategy combines free foundational data with selective premium services targeting specific informational edges.
+
+## Commitment of Traders (COT) reports reveal positioning dynamics
+
+The CFTC publishes free weekly COT reports every Friday at 3:30 PM Eastern (reflecting Tuesday positions) covering Coffee C futures (CFTC Code 083731). The official CFTC website and Public Reporting Environment provide both legacy and disaggregated reports dating back to January 1986, accessible via web interface, downloadable CSV files, and REST API with no authentication required. **This represents the authoritative free source for trader positioning data**.
+
+Third-party platforms significantly enhance usability. Barchart offers free interactive COT charts with historical visualization and multiple report types including proprietary COT Index calculations. Tradingster provides clean web interfaces for both legacy and disaggregated formats. For serious analysis, **COTbase stands out at $16.50/month**, delivering corrected historical data, API access, options-only data, and NinjaTrader 8 integration—features unavailable from free sources.
+
+TradingView integrates COT data through multiple community scripts overlaying trader positioning directly on price charts, with basic access free and premium features from $12.95-$59.95/month. For programmatic access, the Python cot_reports library (open source, free) fetches data directly from CFTC, while Quandl/Nasdaq Data Link offers RESTful API access with a free tier (50 calls/day) and premium plans starting at $49.50/month for unlimited calls.
+
+**Institutional recommendation**: Use free CFTC data via API for baseline positioning analysis, supplement with COTbase premium subscription for corrected historical analysis and advanced features. TradingView provides excellent integration for discretionary traders overlaying positioning on technical charts.
+
+| Source | Type | Frequency | Coverage | Access | Cost |
+|--------|------|-----------|----------|--------|------|
+| CFTC Official | Legacy, Disaggregated, Supplemental COT | Weekly (Friday 3:30 PM ET) | Coffee C futures (083731) | Web, CSV, API | Free |
+| CFTC Public Reporting Environment | All COT types, REST API | Weekly | Coffee C, customizable queries | API, CSV/JSON/XML | Free |
+| Barchart | COT charts, COT Index | Weekly (Friday 3:00 PM CT) | Coffee (KC symbol) | Web interface, interactive charts | Free basic, Premium subscription |
+| COTbase | Corrected data, options-only, API | Weekly | Coffee with historical depth | Web, API, NinjaTrader integration | $16.50/month |
+| TradingView | COT indicators/scripts | Weekly | Coffee (KC) via multiple scripts | Platform indicators | Free basic, $12.95-$59.95/month premium |
+| Quandl/Nasdaq Data Link | Historical COT (Legacy) | Weekly | Coffee futures (CFTC/KC) | REST API, Python/R packages | Free (50 calls/day), $49.50+/month |
+| Python cot_reports library | All CFTC COT types | On-demand | Coffee included | Python library (pip install) | Free (open source) |
+
+## Maritime intelligence tracks physical coffee movements globally
+
+AIS data and shipping intelligence provide leading indicators of supply movements before official trade statistics. **Kpler emerges as the premium institutional choice**, offering near real-time AIS tracking (\<1 minute latency via satellite), cargo flow analysis, and port call data specifically for agricultural commodities including coffee. Their platform integrates 13,000+ AIS receivers tracking 300,000 vessels daily, accessible via API, Python SDK, Excel plugin, and Snowflake integration (enterprise pricing, contact for quotes).
+
+For free baseline vessel tracking, MarineTraffic and VesselFinder provide global coverage with real-time positions and historical AIS data back to 2009. Both offer free basic access with paid subscriptions for advanced features and API access. AISHub delivers completely free real-time AIS data via community-contributed receivers with JSON/XML/CSV API access requiring no authentication.
+
+Bill of lading data proves critical for detailed cargo intelligence. **ImportGenius offers the most accessible entry point**, providing U.S. customs records updated daily with 18 years of historical data, covering 23+ countries including major coffee producers (Colombia, Vietnam, Mexico, India). Plans start at approximately $149/month for basic access, with annual subscriptions offering 36% savings. The platform includes AI-powered company profiling and unlimited search capabilities.
+
+Panjiva (S&P Global) covers 30+ data sources with U.S. data updated weekly and international data monthly (2-month delay). PIERS provides 100% U.S. waterborne import/export coverage with 6x daily updates and 17 million BOLs annually, though pricing requires S&P Global contact. Descartes Datamyne covers 230 markets (75% of world trade) with daily U.S. updates and 500M+ annual shipment records, offering ISO 9001 certified data quality.
+
+**Coffee-specific platforms**: TradeInt specializes in coffee supply chain data with global trade filtering by port, exporter, product type, and timeframe. Eximpedia focuses exclusively on coffee (Robusta and Arabica) with HS code tracking, offering subscription access with free samples.
+
+Freight rate indices provide cost context: Freightos Baltic Index (FBX) offers free daily container rate updates across 12 global lanes, while Xeneta's XSI-C provides daily 40-foot container benchmarks. Both are EU-compliant and publicly accessible.
+
+| Source | Type | Frequency | Coverage | Access | Cost |
+|--------|------|-----------|----------|--------|------|
+| Kpler | Real-time AIS, cargo flows, port calls, ag commodities | Real-time (\<1 min), daily | Global, 14,500 dry bulkers, 10,300 tankers | API, Python SDK, Excel, Snowflake | Enterprise (contact) |
+| MarineTraffic | Real-time AIS, historical (2009+), port calls | Real-time, historical | 550,000+ vessels globally | Web, API, mobile apps | Free basic, Paid advanced |
+| VesselFinder | Real-time AIS, historical (2009+), voyage analysis | Real-time, historical | Global terrestrial/satellite | Web, API (JSON/XML/CSV) | Free basic, Paid reports |
+| ImportGenius | U.S./23+ country customs records, BOL data | Daily (U.S.), varies internationally | U.S. + 23 countries (Colombia, Vietnam) | Web platform, API, Excel export | ~$149/month, annual plans |
+| Panjiva (S&P Global) | Shipment/customs records, 30+ sources | Weekly (U.S.), monthly (international) | 30+ countries, 10M+ companies | Web platform, API, alerts | Enterprise (contact S&P) |
+| PIERS (S&P Global) | Bill of lading, waterborne trade | 6x daily (U.S. imports), monthly (non-U.S.) | 100% U.S. waterborne, 15+ countries | Web platform, API | Enterprise (contact S&P) |
+| Descartes Datamyne | BOL database, 230 markets | Daily (U.S. maritime), regular updates | 230 markets, 180+ countries | Web platform, API, downloads | Annual subscription (contact) |
+| TradeInt | Coffee-specific supply chain data | Historical and recent | Global coffee trade | Web platform, filtering tools | Subscription (contact) |
+| Eximpedia | Coffee import/export trade data | Regular updates | Global (Robusta/Arabica) | Web platform, search/filtering | Subscription, free samples |
+| Freightos Baltic Index (FBX) | Container freight rates | Daily | 12 regional lanes | Public index, API | Free index, platform subscriptions |
+| AISHub | Real-time AIS, community data | Real-time | Global (community-based) | Free API (JSON/XML/CSV) | Free |
+
+## Satellite imagery enables crop health monitoring and yield prediction
+
+**Sentinel-2 satellites provide the optimal free baseline** for coffee plantation monitoring, delivering 10-meter multispectral imagery (13 bands) with 5-day revisit frequency covering all global coffee regions. The European Space Agency's Copernicus program offers unlimited free access via multiple platforms: Copernicus Data Space Ecosystem, Sentinel Hub, Google Earth Engine, and AWS Open Data Registry. Sentinel-2 data enables NDVI monitoring, crop health assessment, plantation mapping, and has demonstrated 90.5% accuracy in coffee classification when combined with DEM data.
+
+For cloud-prone tropical regions, **Sentinel-1 SAR provides all-weather monitoring** with 6-12 day revisit at 5-25 meter resolution depending on mode. C-band synthetic aperture radar penetrates clouds, enabling continuous monitoring of soil moisture, crop structure, and flooding in coffee areas. Both Sentinel-1 and Sentinel-2 data integrate seamlessly through the same free platforms.
+
+NASA's Landsat 8/9 constellation complements Sentinel with 30-meter resolution (100m thermal), 8-day combined revisit, and critically, 50+ years of historical archive enabling long-term change detection. Studies show Landsat NDVI achieves R² = 0.85 for coffee leaf water potential estimation. MODIS provides regional-scale monitoring with 250-meter NDVI/EVI products updated every 8-16 days, ideal for biennial yield pattern analysis across large coffee regions.
+
+**Google Earth Engine stands out as the premier integration platform**, providing free cloud computing access to the complete Sentinel, Landsat, and MODIS archives plus the new Forest Data Partnership coffee probability model (2020-2023). The Python and JavaScript APIs enable large-scale time-series analysis and machine learning classification. This is free for research, education, and nonprofit use, with commercial licensing available.
+
+Commercial satellite imagery offers superior resolution when needed. **Planet Labs delivers daily global coverage** at 3-5 meter resolution (PlanetScope) with sub-meter SkySat imagery (50cm), plus upcoming 40cm Pelican constellation. Studies using Planet/RapidEye data combined with nutrient data achieved R² = 0.88 for coffee yield prediction. Access requires subscription (contact for pricing) via Planet Insights Platform with API and Google Earth Engine integration.
+
+Maxar (WorldView, GeoEye) provides 30-50cm imagery via on-demand tasking through the Maxar Discovery Platform. Airbus Pléiades Neo delivers 30cm daily revisit capability. BlackSky specializes in high-revisit imaging with near real-time delivery. All require commercial licensing with contact-for-pricing models.
+
+**Recommended workflow**: Use free Sentinel-2 (10m, 5-day) plus Landsat (30m, 8-day) via Google Earth Engine for baseline monitoring. Supplement with Sentinel-1 SAR during cloudy seasons. Deploy Planet daily imagery for intensive monitoring of priority plantation areas. Historical Landsat archive provides long-term expansion tracking and biennial pattern analysis.
+
+| Source | Type | Resolution | Frequency | Coverage | Access | Cost |
+|--------|------|-----------|-----------|----------|--------|------|
+| Sentinel-2 | Optical multispectral (13 bands), NDVI, EVI | 10m (visible/NIR), 20m (red edge) | 5-day revisit | Global, all coffee regions | Copernicus Hub, Sentinel Hub, GEE, AWS | Free |
+| Sentinel-1 | C-band SAR, all-weather | 5-25m (mode-dependent) | 6-12 day revisit | Global land/coastal | Copernicus Hub, GEE, AWS | Free |
+| Landsat 8/9 | Optical multispectral (11 bands), thermal | 30m (optical), 100m (thermal) | 8-day combined revisit | Global, 1972+ archive | USGS EarthExplorer, GEE, AWS | Free |
+| MODIS | NDVI, EVI, LST, GPP | 250m (NDVI), 500m-1km | Daily obs, 8-16 day composites | Global | NASA Earthdata, GEE, LANCE | Free |
+| Google Earth Engine | Multi-petabyte catalog, cloud computing | Varies (250m to \<1m) | Continuous updates | Global, coffee models included | Python/JavaScript API, Code Editor | Free (research/education) |
+| Sentinel Hub | Sentinel, Landsat, MODIS, commercial data | 10m-1km (source-dependent) | Daily to 16-day | Global | RESTful APIs, QGIS plugin, Python | Free tier, paid advanced |
+| Planet Labs | PlanetScope optical, SkySat high-res | 3-5m (PlanetScope), 50cm (SkySat) | Daily global coverage | Global coffee regions | Platform, API, GEE integration | Subscription (contact) |
+| Maxar | WorldView, GeoEye very high-res | 30-50cm | On-demand tasking | Global | Maxar Discovery, SecureWatch, ArcGIS | Commercial (contact) |
+| Airbus | Pléiades Neo, SPOT | 30cm (Pléiades), 1.5-6m (SPOT) | Daily revisit capability | Global | OneAtlas platform, API | Commercial (contact) |
+
+## Weather data services provide critical production forecasting inputs
+
+**Visual Crossing Weather API delivers the best all-around package**, offering current conditions, 15-day forecasts, sub-hourly resolution, 50+ years of historical data, and agriculture-specific elements (soil temperature, soil moisture, evapotranspiration) through a single-endpoint REST API. The free tier provides 1,000 records/day with metered pricing at $0.0001/record beyond that, making it extremely cost-effective. Global coverage includes all major coffee regions with 100+ weather elements in JSON/CSV format.
+
+For agricultural specialization, **aWhere stands out with purpose-built agronomic models**. Their platform provides daily observations, 8-day forecasts, agronomic indices (PET, GDD, P/PET ratios), and 3-5 years of historical data at 9km grid resolution globally. Free access is available for South Asia and parts of Africa via the weADAPT platform, with commercial licenses for other regions. The REST API includes OAuth2 authentication and an aWherePy Python package, delivering field-level data specifically designed for crop monitoring.
+
+**ECMWF provides the world's leading weather forecasts** through the IFS HRES model at 9km resolution with 15-day forecasts updated 6-hourly, plus the new AIFS AI weather model. As of October 2025, ECMWF open-data is free under CC-BY 4.0 license, accessible via Open-Meteo's free REST API (no key required), the ecmwf-opendata Python package, or MARS API. This represents exceptional value for global forecast data.
+
+IBM Environmental Intelligence Suite (The Weather Company) delivers hyper-local 4km resolution from 250,000+ stations globally, with agriculture-specific APIs for frost potential, evapotranspiration, and soil moisture/temperature. The platform offers 15-day forecasts with 15-minute precipitation updates and seasonal/sub-seasonal forecasts. Free trial available (30 days) with Standard tier requiring minimum 200,000 calls/month. This premium service justifies cost through accuracy and agriculture specialization.
+
+For coffee-specific frost monitoring (critical for Brazilian arabica), AWIS Frost/Freeze Forecast Services provides 7-day frost forecasts with 24/7 email/text alerts customized to specific locations and crops, backed by 30+ years of agricultural weather experience. Affordable custom pricing makes this accessible for operational monitoring.
+
+OpenWeatherMap remains a solid general choice with free tier (1,000 calls/day) and pay-as-you-call model ($0.0001 per call), covering current weather, forecasts, and 46+ years of historical data. DTN Weather API offers agriculture-specific hyper-local forecasts with 0.1° gridded weather (15-day), historical data (2013+), and proprietary meteorologist team, though pricing requires contact.
+
+**Free government sources**: NOAA's National Centers for Environmental Information provides comprehensive climate data archives with Climate Data Online tool (free, 229+ TB monthly archived). NOAA's National Weather Service API offers real-time U.S. data via free REST API. Copernicus Climate Data Store provides ERA5 reanalysis and seasonal forecasts (free, registration required).
+
+**Drought monitoring**: GRIDMET provides SPI, EDDI, SPEI, and PDSI drought indices at 4km resolution for CONUS via Google Earth Engine (free). NOAA publishes global SPI from CMORPH for international coverage (free).
+
+| Source | Type | Frequency | Coverage | Access | Cost |
+|--------|------|-----------|----------|--------|------|
+| Visual Crossing | Current, 15-day forecast, 50+ years historical, ag elements | Real-time, sub-hourly, daily | Global | REST API (JSON/CSV), Web Query Builder | Free (1K records/day), $0.0001/record |
+| aWhere | Daily obs, 8-day forecast, agronomic models (PET, GDD) | Daily updates | Global (9km), South Asia/Africa free | REST API, aWherePy Python, web platform | Free (South Asia/Africa), commercial |
+| ECMWF/Open-Meteo | IFS HRES (9km), AIFS AI forecasts, 15-day | 6-hourly model runs, 1-hour output | Global | Free REST API (no key), Python package | Free (CC-BY 4.0) |
+| IBM Environmental Intelligence | 15-day forecast, ag APIs (frost, ET, soil), alerts | Real-time, 15-min precip, hourly/daily | Global (4km), 250K+ stations | REST API, Weather Company API | Free trial (30 days), Standard tier |
+| OpenWeatherMap | Current, forecasts, 46+ years historical | Real-time, hourly, daily | Global coverage | REST API (JSON/XML), bulk downloads | Free (1K calls/day), $0.0001/call PAYG |
+| DTN Weather | Current, 15-day forecast, historical (2013+), gridded | Near real-time, 3-hour updates | Global (0.1° gridded) | REST API, SDKs (Python/JS/Java), webhooks | Subscription (contact) |
+| Meteomatics | 2000+ parameters, ag-specific, 90m resolution | Real-time, hourly, daily | Global, EURO1k, US1k | REST API (Meteocache) | Trial available (contact) |
+| AWIS Frost Services | Frost/freeze forecasts, alerts | Real-time, 7-day forecasts | US and global customizable | Email/text alerts, web, API | Affordable custom (contact) |
+| NOAA NCEI | Climate Data Online, Climate Normals, 176-year record | Monthly reports, daily archives | Global, extensive US | Web interface, FTP, downloads | Free |
+| Copernicus CDS/ADS | ERA5 reanalysis, seasonal forecasts, climate data | Various (reanalysis, seasonal) | Global | CDS API (Python), web interface | Free (registration required) |
+| GRIDMET Drought Indices | SPI, EDDI, SPEI, PDSI at 4km | Daily updates | CONUS | Google Earth Engine API | Free |
+
+## Production and inventory statistics establish supply fundamentals
+
+**The International Coffee Organization (ICO) maintains the definitive coffee statistics database**, covering trade volumes/values, production, consumption, inventories, and prices for 192 consuming countries and 54 producing countries since October 1963. The World Coffee Statistics Database launched January 2022 with monthly updates. The free Coffee Market Report releases monthly, while the comprehensive Quarterly Statistical Bulletin and full database access require paid subscriptions (minimum £250 per request for non-members, free for ICO members). The bi-annual Coffee Report and Outlook costs £500. This represents the gold standard for official coffee statistics.
+
+**USDA Foreign Agricultural Service provides the best free government data**, publishing the comprehensive "Coffee: World Markets and Trade" report bi-annually (June and December) with global production volumes, consumption, trade statistics, stocks, and country-specific analysis. The PSD Online database offers interactive access to historical and forecast data. All USDA FAS data is free with no restrictions, making it essential for baseline supply/demand analysis.
+
+For country-specific intelligence:
+
+**Brazil (world's largest producer)**: CONAB (Companhia Nacional de Abastecimento) issues official production forecasts multiple times per harvest season (4+ reports annually, first in January) covering Arabica and Robusta/Conilon with state-by-state breakdowns, planted area, productivity estimates, and export data. Free access via conab.gov.br makes this the authoritative source for Brazilian supply.
+
+**Colombia (3rd largest producer)**: The Colombian Coffee Growers Federation (FNC) publishes regular production data, domestic reference prices, export volumes, and quality standards at national, departmental, and municipal levels. The National Coffee Register tracks detailed farm data. Free public access via federaciondecafeteros.org.
+
+**Vietnam (2nd largest producer)**: USDA FAS Vietnam reports provide more detailed analysis than local sources, though the General Statistics Office tracks 1,763,500 tons annual production. The Vietnam Coffee-Cocoa Association (VICOFA) offers industry perspective.
+
+**Stock data**: ICE (Intercontinental Exchange) publishes daily certified Arabica and Robusta coffee stocks at approved warehouses globally, accessible free via the ICE Report Center with CSV downloads. **As of 2024, arabica stocks hit 509,300 bags (1.5-year low)**, making this critical for supply tightness analysis. The European Coffee Federation published bi-monthly stock reports for major European ports but suspended this in 2023. The Green Coffee Association discontinued U.S. port warehouse stock reports in May 2023, creating a significant data gap.
+
+**Private research**: Volcafe (ED&F Man) publishes free market reviews with production forecasts covering 92% of origin countries. Rabobank releases quarterly coffee outlook reports with price forecasts (some public, full access requires subscription). Euromonitor International offers detailed market analysis for 78+ countries with retail sales, consumption trends, and market share data (premium pricing, annual updates).
+
+| Source | Type | Frequency | Coverage | Access | Cost |
+|--------|------|-----------|----------|--------|------|
+| ICO (International Coffee Organization) | Trade, production, consumption, inventories, prices | Monthly (CMR), Quarterly (QSB), Bi-annual | 192 consuming, 54 producing countries | World Coffee Statistics Database, reports | Free (CMR), Paid (WCSD £250+ min, QSB, Coffee Report £500) |
+| USDA Foreign Agricultural Service | Production, consumption, trade, stocks, forecasts | Bi-annual (June/December) | Global + country-specific | Website, PSD Online database, PDF downloads | Free |
+| CONAB (Brazil) | Production forecasts (Arabica/Robusta), harvest estimates | Multiple per season (4+ reports) | Brazil (national and state-level) | conab.gov.br, downloadable reports | Free |
+| Colombian Coffee Growers Federation (FNC) | Production, domestic prices, exports, quality data | Regular updates | Colombia (national, departmental, municipal) | federaciondecafeteros.org, reports | Free |
+| ICE Certified Stocks | Certified Arabica/Robusta stocks, warehouse inventory | Daily | ICE-approved warehouses globally | ICE Report Center, CSV downloads | Free basic, Paid premium |
+| Volcafe (ED&F Man) | Production forecasts, market outlook | Weekly/periodic, seasonal forecasts | Global (92% of origin countries) | volcafe.com/pages/reports, downloads | Free reports online |
+| Rabobank | Market forecasts, price forecasts, supply/demand | Quarterly coffee outlook, monthly commodity | Global and regional | research.rabobank.com | Some public, subscription for full |
+| Euromonitor International | Market size, retail sales, consumption trends | Annual updates | Global (78+ countries) | Passport database, reports | Premium subscription/purchase |
+| FAO (Food and Agriculture Organization) | Production volumes, area harvested, yield | Annual (published March) | Global (278 products) | FAOSTAT database, UNdata | Free |
+| European Coffee Federation | European imports, stock levels (suspended 2023), trade | Annual report, stocks bi-monthly (suspended) | Europe (EU27 + UK, CH, NO, IS) | ecf-coffee.org, downloadable reports | Free (annual report) |
+| Statista | Market data aggregation, production, trade | Regular updates as sources available | Global | statista.com, database platform | Limited free, Premium from $2,388/year |
+
+## Export, import, and customs data track global trade flows
+
+**UN Comtrade stands as the authoritative free source**, covering 220+ countries with monthly updates and data from 1962 onwards. Coffee trade data is accessible by HS code 0901 (coffee whether or not roasted or decaffeinated) at 2, 4, or 6-digit levels. The new ComtradePlus interface (comtradeplus.un.org) provides improved access with API, web interface, and bulk downloads at no cost. This represents the standard baseline for international trade statistics.
+
+**ITC Trade Map complements Comtrade** with enhanced analytics, offering annual trade flows with mirror data, export performance indicators, international demand metrics, and critically, a company directory with 10M+ businesses. Coverage includes 220+ countries, 5,300 products, and historical data since 2001. Free access (supported by World Bank and EU) makes this essential for identifying trading partners and analyzing market share. The jointly developed ITC/WTO/UNCTAD platform excels at comparative analysis.
+
+**World Bank WITS (World Integrated Trade Solution)** integrates UN Comtrade, UNCTAD TRAINS, and WTO data with added value through tariff analysis, non-tariff measures, and competitiveness indicators. Free access via wits.worldbank.org with API, bulk CSV downloads, and interactive visualization tools covering 200+ countries from 1962.
+
+For detailed shipment-level intelligence, **bill of lading providers offer granular cargo tracking**:
+
+**ImportGenius provides the most accessible entry** with U.S. customs records updated daily (258M+ import shipments, 5.6M+ export shipments), 18 years of U.S. historical data, and coverage of 23+ countries including major coffee producers (Colombia, Vietnam, India, Mexico). The AI-powered platform includes unlimited company profiling, Excel/CSV exports, and enterprise API. Plans start around $149/month with annual subscriptions offering 36% savings, making it cost-effective for SMEs.
+
+**Panjiva (S&P Global Market Intelligence)** covers 30+ data sources with U.S. maritime data updated weekly (within 1 week of customs filing) and international data monthly (2-month delay). The platform provides 10M+ company profiles with supplier-buyer relationships searchable by HS code, company name, DUNS number, and location. Xpressfeed API enables CRM integration. Enterprise pricing requires S&P Global contact.
+
+**PIERS (Port Import/Export Reporting Service)** delivers 100% U.S. waterborne trade coverage with 6x daily updates and 17 million BOLs annually. Historical data from 1950 provides long-term trend analysis. The platform integrates with Global Trade Atlas and includes commodity descriptions, tonnage, TEUs, and estimated values. Part of S&P Global Trade Analytics Suite (enterprise pricing).
+
+**Descartes Datamyne** covers 230 markets (75% of world import-export trade) with daily U.S. maritime updates (~26,000 records/day, 500M+ annual shipments). ISO 9001 certified data includes master/house BOL information, container details, NVOCC/VOCC data, and company contacts across 180+ countries. The platform supports Excel exports (10,000 records), Massive Download (500,000 records), and API access (annual subscription, contact for quote).
+
+**Coffee-specific platforms**: TradeInt specializes in coffee supply chain data with filtering by port, exporter, product type, and timeframe for past global trades. Eximpedia focuses exclusively on coffee (Robusta/Arabica) with HS code tracking and buyer/supplier information.
+
+**Government sources**: U.S. Census Bureau's USA Trade Online provides U.S. import/export statistics by HS level with state-level and port breakdowns (paid subscription, monthly free reports). Eurostat offers EU coffee trade data (intra and extra-EU) with monthly/annual updates, bulk CSV downloads, and data from January 1988 (free). USDA FAS bi-annual Coffee World Markets reports include bean exports by country (free).
+
+**Alternative platforms**: Volza covers 209 countries (90 complete data, 119 mirror data) with 3 billion+ shipment records including 82,467+ active coffee buyers and 556,489 trades in 2023. Pay-per-use pricing with 7-day trial. Tendata covers 91 countries with real-time customs data access tracking 42,084 coffee importers in 2023 worth $7.45B trade value.
+
+| Source | Type | Frequency | Coverage | Access | Cost |
+|--------|------|-----------|----------|--------|------|
+| UN Comtrade | Import/export volumes, values, bilateral flows, HS codes | Monthly updates | 220+ countries, 1962+ | Web (comtradeplus.un.org), API, downloads | Free basic, premium subscriptions |
+| ITC Trade Map | Annual trade flows, mirror data, market indicators | Annual, monthly/quarterly | 220+ countries, 10M+ companies | Web (trademap.org), Excel export | Free (registration required) |
+| World Bank WITS | Merchandise trade, tariffs, NTM, competitiveness | Annual updates | 200+ countries, 1962+ | Web (wits.worldbank.org), API, CSV | Free |
+| ImportGenius | U.S./23+ country customs records, BOL | Daily (U.S.), varies internationally | U.S. + 23 countries (Colombia, Vietnam, India) | Web platform, Enterprise API, Excel/CSV | ~$149/month, annual savings |
+| Panjiva (S&P Global) | Shipment/customs records, 30+ sources | Weekly (U.S.), monthly (international) | 30+ countries, 10M+ companies | Web, Xpressfeed API, alerts | Enterprise (contact S&P) |
+| PIERS (S&P Global) | BOL, 17M annually, 100% U.S. waterborne | 6x daily (U.S. imports), monthly (non-U.S.) | 100% U.S. waterborne, 15+ countries | Web, Global Trade Atlas integration | Enterprise (contact S&P) |
+| Descartes Datamyne | BOL database, 500M+ annually | Daily (U.S. maritime, 26K records/day) | 230 markets, 180+ countries | Web, API, Massive Download | Annual subscription (contact) |
+| TradeInt | Coffee-specific supply chain data | Historical and recent | Global coffee trade | Web platform, filtering tools | Subscription (contact) |
+| Eximpedia | Coffee import/export trade data | Regular updates | Global (Robusta/Arabica) | Web platform | Subscription, free samples |
+| Volza | 3B+ shipment records, 82,467+ coffee buyers (2023) | Regular updates, real-time alerts | 209 countries (90 complete, 119 mirror) | Web platform, API, dashboards | Pay-per-use, 7-day trial |
+| U.S. Census Bureau | U.S. import/export statistics, state/port level | Monthly releases | U.S. with 200+ partners | USA Trade Online, FT900/FT920 reports | USA Trade Online: Paid, Reports: Free |
+| Eurostat | EU coffee trade (intra/extra-EU), HS 0901 | Monthly and annual | 27 EU members, global partners | Web (ec.europa.eu/eurostat), Comext, CSV | Free |
+| ICO World Coffee Statistics Database | Coffee trade volumes/values, detailed statistics | Monthly (MTS), Quarterly (QSB) | 192 consuming, 54 producing countries | WCSD platform, email delivery | Limited free, subscriptions |
+
+## Alternative data expands analytical possibilities
+
+Beyond traditional categories, emerging alternative data sources provide predictive edges through sentiment analysis, supply chain transparency, auction pricing, consumer trends, and sustainability metrics.
+
+**Sentiment and news analytics**: RavenPack delivers institutional-grade news sentiment with 80+ fields describing entities, 20+ sentiment indicators, and real-time updates from 40,000+ web and social media sources in 13 languages. The platform covers commodities including Robusta coffee with sentiment scores (0-100, 50=neutral) and event sentiment scores updated 24/7. Historical database extends 6+ years. Paid subscription (contact for pricing) targets institutional investors. StockPulse provides emotional data intelligence with real-time 24/7 monitoring and historical data since 2012 using proprietary LLMs.
+
+Social media monitoring platforms (Sprout Social $249+/month, Brand24 varies, Hootsuite $99+/month) track Twitter/X, Instagram, Facebook, TikTok, and LinkedIn sentiment. Free alternatives include Python libraries (VADER, BeautifulSoup, Selenium) for custom sentiment analysis. Studies show coffee tweets are typically neutral or positive (45-47%).
+
+**Supply chain transparency**: TraceX Technologies offers blockchain-based farm-to-cup traceability with real-time IoT sensor data, GPS mapping, and sustainability metrics. Implemented with 3,500+ farmers in India's Araku Valley, the platform tracks deforestation risks and certification compliance (enterprise pricing). Sourcemap maps approximately 25% of the world's coffee supply in Latin America, Africa, and Southeast Asia with end-to-end supply chain visualization, due diligence data, and compliance tracking (subscription-based).
+
+INA-Trace provides open-source traceability (GitHub) with QR code consumer access, tracking pre-processing, post-harvest, storage, and payments in Rwanda and Honduras. Free open-source access enables customization. Trace by Fairfood combines NFC Farmer Cards with blockchain ledgers for real-time transaction recording in coffee, cocoa, spice, and fruit sectors.
+
+**Coffee auction data reveals quality premiums**: Cup of Excellence auctions provide transparent pricing for top-quality lots with detailed quality scores, farm information, and buyer data. Colombia 2021 averaged $30.79/lb (top lot $135.10/lb), Ethiopia 2020 averaged $28/lb (top lot $445/lb from Angelino's), with 28 winning lots per auction scoring 87+ points. M-Cultivo private auctions set records—2025 Ethiopian auction reached $1,739/kg (Alo Coffee), Faysel Abdosh auction hit $1,604/kg (Sidama Keramo), generating 6,000+ bids. Ethiopian Coffee Exchange tracks weekly export price adjustments and daily trading for the world's 5th largest exporter ($1.7B earnings in 2023/24).
+
+**Consumer demand indicators**: National Coffee Association's National Coffee Data Trends (NCDT) report provides authoritative U.S. consumption data annually, showing 66% of American adults drink coffee daily and 46% consumed specialty coffee in the past day (2025). The report purchase is required for full data. Specialty Coffee Association publishes the NCDT Breakout Report with detailed specialty coffee analysis (available to members). Tastewise AI platform analyzes trillions of data points across social media, eRetail, and menus for real-time trend tracking (14-day trial, then subscription).
+
+Mintel tracks 30% increase in caffeine-free coffee launches (2022-2023) through its Global New Products Database with ongoing updates and periodic market reports (subscription required). Deloitte's 2024 Coffee Study surveyed 7,000 coffee drinkers across 13 countries examining consumption patterns, sustainability concerns, and specialty trends (free public report).
+
+**Sustainability and certification**: Rainforest Alliance publishes annual certification reports covering 400,000+ certified coffee producers across ~1M hectares, showing 179% higher earnings for certified farms compared to non-certified. Interactive PowerBI reports provide global/regional/country breakdowns (free). Fairtrade International tracks 870,000+ coffee farmers with Fair Trade premiums and minimum price data (free public reports, certification costs $500-$3,000 annually). Specialty Coffee Association's Q Grader program provides quality certifications using the 100-point scale (80+ points = specialty grade, course ~$1,500-2,000).
+
+**Weather and satellite data for forecasting**: Studies demonstrate combining Landsat/Sentinel NDVI data with weather variables achieves R² up to 0.88 for coffee yield prediction. Research shows multi-temporal NDVI from July-August provides highest correlation with yield, while weather explains up to 36% of yield variation in Vietnam's Dak Lak region with 3-6 months advance forecast capability. BR-DWGD (Brazilian Daily Weather Gridded Data), CLIMBra, and ERA5 reanalysis provide the necessary weather inputs (mostly free), while Sentinel-2 and Landsat provide optical data (free). RapidEye/PlanetScope commercial imagery improves resolution when combined with nutrient data.
+
+**Market intelligence platforms**: ICE (Intercontinental Exchange) provides daily Coffee C and Robusta futures prices, volume, open interest, and inventory levels—the global benchmark for price discovery (market data fees required). Bloomberg Terminal (~$2,000+/month) and Refinitiv (enterprise pricing) integrate comprehensive coffee futures, news, analytics, and alternative data feeds. CoffeeBI specializes in coffee market research serving major industry players with out-of-home insights, machine market data, and industry trends (paid subscriptions).
+
+| Source | Type | Frequency | Coverage | Access | Cost |
+|--------|------|-----------|----------|--------|------|
+| RavenPack | News sentiment, ESS, CSS, entity analysis | Real-time 24/7, 6+ years historical | 40K+ sources, 13 languages, Robusta coffee | API, web dashboards, MATLAB integration | Paid (contact) |
+| StockPulse | Social media sentiment, emotional intelligence | Real-time 24/7, historical since 2012 | Global markets, commodities including coffee | Web software, API endpoints | Paid (contact) |
+| Sprout Social | Social media sentiment, engagement metrics | Real-time | Twitter/X, Instagram, Facebook, LinkedIn | Platform dashboard, API | $249+/month |
+| TraceX Technologies | Blockchain traceability, IoT sensors, GPS | Real-time | Global, 3,500+ farmers (India Araku Valley) | Platform, QR codes, API | Enterprise (contact) |
+| Sourcemap | End-to-end supply chain mapping | Real-time | 25% of world's coffee (Latin America, Africa, SE Asia) | Platform interface, API | Subscription |
+| INA-Trace | Pre-processing, post-harvest, storage, payments | Real-time | Rwanda, Honduras | GitHub open source, mobile app | Free (open source) |
+| Cup of Excellence | Auction prices, quality scores, farm info | Seasonal auctions | Multiple countries (Colombia, Ethiopia) | Online auction platform, public results | Free to view, fees to participate |
+| M-Cultivo | Private auction prices, bidding data | Seasonal/ad-hoc | Ethiopia (Echoes of Peak, Faysel Abdosh) | Online auction platform | Free to view, registration for participation |
+| Ethiopian Coffee Exchange | Export prices, volume, minimum price | Weekly price adjustments, daily trading | Ethiopia (5th largest exporter) | Official reports, government data | Free public data |
+| NCA NCDT Report | Consumption patterns, consumer preferences | Annual (Spring) | United States | Purchasable reports, press releases | Report purchase required |
+| SCA Specialty Coffee Breakout | Specialty consumption, preparation methods | Annual (partnership with NCA) | United States | SCA membership/purchase | Members/purchase |
+| Tastewise | Consumer trends, flavor pairings, social/eRetail | Real-time trend tracking | Global food \u0026 beverage | AI platform with GenAI | Subscription (14-day trial) |
+| Mintel | Product launches, consumer trends, market sizing | Ongoing database updates, periodic reports | Global, country-specific | Subscription platform, reports | Subscription (tiered) |
+| Deloitte Coffee Study | Consumption patterns, sustainability, preferences | Periodic (2024 edition) | Global - 13 countries, 7K drinkers | Published reports online | Free (public report) |
+| Rainforest Alliance | Certified farm data, sustainability metrics | Annual reports | 400K+ producers, ~1M hectares | Interactive PowerBI, PDFs | Free public reports |
+| Fairtrade International | Certified producer data, Fair Trade premiums | Annual reports | 870K+ coffee farmers globally | fairtrade.net, reports | Free public reports |
+| SCA Q Grader Program | Quality certifications, cupping scores | Ongoing certifications | Global specialty coffee | Certification programs | Course ~$1,500-2,000 |
+| ICE Coffee Futures | Futures prices, volume, open interest, inventory | Real-time during trading hours, daily | Global benchmark (Coffee C, Robusta) | ICE platform, market data vendors | Market data fees required |
+| Bloomberg Terminal | Real-time prices, news, alt data feeds | Real-time | Global commodities including coffee | Bloomberg Terminal | ~$2,000+/month |
+| Refinitiv | Futures, spot prices, news, analytics | Real-time | Global coffee markets | Refinitiv platform | Enterprise (contact) |
+| databento | All kinds of market data | Historic and realtime | - | - | Onetime/subscription - dev friendly
+| CoffeeBI | Coffee market research, OOH insights | Ongoing news, periodic reports | Global coffee and machine industry | Subscription platform, reports | Paid subscriptions |
+
+## Strategic recommendations for data source selection
+
+**For comprehensive baseline coverage at zero cost**: Combine CFTC COT reports (weekly trader positioning), Sentinel-2/Landsat satellite imagery via Google Earth Engine (crop monitoring and yield prediction), Visual Crossing or ECMWF/Open-Meteo weather data (production forecasting), USDA FAS reports (supply/demand fundamentals), UN Comtrade and ITC Trade Map (trade flows), and ICE certified stocks (inventory tightness). This free foundation covers all essential data categories with sufficient quality for fundamental analysis.
+
+**For institutional-grade analytics**: Add Kpler maritime intelligence ($enterprise) for leading indicators of physical movements, Planet Labs daily satellite imagery ($subscription) for intensive plantation monitoring, IBM Weather or aWhere ($subscription) for agriculture-specific weather models, ICO World Coffee Statistics Database (£250+ minimum) for the most comprehensive official statistics, ImportGenius or Panjiva ($149+/month to $enterprise) for granular shipment tracking, and RavenPack ($paid) for sentiment analysis. Bloomberg or Refinitiv terminals (~$2K+/month) provide integrated access to multiple premium feeds.
+
+**For specific analytical edges**: Deploy coffee-specific platforms like TradeInt for supply chain intelligence, Cup of Excellence and M-Cultivo auction data for quality premium trends, TraceX or Sourcemap for traceability and sustainability verification, NCA NCDT and Tastewise for consumer demand shifts, and specialized frost monitoring (AWIS) for Brazilian arabica risk assessment. These targeted sources address specific informational gaps competitors may overlook.
+
+**Frequency optimization**: Real-time sources (AIS tracking, weather APIs, sentiment analysis, futures prices) provide short-term tactical advantages. Daily sources (ICE stocks, satellite imagery, customs data) enable responsive positioning. Weekly/monthly sources (COT reports, trade statistics, production forecasts) inform medium-term strategy. Annual reports (consumer trends, sustainability metrics, long-term production forecasts) guide strategic allocation.
+
+**Coverage completeness**: Ensure data spans all major coffee origins (Brazil 40% of global arabica, Vietnam 40% of robusta, Colombia, Indonesia, Ethiopia, Honduras) and consumption markets (U.S., Europe, Japan, emerging markets). Cross-reference free and paid sources to validate critical data points. Monitor data gaps like the discontinued GCA warehouse stocks and adapt by using alternative indicators.
+
+The optimal strategy layers free foundational data with selective premium services targeting specific informational advantages, adjusted to trading timeframe, risk tolerance, and capital allocation. Systematic integration of alternative data beyond basic prices creates sustainable analytical edges in increasingly competitive coffee futures markets.
diff --git a/notebooks/01_Experiment.ipynb b/notebooks/01_experiment.ipynb
similarity index 100%
rename from notebooks/01_Experiment.ipynb
rename to notebooks/01_experiment.ipynb
diff --git a/notebooks/02_API.ipynb b/notebooks/02_api.ipynb
similarity index 100%
rename from notebooks/02_API.ipynb
rename to notebooks/02_api.ipynb
diff --git a/notebooks/03_Extraction.ipynb b/notebooks/03_extraction.ipynb
similarity index 100%
rename from notebooks/03_Extraction.ipynb
rename to notebooks/03_extraction.ipynb
diff --git a/notebooks/PSD Commodities.txt b/notebooks/psd commodities.txt
similarity index 100%
rename from notebooks/PSD Commodities.txt
rename to notebooks/psd commodities.txt
diff --git a/pyproject.toml b/pyproject.toml
index fa896bd..089d096 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -2,9 +2,10 @@
name = "materia"
version = "0.1.0"
description = "Add your description here"
-readme = "README.md"
+readme = "readme.md"
authors = [
- { name = "Deeman", email = "hendrik.note@gmail.com" }
+ { name = "Hendrik Deeman", email = "hendrik@beanflows.coffee" },
+ { name = "Simon Deeman", email = "simon@beanflows.coffee" }
]
requires-python = ">=3.13"
dependencies = [
@@ -15,6 +16,7 @@ dependencies = [
"pyyaml>=6.0.2",
"niquests>=3.15.2",
"hcloud>=2.8.0",
+ "prefect>=3.6.15",
]
[project.scripts]
@@ -45,6 +47,7 @@ sqlmesh_materia = {workspace = true }
members = [
"extract/*",
"transform/*",
+ "web",
]
[build-system]
@@ -52,7 +55,6 @@ requires = ["uv_build>=0.9.2,<0.10.0"]
build-backend = "uv_build"
[tool.ruff]
-# Exclude notebooks and common directories
exclude = [
".bzr",
".direnv",
diff --git a/README.md b/readme.md
similarity index 100%
rename from README.md
rename to readme.md
diff --git a/single_server_arch.excalidraw b/single_server_arch.excalidraw
new file mode 100644
index 0000000..0014447
--- /dev/null
+++ b/single_server_arch.excalidraw
@@ -0,0 +1,14053 @@
+{
+ "type": "excalidraw",
+ "version": 2,
+ "source": "https://excalidraw.com",
+ "elements": [
+ {
+ "id": "yaFX2PagL3MlaHNgR6Vna",
+ "type": "rectangle",
+ "x": 596.099609375,
+ "y": 57,
+ "width": 690,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "ATp0mV8TD6b1RjNT1Ah71"
+ ],
+ "frameId": null,
+ "index": "a0",
+ "roundness": null,
+ "seed": 764699867,
+ "version": 5,
+ "versionNonce": 129912059,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "1mUolQvm42UsHsJzIb4Xm"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "1mUolQvm42UsHsJzIb4Xm",
+ "type": "text",
+ "x": 868.5796890258789,
+ "y": 62,
+ "width": 145.0398406982422,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "ATp0mV8TD6b1RjNT1Ah71"
+ ],
+ "frameId": null,
+ "index": "a1",
+ "roundness": null,
+ "seed": 352915835,
+ "version": 7,
+ "versionNonce": 332747829,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Access Control",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "yaFX2PagL3MlaHNgR6Vna",
+ "originalText": "Access Control",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "RxZ7lNSgMaSJdAPmBlr2v",
+ "type": "rectangle",
+ "x": 631.099609375,
+ "y": 82,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "ATp0mV8TD6b1RjNT1Ah71"
+ ],
+ "frameId": null,
+ "index": "a2",
+ "roundness": null,
+ "seed": 1316956699,
+ "version": 8,
+ "versionNonce": 1040250267,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "1UiC4pq2cLwF-YPBnrjMa"
+ },
+ {
+ "id": "Fd7EZ_U3yc9IRvz7gPLR7",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "1UiC4pq2cLwF-YPBnrjMa",
+ "type": "text",
+ "x": 650.5397109985352,
+ "y": 114.5,
+ "width": 221.1197967529297,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "ATp0mV8TD6b1RjNT1Ah71"
+ ],
+ "frameId": null,
+ "index": "a3",
+ "roundness": null,
+ "seed": 1860775611,
+ "version": 7,
+ "versionNonce": 1457980821,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Web Browser (HTTPS)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "RxZ7lNSgMaSJdAPmBlr2v",
+ "originalText": "Web Browser (HTTPS)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "-do2R4980xFRXHBwEr2mL",
+ "type": "rectangle",
+ "x": 991.099609375,
+ "y": 82,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "ATp0mV8TD6b1RjNT1Ah71"
+ ],
+ "frameId": null,
+ "index": "a4",
+ "roundness": null,
+ "seed": 1223270235,
+ "version": 8,
+ "versionNonce": 858098235,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "XQ7WpniMsdpKVfrGbv1PD"
+ },
+ {
+ "id": "uv5B4vwwXd7W0gUyyE6pr",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "XQ7WpniMsdpKVfrGbv1PD",
+ "type": "text",
+ "x": 1014.5697021484375,
+ "y": 114.5,
+ "width": 213.059814453125,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "ATp0mV8TD6b1RjNT1Ah71"
+ ],
+ "frameId": null,
+ "index": "a5",
+ "roundness": null,
+ "seed": 919796731,
+ "version": 7,
+ "versionNonce": 595299061,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Engineer (SSH Tunnel)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "-do2R4980xFRXHBwEr2mL",
+ "originalText": "Engineer (SSH Tunnel)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "rSaST7XbQygkmgG3JHuev",
+ "type": "rectangle",
+ "x": -506.517578125,
+ "y": 927,
+ "width": 330,
+ "height": 165,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "VK9tL9rz27HcVyy-WUcDv"
+ ],
+ "frameId": null,
+ "index": "a6",
+ "roundness": null,
+ "seed": 614974619,
+ "version": 6,
+ "versionNonce": 202279643,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "uiSf3WyUJQJf6ouV6h_gA"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "uiSf3WyUJQJf6ouV6h_gA",
+ "type": "text",
+ "x": -461.8374481201172,
+ "y": 932,
+ "width": 240.63973999023438,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "VK9tL9rz27HcVyy-WUcDv"
+ ],
+ "frameId": null,
+ "index": "a7",
+ "roundness": null,
+ "seed": 1511684411,
+ "version": 7,
+ "versionNonce": 1779983445,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Off-site Backup Storage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "rSaST7XbQygkmgG3JHuev",
+ "originalText": "Off-site Backup Storage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "vsObzYnPHjgw0Xflc0D_C",
+ "type": "rectangle",
+ "x": -471.517578125,
+ "y": 977,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "VK9tL9rz27HcVyy-WUcDv"
+ ],
+ "frameId": null,
+ "index": "a8",
+ "roundness": null,
+ "seed": 76388827,
+ "version": 8,
+ "versionNonce": 760117115,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "qMYeZ9wi2GG8KTzsI99bk"
+ },
+ {
+ "id": "Xo94Lx1y13BSjq9HSL2KU",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "qMYeZ9wi2GG8KTzsI99bk",
+ "type": "text",
+ "x": -443.1174850463867,
+ "y": 997,
+ "width": 203.19981384277344,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "VK9tL9rz27HcVyy-WUcDv"
+ ],
+ "frameId": null,
+ "index": "a9",
+ "roundness": null,
+ "seed": 18065019,
+ "version": 7,
+ "versionNonce": 1855132085,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "S3 / Hetzner Backup\nStorage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "vsObzYnPHjgw0Xflc0D_C",
+ "originalText": "S3 / Hetzner Backup Storage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "eIoZJpJFt3VylWCmraMFx",
+ "type": "rectangle",
+ "x": -156.517578125,
+ "y": 277,
+ "width": 2500.03515625,
+ "height": 1005,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aA",
+ "roundness": null,
+ "seed": 1718558491,
+ "version": 8,
+ "versionNonce": 1160237083,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "c14CjevnHY1vkIi8QcaHJ",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "c14CjevnHY1vkIi8QcaHJ",
+ "type": "text",
+ "x": 956.0101318359375,
+ "y": 282,
+ "width": 274.979736328125,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aB",
+ "roundness": null,
+ "seed": 1326613435,
+ "version": 9,
+ "versionNonce": 1578177301,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Hetzner Server (8TB NVME)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "eIoZJpJFt3VylWCmraMFx",
+ "originalText": "Hetzner Server (8TB NVME)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "ANN60KfhIxD0VRkMXoNpD",
+ "type": "rectangle",
+ "x": -136.517578125,
+ "y": 707,
+ "width": 742.6171875,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "puDQc4A-3eBXlNdHl4sY-",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aC",
+ "roundness": null,
+ "seed": 1663063131,
+ "version": 8,
+ "versionNonce": 361567419,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "HkmzCBjNNoXZ6xffPLIF2",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "HkmzCBjNNoXZ6xffPLIF2",
+ "type": "text",
+ "x": 138.0511016845703,
+ "y": 712,
+ "width": 193.47982788085938,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "puDQc4A-3eBXlNdHl4sY-",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aD",
+ "roundness": null,
+ "seed": 577442043,
+ "version": 9,
+ "versionNonce": 621275253,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Backup Management",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "ANN60KfhIxD0VRkMXoNpD",
+ "originalText": "Backup Management",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "6YOF55j7emdZ0ii6Lvxbs",
+ "type": "rectangle",
+ "x": -31.517578125,
+ "y": 732,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "puDQc4A-3eBXlNdHl4sY-",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aE",
+ "roundness": null,
+ "seed": 1853176219,
+ "version": 12,
+ "versionNonce": 2116076891,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "06w_o5h5FVHA5gGGB0m8Z",
+ "type": "arrow"
+ },
+ {
+ "id": "0cumOGwXKxvipCjq9XlNm",
+ "type": "arrow"
+ },
+ {
+ "id": "vlfDPtP1dWYqdhw3VXDYY",
+ "type": "arrow"
+ },
+ {
+ "id": "Xo94Lx1y13BSjq9HSL2KU",
+ "type": "arrow"
+ },
+ {
+ "id": "ct-gdVGbBmBbv2ZMlrgZd",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "ct-gdVGbBmBbv2ZMlrgZd",
+ "type": "text",
+ "x": -8.847488403320312,
+ "y": 764.5,
+ "width": 214.65982055664062,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "puDQc4A-3eBXlNdHl4sY-",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aF",
+ "roundness": null,
+ "seed": 1416711739,
+ "version": 9,
+ "versionNonce": 87888341,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Scheduled Backup Job",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "6YOF55j7emdZ0ii6Lvxbs",
+ "originalText": "Scheduled Backup Job",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "WmBQSpZT97e_31unMWiHE",
+ "type": "rectangle",
+ "x": 1329.177734375,
+ "y": 302,
+ "width": 994.33984375,
+ "height": 545,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aG",
+ "roundness": null,
+ "seed": 390188763,
+ "version": 8,
+ "versionNonce": 1177903611,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "2Lups9YWHshUPIfnRUaD6",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "2Lups9YWHshUPIfnRUaD6",
+ "type": "text",
+ "x": 1681.6878051757812,
+ "y": 307,
+ "width": 289.3197021484375,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aH",
+ "roundness": null,
+ "seed": 2037988219,
+ "version": 9,
+ "versionNonce": 1808142133,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Data & Transformation Layer",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "WmBQSpZT97e_31unMWiHE",
+ "originalText": "Data & Transformation Layer",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "q7-PxoMjO7tNTXOgo3LTq",
+ "type": "rectangle",
+ "x": 1605.318359375,
+ "y": 327,
+ "width": 192.296875,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aI",
+ "roundness": null,
+ "seed": 1197085723,
+ "version": 12,
+ "versionNonce": 650996379,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "SRPFe2ZcZp2lFORS8DW0S",
+ "type": "arrow"
+ },
+ {
+ "id": "uv5B4vwwXd7W0gUyyE6pr",
+ "type": "arrow"
+ },
+ {
+ "id": "HhRiqbdkTzqXO_eACD8rQ",
+ "type": "arrow"
+ },
+ {
+ "id": "oB0Ot4ICf70IZ8CUqdK-D",
+ "type": "text"
+ },
+ {
+ "id": "5K0ZWOi5NZCeKytPiVfyb",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "oB0Ot4ICf70IZ8CUqdK-D",
+ "type": "text",
+ "x": 1629.8268661499023,
+ "y": 344.5,
+ "width": 143.2798614501953,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aJ",
+ "roundness": null,
+ "seed": 550951099,
+ "version": 9,
+ "versionNonce": 117989525,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Apache Airflow",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "q7-PxoMjO7tNTXOgo3LTq",
+ "originalText": "Apache Airflow",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "DP3c-pKkahtaw5YnTp3Ms",
+ "type": "rectangle",
+ "x": 1364.177734375,
+ "y": 747,
+ "width": 216.765625,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aK",
+ "roundness": null,
+ "seed": 59902299,
+ "version": 10,
+ "versionNonce": 345726779,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "bc9oC8enLOZdYYIO7XaLj",
+ "type": "arrow"
+ },
+ {
+ "id": "DUx7OUuo0Z1KGlDvpeiH8",
+ "type": "text"
+ },
+ {
+ "id": "5K0ZWOi5NZCeKytPiVfyb",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "DUx7OUuo0Z1KGlDvpeiH8",
+ "type": "text",
+ "x": 1394.150619506836,
+ "y": 764.5,
+ "width": 156.81985473632812,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aL",
+ "roundness": null,
+ "seed": 350103035,
+ "version": 9,
+ "versionNonce": 481920501,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "SQLMesh Engine",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "DP3c-pKkahtaw5YnTp3Ms",
+ "originalText": "SQLMesh Engine",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "bqKKeoQ6tFZ8wyZGLo71b",
+ "type": "rectangle",
+ "x": 1725.455078125,
+ "y": 747,
+ "width": 220.8125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aM",
+ "roundness": null,
+ "seed": 733851291,
+ "version": 10,
+ "versionNonce": 1241628635,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "KOf3-4liEtssdCvcPLk5J",
+ "type": "arrow"
+ },
+ {
+ "id": "t5duvO1BqBOFslnl4TDip",
+ "type": "arrow"
+ },
+ {
+ "id": "G1n0-jWcBVAeLcS0wo55A",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "G1n0-jWcBVAeLcS0wo55A",
+ "type": "text",
+ "x": 1747.6414260864258,
+ "y": 764.5,
+ "width": 176.43980407714844,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aN",
+ "roundness": null,
+ "seed": 451093307,
+ "version": 9,
+ "versionNonce": 534708053,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Ingestion Workers",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "bqKKeoQ6tFZ8wyZGLo71b",
+ "originalText": "Ingestion Workers",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "5K0ZWOi5NZCeKytPiVfyb",
+ "type": "arrow",
+ "x": 1594.6484206396249,
+ "y": 389.66639187537174,
+ "width": 122.0879987646249,
+ "height": 346.33360812462837,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aO",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 984679387,
+ "version": 11,
+ "versionNonce": 286461051,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -122.0879987646249,
+ 37.333608124628256
+ ],
+ [
+ -122.0879987646249,
+ 77.33360812462826
+ ],
+ [
+ -122.0879987646249,
+ 102.33360812462826
+ ],
+ [
+ -122.0879987646249,
+ 172.33360812462826
+ ],
+ [
+ -122.0879987646249,
+ 242.33360812462826
+ ],
+ [
+ -122.0879987646249,
+ 267.33360812462826
+ ],
+ [
+ -122.0879987646249,
+ 292.33360812462826
+ ],
+ [
+ -122.0879987646249,
+ 317.33360812462826
+ ],
+ [
+ -122.070436394833,
+ 346.33360812462837
+ ]
+ ],
+ "startBinding": {
+ "elementId": "q7-PxoMjO7tNTXOgo3LTq",
+ "mode": "orbit",
+ "fixedPoint": [
+ 3.2501828116218346e-7,
+ 0.9900333333333341
+ ]
+ },
+ "endBinding": {
+ "elementId": "DP3c-pKkahtaw5YnTp3Ms",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.06666666666666667
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "CBBemoyHkyUNod7EqwoHK",
+ "type": "rectangle",
+ "x": 1670.861328125,
+ "y": 492,
+ "width": 632.65625,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "-qzcxqiorpLHKS8MPkBA9",
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aP",
+ "roundness": null,
+ "seed": 859426939,
+ "version": 8,
+ "versionNonce": 114183349,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "lfIuD8E4hwRzHAIQth6F4",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "lfIuD8E4hwRzHAIQth6F4",
+ "type": "text",
+ "x": 1910.629539489746,
+ "y": 497,
+ "width": 153.1198272705078,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "-qzcxqiorpLHKS8MPkBA9",
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aQ",
+ "roundness": null,
+ "seed": 104859931,
+ "version": 9,
+ "versionNonce": 1301398811,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Execution Logic",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "CBBemoyHkyUNod7EqwoHK",
+ "originalText": "Execution Logic",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "upfyt-t4jXUxce3rBCbyU",
+ "type": "rectangle",
+ "x": 1705.861328125,
+ "y": 517,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "-qzcxqiorpLHKS8MPkBA9",
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aR",
+ "roundness": null,
+ "seed": 1496722875,
+ "version": 10,
+ "versionNonce": 1630334485,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "HhRiqbdkTzqXO_eACD8rQ",
+ "type": "arrow"
+ },
+ {
+ "id": "t5duvO1BqBOFslnl4TDip",
+ "type": "arrow"
+ },
+ {
+ "id": "aFxzqIJbmN6_76bMiQkos",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "aFxzqIJbmN6_76bMiQkos",
+ "type": "text",
+ "x": 1736.0314254760742,
+ "y": 537,
+ "width": 199.65980529785156,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "-qzcxqiorpLHKS8MPkBA9",
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aS",
+ "roundness": null,
+ "seed": 2134818395,
+ "version": 9,
+ "versionNonce": 1190160827,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Continuous Task\n(Sensor/Reschedule)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "upfyt-t4jXUxce3rBCbyU",
+ "originalText": "Continuous Task (Sensor/Reschedule)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "Xg7iaYqLFo26EYW1-z-tI",
+ "type": "rectangle",
+ "x": 2015.861328125,
+ "y": 532,
+ "width": 252.65625,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "-qzcxqiorpLHKS8MPkBA9",
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aT",
+ "roundness": null,
+ "seed": 1126972155,
+ "version": 8,
+ "versionNonce": 770728821,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "4y0KP5sfkxHQkTAkFFxqt",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "4y0KP5sfkxHQkTAkFFxqt",
+ "type": "text",
+ "x": 2036.2495651245117,
+ "y": 549.5,
+ "width": 211.87977600097656,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "-qzcxqiorpLHKS8MPkBA9",
+ "3XHgyUU2GfmrFJLZPbL05",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aU",
+ "roundness": null,
+ "seed": 1904288667,
+ "version": 9,
+ "versionNonce": 844200539,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Transformation DAGs",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "Xg7iaYqLFo26EYW1-z-tI",
+ "originalText": "Transformation DAGs",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "SdMJCMFB16D_i3lMbMG6B",
+ "type": "rectangle",
+ "x": 658.599609375,
+ "y": 707,
+ "width": 617.5,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "xiY_kMcGZSimksH6A2Psf",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aV",
+ "roundness": null,
+ "seed": 577763387,
+ "version": 8,
+ "versionNonce": 1901997269,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "lWb1B5Rmn0CbnrH4BBwPp",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "lWb1B5Rmn0CbnrH4BBwPp",
+ "type": "text",
+ "x": 885.1496963500977,
+ "y": 712,
+ "width": 164.3998260498047,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "xiY_kMcGZSimksH6A2Psf",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aW",
+ "roundness": null,
+ "seed": 1138440411,
+ "version": 9,
+ "versionNonce": 2089252603,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Application Layer",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "SdMJCMFB16D_i3lMbMG6B",
+ "originalText": "Application Layer",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "x7O5lfS6Axf3D0Yh0vXbm",
+ "type": "rectangle",
+ "x": 896.099609375,
+ "y": 732,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "xiY_kMcGZSimksH6A2Psf",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aX",
+ "roundness": null,
+ "seed": 1666540923,
+ "version": 12,
+ "versionNonce": 185322037,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "BgI7Sm_x0igEhyveyuEwH",
+ "type": "arrow"
+ },
+ {
+ "id": "CIb8WbLDAUiJQJTUcg1qL",
+ "type": "arrow"
+ },
+ {
+ "id": "oZuNZRdDJCI1MnxE0_-qd",
+ "type": "arrow"
+ },
+ {
+ "id": "OZAo9G-34-QIWNm5RTCqh",
+ "type": "arrow"
+ },
+ {
+ "id": "rXy5KlnGBrwFTyJmpqvN7",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "rXy5KlnGBrwFTyJmpqvN7",
+ "type": "text",
+ "x": 905.4497222900391,
+ "y": 764.5,
+ "width": 241.29977416992188,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "xiY_kMcGZSimksH6A2Psf",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aY",
+ "roundness": null,
+ "seed": 941686299,
+ "version": 9,
+ "versionNonce": 1410654107,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Async Flask-like Web App",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "x7O5lfS6Axf3D0Yh0vXbm",
+ "originalText": "Async Flask-like Web App",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "NeZ4EghCD47uGDdu_JZT0",
+ "type": "rectangle",
+ "x": 596.099609375,
+ "y": 467,
+ "width": 330,
+ "height": 190,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "Y71MMHrtLE2UXm4Kt8tVD",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aZ",
+ "roundness": null,
+ "seed": 1831895739,
+ "version": 8,
+ "versionNonce": 1272888213,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "SdmYQ0q97z25zjTvygn_a",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "SdmYQ0q97z25zjTvygn_a",
+ "type": "text",
+ "x": 694.7096710205078,
+ "y": 472,
+ "width": 132.77987670898438,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "Y71MMHrtLE2UXm4Kt8tVD",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aa",
+ "roundness": null,
+ "seed": 723940187,
+ "version": 9,
+ "versionNonce": 1932276795,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Ingress Layer",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "NeZ4EghCD47uGDdu_JZT0",
+ "originalText": "Ingress Layer",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "jLMKRAmUupduTdR2bvDOk",
+ "type": "rectangle",
+ "x": 631.099609375,
+ "y": 517,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "Y71MMHrtLE2UXm4Kt8tVD",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "ab",
+ "roundness": null,
+ "seed": 1649758203,
+ "version": 10,
+ "versionNonce": 1275887861,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "Fd7EZ_U3yc9IRvz7gPLR7",
+ "type": "arrow"
+ },
+ {
+ "id": "CIb8WbLDAUiJQJTUcg1qL",
+ "type": "arrow"
+ },
+ {
+ "id": "2bAXS57XZZTojF8s4tJQo",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "2bAXS57XZZTojF8s4tJQo",
+ "type": "text",
+ "x": 650.4897079467773,
+ "y": 537,
+ "width": 221.2198028564453,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "Y71MMHrtLE2UXm4Kt8tVD",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "ac",
+ "roundness": null,
+ "seed": 1421842587,
+ "version": 9,
+ "versionNonce": 699397339,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Caddy / Nginx Reverse\nProxy",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "jLMKRAmUupduTdR2bvDOk",
+ "originalText": "Caddy / Nginx Reverse Proxy",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "rkGkUbG5OwlOD-6K_4zxM",
+ "type": "rectangle",
+ "x": -76.517578125,
+ "y": 952,
+ "width": 2014.93359375,
+ "height": 305,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "ad",
+ "roundness": null,
+ "seed": 1612172603,
+ "version": 8,
+ "versionNonce": 18520661,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "2wjXZPRZr28A4XIEkxEur",
+ "type": "text"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "2wjXZPRZr28A4XIEkxEur",
+ "type": "text",
+ "x": 806.939338684082,
+ "y": 957,
+ "width": 248.01976013183594,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "ae",
+ "roundness": null,
+ "seed": 130051547,
+ "version": 9,
+ "versionNonce": 657629563,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "High-Speed Storage Layer",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "rkGkUbG5OwlOD-6K_4zxM",
+ "originalText": "High-Speed Storage Layer",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "P7LHsozW6hqIjjHypkPG3",
+ "type": "rectangle",
+ "x": 475.794921875,
+ "y": 1142,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#b71c1c",
+ "backgroundColor": "#ffcdd2",
+ "fillStyle": "solid",
+ "strokeWidth": 3,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "af",
+ "roundness": null,
+ "seed": 1053555323,
+ "version": 12,
+ "versionNonce": 333350837,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "Lwf1PVl4Ed3DdLwqxCtYw",
+ "type": "text"
+ },
+ {
+ "id": "AYGioa_0bBGP9O1YW0VqO",
+ "type": "arrow"
+ },
+ {
+ "id": "k2bktM4eceSq03eRE8HL_",
+ "type": "arrow"
+ },
+ {
+ "id": "UAHkkq5s0Hbz5gZKJjuvv",
+ "type": "arrow"
+ },
+ {
+ "id": "O0w8ZsAiWULB-7-HI7xUx",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "Lwf1PVl4Ed3DdLwqxCtYw",
+ "type": "text",
+ "x": 481.65503692626953,
+ "y": 1174.5,
+ "width": 248.27976989746094,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#b71c1c",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "ag",
+ "roundness": null,
+ "seed": 1912402715,
+ "version": 9,
+ "versionNonce": 83278363,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "8TB NVME Local Storage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "P7LHsozW6hqIjjHypkPG3",
+ "originalText": "8TB NVME Local Storage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "YgobDo0D36vcI09LP1XTG",
+ "type": "rectangle",
+ "x": 1665.833984375,
+ "y": 992,
+ "width": 230.109375,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "ah",
+ "roundness": null,
+ "seed": 1371920315,
+ "version": 11,
+ "versionNonce": 1987954965,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "KOf3-4liEtssdCvcPLk5J",
+ "type": "arrow"
+ },
+ {
+ "id": "0cumOGwXKxvipCjq9XlNm",
+ "type": "arrow"
+ },
+ {
+ "id": "wivgMaFbCPmTn5Tlt9UUd",
+ "type": "text"
+ },
+ {
+ "id": "AYGioa_0bBGP9O1YW0VqO",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "wivgMaFbCPmTn5Tlt9UUd",
+ "type": "text",
+ "x": 1683.978759765625,
+ "y": 1009.5,
+ "width": 193.81982421875,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "ai",
+ "roundness": null,
+ "seed": 1548298331,
+ "version": 9,
+ "versionNonce": 267304635,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Raw Ingested Data",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "YgobDo0D36vcI09LP1XTG",
+ "originalText": "Raw Ingested Data",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "eWZrcNs5rX193KU0Iu1Fd",
+ "type": "rectangle",
+ "x": 977.673828125,
+ "y": 992,
+ "width": 238.96875,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aj",
+ "roundness": null,
+ "seed": 660169979,
+ "version": 11,
+ "versionNonce": 980278901,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "OZAo9G-34-QIWNm5RTCqh",
+ "type": "arrow"
+ },
+ {
+ "id": "vlfDPtP1dWYqdhw3VXDYY",
+ "type": "arrow"
+ },
+ {
+ "id": "BqQEZ8KKMG7aTTP8qNp-m",
+ "type": "text"
+ },
+ {
+ "id": "k2bktM4eceSq03eRE8HL_",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "BqQEZ8KKMG7aTTP8qNp-m",
+ "type": "text",
+ "x": 999.4282989501953,
+ "y": 1009.5,
+ "width": 195.45980834960938,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "ak",
+ "roundness": null,
+ "seed": 1786318235,
+ "version": 9,
+ "versionNonce": 1388130139,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Application DB Files",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "eWZrcNs5rX193KU0Iu1Fd",
+ "originalText": "Application DB Files",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "WZpzKUi1bxJNygFQYc2XZ",
+ "type": "rectangle",
+ "x": 330.982421875,
+ "y": 977,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "al",
+ "roundness": null,
+ "seed": 1222287931,
+ "version": 11,
+ "versionNonce": 645154773,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "bc9oC8enLOZdYYIO7XaLj",
+ "type": "arrow"
+ },
+ {
+ "id": "oZuNZRdDJCI1MnxE0_-qd",
+ "type": "arrow"
+ },
+ {
+ "id": "HGzzlLtZre_6qJPM3NBlS",
+ "type": "text"
+ },
+ {
+ "id": "UAHkkq5s0Hbz5gZKJjuvv",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "HGzzlLtZre_6qJPM3NBlS",
+ "type": "text",
+ "x": 340.73252868652344,
+ "y": 997,
+ "width": 240.49978637695312,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "am",
+ "roundness": null,
+ "seed": 1533059803,
+ "version": 9,
+ "versionNonce": 1605667835,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "SQLMesh / Analytics DB\nFiles",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "WZpzKUi1bxJNygFQYc2XZ",
+ "originalText": "SQLMesh / Analytics DB Files",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "Tv3jBXWdJ2LCPLo0dXdN4",
+ "type": "rectangle",
+ "x": -41.517578125,
+ "y": 977,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "an",
+ "roundness": null,
+ "seed": 2057146235,
+ "version": 10,
+ "versionNonce": 212239669,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "id": "06w_o5h5FVHA5gGGB0m8Z",
+ "type": "arrow"
+ },
+ {
+ "id": "hyJzmvwoVLrvEId1ywVRi",
+ "type": "text"
+ },
+ {
+ "id": "O0w8ZsAiWULB-7-HI7xUx",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "hyJzmvwoVLrvEId1ywVRi",
+ "type": "text",
+ "x": -16.017478942871094,
+ "y": 997,
+ "width": 208.9998016357422,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "ao",
+ "roundness": null,
+ "seed": 1221847067,
+ "version": 9,
+ "versionNonce": 1524061339,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Airflow Metadata DB\nFiles",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "Tv3jBXWdJ2LCPLo0dXdN4",
+ "originalText": "Airflow Metadata DB Files",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "AYGioa_0bBGP9O1YW0VqO",
+ "type": "arrow",
+ "x": 1780.9052860546874,
+ "y": 1063,
+ "width": 1033.6103641796872,
+ "height": 115.57097687574242,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "ap",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 2079730875,
+ "version": 12,
+ "versionNonce": 1617565333,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.016864179687445358,
+ 29
+ ],
+ [
+ -0.016864179687445358,
+ 54
+ ],
+ [
+ -1033.6103641796872,
+ 115.57097687574242
+ ]
+ ],
+ "startBinding": {
+ "elementId": "YgobDo0D36vcI09LP1XTG",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "P7LHsozW6hqIjjHypkPG3",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0000019230769235,
+ 0.4139555555555565
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "k2bktM4eceSq03eRE8HL_",
+ "type": "arrow",
+ "x": 1097.1755885156251,
+ "y": 1063,
+ "width": 349.8806666406251,
+ "height": 103.84177400563954,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "aq",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1738988891,
+ "version": 11,
+ "versionNonce": 1138231611,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.017166640625191576,
+ 29
+ ],
+ [
+ -0.017166640625191576,
+ 54
+ ],
+ [
+ -349.8806666406251,
+ 103.84177400563954
+ ]
+ ],
+ "startBinding": {
+ "elementId": "eWZrcNs5rX193KU0Iu1Fd",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "P7LHsozW6hqIjjHypkPG3",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0000019230769235,
+ 0.29422222222222244
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "UAHkkq5s0Hbz5gZKJjuvv",
+ "type": "arrow",
+ "x": 460.996981875,
+ "y": 1078,
+ "width": 27.928260000000023,
+ "height": 52.5,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "ar",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1194883579,
+ "version": 11,
+ "versionNonce": 208960501,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.014560000000017226,
+ 14
+ ],
+ [
+ -0.014560000000017226,
+ 39
+ ],
+ [
+ 27.913700000000006,
+ 52.5
+ ]
+ ],
+ "startBinding": {
+ "elementId": "WZpzKUi1bxJNygFQYc2XZ",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "P7LHsozW6hqIjjHypkPG3",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.14194807692307712,
+ 0
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "O0w8ZsAiWULB-7-HI7xUx",
+ "type": "arrow",
+ "x": 88.49698187500002,
+ "y": 1078,
+ "width": 375.81249999999994,
+ "height": 89.85281752097148,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IV6sXtk3zlGVF0N5s5cGJ",
+ "rGPpS_WY-l7rtE3bBJLPR"
+ ],
+ "frameId": null,
+ "index": "as",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1202553499,
+ "version": 11,
+ "versionNonce": 1649115,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.014560000000017226,
+ 14
+ ],
+ [
+ -0.014560000000017226,
+ 39
+ ],
+ [
+ 375.7979399999999,
+ 89.85281752097148
+ ]
+ ],
+ "startBinding": {
+ "elementId": "Tv3jBXWdJ2LCPLo0dXdN4",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "P7LHsozW6hqIjjHypkPG3",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.0000019230769230314483,
+ 0.3045444444444456
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "SVCb9Sa4qtjf8lG5tqoX4",
+ "type": "rectangle",
+ "x": 1317.185546875,
+ "y": -328,
+ "width": 628.703125,
+ "height": 525,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "at",
+ "roundness": null,
+ "seed": 1371043643,
+ "version": 6,
+ "versionNonce": 147535189,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "TuBeGl522PQIRm54KHLb9"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "TuBeGl522PQIRm54KHLb9",
+ "type": "text",
+ "x": 1515.6772155761719,
+ "y": -323,
+ "width": 231.71978759765625,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "au",
+ "roundness": null,
+ "seed": 331077595,
+ "version": 7,
+ "versionNonce": 615331451,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "CI/CD Pipeline (GitLab)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "SVCb9Sa4qtjf8lG5tqoX4",
+ "originalText": "CI/CD Pipeline (GitLab)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "dECMMSEk_2Eov_teVKh_L",
+ "type": "rectangle",
+ "x": 1670.849609375,
+ "y": -303,
+ "width": 220.078125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "av",
+ "roundness": null,
+ "seed": 1271538811,
+ "version": 7,
+ "versionNonce": 818135733,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "DUw81UL87tSuoUEP7v5Et"
+ },
+ {
+ "id": "SR6U_tNP3JLkry181eQFI",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "DUw81UL87tSuoUEP7v5Et",
+ "type": "text",
+ "x": 1691.4587707519531,
+ "y": -285.5,
+ "width": 178.85980224609375,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "aw",
+ "roundness": null,
+ "seed": 1369824539,
+ "version": 7,
+ "versionNonce": 5680923,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "GitLab Repository",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "dECMMSEk_2Eov_teVKh_L",
+ "originalText": "GitLab Repository",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "KgzLzx8NRG_uZCFnVZKQG",
+ "type": "rectangle",
+ "x": 1685.849609375,
+ "y": -163,
+ "width": 190.078125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "ax",
+ "roundness": null,
+ "seed": 1623294395,
+ "version": 8,
+ "versionNonce": 1493410837,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "w9hAoKSHviOWpvEt7WlP8"
+ },
+ {
+ "id": "SR6U_tNP3JLkry181eQFI",
+ "type": "arrow"
+ },
+ {
+ "id": "9VKmMdNvBd2Hl7rHRpr4L",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "w9hAoKSHviOWpvEt7WlP8",
+ "type": "text",
+ "x": 1711.5287399291992,
+ "y": -145.5,
+ "width": 138.71986389160156,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "ay",
+ "roundness": null,
+ "seed": 574591579,
+ "version": 7,
+ "versionNonce": 1703416763,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "GitLab Runner",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "KgzLzx8NRG_uZCFnVZKQG",
+ "originalText": "GitLab Runner",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "d96eDkgT9SM_9D05CKOIo",
+ "type": "rectangle",
+ "x": 1669.349609375,
+ "y": -53,
+ "width": 223.078125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "az",
+ "roundness": null,
+ "seed": 1995607803,
+ "version": 8,
+ "versionNonce": 629168501,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "YS7b1KYv8CugsOZF-1XhD"
+ },
+ {
+ "id": "9VKmMdNvBd2Hl7rHRpr4L",
+ "type": "arrow"
+ },
+ {
+ "id": "avG8IZD-pmZctNOGL1mXx",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "YS7b1KYv8CugsOZF-1XhD",
+ "type": "text",
+ "x": 1685.348762512207,
+ "y": -35.5,
+ "width": 191.07981872558594,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "b00",
+ "roundness": null,
+ "seed": 22869915,
+ "version": 7,
+ "versionNonce": 878961755,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Build & Test Stage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "d96eDkgT9SM_9D05CKOIo",
+ "originalText": "Build & Test Stage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "1-1g9N63vYl2pO69YIiiX",
+ "type": "rectangle",
+ "x": 1650.888671875,
+ "y": 82,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "b01",
+ "roundness": null,
+ "seed": 1873890363,
+ "version": 10,
+ "versionNonce": 528442069,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "c7_gjpFK6-TjFCUfaCfoZ"
+ },
+ {
+ "id": "avG8IZD-pmZctNOGL1mXx",
+ "type": "arrow"
+ },
+ {
+ "id": "BgI7Sm_x0igEhyveyuEwH",
+ "type": "arrow"
+ },
+ {
+ "id": "SRPFe2ZcZp2lFORS8DW0S",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "c7_gjpFK6-TjFCUfaCfoZ",
+ "type": "text",
+ "x": 1660.6687774658203,
+ "y": 114.5,
+ "width": 240.43978881835938,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "b02",
+ "roundness": null,
+ "seed": 97651931,
+ "version": 7,
+ "versionNonce": 616341755,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Deploy Stage (SSH/SCP)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "1-1g9N63vYl2pO69YIiiX",
+ "originalText": "Deploy Stage (SSH/SCP)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "SR6U_tNP3JLkry181eQFI",
+ "type": "arrow",
+ "x": 1780.888421875,
+ "y": -242.5,
+ "width": 0,
+ "height": 75,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "b03",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1733409147,
+ "version": 8,
+ "versionNonce": 194396213,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "fIvLFQ22G3yUaMY-v9nUg"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 39.5
+ ],
+ [
+ 0,
+ 75
+ ]
+ ],
+ "startBinding": {
+ "elementId": "dECMMSEk_2Eov_teVKh_L",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "KgzLzx8NRG_uZCFnVZKQG",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.06666666666666667
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false
+ },
+ {
+ "id": "fIvLFQ22G3yUaMY-v9nUg",
+ "type": "text",
+ "x": 1712.568483215332,
+ "y": -215.5,
+ "width": 136.63987731933594,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "b04",
+ "roundness": null,
+ "seed": 561173019,
+ "version": 7,
+ "versionNonce": 1343539611,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Merge to Main",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "SR6U_tNP3JLkry181eQFI",
+ "originalText": "Merge to Main",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "9VKmMdNvBd2Hl7rHRpr4L",
+ "type": "arrow",
+ "x": 1780.888421875,
+ "y": -102.5,
+ "width": 0,
+ "height": 45,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "b05",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1965545147,
+ "version": 8,
+ "versionNonce": 2141876629,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 24.5
+ ],
+ [
+ 0,
+ 45
+ ]
+ ],
+ "startBinding": {
+ "elementId": "KgzLzx8NRG_uZCFnVZKQG",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "d96eDkgT9SM_9D05CKOIo",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.06666666666666667
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false
+ },
+ {
+ "id": "avG8IZD-pmZctNOGL1mXx",
+ "type": "arrow",
+ "x": 1780.9010542499998,
+ "y": 18,
+ "width": 0.01749999999992724,
+ "height": 53,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "7uy_BzhNECo_rkg9BnJvR"
+ ],
+ "frameId": null,
+ "index": "b06",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1628653403,
+ "version": 9,
+ "versionNonce": 2074009147,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.012632374999839158,
+ 14
+ ],
+ [
+ -0.012632374999839158,
+ 39
+ ],
+ [
+ 0.004867625000088083,
+ 53
+ ]
+ ],
+ "startBinding": {
+ "elementId": "d96eDkgT9SM_9D05CKOIo",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "1-1g9N63vYl2pO69YIiiX",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "BgI7Sm_x0igEhyveyuEwH",
+ "type": "arrow",
+ "x": 1639.8886718750002,
+ "y": 154.3256972465755,
+ "width": 487.7899986631014,
+ "height": 566.6743027534245,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b07",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1804051451,
+ "version": 12,
+ "versionNonce": 955348725,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "K7tWflTRzSalP_9EIg_2q"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -220.20325000000025,
+ 42.67430275342451
+ ],
+ [
+ -456.28925000000027,
+ 82.67430275342451
+ ],
+ [
+ -456.28925000000027,
+ 122.67430275342451
+ ],
+ [
+ -456.28925000000027,
+ 147.6743027534245
+ ],
+ [
+ -456.28925000000027,
+ 202.6743027534245
+ ],
+ [
+ -456.28925000000027,
+ 272.6743027534245
+ ],
+ [
+ -456.28925000000027,
+ 312.6743027534245
+ ],
+ [
+ -456.28925000000027,
+ 337.6743027534245
+ ],
+ [
+ -456.28925000000027,
+ 407.6743027534245
+ ],
+ [
+ -456.28925000000027,
+ 477.6743027534245
+ ],
+ [
+ -456.28925000000027,
+ 502.6743027534245
+ ],
+ [
+ -456.28925000000027,
+ 527.6743027534246
+ ],
+ [
+ -456.28925000000027,
+ 552.6743027534246
+ ],
+ [
+ -487.7899986631014,
+ 566.6743027534245
+ ]
+ ],
+ "startBinding": {
+ "elementId": "1-1g9N63vYl2pO69YIiiX",
+ "mode": "orbit",
+ "fixedPoint": [
+ -9.615384617343527e-7,
+ 0.7799333333333335
+ ]
+ },
+ "endBinding": {
+ "elementId": "x7O5lfS6Axf3D0Yh0vXbm",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.9034800480769228,
+ -0.018055555555555554
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "K7tWflTRzSalP_9EIg_2q",
+ "type": "text",
+ "x": 1082.329516784668,
+ "y": 454.5,
+ "width": 202.53981018066406,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b08",
+ "roundness": null,
+ "seed": 747072667,
+ "version": 7,
+ "versionNonce": 574447323,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Push Build Artifacts",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "BgI7Sm_x0igEhyveyuEwH",
+ "originalText": "Push Build Artifacts",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "SRPFe2ZcZp2lFORS8DW0S",
+ "type": "arrow",
+ "x": 1780.903121875,
+ "y": 183,
+ "width": 20.230692606609864,
+ "height": 133.00000000000006,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b09",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 398795067,
+ "version": 11,
+ "versionNonce": 837865557,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "xvjODVVC24ToQPV3avCHr"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.014699999999947977,
+ 14
+ ],
+ [
+ -0.014699999999947977,
+ 54
+ ],
+ [
+ -0.014699999999947977,
+ 94
+ ],
+ [
+ -0.014699999999947977,
+ 119
+ ],
+ [
+ -20.230692606609864,
+ 133.00000000000006
+ ]
+ ],
+ "startBinding": {
+ "elementId": "1-1g9N63vYl2pO69YIiiX",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "q7-PxoMjO7tNTXOgo3LTq",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.7423836840822299,
+ -0.037950000000000726
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "xvjODVVC24ToQPV3avCHr",
+ "type": "text",
+ "x": 1714.2184771118164,
+ "y": 244.5002722002182,
+ "width": 133.3398895263672,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0A",
+ "roundness": null,
+ "seed": 111362523,
+ "version": 7,
+ "versionNonce": 1048759163,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Update DAGs",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "SRPFe2ZcZp2lFORS8DW0S",
+ "originalText": "Update DAGs",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "Fd7EZ_U3yc9IRvz7gPLR7",
+ "type": "arrow",
+ "x": 761.114086875,
+ "y": 183,
+ "width": 0.017458333333365772,
+ "height": 323,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0B",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 36982395,
+ "version": 11,
+ "versionNonce": 2021522869,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.014665000000036343,
+ 14
+ ],
+ [
+ -0.014665000000036343,
+ 54
+ ],
+ [
+ -0.014665000000036343,
+ 94
+ ],
+ [
+ -0.014665000000036343,
+ 119
+ ],
+ [
+ -0.014665000000036343,
+ 174
+ ],
+ [
+ -0.014665000000036343,
+ 244
+ ],
+ [
+ -0.014665000000036343,
+ 284
+ ],
+ [
+ -0.014665000000036343,
+ 309
+ ],
+ [
+ 0.0027933333333294286,
+ 323
+ ]
+ ],
+ "startBinding": {
+ "elementId": "RxZ7lNSgMaSJdAPmBlr2v",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "jLMKRAmUupduTdR2bvDOk",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "CIb8WbLDAUiJQJTUcg1qL",
+ "type": "arrow",
+ "x": 761.114086875,
+ "y": 617.9999999999999,
+ "width": 124.00018750000004,
+ "height": 121.75485571757304,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0C",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1295697691,
+ "version": 12,
+ "versionNonce": 1420928027,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.014665000000036343,
+ 14.000000000000114
+ ],
+ [
+ -0.014665000000036343,
+ 39.000000000000114
+ ],
+ [
+ -0.014665000000036343,
+ 64.00000000000011
+ ],
+ [
+ -0.014665000000036343,
+ 89.00000000000011
+ ],
+ [
+ 123.9855225,
+ 121.75485571757304
+ ]
+ ],
+ "startBinding": {
+ "elementId": "jLMKRAmUupduTdR2bvDOk",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "x7O5lfS6Axf3D0Yh0vXbm",
+ "mode": "orbit",
+ "fixedPoint": [
+ -0.014873798076923076,
+ 0.10709999999999885
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "uv5B4vwwXd7W0gUyyE6pr",
+ "type": "arrow",
+ "x": 1121.1140868749999,
+ "y": 183,
+ "width": 473.21893750000004,
+ "height": 152.99819776560184,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0D",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 774450107,
+ "version": 11,
+ "versionNonce": 1136557845,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "UoDEe9H6aksWemTMs2rrg"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.014664999999922657,
+ 14
+ ],
+ [
+ 299.75533500000006,
+ 54
+ ],
+ [
+ 299.75533500000006,
+ 94
+ ],
+ [
+ 299.75533500000006,
+ 119
+ ],
+ [
+ 473.2042725000001,
+ 152.99819776560184
+ ]
+ ],
+ "startBinding": {
+ "elementId": "-do2R4980xFRXHBwEr2mL",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "q7-PxoMjO7tNTXOgo3LTq",
+ "mode": "orbit",
+ "fixedPoint": [
+ -0.020410823108799568,
+ 0.17308333333333317
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "UoDEe9H6aksWemTMs2rrg",
+ "type": "text",
+ "x": 1375.1964661020795,
+ "y": 241.99168368802202,
+ "width": 133.77989196777344,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0E",
+ "roundness": null,
+ "seed": 2032270427,
+ "version": 8,
+ "versionNonce": 1018980539,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Secure Tunnel",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "uv5B4vwwXd7W0gUyyE6pr",
+ "originalText": "Secure Tunnel",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "KOf3-4liEtssdCvcPLk5J",
+ "type": "arrow",
+ "x": 1835.8773628124998,
+ "y": 817.9999999999999,
+ "width": 22.790863605323693,
+ "height": 162.9999999999999,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0F",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1509406971,
+ "version": 12,
+ "versionNonce": 1244124277,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "RnS4_RbzEtlhEsJWsm43p"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.01594093749986314,
+ 29.000000000000114
+ ],
+ [
+ -0.01594093749986314,
+ 69.00000000000011
+ ],
+ [
+ -0.01594093749986314,
+ 109.00000000000011
+ ],
+ [
+ -0.01594093749986314,
+ 134.0000000000001
+ ],
+ [
+ -22.790863605323693,
+ 162.9999999999999
+ ]
+ ],
+ "startBinding": {
+ "elementId": "bqKKeoQ6tFZ8wyZGLo71b",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "YgobDo0D36vcI09LP1XTG",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.6131190330685142,
+ -0.05243333333333264
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "RnS4_RbzEtlhEsJWsm43p",
+ "type": "text",
+ "x": 1786.4914725341796,
+ "y": 894.5002722002182,
+ "width": 98.73989868164062,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0G",
+ "roundness": null,
+ "seed": 1579999643,
+ "version": 8,
+ "versionNonce": 742758747,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Write Raw",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "KOf3-4liEtssdCvcPLk5J",
+ "originalText": "Write Raw",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "bc9oC8enLOZdYYIO7XaLj",
+ "type": "arrow",
+ "x": 1472.5762280078127,
+ "y": 818,
+ "width": 870.5938061328126,
+ "height": 181.1903380562194,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0H",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1056175675,
+ "version": 12,
+ "versionNonce": 1467973077,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "B4Nz60k3UVHeLLMsVQa1G"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.01580613281271326,
+ 29
+ ],
+ [
+ -578.8868061328126,
+ 69
+ ],
+ [
+ -578.8868061328126,
+ 109
+ ],
+ [
+ -578.8868061328126,
+ 134
+ ],
+ [
+ -870.5938061328126,
+ 181.1903380562194
+ ]
+ ],
+ "startBinding": {
+ "elementId": "DP3c-pKkahtaw5YnTp3Ms",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "WZpzKUi1bxJNygFQYc2XZ",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0151884615384619,
+ 0.25923333333333226
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "B4Nz60k3UVHeLLMsVQa1G",
+ "type": "text",
+ "x": 801.9731648062055,
+ "y": 890.7187873080256,
+ "width": 99.31988525390625,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0I",
+ "roundness": null,
+ "seed": 1798272731,
+ "version": 8,
+ "versionNonce": 10466811,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Transform",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "bc9oC8enLOZdYYIO7XaLj",
+ "originalText": "Transform",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "oZuNZRdDJCI1MnxE0_-qd",
+ "type": "arrow",
+ "x": 885.099609375,
+ "y": 814.2455801018519,
+ "width": 519.1171875,
+ "height": 151.75441989814806,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0J",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1366418299,
+ "version": 12,
+ "versionNonce": 584776501,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "LmfELkwUVkmQNrMgfwp0b"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -124.00018750000004,
+ 32.75441989814806
+ ],
+ [
+ -519.1171875,
+ 72.75441989814806
+ ],
+ [
+ -519.1171875,
+ 112.75441989814806
+ ],
+ [
+ -519.1171875,
+ 137.75441989814806
+ ],
+ [
+ -500.11723169498845,
+ 151.75441989814806
+ ]
+ ],
+ "startBinding": {
+ "elementId": "x7O5lfS6Axf3D0Yh0vXbm",
+ "mode": "orbit",
+ "fixedPoint": [
+ -7.211538463007645e-7,
+ 0.8815555555555546
+ ]
+ },
+ "endBinding": {
+ "elementId": "WZpzKUi1bxJNygFQYc2XZ",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.25272307692307683,
+ -0.02636666666666719
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "LmfELkwUVkmQNrMgfwp0b",
+ "type": "text",
+ "x": 309.70722593351957,
+ "y": 891.4332032926832,
+ "width": 55.89994812011719,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0K",
+ "roundness": null,
+ "seed": 1778236443,
+ "version": 7,
+ "versionNonce": 1221410459,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Query",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "oZuNZRdDJCI1MnxE0_-qd",
+ "originalText": "Query",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "OZAo9G-34-QIWNm5RTCqh",
+ "type": "arrow",
+ "x": 1152.099421875,
+ "y": 833.0000000000001,
+ "width": 44.524000000000115,
+ "height": 147.9999999999999,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0L",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 12943547,
+ "version": 12,
+ "versionNonce": 1688194197,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "LXDIMKGyP2FJKCJ-Ix1rh"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 31.5,
+ 13.999999999999886
+ ],
+ [
+ 44.524000000000115,
+ 53.999999999999886
+ ],
+ [
+ 44.524000000000115,
+ 93.99999999999989
+ ],
+ [
+ 44.524000000000115,
+ 118.99999999999989
+ ],
+ [
+ 3.3171985781739295,
+ 147.9999999999999
+ ]
+ ],
+ "startBinding": {
+ "elementId": "x7O5lfS6Axf3D0Yh0vXbm",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.8894223557692307,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "eWZrcNs5rX193KU0Iu1Fd",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.6920720544004186,
+ -0.03836666666666512
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "LXDIMKGyP2FJKCJ-Ix1rh",
+ "type": "text",
+ "x": 1169.0626654695304,
+ "y": 894.4848794383797,
+ "width": 56.81993103027344,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0M",
+ "roundness": null,
+ "seed": 1064022363,
+ "version": 7,
+ "versionNonce": 260092731,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "State",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "OZAo9G-34-QIWNm5RTCqh",
+ "originalText": "State",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "06w_o5h5FVHA5gGGB0m8Z",
+ "type": "arrow",
+ "x": 90.48218187500001,
+ "y": 833,
+ "width": 1.999760000000009,
+ "height": 133.0000000000001,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0N",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 2000866811,
+ "version": 12,
+ "versionNonce": 746811893,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "XwxYvv2KaZ62vwwgvzF_O"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -1.999760000000009,
+ 14
+ ],
+ [
+ -1.999760000000009,
+ 54
+ ],
+ [
+ -1.999760000000009,
+ 94
+ ],
+ [
+ -1.999760000000009,
+ 119
+ ],
+ [
+ -1.9824266666666688,
+ 133.0000000000001
+ ]
+ ],
+ "startBinding": {
+ "elementId": "6YOF55j7emdZ0ii6Lvxbs",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.475273076923077,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "Tv3jBXWdJ2LCPLo0dXdN4",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "XwxYvv2KaZ62vwwgvzF_O",
+ "type": "text",
+ "x": 43.242469787597656,
+ "y": 894.5002722002182,
+ "width": 90.47990417480469,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0O",
+ "roundness": null,
+ "seed": 726488731,
+ "version": 7,
+ "versionNonce": 1696371675,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Snapshot",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "06w_o5h5FVHA5gGGB0m8Z",
+ "originalText": "Snapshot",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "0cumOGwXKxvipCjq9XlNm",
+ "type": "arrow",
+ "x": 239.482421875,
+ "y": 800.7768806279527,
+ "width": 1415.3515625,
+ "height": 203.52807951932482,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0P",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1513999163,
+ "version": 12,
+ "versionNonce": 2005625685,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "5wD_h3QtCSp7MBqcz9Rac"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 274.11699999999996,
+ 46.223119372047336
+ ],
+ [
+ 1042.75,
+ 86.22311937204734
+ ],
+ [
+ 1042.75,
+ 126.22311937204734
+ ],
+ [
+ 1042.75,
+ 151.22311937204734
+ ],
+ [
+ 1415.3515625,
+ 203.52807951932482
+ ]
+ ],
+ "startBinding": {
+ "elementId": "6YOF55j7emdZ0ii6Lvxbs",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1,
+ 0.7435777777777781
+ ]
+ },
+ "endBinding": {
+ "elementId": "YgobDo0D36vcI09LP1XTG",
+ "mode": "orbit",
+ "fixedPoint": [
+ -0.01721599782712081,
+ 0.22154999999999822
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "5wD_h3QtCSp7MBqcz9Rac",
+ "type": "text",
+ "x": 1293.2057814416087,
+ "y": 890.2732036188463,
+ "width": 90.47990417480469,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0Q",
+ "roundness": null,
+ "seed": 141994971,
+ "version": 7,
+ "versionNonce": 699621499,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Snapshot",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "0cumOGwXKxvipCjq9XlNm",
+ "originalText": "Snapshot",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "vlfDPtP1dWYqdhw3VXDYY",
+ "type": "arrow",
+ "x": 239.482421875,
+ "y": 814.0635383317313,
+ "width": 801.4375475507384,
+ "height": 166.93646166826886,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0R",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 168458363,
+ "version": 12,
+ "versionNonce": 101529781,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "3ndu5tnHr-mmb6cVs_Qrx"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 125.29700000000003,
+ 32.93646166826875
+ ],
+ [
+ 761.6600000000001,
+ 72.93646166826875
+ ],
+ [
+ 761.6600000000001,
+ 112.93646166826875
+ ],
+ [
+ 761.6600000000001,
+ 137.93646166826875
+ ],
+ [
+ 801.4375475507384,
+ 166.93646166826886
+ ]
+ ],
+ "startBinding": {
+ "elementId": "6YOF55j7emdZ0ii6Lvxbs",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1,
+ 0.8796888888888892
+ ]
+ },
+ "endBinding": {
+ "elementId": "eWZrcNs5rX193KU0Iu1Fd",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.3142778867529754,
+ -0.039266666666666575
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "3ndu5tnHr-mmb6cVs_Qrx",
+ "type": "text",
+ "x": 1002.2420799282754,
+ "y": 890.573740888387,
+ "width": 90.47990417480469,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0S",
+ "roundness": null,
+ "seed": 213627163,
+ "version": 8,
+ "versionNonce": 386373915,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Snapshot",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "vlfDPtP1dWYqdhw3VXDYY",
+ "originalText": "Snapshot",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "Xo94Lx1y13BSjq9HSL2KU",
+ "type": "arrow",
+ "x": -41.23192782529742,
+ "y": 827.1540018641743,
+ "width": 159.28565029970255,
+ "height": 154.56001652472764,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0T",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1643959739,
+ "version": 11,
+ "versionNonce": 1907251733,
+ "isDeleted": true,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "XYcQixMrwPVXoQ8jLWR0O"
+ }
+ ],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -55.28565029970258,
+ 19.845998135825653
+ ],
+ [
+ -55.28565029970258,
+ 59.84599813582565
+ ],
+ [
+ -55.28565029970258,
+ 99.84599813582565
+ ],
+ [
+ -55.28565029970258,
+ 124.84599813582565
+ ],
+ [
+ -159.28565029970255,
+ 154.56001652472764
+ ]
+ ],
+ "startBinding": {
+ "elementId": "6YOF55j7emdZ0ii6Lvxbs",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.0178576923076922,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "vsObzYnPHjgw0Xflc0D_C",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0147923076923078,
+ 0.07508888888888932
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "XYcQixMrwPVXoQ8jLWR0O",
+ "type": "text",
+ "x": -129.24755096435547,
+ "y": 894.5002722002182,
+ "width": 65.45994567871094,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0U",
+ "roundness": null,
+ "seed": 149972571,
+ "version": 7,
+ "versionNonce": 176930235,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "text": "Upload",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "Xo94Lx1y13BSjq9HSL2KU",
+ "originalText": "Upload",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "HhRiqbdkTzqXO_eACD8rQ",
+ "type": "arrow",
+ "x": 1780.183596875,
+ "y": 398,
+ "width": 55.695095833333426,
+ "height": 108,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0V",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 2020139771,
+ "version": 12,
+ "versionNonce": 56905589,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 55.677824999999984,
+ 29
+ ],
+ [
+ 55.677824999999984,
+ 69
+ ],
+ [
+ 55.677824999999984,
+ 94
+ ],
+ [
+ 55.695095833333426,
+ 108
+ ]
+ ],
+ "startBinding": {
+ "elementId": "q7-PxoMjO7tNTXOgo3LTq",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.7995244982530261,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "upfyt-t4jXUxce3rBCbyU",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "t5duvO1BqBOFslnl4TDip",
+ "type": "arrow",
+ "x": 1835.8759293750002,
+ "y": 617.9999999999999,
+ "width": 0.01771215277790361,
+ "height": 118.00000000000023,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b0W",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 686345115,
+ "version": 12,
+ "versionNonce": 258100827,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351398651,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.014507500000263462,
+ 14.000000000000114
+ ],
+ [
+ -0.014507500000263462,
+ 39.000000000000114
+ ],
+ [
+ -0.014507500000263462,
+ 64.00000000000011
+ ],
+ [
+ -0.014507500000263462,
+ 89.00000000000011
+ ],
+ [
+ 0.003204652777640149,
+ 118.00000000000023
+ ]
+ ],
+ "startBinding": {
+ "elementId": "upfyt-t4jXUxce3rBCbyU",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "bqKKeoQ6tFZ8wyZGLo71b",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.06666666666666667
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "1PGEbXXofrMpfohrxVVio",
+ "type": "rectangle",
+ "x": 625.6015625000009,
+ "y": -115,
+ "width": 640,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "21khyDd6zs-B995JCoP_u"
+ ],
+ "frameId": null,
+ "index": "b0X",
+ "roundness": null,
+ "seed": 10626011,
+ "version": 47,
+ "versionNonce": 776371157,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "yFCWMWw94pxxPfLKc9WUl",
+ "type": "text",
+ "x": 873.0816421508798,
+ "y": -110,
+ "width": 145.0398406982422,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "21khyDd6zs-B995JCoP_u"
+ ],
+ "frameId": null,
+ "index": "b0Y",
+ "roundness": null,
+ "seed": 1577513083,
+ "version": 48,
+ "versionNonce": 474978299,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Access Control",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "1PGEbXXofrMpfohrxVVio",
+ "originalText": "Access Control",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "gHF5MAPJS8DGf3prtDkAt",
+ "type": "rectangle",
+ "x": 970.6015625000009,
+ "y": -90,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "21khyDd6zs-B995JCoP_u"
+ ],
+ "frameId": null,
+ "index": "b0Z",
+ "roundness": null,
+ "seed": 443099419,
+ "version": 51,
+ "versionNonce": 1142044981,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "CzUCzk62tf9lsmBaxmogo",
+ "type": "text",
+ "x": 990.0416641235361,
+ "y": -57.5,
+ "width": 221.1197967529297,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "21khyDd6zs-B995JCoP_u"
+ ],
+ "frameId": null,
+ "index": "b0a",
+ "roundness": null,
+ "seed": 1262177723,
+ "version": 48,
+ "versionNonce": 1748033691,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Web Browser (HTTPS)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "gHF5MAPJS8DGf3prtDkAt",
+ "originalText": "Web Browser (HTTPS)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "OLVY01XALh-ISGYmXbeZ3",
+ "type": "rectangle",
+ "x": 660.6015625000009,
+ "y": -90,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "21khyDd6zs-B995JCoP_u"
+ ],
+ "frameId": null,
+ "index": "b0b",
+ "roundness": null,
+ "seed": 866115163,
+ "version": 51,
+ "versionNonce": 406801045,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "D4wg7arfW0AlG2d9leZNN",
+ "type": "text",
+ "x": 670.1416778564462,
+ "y": -57.5,
+ "width": 240.91976928710938,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "21khyDd6zs-B995JCoP_u"
+ ],
+ "frameId": null,
+ "index": "b0c",
+ "roundness": null,
+ "seed": 241785595,
+ "version": 48,
+ "versionNonce": 102765883,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Data Analyst (Superset)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "OLVY01XALh-ISGYmXbeZ3",
+ "originalText": "Data Analyst (Superset)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "9ZJv2kcWKZwsI2gLOGaAT",
+ "type": "rectangle",
+ "x": -523.8906249999991,
+ "y": 810,
+ "width": 330,
+ "height": 165,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "m4gpQ4MNk8kJAEv6NnGo4"
+ ],
+ "frameId": null,
+ "index": "b0d",
+ "roundness": null,
+ "seed": 404374427,
+ "version": 47,
+ "versionNonce": 2072195061,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "bpMfF4swd4wSNqjIzv5uu",
+ "type": "text",
+ "x": -479.2104949951163,
+ "y": 815,
+ "width": 240.63973999023438,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "m4gpQ4MNk8kJAEv6NnGo4"
+ ],
+ "frameId": null,
+ "index": "b0e",
+ "roundness": null,
+ "seed": 1491408955,
+ "version": 48,
+ "versionNonce": 1434432987,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Off-site Backup Storage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "9ZJv2kcWKZwsI2gLOGaAT",
+ "originalText": "Off-site Backup Storage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "ZCnr6-9V1DRwhiV-hAb6A",
+ "type": "rectangle",
+ "x": -488.8906249999991,
+ "y": 860,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "m4gpQ4MNk8kJAEv6NnGo4"
+ ],
+ "frameId": null,
+ "index": "b0f",
+ "roundness": null,
+ "seed": 783046875,
+ "version": 51,
+ "versionNonce": 199453013,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "dJCAuNLip8J1z3Cq7Dkxp",
+ "type": "text",
+ "x": -464.050521850585,
+ "y": 880,
+ "width": 210.31979370117188,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "m4gpQ4MNk8kJAEv6NnGo4"
+ ],
+ "frameId": null,
+ "index": "b0g",
+ "roundness": null,
+ "seed": 386041211,
+ "version": 48,
+ "versionNonce": 627196539,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "S3 / Hetzner Storage\nBox",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "ZCnr6-9V1DRwhiV-hAb6A",
+ "originalText": "S3 / Hetzner Storage Box",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "Vll2Uql6ufMdawSJE7h3O",
+ "type": "rectangle",
+ "x": -173.8906249999991,
+ "y": 75,
+ "width": 2323.28125,
+ "height": 1060,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0h",
+ "roundness": null,
+ "seed": 959061531,
+ "version": 173,
+ "versionNonce": 179664565,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "kRfQnSKHGwDvRfiXwTsAo",
+ "type": "text",
+ "x": 850.2601318359384,
+ "y": 80,
+ "width": 274.979736328125,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0i",
+ "roundness": null,
+ "seed": 806724283,
+ "version": 174,
+ "versionNonce": 1049246491,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Hetzner Server (8TB NVME)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "Vll2Uql6ufMdawSJE7h3O",
+ "originalText": "Hetzner Server (8TB NVME)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "iDLM6TGlwqQi85LO0ydj9",
+ "type": "rectangle",
+ "x": -153.8906249999991,
+ "y": 560,
+ "width": 731.125,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "iUr5TGEA3efE9J9ETIf62",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0j",
+ "roundness": null,
+ "seed": 342332251,
+ "version": 173,
+ "versionNonce": 1923012629,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "JD5s1diR-Yzei1XIHxsBi",
+ "type": "text",
+ "x": 114.93196105957122,
+ "y": 565,
+ "width": 193.47982788085938,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "iUr5TGEA3efE9J9ETIf62",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0k",
+ "roundness": null,
+ "seed": 1181904891,
+ "version": 174,
+ "versionNonce": 761929659,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Backup Management",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "iDLM6TGlwqQi85LO0ydj9",
+ "originalText": "Backup Management",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "Sl1-E2MiJM6KXbc6q3FXg",
+ "type": "rectangle",
+ "x": 96.10937500000091,
+ "y": 585,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "iUr5TGEA3efE9J9ETIf62",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0l",
+ "roundness": null,
+ "seed": 2016983195,
+ "version": 177,
+ "versionNonce": 1301613941,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "s4TnORFnug3Mr3VLiwVs4",
+ "type": "text",
+ "x": 118.7794647216806,
+ "y": 617.5,
+ "width": 214.65982055664062,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "iUr5TGEA3efE9J9ETIf62",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0m",
+ "roundness": null,
+ "seed": 2003627323,
+ "version": 174,
+ "versionNonce": 1277456475,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Scheduled Backup Job",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "Sl1-E2MiJM6KXbc6q3FXg",
+ "originalText": "Scheduled Backup Job",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "FPRLaPkTyLvLg9YsBxPtO",
+ "type": "rectangle",
+ "x": 1231.156250000001,
+ "y": 100,
+ "width": 898.234375,
+ "height": 600,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0n",
+ "roundness": null,
+ "seed": 930188763,
+ "version": 173,
+ "versionNonce": 1256036053,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "cMlBKBXebFv7y4ZQRNvZy",
+ "type": "text",
+ "x": 1535.6135864257822,
+ "y": 105,
+ "width": 289.3197021484375,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0o",
+ "roundness": null,
+ "seed": 458824315,
+ "version": 174,
+ "versionNonce": 210480379,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Data & Transformation Layer",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "FPRLaPkTyLvLg9YsBxPtO",
+ "originalText": "Data & Transformation Layer",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "tEw1r7vLh1D7UDA28ljTs",
+ "type": "rectangle",
+ "x": 1496.585937500001,
+ "y": 140,
+ "width": 192.296875,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0p",
+ "roundness": null,
+ "seed": 2145784603,
+ "version": 175,
+ "versionNonce": 353236021,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "GT8Y_xkREJfQ5f69ezuYF",
+ "type": "text",
+ "x": 1521.0944442749033,
+ "y": 157.5,
+ "width": 143.2798614501953,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0q",
+ "roundness": null,
+ "seed": 92993467,
+ "version": 174,
+ "versionNonce": 35804571,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Apache Airflow",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "tEw1r7vLh1D7UDA28ljTs",
+ "originalText": "Apache Airflow",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "Hl9NQqt1q_SIUaoWuUrnt",
+ "type": "rectangle",
+ "x": 1266.156250000001,
+ "y": 585,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0r",
+ "roundness": null,
+ "seed": 443172955,
+ "version": 175,
+ "versionNonce": 1745593749,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "gkYpX_ssQqlg9JfxNlVOW",
+ "type": "text",
+ "x": 1307.6463546752939,
+ "y": 605,
+ "width": 177.01979064941406,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0s",
+ "roundness": null,
+ "seed": 1146520827,
+ "version": 174,
+ "versionNonce": 739961403,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "SQLMesh\n(Transformations)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "Hl9NQqt1q_SIUaoWuUrnt",
+ "originalText": "SQLMesh (Transformations)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "RTc_23izLlfdhgiy28yZ9",
+ "type": "rectangle",
+ "x": 1576.156250000001,
+ "y": 600,
+ "width": 220.8125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0t",
+ "roundness": null,
+ "seed": 718417307,
+ "version": 175,
+ "versionNonce": 1728850677,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "C1d-XgQ2-keSwC5S4aPAI",
+ "type": "text",
+ "x": 1598.3425979614267,
+ "y": 617.5,
+ "width": 176.43980407714844,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0u",
+ "roundness": null,
+ "seed": 1628422715,
+ "version": 174,
+ "versionNonce": 2136468187,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Ingestion Workers",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "RTc_23izLlfdhgiy28yZ9",
+ "originalText": "Ingestion Workers",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "uVPoPsCdpBGafcYS2dfH_",
+ "type": "arrow",
+ "x": 1487.414257302722,
+ "y": 206.06691127273706,
+ "width": 87.13342031106868,
+ "height": 367.93308872726294,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0v",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1878115035,
+ "version": 182,
+ "versionNonce": 848626773,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -71.04398731700599,
+ 20.453854740567124
+ ],
+ [
+ -71.04398731700599,
+ 45.453854740567124
+ ],
+ [
+ -71.04398731700599,
+ 85.45385474056712
+ ],
+ [
+ -71.04398731700599,
+ 125.45385474056712
+ ],
+ [
+ -71.04398731700599,
+ 150.45385474056712
+ ],
+ [
+ -71.04398731700599,
+ 220.45385474056712
+ ],
+ [
+ -71.04398731700599,
+ 290.4538547405671
+ ],
+ [
+ -71.04398731700599,
+ 315.4538547405671
+ ],
+ [
+ -71.04398731700599,
+ 340.4538547405671
+ ],
+ [
+ -87.13342031106868,
+ 367.93308872726294
+ ]
+ ],
+ "startBinding": {
+ "elementId": "tEw1r7vLh1D7UDA28ljTs",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.06188575607377891,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "Hl9NQqt1q_SIUaoWuUrnt",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "JfG_RqxjVknbHwc6NdD9b",
+ "type": "rectangle",
+ "x": 1521.562500000001,
+ "y": 370,
+ "width": 587.828125,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "MDtMNbYVUN6y5YlAYZ8fs",
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0w",
+ "roundness": null,
+ "seed": 537571195,
+ "version": 173,
+ "versionNonce": 812373883,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "KaGsRmyKpWsm1oMmuo1V2",
+ "type": "text",
+ "x": 1738.916648864747,
+ "y": 375,
+ "width": 153.1198272705078,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "MDtMNbYVUN6y5YlAYZ8fs",
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0x",
+ "roundness": null,
+ "seed": 60622875,
+ "version": 174,
+ "versionNonce": 1048293813,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Execution Logic",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "JfG_RqxjVknbHwc6NdD9b",
+ "originalText": "Execution Logic",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "nJYcgDZNkbgtrOcdVTvlg",
+ "type": "rectangle",
+ "x": 1556.562500000001,
+ "y": 395,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "MDtMNbYVUN6y5YlAYZ8fs",
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0y",
+ "roundness": null,
+ "seed": 1083919547,
+ "version": 175,
+ "versionNonce": 1033449499,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "RPbCSuKmC9r0ULzugO5p1",
+ "type": "text",
+ "x": 1581.382614135743,
+ "y": 415,
+ "width": 210.35977172851562,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "MDtMNbYVUN6y5YlAYZ8fs",
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b0z",
+ "roundness": null,
+ "seed": 447216987,
+ "version": 174,
+ "versionNonce": 1743106837,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Continuous Simulation\nLoop",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "nJYcgDZNkbgtrOcdVTvlg",
+ "originalText": "Continuous Simulation Loop",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "6wsHVJ1dh4wuS1nV5ahYo",
+ "type": "rectangle",
+ "x": 1866.562500000001,
+ "y": 410,
+ "width": 207.828125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "MDtMNbYVUN6y5YlAYZ8fs",
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b10",
+ "roundness": null,
+ "seed": 1024825851,
+ "version": 173,
+ "versionNonce": 953316539,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "pZYKNaVp--eSaPZSPEv5R",
+ "type": "text",
+ "x": 1895.7266235351572,
+ "y": 427.5,
+ "width": 149.4998779296875,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "MDtMNbYVUN6y5YlAYZ8fs",
+ "0Gs33K1QgIJ6YfHkw0O7m",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b11",
+ "roundness": null,
+ "seed": 1155965595,
+ "version": 174,
+ "versionNonce": 1263044725,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "SQLMesh DAGs",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "6wsHVJ1dh4wuS1nV5ahYo",
+ "originalText": "SQLMesh DAGs",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "Tfa5XC5XbcUC0qPLWD45L",
+ "type": "rectangle",
+ "x": 597.2343750000009,
+ "y": 345,
+ "width": 613.921875,
+ "height": 355,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "QXg2QEzsTqtRt0WUNk6h_",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b12",
+ "roundness": null,
+ "seed": 181245755,
+ "version": 173,
+ "versionNonce": 1371153755,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "jM9QVVIVoOK88ljRJUlNm",
+ "type": "text",
+ "x": 825.1753921508798,
+ "y": 350,
+ "width": 158.0398406982422,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "QXg2QEzsTqtRt0WUNk6h_",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b13",
+ "roundness": null,
+ "seed": 757921755,
+ "version": 174,
+ "versionNonce": 1516876245,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Application layer",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "Tfa5XC5XbcUC0qPLWD45L",
+ "originalText": "Application layer",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "eqAwqCVsmyu7GArHeNLLf",
+ "type": "rectangle",
+ "x": 942.2343750000009,
+ "y": 410,
+ "width": 207.84375,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "QXg2QEzsTqtRt0WUNk6h_",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b14",
+ "roundness": null,
+ "seed": 1511474299,
+ "version": 176,
+ "versionNonce": 530760187,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "9tCJhZhmFQTf7rXKeo6fn",
+ "type": "text",
+ "x": 967.4863204956064,
+ "y": 427.5,
+ "width": 157.33985900878906,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "QXg2QEzsTqtRt0WUNk6h_",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b15",
+ "roundness": null,
+ "seed": 1498348827,
+ "version": 174,
+ "versionNonce": 845066037,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Async Flask App",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "eqAwqCVsmyu7GArHeNLLf",
+ "originalText": "Async Flask App",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "HDwIGNMAQtVtgXbWU9_67",
+ "type": "rectangle",
+ "x": 916.1562500000009,
+ "y": 585,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#fbc02d",
+ "backgroundColor": "#fff9c4",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "QXg2QEzsTqtRt0WUNk6h_",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b16",
+ "roundness": null,
+ "seed": 1447469499,
+ "version": 175,
+ "versionNonce": 730778267,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "JOnOtvdc_1X30TPvTm5Hb",
+ "type": "text",
+ "x": 954.9563217163095,
+ "y": 605,
+ "width": 182.3998565673828,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#fbc02d",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "QXg2QEzsTqtRt0WUNk6h_",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b17",
+ "roundness": null,
+ "seed": 1780527707,
+ "version": 174,
+ "versionNonce": 831324309,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Embedded DuckDB\nEngine",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "HDwIGNMAQtVtgXbWU9_67",
+ "originalText": "Embedded DuckDB Engine",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "W4KZfi9HzzsgGW8Z3dDpJ",
+ "type": "rectangle",
+ "x": 632.2343750000009,
+ "y": 395,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "QXg2QEzsTqtRt0WUNk6h_",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b18",
+ "roundness": null,
+ "seed": 1706012411,
+ "version": 176,
+ "versionNonce": 976273211,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "MrzrVvSuCdQR8sbsYSMA_",
+ "type": "text",
+ "x": 659.9044647216806,
+ "y": 415,
+ "width": 204.65982055664062,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "QXg2QEzsTqtRt0WUNk6h_",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b19",
+ "roundness": null,
+ "seed": 1534465947,
+ "version": 174,
+ "versionNonce": 1302996469,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Apache Superset (BI\nTool)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "W4KZfi9HzzsgGW8Z3dDpJ",
+ "originalText": "Apache Superset (BI Tool)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "k37n4GW3dro90SxDljX_B",
+ "type": "arrow",
+ "x": 1046.1564021833892,
+ "y": 481,
+ "width": 0.03404420572883282,
+ "height": 93,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "QXg2QEzsTqtRt0WUNk6h_",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1A",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1772514363,
+ "version": 180,
+ "versionNonce": 1441472475,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.015005230262886471,
+ 8.000000000000057
+ ],
+ [
+ -0.015005230262886471,
+ 33.00000000000006
+ ],
+ [
+ -0.015005230262886471,
+ 58.00000000000006
+ ],
+ [
+ 0.01903897546594635,
+ 93
+ ]
+ ],
+ "startBinding": {
+ "elementId": "eqAwqCVsmyu7GArHeNLLf",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "HDwIGNMAQtVtgXbWU9_67",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "M-idiRbqx8nKNnKeJ70Ms",
+ "type": "rectangle",
+ "x": 688.1015625000009,
+ "y": 100,
+ "width": 505,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "91UE9EfcRHHxibyoQv7Ql",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1B",
+ "roundness": null,
+ "seed": 1143155931,
+ "version": 173,
+ "versionNonce": 700161877,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "p3fUAMRBU0cWUjKff33CP",
+ "type": "text",
+ "x": 874.2116241455087,
+ "y": 105,
+ "width": 132.77987670898438,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "91UE9EfcRHHxibyoQv7Ql",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1C",
+ "roundness": null,
+ "seed": 2122242427,
+ "version": 174,
+ "versionNonce": 416312443,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Ingress Layer",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "M-idiRbqx8nKNnKeJ70Ms",
+ "originalText": "Ingress Layer",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "VvzWo59cHTLI1WVBbEz4R",
+ "type": "rectangle",
+ "x": 866.9765625000009,
+ "y": 125,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "91UE9EfcRHHxibyoQv7Ql",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1D",
+ "roundness": null,
+ "seed": 368833051,
+ "version": 177,
+ "versionNonce": 1813441717,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "J1BHLjvfZ4uA7Kkib41yy",
+ "type": "text",
+ "x": 886.3666610717783,
+ "y": 145,
+ "width": 221.2198028564453,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "91UE9EfcRHHxibyoQv7Ql",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1E",
+ "roundness": null,
+ "seed": 999093947,
+ "version": 174,
+ "versionNonce": 916661531,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Caddy / Nginx Reverse\nProxy",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "VvzWo59cHTLI1WVBbEz4R",
+ "originalText": "Caddy / Nginx Reverse Proxy",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "HgBZJ36UzaZGiUjrvkEFk",
+ "type": "rectangle",
+ "x": -93.89062499999909,
+ "y": 835,
+ "width": 1872.953125,
+ "height": 275,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1F",
+ "roundness": null,
+ "seed": 1574201179,
+ "version": 173,
+ "versionNonce": 1415679509,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "Dm2CIJftqAunBVwHl-5dS",
+ "type": "text",
+ "x": 650.6961059570322,
+ "y": 840,
+ "width": 383.7796630859375,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1G",
+ "roundness": null,
+ "seed": 1931789307,
+ "version": 174,
+ "versionNonce": 1188415931,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "High-Speed Storage Layer (Local NVME)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "HgBZJ36UzaZGiUjrvkEFk",
+ "originalText": "High-Speed Storage Layer (Local NVME)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "sjI9LufMg8qgQ-ZFDqy5E",
+ "type": "rectangle",
+ "x": 284.6718750000009,
+ "y": 1025,
+ "width": 235.625,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#b71c1c",
+ "backgroundColor": "#ffcdd2",
+ "fillStyle": "solid",
+ "strokeWidth": 3,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1H",
+ "roundness": null,
+ "seed": 58756251,
+ "version": 176,
+ "versionNonce": 294716277,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "qqNS4wbm6uGK96gPKgotu",
+ "type": "text",
+ "x": 306.8244628906259,
+ "y": 1042.5,
+ "width": 191.31982421875,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#b71c1c",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1I",
+ "roundness": null,
+ "seed": 1922711867,
+ "version": 174,
+ "versionNonce": 1317722715,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "8TB NVME Storage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "sjI9LufMg8qgQ-ZFDqy5E",
+ "originalText": "8TB NVME Storage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "4SHKxEQvx4jsZnhI1Lyo4",
+ "type": "rectangle",
+ "x": 916.1562500000009,
+ "y": 860,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1J",
+ "roundness": null,
+ "seed": 164913627,
+ "version": 179,
+ "versionNonce": 1475005653,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "ZP5sr22bUs7lHqi3AJs4X",
+ "type": "text",
+ "x": 943.5763473510751,
+ "y": 880,
+ "width": 205.15980529785156,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1K",
+ "roundness": null,
+ "seed": 1111584379,
+ "version": 174,
+ "versionNonce": 177526523,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Parquet / Data Lake\nFiles",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "4SHKxEQvx4jsZnhI1Lyo4",
+ "originalText": "Parquet / Data Lake Files",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "yzXetlXzuCDxVnX3z_yj0",
+ "type": "rectangle",
+ "x": 251.1093750000009,
+ "y": 860,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1L",
+ "roundness": null,
+ "seed": 1319364379,
+ "version": 175,
+ "versionNonce": 923036213,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "AO-5Sn_BLfeXWRWOugyse",
+ "type": "text",
+ "x": 277.4194869995126,
+ "y": 880,
+ "width": 207.37977600097656,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1M",
+ "roundness": null,
+ "seed": 1701727163,
+ "version": 174,
+ "versionNonce": 2037792667,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "App SQLite/Postgres\nFiles",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "yzXetlXzuCDxVnX3z_yj0",
+ "originalText": "App SQLite/Postgres Files",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "m0uhNVer-plR87rS-Br7l",
+ "type": "rectangle",
+ "x": -58.89062499999909,
+ "y": 860,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1N",
+ "roundness": null,
+ "seed": 1254300763,
+ "version": 175,
+ "versionNonce": 801332117,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "CKASS1Bm-bb_PCmj0BgQf",
+ "type": "text",
+ "x": -13.980537414549872,
+ "y": 880,
+ "width": 170.17982482910156,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1O",
+ "roundness": null,
+ "seed": 443865339,
+ "version": 174,
+ "versionNonce": 627151931,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Airflow Metadata\nStorage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "m0uhNVer-plR87rS-Br7l",
+ "originalText": "Airflow Metadata Storage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "OmXqdG9S1YYrOp_R3Emri",
+ "type": "arrow",
+ "x": 1044.696246250001,
+ "y": 961,
+ "width": 513.84501,
+ "height": 89.48976319240478,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1P",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1376125339,
+ "version": 180,
+ "versionNonce": 173875445,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0.9456387499999437,
+ -7
+ ],
+ [
+ 0.9456387499999437,
+ 18
+ ],
+ [
+ -512.8993712500001,
+ 82.48976319240478
+ ]
+ ],
+ "startBinding": {
+ "elementId": "4SHKxEQvx4jsZnhI1Lyo4",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "sjI9LufMg8qgQ-ZFDqy5E",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0000021220159157,
+ 0.33221666666666655
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "5U7wEmUU20PUqSvzHDd_L",
+ "type": "arrow",
+ "x": 382.39883500000064,
+ "y": 961,
+ "width": 6.92292000000009,
+ "height": 59.49999999999977,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1Q",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 447288891,
+ "version": 180,
+ "versionNonce": 775509211,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.8040199999998094,
+ -6.999999999999886
+ ],
+ [
+ -0.8040199999998094,
+ 18.000000000000114
+ ],
+ [
+ 6.118900000000281,
+ 52.499999999999886
+ ]
+ ],
+ "startBinding": {
+ "elementId": "yzXetlXzuCDxVnX3z_yj0",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "sjI9LufMg8qgQ-ZFDqy5E",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.4505188328912467,
+ 0
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "LwtjCoQtPV6P8rdSgAHKP",
+ "type": "arrow",
+ "x": 72.39883500000064,
+ "y": 961,
+ "width": 201.57706000000007,
+ "height": 78.39942286160942,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1je_iFSnV_ARX90Fzus0p",
+ "UKcAXDeF__94tlIatka3T"
+ ],
+ "frameId": null,
+ "index": "b1R",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1396741851,
+ "version": 180,
+ "versionNonce": 1817655893,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.8040199999998094,
+ -6.999999999999886
+ ],
+ [
+ -0.8040199999998094,
+ 18.000000000000114
+ ],
+ [
+ 200.77304000000026,
+ 71.39942286160954
+ ]
+ ],
+ "startBinding": {
+ "elementId": "m0uhNVer-plR87rS-Br7l",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "sjI9LufMg8qgQ-ZFDqy5E",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.0000021220159150691844,
+ 0.17409999999999853
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "1yKZEnnGr7yzcDnzqiCtO",
+ "type": "rectangle",
+ "x": -523.8906249999991,
+ "y": -390,
+ "width": 330,
+ "height": 655,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1S",
+ "roundness": null,
+ "seed": 1516176251,
+ "version": 47,
+ "versionNonce": 328204667,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "hb4ThmxR5N-Zj0b8-J2La",
+ "type": "text",
+ "x": -474.7505187988272,
+ "y": -385,
+ "width": 231.71978759765625,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1T",
+ "roundness": null,
+ "seed": 407297051,
+ "version": 48,
+ "versionNonce": 780609461,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "CI/CD Pipeline (GitLab)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "1yKZEnnGr7yzcDnzqiCtO",
+ "originalText": "CI/CD Pipeline (GitLab)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "xnEP347xxjmv8gpN6v2b4",
+ "type": "rectangle",
+ "x": -468.9296874999991,
+ "y": -365,
+ "width": 220.078125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1U",
+ "roundness": null,
+ "seed": 1223336123,
+ "version": 48,
+ "versionNonce": 1051204123,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "mIqSB2-6tMeOZyYzozLi4",
+ "type": "text",
+ "x": -448.32052612304597,
+ "y": -347.5,
+ "width": 178.85980224609375,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1V",
+ "roundness": null,
+ "seed": 99406171,
+ "version": 48,
+ "versionNonce": 1930586389,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "GitLab Repository",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "xnEP347xxjmv8gpN6v2b4",
+ "originalText": "GitLab Repository",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "DCHxPdXrciqmyBSORfanC",
+ "type": "rectangle",
+ "x": -453.9296874999991,
+ "y": -225,
+ "width": 190.078125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1W",
+ "roundness": null,
+ "seed": 278916603,
+ "version": 49,
+ "versionNonce": 1282678459,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "lLxqRouLbRh1DR0deJRqW",
+ "type": "text",
+ "x": -428.2505569457999,
+ "y": -207.5,
+ "width": 138.71986389160156,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1X",
+ "roundness": null,
+ "seed": 1543927451,
+ "version": 48,
+ "versionNonce": 2070838901,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "GitLab Runner",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "DCHxPdXrciqmyBSORfanC",
+ "originalText": "GitLab Runner",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "etVqX6fnGlaqOKnmXosMF",
+ "type": "rectangle",
+ "x": -470.4296874999991,
+ "y": -75,
+ "width": 223.078125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1Y",
+ "roundness": null,
+ "seed": 1456663355,
+ "version": 49,
+ "versionNonce": 395743067,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "DQ3vLw15bqSOsMOtGkh4T",
+ "type": "text",
+ "x": -454.43053436279206,
+ "y": -57.5,
+ "width": 191.07981872558594,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1Z",
+ "roundness": null,
+ "seed": 1969736667,
+ "version": 48,
+ "versionNonce": 1046538197,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Build & Test Stage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "etVqX6fnGlaqOKnmXosMF",
+ "originalText": "Build & Test Stage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "XH0bAidT5-RWTMFxH6-Pa",
+ "type": "rectangle",
+ "x": -488.8906249999991,
+ "y": 125,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1a",
+ "roundness": null,
+ "seed": 2077726843,
+ "version": 53,
+ "versionNonce": 39971835,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "JrYNqDq7v1Uq5yBtKG8-i",
+ "type": "text",
+ "x": -479.1105194091788,
+ "y": 157.5,
+ "width": 240.43978881835938,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1b",
+ "roundness": null,
+ "seed": 132436251,
+ "version": 48,
+ "versionNonce": 1040131381,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Deploy Stage (SSH/SCP)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "XH0bAidT5-RWTMFxH6-Pa",
+ "originalText": "Deploy Stage (SSH/SCP)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "lnorsBCdQbhWAqEbRAdav",
+ "type": "arrow",
+ "x": -358.87682349046526,
+ "y": -294,
+ "width": 0.016146421370933695,
+ "height": 57.99999999999997,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1c",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1526855099,
+ "version": 51,
+ "versionNonce": 14202011,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.013801509533834633,
+ 18.5
+ ],
+ [
+ 0.002344911837099062,
+ 57.99999999999997
+ ]
+ ],
+ "startBinding": {
+ "elementId": "xnEP347xxjmv8gpN6v2b4",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "DCHxPdXrciqmyBSORfanC",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.06666666666666667
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "apC-5ilc3PR_XbjqvomVu",
+ "type": "text",
+ "x": -427.21056365966706,
+ "y": -288,
+ "width": 136.63987731933594,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1d",
+ "roundness": null,
+ "seed": 1683064411,
+ "version": 49,
+ "versionNonce": 497989269,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Merge to Main",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "lnorsBCdQbhWAqEbRAdav",
+ "originalText": "Merge to Main",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "H9TG_nIyOyMk75HHwYSwC",
+ "type": "arrow",
+ "x": -358.88603690732674,
+ "y": -154,
+ "width": 0.01894964717740777,
+ "height": 67.99999999999999,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1e",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 178651899,
+ "version": 51,
+ "versionNonce": 1655531835,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.0045880926723498305,
+ 3.5
+ ],
+ [
+ -0.0045880926723498305,
+ 28.5
+ ],
+ [
+ 0.014361554505057939,
+ 67.99999999999999
+ ]
+ ],
+ "startBinding": {
+ "elementId": "DCHxPdXrciqmyBSORfanC",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "etVqX6fnGlaqOKnmXosMF",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.06666666666666667
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "SsOwlIaeR73Qe0Xj1DRas",
+ "type": "arrow",
+ "x": -358.89059564761425,
+ "y": -4,
+ "width": 0.03514430338540109,
+ "height": 117.99999999999999,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "CZNXn4uEAZEHRVA8sRpeI"
+ ],
+ "frameId": null,
+ "index": "b1f",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 914484123,
+ "version": 54,
+ "versionNonce": 2015697909,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.016202516447343385,
+ 7.999999999999943
+ ],
+ [
+ -0.016202516447343385,
+ 32.99999999999994
+ ],
+ [
+ -0.016202516447343385,
+ 57.99999999999994
+ ],
+ [
+ -0.016202516447343385,
+ 82.99999999999994
+ ],
+ [
+ 0.018941786938057703,
+ 117.99999999999999
+ ]
+ ],
+ "startBinding": {
+ "elementId": "etVqX6fnGlaqOKnmXosMF",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "XH0bAidT5-RWTMFxH6-Pa",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "7_LeRndDLaXGCotpnS6Yz",
+ "type": "arrow",
+ "x": 1686.2729305345404,
+ "y": 671,
+ "width": 499.11668053453946,
+ "height": 218.2959085516269,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1g",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 471318587,
+ "version": 301,
+ "versionNonce": 1564641755,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.22665506578960049,
+ 8.000000000000114
+ ],
+ [
+ -0.22665506578960049,
+ 63.000000000000114
+ ],
+ [
+ -0.22665506578960049,
+ 118.00000000000011
+ ],
+ [
+ -0.22665506578960049,
+ 143.0000000000001
+ ],
+ [
+ -499.11668053453946,
+ 218.2959085516269
+ ]
+ ],
+ "startBinding": {
+ "elementId": "RTc_23izLlfdhgiy28yZ9",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "4SHKxEQvx4jsZnhI1Lyo4",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0152927884615381,
+ 0.3372888888888888
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "lMhpaLXaq8X0b3MKN7NcW",
+ "type": "text",
+ "x": 1634.9563249072273,
+ "y": 749.0033006462036,
+ "width": 102.17990112304688,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1h",
+ "roundness": null,
+ "seed": 1162477787,
+ "version": 11,
+ "versionNonce": 1969739093,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Store Raw",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "7_LeRndDLaXGCotpnS6Yz",
+ "originalText": "Store Raw",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "xOTDimrPRt0w-Djblq52s",
+ "type": "arrow",
+ "x": 1394.6962462500007,
+ "y": 686,
+ "width": 208.485635,
+ "height": 197.10751317400604,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1i",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1537944955,
+ "version": 301,
+ "versionNonce": 1437243003,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0.9456387500001711,
+ -7
+ ],
+ [
+ 0.9456387500001711,
+ 48
+ ],
+ [
+ 0.9456387500001711,
+ 103
+ ],
+ [
+ 0.9456387500001711,
+ 128
+ ],
+ [
+ -207.53999624999983,
+ 190.10751317400604
+ ]
+ ],
+ "startBinding": {
+ "elementId": "Hl9NQqt1q_SIUaoWuUrnt",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "4SHKxEQvx4jsZnhI1Lyo4",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0150850961538465,
+ 0.20239999999999883
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "D2wIFCKDKSTSXXl2neXGc",
+ "type": "text",
+ "x": 1313.0419704492197,
+ "y": 749.0033006462036,
+ "width": 165.1998291015625,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1j",
+ "roundness": null,
+ "seed": 847103515,
+ "version": 10,
+ "versionNonce": 550265525,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Transform/Model",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "xOTDimrPRt0w-Djblq52s",
+ "originalText": "Transform/Model",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "JuizRFv146n1jj_9HJ13n",
+ "type": "arrow",
+ "x": 1046.0712462500007,
+ "y": 685.9999999999999,
+ "width": 0.1042762500005665,
+ "height": 170.0000000000001,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1k",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 280251067,
+ "version": 301,
+ "versionNonce": 1789398811,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0.07063875000017106,
+ -7
+ ],
+ [
+ 0.07063875000017106,
+ 48
+ ],
+ [
+ 0.07063875000017106,
+ 103
+ ],
+ [
+ 0.07063875000017106,
+ 128
+ ],
+ [
+ 0.1042762500005665,
+ 163.0000000000001
+ ]
+ ],
+ "startBinding": {
+ "elementId": "HDwIGNMAQtVtgXbWU9_67",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "4SHKxEQvx4jsZnhI1Lyo4",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "IZyRtD2T-vlS2MoH9T5bS",
+ "type": "text",
+ "x": 963.4219600732431,
+ "y": 736.5033006462035,
+ "width": 165.43984985351562,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1l",
+ "roundness": null,
+ "seed": 988887899,
+ "version": 16,
+ "versionNonce": 2130199573,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "High-Speed OLAP\nQuery",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "JuizRFv146n1jj_9HJ13n",
+ "originalText": "High-Speed OLAP Query",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "jgeKakQ-FhFA7le9aby22",
+ "type": "arrow",
+ "x": 763.5238350000005,
+ "y": 496,
+ "width": 142.43643499999996,
+ "height": 380.2316276102862,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1m",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1032263675,
+ "version": 301,
+ "versionNonce": 1051554747,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.8040199999996958,
+ -6.999999999999886
+ ],
+ [
+ -0.8040199999996958,
+ 18.000000000000114
+ ],
+ [
+ -0.8040199999996958,
+ 43.000000000000114
+ ],
+ [
+ -0.8040199999996958,
+ 113.00000000000011
+ ],
+ [
+ -0.8040199999996958,
+ 183.0000000000001
+ ],
+ [
+ -0.8040199999996958,
+ 238.0000000000001
+ ],
+ [
+ -0.8040199999996958,
+ 293.0000000000001
+ ],
+ [
+ -0.8040199999996958,
+ 318.0000000000001
+ ],
+ [
+ 141.63241500000026,
+ 373.2316276102863
+ ]
+ ],
+ "startBinding": {
+ "elementId": "W4KZfi9HzzsgGW8Z3dDpJ",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "4SHKxEQvx4jsZnhI1Lyo4",
+ "mode": "orbit",
+ "fixedPoint": [
+ -0.014937980769230728,
+ 0.13323333333333318
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "rCoIBdku9AAhsIBPrPHqW",
+ "type": "text",
+ "x": 661.6999022802743,
+ "y": 619.006865194555,
+ "width": 202.03982543945312,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1n",
+ "roundness": null,
+ "seed": 1987600539,
+ "version": 16,
+ "versionNonce": 1675688309,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Connect via\nDuckDB/SQLAlchemy",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "jgeKakQ-FhFA7le9aby22",
+ "originalText": "Connect via DuckDB/SQLAlchemy",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "zUTthRidjHaEpXEpIiL52",
+ "type": "arrow",
+ "x": 1099.140218125001,
+ "y": 11,
+ "width": 26.53679589131889,
+ "height": 110.00000000000006,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1o",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1601672507,
+ "version": 178,
+ "versionNonce": 31278171,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0.9464918749999924,
+ -7.000000000000057
+ ],
+ [
+ 0.9464918749999924,
+ 17.999999999999943
+ ],
+ [
+ 0.9464918749999924,
+ 42.99999999999994
+ ],
+ [
+ 0.9464918749999924,
+ 67.99999999999994
+ ],
+ [
+ -25.590304016318896,
+ 103
+ ]
+ ],
+ "startBinding": {
+ "elementId": "gHF5MAPJS8DGf3prtDkAt",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "VvzWo59cHTLI1WVBbEz4R",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.7689646634615385,
+ -0.02487777777777814
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "-EQLsJfmVJj3cXukR4srR",
+ "type": "arrow",
+ "x": 791.8902181250008,
+ "y": 11,
+ "width": 64.88994703989215,
+ "height": 120.99922959750259,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1p",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 401028571,
+ "version": 178,
+ "versionNonce": 147587797,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.8035081249998939,
+ -7.000000000000057
+ ],
+ [
+ -0.8035081249998939,
+ 17.999999999999943
+ ],
+ [
+ -0.8035081249998939,
+ 42.99999999999994
+ ],
+ [
+ -0.8035081249998939,
+ 67.99999999999994
+ ],
+ [
+ 64.08643891489226,
+ 113.99922959750253
+ ]
+ ],
+ "startBinding": {
+ "elementId": "OLVY01XALh-ISGYmXbeZ3",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "VvzWo59cHTLI1WVBbEz4R",
+ "mode": "orbit",
+ "fixedPoint": [
+ -0.014569951923077112,
+ -0.004211111111111323
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "X07AfHAEot6hXxIBStQ3B",
+ "type": "arrow",
+ "x": 1119.2112350000011,
+ "y": 226,
+ "width": 45.65611621561834,
+ "height": 180,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1q",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 786023035,
+ "version": 301,
+ "versionNonce": 1007288571,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -35.39382000000023,
+ -7
+ ],
+ [
+ -35.39382000000023,
+ 18
+ ],
+ [
+ -35.39382000000023,
+ 58
+ ],
+ [
+ -35.39382000000023,
+ 98
+ ],
+ [
+ -35.39382000000023,
+ 123
+ ],
+ [
+ -45.65611621561834,
+ 173
+ ]
+ ],
+ "startBinding": {
+ "elementId": "VvzWo59cHTLI1WVBbEz4R",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.7562146634615382,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "eqAwqCVsmyu7GArHeNLLf",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.6240793865584123,
+ -0.05261666666666732
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "mPyoe174skMIFaZYDk-Jk",
+ "type": "arrow",
+ "x": 856.8717356822731,
+ "y": 219.33954113033408,
+ "width": 59.422867542250174,
+ "height": 164.66045886966592,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1r",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 756136731,
+ "version": 302,
+ "versionNonce": 1649336373,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -38.503709224031354,
+ 10.560109035279964
+ ],
+ [
+ -38.503709224031354,
+ 35.560109035279964
+ ],
+ [
+ -38.503709224031354,
+ 75.56010903527996
+ ],
+ [
+ -38.503709224031354,
+ 115.56010903527996
+ ],
+ [
+ -38.503709224031354,
+ 140.56010903527996
+ ],
+ [
+ -59.422867542250174,
+ 164.66045886966592
+ ]
+ ],
+ "startBinding": {
+ "elementId": "VvzWo59cHTLI1WVBbEz4R",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.02197235576923049,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "W4KZfi9HzzsgGW8Z3dDpJ",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.6102115384615383,
+ -0.038255555555555376
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "Y8djwcKkdjx-VYu2kRqRY",
+ "type": "arrow",
+ "x": -271.03340499999877,
+ "y": 226,
+ "width": 1286.0627720588236,
+ "height": 180.00000000000003,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1s",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1593941947,
+ "version": 183,
+ "versionNonce": 1454778779,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -26.250140000000357,
+ -7.000000000000028
+ ],
+ [
+ -26.250140000000357,
+ 17.99999999999997
+ ],
+ [
+ 1203.2418599999996,
+ 57.99999999999997
+ ],
+ [
+ 1203.2418599999996,
+ 97.99999999999997
+ ],
+ [
+ 1203.2418599999996,
+ 122.99999999999997
+ ],
+ [
+ 1259.8126320588233,
+ 173
+ ]
+ ],
+ "startBinding": {
+ "elementId": "XH0bAidT5-RWTMFxH6-Pa",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.6792576923076922,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "eqAwqCVsmyu7GArHeNLLf",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.27158382198165637,
+ -0.03746666666666745
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "qRy_Y8A-0O7US6BRfGgBm",
+ "type": "text",
+ "x": 872.4085053540048,
+ "y": 271.5,
+ "width": 119.59989929199219,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1t",
+ "roundness": null,
+ "seed": 1590423643,
+ "version": 10,
+ "versionNonce": 911151509,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Deploy Code",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "Y8djwcKkdjx-VYu2kRqRY",
+ "originalText": "Deploy Code",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "ZI3ndv4_T9vqc1JXF3s0f",
+ "type": "arrow",
+ "x": -432.06896499999925,
+ "y": 226,
+ "width": 1149.7206279821464,
+ "height": 165.00000000000006,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1u",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1581460731,
+ "version": 183,
+ "versionNonce": 1729379899,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 20.99958000000018,
+ -7
+ ],
+ [
+ 20.99958000000018,
+ 18
+ ],
+ [
+ 1142.1245800000002,
+ 58
+ ],
+ [
+ 1142.1245800000002,
+ 98
+ ],
+ [
+ 1142.1245800000002,
+ 123
+ ],
+ [
+ 1149.7206279821464,
+ 158.00000000000006
+ ]
+ ],
+ "startBinding": {
+ "elementId": "XH0bAidT5-RWTMFxH6-Pa",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.34546538461538473,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "W4KZfi9HzzsgGW8Z3dDpJ",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.3352192307692305,
+ -0.03315555555555597
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "_CnwxnM6DXlVh2xUL4nK1",
+ "type": "text",
+ "x": 643.4556775610362,
+ "y": 271.5,
+ "width": 133.1998748779297,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1v",
+ "roundness": null,
+ "seed": 820630939,
+ "version": 10,
+ "versionNonce": 1912739573,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Deploy Config",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "ZI3ndv4_T9vqc1JXF3s0f",
+ "originalText": "Deploy Config",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "zTOyj566q5f1Hc2raqW-J",
+ "type": "arrow",
+ "x": 86.40325082882555,
+ "y": 680.1694702463827,
+ "width": 20.275900000000235,
+ "height": 169.9999999999999,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1w",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 368208443,
+ "version": 301,
+ "versionNonce": 939966171,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 9.063204171175585,
+ -1.1694702463827298
+ ],
+ [
+ 9.063204171175585,
+ 53.83052975361727
+ ],
+ [
+ 9.063204171175585,
+ 108.83052975361727
+ ],
+ [
+ 9.063204171175585,
+ 133.83052975361727
+ ],
+ [
+ -11.21269582882465,
+ 168.83052975361716
+ ]
+ ],
+ "startBinding": {
+ "elementId": "Sl1-E2MiJM6KXbc6q3FXg",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.1167576923076922,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "m0uhNVer-plR87rS-Br7l",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "I2SCs4XxlJW09CxbKFcq5",
+ "type": "text",
+ "x": 56.90650321777457,
+ "y": 749.0033006462036,
+ "width": 77.11990356445312,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1x",
+ "roundness": null,
+ "seed": 1111452379,
+ "version": 10,
+ "versionNonce": 1072525397,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Extract",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "zTOyj566q5f1Hc2raqW-J",
+ "originalText": "Extract",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "us5pb9H5D6d2kDzPUTEZM",
+ "type": "arrow",
+ "x": 367.10937500000085,
+ "y": 662.809527942705,
+ "width": 538.046875,
+ "height": 223.17205240833755,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1y",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 711153531,
+ "version": 301,
+ "versionNonce": 337652603,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 148.25000000000017,
+ 33.02643340963914
+ ],
+ [
+ 148.25000000000017,
+ 88.02643340963914
+ ],
+ [
+ 148.25000000000017,
+ 143.02643340963914
+ ],
+ [
+ 148.25000000000017,
+ 168.02643340963914
+ ],
+ [
+ 538.046875,
+ 223.17205240833755
+ ]
+ ],
+ "startBinding": {
+ "elementId": "Sl1-E2MiJM6KXbc6q3FXg",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1,
+ 0.8373222222222214
+ ]
+ },
+ "endBinding": {
+ "elementId": "4SHKxEQvx4jsZnhI1Lyo4",
+ "mode": "orbit",
+ "fixedPoint": [
+ -0.015245673076922756,
+ 0.2997444444444454
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "_ALtjNKcDdwW8ot0l-_5J",
+ "type": "text",
+ "x": 476.79942321777446,
+ "y": 765.8392619985477,
+ "width": 77.11990356445312,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b1z",
+ "roundness": null,
+ "seed": 211857435,
+ "version": 10,
+ "versionNonce": 1575394741,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Extract",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "us5pb9H5D6d2kDzPUTEZM",
+ "originalText": "Extract",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "mQDlflWRIQSY1AOj_bEKJ",
+ "type": "arrow",
+ "x": 365.81549917117775,
+ "y": 680.1694702463822,
+ "width": 20.319233333333386,
+ "height": 170.0000000000001,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b20",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 988411067,
+ "version": 301,
+ "versionNonce": 1336083483,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -9.063204171176949,
+ -1.1694702463821613
+ ],
+ [
+ -9.063204171176949,
+ 53.83052975361784
+ ],
+ [
+ -9.063204171176949,
+ 108.83052975361784
+ ],
+ [
+ -9.063204171176949,
+ 133.83052975361784
+ ],
+ [
+ 11.256029162156437,
+ 168.83052975361795
+ ]
+ ],
+ "startBinding": {
+ "elementId": "Sl1-E2MiJM6KXbc6q3FXg",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.8832423076923078,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "yzXetlXzuCDxVnX3z_yj0",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "8qLbNrKGjGuw-0xoirqjL",
+ "type": "text",
+ "x": 318.1923432177743,
+ "y": 749.0033006462036,
+ "width": 77.11990356445312,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b21",
+ "roundness": null,
+ "seed": 618767707,
+ "version": 10,
+ "versionNonce": 856891157,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Extract",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "mQDlflWRIQSY1AOj_bEKJ",
+ "originalText": "Extract",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "eFFDnsnFCo0Az7u8h6znG",
+ "type": "arrow",
+ "x": 85.10937500000091,
+ "y": 658.9530751200714,
+ "width": 303,
+ "height": 205.72852339785175,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b22",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 567951867,
+ "version": 180,
+ "versionNonce": 310495419,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -188.5,
+ 37.495650921222364
+ ],
+ [
+ -188.5,
+ 92.49565092122236
+ ],
+ [
+ -188.5,
+ 147.49565092122236
+ ],
+ [
+ -188.5,
+ 172.49565092122236
+ ],
+ [
+ -303,
+ 205.72852339785175
+ ]
+ ],
+ "startBinding": {
+ "elementId": "Sl1-E2MiJM6KXbc6q3FXg",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0,
+ 0.79738888888889
+ ]
+ },
+ "endBinding": {
+ "elementId": "ZCnr6-9V1DRwhiV-hAb6A",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0147923076923078,
+ 0.07508888888888932
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "tfYSEyP8nKyEE3qcbXjqh",
+ "type": "text",
+ "x": -136.12059783935456,
+ "y": 766.4520266874973,
+ "width": 65.45994567871094,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b23",
+ "roundness": null,
+ "seed": 2060864155,
+ "version": 10,
+ "versionNonce": 635991157,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "text": "Upload",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "eFFDnsnFCo0Az7u8h6znG",
+ "originalText": "Upload",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "Qo6IFAHZZMrEo1JpXjIl7",
+ "type": "arrow",
+ "x": 1655.4509855263166,
+ "y": 211,
+ "width": 28.675760307017526,
+ "height": 173,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b24",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 881344315,
+ "version": 301,
+ "versionNonce": 1650391387,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 16.36698947368427,
+ 8
+ ],
+ [
+ 16.36698947368427,
+ 33
+ ],
+ [
+ 16.36698947368427,
+ 73
+ ],
+ [
+ 16.36698947368427,
+ 113
+ ],
+ [
+ 16.36698947368427,
+ 138
+ ],
+ [
+ 28.675760307017526,
+ 173
+ ]
+ ],
+ "startBinding": {
+ "elementId": "tEw1r7vLh1D7UDA28ljTs",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.7091141626716502,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "nJYcgDZNkbgtrOcdVTvlg",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "KZUjpCBzMAlM7UKHQlRTv",
+ "type": "arrow",
+ "x": 1686.4764237499992,
+ "y": 496.00000000000006,
+ "width": 0.10363375000156339,
+ "height": 99.99999999999989,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b25",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 424845275,
+ "version": 301,
+ "versionNonce": 841752021,
+ "isDeleted": true,
+ "boundElements": [],
+ "updated": 1769351389244,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0.07132125000111955,
+ -7.000000000000057
+ ],
+ [
+ 0.07132125000111955,
+ 17.999999999999943
+ ],
+ [
+ 0.07132125000111955,
+ 42.99999999999994
+ ],
+ [
+ 0.10363375000156339,
+ 92.99999999999983
+ ]
+ ],
+ "startBinding": {
+ "elementId": "nJYcgDZNkbgtrOcdVTvlg",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "RTc_23izLlfdhgiy28yZ9",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.06666666666666667
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "iG9DjxImkr_2mQV1VrjyY",
+ "type": "rectangle",
+ "x": 625.6015625000009,
+ "y": 65,
+ "width": 640,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0M6D8xQQZSDl9ioCnl_e_"
+ ],
+ "frameId": null,
+ "index": "b26",
+ "roundness": null,
+ "seed": 130646011,
+ "version": 5,
+ "versionNonce": 2085962907,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "N6XZUU6E8k1QRjZd6QsxM"
+ }
+ ],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "N6XZUU6E8k1QRjZd6QsxM",
+ "type": "text",
+ "x": 873.0816421508798,
+ "y": 70,
+ "width": 145.0398406982422,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0M6D8xQQZSDl9ioCnl_e_"
+ ],
+ "frameId": null,
+ "index": "b27",
+ "roundness": null,
+ "seed": 472762523,
+ "version": 6,
+ "versionNonce": 302196373,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Access Control",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "iG9DjxImkr_2mQV1VrjyY",
+ "originalText": "Access Control",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "JZc6TwK4afoz1Q8G9hmZz",
+ "type": "rectangle",
+ "x": 970.6015625000009,
+ "y": 90,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0M6D8xQQZSDl9ioCnl_e_"
+ ],
+ "frameId": null,
+ "index": "b28",
+ "roundness": null,
+ "seed": 2051013947,
+ "version": 6,
+ "versionNonce": 1612183867,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "5d7igm3sl9qjgLzDWRyv5"
+ },
+ {
+ "id": "FvqjkJI32AlK6xSAtF1Ox",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "5d7igm3sl9qjgLzDWRyv5",
+ "type": "text",
+ "x": 990.0416641235361,
+ "y": 122.5,
+ "width": 221.1197967529297,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0M6D8xQQZSDl9ioCnl_e_"
+ ],
+ "frameId": null,
+ "index": "b29",
+ "roundness": null,
+ "seed": 224566747,
+ "version": 6,
+ "versionNonce": 1215007733,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Web Browser (HTTPS)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "JZc6TwK4afoz1Q8G9hmZz",
+ "originalText": "Web Browser (HTTPS)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "Ans_j8zJjaZYHj0H6LOiv",
+ "type": "rectangle",
+ "x": 660.6015625000009,
+ "y": 90,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0M6D8xQQZSDl9ioCnl_e_"
+ ],
+ "frameId": null,
+ "index": "b2A",
+ "roundness": null,
+ "seed": 816327291,
+ "version": 6,
+ "versionNonce": 1859852763,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "3HgHerB1zWrATQv2jh1eZ"
+ },
+ {
+ "id": "-8XBhAcC0mxjw5vEmDD1M",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "3HgHerB1zWrATQv2jh1eZ",
+ "type": "text",
+ "x": 670.1416778564462,
+ "y": 122.5,
+ "width": 240.91976928710938,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "0M6D8xQQZSDl9ioCnl_e_"
+ ],
+ "frameId": null,
+ "index": "b2B",
+ "roundness": null,
+ "seed": 953361179,
+ "version": 6,
+ "versionNonce": 1398818133,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Data Analyst (Superset)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "Ans_j8zJjaZYHj0H6LOiv",
+ "originalText": "Data Analyst (Superset)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "dZ-DYnK9wUWD8Sm-hiUoQ",
+ "type": "rectangle",
+ "x": -523.8906249999991,
+ "y": 990,
+ "width": 330,
+ "height": 165,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "ZEdWuV5rTsGzrt5LfgR8h"
+ ],
+ "frameId": null,
+ "index": "b2C",
+ "roundness": null,
+ "seed": 1045825467,
+ "version": 5,
+ "versionNonce": 1169237627,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "Oo717i2XQJHbh6na5StzN"
+ }
+ ],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "Oo717i2XQJHbh6na5StzN",
+ "type": "text",
+ "x": -479.2104949951163,
+ "y": 995,
+ "width": 240.63973999023438,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "ZEdWuV5rTsGzrt5LfgR8h"
+ ],
+ "frameId": null,
+ "index": "b2D",
+ "roundness": null,
+ "seed": 659773531,
+ "version": 6,
+ "versionNonce": 104256181,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Off-site Backup Storage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "dZ-DYnK9wUWD8Sm-hiUoQ",
+ "originalText": "Off-site Backup Storage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "9Pi0-xMU6XTiWEE7I1jjY",
+ "type": "rectangle",
+ "x": -488.8906249999991,
+ "y": 1040,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "ZEdWuV5rTsGzrt5LfgR8h"
+ ],
+ "frameId": null,
+ "index": "b2E",
+ "roundness": null,
+ "seed": 1906152699,
+ "version": 6,
+ "versionNonce": 995925787,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "VuQ3UXHURzKks80n8mX-z"
+ },
+ {
+ "id": "5SdaBJB97VVqvmOlIojdR",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "VuQ3UXHURzKks80n8mX-z",
+ "type": "text",
+ "x": -464.050521850585,
+ "y": 1060,
+ "width": 210.31979370117188,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "ZEdWuV5rTsGzrt5LfgR8h"
+ ],
+ "frameId": null,
+ "index": "b2F",
+ "roundness": null,
+ "seed": 1018641819,
+ "version": 6,
+ "versionNonce": 764720149,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "S3 / Hetzner Storage\nBox",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "9Pi0-xMU6XTiWEE7I1jjY",
+ "originalText": "S3 / Hetzner Storage Box",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "yhY57ngMbg-zy6YVEXY6p",
+ "type": "rectangle",
+ "x": -169.8906249999991,
+ "y": 259,
+ "width": 2323.28125,
+ "height": 1060,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2G",
+ "roundness": null,
+ "seed": 332583483,
+ "version": 32,
+ "versionNonce": 888218037,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "xgxzGGPHVCfPFpaBE4eOc"
+ }
+ ],
+ "updated": 1769351501904,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "xgxzGGPHVCfPFpaBE4eOc",
+ "type": "text",
+ "x": 854.2601318359384,
+ "y": 264,
+ "width": 274.979736328125,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2H",
+ "roundness": null,
+ "seed": 2010305243,
+ "version": 33,
+ "versionNonce": 1311580949,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501904,
+ "link": null,
+ "locked": false,
+ "text": "Hetzner Server (8TB NVME)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "yhY57ngMbg-zy6YVEXY6p",
+ "originalText": "Hetzner Server (8TB NVME)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "_U9sSDdGXaKClytz5vL9j",
+ "type": "rectangle",
+ "x": -149.8906249999991,
+ "y": 744,
+ "width": 731.125,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "8-83k-joX4prnH0BtLH6u",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2I",
+ "roundness": null,
+ "seed": 692699003,
+ "version": 32,
+ "versionNonce": 1461844085,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "Kwx5fr8wLpKYg2Y-jtzg8"
+ }
+ ],
+ "updated": 1769351501904,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "Kwx5fr8wLpKYg2Y-jtzg8",
+ "type": "text",
+ "x": 118.93196105957122,
+ "y": 749,
+ "width": 193.47982788085938,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "8-83k-joX4prnH0BtLH6u",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2J",
+ "roundness": null,
+ "seed": 846862363,
+ "version": 33,
+ "versionNonce": 160768469,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501904,
+ "link": null,
+ "locked": false,
+ "text": "Backup Management",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "_U9sSDdGXaKClytz5vL9j",
+ "originalText": "Backup Management",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "FUzNq2S_STMju3bDxx27W",
+ "type": "rectangle",
+ "x": 100.10937500000091,
+ "y": 769,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "8-83k-joX4prnH0BtLH6u",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2K",
+ "roundness": null,
+ "seed": 827743419,
+ "version": 36,
+ "versionNonce": 1251745589,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "y4LT46jUAyZoRD7D1MYG6"
+ },
+ {
+ "id": "UGIcpJcAgmEii0Pq01qK_",
+ "type": "arrow"
+ },
+ {
+ "id": "4rOpYk_bcwr7XB4jKp1WI",
+ "type": "arrow"
+ },
+ {
+ "id": "sllCN0NKZUeWtTZ0WDK1F",
+ "type": "arrow"
+ },
+ {
+ "id": "5SdaBJB97VVqvmOlIojdR",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501904,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "y4LT46jUAyZoRD7D1MYG6",
+ "type": "text",
+ "x": 122.7794647216806,
+ "y": 801.5,
+ "width": 214.65982055664062,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "8-83k-joX4prnH0BtLH6u",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2L",
+ "roundness": null,
+ "seed": 1635847515,
+ "version": 33,
+ "versionNonce": 1083994261,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501904,
+ "link": null,
+ "locked": false,
+ "text": "Scheduled Backup Job",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "FUzNq2S_STMju3bDxx27W",
+ "originalText": "Scheduled Backup Job",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "ZHTfASd5wGfN-DUXsxrLl",
+ "type": "rectangle",
+ "x": 1235.156250000001,
+ "y": 284,
+ "width": 898.234375,
+ "height": 600,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2M",
+ "roundness": null,
+ "seed": 1716300283,
+ "version": 32,
+ "versionNonce": 419066741,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "DW9vJTCS-ZMEgsgNQJr-m"
+ }
+ ],
+ "updated": 1769351501905,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "DW9vJTCS-ZMEgsgNQJr-m",
+ "type": "text",
+ "x": 1539.6135864257822,
+ "y": 289,
+ "width": 289.3197021484375,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2N",
+ "roundness": null,
+ "seed": 1421587099,
+ "version": 33,
+ "versionNonce": 279330005,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501905,
+ "link": null,
+ "locked": false,
+ "text": "Data & Transformation Layer",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "ZHTfASd5wGfN-DUXsxrLl",
+ "originalText": "Data & Transformation Layer",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "lEcxDZoezHID6yvTA8cjB",
+ "type": "rectangle",
+ "x": 1500.585937500001,
+ "y": 324,
+ "width": 192.296875,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2O",
+ "roundness": null,
+ "seed": 2105583419,
+ "version": 34,
+ "versionNonce": 651287093,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "gifnikKhcqe44Tfbfm5Tk"
+ },
+ {
+ "id": "1eagBKgwG9iGsuvoC-osz",
+ "type": "arrow"
+ },
+ {
+ "id": "y0YvZmM6Y3DeP-WFje7h0",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501905,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "gifnikKhcqe44Tfbfm5Tk",
+ "type": "text",
+ "x": 1525.0944442749033,
+ "y": 341.5,
+ "width": 143.2798614501953,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2P",
+ "roundness": null,
+ "seed": 1996359643,
+ "version": 33,
+ "versionNonce": 610454421,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501905,
+ "link": null,
+ "locked": false,
+ "text": "Apache Airflow",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "lEcxDZoezHID6yvTA8cjB",
+ "originalText": "Apache Airflow",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "lVGqkdZA8ANLHOnrDEKs_",
+ "type": "rectangle",
+ "x": 1270.156250000001,
+ "y": 769,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2Q",
+ "roundness": null,
+ "seed": 1732662395,
+ "version": 34,
+ "versionNonce": 1943710293,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "XfWrWS9-Py5wfDbPuIJ47"
+ },
+ {
+ "id": "IUHWYFqoaS-pPp83ZC70D",
+ "type": "arrow"
+ },
+ {
+ "id": "1eagBKgwG9iGsuvoC-osz",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501905,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "XfWrWS9-Py5wfDbPuIJ47",
+ "type": "text",
+ "x": 1311.6463546752939,
+ "y": 789,
+ "width": 177.01979064941406,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2R",
+ "roundness": null,
+ "seed": 236719387,
+ "version": 33,
+ "versionNonce": 1411159989,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501905,
+ "link": null,
+ "locked": false,
+ "text": "SQLMesh\n(Transformations)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "lVGqkdZA8ANLHOnrDEKs_",
+ "originalText": "SQLMesh (Transformations)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "ZHw1u2IpKs2-2VRWu8-AA",
+ "type": "rectangle",
+ "x": 1580.156250000001,
+ "y": 784,
+ "width": 220.8125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2S",
+ "roundness": null,
+ "seed": 250720699,
+ "version": 34,
+ "versionNonce": 1852305013,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "X72W6dykK3c3HQciyswGP"
+ },
+ {
+ "id": "PzHkTk14OSi29fzOpxwDu",
+ "type": "arrow"
+ },
+ {
+ "id": "lBVMIhvBLIb1hqdCcsgaV",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "X72W6dykK3c3HQciyswGP",
+ "type": "text",
+ "x": 1602.3425979614267,
+ "y": 801.5,
+ "width": 176.43980407714844,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2T",
+ "roundness": null,
+ "seed": 2062139995,
+ "version": 33,
+ "versionNonce": 1890342869,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false,
+ "text": "Ingestion Workers",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "ZHw1u2IpKs2-2VRWu8-AA",
+ "originalText": "Ingestion Workers",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "1eagBKgwG9iGsuvoC-osz",
+ "type": "arrow",
+ "x": 1512.4863750000009,
+ "y": 384.5,
+ "width": 112.32999999999993,
+ "height": 380,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2U",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 450281211,
+ "version": 34,
+ "versionNonce": 719752181,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -112.32999999999993,
+ 39.5
+ ],
+ [
+ -112.32999999999993,
+ 64.5
+ ],
+ [
+ -112.32999999999993,
+ 104.5
+ ],
+ [
+ -112.32999999999993,
+ 144.5
+ ],
+ [
+ -112.32999999999993,
+ 169.5
+ ],
+ [
+ -112.32999999999993,
+ 239.5
+ ],
+ [
+ -112.32999999999993,
+ 309.5
+ ],
+ [
+ -112.32999999999993,
+ 334.5
+ ],
+ [
+ -112.32999999999993,
+ 359.5
+ ],
+ [
+ -112.32999999999993,
+ 380
+ ]
+ ],
+ "startBinding": {
+ "elementId": "lEcxDZoezHID6yvTA8cjB",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.06188575607377891,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "lVGqkdZA8ANLHOnrDEKs_",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false
+ },
+ {
+ "id": "ll-9KlBiVFAVfr9B_KCHm",
+ "type": "rectangle",
+ "x": 1525.562500000001,
+ "y": 554,
+ "width": 587.828125,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1xPcZymIZaO03548Mke5X",
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2V",
+ "roundness": null,
+ "seed": 2033919899,
+ "version": 32,
+ "versionNonce": 779830613,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "RMyqKGvJwuRyGgqHl-ZEn"
+ }
+ ],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "RMyqKGvJwuRyGgqHl-ZEn",
+ "type": "text",
+ "x": 1742.916648864747,
+ "y": 559,
+ "width": 153.1198272705078,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1xPcZymIZaO03548Mke5X",
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2W",
+ "roundness": null,
+ "seed": 743013435,
+ "version": 33,
+ "versionNonce": 1173476021,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false,
+ "text": "Execution Logic",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "ll-9KlBiVFAVfr9B_KCHm",
+ "originalText": "Execution Logic",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "IHB-7io4Ghskna1oKKzVX",
+ "type": "rectangle",
+ "x": 1560.562500000001,
+ "y": 579,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1xPcZymIZaO03548Mke5X",
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2X",
+ "roundness": null,
+ "seed": 1608793307,
+ "version": 34,
+ "versionNonce": 1039119381,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "7gBILUHDpK1lc44YXUDUD"
+ },
+ {
+ "id": "y0YvZmM6Y3DeP-WFje7h0",
+ "type": "arrow"
+ },
+ {
+ "id": "lBVMIhvBLIb1hqdCcsgaV",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "7gBILUHDpK1lc44YXUDUD",
+ "type": "text",
+ "x": 1585.382614135743,
+ "y": 599,
+ "width": 210.35977172851562,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1xPcZymIZaO03548Mke5X",
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2Y",
+ "roundness": null,
+ "seed": 530442619,
+ "version": 33,
+ "versionNonce": 845834613,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false,
+ "text": "Continuous Simulation\nLoop",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "IHB-7io4Ghskna1oKKzVX",
+ "originalText": "Continuous Simulation Loop",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "9qllA8WNjIQQmiyJcaROy",
+ "type": "rectangle",
+ "x": 1870.562500000001,
+ "y": 594,
+ "width": 207.828125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1xPcZymIZaO03548Mke5X",
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2Z",
+ "roundness": null,
+ "seed": 1622737435,
+ "version": 32,
+ "versionNonce": 1175355797,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "EiGBJEeZ_TjQ0kWYZKs0a"
+ }
+ ],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "EiGBJEeZ_TjQ0kWYZKs0a",
+ "type": "text",
+ "x": 1899.7266235351572,
+ "y": 611.5,
+ "width": 149.4998779296875,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1xPcZymIZaO03548Mke5X",
+ "1SDEtJh-RaHpfuqEzXjBu",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2a",
+ "roundness": null,
+ "seed": 1277691579,
+ "version": 33,
+ "versionNonce": 944998133,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false,
+ "text": "SQLMesh DAGs",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "9qllA8WNjIQQmiyJcaROy",
+ "originalText": "SQLMesh DAGs",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "gFXkHboFc6yD0ApiUr2r4",
+ "type": "rectangle",
+ "x": 601.2343750000009,
+ "y": 529,
+ "width": 613.921875,
+ "height": 355,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "wsH8p1pzxnYFR7GPIaVIy",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2b",
+ "roundness": null,
+ "seed": 1217230683,
+ "version": 32,
+ "versionNonce": 445702229,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "Uv8khIX9hUm3Lw8BuX88q"
+ }
+ ],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "Uv8khIX9hUm3Lw8BuX88q",
+ "type": "text",
+ "x": 829.1753921508798,
+ "y": 534,
+ "width": 158.0398406982422,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "wsH8p1pzxnYFR7GPIaVIy",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2c",
+ "roundness": null,
+ "seed": 1144771579,
+ "version": 33,
+ "versionNonce": 1922829749,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false,
+ "text": "Application layer",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "gFXkHboFc6yD0ApiUr2r4",
+ "originalText": "Application layer",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "IeeurMrAMxQGs57CxKdd1",
+ "type": "rectangle",
+ "x": 946.2343750000009,
+ "y": 594,
+ "width": 207.84375,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "wsH8p1pzxnYFR7GPIaVIy",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2d",
+ "roundness": null,
+ "seed": 1060478107,
+ "version": 35,
+ "versionNonce": 1872400149,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "tT1MCYlD_u3ksg3XNktL2"
+ },
+ {
+ "id": "1p2WlUT4890SbAOJsAleB",
+ "type": "arrow"
+ },
+ {
+ "id": "yqcb8Kb07-STStc_kguVS",
+ "type": "arrow"
+ },
+ {
+ "id": "PKrYXFlnbK2JApD-7BF77",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "tT1MCYlD_u3ksg3XNktL2",
+ "type": "text",
+ "x": 971.4863204956064,
+ "y": 611.5,
+ "width": 157.33985900878906,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "wsH8p1pzxnYFR7GPIaVIy",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2e",
+ "roundness": null,
+ "seed": 355291451,
+ "version": 33,
+ "versionNonce": 1073865845,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false,
+ "text": "Async Flask App",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "IeeurMrAMxQGs57CxKdd1",
+ "originalText": "Async Flask App",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "6qMEJ2g2tB4PjbiifJHNM",
+ "type": "rectangle",
+ "x": 920.1562500000009,
+ "y": 769,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#fbc02d",
+ "backgroundColor": "#fff9c4",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "wsH8p1pzxnYFR7GPIaVIy",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2f",
+ "roundness": null,
+ "seed": 126185947,
+ "version": 34,
+ "versionNonce": 2046024853,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "obwsIyQh6kq9A7dkrne1h"
+ },
+ {
+ "id": "1p2WlUT4890SbAOJsAleB",
+ "type": "arrow"
+ },
+ {
+ "id": "MwGeNgpe0lKS-GQHITmxl",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501907,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "obwsIyQh6kq9A7dkrne1h",
+ "type": "text",
+ "x": 958.9563217163095,
+ "y": 789,
+ "width": 182.3998565673828,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#fbc02d",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "wsH8p1pzxnYFR7GPIaVIy",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2g",
+ "roundness": null,
+ "seed": 122715771,
+ "version": 33,
+ "versionNonce": 483754485,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501907,
+ "link": null,
+ "locked": false,
+ "text": "Embedded DuckDB\nEngine",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "6qMEJ2g2tB4PjbiifJHNM",
+ "originalText": "Embedded DuckDB Engine",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "XOgPRcOpnddFVlkPPoa-O",
+ "type": "rectangle",
+ "x": 636.2343750000009,
+ "y": 579,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "wsH8p1pzxnYFR7GPIaVIy",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2h",
+ "roundness": null,
+ "seed": 1062270747,
+ "version": 35,
+ "versionNonce": 1964722357,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "-8p69YCUVarKQ5CsKk1iG"
+ },
+ {
+ "id": "XwQxkzo4rSFVwhi_MrIC-",
+ "type": "arrow"
+ },
+ {
+ "id": "P9QOhNimnhTMftk9DUZTg",
+ "type": "arrow"
+ },
+ {
+ "id": "XSqwgj_iT7Kc8QjvlO6Z1",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501907,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "-8p69YCUVarKQ5CsKk1iG",
+ "type": "text",
+ "x": 663.9044647216806,
+ "y": 599,
+ "width": 204.65982055664062,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "wsH8p1pzxnYFR7GPIaVIy",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2i",
+ "roundness": null,
+ "seed": 1576623035,
+ "version": 33,
+ "versionNonce": 1954179605,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501907,
+ "link": null,
+ "locked": false,
+ "text": "Apache Superset (BI\nTool)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "XOgPRcOpnddFVlkPPoa-O",
+ "originalText": "Apache Superset (BI Tool)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "1p2WlUT4890SbAOJsAleB",
+ "type": "arrow",
+ "x": 1050.156375000001,
+ "y": 654.5,
+ "width": 0,
+ "height": 110,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "wsH8p1pzxnYFR7GPIaVIy",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2j",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 527182939,
+ "version": 34,
+ "versionNonce": 1049507733,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501908,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 39.5
+ ],
+ [
+ 0,
+ 64.5
+ ],
+ [
+ 0,
+ 89.5
+ ],
+ [
+ 0,
+ 110
+ ]
+ ],
+ "startBinding": {
+ "elementId": "IeeurMrAMxQGs57CxKdd1",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "6qMEJ2g2tB4PjbiifJHNM",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false
+ },
+ {
+ "id": "Jcvo3LY7QRWnDrryFIHUI",
+ "type": "rectangle",
+ "x": 692.1015625000009,
+ "y": 284,
+ "width": 505,
+ "height": 140,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "er3UK3BrV-zd7AKbj3H3V",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2k",
+ "roundness": null,
+ "seed": 393996539,
+ "version": 32,
+ "versionNonce": 862747893,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "SRps2Ersux8jQg-JTFmuz"
+ }
+ ],
+ "updated": 1769351501908,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "SRps2Ersux8jQg-JTFmuz",
+ "type": "text",
+ "x": 878.2116241455087,
+ "y": 289,
+ "width": 132.77987670898438,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "er3UK3BrV-zd7AKbj3H3V",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2l",
+ "roundness": null,
+ "seed": 1001066907,
+ "version": 33,
+ "versionNonce": 1931155029,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501908,
+ "link": null,
+ "locked": false,
+ "text": "Ingress Layer",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "Jcvo3LY7QRWnDrryFIHUI",
+ "originalText": "Ingress Layer",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "o9DsL2rcptx5ljyFjp8uo",
+ "type": "rectangle",
+ "x": 870.9765625000009,
+ "y": 309,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "er3UK3BrV-zd7AKbj3H3V",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2m",
+ "roundness": null,
+ "seed": 757868091,
+ "version": 36,
+ "versionNonce": 1752138677,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "-nRebN_9Oj88j9dGL7SMw"
+ },
+ {
+ "id": "FvqjkJI32AlK6xSAtF1Ox",
+ "type": "arrow"
+ },
+ {
+ "id": "-8XBhAcC0mxjw5vEmDD1M",
+ "type": "arrow"
+ },
+ {
+ "id": "yqcb8Kb07-STStc_kguVS",
+ "type": "arrow"
+ },
+ {
+ "id": "P9QOhNimnhTMftk9DUZTg",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501908,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "-nRebN_9Oj88j9dGL7SMw",
+ "type": "text",
+ "x": 890.3666610717783,
+ "y": 329,
+ "width": 221.2198028564453,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "er3UK3BrV-zd7AKbj3H3V",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2n",
+ "roundness": null,
+ "seed": 1122084571,
+ "version": 33,
+ "versionNonce": 126829845,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501908,
+ "link": null,
+ "locked": false,
+ "text": "Caddy / Nginx Reverse\nProxy",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "o9DsL2rcptx5ljyFjp8uo",
+ "originalText": "Caddy / Nginx Reverse Proxy",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "fYsVc9UradPtm3xfdGgQo",
+ "type": "rectangle",
+ "x": -89.89062499999909,
+ "y": 1019,
+ "width": 1872.953125,
+ "height": 275,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2o",
+ "roundness": null,
+ "seed": 1398674299,
+ "version": 32,
+ "versionNonce": 1461221365,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "XxZfaLfOIc8M7AB0MjwYd"
+ }
+ ],
+ "updated": 1769351501909,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "XxZfaLfOIc8M7AB0MjwYd",
+ "type": "text",
+ "x": 654.6961059570322,
+ "y": 1024,
+ "width": 383.7796630859375,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2p",
+ "roundness": null,
+ "seed": 1055124507,
+ "version": 33,
+ "versionNonce": 1435480405,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501909,
+ "link": null,
+ "locked": false,
+ "text": "High-Speed Storage Layer (Local NVME)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "fYsVc9UradPtm3xfdGgQo",
+ "originalText": "High-Speed Storage Layer (Local NVME)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "JT0dMyZZvrmepEIawenTV",
+ "type": "rectangle",
+ "x": 288.6718750000009,
+ "y": 1209,
+ "width": 235.625,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#b71c1c",
+ "backgroundColor": "#ffcdd2",
+ "fillStyle": "solid",
+ "strokeWidth": 3,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2q",
+ "roundness": null,
+ "seed": 962965691,
+ "version": 35,
+ "versionNonce": 1738063541,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "ZIMqCKcfTT0Wuj6_3bCB0"
+ },
+ {
+ "id": "do0Omvc6vWNxDNC-yobWi",
+ "type": "arrow"
+ },
+ {
+ "id": "0MxIiFNGKPrQQm6ohE8Gx",
+ "type": "arrow"
+ },
+ {
+ "id": "ki4ori4E1wqYgRAnjwrqj",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501909,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "ZIMqCKcfTT0Wuj6_3bCB0",
+ "type": "text",
+ "x": 310.8244628906259,
+ "y": 1226.5,
+ "width": 191.31982421875,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#b71c1c",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2r",
+ "roundness": null,
+ "seed": 1418060123,
+ "version": 33,
+ "versionNonce": 1675173909,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501909,
+ "link": null,
+ "locked": false,
+ "text": "8TB NVME Storage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "JT0dMyZZvrmepEIawenTV",
+ "originalText": "8TB NVME Storage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "cf0963OJ9ti8wwpAFcNyp",
+ "type": "rectangle",
+ "x": 920.1562500000009,
+ "y": 1044,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2s",
+ "roundness": null,
+ "seed": 1234632187,
+ "version": 38,
+ "versionNonce": 809915765,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "9kYJdtQIs_D0ic607NnfG"
+ },
+ {
+ "id": "PzHkTk14OSi29fzOpxwDu",
+ "type": "arrow"
+ },
+ {
+ "id": "IUHWYFqoaS-pPp83ZC70D",
+ "type": "arrow"
+ },
+ {
+ "id": "MwGeNgpe0lKS-GQHITmxl",
+ "type": "arrow"
+ },
+ {
+ "id": "XwQxkzo4rSFVwhi_MrIC-",
+ "type": "arrow"
+ },
+ {
+ "id": "do0Omvc6vWNxDNC-yobWi",
+ "type": "arrow"
+ },
+ {
+ "id": "4rOpYk_bcwr7XB4jKp1WI",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501909,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "9kYJdtQIs_D0ic607NnfG",
+ "type": "text",
+ "x": 947.5763473510751,
+ "y": 1064,
+ "width": 205.15980529785156,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2t",
+ "roundness": null,
+ "seed": 60524187,
+ "version": 33,
+ "versionNonce": 1478876885,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501909,
+ "link": null,
+ "locked": false,
+ "text": "Parquet / Data Lake\nFiles",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "cf0963OJ9ti8wwpAFcNyp",
+ "originalText": "Parquet / Data Lake Files",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "LUdKAx1oIX_5NlGUeUwY0",
+ "type": "rectangle",
+ "x": 255.1093750000009,
+ "y": 1044,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2u",
+ "roundness": null,
+ "seed": 1766193979,
+ "version": 34,
+ "versionNonce": 1146616597,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "BKaZMpa-m7Gs0BpaOBVHy"
+ },
+ {
+ "id": "0MxIiFNGKPrQQm6ohE8Gx",
+ "type": "arrow"
+ },
+ {
+ "id": "sllCN0NKZUeWtTZ0WDK1F",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501910,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "BKaZMpa-m7Gs0BpaOBVHy",
+ "type": "text",
+ "x": 281.4194869995126,
+ "y": 1064,
+ "width": 207.37977600097656,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2v",
+ "roundness": null,
+ "seed": 1727585243,
+ "version": 33,
+ "versionNonce": 1915867253,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501910,
+ "link": null,
+ "locked": false,
+ "text": "App SQLite/Postgres\nFiles",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "LUdKAx1oIX_5NlGUeUwY0",
+ "originalText": "App SQLite/Postgres Files",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "euTCWNLMdWZDwVSmZIP5V",
+ "type": "rectangle",
+ "x": -54.89062499999909,
+ "y": 1044,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2w",
+ "roundness": null,
+ "seed": 952543355,
+ "version": 34,
+ "versionNonce": 362149685,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "N_udRp1y6vSFBpc5fMYSm"
+ },
+ {
+ "id": "ki4ori4E1wqYgRAnjwrqj",
+ "type": "arrow"
+ },
+ {
+ "id": "UGIcpJcAgmEii0Pq01qK_",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351501910,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "N_udRp1y6vSFBpc5fMYSm",
+ "type": "text",
+ "x": -9.980537414549872,
+ "y": 1064,
+ "width": 170.17982482910156,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2x",
+ "roundness": null,
+ "seed": 1953620251,
+ "version": 33,
+ "versionNonce": 1050364053,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501910,
+ "link": null,
+ "locked": false,
+ "text": "Airflow Metadata\nStorage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "euTCWNLMdWZDwVSmZIP5V",
+ "originalText": "Airflow Metadata Storage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "do0Omvc6vWNxDNC-yobWi",
+ "type": "arrow",
+ "x": 1049.656375000001,
+ "y": 1134.5,
+ "width": 525.3589999999999,
+ "height": 93.93299999999999,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2y",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1399653819,
+ "version": 34,
+ "versionNonce": 1842866005,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501910,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0.5,
+ 24.5
+ ],
+ [
+ 0.5,
+ 49.5
+ ],
+ [
+ -524.8589999999999,
+ 93.93299999999999
+ ]
+ ],
+ "startBinding": {
+ "elementId": "cf0963OJ9ti8wwpAFcNyp",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "JT0dMyZZvrmepEIawenTV",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0000021220159157,
+ 0.33221666666666655
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "elbowed": false
+ },
+ {
+ "id": "0MxIiFNGKPrQQm6ohE8Gx",
+ "type": "arrow",
+ "x": 385.6093750000009,
+ "y": 1134.5,
+ "width": 9.216000000000008,
+ "height": 74,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b2z",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1020958299,
+ "version": 34,
+ "versionNonce": 1969894581,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501910,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.5,
+ 24.5
+ ],
+ [
+ -0.5,
+ 49.5
+ ],
+ [
+ 8.716000000000008,
+ 74
+ ]
+ ],
+ "startBinding": {
+ "elementId": "LUdKAx1oIX_5NlGUeUwY0",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "JT0dMyZZvrmepEIawenTV",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.4505188328912467,
+ 0
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "elbowed": false
+ },
+ {
+ "id": "ki4ori4E1wqYgRAnjwrqj",
+ "type": "arrow",
+ "x": 75.60937500000091,
+ "y": 1134.5,
+ "width": 213.063,
+ "height": 84.44599999999991,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "IyUtmP8t0LUN44ozXjZeV",
+ "dlmhivNpeTzFOuPc7phM7"
+ ],
+ "frameId": null,
+ "index": "b30",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 260903675,
+ "version": 34,
+ "versionNonce": 1678497301,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501910,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.5,
+ 24.5
+ ],
+ [
+ -0.5,
+ 49.5
+ ],
+ [
+ 212.563,
+ 84.44599999999991
+ ]
+ ],
+ "startBinding": {
+ "elementId": "euTCWNLMdWZDwVSmZIP5V",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "JT0dMyZZvrmepEIawenTV",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.0000021220159150691844,
+ 0.17409999999999853
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "elbowed": false
+ },
+ {
+ "id": "aGiqfIjkXx3JKwK3zFmVR",
+ "type": "rectangle",
+ "x": -523.8906249999991,
+ "y": -210,
+ "width": 330,
+ "height": 655,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b31",
+ "roundness": null,
+ "seed": 738655131,
+ "version": 5,
+ "versionNonce": 1479820565,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "IRceaqLVmTzgJHLQQMkkA"
+ }
+ ],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "IRceaqLVmTzgJHLQQMkkA",
+ "type": "text",
+ "x": -474.7505187988272,
+ "y": -205,
+ "width": 231.71978759765625,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b32",
+ "roundness": null,
+ "seed": 1048236091,
+ "version": 6,
+ "versionNonce": 669909691,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "CI/CD Pipeline (GitLab)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": "aGiqfIjkXx3JKwK3zFmVR",
+ "originalText": "CI/CD Pipeline (GitLab)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "AFPybdN6K1PoLXlrmleWx",
+ "type": "rectangle",
+ "x": -468.9296874999991,
+ "y": -185,
+ "width": 220.078125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b33",
+ "roundness": null,
+ "seed": 1221267675,
+ "version": 6,
+ "versionNonce": 401922677,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "RKd-xSNi1_uU2yftOMIQd"
+ },
+ {
+ "id": "Tt4kOkNcCAEWUAoQKLMHR",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "RKd-xSNi1_uU2yftOMIQd",
+ "type": "text",
+ "x": -448.32052612304597,
+ "y": -167.5,
+ "width": 178.85980224609375,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b34",
+ "roundness": null,
+ "seed": 1820999035,
+ "version": 6,
+ "versionNonce": 842265435,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "GitLab Repository",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "AFPybdN6K1PoLXlrmleWx",
+ "originalText": "GitLab Repository",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "GfMD60YMzrMRgqY0ds0BE",
+ "type": "rectangle",
+ "x": -453.9296874999991,
+ "y": -45,
+ "width": 190.078125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b35",
+ "roundness": null,
+ "seed": 1962595867,
+ "version": 7,
+ "versionNonce": 834388949,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "wGoAy8HbMybL7aIm4mks_"
+ },
+ {
+ "id": "Tt4kOkNcCAEWUAoQKLMHR",
+ "type": "arrow"
+ },
+ {
+ "id": "H5KBAY6woAyg7EfqddVOk",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "wGoAy8HbMybL7aIm4mks_",
+ "type": "text",
+ "x": -428.2505569457999,
+ "y": -27.5,
+ "width": 138.71986389160156,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b36",
+ "roundness": null,
+ "seed": 554654395,
+ "version": 6,
+ "versionNonce": 733138939,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "GitLab Runner",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "GfMD60YMzrMRgqY0ds0BE",
+ "originalText": "GitLab Runner",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "TG7tfNiGM5lXlWou9_5Ez",
+ "type": "rectangle",
+ "x": -470.4296874999991,
+ "y": 105,
+ "width": 223.078125,
+ "height": 60,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b37",
+ "roundness": null,
+ "seed": 761940827,
+ "version": 7,
+ "versionNonce": 966689077,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "jSKeUn9wl9WszDeHGyn_U"
+ },
+ {
+ "id": "H5KBAY6woAyg7EfqddVOk",
+ "type": "arrow"
+ },
+ {
+ "id": "qxn7D1BXYz8gw_cc27Zyi",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "jSKeUn9wl9WszDeHGyn_U",
+ "type": "text",
+ "x": -454.43053436279206,
+ "y": 122.5,
+ "width": 191.07981872558594,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b38",
+ "roundness": null,
+ "seed": 509487099,
+ "version": 6,
+ "versionNonce": 376248475,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Build & Test Stage",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "TG7tfNiGM5lXlWou9_5Ez",
+ "originalText": "Build & Test Stage",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "C4pOxabsnfcyqKZeuddE6",
+ "type": "rectangle",
+ "x": -488.8906249999991,
+ "y": 305,
+ "width": 260,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b39",
+ "roundness": null,
+ "seed": 1240297627,
+ "version": 8,
+ "versionNonce": 620925589,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "dB5DFBKVRlVnpOHBjqDRR"
+ },
+ {
+ "id": "qxn7D1BXYz8gw_cc27Zyi",
+ "type": "arrow"
+ },
+ {
+ "id": "PKrYXFlnbK2JApD-7BF77",
+ "type": "arrow"
+ },
+ {
+ "id": "XSqwgj_iT7Kc8QjvlO6Z1",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "dB5DFBKVRlVnpOHBjqDRR",
+ "type": "text",
+ "x": -479.1105194091788,
+ "y": 337.5,
+ "width": 240.43978881835938,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b3A",
+ "roundness": null,
+ "seed": 566928699,
+ "version": 6,
+ "versionNonce": 269831483,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Deploy Stage (SSH/SCP)",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "C4pOxabsnfcyqKZeuddE6",
+ "originalText": "Deploy Stage (SSH/SCP)",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "Tt4kOkNcCAEWUAoQKLMHR",
+ "type": "arrow",
+ "x": -358.8906249999991,
+ "y": -124.5,
+ "width": 0,
+ "height": 75,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b3B",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1029195227,
+ "version": 7,
+ "versionNonce": 547190773,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "O_lNUtN4qZvGswRAjQkbL"
+ }
+ ],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 39.5
+ ],
+ [
+ 0,
+ 75
+ ]
+ ],
+ "startBinding": {
+ "elementId": "AFPybdN6K1PoLXlrmleWx",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "GfMD60YMzrMRgqY0ds0BE",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.06666666666666667
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false
+ },
+ {
+ "id": "O_lNUtN4qZvGswRAjQkbL",
+ "type": "text",
+ "x": -427.21056365966706,
+ "y": -97.5,
+ "width": 136.63987731933594,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b3C",
+ "roundness": null,
+ "seed": 598266491,
+ "version": 6,
+ "versionNonce": 1544416731,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Merge to Main",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "Tt4kOkNcCAEWUAoQKLMHR",
+ "originalText": "Merge to Main",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "H5KBAY6woAyg7EfqddVOk",
+ "type": "arrow",
+ "x": -358.8906249999991,
+ "y": 15.5,
+ "width": 0,
+ "height": 85,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b3D",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1434372891,
+ "version": 7,
+ "versionNonce": 645181781,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 24.5
+ ],
+ [
+ 0,
+ 49.5
+ ],
+ [
+ 0,
+ 85
+ ]
+ ],
+ "startBinding": {
+ "elementId": "GfMD60YMzrMRgqY0ds0BE",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "TG7tfNiGM5lXlWou9_5Ez",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.06666666666666667
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false
+ },
+ {
+ "id": "qxn7D1BXYz8gw_cc27Zyi",
+ "type": "arrow",
+ "x": -358.8906249999991,
+ "y": 165.5,
+ "width": 0,
+ "height": 135,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "6T10LHkK6hCcA7O3KM2iM"
+ ],
+ "frameId": null,
+ "index": "b3E",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 390901691,
+ "version": 7,
+ "versionNonce": 761887355,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 39.5
+ ],
+ [
+ 0,
+ 64.5
+ ],
+ [
+ 0,
+ 89.5
+ ],
+ [
+ 0,
+ 114.5
+ ],
+ [
+ 0,
+ 135
+ ]
+ ],
+ "startBinding": {
+ "elementId": "TG7tfNiGM5lXlWou9_5Ez",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "C4pOxabsnfcyqKZeuddE6",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false
+ },
+ {
+ "id": "PzHkTk14OSi29fzOpxwDu",
+ "type": "arrow",
+ "x": 1689.355573784723,
+ "y": 855,
+ "width": 498.1993237847221,
+ "height": 218.5262145084887,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3F",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 2067071067,
+ "version": 61,
+ "versionNonce": 1645034549,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "jGNEdHjEKj58jY8Kn0WLm"
+ }
+ ],
+ "updated": 1769351501909,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -2.793198784722108,
+ 25
+ ],
+ [
+ -2.793198784722108,
+ 80
+ ],
+ [
+ -2.793198784722108,
+ 135
+ ],
+ [
+ -2.793198784722108,
+ 160
+ ],
+ [
+ -498.1993237847221,
+ 218.5262145084887
+ ]
+ ],
+ "startBinding": {
+ "elementId": "ZHw1u2IpKs2-2VRWu8-AA",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "cf0963OJ9ti8wwpAFcNyp",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0152927884615381,
+ 0.3372888888888888
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "jGNEdHjEKj58jY8Kn0WLm",
+ "type": "text",
+ "x": 1635.4724244384772,
+ "y": 950.0033006462036,
+ "width": 102.17990112304688,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3G",
+ "roundness": null,
+ "seed": 722091259,
+ "version": 7,
+ "versionNonce": 381024059,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403275,
+ "link": null,
+ "locked": false,
+ "text": "Store Raw",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "PzHkTk14OSi29fzOpxwDu",
+ "originalText": "Store Raw",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "IUHWYFqoaS-pPp83ZC70D",
+ "type": "arrow",
+ "x": 1398.0734583333344,
+ "y": 869.9999999999999,
+ "width": 206.91720833333352,
+ "height": 190.6402168164542,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3H",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1917773211,
+ "version": 61,
+ "versionNonce": 1709305237,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "rfl8q_p_5y9GaqoYWg1-D"
+ }
+ ],
+ "updated": 1769351501909,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -1.917083333333494,
+ 10.000000000000114
+ ],
+ [
+ -1.917083333333494,
+ 65.00000000000011
+ ],
+ [
+ -1.917083333333494,
+ 120.00000000000011
+ ],
+ [
+ -1.917083333333494,
+ 145.0000000000001
+ ],
+ [
+ -206.91720833333352,
+ 190.6402168164542
+ ]
+ ],
+ "startBinding": {
+ "elementId": "lVGqkdZA8ANLHOnrDEKs_",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "cf0963OJ9ti8wwpAFcNyp",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0150850961538465,
+ 0.20239999999999883
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "rfl8q_p_5y9GaqoYWg1-D",
+ "type": "text",
+ "x": 1313.5564604492197,
+ "y": 950.0033006462036,
+ "width": 165.1998291015625,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3I",
+ "roundness": null,
+ "seed": 137722427,
+ "version": 6,
+ "versionNonce": 1459836859,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Transform/Model",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "IUHWYFqoaS-pPp83ZC70D",
+ "originalText": "Transform/Model",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "MwGeNgpe0lKS-GQHITmxl",
+ "type": "arrow",
+ "x": 1048.0734583333344,
+ "y": 869.9999999999999,
+ "width": 2.8986300000001393,
+ "height": 163.0000000000001,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3J",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 429947611,
+ "version": 61,
+ "versionNonce": 1658417909,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "b32Fn1I7TCihe0suJtcI0"
+ }
+ ],
+ "updated": 1769351501909,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -1.917083333333494,
+ 10.000000000000114
+ ],
+ [
+ -1.917083333333494,
+ 65.00000000000011
+ ],
+ [
+ -1.917083333333494,
+ 120.00000000000011
+ ],
+ [
+ -1.917083333333494,
+ 145.0000000000001
+ ],
+ [
+ 0.9815466666666453,
+ 163.0000000000001
+ ]
+ ],
+ "startBinding": {
+ "elementId": "6qMEJ2g2tB4PjbiifJHNM",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "cf0963OJ9ti8wwpAFcNyp",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "b32Fn1I7TCihe0suJtcI0",
+ "type": "text",
+ "x": 963.4364500732431,
+ "y": 937.5033006462036,
+ "width": 165.43984985351562,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3K",
+ "roundness": null,
+ "seed": 321021819,
+ "version": 6,
+ "versionNonce": 1574348891,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "High-Speed OLAP\nQuery",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "MwGeNgpe0lKS-GQHITmxl",
+ "originalText": "High-Speed OLAP Query",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "XwQxkzo4rSFVwhi_MrIC-",
+ "type": "arrow",
+ "x": 764.1515178571437,
+ "y": 680.0000000000001,
+ "width": 146.9218749999999,
+ "height": 374.0973303868201,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3L",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 721272859,
+ "version": 62,
+ "versionNonce": 1434012757,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "Faxz78xwki3c-VMGFfyEM"
+ }
+ ],
+ "updated": 1769351501910,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -1.917142857142835,
+ 9.999999999999886
+ ],
+ [
+ -1.917142857142835,
+ 34.999999999999886
+ ],
+ [
+ -1.917142857142835,
+ 59.999999999999886
+ ],
+ [
+ -1.917142857142835,
+ 129.9999999999999
+ ],
+ [
+ -1.917142857142835,
+ 199.9999999999999
+ ],
+ [
+ -1.917142857142835,
+ 254.9999999999999
+ ],
+ [
+ -1.917142857142835,
+ 309.9999999999999
+ ],
+ [
+ -1.917142857142835,
+ 334.9999999999999
+ ],
+ [
+ 145.00473214285705,
+ 374.0973303868201
+ ]
+ ],
+ "startBinding": {
+ "elementId": "XOgPRcOpnddFVlkPPoa-O",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "cf0963OJ9ti8wwpAFcNyp",
+ "mode": "orbit",
+ "fixedPoint": [
+ -0.014937980769230728,
+ 0.13323333333333318
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "Faxz78xwki3c-VMGFfyEM",
+ "type": "text",
+ "x": 661.2144622802743,
+ "y": 820.0068651945548,
+ "width": 202.03982543945312,
+ "height": 50,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3M",
+ "roundness": null,
+ "seed": 723846331,
+ "version": 6,
+ "versionNonce": 456582395,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Connect via\nDuckDB/SQLAlchemy",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "XwQxkzo4rSFVwhi_MrIC-",
+ "originalText": "Connect via DuckDB/SQLAlchemy",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "FvqjkJI32AlK6xSAtF1Ox",
+ "type": "arrow",
+ "x": 1100.6160400000008,
+ "y": 190.99999999999997,
+ "width": 19.98746123332444,
+ "height": 107.00000000000003,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3N",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 2067445083,
+ "version": 34,
+ "versionNonce": 602921589,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501908,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.014664999999922657,
+ 14.000000000000028
+ ],
+ [
+ -0.014664999999922657,
+ 39.00000000000003
+ ],
+ [
+ -0.014664999999922657,
+ 64.00000000000003
+ ],
+ [
+ -0.014664999999922657,
+ 89.00000000000003
+ ],
+ [
+ -19.98746123332444,
+ 107.00000000000003
+ ]
+ ],
+ "startBinding": {
+ "elementId": "JZc6TwK4afoz1Q8G9hmZz",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "o9DsL2rcptx5ljyFjp8uo",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.7689646634615385,
+ -0.02487777777777814
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "-8XBhAcC0mxjw5vEmDD1M",
+ "type": "arrow",
+ "x": 790.6160400000009,
+ "y": 190.99999999999997,
+ "width": 69.3752822213188,
+ "height": 117.99920631144536,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3O",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1787908603,
+ "version": 34,
+ "versionNonce": 106349525,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501908,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -0.014665000000036343,
+ 14.000000000000028
+ ],
+ [
+ -0.014665000000036343,
+ 39.00000000000003
+ ],
+ [
+ -0.014665000000036343,
+ 64.00000000000003
+ ],
+ [
+ -0.014665000000036343,
+ 89.00000000000003
+ ],
+ [
+ 69.36061722131876,
+ 117.99920631144536
+ ]
+ ],
+ "startBinding": {
+ "elementId": "Ans_j8zJjaZYHj0H6LOiv",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "o9DsL2rcptx5ljyFjp8uo",
+ "mode": "orbit",
+ "fixedPoint": [
+ -0.014569951923077112,
+ -0.004211111111111323
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "yqcb8Kb07-STStc_kguVS",
+ "type": "arrow",
+ "x": 1084.8828035714293,
+ "y": 410,
+ "width": 19.92135739294372,
+ "height": 173,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3P",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 975919771,
+ "version": 60,
+ "versionNonce": 1121550645,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501909,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 15.718571428571522,
+ 10
+ ],
+ [
+ 15.718571428571522,
+ 35
+ ],
+ [
+ 15.718571428571522,
+ 75
+ ],
+ [
+ 15.718571428571522,
+ 115
+ ],
+ [
+ 15.718571428571522,
+ 140
+ ],
+ [
+ -4.202785964372197,
+ 173
+ ]
+ ],
+ "startBinding": {
+ "elementId": "o9DsL2rcptx5ljyFjp8uo",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.7562146634615382,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "IeeurMrAMxQGs57CxKdd1",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.6240793865584123,
+ -0.05261666666666732
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "P9QOhNimnhTMftk9DUZTg",
+ "type": "arrow",
+ "x": 860.9529815523176,
+ "y": 403.52388572632015,
+ "width": 63.47600601234717,
+ "height": 164.47611427367985,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3Q",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1723551547,
+ "version": 61,
+ "versionNonce": 1323143829,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501909,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -57.312606552316765,
+ 16.476114273679855
+ ],
+ [
+ -57.312606552316765,
+ 41.476114273679855
+ ],
+ [
+ -57.312606552316765,
+ 81.47611427367985
+ ],
+ [
+ -57.312606552316765,
+ 121.47611427367985
+ ],
+ [
+ -57.312606552316765,
+ 146.47611427367985
+ ],
+ [
+ -63.47600601234717,
+ 164.47611427367985
+ ]
+ ],
+ "startBinding": {
+ "elementId": "o9DsL2rcptx5ljyFjp8uo",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.02197235576923049,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "XOgPRcOpnddFVlkPPoa-O",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.6102115384615383,
+ -0.038255555555555376
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "PKrYXFlnbK2JApD-7BF77",
+ "type": "arrow",
+ "x": -300.8907049999992,
+ "y": 406,
+ "width": 1291.0829978003449,
+ "height": 177,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3R",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 849588187,
+ "version": 34,
+ "versionNonce": 1433471797,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "Nz2ykHd8u3W9DLGc9oa2_"
+ }
+ ],
+ "updated": 1769351501907,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 14.500080000000054,
+ 14
+ ],
+ [
+ 14.500080000000054,
+ 39
+ ],
+ [
+ 1243.99208,
+ 79
+ ],
+ [
+ 1243.99208,
+ 119
+ ],
+ [
+ 1243.99208,
+ 144
+ ],
+ [
+ 1291.0829978003449,
+ 177
+ ]
+ ],
+ "startBinding": {
+ "elementId": "C4pOxabsnfcyqKZeuddE6",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.6792576923076922,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "IeeurMrAMxQGs57CxKdd1",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.27158382198165637,
+ -0.03746666666666745
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "Nz2ykHd8u3W9DLGc9oa2_",
+ "type": "text",
+ "x": 883.3014253540048,
+ "y": 472.5,
+ "width": 119.59989929199219,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3S",
+ "roundness": null,
+ "seed": 1878457467,
+ "version": 6,
+ "versionNonce": 1781408475,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Deploy Code",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "PKrYXFlnbK2JApD-7BF77",
+ "originalText": "Deploy Code",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "XSqwgj_iT7Kc8QjvlO6Z1",
+ "type": "arrow",
+ "x": -408.890864999999,
+ "y": 405.99999999999994,
+ "width": 1137.4928505535056,
+ "height": 162.00000000000006,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3T",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 175617307,
+ "version": 34,
+ "versionNonce": 486196789,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "OrrGjkOtQ4x9rTnkSzTqa"
+ }
+ ],
+ "updated": 1769351501908,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -12.499760000000066,
+ 14.000000000000057
+ ],
+ [
+ -12.499760000000066,
+ 39.00000000000006
+ ],
+ [
+ 1108.62524,
+ 79.00000000000006
+ ],
+ [
+ 1108.62524,
+ 119.00000000000006
+ ],
+ [
+ 1108.62524,
+ 144.00000000000006
+ ],
+ [
+ 1124.9930905535055,
+ 162.00000000000006
+ ]
+ ],
+ "startBinding": {
+ "elementId": "C4pOxabsnfcyqKZeuddE6",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.34546538461538473,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "XOgPRcOpnddFVlkPPoa-O",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.3352192307692305,
+ -0.03315555555555597
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "OrrGjkOtQ4x9rTnkSzTqa",
+ "type": "text",
+ "x": 633.1344375610362,
+ "y": 472.5,
+ "width": 133.1998748779297,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3U",
+ "roundness": null,
+ "seed": 1368938939,
+ "version": 7,
+ "versionNonce": 1560893403,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403275,
+ "link": null,
+ "locked": false,
+ "text": "Deploy Config",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "XSqwgj_iT7Kc8QjvlO6Z1",
+ "originalText": "Deploy Config",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "UGIcpJcAgmEii0Pq01qK_",
+ "type": "arrow",
+ "x": 99.43256261343114,
+ "y": 869.9785800285035,
+ "width": 28.323187613430235,
+ "height": 163.02141997149647,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3V",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 41642587,
+ "version": 61,
+ "versionNonce": 833580533,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "8buACuDGN3f5gvJNCHIG6"
+ }
+ ],
+ "updated": 1769351501910,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -28.323187613430235,
+ 10.02141997149647
+ ],
+ [
+ -28.323187613430235,
+ 65.02141997149647
+ ],
+ [
+ -28.323187613430235,
+ 120.02141997149647
+ ],
+ [
+ -28.323187613430235,
+ 145.02141997149647
+ ],
+ [
+ -25.424467613430224,
+ 163.02141997149647
+ ]
+ ],
+ "startBinding": {
+ "elementId": "FUzNq2S_STMju3bDxx27W",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.1167576923076922,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "euTCWNLMdWZDwVSmZIP5V",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "8buACuDGN3f5gvJNCHIG6",
+ "type": "text",
+ "x": 32.54942321777435,
+ "y": 950.0033006462036,
+ "width": 77.11990356445312,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3W",
+ "roundness": null,
+ "seed": 301164283,
+ "version": 6,
+ "versionNonce": 574711835,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Extract",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "UGIcpJcAgmEii0Pq01qK_",
+ "originalText": "Extract",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "4rOpYk_bcwr7XB4jKp1WI",
+ "type": "arrow",
+ "x": 371.1093750000009,
+ "y": 846.7243152337857,
+ "width": 538.0468749999999,
+ "height": 223.2436458965184,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3X",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 914542491,
+ "version": 61,
+ "versionNonce": 227998133,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "iZuCOpYhru6rARcXd9xE1"
+ }
+ ],
+ "updated": 1769351501910,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 154.75,
+ 33.27568476621434
+ ],
+ [
+ 154.75,
+ 88.27568476621434
+ ],
+ [
+ 154.75,
+ 143.27568476621434
+ ],
+ [
+ 154.75,
+ 168.27568476621434
+ ],
+ [
+ 538.0468749999999,
+ 223.2436458965184
+ ]
+ ],
+ "startBinding": {
+ "elementId": "FUzNq2S_STMju3bDxx27W",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1,
+ 0.8373222222222214
+ ]
+ },
+ "endBinding": {
+ "elementId": "cf0963OJ9ti8wwpAFcNyp",
+ "mode": "orbit",
+ "fixedPoint": [
+ -0.015245673076922756,
+ 0.2997444444444454
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "iZuCOpYhru6rARcXd9xE1",
+ "type": "text",
+ "x": 487.29942321777435,
+ "y": 950.0033006462036,
+ "width": 77.11990356445312,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3Y",
+ "roundness": null,
+ "seed": 844899387,
+ "version": 6,
+ "versionNonce": 1270066363,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Extract",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "4rOpYk_bcwr7XB4jKp1WI",
+ "originalText": "Extract",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "sllCN0NKZUeWtTZ0WDK1F",
+ "type": "arrow",
+ "x": 356.6536607142864,
+ "y": 870.0000000000001,
+ "width": 27.354434285714547,
+ "height": 162.9999999999999,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3Z",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1566696667,
+ "version": 61,
+ "versionNonce": 1693055445,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "fxDk-rXiWIQEBFCzGz_QB"
+ }
+ ],
+ "updated": 1769351501910,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 24.45571428571452,
+ 9.999999999999886
+ ],
+ [
+ 24.45571428571452,
+ 64.99999999999989
+ ],
+ [
+ 24.45571428571452,
+ 119.99999999999989
+ ],
+ [
+ 24.45571428571452,
+ 144.9999999999999
+ ],
+ [
+ 27.354434285714547,
+ 162.9999999999999
+ ]
+ ],
+ "startBinding": {
+ "elementId": "FUzNq2S_STMju3bDxx27W",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.8832423076923078,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "LUdKAx1oIX_5NlGUeUwY0",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "fxDk-rXiWIQEBFCzGz_QB",
+ "type": "text",
+ "x": 342.54942321777435,
+ "y": 950.0033006462036,
+ "width": 77.11990356445312,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3a",
+ "roundness": null,
+ "seed": 1864798587,
+ "version": 6,
+ "versionNonce": 1672764763,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Extract",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "sllCN0NKZUeWtTZ0WDK1F",
+ "originalText": "Extract",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "5SdaBJB97VVqvmOlIojdR",
+ "type": "arrow",
+ "x": 89.10937500000091,
+ "y": 842.7817523364487,
+ "width": 307,
+ "height": 201.93226605245343,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3b",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 149727771,
+ "version": 34,
+ "versionNonce": 1748565525,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "YYdDZ6Vfz0dLBWBi5xlDb"
+ }
+ ],
+ "updated": 1769351501905,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -203,
+ 37.218247663551324
+ ],
+ [
+ -203,
+ 92.21824766355132
+ ],
+ [
+ -203,
+ 147.21824766355132
+ ],
+ [
+ -203,
+ 172.21824766355132
+ ],
+ [
+ -307,
+ 201.93226605245343
+ ]
+ ],
+ "startBinding": {
+ "elementId": "FUzNq2S_STMju3bDxx27W",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0,
+ 0.79738888888889
+ ]
+ },
+ "endBinding": {
+ "elementId": "9Pi0-xMU6XTiWEE7I1jjY",
+ "mode": "orbit",
+ "fixedPoint": [
+ 1.0147923076923078,
+ 0.07508888888888932
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "YYdDZ6Vfz0dLBWBi5xlDb",
+ "type": "text",
+ "x": -146.62059783935456,
+ "y": 950.0033006462036,
+ "width": 65.45994567871094,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3c",
+ "roundness": null,
+ "seed": 2141630139,
+ "version": 6,
+ "versionNonce": 1704327675,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351403274,
+ "link": null,
+ "locked": false,
+ "text": "Upload",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "containerId": "5SdaBJB97VVqvmOlIojdR",
+ "originalText": "Upload",
+ "autoResize": true,
+ "lineHeight": 1.25
+ },
+ {
+ "id": "y0YvZmM6Y3DeP-WFje7h0",
+ "type": "arrow",
+ "x": 1652.1068194444454,
+ "y": 395,
+ "width": 37.35436555555566,
+ "height": 173,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3d",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1710694235,
+ "version": 61,
+ "versionNonce": 614953685,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 34.45555555555552,
+ 25
+ ],
+ [
+ 34.45555555555552,
+ 50
+ ],
+ [
+ 34.45555555555552,
+ 90
+ ],
+ [
+ 34.45555555555552,
+ 130
+ ],
+ [
+ 34.45555555555552,
+ 155
+ ],
+ [
+ 37.35436555555566,
+ 173
+ ]
+ ],
+ "startBinding": {
+ "elementId": "lEcxDZoezHID6yvTA8cjB",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.7091141626716502,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "IHB-7io4Ghskna1oKKzVX",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.044444444444444446
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "lBVMIhvBLIb1hqdCcsgaV",
+ "type": "arrow",
+ "x": 1688.479577380953,
+ "y": 680,
+ "width": 3.3183201562499107,
+ "height": 93,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3e",
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1446018043,
+ "version": 61,
+ "versionNonce": 1362907189,
+ "isDeleted": false,
+ "boundElements": [],
+ "updated": 1769351501906,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -1.917202380952176,
+ 10
+ ],
+ [
+ -1.917202380952176,
+ 35
+ ],
+ [
+ -1.917202380952176,
+ 60
+ ],
+ [
+ 1.4011177752977346,
+ 93
+ ]
+ ],
+ "startBinding": {
+ "elementId": "IHB-7io4Ghskna1oKKzVX",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ 1
+ ]
+ },
+ "endBinding": {
+ "elementId": "ZHw1u2IpKs2-2VRWu8-AA",
+ "mode": "orbit",
+ "fixedPoint": [
+ 0.5001,
+ -0.06666666666666667
+ ]
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow",
+ "elbowed": false,
+ "moveMidPointsWithElement": false
+ },
+ {
+ "id": "T3uBsXluPH9Fo9zj-NgJ7",
+ "type": "text",
+ "x": 1755.750000000001,
+ "y": 80.5,
+ "width": 8,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "index": "b3f",
+ "roundness": null,
+ "seed": 1166265403,
+ "version": 3,
+ "versionNonce": 974286773,
+ "isDeleted": true,
+ "boundElements": null,
+ "updated": 1769351507803,
+ "link": null,
+ "locked": false,
+ "text": "",
+ "fontSize": 20,
+ "fontFamily": 5,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "",
+ "autoResize": true,
+ "lineHeight": 1.25
+ }
+ ],
+ "appState": {
+ "gridSize": 20,
+ "gridStep": 5,
+ "gridModeEnabled": false,
+ "viewBackgroundColor": "#ffffff",
+ "lockedMultiSelections": {}
+ },
+ "files": {}
+}
\ No newline at end of file
diff --git a/todo.md b/todo.md
deleted file mode 100644
index e69de29..0000000
diff --git a/transform/sqlmesh_materia/config.yaml b/transform/sqlmesh_materia/config.yaml
index 75f0353..9976785 100644
--- a/transform/sqlmesh_materia/config.yaml
+++ b/transform/sqlmesh_materia/config.yaml
@@ -3,9 +3,16 @@
# Local dev uses virtual environments (e.g., dev_)
# Production uses the 'prod' environment
gateways:
- prod:
+ duckdb:
connection:
type: duckdb
+ catalogs:
+ local: 'local.duckdb'
+ cloudflare:
+ type: iceberg
+ path: '{{ env_var("ICEBERG_WAREHOUSE_NAME") }}'
+ connector_config:
+ endpoint: '{{ env_var("ICEBERG_CATALOG_URI") }}'
extensions:
- name: httpfs
- name: iceberg
@@ -13,16 +20,32 @@ gateways:
r2_secret:
type: iceberg
token: "{{ env_var('R2_ADMIN_API_TOKEN') }}"
+ r2_data_secret:
+ type: r2
+ key_id: "{{ env_var('R2_ADMIN_ACCESS_KEY_ID') }}"
+ secret: "{{ env_var('R2_ADMIN_SECRET_ACCESS_KEY') }}"
+ account_id: "{{ var('CLOUDFLARE_ACCOUNT_ID') }}"
+ region: 'eeur'
-default_gateway: prod
-# --- Catalog Configuration ---
+
+default_gateway: duckdb
+
+# --- Variables ---
+# Make environment variables available to models
+variables:
+ R2_BUCKET: beanflows-data-prod
+ CLOUDFLARE_ACCOUNT_ID: "{{ env_var('CLOUDFLARE_ACCOUNT_ID') }}"
+
+ # --- Catalog Configuration ---
# Attach R2 Iceberg catalog and configure default schema
# https://sqlmesh.readthedocs.io/en/stable/reference/configuration/#execution-hooks
# https://developers.cloudflare.com/r2/data-catalog/config-examples/duckdb/
-before_all:
- - "ATTACH '{{ env_var('ICEBERG_WAREHOUSE_NAME') }}' AS catalog (TYPE ICEBERG, ENDPOINT '{{ env_var('ICEBERG_CATALOG_URI') }}', SECRET r2_secret);"
+#before_all:
+# - "ATTACH '{{ env_var('ICEBERG_WAREHOUSE_NAME') }}' AS catalog (TYPE ICEBERG, ENDPOINT '{{ env_var('ICEBERG_CATALOG_URI') }}', SECRET r2_secret);"
+ # Note: R2 data access is configured via r2_data_secret (TYPE R2)
+ # Models can use r2://bucket/path to read landing data
# Note: CREATE SCHEMA has a DuckDB/Iceberg bug (missing Content-Type header)
# Schema must be pre-created in R2 Data Catalog via Cloudflare dashboard or API
# For now, skip USE statement and rely on fully-qualified table names in models
@@ -48,10 +71,10 @@ linter:
# FLOW: Minimal prompts, automatic changes, summary output
# https://sqlmesh.readthedocs.io/en/stable/reference/configuration/#plan
-plan:
- no_diff: true # Hide detailed text differences for changed models
- no_prompts: true # No interactive prompts
- auto_apply: true # Apply changes automatically
+#plan:
+# no_diff: true # Hide detailed text differences for changed models
+# no_prompts: true # No interactive prompts
+# auto_apply: true # Apply changes automatically
# --- Optional: Set a default target environment ---
# This is intended for local development to prevent users from accidentally applying plans to the prod environment.
@@ -59,7 +82,7 @@ plan:
# https://sqlmesh.readthedocs.io/en/stable/guides/configuration/#default-target-environment
# Uncomment the following line to use a default target environment derived from the logged in user's name.
-# default_target_environment: dev_{{ user() }}
+default_target_environment: dev_{{ user() }}
# Example usage:
# sqlmesh plan # Automatically resolves to: sqlmesh plan dev_yourname
diff --git a/transform/sqlmesh_materia/models/raw/psd_data.sql b/transform/sqlmesh_materia/models/raw/psd_data.sql
index 8f356cd..93acbcc 100644
--- a/transform/sqlmesh_materia/models/raw/psd_data.sql
+++ b/transform/sqlmesh_materia/models/raw/psd_data.sql
@@ -20,5 +20,5 @@ MODEL (
filename varchar
)
);
-SELECT *
- FROM read_csv('zip://extract/psdonline/src/psdonline/data/*.zip/*.csv', header=true, union_by_name=true, filename=true, names = ['commodity_code', 'commodity_description', 'country_code', 'country_name', 'market_year', 'calendar_year', 'month', 'attribute_id', 'attribute_description', 'unit_id', 'unit_description', 'value'], all_varchar=true)
+select *
+FROM read_csv('extract/psdonline/src/psdonline/data/*.csv.gzip', delim=',', encoding='utf-8', compression='gzip', max_line_size=10000000, header=true, union_by_name=true, filename=true, names = ['commodity_code', 'commodity_description', 'country_code', 'country_name', 'market_year', 'calendar_year', 'month', 'attribute_id', 'attribute_description', 'unit_id', 'unit_description', 'value'], all_varchar=true)
diff --git a/transform/sqlmesh_materia/models/README.md b/transform/sqlmesh_materia/models/readme.md
similarity index 100%
rename from transform/sqlmesh_materia/models/README.md
rename to transform/sqlmesh_materia/models/readme.md
diff --git a/transform/sqlmesh_materia/README.md b/transform/sqlmesh_materia/readme.md
similarity index 100%
rename from transform/sqlmesh_materia/README.md
rename to transform/sqlmesh_materia/readme.md
diff --git a/uv.lock b/uv.lock
index 0ca8631..49b292f 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1,5 +1,5 @@
version = 1
-revision = 2
+revision = 3
requires-python = ">=3.13"
resolution-markers = [
"python_full_version >= '3.14' and platform_python_implementation != 'PyPy'",
@@ -14,6 +14,29 @@ members = [
"sqlmesh-materia",
]
+[[package]]
+name = "aiosqlite"
+version = "0.22.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/4e/8a/64761f4005f17809769d23e518d915db74e6310474e733e3593cfc854ef1/aiosqlite-0.22.1.tar.gz", hash = "sha256:043e0bd78d32888c0a9ca90fc788b38796843360c855a7262a532813133a0650", size = 14821, upload-time = "2025-12-23T19:25:43.997Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/00/b7/e3bf5133d697a08128598c8d0abc5e16377b51465a33756de24fa7dee953/aiosqlite-0.22.1-py3-none-any.whl", hash = "sha256:21c002eb13823fad740196c5a2e9d8e62f6243bd9e7e4a1f87fb5e44ecb4fceb", size = 17405, upload-time = "2025-12-23T19:25:42.139Z" },
+]
+
+[[package]]
+name = "alembic"
+version = "1.18.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mako" },
+ { name = "sqlalchemy" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/79/41/ab8f624929847b49f84955c594b165855efd829b0c271e1a8cac694138e5/alembic-1.18.3.tar.gz", hash = "sha256:1212aa3778626f2b0f0aa6dd4e99a5f99b94bd25a0c1ac0bba3be65e081e50b0", size = 2052564, upload-time = "2026-01-29T20:24:15.124Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/45/8e/d79281f323e7469b060f15bd229e48d7cdd219559e67e71c013720a88340/alembic-1.18.3-py3-none-any.whl", hash = "sha256:12a0359bfc068a4ecbb9b3b02cf77856033abfdb59e4a5aca08b7eacd7b74ddd", size = 262282, upload-time = "2026-01-29T20:24:17.488Z" },
+]
+
[[package]]
name = "annotated-types"
version = "0.7.0"
@@ -45,6 +68,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" },
]
+[[package]]
+name = "apprise"
+version = "1.9.7"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "click" },
+ { name = "markdown" },
+ { name = "pyyaml" },
+ { name = "requests" },
+ { name = "requests-oauthlib" },
+ { name = "tzdata", marker = "sys_platform == 'win32'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/bc/f5/97dc06b3401bb67abcef6e8bef7155f192b75795c2a2aa4d59eb5aa7fa66/apprise-1.9.7.tar.gz", hash = "sha256:2f73cc1e0264fb119fdb9b7cde82e8fde40a0f531ac885d8c6f0cf0f6e13aec2", size = 1937173, upload-time = "2026-01-20T18:51:32.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/fb/6b/cfa80a13437896eb8f4504ddac6dfa4ef7f1d2b2261057aa4a30003b8de6/apprise-1.9.7-py3-none-any.whl", hash = "sha256:c7640a81a1097685de66e0508e3da89f49235d566cb44bbead1dd98419bf5ee3", size = 1459879, upload-time = "2026-01-20T18:51:30.766Z" },
+]
+
[[package]]
name = "arpeggio"
version = "2.0.3"
@@ -54,6 +95,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/84/4d/53b8186b41842f7a5e971b1d1c28e678364dcf841e4170f5d14d38ac1e2a/Arpeggio-2.0.3-py2.py3-none-any.whl", hash = "sha256:9374d9c531b62018b787635f37fd81c9a6ee69ef2d28c5db3cd18791b1f7db2f", size = 54656, upload-time = "2025-09-12T12:45:17.971Z" },
]
+[[package]]
+name = "asgi-lifespan"
+version = "2.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "sniffio" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/6a/da/e7908b54e0f8043725a990bf625f2041ecf6bfe8eb7b19407f1c00b630f7/asgi-lifespan-2.1.0.tar.gz", hash = "sha256:5e2effaf0bfe39829cf2d64e7ecc47c7d86d676a6599f7afba378c31f5e3a308", size = 15627, upload-time = "2023-03-28T17:35:49.126Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2f/f5/c36551e93acba41a59939ae6a0fb77ddb3f2e8e8caa716410c65f7341f72/asgi_lifespan-2.1.0-py3-none-any.whl", hash = "sha256:ed840706680e28428c01e14afb3875d7d76d3206f3d5b2f2294e059b5c23804f", size = 10895, upload-time = "2023-03-28T17:35:47.772Z" },
+]
+
[[package]]
name = "astor"
version = "0.8.1"
@@ -72,6 +125,38 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918, upload-time = "2024-11-30T04:30:10.946Z" },
]
+[[package]]
+name = "asyncpg"
+version = "0.31.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/fe/cc/d18065ce2380d80b1bcce927c24a2642efd38918e33fd724bc4bca904877/asyncpg-0.31.0.tar.gz", hash = "sha256:c989386c83940bfbd787180f2b1519415e2d3d6277a70d9d0f0145ac73500735", size = 993667, upload-time = "2025-11-24T23:27:00.812Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/95/11/97b5c2af72a5d0b9bc3fa30cd4b9ce22284a9a943a150fdc768763caf035/asyncpg-0.31.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c204fab1b91e08b0f47e90a75d1b3c62174dab21f670ad6c5d0f243a228f015b", size = 661111, upload-time = "2025-11-24T23:26:04.467Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/71/157d611c791a5e2d0423f09f027bd499935f0906e0c2a416ce712ba51ef3/asyncpg-0.31.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:54a64f91839ba59008eccf7aad2e93d6e3de688d796f35803235ea1c4898ae1e", size = 636928, upload-time = "2025-11-24T23:26:05.944Z" },
+ { url = "https://files.pythonhosted.org/packages/2e/fc/9e3486fb2bbe69d4a867c0b76d68542650a7ff1574ca40e84c3111bb0c6e/asyncpg-0.31.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0e0822b1038dc7253b337b0f3f676cadc4ac31b126c5d42691c39691962e403", size = 3424067, upload-time = "2025-11-24T23:26:07.957Z" },
+ { url = "https://files.pythonhosted.org/packages/12/c6/8c9d076f73f07f995013c791e018a1cd5f31823c2a3187fc8581706aa00f/asyncpg-0.31.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bef056aa502ee34204c161c72ca1f3c274917596877f825968368b2c33f585f4", size = 3518156, upload-time = "2025-11-24T23:26:09.591Z" },
+ { url = "https://files.pythonhosted.org/packages/ae/3b/60683a0baf50fbc546499cfb53132cb6835b92b529a05f6a81471ab60d0c/asyncpg-0.31.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0bfbcc5b7ffcd9b75ab1558f00db2ae07db9c80637ad1b2469c43df79d7a5ae2", size = 3319636, upload-time = "2025-11-24T23:26:11.168Z" },
+ { url = "https://files.pythonhosted.org/packages/50/dc/8487df0f69bd398a61e1792b3cba0e47477f214eff085ba0efa7eac9ce87/asyncpg-0.31.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:22bc525ebbdc24d1261ecbf6f504998244d4e3be1721784b5f64664d61fbe602", size = 3472079, upload-time = "2025-11-24T23:26:13.164Z" },
+ { url = "https://files.pythonhosted.org/packages/13/a1/c5bbeeb8531c05c89135cb8b28575ac2fac618bcb60119ee9696c3faf71c/asyncpg-0.31.0-cp313-cp313-win32.whl", hash = "sha256:f890de5e1e4f7e14023619399a471ce4b71f5418cd67a51853b9910fdfa73696", size = 527606, upload-time = "2025-11-24T23:26:14.78Z" },
+ { url = "https://files.pythonhosted.org/packages/91/66/b25ccb84a246b470eb943b0107c07edcae51804912b824054b3413995a10/asyncpg-0.31.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc5f2fa9916f292e5c5c8b2ac2813763bcd7f58e130055b4ad8a0531314201ab", size = 596569, upload-time = "2025-11-24T23:26:16.189Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/36/e9450d62e84a13aea6580c83a47a437f26c7ca6fa0f0fd40b6670793ea30/asyncpg-0.31.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f6b56b91bb0ffc328c4e3ed113136cddd9deefdf5f79ab448598b9772831df44", size = 660867, upload-time = "2025-11-24T23:26:17.631Z" },
+ { url = "https://files.pythonhosted.org/packages/82/4b/1d0a2b33b3102d210439338e1beea616a6122267c0df459ff0265cd5807a/asyncpg-0.31.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:334dec28cf20d7f5bb9e45b39546ddf247f8042a690bff9b9573d00086e69cb5", size = 638349, upload-time = "2025-11-24T23:26:19.689Z" },
+ { url = "https://files.pythonhosted.org/packages/41/aa/e7f7ac9a7974f08eff9183e392b2d62516f90412686532d27e196c0f0eeb/asyncpg-0.31.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98cc158c53f46de7bb677fd20c417e264fc02b36d901cc2a43bd6cb0dc6dbfd2", size = 3410428, upload-time = "2025-11-24T23:26:21.275Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/de/bf1b60de3dede5c2731e6788617a512bc0ebd9693eac297ee74086f101d7/asyncpg-0.31.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9322b563e2661a52e3cdbc93eed3be7748b289f792e0011cb2720d278b366ce2", size = 3471678, upload-time = "2025-11-24T23:26:23.627Z" },
+ { url = "https://files.pythonhosted.org/packages/46/78/fc3ade003e22d8bd53aaf8f75f4be48f0b460fa73738f0391b9c856a9147/asyncpg-0.31.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19857a358fc811d82227449b7ca40afb46e75b33eb8897240c3839dd8b744218", size = 3313505, upload-time = "2025-11-24T23:26:25.235Z" },
+ { url = "https://files.pythonhosted.org/packages/bf/e9/73eb8a6789e927816f4705291be21f2225687bfa97321e40cd23055e903a/asyncpg-0.31.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ba5f8886e850882ff2c2ace5732300e99193823e8107e2c53ef01c1ebfa1e85d", size = 3434744, upload-time = "2025-11-24T23:26:26.944Z" },
+ { url = "https://files.pythonhosted.org/packages/08/4b/f10b880534413c65c5b5862f79b8e81553a8f364e5238832ad4c0af71b7f/asyncpg-0.31.0-cp314-cp314-win32.whl", hash = "sha256:cea3a0b2a14f95834cee29432e4ddc399b95700eb1d51bbc5bfee8f31fa07b2b", size = 532251, upload-time = "2025-11-24T23:26:28.404Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/2d/7aa40750b7a19efa5d66e67fc06008ca0f27ba1bd082e457ad82f59aba49/asyncpg-0.31.0-cp314-cp314-win_amd64.whl", hash = "sha256:04d19392716af6b029411a0264d92093b6e5e8285ae97a39957b9a9c14ea72be", size = 604901, upload-time = "2025-11-24T23:26:30.34Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/fe/b9dfe349b83b9dee28cc42360d2c86b2cdce4cb551a2c2d27e156bcac84d/asyncpg-0.31.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bdb957706da132e982cc6856bb2f7b740603472b54c3ebc77fe60ea3e57e1bd2", size = 702280, upload-time = "2025-11-24T23:26:32Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/81/e6be6e37e560bd91e6c23ea8a6138a04fd057b08cf63d3c5055c98e81c1d/asyncpg-0.31.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6d11b198111a72f47154fa03b85799f9be63701e068b43f84ac25da0bda9cb31", size = 682931, upload-time = "2025-11-24T23:26:33.572Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/45/6009040da85a1648dd5bc75b3b0a062081c483e75a1a29041ae63a0bf0dc/asyncpg-0.31.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18c83b03bc0d1b23e6230f5bf8d4f217dc9bc08644ce0502a9d91dc9e634a9c7", size = 3581608, upload-time = "2025-11-24T23:26:35.638Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/06/2e3d4d7608b0b2b3adbee0d0bd6a2d29ca0fc4d8a78f8277df04e2d1fd7b/asyncpg-0.31.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e009abc333464ff18b8f6fd146addffd9aaf63e79aa3bb40ab7a4c332d0c5e9e", size = 3498738, upload-time = "2025-11-24T23:26:37.275Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/aa/7d75ede780033141c51d83577ea23236ba7d3a23593929b32b49db8ed36e/asyncpg-0.31.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3b1fbcb0e396a5ca435a8826a87e5c2c2cc0c8c68eb6fadf82168056b0e53a8c", size = 3401026, upload-time = "2025-11-24T23:26:39.423Z" },
+ { url = "https://files.pythonhosted.org/packages/ba/7a/15e37d45e7f7c94facc1e9148c0e455e8f33c08f0b8a0b1deb2c5171771b/asyncpg-0.31.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8df714dba348efcc162d2adf02d213e5fab1bd9f557e1305633e851a61814a7a", size = 3429426, upload-time = "2025-11-24T23:26:41.032Z" },
+ { url = "https://files.pythonhosted.org/packages/13/d5/71437c5f6ae5f307828710efbe62163974e71237d5d46ebd2869ea052d10/asyncpg-0.31.0-cp314-cp314t-win32.whl", hash = "sha256:1b41f1afb1033f2b44f3234993b15096ddc9cd71b21a42dbd87fc6a57b43d65d", size = 614495, upload-time = "2025-11-24T23:26:42.659Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/d7/8fb3044eaef08a310acfe23dae9a8e2e07d305edc29a53497e52bc76eca7/asyncpg-0.31.0-cp314-cp314t-win_amd64.whl", hash = "sha256:bd4107bb7cdd0e9e65fae66a62afd3a249663b844fa34d479f6d5b3bef9c04c3", size = 706062, upload-time = "2025-11-24T23:26:44.086Z" },
+]
+
[[package]]
name = "attrs"
version = "25.3.0"
@@ -147,6 +232,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/27/44/d2ef5e87509158ad2187f4dd0852df80695bb1ee0cfe0a684727b01a69e0/bcrypt-5.0.0-cp39-abi3-win_arm64.whl", hash = "sha256:f2347d3534e76bf50bca5500989d6c1d05ed64b440408057a37673282c654927", size = 144953, upload-time = "2025-09-25T19:50:37.32Z" },
]
+[[package]]
+name = "beartype"
+version = "0.22.9"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c7/94/1009e248bbfbab11397abca7193bea6626806be9a327d399810d523a07cb/beartype-0.22.9.tar.gz", hash = "sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f", size = 1608866, upload-time = "2025-12-13T06:50:30.72Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" },
+]
+
[[package]]
name = "boto3"
version = "1.40.55"
@@ -175,6 +269,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/21/30/f13bbc36e83b78777ff1abf50a084efcc3336b808e76560d8c5a0c9219e0/botocore-1.40.55-py3-none-any.whl", hash = "sha256:cdc38f7a4ddb30a2cd1cdd4fabde2a5a16e41b5a642292e1c30de5c4e46f5d44", size = 14116107, upload-time = "2025-10-17T19:34:44.398Z" },
]
+[[package]]
+name = "cachetools"
+version = "6.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/39/91/d9ae9a66b01102a18cd16db0cf4cd54187ffe10f0865cc80071a4104fbb3/cachetools-6.2.6.tar.gz", hash = "sha256:16c33e1f276b9a9c0b49ab5782d901e3ad3de0dd6da9bf9bcd29ac5672f2f9e6", size = 32363, upload-time = "2026-01-27T20:32:59.956Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/90/45/f458fa2c388e79dd9d8b9b0c99f1d31b568f27388f2fdba7bb66bbc0c6ed/cachetools-6.2.6-py3-none-any.whl", hash = "sha256:8c9717235b3c651603fff0076db52d6acbfd1b338b8ed50256092f7ce9c85bda", size = 11668, upload-time = "2026-01-27T20:32:58.527Z" },
+]
+
[[package]]
name = "cattrs"
version = "25.1.1"
@@ -294,6 +397,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" },
]
+[[package]]
+name = "cloudpickle"
+version = "3.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/27/fb/576f067976d320f5f0114a8d9fa1215425441bb35627b1993e5afd8111e5/cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414", size = 22330, upload-time = "2025-11-03T09:25:26.604Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a", size = 22228, upload-time = "2025-11-03T09:25:25.534Z" },
+]
+
[[package]]
name = "colorama"
version = "0.4.6"
@@ -312,6 +424,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" },
]
+[[package]]
+name = "coolname"
+version = "3.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/24/49/89681dae5d3fe5a2c8cbf108d12e3c10a5778b393ed5c3c2803faf49057b/coolname-3.0.0.tar.gz", hash = "sha256:01eb22437f77a904d5cb993842b3cd07e182e707014a82f3dfa31881968ecee1", size = 61161, upload-time = "2026-01-28T19:15:25.561Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/18/45/bd4b563055b87ccf007ec8b510d5a8cf963f3119951ab495b95a856364ec/coolname-3.0.0-py2.py3-none-any.whl", hash = "sha256:64fd6bc9dac1ef566eaa94e2829360c8dae8d63eb97d8853d39622d169849cbf", size = 39485, upload-time = "2026-01-28T19:15:24.205Z" },
+]
+
[[package]]
name = "coverage"
version = "7.10.7"
@@ -497,6 +618,20 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" },
]
+[[package]]
+name = "docker"
+version = "7.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pywin32", marker = "sys_platform == 'win32'" },
+ { name = "requests" },
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834, upload-time = "2024-05-23T11:13:57.216Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774, upload-time = "2024-05-23T11:13:55.01Z" },
+]
+
[[package]]
name = "duckdb"
version = "1.3.2"
@@ -512,6 +647,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/51/c9/2fcd86ab7530a5b6caff42dbe516ce7a86277e12c499d1c1f5acd266ffb2/duckdb-1.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:cd3d717bf9c49ef4b1016c2216517572258fa645c2923e91c5234053defa3fb5", size = 11395370, upload-time = "2025-07-08T10:40:57.655Z" },
]
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
[[package]]
name = "executing"
version = "2.2.0"
@@ -521,6 +665,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702, upload-time = "2025-01-22T15:41:25.929Z" },
]
+[[package]]
+name = "fakeredis"
+version = "2.33.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "redis" },
+ { name = "sortedcontainers" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/5f/f9/57464119936414d60697fcbd32f38909bb5688b616ae13de6e98384433e0/fakeredis-2.33.0.tar.gz", hash = "sha256:d7bc9a69d21df108a6451bbffee23b3eba432c21a654afc7ff2d295428ec5770", size = 175187, upload-time = "2025-12-16T19:45:52.269Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/6e/78/a850fed8aeef96d4a99043c90b818b2ed5419cd5b24a4049fd7cfb9f1471/fakeredis-2.33.0-py3-none-any.whl", hash = "sha256:de535f3f9ccde1c56672ab2fdd6a8efbc4f2619fc2f1acc87b8737177d71c965", size = 119605, upload-time = "2025-12-16T19:45:51.08Z" },
+]
+
+[package.optional-dependencies]
+lua = [
+ { name = "lupa" },
+]
+
[[package]]
name = "fastapi"
version = "0.115.5"
@@ -544,6 +706,70 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" },
]
+[[package]]
+name = "fsspec"
+version = "2026.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d5/7d/5df2650c57d47c57232af5ef4b4fdbff182070421e405e0d62c6cdbfaa87/fsspec-2026.1.0.tar.gz", hash = "sha256:e987cb0496a0d81bba3a9d1cee62922fb395e7d4c3b575e57f547953334fe07b", size = 310496, upload-time = "2026-01-09T15:21:35.562Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/01/c9/97cc5aae1648dcb851958a3ddf73ccd7dbe5650d95203ecb4d7720b4cdbf/fsspec-2026.1.0-py3-none-any.whl", hash = "sha256:cb76aa913c2285a3b49bdd5fc55b1d7c708d7208126b60f2eb8194fe1b4cbdcc", size = 201838, upload-time = "2026-01-09T15:21:34.041Z" },
+]
+
+[[package]]
+name = "graphviz"
+version = "0.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f8/b3/3ac91e9be6b761a4b30d66ff165e54439dcd48b83f4e20d644867215f6ca/graphviz-0.21.tar.gz", hash = "sha256:20743e7183be82aaaa8ad6c93f8893c923bd6658a04c32ee115edb3c8a835f78", size = 200434, upload-time = "2025-06-15T09:35:05.824Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl", hash = "sha256:54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42", size = 47300, upload-time = "2025-06-15T09:35:04.433Z" },
+]
+
+[[package]]
+name = "greenlet"
+version = "3.3.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/8a/99/1cd3411c56a410994669062bd73dd58270c00cc074cac15f385a1fd91f8a/greenlet-3.3.1.tar.gz", hash = "sha256:41848f3230b58c08bb43dee542e74a2a2e34d3c59dc3076cec9151aeeedcae98", size = 184690, upload-time = "2026-01-23T15:31:02.076Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ec/ab/d26750f2b7242c2b90ea2ad71de70cfcd73a948a49513188a0fc0d6fc15a/greenlet-3.3.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:7ab327905cabb0622adca5971e488064e35115430cec2c35a50fd36e72a315b3", size = 275205, upload-time = "2026-01-23T15:30:24.556Z" },
+ { url = "https://files.pythonhosted.org/packages/10/d3/be7d19e8fad7c5a78eeefb2d896a08cd4643e1e90c605c4be3b46264998f/greenlet-3.3.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:65be2f026ca6a176f88fb935ee23c18333ccea97048076aef4db1ef5bc0713ac", size = 599284, upload-time = "2026-01-23T16:00:58.584Z" },
+ { url = "https://files.pythonhosted.org/packages/ae/21/fe703aaa056fdb0f17e5afd4b5c80195bbdab701208918938bd15b00d39b/greenlet-3.3.1-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7a3ae05b3d225b4155bda56b072ceb09d05e974bc74be6c3fc15463cf69f33fd", size = 610274, upload-time = "2026-01-23T16:05:29.312Z" },
+ { url = "https://files.pythonhosted.org/packages/06/00/95df0b6a935103c0452dad2203f5be8377e551b8466a29650c4c5a5af6cc/greenlet-3.3.1-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:12184c61e5d64268a160226fb4818af4df02cfead8379d7f8b99a56c3a54ff3e", size = 624375, upload-time = "2026-01-23T16:15:55.915Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/86/5c6ab23bb3c28c21ed6bebad006515cfe08b04613eb105ca0041fecca852/greenlet-3.3.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6423481193bbbe871313de5fd06a082f2649e7ce6e08015d2a76c1e9186ca5b3", size = 612904, upload-time = "2026-01-23T15:32:52.317Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/f3/7949994264e22639e40718c2daf6f6df5169bf48fb038c008a489ec53a50/greenlet-3.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:33a956fe78bbbda82bfc95e128d61129b32d66bcf0a20a1f0c08aa4839ffa951", size = 1567316, upload-time = "2026-01-23T16:04:23.316Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/6e/d73c94d13b6465e9f7cd6231c68abde838bb22408596c05d9059830b7872/greenlet-3.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b065d3284be43728dd280f6f9a13990b56470b81be20375a207cdc814a983f2", size = 1636549, upload-time = "2026-01-23T15:33:48.643Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/b3/c9c23a6478b3bcc91f979ce4ca50879e4d0b2bd7b9a53d8ecded719b92e2/greenlet-3.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:27289986f4e5b0edec7b5a91063c109f0276abb09a7e9bdab08437525977c946", size = 227042, upload-time = "2026-01-23T15:33:58.216Z" },
+ { url = "https://files.pythonhosted.org/packages/90/e7/824beda656097edee36ab15809fd063447b200cc03a7f6a24c34d520bc88/greenlet-3.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:2f080e028001c5273e0b42690eaf359aeef9cb1389da0f171ea51a5dc3c7608d", size = 226294, upload-time = "2026-01-23T15:30:52.73Z" },
+ { url = "https://files.pythonhosted.org/packages/ae/fb/011c7c717213182caf78084a9bea51c8590b0afda98001f69d9f853a495b/greenlet-3.3.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:bd59acd8529b372775cd0fcbc5f420ae20681c5b045ce25bd453ed8455ab99b5", size = 275737, upload-time = "2026-01-23T15:32:16.889Z" },
+ { url = "https://files.pythonhosted.org/packages/41/2e/a3a417d620363fdbb08a48b1dd582956a46a61bf8fd27ee8164f9dfe87c2/greenlet-3.3.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b31c05dd84ef6871dd47120386aed35323c944d86c3d91a17c4b8d23df62f15b", size = 646422, upload-time = "2026-01-23T16:01:00.354Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/09/c6c4a0db47defafd2d6bab8ddfe47ad19963b4e30f5bed84d75328059f8c/greenlet-3.3.1-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:02925a0bfffc41e542c70aa14c7eda3593e4d7e274bfcccca1827e6c0875902e", size = 658219, upload-time = "2026-01-23T16:05:30.956Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/89/b95f2ddcc5f3c2bc09c8ee8d77be312df7f9e7175703ab780f2014a0e781/greenlet-3.3.1-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3e0f3878ca3a3ff63ab4ea478585942b53df66ddde327b59ecb191b19dbbd62d", size = 671455, upload-time = "2026-01-23T16:15:57.232Z" },
+ { url = "https://files.pythonhosted.org/packages/80/38/9d42d60dffb04b45f03dbab9430898352dba277758640751dc5cc316c521/greenlet-3.3.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34a729e2e4e4ffe9ae2408d5ecaf12f944853f40ad724929b7585bca808a9d6f", size = 660237, upload-time = "2026-01-23T15:32:53.967Z" },
+ { url = "https://files.pythonhosted.org/packages/96/61/373c30b7197f9e756e4c81ae90a8d55dc3598c17673f91f4d31c3c689c3f/greenlet-3.3.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aec9ab04e82918e623415947921dea15851b152b822661cce3f8e4393c3df683", size = 1615261, upload-time = "2026-01-23T16:04:25.066Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/d3/ca534310343f5945316f9451e953dcd89b36fe7a19de652a1dc5a0eeef3f/greenlet-3.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:71c767cf281a80d02b6c1bdc41c9468e1f5a494fb11bc8688c360524e273d7b1", size = 1683719, upload-time = "2026-01-23T15:33:50.61Z" },
+ { url = "https://files.pythonhosted.org/packages/52/cb/c21a3fd5d2c9c8b622e7bede6d6d00e00551a5ee474ea6d831b5f567a8b4/greenlet-3.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:96aff77af063b607f2489473484e39a0bbae730f2ea90c9e5606c9b73c44174a", size = 228125, upload-time = "2026-01-23T15:32:45.265Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/8e/8a2db6d11491837af1de64b8aff23707c6e85241be13c60ed399a72e2ef8/greenlet-3.3.1-cp314-cp314-win_arm64.whl", hash = "sha256:b066e8b50e28b503f604fa538adc764a638b38cf8e81e025011d26e8a627fa79", size = 227519, upload-time = "2026-01-23T15:31:47.284Z" },
+ { url = "https://files.pythonhosted.org/packages/28/24/cbbec49bacdcc9ec652a81d3efef7b59f326697e7edf6ed775a5e08e54c2/greenlet-3.3.1-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:3e63252943c921b90abb035ebe9de832c436401d9c45f262d80e2d06cc659242", size = 282706, upload-time = "2026-01-23T15:33:05.525Z" },
+ { url = "https://files.pythonhosted.org/packages/86/2e/4f2b9323c144c4fe8842a4e0d92121465485c3c2c5b9e9b30a52e80f523f/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:76e39058e68eb125de10c92524573924e827927df5d3891fbc97bd55764a8774", size = 651209, upload-time = "2026-01-23T16:01:01.517Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/87/50ca60e515f5bb55a2fbc5f0c9b5b156de7d2fc51a0a69abc9d23914a237/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9f9d5e7a9310b7a2f416dd13d2e3fd8b42d803968ea580b7c0f322ccb389b97", size = 654300, upload-time = "2026-01-23T16:05:32.199Z" },
+ { url = "https://files.pythonhosted.org/packages/7c/25/c51a63f3f463171e09cb586eb64db0861eb06667ab01a7968371a24c4f3b/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b9721549a95db96689458a1e0ae32412ca18776ed004463df3a9299c1b257ab", size = 662574, upload-time = "2026-01-23T16:15:58.364Z" },
+ { url = "https://files.pythonhosted.org/packages/1d/94/74310866dfa2b73dd08659a3d18762f83985ad3281901ba0ee9a815194fb/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92497c78adf3ac703b57f1e3813c2d874f27f71a178f9ea5887855da413cd6d2", size = 653842, upload-time = "2026-01-23T15:32:55.671Z" },
+ { url = "https://files.pythonhosted.org/packages/97/43/8bf0ffa3d498eeee4c58c212a3905dd6146c01c8dc0b0a046481ca29b18c/greenlet-3.3.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ed6b402bc74d6557a705e197d47f9063733091ed6357b3de33619d8a8d93ac53", size = 1614917, upload-time = "2026-01-23T16:04:26.276Z" },
+ { url = "https://files.pythonhosted.org/packages/89/90/a3be7a5f378fc6e84abe4dcfb2ba32b07786861172e502388b4c90000d1b/greenlet-3.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:59913f1e5ada20fde795ba906916aea25d442abcc0593fba7e26c92b7ad76249", size = 1676092, upload-time = "2026-01-23T15:33:52.176Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/2b/98c7f93e6db9977aaee07eb1e51ca63bd5f779b900d362791d3252e60558/greenlet-3.3.1-cp314-cp314t-win_amd64.whl", hash = "sha256:301860987846c24cb8964bdec0e31a96ad4a2a801b41b4ef40963c1b44f33451", size = 233181, upload-time = "2026-01-23T15:33:00.29Z" },
+]
+
+[[package]]
+name = "griffe"
+version = "1.15.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/0d/0c/3a471b6e31951dce2360477420d0a8d1e00dea6cf33b70f3e8c3ab6e28e1/griffe-1.15.0.tar.gz", hash = "sha256:7726e3afd6f298fbc3696e67958803e7ac843c1cfe59734b6251a40cdbfb5eea", size = 424112, upload-time = "2025-11-10T15:03:15.52Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9c/83/3b1d03d36f224edded98e9affd0467630fc09d766c0e56fb1498cbb04a9b/griffe-1.15.0-py3-none-any.whl", hash = "sha256:6f6762661949411031f5fcda9593f586e6ce8340f0ba88921a0f2ef7a81eb9a3", size = 150705, upload-time = "2025-11-10T15:03:13.549Z" },
+]
+
[[package]]
name = "grpcio"
version = "1.75.1"
@@ -584,6 +810,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
]
+[[package]]
+name = "h2"
+version = "4.3.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "hpack" },
+ { name = "hyperframe" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/1d/17/afa56379f94ad0fe8defd37d6eb3f89a25404ffc71d4d848893d270325fc/h2-4.3.0.tar.gz", hash = "sha256:6c59efe4323fa18b47a632221a1888bd7fde6249819beda254aeca909f221bf1", size = 2152026, upload-time = "2025-08-23T18:12:19.778Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/69/b2/119f6e6dcbd96f9069ce9a2665e0146588dc9f88f29549711853645e736a/h2-4.3.0-py3-none-any.whl", hash = "sha256:c438f029a25f7945c69e0ccf0fb951dc3f73a5f6412981daee861431b70e2bdd", size = 61779, upload-time = "2025-08-23T18:12:17.779Z" },
+]
+
[[package]]
name = "hcloud"
version = "2.8.0"
@@ -597,6 +836,28 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/76/de/95b8aac296fec6818236eb1cc173ff699ebc597cd160a410743f655cc5ac/hcloud-2.8.0-py3-none-any.whl", hash = "sha256:575db85fbb2558851a9ffcbaacbf2fdf744a097cb05debec0a009913771236fb", size = 97523, upload-time = "2025-10-07T08:21:03.048Z" },
]
+[[package]]
+name = "hpack"
+version = "4.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/2c/48/71de9ed269fdae9c8057e5a4c0aa7402e8bb16f2c6e90b3aa53327b113f8/hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca", size = 51276, upload-time = "2025-01-22T21:44:58.347Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/07/c6/80c95b1b2b94682a72cbdbfb85b81ae2daffa4291fbfa1b1464502ede10d/hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496", size = 34357, upload-time = "2025-01-22T21:44:56.92Z" },
+]
+
+[[package]]
+name = "httpcore"
+version = "1.0.9"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "h11" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
+]
+
[[package]]
name = "httptools"
version = "0.6.4"
@@ -612,6 +873,44 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8", size = 87682, upload-time = "2024-10-16T19:44:46.46Z" },
]
+[[package]]
+name = "httpx"
+version = "0.28.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "anyio" },
+ { name = "certifi" },
+ { name = "httpcore" },
+ { name = "idna" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
+]
+
+[package.optional-dependencies]
+http2 = [
+ { name = "h2" },
+]
+
+[[package]]
+name = "humanize"
+version = "4.15.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ba/66/a3921783d54be8a6870ac4ccffcd15c4dc0dd7fcce51c6d63b8c63935276/humanize-4.15.0.tar.gz", hash = "sha256:1dd098483eb1c7ee8e32eb2e99ad1910baefa4b75c3aff3a82f4d78688993b10", size = 83599, upload-time = "2025-12-20T20:16:13.19Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c5/7b/bca5613a0c3b542420cf92bd5e5fb8ebd5435ce1011a091f66bb7693285e/humanize-4.15.0-py3-none-any.whl", hash = "sha256:b1186eb9f5a9749cd9cb8565aee77919dd7c8d076161cf44d70e59e3301e1769", size = 132203, upload-time = "2025-12-20T20:16:11.67Z" },
+]
+
+[[package]]
+name = "hyperframe"
+version = "6.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/02/e7/94f8232d4a74cc99514c13a9f995811485a6903d48e5d952771ef6322e30/hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08", size = 26566, upload-time = "2025-01-22T21:41:49.302Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/48/30/47d0bf6072f7252e6521f3447ccfa40b421b6824517f82854703d0f5a98b/hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5", size = 13007, upload-time = "2025-01-22T21:41:47.295Z" },
+]
+
[[package]]
name = "hyperscript"
version = "0.3.0"
@@ -639,6 +938,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
]
+[[package]]
+name = "importlib-metadata"
+version = "8.7.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "zipp" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" },
+]
+
[[package]]
name = "iniconfig"
version = "2.1.0"
@@ -793,6 +1104,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
]
+[[package]]
+name = "jinja2-humanize-extension"
+version = "0.4.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "humanize" },
+ { name = "jinja2" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/74/77/0bba383819dd4e67566487c11c49479ced87e77c3285d8e7f7a3401cf882/jinja2_humanize_extension-0.4.0.tar.gz", hash = "sha256:e7d69b1c20f32815bbec722330ee8af14b1287bb1c2b0afa590dbf031cadeaa0", size = 4746, upload-time = "2023-09-01T12:52:42.781Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/26/b4/08c9d297edd5e1182506edecccbb88a92e1122a057953068cadac420ca5d/jinja2_humanize_extension-0.4.0-py3-none-any.whl", hash = "sha256:b6326e2da0f7d425338bebf58848e830421defbce785f12ae812e65128518156", size = 4769, upload-time = "2023-09-01T12:52:41.098Z" },
+]
+
[[package]]
name = "jmespath"
version = "1.0.1"
@@ -830,6 +1154,54 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/17/1c/84f79b4e9702160f9da874ec279e52b2ca8c20ddbfe6ba9207fa420fdaf9/json_stream_rs_tokenizer-0.4.30-cp313-cp313-win_amd64.whl", hash = "sha256:3069d9bf2f65b5c64847808a9179535526b9ec68f6783506814f1f4dc261b93a", size = 181496, upload-time = "2025-08-12T23:05:19.309Z" },
]
+[[package]]
+name = "jsonpatch"
+version = "1.33"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jsonpointer" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/42/78/18813351fe5d63acad16aec57f94ec2b70a09e53ca98145589e185423873/jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c", size = 21699, upload-time = "2023-06-26T12:07:29.144Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/73/07/02e16ed01e04a374e644b575638ec7987ae846d25ad97bcc9945a3ee4b0e/jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade", size = 12898, upload-time = "2023-06-16T21:01:28.466Z" },
+]
+
+[[package]]
+name = "jsonpointer"
+version = "3.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" },
+]
+
+[[package]]
+name = "jsonschema"
+version = "4.26.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "attrs" },
+ { name = "jsonschema-specifications" },
+ { name = "referencing" },
+ { name = "rpds-py" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" },
+]
+
+[[package]]
+name = "jsonschema-specifications"
+version = "2025.9.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "referencing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" },
+]
+
[[package]]
name = "jupyter-client"
version = "8.6.3"
@@ -882,6 +1254,68 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8d/37/2351e48cb3309673492d3a8c59d407b75fb6630e560eb27ecd4da03adc9a/lsprotocol-2023.0.1-py3-none-any.whl", hash = "sha256:c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2", size = 70826, upload-time = "2024-01-09T17:21:14.491Z" },
]
+[[package]]
+name = "lupa"
+version = "2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b8/1c/191c3e6ec6502e3dbe25a53e27f69a5daeac3e56de1f73c0138224171ead/lupa-2.6.tar.gz", hash = "sha256:9a770a6e89576be3447668d7ced312cd6fd41d3c13c2462c9dc2c2ab570e45d9", size = 7240282, upload-time = "2025-10-24T07:20:29.738Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/28/1d/21176b682ca5469001199d8b95fa1737e29957a3d185186e7a8b55345f2e/lupa-2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:663a6e58a0f60e7d212017d6678639ac8df0119bc13c2145029dcba084391310", size = 947232, upload-time = "2025-10-24T07:18:27.878Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/4c/d327befb684660ca13cf79cd1f1d604331808f9f1b6fb6bf57832f8edf80/lupa-2.6-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:d1f5afda5c20b1f3217a80e9bc1b77037f8a6eb11612fd3ada19065303c8f380", size = 1908625, upload-time = "2025-10-24T07:18:29.944Z" },
+ { url = "https://files.pythonhosted.org/packages/66/8e/ad22b0a19454dfd08662237a84c792d6d420d36b061f239e084f29d1a4f3/lupa-2.6-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:26f2b3c085fe76e9119e48c1013c1cccdc1f51585d456858290475aa38e7089e", size = 981057, upload-time = "2025-10-24T07:18:31.553Z" },
+ { url = "https://files.pythonhosted.org/packages/5c/48/74859073ab276bd0566c719f9ca0108b0cfc1956ca0d68678d117d47d155/lupa-2.6-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:60d2f902c7b96fb8ab98493dcff315e7bb4d0b44dc9dd76eb37de575025d5685", size = 1156227, upload-time = "2025-10-24T07:18:33.981Z" },
+ { url = "https://files.pythonhosted.org/packages/09/6c/0e9ded061916877253c2266074060eb71ed99fb21d73c8c114a76725bce2/lupa-2.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a02d25dee3a3250967c36590128d9220ae02f2eda166a24279da0b481519cbff", size = 1035752, upload-time = "2025-10-24T07:18:36.32Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/ef/f8c32e454ef9f3fe909f6c7d57a39f950996c37a3deb7b391fec7903dab7/lupa-2.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6eae1ee16b886b8914ff292dbefbf2f48abfbdee94b33a88d1d5475e02423203", size = 2069009, upload-time = "2025-10-24T07:18:38.072Z" },
+ { url = "https://files.pythonhosted.org/packages/53/dc/15b80c226a5225815a890ee1c11f07968e0aba7a852df41e8ae6fe285063/lupa-2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0edd5073a4ee74ab36f74fe61450148e6044f3952b8d21248581f3c5d1a58be", size = 1056301, upload-time = "2025-10-24T07:18:40.165Z" },
+ { url = "https://files.pythonhosted.org/packages/31/14/2086c1425c985acfb30997a67e90c39457122df41324d3c179d6ee2292c6/lupa-2.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0c53ee9f22a8a17e7d4266ad48e86f43771951797042dd51d1494aaa4f5f3f0a", size = 1170673, upload-time = "2025-10-24T07:18:42.426Z" },
+ { url = "https://files.pythonhosted.org/packages/10/e5/b216c054cf86576c0191bf9a9f05de6f7e8e07164897d95eea0078dca9b2/lupa-2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:de7c0f157a9064a400d828789191a96da7f4ce889969a588b87ec80de9b14772", size = 2162227, upload-time = "2025-10-24T07:18:46.112Z" },
+ { url = "https://files.pythonhosted.org/packages/59/2f/33ecb5bedf4f3bc297ceacb7f016ff951331d352f58e7e791589609ea306/lupa-2.6-cp313-cp313-win32.whl", hash = "sha256:ee9523941ae0a87b5b703417720c5d78f72d2f5bc23883a2ea80a949a3ed9e75", size = 1419558, upload-time = "2025-10-24T07:18:48.371Z" },
+ { url = "https://files.pythonhosted.org/packages/f9/b4/55e885834c847ea610e111d87b9ed4768f0afdaeebc00cd46810f25029f6/lupa-2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b1335a5835b0a25ebdbc75cf0bda195e54d133e4d994877ef025e218c2e59db9", size = 1683424, upload-time = "2025-10-24T07:18:50.976Z" },
+ { url = "https://files.pythonhosted.org/packages/66/9d/d9427394e54d22a35d1139ef12e845fd700d4872a67a34db32516170b746/lupa-2.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dcb6d0a3264873e1653bc188499f48c1fb4b41a779e315eba45256cfe7bc33c1", size = 953818, upload-time = "2025-10-24T07:18:53.378Z" },
+ { url = "https://files.pythonhosted.org/packages/10/41/27bbe81953fb2f9ecfced5d9c99f85b37964cfaf6aa8453bb11283983721/lupa-2.6-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:a37e01f2128f8c36106726cb9d360bac087d58c54b4522b033cc5691c584db18", size = 1915850, upload-time = "2025-10-24T07:18:55.259Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/98/f9ff60db84a75ba8725506bbf448fb085bc77868a021998ed2a66d920568/lupa-2.6-cp314-cp314-macosx_11_0_x86_64.whl", hash = "sha256:458bd7e9ff3c150b245b0fcfbb9bd2593d1152ea7f0a7b91c1d185846da033fe", size = 982344, upload-time = "2025-10-24T07:18:57.05Z" },
+ { url = "https://files.pythonhosted.org/packages/41/f7/f39e0f1c055c3b887d86b404aaf0ca197b5edfd235a8b81b45b25bac7fc3/lupa-2.6-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:052ee82cac5206a02df77119c325339acbc09f5ce66967f66a2e12a0f3211cad", size = 1156543, upload-time = "2025-10-24T07:18:59.251Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/9c/59e6cffa0d672d662ae17bd7ac8ecd2c89c9449dee499e3eb13ca9cd10d9/lupa-2.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96594eca3c87dd07938009e95e591e43d554c1dbd0385be03c100367141db5a8", size = 1047974, upload-time = "2025-10-24T07:19:01.449Z" },
+ { url = "https://files.pythonhosted.org/packages/23/c6/a04e9cef7c052717fcb28fb63b3824802488f688391895b618e39be0f684/lupa-2.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8faddd9d198688c8884091173a088a8e920ecc96cda2ffed576a23574c4b3f6", size = 2073458, upload-time = "2025-10-24T07:19:03.369Z" },
+ { url = "https://files.pythonhosted.org/packages/e6/10/824173d10f38b51fc77785228f01411b6ca28826ce27404c7c912e0e442c/lupa-2.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:daebb3a6b58095c917e76ba727ab37b27477fb926957c825205fbda431552134", size = 1067683, upload-time = "2025-10-24T07:19:06.2Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/dc/9692fbcf3c924d9c4ece2d8d2f724451ac2e09af0bd2a782db1cef34e799/lupa-2.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f3154e68972befe0f81564e37d8142b5d5d79931a18309226a04ec92487d4ea3", size = 1171892, upload-time = "2025-10-24T07:19:08.544Z" },
+ { url = "https://files.pythonhosted.org/packages/84/ff/e318b628d4643c278c96ab3ddea07fc36b075a57383c837f5b11e537ba9d/lupa-2.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e4dadf77b9fedc0bfa53417cc28dc2278a26d4cbd95c29f8927ad4d8fe0a7ef9", size = 2166641, upload-time = "2025-10-24T07:19:10.485Z" },
+ { url = "https://files.pythonhosted.org/packages/12/f7/a6f9ec2806cf2d50826980cdb4b3cffc7691dc6f95e13cc728846d5cb793/lupa-2.6-cp314-cp314-win32.whl", hash = "sha256:cb34169c6fa3bab3e8ac58ca21b8a7102f6a94b6a5d08d3636312f3f02fafd8f", size = 1456857, upload-time = "2025-10-24T07:19:37.989Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/de/df71896f25bdc18360fdfa3b802cd7d57d7fede41a0e9724a4625b412c85/lupa-2.6-cp314-cp314-win_amd64.whl", hash = "sha256:b74f944fe46c421e25d0f8692aef1e842192f6f7f68034201382ac440ef9ea67", size = 1731191, upload-time = "2025-10-24T07:19:40.281Z" },
+ { url = "https://files.pythonhosted.org/packages/47/3c/a1f23b01c54669465f5f4c4083107d496fbe6fb45998771420e9aadcf145/lupa-2.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0e21b716408a21ab65723f8841cf7f2f37a844b7a965eeabb785e27fca4099cf", size = 999343, upload-time = "2025-10-24T07:19:12.519Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/6d/501994291cb640bfa2ccf7f554be4e6914afa21c4026bd01bff9ca8aac57/lupa-2.6-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:589db872a141bfff828340079bbdf3e9a31f2689f4ca0d88f97d9e8c2eae6142", size = 2000730, upload-time = "2025-10-24T07:19:14.869Z" },
+ { url = "https://files.pythonhosted.org/packages/53/a5/457ffb4f3f20469956c2d4c4842a7675e884efc895b2f23d126d23e126cc/lupa-2.6-cp314-cp314t-macosx_11_0_x86_64.whl", hash = "sha256:cd852a91a4a9d4dcbb9a58100f820a75a425703ec3e3f049055f60b8533b7953", size = 1021553, upload-time = "2025-10-24T07:19:17.123Z" },
+ { url = "https://files.pythonhosted.org/packages/51/6b/36bb5a5d0960f2a5c7c700e0819abb76fd9bf9c1d8a66e5106416d6e9b14/lupa-2.6-cp314-cp314t-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:0334753be028358922415ca97a64a3048e4ed155413fc4eaf87dd0a7e2752983", size = 1133275, upload-time = "2025-10-24T07:19:20.51Z" },
+ { url = "https://files.pythonhosted.org/packages/19/86/202ff4429f663013f37d2229f6176ca9f83678a50257d70f61a0a97281bf/lupa-2.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:661d895cd38c87658a34780fac54a690ec036ead743e41b74c3fb81a9e65a6aa", size = 1038441, upload-time = "2025-10-24T07:19:22.509Z" },
+ { url = "https://files.pythonhosted.org/packages/a7/42/d8125f8e420714e5b52e9c08d88b5329dfb02dcca731b4f21faaee6cc5b5/lupa-2.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aa58454ccc13878cc177c62529a2056be734da16369e451987ff92784994ca7", size = 2058324, upload-time = "2025-10-24T07:19:24.979Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/2c/47bf8b84059876e877a339717ddb595a4a7b0e8740bacae78ba527562e1c/lupa-2.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1425017264e470c98022bba8cff5bd46d054a827f5df6b80274f9cc71dafd24f", size = 1060250, upload-time = "2025-10-24T07:19:27.262Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/06/d88add2b6406ca1bdec99d11a429222837ca6d03bea42ca75afa169a78cb/lupa-2.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:224af0532d216e3105f0a127410f12320f7c5f1aa0300bdf9646b8d9afb0048c", size = 1151126, upload-time = "2025-10-24T07:19:29.522Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/a0/89e6a024c3b4485b89ef86881c9d55e097e7cb0bdb74efb746f2fa6a9a76/lupa-2.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9abb98d5a8fd27c8285302e82199f0e56e463066f88f619d6594a450bf269d80", size = 2153693, upload-time = "2025-10-24T07:19:31.379Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/36/a0f007dc58fc1bbf51fb85dcc82fcb1f21b8c4261361de7dab0e3d8521ef/lupa-2.6-cp314-cp314t-win32.whl", hash = "sha256:1849efeba7a8f6fb8aa2c13790bee988fd242ae404bd459509640eeea3d1e291", size = 1590104, upload-time = "2025-10-24T07:19:33.514Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/5e/db903ce9cf82c48d6b91bf6d63ae4c8d0d17958939a4e04ba6b9f38b8643/lupa-2.6-cp314-cp314t-win_amd64.whl", hash = "sha256:fc1498d1a4fc028bc521c26d0fad4ca00ed63b952e32fb95949bda76a04bad52", size = 1913818, upload-time = "2025-10-24T07:19:36.039Z" },
+]
+
+[[package]]
+name = "mako"
+version = "1.3.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markupsafe" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/9e/38/bd5b78a920a64d708fe6bc8e0a2c075e1389d53bef8413725c63ba041535/mako-1.3.10.tar.gz", hash = "sha256:99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28", size = 392474, upload-time = "2025-04-10T12:44:31.16Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl", hash = "sha256:baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59", size = 78509, upload-time = "2025-04-10T12:50:53.297Z" },
+]
+
+[[package]]
+name = "markdown"
+version = "3.10.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b7/b1/af95bcae8549f1f3fd70faacb29075826a0d689a27f232e8cee315efa053/markdown-3.10.1.tar.gz", hash = "sha256:1c19c10bd5c14ac948c53d0d762a04e2fa35a6d58a6b7b1e6bfcbe6fefc0001a", size = 365402, upload-time = "2026-01-21T18:09:28.206Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/59/1b/6ef961f543593969d25b2afe57a3564200280528caa9bd1082eecdd7b3bc/markdown-3.10.1-py3-none-any.whl", hash = "sha256:867d788939fe33e4b736426f5b9f651ad0c0ae0ecf89df0ca5d1176c70812fe3", size = 107684, upload-time = "2026-01-21T18:09:27.203Z" },
+]
+
[[package]]
name = "markdown-it-py"
version = "4.0.0"
@@ -930,6 +1364,7 @@ dependencies = [
{ name = "hcloud" },
{ name = "niquests" },
{ name = "paramiko" },
+ { name = "prefect" },
{ name = "pyarrow" },
{ name = "python-dotenv" },
{ name = "pyyaml" },
@@ -956,6 +1391,7 @@ requires-dist = [
{ name = "hcloud", specifier = ">=2.8.0" },
{ name = "niquests", specifier = ">=3.15.2" },
{ name = "paramiko", specifier = ">=3.5.0" },
+ { name = "prefect", specifier = ">=3.6.15" },
{ name = "pyarrow", specifier = ">=20.0.0" },
{ name = "python-dotenv", specifier = ">=1.1.0" },
{ name = "pyyaml", specifier = ">=6.0.2" },
@@ -1080,6 +1516,66 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c1/9e/1652778bce745a67b5fe05adde60ed362d38eb17d919a540e813d30f6874/numpy-2.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631", size = 10544226, upload-time = "2025-07-24T20:56:34.509Z" },
]
+[[package]]
+name = "oauthlib"
+version = "3.3.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0b/5f/19930f824ffeb0ad4372da4812c50edbd1434f678c90c2733e1188edfc63/oauthlib-3.3.1.tar.gz", hash = "sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9", size = 185918, upload-time = "2025-06-19T22:48:08.269Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/be/9c/92789c596b8df838baa98fa71844d84283302f7604ed565dafe5a6b5041a/oauthlib-3.3.1-py3-none-any.whl", hash = "sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1", size = 160065, upload-time = "2025-06-19T22:48:06.508Z" },
+]
+
+[[package]]
+name = "opentelemetry-api"
+version = "1.39.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "importlib-metadata" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/97/b9/3161be15bb8e3ad01be8be5a968a9237c3027c5be504362ff800fca3e442/opentelemetry_api-1.39.1.tar.gz", hash = "sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c", size = 65767, upload-time = "2025-12-11T13:32:39.182Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cf/df/d3f1ddf4bb4cb50ed9b1139cc7b1c54c34a1e7ce8fd1b9a37c0d1551a6bd/opentelemetry_api-1.39.1-py3-none-any.whl", hash = "sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950", size = 66356, upload-time = "2025-12-11T13:32:17.304Z" },
+]
+
+[[package]]
+name = "orjson"
+version = "3.11.7"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/53/45/b268004f745ede84e5798b48ee12b05129d19235d0e15267aa57dcdb400b/orjson-3.11.7.tar.gz", hash = "sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49", size = 6144992, upload-time = "2026-02-02T15:38:49.29Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/89/25/6e0e52cac5aab51d7b6dcd257e855e1dec1c2060f6b28566c509b4665f62/orjson-3.11.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733", size = 228390, upload-time = "2026-02-02T15:38:06.8Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/29/a77f48d2fc8a05bbc529e5ff481fb43d914f9e383ea2469d4f3d51df3d00/orjson-3.11.7-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4", size = 125189, upload-time = "2026-02-02T15:38:08.181Z" },
+ { url = "https://files.pythonhosted.org/packages/89/25/0a16e0729a0e6a1504f9d1a13cdd365f030068aab64cec6958396b9969d7/orjson-3.11.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785", size = 128106, upload-time = "2026-02-02T15:38:09.41Z" },
+ { url = "https://files.pythonhosted.org/packages/66/da/a2e505469d60666a05ab373f1a6322eb671cb2ba3a0ccfc7d4bc97196787/orjson-3.11.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539", size = 123363, upload-time = "2026-02-02T15:38:10.73Z" },
+ { url = "https://files.pythonhosted.org/packages/23/bf/ed73f88396ea35c71b38961734ea4a4746f7ca0768bf28fd551d37e48dd0/orjson-3.11.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1", size = 129007, upload-time = "2026-02-02T15:38:12.138Z" },
+ { url = "https://files.pythonhosted.org/packages/73/3c/b05d80716f0225fc9008fbf8ab22841dcc268a626aa550561743714ce3bf/orjson-3.11.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1", size = 141667, upload-time = "2026-02-02T15:38:13.398Z" },
+ { url = "https://files.pythonhosted.org/packages/61/e8/0be9b0addd9bf86abfc938e97441dcd0375d494594b1c8ad10fe57479617/orjson-3.11.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705", size = 130832, upload-time = "2026-02-02T15:38:14.698Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/ec/c68e3b9021a31d9ec15a94931db1410136af862955854ed5dd7e7e4f5bff/orjson-3.11.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace", size = 133373, upload-time = "2026-02-02T15:38:16.109Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/45/f3466739aaafa570cc8e77c6dbb853c48bf56e3b43738020e2661e08b0ac/orjson-3.11.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b", size = 138307, upload-time = "2026-02-02T15:38:17.453Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/84/9f7f02288da1ffb31405c1be07657afd1eecbcb4b64ee2817b6fe0f785fa/orjson-3.11.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157", size = 408695, upload-time = "2026-02-02T15:38:18.831Z" },
+ { url = "https://files.pythonhosted.org/packages/18/07/9dd2f0c0104f1a0295ffbe912bc8d63307a539b900dd9e2c48ef7810d971/orjson-3.11.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3", size = 144099, upload-time = "2026-02-02T15:38:20.28Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/66/857a8e4a3292e1f7b1b202883bcdeb43a91566cf59a93f97c53b44bd6801/orjson-3.11.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223", size = 134806, upload-time = "2026-02-02T15:38:22.186Z" },
+ { url = "https://files.pythonhosted.org/packages/0a/5b/6ebcf3defc1aab3a338ca777214966851e92efb1f30dc7fc8285216e6d1b/orjson-3.11.7-cp313-cp313-win32.whl", hash = "sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3", size = 127914, upload-time = "2026-02-02T15:38:23.511Z" },
+ { url = "https://files.pythonhosted.org/packages/00/04/c6f72daca5092e3117840a1b1e88dfc809cc1470cf0734890d0366b684a1/orjson-3.11.7-cp313-cp313-win_amd64.whl", hash = "sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757", size = 124986, upload-time = "2026-02-02T15:38:24.836Z" },
+ { url = "https://files.pythonhosted.org/packages/03/ba/077a0f6f1085d6b806937246860fafbd5b17f3919c70ee3f3d8d9c713f38/orjson-3.11.7-cp313-cp313-win_arm64.whl", hash = "sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539", size = 126045, upload-time = "2026-02-02T15:38:26.216Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/1e/745565dca749813db9a093c5ebc4bac1a9475c64d54b95654336ac3ed961/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0", size = 228391, upload-time = "2026-02-02T15:38:27.757Z" },
+ { url = "https://files.pythonhosted.org/packages/46/19/e40f6225da4d3aa0c8dc6e5219c5e87c2063a560fe0d72a88deb59776794/orjson-3.11.7-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0", size = 125188, upload-time = "2026-02-02T15:38:29.241Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/7e/c4de2babef2c0817fd1f048fd176aa48c37bec8aef53d2fa932983032cce/orjson-3.11.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6", size = 128097, upload-time = "2026-02-02T15:38:30.618Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/74/233d360632bafd2197f217eee7fb9c9d0229eac0c18128aee5b35b0014fe/orjson-3.11.7-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf", size = 123364, upload-time = "2026-02-02T15:38:32.363Z" },
+ { url = "https://files.pythonhosted.org/packages/79/51/af79504981dd31efe20a9e360eb49c15f06df2b40e7f25a0a52d9ae888e8/orjson-3.11.7-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5", size = 129076, upload-time = "2026-02-02T15:38:33.68Z" },
+ { url = "https://files.pythonhosted.org/packages/67/e2/da898eb68b72304f8de05ca6715870d09d603ee98d30a27e8a9629abc64b/orjson-3.11.7-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892", size = 141705, upload-time = "2026-02-02T15:38:34.989Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/89/15364d92acb3d903b029e28d834edb8780c2b97404cbf7929aa6b9abdb24/orjson-3.11.7-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e", size = 130855, upload-time = "2026-02-02T15:38:36.379Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/8b/ecdad52d0b38d4b8f514be603e69ccd5eacf4e7241f972e37e79792212ec/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1", size = 133386, upload-time = "2026-02-02T15:38:37.704Z" },
+ { url = "https://files.pythonhosted.org/packages/b9/0e/45e1dcf10e17d0924b7c9162f87ec7b4ca79e28a0548acf6a71788d3e108/orjson-3.11.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183", size = 138295, upload-time = "2026-02-02T15:38:39.096Z" },
+ { url = "https://files.pythonhosted.org/packages/63/d7/4d2e8b03561257af0450f2845b91fbd111d7e526ccdf737267108075e0ba/orjson-3.11.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650", size = 408720, upload-time = "2026-02-02T15:38:40.634Z" },
+ { url = "https://files.pythonhosted.org/packages/78/cf/d45343518282108b29c12a65892445fc51f9319dc3c552ceb51bb5905ed2/orjson-3.11.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141", size = 144152, upload-time = "2026-02-02T15:38:42.262Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/3a/d6001f51a7275aacd342e77b735c71fa04125a3f93c36fee4526bc8c654e/orjson-3.11.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2", size = 134814, upload-time = "2026-02-02T15:38:43.627Z" },
+ { url = "https://files.pythonhosted.org/packages/1d/d3/f19b47ce16820cc2c480f7f1723e17f6d411b3a295c60c8ad3aa9ff1c96a/orjson-3.11.7-cp314-cp314-win32.whl", hash = "sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576", size = 127997, upload-time = "2026-02-02T15:38:45.06Z" },
+ { url = "https://files.pythonhosted.org/packages/12/df/172771902943af54bf661a8d102bdf2e7f932127968080632bda6054b62c/orjson-3.11.7-cp314-cp314-win_amd64.whl", hash = "sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1", size = 124985, upload-time = "2026-02-02T15:38:46.388Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/1c/f2a8d8a1b17514660a614ce5f7aac74b934e69f5abc2700cc7ced882a009/orjson-3.11.7-cp314-cp314-win_arm64.whl", hash = "sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d", size = 126038, upload-time = "2026-02-02T15:38:47.703Z" },
+]
+
[[package]]
name = "packaging"
version = "25.0"
@@ -1153,6 +1649,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/0f/4c/f98024021bef4d44dce3613feebd702c7ad8883f777ff8488384c59e9774/parver-0.5-py3-none-any.whl", hash = "sha256:2281b187276c8e8e3c15634f62287b2fb6fe0efe3010f739a6bd1e45fa2bf2b2", size = 15172, upload-time = "2023-10-03T21:06:52.796Z" },
]
+[[package]]
+name = "pathspec"
+version = "1.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" },
+]
+
[[package]]
name = "pendulum"
version = "3.1.0"
@@ -1231,6 +1736,80 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/5b/a5/987a405322d78a73b66e39e4a90e4ef156fd7141bf71df987e50717c321b/pre_commit-4.3.0-py2.py3-none-any.whl", hash = "sha256:2b0747ad7e6e967169136edffee14c16e148a778a54e4f967921aa1ebf2308d8", size = 220965, upload-time = "2025-08-09T18:56:13.192Z" },
]
+[[package]]
+name = "prefect"
+version = "3.6.15"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "aiosqlite" },
+ { name = "alembic" },
+ { name = "anyio" },
+ { name = "apprise" },
+ { name = "asgi-lifespan" },
+ { name = "asyncpg" },
+ { name = "cachetools" },
+ { name = "click" },
+ { name = "cloudpickle" },
+ { name = "coolname" },
+ { name = "cryptography" },
+ { name = "dateparser" },
+ { name = "docker" },
+ { name = "exceptiongroup" },
+ { name = "fastapi" },
+ { name = "fsspec" },
+ { name = "graphviz" },
+ { name = "griffe" },
+ { name = "httpcore" },
+ { name = "httpx", extra = ["http2"] },
+ { name = "humanize" },
+ { name = "jinja2" },
+ { name = "jinja2-humanize-extension" },
+ { name = "jsonpatch" },
+ { name = "jsonschema" },
+ { name = "opentelemetry-api" },
+ { name = "orjson" },
+ { name = "packaging" },
+ { name = "pathspec" },
+ { name = "pluggy" },
+ { name = "prometheus-client" },
+ { name = "pydantic" },
+ { name = "pydantic-core" },
+ { name = "pydantic-extra-types" },
+ { name = "pydantic-settings" },
+ { name = "pydocket" },
+ { name = "python-dateutil" },
+ { name = "python-slugify" },
+ { name = "pytz" },
+ { name = "pyyaml" },
+ { name = "readchar" },
+ { name = "rfc3339-validator" },
+ { name = "rich" },
+ { name = "ruamel-yaml" },
+ { name = "ruamel-yaml-clib", marker = "platform_python_implementation == 'CPython'" },
+ { name = "semver" },
+ { name = "sniffio" },
+ { name = "sqlalchemy", extra = ["asyncio"] },
+ { name = "toml" },
+ { name = "typer" },
+ { name = "typing-extensions" },
+ { name = "uvicorn" },
+ { name = "websockets" },
+ { name = "whenever" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/0f/99/169c4d1cff1e6f11835f8427a510daa996af988b6a70cec0746344b88f22/prefect-3.6.15.tar.gz", hash = "sha256:783ff2ed5a29b62151facb567c4d596229b3d19520834e7cb3ae9c682b0704e0", size = 11070537, upload-time = "2026-01-30T00:50:00.264Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d7/95/2145b372daecb8d449530afb12e3e2cb3cd9aceeeecae8ba001dc1bb5ed2/prefect-3.6.15-py3-none-any.whl", hash = "sha256:eff2b5a1385677b9d94629b94428ddddbb9df63eadd8a870f05ef1ab124f9b84", size = 11799648, upload-time = "2026-01-30T00:49:57.145Z" },
+]
+
+[[package]]
+name = "prometheus-client"
+version = "0.24.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f0/58/a794d23feb6b00fc0c72787d7e87d872a6730dd9ed7c7b3e954637d8f280/prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9", size = 85616, upload-time = "2026-01-14T15:26:26.965Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" },
+]
+
[[package]]
name = "prompt-toolkit"
version = "3.0.51"
@@ -1352,6 +1931,40 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" },
]
+[[package]]
+name = "py-key-value-aio"
+version = "0.3.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "beartype" },
+ { name = "py-key-value-shared" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/93/ce/3136b771dddf5ac905cc193b461eb67967cf3979688c6696e1f2cdcde7ea/py_key_value_aio-0.3.0.tar.gz", hash = "sha256:858e852fcf6d696d231266da66042d3355a7f9871650415feef9fca7a6cd4155", size = 50801, upload-time = "2025-11-17T16:50:04.711Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/99/10/72f6f213b8f0bce36eff21fda0a13271834e9eeff7f9609b01afdc253c79/py_key_value_aio-0.3.0-py3-none-any.whl", hash = "sha256:1c781915766078bfd608daa769fefb97e65d1d73746a3dfb640460e322071b64", size = 96342, upload-time = "2025-11-17T16:50:03.801Z" },
+]
+
+[package.optional-dependencies]
+memory = [
+ { name = "cachetools" },
+]
+redis = [
+ { name = "redis" },
+]
+
+[[package]]
+name = "py-key-value-shared"
+version = "0.3.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "beartype" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/7b/e4/1971dfc4620a3a15b4579fe99e024f5edd6e0967a71154771a059daff4db/py_key_value_shared-0.3.0.tar.gz", hash = "sha256:8fdd786cf96c3e900102945f92aa1473138ebe960ef49da1c833790160c28a4b", size = 11666, upload-time = "2025-11-17T16:50:06.849Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/51/e4/b8b0a03ece72f47dce2307d36e1c34725b7223d209fc679315ffe6a4e2c3/py_key_value_shared-0.3.0-py3-none-any.whl", hash = "sha256:5b0efba7ebca08bb158b1e93afc2f07d30b8f40c2fc12ce24a4c0d84f42f9298", size = 19560, upload-time = "2025-11-17T16:50:05.954Z" },
+]
+
[[package]]
name = "pyarrow"
version = "21.0.0"
@@ -1426,6 +2039,55 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" },
]
+[[package]]
+name = "pydantic-extra-types"
+version = "2.11.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pydantic" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/fd/35/2fee58b1316a73e025728583d3b1447218a97e621933fc776fb8c0f2ebdd/pydantic_extra_types-2.11.0.tar.gz", hash = "sha256:4e9991959d045b75feb775683437a97991d02c138e00b59176571db9ce634f0e", size = 157226, upload-time = "2025-12-31T16:18:27.944Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/fe/17/fabd56da47096d240dd45ba627bead0333b0cf0ee8ada9bec579287dadf3/pydantic_extra_types-2.11.0-py3-none-any.whl", hash = "sha256:84b864d250a0fc62535b7ec591e36f2c5b4d1325fa0017eb8cda9aeb63b374a6", size = 74296, upload-time = "2025-12-31T16:18:26.38Z" },
+]
+
+[[package]]
+name = "pydantic-settings"
+version = "2.12.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pydantic" },
+ { name = "python-dotenv" },
+ { name = "typing-inspection" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/43/4b/ac7e0aae12027748076d72a8764ff1c9d82ca75a7a52622e67ed3f765c54/pydantic_settings-2.12.0.tar.gz", hash = "sha256:005538ef951e3c2a68e1c08b292b5f2e71490def8589d4221b95dab00dafcfd0", size = 194184, upload-time = "2025-11-10T14:25:47.013Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl", hash = "sha256:fddb9fd99a5b18da837b29710391e945b1e30c135477f484084ee513adb93809", size = 51880, upload-time = "2025-11-10T14:25:45.546Z" },
+]
+
+[[package]]
+name = "pydocket"
+version = "0.17.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cloudpickle" },
+ { name = "croniter" },
+ { name = "fakeredis", extra = ["lua"] },
+ { name = "opentelemetry-api" },
+ { name = "prometheus-client" },
+ { name = "py-key-value-aio", extra = ["memory", "redis"] },
+ { name = "python-json-logger" },
+ { name = "redis" },
+ { name = "rich" },
+ { name = "typer" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/73/26/ac23ead3725475468b50b486939bf5feda27180050a614a7407344a0af0e/pydocket-0.17.5.tar.gz", hash = "sha256:19a6976d8fd11c1acf62feb0291a339e06beaefa100f73dd38c6499760ad3e62", size = 334829, upload-time = "2026-01-30T18:44:39.702Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/14/98/73427d065c067a99de6afbe24df3d90cf20d63152ceb42edff2b6e829d4c/pydocket-0.17.5-py3-none-any.whl", hash = "sha256:544d7c2625a33e52528ac24db25794841427dfc2cf30b9c558ac387c77746241", size = 93355, upload-time = "2026-01-30T18:44:37.972Z" },
+]
+
[[package]]
name = "pygls"
version = "1.3.1"
@@ -1536,6 +2198,27 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" },
]
+[[package]]
+name = "python-json-logger"
+version = "4.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/29/bf/eca6a3d43db1dae7070f70e160ab20b807627ba953663ba07928cdd3dc58/python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f", size = 17683, upload-time = "2025-10-06T04:15:18.984Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" },
+]
+
+[[package]]
+name = "python-slugify"
+version = "8.0.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "text-unidecode" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/87/c7/5e1547c44e31da50a460df93af11a535ace568ef89d7a811069ead340c4a/python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856", size = 10921, upload-time = "2024-02-08T18:32:45.488Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8", size = 10051, upload-time = "2024-02-08T18:32:43.911Z" },
+]
+
[[package]]
name = "pytz"
version = "2025.2"
@@ -1655,6 +2338,37 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c7/e4/9159114a1d96c0442e1465ace2ec1f197e5027db6f794887cf2ca386cc40/qh3-1.5.4-cp37-abi3-win_amd64.whl", hash = "sha256:90ce786909cd7d39db158d86d4c9569d2aebfb18782d04c81b98a1b912489b5a", size = 1991452, upload-time = "2025-08-11T06:47:58.663Z" },
]
+[[package]]
+name = "readchar"
+version = "4.2.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/dd/f8/8657b8cbb4ebeabfbdf991ac40eca8a1d1bd012011bd44ad1ed10f5cb494/readchar-4.2.1.tar.gz", hash = "sha256:91ce3faf07688de14d800592951e5575e9c7a3213738ed01d394dcc949b79adb", size = 9685, upload-time = "2024-11-04T18:28:07.757Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a9/10/e4b1e0e5b6b6745c8098c275b69bc9d73e9542d5c7da4f137542b499ed44/readchar-4.2.1-py3-none-any.whl", hash = "sha256:a769305cd3994bb5fa2764aa4073452dc105a4ec39068ffe6efd3c20c60acc77", size = 9350, upload-time = "2024-11-04T18:28:02.859Z" },
+]
+
+[[package]]
+name = "redis"
+version = "7.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/43/c8/983d5c6579a411d8a99bc5823cc5712768859b5ce2c8afe1a65b37832c81/redis-7.1.0.tar.gz", hash = "sha256:b1cc3cfa5a2cb9c2ab3ba700864fb0ad75617b41f01352ce5779dabf6d5f9c3c", size = 4796669, upload-time = "2025-11-19T15:54:39.961Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/89/f0/8956f8a86b20d7bb9d6ac0187cf4cd54d8065bc9a1a09eb8011d4d326596/redis-7.1.0-py3-none-any.whl", hash = "sha256:23c52b208f92b56103e17c5d06bdc1a6c2c0b3106583985a76a18f83b265de2b", size = 354159, upload-time = "2025-11-19T15:54:38.064Z" },
+]
+
+[[package]]
+name = "referencing"
+version = "0.37.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "attrs" },
+ { name = "rpds-py" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" },
+]
+
[[package]]
name = "regex"
version = "2025.7.34"
@@ -1706,6 +2420,31 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
]
+[[package]]
+name = "requests-oauthlib"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "oauthlib" },
+ { name = "requests" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/42/f2/05f29bc3913aea15eb670be136045bf5c5bbf4b99ecb839da9b422bb2c85/requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9", size = 55650, upload-time = "2024-03-22T20:32:29.939Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", size = 24179, upload-time = "2024-03-22T20:32:28.055Z" },
+]
+
+[[package]]
+name = "rfc3339-validator"
+version = "0.1.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" },
+]
+
[[package]]
name = "rich"
version = "14.1.0"
@@ -1724,6 +2463,72 @@ jupyter = [
{ name = "ipywidgets" },
]
+[[package]]
+name = "rpds-py"
+version = "0.30.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" },
+ { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" },
+ { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" },
+ { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" },
+ { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" },
+ { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" },
+ { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" },
+ { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" },
+ { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" },
+ { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" },
+ { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" },
+ { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" },
+ { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" },
+ { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" },
+ { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" },
+ { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" },
+ { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" },
+ { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" },
+ { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" },
+ { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" },
+ { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" },
+ { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" },
+ { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" },
+ { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" },
+ { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" },
+ { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" },
+ { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841, upload-time = "2025-11-30T20:23:32.209Z" },
+ { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670, upload-time = "2025-11-30T20:23:33.742Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005, upload-time = "2025-11-30T20:23:35.253Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112, upload-time = "2025-11-30T20:23:36.842Z" },
+ { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049, upload-time = "2025-11-30T20:23:38.343Z" },
+ { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661, upload-time = "2025-11-30T20:23:40.263Z" },
+ { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606, upload-time = "2025-11-30T20:23:42.186Z" },
+ { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126, upload-time = "2025-11-30T20:23:44.086Z" },
+ { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371, upload-time = "2025-11-30T20:23:46.004Z" },
+ { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298, upload-time = "2025-11-30T20:23:47.696Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604, upload-time = "2025-11-30T20:23:49.501Z" },
+ { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391, upload-time = "2025-11-30T20:23:50.96Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868, upload-time = "2025-11-30T20:23:52.494Z" },
+ { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747, upload-time = "2025-11-30T20:23:54.036Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795, upload-time = "2025-11-30T20:23:55.556Z" },
+ { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330, upload-time = "2025-11-30T20:23:57.033Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194, upload-time = "2025-11-30T20:23:58.637Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340, upload-time = "2025-11-30T20:24:00.2Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765, upload-time = "2025-11-30T20:24:01.759Z" },
+ { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834, upload-time = "2025-11-30T20:24:03.687Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470, upload-time = "2025-11-30T20:24:05.232Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630, upload-time = "2025-11-30T20:24:06.878Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148, upload-time = "2025-11-30T20:24:08.445Z" },
+ { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030, upload-time = "2025-11-30T20:24:10.956Z" },
+ { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570, upload-time = "2025-11-30T20:24:12.735Z" },
+ { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" },
+]
+
[[package]]
name = "ruamel-yaml"
version = "0.18.15"
@@ -1827,6 +2632,55 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
]
+[[package]]
+name = "sortedcontainers"
+version = "2.4.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" },
+]
+
+[[package]]
+name = "sqlalchemy"
+version = "2.0.46"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/aa/9ce0f3e7a9829ead5c8ce549392f33a12c4555a6c0609bb27d882e9c7ddf/sqlalchemy-2.0.46.tar.gz", hash = "sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7", size = 9865393, upload-time = "2026-01-21T18:03:45.119Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/4b/fa7838fe20bb752810feed60e45625a9a8b0102c0c09971e2d1d95362992/sqlalchemy-2.0.46-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00", size = 2150268, upload-time = "2026-01-21T19:05:56.621Z" },
+ { url = "https://files.pythonhosted.org/packages/46/c1/b34dccd712e8ea846edf396e00973dda82d598cb93762e55e43e6835eba9/sqlalchemy-2.0.46-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2", size = 3276511, upload-time = "2026-01-21T18:46:49.022Z" },
+ { url = "https://files.pythonhosted.org/packages/96/48/a04d9c94753e5d5d096c628c82a98c4793b9c08ca0e7155c3eb7d7db9f24/sqlalchemy-2.0.46-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee", size = 3292881, upload-time = "2026-01-21T18:40:13.089Z" },
+ { url = "https://files.pythonhosted.org/packages/be/f4/06eda6e91476f90a7d8058f74311cb65a2fb68d988171aced81707189131/sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad", size = 3224559, upload-time = "2026-01-21T18:46:50.974Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/a2/d2af04095412ca6345ac22b33b89fe8d6f32a481e613ffcb2377d931d8d0/sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e", size = 3262728, upload-time = "2026-01-21T18:40:14.883Z" },
+ { url = "https://files.pythonhosted.org/packages/31/48/1980c7caa5978a3b8225b4d230e69a2a6538a3562b8b31cea679b6933c83/sqlalchemy-2.0.46-cp313-cp313-win32.whl", hash = "sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f", size = 2111295, upload-time = "2026-01-21T18:42:52.366Z" },
+ { url = "https://files.pythonhosted.org/packages/2d/54/f8d65bbde3d877617c4720f3c9f60e99bb7266df0d5d78b6e25e7c149f35/sqlalchemy-2.0.46-cp313-cp313-win_amd64.whl", hash = "sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef", size = 2137076, upload-time = "2026-01-21T18:42:53.924Z" },
+ { url = "https://files.pythonhosted.org/packages/56/ba/9be4f97c7eb2b9d5544f2624adfc2853e796ed51d2bb8aec90bc94b7137e/sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10", size = 3556533, upload-time = "2026-01-21T18:33:06.636Z" },
+ { url = "https://files.pythonhosted.org/packages/20/a6/b1fc6634564dbb4415b7ed6419cdfeaadefd2c39cdab1e3aa07a5f2474c2/sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764", size = 3523208, upload-time = "2026-01-21T18:45:08.436Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/d8/41e0bdfc0f930ff236f86fccd12962d8fa03713f17ed57332d38af6a3782/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b", size = 3464292, upload-time = "2026-01-21T18:33:08.208Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/8b/9dcbec62d95bea85f5ecad9b8d65b78cc30fb0ffceeb3597961f3712549b/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447", size = 3473497, upload-time = "2026-01-21T18:45:10.552Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/f8/5ecdfc73383ec496de038ed1614de9e740a82db9ad67e6e4514ebc0708a3/sqlalchemy-2.0.46-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada", size = 2152079, upload-time = "2026-01-21T19:05:58.477Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/bf/eba3036be7663ce4d9c050bc3d63794dc29fbe01691f2bf5ccb64e048d20/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366", size = 3272216, upload-time = "2026-01-21T18:46:52.634Z" },
+ { url = "https://files.pythonhosted.org/packages/05/45/1256fb597bb83b58a01ddb600c59fe6fdf0e5afe333f0456ed75c0f8d7bd/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d", size = 3277208, upload-time = "2026-01-21T18:40:16.38Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/a0/2053b39e4e63b5d7ceb3372cface0859a067c1ddbd575ea7e9985716f771/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e", size = 3221994, upload-time = "2026-01-21T18:46:54.622Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/87/97713497d9502553c68f105a1cb62786ba1ee91dea3852ae4067ed956a50/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf", size = 3243990, upload-time = "2026-01-21T18:40:18.253Z" },
+ { url = "https://files.pythonhosted.org/packages/a8/87/5d1b23548f420ff823c236f8bea36b1a997250fd2f892e44a3838ca424f4/sqlalchemy-2.0.46-cp314-cp314-win32.whl", hash = "sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908", size = 2114215, upload-time = "2026-01-21T18:42:55.232Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/20/555f39cbcf0c10cf452988b6a93c2a12495035f68b3dbd1a408531049d31/sqlalchemy-2.0.46-cp314-cp314-win_amd64.whl", hash = "sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b", size = 2139867, upload-time = "2026-01-21T18:42:56.474Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/f0/f96c8057c982d9d8a7a68f45d69c674bc6f78cad401099692fe16521640a/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa", size = 3561202, upload-time = "2026-01-21T18:33:10.337Z" },
+ { url = "https://files.pythonhosted.org/packages/d7/53/3b37dda0a5b137f21ef608d8dfc77b08477bab0fe2ac9d3e0a66eaeab6fc/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863", size = 3526296, upload-time = "2026-01-21T18:45:12.657Z" },
+ { url = "https://files.pythonhosted.org/packages/33/75/f28622ba6dde79cd545055ea7bd4062dc934e0621f7b3be2891f8563f8de/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede", size = 3470008, upload-time = "2026-01-21T18:33:11.725Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/42/4afecbbc38d5e99b18acef446453c76eec6fbd03db0a457a12a056836e22/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330", size = 3476137, upload-time = "2026-01-21T18:45:15.001Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/a1/9c4efa03300926601c19c18582531b45aededfb961ab3c3585f1e24f120b/sqlalchemy-2.0.46-py3-none-any.whl", hash = "sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e", size = 1937882, upload-time = "2026-01-21T18:22:10.456Z" },
+]
+
+[package.optional-dependencies]
+asyncio = [
+ { name = "greenlet" },
+]
+
[[package]]
name = "sqlglot"
version = "27.8.0"
@@ -1958,6 +2812,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" },
]
+[[package]]
+name = "text-unidecode"
+version = "1.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ab/e2/e9a00f0ccb71718418230718b3d900e71a5d16e701a3dae079a21e9cd8f8/text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93", size = 76885, upload-time = "2019-08-30T21:36:45.405Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", size = 78154, upload-time = "2019-08-30T21:37:03.543Z" },
+]
+
[[package]]
name = "time-machine"
version = "2.19.0"
@@ -2013,6 +2876,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c6/49/cabb1593896082fd55e34768029b8b0ca23c9be8b2dc127e0fc14796d33e/time_machine-2.19.0-cp314-cp314t-win_arm64.whl", hash = "sha256:536bd1ac31ab06a1522e7bf287602188f502dc19d122b1502c4f60b1e8efac79", size = 17068, upload-time = "2025-08-19T17:21:54.064Z" },
]
+[[package]]
+name = "toml"
+version = "0.10.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/be/ba/1f744cdc819428fc6b5084ec34d9b30660f6f9daaf70eead706e3203ec3c/toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f", size = 22253, upload-time = "2020-11-01T01:40:22.204Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588, upload-time = "2020-11-01T01:40:20.672Z" },
+]
+
[[package]]
name = "tornado"
version = "6.5.2"
@@ -2058,11 +2930,11 @@ wheels = [
[[package]]
name = "typing-extensions"
-version = "4.14.1"
+version = "4.15.0"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" },
+ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
]
[[package]]
@@ -2265,6 +3137,75 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" },
]
+[[package]]
+name = "whenever"
+version = "0.9.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "tzdata", marker = "sys_platform == 'win32'" },
+ { name = "tzlocal", marker = "sys_platform != 'darwin' and sys_platform != 'linux'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/cd/9a/6b12d5708a703010877bec0efc5172ae8a851516abc13cd4543ce4d02a20/whenever-0.9.5.tar.gz", hash = "sha256:9d8f2fbc70acdab98a99b81a2ac594ebd4cc68d5b3506b990729a5f0b04d0083", size = 259436, upload-time = "2026-01-11T19:47:51.608Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/48/c7/f5626d4cc477116e6ec3191515981a60cdd021adc97046cb422f6bed327c/whenever-0.9.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d7de2cac536fe28f012928b74e0a3ed15dd8f4ac9940cfce35104cca345937f0", size = 467317, upload-time = "2026-01-11T19:47:21.582Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/81/d59f0e226ef542fc4bc86567d7b9e2bf9016c353b1f83661ee3913a140a7/whenever-0.9.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e00bc8f93fa469c630aad9dfdc538587c28891d6a4dce2f0b08628d5a108a219", size = 438838, upload-time = "2026-01-11T19:47:11.553Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/dc/090732e6e75f15a6084700d3247db6aa1f885971b637531529c62c4ba1c6/whenever-0.9.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ac83555db44e1fcfc032114f45c09af0ed9d641380672c8deb7f1131a0fd783", size = 453069, upload-time = "2026-01-11T19:45:30.238Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/f9/b4744370a9491689fc46327a17e3246a9e107b19efa0e24f51d9dcbe6aeb/whenever-0.9.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c486b1db0b833a007e2b8264f265079e57593925131b83ab69514fb9563b8d9", size = 498413, upload-time = "2026-01-11T19:45:49.811Z" },
+ { url = "https://files.pythonhosted.org/packages/62/78/45ef94ef51cb97c514650c2af33cdfc3de3cf967fcf12955c0e3a430a6cf/whenever-0.9.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a57e8f207b5ad9b0c6bcd3efee38d65a70434c1bdcb95cc5d2e2b7a5237c208", size = 487043, upload-time = "2026-01-11T19:46:09.528Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/23/f45082a60471ee79edc5bf5c09c1d4f55324a2c740fb138a3a691f19d2b6/whenever-0.9.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e1d66a0ece1dabd6952eb7b03a555843bada42bed4683ea71b113f194714144", size = 521879, upload-time = "2026-01-11T19:46:20.093Z" },
+ { url = "https://files.pythonhosted.org/packages/56/5c/8d6dc529595b5387f5727cd6c2c5b8615851d95fec5c599a61ef239cc1b3/whenever-0.9.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4056aaff273a579f0294e5397a0d198f52906bbaf7171da0a12ecd8cdf5026c", size = 483388, upload-time = "2026-01-11T19:46:49.746Z" },
+ { url = "https://files.pythonhosted.org/packages/29/52/366c4658286a5986acb76473e9e21457af2bd1b53dc050cee00160106eaa/whenever-0.9.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9b0e7c669be2897108895f3283e23fe761782c9c1abb0ce8834e57e09ce5cdfd", size = 521135, upload-time = "2026-01-11T19:46:30.122Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/cb/82bbe5ce0879dd38d201214323afad418f1d721111311807c75aaf2e2d16/whenever-0.9.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9e0c7a146da12c37d68387c639f957e3624cf7a55a1d534788d5aea748a261e7", size = 636617, upload-time = "2026-01-11T19:45:39.656Z" },
+ { url = "https://files.pythonhosted.org/packages/ec/32/8dcb6facf229b8e2b5c73d0c50adf800593769e34ab5abcd77828451c4ed/whenever-0.9.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:70c5f3013d6a1b7c40adbc05bc886e017f2b981739aaceafce47069da5b7e617", size = 769643, upload-time = "2026-01-11T19:45:59.047Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/40/6ab4308550851209982b78692d14a9729bf20b6e814ddedf2658e46a6cd8/whenever-0.9.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a8ce45c7271b85292e9d25e802543942b0249e73976c8614d676f0b561b25420", size = 733170, upload-time = "2026-01-11T19:46:39.457Z" },
+ { url = "https://files.pythonhosted.org/packages/47/38/7ad290229e8df99107d04e21ecef9d09f215428ab3aa06c0e46d51cba860/whenever-0.9.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f1db334becda2d7895bc31373b1e53ff73e3a0ea208e2845b4f946ad9a5e667", size = 696797, upload-time = "2026-01-11T19:47:00.001Z" },
+ { url = "https://files.pythonhosted.org/packages/ff/8e/94c4fba5ef73bb817c557e19bb75665cb5761e4badfb60950bd4d3cc5a01/whenever-0.9.5-cp313-cp313-win32.whl", hash = "sha256:4079eabfa21d1418bcc2c3d605e780cfec0ad8161317e12fa0f1ef87cb08fe7d", size = 416152, upload-time = "2026-01-11T19:47:32.083Z" },
+ { url = "https://files.pythonhosted.org/packages/81/b4/17d4bc76ca73c21eb5b7883d10d8bacb7ce7a30a8f36501db2373c63ffb3/whenever-0.9.5-cp313-cp313-win_amd64.whl", hash = "sha256:16497a2b889aeeb0ee80a0d3b9ce14cdb63d7eb7d904e003aae3cd4ac67da1e8", size = 440135, upload-time = "2026-01-11T19:47:42.963Z" },
+ { url = "https://files.pythonhosted.org/packages/30/d3/13db725dfef188bec32e51128e888a869ee97d26d965cfe39edf1321ca8f/whenever-0.9.5-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f222b1d59cdeadc1669657198e572727db8640e0b534e4e1ad0491417ec98379", size = 466415, upload-time = "2026-01-11T19:47:22.7Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/e9/4a9deeb616fbdf8e0c75fc78f13c37270d1d7e7ec776ffdf306262b8c593/whenever-0.9.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6f4ae436a4db888cd5b48a88fb83ae3f70c468a7d0018cc9572e26e99b9f591f", size = 437247, upload-time = "2026-01-11T19:47:13.1Z" },
+ { url = "https://files.pythonhosted.org/packages/15/02/21866bddf5f819f1a3a59463f4637755590cb4045d25a50fb6ab60db97a6/whenever-0.9.5-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68b7c201fc49123159b1518147e48791e95a19cba0b3ebb646a446eb7e95148f", size = 451556, upload-time = "2026-01-11T19:45:31.645Z" },
+ { url = "https://files.pythonhosted.org/packages/51/14/2c84db8f23577ddfd6ecd90c8d192d21dfa75aea57cda44eb53048b27e69/whenever-0.9.5-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5d2a8dd9c565eacb199ff704d96fc95e74f6c324639d970cac3b4d80eefbaebb", size = 498034, upload-time = "2026-01-11T19:45:50.926Z" },
+ { url = "https://files.pythonhosted.org/packages/cc/37/cb69a10573382bbfd14954b5386bf5c47290551246d497a9aa733a5b5a8a/whenever-0.9.5-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0d965ee9dafe1eb37ec273f7520e26b70d8b1bb075c06b0bb9e434363ca66fd", size = 487381, upload-time = "2026-01-11T19:46:10.752Z" },
+ { url = "https://files.pythonhosted.org/packages/47/c4/fcc0f886322f72c5d83ee669ed1aa253c4e58625e5bf64fede03a69aa7a0/whenever-0.9.5-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:035594337920cc9b9eb4531a97037971c109cc60e9a7a53e49e65722a1db7535", size = 520975, upload-time = "2026-01-11T19:46:21.789Z" },
+ { url = "https://files.pythonhosted.org/packages/29/cc/ad7e9c225a97be16b97a20c46802991908a12f9920d83071d669ed7ed79c/whenever-0.9.5-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26c5b04d6fcb0e4ee9f6e62e4400fd99c5f188449314f5863a865be33a653984", size = 481911, upload-time = "2026-01-11T19:46:50.87Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/12/4fa12c102d6aa3190ce1f34dc9f709776e9c3b1537328c46b6444b9a1638/whenever-0.9.5-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04755e5a2b802451332d2a18bf1c45d74f99cd16e61a0724fe763907f32cf7f8", size = 520068, upload-time = "2026-01-11T19:46:31.175Z" },
+ { url = "https://files.pythonhosted.org/packages/a7/e7/08d7c7e59130e8379240fda96cd68ae60435f6d6b6e356a5900c6856e48f/whenever-0.9.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0f7a37894b9cfc1e68b23f25d19ac38da68454f6bf782eab4cfac58578092daa", size = 635235, upload-time = "2026-01-11T19:45:41.389Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/6d/49c5566c5560606659dfed8dd49cadfa4d6a14b3f0d7a3d5a46a0c4e5624/whenever-0.9.5-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:55f10416bed357e0d1d1e4bf5e625974fe0a01348117161b4a0d2a69361c0efc", size = 769640, upload-time = "2026-01-11T19:46:00.112Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/09/e05cdc29897b97f3e3c0ffd485bf165f779c6d89bc4c0c0a76592e7c2e8c/whenever-0.9.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:75bfb8c778db727230fa5e7e2e256615be287d00cb1132b93789525e4d1c5dc6", size = 731095, upload-time = "2026-01-11T19:46:40.693Z" },
+ { url = "https://files.pythonhosted.org/packages/1c/d1/dcb635c2951ed5a112d340f73bf3cc81d69d1af7c0b1a33d0ca9d3299a26/whenever-0.9.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5bdc5ca9cddc9264d587469d994e046ae9c55cfdb6b9048927fe2922ae8763a1", size = 694782, upload-time = "2026-01-11T19:47:01.532Z" },
+ { url = "https://files.pythonhosted.org/packages/56/06/1544751be5e96aeefb59b5fedc1f8f4b0f238197ce21496d5960da20f18c/whenever-0.9.5-cp313-cp313t-win32.whl", hash = "sha256:274b7acfdc1fdfb29ab55299ce0a90cabedd079ff9940e24d05e3de4b04e1638", size = 415984, upload-time = "2026-01-11T19:47:33.34Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/0e/c87cf223816731718e5fef792b1f8c6d124c9fcbec677d4b7c9fcfe8f44f/whenever-0.9.5-cp313-cp313t-win_amd64.whl", hash = "sha256:7c9429fa1249aa39385716644453d9a4de0974b537974988b175d3ba7175a43f", size = 438641, upload-time = "2026-01-11T19:47:44.295Z" },
+ { url = "https://files.pythonhosted.org/packages/d7/e4/5e78fc3b8a2bc84e0f055a89a9f4eabc06bc435463ea112265e1e73592f5/whenever-0.9.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:e381120682f6675cccbcba13b4c88b033f31167f820c161936fa99556e455f03", size = 468861, upload-time = "2026-01-11T19:47:24.176Z" },
+ { url = "https://files.pythonhosted.org/packages/e8/a3/bd597dff8c82b2a1568813015ff25f3df2b6817872c8061176f04e3aad0f/whenever-0.9.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:caa7be36a609d765b9ea1c49159c446521b6ac33ff60b67214aa019713e05dda", size = 441322, upload-time = "2026-01-11T19:47:14.184Z" },
+ { url = "https://files.pythonhosted.org/packages/82/3c/fcb3a85cfdc12783c22d44640be538f78bcc3946cc3fb454139cdaebd119/whenever-0.9.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:037fd64e27df6116c3ffe8e96cdb6562051b0eda3f0bc7c35068fe642a913da9", size = 455230, upload-time = "2026-01-11T19:45:32.978Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/17/83c83dddb55f7576f3748b077774d2bd8521bc2220bd2fa6f711ad8f046e/whenever-0.9.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5c864363a2ff97c0b661915112140b9229132586d035ee4989cbe914aa3e3df4", size = 499473, upload-time = "2026-01-11T19:45:52.257Z" },
+ { url = "https://files.pythonhosted.org/packages/07/11/406d26cf641ef9e3cdd0f11237a2a49b06f225c5f57257850a2e101c8760/whenever-0.9.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e3d2c3f7bc9ceaef7d58fb40f0a4602a1947691eac1bff2623d2f923d4374543", size = 488680, upload-time = "2026-01-11T19:46:12.382Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/15/7d85e7f5710fc4dfaec830da0b069791ca6b7108939ab06a0440cfd11f7a/whenever-0.9.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce45c364734e63a459b3b816f1ce159bb4d4f570faa2b0fa504d6d329dd654a3", size = 522715, upload-time = "2026-01-11T19:46:22.835Z" },
+ { url = "https://files.pythonhosted.org/packages/3f/53/ec6eb7d71624437571ed22c9fbfa7c8532b6868c94138e0775f61c69101c/whenever-0.9.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8fc8e6e500f60299be739e19ffb830b2d9f50da017e14cd832b31f31ee93166", size = 484518, upload-time = "2026-01-11T19:46:51.971Z" },
+ { url = "https://files.pythonhosted.org/packages/17/48/220d4a7335d91face9e5c16ec5228ad454ff58cfb3713c291c90d54b3e84/whenever-0.9.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b422bb8651f094f4420749f4c0d72287121480a495c6d247035bd52a72c4586c", size = 522611, upload-time = "2026-01-11T19:46:32.224Z" },
+ { url = "https://files.pythonhosted.org/packages/be/fd/d1b270585f459f469af7c08e03ba2bcfe058449162354bf809e671ccfb1e/whenever-0.9.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:87635742acdd0adbbed62c6ed2ec4a49e25b1e3c7374f13f39d2c5f9229ae24f", size = 638421, upload-time = "2026-01-11T19:45:42.843Z" },
+ { url = "https://files.pythonhosted.org/packages/2f/0c/7fc33cdb8da7d2b14cd7129f37b48c1aa91644eabc07780333979bdf15f6/whenever-0.9.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1ae39fff83ad73ec563db65707e5bde1e74b350bf4309cfb265d527a6cd222c6", size = 770967, upload-time = "2026-01-11T19:46:01.614Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/39/a379dcf478136619050cee1ed789a9bdb0a6537fe8c43b23ea832e38c8ce/whenever-0.9.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ae5b01eb93c3ad703d7870d9e6566c389b889e97d7efec30c73abf64aa95b47f", size = 735292, upload-time = "2026-01-11T19:46:41.75Z" },
+ { url = "https://files.pythonhosted.org/packages/09/a7/139ac3b81239f1d6275e8eb792c52a48adc6ba303b7e0c9d8ca405a86c76/whenever-0.9.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5e278daa1e650958f9ba7084b1c3c245444acf3e30db9cca5141658347a7c67d", size = 697998, upload-time = "2026-01-11T19:47:02.681Z" },
+ { url = "https://files.pythonhosted.org/packages/2e/37/141041e40f76dd530183c715faae1d8b21e47867fe159b8b88c4960eae2d/whenever-0.9.5-cp314-cp314-win32.whl", hash = "sha256:1b62c62a00bd93e51f71d231aef3178f1c22566b2818c190e755c96fd939b91a", size = 418248, upload-time = "2026-01-11T19:47:34.855Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/7b/c86657bec1a679042c239a247bc3e6a92f3acc53ec858d13c1e770777f41/whenever-0.9.5-cp314-cp314-win_amd64.whl", hash = "sha256:483c2736ce367dbda01133700b064dfa8b6ed24833fc984e1d767e81aa02a189", size = 442418, upload-time = "2026-01-11T19:47:45.727Z" },
+ { url = "https://files.pythonhosted.org/packages/55/3b/2d37c3438214a1bf6caddddf825d5ff86e6cfcdf91a41fa1175334a2bab0/whenever-0.9.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7644b6c35f9c1fa7b7f6cb03bf5764207374bf3e2049cb49e7578648b0d27dd9", size = 468132, upload-time = "2026-01-11T19:47:25.341Z" },
+ { url = "https://files.pythonhosted.org/packages/ba/0d/284336cf592107ee65c61030f1ca9717214365661d642aadf9fbce38bf8d/whenever-0.9.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:be31d5799b49e593da413cddc73728a51d0e80461262c7a4ed66b95819a69016", size = 438449, upload-time = "2026-01-11T19:47:15.283Z" },
+ { url = "https://files.pythonhosted.org/packages/5a/50/a13b1869b06a8838fab79e31707bf882f836764dcf1260ce170c1084011b/whenever-0.9.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6691e1157026773354c77771cd72db727bbd0ee36121cd139cf16f03cddc1699", size = 452750, upload-time = "2026-01-11T19:45:34.047Z" },
+ { url = "https://files.pythonhosted.org/packages/79/9d/3b9006df1289c78a2e3b8bdd6498430ffee57cb851c938a9da9a7f2ca11d/whenever-0.9.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7e31f4bb592cdd433dde40acef83f968b89178b42169724e0b200a318536c4f", size = 497651, upload-time = "2026-01-11T19:45:53.477Z" },
+ { url = "https://files.pythonhosted.org/packages/c3/94/6e66e55649ed8c2e742ca3284e3dd158b0cb3d1272fc7bacc5b0938eba12/whenever-0.9.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f8100609213040dda06e1d078bc43768d5d16dbaabfa75b13c5adb5189056be", size = 488006, upload-time = "2026-01-11T19:46:13.624Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/62/5c0bea83a518f3a76377400bdc29215d2f964be4d1bc8d3886f91824a4cc/whenever-0.9.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:38c415a27661f830320c96f3cf6af99ea96b712c9c3a14975ff8c34263d125c6", size = 521517, upload-time = "2026-01-11T19:46:23.874Z" },
+ { url = "https://files.pythonhosted.org/packages/80/0a/e93c2ccfb993d5ac1434913d9a2cea2e79d93affbbec06942c748d04681f/whenever-0.9.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cee6fce59f948dd30c01107d55d40d2c035c6dfd3005c49d535e10175832601c", size = 483401, upload-time = "2026-01-11T19:46:53.531Z" },
+ { url = "https://files.pythonhosted.org/packages/4d/05/d142ca3b56a1012082d0d2b71f9e9e1b9b42ba266d92294f841cb7acc07e/whenever-0.9.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef181122ffcef41551d5eef483bf12ea48d1115554911a674e404e640ef0fd26", size = 520096, upload-time = "2026-01-11T19:46:33.746Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/b9/53a3ebb2c44e7215fa8c6720361a5c78891538f9c934935ffbf508801aae/whenever-0.9.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e4970bc5c37d4fff22e299314bebebb2d1a88133a67a51f87013dad0ac6535fb", size = 637251, upload-time = "2026-01-11T19:45:43.849Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/17/4f15ae9977972a7b8cd2819c4f03b63884416e4064d6d7366164cd6093f4/whenever-0.9.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:db8043800bd6eba7e681a316cba3734c8d10dad044b4a0dcf5fb0129665902ce", size = 769681, upload-time = "2026-01-11T19:46:03.041Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/a5/280dd222b31f478cef551f0d6554ab224e436b7b4ba1456d3cad864de756/whenever-0.9.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:067235cd1be14f709219eae4e6ae639ec19418e7860d1be1e59c5e4bd9cb3542", size = 732487, upload-time = "2026-01-11T19:46:43.395Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/33/d2bed59cfe7cf358e78bfa26bad4414a0a3d99c6aa5e5b76aea448661bae/whenever-0.9.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:81556be508452f5fe7d7e7837718ff91ddb16089a705febe178fa8baabc99236", size = 696906, upload-time = "2026-01-11T19:47:03.814Z" },
+ { url = "https://files.pythonhosted.org/packages/36/4a/b27b182fdf24c9760a91481c6b97d9f536a15f6bc7c33d750eccaa245670/whenever-0.9.5-cp314-cp314t-win32.whl", hash = "sha256:681c9f4d322182df28037a33f0d4eadf7577fcd590130f7a5d23763a86ab5687", size = 417599, upload-time = "2026-01-11T19:47:36.201Z" },
+ { url = "https://files.pythonhosted.org/packages/6d/93/712f65c4fc3c188b0c163cd650cb04a46f993a22d1ad3f66a3e4a42a39f8/whenever-0.9.5-cp314-cp314t-win_amd64.whl", hash = "sha256:37242c895078bb1bfc26bea460f6d92dc5bdfe4a59e95a4f9e01f99b90f0157e", size = 440654, upload-time = "2026-01-11T19:47:46.924Z" },
+ { url = "https://files.pythonhosted.org/packages/91/fb/1b112af72e5a2b5ac66b5a6a478cc220117224c1481a2b1a35e87222a791/whenever-0.9.5-py3-none-any.whl", hash = "sha256:cc600303e703d57cc42c5db1c81bbc3becb8ef6fde5c46aee5d68c292239fc4b", size = 64873, upload-time = "2026-01-11T19:47:49.585Z" },
+]
+
[[package]]
name = "widgetsnbextension"
version = "4.0.14"
@@ -2273,3 +3214,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/41/53/2e0253c5efd69c965
wheels = [
{ url = "https://files.pythonhosted.org/packages/ca/51/5447876806d1088a0f8f71e16542bf350918128d0a69437df26047c8e46f/widgetsnbextension-4.0.14-py3-none-any.whl", hash = "sha256:4875a9eaf72fbf5079dc372a51a9f268fc38d46f767cbf85c43a36da5cb9b575", size = 2196503, upload-time = "2025-04-10T13:01:23.086Z" },
]
+
+[[package]]
+name = "zipp"
+version = "3.23.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" },
+]
diff --git a/VISION.md b/vision.md
similarity index 100%
rename from VISION.md
rename to vision.md