На прикладі Money Tracker. Це не теоретичний edge case - це 1-2% мобільних сесій у поганій мережі.
У нас є Ledger - файл колективної пам’яті проекту. Туди потрапляють уроки, «виплачені» попередніми Heist-ами. Наступний агент читає їх ДО того, як писати код.
Один з найдорожчих рядків там:
«Never delete refresh tokens on first use; mark them as consumed.»
Звідки він з'явився 👇
Auth-Heist.
Реєстрація + логін + refresh-token rotation.
Класична схема: при оновленні access-token-у refresh теж ротується. Старий стає недійсним. Виглядає безпечно.
Перша імплементація виглядала логічно:
🔺 клієнт приходить з refresh-token;
🔺 сервер одразу видаляє його з БД
🔺 видає новий;
🔺 повертає клієнту.
Проблема знайшлась у тестах race condition.
Сценарій:
🔴 Клієнт надсилає запит А з refresh-токеном.
🔴 Сервер видаляє токен, видає новий, відповідає.
🔴 Відповідь губиться у мережі - timeout або обрив.
🔴 Клієнт ретраїть з тим самим refresh-токеном.
🔴 Сервер: "Цього токена немає в БД"
😡Logout. Юзер злий.
Що означає: погана ідея пройшла гейт. Дорого виправляли.
Рішення: не видаляти токени. Маркувати як consumed. У БД лишається запис, при ретраї сервер бачить consumed=true і повертає кеш попередньої відповіді або новий refresh, якщо вікно ретраю активне.
І найважливіше 👇
Цей рядок тепер у Ledger, у файлі, який Reconnaissance ОБОВ'ЯЗКОВО читає до кожного нового Heist-у з auth-тематикою.
Тобто наступний агент, який торкатиметься токенів, отримає це як ввідні. Без шансу пропустити.
❗️Чому це важливо
Більшість команд "вчаться на своїх помилках" неформально:
🚩Це означає - не вчаться.
🚩Урок живе в голові того, хто помилився.
🚩Звільнився - урок зник.
🚩Прийшов новий розробник - повторив помилку.
Ledger - це механізм, який робить інституційну пам'ять примусовою❗️
Не "було б добре пам'ятати", а "наступний агент не зможе працювати, не прочитавши".
Скільки коштує ваше “ми це вже проходили, але я забув”?
#gangsta_agents #SDD #VibeCoding #SpecDrivenDevelopment