Skip to main content

CertOps

Certificate lifecycle orchestration (workspace-scoped). Control plane never stores private key material.

📄️List certificates grouped by workspace and SHA-256 fingerprint

One row per workspace fingerprint, with fingerprintless sources included as provisional rows in the same globally sorted page. Stable row-kind and UUID tie-breakers apply to every sort. Page and total use one database snapshot. Source and location summaries contain up to 20 records each, with sourceCount reporting all historical associations, activeSourceCount reporting current managed sources, and locationCount reporting the full observation count. Viewer responses omit key, source and deployment references. Each source period includes its linked tokenId when a token exists. Lifecycle does not determine whether an identity is managed or consumes quota.

📄️Get workspace CertOps settings

Returns the workspace-local CertOps kill-switch state, the Job approval policy (`certOpsRequireApprovalAlways`), and the effective side-effect availability. All authorized workspace members may read it. This is a human cookie/session-authenticated workspace surface; internal worker bearer credentials are not accepted. The stored pause state remains distinct from the deployment-wide certops.enabled rollout flag, and this settings endpoint remains available when that rollout flag is disabled.

📄️Update workspace CertOps pause or Job approval settings

Changes the workspace-local kill switch and/or the Job approval policy (`certOpsRequireApprovalAlways`) and remains available while the deployment-wide rollout flag is disabled. Requires a human cookie/session-authenticated workspace admin; internal worker bearer credentials are not accepted. At least one of `certOpsPaused` or `certOpsRequireApprovalAlways` is required. Setting both in one request applies them as a single transaction. A paused workspace rejects new manual jobs and future dispatch or provision side effects with 409 CERTOPS_WORKSPACE_PAUSED; inventory, status, audit, evidence, and existing-work reporting remain available. While Job approval is on, every new job starts `pending_approval`, including trust-anchor distribute or revoke.

📄️Bulk-create CertOps renewal jobs

Queues a renew job for up to 100 managed certificates in one request. Each certificate goes through the same manual job-creation path as POST /jobs (manager role, workspace kill switch, approval gate, payload validation), and jobs are always recorded with source 'api'. The response is a partial-failure envelope: per-certificate successes and failures are reported item by item and never abort the batch, so the request returns 200 even when some or all items fail. Only whole-request shape problems (malformed body, more than 100 ids, non-UUID or duplicate ids) fail with 400. Private key or secret material in the request body is rejected.

📄️Approve a pending CertOps job

Grants the human approval a gated job needs before an agent can claim it. Session-only manager surface (internal worker credentials are rejected) with a non-requester rule: the user who requested the job cannot approve it. The approval is bound to a canonical SHA256 hash of the job payload at decision time; if the payload changes afterwards the claim path voids the approval and returns the job to pending_approval. Available while the workspace kill switch is paused.

📄️Retire a CertOps agent

Retires an agent so its credential stops authenticating (agent protocol routes return 410). Retiring an already-retired agent is idempotent. If the agent holds actively leased jobs the request is blocked with 409 unless force is true, in which case an attributable reason is required. A forced retire fences the agent's in-flight work immediately rather than leaving it to the lease reaper: jobs still at 'claimed' are cancelled with error_code CERTOPS_AGENT_FORCE_RETIRED, while jobs that had reached 'running' become orphaned_unknown_effect and are flagged needs_operator_reconciliation, because their real-world effect is unknown. Both id lists are returned in the response and recorded on the CERTOPS_AGENT_RETIRED audit event.

📄️Approve a CertOps trust anchor

Approves a CA certificate as a trust anchor that distribute-trust jobs may install into an agent's trust store (ADR-0012 decision 6). `pem` must contain exactly one CA certificate (Basic Constraints CA=true); bundles and leaf certificates are rejected. Re-submitting the same fingerprint updates the existing row in place and reactivates it if it was previously retired, rather than creating a duplicate record. Recorded as a CERTOPS_TRUST_ANCHOR_APPROVED audit event.

📄️List installations for a CertOps trust anchor

Returns every certops_trust_anchor_installations row for one trust anchor (agent, store, transition state, provenance, last error), so an operator can see where the anchor actually landed before revoking or distributing it further. Manager-only, same as the other trust-anchor routes. Read-only: unlike the mutating trust-anchor routes, this route does not require the workspace's CertOps state to be active, since an operator diagnosing a paused workspace still needs to see current installations.

📄️Bootstrap a CertOps diagnostic agent

Session-authenticated (requires certops.agents.diagnose, admin-only). Atomically consumes a single-use requestId, creates an agent with agent_kind 'diagnostic', and creates its protocol_smoke job, all in one transaction. The response's credential is returned exactly once and is not recoverable afterward. Retrying with the same requestId never replays the original agentId/credential/job; it fails with diagnostic_bootstrap_already_consumed. Requests are rate limited per workspace. Diagnostic agents that stay inactive for 24 hours are retired automatically; retirement revokes the credential in the same transaction that marks the agent retired, so a retired diagnostic agent's credential fails authentication immediately, not just authorization.