Skip to content

v0.99.38

Latest

Choose a tag to compare

@github-actions github-actions released this 13 Oct 00:03

Added

  • Read-only delivery receipt projection joining the aggregate to its exact
    source event in one snapshot, with message/state binding, optional row MAC
    verification and SQLCipher key support. Missing, busy, damaged or unverified
    sources remain unavailable. The writer installs a partial MAC index so
    polling does not scan history; readers never bootstrap or migrate a store.
    ReceiptProjectionError has stable code receipt_projection.
    Every existing store receives event_row_mac_idx at its next writable open:
    the first open builds the index and authenticated writes maintain it thereafter.
    Older writers ignore the additive index; a read-only projection never installs it.

  • Foundation of the operations catalogue: a description of one operation of
    one vendor client on one host (vocabularies, typed arguments, a
    qualification level with its evidence) and a catalogue that lists them and
    admits only operations that were run for real, for exactly the client and
    version asked. A client version never seen admits nothing. A secret is
    never an argument value, only a reference. synapse ops list and
    synapse ops describe read a catalogue file; nothing runs an operation
    yet. See docs/operations.md.
    The catalogue is now version 2 (operation-catalogue-v2): a name is two or
    three registered words (object.aspect.action) from a tracked vocabulary,
    a row is identified also by component, transport and variant, it states how
    its arguments are bound to the client's own command or request, every effect
    it has and the one permission each effect needs, what it discloses and what
    it asks of the caller. A row is admitted only while the executable found now
    is the one that was qualified and the row is byte-for-byte what was
    qualified. A version 1 file is still read, as an inventory that admits
    nothing. synapse ops gained --transport.

  • Launch records: synapse worker-session writes, for each provider it
    starts, a new owner-only file with the digest of the executable the command
    named, the created process with its start identity and the image it runs;
    in a tmux-backed session the pane's process. Only the command's name, word
    count and digest are kept. The record is the seat's own declaration, not an
    attestation, and says so. A record that cannot be written is reported and
    the session starts all the same. LaunchRecordError has stable code
    launch_record. See the API reference.

  • Foundation of the wake relay: a seat is woken for a message over the first
    adapter that takes it, at most once. Before an adapter is asked its attempt
    is marked on disk, after it the outcome; accepted or uncertain ends the
    work for that message, only refused lets the next adapter run, and an
    attempt left without an outcome by a process that died reads as uncertain.
    Adapters receive one fixed prompt and never a message. Two adapters exist:
    pane_bridge wraps the existing pane bridge unchanged, and native_queue
    queues the prompt through the Codex client's own daemon. Adapters can be
    ordered per seat by the measured median time to acceptance. No service uses
    the relay yet. See docs/wake-relay.md.

  • synapse native-hook claude records a message one session sends to another
    over the client's own channel, without anyone calling native-record: run
    as a PostToolUse hook, it reads the tool call from standard input, writes
    the sender's record to a spool on disk and then tries the hub. It prints
    nothing and exits 0; the send has already happened and the hook cannot
    fail it. The record leaves pending/ only after the hub confirmed it. The
    same call gives one entry and one event, also when several hook processes
    run at once: an entry is created without replacing an existing one, and one
    flush runs at a time. Retry is bounded and a refusal of the record is
    final. native-hook flush and native-hook status work on the spool.
    synapse event-query <db> "native-messages <seat|all>" pairs the sender's
    and the receiver's record of each message and lists the one-sided ones,
    without printing any message text.
    synapse native-seat keeps the local register that says which seat a
    native session is. See docs/cli.md, "Recording from a client hook".

  • synapse label sets the tab label and the status lines of the tmux session
    it runs in, so that a terminal says which group, project, vendor and seat
    work in it. The tab label is short; the status lines carry every detail and
    wrap to the terminal width, again after a resize. Group abbreviations come
    from a profile file. Text is displayed and never run: control characters
    are removed and # is doubled before a value reaches a tmux format. Only
    the one session is changed, and --restore puts its earlier label and
    status back. See docs/terminal-label.md.

  • synapse service status prints, for every Synapse user unit, what is
    wanted of it and what it does: enablement, state, restart count, last
    result, the start limit it was loaded with and the processes its unit file
    says it owns. It names units that are enabled but failed or not running,
    units that restart, and units that still restart without a start limit,
    prints the recovery commands without running them, and reports where the
    tmux server lives. --json gives the same report to a dashboard.

  • The tmux server no longer lives in the control group of the unit that
    started it. When synapse agent-tmux start or synapse worker-session
    would create the tmux server, it starts in a transient systemd scope of its
    own, so stopping the calling unit no longer kills every session on the
    host. synapse service tmux-server prints which unit holds the server and,
    with --move, moves a running server out of a service unit without
    restarting it. Without a systemd user manager tmux starts as before.

  • synapse service hub-restart reads from systemd which user units depend on
    the hub and prints what a restart would do to each. Given the exact process
    id of the running hub it restarts the hub as one service-manager job, never
    as a separate stop and start, waits until the hub answers, and reports each
    dependent as unchanged, restarted, stopped, started or changed. It refuses
    when systemd would restart other units with the hub, unless that is
    explicitly allowed, and it starts, stops or resets no other unit.

  • Blocking CI jobs audit every committed Python requirement lock and npm lock,
    including client and integration dependencies, on every main push and PR.
    Newly tracked locks join the audits automatically.

  • Record-only native_message_record verb (wire version 7). A seat leaves a
    durable record of a message that travelled over a vendor's own channel, such
    as a direct message between two Claude Code sessions or a queued Codex
    message. The hub stores one native_message event and delivers nothing; it
    stamps the recorder, the time and how the recorder's name was bound to the
    connection, and accepts a record only from the seat on its own side.

Changed

  • Both HTTP servers (the A2A bridge and the dashboard) end a connection in
    order. A connection answered before its request was read to the end, such
    as a capacity or Host refusal, is kept only to discard the remaining
    bytes: at most two seconds and two mebibytes per connection and 64
    connections at once, on one thread per server and outside the admission
    bound. On Windows the immediate close reached the client as a reset and
    cost it the answer. A dashboard live-stream client that leaves ends its
    stream quietly on Windows as elsewhere.

  • Split event storage into shared-connection table families and keyed mutation
    preparation/commit steps, preserving public signatures, records, transaction
    observers and durable outcomes. Journal replay dispatches through event-family
    appliers while preserving protected-custody refusal and projection ordering.

  • Hub frame processing now separates envelope admission, connection
    registration and an ordered gate runner. Existing authentication, identity,
    quota, recovery, federation and local-authority checks retain their order.
    Server startup and shutdown use explicit lifetime stages while preserving
    background-task joining, checkpoint anchoring and caller-owned stores.
    Wire messages, CLI options and hub constructor exports are unchanged.

  • Generated systemd user units have a finite start budget. A unit that keeps
    failing waits longer before each restart and ends in the failed state: the
    hub after about 3.5 minutes, presence, wake-listener and waker units after
    about 26 minutes. They previously restarted without limit. Each unit text
    names the processes it owns. Units already installed keep their old text
    until they are regenerated and restarted. The growing delay needs systemd
    254 or later; docs/deployment.md gives the times on older versions.

  • Update cockpit Node.js type declarations to 26.6.4, the GitHub App's
    hash-locked verification dependencies, and the image SBOM action to 0.24.3.
    The image scanner remains explicitly pinned to Syft 1.50.0.

  • CLI mailbox wakes coalesce repeated copies of each durable hub/sequence
    pair while retaining distinct events with identical text and legacy frames
    without valid sequence metadata. Waiters join connection cleanup before
    persisting their surfaced cursor.

  • Lock teardown catches asyncio timeouts on Python 3.10 as well as newer
    interpreters, allowing exact read-only confirmation after a lost release
    reply without replaying the mutation.

  • Hub startup now uses an external composition root. build_hub(config) builds
    typed collaborator families and installs them once; the CLI and base
    SynapseHub.from_config use that path. Existing record and keyword callers
    delegate to the same builder. Custom component factories can supply real
    services, with checks for target/configuration custody and failure cleanup.

  • Hub verb declarations now live beside their handlers. Dispatch, idempotency
    replay protection, ACL access mapping and the journal recovery guard derive
    from that registry. The existing wire vocabulary and guard memberships remain
    unchanged. ACL targets now follow task_update's task_id/id precedence
    and release's task_id/payload precedence, preventing an unrelated payload
    from authorizing a different task or blocking an authorized release.

  • Coalesce overlapping cross-hub chat attempts and terminal sender receipts per
    durable forward. Cancellation releases transient ownership, late answers
    preserve expiry, and independent chats remain concurrent. Offline receipts
    stay pending across restart. Transport exceptions and peer error frames now
    produce fixed diagnostics for chats, roster queries and delivery requests.

  • All hub handler families now declare structural capability contracts,
    including requirements of their forwarding and claim-presence helpers.
    Strict typing verifies the concrete hub at dispatch registration. Contracts
    are internal and static; runtime dispatch, late-bound overrides, wire, CLI
    and the public Python exports remain unchanged.

  • CLI hub queries and task-plan writes now fail with exit 1 when no matching
    reply arrives, instead of silently returning 0. The diagnostic explains
    that a write may already have committed; no automatic retry is performed.

  • synapse lock now returns 1 for refused cleanup or 3 for uncertain cleanup
    after a successful child. Nonzero child exits remain unchanged. Diagnostics
    retain the child status and exact read-only recovery command without exposing
    credentials embedded in the hub URI.

  • A structure budget now guards src/synapse_channel and tools against a unit
    taking on a second responsibility. tools/structure_budget.toml lists every
    class, function and module above a threshold of constructor parameters,
    constructor attributes, constructed collaborators, function length, branches,
    internal imports or access to another object's private members. The
    pre-commit hook and the CI lint job refuse a new unit above a threshold and
    any listed figure that rises; a figure that falls must be lowered in the
    ledger in the same commit.

  • The methods of SynapseHub that the handler modules call carry public names:
    system, send_json, broadcast, broadcast_directed, send_to_agent,
    mirror_to_relay, run_atomic_operation, settle_atomic_operation,
    remember, next_msg_id and the message_seq property replace the same
    names with a leading underscore. Behaviour, the wire and the CLI are
    unchanged. Code outside this repository that calls or overrides one of the
    old names on a hub must use the new name; they were never part of the stable
    Python API, which is the package export list. The static helper
    SynapseHub._optional_int is now the function
    core.numeric_coercion.optional_int_field, and the hub's wait graph is the
    attribute waits. The identity members the handlers read are the public
    attributes identity_pins, static_identity_trust,
    enrolled_identity_keys, enrollment_rate, clock and liveness; an
    enrolment, rotation or revocation takes effect in memory through
    SynapseHub.replace_enrolled_identity_keys.

Fixed

  • A native-message spool on an unavailable Windows volume is refused instead
    of looping while looking for an existing parent. Manual flush reports a
    fixed directory-access refusal; the post-send hook stays quiet and exits 0.

  • Implicit identity-pin selection now checks journal paths with stat before
    opening SQLite. Symlink loops on Python 3.13 and directory paths get the
    controlled startup refusal instead of a traceback; only a genuinely missing
    journal can initialise a new pin namespace.

  • Separate custom hub journals now use separate default identity-pin files,
    including journals in one directory. Startup publishes an empty companion
    atomically without overwriting existing pins; an ambiguous upgrade requires
    explicit operator selection before opening the journal. Conventional and
    explicit defaults retain their contract. See docs/identity-and-acl.md for
    migration and Windows directory permissions.

  • Handoff ACL checks now use the stripped task_id consumed by the handler,
    preserving declared path checks. Ignored payload and id aliases cannot
    select a different permission target; malformed payload-only requests are
    refused before dispatch.

  • Document the group and project map with SVG, PNG and JPG exports, separating
    existing optional adapters from claims of joint qualification.

  • Send write timeouts on Python 3.10 return delivery unknown with exit 3.
    A failed write aborts the one-shot sender's socket before joining its listener,
    keeping a peer that stops reading from blocking shutdown. No message is replayed.

  • Review current official client release notes and record explicit host upgrade
    and security acceptance boundaries. Reviewed notes do not admit newer hosts
    or change the installed client profiles.

  • Conflict prediction repeats a missing read-only state query once within its
    existing response deadline and joins its connection shutdown. Persistent
    snapshot loss still refuses the prediction; lease mutations are never replayed.

  • Regression journeys now exercise the documented uncertain cleanup exit on
    legacy hubs, select a coordination event for causality queries, and validate
    the Python 3.10 typing backport separately from modern runtime dependencies.

  • JavaScript and VS Code development locks use source-map-js 1.2.2, fixing
    indexed source-map denial of service (GHSA-68fv-2mgg-jv7q). Open VSX uses the
    already pinned VS Code packager, removing its vulnerable braces dependency
    chain (GHSA-vfj7-8cjw-p6xm).

  • Read Codex vendor-watch evidence from its official stable-release API and
    validate its exact release-tag prefix. Documentation layout changes no longer
    make the source unavailable; strict source and review checks remain enforced.

  • Render grouped hub construction and legacy keyword options in their correct
    API-reference sections, and resolve the benchmark guide link on the docs site.
    The strict documentation build remains enabled.

  • Lock cleanup uses a fresh client profile to read the epoch persisted by a
    same-identity child renewal, instead of releasing with the parent's stale
    epoch. One keyed release survives interrupted teardown; lost replies recover
    through the exact durable operation without replaying the mutation. Invalid
    readiness or cleanup deadlines fail before acquisition.

  • Structure-budget configuration exceptions now enforce their expiry and
    recorded threshold maximum, including after admission into the baseline.
    Removing a measured source root cannot hide new responsibility debt; failed
    checks and updates preserve the original ledger.

  • End refused WebSocket upgrade attempts cleanly in the Python client. Health
    and roster probes return failure without a transport traceback, and the same
    agent can reconnect after the hub URI or tunnel destination is corrected.

  • Pin the Pi host's brace-expansion dependency to 5.0.12 and verify its actual
    installed files after npm ci. The upstream shrinkwrap could otherwise
    reinstall vulnerable 5.0.9 while the outer lock's audit reported no finding.
    The reviewed SHA-512 archive replaces only this dependency; Pi remains 0.87.1.

  • Review the Codex 0.160.0 release notes for the vendor watch while preserving
    the exercised 0.156.0 Linux stdio profile and separate Windows admission.

  • Exercise lost release and confirmation replies before corrupting durable proof.
    The runtime regression now confirms the original operation through a separate
    read-only CLI recovery and proves that no second release occurs.

  • Correlate claim and wait replies by task, owner and recipient in the real
    deadlock regression. An unrelated earlier claim broadcast can no longer
    start the wait before the other participant owns its task.

Artifact checksums (SHA-256)

ae0bace02674dad99d21087ed0801fe4290580b0eeccac33367e6f242c429cee  synapse_channel-0.99.38-py3-none-any.whl
7bb3062cd20edf9569eb52bd15ab60ba2ce03b6813e7fa5647c65fc119775c08  synapse_channel-0.99.38.tar.gz
6e92fe9187b2367ea4c2a2e719ef19196035ecb5a53f9d2cfe398efb2492a3a1  synapse-channel-v0.99.38-sbom.cdx.json