Skip to content

fix(combos): clear LKGP pins on delete - #12425

Merged
diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.51from
KrzysiekSko:fix/delete-combo-lkgp-12326
Sep 4, 2026
Merged

diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.51from
KrzysiekSko:fix/delete-combo-lkgp-12326

Conversation

@KrzysiekSko

@KrzysiekSko KrzysiekSko commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Cleans up LKGP key_value rows when a persisted combo is deleted.
  • Preserves unrelated LKGP state, including prefix-sharing combo names and names containing SQLite LIKE wildcards.
  • Adds regression coverage for deleted, unrelated, nonexistent, cached, and no-pin delete paths.

Problem

deleteCombo() deleted the combo row but did not delete LKGP pins keyed by that combo name. The result was unreachable key_value rows under namespace = 'lkgp' after the combo no longer existed.

Root Cause

LKGP pins are stored as key = "${comboName}:${modelId}". Existing cleanup helpers either delete one exact comboName:modelId pair (clearLKGP()), all LKGP (clearAllLKGP()), or pins by provider connection id (deleteLKGPByConnectionIds()). deleteCombo() only executed DELETE FROM combos WHERE id = ?, so it never removed rows that belonged exclusively to the deleted combo name.

Solution

  • Add a combo-name LKGP cleanup helper that deletes keys under the exact ${comboName}: namespace prefix.
  • Escape %, _, and \\ in the SQLite LIKE pattern and rely on the : delimiter to avoid collateral deletion.
  • Run combo-row deletion and LKGP-row deletion in one SQLite transaction, then invalidate LKGP read-cache entries for the deleted keys.

Invariant

DELETE COMBO X → REMOVE LKGP STATE OWNED BY X

AND

UNRELATED LKGP STATE → PRESERVED

Forbidden state:

DELETED COMBO → ORPHANED LKGP REFERENCE

Regression Evidence

  • Before the fix, tests/unit/combo-delete-lkgp-cleanup-12326.test.ts failed: deleted combo LKGP rows still returned { provider: 'berry', connectionId: 'conn-1' } instead of null.
  • After the fix, the focused regression test passes.
  • Sabotage check performed by temporarily reverting the deleteCombo() cleanup while keeping the test: focused test failed again; after restoring the fix it passed again.

Behavior Proof

  • deleted combo pins removed
  • unrelated combo pins preserved
  • prefix-sharing names preserved
  • cache invalidated correctly for deleted keys
  • nonexistent/no-pin behavior remains safe

Validation

  • node --import tsx/esm --test tests/unit/combo-delete-lkgp-cleanup-12326.test.ts
  • node --import tsx/esm --test tests/unit/combo-delete-lkgp-cleanup-12326.test.ts tests/unit/combo-cache-invalidation.test.ts
  • npm run typecheck:core
  • npx eslint src/lib/db/repositories/sqliteComboRepository.ts src/lib/db/settings/lkgp.ts src/lib/db/settings.ts tests/unit/combo-delete-lkgp-cleanup-12326.test.ts
  • git diff --check

Scope / Risk

Low scope: persistence cleanup only. No routing-provider, circuit-breaker, API-key ACL, authz, or provider-plugin behavior changed.

Compatibility

No schema migration and no public LKGP contract change. Existing LKGP key format is preserved.

Fixes #12326

@diegosouzapw
diegosouzapw merged commit 11e1c79 into diegosouzapw:release/v3.8.51 Sep 4, 2026
3 checks passed
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
Validado em lote numa worktree combinada com os 6 PRs destas duas levas sobre o tip de `release/v3.8.51`: os seis boardaram **sem um único conflito**, `typecheck:core` limpo e **54/54** nos 7 arquivos de teste que trazem.

O drift de `i18n:check` (`docs/security/GUARDRAILS.md`, `STEALTH_GUIDE.md` — source-changed) foi medido também no tip puro e é idêntico: base-red pré-existente, não desta leva.
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.

fix(backend): deleteCombo() leaves orphaned LKGP entries in key_value

2 participants