handler

package
v0.1.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 26, 2026 License: MIT Imports: 14 Imported by: 0

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

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.

func WriteJSON

func WriteJSON(w http.ResponseWriter, status int, value any)

WriteJSON writes value as JSON with the given status.

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.

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

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 (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

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

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

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

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL