/** * Cypher schema validation for the graph-mcp proxy. * * Tokenises a cypher string for labels (`:Label`) and relationship types * (`[:REL_TYPE]`, including `[r:TYPE]`, `[:TYPE*1..5]`, `[:A|B]`) and checks * each against a schema snapshot. Unknown tokens are returned with the * Levenshtein-nearest known tokens of the same kind as suggestions. * * Design posture: * - Defence layer, not a cypher correctness gate. Pass-through on any * unparseable pattern — Neo4j remains the syntax authority. * - Empty schema snapshot (cache not ready, or Neo4j unreachable at boot) * fails OPEN: ok=true, no rejections. The boot-race treatment is a * deliberate choice — refusing all cypher would wedge the admin agent * harder than the typo class this layer prevents. The caller emits * `validated=false` on the existing [graph-query] line so operators * still see the bypass. * - String literals are stripped before tokenisation to avoid matching * `:Foo` inside quoted content (e.g. `WHERE n.note CONTAINS ':Foo'`). */ export interface SchemaSnapshot { readonly labels: ReadonlySet; readonly relationshipTypes: ReadonlySet; } export interface UnknownToken { token: string; kind: "label" | "relationship"; nearest: string[]; hint: string; } export type ForbiddenKind = "drop-database" | "create-index" | "create-constraint" | "call-dbms" | "call-db-create"; export interface ForbiddenPattern { kind: ForbiddenKind; match: string; hint: string; } export interface ValidationResult { ok: boolean; unknown: UnknownToken[]; forbidden: ForbiddenPattern[]; labelTokens: string[]; edgeTokens: string[]; } export interface ValidateOptions { /** "read" (default) skips DDL/admin forbidden checks. "write" applies them. */ mode?: "read" | "write"; } export declare function stripStringLiterals(cypher: string): string; export declare function validate(cypher: string, snapshot: SchemaSnapshot, options?: ValidateOptions): ValidationResult; //# sourceMappingURL=cypher-validate.d.ts.map