* fix(#2460): pi before_provider_request fail-opens without explicit override
pi/gsd.cjs's buildBeforeProviderRequestHandler unconditionally rewrote
payload.model to the built-in pi/sonnet tier default (claude-sonnet-5)
via resolveTierEntry's catalog fallback. For any pi user on a non-Anthropic
provider (kimi-coding, zai, openrouter, openai-codex, minimax, ...), this
silently broke every request: pi's chosen model was replaced with one the
active provider did not know.
The fix inspects model_profile_overrides.pi[tier] explicitly BEFORE calling
resolveTierEntry (which falls back to the built-in catalog and would mask
the 'user did not opt in' signal). When the user has not set an override
(or set it to null), the handler returns undefined — fail-open — and pi's
chosen model flows through untouched. Only an explicit opt-in via
model_profile_overrides.pi[tier] steers.
Tests:
- the ACTUALLY-REGISTERED handler fail-opens when no override configured
(was: 'steers to default-tier model-catalog pi id' — encoded the bug).
- new test reproducing the reporter's exact repro (model: 'k3' → undefined).
- override path: explicit model_profile_overrides.pi.sonnet config steers
to the user-configured model id.
- defensive: explicit null override also fail-opens.
Per the reporter's suggested fix#1 of #2460.
* test(#2460): regen pi golden parity + install tree fixtures
pi/gsd.cjs changed → pi install hash changed → regenerate the parity
+ install-tree fixtures via UPDATE_GOLDEN=1 + UPDATE_INSTALL_TREE=1.
* fix(#2460): treat empty-string override as fail-open (M1 review)
Per code-review M1 + security M1: an explicit empty-string override
(`{ pi: { sonnet: "" } }`) silently bypassed the fail-open guard because
the check was `=== undefined || === null` only. resolveTierEntry's falsy
`if (userRaw)` then fell back to the built-in catalog and rewrote
payload.model to claude-sonnet-5 — re-introducing the exact bug this PR
fixes, via a degenerate config shape.
Fix: widen the guard to also reject `''`. The test now exercises both
null and '' in a loop, asserting fail-open for both.
* fix(#2460): clear hono/@hono/node-server moderate advisories via npm override
GHSA-v422-hmwv-36x6-class advisories (3 moderate) appeared during this
PR's session:
- @hono/node-server <2.0.5 (path traversal on Windows via encoded paths)
- hono 4.3.3 - 4.12.26 (API Gateway v1 adapter drops distinct repeated
request header values)
- both transitively via @anthropic-ai/claude-agent-sdk -> @modelcontextprotocol
/sdk@1.29.0
The npm audit fix re-resolved hono to 4.12.31 (within the existing ^4.11.4
range declared by MCP SDK), clearing the hono advisory without an override.
The @hono/node-server advisory cannot be re-resolved the same way: MCP SDK
pins @hono/node-server@^1.19.9, and the fix requires 2.0.5+. There is no
MCP SDK release that allows @hono/node-server@2.x (latest 1.29.0 is the
most recent), and bumping @anthropic-ai/claude-agent-sdk to 0.3.x does
not help (its peerDependency is still @modelcontextprotocol/sdk@^1.29.0).
The override (sibling to the existing 'qs' and 'body-parser' entries) is
therefore the only available tool — distinct from the body-parser case in
re-resolution.
Verified: npm audit --omit=dev reports 0/0/0/0 advisories.
Also: regenerated the pi golden-install-parity fixture (the pi/gsd.cjs
change in this PR altered the pi install hash).
* docs(changeset): add Fixed fragment for #2460 PR
The two-otters-jog.md changeset was created earlier but lost during the
cherry-pick detour to fix#2454 PR 1's npm advisory cascade. Recreating
here with PR number 2499 backfilled (no placeholder cycle needed).