Skip to content

Fix every bug listed in BUGS.md - #5

Merged
robertsolves merged 4 commits into
mainfrom
claude/project-thread-ecky3x
Nov 3, 2026
Merged

robertsolves merged 4 commits into
mainfrom
claude/project-thread-ecky3x

Conversation

@robertsolves

Copy link
Copy Markdown
Collaborator

Requested by Robert · project thread

What & why

Fixes all 32 open entries in BUGS.md. Where an entry said it needed a decision, the choice made is noted below.

Connections and profiles

  • Password: new "Forget the saved password" checkbox in the Postgres and Cloud SQL dialogs. It sends a transient forgetPassword intent that deletes the keychain entry. An empty field still means "keep".
  • _mergeProfiles now closes the executors of profiles deleted in another window.
  • _connect reuses an already-open connection instead of dialing a second one. Decision: reuse, not close-and-replace.
  • ConnectionService single-flights opens per profile, and an open that finishes after a close is discarded.
  • The read-only name heuristic now matches prod|production|live|main only as whole words.
  • Connection links: iterations are bounded to 10k–2M, nonce and tag sizes are checked, and malformed profiles become FormatException.

SQL safety and SQLite

  • enforceReadOnly now refuses INSERT/UPDATE/DELETE/MERGE/CREATE/EXECUTE, REPLACE INTO and SELECT … INTO anywhere outside literals and comments. A new bareWords lexer helper in sql_parse.dart does the scanning.
  • SQLite:
    • Soft delete writes CURRENT_TIMESTAMP. The optimistic guard uses IS, which works before SQLite 3.39.
    • The Navigator filter uses a registered dbscope_iregexp() function.
    • Typed placeholders become CAST(? AS affinity) or are dropped.
    • The executor always steps through select, so results are never thrown away.
    • Metadata timeouts are enforced with a sqlite3_progress_handler deadline, behind the new StatementTimeoutCapable interface.
    • DBML export skips enums and labels the file as SQLite.
  • Keyset pager: a nullable sort column now has a NULL-aware cursor, in each backend's own NULL order. ORDER BY is unchanged, so the index is still used.
  • @me_principal: a missing identity now refuses the action. On Postgres it falls back to pg:<login>, and claimed emails are lowercased.
  • A date-only value renders as UTC midnight of that day.

UI

  • TableTabView._readOnly() reads the real flag and reloads when it flips.
  • The row inspector closes an open editor when the selected row changes.
  • Query Run has an in-flight guard and resets the row selection.
  • The date picker keeps seconds, fraction and zone when the time is left as it was.
  • Postgres result headers use type names from a built-in oid table.

Export, files, RPC, jobs

  • CSV quotes a bare \r.
  • .db export writes to a temp file and renames it over the target. Duplicate column names get suffixes. The button is hidden on web.
  • Project file and query history: atomic writes, a cross-isolate lock file (lib/util/file_lock_io.dart), and an unparseable project file is moved aside as .corrupt-<time>.
  • Server scopes subscriptions by caller window.
  • Job tabs call job.get once after subscribing.
  • copy_table opens a dedicated target connection that keeps the profile's read-only setting.
  • add_changelog_line.sh adds the missing --- rule itself. The two changelog lines the bug entry said were missing are added.

Records: closed all 32 BUGS.md entries. Added one new bug: on-device SQLite pushes the file back after every SELECT that returns rows. Added two TODO.md items: type names for custom Postgres types, and offering a reconnect after re-importing a link. Added 31 changelog lines.

How it was tested

  • Linux, Flutter 3.47.7.
  • New test/bug_fixes_test.dart covers: the read-only gate, the placeholder translator, the SQLite executor against real sqlite3 (comment-leading SQL, RETURNING, typed params, regex function, statement timeout), the date renderer, oid names, the heuristic, link bounds and unique column names.
  • New cases in dml_test, pager_test and server_test.
  • Not run against a live Postgres, a phone or multiple macOS windows.

Checklist

  • fvm flutter analyze is clean (and the sqflite plugin package)
  • fvm flutter test passes (285 passed, 7 skipped live-PG)
  • SQL safety invariants in CLAUDE.md still hold (quoted identifiers, parameterised values)
  • No credentials, API keys or .dbscopeconn files in the diff

Generated by Claude Code

Fixes all 32 open entries: connection lifecycle leaks (registry merge,
double connect, server-side single-flight), forgetting a saved password,
the read-only name heuristic, the AI read-only gate, connection-link
bounds, SQLite dialect issues (soft delete, IS, Navigator regex filter,
typed placeholders, comment-leading queries, statement timeout, DBML),
NULL-aware keyset paging, date-only rendering, @me_principal binding,
grid/inspector/run races, export safety (CSV CR, atomic .db, web .db),
Postgres type names, RPC subscription ids per window, the job-finished
race, copy_table's target connection, atomic + locked project/history
writes, and the changelog script's missing --- rule.

Adds test/bug_fixes_test.dart plus cases in dml, pager and server tests.
Files one new bug (on-device reads pushing the file back) and two TODOs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EqzDdVtx5LMyjjW8CxL4NE
connectProfile now closes and reopens the connection when the incoming
profile differs in target, user, SSL mode, plugin config or password,
instead of silently keeping the old connection. Closes the matching
TODO.md item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EqzDdVtx5LMyjjW8CxL4NE
New Postgres profiles get a suggested read-only setting (on for a
prod/live/main name or a remote host, off for localhost) that follows
the name and host until the user flips the switch, and the switch says
why it is on or off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EqzDdVtx5LMyjjW8CxL4NE
PostgresExecutor looks up oids missing from the built-in table in
pg_type once per connection and caches them (misses included). Closes
the matching TODO.md item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EqzDdVtx5LMyjjW8CxL4NE
@robertsolves
robertsolves merged commit b9a9469 into main Nov 3, 2026
4 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.

2 participants