v0.99.6
Added
-
OpenCode 1.17.20 is now a pinned Participant Fabric and IDE bridge. A
reversible project/global adapter owns one local-stdio Synapse MCP entry and
one fail-closed native mutation plugin; strict ownership, bounded race-aware
file updates, token-file persistence, and uninstall preservation keep existing
OpenCode configuration outside its scope. Exact-version headless JSONL and
authenticated HTTP API participants, cancellation, remote attach delivery,
and an ACP protocol-v1 handshake are covered by isolated real-process tests.
The focused CI lane verifies the official OpenCode archive and extracted
binary hashes before exercising adapter lifecycle, claimed/denied native
writes, local turns, authenticated server access, and package contents. -
The experimental VS Code/Cursor client now consumes a bounded strict editor
wire projection with version negotiation, stale-last-good state, fail-closed
mutations, bounded reconnect/backoff, and safe identity/auth close handling.
Claims and releases use canonical Git/workspace roots plus deterministic
per-file task IDs, so multi-root workspaces and two files held by one identity
remain distinct. Gutter projections require the exact canonical worktree and
path; stale credential reads cannot restore an older configuration; switching
hub or identity clears the previous projection; and terminal authentication or
seat-ownership refusals wait for an operator change instead of retrying. Focused
coverage is enforced above 95%, while a real VS Code
Extension Development Host exercises two independent token-gated hubs,
per-hub SecretStorage, configuration reconnects, identical relative paths in
two real Git roots, exact claims, and exact releases. Runtime, timer, protocol,
scope, and test-harness responsibilities
remain split below the documented Godfile threshold. -
synapse hub --secureis the strict multi-seat production umbrella: it
composes the--team-securetrust profile and the--paranoidexposed-hub
profile, then bounds per-agent (100/s, burst 20), per-host (500/s, burst 100),
and per-host connection (10) flood limits. Missing operator material fails
closed before any socket binds, listing every absent input in one aggregate
error; a stricter positive limit is preserved and a rate, burst, or
connection cap above a preset ceiling is refused; startup prints one
consolidated report of the composed gates, effective limits, and the controls
the preset genuinely does not compose. It generates no credentials and enables
no metrics surface. See Secure mode. -
--message-auth-key-fileand--metrics-token-fileread hub secrets from
owner-only (chmod 600) files instead of argv, so a per-message HMAC key or
metrics bearer token is not exposed in the process list. The key file carries
oneKEY_ID:SECRET:SENDER[,SENDER...]entry per line (#comments allowed)
and merges with argv keys for rotation; an explicit--metrics-tokenwins
over its file, mirroring--token/--token-file. The loader refuses a group-
or world-readable file and reports problems by flag and path, never by content.
Security
- Human-readable chat, channel, hub-query, mailbox, routing, resource-bid,
federation-relay, peer-hub, capability-directory, outbound-MCP, workflow,
event-query, memory-recall, accounting, acknowledgement, and Participant
Fabric output now renders ANSI, OSC, carriage-return, newline, bidi, and other
control characters as visible escape notation before they reach a terminal.
Copyable operator commands shell-quote terminal-safe values, bind long-option
values with=, and terminate positional options with--. Generated shell
wrappers, git hooks, and systemd units use the same option boundary; custom
shell providers must be bare command names. This closes command-substitution,
option capture, and shell-function injection paths in setup, doctor, locks,
federation exchange, SQLCipher guidance, claim helpers,fleet-init, and
automatic waiter, provider, hook, and service-start flows. - Headless Claude turns now disable built-in tools, ambient MCP servers, skills,
plugins, hooks, browser integration, and customisations explicitly while also
selecting plan permission mode. Unsupported older CLIs fail closed rather than
accepting a bus prompt with weaker local execution policy. - The hub rejects a non-finite (
nan,inf)--rate,--burst,--host-rate,
or--host-burstat the argument parser for every run:nanpreviously passed
every downstream comparison and then built no limiter at all, so a hub could
appear rate-limited while enforcing nothing.--secureadditionally rejects a
non-finite value and holds each burst to its own ceiling. - The exposure guard now runs before the durable event store is constructed, so
a refused unauthenticated non-loopback bind leaves no database file on disk. SECURITY.mddistinguishes host ingress from container-network reachability:
same-network containers reach the hub container-to-container regardless of the
host publish flags. The shippeddocker-compose.ymlnow attaches the hub to a
dedicated single-service network so both audiences are bounded.- The
--securereport no longer copies the paranoid profile's
"compose--team-secure" missing-hook line, which the umbrella already
enforces; genuinely uncomposed controls (at-rest encryption, mutual TLS, …)
stay listed.
Documentation
-
SECURITY.mdnow explains the container image bind posture that external
audits kept re-flagging: the in-container0.0.0.0bind is required for
port publishing, the exposure guard refuses startup withInsecureBindError
on an unauthenticated non-loopback bind, and the shipped compose file pairs
a loopback-only publish with a dedicated network and the explicit
--insecure-off-loopbackopt-out. The Dockerfile comment now states the
refusal instead of understating it as a warning, and documentation-accuracy
regressions pin both surfaces. -
Secure mode documents the file-backed secret flags and
the burst ceilings, and its production example delivers every secret from an
owner-only file instead of expanding it into argv. -
synapse a2a-serve --allow-origin ORIGINrestricts browser requests to an
opt-in allow-list of exact web origins (scheme://host[:port], ornull),
repeatable for several. A request whoseOriginheader is not listed is
refused403on every route — the public agent card included — before
authentication; a non-browser client sends noOriginand is unaffected, and
with no list configured the check is a no-op. Hardens the loopback bridge
against DNS rebinding and drive-by browser requests.
Fixed
-
Failed headless provider turns no longer copy raw CLI stderr or process-start
exception text into relayable or durable results. Claude, Codex, Gemini, Grok,
Kimi, and Ollama now expose only the exit status plus a bounded safe
classification; unknown diagnostics are withheld. Gemini's binary-health row
also states that account entitlement was not probed, while a recognised retired
consumer-account failure points operators to Antigravity or an eligible
enterprise/API-key configuration. -
synapse git-initnow stores staged-claim identity, hub URI, and the optional
token-file path in Git's official per-worktree config. Linked worktrees can
therefore use different exact seat identities without overwriting one another;
migration removes the old shared values only after the current worktree is
configured and refuses unsafecore.worktree/core.bare=truelayouts with
an explicit repair instead of guessing. -
The MCP guide now reflects the live official-registry state: SYNAPSE CHANNEL
is active there, while a newerserver.jsonremains only a prepared update
until the immutable registry record exposes that exact version. -
Path-based claim enforcement now rejects symlink loops and broken path
components consistently on Python 3.10–3.13 while retaining support for
valid paths whose final file or directory does not exist yet.