Syndroodocs

Trust and registry

A provider runs in the same process as the CLI, with the same access. Syndroo therefore makes the choice explicit instead of pretending an in-process plugin is sandboxed: one implementation per provider, inspected and approved before it is imported.

One implementation per provider

The registry holds exactly one active implementation for each provider id. Official providers come from the build catalog; a configuration entry replaces the official one:

{
  "version": 1,
  "providers": {
    "bluesky": { "path": "./providers/my-bluesky" }
  }
}

path is the only accepted key per provider, and it resolves against the directory of the configuration file, never against the working directory or the CLI installation. Deleting the entry restores the built-in selection. There is no automatic discovery, no package-manager integration and no second implementation to fall back to.

What "trusted" means here

Approving a third-party provider is a statement that you trust this code to run with your credentials and your state. The bounded parameter passing between Core and the plugin is a contract, not a security boundary. The host shows the inspected candidate, and the first active load of a provider requires explicit authorization before the module is imported.

The approval record is written under the state root and binds the inspected fingerprint, provider id, resolved package root, entry point, version and dependency snapshot. The fingerprint is a SHA-256 digest over the sorted relative file names and the content of every included file, plus the package name, version, entry point and dependency graph. It is re-checked immediately before the module is imported, so a changed package is not silently reused.

What inspection does

  • Static filesystem reads only: no import, no lifecycle script, no install, no network.
  • Included files must be regular files. Symlinked files and directories, sockets, devices and FIFOs are refused, and a package root is canonicalized first.
  • Directory names such as node_modules, .git and the test directories are excluded from the walk, along with .md, LICENSE and NOTICE files.
  • Nested node_modules below the package root are rejected, because they could change module resolution for the package's own code.
  • Reads are bounded and use no-follow opens, with per-graph and per-file limits on packages, files, directories, depth and bytes.

Fail closed

An invalid override is refused; it never falls back to the built-in provider, because a silent fallback would send content through an implementation the caller did not choose. An apiVersion mismatch, a missing approval, a fingerprint change or a provider whose default export does not match its manifest all stop the run before anything is sent.

Before a publication sends anything, every selected target's provider is loaded and preflighted. One unavailable provider fails the whole prepare step, so a document cannot half-publish because a plugin was missing at the second target.

Official is a source, not a claim

Provenance is assigned by where an implementation came from: a built-in catalog entry is official, a configured override is third-party. A package name or a field inside a plugin cannot establish official provenance, and an override keeps its third-party provenance even when it ships the same code.

A hosted deployment is stricter: it runs only providers that are official or reviewed and registered with the deployment. Third-party providers belong to a local or self-hosted runtime, where the operator is the one who approves them.