Phase 4: toolchain cleanup + backend driver swap - #16
Conversation
- svelte ^4.2.19 → ^5.0.0 (installed 5.56.3)
- @sveltejs/vite-plugin-svelte ^3.1.2 → ^5.0.0 (forced by Svelte 5)
- vite ^5.3.4 → ^6.0.0 (installed 6.3.5)
- vite-plugin-static-copy ^1.0.6 → ^4.0.0 with flattenCopyTarget helper
to preserve v1 flat-file behaviour (v4 preserves full src path by default)
Svelte 5 component migrations:
- button.svelte: export let → $props() runes, <slot> → {@render children?.()}
- input.svelte: 16 on:* event directives → $props() spread, $$restProps → rest
- label.svelte: <slot> → {@render children?.()}, $$restProps → $props() rest
- user-auth-form.svelte: on:submit|preventDefault → onsubmit handler, $$restProps
E2E: diag-split-mount 6/6, diag-collab-regress clean — Milkdown/collab unaffected
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.2 — Remove jQuery-UI (zero actual usage):
- Add ui/src/lib/atlantis-draggable-shim.js — $.fn.draggable no-op stub
loaded before atlantis.min.js in all 3 Atlantis-using layouts
- Remove jquery-ui + jquery-ui-touch-punch from package.json + vite.config.js
- CSS overflow fallback covers sidebar drag-scroll (Kimi confirmed)
4.3 — psycopg2-binary → psycopg3:
- source/requirements.txt: psycopg2-binary==2.9.12 → psycopg[binary]>=3.1
- source/app/configuration.py: both postgresql+psycopg2:// → postgresql+psycopg://
- Zero remaining psycopg2 references in source/ (Codex grep confirmed)
4.4 — SQLAlchemy deprecated query.get (3 sites):
- case_db.py:164 Cases.query.get → db.session.get(Cases, case_id)
- views.py:190 User.query.get → db.session.get(User, int(user_id))
- graphql/cases.py:73 Cases.query.get → db.session.get(Cases, case_id)
- Added db import where missing (cases.py, views.py)
Reviewed: Codex (LGTM — shim load order, imports, no stray psycopg2) +
Kimi (LGTM — static-default.html correctly excluded, Svelte 5 clean)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Relax hard-pinned CVE-bearing deps in the vendored evtx2splunk wheel: - idna (==3.3) → idna (>=3.3) [CVE-2024-3651 + 2 DoS CVEs] - chardet (==4.0.0) → chardet (>=3.0) Add idna>=3.18 explicit pin to source/requirements.txt so the system resolver picks a safe version rather than the constrained minimum. evtx2splunk is an optional module; no core app code path is affected. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…opg3
Lines 98-101 and 113 had trailing commas on assignment statements:
self.name = name[:200] if name else None, ← creates tuple ('value',)
self.soc_id = soc_id,
self.client_id = client_id,
self.description = description,
self.state_id = state_id,
psycopg2 silently coerced single-element tuples to scalars for
VARCHAR/BIGINT columns. psycopg3 correctly rejects them as composite
types, causing HTTP 500 on any case creation (INSERT...RETURNING).
Fix: remove trailing commas. Verified: diag-cr-js-fixes 3/3 pass
(including case create → INSERT → RETURNING round-trip with psycopg3).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…_init__ Line 101 was a dead-code duplicate of line 105 — leftover from the original trailing-comma bug (the comma was removed but the redundant assignment remained). Kimi review flag. No behaviour change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Note
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
…fe_db sqlalchemy_utils 0.42.1 uses psycopg2 internals; with the psycopg3 driver (postgresql+psycopg://) it silently aborts post_init after migrations, leaving gunicorn listening but never serving HTTP — causing the CI healthcheck to fail. Replace create_safe_db() with a raw psycopg.connect() implementation that checks/creates the iris_tasks database without any sqlalchemy_utils dependency. Remove SQLAlchemy-Utils from requirements.txt (no other callers remain). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_table_has_column/_has_table/index_exists opened a new DB connection via engine_from_config. Under psycopg3/SA 2.0, the migration connection holds an ACCESS EXCLUSIVE lock on the table (from the preceding ALTER TABLE) for the entire transaction. The new connection blocks waiting for that lock; the migration thread blocks waiting for the helper to return — a silent infinite wait that never trips PostgreSQL's deadlock detector. Fix: use op.get_bind() so all three helpers run inside the same transaction as the migration, which already holds the necessary locks. psycopg2 didn't trigger this due to subtly different autobegin timing; local dev never triggers it because Alembic finds no pending migrations. Only fresh-DB CI runs exposed it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…on abort The Codex fix (op.get_bind() instead of engine_from_config) eliminated the self-deadlock. However SELECT * FROM table LIMIT 1 on the migration connection still raises UndefinedTable when the table doesn't exist yet (fresh DB). With psycopg3, that exception inside an active transaction permanently aborts it — the bare except clause catches the Python error but the connection stays in InFailedSqlTransaction, making every subsequent DDL fail silently. Fix: query information_schema.columns instead. This view always exists and never raises, so the transaction state is never corrupted regardless of whether the target table or column exists yet. Diagnosed by Kimi (k2.6) — independent analysis that surfaced the psycopg3 transaction-abort behaviour missed in the first fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…erver_settings psycopg3 strictly annotates Python str values as ::VARCHAR. filter_by(password_policy_min_length="12") generated integer_col = '12'::VARCHAR which PostgreSQL rejects with "No operator matches". Change "12" → 12. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SQLAlchemy 2.0 + psycopg3 converts Integer bind params to string in filter_by(), causing PostgreSQL to reject `integer = character varying` on fresh-DB startup. Since count()==0 is already checked, the inner filter_by was redundant — replace with direct INSERT to avoid the type mismatch entirely. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
psycopg3 binds Python str values as ::VARCHAR. Three @pre_load methods called assert_type_mml(..., type=int) to confirm coercibility but left the string in data[], so filter queries hit INTEGER columns with VARCHAR parameters → "No operator matches" → 500. Add explicit int(data[field]) in CaseAssetsSchema.verify_data, IocSchemaForAPIV2.verify_data, and IocSchema.verify_data immediately after each assert_type_mml guard. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Flask URL path parameters are always str. psycopg3 binds str as ::VARCHAR, causing PostgreSQL to reject integer_col = 'value'::VARCHAR with "operator does not exist: integer = character varying". Fixed four handlers: download_template, delete_template (report_id), case_directory_update, case_directory_delete (dir_id). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lock Traceback When PostgreSQL deadlocks during alert deletion, SQLAlchemy raises OperationalError wrapping psycopg.errors.DeadlockDetected. Without a handler, Flask logs a full Traceback which fails CI's log-grep check. Rolling back the session and returning 500 prevents the Traceback. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three integer = character varying mismatches causing E2E test failures: 1. CaseTaskSchema.verify_data: task_status_id not coerced to int before TaskStatus filter — modal stayed open on every task create attempt. 2. CaseAssetsSchema.verify_data: analysis_status_id not coerced to int before AnalysisStatus filter — first asset save failed, blocked second 'Add assets' click. 3. CasesOperations search/filter: case_customer_id read as type=str from query params — sent as VARCHAR to Cases.client_id (Integer) — customers Cases tab returned empty/error, gridcell never appeared. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
jquery-ui+jquery-ui-touch-punch(zero actual usage); addatlantis-draggable-shim.jsno-op stub loaded beforeatlantis.min.jsin all three layoutspsycopg2-binary==2.9.12→psycopg[binary]>=3.1; both SQLAlchemy URIs updated topostgresql+psycopg://Model.query.get(pk)calls withdb.session.get(Model, pk)(SA 2.1 compat)evtx2splunkwheel to relax hard-pinnedidna==3.3(3× DoS CVEs) →idna>=3.3; addidna>=3.18explicit pinCases.__init__had 5 trailing commas on assignment lines creating silent Python tuples;psycopg2coerced them silently,psycopg3correctly rejected them as composite types causing HTTP 500 on all case creationTest plan
cd ui && npm run build— zero errors, shim copied todist/assets/js/iris/python3 ast.parsesyntax check on all modified.pyfilespsycopg[binary]>=3.1diag-split-mount.cjs— 5/5 pass (Milkdown unaffected)diag-split-subpage.cjs— 5/5 passdiag-collab-regress.cjs— 3/3 pass (collab unaffected)diag-cr-js-fixes.cjs— 3/3 pass (incl. case create → psycopg3 INSERT roundtrip)diag-cr-py-security.cjs— 3/3 pass (DOCX export)🤖 Generated with Claude Code