Skip to content

Feature request: permission-pruned graph traversal #12

Description

@geoHeil

Use case

We are evaluating pgGraph for a multi-tenant application where graph traversal results must respect per-request visibility. The graph contains ordinary relational nodes and edge-table relationships, but not every caller can traverse every node or edge.

A simple example:

  • documents, entities, and relationships are registered as graph nodes/edges.
  • Each row has tenant scope, validity/window metadata, and a visibility marker such as an ACL-set id or permission bucket.
  • A request includes the current tenant, the caller's allowed visibility set, and sometimes an as_of timestamp.
  • Traversal should behave as if nodes/edges the caller cannot see do not exist. Hidden nodes should not appear in output and should not be usable as intermediate hops.

This is stronger than output filtering. If the graph is:

A -- B -- C

and the caller can see A and C but not B, a 2-hop traversal from A should not reach C through hidden B.

Current fit

pgGraph already has useful pieces for this:

  • tenant_column / tenant := ... filters graph membership during traversal.
  • registered filter columns can be pushed into the in-memory filter index.
  • edge labels can be filtered with edge_types.

Those cover some hot paths, for example tenant-only visibility or a small static permission bucket that can be modeled as a registered filter column.

The gap is richer per-request visibility, especially when visibility depends on multiple row fields and request parameters, such as:

  • node visibility and edge visibility both matter;
  • allowed ACL-set ids vary per caller/request;
  • historical as_of traversal must respect row validity windows;
  • hidden intermediate nodes/edges must prune traversal, not just be filtered from hydrated output.

Feature request / design question

Would pgGraph consider a first-class way to express permission-pruned traversal beyond tenant scope? Possible shapes could be:

  • a traversal-time node/edge filter API that is guaranteed to prune expansion;
  • registered visibility columns with request-time allowed-value sets, e.g. acl_set_id IN (...);
  • separate node and edge filter scopes, since traversing through a hidden edge should also be impossible;
  • documented guidance for building request-safe projections when dynamic visibility cannot be pushed into the traversal engine.

The key semantic requirement is: filters used for authorization must participate before a candidate enters the frontier/visited set. Hydration-time filtering is not sufficient for this use case because it can still allow reachability through hidden intermediate rows.

Why this matters

Permission-pruned traversal is common for product graphs over business data: document/entity graphs, customer/account relationships, incident graphs, knowledge graphs, and internal search/RAG contexts. These workloads often need pgGraph's fast bounded traversal, but they also need authorization correctness on the traversal path itself.

Even a documented recommendation like "tenant scope and registered filter columns are safe for traversal pruning; hydrated filters are output-only and should not be used for authorization" would be helpful. A richer API for request-time ACL sets would make pgGraph much easier to adopt for user-facing graphs.

Version checked

This was evaluated against pgGraph 0.1.7.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions