Skip to content

clef-proxy: a JSON array body passes the #2816 'oracle' guard and fabricates an upstream Clef call — typeof [] is 'object', so [] and [1,2] run with the default model and empty state/questions instead of a 400 #2938

Closed

Description

@dezren39

Summary

bin/clef-proxy.mjs is held up in #2816 as one of the two proxies that
already handle non-object JSON bodies correctly — the oracle the other
seven are to copy. Its guard does not actually reject arrays:

// bin/clef-proxy.mjs:211 (main 16bae8ea)
if (!body || typeof body !== 'object') { /* 400 */ }

typeof [] === 'object', so a JSON array body passes the guard. The
handler then reads body.model / body.state / body.questions off the
array (all undefined) and fabricates an upstream Clef call with the
default model and the payload { state: {}, questions: {} } — the same
fabrication class #2821 filed for antigravity-direct, in the one proxy
#2816's fix is most likely to skip because its body text calls clef
already-correct (its acceptance bullet 4 even says "no behaviour change
for ... the guarded clef / opencode-route proxies").

The sibling oracle gets this right: opencode-route-proxy.mjs:659-660
defines isPlainObject as
typeof v === "object" && v !== null && !Array.isArray(v). Clef is the
only bin/*-proxy.mjs handler using the bare typeof guard (grep over
bin/*.mjs, this run).

Evidence (verified this run, main 16bae8ea)

Probe on the laptop (~/git/fleet/probe-2026-10-30-laneB-clefarray/,
real clef-proxy.mjs + proxy-port.mjs, md5-identical to main —
clef-proxy 5e55c6637574d1c69c143bd4430bc030), proxy spawned on a
scratch port with a dummy CLOUDFLARE_API_TOKEN, POST /v1/systemone:

body result
[] HTTP 401 from the upstream call — i.e. NOT a 400: the proxy fabricated {state:{}, questions:{}}, called the Cloudflare gateway with the default model, and relayed its auth error
[1,2] same 401 upstream relay
{} (valid control) same 401 upstream relay — the array responses are indistinguishable from a valid empty-object request
"hello" HTTP 400 "Invalid JSON body: expected an object"
null HTTP 400 (the #2816 case — this part of the guard works)
42 HTTP 400

Process stayed alive throughout (this is a fabrication bug, not the
#2816 crash).

Why it matters

Acceptance criteria

  • POST /v1/systemone (and /systemone, /) with a JSON array
    body returns the proxy's existing 400 "expected an object" error
    before any upstream call is attempted; null, string, and
    number bodies still 400; object bodies are unchanged.
  • The guard matches the opencode-route-proxy.mjs isPlainObject
    semantics (plain object only), or an equivalent shared check —
    triage pins whether clef imports/copies it.
  • A regression test in bin/clef-proxy.test.mjs (existing harness
    style): array body → 400 and no upstream fetch attempted;
    object-body control still reaches the upstream path.
  • Cross-check bin proxies: a JSON null body crashes seven chat proxies — parse succeeds, first deref throws, process exits 1 (clef and opencode-route already 400) #2816's PR when it lands: any proxy that adopted a
    bare typeof body !== 'object' guard gets the same array test.

Dedup checked this run: open/closed search for "clef array",
"clef-proxy body" — no hits. #2816 covers the seven crashing proxies
and names clef as a correct oracle (its secondary note mentions array
bodies only for design-code's dispatch); #2821 is antigravity-direct,
a different file outside the bin proxy set.

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    priority/lowNice to have; do when convenient
    queue/queuedHas a queued task in the Supabase agent queue
    effort/xsTrivial: expected under 30 minutes of work
    on Oct 31, 2026
  2. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

  3. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Design-architect pass 26 (2026-10-31) — agent note: this issue is adopted as part of Phase 1 of design #3068 ("parsed is not validated"). Triage: do NOT re-file, re-scope or split it — record the phase structure instead. The design records the rule this phase lands under: validate the shape you deref at the boundary, before any side effect; "object" means the exact plain-object vocabulary (opencode-route-proxy.mjs:659 idiom); failure is the surface's JSON 400 with the process alive; one shared probe matrix (null, array, scalar, {}, each relied-on field wrong-typed). Phase-specific decisions are on #3068 and in files/designs/code-parsed-is-not-validated.md (goal workspace).

  4. 84 remaining items

  5. added
    queue/claimedQueue worker lifecycle state
    and removed
    queue/claimedQueue worker lifecycle state
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 2, 2026
  6. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · resumed

  7. added a commit that references this issue on Nov 2, 2026
  8. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

  9. added
    task/small-fixQueue packet kind: bounded fix with reproduction and targeted tests
    and removed
    task/triageQueue packet kind: verify, reproduce, and route this item
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/clef-proxybin/clef-proxy.mjseffort/xsTrivial: expected under 30 minutes of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientsource/creatorFiled by the new-issue-creator jobsource/design-architectFiled by the repo design architect jobtask/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions