graphql: add a tenant reachability filter to serviceAccounts - #3292
Draft
GregorShear wants to merge 1 commit into
Draft
graphql: add a tenant reachability filter to serviceAccounts#3292GregorShear wants to merge 1 commit into
GregorShear wants to merge 1 commit into
Conversation
GregorShear
force-pushed
the
greg/gql-tenant-filter
branch
from
August 3, 2026 20:54
18eb725 to
e516e83
Compare
This was referenced Aug 3, 2026
GregorShear
force-pushed
the
greg/gql-tenant-filter
branch
from
August 3, 2026 23:42
e516e83 to
db2611b
Compare
GregorShear
force-pushed
the
greg/gql-tenant-filter
branch
from
August 3, 2026 23:44
db2611b to
5a74132
Compare
serviceAccounts(filter: {tenant}) narrows a listing to the accounts an organization reaches through the role-grant graph. tenant_reachable_prefixes walks the graph from the caller's footholds within the tenant — their authorized prefixes clamped into its subtree — and keeps prefixes reached with QueryServiceAccounts, so a branch-scoped caller witnesses only reach flowing from namespace they occupy. The reachable set is intersected with the caller's own authorized prefixes, keeping the deeper prefix of each overlapping pair, so the filter only ever removes rows the caller could already see. Naming a tenant requires at least one foothold; the denial is a function of the caller's own grants alone and reveals nothing about the tenant, including whether it exists. Also documents the MAX_PREFIXES guard, which the intersection can newly trip when a broad caller prefix fans out into many deeper reachable prefixes.
GregorShear
force-pushed
the
greg/gql-tenant-filter
branch
from
August 3, 2026 23:46
5a74132 to
450ba60
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
serviceAccounts(filter: { tenant: "acmeCo/" }), narrowing a listing to the accounts an organization reaches through the role-grant graph.tenant_reachable_prefixeswalks role grants from the caller's footholds within the tenant — their authorized prefixes clamped into its subtree — and keeps the prefixes reached withQueryServiceAccounts. Seeding from footholds rather than the tenant root means a branch-scoped caller witnesses only reach flowing from namespace they occupy; edges granted to sibling branches contribute nothing. For a caller whose foothold covers the tenant root, the walk is the tenant's full reach.intersect_prefixeskeeps the deeper prefix of each overlapping pair, so the result feedscatalog_name ^@ ANY($1)without admitting anything outside either set. The filter only ever removes rows the caller could already see.QueryServiceAccountssomewhere within (or covering) the tenant's namespace. Without a gate, filtering by an arbitrary tenant and observing which namespaces return rows would reveal its role-grant edges; the check is a function of the caller's own grants alone, so a denial reveals nothing about the tenant.The filter lives on
serviceAccountsonly; promoting it into the sharedPrefixFilterlater is mechanical.Unit tests cover the capability-scoped walk (including ancestor-edge inheritance, sibling-branch exclusion, and multi-seed union) and the intersection. An integration test asserts the filter keeps only the deeper
deepCo/team/branch of a broader authorization, never widens past the caller's access, admits a branch-scoped caller filtering by the enclosing tenant, denies tenants the caller holds nothing in, and rejects malformed input.Dashboard consumer: estuary/ui#2042, which depends on this deploying first.