Follow-up to #2222 / #2224. That PR stopped md/llm from being collateral damage. The underlying problem is still here, and it now fails more quietly than before.
What's wrong
The playground's Advanced Config panel still speaks the {type, code} protocol that /config/dump dropped in the 0.8.x security work. code is a globally forbidden field under the untrusted trust boundary, so the pre-flight always 400s:
CrawlerRunConfig.load({"type": "CrawlerRunConfig", "code": "..."}, provenance=Provenance.UNTRUSTED)
→ UntrustedConfigError: field 'code' is not permitted on CrawlerRunConfig from an untrusted request
crawl and crawl_stream survive only because of the regex fallback in runCrawl() (deploy/docker/static/playground/index.html), which checks the editor text for stream=True. Two consequences:
- Config is silently discarded. With the default snippet
CrawlerRunConfig(stream=True, cache_mode=CacheMode.BYPASS), the fallback sends {crawler_config: {type: 'CrawlerRunConfig', params: {stream: true}}}. The cache_mode line never reaches the server. The run succeeds, so nothing tells the user their config was dropped. Anything they type beyond stream is ignored.
- BrowserConfig is a hard failure. That template has no
stream=True, so no fallback fires and the run aborts with ✖ config error.
So the panel is non-functional on the only endpoint that still displays it.
Why it can't be patched in place
/config/dump used to eval the snippet. That was removed on purpose — it was a gadget-construction oracle. A Python-snippet editor can't work against the current server, so this isn't a matter of fixing the request shape.
Options
- Replace the CodeMirror Python editor with a params/JSON editor that posts
{type, params}, which is what /config/dump accepts today. Keeps the feature, matches the server.
- Remove the panel.
/crawl is still fully usable through the API; the playground just stops advertising a capability it doesn't have.
Either way the regex fallback in runCrawl() should go — it exists only to paper over the broken pre-flight, and it's what makes the config loss silent.
Repro
- Start the Docker server, open
/playground/
- Endpoint
crawl, default snippet, Run → succeeds, but cache_mode was never sent
- Switch Type to
BrowserConfig, Run → ✖ config error, run aborts
Notes
Follow-up to #2222 / #2224. That PR stopped
md/llmfrom being collateral damage. The underlying problem is still here, and it now fails more quietly than before.What's wrong
The playground's Advanced Config panel still speaks the
{type, code}protocol that/config/dumpdropped in the 0.8.x security work.codeis a globally forbidden field under the untrusted trust boundary, so the pre-flight always 400s:crawlandcrawl_streamsurvive only because of the regex fallback inrunCrawl()(deploy/docker/static/playground/index.html), which checks the editor text forstream=True. Two consequences:CrawlerRunConfig(stream=True, cache_mode=CacheMode.BYPASS), the fallback sends{crawler_config: {type: 'CrawlerRunConfig', params: {stream: true}}}. Thecache_modeline never reaches the server. The run succeeds, so nothing tells the user their config was dropped. Anything they type beyondstreamis ignored.stream=True, so no fallback fires and the run aborts with✖ config error.So the panel is non-functional on the only endpoint that still displays it.
Why it can't be patched in place
/config/dumpused toevalthe snippet. That was removed on purpose — it was a gadget-construction oracle. A Python-snippet editor can't work against the current server, so this isn't a matter of fixing the request shape.Options
{type, params}, which is what/config/dumpaccepts today. Keeps the feature, matches the server./crawlis still fully usable through the API; the playground just stops advertising a capability it doesn't have.Either way the regex fallback in
runCrawl()should go — it exists only to paper over the broken pre-flight, and it's what makes the config loss silent.Repro
/playground/crawl, default snippet, Run → succeeds, butcache_modewas never sentBrowserConfig, Run →✖ config error, run abortsNotes
#cfg-statusis written only bypyConfigToJson(). Since Skip /config/dump pre-flight for md/llm endpoints in playground #2224,md/llmskip that call, so a stale✖ config errorfrom a previouscrawlrun stays on screen.