Extension Concepts#

scafctl is built on two types of extensions: providers and auth handlers. Each can be delivered as a builtin (compiled into the scafctl binary) or as a plugin (a standalone binary communicating over gRPC).

This page defines the core terminology and links to the detailed development guides.

Terminology#

TermDefinition
ProviderA stateless execution unit that performs a single operation: fetching data (from), transforming values (transform), validating inputs (validation), executing side effects (action), or authenticating requests (authentication). Providers are the building blocks used inside solution resolvers.
Auth HandlerA stateful authentication manager that handles identity verification, credential storage, token acquisition, and request injection. Auth handlers manage OAuth flows, cache tokens across invocations, and are used by providers (like http) to authenticate outgoing requests.
BuiltinAn extension compiled directly into the scafctl binary. Builtin extensions are registered at startup and require no external binaries. Contributing a builtin extension means adding code to the scafctl repository.
PluginAn extension delivered as a standalone executable that communicates with scafctl over gRPC using hashicorp/go-plugin . Plugins run as separate processes, can be written in any gRPC-capable language, and are distributed independently via OCI catalogs, Go modules, or binary releases.
ExtensionUmbrella term for any provider or auth handler, whether builtin or plugin.
CapabilityA declared feature of a provider (e.g., from, transform, action) or auth handler (e.g., scopes_on_login, tenant_id). Capabilities let scafctl adapt behavior dynamically without hardcoded knowledge of each extension.

Extension Matrix#

BuiltinPlugin
ProviderCompiled into scafctl; 16 built-in providers (http, cel, exec…)Standalone gRPC binary; auto-fetched from OCI catalogs
Auth HandlerCompiled into scafctl; 3 built-in handlers (entra, github, gcp)Standalone gRPC binary; auto-fetched from OCI catalogs

When to Choose Builtin vs Plugin#

FactorBuiltinPlugin
DistributionShips with scafctlDistributed independently
LanguageGo onlyAny language with gRPC support
Dependency managementPart of scafctl’s go.modIsolated dependencies
Process isolationRuns in-processSeparate process (crash isolation)
Update cycleTied to scafctl releasesIndependent release cadence
Use caseCore functionality, general-purposeThird-party integrations, proprietary logic
ContributingPR to scafctl repoPublish to any OCI registry

Key Differences: Providers vs Auth Handlers#

AspectProviderAuth Handler
Interface2 methods: Descriptor(), Execute()8+ methods: Login(), Logout(), Status(), GetToken(), InjectAuth(), …
StateStateless — each execution is independentStateful — manages cached tokens, refresh tokens, sessions
Used bySolution resolvers (via from, transform, etc.)Providers (e.g., http provider calls InjectAuth() on requests)
Registryprovider.Registry (versioned, overwrite-protected)auth.Registry (name-keyed)
Capabilitiesfrom, transform, validation, action, authenticationscopes_on_login, scopes_on_token_request, tenant_id, hostname, federated_token
Plugin artifact kindproviderauth-handler

Plugin Communication#

Both provider plugins and auth handler plugins use hashicorp/go-plugin with gRPC:

┌─────────────────────┐        gRPC        ┌──────────────────────┐
│      scafctl        │◄──────────────────►│    Your Plugin       │
│  (host process)     │                     │  (plugin process)    │
│                     │                     │                      │
│  - Discovers plugin │                     │  - Implements gRPC   │
│  - Manages lifecycle│                     │    service interface  │
│  - Registers in     │                     │  - Exposes extensions│
│    appropriate      │                     │  - Handles execution │
│    registry         │                     │                      │
└─────────────────────┘                     └──────────────────────┘

Each plugin type has its own handshake and gRPC service:

Plugin TypeHandshake CookiegRPC ServiceGo Interface
Providerscafctl_provider_pluginPluginServiceProviderPlugin
Auth Handlerscafctl_auth_handler_pluginAuthHandlerServiceAuthHandlerPlugin

A single plugin binary exposes one type: either providers or auth handlers, not both.

Plugin Lifecycle#

  1. Declaration — plugin dependencies are declared in a solution’s bundle.plugins section with a kind (provider or auth-handler)
  2. Resolution — scafctl resolves version constraints against configured OCI catalogs
  3. Caching — binaries are downloaded and cached at $XDG_CACHE_HOME/scafctl/plugins/
  4. Loading — scafctl starts the plugin process and performs a gRPC handshake
  5. Discovery — scafctl queries the plugin for available extensions (GetProviders or GetAuthHandlers)
  6. Registration — each extension is wrapped and registered in the appropriate registry
  7. Execution — extensions are used like builtins (transparent to solution authors)
  8. Cleanup — plugin processes are terminated when scafctl exits

Development Guides#

GuideWhat It Covers
Provider Development GuideBuilding providers — both builtin (compiled into scafctl) and plugin (standalone gRPC binary)
Auth Handler Development GuideBuilding auth handlers — both builtin (compiled into scafctl) and plugin (standalone gRPC binary)
Plugin Auto-Fetching TutorialHow consumers auto-fetch plugins from OCI catalogs at runtime
Provider ReferenceComplete documentation for all built-in providers
Authentication TutorialUsing authentication in solutions (consumer perspective)