Filter Knowledge Graph queries from users without enabled namespaces

What does this MR do and why?

Filters JWT traversal IDs against knowledge_graph_enabled_namespaces via a subquery in AuthorizationContext, so users not in any KG-enabled namespace are blocked from querying. Returns 403 from the Orbit Data API and a tool error from the MCP endpoint when no enabled namespaces remain.

The filter runs as part of the existing GroupsFinder query -- no extra roundtrip.

Query plan

Raw SQL added by this MR (the WHERE ... IN (SELECT ...) clause):

WHERE namespaces.traversal_ids[1] IN (
  SELECT root_namespace_id FROM knowledge_graph_enabled_namespaces
)

EXPLAIN ANALYZE on GDK (18 enabled namespaces, 84 reporter-accessible groups):

Hash Join  (cost=53.89..56.45 rows=18 width=40) (actual time=0.255..0.295 rows=84 loops=1)
  Hash Cond: (namespaces.traversal_ids[1] = knowledge_graph_enabled_namespaces.root_namespace_id)
  Buffers: shared hit=220
  ->  Hash  (cost=1.18..1.18 rows=18 width=8) (actual time=0.011..0.011 rows=18 loops=1)
        Buckets: 1024  Batches: 1  Memory Usage: 9kB
        Buffers: shared hit=1
        ->  Seq Scan on knowledge_graph_enabled_namespaces
              (actual time=0.006..0.007 rows=18 loops=1)
              Buffers: shared hit=1

Execution: 0.41ms, 220 buffer hits (all shared cache). The root_namespace_id unique index is available; PostgreSQL flattens the subquery into a Hash Join. Result is cached in Rails.cache for 5 min per user.

Changelog: added EE: true

Edited by Michael Angelo Rivera

Merge request reports

Loading