Skip to content

Fix the code review findings: share links, storage, dialogs, CI - #253

Merged
MathiasVDA merged 9 commits into
mainfrom
claude/project-thread-m06cum
Oct 31, 2026
Merged

MathiasVDA merged 9 commits into
mainfrom
claude/project-thread-m06cum

Conversation

@MathiasVDA

@MathiasVDA MathiasVDA commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Requested by Mathias · project thread

Fixes the findings of the MatGUI code review. There is one commit per topic, so you can read it and rebase-merge it commit by commit.

Security

  • Share links no longer run risky queries on load (fix(yasgui): don't run risky share-link queries on load). Before, a link could name any query and endpoint, and it ran at once with the credentials saved for that endpoint. Now updates never run from a link. Invalid queries, and queries that would send an Authorization or API key header or cookies, wait until you click Run query in a toast. The new autoRunSharedQueries option takes "safe" (default), "always" or "never".
  • OAuth 2.0: the popup result is only accepted from the origin of the redirect URI. The verifier and state are no longer written to sessionStorage.
  • Runtime dependencies have no audit findings (npm audit --omit=dev). query-string 10 drops decode-uri-component, which had a high advisory. Unused deps are removed: choices.js (with its deepmerge advisory), blueimp-md5, es6-object-assign, jquery and its dead helpers, datatables.net, column-resizer, colors and free-solid-svg-icons. The five plugins that yasgui imports are now listed in its package.json.
    • Dev tooling still has 17 moderate findings: new glob and minimatch advisories through ESLint 8, typescript-eslint 7 and mocha. They don't ship. Fixing them means migrating to ESLint 9, so that's left for a follow-up.

Correctness

  • A full storage no longer wipes everything. Storage.set called the quota callback and then threw anyway, and the yasgui callback cleared every tab, endpoint and credential. Now it retries without the stored query results. If that still doesn't fit, it keeps working from memory and shows one message.
  • Malformed headers or outputSettings in a link are ignored instead of leaving the page blank.
  • Config import uses N3. It used regexes that paired values by position, so a tab without an endpoint shifted the endpoints of the next tabs.
  • Git save conflict self-heal: when the automatic retry succeeded, the code still showed the conflict error and skipped updating the saved version.

UX

  • In-app dialogs and toasts replace all 41 alert, confirm and prompt calls. They are available as Yasgui.dialogs: showAlert, showConfirm, showChoice, showCopyValue and showToast. They follow the theme, trap focus, cancel on Escape, return focus when closed, and work in sandboxed iframes. Validation in the save modal now shows on the field itself.

CI and build

  • unit-test no longer ends in || exit 0. Type-check and lint now run in CI, after the build, which generates version.ts. Both were broken and are fixed. The duplicate test.yaml is removed.
  • npm run util:bundleSize lists what each bundle is made of and fails when a bundle goes over its budget. Today yasgui is about 5.1 MB minified and 1.5 MB gzipped.
  • Dependabot covers npm, the website and GitHub Actions.
  • Docker: a new nginx.conf adds gzip and cache headers, and the build runs on Node 24.

Docs

  • The user guide covers what happens when you open a share link and when the storage is full.
  • The developer guide covers autoRunSharedQueries and Yasgui.dialogs.
  • The README docs links now point at matgui-doc.matdata.eu, and the Docusaurus url matches it.

Not in this PR

  • Lazy-loading the plugins and the LOV term list. The site, the Docker image and embedders use the IIFE build, which can't code-split. Moving the JSON to a separate file would break embedders that copy only yasgui.min.js. This needs a decision on how MatGUI is distributed, for example an ESM build with dynamic imports, so it's left for a follow-up. The bundle-size report shows where the bytes are.
  • Splitting Tab and TabSettingsModal into smaller modules. This refactor is best done step by step.
  • The ESLint 9 migration for the dev tooling advisories.

Tests

  • New unit tests cover share-link safety, Storage quota handling and a config export/import round trip. The unit suite has 1,772 passing.
  • New browser tests check that an update link doesn't run, a credentialed link waits for Run, a plain link runs, a malformed link still loads, the confirm dialog works, and closing an unsaved tab offers a choice.
  • The full Puppeteer suite passed locally: 97 passing.
  • The nginx config is not verified, because there's no Docker daemon in the cloud session.
  • Changeset: yasgui minor, yasqe, yasr and utils patch.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ECW7opooHkpe4sh6LzSEh5

… prompt

Native dialogs block the page, ignore the theme and are suppressed in sandboxed iframes, where confirm() returns false and the unsaved-changes flow silently loses work. dialogs.ts adds showAlert, showConfirm, showChoice, showCopyValue and showToast, rendered inside the Yasgui root with focus trapping, Escape to cancel and focus returned to the opener. All 41 alert/confirm/prompt calls use them; save-modal validation is shown on the field itself.

Also fixes saving a Git query after a stale version tag: when the automatic retry succeeded, the code fell through to the conflict error and skipped updating the saved-version metadata.
Storage.set called the quota callback and then threw anyway, and the Yasgui callback cleared every tab, endpoint and credential. The callback now replaces the throw. Yasgui retries without the query results kept with the tabs and otherwise keeps working from memory with one message; Yasr and Yasqe only skip the write. Quota errors are recognised by name in current browsers, and the expired-key sweep (which parses all of localStorage) runs at most once a minute, with get() checking expiry itself.

Also adds Yasqe requestSendsCredentials(), used by the share-link check.
A link could name any query and endpoint, and it ran at once with the credentials saved for that endpoint, so a crafted link could run an update as whoever opened it. Updates never run from a link now; queries with syntax errors, or that would send an Authorization/API key header or cookies, wait for the user to click Run query in a toast. New autoRunSharedQueries option: safe (default), always, never. Malformed headers/outputSettings JSON in a link is ignored instead of throwing in the constructor.

Yasgui.dialogs exposes the dialogs to plugins and embedders. Browser tests can use another port with TEST_PORT.
… origin

The postMessage handler took a callback from any window. The code verifier and state are no longer written to sessionStorage (only the closure reads them), and unexpected errors while polling the popup now reject the flow instead of being swallowed.
The import matched literals with regular expressions and paired them by position, so a tab without an endpoint shifted the endpoints of the next tabs, quotes in names broke parsing, and a tab orientation could become the global one. Adds an export/import round-trip test.
The unit-test script ended in '|| exit 0', util:validateTs (failing on yasqe tooltip.ts) and lint were never run in CI, and the lint glob pointed at a folder that no longer exists. build.yml now type-checks, lints, builds, checks bundle sizes against a budget (npm run util:bundleSize, which also lists what each bundle is made of) and runs all tests; test.yaml ran the same steps a second time and is removed. Dependabot covers npm, the website and GitHub Actions.

Dependencies: query-string 10 (drops decode-uri-component, which had a high-severity advisory; npm audit is now clean). Removes packages nothing imports (choices.js, blueimp-md5, es6-object-assign in yasgui; jquery and its dead helpers, datatables.net, column-resizer, colors and free-solid-svg-icons in yasr), lists the five plugins yasgui imports as its dependencies, and moves test and build tooling to devDependencies.
The image used the default nginx server: no compression for a 5 MB bundle and no cache policy. docker/nginx.conf gzips text assets (about 1.5 MB transferred), caches the hashed fonts and images for a year, revalidates yasgui.min.js/css, and sets nosniff and a referrer policy. The build stage moves from Node 20 to 24, as in the publish workflow.
Also points the README documentation links at matgui-doc.matdata.eu, the domain the app links to, and aligns the Docusaurus url with it.
@MathiasVDA MathiasVDA self-assigned this Oct 31, 2026
packages/yasgui/src/version.ts is generated by the build and git-ignored, so util:validateTs failed on a fresh checkout before it.
@MathiasVDA
MathiasVDA merged commit 5df4acc into main Oct 31, 2026
1 check passed
@MathiasVDA
MathiasVDA deleted the claude/project-thread-m06cum branch October 31, 2026 21:32
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