Files
VolcanicCore/docs/superpowers/followups.md

4.2 KiB

Cross-Plan Follow-ups

Items surfaced during review of one plan that belong to a later plan. Prevents silent drops.

Deferred to Plan 7 (CI + observability + hardening)

Originally scoped as Plan 5, then re-deferred to Plan 6 when Plan 5 became the N8N Node Editor Dialog and Plan 6 became Pinned Node Data. These items now go to Plan 7.

  • CI pipeline. There is no automated CI yet. Add a workflow (Gitea Actions if the repo is hosted on Gitea, otherwise GitHub Actions) that runs dotnet build, dotnet test, pnpm --dir frontend test, pnpm --dir frontend build, and the Playwright smoke on push to main. The Playwright job needs pnpm exec playwright install --with-deps chromium before pnpm --dir frontend test:e2e. Bonus: build + push the Docker image on tag pushes.
  • Persist ASP.NET Core DataProtection keys under /data. The Plan-4 Dockerfile smoke run showed the default DataProtection key ring is written to /root/.aspnet/DataProtection-Keys inside the container — ephemeral. On container replacement (redeploy, OOM restart, host reboot) every issued cookie is invalidated and every logged-in user is silently kicked out. Fix in Plan 7: wire AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(Path.Combine(settings.DataDirectory, "dp-keys"))) in Program.cs and cover with an xUnit test that verifies the directory is created on first boot.

Deferred from Plan 6 (Pinned Node Data)

  • Skip upstream execution when downstream has a pin. Currently upstream ancestors of a pinned node still run and their output is discarded. Would need dependency analysis + a "no successors need my output" pass.
  • Pin both input AND output on the same action node. Action nodes only expose the input editor; output-pin on action nodes would let operators "canned-response" a node during test runs.
  • Multi-port pinning. Only port 0 today.
  • Pin sharing / templates. Copy-pin-between-nodes UI.
  • Diff indicator in the dialog: show "what this node WOULD have received" vs. "what the pin says it will receive".
  • Backend index/column for querying "workflows with pinned data." Currently a stale pin on a live workflow can only be found by opening it in the editor.

Deferred from Plan 5 (Node Editor Dialog)

  • Webhook stand-by mode. Trigger option where an active workflow pauses on the webhook node and only continues when a matching HTTP request arrives, instead of running through the first request. Needs pause/resume semantics in Executor; separate spec.
  • Drag-and-drop insertion from JsonTree to ExpressionField. Currently only click-to-insert at caret is supported.
  • Multi-color / semantic highlighting inside {…} (property vs bracket vs literal). Single amber color ships in Plan 5.
  • Cross-node expressions like {nodes.<id>.output.body} and {nodes.<id>.output[0].json.body}. Requires the executor to expose a scoped-view of run state to TemplateEngine.
  • JsonTree accessibility. Add role="tree"/role="treeitem" + aria-expanded/aria-level on branch buttons so screen readers can navigate the structure. MVP ships without these; usable for sighted operators only.
  • msw module alias cleanup. frontend/src/testing/msw.ts exports both server (new) and mswServer (legacy). Four existing test files still use mswServer. Migrate them and drop the alias so there's one canonical name.
  • WebhookUrlHint setTimeout leak on unmount. The 1500ms setCopied(false) fires even if the dialog closes mid-window. Harmless in React 18 but a lingering timer. Guard with a ref or useEffect cleanup.
  • useMemo around normalizePorts in NodeEditorDialog. Runs every render, allocating fresh Port[] arrays; blocks downstream React.memo on PortsColumn. Cheap-per-run but wasteful.
  • Tab-wrap focus-trap test. Implementation is in place; jsdom doesn't simulate real browser tab-order so it's not unit-tested. Add a Playwright smoke assertion if the behavior ever regresses in practice.
  • Preview numeric-precision drift. frontend/src/expr/templateEngine.ts renders JS numbers via String(v), which loses fidelity vs the backend's GetRawText() for over-precision or non-normalized JSON (e.g., 1.50, 9007199254740993). Documented in the header comment; would need JSON source-text preservation to fix.