187 lines
20 KiB
Markdown
187 lines
20 KiB
Markdown
# Промт: платформа, пак 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.go`** — `settlePhase`, `deferItem`, `StalledAfter`; и
|
||
**`platform/internal/pgstore/runs.go`** — `StalledRuns` (`: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-380`…`PD-383`) — родня
|
||
`PD-379`, но **сознательно оставлена**: сначала закрыть уязвимость, потом чистить её окрестность,
|
||
иначе пак распухнет вокруг самого срочного · `PD-375`, `PD-377`, `PD-378`, `PD-386`…`PD-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. **Адверсариальный проход по своей готовой работе — заказан; глубину и веер выбираешь сама.**
|
||
⚠ Куда смотреть в ЭТОМ паке: что видит тот, у кого отозвали доступ · может ли починка вернуть холд дважды или чужой · поток под нагрузкой.
|
||
Дефекты, которые внёс сам пак, называй первыми — приёмке они не видны.
|
||
⚠ **Fable 5** — обычно хватает одного-двух агентов, но это РЕКОМЕНДАЦИЯ, не потолок: веер под предмет выбирает сессия. Модель задавай ЯВНО и знай, сколько их работает.
|
||
|
||
## §5. Оси ревью — 1–3, вправе заменить с аргументом
|
||
|
||
1. **Ось «что видит атакующий»** — не оператор и не тест: тот, у кого отозвали доступ.
|
||
2. **Ось денег:** может ли починка `PD-385`/`PD-391` дважды вернуть один холд или вернуть чужой.
|
||
3. **Ось «поток под нагрузкой»:** пере-проверка сессии на каждом кадре — это запрос к стору на каждый
|
||
тик; не превращается ли гашение в новую стоимость.
|
||
|
||
## §6. Записка-план, комплектность
|
||
|
||
**До правок** — записка-план в зонном журнале. **В конце** — таблица комплектности против §3: строка →
|
||
что сделано → каким ИСПОЛНЕНИЕМ подтверждено. Слово вместо команды = пункт НЕ сделан.
|
||
|
||
## §7. Эхо-протокол старта
|
||
|
||
ДО работы — ≤10 строк: **скоуп · инварианты · не-делать**. Первое действие — вписать свой блок в файл
|
||
канала (§10), сразу второе — послать мне эхо.
|
||
|
||
## §8. Obstacle — обязательная секция
|
||
|
||
**«Что НЕ удалось и что НЕ проверено»** отдельной секцией, не россыпью.
|
||
|
||
## §9. Канал вопросов и твоё право отказаться
|
||
|
||
Конфликт промта с кодом или доками — **пинг, не интерпретация в свою пользу**.
|
||
⚠ **У тебя есть право сказать «этого делать не надо» — с аргументом.** За последние сутки исполнители
|
||
опровергли ЧЕТЫРЕ моих заказа и все четыре раза были правы. Отказ с разбором дороже послушного
|
||
исполнения.
|
||
⚠ **Тесты и гейты не подгонять под зелень** (D39.121).
|
||
|
||
## §10. Как со мной связаться
|
||
|
||
**Адрес — в файле `/tmp/textmachine-channel`.** Впиши свой блок первым делом, чужие не трогай.
|
||
⚠ **Канала нет ⇒ НЕ искать:** вопрос секцией в отчёт, работа продолжается.
|