The Privileged Actions API lets your plugin request host-mediated operations that require elevated permissions: writing to /etc/hosts, mutating the filesystem within a declared scope, and executing scoped processes. All actions are validated before dispatch and travel through the host’s capability enforcement layer.
Import
import {
// Request builders
createHostsWriteActionRequest,
createFilesystemMutateActionRequest,
createProcessExecActionRequest,
createWorkflowRunActionRequest,
validatePrivilegedActionRequest,
createFilesystemScopeCapability,
createProcessScopeCapability,
// Transport
createPrivilegedActionBackendRequest,
requestPrivilegedAction,
// Response helpers
createPrivilegedActionCorrelationId,
isPrivilegedActionSuccessResponse,
isPrivilegedActionErrorResponse,
unwrapPrivilegedActionResponse,
} from "@anikitenko/fdo-sdk";
Types
HostsWriteActionRequest
type HostsWriteActionRequest = {
action: "system.hosts.write";
payload: {
records: HostsRecord[];
dryRun?: boolean;
tag?: string;
};
};
type HostsRecord = {
address: string;
hostname: string;
comment?: string;
};
FilesystemMutateActionRequest
type FilesystemMutateActionRequest = {
action: "system.fs.mutate";
payload: {
scope: string;
operations: FilesystemMutationOperation[];
dryRun?: boolean;
reason?: string;
};
};
FilesystemMutationOperation
All filesystem mutation operations are discriminated unions on type:
type FilesystemMutationOperation =
| { type: "mkdir"; path: string; recursive?: boolean; mode?: number }
| { type: "writeFile"; path: string; content: string; encoding?: "utf8" | "base64"; mode?: number }
| { type: "appendFile"; path: string; content: string; encoding?: "utf8" | "base64" }
| { type: "rename"; from: string; to: string }
| { type: "remove"; path: string; recursive?: boolean; force?: boolean };
ProcessExecActionRequest
type ProcessExecActionRequest = {
action: "system.process.exec";
payload: {
scope: string;
command: string;
args?: string[];
cwd?: string;
env?: Record<string, string>;
timeoutMs?: number;
input?: string;
encoding?: "utf8" | "base64";
dryRun?: boolean;
reason?: string;
};
};
PrivilegedActionSuccessResponse
type PrivilegedActionSuccessResponse<TResult = unknown> = {
ok: true;
correlationId: string;
result?: TResult;
};
PrivilegedActionErrorResponse
type PrivilegedActionErrorResponse = {
ok: false;
correlationId: string;
error: string;
code?: string;
};
PrivilegedActionResponse
The discriminated union returned from all requestPrivilegedAction calls:
type PrivilegedActionResponse<TResult = unknown> =
| PrivilegedActionSuccessResponse<TResult>
| PrivilegedActionErrorResponse;
RequestPrivilegedActionOptions
type RequestPrivilegedActionOptions = {
correlationId?: string; // Provide a fixed correlation id
handler?: string; // Override the iframe bridge handler name
correlationIdPrefix?: string; // Prefix for auto-generated correlation ids
};
Capability helpers
createFilesystemScopeCapability
Builds a typed system.fs.scope.<id> capability string from a scope id. Normalizes the id and throws if it contains no alphanumeric characters.
createFilesystemScopeCapability(scopeId: string): `system.fs.scope.${string}`
createFilesystemScopeCapability("my-plugin-data");
// → "system.fs.scope.my-plugin-data"
createProcessScopeCapability
Builds a typed system.process.scope.<id> capability string.
createProcessScopeCapability(scopeId: string): `system.process.scope.${string}`
createProcessScopeCapability("kubectl");
// → "system.process.scope.kubectl"
Request builders
All builders validate the request structure before returning. They throw if the request is malformed.
createHostsWriteActionRequest
createHostsWriteActionRequest(
request: HostsWriteActionRequest
): HostsWriteActionRequest
const req = createHostsWriteActionRequest({
action: "system.hosts.write",
payload: {
records: [
{ address: "127.0.0.1", hostname: "myapp.local", comment: "local dev" },
],
tag: "my-plugin",
},
});
createFilesystemMutateActionRequest
createFilesystemMutateActionRequest(
request: FilesystemMutateActionRequest
): FilesystemMutateActionRequest
const req = createFilesystemMutateActionRequest({
action: "system.fs.mutate",
payload: {
scope: "my-plugin-data",
operations: [
{ type: "mkdir", path: "/tmp/my-plugin", recursive: true },
{ type: "writeFile", path: "/tmp/my-plugin/config.json", content: '{"key":"value"}' },
],
reason: "Initialize plugin config directory",
},
});
createProcessExecActionRequest
createProcessExecActionRequest(
request: ProcessExecActionRequest
): ProcessExecActionRequest
const req = createProcessExecActionRequest({
action: "system.process.exec",
payload: {
scope: "kubectl",
command: "kubectl",
args: ["get", "pods", "-n", "default", "-o", "json"],
timeoutMs: 10000,
},
});
createWorkflowRunActionRequest
createWorkflowRunActionRequest(
request: ScopedWorkflowRunActionRequest
): ScopedWorkflowRunActionRequest
See Operator Tooling API for workflow types and examples.
validatePrivilegedActionRequest
Validates any privileged action request object. Returns the typed request or throws on invalid input.
validatePrivilegedActionRequest(request: unknown): HostPrivilegedActionRequest
Transport
createPrivilegedActionBackendRequest
Wraps a validated request in an envelope with a correlation id. Use this when you need the full PrivilegedActionBackendRequest envelope (e.g. for testing or custom transport).
createPrivilegedActionBackendRequest<TRequest extends HostPrivilegedActionRequest>(
request: TRequest,
options?: RequestPrivilegedActionOptions
): PrivilegedActionBackendRequest<TRequest>
const envelope = createPrivilegedActionBackendRequest(req, {
correlationIdPrefix: "kubectl-query",
});
// { correlationId: "kubectl-query-1718000000000", request: { ... } }
requestPrivilegedAction
Dispatches a privileged action request through the plugin iframe bridge and returns the host response. This is the primary function you call to execute a privileged operation.
requestPrivilegedAction<TResult = unknown, TRequest extends HostPrivilegedActionRequest = HostPrivilegedActionRequest>(
request: TRequest,
options?: RequestPrivilegedActionOptions
): Promise<PrivilegedActionResponse<TResult>>
requestPrivilegedAction only works inside the FDO plugin iframe runtime. It throws immediately if called outside that context (e.g. in unit tests without a mock).
const response = await requestPrivilegedAction(req, {
correlationIdPrefix: "kubectl-query",
});
if (isPrivilegedActionSuccessResponse(response)) {
console.log(response.result);
} else {
console.error(response.error);
}
Response helpers
createPrivilegedActionCorrelationId
Generates a time-stamped correlation id with an optional prefix.
createPrivilegedActionCorrelationId(prefix?: string): string
createPrivilegedActionCorrelationId("kubectl-query");
// → "kubectl-query-1718000000000"
isPrivilegedActionSuccessResponse
Type guard — returns true if response.ok === true and correlationId is a string.
isPrivilegedActionSuccessResponse<TResult = unknown>(value: unknown): value is PrivilegedActionSuccessResponse<TResult>
isPrivilegedActionErrorResponse
Type guard — returns true if response.ok === false, correlationId is a string, and error is a string.
isPrivilegedActionErrorResponse(value: unknown): value is PrivilegedActionErrorResponse
unwrapPrivilegedActionResponse
Returns response.result for a success response. For error responses, throws an Error with response.error as the message. If response.code is present, it is attached to the thrown error as .code.
unwrapPrivilegedActionResponse<TResult = unknown>(
response: PrivilegedActionResponse<TResult>
): TResult | undefined
try {
const result = unwrapPrivilegedActionResponse(response);
// result is TResult | undefined on success
} catch (err) {
// err is an Error; err.code may be set
}
End-to-end example: execute a scoped process
import {
createProcessExecActionRequest,
requestPrivilegedAction,
isPrivilegedActionSuccessResponse,
parseMissingCapabilityError,
} from "@anikitenko/fdo-sdk";
async function listKubernetesPods(): Promise<string> {
const req = createProcessExecActionRequest({
action: "system.process.exec",
payload: {
scope: "kubectl",
command: "kubectl",
args: ["get", "pods", "-n", "default", "-o", "json"],
timeoutMs: 15000,
},
});
try {
const response = await requestPrivilegedAction(req, {
correlationIdPrefix: "kubectl-pods",
});
if (isPrivilegedActionSuccessResponse(response)) {
return JSON.stringify(response.result, null, 2);
}
return `Error: ${response.error}`;
} catch (err) {
const diag = parseMissingCapabilityError(err);
if (diag) return `Missing capability: ${diag.label}. ${diag.remediation}`;
throw err;
}
}
End-to-end example: write to hosts file
import {
createHostsWriteActionRequest,
requestPrivilegedAction,
unwrapPrivilegedActionResponse,
} from "@anikitenko/fdo-sdk";
async function addHostEntry() {
const req = createHostsWriteActionRequest({
action: "system.hosts.write",
payload: {
records: [{ address: "127.0.0.1", hostname: "myapp.local", comment: "added by my-plugin" }],
tag: "my-plugin",
},
});
const response = await requestPrivilegedAction(req);
return unwrapPrivilegedActionResponse(response); // throws on error
}