Skip to content

Technical guide · Overview

Page status: Active

Local AI Deployment Lock

NutsNews Worker shards must use the home-server local AI provider first.

Visual overview

Primary diagram

System map

NutsNews Worker shards must use the home-server local AI provider first.

Render the repository-owned system map when you need it.

Diagram is not rendered yet.

View as text
Local AI Deployment Lock

NutsNews Worker shards must use the home-server local AI provider first.

flowchart TD
  accTitle: Local AI Deployment Lock
  accDescr {
    NutsNews Worker shards must use the home-server local AI provider first.
  }
  A["Prepare `worker/.env.deploy.local`"] --> B["Set local AI vars + Secrets Store binding"]
  B --> C["Run `npm run generate:wrangler`"]
  C -->|missing AI config| D["BLOCK shard deployment"]
  C -->|valid local AI config| E["Run `npm run deploy:all`"]
  E --> F["Run `npm run check:local-ai-config`"]
  F --> G["Deploy worker shards"]
  G --> H["Shard runtime"]
  H --> I["`aiProvider === local`"]
  I -->|yes| J["Local AI call path active"]
  I -->|no| K["Investigate lock breach immediately"]
  J --> L["Request to shard endpoint"]
  L --> M["Check aiReviewProviderOrder, localAiConfigured"]
  M --> N["openAiCallCount should remain 0"]
  J --> O["CI regression: `test:local-ai-lock`"]
  O --> P["CI regression: `test:immutable`"]
  P --> Q["Deployment accepted"]
  R["Emergency path"] --> S["NUTSNEWS_ALLOW_OPENAI_ONLY_DEPLOYMENT set"]
  S --> T["deploy:openai-only (owner-approved)"]
  R --> U["NUTSNEWS_ALLOW_OPENAI_FALLBACK_DEPLOYMENT set"]
  U --> V["deploy:all with fallback mode (owner-approved)"]

Local AI Deployment Lock

Fullscreen diagram view.

NutsNews Worker shards must use the home-server local AI provider first.

This lock exists because a Worker deploy without AI_PROVIDER=local, LOCAL_AI_URL, and the LOCAL_AI_API_KEY secret binding silently behaves like an OpenAI deployment. That creates unexpected OpenAI usage and hides local-server configuration mistakes.

  • npm run generate:wrangler now refuses to generate production shard configs unless local AI is complete.
  • npm run deploy:all now runs the local-AI config verifier before deploying shards.
  • AI_PROVIDER_FALLBACK_TO_OPENAI=true is required by default.
  • Article reviews and summary translations no longer fall back to OpenAI when fallback is enabled.
  • CI runs a local-AI deployment-lock regression.
  • CI runs an immutable-test guard so locked regression tests cannot be edited later without explicit owner approval.

Create worker/.env.deploy.local from worker/.env.deploy.example:

Terminal window
cd worker
cp .env.deploy.example .env.deploy.local

Set these values:

Terminal window
NUTSNEWS_SECRETS_STORE_ID=...
NUTSNEWS_KV_NAMESPACE_ID=...
AI_PROVIDER=local
LOCAL_AI_URL=https://your-local-ai-tunnel.example.com
LOCAL_AI_MODEL=qwen2.5:3b
AI_PROVIDER_FALLBACK_TO_OPENAI=true
AI_REVIEW_CONCURRENCY=1
ENABLE_LOCAL_AI_SECRET_BINDING=true
LOCAL_AI_API_KEY_SECRET_NAME=LOCAL_AI_API_KEY

The LOCAL_AI_API_KEY value itself must live in Cloudflare Secrets Store. The Worker config only binds the secret name.

Terminal window
cd worker
npm run check:local-ai-config
npm run deploy:all

deploy:local-ai is kept as an alias for deploy:all.

OpenAI-only deploys are blocked by default. Use this only after explicit owner approval:

Terminal window
cd worker
NUTSNEWS_ALLOW_OPENAI_ONLY_DEPLOYMENT=true npm run deploy:openai-only

OpenAI fallback for a local-AI deployment is also blocked by default. Use this only after explicit owner approval:

Terminal window
cd worker
NUTSNEWS_ALLOW_OPENAI_FALLBACK_DEPLOYMENT=true AI_PROVIDER_FALLBACK_TO_OPENAI=true npm run deploy:all

Call one shard manually:

Terminal window
curl "https://nutsnews-worker-0.nutsnews.workers.dev/?limit=1&imageLookups=1"

Look for:

  • aiProvider is local
  • aiReviewProviderOrder is ["local"]
  • localAiConfigured is true
  • openAiFallbackEnabled is false
  • localAiCallCount is greater than 0 when a story reaches AI review
  • openAiCallCount is 0
  • estimatedOpenAiCostUsd is 0

If aiReviewedCount is 0, the shard did not need AI for that run. Try another shard or increase the manual limit.

Terminal window
cd worker
npm run test:local-ai-lock
npm run test:e2e:offline
npm run test:immutable

The offline E2E test already asserts aiProvider === "local" and openAiCallCount === 0.