101 lines
4.5 KiB
Markdown
101 lines
4.5 KiB
Markdown
# YAMS Plugin Naming & Loading Spec (Linux/macOS)
|
||
|
||
Status: draft
|
||
Applies to: Native ABI plugins loaded by the YAMS daemon (first‑class support on Linux and macOS)
|
||
|
||
## Goals
|
||
- Provide a deterministic, secure, cross‑platform policy for discovering, trusting, deduplicating,
|
||
and naming plugins at daemon startup and during explicit loads.
|
||
- Avoid duplicate providers when both `libyams_foo_plugin.*` and `yams_foo_plugin.*` variants exist.
|
||
- Keep Linux and macOS behavior aligned while respecting platform conventions.
|
||
|
||
## Terminology
|
||
- Provider: Logical capability implemented by a plugin (e.g., `model_provider_v1`).
|
||
- Variant: Multiple filesystem artifacts that implement the same provider (e.g., different file
|
||
names or directories).
|
||
|
||
## Discovery Order
|
||
The daemon builds a search list in this priority order (earlier is higher priority):
|
||
1) Configured plugin directories (daemon config `plugin_dirs`, if present)
|
||
2) Environment override (deprecated but supported): `YAMS_PLUGIN_DIR`
|
||
3) User: `$HOME/.local/lib/yams/plugins`
|
||
4) System: `/usr/local/lib/yams/plugins`, `/usr/lib/yams/plugins`
|
||
5) Install prefix (when compiled in): `${CMAKE_INSTALL_PREFIX}/lib/yams/plugins`
|
||
|
||
Note: Discovery is additive; the daemon attempts to load plugins from each existing directory.
|
||
|
||
## Trust Model
|
||
- Default deny: Plugins must be trusted before loading.
|
||
- Trust file: `~/.config/yams/plugins_trust.txt` (one absolute path per line, directory or file).
|
||
- CLI helpers: `yams plugin trust add|remove PATH`
|
||
- Dev override (not for production): `YAMS_PLUGIN_TRUST_ALL=1` trusts paths discovered by the search list.
|
||
- Additional safety checks: world‑writable plugin paths (or parents) are refused.
|
||
|
||
## Deduplication (Linux/macOS)
|
||
To avoid duplicate providers, the daemon deduplicates by provider name with path/file heuristics:
|
||
- Prefer non‑`lib` prefixed filenames when both variants exist in the same directory.
|
||
- Path priority: user directories outrank system directories; among equals, prefer non‑`lib` prefix.
|
||
- If an existing provider is already loaded from a higher‑priority location, lower‑priority variants
|
||
are skipped.
|
||
|
||
Rationale: This avoids double loading like `libyams_onnx_plugin` + `yams_onnx_plugin` and keeps
|
||
behavior consistent across Linux and macOS.
|
||
|
||
## Name Policy
|
||
Controls how a plugin’s display identity is chosen and how file variants are merged.
|
||
|
||
Modes:
|
||
- `relaxed` (default)
|
||
- If no manifest `name` is provided, derive a canonical name from the filename and normalize by
|
||
stripping a leading `lib` from `libyams_*` on UNIX‑like systems.
|
||
- Deduplicate variants by canonical name using the deduplication rules above.
|
||
- `spec`
|
||
- Respect the manifest `name` verbatim for display and selection.
|
||
- File variants that implement the same provider are still deduplicated according to the rules
|
||
above; the manifest name remains authoritative for display.
|
||
|
||
Configuration:
|
||
- Env: `YAMS_PLUGIN_NAME_POLICY=spec|relaxed`
|
||
- Daemon config: `plugin_name_policy: spec|relaxed`
|
||
|
||
## Startup Loading Algorithm (Simplified)
|
||
1) Build the directory list per Discovery Order.
|
||
2) For each directory:
|
||
- Enumerate regular files with extensions: `.so` (Linux), `.dylib` (macOS), `.dll` (Windows).
|
||
- Skip files that do not match `*yams_*_plugin*` (when policy is `spec`, loosen to manifest name).
|
||
- On UNIX, if both `lib<name>` and `<name>` exist, consider only `<name>`.
|
||
- Trust check: refuse untrusted/world‑writable paths.
|
||
- Dlopen + symbol probe (or preflight on macOS): obtain provider identity; apply Name Policy.
|
||
- If provider already loaded, apply path priority and filename preference to keep or replace.
|
||
3) Finalize the provider map; only one instance per provider is active.
|
||
|
||
## Examples
|
||
Linux:
|
||
```
|
||
~/.local/lib/yams/plugins/
|
||
libyams_foo_plugin.so
|
||
/usr/local/lib/yams/plugins/
|
||
yams_foo_plugin.so
|
||
|
||
# With relaxed policy: the user copy wins, canonical name ‘yams_foo_plugin’.
|
||
```
|
||
|
||
macOS:
|
||
```
|
||
/usr/local/lib/yams/plugins/
|
||
libyams_bar_plugin.dylib
|
||
yams_bar_plugin.dylib
|
||
|
||
# The non-lib filename is preferred; the lib-prefixed sibling is skipped.
|
||
```
|
||
|
||
## Security Considerations
|
||
- Only trusted paths are loaded; world‑writable locations are refused.
|
||
- Dev overrides (`YAMS_PLUGIN_TRUST_ALL`) must not be used in production.
|
||
- Name Policy does not affect trust; it only affects identity and deduplication.
|
||
|
||
## Conformance Notes
|
||
- Implementations should behave identically on Linux and macOS, with only filename extensions and
|
||
platform preflight checks differing.
|
||
- Any divergence must be documented and guarded by platform feature tests.
|
||
|