Skip to content

build(frontend): absorb the Community client without moving the Java baseline - #37

Draft
openai0229 wants to merge 9 commits into
mainfrom
chore/community-ref-sync
Draft

openai0229 wants to merge 9 commits into
mainfrom
chore/community-ref-sync

Conversation

@openai0229

@openai0229 openai0229 commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

The locked Community frontend sat at a117f489 (v5.3.2-17) while Community main moved 962 commits ahead. Moving the submodule to main is not enough: the Java compatibility baseline pins the checked-out commit's chat2db-community-server tree, and every newer Community commit changes it, so this PR decouples the two pins and then implements the backend routes the newer client calls.

1. Decouple the frontend lock from the Java baseline

  • scripts/community-frontend.lock.json moves to dedc12663 (client tree 9f4be62c…); third_party/chat2db-community stays on the compatibility baseline commit, so the Java compatibility classpath keeps building from the tree it was validated against.
  • scripts/community-frontend.mjs fetches the locked frontend commit into the submodule object store when it is missing (by SHA, then by refs) and archives from there. Verification checks the locked commit's client tree instead of requiring the submodule index and HEAD to match; the worktree must still be clean.
  • The packaging scripts read community_commit from the frontend lock, the value scripts/prepare-release.mjs validates.
  • Eight of the eleven pinned upstream behavior scripts were deleted upstream (which now runs its battery through prebuild:web:community), and upstream's test:community-boundary needs the sibling chat2db-community-server tree, which the export now materializes.

2. Implement the routes the new client requires

Three of the 25 new client paths are retired dead code (/api/v1/ai/chat, /api/v1/ai/embedding, /api/v2/ai/stream/chat appear only in the upstream guard test that forbids them), so 21 routes were implemented:

  • AI: POST /api/v3/ai/chat/history/session/rename (revision CAS).
  • Table and connection: GET /api/rdb/table/copy/prepare, GET /api/database/supported, POST /api/connection/datasource/identity_color (migration 009 adds datasources.identity_color, validated #RRGGBB, projected into list/detail responses).
  • Task center (/api/tasks/*): list, get, active-count, artifact, delete, events, export, import, prepare-user-exit, abort-user-exit. Events are written in the same transaction as the progress or terminal transition they describe (new transfer_task_events table); delete removes only terminal tasks and their artifacts; the exit handshake stops accepting new transfer work and is reversible without cancelling running tasks.
  • Import preview: upload (multipart staging, 24 h TTL), upload_local (desktop path), sheets, preview (first 100 rows, target columns, name-matched mapping suggestion), execute (starts the durable import task and answers {taskId}).
  • MySQL monitor: GET /api/rdb/active_transaction/list (INNODB_TRX joined with PROCESSLIST, 30 s timeout, mysql.activeTransaction.processPrivilegeRequired for missing PROCESS privilege).

Each route is registered in the desktop dispatch match, LEGACY_PATHS, the Axum router, and the path-coverage test lists, and each landed with tests.

Known limitations, stated instead of faked

  • Import preview executes only same-named mappings; renames, skipped columns and unmappedTarget: NULL answer unsupported_import_mapping, and preview options beyond hasHeader are not applied yet. The durable import builds its INSERT list from file headers matched to table columns.
  • POST /api/jdbc/driver/upload answers unsupported_custom_driver_upload: the runtime loads verified driver packs and has no custom-driver storage or class loading.
  • QUERY_RESULT_EXPORT answers unsupported_task_type: query results export synchronously today and have no durable task form.
  • Deep lock metadata in the active-transaction response is reported as lockMetadataState: UNAVAILABLE.

Verification

  • chat2db-storage: 115 + 4 tests pass (migration, task events, delete guards).
  • chat2db-web: 83 tests pass, including route tests for the supported-database list, driver-upload gap, session rename, task submission branches, prepared exit, and import-preview staging/mapping rejection.
  • cargo clippy -p chat2db-web -p chat2db-core -p chat2db-contract -p chat2db-storage --all-targets -- -D warnings passes; cargo fmt --all --check passes; scripts/check-contracts.sh reports no drift after regenerating the OpenAPI and TypeScript contracts.
  • The decoupling itself was verified by a green 11/11 CI run on the earlier head; this head re-runs the same checks.

AI assistance: implementation, review, and verification performed with Codex.

…baseline

The locked Community frontend sat at `a117f489` (v5.3.2-17) while Community main
moved 962 commits ahead, so none of the upstream UI work could reach the Rust
product.

The submodule cannot simply follow main: `scripts/build-community-h2-classpath.sh`
requires the checked-out commit's `chat2db-community-server` tree to equal the
Java compatibility baseline in `third_party/community-h2-classpath.lock`
(`3cb8af54`), and every newer Community commit changes that tree. Following main
directly failed `Rust-Java IPC`, `MySQL`, and `Desktop (windows-latest)` with
`Community server tree must match compatibility baseline 3cb8af54...`.

Keep the two pins independent:

- `scripts/community-frontend.lock.json` moves to `dedc12663` (client tree
  `9f4be62c090886b726e20fd9bf274d7bd279d5e1`); the submodule stays on the
  compatibility baseline commit, so the Java compatibility classpath keeps
  building from the tree it was validated against.
- `scripts/community-frontend.mjs` fetches the locked frontend commit into the
  submodule object store when it is missing (by SHA, then by refs) and archives
  from there. Verification checks the locked commit's client tree instead of
  requiring the submodule index and HEAD to match; the worktree must still be
  clean.
- The packaging scripts read `community_commit` from the frontend lock, the
  value `scripts/prepare-release.mjs` validates; reading the submodule HEAD
  would fail release aggregation once the pins differ.
- Eight of the eleven pinned upstream behavior scripts were deleted upstream,
  which now runs its battery through `prebuild:web:community`, so the surviving
  three stay pinned.
- Upstream's `test:community-boundary` scans the sibling
  `chat2db-community-server` tree, which the export now materializes instead of
  stubbing or skipping it.
- `docs/architecture.md` and `docs/releases.md` describe the split.
@openai0229
openai0229 force-pushed the chore/community-ref-sync branch from 935fe8c to cf834e2 Compare October 8, 2026 11:43
@openai0229 openai0229 changed the title build(frontend): absorb the Community client up to main build(frontend): absorb the Community client without moving the Java baseline Oct 8, 2026
The Community frontend moved 962 commits ahead and now calls routes this
repository does not implement. This adds the first batch, each registered in the
desktop dispatch match, `LEGACY_PATHS`, the Axum router, and the path-coverage
test lists:

- `POST /api/v3/ai/chat/history/session/rename` renames one durable AI session
  through the existing revision CAS; the sidebar and AI panel expose it.
- `GET /api/rdb/table/copy/prepare` returns the default copy-table name the copy
  dialog pre-fills, sharing `default_copy_table_name` with the copy route.
- `GET /api/database/supported` lists the registered database types so the
  connection form can register dynamic ones.
- `POST /api/jdbc/driver/upload` answers with an explicit
  `unsupported_custom_driver_upload` failure. This runtime loads verified driver
  packs and has no custom-driver storage or class loading, so the dialog reports
  the gap instead of pretending the upload succeeded.

Tests: 80 chat2db-web tests pass, including new route tests for the supported
database list, the driver-upload gap, and the AI session rename flow.
Continues the route work the newer Community frontend needs.

Datasource identity colour:

- Migration `009` adds `datasources.identity_color` (and the task-center columns
  and event table used later in this series).
- Storage validates and stores `#RRGGBB`, Core and the contract DTOs project it,
  and the datasource list/detail responses now carry `identityColor` so the
  colour survives a refresh.
- `POST /api/connection/datasource/identity_color` returns the updated identity
  with the fixed local environment.

Task center (read side), backed by the existing durable transfer tasks:

- `GET /api/tasks/list` accepts the client's `status` vocabulary
  (PENDING/RUNNING/SUCCESS/FAILED/CANCELLED) and projects tasks into the
  `ImportExportTaskDetails` shape the panel polls.
- `GET /api/tasks/get` reads one task by `taskId`.
- `GET /api/tasks/active-count` reports the queued/running total used by the
  desktop exit coordinator.
- `GET /api/tasks/artifact` streams the finished task artifact; the desktop
  keeps using its own reveal-in-explorer path, so the bridge answers
  method-not-allowed.

Contract regeneration ran because the datasource DTOs changed. Verification:
`chat2db-storage` 113 tests, `chat2db-web` 80 tests, contract drift check, and
clippy with `-D warnings` on the touched crates all pass.
`DELETE /api/tasks/delete` removes one finished transfer task and its artifact.
`Storage::delete_transfer_task` deletes only terminal tasks (rejecting queued or
running ones with `InvalidTransfer`), unlinks the managed artifact file, and
`Application::delete_transfer_task` exposes it to the delivery layers. The route
is registered in the dispatch match, `LEGACY_PATHS`, the Axum router, and the
transfer path-coverage list.

Tests: a storage test covers delete-after-completion, the active-task rejection,
and the not-found result after a second delete.
The task-center log view polls ordered events for one task.

- The transfer storage now appends an ordered event inside the same transaction
  as the progress or terminal transition it describes: INFO for progress and
  completion, WARN for cancellation, ERROR for failure. Events carry a
  per-task sequence, level, code, optional stage, message, and timestamp.
- `Storage::list_transfer_task_events` reads a sequence window with a bounded
  limit (1..=200) and rejects unknown tasks.
- The contract exposes `TransferTaskEvent`, Core projects it, and
  `GET /api/tasks/events` answers the client's `{eventId, taskId, sequence,
  level, code, stage?, message, createdAt}` shape as a bare array.

Tests: a storage test covers sequence ordering across progress, completion, and
failure events plus the invalid-limit rejection.
`POST /api/tasks/export` and `POST /api/tasks/import` now translate the panel's
submission into the existing durable transfer services:

- `SQL_EXPORT` runs the SQL-file export, `TABLE_DATA_EXPORT` the format-specific
  table export, and both return `{taskId}` for the panel to track.
- `DATA_FILE_IMPORT` and `SQL_FILE_IMPORT` import either the desktop
  `sourceFile` path or a staged `fileId` resolved through the managed artifact
  store, so the web flow works once the preview upload lands.
- `QUERY_RESULT_EXPORT` answers with an explicit `unsupported_task_type`
  failure: query results are exported synchronously today and have no durable
  task form, so the panel reports the gap instead of silently doing nothing.
  Unknown task types are rejected as `invalid_task_type`.

Tests: 81 chat2db-web tests pass, including a new route test for the
unsupported and invalid submission branches.
The desktop exit coordinator asks the backend to prepare for exit and to abort
that preparation when the window close fails.

- `Application::prepare_user_exit` stops accepting new transfer work through the
  existing `accepting_work` gate, and `abort_user_exit` restores it. Neither
  cancels running tasks, so a failed exit attempt does not destroy user work.
- `import_mysql_file`, `export_mysql_sql_file`, and `export_mysql_other_file`
  now consult that gate and answer `runtime_not_accepting_work`.
- `POST /api/tasks/prepare-user-exit` and `POST /api/tasks/abort-user-exit`
  expose the handshake, registered in the dispatch match, `LEGACY_PATHS`, the
  Axum router, and the transfer path-coverage list.

Tests: 82 chat2db-web tests pass, including a route test proving a prepared exit
blocks new submissions and that aborting restores the gate.
The newer Community import dialog stages a file, previews it against the target
table, and then executes with an explicit column mapping.

- `POST /api/rdb/import_preview/upload` stages a multipart upload into the
  managed artifact store (24 h TTL, 16 MiB cap) and answers the file id.
- `POST /api/rdb/import_preview/upload_local` stages an absolute desktop path;
  the HTTP twin stays `desktop_file_operation_required`, matching the bridge.
- `POST /api/rdb/import_preview/sheets` lists worksheet names through a new
  bounded reader in `chat2db-core` (`worksheet_names`), empty for CSV.
- `POST /api/rdb/import_preview/preview` returns the source columns, the first
  100 rows, the target table columns, and a name-matched mapping suggestion.
- `POST /api/rdb/import_preview/execute` starts the durable import task through
  the staged artifact path and answers `{taskId}`.

Known limitation, explicit in the code: only same-named mappings execute today.
Renames, skipped columns, and `unmappedTarget: NULL` answer
`unsupported_import_mapping` instead of importing the wrong columns, because the
durable import builds its INSERT list from file headers matched to table
columns. Preview options beyond `hasHeader` (delimiters, encodings, sheet
selection) are likewise not applied yet.

Tests: 83 chat2db-web tests pass, including a new test that stages a multipart
CSV, lists its (empty) sheets, and rejects a renamed mapping.
`GET /api/rdb/active_transaction/list` reads `information_schema.INNODB_TRX`
joined with `PROCESSLIST` through the native MySQL connection, with a 30 second
timeout, and projects the monitor's `IActiveTransactionItem` core fields:
transaction id, state, start time, age, isolation level, locked and modified
row counts, lock structures, thread id, user, host, default database, and the
running statement.

Privilege failures answer `mysql.activeTransaction.processPrivilegeRequired`
(MySQL error 1227 or 1142) so the panel can explain the requirement instead of
showing a generic error; other failures answer
`mysql.activeTransaction.unavailable`. Deep lock metadata
(`blocking*`/`lockMetadata*`) is not collected yet, so the response reports
`lockMetadataState: UNAVAILABLE` rather than inventing values.

Verification: 83 chat2db-web tests, 115+4 chat2db-storage tests, clippy with
`-D warnings` on the touched crates, and the contract drift check all pass.

This branch has not been deployed

No deployments
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