Approval required for deploy-cloud
Files touched
1 file- packages/components/src/components/approval-card/approval-card.svelte
- package: "@lostgradient/cinder"
- dryRun: false
Durable human-in-the-loop approval surface for reviewing risky tool operations before they execute.
Presentational human-in-the-loop approval surface for reviewing a tool operation before the host application executes it.
<script lang="ts">
import ApprovalCard from '@lostgradient/cinder/approval-card';
</script>
<ApprovalCard
tool={{ name: 'deploy-cloud', risk: 'medium' }}
sandbox={{
provider: 'codex',
name: 'workspace-write',
workingDir: '/workspace/project',
}}
operation={{
kind: 'command',
command: 'bun run --filter=@lostgradient/cinder validate',
argsPreview: { package: '@lostgradient/cinder' },
}}
env={['DATABASE_URL', 'OPENAI_API_KEY']}
policyVersion="policy-2026-06"
idempotencyKey="approval-01JZ8T"
state="pending"
onResolve={(resolution) => console.log(resolution)}
/>ApprovalCard is fully controlled. It does not execute commands, apply patches,
persist policy decisions, or read environment values. The component only renders
the supplied context and invokes callback props for host-owned actions.
onResolve is the single decision contract. It fires for every action —
Approve, Approve with edits, Deny, and Dismiss — with the complete
ApprovalResolution payload: the selected decision, parsed editedArgs for
edited approvals, optional reason text, and the remember checkbox state.
Action buttons render only while the request is actionable and onResolve is
wired; a card without the callback is purely presentational.
decision: 'deny' means the approver actively refused the operation.
decision: 'cancel' (the Dismiss button) means the prompt was dismissed
without a decision.
tool.name renders in monospace inside the title, distinguishing the
identifier from the surrounding sentence.tool.risk renders as a stacked-bar signal icon (bar count scales with
risk, so it doesn't rely on color alone) with a tooltip carrying the risk
label; the icon itself is the accessible name via aria-label.operation.kind: 'command' renders the command as a syntax-highlighted
shell CodeBlock.operation.kind: 'patch' renders the supplied unified patch as a
syntax-highlighted diff.operation.filesTouched renders one row per unique path, each with a copy
button. Duplicate paths are collapsed.operation.argsPreview renders through PayloadInspector; oversized
previews are replaced with a bounded truncation notice before rendering.env renders variable names only, as plain text. Values are not accepted
and are stripped if a caller accidentally passes NAME=value.Pending requests render action buttons. Non-pending requests render a
read-only, state-tinted summary. When expiresAt passes while state is
still pending, the effective state becomes expired, actions disappear, and
no callback fires automatically.
The card title defaults to an h3 with section headings one level deeper.
Pass headingLevel to fit the card into the host page's document outline,
matching the Card convention.
bun run --filter=@lostgradient/cinder validateA pending command approval with sandbox context, arguments, environment names, and editable arguments.
A read-only approval request whose pending decision window has expired.
A high-risk patch approval that previews the proposed diff, touched files, and arguments.
Name | Type | Default | Description |
|---|---|---|---|
tool required | {
/** Human-readable tool name requesting approval. */
name: string;
/** Risk level assigned by the policy evaluator. */
risk: ApprovalToolRisk;
} | — | Tool requesting approval. |
sandbox | {
/** Sandbox provider, such as Codex or a remote execution backend. */
provider: string;
/** Sandbox profile or policy name. */
name: string;
/** Wor… Show full type{
/** Sandbox provider, such as Codex or a remote execution backend. */
provider: string;
/** Sandbox profile or policy name. */
name: string;
/** Working directory for the pending operation. */
workingDir: string;
} | — | Optional sandbox context in which the operation will run. |
operation required | {
/** Operation family being approved. */
kind: 'command';
/** Shell command for command approvals. */
command: string;
/** File paths that the operat… Show full type{
/** Operation family being approved. */
kind: 'command';
/** Shell command for command approvals. */
command: string;
/** File paths that the operation may read or write. Duplicate paths are collapsed for display. */
filesTouched?: string[];
/**
* JSON-like argument preview shown to the approver.
*
* @schemaPermissive
*/
argsPreview?: unknown;
} | — | Operation details shown to the approver. |
env | string[] | [] | Environment variable names only. Values are ignored if accidentally supplied as NAME=value. |
snapshotId | text | — | Snapshot identifier for the pending approval context. |
policyVersion required | text | — | Policy version that produced the approval request. |
idempotencyKey required | text | — | Idempotency key that makes repeated decisions durable. |
expiresAt | text | — | Optional ISO timestamp after which a pending approval is treated as expired. |
state required | 'pending'|'approved'|'approved_with_edits'|'denied'|'expired'|'cancelled' | — | Persisted approval state. |
editableArgs | boolean | false | Whether approving with edited JSON arguments is available. Default false. |
headingLevel | 2|3|4|5|6 | 3 | Heading level for the card title; section headings render one level deeper. Default 3. |
onResolve | (resolution: ApprovalResolution) => void | — | Called for approve, approve-with-edits, deny, and dismiss with the complete resolution payload. |
id | text | — | — |