Skip to content

stateset/stateset-worker

Repository files navigation

StateSet Worker

Run the StateSet iCommerce engine in a Cloudflare Sandboxwrangler deploy and you have a full commerce engine with messaging channels, MCP tools, and an admin UI.

Architecture

Browser / AI Agent / Messaging Platform
        │
┌───────┴──────────────────────────────────┐
│  Cloudflare Worker (Hono.js)             │
│  - CF Access auth                        │
│  - Admin UI (React SPA)                  │
│  - HTTP/WebSocket proxy to container     │
│  - Cron: SQLite backup to R2             │
└───────┬──────────────────────────────────┘
        │
┌───────┴──────────────────────────────────┐
│  CF Container (Durable Object)           │
│  - @stateset/cli (stateset-channels.js)  │
│  - @stateset/embedded (Rust/SQLite)      │
│  - 6 messaging channels                 │
│  - MCP server (87 tools)                 │
│  - HTTP gateway on port 8080             │
│  - R2 mounted at /data/stateset          │
└──────────────────────────────────────────┘

Requirements

Free-tier Cloudflare features used:

  • Cloudflare Access (authentication)
  • AI Gateway (optional, for API routing/analytics)
  • R2 Storage (optional, for persistence)

Quick Start

# Install dependencies
npm install

# Set your API key
npx wrangler secret put ANTHROPIC_API_KEY

# Deploy
npm run deploy

After deploying, your commerce engine is live at https://stateset-sandbox.your-subdomain.workers.dev/.

The first request takes 1-2 minutes while the container boots. A loading page is shown during startup.

To use the admin UI and protected routes, you'll need to:

  1. Set up Cloudflare Access for authentication
  2. Enable R2 storage so commerce data persists (recommended)

Setting Up Cloudflare Access

The admin UI at /_admin/ and all /api/admin/* routes require Cloudflare Access authentication.

1. Enable Access on workers.dev

  1. Go to the Workers & Pages dashboard
  2. Select your Worker (stateset-sandbox)
  3. In Settings > Domains & Routes, click the ... menu on the workers.dev row
  4. Click Enable Cloudflare Access
  5. Configure who can access (email allow list, Google, GitHub, etc.)
  6. Copy the Application Audience (AUD) tag

2. Set Access Secrets

npx wrangler secret put CF_ACCESS_TEAM_DOMAIN
# Enter: myteam.cloudflareaccess.com

npx wrangler secret put CF_ACCESS_AUD
# Enter: your-application-audience-tag

Find your team domain in the Zero Trust Dashboard under Settings > Custom Pages.

3. Redeploy

npm run deploy

Now /_admin/ requires Cloudflare Access authentication.

Persistent Storage (R2)

By default, commerce data (SQLite database, config) is lost when the container restarts. R2 storage enables persistence.

Setup

  1. Go to R2 > Overview in the Cloudflare Dashboard
  2. Click Manage R2 API Tokens
  3. Create a token with Object Read & Write permissions for the stateset-data bucket
npx wrangler secret put R2_ACCESS_KEY_ID
npx wrangler secret put R2_SECRET_ACCESS_KEY
npx wrangler secret put CF_ACCOUNT_ID

How It Works

SQLite backup — The commerce database is backed up safely using SQLite's built-in .backup API, which handles concurrent writes correctly. A cron job runs every 5 minutes.

Config sync — Gateway configuration is synced to R2 via rsync.

Restore on boot — On container startup, data is restored from R2 if the backup is newer than local data. An integrity check verifies the database before restoring.

Manual backup — Trigger an immediate backup from the admin UI Storage tab or via POST /api/admin/storage/sync.

Admin UI

Access the admin UI at /_admin/ with three tabs:

  • Overview — Gateway status, commerce stats (customers, orders, returns, products), channel summary, restart controls
  • Channels — Per-channel status cards for all 6 messaging channels (Telegram, Discord, Slack, WhatsApp, Email, SMS)
  • Storage — R2 configuration status, last backup time, manual backup button, backup strategy info

Messaging Channels

Configure channels via environment secrets. Each channel is enabled automatically when its token is set.

Telegram

npx wrangler secret put TELEGRAM_BOT_TOKEN

Discord

npx wrangler secret put DISCORD_BOT_TOKEN

Slack

npx wrangler secret put SLACK_BOT_TOKEN
npx wrangler secret put SLACK_APP_TOKEN

WhatsApp

npx wrangler secret put WHATSAPP_TOKEN

Email

npx wrangler secret put EMAIL_SMTP_HOST

SMS (Twilio)

npx wrangler secret put TWILIO_ACCOUNT_SID

Commerce Settings

# Enable apply mode
npx wrangler secret put ALLOW_APPLY
# Enter: true

# Override default AI model
npx wrangler secret put DEFAULT_MODEL
# Enter: claude-opus-4-5

AI Gateway (Optional)

Route API requests through Cloudflare AI Gateway for caching, rate limiting, and analytics:

npx wrangler secret put AI_GATEWAY_API_KEY
npx wrangler secret put AI_GATEWAY_BASE_URL
# Enter: https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/anthropic

AI Gateway variables take precedence over direct ANTHROPIC_API_KEY if both are set.

Container Lifecycle

By default, the container stays alive indefinitely. To sleep after inactivity (reduces cost, adds cold start latency):

npx wrangler secret put SANDBOX_SLEEP_AFTER
# Enter: 10m (or 1h, 30m, etc.)

With R2 configured, data persists across restarts.

Debug Endpoints

Enable with DEBUG_ROUTES=true (requires Cloudflare Access):

Endpoint Description
GET /debug/version Container and stateset version info
GET /debug/processes All container processes (add ?logs=true for output)
GET /debug/cli?cmd=... Run a CLI command in the container
GET /debug/logs?id=... Logs for a specific process
GET /debug/env Sanitized environment configuration
GET /debug/container-config Gateway config from inside the container

Local Development

cp .dev.vars.example .dev.vars
# Edit .dev.vars with your ANTHROPIC_API_KEY
npm install
npm run dev

Set DEV_MODE=true in .dev.vars to skip Cloudflare Access auth.

All Secrets Reference

Secret Required Description
ANTHROPIC_API_KEY Yes* Anthropic API key (or use AI Gateway)
AI_GATEWAY_API_KEY Yes* AI Gateway provider key (requires AI_GATEWAY_BASE_URL)
AI_GATEWAY_BASE_URL No AI Gateway endpoint URL
OPENAI_API_KEY No OpenAI API key (alternative provider)
CF_ACCESS_TEAM_DOMAIN Yes Cloudflare Access team domain
CF_ACCESS_AUD Yes Cloudflare Access application audience
STATESET_GATEWAY_TOKEN No Gateway auth token
R2_ACCESS_KEY_ID No R2 access key for persistent storage
R2_SECRET_ACCESS_KEY No R2 secret key for persistent storage
CF_ACCOUNT_ID No Cloudflare account ID (required for R2)
TELEGRAM_BOT_TOKEN No Telegram channel
DISCORD_BOT_TOKEN No Discord channel
SLACK_BOT_TOKEN No Slack channel
SLACK_APP_TOKEN No Slack channel (required with SLACK_BOT_TOKEN)
WHATSAPP_TOKEN No WhatsApp channel
EMAIL_SMTP_HOST No Email channel
TWILIO_ACCOUNT_SID No SMS channel (Twilio)
ALLOW_APPLY No Set to true to enable apply mode
DEFAULT_MODEL No Override default AI model
DEV_MODE No Set to true for local dev (skips auth)
DEBUG_ROUTES No Set to true to enable /debug/* routes
SANDBOX_SLEEP_AFTER No Container sleep timeout: never (default), 10m, 1h

* One of ANTHROPIC_API_KEY or AI_GATEWAY_API_KEY is required.

Troubleshooting

Container fails to start: Check npx wrangler tail for logs. Verify ANTHROPIC_API_KEY is set.

R2 not mounting: Ensure all three secrets are set (R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, CF_ACCOUNT_ID). R2 mounting only works in production.

Access denied on admin routes: Verify CF_ACCESS_TEAM_DOMAIN and CF_ACCESS_AUD are set correctly.

Slow first request: Cold starts take 1-2 minutes. A loading page is shown automatically.

Config changes not working: Update the Dockerfile cache bust comment and redeploy.

Links

About

StateSet iCommerce Cloudflare Worker

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published