Repository navigation
Releases: itphx/synth
Release list
Synth 0.12.4
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...
Synth 0.11.3
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, envSYNTH_METRICS_ENABLED):
when disabled it returns 404, not 401. An optional bearer token (envSYNTH_METRICS_TOKENor the file
{dataDir}/secrets/metrics-token, 0600) → 401 on a wrong token; the response carries
Cache-Control: no-store. Scraping/metricsitself is not counted in the HTTP metrics. - An in-house mini-registry with no new dependencies (
packages/core/src/metrics/): counter/gauge/histogram,
fixedlabelNames, a cap of 2000 series and thesynth_metrics_series_dropped_totalcounter; the
correctness of the renderer is pinned by golden tests. - A cardinality contract. HTTP metrics carry only the
method, route template andstatuslabels;
session_id,user_id, raw paths and query strings are forbidden, and an unknown route collapses to
other. SSE/api/v2/eventsand/ws/*are excluded from the latency histogram (long-lived connections
distort p95) — a gauge of active streams is used instead. /readyis separate from/health./healthis liveness (the process is alive),/readyreturns
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:/readystays 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/metricsand a
scrape_configexample. Priority isSYNTH_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 →
409CONFLICT; 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 isdocker-compose.observability.ymlplus thedeploy/observability/directory; the runbook is
docs/OBSERVABILITY.md. - Helm. The
metrics.enabled,metrics.existingSecret/tokenKey/tokenOptionalandmetrics.ingress
flags (a dedicated Ingress for/metricsonly — it points straight at the backend Service, UI-nginx does
not proxy/metrics), plus an optionalServiceMonitorwithprometheus.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_idand OpenTelemetry tracing are separate
tasks.
Unified egress layer: address policy, TLS/CA, proxy (ADR-099)
- An address policy for outgoing requests. The
egress.toolsandegress.webhookssections and the
mcp.networkPolicykey share one format{mode, list, exceptions}, with modesdeny/allow(webhooks
also acceptoff— 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/24with the NAT64 prefixes,198.18/15, the IANA IPv6 blocks); the lists in core are
removed. The NAT64 prefixes64:ff9b::/96and64:ff9b:1::/48are 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/securityandGET /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 reportsaddressChecksActive: false, because only the
proxy knows the destination address. - TLS/CA trust — a single source. The
security.tlssection plusSYNTH_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 bystorage.postgres.sslmodeandsecurity.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 → 409CONFLICT). Changes are audited
(scope:'tls') and applied after a restart (restartRequired). - The proxy is part of the egress layer. The
proxysection: 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;noProxyalways takes precedence over the rules;action: directcarries
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
fallbackDirectopt-in is explicit and marked in the log asvia:'fallback'). An authentication failure
(407/SOCKS5 refusal) →EGRESS_PROXY_AUTH_REQUIRED/EGRESS_PROXY_AUTH_FAILED, and the direct route
stays forbidden even withfallbackDirect. 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
defaultprofile uses
SYNTH_PROXY_PASSWORDor{dataDir}/secrets/proxy-password; a profile<name>uses
SYNTH_PROXY_<NAME>_PASSWORDor{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 → 409CONFLICT. Passwords and userinfo are not stored inconfig.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/...
Synth 0.10.1
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 greentypecheck/lint/test. - Step 1 —
ui/lib/api/synthApi.ts: 2 596 → 161 lines (32 domain moduleslib/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 modulestypes/*+ a barrel; the public exports of
@itphx/synth-sharedare identical, 531/531). - Step 3 —
ui/components/panels/LeftPanel.tsx: 2 230 → 59 (subcomponents and hooks inleft-panel/*). - Step 4 —
core/server/app.ts2 014 → 380 andbackend/app.ts1 738 → 286 (modulesapp/*,
the route mounting order is preserved byte for byte). - Step 5 —
core/engine/tools/task.ts: 1 926 → 29 (7 modulesengine/tools/task/*, exports 1:1). - Step 6 —
core/engine/orchestrator.ts: 5 393 → 3 777 (9 modulesorchestrator/*+phases/*,
_processMessage1 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-packageAGENTS.mdand 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 areadr-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 indocs/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_ctxis now configured through Synth: theProviderConfig.numCtxfield (APIPOST/PATCH /providers,
CLIsynth config provider add --num-ctx, envSYNTH_PROVIDER_<NAME>_NUM_CTX) and it takes priority over
the model'scontextWindow.- The ollama provider type switched to the native
/api/chat: a URL with/v1is normalized
(the suffix is stripped with a warning), because the OpenAI-compatible layer ignoresoptions/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 andOLLAMA_CONTEXT_LENGTH.
Security
- P0: the WS calls
send_message/permission_reply/permission_hold/cancelnow authorize by session
visibility;/api/v2/fs/*usesauthorizeProject(read/write separately); the backend session routes
(export/notes/optimization/debug-system-message) are undercanAccessSession. - P1: fail-closed for external paths (
external_directory:ask, anddenyin plan/strict);
{dataDir}/secretsand{dataDir}/securityare 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 withSYNTH_CORS_ALLOW_ALL=true),
aSecurecookie by default, avatar containment byusername, a rate limit onPOST /me/identities/claim. - P2: an SSRF policy for
web_fetch(private/loopback/link-local) with manual redirects (≤5 hops);
docker-compose:SYNTH_API_KEYcomes from.env, no hardcoding. - A gitleaks allowlist for confirmed false positives.
Reliability and fixes
- FileMutex: acquisition is confirmed by
mkdir— theENOENTrace betweenmkdirandstatno
longer yields a "lock without ownership" (droppedScheduleStore/FileLeaderupdates); 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/apiKeyaliases,base_urlvalidation,PATCHsupport. - Flakes stabilized:
task-resume(a fresh session read instead of a stale snapshot),webhooks/service
(drain()instead ofsetTimeout), UISchedulerTab/EventsAdminSettings(waitFor/flush instead of emptyactpauses).
Performance and UI
- Code-splitting: the entry chunk went 2 024 → 420 kB (vendor groups, a separate themes chunk, lazy
RightPanel tabs andAppmodals); 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 overdocs/**and**/*.md),ci—
code/UI tests andpnpm 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 ofactions/create-release@v1. - GitHub is a mirror without Actions: the
publish-githubjob pushesmaster:mainand the tags and creates
a GitHub Release; all three base images (synth,synth-backend,synth-ui) are published togitverse.ruandghcr.io(version tag only). - The stub package
@itphx/synth-runnerwas removed (7 → 6 packages);Runnerremains 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, thedocs/en/catalog (ARCHITECTURE, API_V2,
CONFIGURATION, HYBRID, UI-KIT, ROUTING, LLM_PROVIDERS, QUICKSTART, DEVELOPMENT, PUBLISHING, TROUBLESHOOTING,
KEYCLOAK) and the mandatory glossarydocs/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.shgained the--langand--outoptions. - 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
t11prototype 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.1andghcr.io/itphx/synth:0.10.1,ghcr.io/itphx/synth-backend:0.10.1,ghcr.io/itphx/synth-ui:0.10.1 - Helm: the
synthchart 0.10.1
Installation
CLI (npm — from npmjs.org or the GitVerse Package Registry):
npm install -g @itphx/synth@0.10.1Base 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.1The 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).