Skip to content

fix(cloud-tests): unblock GCP picker when folder enumeration returns 403#2916

Merged
tofikwest merged 1 commit into
mainfrom
tofik/fix-gcp-picker-permission-fallback
May 22, 2026
Merged

fix(cloud-tests): unblock GCP picker when folder enumeration returns 403#2916
tofikwest merged 1 commit into
mainfrom
tofik/fix-gcp-picker-permission-fallback

Conversation

@tofikwest
Copy link
Copy Markdown
Contributor

@tofikwest tofikwest commented May 22, 2026

Summary

Customer Propper (Greg) reported folder-nested GCP projects (propperai-prod, propperai-demo) still didn't appear in the picker after PR #2899 shipped. Verified in production CloudWatch logs — GCP's cloudresourcemanager.googleapis.com/v2/folders endpoint returns 403 PERMISSION_DENIED for his OAuth grant, despite the user holding roles/owner + roles/resourcemanager.folderAdmin at the org level. Folder enumeration silently returns [] → picker has nothing folder-nested to show.

WARN [GCPSecurityService] Failed to list child folders of organizations/43356919874: {
  "error": {
    "code": 403,
    "message": "The caller does not have permission",
    "status": "PERMISSION_DENIED"
  }
}
LOG  [GCPSecurityService] GCP detectProjectsForOrg(43356919874): 13 direct + 0 folder-nested → 13 unique

Fix

Two coordinated changes:

  1. v2/foldersv3/folders — v2 is deprecated and was observed returning 403 in production. v3 is the current API; same query params, same response shape, defensive swap.

  2. Broad-query fallback when enumeration returns 0 folderslistProjectsInOrgFolderTree now retries with lifecycleState:ACTIVE AND parent.type:folder (no parent.id). That returns every folder-nested project the OAuth user can projects.get, regardless of whether we could enumerate the folder tree. Greg's propperai-prod and propperai-demo appear.

Tradeoff (transparent)

In multi-org tenants (rare — most customers have a single org) the fallback may include folder-nested projects from other orgs the user has IAM access to. We're accepting this because:

  • The picker is selection-based — the user chooses what to monitor.
  • The alternative is a silently empty picker like Greg saw.
  • The user already authorized those projects via their IAM grant.

When v3/folders works as expected (the common case), the precise per-folder query is preferred and the fallback never fires. A new test locks in this behavior so the cubic P2 from PR #2899 stays satisfied for healthy tenants.

Tests

  • 2 new regression tests on gcp-security.service.spec.ts:
    • Customer-Propper scenario: v3/folders empty → broad fallback fires → folder-nested projects appear.
    • Healthy multi-org scenario: v3/folders succeeds → precise scoping preserved, broad fallback does not fire.
  • All 15 GCP detection tests pass.
  • Full cloud-security suite: 269/269 (one pre-existing Postgres-TLS env failure unrelated).

Manual test plan

  • Impersonate Greg → open GCP integration → confirm propperai-prod and propperai-demo now appear in the picker.
  • Pull production CloudWatch logs for /ecs/comp-production-api, filter by GCP folder fallback for org — should appear after the deploy hits Greg's connection.
  • Confirm a healthy tenant whose v3/folders succeeds does NOT trigger the fallback (log message GCP folder fallback should not appear for them).

🤖 Generated with Claude Code


Summary by cubic

Unblocks the GCP project picker when folder enumeration is forbidden. Switches to v3/folders and adds a broad fallback so folder-nested projects still show up.

  • Bug Fixes
    • Switched v2/foldersv3/folders for child folder listing.
    • When folder enumeration returns 0, fallback to lifecycleState:ACTIVE AND parent.type:folder (no parent.id); in multi‑org tenants this may include projects from other orgs, which is acceptable for a selection-based picker.
    • Preserves precise per-folder scoping when enumeration succeeds; fallback only runs on empty results.
    • Added regression tests for the Propper case and for healthy multi‑org behavior.

Written for commit 7fdc871. Summary will update on new commits. Review in cubic

…dden

Customer Propper hit a real failure that PR #2899's folder enumeration
could not handle. Verified in production CloudWatch logs:

  WARN [GCPSecurityService] Failed to list child folders of
       organizations/43356919874: {
    "error": {
      "code": 403,
      "message": "The caller does not have permission",
      "status": "PERMISSION_DENIED"
    }
  }
  LOG  [GCPSecurityService] GCP detectProjectsForOrg(43356919874):
       13 direct + 0 folder-nested → 13 unique

Two coordinated changes:

1. Switch `cloudresourcemanager.googleapis.com/v2/folders` →
   `cloudresourcemanager.googleapis.com/v3/folders`. v2 is deprecated
   and was observed returning 403 PERMISSION_DENIED for OAuth grants
   that legitimately had org-level folder roles (roles/owner +
   roles/resourcemanager.folderAdmin). v3 is the current API and
   accepts the same `parent`/`pageSize`/`pageToken` query params, so
   the swap is purely defensive — response shape is identical.

2. Add a broad-query fallback in `listProjectsInOrgFolderTree`. When
   folder enumeration returns zero folder IDs (whether due to 403,
   404, no folders existing, or anything else), retry with a broader
   `lifecycleState:ACTIVE AND parent.type:folder` query. That returns
   every folder-nested project the OAuth user can `projects.get`,
   which solves Greg's case without depending on the folders endpoint
   succeeding.

Multi-org tradeoff: in a multi-org tenant the fallback path may
include folder-nested projects from other orgs the user has access
to. This is acceptable because:
  - the picker is selection-based — the user chooses what to monitor,
  - the alternative is a silently empty picker like Greg saw,
  - the user already authorized those projects via their IAM grant.
When v3/folders works as expected, the precise per-folder query is
preferred and the fallback never fires — verified by a new test that
locks in this behavior.

Tests:
- 2 new regression tests on `gcp-security.service.spec.ts`:
  - customer-Propper scenario: v3/folders empty → broad fallback
    fires → folder-nested projects appear.
  - healthy multi-org scenario: v3/folders succeeds → precise scoping
    preserved, broad fallback does not fire.
- All 15 GCP detection tests pass; full cloud-security suite (269
  tests) passes; one pre-existing TLS env failure is unrelated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
comp-framework-editor Ready Ready Preview, Comment May 22, 2026 6:25pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
app Skipped Skipped May 22, 2026 6:25pm
portal Skipped Skipped May 22, 2026 6:25pm

Request Review

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

@tofikwest tofikwest merged commit 57fd6ba into main May 22, 2026
11 checks passed
@tofikwest tofikwest deleted the tofik/fix-gcp-picker-permission-fallback branch May 22, 2026 18:27
claudfuen pushed a commit that referenced this pull request May 22, 2026
## [3.63.1](v3.63.0...v3.63.1) (2026-05-22)

### Bug Fixes

* **cloud-tests:** only fire GCP broad fallback when folder list was forbidden ([173b031](173b031)), closes [#2916](#2916) [#2916](#2916)
* **cloud-tests:** unblock GCP picker when folder enumeration is forbidden ([7fdc871](7fdc871))
@claudfuen
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.63.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants