Skip to content

[Бъг]: 0000_init.sql е редактирана след прилагане — мълчаливо разминаване на схемата (HTTP 500 на страницата на договора) #288

Description

@nikolaypaskov

Какво се случва

packages/db/migrations/0000_init.sql е миграция, която отдавна е приложена, но оттогава е редактирана на място многократно. D1 отчита миграциите по име на файл в таблицата d1_migrations и никога не преприлага файл, който вече е записан там. Затова всяка среда, създадена преди дадена редакция, остава без добавеното от нея — а wrangler d1 migrations apply отчита всички миграции като приложени.

Резултатът е схема, която се разминава мълчаливо. На база данни, създадена на 17.06.2026 г. и след това доведена „до последна версия“, липсват:

  • таблиците authority_joint_participation и contract_co_authorities;
  • колоните contracts.ordering_unit_name и tenders.ordering_unit_name (добавени с af4917e).

Заради липсващата колона GET /contracts/:id и GET /contracts/:id.json връщат HTTP 500:

D1_ERROR: no such column: c.ordering_unit_name at offset 557: SQLITE_ERROR

Нито една номерирана миграция не добавя тази колона — тя съществува само в редактирания 0000_init.sql.

Защо CI не го хваща

packages/db/src/migrations.test.ts изгражда схемата, като преиграва цялата верига върху нова база данни — това винаги минава. Няма проверка за целостта (checksum) на вече приложените миграции и никъде в AGENTS.md или CONTRIBUTING.md не е записано, че приложена миграция не се редактира.

Стъпки за възпроизвеждане

  1. Създайте D1 по 0000_init.sql отпреди комита af4917e (или използвайте среда, създадена преди него).
  2. Изпълнете wrangler d1 migrations apply sigma --local → отчита всички миграции с ✅.
  3. Отворете страницата на кой да е договор → HTTP 500.

Проверка кои среди са засегнати

За всяка среда поотделно (sigma-blue, sigma-green, staging):

SELECT (SELECT COUNT(*) FROM pragma_table_info('contracts') WHERE name='ordering_unit_name') AS c_col,
       (SELECT COUNT(*) FROM pragma_table_info('tenders')   WHERE name='ordering_unit_name') AS t_col,
       (SELECT COUNT(*) FROM sqlite_master WHERE type='table'
          AND name IN ('authority_joint_participation','contract_co_authorities')) AS tables_present;

При изправна схема очакваният резултат е 1, 1, 2. По-малко означава разминаване.

Предложение за поправка

  1. Поправка на всяка засегната среда поотделно, а не чрез миграция. SQLite няма ADD COLUMN IF NOT EXISTS, а повторното добавяне на съществуваща колона е грешка (duplicate column name). Затова обща миграция 0006 би счупила всяка среда, създадена след af4917e — включително всяка нова. Проверете схемата и добавете само липсващото; CREATE TABLE IF NOT EXISTS за двете таблици е безопасно, ALTER TABLE … ADD COLUMN не е.
  2. Миграциите да станат само за добавяне (append-only) — правилото да се запише в AGENTS.md и CONTRIBUTING.md.
  3. migrations.lock с checksum на всеки файл и тест, който пада при промяна на вече записан хеш. Това е контролът, който реално налага т. 2 — в духа на съществуващата проверка за разминаване при CANONICAL_QUERY_PARAMS.
  4. Проверка за разминаване на схемата при деплой срещу целевата D1. scripts/compare-served-sqlite.mjs вече съдържа повечето от нужното.

Проверено: добавянето на липсващите две колони и две таблици възстановява коректното поведение — GET /contracts/:id отговаря с 404 вместо 500.

Къде се проявява

Уеб (sigma.midt.bg) и @sigma/db / миграциите. Проявява се само в среди, създадени преди съответната редакция; нова среда е изрядна, което и прикрива проблема.

Среда

Открито при преглед на кода и възпроизведено локално върху f72306c (production build през wrangler dev --local, D1 със 100 002 договора). Не е проверявано срещу разгърнатите среди — заявката по-горе отговаря на този въпрос.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugНещо не работиpriority: highВисок приоритет

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions