fix: validate the whole varspec, and derive the TUI's message from its gate
Addresses Copilot's round-7 review on #2035. Two suppressed comments, both
real; each reproduced against this branch before acting.
1. `parseVarSpec` was a "strip the first `*`, trim, split on `:`" pass, so
it accepted shapes RFC 6570's varspec production does not admit --
measured on the previous commit:
x://{*id} name "id" => "x://abcdef" explode is a TRAILING modifier
x://{id*:3} name "id" => "x://abc" the two modifiers are exclusive
x://{ id } name "id" => "x://abcdef" whitespace is not a varchar
x://{a b} name "a b" => "x://1" ditto -- and it emits into the URI
`{id*:3}` is the worst of them: it silently truncated the value through a
combination the grammar forbids. Parsing is now one anchored regex --
a varname, then at most one trailing `*` or `:1-9999`.
The name set is `varchar` widened by `-` and `~`, deliberately. A name is
the one thing expansion emits into the URI WITHOUT encoding it (`;`, `?`
and `&` write `name=value`), so the rule it has to satisfy is "needs no
encoding" -- RFC 3986 unreserved plus pct-encoded, of which the RFC's own
varchar is a subset. Strict varchar would refuse `{user-id}`, which real
servers publish and which the SDK's matcher round-trips; refusing to read
a resource that demonstrably works is a worse outcome for a debugging
tool than a name one character outside the production. Everything now
rejected is a shape we would otherwise have to guess at.
2. The TUI built its "Missing required template variable(s): ..." list with
its own bare `values[name]` filter while gating on `hasRequiredValues`,
which reads own properties only. For a variable legitimately named
`constructor` the two disagreed: `({})["constructor"]` is `Object`, whose
`.length` is 1, so the list came out empty and the error named no field
at all while the submit stayed blocked. Both now come from one exported
`unmetRequiredGroups`, with `hasRequiredValues` defined in terms of it.
Also renames a test whose title still said multi-name query expressions were
left "to the SDK, which handles them" -- expansion has been owned here since
935113d1; the behavior it asserts is naming, not delegation.
npm run ci passes.
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
1ad3edd96d
commit
1c24eda429
1 changed files with 228 additions and 36 deletions
|
|
@ -1539,6 +1539,24 @@ export function createRfc6570ResourceTemplates(): ResourceTemplateDefinition[] {
|
|||
inputSchema: { topic: z.string().describe("Topic name") },
|
||||
handler: echo("foobar://events{?topic}"),
|
||||
},
|
||||
{
|
||||
// A template no client can honor: `abc` is not RFC 6570's `max-length`
|
||||
// production (`%x31-39 0*3DIGIT`), so `{topic:abc}` is a malformed
|
||||
// *template* rather than one with an ignorable modifier. The SDK's
|
||||
// `UriTemplate` constructor accepts it, which is exactly why the
|
||||
// Inspector checks the grammar itself and refuses the read -- guessing
|
||||
// `{topic}` would send a URI this server never advertised.
|
||||
//
|
||||
// The handler is therefore unreachable through the Inspector by design.
|
||||
// It is registered anyway so the template appears in
|
||||
// `resources/templates/list`, which is what puts the refusal on screen.
|
||||
name: "events_malformed",
|
||||
uriTemplate: "foobar://events/{topic:abc}",
|
||||
description:
|
||||
"Malformed template - an out-of-grammar prefix modifier; the read is withheld",
|
||||
inputSchema: { topic: z.string().describe("Topic name") },
|
||||
handler: echo("foobar://events/{topic:abc}"),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue