import type { ExecutionQueueInfo, ExecutionResult, InternalExecutionOptions, KernelOutput, StartKernelOptions } from '../kernel/types'; import { CANONICAL_HASH_PROFILE, type CanonicalJsonValue } from './canonical-json'; import { ProvenanceStore } from './provenance-store'; export type ReplaySealState = 'pending' | 'running' | 'completed' | 'failed'; export interface ReplaySealArtifactRequest { path: string; sha256: string; size_bytes: number; } export interface ReplaySealRequest { notebook_path: string; run_id: string; task_id: string; source_id: string; source_notebook_sha256: string; artifacts: ReplaySealArtifactRequest[]; kernel_name?: string; input_manifest: Record; environment_manifest: Record; } export interface SealCellManifest { cell_id: string; source_sha256: string; exploratory_outputs_sha256: string; outputs_sha256: string; replay_comparison_outputs_sha256: string; outputs_match_exploratory: boolean; exploratory_execution_count: number | null; execution_id: string; execution_count: number; status: 'completed'; } export interface SealArtifactManifest { source_path: string; path: string; sha256: string; size_bytes: number; } export interface RuntimeEnvironment { schema_version: 1; python: { executable: string; executable_realpath: string; implementation: string; version: string; platform: string; }; python_no_user_site: true; base_packages: Record; base_packages_sha256: string; task_local: { package_directory: string; packages: Record; packages_sha256: string; } | null; } export interface ReplaySealManifest { schema_version: 1; hash_profile: typeof CANONICAL_HASH_PROFILE; seal_id: string; source_notebook: { path: string; sha256: string; }; notebook: { path: string; sha256: string; }; input_manifest_sha256: string; environment_manifest_sha256: string; runtime_environment: RuntimeEnvironment; runtime_environment_sha256: string; event_chain_head_sha256: string; event_ledger: { path: string; prefix_size_bytes: number; prefix_sha256: string; head_sha256: string; head_seq: number; }; cells: SealCellManifest[]; artifacts: SealArtifactManifest[]; isolation: { fresh_kernel: true; network_isolated: false; filesystem_isolated: false; }; bootstrap?: { package_directory: string; source_sha256: string; outputs_sha256: string; execution_id: string; execution_count: number; status: 'completed'; }; manifest_sha256: string; } export type ReplaySealStatusResponse = { seal_id: string; status: 'pending' | 'running'; } | { seal_id: string; status: 'completed'; manifest: ReplaySealManifest; } | { seal_id: string; status: 'failed'; error: string; }; export interface ReplayKernelService { startKernel(options?: StartKernelOptions): Promise; executeCode(sessionId: string, code: string, onOutput: (output: KernelOutput, cellId?: string | null) => Promise, onQueueInfo?: (info: ExecutionQueueInfo) => void, cellId?: string | null, internalOptions?: InternalExecutionOptions): Promise; stopKernel(sessionId: string): Promise; } export interface ReplaySealServiceOptions { rootDirectory: string; kernelService: ReplayKernelService; provenanceStore?: ProvenanceStore; durable?: boolean; idFactory?: () => string; clock?: () => Date; } export declare class ReplaySealValidationError extends Error { readonly code = "REPLAY_SEAL_VALIDATION_ERROR"; constructor(message: string); } export declare class ReplaySealConflictError extends Error { readonly code = "IDEMPOTENCY_CONFLICT"; constructor(); } /** * Normalize only nbformat's equivalent text encodings for replay comparison. * * - stream.text: an array of strings is joined, a string is unchanged; * - data values for text/*, application/javascript, and image/svg+xml use the * same array-to-string join; * - every other JSON value, including binary MIME arrays and traceback, is * preserved exactly. * * This is intentionally separate from outputs_sha256, which hashes the exact * output JSON written to the immutable executed notebook. */ export declare function normalizeNotebookOutputsForComparison(value: unknown): CanonicalJsonValue[]; /** * Fresh-kernel, top-to-bottom replay and immutable evidence sealing. * * The service deliberately makes no network/filesystem-isolation claim. A * dedicated kernel prevents state inheritance from an exploratory session; * the immutable copies, hashes, and server-authored event prefix bind what ran. */ export declare class ReplaySealService { private static readonly queues; private readonly rootDirectory; private readonly registryDirectory; private readonly kernelService; private readonly provenanceStore; private readonly durable; private readonly idFactory; private readonly clock; private readonly processInstanceId; private readonly activeJobs; private readonly attemptedJobs; constructor(options: ReplaySealServiceOptions); submit(rawRequest: ReplaySealRequest, idempotencyKey: string): Promise; getStatus(sealId: string): Promise; private ensureRunning; private runJob; private failJob; private executeNotebookCell; private executeServerCode; private executeAndCapture; private appendExecutionEvent; private buildSealedNotebook; private preflightArtifacts; private sealArtifacts; private copyRegularFileImmutable; private baseEnvironmentProbeSource; private taskLocalBootstrapSource; private parseBaseEnvironmentProbe; private parseTaskLocalProbe; private compareBaseEnvironment; private compareTaskLocalEnvironment; private taskLocalDeclaration; private validateEnvironmentDeclaration; private parseFrozenNotebook; private normalizeRequest; private validateIdempotencyKey; private responseFor; private verifiedResponseFor; private verifyCompletedSeal; private verifyLedgerPrefix; private verifyManifestCells; private hashRegularFile; private registryPath; private ensureRegistryDirectory; private createSafeSealDirectory; private ensureSafeDirectoryChain; private hardenSealDirectory; private sealRequestEventKey; private persistJob; private updateJob; private readJob; private writeJsonAtomic; private writeImmutable; private readNotebookSource; private captureLedgerPrefix; private toJupyterOutput; private markerPayload; private parseObject; private stringMap; private plainRecord; private optionalRecord; private nonempty; private cellSource; private relativeInside; private assertNoSymlinkComponents; private assertNoSymlinkComponentsSync; private syncDirectory; private cloneJson; private errorMessage; private isNodeError; private runSerialized; }