Summary
PR #79 + the follow-up commit f44b06567 hardened resolveAWSCloudAccountID to fail closed on STS errors, preventing cross-tenant recommendation leaks in multi-tenant deployments. The fix landed without regression tests for the new failure paths — the existing internal/api/exchange_lookup_test.go covers the happy paths and the legitimate "no AWS context" fall-through but does not exercise:
- Transient STS error →
resolveAWSCloudAccountID returns a non-nil error, purchaseRecLookupFromStore aborts, handler returns 500/error to client.
- AWS SDK config load failure → returns
("", nil) and skips the AccountIDs filter (legitimate path, distinct from the STS-error path).
- Region query-string omitted → handler normalizes from
cfg.Region, store query is region-scoped (the MAJOR fix from afc3aa1ff).
- ListCloudAccounts error → bubbles up as wrapped error with
list cloud accounts for reshape scope: prefix.
Without these, a future refactor can silently break the security gates that the recent fixes added.
Why these specifically
These arent UI/UX concerns — they are security regression guards. The CRITICAL failure mode they prevent is "transient STS error in a multi-tenant deployment shows tenant A their alternatives + tenant B sources mixed in". The fix is in place; the test pinning it isnt.
Proposed tests
All in internal/api/exchange_lookup_test.go:
// Mock the STS-resolver primitive to return an error.
func TestResolveAWSCloudAccountID_FailsClosedOnSTSError(t *testing.T) { ... }
// Same primitive returns ("", nil) — legitimate Azure/GCP host path.
func TestResolveAWSCloudAccountID_PassesNilWhenNoAWSContext(t *testing.T) { ... }
// Mock a fake recsLister returning an error from ListStoredRecommendations.
func TestPurchaseRecLookupFromStore_PropagatesStoreError(t *testing.T) { ... }
// Region query-string empty — handler normalizes from cfg.Region.
func TestHandleRIExchangeReshape_EmptyRegionUsesConfigRegion(t *testing.T) { ... }
The STS-error test is the most important — it pins the multi-tenant safety contract.
References
Severity
Low-Medium — no current bug, but a regression guard for an addressed CRITICAL.
Effort
Small — ~80 LOC, all in one test file. Mocking STS GetCallerIdentity requires an extra interface seam (stsClient) which doesnt exist today; either add it or use a higher-level test that drives the failure through the public Handler API.
Summary
PR #79 + the follow-up commit
f44b06567hardenedresolveAWSCloudAccountIDto fail closed on STS errors, preventing cross-tenant recommendation leaks in multi-tenant deployments. The fix landed without regression tests for the new failure paths — the existinginternal/api/exchange_lookup_test.gocovers the happy paths and the legitimate "no AWS context" fall-through but does not exercise:resolveAWSCloudAccountIDreturns a non-nil error,purchaseRecLookupFromStoreaborts, handler returns 500/error to client.("", nil)and skips the AccountIDs filter (legitimate path, distinct from the STS-error path).cfg.Region, store query is region-scoped (the MAJOR fix fromafc3aa1ff).list cloud accounts for reshape scope:prefix.Without these, a future refactor can silently break the security gates that the recent fixes added.
Why these specifically
These arent UI/UX concerns — they are security regression guards. The CRITICAL failure mode they prevent is "transient STS error in a multi-tenant deployment shows tenant A their alternatives + tenant B sources mixed in". The fix is in place; the test pinning it isnt.
Proposed tests
All in
internal/api/exchange_lookup_test.go:The STS-error test is the most important — it pins the multi-tenant safety contract.
References
50548797e,afc3aa1ff,f44b06567internal/api/exchange_lookup.go,internal/api/exchange_lookup_test.go,internal/api/handler_ri_exchange.goSeverity
Low-Medium — no current bug, but a regression guard for an addressed CRITICAL.
Effort
Small — ~80 LOC, all in one test file. Mocking
STS GetCallerIdentityrequires an extra interface seam (stsClient) which doesnt exist today; either add it or use a higher-level test that drives the failure through the public Handler API.