Skip to content

FEATURE: Flow Plugin#75

Merged
Go2Engle merged 8 commits intomainfrom
feature/add-flow-diagram-plugin
Apr 20, 2026
Merged

FEATURE: Flow Plugin#75
Go2Engle merged 8 commits intomainfrom
feature/add-flow-diagram-plugin

Conversation

@Go2Engle
Copy link
Copy Markdown
Owner

@Go2Engle Go2Engle commented Apr 20, 2026

This pull request introduces a new "Flow" plugin and entity type, enabling users to create, edit, and manage interactive system flow diagrams that are backed by catalog entities. The implementation includes backend API endpoints, schema and registry updates, access control, and frontend integration, ensuring that "Flow" entities are first-class citizens in the system and UI. Additionally, the UI and command palette are updated to support and display the new entity type.

Flow plugin and entity support:

  • Added a new Flow entity kind to the catalog, including its JSON schema (flow.json) for validation and a corresponding entry in the plugin registry, describing its features and configuration options. [1] [2] [3]
  • Implemented backend API endpoints for CRUD operations on Flow entities, including role-based access control, auditing, and event publishing. These endpoints are registered in the API server and include logic for editor role validation and sidebar visibility. [1] [2] [3] [4]
  • Updated the topology data handler to exclude Flow entities from topology graphs, as flows are meant to be diagrammatic and not part of the inferred system topology.

Frontend and UI integration:

  • Added lazy-loaded support for a new /flow route in the web frontend, with a suspense fallback, and included the Flow page in the application routes. [1] [2] [3]
  • Updated the command palette and entity card components to recognize and visually represent the Flow kind using a new icon and color scheme. [1] [2] [3] [4] [5]

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

Warning

Rate limit exceeded

@Go2Engle has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 29 minutes and 26 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 29 minutes and 26 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8ec62e42-66f1-429e-924e-e2f63af85c25

📥 Commits

Reviewing files that changed from the base of the PR and between 3bc7e9e and b356a8e.

📒 Files selected for processing (12)
  • internal/api/handlers/entities.go
  • internal/api/handlers/flow.go
  • internal/api/handlers/plugins.go
  • internal/entity/schemas/flow.json
  • internal/plugins/bundled/registry.json
  • internal/plugins/errors.go
  • web/src/components/EntityCard.tsx
  • web/src/components/FlowTab.tsx
  • web/src/lib/api.ts
  • web/src/lib/flow.tsx
  • web/src/pages/Catalog.tsx
  • web/src/pages/Flow.tsx
📝 Walkthrough

Walkthrough

This pull request introduces a new Flow plugin that enables users to create, manage, and visualize interactive system flow diagrams. The implementation adds backend CRUD endpoints with role-based access control, a comprehensive diagram editor frontend component, and integrates the Flow entity kind throughout the application UI.

Changes

Cohort / File(s) Summary
Backend Flow Handler Implementation
internal/api/handlers/flow.go, internal/plugins/bundled/registry.json, internal/entity/kinds.go
Adds four public handler methods for Flow CRUD operations (GetFlowSettings, CreateFlowEntity, UpdateFlowEntity, DeleteFlowEntity) with permission enforcement, entity validation, audit logging, and event publishing. Registers Flow as a new entity kind with configurable editorRole (default "developer") and showInSidebar (default true) settings.
Backend Flow Schema & Validation
internal/entity/schemas/flow.json, internal/api/handlers/plugins.go, internal/api/handlers/topology.go
Defines JSON schema for Flow entity structure (viewport, nodes with entity/mock variants, directional edges). Updates plugin validation to trim and validate editorRole against registered roles. Skips Flow entities during topology graph construction to prevent flow diagrams from contributing nodes/edges to the dependency graph.
Backend Server Routing
internal/api/server.go
Wires authenticated Flow plugin routes: GET /plugins/flow/settings, POST /plugins/flow/entities, PUT /plugins/flow/entities/{name}, and DELETE /plugins/flow/entities/{name} with namespace query param support.
Frontend Flow Page & Diagram Editor
web/src/pages/Flow.tsx, web/src/components/FlowTab.tsx
Implements comprehensive flow diagram editor/viewer (2104 lines) with drag-drop node positioning, pan/zoom controls, edge creation/editing, and shape-based mock nodes. Supports entity-backed nodes, bidirectional relationships, animated edges, and "Seed Edges" analysis from entity dependencies. Includes save/delete operations with draft state tracking, read-only preview mode, and role-based edit restrictions. FlowTab provides a preview rendering with SVG-based edge paths and node visualization for the EntityDetail page.
Frontend Route & App Structure
web/src/App.tsx, web/src/pages/EntityDetail.tsx, web/src/lib/api.ts, web/src/lib/types.ts
Converts route imports to lazy-loading with Suspense fallback. Adds /flow route and new tab for Flow entities in EntityDetail page. Extends API client with Flow-related endpoints (getFlowSettings, listFlows, createFlow, updateFlow, deleteFlow). Introduces Flow modeling types: FlowSpec, FlowNode, FlowEdge, FlowViewport, FlowPluginSettings, and FlowEntityRef.
Frontend UI Integration
web/src/components/Sidebar.tsx, web/src/components/CommandPalette.tsx, web/src/components/EntityCard.tsx
Adds sidebar navigation entry for Flow (conditionally shown based on showInSidebar setting fetched via getFlowSettings). Associates Flow kind with Workflow icon and sky-colored badge styling in CommandPalette and EntityCard. Sidebar logic detects Flow plugin state and conditionally enables/disables the Flow link.
Frontend Configuration & Catalog
web/src/pages/Plugins.tsx, web/src/pages/Catalog.tsx, web/src/pages/Dashboard.tsx
Extends plugin configuration UI to support role-picker fields (schema fields with x-role-picker: true) with async role option loading from api.listRoles(). Adds Flow to catalog KIND_META with Network icon and color theming. Updates Dashboard iconMap to include Network icon.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser as Web Client
    participant API as Flow API<br/>(handlers)
    participant DB as Database
    participant EventBus as Event System

    User->>Browser: Creates new Flow entity
    Browser->>API: POST /plugins/flow/entities<br/>(entity spec)
    API->>API: Validate write access<br/>(check editorRole permission)
    API->>API: Validate entity structure<br/>(Kind="Flow")
    API->>DB: Create Flow entity
    API->>EventBus: Publish EntityCreated event
    API->>DB: Write audit log<br/>(entity state, client IP)
    API-->>Browser: HTTP 201 + entity
    Browser->>Browser: Update local flows list<br/>Reload saved flow draft

    User->>Browser: Modifies Flow diagram<br/>(adds nodes/edges)
    Browser->>API: PUT /plugins/flow/entities/{name}<br/>(updated spec)
    API->>API: Validate write access
    API->>DB: Fetch previous state<br/>(for audit)
    API->>DB: Update Flow entity
    API->>EventBus: Publish EntityUpdated event
    API->>DB: Write audit log<br/>(before/after states)
    API-->>Browser: HTTP 200 + entity

    User->>Browser: Requests Flow settings
    Browser->>API: GET /plugins/flow/settings
    API->>DB: Load Flow plugin config
    API->>API: Compute canEdit permission<br/>(editorRole vs caller role)
    API-->>Browser: HTTP 200 + settings<br/>(showInSidebar, editorRole, canEdit)
    Browser->>Browser: Conditionally render<br/>editor vs. read-only view
Loading
sequenceDiagram
    participant User
    participant Canvas as Flow Editor<br/>Canvas
    participant StateStore as Draft<br/>State
    participant API as Flow API
    participant DB as Database

    User->>Canvas: Drag entity node
    Canvas->>StateStore: Update node position
    StateStore->>StateStore: Mark draft dirty
    Canvas->>Canvas: Re-render canvas

    User->>Canvas: Click "Seed Edges"
    Canvas->>Canvas: Analyze existing entity nodes<br/>(dependsOn, consumesApis, etc.)
    Canvas->>Canvas: Generate relationship edges
    Canvas->>StateStore: Add edges to draft
    Canvas->>Canvas: Re-render with new edges

    User->>Canvas: Click "Save"
    Canvas->>API: POST or PUT /plugins/flow/entities<br/>(full FlowSpec + metadata)
    API->>API: Validate against schema
    API->>DB: Persist Flow entity
    API-->>Canvas: HTTP 200/201 + persisted entity
    Canvas->>StateStore: Clear dirty flag
    Canvas->>Canvas: Reload draft from server
    Canvas->>User: Show success notice
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 A flow of diagrams now takes flight,
With nodes and edges shining bright!
Mock boxes dance, and entities link,
Drag them 'round, adjust, and think.
The Flow is here—workflow dreams made real!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'FEATURE: Flow Plugin' is concise and directly reflects the main changeset, which introduces a comprehensive Flow plugin with entity kind definitions, HTTP handlers, frontend pages, and UI components.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/add-flow-diagram-plugin

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 and usage tips.

@Go2Engle Go2Engle changed the title Refine Flow mockup sizing and lazy-load app routes FEATURE: Flow Plugin Apr 20, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

Caution

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

⚠️ Outside diff range comments (1)
web/src/pages/EntityDetail.tsx (1)

365-397: ⚠️ Potential issue | 🟠 Major

Generic entity endpoints must enforce Flow editor permissions.

The generic PUT /entities/Flow/{name} and DELETE /entities/Flow/{name} endpoints bypass Flow's editorRole restriction. These handlers are gated only by RequireRole("developer"), allowing any developer to edit or delete Flow entities even if they lack the Flow editor role. Add ensureFlowWriteAccess() check to UpdateEntity and DeleteEntity when kind == "Flow".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/pages/EntityDetail.tsx` around lines 365 - 397, Update the generic
entity handlers so Flow edits/deletes require Flow editor permissions: in the
UpdateEntity and DeleteEntity handlers, when entity.kind === "Flow" call
ensureFlowWriteAccess() (and abort/return a forbidden/error response if it
fails) before performing the update or delete; ensure this check runs in both
UpdateEntity and DeleteEntity code paths and gates any downstream logic that
modifies or removes Flow entities.
🧹 Nitpick comments (3)
internal/api/handlers/flow.go (1)

41-50: Reusing entity.ErrEntityNotFound for a missing plugin conflates two concepts.

getFlowPlugin returns entity.ErrEntityNotFound when the flow row is missing from the plugins table. Callers then translate that back to "flow plugin not installed" (lines 72-74, 94-96). Consider a dedicated sentinel (e.g. ErrPluginNotInstalled in the plugins package) to avoid future mis-detection if ErrEntityNotFound ever leaks through a different code path.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/handlers/flow.go` around lines 41 - 50, Replace use of the
generic entity.ErrEntityNotFound in getFlowPlugin with a dedicated sentinel
error in the plugins package (e.g., plugins.ErrPluginNotInstalled); create that
error in the plugins package, update getFlowPlugin to return
plugins.ErrPluginNotInstalled when h.DB.GetPlugin returns a nil plugin, and
update any callers of getFlowPlugin (the handlers that currently interpret
entity.ErrEntityNotFound) to check for plugins.ErrPluginNotInstalled instead of
entity.ErrEntityNotFound so the “flow plugin not installed” case is unambiguous.
web/src/components/FlowTab.tsx (1)

25-181: Significant duplication with web/src/pages/Flow.tsx.

ensureFlowSpec, isMockNode, nodeColor, withAlpha, mockFoldFill, estimateWrappedLines, getNodeDimensions, renderMockNodeShell, mockContentClasses, mockContentStyle, edgePath, edgeLabelPosition, edgeOffsetTransform, kindColors, MOCK_SHAPE_OPTIONS, and the size constants are copy-pasted between this file and web/src/pages/Flow.tsx (lines ~60-368). Any future tweak to shape geometry/sizing will need to be made in two places and will quietly drift (e.g. the existing divergence in mockShapeLabel return strings: "Mock Pill" vs "Pill"). Consider extracting a shared module like web/src/lib/flow.ts that both the preview and editor import.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/components/FlowTab.tsx` around lines 25 - 181, Duplicate flow
utilities and constants (ensureFlowSpec, isMockNode, nodeColor, withAlpha,
mockFoldFill, estimateWrappedLines, getNodeDimensions, mockShapeLabel, plus
MOCK_SHAPE_OPTIONS, kindColors and size constants) exist in both FlowTab and
Flow; extract them into a single shared module and import it from both places.
Create a new shared module that exports the listed functions and constants, move
the implementations (keeping the canonical strings like mockShapeLabel returns
consistent), update FlowTab to import the utilities instead of redefining them,
and update the other file (Flow) to import the same module so all
geometry/sizing/labels are maintained in one place. Ensure exported types
(FlowSpec, FlowNode, FlowMockNode, FlowEntityNode, FlowEdge) are available or
re-exported so existing type usages in ensureFlowSpec and getNodeDimensions
continue to compile.
web/src/pages/Flow.tsx (1)

989-989: Use functional setDirty to avoid stale closure on dirty.

setDirty(added > 0 || dirty) captures dirty at render time. If this handler is ever triggered while another update is already pending, dirty will be stale. Safer to write:

-    setDirty(added > 0 || dirty);
+    setDirty((prev) => added > 0 || prev);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/pages/Flow.tsx` at line 989, The current call setDirty(added > 0 ||
dirty) uses the captured dirty value and can suffer from a stale-closure race;
change it to use the functional updater form of the state setter (i.e., pass a
function that receives the previous dirty value and returns added > 0 ||
previous) so the update always composes with any pending state changes—update
the code around the setDirty call in the handler that references added and dirty
(look for the setDirty call) to use the prev-state functional pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/api/handlers/flow.go`:
- Around line 115-119: The CreateFlowEntity and UpdateFlowEntity handlers
currently call json.NewDecoder(r.Body).Decode(&e) without limiting body size;
wrap r.Body with http.MaxBytesReader before creating the decoder (e.g., maxBytes
:= int64(1<<20) or a shared const) and use
json.NewDecoder(http.MaxBytesReader(w, r.Body, maxBytes)). After decoding,
detect if the error is due to exceeding the limit and return
http.StatusRequestEntityTooLarge (413), otherwise return the existing bad
request error; update both CreateFlowEntity and UpdateFlowEntity and keep
references to json.NewDecoder, r.Body, and http.MaxBytesReader.

In `@internal/api/handlers/plugins.go`:
- Around line 194-203: The Flow editor role is being validated after trimming
but the trimmed value isn't written back, so whitespace like " developer "
passes validation but is stored with spaces; in the name == "flow" block update
merged["editorRole"] to the trimmed role (after computing role :=
strings.TrimSpace(...)), ensure you set merged["editorRole"] = "developer" when
role == "" and otherwise, after auth.IsValidRole(role) returns true, persist
merged["editorRole"] = role; use the merged map and auth.IsValidRole references
to locate the change.

In `@internal/entity/schemas/flow.json`:
- Around line 18-20: The schema currently allows zero/negative sizes; update the
JSON schema to require strictly positive values by adding "exclusiveMinimum": 0
to the "zoom" property and to the "width" and "height" properties (both
occurrences referenced in this file), ensuring these numeric fields are
validated as > 0 rather than allowing 0 or negatives.

In `@internal/plugins/bundled/registry.json`:
- Around line 861-862: Update the plugin registry entry so the plugin advertises
its Flow detail tab by populating the entityPanels array instead of leaving it
empty; specifically, in the same plugin object that currently has
"entityPanels": [] and "actionTypes": [], set "entityPanels" to include the Flow
entity kind (e.g., "Flow") so registry-driven metadata is aware the plugin
provides a Flow detail tab.

In `@web/src/components/EntityCard.tsx`:
- Line 22: Replace the hard-coded Tailwind "sky-*" classes used for the Flow
badge in EntityCard (the Flow entry in the badge mapping) with styles that
reference Gantry CSS variables (e.g., --gantry-bg-*, --gantry-text-*,
--gantry-border, --gantry-accent as appropriate). Update the Flow badge
rendering (look for the Flow key in the badge/class mapping or the JSX that
applies that class string) to use either a class that consumes those CSS
variables or inline style attributes that set backgroundColor, color and any
dark-mode variants via the matching Gantry vars, ensuring only the allowed
variables (--gantry-bg-primary/secondary/tertiary,
--gantry-text-primary/secondary, --gantry-border, --gantry-accent,
--gantry-accent-hover, --gantry-danger) are referenced.

In `@web/src/lib/api.ts`:
- Around line 209-215: The updateFlow call in updateFlow (web/src/lib/api.ts)
does not propagate the passed namespace into the request body, so the server may
read metadata.namespace and default to "default"; modify updateFlow to merge the
passed namespace into the Entity metadata before sending (e.g., set
metadata.namespace = namespace when namespace is provided and not
empty/undefined, leaving existing metadata.namespace otherwise) so the request
body contains the correct namespace that the UpdateFlowEntity handler will use.

In `@web/src/pages/Catalog.tsx`:
- Around line 47-50: Replace the hardcoded Tailwind color in the Flow kind
definition by using the Gantry CSS variable; specifically update the Flow
object's color property (the one currently set to 'text-sky-500') to reference
the appropriate --gantry-* variable (e.g., --gantry-accent or the theme color
used for kinds) so the icon color stays theme-compatible across the app.

In `@web/src/pages/Flow.tsx`:
- Around line 1259-1290: Replace the hardcoded hex stroke colors in the edge
rendering paths with the theme CSS variables so edges respect dark mode;
specifically update the stroke attributes used in the single-path branch and the
twoWay forward/reverse branches (the path elements rendering with stroke={...}
in Flow.tsx) to use var(--gantry-text-primary) for the selected/active strokes
and var(--gantry-text-secondary) for the unselected/inactive strokes (or
dedicated tokens if available), keeping existing strokeWidth, strokeDasharray,
markerStart/markerEnd and animation logic intact.
- Around line 481-553: The effect watching flowBounds causes an infinite
re-render because getFlowBounds returns a new object each render; memoize the
result by replacing the direct call to getFlowBounds(flowSpec) with a useMemo
that computes flowBounds and depends on the true inputs (e.g., flowSpec and any
values used inside getFlowBounds) so the reference stabilizes; keep the existing
useEffect that calls setRenderBounds(flowBounds) but use the memoized flowBounds
variable (functions: getFlowBounds, setRenderBounds, useEffect, and the
flowBounds constant) to prevent the dependency loop.
- Around line 1191-1195: The onWheelCapture synthetic handler is ineffective at
preventing page scroll because React registers passive wheel listeners; replace
it by adding a native wheel listener on viewportRef.current inside a useEffect
that attaches with { passive: false }, calls event.preventDefault() and
event.stopPropagation(), computes the new zoom using canvasZoom and ZOOM_STEP
and invokes applyZoomAtClientPoint with event.clientX/event.clientY; ensure the
effect adds the listener when viewportRef.current exists, updates when
canvasZoom or applyZoomAtClientPoint change, and removes the listener in the
cleanup.

---

Outside diff comments:
In `@web/src/pages/EntityDetail.tsx`:
- Around line 365-397: Update the generic entity handlers so Flow edits/deletes
require Flow editor permissions: in the UpdateEntity and DeleteEntity handlers,
when entity.kind === "Flow" call ensureFlowWriteAccess() (and abort/return a
forbidden/error response if it fails) before performing the update or delete;
ensure this check runs in both UpdateEntity and DeleteEntity code paths and
gates any downstream logic that modifies or removes Flow entities.

---

Nitpick comments:
In `@internal/api/handlers/flow.go`:
- Around line 41-50: Replace use of the generic entity.ErrEntityNotFound in
getFlowPlugin with a dedicated sentinel error in the plugins package (e.g.,
plugins.ErrPluginNotInstalled); create that error in the plugins package, update
getFlowPlugin to return plugins.ErrPluginNotInstalled when h.DB.GetPlugin
returns a nil plugin, and update any callers of getFlowPlugin (the handlers that
currently interpret entity.ErrEntityNotFound) to check for
plugins.ErrPluginNotInstalled instead of entity.ErrEntityNotFound so the “flow
plugin not installed” case is unambiguous.

In `@web/src/components/FlowTab.tsx`:
- Around line 25-181: Duplicate flow utilities and constants (ensureFlowSpec,
isMockNode, nodeColor, withAlpha, mockFoldFill, estimateWrappedLines,
getNodeDimensions, mockShapeLabel, plus MOCK_SHAPE_OPTIONS, kindColors and size
constants) exist in both FlowTab and Flow; extract them into a single shared
module and import it from both places. Create a new shared module that exports
the listed functions and constants, move the implementations (keeping the
canonical strings like mockShapeLabel returns consistent), update FlowTab to
import the utilities instead of redefining them, and update the other file
(Flow) to import the same module so all geometry/sizing/labels are maintained in
one place. Ensure exported types (FlowSpec, FlowNode, FlowMockNode,
FlowEntityNode, FlowEdge) are available or re-exported so existing type usages
in ensureFlowSpec and getNodeDimensions continue to compile.

In `@web/src/pages/Flow.tsx`:
- Line 989: The current call setDirty(added > 0 || dirty) uses the captured
dirty value and can suffer from a stale-closure race; change it to use the
functional updater form of the state setter (i.e., pass a function that receives
the previous dirty value and returns added > 0 || previous) so the update always
composes with any pending state changes—update the code around the setDirty call
in the handler that references added and dirty (look for the setDirty call) to
use the prev-state functional pattern.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 05058585-5fba-47fd-a5eb-1d8d69a410c3

📥 Commits

Reviewing files that changed from the base of the PR and between 888b2eb and 3bc7e9e.

📒 Files selected for processing (19)
  • internal/api/handlers/flow.go
  • internal/api/handlers/plugins.go
  • internal/api/handlers/topology.go
  • internal/api/server.go
  • internal/entity/kinds.go
  • internal/entity/schemas/flow.json
  • internal/plugins/bundled/registry.json
  • web/src/App.tsx
  • web/src/components/CommandPalette.tsx
  • web/src/components/EntityCard.tsx
  • web/src/components/FlowTab.tsx
  • web/src/components/Sidebar.tsx
  • web/src/lib/api.ts
  • web/src/lib/types.ts
  • web/src/pages/Catalog.tsx
  • web/src/pages/Dashboard.tsx
  • web/src/pages/EntityDetail.tsx
  • web/src/pages/Flow.tsx
  • web/src/pages/Plugins.tsx

Comment thread internal/api/handlers/flow.go
Comment on lines +194 to +203
if name == "flow" {
role, _ := merged["editorRole"].(string)
role = strings.TrimSpace(role)
if role == "" {
merged["editorRole"] = "developer"
} else if !auth.IsValidRole(role) {
writeError(w, http.StatusBadRequest, "invalid flow editor role")
return
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Persist the normalized Flow editor role.

A value like " developer " is validated as developer but saved with whitespace, which can break downstream role checks. Store the trimmed value after validation.

🐛 Proposed fix
 	if name == "flow" {
 		role, _ := merged["editorRole"].(string)
 		role = strings.TrimSpace(role)
 		if role == "" {
 			merged["editorRole"] = "developer"
 		} else if !auth.IsValidRole(role) {
 			writeError(w, http.StatusBadRequest, "invalid flow editor role")
 			return
+		} else {
+			merged["editorRole"] = role
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/handlers/plugins.go` around lines 194 - 203, The Flow editor
role is being validated after trimming but the trimmed value isn't written back,
so whitespace like " developer " passes validation but is stored with spaces; in
the name == "flow" block update merged["editorRole"] to the trimmed role (after
computing role := strings.TrimSpace(...)), ensure you set merged["editorRole"] =
"developer" when role == "" and otherwise, after auth.IsValidRole(role) returns
true, persist merged["editorRole"] = role; use the merged map and
auth.IsValidRole references to locate the change.

Comment thread internal/entity/schemas/flow.json Outdated
Comment thread internal/plugins/bundled/registry.json Outdated
Comment thread web/src/components/EntityCard.tsx Outdated
Comment thread web/src/lib/api.ts
Comment thread web/src/pages/Catalog.tsx Outdated
Comment thread web/src/pages/Flow.tsx Outdated
Comment thread web/src/pages/Flow.tsx Outdated
Comment thread web/src/pages/Flow.tsx Outdated
@Go2Engle Go2Engle merged commit 42af76d into main Apr 20, 2026
1 check passed
@Go2Engle Go2Engle deleted the feature/add-flow-diagram-plugin branch April 20, 2026 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant