textmachine/docs/PLATFORM_P11_SESSION_PROMPT.md

20 KiB
Raw Blame History

Промт: платформа, пак P11 — отзыв сессии перестаёт быть словом, застрявшие деньги перестают быть невидимыми

Выдан оркестратором №19, 28.08.2026. Пак идёт ПАРАЛЛЕЛЬНО бэкендовому. ⚠ ФАЙЛЫ вы не делите (модули отдельные, платформа кода движка не компилирует — проверено), но ШОВ общий и ведётся руками: таблица кодов выхода · argv литералами · аллоулист status --json. Бэкендовый пак трогает первые две. Увидишь расхождение — ПИНГ, батарея его не поймает по построению. Источник состава — читающий пак P8-REVIEW (D39.159): 24 строки регистра, открытых 23. Этот пак берёт СЕМЬ, и почему именно их — §3.5.

§0. Какая проблема и что решит твой результат

1. «Выйти везде» не выключает уже открытый канал — PD-379, единственный открытый major уязвимости. Аутентификация происходит РОВНО ОДИН РАЗ, на входе в guard; дальше streamEvents уходит в pump, и цикл до конца соединения строку сессии не смотрит НИ РАЗУ. Значит logout, logout-all, tmplatformctl revoke и оба потолка сессии (idle и абсолютный) открытый GET /v0/books/{bookId}/events не прекращают.

Это пере-проверено ТРИЖДЫ независимо (финдер · рефутер в отдельной копии · координатор пака): revoke --user отчитался «revoked 4 sessions», новый запрос той же кукой дал 401, а тот же поток через 9 секунд ПОСЛЕ отзыва отдал настоящий кадр данных. На демоне с пятисекундным idle и десятисекундным абсолютным потолком поток жил ещё сорок секунд.

Бьёт по ОБЪЯВЛЕННОЙ норме, а не по вкусу: ASVS 5.0 7.4.1 — требование УРОВНЯ 1 при объявленном зоной L2. И STACK_DECISIONS §13 отказывается от лимита одновременных сессий именно в обмен на мгновенный отзыв — то есть цена уже заплачена, а товар не получен.

2. Застрявшие деньги невидимы ТАМ, КУДА ПОСЫЛАЕТ ЛОГ — PD-385, второй major.Абсолюта «невидим вообще» тут НЕТ — он опровергнут рефутером прошлого пака, и первая редакция этого промта его по ошибке повторяла: холд ВИДЕН через tmplatformctl balance --user, гейдж старейшего открытого холда растёт, tmplatformctl books пишет «WHY NOT: unsettled hold». Слепы ТРИ поверхности ПОРОГА, и терминальной ручки нет. Живая проба на состоянии, выращенном штатными путями: runs --stalled отвечает «no run is failing to reconcile», runs — «no run is live», run abandon — «is not a live run», гейдж 0 — при этом в базе settled_at NULL, пять неудач реконсиляции и открытая резервация на 90 000 микро-USD.

Что решит результат: отзыв сессии станет действием, а не словом; а деньги, застрявшие в расчёте, станут видны тому, кого лог за ними и посылает.

§1. Зона записи и git

Твоя зона — platform/. Итоги, находки, вопросы — зонный журнал platform/docs/platform-PROGRESS.md.

  • Ты НЕ коммитишь. Лендит оркестратор после адверсариальной приёмки.
  • backend/ НЕ ТРОГАТЬ. Там параллельно работает бэкенд-пак «деньги». Нужна правка там — ПИНГ.
  • docs/ — не твоя зона. Нужна правка канона контракта — опиши ПРЕДЛОЖЕНИЕМ в своём журнале, правлю я: канон и константа версии обязаны сойтись в ОДНОМ коммите, а коммичу я.
  • Стендовый tmctl собирай из ЗАФИКСИРОВАННОЙ копии backend/, если он понадобится: рабочее дерево сейчас правит параллельная сессия, и бинарь из него мерит непонятно что. Без него живые тесты просто уходят в SKIP — это нормально и батарея остаётся зелёной.
  • В дереве незакоммиченная работа полигона (20 позиций) — не касаться.

§2. Карта чтения — ≤5 позиций, ЗАКОН

  1. platform/docs/DEFECT_REGISTER.md, строки PD-379 · PD-385 · PD-384 · PD-391 · PD-394 · PD-397тела читать целиком, там траектории и живые пробы предыдущего пака.
  2. platform/internal/httpapi/stream.go целиком + guard/Require в auth — предмет PD-379.
  3. platform/internal/runs/reconcile.gosettlePhase, deferItem, StalledAfter; и platform/internal/pgstore/runs.goStalledRuns (:406) и AbandonRun (:452). ⚠ AbandonRun живёт в pgstore, а не в internal/runs — первая редакция приписала его не туда.
  4. platform/docs/STACK_DECISIONS.md §13 — там объявлен размен «нет лимита сессий В ОБМЕН на мгновенный отзыв», и §-норма уровня ASVS.
  5. docs/architecture/05-decisions-log.md, тело D39.159 (греп ^## D39.159) — акт приёмки читающего пака, откуда взялись эти строки.

§3. Состав пака — ШЕСТЬ строк, две группы

§3.1. PD-379 — отзыв обязан гасить открытый поток. ЗАКАЗ, форма свободна

Заказано: после logout / logout-all / revoke, а равно по истечении АБСОЛЮТНОГО потолка сессии, уже открытый поток событий прекращается. Idle-потолок из заказа ИСКЛЮЧЁН, и это поправка (нашёл опровергатель): окно бездействия скользит только на ЗАПРОСЕ (auth/middleware.go:63-66), а SSE — ОДИН запрос на всю жизнь соединения. Значит поток по определению никогда не трогает свою сессию, и гашение по idle убивало бы поток под АКТИВНЫМ пользователем — это регресс, а не починка.

Свободен и обязан обосновать — ГДЕ проверять.И я зря пугал ценой: pump уже зовёт ReadStream на КАЖДОЙ итерации (stream.go:169; комментарий :29-33 сам считает «два индексированных запроса в секунду на соединение»), так что проверка сессии кладётся в тот же тик и лишнего запроса НЕ создаёт. Значит «окно» заводить не обязательно — первая редакция гнала тебя к нему страхом, которого нет. Если окно всё же остаётся — назови его ЧИСЛОМ.

Сигнала «тебя выгнали» в протоколе НЕТ, и это придётся решать. Заголовок ответа уходит ДО pump (stream.go:84-85), поэтому кодом ответа уже не скажешь; терминальных событий ровно два — end («книга закончена») и resync_required («пере-синхронизируйся»), и оба скажут клиенту неправду. Новое имя события — правка КАНОНА, которую §1 тебе запрещает. Поэтому: форму назови ПРЕДЛОЖЕНИЕМ в журнале, я впишу в канон и подниму версию; в коде реализуй так, чтобы имя менялось одной строкой. ⚠ И не сломай догон: hello несёт позицию, гашение обязано быть отличимо от обрыва сети.

§3.2. PD-385 — застрявший расчёт обязан быть виден. ЗАКАЗ

Заказано: прогон с недоведённым расчётом виден операторской поверхности, на которую его посылает лог-строка, и с ним можно что-то сделать.

Рефутер предыдущего пака ОПРОВЕРГ заголовочный абсолют «невидим» — тело строки это несёт. Прочти тело целиком и не чини то, что уже видно: заказ про КОНКРЕТНЫЙ слепой угол, а не про «сделать всё видимым».

§3.3. Денежная группа — четыре строки, все про ОДНО

PD-384 (расчёт, упавший ДЁШЕВО, не считается нигде) · PD-391 (run abandon не возвращает холд «на ближайшем свипе») · PD-394 (гард отрицательного расхода в Settle не запинен) · PD-397 (два самых сильных денежных инварианта объявлены, но не запинены).

Заказано: каждая закрыта либо ПИНОМ, либо строкой с причиной, почему не закрывается. ⚠ Три из четырёх — про ПИНЫ, а не про код. Это не «мелочь для галочки»: PD-397 прямо говорит, что сильнейшие денежные инварианты держатся на слове. Пин, посаженный мутацией, и есть предмет.

§3.4. Свободная форма и право пере-формулировать

Тела строк писаны неделю назад читающим паком. Дерево с тех пор двигалось трижды (D39.162, D39.166 и фикс-раунды). Если строка описывает состояние, которого уже нет, — это находка, скажи её, а не чини по букве. Сегодня такое случалось: строка регистра держалась на основании, снесённом чужим паком.

§3.5. Чего в паке НЕТ — пропуски ПОДПИСАНЫ

Счёт первой редакции был неверен (поправка опровергателя): строк пака 24, закрыта только PD-398, значит открытых ДВАДЦАТЬ ТРИ. Беру СЕМЬ.

  • Взято: обе major (уязвимость и невидимые деньги) плюс денежная группа, которая с PD-385 составляет ОДИН предмет — «деньги, застрявшие или не посчитанные».
  • PD-376 ДОБАВЛЕНА — первая редакция не назвала её НИ ВО ВЗЯТЫХ, НИ В ПРОПУСКАХ, а это нарушение нормы «пропуски подписаны», и на самом дешёвом пункте: строка ДЕНЕЖНАЯ (PD-159 стоит fixed, но её пин доказывает свойство СЛАБЕЕ, чем читается — мутация проходит батарею), а готовый пин уже написан ФАЙЛОМ в platform/docs/p8-review/axis1-money/. Возьми и проверь посадкой, что он ловит именно ту мутацию.
  • НЕ взято и почему: группа телеметрии (PD-389, PD-390, PD-392, PD-393) — отдельный предмет, ей нужен свой пак и своя ось ревью · группа сессий и кук (PD-380PD-383) — родня PD-379, но сознательно оставлена: сначала закрыть уязвимость, потом чистить её окрестность, иначе пак распухнет вокруг самого срочного · PD-375, PD-377, PD-378, PD-386PD-388, PD-395, PD-396 — россыпь minor/info, идёт следующим паком. ⚠ PD-398 первая редакция включила в этот список ОШИБОЧНО — она уже fixed (приёмка 27.08).
  • Увидишь по дороге, что невзятая строка чинится ОДНОЙ строкой внутри твоего же диффа — бери и скажи. Запрет тут не ради чистоты, а ради размера.

§4. Самопроверка ИСПОЛНЕНИЕМ — «перечитал сам» её не удовлетворяет

  1. Батарея зоны под -race С ЖИВЫМ Postgres, линтер 0 issues; числа — с командами. ⚠ TM_PLATFORM_TEST_DSN ставить ОБЯЗАТЕЛЬНО: без него значительная часть батареи уходит в SKIP, а зелень рапортуется всё равно. Число пропусков посчитай КОМАНДОЙ и приведи с DSN и без.
  2. PD-379 доказывается ЖИВЬЁМ и ДВУМЯ РАЗДЕЛЬНЫМИ сценариями — первая редакция склеивала их в один, и склейка делала регресс зелёным (нашёл опровергатель): реализация «таймер до абсолютного потолка» гасит поток по потолку, сценарий зелен, а ОТЗЫВ не починен. (а) ДЛИННЫЕ потолки + revoke → доказывает отзыв. (б) короткие потолки БЕЗ отзыва → доказывает потолок. ⚠ Юнит на «функция проверки вызвана» — вырожденный: сегодня она вызвана один раз на входе, и это ровно дефект.
  3. PD-385 доказывается СОСТОЯНИЕМ, выращенным штатными путями (интейк → HTTP-старт → отказ спавна → abandon), как его и нашли, а не подложенной строкой в базе.
  4. Свои посадки мутаций: минимум по одной на пункт; вердикт — по ДЕЛЬТЕ и ТОПИЧНОСТИ упавшего теста, не по цвету батареи.
  5. Адверсариальный проход по своей готовой работе — заказан; ГЛУБИНУ и веер выбираешь сама под предмет. Направление ниже — моё, регламент — нет. ⚠ Куда смотреть в ЭТОМ паке: что видит тот, у кого отозвали доступ · может ли починка вернуть холд дважды или чужой · поток под нагрузкой. Дефекты, которые внёс сам пак, называй первыми — они самые ценные и приёмке не видны. ⚠ Тяжёлая модель — один агент максимум, на самую тяжёлую линзу; модель задавай ЯВНО, порождать своих агентов запрещай.

§5. Оси ревью — 13, вправе заменить с аргументом

  1. Ось «что видит атакующий» — не оператор и не тест: тот, у кого отозвали доступ.
  2. Ось денег: может ли починка PD-385/PD-391 дважды вернуть один холд или вернуть чужой.
  3. Ось «поток под нагрузкой»: пере-проверка сессии на каждом кадре — это запрос к стору на каждый тик; не превращается ли гашение в новую стоимость.

§6. Записка-план, комплектность

До правок — записка-план в зонном журнале. В конце — таблица комплектности против §3: строка → что сделано → каким ИСПОЛНЕНИЕМ подтверждено. Слово вместо команды = пункт НЕ сделан.

§7. Эхо-протокол старта

ДО работы — ≤10 строк: скоуп · инварианты · не-делать. Первое действие — вписать свой блок в файл канала (§10), сразу второе — послать мне эхо.

§8. Obstacle — обязательная секция

«Что НЕ удалось и что НЕ проверено» отдельной секцией, не россыпью.

§9. Канал вопросов и твоё право отказаться

Конфликт промта с кодом или доками — пинг, не интерпретация в свою пользу. ⚠ У тебя есть право сказать «этого делать не надо» — с аргументом. За последние сутки исполнители опровергли ЧЕТЫРЕ моих заказа и все четыре раза были правы. Отказ с разбором дороже послушного исполнения. ⚠ Тесты и гейты не подгонять под зелень (D39.121).

§10. Как со мной связаться

Адрес — в файле /tmp/textmachine-channel. Впиши свой блок первым делом, чужие не трогай. ⚠ Канала нет ⇒ НЕ искать: вопрос секцией в отчёт, работа продолжается.