[PIX-11101] feat(blog): агентский endpoint публикации одобренных постов #839

Merged
andrei merged 2 commits from agent-cto/pix-11101 into master 2026-06-21 10:01:48 +00:00
Owner

Что сделано

Добавляет POST /api/agent/blog/:id/publish — отдельный endpoint для публикации постов, уже одобренных CEO.

Ключевые свойства:

  • Аутентификация через AGENT_BLOG_PUBLISH_TOKEN (отдельный токен, не admin credentials)
  • Timing-safe сравнение (crypto.timingSafeEqual, аналогично adminSecret.ts)
  • Агент НЕ может одобрять посты — сервисный слой блокирует публикацию без approvedAt (HTTP 409)
  • POST /admin/blog/:id/approve остаётся JWT+2FA, board-only
  • Endpoint недоступен пока токен не настроен (HTTP 503)

Зачем

CEO отклонил запрос на admin credentials (approval 0e59d98d). Это минимальный, безопасный архитектурный путь: агент публикует только то, что CEO уже одобрил. Разблокирует PIX-7298.

Что нужно от CEO

  1. Сгенерировать токен: openssl rand -hex 32
  2. Добавить в prod env: AGENT_BLOG_PUBLISH_TOKEN=<токен>
  3. Сообщить токен агентам PIX-7298 через Paperclip secrets/env

План тестирования

  • 5 новых тестов, 5/5 passed (blog.agent-publish.test.ts)
  • 189 тестов суммарно, 189/189 passed
  • tsc --noEmit: 0 ошибок (api + app)
  • app build:

Где могу ошибаться

  • Если prod env читается другим механизмом (секреты через vault/docker env) — токен нужно добавить там
  • Нет rate-limit отдельно на этот endpoint (наследует adminSensitiveLimiter)
## Что сделано Добавляет `POST /api/agent/blog/:id/publish` — отдельный endpoint для публикации постов, уже одобренных CEO. **Ключевые свойства:** - Аутентификация через `AGENT_BLOG_PUBLISH_TOKEN` (отдельный токен, не admin credentials) - Timing-safe сравнение (crypto.timingSafeEqual, аналогично adminSecret.ts) - Агент НЕ может одобрять посты — сервисный слой блокирует публикацию без `approvedAt` (HTTP 409) - `POST /admin/blog/:id/approve` остаётся JWT+2FA, board-only - Endpoint недоступен пока токен не настроен (HTTP 503) ## Зачем CEO отклонил запрос на admin credentials (approval 0e59d98d). Это минимальный, безопасный архитектурный путь: агент публикует только то, что CEO уже одобрил. Разблокирует PIX-7298. ## Что нужно от CEO 1. Сгенерировать токен: `openssl rand -hex 32` 2. Добавить в prod env: `AGENT_BLOG_PUBLISH_TOKEN=<токен>` 3. Сообщить токен агентам PIX-7298 через Paperclip secrets/env ## План тестирования - [x] 5 новых тестов, 5/5 passed (blog.agent-publish.test.ts) - [x] 189 тестов суммарно, 189/189 passed - [x] tsc --noEmit: 0 ошибок (api + app) - [x] app build: ✅ ## Где могу ошибаться - Если prod env читается другим механизмом (секреты через vault/docker env) — токен нужно добавить там - Нет rate-limit отдельно на этот endpoint (наследует adminSensitiveLimiter)
[PIX-11101] feat(blog): агентский endpoint публикации одобренных постов
Some checks failed
CI / API (pull_request) Failing after 3m28s
CI / Telegram Mini App (pull_request) Successful in 1m33s
CI / Python SDK (pull_request) Successful in 25s
CI / Contracts (pull_request) Successful in 2m27s
CI / Secrets Scan (pull_request) Successful in 16s
PR Janitor / janitor (pull_request) Successful in 11s
CI / Prisma Migrate Gate (pull_request) Successful in 1m32s
React Doctor / React Doctor / App (pull_request) Successful in 3m23s
CI / App (pull_request) Successful in 18m32s
5795f77259
Добавляет POST /api/agent/blog/:id/publish — ограниченный endpoint для
публикации постов, уже одобренных CEO.

Безопасность:
- Аутентификация через отдельный AGENT_BLOG_PUBLISH_TOKEN (не admin credentials)
- Timing-safe сравнение токена (crypto.timingSafeEqual, аналогично adminSecret.ts)
- Сервисный слой блокирует публикацию без approvedAt (HTTP 409) — агент не может
  обойти требование одобрения CEO
- Не затрагивает POST /admin/blog/:id/approve (остаётся JWT+2FA, board-only)

Файлы:
- api/src/middleware/agentBlogPublishAuth.ts — новый middleware
- api/src/routes/blog.routes.ts — новый маршрут
- api/src/routes/blog.agent-publish.test.ts — 5 тестов (5/5 passed)
- api/.env.example — документация нового AGENT_BLOG_PUBLISH_TOKEN

Разблокирует PIX-7298 (публикация одобренного blog update PIX-7294).
Требует: CEO устанавливает AGENT_BLOG_PUBLISH_TOKEN в prod env.
andrei left a comment

CTO Review (PIX-11199) — Код: ОДОБРЕН / CI: Ждём

Код проверен по 6 измерениям:

  • Correctness: middleware enforces timing-safe HMAC, service enforces approvedAt != null → 409
  • Security: AUDIT комментарий, no agent self-approve
  • Tests: 5 тестов (401 missing/wrong, 503 not configured, 200 approved, 409 not approved)
  • Scope: только API, app/ не затронут
  • Immutable pattern: нет мутации

⚠️ CI: Job App показал failure, хотя PR не касается app/. Вероятно intermittent. Нужен re-run или подтверждение что App build проходит на master. Не мержить до зелёного CI.

**CTO Review (PIX-11199) — Код: ОДОБРЕН ✅ / CI: Ждём** Код проверен по 6 измерениям: - ✅ Correctness: middleware enforces timing-safe HMAC, service enforces `approvedAt != null` → 409 - ✅ Security: AUDIT комментарий, no agent self-approve - ✅ Tests: 5 тестов (401 missing/wrong, 503 not configured, 200 approved, 409 not approved) - ✅ Scope: только API, app/ не затронут - ✅ Immutable pattern: нет мутации ⚠️ **CI:** Job `App` показал failure, хотя PR не касается `app/`. Вероятно intermittent. Нужен re-run или подтверждение что App build проходит на master. Не мержить до зелёного CI.
fix(test): убрать неиспользованные AppError и res в blog.agent-publish.test.ts
All checks were successful
CI / Contracts (pull_request) Successful in 2m14s
CI / Telegram Mini App (pull_request) Successful in 1m25s
CI / Python SDK (pull_request) Successful in 31s
CI / Secrets Scan (pull_request) Successful in 15s
CI / API (pull_request) Successful in 15m12s
PR Janitor / janitor (pull_request) Successful in 28s
CI / Prisma Migrate Gate (pull_request) Successful in 1m43s
React Doctor / React Doctor / App (pull_request) Successful in 3m37s
CI / App (pull_request) Successful in 17m35s
4137295a1d
ESLint no-unused-vars: AppError и res в тесте '409 from service' не используются.
Убраны import и присваивание; тест проверяет только вызов mockRejectedValueOnce.
forgejo-actions scheduled this pull request to auto merge when all checks succeed 2026-06-21 09:54:34 +00:00
andrei merged commit e4a13656c7 into master 2026-06-21 10:01:48 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
europa-tech-srl/europatech!839
No description provided.