v0.99.3
Added
-
The experimental VS Code/Cursor extension 0.3.0 now renders file and
directory claims on every visible gutter line, with distinct own/other shapes,
theme-specific contrast, owner hover text, and true-scope overview marks.
Semantic.synapse-symbolclaims follow resolved editor symbol ranges; when a
provider cannot resolve a symbol, one explicit alert marker appears instead
of widening the lease to the whole file. Pure range decisions and VS Code
rendering live in separate focused modules. -
The experimental VS Code/Cursor extension can now authenticate to secured
hubs without a token setting.SYNAPSE: Set hub tokenstores one credential
per canonical hub URI in VS Code SecretStorage; clear deletes it. A real
Extension Development Host test now drives wrong-token refusal, the
SecretStorage store/read/delete path, authenticated roster presence, and a
file claim against a disposable token-gated Python hub. -
synapse identity reclaimadds a deny-by-default recovery path for stale
trust-on-first-use pins. A cryptographically bound operator needs an exact
identity-pin-reclaimACL grant, the observed key id, a reason, and a durable
hub journal. Normal recovery waits for the target socket to disappear and
its ownership lease TTL to lapse, or for a socket-up target to remain without
a recent reaction or live waiter for that TTL after its liveness window;
explicit--break-glassmay evict any other live or still-leased holder.
Every applied action is compare-and-swap guarded,
write-ahead audited, broadcast without key material, and removes rather than
silently replacing the old key. Pin-refusal diagnostics now point at this
governed command instead of manual JSON deletion.
Changed
-
The A2A HTTP+JSON bridge now aligns its explicit 1.0 wire path with the
official SDK/TCK: ISO 8601 UTC task timestamps,application/jsonresponses,
explicitA2A-Versionnegotiation, AIP-193 errors, task-not-found semantics
for unknown continuation ids, context-safe non-terminal continuation, and the
direct 1.0 inline push-config shape. Independent validation with
a2a-sdk==1.1.0completes discovery/send/get/list/cancel; official TCK
5996b79HTTP+JSON MUST results are 55 passed, 5 structured-response
failures, and 175 skipped. This is partial evidence, not certification. -
Stable error taxonomy codes now drive two real boundary families instead of
remaining metadata only. The A2A HTTP bridge maps typed validation, missing,
conflict, quota, and store failures to 400, 404, 409, 429, and 500 without
message matching; outbound MCP CLI commands distinguish invalid config
(exit 2), deny-by-default access refusal (exit 3), and tool failure (exit 1).
Existing A2A exceptions remainValueErrorcompatible. -
synapse whonow bounds the full-roster mailbox-pending section to the 20
largest positive counts and reports complete identity/message totals, so
hundreds of dead test identities cannot flood normal operator output.
--all-mailbox-pending(alias--all) restores the complete retained map;
project filtering happens before the bound. The hub-side 512-identity
projection and durable journal evidence are unchanged.
Deprecated
synapse hub --metrics-query-token-oknow emits a parse-time warning and is
scheduled for removal in 0.101.0. The safe default remains unchanged; send
metrics credentials in theAuthorization: Bearerheader instead of URLs,
where tokens can leak into logs, histories, and proxy records.
Fixed
-
The declared runtime floor
websockets>=12.0was false metadata:
production modules across the client, core transport, and demo layers
importwebsockets.asyncio, which ships since websockets 13.0, so a 12.x
environment resolved by the old floor failed withModuleNotFoundError
on first import. Both public declarations (pyproject.tomland
requirements.txt) now state>=13.0and a packaging test pins the
floor. -
synapse demoand the packaged coding-fleet demo no longer print an
opening handshake failedtraceback on stderr during a clean first run.
Both readiness probes opened and closed a bare TCP socket, which the hub
logs as an aborted handshake atERROR— after the probe returns, so no
probe-scoped suppression could catch it, and the old import-time silencing
targeted the obsoletewebsockets.serverlogger anyway. The probes now
complete one real WebSocket handshake and close it cleanly: no error
record exists to hide, neither module mutates process-wide logging at
import, and genuine handshake errors stay visible. -
The generated
synapse-hub.serviceand the checked-in deploy template no
longer order the hubAfter=default.target. Combined with
WantedBy=default.targetthat ordering formed a boot cycle — systemd gives
target units an implicitAfter=on theirWants=dependencies — and
systemd broke it by deleting the dependentsynapse-presence@and
synapse-arm@start jobs, so presence holders and durable wake listeners
stayed dead after every reboot while readingenabled. Regression tests now
assert that no rendered or checked-in unit installing intodefault.target
orders itself after it. -
EventStore.delete()now uses one static parameterisedDELETEstatement
throughexecutemany()instead of constructing anINclause. This removes
theB608suppression without depending on optional SQLite JSON1 support,
preserves iterable inputs, and reports only rows that actually existed even
when requested sequence numbers are duplicated or missing. -
synapse a2a-servenow cancels and awaits tasks owned by its private agent
event loop before stopping and closing it, so normalCtrl+Cshutdown no
longer destroys live WebSocket keepalive or heartbeat tasks. -
syn inboxandsyn-inboxnow read the exact resolved identity by default
and advance an identity-specific cursor. Previously they silently used the
project-wide filter and shared project cursor, so one terminal could display
and consume another terminal's directed messages. Broader reads now require
the explicit--project-wideflag;--name PROJ/nameselects another exact
address, and existing--asaliases retain independent cursors. -
The A2A HTTP protocol helpers import on Python 3.10 again:
datetime.UTC
(a 3.11 alias) is replaced bytimezone.utc, and mypy now types the whole
tree against the 3.10 floor (python_version = "3.10") so an
above-the-floor stdlib symbol fails locally instead of only in the 3.10 CI
job. Two tools gained the version-branchtomllib/tomliimport the drift
checker already used.
Documentation
- The deployment exposure guide now leads with the recommended team shape —
token and TLS together (nativewss://or a TLS-terminating proxy) —
and describes token-without-TLS as the trusted-LAN fallback that logs the
plaintext-transport advisory. - The docs landing page ranks client paths by evidence-bounded support tiers:
hub +synCLI are the supported core under the stability contract; the
MCP server face is a shipped adapter whose named boundaries the contract
freezes; the A2A bridge is validated, partial interop (official SDK
lifecycle passes; TCK MUST run 55 passed / 5 documented gaps — evidence,
not certification); Go/JS embed within stated boundaries; the cockpit PWA
and VS Code extension preview stay experimental. - The experimental VS Code/Cursor extension now has a repeatable,
version-pinned officialvscepackaging path, a development-only payload
exclusion list, local VSIX installation instructions, and a CI-uploaded
installable artifact. Its unauthenticated-loopback runtime boundary is
unchanged and explicit.
Security
-
The VS Code/Cursor extension refuses non-loopback
ws://connections before
opening a socket, rejects credentials/query parameters/fragments in hub URIs,
and presents a shared token only on the first protocol heartbeat. Remote hubs
require trustedwss://; bearer values never enter settings JSON or URLs. -
The exposure guard now logs a startup advisory when a token authenticates a
non-loopback bind over plaintextws://— the token and every coordination
frame are readable on the network path. Native WSS (--tls-certfile/
--tls-keyfile) or awss://proxy silences it, and--paranoidcontinues
to require native WSS outright. The advisory never blocks the documented
team-LAN posture (transport encryption recommended there), so existing
deployments keep starting — loudly instead of silently.