Repository navigation
feat(requestrouter): let request routers say they need no API key or base URL - #43
Conversation
…base URL Add api_key_optional and base_url_optional to RequestRouterDescriptor. A router that sets api_key_optional receives connections whose api_key is empty; one that sets base_url_optional can be saved and tested without a base URL. Unset, or an absent descriptor, keeps today's behaviour: a connection needs both. Closes Silo-Server#42
Say that the admin form, not the API, refuses a server without a key or URL, that only Fulfill, CheckStatus and ListConfigOptions skip a connection without a key, and that httpclient needs both. Update the plugin rather than reinstall it, so its servers stay bound. Cover base_url_optional alone and unchanged metadata for plugins without the flags.
Silo Kody — review completeReview finished. Check the inline comments for findings and verify each suggestion against the code and tests. Reviewing changes in Silo
Review settingsReview OptionsThe following review options are enabled or disabled:
|
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
… the flags Silo reads a bare plugin binary's manifest strictly, so a host that predates the flags refuses such a binary; an archive installs. Tracked in Silo-Server/silo-server#2436.
Silo Kody — review completeReview finished. Check the inline comments for findings and verify each suggestion against the code and tests. Reviewing changes in Silo
Review settingsReview OptionsThe following review options are enabled or disabled:
|
* chore(api): drop breaking-change approvals consumed by #2413 The getBrandingCapabilities and getThemeOverrides approvals belong to the change #2413 merged, so the contract check reports them as stale against the new base for any change to the v2 contract. * fix(requests): send requests to routers that need no API key A request_router plugin can now declare api_key_optional and base_url_optional (silo-plugin-sdk#42). Routing, status checks, the download refresh, the route preview and the connection test use a connection without a key when its plugin declares api_key_optional, through one check that reads the declaration only for a connection without a key. A server saved without a key can change its URL without one; a saved key still has to be typed again. The v2 plugin installation view carries both flags on a request_router.v1 capability, and the admin form saves and tests a server without a key or URL when its plugin needs neither, and stops showing it as needing setup. Closes #2380 * chore(deps): build against silo-plugin-sdk#43 until it is released Temporary: replace the SDK with the commit of Silo-Server/silo-plugin-sdk#43 so CI can build this branch. Replace this commit with a bump to the release that carries api_key_optional and base_url_optional before merging. * style(plugins): keep Silo imports in their own group in the plugin handlers * fix(requests): keep progress, saved keys and cleared URLs right for key-less routers - The download refresh keeps a key-less target's progress when its router's declaration can't be read, instead of clearing it: statusCheckable now returns the read error. - The save checks again, under the row lock, that a blank key keeps the saved key only for the address it was saved for, so a key or address saved by another admin between validation and the write is never paired with a different address. - A blank URL on a saved server is tested and validated as blank when its router declares base_url_optional, since that is what the save stores. * fix(requests): count a cleared URL as a change of address for a saved key For a router that declares base_url_optional, clearing a saved server's URL pointed the saved key at a different destination without asking for it again. A blank address is now a different address everywhere the rule applies: the save asks for the key again, the locked write refuses to keep it, and the connection test goes without it. * fix(requests): test the saved address when a probe leaves base_url out The v2 options body lets a client leave base_url out to test a saved server. For a router that declares base_url_optional, that was treated like a cleared URL and tested without an address. Only a base_url sent blank on purpose is a clear now; the request carries that through Integration.BaseURLCleared, and an omitted URL tests the saved one. * fix(requests): validate and probe the blank base URL a save stores A save with a blank URL for a server saved without a key validated the saved address but stored a blank one. With api_key_optional such a server takes requests, so routing would send the plugin an empty URL. The save now validates the URL it is given; a blank URL still stands for the saved address in a connection test. A v2 base_url of spaces also reached the plugin as sent when the router takes no URL, while the save stored it blank. adminRequestBaseURL now returns "" for any blank address. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(deps): build against silo-plugin-sdk v0.26.0 silo-plugin-sdk#43 is released in v0.26.0, so the temporary replace that pointed the SDK at the change's fork commit goes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Quick104 <31828688+Quick104@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Problem
Closes #42
Related issue: Silo-Server/silo-server#2380
A request-router plugin can't say it works without an API key or a base URL. Silo skips every router connection whose key is empty, and its admin form won't save a server without both. A router that talks to a local tool, or authenticates some other way, never receives a request unless the admin types in a dummy key.
Approach
RequestRouterDescriptorgets two plain booleans,api_key_optional = 4andbase_url_optional = 5, read from the manifest like the existing flags.silo-server#2380 suggested
requires_api_keyandrequires_base_url, defaulting to true. A proto3boolcan't default to true, and this descriptor's contract is that an absent descriptor means every flag is false. Naming the flags the other way round keeps that contract. Unset flags, an absent descriptor, a host on an older SDK, and code that reads the generated getters all mean "needs both", which is how every router is treated today. Anoptional boolwith presence would have needed a nil-means-true helper, and a host that forgot it would treat every existing router as key-less.The proto comments, a new "API key and base URL" section in the README, and
docs/compatibility.mdcover:The README also notes that
httpclientstill refuses an empty key or URL, so a key-less router needs its own client.Release impact: additive, so a minor release.
docs/compatibility.mdsays "added in v0.26.0", following the README's release rules.Downstream: silo-server reads the flags for routing, status checks, the connection test and the admin form in Silo-Server/silo-server#2439. That PR builds on this one and stays a draft until a release with these fields is tagged. No first-party router needs a change, because the Sonarr/Radarr and Seerr plugins need both.
Validation
go testfor./pkg/pluginsdk/manifest/,./pkg/pluginsdk/convert/and./pkg/pluginproto/silo/plugin/v1/: pass. The new tests cover:go veton those packages: clean.go buildof all four examples: pass.buf generateusing protoc-gen-go v1.36.11 and protoc-gen-go-grpc v1.6.1. Onlyrequest_router.pb.gochanges.protocisn't installed here, so I ranbuf generatedirectly rather thanmake proto; buf compiles the protos itself.buf lint: no new findings, the same 70 as v0.25.0.buf breakingagainst v0.25.0: pass.gofmt -lon the touched packages: clean. Across the repo it listspkg/pluginsdk/runtime/scan_source_test.go, which this PR doesn't touch and whichmainalready lists.go.work.go test ./...across the whole repo. CI runs it.Risks
api_key_optionalis still skipped by a host that predates it, so on such a host it works only with a key entered.Checklist
AI Disclosure
Harness: Claude Code (Claude desktop app)
Tool(s): Claude Code, Claude Code subagents for exploration and review, GitHub CLI, buf
Model(s): claude-opus-5-5
Involvement: AI-assisted with Claude Opus. I directed the task and designed the work.
Adversarial review: a separate Claude Code subagent reviewed the diff. It covered the proto contract, the generated code, buf lint and breaking checks, and how manifests are loaded, stored and decoded. It found three problems in the docs, which also had test gaps:
httpclientrefuses an empty key or URL.All of these are fixed in 8336f80. Testing the flags live on a Silo dev build then showed the strict binary-manifest parse above, and 076eab6 documents it.