import type { RecoveryFsRoot } from "@gajae-code/natives"; import type { ResumeSessionIdentity } from "../session-manager"; import { type NativeDirectoryTreeSnapshot } from "../session-storage"; import { type ManagedDirectoryRoot, type ManagedSessionSecurityPolicy, type ManagedStorageLock } from "./managed-session-storage"; export declare const MANAGED_SESSION_LAYOUT_VERSION: 2; export declare const MANAGED_SESSION_IDENTITY_VERSION: 1; export declare const MANAGED_SESSION_BINDING_FILE = ".gjc-managed-session-scope.v2.json"; export interface ManagedScope { apiVersion: 1; layoutVersion: 2; identityVersion: 1; agentDir: string; sessionsRoot: string; canonicalCwd: string; legacyLexicalCwd: string; directoryName: string; directoryPath: string; platform: "posix" | "win32"; } /** * Opaque managed writer authority captured by a trusted destination. The open * transaction must use this authority rather than reacquiring its root from a * pathname after resume inspection. */ export interface ManagedCandidateWriteAuthority { readonly rootAuthority: ManagedDirectoryRoot; readonly retainedAuthority?: RecoveryFsRoot; readonly retainedDirectory?: string; } export declare function managedDirectoryAuthorityForScope(scope: ManagedScope): RecoveryFsRoot | undefined; export declare function managedDirectoryIdentityForScope(scope: ManagedScope): { dev: bigint; ino: bigint; }; export declare function managedRootForScope(scope: ManagedScope): ManagedDirectoryRoot; export type ManagedMigrationPolicy = "copy-retain" | "disabled"; export type ManagedScopeErrorCode = "cwd_missing" | "cwd_not_directory" | "identity_unavailable" | "network_unsupported" | "sessions_root_unavailable" | "binding_conflict" | "binding_invalid" | "migration_busy" | "atomic_unavailable" | "invalid_request" | "durability_failed" | "durability_not_provable" | "capacity_exceeded"; export type ManagedScopeResolution = { kind: "resolved"; scope: ManagedScope; } | { kind: "error"; code: ManagedScopeErrorCode; message: string; cause?: { readonly classification: string; readonly diagnostic?: string; }; }; export interface ManagedCandidate { sessionId: string; path: string; cwd: string; provenance: "v2" | "legacy"; identity: ResumeSessionIdentity; migrationState: "native_v2" | "legacy_unmigrated" | "migrated_v2"; } export type ManagedCandidateListing = { kind: "complete"; scope: ManagedScope; owned: readonly ManagedCandidate[]; foreignCount: number; invalid: readonly { code: string; }[]; } | { kind: "error"; code: "scan_failed" | "unsafe_root" | "invalid_candidate"; message: string; }; export type ManagedOpenFailure = "migration_busy" | "binding_conflict" | "binding_invalid" | "destination_conflict" | "source_changed" | "unsafe_artifacts" | "artifact_capacity_exceeded" | "durability_failed" | "atomic_unavailable" | "invalid_request" | "durability_not_provable" | "migration_retired" | "legacy_migration_disabled" | "managed_storage_unsupported"; export type ManagedOpenCandidateResult = { kind: "opened"; path: string; candidate: ManagedCandidate; migrated: boolean; } | { kind: "error"; code: ManagedOpenFailure; message: string; }; export type ManagedDeleteCandidateResult = { kind: "deleted"; tombstonePath: string; } | { kind: "already_deleted"; tombstonePath: string; } | { kind: "cleanup_pending"; tombstonePath: string; phase: "artifacts" | "transcript"; message: string; } | { kind: "error"; code: ManagedOpenFailure; message: string; }; export interface ManagedVerifiedDeleteTestEvent { readonly flow: "direct" | "reconcile"; readonly stage: "initial" | "artifact-finalization" | "transcript-after-artifacts-removed"; } export interface ManagedLockReleaseTestEvent { readonly path: string; readonly attemptId: string; } /** Test-only ordering seams for verified deletion and managed-lock release. */ export declare const ManagedSessionScopeTestHooks: { beforeVerifiedDelete?: (event: ManagedVerifiedDeleteTestEvent) => void | Promise; beforeManagedLockRelease?: (event: ManagedLockReleaseTestEvent) => void | Promise; }; declare function scopeDigest(platform: "posix" | "win32", canonicalPath: string): string; export declare const computeManagedScopeDigest: typeof scopeDigest; /** * Resolve benign symlinks in the deepest existing ancestor of a trusted storage * root (e.g. macOS `/var -> /private/var`, or a symlinked `$HOME`) while keeping * any not-yet-created tail verbatim. The native owner-only primitive and the * session-storage reparse guard traverse with `O_NOFOLLOW` and reject every * symlink component, so the trusted root must be canonical before it reaches * them; canonicalizing only the existing prefix never follows an * attacker-plantable component below the root. */ export declare function canonicalizeTrustedPath(target: string): string; interface ManagedScopeInput { cwd: string; agentDir: string; sessionsRoot: string; } export declare function resolveManagedScope(input: ManagedScopeInput): ManagedScopeResolution; /** Resolve a scope for a synchronous write without mutating an existing ACL mismatch. */ export declare function resolveManagedScopeForWrite(input: ManagedScopeInput): ManagedScopeResolution; export declare function canonicalBindingOpenFlags(platform?: NodeJS.Platform): number; export declare function fsyncCanonicalBinding(bindingPath: string, expected: string): void; export declare function ensureManagedScope(scope: ManagedScope, policy?: ManagedSessionSecurityPolicy): Promise; /** * Re-apply owner-only security to every descendant of a managed scope directory. * * A managed scope can accumulate group/other-readable descendants when a * different code path writes into it without the secured managed-storage * helpers — notably the resident-cache `EphemeralBlobStore` created on the * explicit session path. The managed-tree snapshot fails closed on the first * such descendant (`mode_mismatch`), which would otherwise abort launch with an * uncaught exception. Re-securing the tree in place lets a drifted scope * recover on the next launch instead of trapping the user behind a fatal error. */ /** Re-secure owner-only modes under a managed directory (exported for legacy-local migration). */ export declare function resecureOwnerOnlyManagedTree(directory: string): void; /** * True when a managed setup error reflects a fixable owner-only *mode* drift * (group/other permission bits) rather than an ownership or identity change. * Only mode drift can be self-healed by re-applying owner-only permissions. */ export declare function isRecoverableOwnerOnlyModeDrift(error: unknown): boolean; /** Synchronously create and validate the v2 binding before a default session writer exists. */ export declare function prepareManagedSessionScopeForWriteSync(scope: ManagedScope, policy?: ManagedSessionSecurityPolicy, authority?: ManagedCandidateWriteAuthority): ManagedScopeResolution; export declare function listManagedCandidates(scope: ManagedScope): ManagedCandidateListing; export declare function artifactTreeReplayCompatible(observed: NativeDirectoryTreeSnapshot, expected: NativeDirectoryTreeSnapshot): boolean; type DetachedArtifactRoot = { originalPath: string; detachedPath: string; identity: { dev: bigint; ino: bigint; size: bigint; mtimeNs: bigint; parentDev: bigint; parentIno: bigint; }; tree: NativeDirectoryTreeSnapshot; }; export declare function matchesMigrationArtifactRoot(pathname: string, identity: { dev: bigint; ino: bigint; size: bigint; mtimeNs: bigint; }, expectedTree: NativeDirectoryTreeSnapshot, platform?: NodeJS.Platform): boolean; type SourceArtifactCleanup = { state: "cleanup_pending"; role: "exchange_placeholder"; retainedPath: string; identity: DetachedArtifactRoot["identity"]; tree: NativeDirectoryTreeSnapshot; }; export declare function cleanupAuthorityMatches(cleanup: SourceArtifactCleanup, parent: string, platform?: NodeJS.Platform): boolean; export declare function detachArtifactRootForMigration(plan: DetachedArtifactRoot, platform?: NodeJS.Platform): { detached: DetachedArtifactRoot; detachOutcome: "clean"; } | { detached: DetachedArtifactRoot; detachOutcome: "cleanup_pending"; cleanup: SourceArtifactCleanup; }; export declare function restorePreparedArtifactRoot(scope: ManagedScope, source: ManagedCandidate, lock?: ManagedStorageLock): void; /** Resume tombstoned cleanup under its original operation lease without restoring retired candidates. */ export declare function reconcileManagedTombstones(scope: ManagedScope, expectedCandidate?: ManagedCandidate): Promise; /** Create the v2 binding and private write protocol directories before managed writes. */ export declare function prepareManagedSessionScopeForWrite(scope: ManagedScope, policy?: ManagedSessionSecurityPolicy, authority?: ManagedCandidateWriteAuthority, expectedCandidate?: ManagedCandidate, expectedIdentity?: ResumeSessionIdentity): Promise; /** * Open a validated candidate for mutation. Legacy transcripts are copied exactly once * into v2 and retained at their original location; no transcript data is merged. */ export declare function openManagedCandidateForWrite(scope: ManagedScope, candidate: ManagedCandidate, expectedIdentityOrMigrationPolicy?: ResumeSessionIdentity | ManagedMigrationPolicy, migrationPolicy?: ManagedMigrationPolicy, authority?: ManagedCandidateWriteAuthority): Promise; /** Tombstone a verified managed candidate before exact-identity deletion. */ export declare function deleteManagedSessionCandidate(scope: ManagedScope, candidate: ManagedCandidate): Promise; export {};