Labels on deployment markers

Go · Go · beginner · modification

Lets CI pipelines attach labels to a deployment (region, commit, who triggered it) so the deploy dashboard can filter markers by them. Labels are validated up front: at most 20, keys in a strict snake_case alphabet, values capped at 200 bytes, with a plain 400 for anything else. The server stamps a `source` label with the pipeline's name on every deployment, overwriting whatever the client sent, so a pipeline can't post markers as another one. The shared GitHub Actions deploy step now sends `region` and `commit`.

Go 1.22 service, standard library only (`net/http` method-pattern `ServeMux`, `log/slog`). `cmd/server/main.go` (unchanged) registers `POST /api/deployments` behind `auth.RequirePipeline`, which checks the pipeline's bearer token, answers 401 itself for a bad one, and puts the `auth.Pipeline` (`ID int64`, `Name string`: the pipeline's unique name, at most 60 ASCII characters) into the request context. The mux is served by a plain `http.Server` with no other middleware. `Deployment` (existing) already has `Labels map[string]string`: the `labels jsonb not null default '{}'` column, the field and `Store.Insert` writing it shipped in the previous PR, and the dashboard's filters read it. `Handler` (existing) holds `Store Store` and `Log *slog.Logger`.

Requirements

Files touched

--- internal/deploys/handler.go
 import (
 	"encoding/json"
+	"errors"
+	"fmt"
 	"net/http"
+	"regexp"
 	"time"
 
 )
 
-const maxBodyBytes = 64 << 10
+const (
+	maxBodyBytes     = 64 << 10
+	maxLabels        = 20
+	maxLabelValueLen = 200
+)
 
 type createRequest struct {
-	Service     string    `json:"service"`
-	Version     string    `json:"version"`
-	Environment string    `json:"environment"`
-	FinishedAt  time.Time `json:"finished_at"`
+	Service     string            `json:"service"`
+	Version     string            `json:"version"`
+	Environment string            `json:"environment"`
+	FinishedAt  time.Time         `json:"finished_at"`
+	Labels      map[string]string `json:"labels"`
 }
 

Review this PR

Go practice