Skip to content

ethicsengine.org Worker breaks all /api/v1/* (CF 1101) #31

Description

@emooreatx

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)

  1. Remove the apex Workers route. Orange-cloud CF + Caddy already handles the routing per surface.yml. Simplest path.
  2. 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.
  3. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions