Repository navigation
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.
ReceiptProjectionErrorhas stable codereceipt_projection.
Every existing store receivesevent_row_mac_idxat 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 listand
synapse ops describeread a catalogue file; nothing runs an operation
yet. Seedocs/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 opsgained--transport. -
Launch records:
synapse worker-sessionwrites, 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.LaunchRecordErrorhas 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;acceptedoruncertainends the
work for that message, onlyrefusedlets 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_bridgewraps the existing pane bridge unchanged, andnative_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. Seedocs/wake-relay.md. -
synapse native-hook clauderecords a message one session sends to another
over the client's own channel, without anyone callingnative-record: run
as aPostToolUsehook, 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 exits0; the send has already happened and the hook cannot
fail it. The record leavespending/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 flushandnative-hook statuswork 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-seatkeeps the local register that says which seat a
native session is. Seedocs/cli.md, "Recording from a client hook". -
synapse labelsets 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--restoreputs its earlier label and
status back. Seedocs/terminal-label.md. -
synapse service statusprints, 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.--jsongives the same report to a dashboard. -
The tmux server no longer lives in the control group of the unit that
started it. Whensynapse agent-tmux startorsynapse 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-serverprints 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-restartreads 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_recordverb (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 onenative_messageevent 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 orHostrefusal, 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 thefailedstate: 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.mdgives 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_configuse 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 followtask_update'stask_id/idprecedence
andrelease'stask_id/payloadprecedence, 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
1when no matching
reply arrives, instead of silently returning0. The diagnostic explains
that a write may already have committed; no automatic retry is performed. -
synapse locknow returns1for refused cleanup or3for 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_channelandtoolsagainst a unit
taking on a second responsibility.tools/structure_budget.tomllists 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
SynapseHubthat 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_idand themessage_seqproperty 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_intis now the function
core.numeric_coercion.optional_int_field, and the hub's wait graph is the
attributewaits. The identity members the handlers read are the public
attributesidentity_pins,static_identity_trust,
enrolled_identity_keys,enrollment_rate,clockandliveness; 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 exits0. -
Implicit identity-pin selection now checks journal paths with
statbefore
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. Seedocs/identity-and-acl.mdfor
migration and Windows directory permissions. -
Handoff ACL checks now use the stripped
task_idconsumed by the handler,
preserving declared path checks. Ignoredpayloadandidaliases 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 unknownwith exit3.
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-js1.2.2, fixing
indexed source-map denial of service (GHSA-68fv-2mgg-jv7q). Open VSX uses the
already pinned VS Code packager, removing its vulnerablebracesdependency
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 afternpm 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