The Capabilities API gives you typed utilities to declare what permissions your plugin needs, validate them at runtime, and produce actionable diagnostics when a capability is missing or misconfigured.
Import
import {
createCapabilityBundle,
createProcessCapabilityBundle,
createFilesystemCapabilityBundle,
createWorkflowCapabilityBundle,
describeCapability,
parseMissingCapabilityError,
requireProcessScopeCapability,
requireFilesystemScopeCapability,
requireWorkflowProcessCapabilities,
} from "@anikitenko/fdo-sdk";
Types
PluginCapability
The full union of capability strings the FDO host recognizes:
type FilesystemScopeCapability = `system.fs.scope.${string}`;
type ProcessScopeCapability = `system.process.scope.${string}`;
type PluginCapability =
| "storage.json"
| "sudo.prompt"
| "system.hosts.write"
| "system.process.exec"
| FilesystemScopeCapability
| ProcessScopeCapability;
| Value | Category | Effect |
|---|
"storage.json" | storage | Persistent JSON key-value store |
"sudo.prompt" | sudo | Elevated privilege prompts |
"system.hosts.write" | hosts | Hosts-file mutation via host |
"system.process.exec" | process | Scoped process execution |
"system.fs.scope.<id>" | filesystem-scope | Scoped filesystem mutation |
"system.process.scope.<id>" | process-scope | Scoped process execution under a named policy |
CapabilityCategory
type CapabilityCategory =
| "storage"
| "sudo"
| "hosts"
| "filesystem-scope"
| "process"
| "process-scope"
| "unknown";
CapabilityDescriptor
Returned by describeCapability. Provides human-readable metadata about a capability.
type CapabilityDescriptor = {
capability: string;
label: string;
description: string;
category: CapabilityCategory;
};
MissingCapabilityDiagnostic
Returned by parseMissingCapabilityError. Contains everything you need to surface a user-facing error when a capability is not granted.
type MissingCapabilityDiagnostic = {
capability: PluginCapability | string;
action: string; // What the plugin was trying to do
category: CapabilityCategory;
label: string; // Human-readable capability name
description: string; // What the capability allows
remediation: string; // How to fix the missing capability
};
Bundle builders
createCapabilityBundle
Deduplicates and sorts an array of capabilities. Use this when assembling a PluginInitRequest.capabilities list.
createCapabilityBundle(capabilities: PluginCapability[]): PluginCapability[]
const caps = createCapabilityBundle([
"system.process.exec",
"system.process.scope.docker-cli",
"system.process.exec", // deduplicated
]);
// → ["system.process.exec", "system.process.scope.docker-cli"]
createProcessCapabilityBundle
Returns the canonical capability pair needed to execute scoped processes under a named scope. Normalizes the scope id (lowercase, alphanumeric/dash/dot only).
createProcessCapabilityBundle(scopeId: string): PluginCapability[]
const caps = createProcessCapabilityBundle("kubectl");
// → ["system.process.exec", "system.process.scope.kubectl"]
Throws if scopeId contains no alphanumeric characters after normalization.
createFilesystemCapabilityBundle
Returns the capability pair needed for scoped filesystem mutation: system.hosts.write plus the scoped system.fs.scope.<id> capability.
createFilesystemCapabilityBundle(scopeId: string): PluginCapability[]
const caps = createFilesystemCapabilityBundle("my-plugin-data");
// → ["system.fs.scope.my-plugin-data", "system.hosts.write"]
Throws if scopeId contains no alphanumeric characters after normalization.
createWorkflowCapabilityBundle
Alias for createProcessCapabilityBundle. Workflows require the same process execution capabilities.
createWorkflowCapabilityBundle(scopeId: string): PluginCapability[]
const caps = createWorkflowCapabilityBundle("deploy-workflow");
// → ["system.process.exec", "system.process.scope.deploy-workflow"]
Introspection
describeCapability
Returns a CapabilityDescriptor for any capability string — including unknown or future capabilities.
describeCapability(capability: PluginCapability | string): CapabilityDescriptor
const desc = describeCapability("system.process.exec");
// {
// capability: "system.process.exec",
// label: "Scoped Tool Execution",
// description: "Allows host-mediated execution of allowlisted operational tools...",
// category: "process"
// }
const scopeDesc = describeCapability("system.process.scope.kubectl");
// {
// capability: "system.process.scope.kubectl",
// label: "Process Scope: kubectl",
// description: "Allows scoped process execution inside the \"kubectl\" host policy.",
// category: "process-scope"
// }
parseMissingCapabilityError
Parses a thrown error (or error string) that matches the FDO missing-capability error pattern. Returns a MissingCapabilityDiagnostic if the error is a capability error, or null otherwise.
parseMissingCapabilityError(error: unknown): MissingCapabilityDiagnostic | null
try {
// some SDK call that requires a capability
} catch (err) {
const diag = parseMissingCapabilityError(err);
if (diag) {
console.error(`Missing: ${diag.label}`);
console.error(`Remediation: ${diag.remediation}`);
}
}
The parsed object includes:
| Field | Description |
|---|
capability | The missing capability string |
action | What the plugin was trying to do |
category | Capability category |
label | Human-readable name |
description | What the capability allows |
remediation | Steps to fix the issue |
Runtime guards
These functions throw a structured error if the required capability has not been granted. Call them before any privileged operation in your handler or render logic.
requireProcessScopeCapability
requireProcessScopeCapability(scopeId: string, action: string): void
Throws if system.process.scope.<scopeId> is not in the granted set.
requireProcessScopeCapability("kubectl", "list Kubernetes pods");
requireFilesystemScopeCapability
requireFilesystemScopeCapability(scopeId: string, action: string): void
Throws if system.fs.scope.<scopeId> is not in the granted set.
requireFilesystemScopeCapability("my-plugin-data", "write plugin config file");
requireWorkflowProcessCapabilities
Checks both system.process.exec and the scoped process capability for a given scope id. Use this before dispatching any workflow action.
requireWorkflowProcessCapabilities(scopeId: string, action: string): void
requireWorkflowProcessCapabilities("deploy-workflow", "run deployment workflow");
Full example
import {
createProcessCapabilityBundle,
parseMissingCapabilityError,
requireProcessScopeCapability,
} from "@anikitenko/fdo-sdk";
// Declare capabilities in plugin init
const capabilities = createProcessCapabilityBundle("kubectl");
// Pass to PluginInitRequest: { capabilities }
// Guard before use
function runKubectl() {
try {
requireProcessScopeCapability("kubectl", "execute kubectl commands");
// proceed with the privileged action
} catch (err) {
const diag = parseMissingCapabilityError(err);
if (diag) {
// Surface to user
return `Error: ${diag.label} is required. ${diag.remediation}`;
}
throw err;
}
}
Scope ids are normalized to lowercase alphanumeric with dashes and dots only. Spaces and special characters are replaced with -. Make sure the scope id in your plugin matches exactly what is configured in the host PluginRegistry.configureCapabilities() call.