Repository navigation
Import React Studio with original history and provenance checks - #8924
Conversation
A component-based web studio for Elsa Workflows 3.x, built with Next.js, React, TypeScript, Tailwind CSS, shadcn/ui and React Flow. Core modules are always on: dashboard, workflow definitions (list and visual editor) and workflow instances. Every other module is enabled per deployment through configuration and hidden when the backend lacks the matching feature: environments, labels, secrets, security, alterations, user tasks, settings, appearance, console logs and structured logs. The designer supports flowchart, sequence and state machine containers, a quick-add palette, live validation, data-flow overlays, a call-context view of the workflow hierarchy, and keyboard-driven editing.
Replaces the single README with a landing page carrying screenshots of the designer, dashboard, call context, instance viewer, human tasks and secrets, plus six guides under docs/: - getting-started: prerequisites, install, connecting to a server - configuration: adding servers, auth providers, feature flags, theming, environment variables and their precedence - modules: what each module does, the server feature it needs, and how to build and register a new one - designer: containers, quick add, data flow, call context, shortcuts - deployment: Docker, standalone output, reverse proxies - troubleshooting: CORS, hidden modules, sign-in failures, definitions from older Elsa versions
The secret forms hardcoded a single "Configuration key" input, shown whenever a store was read-only or could not be written to. That rule only ever described the configuration store, so a vault-backed store -- which needs its own coordinates, and in managed mode a value as well -- had no usable form. Stores now declare their fields, so the create dialog, the rotate dialog and the inline rotation card render whatever a store asks for and submit it as secret metadata. Whether a value editor appears comes from the store's requiresValue rather than being inferred from its capabilities. Servers predating the descriptor change keep working: storeFields synthesizes the configuration store's field, storeRequiresValue falls back to the old capability rule, and the configuration key is still sent as its own request property alongside the metadata. The detail page's Properties card now also shows where a secret lives, from the store-declared metadata the detail endpoint returns. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The create dialog told every operator their value would be "stored encrypted", and the value field repeated it. That is only true of the encrypted store: a vault-backed value goes to the vault and Elsa keeps nothing, and a reference store captures no value at all. The copy now comes from the store: the dialog says whether a value is being submitted or a reference recorded, and the value field names where the value is written. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A JSON secret whose value does not parse is rejected by the server, which means a failed round trip and a toast. The value field now parses it as you type when the type's editor hint says JSON, shows the parser's own message under the field, and keeps the submit button disabled until it parses. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The activity chart had columns filling their whole slot, so 24 hourly buckets read as one blocky stepped band rather than as bars; the axis labelled a count scale "8.5"; gridlines were dashed; and the started series was drawn as disconnected per-column dashes that looked like stray marks. Columns are now capped at 24px and centred in their slot, stacked segments are separated by a consistent 2px of surface with a 4px cap on top and a square foot on the baseline, gridlines are solid hairlines on whole-number ticks, and the axis tops out on a tick so the tallest column ends at a gridline. Started became a soft area wash behind the columns: as a stroked outline it traced a box around the plot and read as a border. Hovering a quiet hour now says "No activity" instead of listing five zeros. Cards no longer grow with their row counts, which is what made the grid look ragged as workflows accumulated. The primary and activity zones have fixed row heights, lists scroll inside their cards, and the last widget in a stack absorbs the leftover height so both columns end on the same line. Below lg the rows stack and size to content as before. Instances per workflow used --primary for "finished / other" beside --status-info for "running": two sky blues measuring 9.8 apart, below the readable floor even with full colour vision. Those are states, not identities, so the bars now use the success / info / danger status tones, which pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three things made the chart look broken as soon as you pointed at it. Hovering any bucket faded every other column to 60%, so the whole chart washed out exactly while it was being read. The hovered slot is marked already; the dimming is gone. The hovered slot was marked with a full-height filled band, which in an empty hour rendered as a tall grey column indistinguishable from a bar -- it read as a spike in an hour with nothing in it. It is now a one-pixel crosshair. The tooltip was pinned to the left edge, where it covered the very columns it describes and the y-axis labels with them. It now parks on the side opposite the hovered slot, so it never covers what is being inspected and does not chase the cursor. Started also moves from neutral grey to the slate chart tone: at 10% of the foreground the envelope read as a loading skeleton rather than as data, especially in an hour where work started and nothing had finished yet. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Started and the coloured outcomes count different populations. A workflow that starts in one hour can finish in a later one, so an hour can record more outcomes than starts -- this server currently has a bucket with 11 started and 12 outcomes. Drawing the stack inside a "started" envelope claims a part-of-whole relationship that does not hold, and when it breaks the stack visibly overflows the container that is supposed to contain it. The chart is now the outcomes alone. Started keeps its per-bucket figure in the tooltip and its total in the header, where it reads as a separate number rather than as a container, and it carries no swatch because nothing in the plot corresponds to it. The axis scales to what is actually drawn and aims for about three intervals, so it no longer tops out far above the tallest column. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The journal API returns one record per lifecycle event, and the list rendered one row per record. The order-review sample has three activities and filled the panel with eight four-line rows: Start/Started, Start/Completed, ReviewOrder/Started, ReviewOrder/Suspended, and so on. Nesting was absent entirely -- "Hide system" dropped the workflow and flowchart rather than using them, so the structure the workflow actually had never appeared. A row is now one activity execution: status, name, and how long it took. The events that produced it are revealed on click, together with the type, the offset from the workflow start, per-event timestamps and the exception a faulted record carries in its payload. Three activities render as three rows. Hierarchy is rebuilt from nodeId, the colon-delimited path the server already sends (Workflow1:flowchart1:reviewOrder), preferring parentActivityInstanceId where a version supplies it. An activity that runs more than once gets one span per iteration, attached to the iteration of its parent that was open at the time, so a loop body does not collapse into a single row. Interaction follows what trace viewers have settled on: a chevron folds a subtree and shows a descendant count when closed, the row body selects the activity and opens its detail, arrow keys walk the tree, subtrees below depth 2 start folded, and expand/collapse-all appear only when there is nesting to act on. "Hide system" becomes "Hide containers" and now promotes the children instead of discarding the subtree. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A span's duration was wall-clock time, so a user task parked overnight for a human read as an overnight activity. In the order-review sample ReviewOrder showed 1h 49m; it ran for about a millisecond and waited for the rest. Ranking activities by that number finds whatever suspended, never whatever is slow. Spans now carry the time spent suspended, summed over every Suspended → Resumed pair that closed, and the duration column reports execution time with that taken out. A row shows the wait beside it in amber when there is one, so the elapsed time is still visible and still attributed. A suspension that has not resumed is not counted: the span has no end either, so there is nothing to subtract from. Containers inherit what their children waited on -- a flowchart whose only activity waited an hour did not work for an hour. Branches that suspend in parallel would double-count, so the inherited total is clamped to the span's own duration. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The span tree keys on activityInstanceId, falling back to nodeId, and rebuilds nesting by splitting nodeId on ':'. Both are declared required on the record type, but that is an assumption about the server rather than a guarantee, and neither path tolerated their absence. A record with an activityInstanceId but no nodeId threw: parentNodeId called lastIndexOf on undefined, which takes the whole instance viewer down, not just the journal. A record with neither keyed every event as `undefined`, folding the entire journal into a single row. Identity now falls through activityInstanceId → nodeId → activityId → record id, so the worst case is one span per event -- the flat list this replaced -- and nesting is skipped for spans with no path instead of crashing on one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…vider Feature/keyvault secret provider
Two problems with authoring branches. Switch cases could not hold anything. elsa-core's SwitchCase has a Label, a Condition and an Activity, but the studio only ever edited the first two: no port descriptor mentions cases, so listSlots never produced a slot for them. A Switch with three cases could run only its Default, and the case branches were unreachable from the designer. Cases now produce one slot each, named after the case label, ordered before Default -- so they accept any activity or container through the same path Then and Else already used. Filling a branch also did not read as the decision it is. Creating a workflow offers three flow types as cards with plain-language descriptions; filling an If's Then offered the same three buried in a searchable activity palette under the server's own type documentation. A branch slot now leads with that chooser and keeps the full palette one click behind it, for the single-activity case. Both places read from one list of flow types, so they cannot drift. Verified against a Switch with Gold and Silver cases: the card shows a slot per case, the chooser fills one with a Sequence and navigates into it, and the nested flow round-trips to the server inside cases[0].activity. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Let every branch start a nested flow, including Switch cases
|
Important Review skippedToo many files! This PR contains 353 files, which is 203 over the limit of 150. To get a review, reduce the PR to 150 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to Team to raise the limit. Usage-priced reviews support at most 300 files. ⚙️ Run configuration
⛔ Files ignored due to path filters: 17
📒 Files selected for processing: 353
You can disable this status message by setting the
Comment |
|
@greptileai Please review the current history-preserving import and provenance guard. |
|
@coderabbitai review |
|
[Medium impact] No blocking finding remains for the scoped immutable import mechanics; merge must preserve the recorded ancestry and exact donor subtree. SummaryImports the unchanged React Studio source into
Reviews (5) · Last reviewed commit: "Merge branch 'codex/8859-react-studio-mo..." · Reviewed by Greptile |
|
@greptileai Fixed both findings: boundary checks now disable rename detection, and real-Git regression cases cover changed imported files and an outside deletion represented as a rename. All eight cases and the actual import verifier pass. |
|
Both findings are resolved. The provenance boundary check now uses No further Greptile findings. |
…59-react-studio-import
|
@greptileai Please review integrated head e1c6db0 after the current-main merge. |
|
@coderabbitai review Current integrated head: e1c6db0 |
|
…59-react-studio-import
|
@greptileai Please review final integrated head 1a2936f. The latest main is incorporated and the addressed findings are verified and resolved. This PR intentionally preserves the immutable donor import and provenance; the opening/autosave defect in that historical snapshot is fixed in adaptation PR #8925 at e42edff, not by altering imported donor files. Please assess this PR's scoped provenance/import behavior; the resolved inline thread links the production correction and regression evidence. |
|
@coderabbitai review Please re-review final integrated head 1a2936f; verified fixes and latest main are included. |
|
|
@greptileai Please re-review immutable import mechanics at unchanged head 1a2936f. The newly reported Switch copied-branch IDs issue is now corrected in adaptation PR #8925 at f4a8442 and propagated through production tip5e841832a23fac5713fd95363a67648852385243. The resolved thread links exact source and eight passing clone/navigation regressions. This PR preserves the donor import and receipt exactly, so implementation fixes live in adaptation rather than rewriting provenance. Please evaluate this PR's scoped import mechanics with the production correction accounted for. |
|
User-authorized self-review for #8859. APPROVE + HIGH @ 1a2936f Reviewed the history-preserving import and its immutable merge/tree receipt, original 14-commit ancestry, source-tip cutoff, verifier/eight regression cases, documentation entrypoints and source-validation workflow. The original donor tree remains unchanged at the receipted import commit. No license grant is inferred or attribution rewritten. Nexxbiz clearance was explicitly waived by the task owner. The donor-baseline Switch-copy finding is fixed in the subsequent production adaptation #8925 at f4a8442; the original snapshot is deliberately preserved. The new regression proves copied branch/descendant IDs and node paths, internal connections and original lookup remain correct. The updated full adaptation passes 208 unit, 28 hosting and 49 browser tests. Current exact-head CI is green, Greptile is 5/5 and the exhaustive thread audit has zero unresolved findings. This is an author self-review under the task owner's explicit standing authority, not an independent approval. Merge uses the reviewed head and preserves donor ancestry, without squash/rebase or protection changes. Donor redirect/archive follows actual-main receipt verification and a final source-tip check. |
Part of #8859; implements the source-preservation portion of #8840 and updates the #8841 decision. Stacked on #8923.
Imports the complete React Studio snapshot into
studio/react/using a two-parent merge. The original 14 commit IDs remain ancestors, and the imported subtree exactly matches the donor root tree. Adaptation will follow separately so reviewers can distinguish source provenance from functional changes.Adds the source receipt, a retained provenance workflow, and eight real-Git regression cases. Records the task owner's removal of the employer-clearance gate and actual donor license status (no license file; no inferred MIT grant). Donor archival/redirect waits for independently reviewed merge and a final remote-tip check.
Validation: provenance verifier passed; eight regression cases passed; generated ADR index and
git diff --checkpassed. The unchanged donor baseline previously passed 74 Vitest tests, lint, type checking, production build, and browser sign-in/dashboard against the reference server. This PR does not claim the Vite port, production SDK, packaging or epic completion.Review: Greptile required; CodeRabbit is the sole advisory reviewer. Independent Elsa 3 Code Review
APPROVE + HIGH @ <full head SHA>and green CI remain required for merge.