docs(library-decisions): trace @xyflow/react for the editor board
Pre-approve the ADR-022 library trace for the React Flow board substrate (ADR-028/029) so walking-skeleton implementers of packages/editor do not stall on the library-policy pre-commit hook. Trace only — the package is not installed by this commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
This commit is contained in:
109
docs/library-decisions/2026-07-12-@xyflow/react.md
Normal file
109
docs/library-decisions/2026-07-12-@xyflow/react.md
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
---
|
||||||
|
package: "@xyflow/react"
|
||||||
|
version: "^12.0.0"
|
||||||
|
tier: feature
|
||||||
|
decision: approved
|
||||||
|
date: 2026-07-12
|
||||||
|
deciders: [implementer-agent]
|
||||||
|
adr: null
|
||||||
|
lastRevalidated: null
|
||||||
|
is-sub-processor: false
|
||||||
|
processes-pii: false
|
||||||
|
filter-results:
|
||||||
|
license: MIT
|
||||||
|
types: native
|
||||||
|
maintenance: active
|
||||||
|
boundary-fit: pass
|
||||||
|
shadow-check: pass
|
||||||
|
eu-residency: n/a
|
||||||
|
cve-scan: clean
|
||||||
|
named-consumer: pass
|
||||||
|
socketRisk: clean
|
||||||
|
verification-commands:
|
||||||
|
- "npm info @xyflow/react license"
|
||||||
|
- "npm info @xyflow/react types"
|
||||||
|
- 'cat package.json | grep -E ''"(zod|inversify|payload|@trpc/server|superjson|reflect-metadata)"'''
|
||||||
|
- "npm info @xyflow/react time.modified"
|
||||||
|
- "npm info @xyflow/react time --json | tail -5"
|
||||||
|
- "npm info @xyflow/react dependencies --json"
|
||||||
|
- "pnpm audit --audit-level=moderate 2>&1 | head -40"
|
||||||
|
- "curl -s 'https://api.github.com/advisories?affects=%40xyflow%2Freact&per_page=10'"
|
||||||
|
accepted-cves: []
|
||||||
|
---
|
||||||
|
|
||||||
|
## Filter: license
|
||||||
|
|
||||||
|
<!-- Result: MIT -->
|
||||||
|
|
||||||
|
`npm info @xyflow/react license` returns `MIT`. The GitHub repository (`xyflow/xyflow`) confirms `spdx_id: MIT`. Within the allowlist.
|
||||||
|
|
||||||
|
## Filter: types
|
||||||
|
|
||||||
|
<!-- Result: native -->
|
||||||
|
|
||||||
|
Authored in TypeScript; the published manifest declares `"types": "dist/esm/index.d.ts"`. No separate `@types/` package is needed.
|
||||||
|
|
||||||
|
## Filter: shadow-check
|
||||||
|
|
||||||
|
<!-- Result: pass -->
|
||||||
|
|
||||||
|
`@xyflow/react` (React Flow) is a node-based canvas/board component library. It does not duplicate any locked must-have (zod, inversify, payload, @trpc/server, superjson, reflect-metadata — root `package.json` grep matches only `zod`), and no other canvas or node-graph library exists in the workspace. Pass.
|
||||||
|
|
||||||
|
## Filter: boundary-fit
|
||||||
|
|
||||||
|
<!-- Result: pass -->
|
||||||
|
|
||||||
|
Target is `packages/editor` (feature tier — the ADR-029 editor rebuild, seeded by the walking-skeleton PRD). `@xyflow/react` is a pure client-side React component library: it imports no `@sentry/*` or `@opentelemetry/sdk-*` modules (ADR-017 §4 unaffected), crosses no feature boundaries, and its transitive imports (`classcat`, an internal `zustand@^4` store, `@xyflow/system` with the d3-drag/d3-zoom/d3-selection/d3-interpolate interaction modules) are all in-process UI libraries. ADR-006, ADR-010, ADR-017 all pass.
|
||||||
|
|
||||||
|
## Filter: maintenance
|
||||||
|
|
||||||
|
<!-- Result: active -->
|
||||||
|
|
||||||
|
Latest release `12.11.2` published `2026-07-06T12:42:54.957Z` — six days before this trace. Release cadence is roughly monthly on the 12.x line (`12.10.0` 2025-12-04, `12.10.1` 2026-02-19, `12.10.2` 2026-03-27, `12.11.0` 2026-06-01, `12.11.2` 2026-07-06). The `xyflow/xyflow` monorepo was last pushed `2026-07-09`, has ~37.6k stars and 127 open issues, and is commercially backed by xyflow GmbH. ~6.7M npm downloads/week. Active.
|
||||||
|
|
||||||
|
## Filter: eu-residency
|
||||||
|
|
||||||
|
<!-- Result: n/a -->
|
||||||
|
|
||||||
|
Pure in-browser rendering/interaction library. No vendor-controlled endpoints, no telemetry, no data transmission of any kind (React Flow Pro is a separate subscription for examples/support; the OSS package makes no network calls). Not applicable.
|
||||||
|
|
||||||
|
## Filter: cve-scan
|
||||||
|
|
||||||
|
<!-- Result: clean -->
|
||||||
|
|
||||||
|
The GitHub Advisory Database reports zero advisories for `@xyflow/react`, `@xyflow/system`, `classcat`, and `zustand`. One transitive note: `d3-interpolate` depends on `d3-color@1 - 3`, which was historically affected by GHSA-36jr-mh4h-2g58 (ReDoS, patched `>=3.1.0`); the range resolves to `3.1.0` today, so fresh installs receive the patched version. `pnpm audit --audit-level=moderate` at the workspace root surfaces only pre-existing advisories in dev tooling (`vitest` via `@stryker-mutator/vitest-runner`, `shell-quote` via `concurrently`) — none related to this package. Clean relative to this adoption.
|
||||||
|
|
||||||
|
## Filter: named-consumer
|
||||||
|
|
||||||
|
<!-- Result: pass -->
|
||||||
|
|
||||||
|
`packages/editor` — the walking-skeleton PRD (`docs/work/prds/walking-skeleton.prd.md`) specifies "React Flow board shell, one iframe frame node, canvas-protocol client (selection round-trip), minimal zustand store" as the first code of the ADR-029 editor rebuild. ADR-028 mandates the board architecture by construction ("React Flow frames containing live iframes"), and the platform-retrofit PRD explicitly batches this trace so walking-skeleton implementers do not stall on the ADR-022 pre-commit hook. The consumer is a scheduled, named package blocked today — not hypothetical.
|
||||||
|
|
||||||
|
## Filter: socketRisk
|
||||||
|
|
||||||
|
<!-- Result: clean -->
|
||||||
|
|
||||||
|
The official Socket CLI requires an organization API token (`socket package score` fails with "requires a Socket API token"), which is unavailable in this environment, and socket.dev package pages are bot-gated (HTTP 403). Manual supply-chain audit performed instead.
|
||||||
|
|
||||||
|
`@xyflow/react@12.11.2` runtime dependencies:
|
||||||
|
|
||||||
|
- `classcat@^5.0.3` — zero-dependency classnames utility (Jorge Bucaran), MIT
|
||||||
|
- `zustand@^4.4.0` — React Flow's internal store (Poimandres), zero-dependency apart from `use-sync-external-store`
|
||||||
|
- `@xyflow/system@0.0.79` — same monorepo/publisher; depends on `d3-drag`, `d3-zoom`, `d3-selection`, `d3-interpolate` (Mike Bostock's D3 interaction modules) plus their `@types/*` packages
|
||||||
|
|
||||||
|
No `preinstall`/`postinstall` lifecycle scripts anywhere on the runtime path (`classcat`'s `prepare` script runs only from a git checkout, not from the registry tarball). No network access, no obfuscation. Publisher xyflow GmbH has maintained the package continuously since the react-flow v9 era. Supply-chain risk assessed as clean.
|
||||||
|
|
||||||
|
## Prompt: replaces
|
||||||
|
|
||||||
|
Nothing in the workspace is retired — no canvas or board library exists in the monorepo today. The founder's editor prototype (outside the repo, in the product bundle) already validated React Flow as the board substrate; ADR-029 rebuilds the editor under template conventions rather than vendoring it, so this adoption carries the prototype's proven substrate forward. What it displaces is the alternative of a hand-built pan/zoom/drag canvas — ADR-028 explicitly retires the prototype's hand-built `NodeRenderer` approach in favor of React Flow frames hosting live iframes.
|
||||||
|
|
||||||
|
## Prompt: migration-cost-out
|
||||||
|
|
||||||
|
**Hard.** The board shell, frame nodes, viewport interactions, selection model, and canvas-protocol client will be written against React Flow's node/edge/viewport APIs, and the editor store's registry mirrors React Flow's coordinate model. Swapping the canvas engine at month 18 means rewriting `packages/editor`'s board and interaction layer. Two containments keep it short of impossible: ADR-029's explicit view-model mapping layer keeps DesignDoc v1 (the persisted contract) independent of React Flow types, so no persisted data is coupled; and the dependency is confined to `packages/editor` — no other feature imports it. No vendor lock-in, no protocol coupling.
|
||||||
|
|
||||||
|
## Prompt: alternatives-considered
|
||||||
|
|
||||||
|
1. **tldraw SDK** — purpose-built infinite-canvas SDK with excellent interaction polish. Auto-reject on filter 1: distributed under the tldraw license (watermark requirement or paid business license), outside the ADR-022 SPDX allowlist.
|
||||||
|
2. **Hand-built canvas** (inherit the prototype's `NodeRenderer` + custom pan/zoom) — ADR-028 names selection, hover, drag, hit-testing, and measurement across an origin boundary as "the hardest UI-architecture problem in the product"; rebuilding those primitives by hand duplicates years of React Flow's battle-testing for zero product differentiation, and ADR-028 already retires `NodeRenderer` from the board path.
|
||||||
|
3. **react-konva / WebGL renderers** — canvas-2D/WebGL scene graphs cannot host live DOM iframes inside frames, which ADR-028's iframe canvas requires by construction. Architecturally disqualified.
|
||||||
|
4. **reaflow** — React node-graph alternative, but ELK-auto-layout-centric with a far smaller community; wrong fit for a free-form design board with user-positioned frames.
|
||||||
Reference in New Issue
Block a user