Milestones M3 and M4: API, auth, dashboard, CLI, edge, deploy

Six work packages, wired in cmd/kudurru/serve.go (commit "feat(serve): wire milestones M3 and M4"). Decisions D98 to D105 in architecture.md record what changed; three integration fixes landed on top (authorization used only name and groups; tokens of local users did not reload their principal; the CLI sent name where the server takes description).

PackageReportHeadline
REST API + external-dns webhookapi.md64 paths, 84 operations; envelope, keyset pagination, If-Match, managed_by conflicts, SSE with resume; route-permission lint; generated Go client; webhook conformance against external-dns v0.23
Authentication and authorizationauth.mdUsers, kdr_ tokens, sealed sessions, OIDC (dex e2e), Kubernetes SA tokens with SAR on envtest, RBAC engine, admin socket; 2-6 µs per authenticated request
Dashboardui.mdReact 19 + Astryx, 183 vitest tests, 235 KiB gzip initial load, embedded with a committed placeholder so Go builds without Bun
CLIcli.md30 top-level commands with golden tests; contexts, keyring, apply/get/describe, dig-like query, logs --follow, admin socket client
dnsdist and keepalived supervisorsedge.mdYAML/Lua renderers with 22 golden files, supervisors tested against fake binaries, vip drain, FIFO state file; make edge-check for a Docker runner
Deployment assetsdeploy.mdHelm chart validated over 33 permutations with kubeconform, kustomize overlays rendered from the chart, compose profiles, Grafana dashboard generated from registered metrics, goreleaser + release workflow

Verified live from one config: local login, cookie and token sessions with the admin's roles, kudurru get zones / get blocklists -A / query / blocking disable 1m / apply -f - (the new record resolved immediately) / stats summary / logs / audit, the real dashboard bundle served with its assets, /api/v1/openapi.json.

Not verifiable in this sandbox: make edge-check (needs Docker), the Helm chart on a cluster, kind + MetalLB, two-VM VRRP. (v0.1 fix round: make edge-check failed on its first real run, because the keepalived image did not build; fixed, it passes and is a CI gate, see edge.md. kind + MetalLB is the kind workflow.)

Source: docs/m3/README.md