SlangUA AGENTS.md

Repository instructions for AI agents and contributors working on SlangUA, written in Ukrainian. They define the required documentation, architecture boundaries, security rules, and development sequence.

In plain words
What is it for?
Use them before changing SlangUA code, especially API, translation, authentication, age-gate, rate-limit, or prompt-injection protections.
Why use it?
They reduce the risk of changes that violate the project’s design or security requirements. They also tell contributors where to find the current roadmap and technical contracts.

Instructions file for CodexOpenCode

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add instructions/alextoster/slangua/agents-md
Clone the repo
git clone --depth 1 https://github.com/AlexToster/SlangUA

Made for: Codex, OpenCode.

Per session 6,238 This file is loaded in full into every session.
When invoked 6,238 The same file — it is already loaded in full.
Security scan A 0 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5 $0.06238 $0.06238
Opus 5 $0.03119 $0.03119
Sonnet 5 $0.01248 $0.01248
Haiku 4.5 $0.00624 $0.00624

Measured 2d ago against content hash d4007a515bf6, method: parsed. Prices are Anthropic first-party input rates as of 2026-08-30, from the pricing page.

Security

Grade A, and why

SlangUA AGENTS.md scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 2d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

AGENTS.md · 146 lines

How it starts

The opening of the file, as written. The whole thing — 146 lines — stays where its author put it; the contents beside it link to each section on GitHub.

AGENTS.md

Правила роботи в репозиторії SlangUA для AI-агентів і нових контриб'юторів.

Цей файл описує як тут працювати. Що саме побудовано — у README.md та plans/docs/README.md. Повний технічний контекст одним документом, який можна віддати сторонній моделі, — plans/SLANGUA-BRIEFING.md.


1. Перед початком роботи

  1. Прочитай plans/docs/README.mdplans/architecture.mdplans/ROADMAP.md. Документація тут є контрактом, а не описом післяфактум.
  2. Виконай git status один раз на початку. Незв'язані зміни, які вже були в робочій копії, — чужі: не комітити, не відкочувати, не «чистити».
  3. Знайди поточну стадію в ROADMAP. Стадії виконуються послідовно; не перестрибуй наперед.
  4. Перед зміною поведінки API або безпеки прочитай відповідний документ у plans/docs/ — там зафіксовано обґрунтування, і його потрібно оновити разом із кодом.

2. Непорушні інваріанти

Це не стильові побажання. Порушення будь-якого пункту — привід відкинути зміну.

  • Не послаблювати age gate, автентифікацію, перевірку власності, rate limiting, захист від prompt injection і серверну валідацію заради спрощення UI. Ніколи.
  • Age gate має єдину справжню точку перевірки для перекладу — TranslationService. Він порівнює ageRestricted стилю з user.ageConfirmedAdult до звернення до preview-кешу і до AI. GET /styles повертає всі увімкнені стилі разом із прапорцем ageRestricted (він не фільтрує), а UI лише блокує картку — щоб користувач бачив стиль і міг підтвердити вік. Клієнтське блокування не є захистом і не може його замінити. Окрема серверна перевірка того самого правила стоїть у POST /share/inline (шарити 18+ може лише підтверджений повнолітній) — це власний gate іншої дії, а не дублікат.
  • Сервер ніколи не довіряє тексту від клієнта. POST /translate/save приймає лише previewId; POST /share/inline — лише previewId або translationId. Ні originalText, ні translatedText з клієнта не зберігаються і не надсилаються.
  • Rate limiter падає закрито. Якщо Redis недоступний — 503 RATE_LIMITER_UNAVAILABLE. Сервіс не працює, вдаючи, що лімітів немає.
  • Style Engine не має тихого fallback. Невідомий або вимкнений стиль завжди кидає помилку, яка перетворюється на 400 зі списком доступних стилів. Ніякого підставляння GEN_Z.
  • Шеринг — лише всередині Telegram. Основний шлях: сервер рендерить текст (shareText), клієнт передає його у власний чат-пікер Telegram через openTelegramLink('t.me/share/url?...'); inline mode (switchInlineQuery) — резервний шлях. Заборонено: браузерний share sheet, будь-який неявно створений публічний URL з перекладом, а також будь-що в share-інтенті, крім самого тексту повідомлення (ні токена, ні previewId, ні внутрішнього посилання).
  • Адмінка невидима для не-адмінів і не має ролі в базі. Доступ дають два незалежні фактори: Telegram-id у ADMIN_TELEGRAM_IDS і пароль (ADMIN_PASSWORD_HASH), який відкриває крок-ап сесію під X-Admin-Token. Кому не дозволено — усі /api/v1/admin/* віддають 404 з тим самим тілом, що й неіснуючий маршрут (не 401 і не 403: вони підтверджують існування панелі). Тому гейт — це хук onRequest, а не preHandler: Fastify валідує тіло раніше за preHandler, і 400 VALIDATION_ERROR виказував би маршрут так само. Прапорець isAdmin у /user/me — лише підказка клієнту, чи малювати кнопку, а не рішення про доступ. Ознаки адміна в Postgres немає навмисно: адмінство — конфігурація деплою, а рядок у БД міг би змінити будь-хто з правом запису, і відкат з бекапу воскресив би колишнього адміна.
  • Кіл-світч провайдерів — не circuit breaker, і він не має TTL. Breaker відповідає на питання «чи провайдер зараз падає?» і сам себе лікує через CIRCUIT_BREAKER_RESET_MS; кіл-світч відповідає на питання «чи людина взагалі хоче туди трафік?» і не лікується ніколи — ні через кулдаун, ні через рестарт, ні через успішний пробний запит. Стан — один хеш Redis ai:provider:disabled (поле = id провайдера, значення = {by, at, reason}), без TTL: у пам'яті процесу він тихо ввімкнув би провайдера на наступному деплої, а з TTL — воскресив би його в довільний момент, коли ніхто не дивиться. AIService читає світч один раз на запит, перед breaker'ами, і вимкнений провайдер не потрапляє ні в ланцюг fallback, ні в пробний запит на відновлення, ні в явний виклик за id. Світч сильніший і за preview-кеш: TranslationService викликає aiService.hasPermittedProviders() до звернення до кешу на обох шляхах перекладу, тому при повністю вимкненому ланцюгу теплий кеш віддає той самий 503, а не власний вивід уже вбитого провайдера до кінця TTL — інакше оператор не може сказати, чи його рішення взагалі подіяло. Стан breaker'ів у цій точці навмисно не читається: breaker лікується сам, і під час справжнього збою кеш саме й має продовжувати відповідати. Читання падає закрито: помилка Redis перетворюється на звичний 503 AI_PROVIDER_UNAVAILABLE, бо трактувати її як «нічого не вимкнено» означало б відправити трафік саме туди, куди оператор заборонив. Наявність поля — це і є світч: нерозбірливе значення все одно вимикає провайдера (щоб HSET, зроблений руками під час інциденту, працював). Вимкнути все дозволено навмисно — інакше панель була б безсилою саме тоді, коли потрібна, — але наслідок озвучується заздалегідь: клієнт попереджає, сервер логує результат на рівні error з Telegram-id оператора, а користувач бачить той самий 503, у якому немає ні id провайдера, ні причини.
  • Спостережуваність нічого не сповільнює і нічого не ідентифікує. Метрики й стрічка помилок пишуться в одному хуку onResponse — після того, як відповідь уже пішла, — тому обидва записи падають відкрито: помилка Redis коштує однієї точки на графіку і логується на рівні debug. Це не суперечить правилу «rate limiter падає закрито»: лімітер вирішує, чи пускати запит, і мусить відмовити, коли не може вирішити, а цей хук лише описує вже завершене. Читання, навпаки, падає закрито — сторінка з нулями читалася б як «трафіку немає», а не «даних немає». Що можна зберігати — це список дозволеного, а не фільтр: статус-код, шаблон маршруту (/api/v1/history/:id, ніколи конкретний шлях із id), наш код помилки, технічне повідомлення, обрізане до 300 символів, внутрішній id користувача і requestId. Ні тіла запиту, ні заголовків, ні тексту перекладу, ні Telegram-id: стрічка, що цитувала б текст користувача, відтворила б у Redis саме те, що розділення preview/save тримає подалі. Не рахуються OPTIONS, /health* і самі /api/v1/admin/* — панель опитує себе, і оператор, який дивиться на графік, не повинен його роздувати. Код і повідомлення в стрічку кладе captureErrorSnapshot(request, code, message): глобальний обробник помилок робить це для всього, що до нього доходить, а маршрути, які ловлять свої помилки самі (/translate/*, /share/inline), мусять викликати його явно — інакше найчастіший реальний збій виглядав би в стрічці як голий 5xx без причини.
  • Аудіо голосового вводу не зберігається ніде і ніколи. POST /api/v1/transcribe отримує запис, передає його провайдеру й повертає текст: ні Postgres, ні Redis, ні тимчасовий файл, ні рядок логу. Транскрипт стає рядком Translation лише тоді, коли користувач сам зробить preview і збереже його — голос це спосіб набору, а не окремий шлях перекладу. Маршрут обов'язково автентифікований (відкритий ендпоінт транскрипції — це безкоштовний STT-проксі за кошт оператора) і має власний бюджет запитів, бо кожен виклик витрачає квоту провайдера, спільну для всього деплою. Ключі транскрипції — окремий пул (STT_API_KEY), а не ключі AI-шару. Деталі — plans/docs/06-security.md.
  • Секрети лише через env. Ключі AI-провайдерів ніколи не потрапляють на клієнт.

Read the full file on GitHub · 146 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 2d ago First seen · 146 lines · 6,238 tokens per session scan A d4007a515bf6

Subscribe to this mod's changes

SlangUA AGENTS.md is an instructions file published in the GitHub repository AlexToster/SlangUA (5 stars, last pushed 4d ago), licensed MIT. It adds 6,238 tokens to every session, about $0.0312 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.