- GetDesiredStateResponse.deployment_id set: the desired revision is
applied as a push with that ID, also in manual mode (ADR 0022).
- The reports of the last 20 push deployments are kept in state.json.
A resent push with a handled deployment ID is not applied again; its
report is delivered again unless it is still queued.
- A push already queued with the same deployment ID is not queued twice.
- Reports the server refuses for good (InvalidArgument, NotFound,
AlreadyExists, FailedPrecondition, OutOfRange) are dropped instead of
blocking the report queue.
- Tests for polling pushes, resent pushes, mode changes via a new
Welcome, persistence and bounds of handled deployments.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- CLI: enroll, run, status, version, help (core.Main with a role
factory); the agent binaries use a placeholder factory until the
BIND and Kea roles are wired in.
- Enrollment: local ECDSA P-256 key and CSR, TLS 1.3 to the agent API
with the server chain pinned to the CA fingerprint.
- ServerSource: mTLS gRPC with keepalive, Connect stream (Hello,
Welcome, heartbeats, apply and renew commands), reconnect with
exponential backoff and jitter, GetDesiredState polling as fallback,
certificate renewal after half of the lifetime.
- Apply pipeline: fetch, bundle verification with replay protection,
store, Validate, Activate, Health with retries, rollback to the last
good revision; outcomes succeeded/rejected/rolled_back/failed are
queued in state.json and reported; failed revisions are retried only
by a newer revision or an explicit push.
- Lease reporting with change detection, persistent sequence and full
snapshots at start, per connection and periodically.
- Tests with fake roles, a fake source and an in-process fake
AgentService over real mTLS.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>