feat(autoscan): make source setup descriptor-driven and self-contained
Autoscan setup asked operators to hold five concepts — plugin, capability, source, connection, delivery mode — before anything scanned, spread across four tabs. Sources never stated which library they fed, so a misconfigured one ran cleanly and silently did nothing. The admin UI also hardcoded two plugin identities: SourcesPanel.tsx carried 33 references to silo.autoscan.cephfs / silo.autoscan.arr-webhook plus a bespoke CephFS config editor. A third-party scan-source plugin could render no configuration UI at all without patching silo-server. Host side, add a ScanSourceDescriptor read from capability manifest metadata: delivery modes, connection requirement, connection kinds, and the per-source config form. Capabilities that declare nothing resolve to poll + optional connection — exactly the pre-descriptor behavior, so existing installs are unaffected. Compatibility descriptors for the two first-party plugins live in one file with a clear exit: the manifest always wins, so a plugin takes ownership by publishing its own. UI side, the Add-source flow builds its steps from the descriptor rather than from plugin ids, so a single-mode source is never asked how changes arrive and a credential-free one never sees the connection step. Connections are created inline (previously a dead end that forced cancelling out of the dialog), and webhook setup finishes in one place: mappings, then the URL with the exact Sonarr/Radarr triggers the host actually parses. Mapping rows seed from library paths collapsed to their common ancestor per mount point. Verified against a real install: 96 library paths become 2 rows. Rewrites match by longest prefix at a segment boundary, so one row per mount covers everything beneath it. Fold the Connections and Settings tabs into an Advanced section (4 tabs -> 2); old ?tab= links land on Sources with it expanded. Source rows now name the libraries they feed and warn when a source can never resolve one. API changes are additive within /api/v1: new optional fields on /autoscan/scan-source-plugins only.
This commit is contained in:
@@ -2107,10 +2107,35 @@ export interface AutoscanSourcesResponse {
|
||||
sources: AutoscanSource[];
|
||||
}
|
||||
|
||||
/** Whether a scan source needs upstream credentials to reach its provider. */
|
||||
export type AutoscanConnectionRequirement = "none" | "optional" | "required";
|
||||
|
||||
/**
|
||||
* The setup contract for one scan source, declared by its plugin manifest and
|
||||
* resolved host-side. The Add-source flow builds its steps from this rather
|
||||
* than branching on plugin ids, so a new plugin configures itself.
|
||||
*
|
||||
* The host always populates this, substituting defaults (poll + optional
|
||||
* connection) for capabilities that declare nothing.
|
||||
*/
|
||||
export interface AutoscanScanSourceDescriptor {
|
||||
delivery_modes: AutoscanDeliveryMode[];
|
||||
connection: AutoscanConnectionRequirement;
|
||||
connection_kinds?: string[];
|
||||
/** Plugin already emits Silo-native paths, so path rewrites can be skipped. */
|
||||
emits_native_paths?: boolean;
|
||||
summary?: string;
|
||||
icon_url?: string;
|
||||
/** Per-source config fields, rendered by the shared plugin SchemaForm. */
|
||||
config_form?: PluginAdminForm;
|
||||
}
|
||||
|
||||
export interface AutoscanAvailableSource {
|
||||
plugin_id: string;
|
||||
capability_id: string;
|
||||
display_name: string;
|
||||
description?: string;
|
||||
descriptor: AutoscanScanSourceDescriptor;
|
||||
}
|
||||
|
||||
export interface AutoscanAvailableSourcesResponse {
|
||||
@@ -3442,6 +3467,13 @@ export interface PluginAdminFormField {
|
||||
show_when?: PluginAdminFormCondition[];
|
||||
validation?: PluginAdminFormValidation;
|
||||
exclusive_group_field?: string;
|
||||
/**
|
||||
* Names a host-known value this field can be populated from in one click.
|
||||
* Used by autoscan source config so a path field can be filled from Silo's
|
||||
* own library paths without the UI knowing which plugin owns it. Unknown
|
||||
* values render no action.
|
||||
*/
|
||||
fill_from?: string;
|
||||
}
|
||||
|
||||
export interface PluginCapability {
|
||||
|
||||
Reference in New Issue
Block a user