Skip to content

feat(ui): onboard Azure subscriptions from a Management Group - #12386

Merged
pfe-nazaries merged 19 commits into
masterfrom
feature/azure-org-onboarding-ui
Aug 12, 2026
Merged

pfe-nazaries merged 19 commits into
masterfrom
feature/azure-org-onboarding-ui

Conversation

@pfe-nazaries

@pfe-nazaries pfe-nazaries commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Draft on purpose. Two things are outstanding: the UI screenshots (being captured now) and the release gate — this must not merge before the cloud API deploys the Azure organization endpoints. Everything else is ready for review.

Context

Azure customers with many subscriptions can only onboard one subscription at a time today, each with its own service-principal credential, while AWS Organizations and GCP Organizations already have one-click multi-account onboarding. This closes that parity gap: Azure Management Group onboarding, tracked on the roadmap for 2026-Q3.

The GCP effort (merged 2026-07-31) deliberately left a provider-agnostic organization contract behind — strategy seam, discriminated unions, exhaustive satisfies Record<OrgFlowType,…> tables, shared wizard lifecycle, browser-mode harness, MSW fixtures. Azure is therefore a compile-enumerated extension of that contract rather than a rebuild: adding AZURE to ORG_FLOW_TYPES makes the type checker list every remaining gap.

This is layer 3 of the Azure stack, on top of #12383.

Jira: PROWLER-2365 (epic PROWLER-2364). The API side is PROWLER-2366.

Description

New Azure-specific pieces, all azure-*-prefixed, plugged into existing seams:

  • azure-method-selector.tsx — single subscription vs Management Group, with the cloud-upgrade upsell outside Prowler Cloud.
  • azure-org-setup-form.tsx — Entra tenant ID + optional name, then service-principal credentials.
  • azureOrgSetupStrategy — external id, secret payload, secret-error mapping, discovery ingest, auth-failure copy.
  • mapAzureDiscovery + the apply payload arm, mapping root / management_groups / subscriptions onto the shared tree.
  • Wire types, NODE_KIND for management groups, badge/docs/upsell/terminology entries.

Everything else is reused unchanged: the submission chain (find-or-create org → secret → discovery → poll → ingest), tree selection, apply, connection tests, launch/schedule, re-entry via Update Credentials, kind-aware delete, degraded-hierarchy fallback.

Three points from the API contract are worth calling out, because they are simpler than an early reading of it suggests:

  • Onboarding is allowed only from the tenant-root Management Group, so the wizard collects no Management Group — the API derives it from the tenant. The root_external_id write seam is dead code and is removed here; the read path stays.
  • The organization secret sends {client_id, client_secret} only; the tenant comes from the organization.
  • Discovery carries a sanitized error_message beside the machine error code. Failure copy resolves curated → error_message → auth fallback, so a code the API adds later still says something useful.

Testing follows the integration-first policy: the Azure cases were written red against a frozen type frontier, then implemented. They live as a new describe group inside the consolidated providers-page.integration.test.tsx (the "1 integration file = 1 real page" convention introduced in #12383), one case per spec scenario — happy path, subscription nesting, alias prefill, inert and blocked rows, apply payload shape, both credential-replace warnings, discovery failure + retry, launch outcomes, OSS gating, kind-aware delete. No new unit tests except where internals warrant them.

One real defect surfaced while turning them green: the harness read a row's uid from the whole row's textContent, which glues the uid column to the name column — so the management-group pattern swallowed the display name (…/managementGroups/archivedArchived). It now matches per text node, which also removes the same latent trap for AWS OU ids.

Steps to review

  1. Read types/organizations.ts first — it is the contract the rest of the diff is forced into.
  2. cd ui && pnpm exec vitest run --project integration → 61/61. Run the two projects separately: running them concurrently starves the browser workers and times out unrelated suites.
  3. cd ui && pnpm exec vitest run --project unit → 2804/2804.
  4. pnpm run typecheck and pnpm run lint → clean.
  5. Note that CI has not run on this PR: every workflow filters pull_request on base master/v5.*, so only the bottom of a stack is gated. The full set runs once this becomes base-master.

Checklist

  • Are there new checks included in this PR? No
  • Review if the code is being covered by tests.
  • Review if code is being documented following the style guide.
  • Review if backport is needed. — no.
  • Review if is needed to change the Readme.md — no.
  • Ensure a changelog fragment is added under <component>/changelog.d/. — ui/changelog.d/azure-management-group-onboarding.added.md.

UI

  • All issue/task requirements work as expected on the UI — verified against the mock API booted as cloud.
  • Screenshots/Video — Desktop (X > 1024px) — being captured; posted before this leaves draft.
  • Screenshots/Video — Tablet / Mobile — the providers wizard is a desktop surface; same coverage as the AWS and GCP organization PRs.
  • Ensure a changelog fragment is added under ui/changelog.d/.

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Summary by CodeRabbit

  • New Features
    • Added Azure organization onboarding with tenant authentication and service-principal credentials.
    • Added single-subscription and Management Group onboarding options.
    • Added Azure subscription discovery, selection, connection, apply, and deletion workflows.
    • Added Azure hierarchy visualization, terminology, badges, documentation links, and upgrade messaging.
  • Bug Fixes
    • Improved discovery errors with clear server-provided failure messages.
    • Improved long Azure resource ID readability while preserving full IDs for accessibility.
    • Improved organization naming when names are left blank.
    • Improved hierarchy-depth messages with provider-specific terminology.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0dbfed2d-3aa7-49e1-91ce-fc7ba0b7976d

📥 Commits

Reviewing files that changed from the base of the PR and between ea2f79e and da0b40e.

📒 Files selected for processing (3)
  • ui/__tests__/msw/handlers/organizations.fixtures.ts
  • ui/app/(prowler)/providers/providers-page.integration.test.tsx
  • ui/components/providers/table/data-table-row-actions.tsx

📝 Walkthrough

Walkthrough

Azure Management Group onboarding now supports tenant discovery, management-group hierarchies, subscription selection, apply payloads, credential handling, error messages, deletion flows, and integration coverage.

Changes

Azure organization onboarding

Layer / File(s) Summary
Azure contracts and fixtures
ui/types/organizations.ts, ui/__tests__/msw/handlers/organizations.fixtures.ts, ui/lib/organizations.ts, ui/store/organizations/store.test.ts
Added Azure discovery, hierarchy, secret, apply-payload, management-group, and subscription models. Added Azure fixtures and mixed-hierarchy data.
Discovery mapping and apply requests
ui/actions/organizations/organizations.adapter.ts, ui/actions/organizations/organizations.ts, ui/__tests__/msw/handlers/organizations.ts
Mapped Azure discovery results into normalized hierarchy data. Added Azure subscription apply attributes and preserved organization root identifiers and discovery error messages.
Azure setup flow and provider wiring
ui/components/providers/organizations/*, ui/components/providers/wizard/*, ui/components/providers/workflow/forms/connect-account-form.tsx, ui/components/providers/organizations/hooks/*
Added Azure method selection, setup phases, credential submission, discovery retries, strategy-specific errors, wizard routing, documentation links, and Azure terminology.
Hierarchy display and validation coverage
ui/app/(prowler)/providers/*, ui/components/providers/organizations/org-account-tree-item.tsx, ui/tests/providers/providers-page.ts, ui/lib/cloud-upgrade.*, ui/changelog.d/*
Added subscription and management-group assertions, lifecycle tests, shortened Azure IDs, cloud-upgrade content, and changelog entries.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: alejandrobailo

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the primary change: Azure subscription onboarding from a Management Group.
Description check ✅ Passed The description includes context, implementation details, review steps, testing results, checklist status, changelog information, and known release conditions.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/azure-org-onboarding-ui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

✅ All required changelog fragments are present.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

No Conflicts

No conflict markers, and the branch merges cleanly into its base.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🔒 Container Security Scan

Image: prowler-ui:718a160
Last scan: 2026-08-12 06:52:10 UTC

✅ No Vulnerabilities Detected

The container image passed all security checks. No known CVEs were found.

📋 Resources:

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🔎 Container Security Scan (Grype)

Image: prowler-ui:718a160
Last scan: 2026-08-12 06:53:27 UTC

✅ Nothing Blocking

No findings at critical or high severity.


📋 Resources:

@pfe-nazaries
pfe-nazaries force-pushed the feature/azure-org-onboarding-ui branch from d5641aa to 7ec278a Compare August 7, 2026 11:36
@pfe-nazaries
pfe-nazaries marked this pull request as ready for review August 10, 2026 07:26
@pfe-nazaries
pfe-nazaries requested a review from a team August 10, 2026 07:26
@alejandrobailo alejandrobailo self-assigned this Aug 10, 2026

@Alan-TheGentleman Alan-TheGentleman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The Azure organization name contract is inconsistent. The form presents the field as optional and says an empty value falls back to the name stored in Azure, but creation actually falls back to the tenant ID, while editing passes an empty string to updateOrganizationName(), which rejects it.

Please align this contract in both creation and editing. Either implement the Azure display-name fallback that the UI promises, or change the copy and validation so the organization name is required and handled consistently.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
ui/lib/organizations.test.ts (1)

120-136: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for shortenNodeId.

ui/lib/organizations.ts exports the new shortenNodeId function. This suite covers every other exported helper of that module, but not shortenNodeId. Two branches carry behavior that a future edit can break silently: the case-insensitive match on the ARM prefix, and the undefined result for AWS OU ids and GCP folder refs. org-account-tree-item.tsx depends on the undefined result to keep showing the canonical id.

♻️ Proposed test block
+describe("shortenNodeId", () => {
+  it("returns the trailing name of a management-group resource id", () => {
+    expect(
+      shortenNodeId(
+        "/providers/Microsoft.Management/managementGroups/engineering",
+      ),
+    ).toBe("engineering");
+  });
+
+  it("matches the ARM prefix case-insensitively", () => {
+    expect(
+      shortenNodeId(
+        "/providers/microsoft.management/managementgroups/engineering",
+      ),
+    ).toBe("engineering");
+  });
+
+  it("returns undefined for ids that are already short", () => {
+    expect(shortenNodeId("ou-abcd-12345678")).toBeUndefined();
+    expect(shortenNodeId("folders/123456789012")).toBeUndefined();
+  });
+});

Add shortenNodeId to the import list at line 10.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui/lib/organizations.test.ts` around lines 120 - 136, Add shortenNodeId to
the organizations test import and add coverage for its ARM prefix matching,
including case-insensitive input, plus assertions that AWS OU IDs and GCP folder
references return undefined. Keep the existing canonical-ID behavior validated
for unsupported formats.
ui/components/providers/organizations/org-account-tree-item.tsx (1)

82-101: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep the canonical id in the accessible name instead of aria-label.

aria-label is not allowed on the implicit generic role used by the plain <span>, so screen-reader support cannot rely on it. Add the canonical value in an element with a valid accessible name; if shortened is shown, hide it with aria-hidden="true" so the id is not announced twice.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui/components/providers/organizations/org-account-tree-item.tsx` around lines
82 - 101, Update TruncatedId so the canonical value is exposed through valid
text content rather than aria-label on the plain span. When shortened is
displayed, render the canonical value in an accessible element and mark the
shortened presentation with aria-hidden="true" to prevent duplicate
announcements; preserve the tooltip and visual truncation behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/app/`(prowler)/providers/providers-page.integration.test.tsx:
- Around line 138-140: Export AZURE_ORG_NAME and AZURE_GROUP_NODE_ID from
organizations.fixtures.ts, then import both in the existing fixture import block
of the integration test. Remove the local literal declarations so
waitForOrganizationRow and waitForNodeDelete use the fixture-owned values.

In `@ui/components/providers/organizations/hooks/org-setup-strategy.test.ts`:
- Around line 74-87: Strengthen the test in the org flow
`it.each(ORG_FLOW_TYPES)` case by also asserting that the returned `message`
does not contain the server-provided `"Hierarchy too deep."` text, while
retaining the existing curated-wording assertion.

In `@ui/components/providers/organizations/hooks/org-setup-strategy.ts`:
- Around line 404-421: Update the doc comment above bindOrgSetupStrategy to
describe the default arm as a compile-time exhaustiveness check using the never
assignment, rather than implying it produces a runtime message or names an
offending organization type.

In `@ui/components/providers/workflow/forms/connect-account-form.tsx`:
- Around line 398-409: Update the Azure method screen branch in the provider
form, identified by prevStep === 2, providerType === "azure", and method ===
null, to provide an explicit tour anchor or tour-visibility handling for its
rendered content. Keep the existing ProviderTitleDocs and AzureMethodSelector
behavior unchanged, and align the added handling with the existing showUidForm
and tour-aware state used by the Next button.

---

Outside diff comments:
In `@ui/components/providers/organizations/org-account-tree-item.tsx`:
- Around line 82-101: Update TruncatedId so the canonical value is exposed
through valid text content rather than aria-label on the plain span. When
shortened is displayed, render the canonical value in an accessible element and
mark the shortened presentation with aria-hidden="true" to prevent duplicate
announcements; preserve the tooltip and visual truncation behavior.

In `@ui/lib/organizations.test.ts`:
- Around line 120-136: Add shortenNodeId to the organizations test import and
add coverage for its ARM prefix matching, including case-insensitive input, plus
assertions that AWS OU IDs and GCP folder references return undefined. Keep the
existing canonical-ID behavior validated for unsupported formats.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a036de62-0e0c-4b0e-a039-0f295a882cee

📥 Commits

Reviewing files that changed from the base of the PR and between 06ef076 and 4a477b0.

📒 Files selected for processing (34)
  • ui/__tests__/msw/handlers/organizations.fixtures.ts
  • ui/__tests__/msw/handlers/organizations.ts
  • ui/actions/organizations/organizations.adapter.ts
  • ui/actions/organizations/organizations.test.ts
  • ui/actions/organizations/organizations.ts
  • ui/app/(prowler)/providers/providers-page.harness.tsx
  • ui/app/(prowler)/providers/providers-page.integration.test.tsx
  • ui/changelog.d/azure-management-group-onboarding.added.md
  • ui/changelog.d/org-hierarchy-depth-copy.fixed.md
  • ui/components/providers/organizations/azure-method-selector.tsx
  • ui/components/providers/organizations/azure-org-setup-form.tsx
  • ui/components/providers/organizations/gcp-org-setup-form.tsx
  • ui/components/providers/organizations/hooks/org-setup-strategy.test.ts
  • ui/components/providers/organizations/hooks/org-setup-strategy.ts
  • ui/components/providers/organizations/hooks/use-org-setup-submission.test.ts
  • ui/components/providers/organizations/hooks/use-org-setup-submission.ts
  • ui/components/providers/organizations/org-account-tree-item.tsx
  • ui/components/providers/organizations/org-setup-form.tsx
  • ui/components/providers/organizations/org-terminology.ts
  • ui/components/providers/table/data-table-row-actions.test.tsx
  • ui/components/providers/wizard/hooks/use-provider-wizard-controller.ts
  • ui/components/providers/wizard/provider-wizard-modal.tsx
  • ui/components/providers/wizard/provider-wizard-modal.utils.test.ts
  • ui/components/providers/wizard/provider-wizard-modal.utils.ts
  • ui/components/providers/workflow/forms/connect-account-form.tsx
  • ui/lib/cloud-upgrade.test.ts
  • ui/lib/cloud-upgrade.ts
  • ui/lib/external-urls.ts
  • ui/lib/organizations.test.ts
  • ui/lib/organizations.ts
  • ui/store/organizations/store.test.ts
  • ui/tests/providers/providers-page.ts
  • ui/types/cloud-upgrade.ts
  • ui/types/organizations.ts

Comment thread ui/app/(prowler)/providers/providers-page.integration.test.tsx Outdated
Comment thread ui/components/providers/organizations/hooks/org-setup-strategy.ts
Comment thread ui/components/providers/workflow/forms/connect-account-form.tsx
@pfe-nazaries
pfe-nazaries force-pushed the feature/azure-org-onboarding-ui branch from a964d88 to ae4e624 Compare August 10, 2026 10:01
@pfe-nazaries

Copy link
Copy Markdown
Contributor Author

CodeRabbit Autofix Review Complete

Reviewed 4 feedback items, applied 2. Branch was also rebased onto the updated feature/azure-org-suite-consolidation.

Applied

  • Doc comment on bindOrgSetupStrategy now describes the default arm as a compile-time never check instead of a runtime message — the comment was left stale by b46d9997. Commit 228f7c1f.
  • AZURE_ORG_NAME and AZURE_GROUP_NODE_ID are now exported from organizations.fixtures.ts and imported by the integration suite, so a fixture rename fails at compile time instead of timing out in waitForOrganizationRow / waitForNodeDelete. Commit ae4e6246.

Not applied

  • Assert that the server message is absent — deferred. Speculative test strengthening; the current implementation does not concatenate both strings.
  • Update the Azure method selector for tour accessibility — deferred. The finding itself notes the add-provider tour does not break, so this is future-proofing for anchors that do not exist yet, in product code.

Files modified

  • ui/components/providers/organizations/hooks/org-setup-strategy.ts
  • ui/__tests__/msw/handlers/organizations.fixtures.ts
  • ui/app/(prowler)/providers/providers-page.integration.test.tsx

Typecheck, ESLint, Prettier and the related unit tests pass on feature/azure-org-onboarding-ui.

@pfe-nazaries

Copy link
Copy Markdown
Contributor Author

Organization name contract — aligned

Thanks, this was a real inconsistency. All three of your points checked out, though one had moved: a964d882 had already deleted the Azure form's EDIT_NAME branch and its updateOrganizationName import, so the blank-name rejection no longer came from the Azure form. It came from the shared inline rename modal (data-table-row-actions.tsx), which serves every organization type.

Two findings shaped the fix:

  1. The promised fallback was never implementable. The organization is created in use-org-setup-submission.ts before discovery runs, and the Azure display name only arrives afterwards in AzureDiscoveredRoot.display_name. By the time Prowler knows the tenant's name, the organization name is already persisted. The same holds for AWS and GCP.
  2. The mismatch was house-wide and pre-existing, not introduced here. AWS, GCP and the rename modal all made the same promise on the base branch while getResolvedName fell back to the identifier — and the three copies had already drifted (the Organization name stored in vs the organization name stored in).

So the contract is now the honest one, and identical in both directions:

  • Creation — blank names the organization after its identifier (unchanged behaviour, now stated truthfully: "If left blank, Prowler will use the tenant ID.").
  • Renaming — blank now applies that same fallback instead of returning "Organization name cannot be empty.". Rows with no external id keep the name required, since there is nothing to fall back to.
  • The sentence lives in organizationNameFallbackHint() alongside the rest of the per-type vocabulary, so the three setup forms can no longer word it differently. nameSourceLabel became identifierLabel.

Commit 12abaedc. Typecheck, ESLint, Prettier and the unit suite pass; added an integration case asserting the blank rename PATCHes the identifier. The tutorial in #12389 is updated to match (762b12e3).

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 10, 2026

@Alan-TheGentleman Alan-TheGentleman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The organization name contract is now consistent across creation and renaming. Approved.

Base automatically changed from feature/azure-org-suite-consolidation to master August 11, 2026 16:50
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

- Add Azure discovery, hierarchy, secret and apply payload types
- Enable the Azure organizations flow and the management-group node kind
- Discriminate organization secret payloads on organization type
- Extend the setup strategy with the root external id and Azure fields
- Leave the per-type gaps the compiler now enumerates to the Azure arms
- Record the sharp install in the UI dependency log
- Add the Azure organizations method selector and setup form
- Map management-group discovery and apply the selected subscriptions
- Show the cloud upgrade upsell for the Azure method outside Prowler Cloud
- Cover the flow in the consolidated providers page integration suite
- Drop the dead organization root write seam
- Tell Azure users about Management Groups, not folders they cannot have
- Move per-provider discovery copy onto the setup strategy arms
- Require every organization type to bring its own shared-code wording
- Cover the shared code across all onboarding flows
- Show the Management Group name where the ARM id is all shared prefix
- Keep the canonical resource id in the tooltip and accessible name
- Leave AWS and GCP identifiers rendered in full
- Assert what the id column reads, not only the uid behind it
- Read the discovery root from `root_management_group`, the key the API
  actually sends, instead of `root` — the previous name threw on ingest
- Replace the dead `azure_management_group_not_found` copy with
  `azure_root_management_group_not_found` and curate the emitted codes
  that had no wording
- Correct the Azure blocked-reason names to the conflict vocabulary the
  API shares with GCP, and cover a subscription blocked only by state
- Casefold the tenant ID so find-or-create matches the canonical
  external id the API stores
- Add never-assigning default arms to the apply payload and strategy switches
- Reach the setup forms' own node with a ref instead of getElementById
- Expose the canonical container id via aria-label so the harness drops its regex
- Restore the dependency log to its committed state
- Re-drop the wizard modal comments removed in 102d2b5
- Trim the apply-payload guard note to its non-obvious why
- Validate the tenant and client IDs with z.guid() instead of z.uuid()
- z.uuid() enforces the RFC-9562 version and variant nibbles, so it
  rejected real Azure identifiers while accepting the nil UUID
- Give the id span role="img" so its aria-label is honoured
- ARIA prohibits naming a bare span, letting screen readers fall back
  to the shortened text and lose the canonical id
- Point the harness's inert-note lookup at the icon, now that the id
  column carries the role as well
- Remove the EDIT_NAME branch, its save handler and the state it owned
- Nothing produces that intent: the row actions only ever pass
  EDIT_CREDENTIALS, and renaming happens in the inline modal
- State the identifier the name falls back to, not a provider-side name:
  the organization is created before discovery, so no such name is known
- Apply the same fallback when renaming, which previously rejected a blank
- Centralize the hint so the three setup forms cannot word it differently
- Drop comments that restate the code or the test title they sit under
- Keep each rationale where it belongs instead of repeating it per call site
- Reattach the AWS hierarchy fixture doc to the fixture it documents
@pfe-nazaries
pfe-nazaries force-pushed the feature/azure-org-onboarding-ui branch from 6e98a1f to ea2f79e Compare August 11, 2026 16:50
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/__tests__/msw/handlers/organizations.fixtures.ts`:
- Around line 737-741: Update the documentation comment describing the fresh
Azure organization onboarding fixture to state that three subscriptions are
blocked, matching the result produced by buildAzureDiscoveryResult; leave the
readiness and management-group details unchanged.

In `@ui/app/`(prowler)/providers/providers-page.integration.test.tsx:
- Around line 155-162: Refactor OrganizationSecretRequestBody by extracting its
nested data and attributes object types into dedicated interfaces, then
reference those interfaces from the parent interface instead of using inline
nested objects. Follow the existing RenameRequestBody pattern and preserve the
optional secret_type and secret properties.

In `@ui/components/providers/organizations/azure-org-setup-form.tsx`:
- Around line 145-171: Update the Azure organization setup submit flow to handle
ORG_WIZARD_INTENT.EDIT_NAME by calling updateOrganizationName with the existing
organization ID and the new name instead of advancing to ORG_SETUP_PHASE.ACCESS.
Pass the modal’s onClose callback to the update flow and invoke it only after
the update succeeds; preserve the existing behavior for other intents.

In `@ui/components/providers/table/data-table-row-actions.tsx`:
- Around line 228-236: Normalize the name value in the edit-name flow around the
validate callback and onSave handler: trim whitespace before validation so
whitespace-only input is rejected, and trim before choosing between the entered
name and nameFallback so whitespace-only input uses the fallback. Preserve the
existing required-message and updateOrganizationName behavior for non-empty
names.

In `@ui/lib/external-urls.ts`:
- Around line 17-18: Do not expose AZURE_ORGANIZATIONS until the linked Azure
management-group documentation reflects the released onboarding flow; either
update the documentation content first or gate/remove this URL entry until that
update is available.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 48ad0566-9f61-4c45-9f41-aee9eddd734a

📥 Commits

Reviewing files that changed from the base of the PR and between 6d7bc8a and ea2f79e.

📒 Files selected for processing (35)
  • ui/__tests__/msw/handlers/organizations.fixtures.ts
  • ui/__tests__/msw/handlers/organizations.ts
  • ui/actions/organizations/organizations.adapter.ts
  • ui/actions/organizations/organizations.test.ts
  • ui/actions/organizations/organizations.ts
  • ui/app/(prowler)/providers/providers-page.harness.tsx
  • ui/app/(prowler)/providers/providers-page.integration.test.tsx
  • ui/changelog.d/azure-management-group-onboarding.added.md
  • ui/changelog.d/org-hierarchy-depth-copy.fixed.md
  • ui/components/providers/organizations/azure-method-selector.tsx
  • ui/components/providers/organizations/azure-org-setup-form.tsx
  • ui/components/providers/organizations/gcp-org-setup-form.tsx
  • ui/components/providers/organizations/hooks/org-setup-strategy.test.ts
  • ui/components/providers/organizations/hooks/org-setup-strategy.ts
  • ui/components/providers/organizations/hooks/use-org-setup-submission.test.ts
  • ui/components/providers/organizations/hooks/use-org-setup-submission.ts
  • ui/components/providers/organizations/org-account-tree-item.tsx
  • ui/components/providers/organizations/org-setup-form.tsx
  • ui/components/providers/organizations/org-terminology.ts
  • ui/components/providers/table/data-table-row-actions.test.tsx
  • ui/components/providers/table/data-table-row-actions.tsx
  • ui/components/providers/wizard/hooks/use-provider-wizard-controller.ts
  • ui/components/providers/wizard/provider-wizard-modal.tsx
  • ui/components/providers/wizard/provider-wizard-modal.utils.test.ts
  • ui/components/providers/wizard/provider-wizard-modal.utils.ts
  • ui/components/providers/workflow/forms/connect-account-form.tsx
  • ui/lib/cloud-upgrade.test.ts
  • ui/lib/cloud-upgrade.ts
  • ui/lib/external-urls.ts
  • ui/lib/organizations.test.ts
  • ui/lib/organizations.ts
  • ui/store/organizations/store.test.ts
  • ui/tests/providers/providers-page.ts
  • ui/types/cloud-upgrade.ts
  • ui/types/organizations.ts

Comment thread ui/__tests__/msw/handlers/organizations.fixtures.ts
Comment thread ui/app/(prowler)/providers/providers-page.integration.test.tsx
Comment thread ui/components/providers/organizations/azure-org-setup-form.tsx
Comment thread ui/components/providers/table/data-table-row-actions.tsx
Comment thread ui/lib/external-urls.ts
- Trim the organization name before validating and before the fallback
- Flatten the secret request body interface in the providers suite
- Correct the blocked-subscription count in the Azure fixture comment
@pfe-nazaries

Copy link
Copy Markdown
Contributor Author

CodeRabbit autofix — 3 applied, 2 dismissed

Reviewed 5 unresolved CodeRabbit threads. All 5 are now resolved.

Applied in da0b40e59:

  • ui/components/providers/table/data-table-row-actions.tsx — a whitespace-only name passed the client validator and skipped the identifier fallback (" " is truthy), so updateOrganizationName trimmed it to empty and returned an error toast instead of applying the fallback. Now trimmed before both the validation and the fallback selection.
  • ui/app/(prowler)/providers/providers-page.integration.test.tsx — flattened OrganizationSecretRequestBody into dedicated interfaces, matching ApplyRequestData and RenameRequestData in the same file.
  • ui/__tests__/msw/handlers/organizations.fixtures.ts — the fixture comment said two subscriptions are blocked; buildAzureDiscoveryResult returns two ready and three blocked.

Dismissed, with reasons:

  • Implement the Azure EDIT_NAME flow (azure-org-setup-form.tsx) — nothing in ui/ ever opens the wizard with that intent. ORG_WIZARD_INTENT.EDIT_NAME exists only as a constant in wizard/types.ts and as reads in the AWS and GCP forms, so the branch is unreachable there too. Renaming goes through the shared EditNameForm modal, which is the code the fix above touches. The dead branch was removed from the Azure form deliberately.
  • Update the Azure management-group documentation before exposing this link (lib/external-urls.ts) — the linked page is added by the docs PR in this stack, which is still open. The link resolves once that lands.

tsc --noEmit and eslint pass on the changed files.

@pfe-nazaries
pfe-nazaries merged commit b480907 into master Aug 12, 2026
47 of 48 checks passed
@pfe-nazaries
pfe-nazaries deleted the feature/azure-org-onboarding-ui branch August 12, 2026 07:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants