Skip to content

v0.99.12

Choose a tag to compare

@github-actions github-actions released this 20 Jul 16:02

Security

  • Always install a WebSocket handshake Origin/Host guard on the core hub
    (even when metrics are disabled): browser Origins require an explicit
    concrete --allow-origin allow-list; Host authorities are derived from
    the loopback bind and optional --advertised-host (no wildcard trust);
    origin-less native clients remain compatible only through a trusted Host;
    disallowed upgrades receive a deterministic 403 before the socket
    upgrades and cannot read history.
  • Persist a hash-chained, owner-only Merkle checkpoint of the durable event
    log OUTSIDE the log it attests, and verify it fail-closed before the hub
    serves: a log shorter than its checkpoint (tail truncation) or a recomputed
    prefix root that differs (log replacement) now raises AntiRollbackError
    at startup instead of restarting silently. Once verified, the hub anchors
    the current state as the newest chain link. synapse merkle checkpoint
    shows the newest link or verifies the log against it (exit 0 clean / 2
    detection, JSON verdict). This is the local anti-rollback layer only;
    external witnessing stays owner-gated and out of scope.
  • Bound open-hub idle sockets and single-host connection floods by default:
    --max-connections-per-host now defaults to 32 (pass 0 to disable),
    and every hub — open or secured — reaps a socket that does not bind a name
    within --auth-timeout (close code 4012; open hubs use reason
    registration timeout). Secure mode clamps the open default down to its
    stricter per-host ceiling rather than refusing hub --secure solely for
    inheriting the open default.
  • Serve the multi-hub event log only under an operator-configured
    MultiHubServingPolicy: a hub with no policy now refuses every peer
    (fail-closed) instead of serving the entire log to any unauthenticated
    frame, matching the operator-relay posture. A refused peer receives an
    empty snapshot that leaks neither the log nor the grant's existence.
  • Key wait edges by the waited task instead of the incumbent holder and
    resolve ownership live at cycle-check time: a claim, renewal, or handoff
    for one task can no longer erase a wait on an unrelated task, and a
    release, lease expiry, handoff, or disconnect can no longer leave a stale
    agent edge that refuses a later legitimate wait as a false-positive
    deadlock. Wait edges prune on release and on every heartbeat-driven lease
    expiry.
  • Reserve the global agent names SynapseHub, Synapse, and system
    case-insensitively so a client cannot impersonate hub or protocol provenance.
    Registration is refused before authentication, trust-on-first-use pinning,
    takeover, or ownership-lease state changes. Project-scoped identities such as
    PROJECT/system remain valid; clients using a reserved global name must
    migrate to a non-reserved or project-scoped identity.
  • Persist authenticated-frame nonce decisions so a journal-backed hub restart
    no longer re-opens the in-memory replay window. Optional compatibility or
    strict sequence-floor modes use the same durable boundary; configured stale
    sequences, nonce replays, sender mismatches, expired keys, and invalid domains
    fail closed.
  • Bind relay-approval and live-claim quota accounting to server-derived
    principals rather than client-selected display names, closing identity-churn
    bypasses without weakening project-scoped identities.
  • Bound accepted durable chat ingress before history or journal growth, using
    server-derived principal windows over event count and full normalized frame
    bytes; active buckets cannot be reset by reconnect churn.
  • Journal claim and guard denials as authenticated evidence. A guard that
    cannot persist its denial remains fail-closed and does not silently turn an
    unrecorded refusal into an allow.
  • Bound A2A HTTP admission and request-body reads so slow or oversized clients
    cannot occupy the bridge indefinitely.

Added

  • Board tasks carry an optional project scope and a monotonic version, with an
    expected_version compare-and-set guard on ledger_task/ledger_task_update
    and matching synapse task declare --project/--expected-version and
    task update --project/--expected-version flags. A re-declaration with a
    conflicting non-empty scope is refused, the guard refuses stale writers, and
    both fields journal and replay durably.
  • Persistent capability registration for automated dispatch: an advertise
    with persist: true registers a project-scoped seat's card so it survives
    disconnects (24-hour refresh TTL), with dispatchable opt-out, a structural
    -rx sidecar path for wake listeners registering their seat, and additive
    persistent/dispatchable keys in the manifest. synapse wait --capability-card FILE re-registers the card on every (re)connect, so
    registration self-heals across re-arms and hub restarts.
  • Opt-in ready-task dispatcher: synapse dispatch --project P computes a
    deterministic plan from live board/state/manifest/who snapshots, pins
    suggested_owner through the version compare-and-set guard, and wakes the
    seat's online identity under a stable idempotency key — exactly once, even
    across crashes, via an append-only JSONL outbox that reconciles pending
    intents on restart. A dispatch:<project> singleton lease serialises
    concurrent dispatchers; the dispatcher never claims real tasks, approves,
    lands, or broadcasts.
  • Native Agent Evidence Format (AEF) runtime: restricted JCS canonicalization,
    integer time, versioned signature domains, Ed25519 receipt verification,
    durable replay/conflict decisions, legacy-event projection, native chained
    receipt emission, a crash-safe outbox, and hub/CLI runtime integration. The
    verifier distinguishes legacy evidence from native AEF rather than upgrading
    old guarantees by presentation.
  • Durable federation partition/heal lifecycle evidence, including replay after
    restart, so a past degraded interval is queryable instead of existing only
    as transient operator state.

Changed

  • Validation documentation now reports the enforced 98% coverage floor and
    the dated 98.85% Codecov measurement separately; it no longer turns the
    badge's rounded 99% display into an unsupported "above 99%" claim.
  • The release workflow now publishes the verified wheel and sdist SHA-256
    digests in the GitHub Release notes body itself (a fenced "Artifact checksums
    (SHA-256)" section), not only as the attached SHA256SUMS asset, so a
    consumer can confirm own-provenance straight from the release notes. The
    digests are the same ones sha256sum --check --strict-verified before the
    assets are attached.
  • The identity-and-ACL guide now carries an end-to-end worked example for
    recovering a changed machine key through the governed pin reclaim: a
    copy-paste identity-pin-reclaim ACL grant, the fresh-TOFU recovery-operator
    recipe that sidesteps the bootstrap paradox, and the exact synapse identity reclaim invocation with its compare-and-swap and audit-trail guarantees.
  • Cockpit and Studio bootstrap configuration is now inert JSON consumed by
    same-origin scripts; production script-src stays at 'self' without an
    executable inline-script exception.
  • Ordinary CLI and MCP path claims inside Git now resolve the same canonical
    worktree identity as git-claim, while deliberate keyless mutexes and
    genuine non-Git scopes retain their previous semantics.

Fixed

  • Keep ambient agent-tmux wakes from replacing active user work with an
    unconditional stop. The fixed payload-free prompt now gates work on the
    configured/current identity and an exact-target inbox item, ignores routine
    status and broadcast-only wakes, resumes the active user-directed task when
    there is no actionable directed work, and waits only when otherwise idle.
  • Apply durable claim-family mutations atomically: provisional state remains
    private until the SQLite transaction commits, failed persistence restores
    the prior state exactly, and post-commit cleanup cannot invert durable/live
    truth. The serialized mutation actor moves guarded storage work off the event
    loop and drains in-flight work before cancellation propagates.
  • Carry a bounded client_msg_id through live chat, retained history, durable
    replay, mailbox delivery, and receipt frames so at-least-once receivers can
    deduplicate reconnect retries without the hub silently dropping attempts.
  • Reject oversized JSON integer literals as malformed frames instead of letting
    Python's integer-conversion limit escape the protocol boundary and close the
    client with an internal-error status.
  • Use the supported asyncio WebSocket server API across the declared
    websockets>=13 range, restoring real registration plus /health and
    /metrics on both the dependency floor and current releases.
  • Exit synapse listen non-zero when the hub closes the connection instead of
    leaving a dead listener process apparently alive.
  • Keep container health probes aligned with the concrete Host authority on a
    wildcard bind; both Docker's health check and the compose CI smoke use
    ws://127.0.0.1:8876.

Artifact checksums (SHA-256)

f4a6e5bd17e3081ee004df22a78727a40c87610e5e81aafc558d9609e567d44c  synapse_channel-0.99.12-py3-none-any.whl
089e540242a2ad713ae81d345c04bb527fb8206e988a36e32324a411f5e20f6c  synapse_channel-0.99.12.tar.gz
2bbbb2ade980a8c78f37afbb9aabe493792d42d8f6a8bbe2c12c54930d540649  synapse-channel-v0.99.12-sbom.cdx.json