Skip to content

ENG-913: resource setup in React for metadata-driven types - #2089

Merged
luanlorenzo merged 13 commits into
mainfrom
luan/eng-913
Nov 4, 2026
Merged

luanlorenzo merged 13 commits into
mainfrom
luan/eng-913

Conversation

@luanlorenzo

@luanlorenzo luanlorenzo commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

📝 Description

/resources/new?type=<catalog id> creates metadata-driven resources and dev envs in React. Other types keep the CLJS wizard until their ticket lands.

📣 User-facing impact

None: the same setup wizard, now in React.

🔗 Related Issue

ENG-913

🚀 Type of Change

  • ✨ New feature (non-breaking change which adds functionality)

📋 Changes Made

  • ?type= picks the React or CLJS wizard; the CLJS catalog now passes it.
  • Credential renderers read their store from context, so the wizard and Configure Role share them.
  • Fixes Q14, Q15, Q16, Q19, Q21.

🧪 Testing

Same POST /resources body as CLJS for all 24 types. Configure Role saves are unchanged.

1-create-postgres 3-ssh-keeps-cljs-wizard 4-configure-role-same-save

📄 Additional Notes

Configure Role picks up the new look of the shared inputs.

@luanlorenzo luanlorenzo added the minor Bumps the minor version on release (new features) label Oct 29, 2026
@sandromello

Copy link
Copy Markdown
Contributor

✅ Build Completed with Success, Version=2089.0.0-g4babfd7

@sandromello

Copy link
Copy Markdown
Contributor

✅ Build Completed with Success, Version=2089.0.0-g4aecffe

@sandromello

Copy link
Copy Markdown
Contributor

✅ Build Completed with Success, Version=2089.0.0-ga3ba1f5

Base automatically changed from luan/eng-911 to main October 29, 2026 19:43
@luanlorenzo luanlorenzo changed the title feat(webapp): ENG-913 resource setup in React for metadata-driven types ENG-913: resource setup in React for metadata-driven types Oct 29, 2026
@luanlorenzo
luanlorenzo marked this pull request as ready for review October 29, 2026 20:53
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

ENG-913: Add React setup for metadata-driven resources

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Route supported catalog types to a React resource wizard while retaining CLJS setup for others.
• Create resources, agents, and roles with metadata-driven credentials and CLJS-compatible payloads.
• Share credential controls with Configure Role and test setup payloads against recorded CLJS
 examples.
Diagram

graph TD
  Catalog["Resource catalog"] --> Gate{"Supported subtype?"} -->|React| Wizard["React wizard"] --> Credentials["Role credentials"] --> Payload["Create payload"] --> API["Resources API"] --> Success["Success actions"]
  Gate -->|Other type| Legacy["CLJS wizard"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Migrate every resource type together
  • ➕ Avoids maintaining a per-subtype routing gate.
  • ➖ Requires porting specialized setup flows now and increases rollout risk.
2. Keep separate credential controls for creation
  • ➕ Isolates the new wizard from Configure Role.
  • ➖ Duplicates source encoding and field behavior, making the two flows more likely to diverge.

Recommendation: Keep the subtype-gated rollout and shared credential renderers. They limit the migration to metadata-driven flows while preserving established credential behavior; review the shared-store boundary and payload compatibility closely.

Files changed (59) +2986 / -292

Enhancement (32) +1685 / -43
connection_detail_modal.cljsPass catalog ID into setup navigation +2/-1

Pass catalog ID into setup navigation

• The catalog modal supplies the selected entry ID so the destination can choose its wizard.

webapp/src/webapp/connections/views/resource_catalog/connection_detail_modal.cljs

helpers.cljsAdd the catalog ID to the setup URL +3/-3

Add the catalog ID to the setup URL

• Non-onboarding navigation now passes the selected catalog ID as the type query parameter; onboarding navigation remains unchanged.

webapp/src/webapp/connections/views/resource_catalog/helpers.cljs

Router.jsxRoute resource creation through a subtype gate +16/-0

Route resource creation through a subtype gate

• Adds /resources/new with an admin-only React wizard for supported types and CatchAll for CLJS types.

webapp_v2/src/Router.jsx

AttributesSelect.module.cssLighten managed attribute styling +4/-4

Lighten managed attribute styling

• Changes managed-attribute pill and option colors to indigo-7.

webapp_v2/src/components/AttributesSelect/AttributesSelect.module.css

index.jsxSupport creating attributes in the shared picker +38/-9

Support creating attributes in the shared picker

• Adds label and onCreate props, offering a create option for a new search term. The picker serves both Configure Role and resource setup.

webapp_v2/src/components/AttributesSelect/index.jsx

SourceMenu.jsxKeep credential source picker width stable +20/-3

Keep credential source picker width stable

• Renders all source labels in an overlapping grid so changing the selection does not shift the adjacent input.

webapp_v2/src/components/SourcedInput/SourceMenu.jsx

SourceMenu.module.cssStyle fixed-width source labels +14/-0

Style fixed-width source labels

• Adds grid positioning and hidden-label styling for the source menu.

webapp_v2/src/components/SourcedInput/SourceMenu.module.css

SourcedInput.module.cssAlign sourced inputs with wizard styling +9/-9

Align sourced inputs with wizard styling

• Adjusts source-picker surfaces, borders, radius, and font sizes.

webapp_v2/src/components/SourcedInput/SourcedInput.module.css

index.jsxShow credential descriptions beside labels +18/-6

Show credential descriptions beside labels

• Adds an optional label tooltip and CSS-variable-based label sizing and spacing.

webapp_v2/src/components/SourcedInput/index.jsx

ByResourceSetup.jsxChoose React or CLJS setup from catalog metadata +43/-0

Choose React or CLJS setup from catalog metadata

• Loads catalog metadata, resolves the type query parameter, and selects the wizard by subtype. Missing or unknown IDs return to the catalog.

webapp_v2/src/modes/ByResourceSetup.jsx

templates.jsAdd masking template card descriptions +6/-0

Add masking template card descriptions

• Provides concise descriptions for three masking templates used by the resource success cards.

webapp_v2/src/pages/Features/DataMasking/templates.js

AgentStep.jsxAdd agent selection and creation step +153/-0

Add agent selection and creation step

• Lets admins select an existing agent or create one, then displays Docker or Kubernetes deployment instructions.

webapp_v2/src/pages/Resources/Setup/AgentStep.jsx

NameStep.jsxAdd resource type and name step +59/-0

Add resource type and name step

• Shows the selected catalog type and collects the new resource name.

webapp_v2/src/pages/Resources/Setup/NameStep.jsx

RolesStep.jsxAdd multi-role setup step +42/-0

Add multi-role setup step

• Loads role options and renders removable role forms with an add-role action.

webapp_v2/src/pages/Resources/Setup/RolesStep.jsx

Setup.module.cssStyle the wizard layout +33/-0

Style the wizard layout

• Adds an independently scrolling setup layout, footer, and wizard-specific label dimensions.

webapp_v2/src/pages/Resources/Setup/Setup.module.css

SuccessStep.jsxAdd resource creation success screen +101/-0

Add resource creation success screen

• Shows created role names and offers terminal access when eligible, another-resource navigation, and activation cards.

webapp_v2/src/pages/Resources/Setup/SuccessStep.jsx

SuccessStep.module.cssStyle success action cards +9/-0

Style success action cards

• Adds full-width action-card and hover styles.

webapp_v2/src/pages/Resources/Setup/SuccessStep.module.css

activation.jsChoose activation recommendations and destinations +119/-0

Choose activation recommendations and destinations

• Builds Guardrails, masking, and AI analyzer cards based on provider availability, license, existing rules, and templates.

webapp_v2/src/pages/Resources/Setup/activation.js

catalog.jsMap catalog IDs to setup subtypes +70/-0

Map catalog IDs to setup subtypes

• Resolves catalog overrides and metadata configurations, and defines the subtypes eligible for React setup.

webapp_v2/src/pages/Resources/Setup/catalog.js

StepHeader.jsxAdd reusable setup step heading +27/-0

Add reusable setup step heading

• Displays step titles, explanatory text, and optional documentation links.

webapp_v2/src/pages/Resources/Setup/components/StepHeader.jsx

StepRow.jsxAdd wizard field row layout +20/-0

Add wizard field row layout

• Places explanatory text beside fields in the CLJS wizard’s three-to-four-column layout.

webapp_v2/src/pages/Resources/Setup/components/StepRow.jsx

index.jsxOrchestrate the React resource wizard +118/-0

Orchestrate the React resource wizard

• Initializes setup from the URL and metadata, renders the name, agent, roles, and success steps, and wires footer actions.

webapp_v2/src/pages/Resources/Setup/index.jsx

payload.jsBuild CLJS-compatible resource creation bodies +47/-0

Build CLJS-compatible resource creation bodies

• Combines setup metadata, agent selection, role credentials, commands, attributes, and role defaults for POST /resources.

webapp_v2/src/pages/Resources/Setup/payload.js

roleCredentials.jsGive each new role an isolated credential store +85/-0

Give each new role an isolated credential store

• Reuses shared secret actions, re-encodes typed values on method changes, preserves a typed password across AWS IAM selection, and exports staged secrets.

webapp_v2/src/pages/Resources/Setup/roleCredentials.js

ActivationCards.jsxRender post-creation feature cards +134/-0

Render post-creation feature cards

• Loads activation context for admins and displays feature recommendations with navigation, sales, and analytics actions.

webapp_v2/src/pages/Resources/Setup/sections/ActivationCards.jsx

RoleForm.jsxCollect role attributes and metadata credentials +177/-0

Collect role attributes and metadata credentials

• Adds role naming, protection-profile attributes, credential methods, and metadata-defined fields using shared Configure Role controls.

webapp_v2/src/pages/Resources/Setup/sections/RoleForm.jsx

store.jsManage setup state and resource creation +265/-0

Manage setup state and resource creation

• Adds wizard state, name validation, agent and attribute creation, role management, resource submission, and activation-data loading.

webapp_v2/src/pages/Resources/Setup/store.js

index.jsxStrengthen secret field labels +1/-1

Strengthen secret field labels

• Increases the label font weight for secret fields.

webapp_v2/src/pages/Roles/Configure/components/SecretField/index.jsx

PredefinedFields.jsxSupport masked fields during resource creation +32/-6

Support masked fields during resource creation

• Reads credentials from context and adds a create mode that renders metadata fields as new sourced inputs with description tooltips.

webapp_v2/src/pages/Roles/Configure/sections/credentials/shared/PredefinedFields.jsx

analytics.jsAdd Segment event tracking +10/-0

Add Segment event tracking

• Defines the activation CTA event and adds a track wrapper that includes the hostname.

webapp_v2/src/services/analytics.js

resources.jsExpose resource lookup and creation +2/-0

Expose resource lookup and creation

• Adds GET-by-name and POST resource methods for wizard validation and submission.

webapp_v2/src/services/resources.js

useUserStore.jsGate Segment events on tracking consent +8/-1

Gate Segment events on tracking consent

• Adds trackEvent, which checks analyticsTracking and reports tracking failures without interrupting the UI.

webapp_v2/src/stores/useUserStore.js

Refactor (17) +280 / -236
CredentialsTab.jsxReuse extracted connection-method controls +7/-91

Reuse extracted connection-method controls

• Replaces locally defined method and secrets-provider selectors with shared components.

webapp_v2/src/pages/Roles/Configure/CredentialsTab.jsx

DetailsTab.jsxUse the shared attributes selector +1/-1

Use the shared attributes selector

• Points Configure Role at the selector now shared with resource setup.

webapp_v2/src/pages/Roles/Configure/DetailsTab.jsx

ConnectionMethod.jsxExtract reusable credential method selectors +101/-0

Extract reusable credential method selectors

• Provides method cards and a secrets-manager provider selector for both role configuration and resource setup.

webapp_v2/src/pages/Roles/Configure/components/ConnectionMethod.jsx

ClaudeCodeRenderer.jsxRead Claude Code credentials from context +7/-7

Read Claude Code credentials from context

• Switches secret staging and migration actions to the context-selected credential store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/ClaudeCodeRenderer.jsx

KubernetesTokenRenderer.jsxRead Kubernetes credentials from context +6/-6

Read Kubernetes credentials from context

• Switches staged secrets, sources, and actions to the context-selected credential store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/KubernetesTokenRenderer.jsx

McpProxyRenderer.jsxRead MCP proxy credentials from context +9/-9

Read MCP proxy credentials from context

• Switches secret and draft state access to the context-selected credential store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/McpProxyRenderer.jsx

McpRenderer.jsxRead MCP credentials from context +5/-5

Read MCP credentials from context

• Switches staged-secret state and actions to the context-selected credential store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/McpRenderer.jsx

SshRenderer.jsxRead SSH credentials from context +5/-5

Read SSH credentials from context

• Switches secret and subtype-draft actions to the context-selected credential store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/SshRenderer.jsx

AgentSelector.jsxUse context for credential agent drafts +3/-3

Use context for credential agent drafts

• Reads and writes the selected agent draft through the context-selected store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/shared/AgentSelector.jsx

AllowInsecureSsl.jsxUse context for insecure SSL credentials +5/-5

Use context for insecure SSL credentials

• Moves SSL secret staging and display-state reads to the context-selected store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/shared/AllowInsecureSsl.jsx

CommandArgs.jsxUse context for command drafts +3/-3

Use context for command drafts

• Reads and writes command arguments through the context-selected store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/shared/CommandArgs.jsx

ConfigurationFiles.jsxUse context for configuration file secrets +7/-7

Use context for configuration file secrets

• Switches staged file contents, renames, and secret actions to the context-selected store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/shared/ConfigurationFiles.jsx

EnvironmentVariables.jsxUse context for environment variable secrets +9/-9

Use context for environment variable secrets

• Switches variable staging, sources, renames, and actions to the context-selected store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/shared/EnvironmentVariables.jsx

HttpHeaders.jsxUse context for HTTP header secrets +9/-9

Use context for HTTP header secrets

• Switches header staging, sources, renames, and actions to the context-selected store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/shared/HttpHeaders.jsx

store.jsProvide a credential-store context +13/-0

Provide a credential-store context

• Defaults credential renderers to Configure Role while allowing each wizard role to supply its own store.

webapp_v2/src/pages/Roles/Configure/sections/credentials/store.js

store.jsReuse shared secret actions in Configure Role +2/-76

Reuse shared secret actions in Configure Role

• Replaces inlined secret staging, source, deletion, cancellation, and rename actions with the shared credentials slice.

webapp_v2/src/pages/Roles/Configure/store.js

credentialsSlice.jsExtract shared credential mutation actions +88/-0

Extract shared credential mutation actions

• Defines secret staging, source changes, deletion, cancellation, and renaming for both credential stores.

webapp_v2/src/pages/Roles/Configure/utils/credentialsSlice.js

Tests (8) +996 / -0
aws-ssm-two-roles.jsonRecord the CLJS AWS SSM two-role payload +59/-0

Record the CLJS AWS SSM two-role payload

• Provides a reference creation body for two roles with distinct credentials.

webapp_v2/test/fixtures/resourceSetup/aws-ssm-two-roles.json

metadata.jsonProvide representative catalog metadata +427/-0

Provide representative catalog metadata

• Fixtures catalog IDs, subtypes, commands, and credential definitions for routing and payload tests.

webapp_v2/test/fixtures/resourceSetup/metadata.json

mysql-aws-iam.jsonRecord the CLJS MySQL AWS IAM payload +32/-0

Record the CLJS MySQL AWS IAM payload

• Provides a reference body covering IAM-encoded credentials, a filesystem field, and profile opt-out.

webapp_v2/test/fixtures/resourceSetup/mysql-aws-iam.json

postgres-manual.jsonRecord the CLJS manual PostgreSQL payload +35/-0

Record the CLJS manual PostgreSQL payload

• Provides a reference body with manual credentials and role attributes.

webapp_v2/test/fixtures/resourceSetup/postgres-manual.json

postgres-new-agent.jsonRecord the CLJS new-agent payload +33/-0

Record the CLJS new-agent payload

• Provides a reference PostgreSQL body using a newly created agent ID.

webapp_v2/test/fixtures/resourceSetup/postgres-new-agent.json

postgres-vault-kv2.jsonRecord the CLJS Vault-backed payload +33/-0

Record the CLJS Vault-backed payload

• Provides a reference PostgreSQL body mixing Vault KV v2 and manual field sources.

webapp_v2/test/fixtures/resourceSetup/postgres-vault-kv2.json

python.jsonRecord the CLJS development-environment payload +30/-0

Record the CLJS development-environment payload

• Provides a reference Python resource body with a catalog command and no credentials.

webapp_v2/test/fixtures/resourceSetup/python.json

resourceSetup.test.jsTest subtype selection, payloads, and wizard state +347/-0

Test subtype selection, payloads, and wizard state

• Checks catalog resolution, React eligibility, fixture-matched create bodies, credential source transitions, state reset, name validation, and activation-card decisions.

webapp_v2/test/resourceSetup.test.js

Documentation (2) +25 / -13
COMPONENTS.mdDocument shared setup controls +23/-12

Document shared setup controls

• Documents credential store injection, the shared attributes picker, sourced-input presentation, and Segment tracking.

webapp_v2/COMPONENTS.md

CONTEXT_MIGRATION.mdDocument the split setup route +2/-1

Document the split setup route

• Records which resource subtypes use React and which continue through the CLJS route.

webapp_v2/CONTEXT_MIGRATION.md

@luanlorenzo
luanlorenzo requested a review from racerxdl October 29, 2026 20:58
@qodo-code-review

qodo-code-review Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (2) 📎 Requirement gaps (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. New resources can use the wrong agent ✓ Resolved

Resolving commit: 6ccb29c

Resolution reason
setAgentMode now clears agentId when changing agent mode, preventing a newly created agent workflow
from retaining and submitting the previously selected agent. A regression test verifies this
behavior.
Description
setAgentMode('create') leaves an already selected agentId in place while the agent selector
becomes disabled. If an admin selects an existing agent and then chooses to create a new one, the
footer still permits advancing and the resource payload uses the existing agent’s ID.


Remediation recommended

2. The attributes control has no label ✗ Dismissed
Description
DetailsTab now imports the shared AttributesSelect, but its existing usage supplies no label
prop and the shared component only forwards that optional prop to PillsInput. When the details
form renders the attributes combobox, its nearby heading is not associated with the actual input.

3. Old saves can finish a newer wizard ✓ Resolved

Resolving commit: 6ccb29c

Resolution reason
Submission now captures a run- and request-scoped guard and checks it after the create request
resolves or fails, preventing stale saves from updating submission state, showing success, or
entering the success step after a new wizard run starts. A regression test verifies this behavior.
Description
submit commits its captured roles and success step after resourcesService.create resolves
without checking whether the wizard run is still current. If an admin begins another setup while the
POST is pending, the earlier response can replace the newer setup’s screen and created-role state.

4. Legacy setups fail during catalog outages ✓ Resolved

Resolving commit: 6ccb29c

Resolution reason
ByResourceSetup now resolves the setup configuration before handling missing metadata and
immediately renders the CLJS wizard for mapped non-React types, allowing legacy catalog-only setups
such as linux-vm to work during metadata outages. A regression test also verifies resolution without
metadata.
Description
ByResourceSetup checks the metadata error state before calling setupConfigFor, even though
SETUP_MAPPINGS can resolve ssh, tcp, httpproxy, and linux-vm without metadata. If the
metadata request fails, administrators following a direct link such as
/resources/new?type=linux-vm see a catalog-load failure instead of reaching the CLJS wizard.

View medium (19)
5. Mantine label overrides leak globally ✗ Dismissed
Description
Setup.module.css uses :global(.mantine-InputWrapper-label) to style Mantine labels instead of
keeping the selector scoped to the module or configuring the theme. Every matching Mantine input
label under .content, including labels outside the component’s intended styling API, receives this
override.

6. Setup credentials have no real labels ✗ Dismissed
Description
SourcedInput renders FieldLabel as visual text instead of a <label> and does not associate the
label with its input or textarea. The new create-mode credential fields use this component, so each
visible credential control lacks an explicit or implicit label association, while the source
selector has only an aria-label.

7. Rails resources cannot be created ✗ Dismissed
Description
The React setup allowlist registers ruby-on-rails but not the required rails catalog type. When
type=rails is provided, setup resolution returns no configuration and ByResourceSetup redirects
the user back to /resource-catalog instead of opening a wizard.

8. Concurrent setup writes bypass store freshness ✓ Resolved

Resolving commit: 6ccb29c

Resolution reason
Removed the module-level run/request counters and moved them into the Zustand state. The latest()
helper now reads and updates store-owned generation and per-request counters, while start()
increments the run generation so stale async responses are rejected.
Description
latest tracks run and per-request counters in module-level variables rather than exposing a
generation or request ID in the Zustand state. When loadAgents and findNewAgent overlap or other
async setup writers run concurrently, freshness is not represented by the store-owned resource state
required for consistent request lifecycle handling.

9. Returning to roles can block saving ✓ Resolved

Resolving commit: b1a7c28

Resolution reason
loadRoleOptions now obtains a per-request roleOptions identity via latest('roleOptions') and
applies results only when that request remains current, preventing stale loads from overwriting
newer readiness state.
Description
loadRoleOptions rejects responses from earlier wizard runs but does not distinguish multiple loads
within the same run. If an administrator goes Back and returns to Roles while the first load is
pending, an older failure arriving after a successful second load changes roleOptions back to
error and disables Save.

10. Old agent requests corrupt new setup ✓ Resolved

Resolving commit: b1a7c28

Resolution reason
Added per-request and per-wizard-run freshness guards for agent creation, agent loading, and agent
lookup, including success, failure, loading, and selection state updates. Leaving the agent step now
invalidates in-flight creation and lookup requests, preventing stale responses from modifying the
active setup.
Description
createAgent commits success or failure without verifying that its creation attempt still belongs
to the current wizard, while loadAgents and findNewAgent do not consistently guard their
asynchronous state writes. If an administrator leaves the agent step, starts another setup, or
retries a lookup while a request is pending, an older response can restore an abandoned agent’s key,
start a lookup that selects its ID, or replace a newer lookup result.

11. Activation cards skip shared role checks ✗ Dismissed
Description
ActivationCards uses the isAdmin boolean from useUserStore to decide whether to load and
render admin-only activation cards instead of calling hasRole. Those role-based access decisions
therefore bypass the shared role helper at both the request and rendering boundaries.

12. Agent lists can show stale choices ✓ Resolved

Resolving commit: 932eeb6

Resolution reason
Added a monotonic agentsRequest ID and guarded loadAgents and createAgent's follow-up lookup commits
so stale responses cannot replace current agent data or loading state.
Description
loadAgents and the follow-up list request inside createAgent update agents and agentsLoading
without a generation or request ID check. When those requests overlap, an older response can replace
a newer agent list or clear the loading state while another request is still pending.

13. Pressing Enter to add an attribute creates the resource ✓ Resolved

Resolving commit: 932eeb6

Resolution reason
The AttributesSelect key handler now prevents Enter from submitting the enclosing form and, when no
option is highlighted and attribute creation is allowed, explicitly creates the typed attribute.
Description
AttributesSelect does nothing with Enter unless an option is highlighted, and the roles step
renders it inside the resource-setup-form <form>, whose onSubmit calls submit(connections) →
POST /resources. If an admin types a new attribute name and presses Enter (the usual way to accept
a "Create" entry), the browser submits the form: once the required fields are filled, the resource
is created on the spot without the new attribute and the wizard moves to the success step.

14. Success copy splits into text nodes ✓ Resolved

Resolving commit: 932eeb6

Resolution reason
The confirmation message was split into two separate Text elements, eliminating the mixed bare-text
and expression content within one Text component while preserving the visual line break.
Description
SuccessStep places a template expression, a <br />, and a bare text node inside one Text
element instead of producing the complete message from one string expression. This occurs in the
ready-resource confirmation and leaves the sentence content divided across JSX text nodes.

15. Legacy setup links return to the catalog ✓ Resolved

Resolving commit: 932eeb6

Resolution reason
Added oracle and tcp catalog mappings with the expected types and subtypes, and added tests
verifying both resolve correctly.
Description
setupConfigFor omits the existing oracle and tcp catalog aliases and only falls back to an
exact metadata ID match. When either legacy ID is handed off without a matching metadata entry,
ByResourceSetup redirects to the catalog instead of opening its React or ClojureScript wizard.

16. Keyboard users cannot choose a method ✗ Dismissed
Description
MethodCard renders each installation method as a Mantine Box with onClick but no native
control, tabindex, role, or keyboard handler. The new Agent step mounts these cards for Docker and
Kubernetes, so keyboard users cannot select an installation method.

17. Unchecked names can advance setup ✓ Resolved

Resolving commit: 932eeb6

Resolution reason
The commit captures the name and run generation before checking it, then ignores successful or error
responses unless both the wizard run and current name still match the request. This prevents stale
404 responses from advancing setup.
Description
checkName advances on a 404 without verifying that the current name is still the one sent to
resourcesService.get. If an administrator edits the name while the request is pending, the
response for the old name advances the new, unchecked name to the agent step.

18. New attributes can be omitted on save ✓ Resolved

Resolving commit: 932eeb6

Resolution reason
createAttribute now adds the attribute to the role optimistically before awaiting the API request,
ensuring an immediate save includes it. If creation fails, the attribute is removed from both the
available attributes and the role, with an error notification shown.
Description
createAttribute adds a name to the role only after its API request completes, but the roles form
does not wait for that request before submitting. If an administrator creates an attribute and
immediately saves, submit snapshots the earlier role and sends a resource payload without the
selected attribute.

19. Old activation data replaces current setup ✓ Resolved

Resolving commit: 932eeb6

Resolution reason
Added a setup-run generation guard: loadActivation captures the current run and discards
asynchronous results when the setup has changed, while start() increments the run generation.
Description
loadActivation captures the current roles and unconditionally writes its asynchronous results into
the shared activation state. If a new setup starts before the previous batch completes, the
earlier batch can overwrite activation cards for the newer setup run.

20. Fast saves omit the protection profile ✓ Resolved

Resolving commit: 932eeb6

Resolution reason
The wizard now tracks protection-profile loading with roleOptions, blocks submission unless the
profile lookup succeeds, and displays a retry alert when the lookup fails. This prevents fast saves
from omitting the profile attribute.
Description
loadRoleOptions fetches the active protection profile asynchronously, while submit treats an
as-yet-unloaded profile as having no attribute. If the administrator reaches the roles step and
saves before that lookup finishes, the created role is submitted without the active profile's
attribute.

21. Attribute outages allow incomplete roles ✓ Resolved

Resolving commit: 6ccb29c

Resolution reason
Role options now become ready only when both attributes and the protection profile load
successfully; an attribute failure produces an error state with updated retry messaging, preventing
incomplete saves.
Description
loadRoleOptions replaces a failed attribute lookup with an empty list but marks the options ready
whenever the separate protection-profile lookup succeeds. During an attribute-service outage, admins
can save roles without being shown the existing attributes they intended to attach, and receive no
attribute-load error or retry control.

22. Analytics failures become console noise ✗ Dismissed
Description
trackEvent catches rejected analytics requests and reports them with console.warn instead of the
application's logging mechanism. Every failed event in production reaches this ad-hoc
browser-console path, producing unstructured warnings rather than controlled application logging.

23. Agent lookup failures stall setup ✓ Resolved

Resolving commit: 932eeb6

Resolution reason
The commit preserves the created agent token, tracks ID lookup separately with pending/done/error
states, exposes findNewAgent for retry, and adds a retry alert on the agent step without repeating
agent creation.
Description
createAgent marks a successful creation as ready before its separate agent-list request resolves
an ID, and a failed or empty lookup leaves that ID null. In that state the create control is hidden
and the next-step control is disabled, with no retry for the lookup on the agent step.


Informational

24. Navigation IDs break the naming contract ✗ Dismissed
Description
dispatch-setup-navigation dispatches :navigate and :resource-setup-new as bare re-frame
keywords in the changed navigation call. Any handler or subscription lookup reached through this new
dispatch remains dependent on non-namespaced identifiers, contrary to the required event ID format.

25. A user's analyzer pitch hides for others 📘 Rule violation ≡ Correctness
Description
onCta writes the global ai-session-analyzer-promotion-seen key when an administrator opens the
analyzer card. The analyzer page reads that same unscoped key for every user, so one user's
interaction suppresses the promotion for other users sharing the browser profile.
Code

webapp_v2/src/pages/Resources/Setup/sections/ActivationCards.jsx[86]

+        localStorage.setItem('ai-session-analyzer-promotion-seen', 'true')
Relevance

● Weak

A closely matching per-user localStorage scoping suggestion was explicitly rejected recently.

PR-#1679

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The changed activation flow writes an unscoped dismissal/promotion key, while the existing analyzer
page reads that exact global key to determine whether the promotion was seen.

Rule 2791676: localStorage dismissal keys must be scoped per user to avoid cross-user suppression
webapp_v2/src/pages/Resources/Setup/sections/ActivationCards.jsx[83-89]
webapp_v2/src/pages/Features/AiSessionAnalyzer/index.jsx[18-41]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The analyzer promotion state is stored under a global localStorage key, so one user's interaction can suppress the promotion for another user sharing the same browser profile.

## Fix Focus Areas
- webapp_v2/src/pages/Resources/Setup/sections/ActivationCards.jsx[83-89]
- webapp_v2/src/pages/Features/AiSessionAnalyzer/index.jsx[18-41]

## Recommended Fix
Include the current user ID in the promotion storage key, and update both the writer and reader to use the same user-scoped key. Preserve the existing behavior when no user ID is available by avoiding a persistent global dismissal value.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗


26. New setup files keep PascalCase names ✗ Dismissed
Description
The added resource setup files use PascalCase names such as AgentStep.jsx instead of the required
kebab-case convention. This affects the new setup components and stylesheet files throughout
pages/Resources/Setup, creating inconsistent paths for maintainers and tooling.

View low (2)
27. Credential fields stay page-scoped 📘 Rule violation ⚙ Maintainability
Description
PredefinedFields and ConnectionMethodSection remain under Configure Role directories despite
serving as shared components. Both Configure Role and Resources Setup import them, so their
page-specific locations obscure their cross-page reuse scope.
Code

webapp_v2/src/pages/Roles/Configure/sections/credentials/shared/PredefinedFields.jsx[R45-50]

+  const stagedSecrets = useCredentialsStore((s) => s.stagedSecrets)
+  const fieldSources = useCredentialsStore((s) => s.fieldSources)
+  const replaceSecret = useCredentialsStore((s) => s.replaceSecret)
+  const cancelSecretChange = useCredentialsStore((s) => s.cancelSecretChange)
+  const setFieldSource = useCredentialsStore((s) => s.setFieldSource)
+  const createMode = useCredentialsStore((s) => s.createMode)
Relevance

● Weak

Recent precedent rejects relocating reused page components solely to satisfy broad
directory-placement rules.

PR-#1893
PR-#1834

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PredefinedFields is defined in a Configure Role credential-sections directory and imported by
CatalogRenderer and Resources Setup's RoleForm; ConnectionMethodSection is defined under
Configure Role and imported by CredentialsTab and the same Resources Setup form. These definitions
and consumers show that both components are reused across unrelated pages, while the checklist calls
for such components to reside under src/components/.

Rule 1800988: Enforce directory placement based on React component reuse scope
webapp_v2/src/pages/Roles/Configure/sections/credentials/shared/PredefinedFields.jsx[37-50]
webapp_v2/src/pages/Roles/Configure/sections/credentials/CatalogRenderer.jsx[2-2]
webapp_v2/src/pages/Resources/Setup/sections/RoleForm.jsx[18-20]
webapp_v2/src/pages/Roles/Configure/components/ConnectionMethod.jsx[45-75]
webapp_v2/src/pages/Roles/Configure/CredentialsTab.jsx[18-21]
webapp_v2/src/pages/Resources/Setup/sections/RoleForm.jsx[15-17]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`PredefinedFields` and `ConnectionMethodSection` are reused by Configure Role and Resources Setup but remain in Configure Role-specific directories. Move them to a location that reflects their cross-page reuse.

## Fix Focus Areas
- webapp_v2/src/pages/Roles/Configure/sections/credentials/shared/PredefinedFields.jsx[45-50]
- webapp_v2/src/pages/Roles/Configure/sections/credentials/CatalogRenderer.jsx[2-2]
- webapp_v2/src/pages/Resources/Setup/sections/RoleForm.jsx[18-20]
- webapp_v2/src/pages/Roles/Configure/components/ConnectionMethod.jsx[45-45]
- webapp_v2/src/pages/Roles/Configure/CredentialsTab.jsx[18-21]
- webapp_v2/src/pages/Resources/Setup/sections/RoleForm.jsx[15-17]

## Recommended Fix
Move both components to `webapp_v2/src/components/` and update their Configure Role and Resources Setup imports. Preserve `PredefinedFields`' credentials-store context and `createMode` behavior, and preserve `ConnectionMethodSection`'s existing exports and behavior.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Dismiss ↗ | View ↗


28. New picker styling bypasses utility classes ✗ Dismissed
Description
The added source picker layout relies on custom selectors in SourceMenu.module.css, including
.labels and [data-hidden], instead of utility classes in the component markup. The selectors
provide the picker’s primary sizing and visibility behavior, so the new source menu depends on
bespoke stylesheet rules rather than the mandated utility styling approach.

Grey Divider

Context sources
✅ Compliance rules (platform): 125 rules
✅ Skills: build-ticket
✅ Cross-repo context — repo relationships
  Explored: repo: hoophq/documentation (sha: 5bb1076b) — View relationship
Review mode: Auto: ⚖️ Balanced: Downgraded extended -> standard: change is below the extended eligibility bar (hunks 12/18, lines 988/200; both must reach the floor). Router rationale: Dense new wizard logic spans routing, async state, roles, payloads, and activation.
✅ Fix-loop round: fix loop

Grey Divider

⚠️ Warning | Comment size exceeded, non finding content trimmed Learn more

Grey Divider

Qodo Logo

@sandromello

Copy link
Copy Markdown
Contributor

✅ Build Completed with Success, Version=2089.0.0-gf266734

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 932eeb6

@sandromello

Copy link
Copy Markdown
Contributor

✅ Build Completed with Success, Version=2089.0.0-g932eeb6

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit b1a7c28

@sandromello

Copy link
Copy Markdown
Contributor

✅ Build Completed with Success, Version=2089.0.0-gb1a7c28

Comment thread webapp_v2/src/stores/useUserStore.js Resolved
Comment thread webapp_v2/src/modes/ByResourceSetup.jsx Resolved
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit dd085a1

@sandromello

Copy link
Copy Markdown
Contributor

✅ Build Completed with Success, Version=2089.0.0-gdd085a1

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 6ccb29c

@sandromello

Copy link
Copy Markdown
Contributor

✅ Build Completed with Success, Version=2089.0.0-g6ccb29c

@luanlorenzo
luanlorenzo merged commit ec6fc1e into main Nov 4, 2026
@luanlorenzo
luanlorenzo deleted the luan/eng-913 branch November 4, 2026 16:41
@github-actions github-actions Bot locked and limited conversation to collaborators Nov 4, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

minor Bumps the minor version on release (new features)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants