Skip to content

Physical Architecture

This section binds the logical architecture to Cloudflare and PlanetScale components. Each physical component is a service realizing functions defined in the logical layer.

graph TB
  subgraph "Cloudflare Edge"
    subgraph "Compute"
      API["dashboard-api Worker<br/>(Hono, CF Access)"]
      Platform["platform-api Worker<br/>(API key/OAuth)"]
      Ingest["ingest Worker<br/>(Workflows, Queues)"]
      Pages["CF Pages<br/>(React SPA + Docs)"]
    end
    subgraph "Storage & Streaming"
      R2["R2<br/>(assets, archives, Iceberg)"]
      Pipelines["Pipelines<br/>(3 telemetry streams)"]
      KV["KV<br/>(config cache)"]
      DO["Durable Objects<br/>(watermarks)"]
      AE["Analytics Engine<br/>(real-time counters)"]
    end
    subgraph "Security"
      Access["CF Access<br/>(Google SSO)"]
    end
  end

  subgraph "PlanetScale"
    PS[(PostgreSQL<br/>153 tables)]
  end

  subgraph "External"
    Shopify["Shopify<br/>(GraphQL API)"]
    Dropbox["Dropbox<br/>(share links)"]
  end

  Access --> API
  Access --> Pages
  API -->|Hyperdrive| PS
  API -->|Service Binding| Ingest
  Platform -->|Hyperdrive| PS
  Ingest -->|Hyperdrive| PS
  Ingest --> R2
  Ingest --> Pipelines
  Ingest --> DO
  Ingest --> Shopify
  Ingest --> Dropbox
  Pipelines --> R2
  API --> R2
  API --> KV

The primary HTTP surface. Built with Hono and deployed as a single Worker:

dashboard-api Worker (EngineeredSystem)
├── middleware/
│ ├── cf-access.ts # JWT validation → Principal (CCO Agent identification)
│ ├── error-handler.ts # Structured error responses
│ └── request-id.ts # Trace correlation
├── routes/
│ ├── performance.ts # Measurement Data + Objective Specification CRUD
│ ├── combos.ts # Creative Act Reports, Plan Specifications, Suggestions
│ ├── tags.ts # Tag ICEs, ICE Collections, analytics
│ ├── assets.ts # ICE ingest trigger, denotation status
│ ├── csv.ts # Document Artifact trigger, download
│ ├── orders.ts # Commercial Transaction Record lookup
│ └── health.ts # EngineeredSystem health
├── lib/
│ ├── db.ts # Drizzle + Hyperdrive
│ └── shopify.ts # Shared Shopify client
└── bindings: R2, Queue, Hyperdrive, KV (optional)

Background job orchestration. CF Workflows handle durable multi-step workflows, with Workers providing the compute for each step:

ingest Worker (EngineeredSystem — Workflow step executor)
├── workflows/
│ ├── shopify-bulk-sync.ts # Workflow: initiate → poll → download → parse → upsert → enrich+stream
│ ├── measurement-refresh.ts # Workflow: DuckDB query R2 → compute → classify → write Iceberg
│ ├── asset-ingest.ts # Workflow: Dropbox → R2 (IBE) → DB → Shopify metafield
│ ├── csv-export.ts # Workflow: query → Document Artifact → R2 (IBE)
│ ├── combo-suggestions.ts # Workflow: generate suggestion artifacts from Measurement Data
│ └── combo-import.ts # Workflow: parse CSV → upsert combo_report artifacts
├── handlers/
│ ├── product-tag-sync.ts # Act: updating product Qualities (tags)
│ └── webhook-handler.ts # Shopify webhook → domain write + Pipeline stream push
├── scheduled.ts # Cron trigger → start Workflows
└── bindings: R2, Hyperdrive, Pipelines (COMMERCE_TELEMETRY, PUBLICATION_TELEMETRY, SYNC_TELEMETRY)

React SPA deployed to Cloudflare Pages:

  • Build: cd client && npm run build (Vite)
  • Routing: Pages handles SPA fallback (all paths → index.html)
  • API proxy: Pages Functions or custom domain routing to dashboard-api Worker
  • Auth: CF Access gate sits in front of both Pages and Workers

When dashboard-api needs to invoke ingest Worker directly (e.g., synchronous health aggregation), Service Bindings provide zero-overhead calls:

# wrangler.toml for dashboard-api
[[services]]
binding = "INGEST"
service = "ingest"
// In dashboard-api route handler
const result = await env.INGEST.fetch(new Request('http://internal/health'));

Service bindings run on the same thread of the same server — no network hop.

ServiceRoleConnectionOntological role
PlanetScalePrimary database (PostgreSQL) — domain/transactionalVia HyperdriveIBE store for domain entities (orders, products, publishers, macrodata artifacts)
Cloudflare R2Object storage + Data Catalog (Iceberg)Worker binding (env.R2_BUCKET)IBE store for assets, JSONL archives; Iceberg tables for analytics
Cloudflare PipelinesStreaming ingestion → R2 Data CatalogWorker binding (env.COMMERCE_TELEMETRY, etc.)Event streaming: domain events → Iceberg tables
Cloudflare WorkflowsDurable multi-step executionWorkflow bindingsProcedureExecution orchestration (replaces Queues for complex jobs)
Cloudflare Durable ObjectsStateful singletonsDO bindingWatermark/cursor state for pipeline orchestration
Cloudflare KV (optional)Configuration cache, feature flagsWorker binding (env.KV)Cached ICE fragments
ScheduleWorkflowScenario
0 6 * * * (daily 6am UTC)Shopify Bulk SyncDaily Sync
0 * * * * (hourly)Measurement RefreshPipeline
0 3 * * 0 (weekly Sun 3am)Asset Health CheckAsset Ingest

All cron triggers execute in the ingest Worker’s scheduled() handler and start CF Workflows for actual processing. Each Workflow has durable step tracking.