Skip to content

fix(services): keep unsaved connection drafts across background refreshes - #513

Merged
PeterGuy326 merged 9 commits into
mainfrom
fix/services-unsaved-draft-refresh
Oct 5, 2026
Merged

PeterGuy326 merged 9 commits into
mainfrom
fix/services-unsaved-draft-refresh

Conversation

@PeterGuy326

@PeterGuy326 PeterGuy326 commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes a background services refresh silently discarding unsaved connection fields, including a typed PAT. A dirty form keeps the user's draft when saved connection values change; successful save or disconnect clears the dirty state so normal synchronization resumes. No service API or persisted schema changes.

The regression test changes saved addresses during a background owb:services-changed refresh, verifies the typed token survives, then verifies it is submitted. All editable fields mark the draft dirty. Failed saves retain it. CHANGELOG has the Unreleased entry.

Validation ledger

Environment: macOS arm64, Node 24.14.1, npm 11.11.0; npm ci, with the built CI-pinned design-system revision 4a82fce41f89f1a55b6b02cdb54f7a4e9ce9d84d. Tests mock the service bridge and use fixture tokens only, with no real credentials.

ID Acceptance criterion Command from repository root Expected Observed
V1 Workspace/server projects compile npm run build Exit 0 PASS, exit 0
V2 Renderer types remain compatible npm run typecheck:renderer Exit 0 PASS, exit 0
V3 Refresh preserves and submits an unsaved PAT, with existing connection behavior intact node scripts/run-renderer-tests.mjs renderer/test/service-connections.test.tsx All cases pass PASS, 7/7
V4 Full platform regression/security Updated-head GitHub verify and Security Baseline All green FAIL: both Node 24 jobs fail at the final audit gate on existing http-cache-semantics@4.2.0; 9/11 checks green, including CodeQL

Limitations and rollback

The original #512 Ubuntu full-suite failure was not independently reproduced locally. This regression test proves the identified data-loss mechanism is fixed; #512 stays open if its failure recurs. The draft remains component-local and is still lost when that form is unmounted. A failed save keeps the draft dirty and pauses external value synchronization until a successful save/disconnect or remount. No Windows GUI acceptance was performed on this macOS host. Revert the form dirty-state change and its test to roll back.

Refs #512. Synced with current main; another maintainer must supply the non-author approval. This is a repair recommendation, not self-approval.

Current shared audit blocker: GHSA-ch52-4w7c-c8xp. A separate 4.3.0 experiment clears npm's version-range check but still reproduces the shared-cache reuse issue, so it was not published as a security repair. No audit threshold or required check was weakened.

2026-10-05 follow-up

The current head additionally contains the dependency removal tracked in #562: app-builder-lib now uses the official @electron/get 5.1.0 already used by Electron, removing got/cacheable-request/http-cache-semantics instead of merely escaping the advisory range. Minimum build Node is 22.12.0; CI still runs Node 24 and the unchanged high-severity audit. Legacy Got download options and GLOBAL_AGENT_* proxy options are not supported by get 5; repository release commands use the existing native Electron distribution.

Fresh local validation after this dependency change: npm ci --ignore-scripts --no-audit --no-fund (exit 0), node --test scripts/test/electron-download.test.mjs (2/2, real loopback artifact download, checksum verification, validated cache reuse, corrupt SHA256 rejection), npm run security:check (exit 0; no high/critical findings, two existing moderate Vitest findings). The earlier feature-specific results above describe the feature implementation; earlier red audit CI refers to the previous head. Fresh complete current-head CI is running and has not yet been declared passed. Another maintainer must review the current head; no self-approval or branch-protection bypass.

Current-head CI result

All 11 current-head checks passed at 97df0f6a0552d37d6739a783496c0f4143b568bb, including both full Node 24 jobs, required security checks, both native staging jobs, both installer jobs and layout parity. Prior pending/failure text above records earlier snapshots, not a remaining current-head CI blocker. Independent current-head approval is the remaining merge gate.

…shes

The ConnectionForm sync effect unconditionally reset every field,
including a typed PAT, whenever the saved connection values changed.
A background services refresh landing while a draft was unsaved could
therefore silently discard the user's input, and the next submit went
out without a token.

Guard the sync effect with a dirty flag: user edits mark the form dirty
and win over background refreshes; the flag clears once a save or
disconnect accepts the server state. Add a regression test where a
refresh lands with changed saved addresses while a PAT is typed — it
fails on main and passes with this change.

Refs #512
@PeterGuy326

Copy link
Copy Markdown
Contributor Author

@sun-970 friendly nudge — a review is requested from you here. The diff has been stable for a while (head 4c88d54); once #530/#531 land on main I will sync this branch so the required checks go green before you start. Thanks!

@PeterGuy326

Copy link
Copy Markdown
Contributor Author

@sun-970 A quick status update: the branch has been re-synced with latest main (which now carries the #531/#534 explicit test budgets), and the same diff content already went green on every required check in the previous round. This one is ready for your review whenever you have a moment.

@PeterGuy326

Copy link
Copy Markdown
Contributor Author

Reviewed the diff (2 files, +35/-5). The fix is correct and well scoped.

What it does:

  • Adds a dirtyRef flag set true on every user edit (apiUrl, webUrl, token, workspaceId, clear-token).
  • The background-refresh useEffect now returns early while a draft is dirty, so a refresh landing with different saved addresses no longer clobbers what the user is typing.
  • dirtyRef is cleared on a successful save and on disconnect, which is exactly where the draft stops being a draft.
  • The new test seeds a typed PAT, delivers an owb:services-changed refresh with changed saved addresses, asserts the typed value survives, and then asserts the save actually sends the typed token. That covers the regression end to end.

CI: all checks pass on head d109395, including Node 24 on both platforms, CodeQL, layout parity and the staging smoke runs.

Two non-blocking notes:

  1. Clearing the flag only on success means a failed save keeps the draft dirty, which is the desired behavior, but the user also cannot see a subsequent background refresh until they save or navigate away. A short hint such as "unsaved changes; background refresh paused" would make that state less surprising.

  2. The flag is per form instance. If the settings surface ever remounts while a draft is dirty, the draft is lost for the same reason it was before this fix. Not a regression, just a known edge to keep in mind.

This PR is authored by the repository owner, so it cannot self-approve under the branch protection rules. Requesting review from another maintainer.

Reviewed-by: PeterGuy326 (as maintainer). Merging is blocked on a non-author approval.

@PeterGuy326
PeterGuy326 merged commit 2bd2deb into main Oct 5, 2026
11 checks 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.

1 participant