Fix: wildcard certificates no longer break the Gateway. A DNS name such as *.home.hrajfrisbee.cz put * into the listener name; the API server rejected the patch, which blocked every certificate on that Gateway (cilium-gateway in the home lab). The DNS part of the name is now lowercased, * becomes wildcard, other characters outside [a-z0-9] become -, and names over 253 chars are cut with a hash suffix. Names that were valid before are unchanged, so existing listeners are not renamed.
Conventions port from the newer repos: CLAUDE.md in the house shape, .claude/ settings, /ship + /release, reviewer agents, docs/plans + execution logs + reviews, CHANGELOG stub, Makefile with make check, golangci-lint config, baseline tests, commit stamping (--version, startup log, image label), and a CI check job gating the image build.
Behaviour changes to know about
/ship no longer tags; /release creates vX.Y.Z tags.
--metrics-bind-address is now passed to the manager (deployment already uses :8080).
A manual CI dispatch with tag latest is rejected; :latest moves only on tag pushes.
Go module path is now gitea.home.hrajfrisbee.cz/kacerr/gatewayapi-certificates-operator.
Verification
make check (lint, vet, short tests) and go test -race ./... pass; internal/gateway at 98.6% coverage.
The failing production input (wildcard-home-hrajfrisbee / *.home.hrajfrisbee.cz) is a test case.
Image builds locally and --version prints the stamped commit.
Not verified: the new CI workflow has not run, and the fix has not run against a cluster.
After merge
Tag v0.1.0, then kubectl -n gateway-cert-operator-system rollout restart deploy/gateway-cert-operator (the Deployment pins :latest).
## What
Two things on one branch:
1. **Fix: wildcard certificates no longer break the Gateway.** A DNS name such as `*.home.hrajfrisbee.cz` put `*` into the listener name; the API server rejected the patch, which blocked every certificate on that Gateway (`cilium-gateway` in the home lab). The DNS part of the name is now lowercased, `*` becomes `wildcard`, other characters outside `[a-z0-9]` become `-`, and names over 253 chars are cut with a hash suffix. Names that were valid before are unchanged, so existing listeners are not renamed.
2. **Conventions port** from the newer repos: CLAUDE.md in the house shape, `.claude/` settings, `/ship` + `/release`, reviewer agents, `docs/plans` + execution logs + reviews, CHANGELOG stub, Makefile with `make check`, golangci-lint config, baseline tests, commit stamping (`--version`, startup log, image label), and a CI `check` job gating the image build.
## Behaviour changes to know about
- `/ship` no longer tags; `/release` creates `vX.Y.Z` tags.
- `--metrics-bind-address` is now passed to the manager (deployment already uses `:8080`).
- A manual CI dispatch with tag `latest` is rejected; `:latest` moves only on tag pushes.
- Go module path is now `gitea.home.hrajfrisbee.cz/kacerr/gatewayapi-certificates-operator`.
## Verification
- `make check` (lint, vet, short tests) and `go test -race ./...` pass; `internal/gateway` at 98.6% coverage.
- The failing production input (`wildcard-home-hrajfrisbee` / `*.home.hrajfrisbee.cz`) is a test case.
- Image builds locally and `--version` prints the stamped commit.
- Not verified: the new CI workflow has not run, and the fix has not run against a cluster.
## After merge
Tag `v0.1.0`, then `kubectl -n gateway-cert-operator-system rollout restart deploy/gateway-cert-operator` (the Deployment pins `:latest`).
Plans: `docs/plans/2026-10-08-2028-house-conventions.md`, `docs/plans/2026-10-08-2046-listener-name-sanitize.md`. Review: `docs/reviews/`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- CLAUDE.md in five sections with Go, testing, plan, changelog, branching
and tagging rules; known sharp edges moved to Gotchas
- docs/flows.md: metrics are served on :8080, name collisions are rejected
by the API server, last-cert deletion never cleans up
- README moved to the repo root, deploy command corrected
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- /ship now commits and pushes with a branch guard and no longer tags;
/release tags vMAJOR.MINOR.PATCH and confirms before pushing
- operator-reviewer and go-operator-reviewer agents from egress-proxies-operator
- committed permission allowlist; settings.local.json ignored
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- make check runs lint + vet + test-short; lint is pinned to the go.mod
toolchain so it works when the host Go is newer than golangci-lint's
- gofumpt main.go and patch.go; drop unused gatewayGroup/gatewayKind vars
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- module path is now gitea.home.hrajfrisbee.cz/kacerr/gatewayapi-certificates-operator
- internal/version resolves the commit from ldflags or Go build info;
--version prints it and the first log line carries it
- --metrics-bind-address is passed to the manager instead of being dropped
- Dockerfile takes GIT_COMMIT, honours TARGETARCH, labels the image revision
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Covers current correct behaviour of the pure functions in internal/gateway.
Known-buggy inputs (wildcards, collisions, truncation) are left out on purpose.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- check job runs go vet, go build and go test -short before the build
- images are pushed as :<tag> and :sha-<12>; :latest moves only on tag pushes
- GIT_COMMIT build arg and OCI source/created labels
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ci: reject a manual dispatch with tag "latest"; concurrency group per tag
- Dockerfile: declare GIT_COMMIT after the module download layer
- Makefile: docker-build targets linux/amd64 by default
- patch.go: no shared package-level pointers; main.go: no init()
- tests: assert that merge replaces managed listener content
- docs: flows.md startup section matches main.go; review saved to docs/reviews
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A DNS name like *.home.hrajfrisbee.cz put "*" into the listener name; the
API server rejected the patch, which blocked every certificate on that
Gateway.
- lowercase the DNS part, spell "*" as "wildcard", map other characters
outside [a-z0-9] to "-"
- names over 253 chars are cut and get a hash suffix instead of a blind cut
- names that were valid before are unchanged
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
Two things on one branch:
*.home.hrajfrisbee.czput*into the listener name; the API server rejected the patch, which blocked every certificate on that Gateway (cilium-gatewayin the home lab). The DNS part of the name is now lowercased,*becomeswildcard, other characters outside[a-z0-9]become-, and names over 253 chars are cut with a hash suffix. Names that were valid before are unchanged, so existing listeners are not renamed..claude/settings,/ship+/release, reviewer agents,docs/plans+ execution logs + reviews, CHANGELOG stub, Makefile withmake check, golangci-lint config, baseline tests, commit stamping (--version, startup log, image label), and a CIcheckjob gating the image build.Behaviour changes to know about
/shipno longer tags;/releasecreatesvX.Y.Ztags.--metrics-bind-addressis now passed to the manager (deployment already uses:8080).latestis rejected;:latestmoves only on tag pushes.gitea.home.hrajfrisbee.cz/kacerr/gatewayapi-certificates-operator.Verification
make check(lint, vet, short tests) andgo test -race ./...pass;internal/gatewayat 98.6% coverage.wildcard-home-hrajfrisbee/*.home.hrajfrisbee.cz) is a test case.--versionprints the stamped commit.After merge
Tag
v0.1.0, thenkubectl -n gateway-cert-operator-system rollout restart deploy/gateway-cert-operator(the Deployment pins:latest).Plans:
docs/plans/2026-10-08-2028-house-conventions.md,docs/plans/2026-10-08-2046-listener-name-sanitize.md. Review:docs/reviews/.🤖 Generated with Claude Code