Skip to content

codypendent v0.14.0 (build 146)

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Sep 19:14
088115e

v0.14.0

Everything since v0.13.0. This release combines the council and TUI work that
landed after that tag with an eleven-part adversarial review of the execution,
recovery, control-plane, client and release boundaries.

The minor bump reflects new durable council behavior, repository-scoped
control-plane synchronization, and the first complete remote-runner policy
boundary. The rest of the release is intentionally dominated by correctness:
work that succeeds must not be repeated, authority supplied by a remote job
must not outrank local policy, and a client must not claim a server capability
that does not exist.

Councils that preserve and review the work

Council deliberation now has an explicit board shared across rounds, and every
round reaches a chair decision instead of merely producing a final summary.
Members have concrete role obligations; a member that exhausts its time keeps
and receives credit for its partial work; an independent reviewer reads the
synthesis before handoff; and citation verification checks the cited material
instead of accepting claims that it was checked.

A runner with a real local trust boundary

A claimed job can now narrow, but never expand, an immutable local runner
policy. Host mounts, working directory, environment access, resource bounds
and data classification are validated locally and bound into deterministic job
and attestation hashes.

Container execution keeps a stable daemon-owned identity and kills and reaps
the real container on every terminal path. Process execution polls host
cancellation and reaps the process group. Combined output is bounded while it
is read rather than after it has consumed memory.

Artifact paths are resolved beneath the attempt directory with no-follow
filesystem operations, required output failures are terminal, and upload
progress is journaled so a completed non-idempotent job is not re-executed just
because registration was interrupted. Cleanup handles mode-000 trees without
following symlinks and quarantines an attempt it cannot securely remove.
Claims use absolute expiry plus bounded renew/finalize calls; a failed or
non-monotonic renewal cancels the workload.

Recovery that does not repeat effects

Writing runs require launch and turn checkpoints before destructive work.
Paused runs reserve one recovery owner, restore their own durable assistant and
tool turns, reattach the existing worktree lease, retain approvals and
cancellation, and fail closed when safe replay cannot be established.

Terminal transitions are compare-and-set, so a late executor error cannot
overwrite cancellation, pause or completion. Repository and model provenance
is resolved at the originating durable sequence; corrupt provenance never
falls back to the daemon's current directory. A forced worktree release is
refused if its safety patch cannot capture the tree.

The daemon now starts a real control-plane synchronization service using the
generated protocol, repository-scoped cursors, durable backoff and owner-only
OS credential storage. Provider connections have explicit connect/idle
timeouts and bounded error bodies.

Control-plane authentication and tenant isolation

Refresh, pairing, daemon and WebSocket credentials use OS-generated 256-bit
secret material. JWT validation fixes algorithm, issuer and audience and
enforces issued-at, expiry and maximum-lifetime bounds. Refresh rotation is an
atomic compare-and-set; replay revokes the stolen descendant family rather
than every session belonging to the user.

Authorization rechecks active users, memberships and organizations and carries
credential purpose and audience into each route decision. Pairing completion
locks and validates the challenge, membership, scope, daemon and credential in
one transaction in both the memory and PostgreSQL stores. The live PostgreSQL
suite covers concurrent completion and rollback.

Caller-asserted identity linking is disabled with an explicit 501 until a
verified provider flow exists. Object uploads recheck both organization and
daemon policy before writing, direct arbitrary PUT is disabled, and downloads
derive their key only from authorized metadata. WebSocket clients use
short-lived one-use scoped tickets; subscription begins before complete,
repository-scoped replay and event-id deduplication close the replay/live race.

Synchronization that converges under crashes and policy changes

Authoritative session, run, artifact, approval, fork and graph writes now feed
the control-plane outbox in their production transactions, with startup repair
for legacy rows. Federated and legacy local repository identities resolve only
through the authenticated repository catalog and a hash-verified consent
manifest; catalog responses expose the live organization∩repository policy,
not a stale wider repository row.

Organization policy is drained to a stable cursor before the first outbound
byte. Artifact classifications and every graph fact are checked at the daemon
and again by the control plane. Policy-blocked rows can recover after a later
widening, while malformed and terminally rejected rows move to a durable
dead-letter state so they cannot starve the queue.

Policy repair appends a fresh sanitized occurrence instead of rewriting a
possibly committed sequence, and it preserves per-subject chronology. Session
and graph deletions supersede ambiguous queued publications; session
tombstones also dominate late summaries in a repository-and-daemon-scoped
ledger, preventing resurrection without letting another repository suppress a
same-named session. Revisited run states carry a durable sync revision so
Running → Paused → Running remains three distinct occurrences.

Cancelled runs can no longer leave child sessions permanently uncloseable when
cancellation lands during assembly-owned startup. After a short grace period, a
state- and event-guarded watchdog idempotently supplies missing RunCompleted
evidence; council cleanup reuses its attached connection and leaves a write-free
backoff between close-barrier polls. The real-daemon lifecycle race passed six
consecutive focused runs in addition to the affected package suites.

Clients that agree on what is live

Desktop session attachment is generation-correlated. The old session remains
authoritative until the replacement is accepted, attach-time frames are
buffered, stale history is rejected, snapshots set sequence watermarks and gap
repair remains scoped to the correct session through reconnects.

Web routes have an authentication guard and stale async responses cannot
replace newer state. React consumers share a multicast control-plane stream
with listener isolation and reference-counted teardown.

Bearer credentials now keep protected routes available even though the server
does not yet expose current-user lookup. Stream subscriptions require an
explicit supported stream in both the core and React APIs, so an omitted scope
cannot be reported as an all-stream connection while the server silently
narrows its ticket to sync events.

The control-plane SDK now maps to the actual Axum routes and generated wire
types. API-compatible methods for capabilities the server has not implemented
reject locally with UnsupportedControlPlaneCapabilityError instead of
issuing fabricated requests.

The TUI moves new/switch/fork/reconnect preparation off its sole input loop,
rejects superseded completions by generation, bounds deferred input and
deduplicates reconnect catch-up. Accessible mode now has command parity,
incremental streaming output, cold blackboard loading and visible writer
failure. The composer also edits like an editor and its surfaces answer the
keys they advertise.

Release integrity

Every third-party workflow action is pinned to a full commit SHA. Jobs default
to read-only permissions, checkouts do not persist credentials, and only the
publisher receives release-write authority. The PostgreSQL service image is
digest-pinned.

Both Rust workspaces, both lockfiles, generated protocol families, browser
clients, PostgreSQL integration tests and dependency policies are release
gates. Root and control-plane migration checksum manifests are immutable even
in shallow clones, with a regression that tampers with both SQL and manifest
from a depth-one checkout. A structural workflow test prevents these controls
from silently drifting.

Malformed durable sync rows now fail closed as unknown events instead of
inventing an empty subject and presenting a partial projection as a valid
delta. New sync writes reject blank, oversized, and control-character subject
identifiers before persistence.

Validation

The pre-final-review root workspace baseline completed 3,991 tests with 9
expected ignores and no failures. The final changed-package gates then passed
406 daemon unit tests, 14 daemon synchronization integrations, 294 composition
root unit tests, the real-router synchronization end-to-end test and 129
control-plane tests. Strict all-target/all-feature Clippy, both
generated-protocol checks and formatting passed. The separate Tauri workspace
passed format, locked all-target compilation, strict Clippy, 33 unit tests and
doc tests.

The focused client suites passed 158 desktop tests, 460 protocol SDK tests, 46
control-plane SDK tests, 10 React binding tests and 16 web tests. Both
Cargo-deny policies, both migration manifests and release workflow security
checks passed.

The full review and the deliberately retained architectural follow-ups are in
docs/reviews/2026-08-29-massive-review.md.