import { validateFixtureBehavior, type FixtureBehavior, } from './fixture-behavior'; export const RUNTIME_EXECUTION_CAPABILITIES = [ 'artifact.read', 'file.read', 'receipt.read', 'receipt.write', 'tool.inspect', 'tool.execute', 'event.wait', 'run.child', 'run.progress', 'run.heartbeat', 'sheet.read', 'sheet.write', 'db.session', 'rate.acquire', 'budget.charge', 'billing.write', 'egress.fetch', 'secret.resolve', ] as const; export type RuntimeExecutionCapability = (typeof RUNTIME_EXECUTION_CAPABILITIES)[number]; const CAPABILITY_SET = new Set(RUNTIME_EXECUTION_CAPABILITIES); /** * Immutable authority persisted with a durable launch. It contains facts, not * a bearer credential, so a scheduler can mint one short-lived token per leg. */ export type RuntimeAuthorityDescriptor = { orgId: string; workflowId: string; runId: string; billingRunId?: string | null; playName: string; allowedSecrets: string[]; maxCreditsPerRun?: number | null; integrationMode?: 'live' | 'eval_stub' | 'fixture' | null; fixtureBehavior?: FixtureBehavior | null; synthetic?: boolean | null; actorUserId?: string | null; actorEmail?: string | null; /** * Whether THIS run may capture the docflow provenance trace. * * Resolved once, server-side, at run admission — the only place that has both * an actor and the rollout catalog. The runtime executes in a sandbox or on * the customer's machine with no auth context and must never ask: capture is * per-row on the hottest path there is, so the answer has to arrive as a fact * it was handed, like `maxCreditsPerRun` and `integrationMode` beside it. * * Absent means OFF. A launch queued before this field existed, a scheduler * that drops unknown keys, a caller that forgets to thread it — all land on * the pre-feature behavior, which is the whole point of the switch. */ docflowEnabled?: boolean | null; capabilities: RuntimeExecutionCapability[]; }; export const DEFAULT_RUNTIME_EXECUTION_CAPABILITIES = [ ...RUNTIME_EXECUTION_CAPABILITIES, ] as const satisfies readonly RuntimeExecutionCapability[]; /** Daytona receives these safe-to-steal capabilities, never raw DB access. */ export const DAYTONA_RUNTIME_EXECUTION_CAPABILITIES = DEFAULT_RUNTIME_EXECUTION_CAPABILITIES.filter( (capability) => capability !== 'db.session', ); export function isRuntimeExecutionCapability( value: unknown, ): value is RuntimeExecutionCapability { return typeof value === 'string' && CAPABILITY_SET.has(value); } export function normalizeRuntimeExecutionCapabilities( values: readonly unknown[] | null | undefined, ): RuntimeExecutionCapability[] { if (!Array.isArray(values)) return []; return [...new Set(values.filter(isRuntimeExecutionCapability))].sort(); } export function hasRuntimeExecutionCapability( values: readonly string[] | null | undefined, capability: RuntimeExecutionCapability, ): boolean { return Array.isArray(values) && values.includes(capability); } export function requireRuntimeAuthorityDescriptor( value: unknown, ): RuntimeAuthorityDescriptor { if (!value || typeof value !== 'object' || Array.isArray(value)) { throw new Error( 'Durable play launch is missing runtimeAuthority. Re-submit the run with the current runtime contract.', ); } const descriptor = value as Partial; const requiredStrings = [ descriptor.orgId, descriptor.workflowId, descriptor.runId, descriptor.playName, ]; const capabilities = normalizeRuntimeExecutionCapabilities( descriptor.capabilities, ); const fixtureBehavior = validateFixtureBehavior(descriptor.fixtureBehavior); if ( requiredStrings.some( (entry) => typeof entry !== 'string' || entry.trim().length === 0, ) || capabilities.length === 0 || !fixtureBehavior.ok || (fixtureBehavior.behavior !== null && descriptor.integrationMode !== 'fixture') ) { throw new Error( 'Durable play launch contains an invalid runtimeAuthority descriptor.', ); } return { orgId: descriptor.orgId!, workflowId: descriptor.workflowId!, runId: descriptor.runId!, billingRunId: descriptor.billingRunId ?? null, playName: descriptor.playName!, allowedSecrets: Array.isArray(descriptor.allowedSecrets) ? descriptor.allowedSecrets.filter( (entry): entry is string => typeof entry === 'string', ) : [], maxCreditsPerRun: descriptor.maxCreditsPerRun ?? null, integrationMode: descriptor.integrationMode ?? null, fixtureBehavior: fixtureBehavior.ok ? fixtureBehavior.behavior : null, synthetic: descriptor.synthetic === true, actorUserId: descriptor.actorUserId ?? null, actorEmail: descriptor.actorEmail ?? null, // `=== true`, not `?? false`: the normalizer is what a durable launch is // read back through, so anything that is not an explicit yes — missing, // null, a string that survived a JSON round trip — denies. docflowEnabled: descriptor.docflowEnabled === true, capabilities, }; }