Data Flow¶
Cloudrift has two distinct data flow paths depending on whether it's running as a desktop app or in Docker.
Desktop Data Flow¶
sequenceDiagram
participant UI as Flutter UI
participant DS as CliDatasource
participant CLI as cloudrift binary
participant AWS as AWS APIs
UI->>DS: runScan(service, config)
DS->>CLI: Process.run("cloudrift scan --format=json")
CLI->>AWS: DescribeInstances / ListBuckets
AWS-->>CLI: Resource data
CLI-->>DS: JSON stdout
DS-->>UI: ScanResult
UI->>UI: Update providers & render Desktop path details:
- User clicks "Run Scan" on the Scan screen
ScanNotifiercallsScanRepository.runScan()ScanRepositorycallsCliDatasource.runScan()CliDatasource._runScanDesktop()invokesProcess.runwith the CLI binary- CLI args:
scan --config=<path> --service=<svc> --format=json --no-emoji - Working directory is set to the CLI repo folder
- CLI queries AWS APIs and evaluates OPA policies
- JSON output is parsed from stdout using
_extractJson() ScanResult.fromJson()deserializes the responseScanNotifierupdates state → all dependent providers recompute
Web Data Flow¶
sequenceDiagram
participant Browser as Flutter Web
participant Nginx as nginx :80
participant API as Go API :8081
participant CLI as cloudrift binary
participant AWS as AWS APIs
Browser->>Nginx: POST /api/scan
Nginx->>API: Proxy to :8081
API->>CLI: exec.Command("cloudrift scan")
CLI->>AWS: DescribeInstances / ListBuckets
AWS-->>CLI: Resource data
CLI-->>API: JSON stdout
API-->>Nginx: JSON response
Nginx-->>Browser: JSON response
Browser->>Browser: Update providers & render Web path details:
- Same UI trigger, but
kIsWebistrue CliDatasource._runScanWeb()sends HTTP POST to/api/scan- nginx proxies the request to the Go API on port 8081
- Go API executes the CLI binary as a subprocess
- CLI output is captured and returned as JSON
- Response flows back through nginx to the browser
- Same
ScanResult.fromJson()deserialization
Terraform Data Flow (Web Only)¶
sequenceDiagram
participant Browser as Flutter Web
participant API as Go API
participant TF as Terraform
Browser->>API: POST /api/terraform/upload (files)
API-->>Browser: {uploaded: [...]}
Browser->>API: POST /api/terraform/plan
API-->>Browser: {job_id: "abc123"}
loop Poll every 2s
Browser->>API: GET /api/terraform/job?id=abc123
API-->>Browser: {status: "running", phase: "init"}
end
API->>TF: terraform init
TF-->>API: Success
API->>TF: terraform plan -out=tfplan
TF-->>API: Success
API->>TF: terraform show -json tfplan
TF-->>API: Plan JSON
Browser->>API: GET /api/terraform/job?id=abc123
API-->>Browser: {status: "completed", plan_path: "..."} State Flow¶
graph LR
ScanNotifier -->|invalidates| ScanHistory
ScanHistory -->|watched by| LatestResult
LatestResult -->|watched by| ResourceSummaries
LatestResult -->|watched by| ComplianceScore
ResourceSummaries -->|renders| Dashboard
ComplianceScore -->|renders| Dashboard
ResourceSummaries -->|renders| Resources
ComplianceScore -->|renders| Compliance All derived providers use Riverpod's watch mechanism. When ScanNotifier completes a scan, it invalidates scanHistoryProvider, which triggers a cascade of recomputations through all dependent providers. The UI rebuilds automatically.