/**
 * Soft-delete primitive for the knowledge graph.
 *
 * MCP-tool callers must NEVER `DETACH DELETE` user-domain nodes. Use
 * `trashNode` to mark a node `:Trashed`; `restoreNode` removes the label;
 * `emptyTrash` hard-deletes nodes whose `trashedAt < now - graceDays`. The
 * 2026-04-20 incident wiped 19 nodes via a single autonomous `DETACH DELETE`
 * — Neo4j Community has no PITR, so properties were unrecoverable. This
 * primitive contains the blast radius for every caller.
 *
 * Unique-constraint handling: when the trashed node's labels carry single-
 * key UNIQUE constraints (e.g. `LocalBusiness.accountId`), the live values
 * are snapshotted into `_trashedKeys` (JSON) and nulled on the node, so
 * MERGE against the same key won't collide. `restoreNode` writes them back
 * and fails loudly when an active node already occupies the slot.
 *
 * Label-aware cascade: when `trashNode` trashes a `:Conversation`, it also
 * trashes every `(m:Message)-[:PART_OF]->(c)` Message in the same managed
 * transaction. This makes `MATCH (m:Trashed)` a correct audit primitive —
 * trashing a Conversation without cascading to its Messages silently
 * under-reports the blast radius. `restoreNode` reverses both sides.
 */
import type { Session } from "neo4j-driver";
export interface TrashParams {
    session: Session;
    accountId: string;
    elementId: string;
    /** Provenance marker — appears verbatim in `trashedBy` and `[trash:marked] by=`. */
    by: string;
    reason?: string;
}
export interface TrashResult {
    trashed: boolean;
    alreadyTrashed: boolean;
    nodeId: string;
    /** Labels excluding `:Trashed`. */
    labels: string[];
    trashedAt: string;
    originalKeys: Record<string, unknown>;
}
export declare function trashNode(params: TrashParams): Promise<TrashResult>;
export interface RestoreParams {
    session: Session;
    accountId: string;
    elementId: string;
}
export interface RestoreResult {
    restored: boolean;
    nodeId: string;
    labels: string[];
    restoredKeys: Record<string, unknown>;
}
export declare function restoreNode(params: RestoreParams): Promise<RestoreResult>;
export interface EmptyTrashParams {
    session: Session;
    accountId: string;
    /** Default 30. */
    graceDays?: number;
    dryRun?: boolean;
    /** Optional label whitelist — only nodes carrying any of these labels are eligible. */
    labels?: string[];
    /** Side-effect callback invoked before the `DETACH DELETE` for each
     *  emptied node, e.g. to clean disk attachments or purge sibling JSONL
     *  transcripts.
     *
     *  Contract (Task 237): if the callback **throws**, the candidate is
     *  **skipped this run** — no `DETACH DELETE` runs and no `[trash:emptied]`
     *  line emits. The thrown message lands in
     *  `[trash:empty-run] reason=onEmpty-failed` and the candidate becomes
     *  eligible again on the next sweep. Pre-Task-237 consumers
     *  (`removeAttachmentDir` for `:KnowledgeDocument`) cannot throw because
     *  they wrap `fs.rm({force:true})`, so the contract change is invisible
     *  to them. */
    onEmpty?: (node: TrashCandidate) => Promise<void>;
}
export interface TrashCandidate {
    elementId: string;
    labels: string[];
    trashedAt: string;
    trashedBy: string | null;
    /** Original unique-key snapshot — useful for KnowledgeDocument disk cleanup. */
    trashedKeys: Record<string, unknown>;
}
export interface EmptyTrashResult {
    graceDays: number;
    dryRun: boolean;
    candidates: TrashCandidate[];
    emptied: number;
}
export declare function emptyTrash(params: EmptyTrashParams): Promise<EmptyTrashResult>;
/**
 * Read-filter clause excluding trashed nodes for the given Cypher alias.
 *
 * Filters both the `:Trashed` label (primitive) and the `deletedAt`
 * property (KnowledgeDocument soft-delete). Belt-and-braces: a row marked
 * by either signal is excluded from reads.
 *
 *   notTrashed("node")    → "(NOT node:Trashed AND node.deletedAt IS NULL)"
 *   notTrashed("related") → "(NOT related:Trashed AND related.deletedAt IS NULL)"
 */
export declare function notTrashed(alias: string): string;
/** Runtime accessor for the static unique-keys map (for tests + sibling tooling). */
export declare function uniqueKeysForLabels(labels: string[]): string[];
/** Property names trashNode writes — exposed so callers can re-MERGE without colliding. */
export declare const TRASH_METADATA_PROPS: readonly string[];
//# sourceMappingURL=index.d.ts.map