Repository navigation
Closed
Labels
effort/lWeeksWeeksimpact/fewLimited audienceLimited audiencepriority/p3Polish / idea / may never shipPolish / idea / may never shipseverity/lowMinor harmMinor harmtriagedItem has been triagedItem has been triagedtype/featNew capabilityNew capabilityurgency/eventuallyNo deadlineNo deadline
Description
Summary
The current PurchaseHistoryFilter.ExternalIDs []string treats all external account numbers (e.g. AWS account IDs, Azure subscription IDs) as a flat list with no provider context. This means a filter for account number 123456789012 could in principle match rows from any provider that happens to share that number, rather than only matching the intended provider's rows.
Proposed change
Replace ExternalIDs []string with ExternalIDsByProvider map[string][]string (provider key -> list of external IDs). The predicate builder would then emit:
(cloud_account_id = ANY($u)
OR (provider = $p1 AND account_id = ANY($ids_for_p1))
OR (provider = $p2 AND account_id = ANY($ids_for_p2))
...)This ensures a filter for aws/123456789012 never pulls azure/123456789012 rows.
Scope
internal/config/types.go:PurchaseHistoryFilter.ExternalIDs->ExternalIDsByProvider map[string][]stringinternal/config/store_postgres.go:appendAccountPredicategains provider groupinginternal/api/analytics_postgres.go:accountFilterClausegains provider grouping (the full version reverted in PR fix(api): filter purchases by account UUID AND external id (closes #701, #498, #866) #956 is the target shape)internal/api/scoping.go:resolveAccountFilterIDs/resolveSingleAccountFilterIDsreturnmap[string][]stringinstead of[]stringinternal/api/handler_dashboard.go,handler_history.go,handler_analytics.go: update callers
Notes
- This was partially implemented in the
fix/account-filter-id-representationbranch but reverted (PR fix(api): filter purchases by account UUID AND external id (closes #701, #498, #866) #956) because it was build-breaking and outside the PR's focused scope. The fullsortedProviderKeys+ per-provider predicate logic is the intended end state. - The
ExternalIDs []stringflat form (landed in PR fix(api): filter purchases by account UUID AND external id (closes #701, #498, #866) #956) is the correct interim shape while this refactor is pending. - Add a regression test that verifies an
aws-scoped filter does not match a row whoseprovider = 'azure'andaccount_idhappens to be the same string.
Metadata
Metadata
Assignees
Labels
effort/lWeeksWeeksimpact/fewLimited audienceLimited audiencepriority/p3Polish / idea / may never shipPolish / idea / may never shipseverity/lowMinor harmMinor harmtriagedItem has been triagedItem has been triagedtype/featNew capabilityNew capabilityurgency/eventuallyNo deadlineNo deadline
Activity
refactor(api,config): revert ExternalIDsByProvider to flat ExternalID…
fix(api): filter purchases by account UUID AND external id (closes #701…
cristim commentedon Jul 27, 2026
Verification sweep against
main(101f099fb) on 2026-07-27 finds this already resolved.The ExternalIDsByProvider map landed with per-provider grouping in appendAccountPredicate.
Evidence: commit 5885697 (PR #956).
Recommending close.
cristim commentedon Sep 2, 2026
Verified resolved at 3c0f8ac: PurchaseHistoryFilter carries ExternalIDsByProvider (internal/config/types.go:747) and appendAccountPredicate emits a per-provider
(provider = $p AND account_id = ANY($ids))clause so an aws-scoped external id never matches an azure row. Evidence: internal/config/store_postgres.go:2107-2120 (#956, commit 5885697). Residual axes checked: analytics path (internal/api/analytics_postgres.go:104 accountFilterClause takes the same map), GetActivePurchaseHistory (store_postgres.go:2057 uses appendAccountPredicate), cross-provider regression test present at store_postgres_pgxmock_test.go:1031-1045. Closing as completed; reopen if the behaviour recurs.fix(api): filter purchases by account UUID AND external id (closes #701…