Summary
The Cloudflare Worker on ethicsengine.org apex throws on every /api/v1/* request (Cloudflare error 1101 = "Worker threw exception") and serves a Next.js 404 for /health. The backend itself is healthy — same requests against api.ethicsengine.org (which goes Caddy → CIRISNode container) return 200 with the correct JSON.
Caught by CIRISCore's new scripts/weekly-status.sh surface probe (20/22 passing; both failures on this domain).
Reproduction (2026-05-25 ~14:07 UTC)
$ curl -sI https://ethicsengine.org/api/v1/scores
HTTP/2 500
server: cloudflare
content-type: text/plain
content-length: 16
# body: "error code: 1101" ← CF: Worker threw exception
$ curl -sI https://ethicsengine.org/health
HTTP/2 404
x-opennext: 1 ← OpenNext (Next.js on Workers)
x-powered-by: Next.js
content-type: text/html
# body: Next.js 404 page (~16 KB)
$ curl -s https://api.ethicsengine.org/api/v1/scores | head -c 80
{"scores":[{"model_id":"claude-sonnet-4-5-... ← 200, backend fine
$ curl -s https://api.ethicsengine.org/health
{"status":"ok","version":1,...} ← 200, backend fine
What's likely happening
The x-opennext: 1 + x-powered-by: Next.js headers identify the responder as an OpenNext-built Next.js Worker — same toolchain as ui/wrangler.ethicsengine.toml (which binds admin.ethicsengine.org).
No wrangler.*.toml in this repo currently binds to the apex ethicsengine.org, so this Worker was either:
- Deployed by hand using
wrangler.ethicsengine.toml with the route overridden, or
- Built from a sibling/forked config that's not committed.
Whatever it is, it has no /api/v1/* route handler — those requests fall through to something that throws an unhandled exception, surfaced by CF as 1101. It also captures /health and serves the Next.js not-found page instead of proxying or rewriting to the backend's /api/v1/health.
CIRISCore side
ansible/surface.yml declares ethicsengine.org with cloudflare_proxy: true and route handlers expecting traffic to land on Caddy on registry-us/registry-eu:
- id: ethicsengine-public
served_by: [registry-us, registry-eu]
domains: [ethicsengine.org]
cloudflare_proxy: true # orange-cloud — Cloudflare Worker is in front of Caddy
routes:
- {path: /health, proxy: ciris_node, rewrite_to: /api/v1/health}
- {path: "/api/v1/scores*", proxy: ciris_node}
- {path: "*", proxy: ciris_node}
The Worker is intercepting before any of those routes get a chance.
Suggested fix (pick one)
- Remove the apex Workers route. Orange-cloud CF + Caddy already handles the routing per
surface.yml. Simplest path.
- Make the Worker explicit-passthrough for
/api/*: have the OpenNext Worker fetch() the origin (Caddy on registry-us/eu) for anything matching /api/*, only handle Next.js-owned routes itself.
- Move the apex to a dedicated Pages project with its own committed
wrangler.ethicsengine-apex.toml, so CIRISCore's surface manifest has a source-of-truth to audit against.
Happy to be redirected if the apex is actually owned by the portal team rather than CIRISNode — the OpenNext fingerprint + sibling admin Worker is what pointed me here.
Summary
The Cloudflare Worker on
ethicsengine.orgapex throws on every/api/v1/*request (Cloudflare error 1101 = "Worker threw exception") and serves a Next.js 404 for/health. The backend itself is healthy — same requests againstapi.ethicsengine.org(which goes Caddy → CIRISNode container) return 200 with the correct JSON.Caught by CIRISCore's new
scripts/weekly-status.shsurface probe (20/22 passing; both failures on this domain).Reproduction (2026-05-25 ~14:07 UTC)
What's likely happening
The
x-opennext: 1+x-powered-by: Next.jsheaders identify the responder as an OpenNext-built Next.js Worker — same toolchain asui/wrangler.ethicsengine.toml(which bindsadmin.ethicsengine.org).No
wrangler.*.tomlin this repo currently binds to the apexethicsengine.org, so this Worker was either:wrangler.ethicsengine.tomlwith the route overridden, orWhatever it is, it has no
/api/v1/*route handler — those requests fall through to something that throws an unhandled exception, surfaced by CF as 1101. It also captures/healthand serves the Next.js not-found page instead of proxying or rewriting to the backend's/api/v1/health.CIRISCore side
ansible/surface.ymldeclaresethicsengine.orgwithcloudflare_proxy: trueand route handlers expecting traffic to land on Caddy onregistry-us/registry-eu:The Worker is intercepting before any of those routes get a chance.
Suggested fix (pick one)
surface.yml. Simplest path./api/*: have the OpenNext Workerfetch()the origin (Caddy on registry-us/eu) for anything matching/api/*, only handle Next.js-owned routes itself.wrangler.ethicsengine-apex.toml, so CIRISCore's surface manifest has a source-of-truth to audit against.Happy to be redirected if the apex is actually owned by the portal team rather than CIRISNode — the OpenNext fingerprint + sibling admin Worker is what pointed me here.