import type { OpRecord } from '@struktoai/mirage-core/observe/record'; import type { Ops } from '@struktoai/mirage-core/ops/ops'; import { FileTable } from '@struktoai/mirage-core/runtime/handles/index'; import type { FileStat } from '@struktoai/mirage-core/types'; import type { Session } from '@struktoai/mirage-core/workspace/session/session'; export interface FuseAttr { mtime: Date; atime: Date; ctime: Date; nlink: number; size: number; mode: number; uid: number; gid: number; } export interface Handle { path: string; data?: Uint8Array; writeBuf?: [number, Uint8Array][]; } interface PrefetchEntry { data: Uint8Array; expires: number; } export interface MountCoreOptions { rootPrefix?: string; /** * Bind every op to this session's mount grants. The kernel-tier * primitive: bind-mount the tree into a container and the narrowing * travels with it. Enforcement happens inside dispatch/Ops via the * session context, so binding at the op entry point is sufficient. */ session?: Session; } /** * Protocol-neutral mount logic shared by every kernel adapter. * * Everything here is expressed in POSIX terms (attribute records, ordinary * thrown errors) and imports nothing from `@zkochan/fuse-native`, so it is * reusable by a non-FUSE adapter and unit-testable without a kernel. * * The division of labour: this class decides *what* the filesystem * contains, an adapter decides *how* to say it to a particular kernel * interface. Adapters translate the errors thrown here into their own * error codes with `classifyErrno`. Mirrors Python's `MountCore`. * * Every op goes through `ws.fs`, which delegates to the dispatcher, so * a mount walks the same door as a shell line (mount modes, policies, * cache, invalidation) and every op it runs lands in `ws.records` for * `drainOps`. Reaching `ws.dispatch` from here instead would skip the * record; reaching a backend directly would skip the door. */ export declare class MountCore { readonly ops: Ops; readonly session: Session | null; private readonly now; private readonly root; readonly handles: FileTable; readonly xattrs: Map>>; readonly prefetchCache: Map; private readonly prefetchInflight; private readonly uid; private readonly gid; constructor(ops: Ops, options?: MountCoreOptions); resolve(path: string): string; dirStat(): FuseAttr; fileStat(size: number): FuseAttr; /** * Fold merged stat attributes into an attr record. The workspace stat * already carries the namespace overlay (chmod bits, chown ids, touched * mtime), so honoring these fields here is what makes metadata ops * visible through a mount. String uid/gid (names) are skipped: the kernel * wants numeric ids and there is no user db to map against. */ applyStatAttrs(entry: FuseAttr, s: FileStat): FuseAttr; /** * The target to present for a namespace link at a mount path, or null * when not a link. Relative targets are stored verbatim and returned * as-is. Absolute targets name virtual paths, so they are rewritten * relative to the link's directory: returned raw, the kernel would * resolve them against the host root and escape the mountpoint. */ linkTarget(path: string): string | null; /** * The attrs a namespace link reports, from its own node row. * * Built from the target string alone, every link over a mount answered * the mount's construction time and the mounting user, so what * `chown -h` and `touch -h` wrote was invisible through the kernel. * The row is the same one the door answers a no-follow stat with. Size * stays the displayable target's length (what this mount's readlink * returns), and the mode is always lrwxrwxrwx: a symlink's permission * bits are not consulted by any POSIX system. */ linkStat(target: string, virtual: string): FuseAttr; cachedSize(path: string): number | null; cachedData(path: string): Uint8Array | null; /** * Fetch bytes for a size-unknown file and cache them so the open → read → * fstat burst (and subsequent stats within the TTL) reuse the same fetch. * With getattr reporting 0 pre-open, this hydration is what lets fgetattr * answer with the real byte length after open (mirrors Python's * `prefetch_read`). */ prefetch(path: string): Promise; /** Drain and return accumulated op records (mirrors Python's drainOps). */ drainOps(): OpRecord[]; private writeFile; /** * Merge buffered writes over the raw base and persist the result. * The base is read raw so a flush never stores a rendered view back * into the mount. */ private applyWrites; getattr(path: string): Promise; /** Attributes through an open handle, or path-based when not hydrated. */ fgetattr(path: string, fd: number): Promise; readdir(path: string): Promise; read(path: string, fd: number, pos: number, len: number): Promise; /** Buffer a write on its handle, or apply it directly when there is none. */ write(path: string, fd: number, data: Uint8Array, pos: number): Promise; create(path: string): Promise; mkdir(path: string): Promise; readlink(path: string): string; /** * Create namespace link `dest -> src` (ln -s src dest; libfuse passes * the pointee first). Relative sources are stored verbatim (resolved * at follow time, exactly like the shell `ln -s`); absolute sources * are mapped into virtual space so a scoped mount stores the path it * will later follow. */ symlink(src: string, dest: string): Promise; /** * Remove the entry at `path`, a link entry like any other. * * A link routes through the op door rather than straight to the node * table: `unlink` is a LINK_ENTRY_OPS member, so the door answers a * link path itself, gated by session grants and admission policies * and recorded on the ledger. Writing the table here instead let a * session-scoped kernel mount delete a link on a mount its profile * hides. Mirrors Python's MountCore.unlink. */ unlink(path: string): Promise; rename(src: string, dst: string): Promise; rmdir(path: string): Promise; truncate(path: string, size: number): Promise; statfs(): Record; setxattr(path: string, name: string, value: Buffer): void; getxattr(path: string, name: string): Buffer | undefined; listxattr(path: string): string[]; removexattr(path: string, name: string): void; open(path: string): Promise; release(fd: number): Promise; flush(path: string, fd: number): Promise; } export {}; //# sourceMappingURL=core.d.ts.map