Skip to content

Releases: husker/a2acast

0.21.0 — actor attestation end-to-end (default off), real exec on owner-signed grant

Choose a tag to compare

@husker husker released this 28 Aug 22:34
c82aa13

Actor attestation lands end-to-end (parse → emit → surface → authorize), the
owner-signed grant gains a real exec path, and the receive path stops
persisting task state from frames it has not authenticated. Every new wire
behaviour is off unless the operator turns it on: actor_receive,
actor_emit, and require_actor_for_exec are each read with is True, so an
absent key is off and older peers are unaffected.

  • #188 Phases 1–3 — actor attestation. A frame can now carry which actor
    (harness session) acted, not just which node. Phase 1 parses and verifies the
    actor field on receive (actor_receive, default off); Phase 2 emits it
    sender-side behind an explicit fleet-capability assertion (actor_emit,
    default off); Phase 2b surfaces the verified actor fingerprint in deliveries;
    Phase 3 authorizes auto-exec on the (node, actor) pair against a curated
    actor_allow map when require_actor_for_exec is on (default off). This
    addresses the #136 boundary that co-located agents share one node key — but
    only once an operator enables it; shipping the code changes no live posture.
  • #186/#187 — authenticate frames before task persistence. The receive path
    wrote task records before the frame's verdict was established. Task state is
    now written only after authentication.
  • #157/#62/#180 — B2b-2b: real exec on an owner-signed grant. A verified
    owner-signed grant can execute a curated pipx/pip/uv-tool-pypi upgrade,
    making the operational half of #62 usable rather than dry-run only. Gated on
    the existing curated exec_allow; the roster is not an authorization source.
  • #158/#178mesh fleet WAKE column. The wake-stall verdict is now
    reader-assertible fleet-wide instead of local-only.
  • #177/#179 — presence liveness requires proven delivery. A live pid is no
    longer accepted as proof a node will deliver; a wedged hook holding the
    relay subscription reads as stalled rather than listening.
  • #76 F3/#185 — separate auto-discovery roster budget. Auto-discovery no
    longer consumes the operator-seeded roster budget.
  • #182/#192 — aged fleet-health reports render as stale(<age>), not
    unknown, so a report that arrived and aged is distinguishable from one that
    never arrived.
  • #136/#189, #183/#184 — docs. The node-identity boundary (one node key per
    machine, shared by co-located agents) and what the mesh health signals do and
    do not prove.
  • #190 and iam-rename test hermeticity. Two tests depended on wall-clock
    polling and ambient node identity; both are now deterministic.

0.20.0 — fleet-wide liveness: supervised + wake-path watchdogs, remote receiver/agent health, mesh fleet

Choose a tag to compare

@husker husker released this 01 Aug 23:20

Fleet-wide liveness truth: every stall mode of a receiver is now detectable, most are auto-recovered, and each node's health is visible from every other node — plus two receive-path crash-class fixes. All new presence fields (recv/agent/wake) are additive, advisory, and display-only; older peers ignore them and read as "unknown" (mixed-version-safe).

  • #158/#164watch --supervised stall-watchdog: a supervised receiver with a stale heartbeat recovers itself (close-response, then os._exit under a KeepAlive restarter).
  • #166/#167 — presence carries receiver-health: pong/ack frames stamp the sender's own recv: healthy|stalled.
  • #169mesh fleet: read-only fleet health table (last-seen, posture/status, RECEIVER/AGENT columns).
  • #170/#171 — agent-liveness heartbeat: distinguishes a live agent from a bare watcher; propagated as a raw agent: active|idle column.
  • #173/#175 — receive-path type-gating: crafted authenticated frames carrying non-strings where state strings are expected can no longer crash the receive loop.
  • #158/#176 — wake-path watchdog: detects deliveries buffered while no agent drains them; SIGTERMs a positively-identified wedged defer-mode hook (relay/unknown-mode holders never touched, pid-reuse guarded) so the wake path re-arms; surfaces the unarmed case via classification logs, mesh status, and a wake: ok|stalled presence key.
  • #168 — no session URLs in the public record (repo attribution kill-switch + CLAUDE.md hard constraint).

See CHANGELOG.md for detail. Upgrade nodes with pipx install --force a2acast (or your install method) and restart long-lived mesh processes to cycle onto the new code.

v0.19.0

Choose a tag to compare

@husker husker released this 30 Jul 04:48
e648ca6

Receiver-stall visibility (#158/#161), a Windows signing fix (#159), and the first real-exec slice of supervised adoption (#162 B2b-2a, dormant/default-off).

  • #158/#161 — per-node receiver heartbeat + mesh status ok/STALLED/no-heartbeat indicator; a silently stalled watcher is now visible instead of dark.
  • #159A2ACAST_SSH_KEYGEN override fixes the Windows OpenSSH 9.5p2 -Y sign ~60s timeout race that degraded frames to unsigned.
  • #162adopt-supervise --exec applies owner-signed git-working-tree upgrades (fetch-verify the signed SHA -> checkout -> import smoke-test -> local rollback on won't-start). Dormant: default dry-run; a received frame never auto-execs.

Independently seated (lighthouse) + CI green including all Windows lanes.

v0.18.0 — owner-signed approvals over the mesh (observe-only / dry-run, default-off)

Choose a tag to compare

@husker husker released this 29 Jul 01:35
b8aae9d

Fleet-adoption release for the #62 owner-signed-approval pipeline. Every step below is off by default, log-only or dry-run, and inert on 0.17.0 nodes — the fleet adopts the wire format before any node acts on an approval.

  • Phase A (#152)mesh approve … --broadcast distributes an owner-signed grant; a receiver verifies it against the pinned owner pubkey and logs MESH_APPROVAL_OK/BAD. No action, no nonce consumed.
  • B1 (#153)act_on_approvals opt-in (default off, operator-only, never frame-settable); when on, logs MESH_APPROVAL_WOULD_ACT, still no action.
  • B2a (#154) — a verified adopt-release grant writes an authenticated pending-adoption record + logs MESH_ADOPT_PENDING. Receive path runs no code.
  • B2b-1 (#155)mesh adopt-supervise (operator-run, opt-in) reads a pending record, re-verifies the owner signature, detects install type, maps the pinned artifact to the op it would run, logs MESH_ADOPT_WOULDEXEC/REFUSED. Installs nothing, cycles nothing.

The real package-manager exec (B2b-2) is a separate, operator-gated slice — not in this release.

a2acast 0.17.0 — signed-approvals flagship groundwork

Choose a tag to compare

@husker husker released this 27 Jul 21:15
afc819e

Fleet-adoption release for the #62/#74/#76/#93 trust program: signing, enrollment, revocation, and enforcement machinery, all observe-only and default-off. Satisfies #74's fleet-wide-signing precondition. Full notes in CHANGELOG.md ## 0.17.0.

0.16.1 — no more silent delivery loss; per-node signing

Choose a tag to compare

@husker husker released this 22 Jul 21:17
298ef6a

0.16.1

  • Fixed the two delivery-loss mechanisms behind #86, validated live on all
    three platforms:
    • Every delivery path now writes the per-node activity file (shared
      _activity_line format), so a lifecycle hook deferring behind a plain
      mesh watch presence holder wakes on delivery instead of starving and
      dying silently when the watch exits.
    • Transport checkpoints (cursor + replay fingerprint) run only after the
      delivery handoff — inline after a successful emit for standalone
      watches, deferred until after the hook's own output in hook relay mode.
      A death before handoff leaves the frame re-deliverable: at-least-once
      instead of silent loss. Undeliverable frames are consumed exactly once
      and leave a visible activity trace.
    • Activity previews decode message envelopes (not just tasks), keeping
      the watch and MCP writers in agreement.
  • The agent-session watch warning now names the one-shot
    mesh watch --timeout re-arm fallback for harnesses where the hook
    cannot wake yet; the defer-mode wake summary mentions the CLI drain
    commands for sessions without MCP tools.
  • Known limb, tracked in #90: on Windows the harness-spawned async
    claude-hook process exits instantly and never receives — with this
    release that degrades to delayed redelivery, never loss; the one-shot
    re-arm loop remains the Windows posture.

This release also ships everything from 0.16.0, which was never published (PyPI latest was 0.15.1):

0.16.0

  • Per-node message signing (#62 phase 2): every node holds its own ed25519
    key, signs its outbound frames over the wire AAD + payload, and classifies
    inbound frames against a locally-pinned identity (verified / unverified /
    unsigned / mismatch). Trust is trust-on-first-use; the receive path is
    NON-ENFORCING — it surfaces a verdict and pins peers but drops no frame.
    Enforcement + the downgrade ratchet are still pending (#74). A node
    generates its key on first send, so upgrading an existing node is enough.
  • Owner keys are passphrase-protected by default (#64): minting an approval then needs the passphrase on the terminal, which a harnessed agent cannot answer — so an owner signature proves a human acted, not just that a process read the key. owner-init --no-passphrase keeps the old unprotected key (loudly warned); owner-trust --replace rotates the trusted owner key.
  • Owner-trust now prints a SHA256 fingerprint and requires a terminal
    confirmation before pinning; the owner private key's permissions are
    asserted (POSIX mode + Windows ACL).
  • Bound the replay ledger with time-based eviction (#77); mesh status shows
    the held count.
  • mesh peek no longer mislabels expired large-message attachments as
    [UNVERIFIED] (#65).
  • mesh watch --follow warns when it would be a write-only pipe in an agent
    session; join steers to the lifecycle hook (#57).
  • mesh mcp-serve --harness resolves identity from the pin at each startup,
    so mesh iam renames take effect (#59, #60).
  • The generated .gitignore now uses a .meshwire.* glob, closing a gap that
    left the owner private key stageable.

0.15.1 — pinned join bootstrap + CI

Choose a tag to compare

@husker husker released this 19 Jul 03:00
ca60537
  • Security: invite bootstrap blocks now download mesh.py pinned to the inviting node's release tag (v<VERSION>) instead of the tip of main, so a bad or malicious push to main cannot break or compromise future joins.
  • GitHub Actions CI: the unittest suite runs on Linux and macOS across Python 3.8–3.13 (Windows observational — #48), a consistency job keeps mesh.py/pyproject.toml/plugin manifest versions in lock-step, and a gitleaks job scans full history for leaked secrets on every push.
  • PyPI publish workflow (trusted publishing, runs on GitHub release).
  • Docs: list mesh_delegate in the MCP tools roster.

0.15.0 — machine-wide worker pool

Choose a tag to compare

@husker husker released this 19 Jul 03:00
a639eaf
  • Opt-in machine-wide worker pool with distinct Codex, Copilot, and Goose/Ollama identities.
  • Versioned isolated-worktree jobs, structured branch/commit results, and recipient-scoped task records so parallel supervisors cannot race.
  • Journaled execution, reply-only retries, health/cooldown routing, MCP delegation, conservative worktree cleanup, and macOS LaunchAgent lifecycle.
  • Preserves the existing default-off, default-empty-allowlist Codex supervisor and documents that worktrees are not security sandboxes.