15 KiB
Бэклог платформы (зонный)
Ведёт зона
platform/(решение владельца 02.08, D39.84: фронт и платформа держат СВОИ бэклоги; единый бэклогdocs/PROGRESS.mdостаётся трекером движка/полигона/доков и фронт/платформа-строк не принимает). Нормы те же: ID стабилен навсегда, каждая петля получает диспозицию. Запросы к ДВИЖКУ сюда не пишутся — они заходят строками единого бэклога через оркестратора (пример: строки 99–102). Засеян оркестратором при лендинге D39.84 — дальше правит платформа-сессия.
Диспозиции после P1 (05.08) — в журнале зоны, раздел «Диспозиции бэклога зоны» (
docs/platform-PROGRESS.md). Коротко: П-6 и П-8 ЗАКРЫТЫ, П-7 закрыт по схеме и операциям (постановка холда воркером — часть П-1), П-4 отменён и поглощён П-7, П-5 переопределён под кредитную модель и ждёт правки спеки, П-1 продолжена, П-2/П-3 не трогали. Дублировать их здесь не стали — у строки один источник истины.
| ID | Хвост | Вес | Источник |
|---|---|---|---|
| П-1 | HTTP/SSE-слой и сервисная обвязка (экс-строка 96 единого бэклога): read-API поверх готовых OpenReadOnly-путей движка; SSE-события ПУШИТ воркер, фронт read-model не опрашивает (каждый read-вызов движка — дорогой ре-ингест, до строки 100 единого); аутентификация ратифицирована D39.84: одна серверная сессия в Postgres — __Host-кука браузеру · Authorization: Bearer десктопу/CLI · principal создаётся ТОЛЬКО в middleware, CSRF только на cookie-пути; ⚠ порядок деплоя: read-путь движка схему НЕ мигрирует (store.go:135-143, «schema vN … expects vM») — после апгрейда бинарника по каждой книге первой идёт write-команда; форма потока ратифицирована D39.85 (docs/research/23): воркер-обёртка платформы супервайзит процесс tmctl, ингестит NDJSON-события идемпотентным апсертом (run_id, seq) в Postgres (Reporting Database, не полный CQRS), SSE — из Postgres; ре-синк на обрыве — tmctl status --json; живой SQLite движка НЕ читать (анти-паттерн, аргументы в research/23 §4); ревью-гард: путь Go-модуля платформы никогда не вкладывать под textmachine/backend/* |
Ф3, после контракта API (строка 95 единого) | D39.81, D39.84, D39.85, STACK_DECISIONS §5 |
| П-2 | Глобальный брокер рейт-лимитов провайдеров (экс-строка 97): гарды движка per-процесс (pipeline/ratelimit.go:11, mistral ~48% отказов под параллелизмом), а лимит провайдера — на ВЕСЬ аккаунт: N прогонов = N независимых гардов против общего лимита; воркер отпрашивается у платформы перед вызовом |
ДО второго параллельного пользователя | D39.81, D39.84 |
| П-3 | Очередь и конкурентность по книге: River на том же Postgres, сериализация по book_id + пиннинг книги к одному хосту на MVP, лизы book_leases с heartbeat — вежливое ожидание вместо аварии |
Ф3-пак платформы | STACK_DECISIONS §5, D39.84 |
| П-4 | Учёт токенов/денег per-user + бюджет-гейт ДО старта задачи (сырьё уже считает движок: request_log + internal/ledger; помнить: леджер = нижняя граница — строка 78 единого) |
Ф3-пак платформы | platform/README, D39.84 |
| П-6 | OAuth-вход популярных провайдеров (Google первым) + модель аккаунта (направление владельца 04.08): authorization code + PKCE, валидация ID-токена, связывание аккаунта по ПОДТВЕРЖДЁННОЙ почте; собственная серверная сессия сохраняется (D39.84) — OAuth даёт только СОБЫТИЕ входа. Форма и библиотеки — по ресёрч-пакету направления (ратифицирует оркестратор); писатель куки с __Host-атрибутами и dev-профиль — здесь же (PD-8) |
P1, вместе с П-1 | владелец 04.08 |
| П-7 | Кредитный баланс и фри-тир (решения владельца 05.08; ПРОДАЖИ НЕТ — бета на предоплаченных ключах владельца): append-only леджер в целых микро-долларах, грант фри-тира из админки (дефолт $5, настраиваемый), холд ДО спавна прогона + пер-книжный потолок движку (жёсткий стоп исполняет движок), расчёт на границе попытки. ⚠ Окон с обнулением НЕТ — баланс, а не подписка: черновик usage_windows в подписочной форме заменяется. Платёжный провайдер не проектируется до решения продавать. Разбор — docs/PLATFORM_DIRECTION.md §2 |
P1+, после П-6 | владелец 04–05.08 |
| П-8 | Минимальная админ-поверхность: начислить/списать кредиты аккаунту (одна запись леджера), посмотреть баланс и состояние прогонов. Защищённая ручка либо CLI — форму предлагает сессия. Без неё фри-тир неуправляем | вместе с П-7 | владелец 05.08 |
| П-5 | API лимитов/использования + оповещение стопа по потолку (решение владельца 04.08, D39.100/ПТ-35, механизм «как Claude Code»): страница лимитов в настройках читает СТАТУС использования (не суммы — деньги на провод не идут, D39.84); стоп по потолку → статус paused + оповещение «перевод остановлен: лимиты исчерпаны»; сырьё у движка есть (request_log/ledger, потолки конфига), форму API предлагает P0 |
Ф3, вместе с П-1 | D39.100, ПТ-35, контракт К-8 |
| П-9 | Загрузка книги POST /books (multipart) — единственная ручка контракта 0.2.0, которую пак раннера НЕ взял. Причина названа, а не умолчана: это не «ещё один хендлер», а хранилище (куда лёг файл, кто его чистит при отказе), разбор (статусы uploading/parsing/rejected существуют в схеме и ни одним писателем не заполняются), каталог проекта движка (кто пишет book.yaml — платформа его НЕ правит, D39.110) и пер-маршрутный потолок тела вместе с тестом, которого ждёт PD-72. Пока её нет, книги заводятся дев-инструментом tmplatformctl book add, и библиотека читает их так же, как читала бы загруженные: read-model один. ⚠ PD-72 закрывается ВМЕСТЕ с этой ручкой, не раньше — ИСПОЛНЕНО P5 (11.08), с одной НАЗВАННОЙ половиной на ратификации: ручка построена потоково (r.MultipartReader, пер-маршрутный потолок тела, свой дедлайн чтения), хранилище — каталог книги под TM_PLATFORM_BOOKS_DIR, статусы uploading → parsing → not_started | rejected получили писателей, разбор зовёт tmctl manifest, PD-72 закрыт своим тестом. НЕ построено и вынесено вопросом в журнал: кто пишет стартовый book.yaml при интейке (D39.110 §2b) — шов books.ErrNotProvisioned назван, без конфигурации книга отказывает разбором → развилка РЕШЕНА D39.130: бета = форма Б (стройка = П-14); движковая форма В (tmctl init) = строка 170 единого |
Ф3, следующий пак | сессия P4 (границей промта D39.119 §5а), исполнено P5 |
| П-10 | Честная оценка «$/глава» от ДВИЖКА. Сейчас ставка — константа платформы ($0.03, провенанс exp08 v2 через D30.4, STACK_DECISIONS §20), и это осознанная бета-мера: движковой поверхности оценки не существует, а выдумывать её запрещено. Ставка решает только ДЛИНУ шкалы (деньги защищены холдом и потолком движка), но на книге, которая заметно дороже или дешевле средней, шкала врёт пользователю о том, сколько глав он покупает. Нужна оценка от движка по конкретной книге — запрос уходит строкой ЕДИНОГО бэклога через оркестратора, не сюда |
когда-нибудь (до первого платящего) | сессия P4 |
| П-11 | Наблюдаемость раннера. Метрик и трейсинга в зоне нет вовсе (грепнуто: ни prometheus, ни otel, ни expvar, ни pprof), а у раннера появились величины, которые без них не видны: глубина очереди, возраст незакрытых холдов, число прогонов в карантине, отставание тейлера, длительность свипа. Сегодня всё это читается только глазами по логам и SQL. Связано с PD-115 (у зоны нет внешнего эталона ни по одной оси, кроме безопасности) — ИСПОЛНЕНО P5 (11.08): prometheus/client_golang v1.24.1 на отдельном слушателе TM_PLATFORM_METRICS_ADDR; глубина очереди · возраст самого старого открытого холда · карантины · отставание тейлера · книги в интейке · длительность свипа и счётчик недоведённых проходов · запросы и задержки по паттерну маршрута. Ось наблюдаемости получила внешний эталон (практики именования Prometheus + золотые сигналы, ENGINEERING_STANDARDS §2) — половина PD-115 |
Ф3 | сессия P4, исполнено P5 |
| П-12 | Квота интейка и ретеншен отклонённых книг. POST /books даёт аутентифицированному аккаунту писать на диск оператора: один аплоад ограничен (64 МиБ), число аплоадов — ничем. Отклонённая по вине источника книга каталог теряет, отклонённая по вине деплоя — сохраняет намеренно, и не чистит их никто. Нужны лимит книг на аккаунт (сколько книг входит во фри-тир — продуктовая политика, не инженерная) и свип ретеншена. Строка регистра — PD-175 |
до первого чужого пользователя | сессия P5 |
| П-13 | Оценка размера книги в символах — у ДВИЖКА. character_count контракта платформа считает потоково на приёме (байты, не являющиеся продолжением UTF-8), что точно для UTF-8 и приблизительно для GB18030/UTF-16, которые движок принимает и декодирует сам. Манифест несёт source_bytes и encoding, но не число символов. Запрос уходит строкой ЕДИНОГО бэклога через оркестратора; строка регистра — PD-177 → строка 171 единого заведена 14.08 |
когда-нибудь | сессия P5 |
| П-14 | Стройка интейка формы Б (ратификация D39.130): при создании книги платформа рендерит стартовый book.yaml из деплой-шаблона (шов books.ErrNotProvisioned уже назван P5); требования к полям — читать backend/internal/config/book.go как справочник, шаблон — деплой-артефакт оператора, не код; при приходе формы В (строка 170 единого, tmctl init) рендер заменяется вызовом движка |
следующее касание зоны | ратификация D39.130 (приёмка P5) |