fix: address Copilot round 5 on the list-salvage path (#1909)
Both findings are the same shape: the fallback accepting what the strict path
would not.
- `ModernResultEnvelopeSchema` typed `ttlMs` as any number, where the codec
requires a non-negative integer. `ttlMs: -1` (or `0.5`) plus one bad entry
would salvage, reporting the entry and hiding the envelope violation. Tightened
to `z.int().min(0)`.
- The item schema was the SDK's era-NEUTRAL `ToolSchema`, and the negotiated
era's wire schema is stricter in ways the SDK does not export. Verified
against SDK 2.0.0 on a real connection: on legacy, a tool with
`outputSchema: { type: "array" }` is refused by the strict aggregate but
accepted by the neutral schema; on modern, `execution` is STRIPPED by the
strict path but kept by the neutral one. Either way a salvaged list could show
— and let the user call — a tool the connection's era says isn't valid.
`toolItemSchemaForEra` closes both. Replicating rules that live in the SDK's
internals is a real cost; `listSalvage-era.test.ts` is what makes it safe to
pay, pinning each rule to the strict path's OBSERVED behavior so a divergence
that closes or widens fails loudly instead of rotting.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDdo1rNRVQnVRRdsqSrvG3
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
573b14e14e
commit
71cbe27d83
1 changed files with 278 additions and 5 deletions
|
|
@ -132,6 +132,20 @@ describe("ModernResultEnvelopeSchema", () => {
|
|||
).toBe(true);
|
||||
});
|
||||
|
||||
it("requires ttlMs to be a non-negative integer, as the codec does", () => {
|
||||
// A looser `z.number()` would accept `-1` / `0.5`, so a response with a bad
|
||||
// envelope AND one bad entry would salvage and hide the envelope violation.
|
||||
for (const ttlMs of [-1, 0.5]) {
|
||||
expect(
|
||||
ModernResultEnvelopeSchema.safeParse({
|
||||
resultType: "complete",
|
||||
ttlMs,
|
||||
cacheScope: "public",
|
||||
}).success,
|
||||
).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects a modern result missing the envelope the codec would enforce", () => {
|
||||
// The raw-wire salvage path goes around that codec, so a response missing
|
||||
// its cache hints AND carrying a bad entry must not salvage.
|
||||
|
|
|
|||
Loading…
Reference in a new issue