Skip to content

ADR-0034: bounded native paths with typed projections and explicit direction

Status: accepted. All 698 provider units and 11 targeted live cases (four path facts plus seven native regressions) pass locally, with zero failures/skips and zero build warnings/errors. All four path fact names were audited against the retained local log; the owned fixture and network were removed. This increment does not claim a rerun of the full integration/specification suites.

FS-16 requires typed entry points with mandatory maximum depth, direction and result limit, retaining the native Cypher lane. Acceptance includes cycles, empty graphs, depth bounds and path materialization. Provide Database.QueryPathsAsync<TNode, TRelationship> using an explicit GraphPathPattern and native anchor values, with node/relationship projectors. This is an untracked native API; it neither changes the finalized EF model nor implements a second entity mapper. EF model filters, converters and identity/fixup are not implicitly applied to caller-declared native metadata.

The pattern validates the start label and 1–16 relationship types using the existing ASCII identifier policy. A call snapshots 1–16 non-null native scalar anchor fields, canonicalizes their order and parameterizes values. Require explicit Outgoing, Incoming or Both direction, maximum depth 0–64 and result limit 1–10000. Minimum depth defaults to one; zero-hop paths require an explicit minimum of zero. Only validated bounds and identifiers enter the fixed Cypher 5 statement. Arbitrary predicates, unbounded depth and wildcard relationship-type selection are not exposed.

One statement collects at most two start candidates before expansion. Zero returns an empty result with StartFound=false; two rejects before user projection rather than choosing an arbitrary node. Exactly one starts a native variable-length expansion. The query collects at most limit+1 paths so HasMorePaths reports an observed extra result, without a separate count query or silent truncation. A unique/indexed application anchor is recommended, but no schema is created and the physical same-statement diagnostic remains authoritative.

Retain default Cypher 5 relationship uniqueness: a node may repeat, but a physical relationship cannot repeat within one path. Parallel relationships remain distinct choices and cycles/self-loops remain visible. The explicit depth bound prevents unbounded repetition. Results preserve ordered node/relationship values and step directions relative to stored edge orientation. For self-loops the step direction follows Incoming when requested, otherwise Outgoing. No shortest-path, weighted-path, simple-node-path or deterministic result-order guarantee is introduced.

Validate every returned path, including the truncation witness, before invoking user projectors. Check native shape, depth, relationship types/uniqueness, anchor label and endpoint/direction sequence. Public result collections are read-only; projected values remain caller-owned. Native transaction ownership, cancellation checks, reentrancy and cleanup are reused. Results are never attached to EF and remain usable after owned session disposal.

Depth and count bounds do not bound graph scan/expansion work, property bytes or execution time. A dense graph can still be expensive; use a selective anchor and server timeout policy. Arbitrary native Cypher remains available for explicitly reviewed alternative algorithms. Record advanced traversal, deadlines and payload projection as extensions in the future register rather than claiming them here.

Acceptance must compare all directions against actual native paths over cycles, parallel edges, self-loops and disconnected nodes; distinguish missing/isolated/zero-hop starts; verify exact depth and truncation semantics, composite anchor parameters and duplicate rejection; preserve borrowed transaction writes, rollback, cancellation/projector errors and untracked ownership. Source-only tests do not close the live gate.

Sources checked 2026-10-11: variable-length paths and repeatable node/relationship path semantics. Explicit Cypher 5 retains its default relationship uniqueness, without opting into newer repeatable-element modes.