refactor(plugins): tighten web fetch provider boundary (#59646)

* refactor(plugins): tighten web fetch provider boundary

* fix(config): sync fetch secret parity and baseline

* fix(ci): enforce web fetch boundary guard
This commit is contained in:
Vincent Koc
2026-04-02 20:53:57 +09:00
committed by GitHub
parent 5abd5d889f
commit 6eca1949d5
15 changed files with 378 additions and 85 deletions

View File

@@ -136,6 +136,7 @@ export function installWebSearchProviderContractSuite(params: {
export function installWebFetchProviderContractSuite(params: {
provider: Lazy<WebFetchProviderPlugin>;
credentialValue: Lazy<unknown>;
pluginId?: string;
}) {
it("satisfies the base web fetch provider contract", () => {
const provider = resolveLazy(params.provider);
@@ -152,11 +153,28 @@ export function installWebFetchProviderContractSuite(params: {
expect(provider.envVars).toEqual([...new Set(provider.envVars)]);
expect(provider.envVars.every((entry) => entry.trim().length > 0)).toBe(true);
expect(provider.credentialPath.trim()).not.toBe("");
if (provider.inactiveSecretPaths) {
expect(provider.inactiveSecretPaths).toEqual([...new Set(provider.inactiveSecretPaths)]);
// Runtime inactive-path classification uses inactiveSecretPaths as the complete list.
expect(provider.inactiveSecretPaths).toContain(provider.credentialPath);
}
const fetchConfigTarget: Record<string, unknown> = {};
provider.setCredentialValue(fetchConfigTarget, credentialValue);
expect(provider.getCredentialValue(fetchConfigTarget)).toEqual(credentialValue);
if (provider.setConfiguredCredentialValue && provider.getConfiguredCredentialValue) {
const configTarget = {} as OpenClawConfig;
provider.setConfiguredCredentialValue(configTarget, credentialValue);
expect(provider.getConfiguredCredentialValue(configTarget)).toEqual(credentialValue);
}
if (provider.applySelectionConfig && params.pluginId) {
const applied = provider.applySelectionConfig({} as OpenClawConfig);
expect(applied.plugins?.entries?.[params.pluginId]?.enabled).toBe(true);
}
const config = {
tools: {
web: {

View File

@@ -1421,12 +1421,19 @@ export type WebFetchProviderPlugin = {
signupUrl: string;
docsUrl?: string;
autoDetectOrder?: number;
/** Canonical plugin-owned config path for this provider's primary fetch credential. */
credentialPath: string;
/**
* Legacy or inactive credential paths that should warn but not activate this provider.
* Include credentialPath here when overriding the list, because runtime classification
* treats inactiveSecretPaths as the full inactive surface for this provider.
*/
inactiveSecretPaths?: string[];
getCredentialValue: (fetchConfig?: Record<string, unknown>) => unknown;
setCredentialValue: (fetchConfigTarget: Record<string, unknown>, value: unknown) => void;
getConfiguredCredentialValue?: (config?: OpenClawConfig) => unknown;
setConfiguredCredentialValue?: (configTarget: OpenClawConfig, value: unknown) => void;
/** Apply the minimal config needed to select this provider without scattering plugin config writes in core. */
applySelectionConfig?: (config: OpenClawConfig) => OpenClawConfig;
resolveRuntimeMetadata?: (
ctx: WebFetchRuntimeMetadataContext,