docs: plan 6 wrap-up — status, invariants, followups re-numbered

This commit is contained in:
Claude
2026-08-30 14:50:49 +00:00
parent 6a820bb7fa
commit ac2ccf3b64
2 changed files with 29 additions and 5 deletions

View File

@@ -2,12 +2,21 @@
Items surfaced during review of one plan that belong to a later plan. Prevents silent drops.
## Deferred to Plan 6 (CI + observability + hardening)
## Deferred to Plan 7 (CI + observability + hardening)
Originally scoped as Plan 5, but Plan 5 was reassigned to the N8N-style Node Editor Dialog. These items now go to Plan 6.
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 6: 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.
- **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)
@@ -15,7 +24,6 @@ Originally scoped as Plan 5, but Plan 5 was reassigned to the N8N-style Node Edi
- **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`.
- **Pinned input data** (n8n's "pin this data on a node") — override the input the dialog uses for previews and the executor uses for that node.
- **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.