Why this exists
Split out of #2291, which proposed reaching "resolve authorization once per page"
(instead of once per project) via a paginated OpenFGA ListObjects path. Review of
that proposal found ListObjects has no pagination in the OpenFGA API itself and its
cost scales with a user's inherited-grant footprint on this platform's recursive
parent relation — some users hold evaluated writer on 1,000+ projects across dozens
of foundations purely through inheritance, so a single ListObjects call is bounded
only by OpenFGA's own truncation cutoff, not a cheap per-page primitive.
The same underlying goal — authorization resolved once per page rather than once per
item, without full-set enumeration or per-item check fan-out — is already scoped as an
architecture-team-directed JIRA ticket, LFXV2-2887 ("Query Service
model-awareness: serve evaluated relations (writer) so clients can drop permission
sweeps"), which explicitly rules out ListObjects:
"...or FGA ListObjects, which the platform is deliberately built to avoid."
This is a lightweight tracking issue so lfx-self-serve contributors without JIRA
access have visibility into that direction and its implications for this repo, without
re-proposing the rejected ListObjects approach.
Summary of LFXV2-2887's direction
- Collapse
fga-sync into the indexer service and push direct-grant tuples into
OpenSearch in realtime, removing lfx-v2-query-service's need to call ReadTuples
for direct-grant filtering.
- Add OpenFGA model-awareness to
lfx-v2-query-service so it can perform model
traversal itself and serve client-requested evaluated relations (e.g. writer),
filtered in the search index — pagination comes from the existing OpenSearch
keyset (search_after) paging, with no reliance on an unbounded OpenFGA call.
What it would unlock for lfx-self-serve, per the JIRA ticket: a cheap evaluated
eligibility signal for "does this user hold writer/meeting_coordinator on anything",
per-page result filtering by evaluated relation without per-page batch-check fan-out,
and retiring the deferred full-sweep machinery behind /api/projects and the
writer-summary direct-grant approximation.
Scope of this issue
Tracking only. No implementation here — implementation lives in
lfx-v2-query-service / lfx-v2-fga-sync under LFXV2-2887. Update this issue (or file
follow-ups against it) as that work lands and lfx-self-serve call sites
(WriterGrantsService, the create picker, writer-summary) migrate.
Related
Why this exists
Split out of #2291, which proposed reaching "resolve authorization once per page"
(instead of once per project) via a paginated OpenFGA
ListObjectspath. Review ofthat proposal found
ListObjectshas no pagination in the OpenFGA API itself and itscost scales with a user's inherited-grant footprint on this platform's recursive
parentrelation — some users hold evaluatedwriteron 1,000+ projects across dozensof foundations purely through inheritance, so a single
ListObjectscall is boundedonly by OpenFGA's own truncation cutoff, not a cheap per-page primitive.
The same underlying goal — authorization resolved once per page rather than once per
item, without full-set enumeration or per-item check fan-out — is already scoped as an
architecture-team-directed JIRA ticket, LFXV2-2887 ("Query Service
model-awareness: serve evaluated relations (writer) so clients can drop permission
sweeps"), which explicitly rules out
ListObjects:This is a lightweight tracking issue so
lfx-self-servecontributors without JIRAaccess have visibility into that direction and its implications for this repo, without
re-proposing the rejected
ListObjectsapproach.Summary of LFXV2-2887's direction
fga-syncinto the indexer service and push direct-grant tuples intoOpenSearch in realtime, removing
lfx-v2-query-service's need to callReadTuplesfor direct-grant filtering.
lfx-v2-query-serviceso it can perform modeltraversal itself and serve client-requested evaluated relations (e.g.
writer),filtered in the search index — pagination comes from the existing OpenSearch
keyset (
search_after) paging, with no reliance on an unbounded OpenFGA call.What it would unlock for
lfx-self-serve, per the JIRA ticket: a cheap evaluatedeligibility signal for "does this user hold writer/meeting_coordinator on anything",
per-page result filtering by evaluated relation without per-page batch-check fan-out,
and retiring the deferred full-sweep machinery behind
/api/projectsand thewriter-summarydirect-grant approximation.Scope of this issue
Tracking only. No implementation here — implementation lives in
lfx-v2-query-service/lfx-v2-fga-syncunder LFXV2-2887. Update this issue (or filefollow-ups against it) as that work lands and
lfx-self-servecall sites(
WriterGrantsService, the create picker,writer-summary) migrate.Related