Skip to content

control-plane-api: add filter to the liveSpecs GraphQL query and deprecate by - #3383

Draft
GregorShear wants to merge 2 commits into
masterfrom
greg/gql-live-specs-filter
Draft

control-plane-api: add filter to the liveSpecs GraphQL query and deprecate by#3383
GregorShear wants to merge 2 commits into
masterfrom
greg/gql-live-specs-filter

Conversation

@GregorShear

Copy link
Copy Markdown
Contributor

Gives liveSpecs the same treatment storageMappings received in #3242: the by argument is now optional and deprecated, replaced by a composable filter argument with a catalogName filter backed by the shared PrefixFilter input.

API changes

  • liveSpecs(by:) is optional and deprecated. It is retained for existing clients and its behavior is unchanged: it requires a names or prefix selection, applies its predicates conjunctively, and fails the entire request on an unauthorized name or prefix.
  • New liveSpecs(filter: { catalogName: { startsWith | in } }). startsWith replaces by.prefix (subtree match) and in replaces by.names (exact set). The filter only narrows: results are scoped to the prefixes where the caller has catalog-read capability, and unauthorized or unknown filter entries are dropped rather than erroring.
  • Omitting both by and filter returns every live spec the caller can read. As with storageMappings, a caller with more than 20 readable prefixes must narrow with a filter.
  • by and filter are mutually exclusive.

Implementation

Both paths resolve into one shared SQL query. The legacy by predicates are untouched; the filter path adds two text[] binds: the caller's authorized read prefixes (^@ any(...) scoping) and the exact in set. The filter path reuses filtered_authorized_prefixes, so the narrow-only invariant has the same single owner as storageMappings, alertConfigs, and inviteLinks.

Testing

  • New sqlx tests cover the filter path: unfiltered listing, startsWith/in narrowing, cross-tenant entries dropped, empty-filter forms, mutual exclusions, the MAX_PREFIXES guard, and the preserved by error behaviors.
  • New agent integration query snapshots exercise filter.catalogName as two users with different grants.
  • Regenerated the GraphQL SDL and sqlx query cache.

Gives `liveSpecs` the same treatment `storageMappings` received in #3242. The `by` argument is now optional and deprecated, replaced by a composable `filter` with a `catalogName` PrefixFilter: `startsWith` replaces `by.prefix` and `in` replaces `by.names`.

The two arguments are mutually exclusive and authorize differently: `by` keeps its exact legacy contract — requiring a `names` or `prefix` selection and failing the entire request on an unauthorized name — while `filter` resolves through `filtered_authorized_prefixes` and only narrows the caller's readable prefixes. Omitting both returns every live spec the caller can read, subject to the same MAX_PREFIXES guard as `storageMappings`.

Both paths resolve into one shared SQL query: the filter path adds text[] binds for the caller's read prefixes and the exact `in` set, leaving the legacy predicates untouched.
…as a stable layout

rustfmt flip-flops between two layouts of the long tuple-match scrutinee — `cargo fmt` writes one and `cargo fmt --check` demands the other — which failed CI's format check. Matching on `by` alone keeps the scrutinee short enough for a single stable layout.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant