LiteralString Type Constraint for Query Construction
Summary
The Eidos system enforces a strict architectural constraint requiring query fragments to be typed as LiteralString to ensure security and type safety. This policy identifies the PatternBuilder as a trusted boundary, allowing it to construct Cypher query components from controlled inputs while maintaining compatibility with static analysis tools and preventing injection vulnerabilities.
Details
Within the Eidos knowledge graph API, the construction of Cypher queries for Neo4j is governed by a security-conscious typing strategy. To mitigate the risk of injection attacks and to satisfy the requirements of static type checkers like Pyright or Mypy, the system distinguishes between standard Python strings (str) and LiteralString. This distinction is critical for functions that assemble the structural components of a query—such as node labels, relationship types, and variable names—which must never be derived from untrusted user input.
The PatternBuilder Trusted Boundary
The PatternBuilder class in builder.py serves as a central component for assembling these query fragments. An architectural decision was made to designate PatternBuilder as a “trusted boundary.” This designation implies that the logic within the builder is verified to only produce safe, structural query parts.
Initially, the PatternBuilder.build() method returned a standard str. This caused friction in the codebase, specifically when the output of build() was passed to methods like append_query_part or the where method, which require LiteralString. Developers were forced to use manual type casts at the call sites to satisfy the type checker.
To streamline the implementation and reinforce the security model, the return types for all three build() methods within the builder architecture were updated to return LiteralString directly. This change allows the builder to “promote” the assembled query fragments to a trusted status, reflecting the fact that they are constructed from controlled pieces.
Implementation and Refactoring
The refactoring process involved several key steps:
- Upstream Type Update: The return signature of
PatternBuilder.build()was changed fromstrtoLiteralString. - Removal of Downstream Casts: Because the source now returns the correct type, manual casts at call sites (e.g., within the
wheremethod logic) were reverted. This reduced code clutter and moved the responsibility for type safety to the builder itself. - Consistency with create_literal_str: This pattern aligns with the existing use of
create_literal_str, a utility used throughout Eidos to explicitly mark a string as a safe literal. By integrating this into thePatternBuilder, the system ensures that any query part generated through the builder is automatically treated as a safe, structural element.
Security Implications
This constraint is a key part of the Eidos security architecture. By enforcing LiteralString at the type level, the system creates a compile-time (or check-time) barrier against the accidental inclusion of raw user data into the structural parts of a Cypher query. While the Hermes agent handles external channel I/O, the Eidos API maintains the integrity of the knowledge graph by ensuring that only validated, “literal” fragments are used to manipulate the Neo4j backend.
Related
- Eidos
- Hyle Type System
- Security Boundary
- Neo4j Integration
- Hermes Agent