Documentation
¶
Overview ¶
Package handler contains the HTTP-facing adapters for the RA V2 API. Handlers map between OpenAPI JSON DTOs and the service-layer domain types. Errors are surfaced as RFC 7807 Problem Details.
Index ¶
- func WriteError(w http.ResponseWriter, err error)
- func WriteJSON(w http.ResponseWriter, status int, value any)
- type IdentityHandler
- func (h *IdentityHandler) Detail(w http.ResponseWriter, r *http.Request)
- func (h *IdentityHandler) Link(w http.ResponseWriter, r *http.Request)
- func (h *IdentityHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *IdentityHandler) Register(w http.ResponseWriter, r *http.Request)
- func (h *IdentityHandler) Revoke(w http.ResponseWriter, r *http.Request)
- func (h *IdentityHandler) Rotate(w http.ResponseWriter, r *http.Request)
- func (h *IdentityHandler) Unlink(w http.ResponseWriter, r *http.Request)
- func (h *IdentityHandler) VerifyControl(w http.ResponseWriter, r *http.Request)
- type LifecycleHandler
- func (h *LifecycleHandler) CancelServerCertRenewal(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) Detail(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) GetCSRStatus(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) GetIdentityCerts(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) GetServerCertRenewal(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) GetServerCerts(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) Revoke(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) SubmitIdentityCSR(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) SubmitServerCSR(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) SubmitServerCertRenewal(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) VerifyACME(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) VerifyDNS(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) VerifyRenewalACME(w http.ResponseWriter, r *http.Request)
- func (h *LifecycleHandler) WithIdentityViews(identities *service.IdentityService) *LifecycleHandler
- type Problem
- type RegistrationHandler
- type V1CertificatesHandler
- func (h *V1CertificatesHandler) GetCSRStatus(w http.ResponseWriter, r *http.Request)
- func (h *V1CertificatesHandler) GetIdentityCerts(w http.ResponseWriter, r *http.Request)
- func (h *V1CertificatesHandler) GetServerCerts(w http.ResponseWriter, r *http.Request)
- func (h *V1CertificatesHandler) SubmitIdentityCSR(w http.ResponseWriter, r *http.Request)
- func (h *V1CertificatesHandler) SubmitServerCSR(w http.ResponseWriter, r *http.Request)
- type V1LifecycleHandler
- type V1RegistrationHandler
- type V1RenewalHandler
- func (h *V1RenewalHandler) CancelServerCertRenewal(w http.ResponseWriter, r *http.Request)
- func (h *V1RenewalHandler) GetServerCertRenewal(w http.ResponseWriter, r *http.Request)
- func (h *V1RenewalHandler) SubmitServerCertRenewal(w http.ResponseWriter, r *http.Request)
- func (h *V1RenewalHandler) VerifyRenewalACME(w http.ResponseWriter, r *http.Request)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func WriteError ¶
func WriteError(w http.ResponseWriter, err error)
WriteError maps a domain error to an RFC 7807 Problem response. Unknown errors produce 500; known sentinel errors map to specific statuses. Error messages are safe to include in responses because the domain layer never embeds internal details in Error.Message.
Types ¶
type IdentityHandler ¶ added in v0.1.6
type IdentityHandler struct {
// contains filtered or unexported fields
}
IdentityHandler wires the /v2/ans/identities surface — the "who" behind the agents. Ownership is enforced inside the service (the owner gate is the link mechanism's security boundary), so these handlers only extract the authenticated principal and map DTOs.
func NewIdentityHandler ¶ added in v0.1.6
func NewIdentityHandler(svc *service.IdentityService) *IdentityHandler
NewIdentityHandler constructs an IdentityHandler.
func (*IdentityHandler) Detail ¶ added in v0.1.6
func (h *IdentityHandler) Detail(w http.ResponseWriter, r *http.Request)
Detail handles GET /v2/ans/identities/{identityId} — the identity plus its live links.
func (*IdentityHandler) Link ¶ added in v0.1.6
func (h *IdentityHandler) Link(w http.ResponseWriter, r *http.Request)
Link handles POST /v2/ans/identities/{identityId}/links — the owner-gated batch link. 200 {linked: N}; the batch sealed as ONE IDENTITY_LINKED event on the identity stream.
func (*IdentityHandler) List ¶ added in v0.1.6
func (h *IdentityHandler) List(w http.ResponseWriter, r *http.Request)
List handles GET /v2/ans/identities — one page of the caller's identities, in the v2 limit + opaque-cursor envelope mirroring AgentListResponse (`items` array): one collection convention across the v2 surface.
func (*IdentityHandler) Register ¶ added in v0.1.6
func (h *IdentityHandler) Register(w http.ResponseWriter, r *http.Request)
Register handles POST /v2/ans/identities → 202 + challenges.
func (*IdentityHandler) Revoke ¶ added in v0.1.6
func (h *IdentityHandler) Revoke(w http.ResponseWriter, r *http.Request)
Revoke handles POST /v2/ans/identities/{identityId}/revoke — a state change (an identity cannot be deleted; its history is append-only in the TL), mirroring the agent's revoke verb.
func (*IdentityHandler) Rotate ¶ added in v0.1.6
func (h *IdentityHandler) Rotate(w http.ResponseWriter, r *http.Request)
Rotate handles PUT /v2/ans/identities/{identityId} → 202 + fresh challenges over the staged replacement.
func (*IdentityHandler) Unlink ¶ added in v0.1.6
func (h *IdentityHandler) Unlink(w http.ResponseWriter, r *http.Request)
Unlink handles DELETE /v2/ans/identities/{identityId}/links/{agentId}. The association ends (204); its history persists in the identity's audit chain and the raw log tiles.
func (*IdentityHandler) VerifyControl ¶ added in v0.1.6
func (h *IdentityHandler) VerifyControl(w http.ResponseWriter, r *http.Request)
VerifyControl handles POST /v2/ans/identities/{identityId}/verify-control. Clean proofs flip the identity to VERIFIED (or complete a rotation) and seal the event — the 200 echoes the updated identity.
type LifecycleHandler ¶
type LifecycleHandler struct {
// contains filtered or unexported fields
}
LifecycleHandler groups the non-register routes: list/detail/certs (reads) and verify-acme/verify-dns/revoke (writes). All agent-scoped routes assume the ownership middleware has already run.
func NewLifecycleHandler ¶
func NewLifecycleHandler(svc *service.RegistrationService) *LifecycleHandler
NewLifecycleHandler constructs a LifecycleHandler.
func (*LifecycleHandler) CancelServerCertRenewal ¶
func (h *LifecycleHandler) CancelServerCertRenewal(w http.ResponseWriter, r *http.Request)
CancelServerCertRenewal handles DELETE .../certificates/server/renewal. Returns 204 on success, 404 if no renewal exists, 422 if the renewal already completed. Matches the reference RA's handler.
func (*LifecycleHandler) Detail ¶
func (h *LifecycleHandler) Detail(w http.ResponseWriter, r *http.Request)
Detail handles GET /v2/ans/agents/{agentId}. Ownership verified by middleware; the agent is attached to the context but we re-fetch (incl. endpoints) through the service so the response carries every field the V2 AgentDetails schema requires.
func (*LifecycleHandler) GetCSRStatus ¶
func (h *LifecycleHandler) GetCSRStatus(w http.ResponseWriter, r *http.Request)
GetCSRStatus handles GET .../csrs/{csrId}/status. Returns the V2 `CsrStatusResponse` with {csrId, type, status, submittedAt, updatedAt, failureReason}. 404 if the CSR doesn't exist or isn't scoped to this agent — matching the reference's ownership check.
func (*LifecycleHandler) GetIdentityCerts ¶
func (h *LifecycleHandler) GetIdentityCerts(w http.ResponseWriter, r *http.Request)
GetIdentityCerts handles GET .../certificates/identity.
func (*LifecycleHandler) GetServerCertRenewal ¶
func (h *LifecycleHandler) GetServerCertRenewal(w http.ResponseWriter, r *http.Request)
GetServerCertRenewal handles GET .../certificates/server/renewal. Returns 200 with `RenewalStatusResponse` or 404 if no renewal exists. Status is derived from the renewal's fields via determineRenewalStatus — matching the reference RA's handler.
func (*LifecycleHandler) GetServerCerts ¶
func (h *LifecycleHandler) GetServerCerts(w http.ResponseWriter, r *http.Request)
GetServerCerts handles GET .../certificates/server. Returns every server certificate (BYOC + CA-issued once Stage 5c's server CSR flow lands). Matches the reference RA's `CertificateOperationsHandler.getAgentServerCertificateByAgentId`.
func (*LifecycleHandler) List ¶
func (h *LifecycleHandler) List(w http.ResponseWriter, r *http.Request)
List handles GET /v2/ans/agents. Ownership-scoped to the caller; default status filter is [ACTIVE] per spec.
func (*LifecycleHandler) Revoke ¶
func (h *LifecycleHandler) Revoke(w http.ResponseWriter, r *http.Request)
Revoke handles POST .../revoke.
func (*LifecycleHandler) SubmitIdentityCSR ¶
func (h *LifecycleHandler) SubmitIdentityCSR(w http.ResponseWriter, r *http.Request)
SubmitIdentityCSR handles POST .../certificates/identity. Body is a `CsrSubmissionRequest` (V2 §1362) with a single `csrPEM` field. Returns 202 with `{csrId, message}` per `CsrSubmissionResponse`.
Parity with reference `CertificateOperationsHandler.submitAgentIdentityCsr`: the reference validates + persists the CSR synchronously and emits a domain event the infrastructure handler picks up to actually issue the cert. We take the same approach — the service saves the CSR with status=PENDING; a future job will flip it to SIGNED.
func (*LifecycleHandler) SubmitServerCSR ¶
func (h *LifecycleHandler) SubmitServerCSR(w http.ResponseWriter, r *http.Request)
SubmitServerCSR handles POST .../certificates/server. Body is a `CsrSubmissionRequest`; returns 202 `CsrSubmissionResponse`. Matches `CertificateOperationsHandler.submitAgentServerCsr`.
func (*LifecycleHandler) SubmitServerCertRenewal ¶
func (h *LifecycleHandler) SubmitServerCertRenewal(w http.ResponseWriter, r *http.Request)
SubmitServerCertRenewal handles POST .../certificates/server/renewal. Body is a `ServerCertificateRenewalRequest` with exactly one of serverCsrPEM / serverCertificatePEM. Returns 202 on success with `RenewalSubmissionResponse`. Matches reference `CertificateRenewalOperationsHandler.submitServerCertificateRenewal`.
func (*LifecycleHandler) VerifyACME ¶
func (h *LifecycleHandler) VerifyACME(w http.ResponseWriter, r *http.Request)
VerifyACME handles POST .../verify-acme. No request body. Always 202: domain validation succeeded and certificates are either issued (status PENDING_DNS, phase DNS_PROVISIONING) or still being finalized by an asynchronous issuer (status PENDING_VALIDATION, phase CERTIFICATE_ISSUANCE — the caller re-POSTs to re-drive).
func (*LifecycleHandler) VerifyDNS ¶
func (h *LifecycleHandler) VerifyDNS(w http.ResponseWriter, r *http.Request)
VerifyDNS handles POST .../verify-dns.
func (*LifecycleHandler) VerifyRenewalACME ¶
func (h *LifecycleHandler) VerifyRenewalACME(w http.ResponseWriter, r *http.Request)
VerifyRenewalACME handles POST .../certificates/server/renewal/verify-acme. For BYOC renewals verification completes synchronously and we return 200; for CSR renewals the issuance is async and we return 202 — matching the reference RA's handler.
func (*LifecycleHandler) WithIdentityViews ¶ added in v0.1.6
func (h *LifecycleHandler) WithIdentityViews(identities *service.IdentityService) *LifecycleHandler
WithIdentityViews attaches the identity service used to compute the additive identities[] field on agent detail responses.
type Problem ¶
type Problem struct {
Type string `json:"type"`
Title string `json:"title"`
Status int `json:"status"`
Detail string `json:"detail,omitempty"`
Code string `json:"code,omitempty"`
}
Problem is the RFC 7807 response body for errors.
type RegistrationHandler ¶
type RegistrationHandler struct {
// contains filtered or unexported fields
}
RegistrationHandler wires HTTP routes for POST /v2/ans/agents and the related verify-* endpoints.
func NewRegistrationHandler ¶
func NewRegistrationHandler(svc *service.RegistrationService) *RegistrationHandler
NewRegistrationHandler constructs a RegistrationHandler.
func (*RegistrationHandler) Register ¶
func (h *RegistrationHandler) Register(w http.ResponseWriter, r *http.Request)
Register is the handler for POST /v2/ans/agents.
type V1CertificatesHandler ¶
type V1CertificatesHandler struct {
// contains filtered or unexported fields
}
V1CertificatesHandler wires the V1 certificate-operation routes:
GET /v1/agents/{agentId}/certificates/identity
POST /v1/agents/{agentId}/certificates/identity
GET /v1/agents/{agentId}/certificates/server
POST /v1/agents/{agentId}/certificates/server
GET /v1/agents/{agentId}/csrs/{csrId}/status
Reference-parity observation: V1 and V2 certificate DTOs (`CertificateResponse`, `CsrSubmissionRequest`, `CsrSubmissionResponse`, `CsrStatusResponse`) are byte-identical in the reference spec — the V1 and V2 operations reference the same component schemas (see api-spec.yaml §562 vs §938 both returning `CertificateResponse`). So V1 cert responses reuse the V2 DTO types in this file rather than duplicating identical shapes. If that diverges in a future spec version, this is the place to fork them.
Schema-version note: cert-submission handlers do NOT enqueue TL events. The V1 RA emits a TL leaf only on terminal transitions (AGENT_REGISTERED / AGENT_REVOKED / AGENT_RENEWED / AGENT_DEPRECATED); CSR submission is intermediate state that the reference records in its domain-level lifecycle store, not the TL.
func NewV1CertificatesHandler ¶
func NewV1CertificatesHandler(svc *service.RegistrationService) *V1CertificatesHandler
NewV1CertificatesHandler constructs a V1CertificatesHandler.
func (*V1CertificatesHandler) GetCSRStatus ¶
func (h *V1CertificatesHandler) GetCSRStatus(w http.ResponseWriter, r *http.Request)
GetCSRStatus handles GET /v1/agents/{agentId}/csrs/{csrId}/status.
func (*V1CertificatesHandler) GetIdentityCerts ¶
func (h *V1CertificatesHandler) GetIdentityCerts(w http.ResponseWriter, r *http.Request)
GetIdentityCerts handles GET /v1/agents/{agentId}/certificates/identity.
func (*V1CertificatesHandler) GetServerCerts ¶
func (h *V1CertificatesHandler) GetServerCerts(w http.ResponseWriter, r *http.Request)
GetServerCerts handles GET /v1/agents/{agentId}/certificates/server.
func (*V1CertificatesHandler) SubmitIdentityCSR ¶
func (h *V1CertificatesHandler) SubmitIdentityCSR(w http.ResponseWriter, r *http.Request)
SubmitIdentityCSR handles POST /v1/agents/{agentId}/certificates/identity.
func (*V1CertificatesHandler) SubmitServerCSR ¶
func (h *V1CertificatesHandler) SubmitServerCSR(w http.ResponseWriter, r *http.Request)
SubmitServerCSR handles POST /v1/agents/{agentId}/certificates/server.
type V1LifecycleHandler ¶
type V1LifecycleHandler struct {
// contains filtered or unexported fields
}
V1LifecycleHandler groups the V1 post-registration transitions: verify-acme, verify-dns, revoke. Shares the `RegistrationService` with V2; diverges only in DTO shape and TL-lane emission.
Every handler method stamps `service.VerifyInput{SchemaVersion:"V1"}` (or the revoke equivalent) on the service call so state transitions enqueue V1 envelopes to `/v1/internal/agents/event`.
func NewV1LifecycleHandler ¶
func NewV1LifecycleHandler(svc *service.RegistrationService) *V1LifecycleHandler
NewV1LifecycleHandler constructs a V1LifecycleHandler.
func (*V1LifecycleHandler) Revoke ¶
func (h *V1LifecycleHandler) Revoke(w http.ResponseWriter, r *http.Request)
Revoke handles POST /v1/agents/{agentId}/revoke. Enqueues an AGENT_REVOKED V1 envelope to the TL. Response shape matches `AgentRevocationResponse` in the reference spec.
func (*V1LifecycleHandler) VerifyACME ¶
func (h *V1LifecycleHandler) VerifyACME(w http.ResponseWriter, r *http.Request)
VerifyACME handles POST /v1/agents/{agentId}/verify-acme. No body. V1 TL receives no leaf for this intermediate transition — the V1 enum lacks DOMAIN_VALIDATION. The agent's domain state still advances to PENDING_DNS.
func (*V1LifecycleHandler) VerifyDNS ¶
func (h *V1LifecycleHandler) VerifyDNS(w http.ResponseWriter, r *http.Request)
VerifyDNS handles POST /v1/agents/{agentId}/verify-dns. On successful ACTIVE transition, enqueues an AGENT_REGISTERED V1 envelope to the TL — this is the FIRST TL leaf V1 agents get (V1 defers emission from /register until the agent is live, matching the reference lifecycle).
type V1RegistrationHandler ¶
type V1RegistrationHandler struct {
// contains filtered or unexported fields
}
V1RegistrationHandler wires HTTP routes for the V1 `/v1/agents/*` registration + detail surface.
func NewV1RegistrationHandler ¶
func NewV1RegistrationHandler(svc *service.RegistrationService) *V1RegistrationHandler
NewV1RegistrationHandler constructs a V1RegistrationHandler.
func (*V1RegistrationHandler) Detail ¶
func (h *V1RegistrationHandler) Detail(w http.ResponseWriter, r *http.Request)
Detail is the handler for GET /v1/agents/{agentId}. Ownership is enforced by `ramiddleware.ReadOwnership` before this runs (404 on not-owned); we refetch via the service layer here for testability — the handler doesn't depend on middleware wiring in unit tests. This mirrors the V2 `LifecycleHandler.Detail` pattern.
func (*V1RegistrationHandler) Register ¶
func (h *V1RegistrationHandler) Register(w http.ResponseWriter, r *http.Request)
Register is the handler for POST /v1/agents/register. Produces an AgentRegistrationPending response (202). Does NOT emit a TL event — the V1 AGENT_REGISTERED leaf is written only once the registration completes (domain validated + DNS live), which happens in the verify-dns / verify-acme handlers.
type V1RenewalHandler ¶
type V1RenewalHandler struct {
// contains filtered or unexported fields
}
V1RenewalHandler wires the V1 server-cert renewal routes:
POST /v1/agents/{agentId}/certificates/server/renewal
GET /v1/agents/{agentId}/certificates/server/renewal
DELETE /v1/agents/{agentId}/certificates/server/renewal
POST /v1/agents/{agentId}/certificates/server/renewal/verify-acme
Reference-parity observation: the V1 renewal DTOs (`ServerCertificateRenewalRequest`, `RenewalSubmissionResponse`, `RenewalStatusResponse`, `RenewalVerificationResponse`) are byte-identical to V2 — both RA versions reference the same spec components. V1 and V2 handlers share the DTO types here; the only V1-specific piece is the `nextStep.endpoint` URL scheme (/v1/… instead of /v2/ans/…).
TL emit: the V2 renewal service does not enqueue TL events today (AGENT_RENEWED emission awaits the async cert-issuance path); V1 therefore also emits nothing on the renewal write paths. When issuance lands, both lanes will emit on completion — V2 as CERTIFICATE_RENEWED, V1 as AGENT_RENEWED.
Both server-cert paths supported (matching the reference): operators can submit `serverCsrPEM` to have the configured `ServerCertificateIssuer` port issue the cert, or `serverCertificatePEM` + chain for BYOC. Exactly one required.
func NewV1RenewalHandler ¶
func NewV1RenewalHandler(svc *service.RegistrationService) *V1RenewalHandler
NewV1RenewalHandler constructs a V1RenewalHandler.
func (*V1RenewalHandler) CancelServerCertRenewal ¶
func (h *V1RenewalHandler) CancelServerCertRenewal(w http.ResponseWriter, r *http.Request)
CancelServerCertRenewal handles DELETE /v1/agents/{agentId}/certificates/server/renewal. 204 on success.
func (*V1RenewalHandler) GetServerCertRenewal ¶
func (h *V1RenewalHandler) GetServerCertRenewal(w http.ResponseWriter, r *http.Request)
GetServerCertRenewal handles GET /v1/agents/{agentId}/certificates/server/renewal.
func (*V1RenewalHandler) SubmitServerCertRenewal ¶
func (h *V1RenewalHandler) SubmitServerCertRenewal(w http.ResponseWriter, r *http.Request)
SubmitServerCertRenewal handles POST /v1/agents/{agentId}/certificates/server/renewal.
func (*V1RenewalHandler) VerifyRenewalACME ¶
func (h *V1RenewalHandler) VerifyRenewalACME(w http.ResponseWriter, r *http.Request)
VerifyRenewalACME handles POST /v1/agents/{agentId}/certificates/server/renewal/verify-acme.