Skip to content

Code review fixes: publish safety, SQL guard, unsaved edits, hardening - #31

Open
ScaleLeanChris wants to merge 30 commits into
mainfrom
review/integration
Open

ScaleLeanChris wants to merge 30 commits into
mainfrom
review/integration

Conversation

@ScaleLeanChris

Copy link
Copy Markdown
Contributor

Fixes from the initial code review. Six fix branches are merged here, each followed up after an independent integration review.

Closes #17, closes #18, closes #19, closes #20, closes #21, closes #22, closes #23, closes #24, closes #25, closes #26, closes #27, closes #29. Refs #28 (signing and notarization still need credentials). #30 (splitting large files) follows after this merges.

What changed

Verification

  • On Node 24, type check (npm run check) is clean, npm test passes 165/165, and npm run build succeeds. npm audit reports no vulnerabilities.
  • Not yet tried by hand in the app: the quit confirm, the workspace-switch confirm, the Browse pickers (including bq), and the Abandon dialog.
  • Packaging hangs on Node 26; use Node 24.

🤖 Generated with Claude Code

ScaleLeanChris and others added 30 commits October 6, 2026 17:03
Pin actions/checkout, setup-node, upload-artifact and download-artifact to
full commit SHAs with version comments. Add weekly Dependabot updates for
github-actions and npm. Signing and notarization remain a follow-up.

Refs #28

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Honor UC_STUDIO_DEV and UC_STUDIO_ROOT only when the app is not packaged.
Flip RunAsNode, NODE_OPTIONS and --inspect fuses off and asar integrity and
asar-only loading on after packaging; the package smoke asserts the fuse
state and runs the worker checks with the development Electron runtime.

Fixes #20

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Landing Studio reports unsaved edits to App, which asks before navigation
or a re-verify discards them. The page builder keeps typed values across
revision changes and Preview switches (cached like DraftEditor) and warns
when a newer revision exists. The warehouse SQL editor keeps a
per-workspace draft in sessionStorage.

Fixes #19

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Key the canvas AgentPanel by page and slot and skip setActiveSession
if the panel unmounted while a session was being created. Guard the
Resolve template result and the draft pull follow-up with the
currentPath check, and reset the busy state when the page changes.

Fixes #23

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Reserve through the shared StudioServices connection so allocations
  queue behind publishes and respect the login guard.
- Treat a 'preparing' receipt with no recorded batches as retryable
  'blocked' when no reservation is running in this process. A batch is
  persisted before every allocation request, so no IDs were requested.
  Receipt writes are now compare-and-set on the attempt ID, so an
  attempt that was taken over stops before allocating.
- Refuse draft edits while a reservation for that draft is running.
- Save the landing preparation record with the receipt before the
  post-allocation revision check.
- Guard JSON parsing of stored receipts and the landing template list.

Fixes #22

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Add settings.pickNodePath and settings.pickCliPath, which open
dialog.showOpenDialog in the main process and persist only the returned
path through host-only worker methods. settings.save now rejects any
change to nodePath or cliPath from the renderer. The settings dialog shows
the paths read-only with Browse buttons.

Fixes #21

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

Add .catch handlers with toasts to app.restartEngine, preview.reload,
window.openStore, auth.cancel and workspace.sample. Make sample preview
edit targets focusable buttons that respond to Enter and Space. Export
escapeHtml and a textHtml helper from shared/page-builder and reuse them
in Landing Studio. Ignore downloads/.

Fixes #29

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Verification now compares the live page against both the draft and its
baseline. An unchanged live page clears the attempt so the publish can be
retried; a page matching neither needs an explicit, host-confirmed abandon
that reopens the draft from the live content as a new revision. A non-JSON
pull reports a retryable verification error instead of a SyntaxError.

Fixes #17

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…eview partition

The worker reports toolkit child pids; main kills their process groups when
the worker exits and stops the worker with a shutdown timeout before kill
on engine restart, mirroring before-quit. A successful init resets the
crash-restart budget. Previews share one in-memory partition that is
cleared on close.

Fixes #25

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The SQL guard skipped the first item inside a parenthesized join, so
other projects and INFORMATION_SCHEMA could be read. Every FROM item is
now validated, including the first item of parenthesized and nested
joins, and comma joins inside parentheses. Dotted names outside FROM
items that can only name a table (project ids, region qualifiers,
INFORMATION_SCHEMA, ultracart_dw* datasets, quoted dotted paths) are
rejected unless they are an allowed ultracart_dw.uc_* view.

The dry-run receipt now requires ultracart_dw tables to match uc_*. It
keeps ultracart_dw_streaming only as the documented base dataset of the
curated views, and rejects any resolved table for SQL that names none.

Fixes #18

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

Fixes #24

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

Decode bq stdout once from collected Buffer chunks so multibyte UTF-8
characters split across chunks survive, and track output size with a
running byte counter instead of re-measuring the whole string.

Leave plain numeric CSV values (including negatives) unprefixed while
keeping the formula guard for all other text.

Match statement keywords only at statement position (start, after a CTE
body, after a set operator, or opening a parenthesized statement) so
columns like model/set/load and REPLACE() are allowed. EXTERNAL_QUERY
stays blocked anywhere and the dry run still requires statementType
SELECT.

Require byte ceilings of at least 10 MiB, the BigQuery billing minimum.

Fixes #26

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… review when inspection fails

Fixes #27

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Report warehouse bq children to the child observer (detached group) so
  they are killed when the worker exits.
- Replace the post-init restart reset with a 3-restarts-per-5-minutes budget
  (RestartBudget); manual restart still resets it.
- settings.save no longer forwards node/CLI paths; the worker keeps the
  stored ones so a concurrent Browse pick is not overwritten.

Refs #25

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Skip and log unreadable session rows during the workspace-id migration, run it in a transaction, and only prompt for the storefront host when the live page matches neither the baseline nor the draft.

Refs #27

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

Quit now asks the renderer about unsaved edits before stopping the worker and
shows a native confirm; cancelling keeps a live engine. Workspace changes in
ConnectDialog go through the discard guard. Page-builder localStorage cache is
cleared on save, discard and missing draft, and pruned (30 days, 50 entries).

Refs #19

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Refs #19

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…are byte floor

- validateWarehouseSql collects CTE names only from WITH [RECURSIVE] lists
  (first entry and after commas), so WINDOW names and other `x AS (` forms
  no longer whitelist FROM items. Unquoted dashed or dotted continuations
  after a FROM path are rejected before the CTE check, since BigQuery reads
  them as one path.
- The bq executable is chosen only in the main process via
  dialog.showOpenDialog (warehouse.pickBqPath) and saved through the
  host-only warehouse.setBqPath. configure/diagnose reject renderer-supplied
  bqPath changes; the basename must be bq, bq.cmd or bq.exe.
- warehouse_save_query maxBytes uses WAREHOUSE_MIN_BYTES as its minimum.

Refs #18

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	src/main/warehouse-diagnostics.ts
…nt limit

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Quit no longer waits forever on a renderer that stops responding: after
  2s without an answer about unsaved edits, close the window and quit, with
  a 5s safety net after a confirmed quit.
- Confirming "Discard and continue" now remounts Landing Studio. Before
  this, switching to the same workspace kept the discarded edits on screen
  while the unsaved tracker was cleared, so a later quit would not warn.

Found by driving the packaged renderer with Playwright.

Refs #19

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment