Skip to content

Implement Flows as first-class entities and same-Canvas baseline routing (Slices 1–2)#43

Merged
CuriouslyCory merged 3 commits into
mainfrom
feature/feat/flows-first-class
May 30, 2026
Merged

Implement Flows as first-class entities and same-Canvas baseline routing (Slices 1–2)#43
CuriouslyCory merged 3 commits into
mainfrom
feature/feat/flows-first-class

Conversation

@CuriouslyCory

@CuriouslyCory CuriouslyCory commented May 30, 2026

Copy link
Copy Markdown
Owner

Summary

Ships Slices 1 and 2 of the flow-routed-connections master plan (issue #2), establishing Flows as first-class Component-owned entities and implementing same-Canvas baseline routing via FlowRoute.

  • Flow model: first-class row owned by a Component; carries kind, key (unique per owner), title, polarity, signature, sourceSpecId (derived vs. user-authored). Individually addressable, soft-deletable, MCP-resolvable.
  • FlowSpec model: 1:1 contract per Component; OpenAPI parser implemented; non-destructive re-parse preserves matching keys and soft-deletes dropped keys with fresh deletionId per batch; source is UNTRUSTED with bounded loader (1 MB cap, 32 depth, 500 ops).
  • FlowRoute model: same-Canvas binding of Flow to Edge; (outerEdgeId, flowId) de-dupe via partial unique index; service-enforced touches-endpoint invariant (Flow owner is an endpoint of the outer Edge).
  • Service layer: attachFlowSpec, addFlow, updateFlow, deleteFlow, routeFlow, unrouteFlow; deleteNode cascade extended to owned Flows + FlowSpec; deleteEdge mints deletionId when sweeping FlowRoutes, symmetrically restored by new restoreEdge.
  • UI: Component-detail side panel with spec paste field and read-only flow palette; "+ flow" popover on selected Connections, listing routed and unrouted Flows from either endpoint; "N flows" pill on Component body; "N / M routed" pill on Connection body.
  • getCanvas extended: returns edgeFlows aggregation per interior Edge: { edgeId, total, routed, unrouted, orphan, byKind } powering the pills and popover.
  • Documentation: ADR-0011 justifies Flow as first-class and captures polarity, spec sourcing, and re-parse decisions; CONTEXT.md flows and domain glossary updated; flow-routed plan marked Slices 1–2 complete, open questions resolved.

Testing

  • Vitest suites at service seam:
    • flow.service.test.ts (528 lines): attachFlowSpec (with OpenAPI parse + non-destructive re-parse), addFlow, updateFlow, deleteFlow, cascade arms in deleteNode, concurrency regression for idx_flow_dedup partial unique index
    • flow-parser.test.ts (207 lines): OpenAPI walker, operation extraction, error handling (OOM, depth/size caps, malformed specs)
    • flow-route.service.test.ts (573 lines): routeFlow, unrouteFlow, polarity-vs-endpoint validation (touched endpoint only), orphan handling, deleteEdge cascade with restoreEdge symmetry, concurrency regression for idx_flow_route_dedup
    • node.service.test.ts expanded: Flow + FlowRoute sweep in deleteNode cascade, pre-checks in restoreNode for dedup collisions
  • E2E verification: UI spec paste, Flow palette render, popover affordance on selected Connection, pills (N flows, N / M routed), Escape key dismiss, UTF-8 handling in spec source
  • Edge cases verified:
    • Re-parse preserves hand-authored Flows (sourceSpecId IS NULL)
    • Soft-deleted Flow orphans its FlowRoute visibly (deleted Flow linked from a route)
    • Concurrent attachFlowSpec on the same Component fails with ConflictError (named pattern per ADR-0010)
    • Undo (restoreNode / restoreEdge) restores exact deletion set keyed by deletionId
    • OpenAPI with $ref, webhooks, callbacks intentionally not extracted (security boundary)

Notes

  • MCP tools split to follow-up issue (Authenticated MCP route + read resources + llms.txt #18 auth + MCP write tools #19 MCP tools) so the schema + service + UI can ship without blocking on the MCP route.
  • Slice 3 (cross-scope routing) remains plan-only — gated check that routeFlow to an inner Edge is authorized only by that inner Canvas owner (ADR-0012 forthcoming).
  • Open questions from the master plan (items 1–7) are resolved and tracked in ADR-0011 and docs/plans/flow-routed-connections.md.

Summary by CodeRabbit

  • New Features

    • Flow routing on the canvas: route/unroute flows to connections with per-connection routed/unrouted counts shown.
    • A contextual "+ flow" affordance lets owners assign flows from a selected connection.
    • Deletion/restore now preserves and restores routed-flow state so cascaded deletes/undo behave atomically.
  • Documentation

    • Updated docs describing flow routing, deletion semantics, and canvas aggregation visibility.

Review Change Stack

- Implement FlowRoute schema, routeFlow/unrouteFlow service ops, and getRoutedFlowIdsForEdge query for same-Canvas flow-to-connection binding
- Add getCanvas.edgeFlows aggregation (total/routed/unrouted/orphan counts per edge) and surface via routed-count pill on Connection body
- Wire "+ flow" popover on selected Connection to list and route unrouted Flows from either endpoint
- Extend deleteEdge to mint deletionId and cascade-sweep incident FlowRoutes; add restoreEdge symmetry for batch undo
- Extend deleteNode cascade to pre-check idx_flow_route_dedup before restore
- Update CONTEXT.md Flow/FlowRoute/getCanvas/Deletion id entries; amend ADR-0008 for deleteEdge cascade; ship Slice 2 in flow-routed-connections plan
@vercel

vercel Bot commented May 30, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
infinite-docs Ready Ready Preview, Comment May 30, 2026 2:59am

Request Review

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b754a477-0583-4d85-b769-107b7b0365ab

📥 Commits

Reviewing files that changed from the base of the PR and between db0a003 and 1bc145c.

📒 Files selected for processing (14)
  • CONTEXT.md
  • docs/adr/0008-cascading-soft-delete-stamped-batch.md
  • docs/adr/0014-deleteedge-restoreedge-cascade.md
  • docs/plans/flow-routed-connections.md
  • src/app/p/[slug]/_canvas/canvas.tsx
  • src/app/p/[slug]/_canvas/component-node.tsx
  • src/app/p/[slug]/_canvas/connection-edge.tsx
  • src/app/p/[slug]/_canvas/route-flow-popover.tsx
  • src/lib/schemas.ts
  • src/server/api/routers/architecture.ts
  • src/server/architecture/__tests__/flow-route.service.test.ts
  • src/server/architecture/__tests__/node.service.test.ts
  • src/server/architecture/edge.service.ts
  • src/server/architecture/node.service.ts

📝 Walkthrough

Walkthrough

This PR implements Slice 2 of flow-routed-connections, adding the ability to route Flow objects onto Connections (Edges) and displaying routed-flow counts plus an affordance to assign more flows. It introduces a FlowRoute schema, routing service operations, cascading soft-delete/restoration mechanics that thread FlowRoute rows through the deletion undo model, a canvas aggregation layer computing per-edge flow counts, and frontend UI components (routed pill, "+ flow" popover) with optimistic updates.

Flow-Routed Connections Slice 2

Layer / File(s) Summary
Documentation Updates
CONTEXT.md, docs/adr/0008-cascading-soft-delete-stamped-batch.md, docs/plans/flow-routed-connections.md, docs/adr/0014-deleteedge-restoreedge-cascade.md
Updated glossary, ADR status, and plan status to document Slice 2 shipped scope: Connection routed-count affordances, getCanvas.edgeFlows aggregation, FlowRoute soft-delete cascades with deletionId stamping.
FlowRoute Data Model & Migration
prisma/migrations/20260530004633_add_flow_route/migration.sql, prisma/schema.prisma
Adds FlowRoute table with projectId, flowId, outerEdgeId, innerEdgeId (optional), soft-delete fields (deletedAt, deletionId), partial unique dedupe index (outerEdgeId, flowId) WHERE deletedAt IS NULL, and relations into Project, Flow, and Edge Prisma models.
Prisma error helpers
src/server/architecture/prisma-errors.ts
Adds isFlowRouteDedupCollision and helper to detect unique-violation collisions for the FlowRoute dedupe index.
Flow Routing Schemas & Service
src/lib/schemas.ts, src/server/architecture/flow-route.service.ts, src/server/architecture/errors.ts
Adds Zod input schemas and types; implements routeFlow (validation, ownership, endpoint check, dedupe -> ConflictError), unrouteFlow (soft-delete), and getRoutedFlowIdsForEdge (capability-slug read); extends ConflictErrorDetails with conflictingFlowRouteIds.
Edge delete/restore cascade
src/server/architecture/edge.service.ts
deleteEdge now sweeps incident FlowRoutes and stamps deletionId when any are swept (lone-delete returns deletionId: null); restoreEdge revives stamped edges and FlowRoutes with dedup pre-checks and conflict mapping.
Node service / getCanvas edgeFlows
src/server/architecture/node.service.ts
Adds EdgeFlowsEntry; getCanvas runs raw SQL aggregations to compute per-edge totals (total/routed/unrouted-orphan and byKind), merges zero-filled results into edgeFlows; deleteNode/restoreNode sweep/restore FlowRoutes and return flowRouteIds.
TRPC Router & transactional wiring
src/server/api/routers/architecture.ts
Wires routeFlow/unrouteFlow (protected) and getRoutedFlowIdsForEdge (public) procedures; wraps deleteEdge/restoreEdge in ctx.db.$transaction(...).
Canvas enrichment & optimistic routing
src/app/p/[slug]/_canvas/canvas.tsx
Adds withEdgeFlows to enrich edges with edgeFlows and endpoints, seeds interiorEdges then computes enrichedEdges, patches cold cache shape to include edgeFlows, and implements optimistic commitRouteFlow/commitUnrouteFlow with rollback and cache invalidation.
Connection Edge UI & Route Popover
src/app/p/[slug]/_canvas/connection-edge.tsx, src/app/p/[slug]/_canvas/route-flow-popover.tsx
Extends ConnectionEdgeData with edgeFlows and endpoints, adds RouteFlowAction/RouteFlowContext, shows routed-count pill and conditional owner-only "+ flow" button, and adds RouteFlowPopover with Suspense-backed UnroutedFlowList and FlowGroup UI.
Tests & test DB
src/server/architecture/__tests__/flow-route.service.test.ts, src/server/architecture/__tests__/edge.service.test.ts, src/server/architecture/__tests__/helpers/test-db.ts, src/server/architecture/__tests__/node.service.test.ts
Adds extensive tests for route/unroute, deleteEdge/restoreEdge cascades and carve-out, getCanvas.edgeFlows aggregation, deleteNode/restoreNode FlowRoute arms, capability-slug read behavior; updates test DB reset and some test transaction wrapping.
Minor UI tweak
src/app/p/[slug]/_canvas/component-node.tsx
Tailwind className tweaks for Handle elements (no behavior change).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 A rabbit's ode to flow routes on connections true,
Where edges now carry counts of flows passing through,
Soft-stamped and restored in cascading grace,
With popover blooms letting flows find their place. 🌸

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main implementation objective: introducing Flows as first-class entities with same-Canvas baseline routing across Slices 1–2. It is specific, concise, and clearly conveys the primary change.
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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/feat/flows-first-class

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

@CuriouslyCory

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@src/app/p/`[slug]/_canvas/canvas.tsx:
- Around line 817-899: The rollback currently replaces the whole edgeFlows entry
with prevEdgeFlows in commitRouteFlow and commitUnrouteFlow, which can clobber
overlapping optimistic updates; instead compute and store the exact optimistic
delta you applied (e.g. for commitRouteFlow: routed +=1, unrouted -=1; for
commitUnrouteFlow: routed -=1, unrouted +=1) when calling patchCanvas and on
failure apply an inverse delta patch that adjusts only the numeric fields (using
Math.max(0, ...)) rather than restoring prevEdgeFlows wholesale; additionally,
when applying the inverse delta, reconcile by checking current values (from
utils.architecture.getCanvas.getData(canvasInput) or the patch callback’s
current state) to ensure you only revert if the current counts still include
your optimistic change so you don’t overwrite newer successful updates.
- Line 1013: Update the Tailwind v3-style important modifiers used in the Canvas
panel's className by converting the prefixed form "!top-0 !right-0 !bottom-0
!m-0 flex" to the Tailwind v4 suffix form "top-0! right-0! bottom-0! m-0! flex";
locate the JSX element that contains the className string (search for the exact
"!top-0 !right-0 !bottom-0 !m-0 flex" text) and replace each prefixed utility
with the corresponding trailing-! variant so Tailwind v4 applies the important
flag correctly.

In `@src/app/p/`[slug]/_canvas/connection-edge.tsx:
- Around line 147-153: The "+ flow" button is currently shown whenever canEdit
and hasUnrouted are true, but it must only appear for the currently selected
edge; update the showFlowButton computation to also require the edge selection
check used elsewhere (e.g., ensure selectedEdgeId === d.id or d.isSelected) so
the control appears only on the selected edge; apply the same selection gating
to the identical logic region around the 245-265 block so both places use the
selection-aware condition (referencing flows, hasUnrouted, showFlowButton and
the file's selection identifier).
🪄 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: 68e76734-9a79-4782-9b40-6820c2d22bb7

📥 Commits

Reviewing files that changed from the base of the PR and between 47ec0a4 and db0a003.

📒 Files selected for processing (18)
  • CONTEXT.md
  • docs/adr/0008-cascading-soft-delete-stamped-batch.md
  • docs/plans/flow-routed-connections.md
  • prisma/migrations/20260530004633_add_flow_route/migration.sql
  • prisma/schema.prisma
  • src/app/p/[slug]/_canvas/canvas.tsx
  • src/app/p/[slug]/_canvas/connection-edge.tsx
  • src/app/p/[slug]/_canvas/route-flow-popover.tsx
  • src/lib/schemas.ts
  • src/server/api/routers/architecture.ts
  • src/server/architecture/__tests__/edge.service.test.ts
  • src/server/architecture/__tests__/flow-route.service.test.ts
  • src/server/architecture/__tests__/helpers/test-db.ts
  • src/server/architecture/edge.service.ts
  • src/server/architecture/errors.ts
  • src/server/architecture/flow-route.service.ts
  • src/server/architecture/node.service.ts
  • src/server/architecture/prisma-errors.ts

Comment thread src/app/p/[slug]/_canvas/canvas.tsx
Comment thread src/app/p/[slug]/_canvas/canvas.tsx Outdated
Comment thread src/app/p/[slug]/_canvas/connection-edge.tsx
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