Skip to content

Release v2.0.1#24

Merged
piotrblaszczyk merged 8 commits into
releasefrom
main
May 29, 2026
Merged

Release v2.0.1#24
piotrblaszczyk merged 8 commits into
releasefrom
main

Conversation

@piotrblaszczyk
Copy link
Copy Markdown
Contributor

No description provided.

kacpercierzniewski and others added 8 commits May 27, 2026 10:09
* refactor(sdk): remove the nodeids from handles

* refactor(sdk): remove nodeids usage

* refactor(sdk): add migration for old handles

* refactor(sdk): remove integration part


refactor(sdk): remove logs

* refactor(sdk): fix issue with overlapped inner handles

* refactor(sdk): finish cleanup of nodeId-from-handles refactor

- node-properties: remove debug console.log and silent-fallback nodeId guard;
  source nodeId from the node being edited rather than getStoreSingleSelected
- filterOutEdgesBySourceHandles: scope by sourceNodeId so deletions don't
  match cross-node innerIds; drop the redundant remove-edges-matching-pattern util
- ai-tools-control: drop dead getStoreSingleSelected guard (nodeId no longer used)
- ConnectableItem: drop unused PropsForHandleConfig variant; both consumers
  already pass handleId directly
- getHandleId: restore JSDoc updated for the new signature
- demo/multi-port-node-template: migrate missed getHandleId({ nodeId, ... }) callsites
- tests: cover getHandleId and filterOutEdgesBySourceHandles
- changeset: major bump documenting the breaking handle-id contract change

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(backend): add AuthPort seam for backend authn/authz

Introduces an AuthPort interface so consumers can plug their own auth
provider into the reference backend without forking HTTP routes. Ships
with AllowAllAuthPort as the permissive default (loud startup warning)
and a docs guide showing a JWT-based implementation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(backend): add AuthPort seam for backend

* chore: refresh DECISION-LOGS.md

* fix(backend): restore execute / snapshot-invalid log calls

The previous refactor dropped logger.info('execute requested') and
logger.warn('snapshot invalid') from the execute handler. Two effects:
ESLint flagged the `logger` import as unused, and operationally there
was no way to correlate a client execute request with the backend
executionId, or to surface invalid published snapshots in dashboards.
Restored at the same call sites as before.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(backend): tighten AuthPort seam — throw-based deny, opt-in default, route tests

- Replace `Authorize` (Response | null) with `assertAuthorized` that throws
  `AuthDeniedError`; `app.onError` in server.ts maps to 401/403. Removes the
  `if (denied) return denied` footgun: a handler that calls the assertion
  cannot accidentally let the next line run.
- Add optional `attributes` slot to per-row AuthResource kinds so future ABAC
  ports can receive loaded rows without a breaking change.
- Flip AllowAllAuthPort polarity: require explicit `WB_AUTH_PORT=allow-all`
  to construct, instead of "wide everywhere except NODE_ENV=production".
  Default-secure now means a forgotten env var fails loudly. .env(.example)
  ship the variable for local dev.
- Add routes/workflows.test.ts and routes/executions.test.ts pinning that
  every handler calls assertAuthorized with the correct action+resource,
  and that deny short-circuits before any DB or engine work.
- ADR refresh: SSE / EventSource caveats (cookie or short-lived query
  token), CORS gotchas for real ports, provider-specific JWT roles claim
  note, throw-based decision rationale.
- README: "No real authentication" first; the AllowAllAuthPort mention
  follows as the mechanism, not the headline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(execution-core): add safe-navigation syntax to template resolver

Two opt-in modifiers for missing references; plain {{x.y}} stays strict.

- {{x.y?}} resolves to '' when the reference is missing
- {{x.y | default:'value'}} resolves to the provided default
- Plain {{x.y}} continues to throw — explicit is better than implicit
- Malformed references like {{nodes.foo?bar}} (modifier mid-path) throw
  loudly rather than passing through literally into the resolved string;
  two-stage parse (outer "looks like a template" regex + inner grammar
  validator) surfaces typos that the previous single regex would have
  silently left in the LLM prompt or decision-node condition.

31 tests cover plain/safe/default forms, deep missing paths, mixed
templates, JSON-stringified non-strings, falsy-but-present bypass of
the modifier, and the new malformed-template error path.

Refs: WB-181

* feat(execution-core): better error handling

* refactor(execution-core): tighten template path regex and relocate error-chain walker

Move extractDeepestError (renamed from flattenErrorChain) out of graph-runner.ts
into errors.ts where NodeExecutionError lives - the runner no longer mixes
scheduling concerns with error-shape normalization.

Tighten PARSE_REGEX path-class from [^?|}\s]+? to [\w.-]+? so a typo with
':', '[', ',', '*' etc. throws Malformed template reference (syntax error)
instead of falling through to Unresolved template reference (missing data).
Different mental model, different fix.

Switch the regex to named capture groups, dropping the unsafe double cast.

Documentation: link AI Agent and Decision node pages to the Missing values
section of the variable-picker guide.
refactor(backend): wire N+1 SSE fix into the actually-used endpoint

The first pass at WB-186 introduced fetchEventsAfter + drainEventsSince
but only wired them into a new GET /:id handler. That endpoint isn't
called by the frontend — use-backend-execution.ts opens EventSource on
the streamUrl returned by POST /execute, which is /:id/stream. Result:
drainEventsSince was unit-tested and dead-pathed, while the hot SSE
endpoint kept the original full-history-fetch-then-filter pattern. The
N+1 bug was unchanged in production traffic. Helper-only tests masked
the drift because the route had no integration coverage.

This commit:

- Restores GET /:id as a JSON metadata endpoint (REST convention,
  reverses the accidental co-opting into SSE).
- Rewrites GET /:id/stream to use drainEventsSince + fetchEventsAfter
  for both the snapshot and live drains — one query shape across the
  route. Heartbeat + abort cleanup preserved.
- Drops the now-unused executionEvents Drizzle import the in-route
  query previously needed; the route reaches the table only through
  fetchEventsAfter.

Cleanups:

- drain-events.ts: EventWriter and DrainResult demoted from
  export type to module-local types. knip flagged them as unused
  exports; consumer code reaches them only by inference from
  drainEventsSince's signature.
- drain-events.test.ts: extract an inline fixedFetcher helper to
  satisfy unicorn/consistent-function-scoping.

The earlier deletion of fetch-events-after.test.ts is preserved — the
helper now carries zero testing scaffolding in its signature; SQL
coverage moves to a separate integration test path when wanted.

Refs: WB-186

* refactor(backend): extract SSE drain coordinator into a testable unit

The serialize-coalesce concurrency logic lived inline in the /:id/stream
route and could only be exercised by re-implementing it inside a test,
so the test guarded a copy rather than the shipped code. Extract it into
createSerializedDrainer and test the real function.

- serialized-drainer.ts: owns the concurrency policy (one drain at a
  time, coalesce a burst into a single follow-up pass, track done/stop).
  The route wires fetchEventsAfter + drainEventsSince through it.
- Close the snapshot->subscribe lost-wakeup window: a terminal event
  inserted between the snapshot read and subscribe fired its NOTIFY into
  the void and the stream hung in "running". A catch-up drain after
  subscribe replays anything missed from the snapshot cursor.
- Log SSE write failures at the route boundary instead of swallowing
  them silently; document that DrainResult.writeFailed means the client
  disconnected, not data corruption.
- drain-events.test.ts: drop the duplicated harness test, now covered
  against the real createSerializedDrainer.

Refs: WB-186
* chore(deps): bump @synergycodes/overflow-ui

* fix(deps): align ajv catalog to ^8.18.0 to match @jsonforms/core
* fix(sdk): fix hardcoded source handle position

* fix(sdk): proper port positions for long descriptions

* chore(sdk): tighten WB-192 fix scope, drop duplicate type, cross-ref
icon size, add changeset
@piotrblaszczyk piotrblaszczyk merged commit e79f79e into release May 29, 2026
1 check passed
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.

2 participants