Skip to content

Releases: itphx/synth

Synth 0.12.4

Choose a tag to compare

@RamazanovDV RamazanovDV released this 28 Oct 19:01

0.12.4 (2026-10-28)

Новые возможности

  • feat(attachments): видео нативно, аудио-в-видео и выбор сообщения
  • feat(mcp): вложения MCP-результата (image/audio/resource)
  • feat(tools): медиа из инструментов — ToolResult.attachments + web_fetch
  • feat(attachments): outbound — send_attachment, stream.done.attachments, раздача по sha
  • feat(pipelines): вложения в прогоне (attachments[])
  • feat(events): вложения внешнего события (attachments[])
  • feat(attachments): тул save_attachment + fs.changed
  • feat(attachments): оригиналы в blob + staging-загрузка без сессии
  • feat(attachments): native → aux-текст → отброс + стоп после role-отказа
  • feat(ui): модели по модальностям в «Мультимодальном вводе»
  • feat(attachments): derive — обработка медиа вспомогательной моделью
  • feat(models): тул list_models — каталог с модальностями для агента
  • feat(attachments): модели обработки по модальностям — конфиг и API
  • feat(processes): detach идущего execute_shell без перезапуска
  • feat(ui): кнопка «В фон» и ctrl+b для идущего прогона
  • feat(background): detach идущего саб-агента в фон (ядро)
  • feat(attachments): тул attach_workspace_file — файл из workspace как вложение
  • feat(ui): админ-раздел «Мультимодальный ввод»
  • feat(attachments): отброшенное вложение не теряется + runtime-API настроек
  • feat(settings): runtime-настройки мультимодального ввода в слое конфигурации
  • feat(ui): «Вмешаться» — иконочный тумблер вместо трёх режимов отправки
  • feat(attachments): метрики и перенос вложений в экспорте проекта
  • feat(driver,chart): импорт core сужен до FileBlobStore, опция отдельного блоб-тома
  • feat(storage): contextFiles в SQL, порт skills подключён к домену
  • feat(pipelines): артефакты прогонов в blob-порте
  • feat(ui): вложения в отправленном сообщении
  • feat(llm): вложения доходят до провайдеров, gateway не логирует base64
  • feat(storage): skills — метаданные в SQL, содержимое в blobs, порт без путей
  • feat(attachments): сервис, HTTP-контур, blob-root, GC и ссылки
  • feat(storage): packs и legacy pipelines в PostgreSQL
  • feat(storage): blob-подложка stat/readStream, учёт ссылок blobRefs, медиа-части, модальности
  • feat(ui): вложения в композере и отправке
  • feat(ui): store и компоненты вложений композера
  • feat(ui): подготовка вложений — HEIC→JPEG, office→текст+картинки, группы
  • feat(ui): утилиты подготовки вложений (accept/mime, извлечение office, large-text-paste)
  • feat(worktree): sweep осиротевших записей при старте
  • feat(ui): worktrees — инвентарь, привязка, индикатор, скрытие в дереве
  • feat(worktree): тулы git_worktree_*, HTTP-контур и событие (этап 1.4)
  • feat(worktree): per-session cwd — привязка, резолв, containment (этап 1.4)
  • feat(worktree): WorktreeService — git-операции, lifecycle, детект secondary
  • feat(storage): порт WorktreeRepository и три backend'а (этап 1.4)
  • feat: метрики synth_executor_* (ADR-094) на обеих сторонах
  • feat: SSH-ключи доставляются исполнителю на время вызова (протокол 4), CA — конфигурация
  • feat(question): таймер обратного отсчёта в доке
  • feat(question): таймаут-опция, уведомление и сворачиваемый док с подтверждением
  • feat(ui): карточка фона в системном блоке, уведомления, компактные кнопки
  • feat(tools,background): реестр для агента, модель саб-агента, стартовые события
  • feat(execution): фоновые процессы в remote и устойчивый контракт
  • feat(steering): инъекции в дочернюю сессию саб-агента (ADR-104)
  • feat(executor): фоновые процессы и протокол v3 (ADR-077 шаг 7c)
  • feat(ui): вкладка «Процессы» в правой панели
  • feat(ui): док вопроса агента над композером
  • feat(api): HTTP-контур реестра фоновых прогонов
  • feat(processes): фоновые процессы и execute_shell background
  • feat(execution): фоновый spawn в порту и append в BlobStore
  • feat(background): фоновые саб-агенты и отчёт по лимиту шагов
  • feat(engine): вопрос пользователю посреди хода (этап 1, блок 3)
  • feat(storage): контракты и порты вопросов и реестра фонов
  • feat: тулы автоматизации (пайплайны, расписания) и управление памятью проекта
  • feat(charts): Grafana-дашборд «Synth — Память»
  • feat(ui): вкладка «Память» в правой панели
  • feat(plugin-memory): телеметрия recall и memory_search
  • feat(memory): GET /sessions/:id/memory для вкладки «Память»
  • feat(metrics): память в контексте и recall
  • feat(plugin-memory): не индексировать каталоги и файлы секретов
  • feat(ui): область индекса в разделе «Память»
  • feat(cli): --scope для индексов памяти
  • feat(memory): scope индекса в портале
  • feat(plugin-memory): общий (инстансный) индекс и слияние recall
  • feat(memory): область видимости индекса в слое хранения
  • feat(cli): synth memory — клиент портала памяти
  • feat(ui): цель pipeline в редакторе расписаний
  • feat(memory): проектная авторизация портала памяти
  • feat(scheduler): запуск прогона пайплайна по расписанию
  • feat(ui): SVG-визуализация графа памяти
  • feat(prompt): слой plugin.tools в манифесте промпта
  • feat(metrics): synth_memory_index_chunks — объём корпуса по состояниям
  • feat(pipelines): встроенный шаблон «Память: консолидация сессии» (М4b)
  • feat(ui): раздел «Граф» в админке памяти
  • feat(memory): портал — чтение графа памяти
  • feat(memory-plugin): граф сущностей без LLM
  • feat(ui): консолидация фактов в разделе «Память»
  • feat(memory): портал — консолидация фактов
  • feat(memory-plugin): консолидация фактов — дедуп по эмбеддингам
  • feat(ui): операции с индексами памяти в админ-разделе
  • feat(memory): мутации индексов в портале через админ-тул плагина
  • feat(memory-plugin): ванильный RAG — чанкер, эмбеддинги, поколения, гибридный поиск
  • feat(dev): плагин памяти ставится и активируется в dev автоматически
  • feat(memory): плагин памяти, порты хранения, сервисы фасада и портал (М0–М1)
  • feat(plugins): чтение журнала действий плагинов — API и раздел в UI (ADR-090)
  • feat(ui): раздел «Доступы» — OAuth-коннекторы, маска и переавторизация (ADR-105 Ф4)
  • feat(webhooks): ротация signing-секретов в synth secrets rotate
  • feat(ui): раздел «Полномочия» — политика Authority read-only (ADR-106 Ф5)
  • feat(oauth): ротация мастер-ключа для внешних доступов (ADR-105 Ф4)
  • feat(plugins): подтверждение установки привязано к content-hash, срок 24 ч, выдаёт ADMIN (ADR-090)
  • feat(storage-postgres): порты Authority-слоя (ADR-106 Ф5)
  • feat(oauth): append-only журнал credential-операций (ADR-105 Ф4)
  • feat(authority): активация контента provides.authority в политику инстанса (ADR-106 Ф5)
  • feat(oauth): HTTP-контур внешних доступов — createOAuthRoutes и монтирование (ADR-105 Ф4)
  • feat(authority): одобрение по существу — сводка ролей/действий/целей пакета (ADR-106 Ф5)
  • feat(authority): режим сессии как потолок — yolo не снимает ask другого участника (ADR-106 Ф4)
  • feat(authority): потолок хода считается один раз и не поднимается другим участником (ADR-106 Ф4)
  • feat(authority): участники сессии — аддитивное поле и вывод из проекта (ADR-106 Ф4)
  • feat(plugins): Ф7 — UI и документация гибридного режима плагинов (PROP-090)
  • feat(authority): принципал хода фиксируется при приёме ввода (ADR-106 Ф4)
  • feat(plugins): Ф7 — discovery политики и привязка plugin_id (сервер)
  • feat(plugins): Ф7 — серверная политика гибрида и plugin-bound токены (PROP-090)
  • feat(mcp): права на привязку внешнего доступа к коннектору (ADR-105 Ф3)
  • feat(oauth): каталог OAuth-провайдеров из конфига (ADR-105 Ф3)
  • feat(mcp): 400 на plaintext-секрет в API реестра и probe (ADR-105 Ф3)
  • feat(steering): единый контракт режима в гибриде — mode доезжает до remote, mode_applied в ack (ADR-104 этап 3)
  • feat(mcp): запрет plaintext-секретов в реестре и миграция в доступ (ADR-105 Ф3)
  • feat(core): ADR-105 Ф3 — access-токен доступа в MCP-транспорте
  • feat(steering): приоритет инъекций — interrupt раньше steer, внутри класса FIFO (ADR-104 этап 3, A)
  • feat(authority): подтверждения, привязанные к принципалу и ходу (PROP-108 Ф3)
  • feat(ui): режим interrupt и маркер прерванного хода (PROP-098)
  • feat(authority): принуждение решений в permission-слое (PROP-108 Ф2)
  • feat(steering): режим interrupt в API и очереди (PROP-098 этап 2)
  • feat(oauth): клиент PKCE/refresh/revoke через egress (PROP-107 Ф2)
  • feat(steering): прерывание генерации без завершения хода (PROP-098 этап 2)
  • feat(ui): селектор режима отправки при активном ходе (PROP-098)
  • feat(authority): метрики решений Authority-слоя (PROP-108 Ф1)
  • feat(storage-postgres): порт внешних доступов (PROP-107 Ф1)
  • feat(authority): shadow-интеграция Authority-слоя (PROP-108 Ф1)
  • feat(steering): маркер вмешательства в ленте и проброс mode в UI
  • feat(authority): резолвер решений (PROP-108 Ф1)
  • feat(steering): оркестратор вплетает инъекции на границе шага (persist metadata.steer, событие message.injected)
  • feat(steering): режим mode в POST /sessions/:id/prompt — steer в очередь инъекций, interrupt с понятной 400
  • feat(authority): контракты Authority-слоя и порт политики (PROP-108 Ф0)
  • feat(core): порт внешних доступов подключён к слою хранения (PROP-107 Ф1)
  • feat(plugins): Ф6 — UI-раздел «Плагины» в админ-панели (PROP-090)
  • feat(plugins): Ф5в — managed deploy-time и неприкосновенность management-плагинов (PROP-090)
  • feat(plugins): Ф4б-3 — точка tools по протоколу и suite на удалённой реализации (PROP-090)
  • feat(plugins): Ф4б-2 — процесс удалённого плагина, токен-файл, выбор транспорта (PROP-090)
  • feat(plugins): Ф4б-1 — wire-протокол и remote-загрузчик (PROP-090)
  • feat(plugins): Д2 — update и rollback версий плагина (PROP-090)
  • feat(plugins): Д1 — источники установки: локальный .tgz и npm (PROP-090)
  • feat(plugins): Ф5б-3 — CLI synth plugin *, byte-copy ассетов, чистка версий
  • feat(plugins): Ф5б-2 — HTTP API плагинов и RBAC-матрица (PROP-090)
  • feat(plugins): Ф5б-1 — PluginRuntime, старт-активация и общий реестр блоков (PROP-090)
  • feat(plugins): Ф5а — сервис установки плагинов (PROP-090)
  • feat(plugins): Ф4а — inline-загрузчик кода плагина (PROP-090)
  • feat(plugins): Ф3в — точка tools и контрактный suite расширений (PROP-090)
  • feat(plugins): Ф3б — точка расширения llmFilters и эмбеддинги через gateway (PROP-090)
  • feat(plugi...
Read more

Synth 0.11.3

Choose a tag to compare

@RamazanovDV RamazanovDV released this 20 Oct 21:24

0.11.3 (2026-10-21)

A major platform release: observability and metrics (ADR-094), a unified egress layer — address
policy, TLS/CA trust and proxy (ADR-099, replacing PROP-088), a storage layer with PostgreSQL
(ADR-096/097/098), an instance maintenance contour — backup, migrations, restart (ADR-091/092),
analytics and reporting (PROP-102) and offline distribution for closed networks (PROP-101).
148 commits after v0.10.1 (864 files, +122 344 / −3 728) — the gap since 0.10.1 is closed by a single
release.

Observability and metrics (ADR-094)

  • Prometheus export. GET /metrics — the text Prometheus exposition format 0.0.4, outside
    /api/v2, on the same port. Disabled by default (metrics.enabled=false, env SYNTH_METRICS_ENABLED):
    when disabled it returns 404, not 401. An optional bearer token (env SYNTH_METRICS_TOKEN or the file
    {dataDir}/secrets/metrics-token, 0600) → 401 on a wrong token; the response carries
    Cache-Control: no-store. Scraping /metrics itself is not counted in the HTTP metrics.
  • An in-house mini-registry with no new dependencies (packages/core/src/metrics/): counter/gauge/histogram,
    fixed labelNames, a cap of 2000 series and the synth_metrics_series_dropped_total counter; the
    correctness of the renderer is pinned by golden tests.
  • A cardinality contract. HTTP metrics carry only the method, route template and status labels;
    session_id, user_id, raw paths and query strings are forbidden, and an unknown route collapses to
    other. SSE /api/v2/events and /ws/* are excluded from the latency histogram (long-lived connections
    distort p95) — a gauge of active streams is used instead.
  • /ready is separate from /health. /health is liveness (the process is alive), /ready returns
    200 once the application is initialized (storage context built, migrations applied, queue ready); 503
    happens only at startup and in the fail-closed state. Storage degradation does not take the pod out
    of rotation
    : /ready stays 200, and degradation is signalled by a metric and an alert.
  • Metric domains: HTTP; process/Node (RSS, heap, CPU, event loop lag, uptime, build_info); sessions
    and queue; LLM (provider/model/outcome, latency, tokens, retries, cost); storage ({dataDir} size,
    records per store, degraded/backend); events (ingested/decisions/journal); scheduler; webhooks; hybrid;
    a mirror of the decision metrics (ADR-084).
  • Runtime toggle in the UI. The admin section “Metrics” (Settings → Administration, category
    metrics, ADMIN role): status (running, /ready, storage, version, uptime,
    series/bytes/droppedSeries), a toggle, a write-only token, copying /metrics and a
    scrape_config example. Priority is SYNTH_METRICS_ENABLED > runtime (settings.json/PG) >
    config.yaml > false; the change is applied after a process restart (restartRequired → a banner
    and a graceful-restart button). API: GET/PUT/DELETE /api/v2/settings/metrics,
    GET /api/v2/settings/metrics/status, PUT/DELETE /api/v2/settings/metrics/token (with an env token →
    409 CONFLICT; the value is never returned).
  • Shipped artifacts. Grafana dashboards (charts/synth/files/dashboards/: overview, LLM, events-ops)
    and alert rules (charts/synth/files/alerts/synth-rules.yaml, 19 rules) live in the repository; the dev
    stack is docker-compose.observability.yml plus the deploy/observability/ directory; the runbook is
    docs/OBSERVABILITY.md.
  • Helm. The metrics.enabled, metrics.existingSecret/tokenKey/tokenOptional and metrics.ingress
    flags (a dedicated Ingress for /metrics only — it points straight at the backend Service, UI-nginx does
    not proxy /metrics), plus an optional ServiceMonitor with prometheus.io/* annotations. The
    dashboards and alerts can select the environment and the instance (env/instance), so a single
    Prometheus serves both dev and test.
  • ADR-094 remainder: JSON logs with request_id/session_id and OpenTelemetry tracing are separate
    tasks.

Unified egress layer: address policy, TLS/CA, proxy (ADR-099)

  • An address policy for outgoing requests. The egress.tools and egress.webhooks sections and the
    mcp.networkPolicy key share one format {mode, list, exceptions}, with modes deny/allow (webhooks
    also accept off — dev only). The policy applies live, per request, and acts on every redirect
    hop
    . Addresses are normalized by a single helper (the IPv4-mapped IPv6 bypass is closed), DNS resolves
    all A/AAAA records, and every address is checked against the CIDR list (fail-closed on a resolution error
    or an empty result). One guard (engine/net/egress-guard.ts) replaces three separate implementations:
    web_fetch, webhooks, remote skills and URL instruction sources, and the provider favicon all go
    through it.
  • A single canonical list of blocked ranges. The default list of private ranges did not cover multicast,
    reserved and broadcast, and core kept a second, dead list (applied only when no policy was passed — which
    never happens at runtime), creating a false impression of full coverage. There is now one source of truth —
    packages/shared/src/types/mcp.ts, DEFAULT_MCP_PRIVATE_CIDRS: 26 ranges (multicast, reserved,
    broadcast, 192.0.0.0/24 with the NAT64 prefixes, 198.18/15, the IANA IPv6 blocks); the lists in core are
    removed. The NAT64 prefixes 64:ff9b::/96 and 64:ff9b:1::/48 are intentionally not blocked: on
    IPv6-only networks with DNS64 the resolver returns the synthesized AAAA records exactly from them — blocking
    them would break the egress to public hosts.
  • Log and audit. Append-only {dataDir}/audit/egress.jsonl: scope, host, url without query and
    userinfo, method, status (allowed/blocked/error), httpStatus, bytes, durationMs, reason, the rule
    that matched, sessionId/projectId/actor. Bodies and headers are never logged; retention is
    egress.log.retentionDays. Policy changes are recorded in {dataDir}/audit/security.jsonl. Reading:
    GET /api/v2/audit/security and GET /api/v2/audit/egress (ADMIN/AUDITOR).
  • Offline URL check. POST /api/v2/settings/egress/check (scope + url) parses the URL, resolves
    DNS and compares against the policy without making an HTTP request (the endpoint itself does not
    become an SSRF probe); behind a proxy it honestly reports addressChecksActive: false, because only the
    proxy knows the destination address.
  • TLS/CA trust — a single source. The security.tls section plus SYNTH_TLS_* env; priority is
    env > runtime (UI) > config.yaml > defaults. A CA bundle (several certificates in one PEM),
    rejectUnauthorized, a default mTLS client and per-host profiles (mappings[]: exact,
    *.suffix, * patterns, case-insensitive, first match wins — otherwise the default). The bootstrap file
    is {dataDir}/security-tls.json (0600, read before the database connection), PEM material lives in
    {dataDir}/secrets/tls/ (0600). PostgreSQL uses the same profile resolver by host, so a “certificate
    for the database” is not configured separately. TLS parameters in the PostgreSQL DSN are forbidden —
    trust is defined only by storage.postgres.sslmode and security.tls.
  • Runtime TLS settings from the UI. API GET/PUT /api/v2/settings/tls,
    PUT/DELETE /api/v2/settings/tls/ca, PUT/DELETE /api/v2/settings/tls/client,
    POST/PUT/DELETE /api/v2/settings/tls/mappings[/:id], POST /api/v2/settings/tls/validate. Responses
    carry metadata only (sources, subject, hasKey, readOnly): PEM and keys are never returned; settings
    coming from config/env are read-only (a mutation → 409 CONFLICT). Changes are audited
    (scope:'tls') and applied after a restart (restartRequired).
  • The proxy is part of the egress layer. The proxy section: HTTP/HTTPS/SOCKS5, Basic authentication,
    TLS/mTLS to an HTTPS proxy (separate from the trust towards the target), noProxy, fromEnv,
    fallbackDirect, timeout. The model is profiles + host rules: mode: all|selected,
    defaultProfile, profiles.<name> (the name is immutable), rules[] — declaration order is priority,
    the first match wins; noProxy always takes precedence over the rules; action: direct carries
    no profile. Host patterns: exact, .suffix, *.suffix, host:port, IP literal, CIDR, *; a CIDR
    matches only an IP literal of the target
    (DNS is not resolved for rules — otherwise the route would
    depend on DNS).
  • Fail-closed transport. An unreachable proxy → EGRESS_PROXY_UNAVAILABLE (no silent “go direct”; the
    fallbackDirect opt-in is explicit and marked in the log as via:'fallback'). An authentication failure
    (407/SOCKS5 refusal) → EGRESS_PROXY_AUTH_REQUIRED/EGRESS_PROXY_AUTH_FAILED, and the direct route
    stays forbidden even with fallbackDirect. A broken configuration (unknown scheme, Basic without a
    password, ntlm/negotiate) fails the startup (EGRESS_PROXY_CONFIG_INVALID).
  • Proxy passwords and TLS material live in env or files only. The default profile uses
    SYNTH_PROXY_PASSWORD or {dataDir}/secrets/proxy-password; a profile <name> uses
    SYNTH_PROXY_<NAME>_PASSWORD or {dataDir}/secrets/proxy/<name>.password (0600); a profile’s TLS
    material is {dataDir}/secrets/proxy/<name>/{ca.pem,client.crt,client.key}. The values are write-only:
    they are never returned, never logged and never written to the audit log; with an env password a UI
    mutation → 409 CONFLICT. Passwords and userinfo are not stored in config.yaml.
  • API and UI. GET/PUT/DELETE /api/v2/settings/proxy (profiles/rules/mode; status
    saved/running/defaults, isOverridden, password, restartRequired),
    PUT/DELETE /api/v2/settings/proxy/password, .../profiles/:name/password,
    .../profiles/:name/tls/ca, `.../profiles/...
Read more

Synth 0.10.1

Choose a tag to compare

@RamazanovDV RamazanovDV released this 15 Oct 16:10

0.10.1 (2026-10-15)

An engineering release without new subsystems: god-object decomposition (ADR-095), the split of
architecture documents into ADR and PROP, num_ctx configured through Synth, the native
/api/chat for Ollama and a series of security fixes (P0/P1/P2). 52 commits after v0.10.0.

God-object decomposition (ADR-095)

  • The seam extraction pattern was adopted: the facade keeps its public API, related blocks move
    into modules and methods delegate; one seam — one commit, every step under green typecheck/lint/test.
  • Step 1 — ui/lib/api/synthApi.ts: 2 596 → 161 lines (32 domain modules lib/api/* + a barrel,
    a verbatim move of 223 methods, a contract test of the surface).
  • Step 2 — shared/types/index.ts: 1 452 → 51 (12 modules types/* + a barrel; the public exports of
    @itphx/synth-shared are identical, 531/531).
  • Step 3 — ui/components/panels/LeftPanel.tsx: 2 230 → 59 (subcomponents and hooks in left-panel/*).
  • Step 4 — core/server/app.ts 2 014 → 380 and backend/app.ts 1 738 → 286 (modules app/*,
    the route mounting order is preserved byte for byte).
  • Step 5 — core/engine/tools/task.ts: 1 926 → 29 (7 modules engine/tools/task/*, exports 1:1).
  • Step 6 — core/engine/orchestrator.ts: 5 393 → 3 777 (9 modules orchestrator/* + phases/*,
    _processMessage 1 668 → ~980 lines).
  • Behaviour did not change: the full run (~5 084 tests) is green, each step is a separate commit that
    updates the per-package AGENTS.md and the roadmap. The remaining 6b-2 part (the Tool Use loop body) is deferred on purpose.

Architecture decisions: splitting ADR and PROP

  • The catalog is split into ADR — accepted decisions (43) and PROP — proposals with a due date
    (41: 32 actionable + 9 vision); the files are adr-NNN-*.md / prop-NNN-*.md, the ids and references
    were updated across the repository.
  • The rules live in the new docs/ARCH_DECISIONS.md: five document classes, "by default there is no
    document", an ADR no longer than a page, the history block; the proposal index and due dates are in docs/roadmap.md.
  • The checker scripts/adr-check.mjs (pnpm adr:check/pnpm adr:write) assembles the ADR/PROP index and
    runs in a dedicated docs workflow.
  • The bulky historical ADRs were compressed to one page and their as-built part moved into the spec homes:
    ADR-052 (415→60), ADR-046 (652→54), ADR-069 (608→59), ADR-070 (717→72), ADR-089 (601→49).
  • New proposals: PROP-091 (backup/restore/transfer), PROP-092 (instance lifecycle),
    PROP-093 (docs versioning), PROP-094 (observability and metrics), PROP-096 (background subagent sessions),
    PROP-097 (background processes), PROP-098 (steering), PROP-099 (memory footprint optimization).
  • Roadmap: the "Priority goals of release 0.11" section — PostgreSQL (+ a YDB assessment), operations and
    ops skills, memory optimization.

Providers and context window

  • num_ctx is now configured through Synth: the ProviderConfig.numCtx field (API POST/PATCH /providers,
    CLI synth config provider add --num-ctx, env SYNTH_PROVIDER_<NAME>_NUM_CTX) and it takes priority over
    the model's contextWindow.
  • The ollama provider type switched to the native /api/chat: a URL with /v1 is normalized
    (the suffix is stripped with a warning), because the OpenAI-compatible layer ignores options/num_ctx.
  • README/compose/LLM_PROVIDERS and the portal were updated: the recommended local model is qwen3.8:27b,
    with an explanation of the effective window and OLLAMA_CONTEXT_LENGTH.

Security

  • P0: the WS calls send_message/permission_reply/permission_hold/cancel now authorize by session
    visibility; /api/v2/fs/* uses authorizeProject (read/write separately); the backend session routes
    (export/notes/optimization/debug-system-message) are under canAccessSession.
  • P1: fail-closed for external paths (external_directory: ask, and deny in plan/strict);
    {dataDir}/secrets and {dataDir}/security are in the denied prefixes; shell-guard is fail-closed for
    $VAR/glob/$() and resolves $SYNTH_DATA_DIR.
  • P1: OIDC issuer/audience, fail-closed CORS (open CORS only with SYNTH_CORS_ALLOW_ALL=true),
    a Secure cookie by default, avatar containment by username, a rate limit on POST /me/identities/claim.
  • P2: an SSRF policy for web_fetch (private/loopback/link-local) with manual redirects (≤5 hops);
    docker-compose: SYNTH_API_KEY comes from .env, no hardcoding.
  • A gitleaks allowlist for confirmed false positives.

Reliability and fixes

  • FileMutex: acquisition is confirmed by mkdir — the ENOENT race between mkdir and stat no
    longer yields a "lock without ownership" (dropped ScheduleStore/FileLeader updates); a deterministic
    regression was added.
  • A terminal LLM error is persisted into the session (metadata.status=error) and kept out of the LLM context.
  • Providers API: the url/model/apiKey aliases, base_url validation, PATCH support.
  • Flakes stabilized: task-resume (a fresh session read instead of a stale snapshot), webhooks/service
    (drain() instead of setTimeout), UI SchedulerTab/EventsAdminSettings (waitFor/flush instead of empty act pauses).

Performance and UI

  • Code-splitting: the entry chunk went 2 024 → 420 kB (vendor groups, a separate themes chunk, lazy
    RightPanel tabs and App modals); heavy modals mount on first open while keeping the closing animation.
  • A WCAG AA contrast test across 62 themes was added (contrast.test.ts).

CI, build and publishing

  • The workflows were split: ci-docs (adr-check + docs-link-check over docs/** and **/*.md), ci —
    code/UI tests and pnpm audit (report-only); a regular push is checked by tests, while build and publishing
    happen only on a release tag.
  • A dedicated step publishes the GitVerse Release body (scripts/publish-release.mjs) instead of actions/create-release@v1.
  • GitHub is a mirror without Actions: the publish-github job pushes master:main and the tags and creates
    a GitHub Release; all three base images (synth, synth-backend, synth-ui) are published to gitverse.ru and ghcr.io (version tag only).
  • The stub package @itphx/synth-runner was removed (7 → 6 packages); Runner remains only in PROP-050.
  • The GitHub Release body is English (changelog.sh --lang en), together with the English "Installation" block.

Documentation

  • English documentation for the GitHub mirror: README.en.md, the docs/en/ catalog (ARCHITECTURE, API_V2,
    CONFIGURATION, HYBRID, UI-KIT, ROUTING, LLM_PROVIDERS, QUICKSTART, DEVELOPMENT, PUBLISHING, TROUBLESHOOTING,
    KEYCLOAK) and the mandatory glossary docs/en/GLOSSARY.md (RU→EN, product strings take priority).
  • A pair of release descriptions was introduced: docs/releases/<VERSION>.md (the GitVerse body) and
    <VERSION>.en.md (the GitHub body); scripts/changelog.sh gained the --lang and --out options.
  • Community files for the public mirror: CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, SUPPORT, CHANGELOG,
    THIRD-PARTY-NOTICES, issue/PR templates.
  • The positioning was updated: "AI platform for team collaboration" (self-hosted); promises about the
    unimplemented opencode/cline engines were removed.
  • References to the t11 prototype were removed from the instructions and actionable places.
  • The dev docs were updated for the decomposition (per-package AGENTS.md, module maps).

Artifacts

  • npm: @itphx/synth*@0.10.1 (6 packages; npmjs.org and GitVerse Package Registry)
  • Docker: the base images are published to both registries (version tag only) — gitverse.ru/itphx/synth:0.10.1, gitverse.ru/itphx/synth-backend:0.10.1, gitverse.ru/itphx/synth-ui:0.10.1 and ghcr.io/itphx/synth:0.10.1, ghcr.io/itphx/synth-backend:0.10.1, ghcr.io/itphx/synth-ui:0.10.1
  • Helm: the synth chart 0.10.1

Installation

CLI (npm — from npmjs.org or the GitVerse Package Registry):

npm install -g @itphx/synth@0.10.1

Base Docker image from the GitHub Container Registry:

docker pull ghcr.io/itphx/synth:0.10.1
docker run -p 4300:4300 ghcr.io/itphx/synth:0.10.1

The primary image registry is gitverse.ru/itphx/synth:0.10.1;
all three base images (synth, synth-backend, synth-ui) are published to
both gitverse.ru and ghcr.io (version tag only).