CertOps Agent
Machine surface for the CertOps executor and outbound-only agent. Scoped-token authenticated.
Report an event for one CertOps job
Machine-token route for reporting lifecycle events scoped to the path jobId. Requires certops:events:write. Workspace identity is derived from the authenticated CertOps API token; body workspaceId cannot override it. The route uses the same private-key rejection, generic-secret redaction, idempotency, audit, and persistence path as POST /api/v1/certops/executor/events.
Attach evidence to one CertOps job
Machine-token route for attaching sanitized evidence to the path jobId. Requires certops:evidence:write. Workspace identity is derived from the authenticated CertOps API token; body workspaceId cannot override it. Private key material is rejected with 422, generic secrets are redacted, and optional output is limited to 65,536 UTF-8 bytes and stored only as redacted output.
Report executor events
Aggregate executor ingestion endpoint for normalized job and public evidence events. Lifecycle events require `certops:events:write`; evidence-bearing events additionally require `certops:evidence:write`. The route is hidden with 404 when `certops.enabled` is disabled. `eventId` is idempotent within a workspace and job: exact retries return 202 without repeating logs, evidence, audit rows, or status side effects, while a different sanitized envelope using the same key returns 409. Late lifecycle events are recorded in the job log but cannot regress or reopen a terminal job. Payloads containing private key material are rejected with 422. Generic secret material in metadata and bounded evidence output is redacted to `[REDACTED]` before persistence. Per-job event/evidence routes are narrow machine-token aliases that reuse the same hardened ingestion behavior.
Register an agent
Outbound-only agent enrollment using a single-use, hashed, expiring bootstrap token (bearer); registration returns the per-agent credential exactly once, together with the active job-signing public key. Request body is the agent-protocol envelope with messageType register (packages/contracts/certops/agent-protocol.schema.json, additionalProperties false); that schema remains authoritative for body shapes. Unknown, expired, used, and revoked bootstrap tokens all return the same generic 401 so callers cannot probe token state. Private key material is audited and rejected with 422 before rollout gating. Hidden with 404 while certops.enabled is disabled.
Agent heartbeat
Steady-state heartbeat authenticated with the per-agent credential (bearer). Updates last_seen_at, records the envelope clockOffsetMs and body ntpSynced/uptimeSeconds/pinnedSigningKeyId for clock-drift and key-rotation fleet monitoring, flips an offline agent back to active, and announces the active job-signing public key. Request body is the agent-protocol envelope with messageType heartbeat (packages/contracts/certops/agent-protocol.schema.json, additionalProperties false). A retired agent authenticates but receives 410 without any last_seen_at update. Private key material is audited and rejected with 422. Hidden with 404 while certops.enabled is disabled.
Claim pending jobs
Outbound-only claim poll authenticated with the per-agent credential (bearer). Request body is the agent-protocol envelope with messageType claim (packages/contracts/certops/agent-protocol.schema.json, additionalProperties false); the body only expresses poll preferences (maxJobs, supportedActions), never a specific job selection. Server selects pending workspace jobs with FOR UPDATE SKIP LOCKED, leases them, and returns signed dispatch payloads: job-payload fields plus claimId, leaseExpiresAt, attemptCount, and the Ed25519 dispatch fields nonce, issuedAt, expiresAt, signingKeyId, signature. Dispatch is blocked while the workspace kill switch is on (409 CERTOPS_WORKSPACE_PAUSED); results reporting never is. A retired agent receives 410. Hidden with 404 while certops.enabled is disabled.
Renew a claimed job lease
Re-proves claim ownership (authenticated agent + claimId), transitions claimed→running on first renew, extends lease_expires_at, stamps lease_renewed_at, and extends the still-open dispatch nonce so late results remain reportable through the reaper hard-grace window. The agent must call this before each external side effect (ACME/DNS/deploy/ reload). See COORDINATION-B6.md. Not an agent-protocol envelope messageType: lean JSON body with claimId and optional sequence.
Report job results and evidence
Result/evidence ingestion authenticated with the per-agent credential (bearer). Request body is the agent-protocol envelope with messageType result or evidence, dispatched on the envelope messageType (packages/contracts/certops/agent-protocol.schema.json, additionalProperties false). Result ingestion re-proves claim ownership (agent + claimId, where attemptId doubles as the claimId), consumes the single-use dispatch nonce (replay ledger), and transitions the job terminally in one transaction. Evidence messages append job-scoped public evidence without any job transition. The workspace kill switch never blocks results. A retired agent receives 410. Payloads containing private key material are rejected with 422. Hidden with 404 while certops.enabled is disabled.